diff --git a/extensions/migrate-claude/provider.test.ts b/extensions/migrate-claude/provider.test.ts index 01bb4440f6d..7d8167f883a 100644 --- a/extensions/migrate-claude/provider.test.ts +++ b/extensions/migrate-claude/provider.test.ts @@ -133,7 +133,11 @@ describe("Claude migration provider", () => { }, }), ); - await writeFile(path.join(source, ".claude", "commands", "ship.md"), "Ship $ARGUMENTS\n"); + const commandDescriptionPrefix = "a".repeat(179); + await writeFile( + path.join(source, ".claude", "commands", "ship.md"), + `${commandDescriptionPrefix}😀tail\n`, + ); await writeFile(path.join(source, ".claude", "skills", "Review", "SKILL.md"), "# Review\n"); const config = { @@ -169,9 +173,13 @@ describe("Claude migration provider", () => { expect(await fs.readFile(path.join(workspaceDir, "AGENTS.md"), "utf8")).toContain( "Imported from Claude: project CLAUDE.md", ); - await expect( - fs.access(path.join(workspaceDir, "skills", "claude-command-ship", "SKILL.md")), - ).resolves.toBeUndefined(); + const generatedSkill = await fs.readFile( + path.join(workspaceDir, "skills", "claude-command-ship", "SKILL.md"), + "utf8", + ); + expect(generatedSkill.split("\n").find((line) => line.startsWith("description: "))).toBe( + `description: ${JSON.stringify(commandDescriptionPrefix)}`, + ); await expect( fs.access(path.join(workspaceDir, "skills", "review", "SKILL.md")), ).resolves.toBeUndefined(); diff --git a/extensions/migrate-claude/skills.ts b/extensions/migrate-claude/skills.ts index 792928b124f..3db062dd4f4 100644 --- a/extensions/migrate-claude/skills.ts +++ b/extensions/migrate-claude/skills.ts @@ -9,6 +9,7 @@ import { MIGRATION_REASON_TARGET_EXISTS, } from "openclaw/plugin-sdk/migration"; import type { MigrationItem } from "openclaw/plugin-sdk/plugin-entry"; +import { truncateUtf16Safe } from "openclaw/plugin-sdk/text-utility-runtime"; import { exists, readText, sanitizeName } from "./helpers.js"; import type { ClaudeSource } from "./source.js"; import type { PlannedTargets } from "./targets.js"; @@ -153,7 +154,7 @@ function generatedCommandSkillContent(params: { return [ "---", `name: ${params.skillName}`, - `description: ${JSON.stringify(description.slice(0, 180))}`, + `description: ${JSON.stringify(truncateUtf16Safe(description, 180))}`, "disable-model-invocation: true", "---", "",