* Build a context string when frontmatter skill installation failed. * @param {boolean} hasSkillInstallFailures - Whether any skill installs failed * @param {string} skillInstallErrors - Newline-separated list of "skill error" entries * @returns {string} Formatted context string, or empty str
(hasSkillInstallFailures, skillInstallErrors)
| 2153 | * @returns {string} Formatted context string, or empty string if no failures |
| 2154 | */ |
| 2155 | function buildSkillInstallFailureContext(hasSkillInstallFailures, skillInstallErrors) { |
| 2156 | if (!hasSkillInstallFailures) { |
| 2157 | return ""; |
| 2158 | } |
| 2159 | |
| 2160 | let skillList = ""; |
| 2161 | if (skillInstallErrors) { |
| 2162 | const errorLines = skillInstallErrors.split("\n").filter(line => line.trim()); |
| 2163 | for (const errorLine of errorLines) { |
| 2164 | // New format uses tab delimiter; keep colon parsing as a backward-compatible fallback. |
| 2165 | const tabIdx = errorLine.indexOf("\t"); |
| 2166 | if (tabIdx >= 0) { |
| 2167 | const skill = errorLine.slice(0, tabIdx); |
| 2168 | const error = errorLine.slice(tabIdx + 1); |
| 2169 | skillList += `- \`${skill}\`: ${error}\n`; |
| 2170 | continue; |
| 2171 | } |
| 2172 | const colonIdx = errorLine.indexOf(":"); |
| 2173 | if (colonIdx >= 0) { |
| 2174 | const skill = errorLine.slice(0, colonIdx); |
| 2175 | const error = errorLine.slice(colonIdx + 1); |
| 2176 | skillList += `- \`${skill}\`: ${error}\n`; |
| 2177 | } else { |
| 2178 | skillList += `- ${errorLine}\n`; |
| 2179 | } |
| 2180 | } |
| 2181 | } |
| 2182 | |
| 2183 | const templatePath = getPromptPath("skill_install_failure.md"); |
| 2184 | return "\n" + renderTemplateFromFile(templatePath, { skills: skillList }); |
| 2185 | } |
| 2186 | |
| 2187 | /** |
| 2188 | * For the Copilot engine, adds a suggestion to use `permissions.copilot-requests: write` |
no test coverage detected