File size: 3,570 Bytes
bf96836
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
#!/usr/bin/env node
/**
 * Agent Generator
 *
 * Generates platform-specific agent files from the shared source in .ai/agents/.
 * Each agent body is stored once in .ai/agents/{name}.md (no frontmatter).
 * Per-platform frontmatter is defined in scripts/agent-config.json.
 *
 * Outputs:
 *   .claude/agents/{name}.md  — Claude Code agents
 *   .gemini/agents/{name}.md  — Gemini CLI agents
 *
 * Usage:
 *   node scripts/gen-agents.js
 *   node scripts/gen-agents.js --dry-run   (preview only, no writes)
 */

const fs = require('fs');
const path = require('path');

const ROOT = path.resolve(__dirname, '..');
const AI_AGENTS_DIR = path.join(ROOT, '.ai', 'agents');
const CLAUDE_AGENTS_DIR = path.join(ROOT, '.claude', 'agents');
const GEMINI_AGENTS_DIR = path.join(ROOT, '.gemini', 'agents');
const CONFIG_FILE = path.join(__dirname, 'agent-config.json');

const isDryRun = process.argv.includes('--dry-run');

function ensureDir(dir) {
  if (!fs.existsSync(dir)) {
    fs.mkdirSync(dir, { recursive: true });
  }
}

function buildFrontmatter(config) {
  const lines = ['---'];
  for (const [key, value] of Object.entries(config)) {
    if (Array.isArray(value)) {
      lines.push(`${key}: [${value.map(v => `"${v}"`).join(', ')}]`);
    } else if (typeof value === 'string') {
      lines.push(`${key}: ${value}`);
    } else {
      lines.push(`${key}: ${value}`);
    }
  }
  lines.push('---');
  return lines.join('\n');
}

function generateAgent(name, body, platformConfig, outputDir) {
  const frontmatter = buildFrontmatter(platformConfig);
  const content = `${frontmatter}\n\n${body.trimStart()}`;
  const outputFile = path.join(outputDir, `${name}.md`);

  if (isDryRun) {
    console.log(`[dry-run] Would write: ${outputFile}`);
    console.log(`  Frontmatter keys: ${Object.keys(platformConfig).join(', ')}`);
    return;
  }

  fs.writeFileSync(outputFile, content, 'utf8');
  console.log(`  Written: ${outputFile}`);
}

function main() {
  // Read config
  if (!fs.existsSync(CONFIG_FILE)) {
    console.error(`Error: Config file not found: ${CONFIG_FILE}`);
    process.exit(1);
  }
  const config = JSON.parse(fs.readFileSync(CONFIG_FILE, 'utf8'));

  // Ensure output dirs exist
  if (!isDryRun) {
    ensureDir(CLAUDE_AGENTS_DIR);
    ensureDir(GEMINI_AGENTS_DIR);
  }

  const agentNames = Object.keys(config);
  console.log(`Generating ${agentNames.length} agents for 2 platforms...\n`);

  let claudeCount = 0;
  let geminiCount = 0;
  const errors = [];

  for (const name of agentNames) {
    const sourceFile = path.join(AI_AGENTS_DIR, `${name}.md`);

    if (!fs.existsSync(sourceFile)) {
      errors.push(`Missing source: ${sourceFile}`);
      continue;
    }

    const body = fs.readFileSync(sourceFile, 'utf8');
    const agentConfig = config[name];

    console.log(`${name}:`);

    // Generate Claude agent
    if (agentConfig.claude) {
      generateAgent(name, body, agentConfig.claude, CLAUDE_AGENTS_DIR);
      claudeCount++;
    }

    // Generate Gemini agent
    if (agentConfig.gemini) {
      generateAgent(name, body, agentConfig.gemini, GEMINI_AGENTS_DIR);
      geminiCount++;
    }
  }

  console.log(`\nDone.`);
  if (isDryRun) {
    console.log(`[dry-run] No files written.`);
  } else {
    console.log(`  Claude agents: ${claudeCount}${CLAUDE_AGENTS_DIR}`);
    console.log(`  Gemini agents: ${geminiCount}${GEMINI_AGENTS_DIR}`);
  }

  if (errors.length > 0) {
    console.error('\nErrors:');
    for (const err of errors) {
      console.error(`  ${err}`);
    }
    process.exit(1);
  }
}

main();