Files
aiagent/frontend/src/utils/agentSkills.ts
renjianbo de415ca310 feat: add Prompt template library, agent_call inter-agent tool, and RAG memory
- New PromptTemplatePicker component for browsing 13 preset prompt templates
- AgentConfig.vue: "Load from library" button for system prompt
- Agents.vue: "Create from Prompt template" entry with agent node + RAG memory
- seed_prompt_templates.py: 13 preset templates (客服/研发/教育/内容/分析/创意/健康医疗)
- agent_call tool: agents can delegate tasks to other agents (19th builtin tool)
- Created 全能助手 (general orchestrator) and 家庭医生助手 agents
- Switch template-created agents from type:llm to type:agent for full ReAct + RAG

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-05-03 21:57:30 +08:00

78 lines
2.9 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* 从 Agent 工作流中提取 / 写入 LLM 节点的工具skills配置。
*/
import type { WorkflowNode } from '@/types'
/** 与后端 tools_bootstrap 内置工具一致,用于列表展示与配置勾选 */
export const BUILTIN_SKILL_OPTIONS: { name: string; label: string }[] = [
{ name: 'http_request', label: 'HTTP 请求' },
{ name: 'file_read', label: '读文件' },
{ name: 'file_write', label: '写文件' },
{ name: 'text_analyze', label: '文本分析' },
{ name: 'datetime', label: '日期时间' },
{ name: 'math_calculate', label: '数学计算' },
{ name: 'system_info', label: '系统信息' },
{ name: 'json_process', label: 'JSON 处理' },
{ name: 'database_query', label: '数据库查询' },
{ name: 'adb_log', label: 'ADB 日志' },
{ name: 'agent_call', label: '调用 Agent' },
]
export const BUILTIN_SKILL_LABELS: Record<string, string> = Object.fromEntries(
BUILTIN_SKILL_OPTIONS.map((o) => [o.name, o.label])
)
function isLlmNode(n: WorkflowNode): boolean {
const t = (n.type || '').toLowerCase()
const dt = (n.data?.type || '').toLowerCase()
return t === 'llm' || t === 'template' || dt === 'llm'
}
/** 工作流中所有 LLM 节点上已选工具的并集(去重排序) */
export function extractSkillToolNames(workflow_config: { nodes?: WorkflowNode[] } | null | undefined): string[] {
const set = new Set<string>()
for (const n of workflow_config?.nodes || []) {
if (!isLlmNode(n)) continue
const raw = n.data?.tools ?? n.data?.selected_tools
if (Array.isArray(raw)) {
raw.forEach((x) => set.add(String(x)))
}
}
return Array.from(set).sort()
}
/**
* 作为「能力配置」写入时的目标节点:优先 llm-unified否则第一个带工具的 LLM否则第一个 LLM。
*/
export function findPrimaryLlmNodeForTools(nodes: WorkflowNode[] | undefined): WorkflowNode | null {
if (!nodes?.length) return null
const byId = nodes.find((n) => n.id === 'llm-unified' && isLlmNode(n))
if (byId) return byId
const withTools = nodes.find(
(n) =>
isLlmNode(n) &&
(n.data?.enable_tools === true ||
(Array.isArray(n.data?.tools) && n.data.tools.length > 0) ||
(Array.isArray(n.data?.selected_tools) && n.data.selected_tools.length > 0))
)
if (withTools) return withTools
return nodes.find((n) => isLlmNode(n)) || null
}
export function patchWorkflowSkillTools(
workflow_config: { nodes: WorkflowNode[]; edges: unknown[] },
toolNames: string[]
): { nodes: WorkflowNode[]; edges: unknown[] } {
const wf = JSON.parse(JSON.stringify(workflow_config)) as { nodes: WorkflowNode[]; edges: unknown[] }
const target = findPrimaryLlmNodeForTools(wf.nodes)
if (!target) return wf
const names = [...new Set(toolNames)].filter(Boolean).sort()
if (!target.data) target.data = {}
target.data.enable_tools = names.length > 0
target.data.tools = names
target.data.selected_tools = names
return wf
}