aiwg
Version:
Deployment tool and support utility for AI context. Copies agents, skills, commands, rules, and behaviors into the paths each AI platform reads (Claude Code, Codex, Copilot, Cursor, Warp, OpenClaw, and 6 more) so one source of truth works across 10 platfo
112 lines (91 loc) • 3 kB
JavaScript
import { readFileSync, writeFileSync, readdirSync } from 'fs';
import { join } from 'path';
// Get target directory from command line, default to .claude/agents
const agentsDir = process.argv[2] || '.claude/agents';
// Required tools that must be present
const requiredTools = ['Read', 'Write', 'MultiEdit', 'Bash', 'WebFetch'];
// Tool name normalization map
const toolMap = {
'read': 'Read',
'write': 'Write',
'multiedit': 'MultiEdit',
'edit': 'Edit',
'bash': 'Bash',
'glob': 'Glob',
'grep': 'Grep',
'webfetch': 'WebFetch'
};
function normalizeTools(toolsLine) {
// Extract tools from the line
// Could be: tools: ["read", "write"] or tools: Read, Grep, Glob
const match = toolsLine.match(/tools:\s*(.+)/);
if (!match) return toolsLine;
const toolsStr = match[1].trim();
let tools = [];
// Check if it's JSON array format
if (toolsStr.startsWith('[')) {
try {
const parsed = JSON.parse(toolsStr);
tools = parsed.map(t => t.toLowerCase());
} catch (e) {
console.error('Failed to parse JSON tools:', toolsStr);
return toolsLine;
}
} else {
// Comma-separated format
tools = toolsStr.split(',').map(t => t.trim().toLowerCase());
}
// Normalize tool names
const normalizedTools = new Set();
tools.forEach(tool => {
const normalized = toolMap[tool] || tool;
normalizedTools.add(normalized);
});
// Add required tools
requiredTools.forEach(tool => normalizedTools.add(tool));
// Remove 'Edit' if 'MultiEdit' is present (as requested to avoid overlap)
if (normalizedTools.has('MultiEdit') && normalizedTools.has('Edit')) {
normalizedTools.delete('Edit');
}
// Sort tools for consistency
const sortedTools = Array.from(normalizedTools).sort();
// Return as comma-separated list without quotes or brackets
return `tools: ${sortedTools.join(', ')}`;
}
function updateAgentFile(filePath) {
const content = readFileSync(filePath, 'utf-8');
const lines = content.split('\n');
let modified = false;
const updatedLines = lines.map((line, idx) => {
if (line.startsWith('tools:')) {
const normalized = normalizeTools(line);
if (normalized !== line) {
modified = true;
console.log(` Updated: ${line} -> ${normalized}`);
}
return normalized;
}
return line;
});
if (modified) {
writeFileSync(filePath, updatedLines.join('\n'), 'utf-8');
return true;
}
return false;
}
// Main execution
// Skip non-agent files
const skipFiles = ['README.md', 'manifest.md', 'agent-template.md', 'openai-compat.md'];
const files = readdirSync(agentsDir)
.filter(f => f.endsWith('.md') && !skipFiles.includes(f))
.map(f => join(agentsDir, f));
let updatedCount = 0;
console.log('Updating agent tool configurations...\n');
files.forEach(file => {
console.log(`Processing: ${file}`);
if (updateAgentFile(file)) {
updatedCount++;
}
});
console.log(`\nCompleted: ${updatedCount} agents updated`);