feat: fix skill transformation pipeline across all targets (#334)

This commit is contained in:
Trevin Chow
2026-03-21 19:45:20 -07:00
committed by GitHub
parent 0f6448d81c
commit 4087e1df82
33 changed files with 624 additions and 86 deletions

View File

@@ -106,11 +106,15 @@ function convertCommandToSkill(
export function transformContentForCopilot(body: string): string {
let result = body
// 1. Transform Task agent calls
const taskPattern = /^(\s*-?\s*)Task\s+([a-z][a-z0-9-]*)\(([^)]+)\)/gm
// 1. Transform Task agent calls (supports namespaced names like compound-engineering:research:agent-name)
const taskPattern = /^(\s*-?\s*)Task\s+([a-z][a-z0-9:-]*)\(([^)]*)\)/gm
result = result.replace(taskPattern, (_match, prefix: string, agentName: string, args: string) => {
const skillName = normalizeName(agentName)
return `${prefix}Use the ${skillName} skill to: ${args.trim()}`
const finalSegment = agentName.includes(":") ? agentName.split(":").pop()! : agentName
const skillName = normalizeName(finalSegment)
const trimmedArgs = args.trim()
return trimmedArgs
? `${prefix}Use the ${skillName} skill to: ${trimmedArgs}`
: `${prefix}Use the ${skillName} skill`
})
// 2. Transform slash command references (replace colons with hyphens)

View File

@@ -119,15 +119,19 @@ function mapAgentTools(agent: ClaudeAgent): string[] | undefined {
* 2. Task agent calls: Task agent-name(args) → Task agent-name: args
* 3. Agent references: @agent-name → the agent-name droid
*/
function transformContentForDroid(body: string): string {
export function transformContentForDroid(body: string): string {
let result = body
// 1. Transform Task agent calls
// Match: Task repo-research-analyst(feature_description)
const taskPattern = /^(\s*-?\s*)Task\s+([a-z][a-z0-9-]*)\(([^)]+)\)/gm
// Match: Task repo-research-analyst(args) or Task compound-engineering:research:repo-research-analyst(args)
const taskPattern = /^(\s*-?\s*)Task\s+([a-z][a-z0-9:-]*)\(([^)]*)\)/gm
result = result.replace(taskPattern, (_match, prefix: string, agentName: string, args: string) => {
const name = normalizeName(agentName)
return `${prefix}Task ${name}: ${args.trim()}`
const finalSegment = agentName.includes(":") ? agentName.split(":").pop()! : agentName
const name = normalizeName(finalSegment)
const trimmedArgs = args.trim()
return trimmedArgs
? `${prefix}Task ${name}: ${trimmedArgs}`
: `${prefix}Task ${name}`
})
// 2. Transform slash command references

View File

@@ -86,11 +86,15 @@ function convertCommand(command: ClaudeCommand, usedNames: Set<string>): GeminiC
export function transformContentForGemini(body: string): string {
let result = body
// 1. Transform Task agent calls
const taskPattern = /^(\s*-?\s*)Task\s+([a-z][a-z0-9-]*)\(([^)]+)\)/gm
// 1. Transform Task agent calls (supports namespaced names like compound-engineering:research:agent-name)
const taskPattern = /^(\s*-?\s*)Task\s+([a-z][a-z0-9:-]*)\(([^)]*)\)/gm
result = result.replace(taskPattern, (_match, prefix: string, agentName: string, args: string) => {
const skillName = normalizeName(agentName)
return `${prefix}Use the ${skillName} skill to: ${args.trim()}`
const finalSegment = agentName.includes(":") ? agentName.split(":").pop()! : agentName
const skillName = normalizeName(finalSegment)
const trimmedArgs = args.trim()
return trimmedArgs
? `${prefix}Use the ${skillName} skill to: ${trimmedArgs}`
: `${prefix}Use the ${skillName} skill`
})
// 2. Rewrite .claude/ paths to .gemini/

View File

@@ -135,10 +135,15 @@ function convertCommandToSkill(
export function transformContentForKiro(body: string, knownAgentNames: string[] = []): string {
let result = body
// 1. Transform Task agent calls
const taskPattern = /^(\s*-?\s*)Task\s+([a-z][a-z0-9-]*)\(([^)]+)\)/gm
// 1. Transform Task agent calls (supports namespaced names like compound-engineering:research:agent-name)
const taskPattern = /^(\s*-?\s*)Task\s+([a-z][a-z0-9:-]*)\(([^)]*)\)/gm
result = result.replace(taskPattern, (_match, prefix: string, agentName: string, args: string) => {
return `${prefix}Use the use_subagent tool to delegate to the ${normalizeName(agentName)} agent: ${args.trim()}`
const finalSegment = agentName.includes(":") ? agentName.split(":").pop()! : agentName
const agentRef = normalizeName(finalSegment)
const trimmedArgs = args.trim()
return trimmedArgs
? `${prefix}Use the use_subagent tool to delegate to the ${agentRef} agent: ${trimmedArgs}`
: `${prefix}Use the use_subagent tool to delegate to the ${agentRef} agent`
})
// 2. Rewrite .claude/ paths to .kiro/ (with word-boundary-like lookbehind)

View File

@@ -90,16 +90,19 @@ function convertAgent(agent: ClaudeAgent, usedNames: Set<string>): PiGeneratedSk
}
}
function transformContentForPi(body: string): string {
export function transformContentForPi(body: string): string {
let result = body
// Task repo-research-analyst(feature_description)
// Task repo-research-analyst(feature_description) or Task compound-engineering:research:repo-research-analyst(args)
// -> Run subagent with agent="repo-research-analyst" and task="feature_description"
const taskPattern = /^(\s*-?\s*)Task\s+([a-z][a-z0-9-]*)\(([^)]+)\)/gm
const taskPattern = /^(\s*-?\s*)Task\s+([a-z][a-z0-9:-]*)\(([^)]*)\)/gm
result = result.replace(taskPattern, (_match, prefix: string, agentName: string, args: string) => {
const skillName = normalizeName(agentName)
const finalSegment = agentName.includes(":") ? agentName.split(":").pop()! : agentName
const skillName = normalizeName(finalSegment)
const trimmedArgs = args.trim().replace(/\s+/g, " ")
return `${prefix}Run subagent with agent=\"${skillName}\" and task=\"${trimmedArgs}\".`
return trimmedArgs
? `${prefix}Run subagent with agent=\"${skillName}\" and task=\"${trimmedArgs}\".`
: `${prefix}Run subagent with agent=\"${skillName}\".`
})
// Claude-specific tool references

View File

@@ -122,10 +122,15 @@ export function transformContentForWindsurf(body: string, knownAgentNames: strin
// In Windsurf, @skill-name is the native invocation syntax for skills.
// Since agents are now mapped to skills, @agent-name already works correctly.
// 4. Transform Task agent calls to skill references
const taskPattern = /^(\s*-?\s*)Task\s+([a-z][a-z0-9-]*)\(([^)]+)\)/gm
// 4. Transform Task agent calls to skill references (supports namespaced names)
const taskPattern = /^(\s*-?\s*)Task\s+([a-z][a-z0-9:-]*)\(([^)]*)\)/gm
result = result.replace(taskPattern, (_match, prefix: string, agentName: string, args: string) => {
return `${prefix}Use the @${normalizeName(agentName)} skill: ${args.trim()}`
const finalSegment = agentName.includes(":") ? agentName.split(":").pop()! : agentName
const skillRef = normalizeName(finalSegment)
const trimmedArgs = args.trim()
return trimmedArgs
? `${prefix}Use the @${skillRef} skill: ${trimmedArgs}`
: `${prefix}Use the @${skillRef} skill`
})
return result