diff --git a/frontend/src/components/workspace/iframe-test-panel.tsx b/frontend/src/components/workspace/iframe-test-panel.tsx index a1589fb0..6c10042f 100644 --- a/frontend/src/components/workspace/iframe-test-panel.tsx +++ b/frontend/src/components/workspace/iframe-test-panel.tsx @@ -56,13 +56,17 @@ export function IframeTestPanel() { } function handleSendSelectSkill() { - iframeSkill.sendSelectSkill(["skill_001"]); - addLog("postMessage → selectSkill (skill_id=['skill_001'])"); + iframeSkill.sendSelectSkill([{ id: "skill_001", name: "测试技能1" }]); + addLog("postMessage → selectedSkills ([{id:'skill_001',name:'测试技能1'}])"); } function handleSendSelectSkillArray() { - iframeSkill.sendSelectSkill(["1246", "1247", "1248"]); - addLog("postMessage → selectSkill (skill_id=['1246','1247','1248'])"); + iframeSkill.sendSelectSkill([ + { id: "1246", name: "技能A" }, + { id: "1247", name: "技能B" }, + { id: "1248", name: "技能C" }, + ]); + addLog("postMessage → selectedSkills (3 skills)"); } function handleOpenSkillDialog() { @@ -72,7 +76,7 @@ export function IframeTestPanel() { function handleClearSkill() { iframeSkill.clearSkill(); - addLog("clearSkill 已调用,postMessage → skill_id=[]"); + addLog("clearSkill 已调用,postMessage → selectedSkills=[]"); } function handleTestClipboardCopy() { diff --git a/frontend/src/components/workspace/input-box.tsx b/frontend/src/components/workspace/input-box.tsx index 40bc98a0..85a909a5 100644 --- a/frontend/src/components/workspace/input-box.tsx +++ b/frontend/src/components/workspace/input-box.tsx @@ -57,6 +57,10 @@ import { DropdownMenuSeparator, } from "@/components/ui/dropdown-menu"; import { useI18n } from "@/core/i18n/hooks"; +import type { + SelectedSkillPayloadItem, + SuggestionSkillChildren, +} from "@/core/i18n/locales/types"; import { POST_MESSAGE_TYPES, sendToParent } from "@/core/iframe-messages"; import { useModels } from "@/core/models/hooks"; import type { AgentThreadContext } from "@/core/threads"; @@ -491,7 +495,7 @@ export function InputBox({ function SuggestionListContainer({ sendSelectSkill, }: { - sendSelectSkill: (skill_id: string[]) => void; + sendSelectSkill: (selectedSkills: SelectedSkillPayloadItem[]) => void; }) { return (
@@ -504,7 +508,7 @@ function SuggestionListContainer({ function SuggestionList({ sendSelectSkill, }: { - sendSelectSkill: (skill_id: string[]) => void; + sendSelectSkill: (selectedSkills: SelectedSkillPayloadItem[]) => void; }) { const { t } = useI18n(); const { textInput } = usePromptInputController(); @@ -521,20 +525,31 @@ function SuggestionList({ suggestion: { prompt: string; skill_id?: string[]; - children?: { skill_id: string[] }[]; + children?: SuggestionSkillChildren[]; + suggestion: string; }, ) => { - // 优先从 children 中提取 skill_id 数组,发送给宿主页 + // 优先从 children 中提取 skill_id 数组,转换为 selectedSkills 发送给宿主页 const childSkillIds = (suggestion.children ?? []) .flatMap((item) => item.skill_id) .map((item) => item.trim()) .filter((id): id is string => Boolean(id)); if (childSkillIds.length > 0) { - sendSelectSkill(childSkillIds); + sendSelectSkill( + childSkillIds.map((id) => ({ + id, + name: suggestion.suggestion, + })), + ); return; } if (suggestion.skill_id && suggestion.skill_id.length > 0) { - sendSelectSkill(suggestion.skill_id); + sendSelectSkill( + suggestion.skill_id.map((id) => ({ + id, + name: suggestion.suggestion, + })), + ); return; } // 原有逻辑 diff --git a/frontend/src/core/i18n/locales/en-US.ts b/frontend/src/core/i18n/locales/en-US.ts index cbc15ccf..95b883da 100644 --- a/frontend/src/core/i18n/locales/en-US.ts +++ b/frontend/src/core/i18n/locales/en-US.ts @@ -120,34 +120,34 @@ export const enUS: Translations = { prompt: "Write an academic paper about [topic], including abstract, introduction, body and references.", icon: PenLineIcon, - skill_id: "1245", + children: [{ id: "1245", name: "Paper Writing" }], }, { suggestion: "Report Generation", prompt: "Analyze [topic] in depth and generate a well-structured research report.", icon: MicroscopeIcon, - skill_id: "520", + children: [{ id: "520", name: "Report Generation" }], }, { suggestion: "Copywriting", prompt: "Create a complete planning proposal and promotional copy for [project/event].", icon: ShapesIcon, - skill_id: "409", + children: [{ id: "409", name: "Copywriting" }], }, { suggestion: "Document Processing", prompt: "Process [document] with reading, summarizing, translating or format conversion.", icon: CompassIcon, - skill_id: "5", + children: [{ id: "5", name: "Document Processing" }], }, { suggestion: "Market Research", prompt: "TestingTestingTestingTestingTesting", icon: ShapesIcon, - skill_id: "1216", + children: [{ id: "1216", name: "Market Research" }], }, ], suggestionsCreate: [ diff --git a/frontend/src/core/i18n/locales/types.ts b/frontend/src/core/i18n/locales/types.ts index 8a2cab92..251861be 100644 --- a/frontend/src/core/i18n/locales/types.ts +++ b/frontend/src/core/i18n/locales/types.ts @@ -1,5 +1,11 @@ import type { LucideIcon } from "lucide-react"; +export interface SelectedSkillPayloadItem { + id: string | number; + name: string; +} + + export interface Translations { // Locale meta locale: { @@ -97,7 +103,7 @@ export interface Translations { suggestion: string; prompt: string; icon: LucideIcon; - skill_id?: string; + children: SelectedSkillPayloadItem[]; }[]; suggestionsCreate: ( | { diff --git a/frontend/src/core/i18n/locales/zh-CN.ts b/frontend/src/core/i18n/locales/zh-CN.ts index ebf76b9a..90832e2f 100644 --- a/frontend/src/core/i18n/locales/zh-CN.ts +++ b/frontend/src/core/i18n/locales/zh-CN.ts @@ -117,31 +117,31 @@ export const zhCN: Translations = { prompt: "为[主题/产品]撰写吸引人的自媒体文案,包括标题、正文和话题标签。", icon: PenLineIcon, - skill_id: "1245", + children: [{ id: "1245", name: "自媒体文案" }], }, { suggestion: "需求文档", prompt: "编写[项目/功能]的需求文档,包含功能描述、用户故事和验收标准。", icon: CompassIcon, - skill_id: "520", + children: [{ id: "520", name: "需求文档" }], }, { suggestion: "使用指南", prompt: "编写[产品/功能]的使用指南,包含操作步骤、注意事项和常见问题。", icon: GraduationCapIcon, - skill_id: "409", + children: [{ id: "409", name: "使用指南" }], }, { suggestion: "Excel数据分析", prompt: "对[Excel文件/数据]进行分析,生成数据洞察和可视化建议。", icon: MicroscopeIcon, - skill_id: "5", + children: [{ id: "5", name: "Excel数据分析" }], }, { suggestion: "市场调研", prompt: "针对[行业/产品]进行市场调研,分析市场规模、竞品和趋势。", icon: ShapesIcon, - skill_id: "1216", + children: [{ id: "1216", name: "市场调研" }], }, ], suggestionsCreate: [ diff --git a/frontend/src/core/iframe-messages.ts b/frontend/src/core/iframe-messages.ts index 56eaf49b..b2844051 100644 --- a/frontend/src/core/iframe-messages.ts +++ b/frontend/src/core/iframe-messages.ts @@ -12,7 +12,7 @@ export const POST_MESSAGE_TYPES = { // 会话是否处于聊天态 IS_CHATTING: "isChatting", // 选择预定义 skill - SELECT_SKILL: "selectSkill", + SELECT_SKILL: "selectedSkills", // 打开 skill 选择对话框 OPEN_SKILL_DIALOG: "openSkillDialog", } as const; @@ -42,7 +42,7 @@ export interface IsChattingMessage { export interface SelectSkillMessage { type: typeof POST_MESSAGE_TYPES.SELECT_SKILL; - skill_id: string[]; + selectedSkills: SelectedSkillPayloadItem[]; } export interface OpenSkillDialogMessage { @@ -56,6 +56,11 @@ export interface SelectedSkillMessage { title: string; } +export interface SelectedSkillPayloadItem { + id: string | number; + name: string; +} + type UnknownRecord = Record; function asRecord(value: unknown): UnknownRecord | null { diff --git a/frontend/src/hooks/use-iframe-skill.ts b/frontend/src/hooks/use-iframe-skill.ts index 2533eca6..01b2dd38 100644 --- a/frontend/src/hooks/use-iframe-skill.ts +++ b/frontend/src/hooks/use-iframe-skill.ts @@ -5,6 +5,7 @@ import { POST_MESSAGE_TYPES, RECEIVE_MESSAGE_TYPES, isSelectedSkillMessage, + type SelectedSkillPayloadItem, sendToParent, } from "@/core/iframe-messages"; @@ -17,7 +18,7 @@ interface SkillData { // Hook 返回类型 interface UseIframeSkillReturn { selectedSkill: SkillData | null; - sendSelectSkill: (skill_id: string[]) => void; + sendSelectSkill: (selectedSkills: SelectedSkillPayloadItem[]) => void; openSkillDialog: () => void; clearSkill: () => void; } @@ -68,8 +69,8 @@ export function useIframeSkill(): UseIframeSkillReturn { }, []); // 发送选择预定义 skill - const sendSelectSkill = useCallback((skill_id: string[]) => { - const message = { type: POST_MESSAGE_TYPES.SELECT_SKILL, skill_id }; + const sendSelectSkill = useCallback((selectedSkills: SelectedSkillPayloadItem[]) => { + const message = { type: POST_MESSAGE_TYPES.SELECT_SKILL, selectedSkills }; console.log("[useIframeSkill] sendSelectSkill:", message); sendToParent(message); }, []); @@ -84,12 +85,12 @@ export function useIframeSkill(): UseIframeSkillReturn { sendToParent(message); }, []); - // 清除选中并发送空 skill_id 数组给主页 + // 清除选中并发送空 selectedSkills 数组给主页 const clearSkill = useCallback(() => { setSelectedSkill(null); // 发送空数组给主页,通知取消选择 - const message = { type: POST_MESSAGE_TYPES.SELECT_SKILL, skill_id: [] }; - console.log("[useIframeSkill] clearSkill, sending skill_id=[]:", message); + const message = { type: POST_MESSAGE_TYPES.SELECT_SKILL, selectedSkills: [] }; + console.log("[useIframeSkill] clearSkill, sending selectedSkills=[]:", message); sendToParent(message); }, []);