Skip to content

Commit ee1a1b5

Browse files
committed
better max tool block
1 parent bd065f2 commit ee1a1b5

File tree

19 files changed

+97
-18
lines changed

19 files changed

+97
-18
lines changed

electron.vite.config.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,12 @@ export default defineConfig({
4545
plugins: [tailwind(), autoprefixer()]
4646
}
4747
},
48-
plugins: [vue(), svgLoader(), vueDevTools()]
48+
plugins: [
49+
vue(),
50+
svgLoader(),
51+
vueDevTools({
52+
launchEditor: 'cursor'
53+
})
54+
]
4955
}
5056
})

src/main/presenter/llmProviderPresenter/baseProvider.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ export interface ChatMessageContent {
2525

2626
export abstract class BaseLLMProvider {
2727
// 最大工具调用次数限制
28-
protected static readonly MAX_TOOL_CALLS = 20
28+
protected static readonly MAX_TOOL_CALLS = 2
2929

3030
protected provider: LLM_PROVIDER
3131
protected models: MODEL_META[] = []

src/main/presenter/llmProviderPresenter/providers/anthropicProvider.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -605,8 +605,7 @@ ${context}
605605
// 检查是否达到最大工具调用次数
606606
if (toolCallCount >= MAX_TOOL_CALLS) {
607607
yield {
608-
content: `\n<maximum_tool_calls_reached count="${MAX_TOOL_CALLS}">\n`,
609-
reasoning_content: undefined
608+
maximum_tool_calls_reached: true
610609
}
611610
needContinueConversation = false
612611
break

src/main/presenter/llmProviderPresenter/providers/geminiProvider.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -678,7 +678,7 @@ export class GeminiProvider extends BaseLLMProvider {
678678
// 检查是否达到最大工具调用次数
679679
if (toolCallCount >= MAX_TOOL_CALLS) {
680680
yield {
681-
content: `\n<maximum_tool_calls_reached count="${MAX_TOOL_CALLS}">\n`
681+
maximum_tool_calls_reached: true
682682
}
683683
needContinueConversation = false
684684
break

src/main/presenter/llmProviderPresenter/providers/ollamaProvider.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -384,7 +384,7 @@ export class OllamaProvider extends BaseLLMProvider {
384384
// 检查是否达到最大工具调用次数
385385
if (toolCallCount >= MAX_TOOL_CALLS) {
386386
yield {
387-
content: `\n<maximum_tool_calls_reached count="${MAX_TOOL_CALLS}">\n`
387+
maximum_tool_calls_reached: true
388388
}
389389
needContinueConversation = false
390390
break

src/main/presenter/llmProviderPresenter/providers/openAICompatibleProvider.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -462,7 +462,7 @@ export class OpenAICompatibleProvider extends BaseLLMProvider {
462462
// 检查是否达到最大工具调用次数
463463
if (toolCallCount >= MAX_TOOL_CALLS) {
464464
yield {
465-
content: `\n<maximum_tool_calls_reached count="${MAX_TOOL_CALLS}">\n`
465+
maximum_tool_calls_reached: true
466466
}
467467
needContinueConversation = false
468468
break

src/main/presenter/threadPresenter/index.ts

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -227,7 +227,8 @@ export class ThreadPresenter implements IThreadPresenter {
227227
tool_call_id,
228228
tool_call_name,
229229
tool_call_params,
230-
tool_call_response
230+
tool_call_response,
231+
maximum_tool_calls_reached
231232
} = msg
232233
const state = this.generatingMessages.get(eventId)
233234
if (state) {
@@ -239,6 +240,23 @@ export class ThreadPresenter implements IThreadPresenter {
239240
})
240241
}
241242

243+
// 处理工具调用达到最大次数的情况
244+
if (maximum_tool_calls_reached) {
245+
const lastBlock = state.message.content[state.message.content.length - 1]
246+
if (lastBlock) {
247+
lastBlock.status = 'success'
248+
}
249+
state.message.content.push({
250+
type: 'action',
251+
content: 'common.error.maximumToolCallsReached',
252+
status: 'success',
253+
timestamp: Date.now(),
254+
action_type: 'maximum_tool_calls_reached'
255+
})
256+
await this.messageManager.editMessage(eventId, JSON.stringify(state.message.content))
257+
return
258+
}
259+
242260
// 处理reasoning_content的时间戳
243261
if (reasoning_content) {
244262
if (state.reasoningStartTime === null) {
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
<template>
2+
<div
3+
class="text-xs bg-red-100 text-red-700 rounded-lg border border-red-400 flex flex-col gap-2 px-2 py-2"
4+
>
5+
<div class="flex flex-row gap-2 items-center cursor-pointer">
6+
<Icon icon="lucide:info" class="w-4 h-4 text-red-700" />
7+
</div>
8+
<div class="prose prose-sm max-w-full break-all whitespace-pre-wrap leading-7">
9+
{{ t(block.content) }}
10+
{{ block }}
11+
</div>
12+
</div>
13+
</template>
14+
15+
<script setup lang="ts">
16+
import { useI18n } from 'vue-i18n'
17+
import { Icon } from '@iconify/vue'
18+
19+
const { t } = useI18n()
20+
21+
defineProps<{
22+
block: {
23+
content: string
24+
action_type?: string
25+
}
26+
}>()
27+
</script>

src/renderer/src/components/message/MessageItemAssistant.vue

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@
4343
:message-id="message.id"
4444
:thread-id="currentThreadId"
4545
/>
46+
<MessageBlockAction v-else-if="block.type === 'action'" :block="block" />
4647
<MessageBlockError v-else-if="block.type === 'error'" :block="block" />
4748
</div>
4849
</div>
@@ -78,7 +79,7 @@ import ModelIcon from '@/components/icons/ModelIcon.vue'
7879
import { Icon } from '@iconify/vue'
7980
import { toBlob } from 'html-to-image'
8081
import { useDark } from '@vueuse/core'
81-
82+
import MessageBlockAction from './MessageBlockAction.vue'
8283
const props = defineProps<{
8384
message: AssistantMessage
8485
}>()

src/renderer/src/i18n/en-US/common.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,9 @@ export default {
2020
cleanMessagesFailed: 'Failed to clean messages',
2121
userCanceledGeneration: 'User canceled generation',
2222
sessionInterrupted: 'Session was unexpectedly interrupted, generation is incomplete',
23-
noModelResponse: 'Model did not return any content, it may have timed out'
23+
noModelResponse: 'Model did not return any content, it may have timed out',
24+
invalidJson: 'Invalid JSON format',
25+
maximumToolCallsReached: 'Maximum tool calls reached'
2426
},
2527
resetDataConfirmTitle: 'Reset All Data?',
2628
resetDataConfirmDescription:

0 commit comments

Comments
 (0)