diff --git a/packages/core/src/extension/claude-converter.ts b/packages/core/src/extension/claude-converter.ts index 28835bc87..fa5cf2ded 100644 --- a/packages/core/src/extension/claude-converter.ts +++ b/packages/core/src/extension/claude-converter.ts @@ -24,6 +24,7 @@ import { stringify as stringifyYaml, } from '../utils/yaml-parser.js'; import { createDebugLogger } from '../utils/debugLogger.js'; +import { normalizeContent } from '../utils/textUtils.js'; const debugLogger = createDebugLogger('CLAUDE_CONVERTER'); @@ -226,10 +227,11 @@ async function convertAgentFiles(agentsDir: string): Promise { try { const content = await fs.promises.readFile(filePath, 'utf-8'); + const normalizedContent = normalizeContent(content); // Parse frontmatter const frontmatterRegex = /^---\n([\s\S]*?)\n---\n([\s\S]*)$/; - const match = content.match(frontmatterRegex); + const match = normalizedContent.match(frontmatterRegex); if (!match) { // No frontmatter, skip this file diff --git a/packages/core/src/skills/skill-load.ts b/packages/core/src/skills/skill-load.ts index dc6f2c616..639b85071 100644 --- a/packages/core/src/skills/skill-load.ts +++ b/packages/core/src/skills/skill-load.ts @@ -3,6 +3,7 @@ import * as fs from 'fs/promises'; import * as path from 'path'; import { parse as parseYaml } from '../utils/yaml-parser.js'; import { createDebugLogger } from '../utils/debugLogger.js'; +import { normalizeContent } from '../utils/textUtils.js'; const debugLogger = createDebugLogger('SKILL_LOAD'); @@ -56,21 +57,6 @@ export async function loadSkillsFromDir( } } -/** - * Normalizes skill file content for consistent parsing across platforms. - * - Strips UTF-8 BOM to ensure frontmatter starts at the first character. - * - Normalizes line endings so skills authored on Windows (CRLF) parse correctly. - */ -function normalizeSkillFileContent(content: string): string { - // Strip UTF-8 BOM to ensure frontmatter starts at the first character. - let normalized = content.replace(/^\uFEFF/, ''); - - // Normalize line endings so skills authored on Windows (CRLF) parse correctly. - normalized = normalized.replace(/\r\n/g, '\n').replace(/\r/g, '\n'); - - return normalized; -} - export function parseSkillContent( content: string, filePath: string, @@ -78,7 +64,7 @@ export function parseSkillContent( debugLogger.debug(`Parsing skill content from: ${filePath}`); // Normalize content to handle BOM and CRLF line endings - const normalizedContent = normalizeSkillFileContent(content); + const normalizedContent = normalizeContent(content); // Split frontmatter and content // Use (?:\n|$) to allow frontmatter ending with or without trailing newline diff --git a/packages/core/src/skills/skill-manager.ts b/packages/core/src/skills/skill-manager.ts index 8ee69e9a0..05eabdd5a 100644 --- a/packages/core/src/skills/skill-manager.ts +++ b/packages/core/src/skills/skill-manager.ts @@ -20,6 +20,7 @@ import { SkillError, SkillErrorCode } from './types.js'; import type { Config } from '../config/config.js'; import { validateConfig } from './skill-load.js'; import { createDebugLogger } from '../utils/debugLogger.js'; +import { normalizeContent } from '../utils/textUtils.js'; const debugLogger = createDebugLogger('SKILL_MANAGER'); @@ -333,7 +334,7 @@ export class SkillManager { level: SkillLevel, ): SkillConfig { try { - const normalizedContent = normalizeSkillFileContent(content); + const normalizedContent = normalizeContent(content); // Split frontmatter and content const frontmatterRegex = /^---\n([\s\S]*?)\n---(?:\n|$)([\s\S]*)$/; @@ -649,13 +650,3 @@ export class SkillManager { } } } - -function normalizeSkillFileContent(content: string): string { - // Strip UTF-8 BOM to ensure frontmatter starts at the first character. - let normalized = content.replace(/^\uFEFF/, ''); - - // Normalize line endings so skills authored on Windows (CRLF) parse correctly. - normalized = normalized.replace(/\r\n/g, '\n').replace(/\r/g, '\n'); - - return normalized; -} diff --git a/packages/core/src/subagents/subagent-manager.ts b/packages/core/src/subagents/subagent-manager.ts index fea33040c..0552fa60c 100644 --- a/packages/core/src/subagents/subagent-manager.ts +++ b/packages/core/src/subagents/subagent-manager.ts @@ -29,6 +29,7 @@ import { SubagentValidator } from './validation.js'; import { SubAgentScope } from './subagent.js'; import type { Config } from '../config/config.js'; import { createDebugLogger } from '../utils/debugLogger.js'; +import { normalizeContent } from '../utils/textUtils.js'; const debugLogger = createDebugLogger('SUBAGENT_MANAGER'); import { BuiltinAgentRegistry } from './builtin-agents.js'; @@ -908,9 +909,11 @@ function parseSubagentContent( validator: SubagentValidator, ): SubagentConfig { try { + const normalizedContent = normalizeContent(content); + // Split frontmatter and content const frontmatterRegex = /^---\n([\s\S]*?)\n---\n([\s\S]*)$/; - const match = content.match(frontmatterRegex); + const match = normalizedContent.match(frontmatterRegex); if (!match) { throw new Error('Invalid format: missing YAML frontmatter');