feat: Universal Agent API Bridge & Modular Skill Engine Overhaul

- Add Gitea/Vikunja API sync scripts to eliminate prompt-pollution.
- Move submodules to .agent/vendor for proper CLI encapsulation.
- Implement extract_skills.js to dynamically flatten 19 active skills.
- Translate CLI skill descriptions to Korean.
- Mask .env.agent in .gitignore ensuring true Zero-Pollution secure template.
This commit is contained in:
2026-03-29 08:09:19 +09:00
parent aec8d601cb
commit 36eed3f5fb
16 changed files with 471 additions and 13 deletions

View File

@@ -0,0 +1,77 @@
const fs = require('fs');
const path = require('path');
const { execSync } = require('child_process');
// 1. Load configuration from .env.agent
const envPath = path.join(__dirname, '../config/.env.agent');
if (!fs.existsSync(envPath)) {
console.error("Error: .agent/config/.env.agent file not found. Please create it from the template.");
process.exit(1);
}
const envContent = fs.readFileSync(envPath, 'utf8');
const env = {};
envContent.split('\n').forEach(line => {
// Basic dotenv parser supporting basic key="value" formats
const match = line.match(/^([^#=]+)="?(.*?)"?$/);
if (match) {
env[match[1].trim()] = match[2].trim();
}
});
// 2. Resolve Wiki URL (handle simple interpolations)
let wikiUrl = env.WIKI_REPO_URL;
if (!wikiUrl) {
console.error("Error: WIKI_REPO_URL is not defined in .env.agent.");
process.exit(1);
}
if (wikiUrl.includes('${GITEA_USERNAME}')) {
wikiUrl = wikiUrl.replace('${GITEA_USERNAME}', env.GITEA_USERNAME || '');
}
if (wikiUrl.includes('${GITEA_API_TOKEN}')) {
wikiUrl = wikiUrl.replace('${GITEA_API_TOKEN}', env.GITEA_API_TOKEN || '');
}
if (wikiUrl.includes('[YOUR_')) {
console.error("Warning: WIKI_REPO_URL looks like it contains placeholder tags ([YOUR_...]). Ensure the config is set up correctly.");
// We let it proceed in case it's a test environment with dummy tags
}
// 3. Execute Git commands in the Wiki directory
const wikiDir = path.join(__dirname, '../../.knowledge/project_wiki');
if (!fs.existsSync(path.join(wikiDir, '.git'))) {
console.error(`Error: .git repository not found inside ${wikiDir}. Wiki must be initialized via git first.`);
process.exit(1);
}
try {
console.log("Adding Wiki changes...");
execSync('git add .', { cwd: wikiDir, stdio: 'inherit' });
// Check if there are changes to commit
const status = execSync('git status --porcelain', { cwd: wikiDir }).toString();
if (status.trim().length > 0) {
console.log("Committing changes...");
execSync('git commit -m "docs(agent): Auto-sync Wiki from Antigravity Agent"', { cwd: wikiDir, stdio: 'inherit' });
} else {
console.log("No changes to commit in Wiki.");
}
console.log("Pushing to Gitea Wiki repository...");
// WARNING: Output masking is not actively done here; this relies on the underlying tool to obscure tokens if echoed,
// but execSync with 'inherit' might leak the URL if git fails. We mask it manually for display, but git handles the URL internally.
execSync(`git push "${wikiUrl}" main`, { cwd: wikiDir, stdio: 'pipe' });
console.log("✅ Wiki synchronization completed successfully.");
} catch (e) {
console.error("❌ Failed to sync wiki.");
// Mask API tokens in error messages
const errorMessage = e.message.replace(new RegExp(env.GITEA_API_TOKEN || 'dummy', 'g'), '********');
console.error(errorMessage);
if (e.stderr) {
const stderrStr = e.stderr.toString().replace(new RegExp(env.GITEA_API_TOKEN || 'dummy', 'g'), '********');
console.error(stderrStr);
}
process.exit(1);
}