diff --git a/.github/workflows/mattpocock-skills-reviewer.lock.yml b/.github/workflows/mattpocock-skills-reviewer.lock.yml index 8eab732c87d..3f016644d9a 100644 --- a/.github/workflows/mattpocock-skills-reviewer.lock.yml +++ b/.github/workflows/mattpocock-skills-reviewer.lock.yml @@ -295,6 +295,8 @@ jobs: - name: Install frontmatter skill 1 env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GH_AW_INFO_ENGINE_ID: "copilot" + GH_AW_GH_SKILL_AGENT_NAME: "github-copilot" GH_AW_SKILL_DIR: ".github/skills" GH_AW_FRONTMATTER_SKILLS: "mattpocock/skills/diagnosing-bugs@801dca688564c529fa84f247f64472520d9ebe28" uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 @@ -307,6 +309,8 @@ jobs: - name: Install frontmatter skill 2 env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GH_AW_INFO_ENGINE_ID: "copilot" + GH_AW_GH_SKILL_AGENT_NAME: "github-copilot" GH_AW_SKILL_DIR: ".github/skills" GH_AW_FRONTMATTER_SKILLS: "mattpocock/skills/tdd@801dca688564c529fa84f247f64472520d9ebe28" uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 @@ -319,6 +323,8 @@ jobs: - name: Install frontmatter skill 3 env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GH_AW_INFO_ENGINE_ID: "copilot" + GH_AW_GH_SKILL_AGENT_NAME: "github-copilot" GH_AW_SKILL_DIR: ".github/skills" GH_AW_FRONTMATTER_SKILLS: "mattpocock/skills/improve-codebase-architecture@801dca688564c529fa84f247f64472520d9ebe28" uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 @@ -331,6 +337,8 @@ jobs: - name: Install frontmatter skill 4 env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GH_AW_INFO_ENGINE_ID: "copilot" + GH_AW_GH_SKILL_AGENT_NAME: "github-copilot" GH_AW_SKILL_DIR: ".github/skills" GH_AW_FRONTMATTER_SKILLS: "mattpocock/skills/grill-with-docs@801dca688564c529fa84f247f64472520d9ebe28" uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 @@ -343,6 +351,8 @@ jobs: - name: Install frontmatter skill 5 env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GH_AW_INFO_ENGINE_ID: "copilot" + GH_AW_GH_SKILL_AGENT_NAME: "github-copilot" GH_AW_SKILL_DIR: ".github/skills" GH_AW_FRONTMATTER_SKILLS: "mattpocock/skills/to-prd@801dca688564c529fa84f247f64472520d9ebe28" uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 @@ -355,6 +365,8 @@ jobs: - name: Install frontmatter skill 6 env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GH_AW_INFO_ENGINE_ID: "copilot" + GH_AW_GH_SKILL_AGENT_NAME: "github-copilot" GH_AW_SKILL_DIR: ".github/skills" GH_AW_FRONTMATTER_SKILLS: "mattpocock/skills/codebase-design@801dca688564c529fa84f247f64472520d9ebe28" uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 @@ -367,6 +379,8 @@ jobs: - name: Install frontmatter skill 7 env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GH_AW_INFO_ENGINE_ID: "copilot" + GH_AW_GH_SKILL_AGENT_NAME: "github-copilot" GH_AW_SKILL_DIR: ".github/skills" GH_AW_FRONTMATTER_SKILLS: "mattpocock/skills/domain-modeling@801dca688564c529fa84f247f64472520d9ebe28" uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 diff --git a/actions/setup/js/install_frontmatter_skills.cjs b/actions/setup/js/install_frontmatter_skills.cjs index b67aec9b659..ec0a5240f36 100644 --- a/actions/setup/js/install_frontmatter_skills.cjs +++ b/actions/setup/js/install_frontmatter_skills.cjs @@ -22,33 +22,35 @@ function parseSkillSpecs(rawSkills) { /** * @param {string} skillSpec * @param {string} skillsDst + * @param {string} skillInstallAgent * @returns {SkillInstallCommand} */ -function buildSkillInstallCommand(skillSpec, skillsDst) { +function buildSkillInstallCommand(skillSpec, skillsDst, skillInstallAgent = "") { const atIndex = skillSpec.lastIndexOf("@"); const hasPin = atIndex >= 0; const skillBase = hasPin ? skillSpec.slice(0, atIndex) : skillSpec; const skillRef = hasPin ? skillSpec.slice(atIndex + 1) : ""; const parts = skillBase.split("/"); const pinArgs = skillRef ? ["--pin", skillRef] : []; + const agentArgs = skillInstallAgent ? ["--agent", skillInstallAgent] : []; if (parts.length >= 3) { return { displaySpec: skillSpec, - args: ["skill", "install", `${parts[0]}/${parts[1]}`, parts.slice(2).join("/"), ...pinArgs, "--dir", skillsDst, "--force"], + args: ["skill", "install", `${parts[0]}/${parts[1]}`, parts.slice(2).join("/"), ...pinArgs, ...agentArgs, "--dir", skillsDst, "--force"], }; } if (parts.length === 2) { return { displaySpec: skillSpec, - args: ["skill", "install", skillBase, "--all", ...pinArgs, "--dir", skillsDst, "--force"], + args: ["skill", "install", skillBase, "--all", ...pinArgs, ...agentArgs, "--dir", skillsDst, "--force"], }; } return { displaySpec: skillSpec, - args: ["skill", "install", skillSpec, "--dir", skillsDst, "--force"], + args: ["skill", "install", skillSpec, ...agentArgs, "--dir", skillsDst, "--force"], }; } @@ -139,12 +141,16 @@ async function writeSkillSummary(skillDir, skills, installedSkillCount, failures async function main() { const skillDir = process.env.GH_AW_SKILL_DIR || ""; + const skillInstallAgent = process.env.GH_AW_GH_SKILL_AGENT_NAME || ""; const skills = parseSkillSpecs(process.env.GH_AW_FRONTMATTER_SKILLS || ""); const skillsDst = path.join("/tmp/gh-aw", skillDir); fs.mkdirSync(skillsDst, { recursive: true }); core.info(`Installing frontmatter skills to ${skillsDst}`); + if (skillInstallAgent) { + core.info(`Installing frontmatter skills for gh skill agent ${skillInstallAgent}`); + } core.info("Existing skills at destination may be replaced (--force) to ensure pinned refs are up to date"); /** @type {Array<{skill: string; error: string}>} */ @@ -152,7 +158,7 @@ async function main() { for (const skillSpec of skills) { core.info(`Installing skill reference: ${skillSpec}`); - const command = buildSkillInstallCommand(skillSpec, skillsDst); + const command = buildSkillInstallCommand(skillSpec, skillsDst, skillInstallAgent); try { await exec.exec("gh", command.args); } catch (err) { diff --git a/actions/setup/js/install_frontmatter_skills.test.cjs b/actions/setup/js/install_frontmatter_skills.test.cjs index 81cf0eb679c..48c38921fcf 100644 --- a/actions/setup/js/install_frontmatter_skills.test.cjs +++ b/actions/setup/js/install_frontmatter_skills.test.cjs @@ -16,6 +16,8 @@ describe("install_frontmatter_skills", () => { beforeEach(() => { originalEnv = { GH_AW_SKILL_DIR: process.env.GH_AW_SKILL_DIR, + GH_AW_INFO_ENGINE_ID: process.env.GH_AW_INFO_ENGINE_ID, + GH_AW_GH_SKILL_AGENT_NAME: process.env.GH_AW_GH_SKILL_AGENT_NAME, GH_AW_FRONTMATTER_SKILLS: process.env.GH_AW_FRONTMATTER_SKILLS, }; originalCore = global.core; @@ -41,6 +43,16 @@ describe("install_frontmatter_skills", () => { } else { process.env.GH_AW_SKILL_DIR = originalEnv.GH_AW_SKILL_DIR; } + if (originalEnv.GH_AW_INFO_ENGINE_ID === undefined) { + delete process.env.GH_AW_INFO_ENGINE_ID; + } else { + process.env.GH_AW_INFO_ENGINE_ID = originalEnv.GH_AW_INFO_ENGINE_ID; + } + if (originalEnv.GH_AW_GH_SKILL_AGENT_NAME === undefined) { + delete process.env.GH_AW_GH_SKILL_AGENT_NAME; + } else { + process.env.GH_AW_GH_SKILL_AGENT_NAME = originalEnv.GH_AW_GH_SKILL_AGENT_NAME; + } if (originalEnv.GH_AW_FRONTMATTER_SKILLS === undefined) { delete process.env.GH_AW_FRONTMATTER_SKILLS; } else { @@ -54,7 +66,19 @@ describe("install_frontmatter_skills", () => { }); it("splits repo-level and path-level skill specs into gh skill install arguments", () => { - expect(script.buildSkillInstallCommand("githubnext/skills@abc123", "/tmp/gh-aw/.claude/skills").args).toEqual(["skill", "install", "githubnext/skills", "--all", "--pin", "abc123", "--dir", "/tmp/gh-aw/.claude/skills", "--force"]); + expect(script.buildSkillInstallCommand("githubnext/skills@abc123", "/tmp/gh-aw/.claude/skills", "claude-code").args).toEqual([ + "skill", + "install", + "githubnext/skills", + "--all", + "--pin", + "abc123", + "--agent", + "claude-code", + "--dir", + "/tmp/gh-aw/.claude/skills", + "--force", + ]); expect(script.buildSkillInstallCommand("githubnext/skills/review/security@abc123", "/tmp/gh-aw/.claude/skills").args).toEqual([ "skill", "install", @@ -66,6 +90,19 @@ describe("install_frontmatter_skills", () => { "/tmp/gh-aw/.claude/skills", "--force", ]); + expect(script.buildSkillInstallCommand("githubnext/skills/review/security@abc123", "/tmp/gh-aw/.claude/skills", "claude-code").args).toEqual([ + "skill", + "install", + "githubnext/skills", + "review/security", + "--pin", + "abc123", + "--agent", + "claude-code", + "--dir", + "/tmp/gh-aw/.claude/skills", + "--force", + ]); }); it("omits --pin when the resolved skill spec is unpinned", () => { @@ -74,19 +111,30 @@ describe("install_frontmatter_skills", () => { it("reads skill specs from the env var and installs them at runtime", async () => { process.env.GH_AW_SKILL_DIR = ".claude/skills"; + process.env.GH_AW_INFO_ENGINE_ID = "claude"; + process.env.GH_AW_GH_SKILL_AGENT_NAME = "claude-code"; process.env.GH_AW_FRONTMATTER_SKILLS = ["githubnext/skills@abc123", "githubnext/skills/review/security@def456", "${{ inputs.skill_ref }}"].join("\n"); fs.mkdirSync("/tmp/gh-aw/.claude/skills/example", { recursive: true }); fs.writeFileSync("/tmp/gh-aw/.claude/skills/example/SKILL.md", "# test\n", "utf8"); await script.main(); - expect(global.exec.exec).toHaveBeenNthCalledWith(1, "gh", ["skill", "install", "githubnext/skills", "--all", "--pin", "abc123", "--dir", "/tmp/gh-aw/.claude/skills", "--force"]); - expect(global.exec.exec).toHaveBeenNthCalledWith(2, "gh", ["skill", "install", "githubnext/skills", "review/security", "--pin", "def456", "--dir", "/tmp/gh-aw/.claude/skills", "--force"]); - expect(global.exec.exec).toHaveBeenNthCalledWith(3, "gh", ["skill", "install", "${{ inputs.skill_ref }}", "--dir", "/tmp/gh-aw/.claude/skills", "--force"]); + expect(global.exec.exec).toHaveBeenNthCalledWith(1, "gh", ["skill", "install", "githubnext/skills", "--all", "--pin", "abc123", "--agent", "claude-code", "--dir", "/tmp/gh-aw/.claude/skills", "--force"]); + expect(global.exec.exec).toHaveBeenNthCalledWith(2, "gh", ["skill", "install", "githubnext/skills", "review/security", "--pin", "def456", "--agent", "claude-code", "--dir", "/tmp/gh-aw/.claude/skills", "--force"]); + expect(global.exec.exec).toHaveBeenNthCalledWith(3, "gh", ["skill", "install", "${{ inputs.skill_ref }}", "--agent", "claude-code", "--dir", "/tmp/gh-aw/.claude/skills", "--force"]); expect(global.core.summary.addRaw).toHaveBeenCalledWith(expect.stringContaining("### Frontmatter skills installed")); expect(global.core.summary.addRaw).toHaveBeenCalledWith(expect.stringContaining('["githubnext/skills@abc123","githubnext/skills/review/security@def456","${{ inputs.skill_ref }}"]')); }); + it("omits --agent when no gh skill agent name is provided", async () => { + process.env.GH_AW_SKILL_DIR = ".claude/skills"; + process.env.GH_AW_FRONTMATTER_SKILLS = "githubnext/skills@abc123"; + + await script.main(); + + expect(global.exec.exec).toHaveBeenCalledWith("gh", ["skill", "install", "githubnext/skills", "--all", "--pin", "abc123", "--dir", "/tmp/gh-aw/.claude/skills", "--force"]); + }); + it("records failures without throwing when skill install fails", async () => { process.env.GH_AW_SKILL_DIR = ".claude/skills"; process.env.GH_AW_FRONTMATTER_SKILLS = "bad/repo@abc123"; diff --git a/pkg/workflow/activation_skills_step_test.go b/pkg/workflow/activation_skills_step_test.go index 84268ab2ee5..c265080a956 100644 --- a/pkg/workflow/activation_skills_step_test.go +++ b/pkg/workflow/activation_skills_step_test.go @@ -38,6 +38,8 @@ func TestBuildActivationJob_AddsFrontmatterSkillsInstallSteps(t *testing.T) { assert.Contains(t, steps, "ensure_gh_cli_min_version.sh", "expected gh upgrade step to delegate to ensure_gh_cli_min_version.sh") assert.Contains(t, steps, "Install frontmatter skill 1", "expected first frontmatter skill install step in activation job") assert.Contains(t, steps, "Install frontmatter skill 2", "expected second frontmatter skill install step in activation job") + assert.Contains(t, steps, "GH_AW_INFO_ENGINE_ID: \"claude\"", "expected engine id env var for gh skill agent mapping") + assert.Contains(t, steps, "GH_AW_GH_SKILL_AGENT_NAME: \"claude-code\"", "expected gh skill agent env var for claude") assert.Contains(t, steps, "GH_AW_SKILL_DIR: \".claude/skills\"", "expected engine skill directory env var") assert.Contains(t, steps, "GH_AW_FRONTMATTER_SKILLS: \"githubnext/skills@1f181b37d3fe5862ab590648f25a292e345b5de6\"", "expected first skill env var") assert.Contains(t, steps, "GH_AW_FRONTMATTER_SKILLS: \"githubnext/skills/review/security@1f181b37d3fe5862ab590648f25a292e345b5de6\"", "expected second skill env var") @@ -80,11 +82,59 @@ func TestBuildActivationJob_AddsPerSkillAuthSteps(t *testing.T) { steps := strings.Join(job.Steps, "") assert.Contains(t, steps, "GH_TOKEN: ${{ secrets.SKILL_PAT }}", "expected first skill install step to use per-skill github-token") + assert.Contains(t, steps, "GH_AW_INFO_ENGINE_ID: \"copilot\"", "expected AI fallback engine id env var for gh skill agent mapping") + assert.Contains(t, steps, "GH_AW_GH_SKILL_AGENT_NAME: \"github-copilot\"", "expected gh skill agent env var for copilot fallback") assert.Contains(t, steps, "Generate GitHub App token for frontmatter skill 2", "expected app token mint step for second skill") assert.Contains(t, steps, "id: frontmatter-skill-app-token-2", "expected deterministic app token step id") assert.Contains(t, steps, "GH_TOKEN: ${{ steps.frontmatter-skill-app-token-2.outputs.token }}", "expected second skill install step to use minted app token") } +func TestBuildActivationJob_DefaultsSkillInstallEngineToCopilot(t *testing.T) { + compiler := NewCompiler(WithVersion("dev")) + compiler.SetActionMode(ActionModeDev) + + data := &WorkflowData{ + Name: "skills-workflow", + On: `"on": + workflow_dispatch:`, + Skills: []string{ + "githubnext/skills@1f181b37d3fe5862ab590648f25a292e345b5de6", + }, + } + + job, err := compiler.buildActivationJob(data, false, "", "skills.lock.yml") + require.NoError(t, err) + require.NotNil(t, job) + + steps := strings.Join(job.Steps, "") + assert.Contains(t, steps, "GH_AW_INFO_ENGINE_ID: \"copilot\"", "expected default engine id env var for frontmatter skill installs") + assert.Contains(t, steps, "GH_AW_GH_SKILL_AGENT_NAME: \"github-copilot\"", "expected default gh skill agent env var for frontmatter skill installs") + assert.Contains(t, steps, "GH_AW_SKILL_DIR: \".github/skills\"", "expected default engine skill directory env var") +} + +func TestBuildActivationJob_UsesLegacyAIEngineForSkillArtifactPath(t *testing.T) { + compiler := NewCompiler(WithVersion("dev")) + compiler.SetActionMode(ActionModeDev) + + data := &WorkflowData{ + Name: "skills-workflow", + On: `"on": + workflow_dispatch:`, + AI: "claude", + Skills: []string{ + "githubnext/skills@1f181b37d3fe5862ab590648f25a292e345b5de6", + }, + } + + job, err := compiler.buildActivationJob(data, false, "", "skills.lock.yml") + require.NoError(t, err) + require.NotNil(t, job) + + steps := strings.Join(job.Steps, "") + assert.Contains(t, steps, "/tmp/gh-aw/.claude/skills", "expected activation artifact upload to include the legacy ai engine skill directory") + assert.NotContains(t, steps, "/tmp/gh-aw/.github/skills", "expected legacy ai workflows to avoid the default copilot skill directory") +} + func TestBuildActivationJob_AppIgnoreIfMissingFallsBackToActivationToken(t *testing.T) { compiler := NewCompiler(WithVersion("dev")) compiler.SetActionMode(ActionModeDev) diff --git a/pkg/workflow/agentic_engine.go b/pkg/workflow/agentic_engine.go index 70d5f46ca3d..38b8900bc31 100644 --- a/pkg/workflow/agentic_engine.go +++ b/pkg/workflow/agentic_engine.go @@ -100,6 +100,10 @@ type Engine interface { // IsExperimental returns true if this engine is experimental IsExperimental() bool + + // GetGHSkillAgentName returns the gh skill --agent value for this engine. + // Returns an empty string when gh skill install does not support the engine. + GetGHSkillAgentName() string } // EngineCapabilities captures optional engine features. @@ -314,6 +318,7 @@ type BaseEngine struct { displayName string description string experimental bool + ghSkillAgentName string capabilities EngineCapabilities dedicatedLLMGatewayPort int } @@ -334,6 +339,10 @@ func (e *BaseEngine) IsExperimental() bool { return e.experimental } +func (e *BaseEngine) GetGHSkillAgentName() string { + return e.ghSkillAgentName +} + func (e *BaseEngine) GetCapabilities() EngineCapabilities { return e.capabilities } diff --git a/pkg/workflow/antigravity_engine.go b/pkg/workflow/antigravity_engine.go index 1b304e3d483..6af5458e6b1 100644 --- a/pkg/workflow/antigravity_engine.go +++ b/pkg/workflow/antigravity_engine.go @@ -19,10 +19,11 @@ type AntigravityEngine struct { func NewAntigravityEngine() *AntigravityEngine { return &AntigravityEngine{ BaseEngine: BaseEngine{ - id: "antigravity", - displayName: "Antigravity CLI", - description: "Antigravity CLI with headless mode and LLM gateway support", - experimental: true, + id: "antigravity", + displayName: "Antigravity CLI", + description: "Antigravity CLI with headless mode and LLM gateway support", + experimental: true, + ghSkillAgentName: "antigravity", capabilities: EngineCapabilities{ ToolsAllowlist: true, MaxTurns: true, diff --git a/pkg/workflow/claude_engine.go b/pkg/workflow/claude_engine.go index bc6eed2a31c..4d6cbd6c3b6 100644 --- a/pkg/workflow/claude_engine.go +++ b/pkg/workflow/claude_engine.go @@ -22,10 +22,11 @@ type ClaudeEngine struct { func NewClaudeEngine() *ClaudeEngine { return &ClaudeEngine{ BaseEngine: BaseEngine{ - id: "claude", - displayName: "Claude Code", - description: "Uses Claude Code with full MCP tool support and allow-listing", - experimental: false, + id: "claude", + displayName: "Claude Code", + description: "Uses Claude Code with full MCP tool support and allow-listing", + experimental: false, + ghSkillAgentName: "claude-code", capabilities: EngineCapabilities{ ToolsAllowlist: true, MaxTurns: true, // Claude supports max-turns feature diff --git a/pkg/workflow/codex_engine.go b/pkg/workflow/codex_engine.go index 31d2d0b998d..e49d5b37ce1 100644 --- a/pkg/workflow/codex_engine.go +++ b/pkg/workflow/codex_engine.go @@ -50,10 +50,11 @@ type CodexEngine struct { func NewCodexEngine() *CodexEngine { return &CodexEngine{ BaseEngine: BaseEngine{ - id: "codex", - displayName: "Codex", - description: "Uses OpenAI Codex CLI with MCP server support", - experimental: false, + id: "codex", + displayName: "Codex", + description: "Uses OpenAI Codex CLI with MCP server support", + experimental: false, + ghSkillAgentName: "codex", capabilities: EngineCapabilities{ ToolsAllowlist: true, MaxTurns: true, // AWF max-turns is supported for Codex runs diff --git a/pkg/workflow/compiler_activation_job_builder.go b/pkg/workflow/compiler_activation_job_builder.go index 69402daf537..fe678aeee14 100644 --- a/pkg/workflow/compiler_activation_job_builder.go +++ b/pkg/workflow/compiler_activation_job_builder.go @@ -50,6 +50,17 @@ type activationJobBuildContext struct { activationInferredPerms map[PermissionScope]PermissionLevel } +// resolveActivationEngineID resolves the workflow engine for activation-time paths, +// defaulting to the repository-wide default engine when frontmatter leaves it unset. +// This keeps skill installation and activation artifact uploads on the same engine-specific directory. +func resolveActivationEngineID(workflowData *WorkflowData) string { + engineID := strings.TrimSpace(ResolveEngineID(workflowData)) + if engineID == "" { + return string(constants.DefaultEngine) + } + return engineID +} + // newActivationJobBuildContext initializes activation-job state with setup, aw_info, and base outputs. func (c *Compiler) newActivationJobBuildContext( data *WorkflowData, @@ -534,11 +545,12 @@ func (c *Compiler) addActivationSkillInstallSteps(ctx *activationJobBuildContext return nil } - engineID := "" - if ctx.data.EngineConfig != nil { - engineID = ctx.data.EngineConfig.ID - } + engineID := resolveActivationEngineID(ctx.data) skillDir := GetEngineSkillDir(engineID) + skillInstallAgentName := "" + if engine, err := GetGlobalEngineRegistry().GetEngine(strings.ToLower(engineID)); err == nil { + skillInstallAgentName = engine.GetGHSkillAgentName() + } ctx.steps = append(ctx.steps, " - name: Upgrade gh CLI for frontmatter skills\n") ctx.steps = append(ctx.steps, fmt.Sprintf(" run: bash \"${RUNNER_TEMP}/gh-aw/actions/ensure_gh_cli_min_version.sh\" \"%s\"\n", constants.GhSkillsMinVersion)) @@ -569,6 +581,8 @@ func (c *Compiler) addActivationSkillInstallSteps(ctx *activationJobBuildContext ctx.steps = append(ctx.steps, fmt.Sprintf(" - name: Install frontmatter skill %d\n", i+1)) ctx.steps = append(ctx.steps, " env:\n") ctx.steps = append(ctx.steps, fmt.Sprintf(" GH_TOKEN: %s\n", tokenExpr)) + ctx.steps = append(ctx.steps, formatYAMLEnv(" ", "GH_AW_INFO_ENGINE_ID", engineID)) + ctx.steps = append(ctx.steps, formatYAMLEnv(" ", "GH_AW_GH_SKILL_AGENT_NAME", skillInstallAgentName)) ctx.steps = append(ctx.steps, formatYAMLEnv(" ", "GH_AW_SKILL_DIR", skillDir)) ctx.steps = append(ctx.steps, formatYAMLEnv(" ", "GH_AW_FRONTMATTER_SKILLS", skillRef.Skill)) ctx.steps = append(ctx.steps, fmt.Sprintf(" uses: %s\n", getCachedActionPin("actions/github-script", ctx.data))) @@ -840,10 +854,7 @@ func (c *Compiler) addActivationArtifactUploadStep(ctx *activationJobBuildContex ctx.steps = append(ctx.steps, " /tmp/gh-aw/aw-prompts/prompt-import-tree.json\n") ctx.steps = append(ctx.steps, " /tmp/gh-aw/"+constants.GithubRateLimitsFilename+"\n") ctx.steps = append(ctx.steps, " /tmp/gh-aw/base\n") - engineID := "" - if ctx.data.EngineConfig != nil { - engineID = ctx.data.EngineConfig.ID - } + engineID := resolveActivationEngineID(ctx.data) // Include the engine-specific sub-agent staging directory only when inline agents are enabled. if isFeatureEnabled(constants.FeatureFlag("inline-agents"), ctx.data) { subAgentDir := GetEngineSubAgentDir(engineID) diff --git a/pkg/workflow/copilot_engine.go b/pkg/workflow/copilot_engine.go index 0acfdeabe9c..b131c23d9fa 100644 --- a/pkg/workflow/copilot_engine.go +++ b/pkg/workflow/copilot_engine.go @@ -34,10 +34,11 @@ func NewCopilotEngine() *CopilotEngine { copilotLog.Print("Creating new Copilot engine instance") return &CopilotEngine{ BaseEngine: BaseEngine{ - id: "copilot", - displayName: "GitHub Copilot CLI", - description: "Uses GitHub Copilot CLI with MCP server support", - experimental: false, + id: "copilot", + displayName: "GitHub Copilot CLI", + description: "Uses GitHub Copilot CLI with MCP server support", + experimental: false, + ghSkillAgentName: "github-copilot", capabilities: EngineCapabilities{ ToolsAllowlist: true, MaxTurns: true, // AWF max-turns is supported for Copilot runs diff --git a/pkg/workflow/gemini_engine.go b/pkg/workflow/gemini_engine.go index e2e98cc958d..ad5e54a1cba 100644 --- a/pkg/workflow/gemini_engine.go +++ b/pkg/workflow/gemini_engine.go @@ -19,10 +19,11 @@ type GeminiEngine struct { func NewGeminiEngine() *GeminiEngine { return &GeminiEngine{ BaseEngine: BaseEngine{ - id: "gemini", - displayName: "Google Gemini CLI", - description: "Google Gemini CLI with headless mode and LLM gateway support", - experimental: false, + id: "gemini", + displayName: "Google Gemini CLI", + description: "Google Gemini CLI with headless mode and LLM gateway support", + experimental: false, + ghSkillAgentName: "gemini-cli", capabilities: EngineCapabilities{ ToolsAllowlist: true, MaxTurns: true, diff --git a/pkg/workflow/opencode_engine.go b/pkg/workflow/opencode_engine.go index 35753a2f876..b427883d192 100644 --- a/pkg/workflow/opencode_engine.go +++ b/pkg/workflow/opencode_engine.go @@ -20,10 +20,11 @@ func NewOpenCodeEngine() *OpenCodeEngine { return &OpenCodeEngine{ UniversalLLMConsumerEngine: UniversalLLMConsumerEngine{ BaseEngine: BaseEngine{ - id: "opencode", - displayName: "OpenCode", - description: "OpenCode CLI with headless mode and multi-provider LLM support", - experimental: true, + id: "opencode", + displayName: "OpenCode", + description: "OpenCode CLI with headless mode and multi-provider LLM support", + experimental: true, + ghSkillAgentName: "opencode", capabilities: EngineCapabilities{ ToolsAllowlist: false, MaxTurns: true, diff --git a/pkg/workflow/pi_engine.go b/pkg/workflow/pi_engine.go index ce43c83c24e..069a660c78e 100644 --- a/pkg/workflow/pi_engine.go +++ b/pkg/workflow/pi_engine.go @@ -34,10 +34,11 @@ type PiEngine struct { func NewPiEngine() *PiEngine { return &PiEngine{ BaseEngine: BaseEngine{ - id: "pi", - displayName: "Pi", - description: "Pi AI coding agent (experimental)", - experimental: true, + id: "pi", + displayName: "Pi", + description: "Pi AI coding agent (experimental)", + experimental: true, + ghSkillAgentName: "pi", capabilities: EngineCapabilities{ ToolsAllowlist: true, MaxTurns: true,