|
9 | 9 | </svg> |
10 | 10 | </button> |
11 | 11 |
|
12 | | - <!-- 组内工具:每个工具一行,可单独展开参数与结果 --> |
| 12 | + <!-- 组内工具:每个工具一行,有专用渲染器的按工具名展示,其余可单独展开参数与结果 --> |
13 | 13 | <div v-show="isExpanded && toolItems.length" class="group-body"> |
14 | | - <ToolItem v-for="(toolItem, index) in toolItems" :key="toolItem.id ?? index" :tool-item="toolItem" class="group-row" /> |
| 14 | + <template v-for="(toolItem, index) in toolItems" :key="toolItem.id ?? index"> |
| 15 | + <div v-if="resolveToolRenderer(toolItem.name)" class="group-row group-row-custom"> |
| 16 | + <component |
| 17 | + :is="resolveToolRenderer(toolItem.name)" |
| 18 | + :content="toolItem" |
| 19 | + :loading="toolItem.status === 'RUNNING'" |
| 20 | + :expanded="isToolExpanded(toolItem, index)" |
| 21 | + @toggle="toggleTool(toolItem, index)" |
| 22 | + /> |
| 23 | + </div> |
| 24 | + <ToolItem v-else :tool-item="toolItem" class="group-row" /> |
| 25 | + </template> |
15 | 26 | </div> |
16 | 27 | </div> |
17 | 28 | </template> |
18 | 29 |
|
19 | 30 | <script setup lang="ts"> |
20 | | -import { computed, ref } from 'vue' |
| 31 | +import { computed, ref, type Component } from 'vue' |
21 | 32 | import ToolItem from './components/ToolItem.vue' |
| 33 | +import Terminal from '../tool/Terminal.vue' |
| 34 | +import Patch from '../tool/Patch.vue' |
| 35 | +import ReadFile from '../tool/ReadFile.vue' |
| 36 | +import ListDir from '../tool/ListDir.vue' |
| 37 | +import Grep from '../tool/Grep.vue' |
| 38 | +import Glob from '../tool/Glob.vue' |
| 39 | +import CreateFile from '../tool/CreateFile.vue' |
| 40 | +import ListSkills from '../tool/ListSkills.vue' |
| 41 | +import DownloadSkills from '../tool/DownloadSkills.vue' |
| 42 | +import RunSkill from '../tool/RunSkill.vue' |
22 | 43 |
|
23 | 44 | /** |
24 | 45 | * 分组工具卡:由 content-list 把相邻 TOOL 折叠而成,content.children 为组内 TOOL 内容项。 |
| 46 | + * 组内工具按工具名使用专用渲染器(与单个 TOOL 的 tool/index.vue 一致),未匹配的工具以参数/结果行展示。 |
25 | 47 | * 状态由组内工具汇总:有执行中为执行中,否则有失败为失败,否则成功。 |
26 | 48 | * 执行中默认展开,结束后默认收起,手动切换后以手动为准。 |
27 | 49 | */ |
28 | 50 | const props = defineProps<{ content: any }>() |
29 | 51 |
|
30 | 52 | const toolItems = computed<any[]>(() => props.content.children ?? []) |
31 | 53 |
|
| 54 | +// 工具名(小写)→ 专用渲染器;新增工具时与 tool/index.vue 同步 |
| 55 | +const toolRenderers: Record<string, Component> = { |
| 56 | + run_command: Terminal, |
| 57 | + apply_patch: Patch, |
| 58 | + read_file: ReadFile, |
| 59 | + list_dir: ListDir, |
| 60 | + grep: Grep, |
| 61 | + glob: Glob, |
| 62 | + create_file: CreateFile, |
| 63 | + list_skills: ListSkills, |
| 64 | + download_skills: DownloadSkills, |
| 65 | + run_skill: RunSkill, |
| 66 | +} |
| 67 | +
|
| 68 | +function resolveToolRenderer(toolName: unknown): Component | undefined { |
| 69 | + return toolRenderers[String(toolName || '').toLowerCase()] |
| 70 | +} |
| 71 | +
|
| 72 | +type GroupToolItem = { id?: string; status?: string } |
| 73 | +
|
| 74 | +// 组内专用渲染器的展开状态:执行中默认展开,结束后默认收起,手动切换后以手动为准 |
| 75 | +const manualToolExpanded = ref<Record<string, boolean>>({}) |
| 76 | +
|
| 77 | +function toolKey(toolItem: GroupToolItem, index: number) { |
| 78 | + return String(toolItem.id ?? index) |
| 79 | +} |
| 80 | +
|
| 81 | +function isToolExpanded(toolItem: GroupToolItem, index: number) { |
| 82 | + return manualToolExpanded.value[toolKey(toolItem, index)] ?? toolItem.status === 'RUNNING' |
| 83 | +} |
| 84 | +
|
| 85 | +function toggleTool(toolItem: GroupToolItem, index: number) { |
| 86 | + manualToolExpanded.value[toolKey(toolItem, index)] = !isToolExpanded(toolItem, index) |
| 87 | +} |
| 88 | +
|
32 | 89 | const groupStatus = computed(() => { |
33 | 90 | const childStatuses = toolItems.value.map((toolItem) => toolItem.status) |
34 | 91 | if (childStatuses.includes('RUNNING')) return 'running' |
@@ -116,6 +173,10 @@ const isExpanded = computed({ |
116 | 173 | overflow: hidden; |
117 | 174 | } |
118 | 175 |
|
| 176 | +.group-row-custom { |
| 177 | + padding: 5px 12px; |
| 178 | +} |
| 179 | +
|
119 | 180 | .group-row + .group-row { |
120 | 181 | border-top: 1px solid var(--bd, #ebeef5); |
121 | 182 | } |
|
0 commit comments