初始化模版工程
This commit is contained in:
131
components/nova-sdk/message-list/message-item/ToolCallAction.tsx
Normal file
131
components/nova-sdk/message-list/message-item/ToolCallAction.tsx
Normal file
@@ -0,0 +1,131 @@
|
||||
import React from 'react'
|
||||
import {
|
||||
Code,
|
||||
Terminal,
|
||||
Search,
|
||||
FileCode,
|
||||
Globe,
|
||||
FileText,
|
||||
FileEdit,
|
||||
Image,
|
||||
GalleryHorizontal,
|
||||
Puzzle,
|
||||
Bot,
|
||||
RefreshCw,
|
||||
Eye,
|
||||
Layers,
|
||||
Wrench,
|
||||
} from 'lucide-react'
|
||||
import { cn } from '@/utils/cn'
|
||||
import type { ApiEvent } from '../../types'
|
||||
import { SILENT_ACTION_TYPES } from './utils'
|
||||
|
||||
export interface ToolCallActionProps {
|
||||
name?: string
|
||||
arguments?: string[]
|
||||
action_type?: string
|
||||
event?: ApiEvent
|
||||
onClick?: (event: ApiEvent) => void
|
||||
}
|
||||
|
||||
// ─── action_type → { icon, label } ──────────────────────────────────────────
|
||||
const ACTION_TYPE_META: Record<string, { icon: React.ReactNode; label: string }> = {
|
||||
shell_execute: { icon: <Terminal className="w-4 h-4" />, label: '执行命令' },
|
||||
terminal_operator: { icon: <Terminal className="w-4 h-4" />, label: '终端操作' },
|
||||
code_execute: { icon: <Code className="w-4 h-4" />, label: '运行代码' },
|
||||
file_operator: { icon: <FileCode className="w-4 h-4" />, label: '文件操作' },
|
||||
file_create: { icon: <FileText className="w-4 h-4" />, label: '创建文件' },
|
||||
file_read: { icon: <FileText className="w-4 h-4" />, label: '读取文件' },
|
||||
file_replace_text: { icon: <FileEdit className="w-4 h-4" />, label: '编辑文件' },
|
||||
file_write_text: { icon: <FileEdit className="w-4 h-4" />, label: '写入文件' },
|
||||
str_replace: { icon: <FileEdit className="w-4 h-4" />, label: '替换内容' },
|
||||
info_search_web: { icon: <Search className="w-4 h-4" />, label: '搜索网页' },
|
||||
info_fetch_webpage: { icon: <Globe className="w-4 h-4" />, label: '获取网页' },
|
||||
news_search: { icon: <Search className="w-4 h-4" />, label: '新闻搜索' },
|
||||
image_search: { icon: <Image className="w-4 h-4" />, label: '图片搜索' },
|
||||
info_search_custom_knowledge: { icon: <Search className="w-4 h-4" />, label: '知识检索' },
|
||||
search_custom_knowledge: { icon: <Search className="w-4 h-4" />, label: '知识检索' },
|
||||
browser_use: { icon: <Globe className="w-4 h-4" />, label: '浏览器操作' },
|
||||
slide_init: { icon: <GalleryHorizontal className="w-4 h-4" />, label: '初始化幻灯片' },
|
||||
slide_template: { icon: <GalleryHorizontal className="w-4 h-4" />, label: '选择模板' },
|
||||
slide_create: { icon: <GalleryHorizontal className="w-4 h-4" />, label: '生成幻灯片' },
|
||||
slide_create_batch: { icon: <Layers className="w-4 h-4" />, label: '批量生成幻灯片' },
|
||||
slide_present: { icon: <GalleryHorizontal className="w-4 h-4" />, label: '展示幻灯片' },
|
||||
media_generate_image: { icon: <Image className="w-4 h-4" />, label: '生成图片' },
|
||||
media_vision_image: { icon: <Eye className="w-4 h-4" />, label: '识别图片' },
|
||||
generate_image: { icon: <Image className="w-4 h-4" />, label: '生成图片' },
|
||||
call_flow: { icon: <RefreshCw className="w-4 h-4" />, label: '调用流程' },
|
||||
integrated_app: { icon: <Puzzle className="w-4 h-4" />, label: '集成应用' },
|
||||
custom_api: { icon: <Wrench className="w-4 h-4" />, label: '自定义工具' },
|
||||
skill_loader: { icon: <Bot className="w-4 h-4" />, label: '加载技能' },
|
||||
brand_search: { icon: <Search className="w-4 h-4" />, label: '品牌检索' },
|
||||
xiaohongshu_search: { icon: <Search className="w-4 h-4" />, label: '小红书搜索' },
|
||||
e_commerce: { icon: <Search className="w-4 h-4" />, label: '电商搜索' },
|
||||
experience_query: { icon: <Search className="w-4 h-4" />, label: '经验查询' },
|
||||
writer: { icon: <FileEdit className="w-4 h-4" />, label: '文档创作' },
|
||||
parallel_map: { icon: <Layers className="w-4 h-4" />, label: '并行任务' },
|
||||
media_comments: { icon: <Search className="w-4 h-4" />, label: '媒体搜索' },
|
||||
system_api: { icon: <Wrench className="w-4 h-4" />, label: '系统接口' },
|
||||
}
|
||||
|
||||
/**
|
||||
* 工具调用 Action 组件
|
||||
* - 静默事件类型 → 不渲染
|
||||
* - name / label / argsText 全空 → 不渲染
|
||||
* - 点击触发外部 onClick(打开右侧面板)
|
||||
*/
|
||||
export function ToolCallAction({
|
||||
name,
|
||||
arguments: args,
|
||||
action_type,
|
||||
event,
|
||||
onClick,
|
||||
}: ToolCallActionProps) {
|
||||
// 静默类型直接跳过
|
||||
if (action_type && SILENT_ACTION_TYPES.has(action_type)) return null
|
||||
|
||||
const meta = action_type ? ACTION_TYPE_META[action_type] : undefined
|
||||
const icon = meta?.icon ?? <Code className="w-4 h-4" />
|
||||
const label = name || meta?.label || ''
|
||||
const argsText = args?.filter(Boolean).join(' ') || ''
|
||||
|
||||
// 没有任何可展示内容时不渲染
|
||||
if (!label && !argsText) return null
|
||||
|
||||
const handleClick = () => {
|
||||
if (event && onClick) onClick(event)
|
||||
}
|
||||
const isClickable = !!(event && onClick)
|
||||
|
||||
return (
|
||||
<div
|
||||
className={cn(
|
||||
'inline-flex items-center gap-2 px-3 py-1.5 rounded-lg max-w-full mb-2',
|
||||
'border border-gray-200 bg-white/80',
|
||||
'text-sm',
|
||||
isClickable && 'cursor-pointer transition-all duration-150 hover:bg-gray-50 hover:border-gray-300',
|
||||
)}
|
||||
onClick={isClickable ? handleClick : undefined}
|
||||
role={isClickable ? 'button' : undefined}
|
||||
tabIndex={isClickable ? 0 : undefined}
|
||||
onKeyDown={
|
||||
isClickable
|
||||
? e => {
|
||||
if (e.key === 'Enter' || e.key === ' ') {
|
||||
e.preventDefault()
|
||||
handleClick()
|
||||
}
|
||||
}
|
||||
: undefined
|
||||
}
|
||||
>
|
||||
<span className="shrink-0 text-gray-500">{icon}</span>
|
||||
{label && <span className="shrink-0 font-medium text-gray-800">{label}:</span>}
|
||||
{argsText && (
|
||||
<code className="min-w-0 flex-1 truncate font-mono text-xs text-gray-500">
|
||||
{argsText}
|
||||
</code>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user