fix: strip unsupported Gemini agent skills frontmatter (#971)
This commit is contained in:
@@ -757,6 +757,7 @@ function stripSubTags(content) {
|
||||
* - tools: must be a YAML array (not comma-separated string)
|
||||
* - tool names: must use Gemini built-in names (read_file, not Read)
|
||||
* - color: must be removed (causes validation error)
|
||||
* - skills: must be removed (causes validation error)
|
||||
* - mcp__* tools: must be excluded (auto-discovered at runtime)
|
||||
*/
|
||||
function convertClaudeToGeminiAgent(content) {
|
||||
@@ -771,11 +772,19 @@ function convertClaudeToGeminiAgent(content) {
|
||||
const lines = frontmatter.split('\n');
|
||||
const newLines = [];
|
||||
let inAllowedTools = false;
|
||||
let inSkippedArrayField = false;
|
||||
const tools = [];
|
||||
|
||||
for (const line of lines) {
|
||||
const trimmed = line.trim();
|
||||
|
||||
if (inSkippedArrayField) {
|
||||
if (!trimmed || trimmed.startsWith('- ')) {
|
||||
continue;
|
||||
}
|
||||
inSkippedArrayField = false;
|
||||
}
|
||||
|
||||
// Convert allowed-tools YAML array to tools list
|
||||
if (trimmed.startsWith('allowed-tools:')) {
|
||||
inAllowedTools = true;
|
||||
@@ -801,6 +810,12 @@ function convertClaudeToGeminiAgent(content) {
|
||||
// Strip color field (not supported by Gemini CLI, causes validation error)
|
||||
if (trimmed.startsWith('color:')) continue;
|
||||
|
||||
// Strip skills field (not supported by Gemini CLI, causes validation error)
|
||||
if (trimmed.startsWith('skills:')) {
|
||||
inSkippedArrayField = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Collect allowed-tools/tools array items
|
||||
if (inAllowedTools) {
|
||||
if (trimmed.startsWith('- ')) {
|
||||
@@ -2414,6 +2429,7 @@ function installAllRuntimes(runtimes, isGlobal, isInteractive) {
|
||||
if (process.env.GSD_TEST_MODE) {
|
||||
module.exports = {
|
||||
getCodexSkillAdapterHeader,
|
||||
convertClaudeToGeminiAgent,
|
||||
convertClaudeAgentToCodexAgent,
|
||||
generateCodexAgentToml,
|
||||
generateCodexConfigBlock,
|
||||
|
||||
47
tests/gemini-config.test.cjs
Normal file
47
tests/gemini-config.test.cjs
Normal file
@@ -0,0 +1,47 @@
|
||||
/**
|
||||
* GSD Tools Tests - Gemini agent conversion
|
||||
*
|
||||
* Verifies Gemini-specific agent frontmatter conversion removes
|
||||
* unsupported fields while preserving converted tools and body text.
|
||||
*/
|
||||
|
||||
process.env.GSD_TEST_MODE = '1';
|
||||
|
||||
const { test, describe } = require('node:test');
|
||||
const assert = require('node:assert');
|
||||
|
||||
const { convertClaudeToGeminiAgent } = require('../bin/install.js');
|
||||
|
||||
describe('convertClaudeToGeminiAgent', () => {
|
||||
test('drops unsupported skills frontmatter while keeping converted tools', () => {
|
||||
const input = `---
|
||||
name: gsd-codebase-mapper
|
||||
description: Explores codebase and writes structured analysis documents.
|
||||
tools: Read, Bash, Grep, Glob, Write
|
||||
color: cyan
|
||||
skills:
|
||||
- gsd-mapper-workflow
|
||||
---
|
||||
|
||||
<role>
|
||||
Use \${PHASE} in shell examples.
|
||||
</role>`;
|
||||
|
||||
const result = convertClaudeToGeminiAgent(input);
|
||||
const frontmatter = result.split('---')[1] || '';
|
||||
|
||||
assert.ok(frontmatter.includes('name: gsd-codebase-mapper'), 'keeps name');
|
||||
assert.ok(frontmatter.includes('description: Explores codebase and writes structured analysis documents.'), 'keeps description');
|
||||
assert.ok(frontmatter.includes('tools:'), 'adds Gemini tools array');
|
||||
assert.ok(frontmatter.includes(' - read_file'), 'maps Read -> read_file');
|
||||
assert.ok(frontmatter.includes(' - run_shell_command'), 'maps Bash -> run_shell_command');
|
||||
assert.ok(frontmatter.includes(' - search_file_content'), 'maps Grep -> search_file_content');
|
||||
assert.ok(frontmatter.includes(' - glob'), 'maps Glob -> glob');
|
||||
assert.ok(frontmatter.includes(' - write_file'), 'maps Write -> write_file');
|
||||
assert.ok(!frontmatter.includes('color:'), 'drops unsupported color field');
|
||||
assert.ok(!frontmatter.includes('skills:'), 'drops unsupported skills field');
|
||||
assert.ok(!frontmatter.includes('gsd-mapper-workflow'), 'drops skills list items');
|
||||
assert.ok(result.includes('$PHASE'), 'escapes ${PHASE} shell variable for Gemini');
|
||||
assert.ok(!result.includes('${PHASE}'), 'removes Gemini template-string pattern');
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user