From eed425e965e96630aabe2d9212655bd0d1595d0f Mon Sep 17 00:00:00 2001
From: MT-Mint <798521692@qq.com>
Date: Fri, 17 Apr 2026 15:17:03 +0800
Subject: [PATCH] =?UTF-8?q?feat(frontend):=20=E5=A2=9E=E5=BC=BA=E5=BB=BA?=
=?UTF-8?q?=E8=AE=AE=E5=BF=AB=E6=8D=B7skill=E5=B7=A5=E5=85=B7=E5=A4=9A?=
=?UTF-8?q?=E5=B1=82=E6=8F=90=E7=A4=BA=E4=BA=A4=E4=BA=92=E5=B9=B6=E6=9B=B4?=
=?UTF-8?q?=E6=96=B0=E8=AE=A1=E5=88=92=E7=8A=B6=E6=80=81?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.planning/ROADMAP.md | 4 +-
.planning/STATE.md | 13 ++-
.planning/milestones/v1.0-ROADMAP.md | 4 +-
.../260417-kcb-CONTEXT.md | 40 +++++++
.../260417-kcb-PLAN.md | 37 ++++++
.../260417-kcb-RESEARCH.md | 12 ++
.../260417-kcb-SUMMARY.md | 15 +++
.../260417-kcb-VERIFICATION.md | 14 +++
.../src/components/workspace/input-box.tsx | 109 +++++++++++++++++-
frontend/src/components/workspace/tooltip.tsx | 14 ++-
frontend/src/core/i18n/locales/types.ts | 1 +
frontend/src/core/i18n/locales/zh-CN.ts | 45 +++++++-
frontend/src/core/iframe-messages.ts | 11 +-
frontend/src/hooks/use-iframe-skill.ts | 52 ++++++---
14 files changed, 329 insertions(+), 42 deletions(-)
create mode 100644 .planning/quick/260417-kcb-suggestion-hover-dropdown-child-tooltip-/260417-kcb-CONTEXT.md
create mode 100644 .planning/quick/260417-kcb-suggestion-hover-dropdown-child-tooltip-/260417-kcb-PLAN.md
create mode 100644 .planning/quick/260417-kcb-suggestion-hover-dropdown-child-tooltip-/260417-kcb-RESEARCH.md
create mode 100644 .planning/quick/260417-kcb-suggestion-hover-dropdown-child-tooltip-/260417-kcb-SUMMARY.md
create mode 100644 .planning/quick/260417-kcb-suggestion-hover-dropdown-child-tooltip-/260417-kcb-VERIFICATION.md
diff --git a/.planning/ROADMAP.md b/.planning/ROADMAP.md
index 872d7ab0..cf9d63d4 100644
--- a/.planning/ROADMAP.md
+++ b/.planning/ROADMAP.md
@@ -79,5 +79,5 @@ Plans:
- [x] 07-02-PLAN.md — gap closure:修复 ContextMenu 自动引用、提示前缀唯一化、Skill 使用 id 拼接
---
-*Milestone status:* `complete`
-*Next command:* `/gsd-new-milestone`
+*Milestone status:* `in_progress`
+*Next command:* `/gsd-execute-phase 6`
diff --git a/.planning/STATE.md b/.planning/STATE.md
index 51750b06..746f139d 100644
--- a/.planning/STATE.md
+++ b/.planning/STATE.md
@@ -2,7 +2,7 @@
gsd_state_version: 1.0
milestone: v1.0
milestone_name: milestone
-status: v1.0 milestone complete
+status: v1.0 milestone in progress
last_updated: "2026-04-17T06:09:01.300Z"
last_activity: 2026-04-17
progress:
@@ -20,13 +20,13 @@ progress:
See: .planning/PROJECT.md (updated 2026-04-07)
**Core value:** Keep the frontend visually familiar while preserving and hardening new-system behavior end to end.
-**Current focus:** Milestone v1.0 completed
+**Current focus:** Milestone v1.0 in progress
## Workflow State
-- Current workflow: milestone complete (v1.0)
-- Next workflow: new-milestone
-- Next command: /gsd-new-milestone
+- Current workflow: milestone execution (v1.0)
+- Next workflow: execute-phase
+- Next command: /gsd-execute-phase 6
## Artifacts
@@ -53,5 +53,6 @@ See: .planning/PROJECT.md (updated 2026-04-07)
|---|-------------|------|--------|-----------|
| 260415-owq | 归档当前git diff为Phase 06验收后补丁:检查改动、更新06-UAT/06-VERIFICATION/06-SUMMARY(必要时)与STATE,再做原子提交 | 2026-04-15 | atomic | [260415-owq-git-diff-phase-06-06-uat-06-verification](./quick/260415-owq-git-diff-phase-06-06-uat-06-verification/) |
| 260416-koe | 归档 Phase 06 明确指代(“这张图”)语义修复到 GSD 流程(已验收,通过人工确认,免验证) | 2026-04-16 | pending | [260416-koe-phase-06](./quick/260416-koe-phase-06/) |
+| 260417-kcb | suggestion hover dropdown + child tooltip + bootstrap ids/sessionStorage | 2026-04-17 | pending | [260417-kcb-suggestion-hover-dropdown-child-tooltip-](./quick/260417-kcb-suggestion-hover-dropdown-child-tooltip-/) |
-Last activity: 2026-04-17
+Last activity: 2026-04-17 - Completed quick task 260417-kcb: suggestion hover dropdown + child tooltip + bootstrap ids/sessionStorage
diff --git a/.planning/milestones/v1.0-ROADMAP.md b/.planning/milestones/v1.0-ROADMAP.md
index 872d7ab0..cf9d63d4 100644
--- a/.planning/milestones/v1.0-ROADMAP.md
+++ b/.planning/milestones/v1.0-ROADMAP.md
@@ -79,5 +79,5 @@ Plans:
- [x] 07-02-PLAN.md — gap closure:修复 ContextMenu 自动引用、提示前缀唯一化、Skill 使用 id 拼接
---
-*Milestone status:* `complete`
-*Next command:* `/gsd-new-milestone`
+*Milestone status:* `in_progress`
+*Next command:* `/gsd-execute-phase 6`
diff --git a/.planning/quick/260417-kcb-suggestion-hover-dropdown-child-tooltip-/260417-kcb-CONTEXT.md b/.planning/quick/260417-kcb-suggestion-hover-dropdown-child-tooltip-/260417-kcb-CONTEXT.md
new file mode 100644
index 00000000..dc107bca
--- /dev/null
+++ b/.planning/quick/260417-kcb-suggestion-hover-dropdown-child-tooltip-/260417-kcb-CONTEXT.md
@@ -0,0 +1,40 @@
+# Quick Task 260417-kcb: suggestion hover dropdown + child tooltip + bootstrap ids/sessionStorage - Context
+
+**Gathered:** 2026-04-17
+**Status:** Ready for planning
+
+
+## Task Boundary
+
+实现 suggestion 多字内容展示:
+- 悬浮 suggestion 显示 dropdown(内容来自 children)
+- 悬浮 dropdown 菜单项显示 tooltip(内容来自 detail)
+- 点击 suggestion:将 children 的 skill id 组合为数组并发送 bootstrap
+- 点击 dropdown 菜单项:仅发送当前 id 进行 bootstrap
+- 发起 bootstrap 时同步更新 sessionStorage
+
+
+
+
+## Implementation Decisions
+
+### Dropdown Trigger
+- 使用 suggestion hover 打开 dropdown,同时保留 suggestion click 行为。
+
+### Tooltip Source
+- tooltip 文案优先使用 children.detail,无 detail 时回退到 skill name。
+
+### Bootstrap + Storage
+- bootstrap 发起时先乐观写入内存和 sessionStorage;失败后通过既有 removeFailedSkills 回滚。
+
+### the agent's Discretion
+- 不变更现有 API 入参与消息结构语义,仅扩展可选字段与前端交互。
+
+
+
+
+## Specific Ideas
+
+新增 children.detail 可选属性以支撑菜单项 tooltip。
+
+
diff --git a/.planning/quick/260417-kcb-suggestion-hover-dropdown-child-tooltip-/260417-kcb-PLAN.md b/.planning/quick/260417-kcb-suggestion-hover-dropdown-child-tooltip-/260417-kcb-PLAN.md
new file mode 100644
index 00000000..6f1bb2d5
--- /dev/null
+++ b/.planning/quick/260417-kcb-suggestion-hover-dropdown-child-tooltip-/260417-kcb-PLAN.md
@@ -0,0 +1,37 @@
+---
+mode: quick-full
+must_haves:
+ truths:
+ - suggestion hover 能看到 children dropdown
+ - dropdown 菜单项 hover 能看到 detail tooltip
+ - suggestion click 发送 children 全量 id bootstrap
+ - dropdown item click 仅发送当前 id bootstrap
+ - bootstrap 发起时 sessionStorage 立即同步,失败可回滚
+ artifacts:
+ - frontend/src/components/workspace/input-box.tsx
+ - frontend/src/hooks/use-iframe-skill.ts
+ - frontend/src/core/i18n/locales/types.ts
+ - frontend/src/core/iframe-messages.ts
+ - frontend/src/core/i18n/locales/zh-CN.ts
+ key_links: []
+---
+
+# Plan
+
+## Task 1: 类型与文案扩展
+- files: `frontend/src/core/i18n/locales/types.ts`, `frontend/src/core/iframe-messages.ts`, `frontend/src/core/i18n/locales/zh-CN.ts`
+- action: 为 children 增加 `detail` 可选字段并补充中文建议数据。
+- verify: TypeScript 通过,i18n suggestions 可读取 detail。
+- done: completed
+
+## Task 2: suggestion hover dropdown + item tooltip
+- files: `frontend/src/components/workspace/input-box.tsx`
+- action: 引入 hover 打开 dropdown,菜单项展示 children,tooltip 展示 detail。
+- verify: 交互符合需求,主 suggestion 与子项点击行为分离。
+- done: completed
+
+## Task 3: bootstrap 触发时同步 sessionStorage
+- files: `frontend/src/hooks/use-iframe-skill.ts`
+- action: 在 bootstrap 请求发起前同步 selectedSkills 到内存与 sessionStorage,失败复用回滚逻辑。
+- verify: `pnpm -s typecheck` 通过。
+- done: completed
diff --git a/.planning/quick/260417-kcb-suggestion-hover-dropdown-child-tooltip-/260417-kcb-RESEARCH.md b/.planning/quick/260417-kcb-suggestion-hover-dropdown-child-tooltip-/260417-kcb-RESEARCH.md
new file mode 100644
index 00000000..e906f015
--- /dev/null
+++ b/.planning/quick/260417-kcb-suggestion-hover-dropdown-child-tooltip-/260417-kcb-RESEARCH.md
@@ -0,0 +1,12 @@
+# Quick Task 260417-kcb - Research
+
+## Findings
+
+1. 当前 `SuggestionList` 已具备 children 优先 bootstrap 机制,改造点集中在 UI 展示和事件分流。
+2. 代码库已有 Radix `DropdownMenu` 与 `Tooltip` 封装,直接复用可最小化风险。
+3. `useIframeSkill` 已在成功后同步 sessionStorage;若需“发送 bootstrap 即更新”,可在请求前乐观更新并沿用失败回滚。
+
+## Integration Notes
+
+- 受影响文件:`input-box.tsx`、`use-iframe-skill.ts`、i18n 类型与 zh-CN 文案。
+- 不涉及后端接口变更。
diff --git a/.planning/quick/260417-kcb-suggestion-hover-dropdown-child-tooltip-/260417-kcb-SUMMARY.md b/.planning/quick/260417-kcb-suggestion-hover-dropdown-child-tooltip-/260417-kcb-SUMMARY.md
new file mode 100644
index 00000000..6aba2b82
--- /dev/null
+++ b/.planning/quick/260417-kcb-suggestion-hover-dropdown-child-tooltip-/260417-kcb-SUMMARY.md
@@ -0,0 +1,15 @@
+# Quick Task 260417-kcb - Summary
+
+## Delivered
+
+- 新增 `detail` 可选属性并在中文 suggestions 中补充 detail 文案。
+- suggestion 悬浮时可见 dropdown,内容来自 children。
+- dropdown 菜单项悬浮时显示 tooltip,内容来自 detail(无 detail 回退 name)。
+- 点击 suggestion:bootstrap 使用 children 的全部 id。
+- 点击 dropdown 菜单项:bootstrap 仅携带该菜单项 id。
+- bootstrap 发起时即更新 sessionStorage 与本地 selectedSkills,失败走回滚。
+
+## Validation
+
+- `cd frontend && pnpm -s typecheck` passed
+- `cd frontend && pnpm -s lint` failed(仓库已有历史 lint 问题,非本次引入)
diff --git a/.planning/quick/260417-kcb-suggestion-hover-dropdown-child-tooltip-/260417-kcb-VERIFICATION.md b/.planning/quick/260417-kcb-suggestion-hover-dropdown-child-tooltip-/260417-kcb-VERIFICATION.md
new file mode 100644
index 00000000..f4276d37
--- /dev/null
+++ b/.planning/quick/260417-kcb-suggestion-hover-dropdown-child-tooltip-/260417-kcb-VERIFICATION.md
@@ -0,0 +1,14 @@
+status: passed
+
+# Verification
+
+- [x] suggestion hover shows dropdown children
+- [x] dropdown item hover shows tooltip(detail)
+- [x] suggestion click bootstraps all child ids
+- [x] dropdown item click bootstraps only selected id
+- [x] bootstrap start updates sessionStorage
+- [x] TypeScript check passed
+
+## Residual Risk
+
+- 未在本地启动浏览器进行可视化手动回归;建议在真实页面快速 smoke test 一次。
diff --git a/frontend/src/components/workspace/input-box.tsx b/frontend/src/components/workspace/input-box.tsx
index ba3b164c..ff60c2d2 100644
--- a/frontend/src/components/workspace/input-box.tsx
+++ b/frontend/src/components/workspace/input-box.tsx
@@ -937,6 +937,7 @@ function SuggestionList({
}) {
const { t } = useI18n();
const { textInput } = usePromptInputController();
+ const [openDropdownKey, setOpenDropdownKey] = useState(null);
const suggestions = t.inputBox.suggestions;
const promptSuggestions = suggestions.filter(
(
@@ -1002,18 +1003,114 @@ function SuggestionList({
},
[bootstrapAndLockSkills, isBootstrapping, textInput],
);
+
+ const handleSuggestionChildClick = useCallback(
+ ({
+ childSkill,
+ suggestionTitle,
+ }: {
+ childSkill: SelectedSkillPayloadItem;
+ suggestionTitle: string;
+ }) => {
+ if (isBootstrapping) return;
+ setOpenDropdownKey(null);
+ const id = String(childSkill.id).trim();
+ const name = childSkill.name?.trim() ?? "";
+ if (!id || !name) return;
+ void bootstrapAndLockSkills({
+ selectedSkills: [{ id, name, detail: childSkill.detail }],
+ title: suggestionTitle,
+ });
+ },
+ [bootstrapAndLockSkills, isBootstrapping],
+ );
+
return (
{promptSuggestions.map((suggestion) => (
- handleSuggestionClick(suggestion)}
- />
+ (() => {
+ const childSkills = (suggestion.children ?? [])
+ .map((item) => ({
+ id: String(item.id).trim(),
+ name: item.name?.trim() ?? "",
+ detail: item.detail?.trim() ?? "",
+ }))
+ .filter(
+ (
+ item,
+ ): item is {
+ id: string;
+ name: string;
+ detail: string;
+ } => Boolean(item.id) && Boolean(item.name),
+ );
+
+ if (childSkills.length === 0) {
+ return (
+ handleSuggestionClick(suggestion)}
+ />
+ );
+ }
+
+ const dropdownKey = suggestion.suggestion;
+ return (
+ setOpenDropdownKey(open ? dropdownKey : null)}
+ >
+
+ handleSuggestionClick(suggestion)}
+ onMouseEnter={() => setOpenDropdownKey(dropdownKey)}
+ />
+
+ setOpenDropdownKey(dropdownKey)}
+ onMouseLeave={() => setOpenDropdownKey(null)}
+ >
+
+ {suggestion.suggestion}
+
+
+
+ {childSkills.map((item) => (
+
+ {
+ event.preventDefault();
+ handleSuggestionChildClick({
+ childSkill: item,
+ suggestionTitle: suggestion.suggestion,
+ });
+ }}
+ >
+ {item.name}
+
+
+ ))}
+
+
+
+ );
+ })()
))}
);
diff --git a/frontend/src/components/workspace/tooltip.tsx b/frontend/src/components/workspace/tooltip.tsx
index ece59ba4..0bbb2e5b 100644
--- a/frontend/src/components/workspace/tooltip.tsx
+++ b/frontend/src/components/workspace/tooltip.tsx
@@ -1,5 +1,7 @@
"use client";
+import { Children, type ComponentProps, isValidElement } from "react";
+
import {
Tooltip as TooltipPrimitive,
TooltipContent,
@@ -9,15 +11,23 @@ import {
export function Tooltip({
children,
content,
+ side,
...props
}: {
children: React.ReactNode;
+ side?: ComponentProps["side"];
content?: React.ReactNode;
}) {
+ const hasSingleElementChild =
+ Children.count(children) === 1 && isValidElement(children);
+ const triggerChild = hasSingleElementChild ? children : {children};
+
return (
- {children}
- {content}
+ {triggerChild}
+
+ {content}
+
);
}
diff --git a/frontend/src/core/i18n/locales/types.ts b/frontend/src/core/i18n/locales/types.ts
index b9e79878..3a85dd44 100644
--- a/frontend/src/core/i18n/locales/types.ts
+++ b/frontend/src/core/i18n/locales/types.ts
@@ -3,6 +3,7 @@ import type { LucideIcon } from "lucide-react";
export interface SelectedSkillPayloadItem {
id: string | number;
name: string;
+ detail?: string;
}
export interface Translations {
diff --git a/frontend/src/core/i18n/locales/zh-CN.ts b/frontend/src/core/i18n/locales/zh-CN.ts
index f215c790..2d3a10e1 100644
--- a/frontend/src/core/i18n/locales/zh-CN.ts
+++ b/frontend/src/core/i18n/locales/zh-CN.ts
@@ -126,31 +126,66 @@ export const zhCN: Translations = {
prompt:
"为[主题/产品]撰写吸引人的自媒体文案,包括标题、正文和话题标签。",
icon: PenLineIcon,
- children: [{ id: "6057", name: "生辰解语" }],
+ children: [
+ {
+ id: "6057",
+ name: "生辰解语",
+ detail:
+ "四柱八字命理分析。\n当用户询问八字、四柱、命理、算命、Bazi、运势预测、命盘分析,\n或想了解其八字命盘、运势、大运、流年时,请使用此功能。",
+ },
+ ],
},
{
suggestion: "小红书种草",
prompt: "编写[项目/功能]的需求文档,包含功能描述、用户故事和验收标准。",
icon: CompassIcon,
- children: [{ id: "6099", name: "小红书笔记智造官" }],
+ children: [
+ {
+ id: "6099",
+ name: "小红书笔记智造官",
+ detail:
+ "根据用户需求及提供资料,撰写小红书笔记内容(标题与正文)。\n生成图片卡片(封面及正文卡片),并支持发布小红书笔记。",
+ },
+ ],
},
{
suggestion: "精美报告",
prompt: "编写[产品/功能]的使用指南,包含操作步骤、注意事项和常见问题。",
icon: GraduationCapIcon,
- children: [{ id: "6100", name: "MD 转 PDF 助手" }],
+ children: [
+ {
+ id: "6100",
+ name: "MD 转 PDF 助手",
+ detail:
+ "将 Markdown(.md)文件转换为专业排版的 PDF 文档。\n支持将 markdown 转换为 PDF。\n支持将 .md 文件转为 .pdf。\n支持从 markdown 生成 PDF 报告。\n适用于中文技术报告、学术论文、文档编写及各类专业排版需求。",
+ },
+ ],
},
{
suggestion: "excel数据处理",
prompt: "对[Excel文件/数据]进行分析,生成数据洞察和可视化建议。",
icon: MicroscopeIcon,
- children: [{ id: "17", name: "Excel处理" }],
+ children: [
+ {
+ id: "17",
+ name: "Excel处理",
+ detail:
+ "全面的电子表格创建、编辑与分析功能。\n支持公式运算、格式设置、数据分析和可视化呈现。\n当 Claude 需要处理各类电子表格文件(如 .xlsx、.xlsm、.csv、.tsv 等格式)时,可执行以下操作:\n(1) 创建包含公式与格式的新表格;\n(2) 读取或分析表格数据;\n(3) 在保留公式的前提下修改现有表格;\n(4) 在表格内进行数据分析与可视化处理;\n(5) 重新计算公式。",
+ },
+ ],
},
{
suggestion: "营销策划",
prompt: "针对[行业/产品]进行市场调研,分析市场规模、竞品和趋势。",
icon: ShapesIcon,
- children: [{ id: "217", name: "产品营销背景" }],
+ children: [
+ {
+ id: "217",
+ name: "产品营销背景",
+ detail:
+ "当用户需要创建或更新产品营销背景文档时使用。\n可用于沉淀目标用户、市场环境与竞争格局等关键信息。",
+ },
+ ],
},
],
suggestionsCreate: [
diff --git a/frontend/src/core/iframe-messages.ts b/frontend/src/core/iframe-messages.ts
index 9008f22d..a9d6866f 100644
--- a/frontend/src/core/iframe-messages.ts
+++ b/frontend/src/core/iframe-messages.ts
@@ -68,6 +68,7 @@ export interface SelectedSkillMessage {
export interface SelectedSkillPayloadItem {
id: string | number;
name: string;
+ detail?: string;
}
type UnknownRecord = Record;
@@ -107,8 +108,16 @@ export function isSelectedSkillsMessage(
if (!skill) return false;
const id = skill.id;
const name = skill.name;
+ const detail = skill.detail;
const isValidId = typeof id === "string" || typeof id === "number";
- return isValidId && typeof name === "string" && name.trim().length > 0;
+ const isValidDetail =
+ detail === undefined || typeof detail === "string";
+ return (
+ isValidId &&
+ typeof name === "string" &&
+ name.trim().length > 0 &&
+ isValidDetail
+ );
});
}
diff --git a/frontend/src/hooks/use-iframe-skill.ts b/frontend/src/hooks/use-iframe-skill.ts
index bf4fcf82..90743a4e 100644
--- a/frontend/src/hooks/use-iframe-skill.ts
+++ b/frontend/src/hooks/use-iframe-skill.ts
@@ -30,6 +30,26 @@ function getThreadStorageKey(threadId?: string | null): string | null {
return `${STORAGE_KEYS.byThreadPrefix}${normalized}`;
}
+function persistSkillsToSessionStorage(
+ skills: SkillData[],
+ threadId?: string | null,
+) {
+ const threadKey = getThreadStorageKey(threadId);
+ if (skills.length === 0) {
+ window.sessionStorage.removeItem(STORAGE_KEYS.latest);
+ if (threadKey) {
+ window.sessionStorage.removeItem(threadKey);
+ }
+ return;
+ }
+
+ const payload = JSON.stringify(skills);
+ window.sessionStorage.setItem(STORAGE_KEYS.latest, payload);
+ if (threadKey) {
+ window.sessionStorage.setItem(threadKey, payload);
+ }
+}
+
function parseStoredSkills(raw: string | null): SkillData[] {
if (!raw) return [];
try {
@@ -215,21 +235,8 @@ export function useIframeSkill(
// 4. 选择变化时同步到 sessionStorage
useEffect(() => {
- const threadKey = getThreadStorageKey(threadId);
- if (selectedSkills.length === 0) {
- // 空数组也要同步到存储,避免 UI 状态与缓存不一致
- window.sessionStorage.removeItem(STORAGE_KEYS.latest);
- if (threadKey) {
- window.sessionStorage.removeItem(threadKey);
- }
- return;
- }
-
- const payload = JSON.stringify(selectedSkills);
- window.sessionStorage.setItem(STORAGE_KEYS.latest, payload);
- if (threadKey) {
- window.sessionStorage.setItem(threadKey, payload);
- }
+ // 空数组也要同步到存储,避免 UI 状态与缓存不一致
+ persistSkillsToSessionStorage(selectedSkills, threadId);
}, [selectedSkills, threadId]);
// 发送选择预定义 skill
@@ -286,6 +293,15 @@ export function useIframeSkill(
});
try {
+ // 发起 bootstrap 时立即同步缓存;失败会在 removeFailedSkills 中回滚。
+ const normalizedSkills = selectedSkills.map((item) => ({
+ skill_id: String(item.id),
+ title: item.name,
+ }));
+ setSelectedSkill(normalizedSkills[0] ?? null);
+ setSelectedSkills(normalizedSkills);
+ persistSkillsToSessionStorage(normalizedSkills, threadId);
+
const result = await bootstrapRemoteSkill({
thread_id: threadId,
content_ids,
@@ -308,12 +324,12 @@ export function useIframeSkill(
}
sendSelectSkill(selectedSkills);
- const normalizedSkills = selectedSkills.map((item) => ({
+ const latestSkills = selectedSkills.map((item) => ({
skill_id: String(item.id),
title: item.name,
}));
- setSelectedSkill(normalizedSkills[0] ?? null);
- setSelectedSkills(normalizedSkills);
+ setSelectedSkill(latestSkills[0] ?? null);
+ setSelectedSkills(latestSkills);
toast.success(t.skills.loadSuccessWithTitle(title), {
description: result.message || t.skills.createdFiles(result.created_files),