feat(temple): add Temple modal with Tools browser and Skills management

This commit is contained in:
2026-04-08 16:46:02 +08:00
parent 51e38e039b
commit aa12c92a5a
12 changed files with 2571 additions and 41 deletions

View File

@@ -0,0 +1,133 @@
import { ref, computed } from 'vue'
import { toolsApi, type ToolCategory, type ToolInfo, type ToolsResponse } from '@/api/tools'
export type TabType = 'tools' | 'skills'
export function useTemple() {
// ===== State =====
const activeTab = ref<TabType>('tools')
const toolsLoading = ref(false)
const toolsError = ref<string | null>(null)
// Tools data
const categories = ref<ToolCategory[]>([])
const summary = ref({
total_commands: 0,
active_commands: 0,
total_tools: 0,
manifest_tools: 0,
agent_tools: 0,
})
// Selection state (Tools Tab)
const selectedCategory = ref<string | null>(null) // 大分类名,如 "注册层"
const selectedSubgroup = ref<string | null>(null) // 子分类名,如 "文件操作"
const selectedTool = ref<ToolInfo | null>(null)
// ===== Computed =====
/** 展平所有工具列表 */
const allTools = computed(() => {
return categories.value.flatMap((cat) =>
cat.subgroups.flatMap((sub) => sub.tools)
)
})
/** 当前选中的大分类下的子分类 */
const currentSubgroups = computed(() => {
if (!selectedCategory.value) return []
const cat = categories.value.find((c) => c.name === selectedCategory.value)
return cat?.subgroups ?? []
})
/** 当前选中子分类下的工具 */
const currentTools = computed(() => {
if (!selectedSubgroup.value) return []
for (const cat of categories.value) {
const sub = cat.subgroups.find((s) => s.name === selectedSubgroup.value)
if (sub) return sub.tools
}
return []
})
/** 当前选中工具的详情 */
const currentToolDetail = computed(() => selectedTool.value)
// ===== Actions =====
async function fetchTools() {
toolsLoading.value = true
toolsError.value = null
try {
const res = await toolsApi.list()
const data: ToolsResponse = res.data
categories.value = data.categories
summary.value = data.summary
// 默认选中第一个分类和子分类
if (categories.value.length > 0) {
const firstCat = categories.value[0]
selectedCategory.value = firstCat.name
if (firstCat.subgroups.length > 0) {
selectedSubgroup.value = firstCat.subgroups[0].name
}
}
} catch (e: unknown) {
toolsError.value = e instanceof Error ? e.message : 'Failed to load tools'
console.error('[useTemple] fetchTools error:', e)
} finally {
toolsLoading.value = false
}
}
function selectCategory(name: string) {
selectedCategory.value = name
selectedSubgroup.value = null
selectedTool.value = null
// 自动选中第一个子分类
const cat = categories.value.find((c) => c.name === name)
if (cat && cat.subgroups.length > 0) {
selectedSubgroup.value = cat.subgroups[0].name
}
}
function selectSubgroup(name: string) {
selectedSubgroup.value = name
selectedTool.value = null
}
function selectTool(tool: ToolInfo) {
selectedTool.value = tool
}
function clearToolSelection() {
selectedTool.value = null
}
function switchTab(tab: TabType) {
activeTab.value = tab
}
return {
// State
activeTab,
toolsLoading,
toolsError,
categories,
summary,
selectedCategory,
selectedSubgroup,
selectedTool,
// Computed
allTools,
currentSubgroups,
currentTools,
currentToolDetail,
// Actions
fetchTools,
selectCategory,
selectSubgroup,
selectTool,
clearToolSelection,
switchTab,
}
}