diff --git a/frontend/src/core/skills/api.test.ts b/frontend/src/core/skills/api.test.ts deleted file mode 100644 index 0aecc289..00000000 --- a/frontend/src/core/skills/api.test.ts +++ /dev/null @@ -1,34 +0,0 @@ -import assert from "node:assert/strict"; -import test from "node:test"; - -const { normalizeBootstrapRemoteSkillRequest } = await import( - new URL("./normalize-bootstrap.ts", import.meta.url).href -); - -void test("keeps content_ids as primary contract", () => { - const normalized = normalizeBootstrapRemoteSkillRequest({ - thread_id: "t1", - content_ids: [11, 22], - }); - - assert.deepEqual(normalized.content_ids, [11, 22]); -}); - -void test("maps legacy content_id to content_ids for compatibility", () => { - const normalized = normalizeBootstrapRemoteSkillRequest({ - thread_id: "t1", - content_id: 7, - }); - - assert.deepEqual(normalized.content_ids, [7]); -}); - -void test("throws when neither content_ids nor content_id is provided", () => { - assert.throws( - () => - normalizeBootstrapRemoteSkillRequest({ - thread_id: "t1", - }), - /content_ids is required/, - ); -}); diff --git a/frontend/src/core/skills/api.ts b/frontend/src/core/skills/api.ts index 049eb7f8..0b12b90f 100644 --- a/frontend/src/core/skills/api.ts +++ b/frontend/src/core/skills/api.ts @@ -1,9 +1,6 @@ import { getBackendBaseURL } from "@/core/config"; -import { - normalizeBootstrapRemoteSkillRequest, -} from "./normalize-bootstrap"; -import type { Skill } from "./types"; +import type { Skill } from "./type"; export async function loadSkills() { const skills = await fetch(`${getBackendBaseURL()}/api/skills`); @@ -38,6 +35,7 @@ export interface InstallSkillResponse { message: string; } +// [移植自 main 分支 ef9a071] 添加 skill yaml 解析和远程 skill 初始化 API export interface MaterializeSkillYamlRequest { thread_id: string; path: string; @@ -55,9 +53,7 @@ export interface MaterializeSkillYamlResponse { export interface BootstrapRemoteSkillRequest { thread_id: string; - content_ids?: number[]; - // Legacy input, kept for minimal compatibility at the API boundary. - content_id?: number; + content_id: number; language_type?: number; target_dir?: string; clear_target?: boolean; @@ -98,9 +94,14 @@ export async function installSkill( return response.json(); } +// [移植自 main 分支 ef9a071] 解析 skill.yaml 文件并创建目录结构 export async function materializeSkillYaml( request: MaterializeSkillYamlRequest, ): Promise { + console.log("[skills/api] ========== materializeSkillYaml START =========="); + console.log("[skills/api] request:", JSON.stringify(request, null, 2)); + console.log("[skills/api] API URL:", `${getBackendBaseURL()}/api/skills/materialize-yaml`); + const response = await fetch( `${getBackendBaseURL()}/api/skills/materialize-yaml`, { @@ -112,20 +113,35 @@ export async function materializeSkillYaml( }, ); + console.log("[skills/api] response status:", response.status, response.statusText); + if (!response.ok) { const errorData = await response.json().catch(() => ({})); const errorMessage = errorData.detail ?? `HTTP ${response.status}: ${response.statusText}`; + console.error("[skills/api] materializeSkillYaml FAILED:", errorMessage); + console.error("[skills/api] error data:", errorData); throw new Error(errorMessage); } - return response.json(); + const result = await response.json(); + console.log("[skills/api] materializeSkillYaml SUCCESS:", result); + console.log("[skills/api] ========== materializeSkillYaml END =========="); + return result; } +// [移植自 main 分支 ef9a071] 从远程平台获取 skill 并初始化 export async function bootstrapRemoteSkill( request: BootstrapRemoteSkillRequest, ): Promise { - const normalizedRequest = normalizeBootstrapRemoteSkillRequest(request); + console.log("[skills/api] ========== bootstrapRemoteSkill START =========="); + console.log("[skills/api] request:", JSON.stringify(request, null, 2)); + console.log("[skills/api] thread_id:", request.thread_id); + console.log("[skills/api] content_id:", request.content_id); + console.log("[skills/api] language_type:", request.language_type); + console.log("[skills/api] target_dir:", request.target_dir); + console.log("[skills/api] API URL:", `${getBackendBaseURL()}/api/skills/bootstrap-remote`); + const response = await fetch( `${getBackendBaseURL()}/api/skills/bootstrap-remote`, { @@ -133,16 +149,26 @@ export async function bootstrapRemoteSkill( headers: { "Content-Type": "application/json", }, - body: JSON.stringify(normalizedRequest), + body: JSON.stringify(request), }, ); + console.log("[skills/api] response status:", response.status, response.statusText); + if (!response.ok) { const errorData = await response.json().catch(() => ({})); const errorMessage = errorData.detail ?? `HTTP ${response.status}: ${response.statusText}`; + console.error("[skills/api] bootstrapRemoteSkill FAILED:", errorMessage); + console.error("[skills/api] error data:", errorData); throw new Error(errorMessage); } - return response.json(); + const result = await response.json(); + console.log("[skills/api] bootstrapRemoteSkill SUCCESS:", result); + console.log("[skills/api] created_directories:", result.created_directories); + console.log("[skills/api] created_files:", result.created_files); + console.log("[skills/api] sandbox_id:", result.sandbox_id); + console.log("[skills/api] ========== bootstrapRemoteSkill END =========="); + return result; } diff --git a/frontend/src/core/skills/normalize-bootstrap.ts b/frontend/src/core/skills/normalize-bootstrap.ts deleted file mode 100644 index 236cf62f..00000000 --- a/frontend/src/core/skills/normalize-bootstrap.ts +++ /dev/null @@ -1,44 +0,0 @@ -export interface BootstrapRemoteSkillRequestLike { - thread_id: string; - content_ids?: number[]; - content_id?: number; - language_type?: number; - target_dir?: string; - clear_target?: boolean; -} - -export interface NormalizedBootstrapRemoteSkillRequest - extends Omit { - content_ids: number[]; -} - -export function normalizeBootstrapRemoteSkillRequest( - request: BootstrapRemoteSkillRequestLike, -): NormalizedBootstrapRemoteSkillRequest { - const normalizedContentIds = Array.isArray(request.content_ids) - ? request.content_ids - .map((id) => Number(id)) - .filter((id) => Number.isFinite(id) && id > 0) - : []; - - const legacyContentId = - request.content_id != null && Number.isFinite(Number(request.content_id)) - ? Number(request.content_id) - : undefined; - - const contentIds = - normalizedContentIds.length > 0 - ? normalizedContentIds - : legacyContentId != null - ? [legacyContentId] - : []; - - if (contentIds.length === 0) { - throw new Error("content_ids is required."); - } - - return { - ...request, - content_ids: contentIds, - }; -} diff --git a/frontend/src/core/skills/types.ts b/frontend/src/core/skills/types.ts deleted file mode 100644 index 79424fdc..00000000 --- a/frontend/src/core/skills/types.ts +++ /dev/null @@ -1 +0,0 @@ -export type { Skill } from "./type"; diff --git a/frontend/src/hooks/use-selected-skill-listener.ts b/frontend/src/hooks/use-selected-skill-listener.ts index 6769d971..313a6cfd 100644 --- a/frontend/src/hooks/use-selected-skill-listener.ts +++ b/frontend/src/hooks/use-selected-skill-listener.ts @@ -79,7 +79,7 @@ export function useSelectedSkillListener({ try { const result = await bootstrapRemoteSkill({ thread_id: threadId, - content_ids: [Number(id)], + content_id: Number(id), language_type: languageType, target_dir: "/mnt/user-data/uploads/skill", clear_target: true,