antigravity-ai-kit 2.1.0 → 3.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.agent/README.md +4 -4
- package/.agent/agents/README.md +16 -12
- package/.agent/agents/architect.md +1 -0
- package/.agent/agents/backend-specialist.md +11 -0
- package/.agent/agents/code-reviewer.md +1 -0
- package/.agent/agents/database-architect.md +11 -0
- package/.agent/agents/devops-engineer.md +11 -0
- package/.agent/agents/e2e-runner.md +1 -0
- package/.agent/agents/explorer-agent.md +11 -0
- package/.agent/agents/frontend-specialist.md +11 -0
- package/.agent/agents/mobile-developer.md +11 -0
- package/.agent/agents/performance-optimizer.md +11 -0
- package/.agent/agents/planner.md +1 -0
- package/.agent/agents/refactor-cleaner.md +1 -0
- package/.agent/agents/reliability-engineer.md +11 -0
- package/.agent/agents/security-reviewer.md +1 -0
- package/.agent/agents/sprint-orchestrator.md +10 -0
- package/.agent/agents/tdd-guide.md +1 -0
- package/.agent/commands/code-review.md +1 -0
- package/.agent/commands/debug.md +1 -0
- package/.agent/commands/deploy.md +1 -0
- package/.agent/commands/help.md +252 -31
- package/.agent/commands/plan.md +1 -0
- package/.agent/commands/status.md +1 -0
- package/.agent/commands/tdd.md +1 -0
- package/.agent/contexts/brainstorm.md +26 -0
- package/.agent/contexts/debug.md +28 -0
- package/.agent/contexts/implement.md +29 -0
- package/.agent/contexts/review.md +27 -0
- package/.agent/contexts/ship.md +28 -0
- package/.agent/engine/identity.json +13 -0
- package/.agent/engine/loading-rules.json +23 -1
- package/.agent/engine/marketplace-index.json +29 -0
- package/.agent/engine/reliability-config.json +14 -0
- package/.agent/engine/sdlc-map.json +44 -0
- package/.agent/engine/workflow-state.json +28 -2
- package/.agent/hooks/hooks.json +27 -25
- package/.agent/manifest.json +12 -4
- package/.agent/rules.md +2 -1
- package/.agent/skills/README.md +10 -5
- package/.agent/skills/i18n-localization/SKILL.md +191 -0
- package/.agent/skills/mcp-integration/SKILL.md +224 -0
- package/.agent/skills/parallel-agents/SKILL.md +1 -1
- package/.agent/skills/shell-conventions/SKILL.md +92 -0
- package/.agent/skills/ui-ux-pro-max/SKILL.md +557 -0
- package/.agent/skills/ui-ux-pro-max/data/charts.csv +26 -0
- package/.agent/skills/ui-ux-pro-max/data/colors.csv +97 -0
- package/.agent/skills/ui-ux-pro-max/data/icons.csv +101 -0
- package/.agent/skills/ui-ux-pro-max/data/landing.csv +31 -0
- package/.agent/skills/ui-ux-pro-max/data/products.csv +97 -0
- package/.agent/skills/ui-ux-pro-max/data/react-performance.csv +45 -0
- package/.agent/skills/ui-ux-pro-max/data/stacks/astro.csv +54 -0
- package/.agent/skills/ui-ux-pro-max/data/stacks/flutter.csv +53 -0
- package/.agent/skills/ui-ux-pro-max/data/stacks/html-tailwind.csv +56 -0
- package/.agent/skills/ui-ux-pro-max/data/stacks/jetpack-compose.csv +53 -0
- package/.agent/skills/ui-ux-pro-max/data/stacks/nextjs.csv +53 -0
- package/.agent/skills/ui-ux-pro-max/data/stacks/nuxt-ui.csv +51 -0
- package/.agent/skills/ui-ux-pro-max/data/stacks/nuxtjs.csv +59 -0
- package/.agent/skills/ui-ux-pro-max/data/stacks/react-native.csv +52 -0
- package/.agent/skills/ui-ux-pro-max/data/stacks/react.csv +54 -0
- package/.agent/skills/ui-ux-pro-max/data/stacks/shadcn.csv +61 -0
- package/.agent/skills/ui-ux-pro-max/data/stacks/svelte.csv +54 -0
- package/.agent/skills/ui-ux-pro-max/data/stacks/swiftui.csv +51 -0
- package/.agent/skills/ui-ux-pro-max/data/stacks/vue.csv +50 -0
- package/.agent/skills/ui-ux-pro-max/data/styles.csv +68 -0
- package/.agent/skills/ui-ux-pro-max/data/typography.csv +58 -0
- package/.agent/skills/ui-ux-pro-max/data/ui-reasoning.csv +101 -0
- package/.agent/skills/ui-ux-pro-max/data/ux-guidelines.csv +100 -0
- package/.agent/skills/ui-ux-pro-max/data/web-interface.csv +31 -0
- package/.agent/skills/ui-ux-pro-max/scripts/core.py +253 -0
- package/.agent/skills/ui-ux-pro-max/scripts/design_system.py +1067 -0
- package/.agent/skills/ui-ux-pro-max/scripts/search.py +114 -0
- package/.agent/templates/adr-template.md +32 -0
- package/.agent/templates/bug-report.md +37 -0
- package/.agent/templates/feature-request.md +32 -0
- package/.agent/workflows/README.md +92 -78
- package/.agent/workflows/brainstorm.md +154 -100
- package/.agent/workflows/create.md +142 -75
- package/.agent/workflows/debug.md +157 -98
- package/.agent/workflows/deploy.md +195 -144
- package/.agent/workflows/enhance.md +157 -65
- package/.agent/workflows/orchestrate.md +171 -114
- package/.agent/workflows/plan.md +147 -72
- package/.agent/workflows/preview.md +140 -83
- package/.agent/workflows/quality-gate.md +196 -0
- package/.agent/workflows/retrospective.md +197 -0
- package/.agent/workflows/review.md +188 -0
- package/.agent/workflows/status.md +142 -91
- package/.agent/workflows/test.md +168 -95
- package/.agent/workflows/ui-ux-pro-max.md +181 -127
- package/README.md +215 -78
- package/bin/ag-kit.js +344 -10
- package/lib/agent-registry.js +214 -0
- package/lib/agent-reputation.js +351 -0
- package/lib/cli-commands.js +235 -0
- package/lib/conflict-detector.js +245 -0
- package/lib/engineering-manager.js +354 -0
- package/lib/error-budget.js +294 -0
- package/lib/hook-system.js +252 -0
- package/lib/identity.js +245 -0
- package/lib/loading-engine.js +208 -0
- package/lib/marketplace.js +298 -0
- package/lib/plugin-system.js +604 -0
- package/lib/security-scanner.js +309 -0
- package/lib/self-healing.js +434 -0
- package/lib/session-manager.js +261 -0
- package/lib/skill-sandbox.js +244 -0
- package/lib/task-governance.js +523 -0
- package/lib/task-model.js +317 -0
- package/lib/updater.js +201 -0
- package/lib/verify.js +240 -0
- package/lib/workflow-engine.js +353 -0
- package/lib/workflow-persistence.js +160 -0
- package/package.json +7 -3
package/bin/ag-kit.js
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* Antigravity AI Kit CLI
|
|
5
5
|
*
|
|
6
6
|
* Usage:
|
|
7
|
-
* npx
|
|
7
|
+
* npx antigravity-ai-kit init
|
|
8
8
|
* ag-kit init [options]
|
|
9
9
|
*
|
|
10
10
|
* @author Emre Dursun
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
const fs = require('fs');
|
|
15
15
|
const path = require('path');
|
|
16
16
|
|
|
17
|
-
const VERSION = '
|
|
17
|
+
const VERSION = '3.0.0';
|
|
18
18
|
const AGENT_FOLDER = '.agent';
|
|
19
19
|
|
|
20
20
|
// ANSI colors
|
|
@@ -49,8 +49,9 @@ ${colors.reset}
|
|
|
49
49
|
${colors.green}🚀 Antigravity AI Kit v${VERSION}${colors.reset}
|
|
50
50
|
${colors.yellow} Transform Your IDE into an Autonomous Engineering Team${colors.reset}
|
|
51
51
|
|
|
52
|
-
• 19 AI Agents •
|
|
53
|
-
• 31 Commands •
|
|
52
|
+
• 19 AI Agents • 31 Skills
|
|
53
|
+
• 31 Commands • 14 Workflows
|
|
54
|
+
• Runtime Engine • Error Budget
|
|
54
55
|
`);
|
|
55
56
|
}
|
|
56
57
|
|
|
@@ -60,7 +61,16 @@ function showHelp() {
|
|
|
60
61
|
${colors.bright}Usage:${colors.reset}
|
|
61
62
|
ag-kit init [options] Install .agent folder to your project
|
|
62
63
|
ag-kit update Update to latest version
|
|
63
|
-
ag-kit status Check installation status
|
|
64
|
+
ag-kit status Check installation status (alias: dashboard)
|
|
65
|
+
ag-kit verify Run manifest integrity checks
|
|
66
|
+
ag-kit scan Run security scan
|
|
67
|
+
ag-kit plugin list List installed plugins
|
|
68
|
+
ag-kit plugin install <p> Install plugin from directory
|
|
69
|
+
ag-kit plugin remove <n> Remove installed plugin
|
|
70
|
+
ag-kit market search <q> Search marketplace plugins
|
|
71
|
+
ag-kit market info <name> Get marketplace plugin details
|
|
72
|
+
ag-kit market install <n> Install from marketplace
|
|
73
|
+
ag-kit heal [--file <f>] Detect and diagnose CI failures
|
|
64
74
|
ag-kit --help Show this help message
|
|
65
75
|
ag-kit --version Show version
|
|
66
76
|
|
|
@@ -69,11 +79,18 @@ ${colors.bright}Options:${colors.reset}
|
|
|
69
79
|
--path <dir> Install to specific directory
|
|
70
80
|
--quiet Suppress output (for CI/CD)
|
|
71
81
|
--dry-run Preview actions without executing
|
|
82
|
+
--apply Apply self-healing patches (default: dry-run)
|
|
83
|
+
--file <path> CI log file for heal command
|
|
72
84
|
|
|
73
85
|
${colors.bright}Examples:${colors.reset}
|
|
74
86
|
npx antigravity-ai-kit init
|
|
75
87
|
ag-kit init --force
|
|
76
|
-
ag-kit
|
|
88
|
+
ag-kit scan
|
|
89
|
+
ag-kit plugin list
|
|
90
|
+
|
|
91
|
+
${colors.bright}IDE Reference:${colors.reset}
|
|
92
|
+
Type ${colors.cyan}/help${colors.reset} in your AI-powered IDE for the full reference:
|
|
93
|
+
commands, workflows, agents, skills, rules, and checklists.
|
|
77
94
|
`);
|
|
78
95
|
}
|
|
79
96
|
|
|
@@ -169,6 +186,10 @@ ${colors.bright}Next steps:${colors.reset}
|
|
|
169
186
|
2. Run ${colors.cyan}/status${colors.reset} to verify
|
|
170
187
|
3. Use ${colors.cyan}/help${colors.reset} to see available commands
|
|
171
188
|
|
|
189
|
+
${colors.bright}Validate your installation:${colors.reset}
|
|
190
|
+
${colors.cyan}ag-kit verify${colors.reset} Manifest integrity check
|
|
191
|
+
${colors.cyan}ag-kit scan${colors.reset} Security scan
|
|
192
|
+
|
|
172
193
|
${colors.bright}Quick start:${colors.reset}
|
|
173
194
|
${colors.cyan}/plan${colors.reset} Create implementation plan
|
|
174
195
|
${colors.cyan}/implement${colors.reset} Execute the plan
|
|
@@ -196,9 +217,298 @@ function statusCommand() {
|
|
|
196
217
|
const commands = countItems(path.join(agentPath, 'commands'), 'file');
|
|
197
218
|
const workflows = countItems(path.join(agentPath, 'workflows'), 'file');
|
|
198
219
|
|
|
220
|
+
log(' ═══ Capabilities ═══', 'cyan');
|
|
199
221
|
console.log(` 📦 Skills: ${skills}`);
|
|
200
222
|
console.log(` ⌨️ Commands: ${commands}`);
|
|
201
|
-
console.log(` 🔄 Workflows: ${workflows}
|
|
223
|
+
console.log(` 🔄 Workflows: ${workflows}`);
|
|
224
|
+
|
|
225
|
+
// Workflow phase + available transitions
|
|
226
|
+
try {
|
|
227
|
+
const workflowEngine = require('../lib/workflow-engine');
|
|
228
|
+
const phase = workflowEngine.getCurrentPhase(process.cwd());
|
|
229
|
+
const available = workflowEngine.getAvailableTransitions(process.cwd());
|
|
230
|
+
console.log(` 🔁 Phase: ${phase}`);
|
|
231
|
+
if (available.length > 0) {
|
|
232
|
+
const nextPhases = available.map((t) => t.to).join(', ');
|
|
233
|
+
console.log(` ➡️ Next: ${nextPhases}`);
|
|
234
|
+
}
|
|
235
|
+
} catch {
|
|
236
|
+
// Engine not available, skip silently
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
// Error budget
|
|
240
|
+
try {
|
|
241
|
+
const errorBudget = require('../lib/error-budget');
|
|
242
|
+
const report = errorBudget.getBudgetReport(process.cwd());
|
|
243
|
+
const statusIcon = report.status === 'HEALTHY' ? '🟢' : report.status === 'WARNING' ? '🟡' : '🔴';
|
|
244
|
+
console.log(` ${statusIcon} Budget: ${report.status}`);
|
|
245
|
+
if (report.violations.length > 0) {
|
|
246
|
+
log(` ⚠️ Violations: ${report.violations.join(', ')}`, 'yellow');
|
|
247
|
+
}
|
|
248
|
+
} catch {
|
|
249
|
+
// Budget not available, skip silently
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
// Task metrics
|
|
253
|
+
try {
|
|
254
|
+
const taskModel = require('../lib/task-model');
|
|
255
|
+
const metrics = taskModel.getTaskMetrics(process.cwd());
|
|
256
|
+
if (metrics.total > 0) {
|
|
257
|
+
console.log('');
|
|
258
|
+
log(' ═══ Tasks ═══', 'cyan');
|
|
259
|
+
console.log(` 📋 Open: ${metrics.counts.open || 0}`);
|
|
260
|
+
console.log(` 🔨 In Progress: ${metrics.counts['in-progress'] || 0}`);
|
|
261
|
+
console.log(` 👁️ In Review: ${metrics.counts.review || 0}`);
|
|
262
|
+
console.log(` ✅ Done: ${metrics.counts.done || 0}`);
|
|
263
|
+
console.log(` 🚫 Blocked: ${metrics.counts.blocked || 0}`);
|
|
264
|
+
if (metrics.completionRate > 0) {
|
|
265
|
+
console.log(` 📊 Completion: ${metrics.completionRate}%`);
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
} catch {
|
|
269
|
+
// Task model not available, skip silently
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
// Hook readiness
|
|
273
|
+
try {
|
|
274
|
+
const hookSystem = require('../lib/hook-system');
|
|
275
|
+
const hookReport = hookSystem.getHookReport(process.cwd());
|
|
276
|
+
console.log('');
|
|
277
|
+
log(' ═══ Hooks ═══', 'cyan');
|
|
278
|
+
console.log(` 🪝 Events: ${hookReport.events.length}`);
|
|
279
|
+
console.log(` ✅ Ready: ${hookReport.readyCount}/${hookReport.events.length}`);
|
|
280
|
+
} catch {
|
|
281
|
+
// Hook system not available, skip silently
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
// Developer identity
|
|
285
|
+
try {
|
|
286
|
+
const identity = require('../lib/identity');
|
|
287
|
+
const current = identity.getCurrentIdentity(process.cwd());
|
|
288
|
+
if (current) {
|
|
289
|
+
console.log('');
|
|
290
|
+
log(' ═══ Identity ═══', 'cyan');
|
|
291
|
+
console.log(` 👤 Developer: ${current.name}`);
|
|
292
|
+
console.log(` 🔑 Role: ${current.role}`);
|
|
293
|
+
}
|
|
294
|
+
} catch {
|
|
295
|
+
// Identity not available, skip silently
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
// Plugins
|
|
299
|
+
try {
|
|
300
|
+
const pluginSystem = require('../lib/plugin-system');
|
|
301
|
+
const plugins = pluginSystem.listPlugins(process.cwd());
|
|
302
|
+
if (plugins.length > 0) {
|
|
303
|
+
console.log('');
|
|
304
|
+
log(' ═══ Plugins ═══', 'cyan');
|
|
305
|
+
console.log(` 🔌 Installed: ${plugins.length}`);
|
|
306
|
+
for (const plugin of plugins) {
|
|
307
|
+
console.log(` • ${plugin.name} v${plugin.version}`);
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
} catch {
|
|
311
|
+
// Plugin system not available, skip silently
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
// Phase 4 dashboard sections (D-5, E-5)
|
|
315
|
+
try {
|
|
316
|
+
const cliCommands = require('../lib/cli-commands');
|
|
317
|
+
cliCommands.renderDashboardSections(process.cwd());
|
|
318
|
+
} catch {
|
|
319
|
+
// Phase 4 modules not available, skip silently
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
console.log('');
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
function verifyCommand() {
|
|
326
|
+
showBanner();
|
|
327
|
+
logStep('1/1', 'Running manifest integrity checks...\n');
|
|
328
|
+
|
|
329
|
+
try {
|
|
330
|
+
const verify = require('../lib/verify');
|
|
331
|
+
const report = verify.runAllChecks(process.cwd());
|
|
332
|
+
|
|
333
|
+
for (const result of report.results) {
|
|
334
|
+
const icon = result.status === 'pass' ? '✓' : result.status === 'fail' ? '✗' : '⚠';
|
|
335
|
+
const color = result.status === 'pass' ? 'green' : result.status === 'fail' ? 'red' : 'yellow';
|
|
336
|
+
log(` ${icon} ${result.message}`, color);
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
console.log('');
|
|
340
|
+
log(` Passed: ${report.passed} Failed: ${report.failed} Warnings: ${report.warnings}`, report.failed > 0 ? 'red' : 'green');
|
|
341
|
+
console.log('');
|
|
342
|
+
|
|
343
|
+
if (report.failed > 0) {
|
|
344
|
+
process.exit(1);
|
|
345
|
+
}
|
|
346
|
+
} catch (/** @type {any} */ error) {
|
|
347
|
+
log(` ✗ Verification failed: ${error.message}`, 'red');
|
|
348
|
+
process.exit(1);
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
function updateCommand(updateOptions) {
|
|
353
|
+
showBanner();
|
|
354
|
+
|
|
355
|
+
const agentPath = path.join(updateOptions.path || process.cwd(), '.agent');
|
|
356
|
+
if (!fs.existsSync(agentPath)) {
|
|
357
|
+
log('\n❌ No .agent/ folder found. Run: ag-kit init\n', 'red');
|
|
358
|
+
process.exit(1);
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
const sourceRoot = path.join(__dirname, '..');
|
|
362
|
+
const targetRoot = updateOptions.path || process.cwd();
|
|
363
|
+
|
|
364
|
+
try {
|
|
365
|
+
const updater = require('../lib/updater');
|
|
366
|
+
const isDryRun = updateOptions.dryRun;
|
|
367
|
+
|
|
368
|
+
if (isDryRun) {
|
|
369
|
+
log('\n🔍 Dry run mode — no changes will be made\n', 'cyan');
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
logStep('1/2', isDryRun ? 'Analyzing differences...' : 'Applying updates...');
|
|
373
|
+
|
|
374
|
+
const report = updater.applyUpdate(sourceRoot, targetRoot, isDryRun);
|
|
375
|
+
|
|
376
|
+
if (report.added.length > 0) {
|
|
377
|
+
log(`\n 📁 New files (${report.added.length}):`, 'green');
|
|
378
|
+
for (const file of report.added) {
|
|
379
|
+
log(` + ${file}`, 'green');
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
if (report.updated.length > 0) {
|
|
384
|
+
log(`\n 📝 Updated files (${report.updated.length}):`, 'cyan');
|
|
385
|
+
for (const file of report.updated) {
|
|
386
|
+
log(` ~ ${file}`, 'cyan');
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
if (report.skipped.length > 0) {
|
|
391
|
+
log(`\n 🔒 Preserved files (${report.skipped.length}):`, 'yellow');
|
|
392
|
+
for (const file of report.skipped) {
|
|
393
|
+
log(` ○ ${file}`, 'yellow');
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
logStep('2/2', 'Summary');
|
|
398
|
+
console.log(`\n Added: ${report.added.length} Updated: ${report.updated.length} Skipped: ${report.skipped.length} Unchanged: ${report.unchanged.length}\n`);
|
|
399
|
+
|
|
400
|
+
if (report.added.length === 0 && report.updated.length === 0) {
|
|
401
|
+
log(' ✅ Already up to date!\n', 'green');
|
|
402
|
+
} else if (!isDryRun) {
|
|
403
|
+
log(' ✅ Update complete!\n', 'green');
|
|
404
|
+
}
|
|
405
|
+
} catch (/** @type {any} */ error) {
|
|
406
|
+
log(` ✗ Update failed: ${error.message}`, 'red');
|
|
407
|
+
process.exit(1);
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
function scanCommand() {
|
|
412
|
+
showBanner();
|
|
413
|
+
logStep('1/1', 'Running enhanced security scan...\n');
|
|
414
|
+
|
|
415
|
+
try {
|
|
416
|
+
const scanner = require('../lib/security-scanner');
|
|
417
|
+
const report = scanner.getSecurityReport(process.cwd());
|
|
418
|
+
|
|
419
|
+
log(` 📂 Files scanned: ${report.filesScanned}`, 'cyan');
|
|
420
|
+
console.log('');
|
|
421
|
+
|
|
422
|
+
if (report.findings.length === 0) {
|
|
423
|
+
log(' ✅ No security findings — all clear!\n', 'green');
|
|
424
|
+
} else {
|
|
425
|
+
for (const finding of report.findings) {
|
|
426
|
+
const icon = finding.severity === 'critical' ? '🔴' : finding.severity === 'high' ? '🟠' : finding.severity === 'medium' ? '🟡' : '⚪';
|
|
427
|
+
log(` ${icon} [${finding.severity.toUpperCase()}] ${finding.detail}`, finding.severity === 'critical' ? 'red' : finding.severity === 'high' ? 'yellow' : 'reset');
|
|
428
|
+
console.log(` File: ${finding.file}${finding.line ? `:${finding.line}` : ''}`);
|
|
429
|
+
}
|
|
430
|
+
console.log('');
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
log(` 🔴 Critical: ${report.criticalCount} 🟠 High: ${report.highCount} 🟡 Medium: ${report.mediumCount} ⚪ Low: ${report.lowCount}`, report.clean ? 'green' : 'red');
|
|
434
|
+
console.log('');
|
|
435
|
+
|
|
436
|
+
if (!report.clean) {
|
|
437
|
+
process.exit(1);
|
|
438
|
+
}
|
|
439
|
+
} catch (/** @type {any} */ error) {
|
|
440
|
+
log(` ✗ Security scan failed: ${error.message}`, 'red');
|
|
441
|
+
process.exit(1);
|
|
442
|
+
}
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
function pluginCommand(subCommand, pluginArg) {
|
|
446
|
+
showBanner();
|
|
447
|
+
|
|
448
|
+
try {
|
|
449
|
+
const pluginSystem = require('../lib/plugin-system');
|
|
450
|
+
|
|
451
|
+
switch (subCommand) {
|
|
452
|
+
case 'list': {
|
|
453
|
+
const plugins = pluginSystem.listPlugins(process.cwd());
|
|
454
|
+
if (plugins.length === 0) {
|
|
455
|
+
log(' No plugins installed\n', 'yellow');
|
|
456
|
+
} else {
|
|
457
|
+
log(` ═══ Installed Plugins (${plugins.length}) ═══\n`, 'cyan');
|
|
458
|
+
for (const plugin of plugins) {
|
|
459
|
+
console.log(` 🔌 ${plugin.name} v${plugin.version}`);
|
|
460
|
+
console.log(` Author: ${plugin.author}`);
|
|
461
|
+
console.log(` Installed: ${plugin.installedAt}`);
|
|
462
|
+
console.log('');
|
|
463
|
+
}
|
|
464
|
+
}
|
|
465
|
+
break;
|
|
466
|
+
}
|
|
467
|
+
case 'install': {
|
|
468
|
+
if (!pluginArg) {
|
|
469
|
+
log(' ✗ Usage: ag-kit plugin install <path>\n', 'red');
|
|
470
|
+
process.exit(1);
|
|
471
|
+
}
|
|
472
|
+
const pluginPath = path.resolve(pluginArg);
|
|
473
|
+
logStep('1/1', `Installing plugin from ${pluginPath}...`);
|
|
474
|
+
const result = pluginSystem.installPlugin(pluginPath, process.cwd());
|
|
475
|
+
if (result.success) {
|
|
476
|
+
log('\n ✅ Plugin installed successfully!', 'green');
|
|
477
|
+
console.log(` Agents: ${result.installed.agents} Skills: ${result.installed.skills} Workflows: ${result.installed.workflows} Hooks: ${result.installed.hooks}\n`);
|
|
478
|
+
} else {
|
|
479
|
+
log('\n ✗ Plugin installation failed:', 'red');
|
|
480
|
+
for (const error of result.errors) {
|
|
481
|
+
log(` • ${error}`, 'red');
|
|
482
|
+
}
|
|
483
|
+
console.log('');
|
|
484
|
+
process.exit(1);
|
|
485
|
+
}
|
|
486
|
+
break;
|
|
487
|
+
}
|
|
488
|
+
case 'remove': {
|
|
489
|
+
if (!pluginArg) {
|
|
490
|
+
log(' ✗ Usage: ag-kit plugin remove <name>\n', 'red');
|
|
491
|
+
process.exit(1);
|
|
492
|
+
}
|
|
493
|
+
logStep('1/1', `Removing plugin: ${pluginArg}...`);
|
|
494
|
+
const result = pluginSystem.removePlugin(pluginArg, process.cwd());
|
|
495
|
+
if (result.success) {
|
|
496
|
+
log('\n ✅ Plugin removed successfully!\n', 'green');
|
|
497
|
+
} else {
|
|
498
|
+
log(`\n ✗ ${result.error}\n`, 'red');
|
|
499
|
+
process.exit(1);
|
|
500
|
+
}
|
|
501
|
+
break;
|
|
502
|
+
}
|
|
503
|
+
default:
|
|
504
|
+
log(' Usage: ag-kit plugin <list|install|remove>', 'yellow');
|
|
505
|
+
console.log('');
|
|
506
|
+
break;
|
|
507
|
+
}
|
|
508
|
+
} catch (/** @type {any} */ error) {
|
|
509
|
+
log(` ✗ Plugin command failed: ${error.message}`, 'red');
|
|
510
|
+
process.exit(1);
|
|
511
|
+
}
|
|
202
512
|
}
|
|
203
513
|
|
|
204
514
|
// Parse arguments
|
|
@@ -209,7 +519,9 @@ const options = {
|
|
|
209
519
|
force: args.includes('--force'),
|
|
210
520
|
quiet: args.includes('--quiet'),
|
|
211
521
|
dryRun: args.includes('--dry-run'),
|
|
522
|
+
apply: args.includes('--apply'),
|
|
212
523
|
path: null,
|
|
524
|
+
file: null,
|
|
213
525
|
};
|
|
214
526
|
|
|
215
527
|
// Parse --path option
|
|
@@ -218,21 +530,43 @@ if (pathIndex !== -1 && args[pathIndex + 1]) {
|
|
|
218
530
|
options.path = args[pathIndex + 1];
|
|
219
531
|
}
|
|
220
532
|
|
|
533
|
+
// Parse --file option
|
|
534
|
+
const fileIndex = args.indexOf('--file');
|
|
535
|
+
if (fileIndex !== -1 && args[fileIndex + 1]) {
|
|
536
|
+
options.file = args[fileIndex + 1];
|
|
537
|
+
}
|
|
538
|
+
|
|
221
539
|
// Execute command
|
|
222
540
|
switch (command) {
|
|
223
541
|
case 'init':
|
|
224
542
|
initCommand(options);
|
|
225
543
|
break;
|
|
226
544
|
case 'status':
|
|
545
|
+
case 'dashboard':
|
|
227
546
|
statusCommand();
|
|
228
547
|
break;
|
|
229
548
|
case 'update':
|
|
230
|
-
|
|
549
|
+
updateCommand(options);
|
|
231
550
|
break;
|
|
232
551
|
case 'verify':
|
|
233
|
-
|
|
234
|
-
log(' This will validate the integrity of all .agent/ files\n', 'cyan');
|
|
552
|
+
verifyCommand();
|
|
235
553
|
break;
|
|
554
|
+
case 'scan':
|
|
555
|
+
scanCommand();
|
|
556
|
+
break;
|
|
557
|
+
case 'plugin':
|
|
558
|
+
pluginCommand(args[1], args[2]);
|
|
559
|
+
break;
|
|
560
|
+
case 'market': {
|
|
561
|
+
const cliCommands = require('../lib/cli-commands');
|
|
562
|
+
cliCommands.marketCommand(process.cwd(), args[1], args[2], options);
|
|
563
|
+
break;
|
|
564
|
+
}
|
|
565
|
+
case 'heal': {
|
|
566
|
+
const cliCmd = require('../lib/cli-commands');
|
|
567
|
+
cliCmd.healCommand(process.cwd(), { file: options.file, apply: options.apply });
|
|
568
|
+
break;
|
|
569
|
+
}
|
|
236
570
|
case '--version':
|
|
237
571
|
case '-v':
|
|
238
572
|
console.log(VERSION);
|
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Antigravity AI Kit — Agent Registry
|
|
3
|
+
*
|
|
4
|
+
* Formalizes agent contracts by validating that every agent markdown
|
|
5
|
+
* file exposes required metadata structure.
|
|
6
|
+
*
|
|
7
|
+
* @module lib/agent-registry
|
|
8
|
+
* @author Emre Dursun
|
|
9
|
+
* @since v3.0.0
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
'use strict';
|
|
13
|
+
|
|
14
|
+
const fs = require('fs');
|
|
15
|
+
const path = require('path');
|
|
16
|
+
|
|
17
|
+
const AGENT_DIR = '.agent';
|
|
18
|
+
const AGENTS_SUBDIR = 'agents';
|
|
19
|
+
const MANIFEST_FILE = 'manifest.json';
|
|
20
|
+
|
|
21
|
+
/** Minimum expected file size for a valid agent file (bytes) */
|
|
22
|
+
const MIN_AGENT_SIZE = 100;
|
|
23
|
+
/** Maximum expected file size for a valid agent file (bytes) */
|
|
24
|
+
const MAX_AGENT_SIZE = 50000;
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* @typedef {object} AgentValidation
|
|
28
|
+
* @property {string} name - Agent name
|
|
29
|
+
* @property {boolean} valid - Overall validity
|
|
30
|
+
* @property {string[]} errors - Validation errors
|
|
31
|
+
* @property {string[]} warnings - Validation warnings
|
|
32
|
+
* @property {object} metadata - Extracted metadata
|
|
33
|
+
*/
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* @typedef {object} RegistryReport
|
|
37
|
+
* @property {number} total - Total agents checked
|
|
38
|
+
* @property {number} valid - Number of valid agents
|
|
39
|
+
* @property {number} invalid - Number of invalid agents
|
|
40
|
+
* @property {AgentValidation[]} agents - Individual agent results
|
|
41
|
+
*/
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Extracts metadata from an agent markdown file by parsing its structure.
|
|
45
|
+
*
|
|
46
|
+
* @param {string} content - Raw markdown content
|
|
47
|
+
* @returns {object} Extracted metadata
|
|
48
|
+
*/
|
|
49
|
+
function extractAgentMetadata(content) {
|
|
50
|
+
const lines = content.split('\n');
|
|
51
|
+
const metadata = {
|
|
52
|
+
hasTitle: false,
|
|
53
|
+
title: '',
|
|
54
|
+
hasRoleDescription: false,
|
|
55
|
+
hasCapabilities: false,
|
|
56
|
+
hasOutputFormat: false,
|
|
57
|
+
headingCount: 0,
|
|
58
|
+
lineCount: lines.length,
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
for (const line of lines) {
|
|
62
|
+
const trimmed = line.trim();
|
|
63
|
+
|
|
64
|
+
// Check for title (# heading)
|
|
65
|
+
if (trimmed.startsWith('# ') && !metadata.hasTitle) {
|
|
66
|
+
metadata.hasTitle = true;
|
|
67
|
+
metadata.title = trimmed.slice(2).trim();
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// Count all headings
|
|
71
|
+
if (trimmed.startsWith('#')) {
|
|
72
|
+
metadata.headingCount += 1;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// Check for role/responsibility keywords
|
|
76
|
+
const roleLower = trimmed.toLowerCase();
|
|
77
|
+
if (roleLower.includes('role') || roleLower.includes('responsibility') || roleLower.includes('purpose') || roleLower.includes('identity')) {
|
|
78
|
+
metadata.hasRoleDescription = true;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// Check for capabilities/skills mentions
|
|
82
|
+
if (roleLower.includes('capabilit') || roleLower.includes('skill') || roleLower.includes('tool') || roleLower.includes('expertise')) {
|
|
83
|
+
metadata.hasCapabilities = true;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// Check for output format
|
|
87
|
+
if (roleLower.includes('output') || roleLower.includes('format') || roleLower.includes('deliver') || roleLower.includes('produce')) {
|
|
88
|
+
metadata.hasOutputFormat = true;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
return metadata;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Validates a single agent file against contract requirements.
|
|
97
|
+
*
|
|
98
|
+
* @param {string} agentName - Name of the agent
|
|
99
|
+
* @param {string} projectRoot - Root directory of the project
|
|
100
|
+
* @returns {AgentValidation}
|
|
101
|
+
*/
|
|
102
|
+
function validateAgent(agentName, projectRoot) {
|
|
103
|
+
const agentPath = path.join(projectRoot, AGENT_DIR, AGENTS_SUBDIR, `${agentName}.md`);
|
|
104
|
+
/** @type {string[]} */
|
|
105
|
+
const errors = [];
|
|
106
|
+
/** @type {string[]} */
|
|
107
|
+
const warnings = [];
|
|
108
|
+
|
|
109
|
+
if (!fs.existsSync(agentPath)) {
|
|
110
|
+
return { name: agentName, valid: false, errors: [`File not found: ${agentName}.md`], warnings: [], metadata: {} };
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
const stats = fs.statSync(agentPath);
|
|
114
|
+
const content = fs.readFileSync(agentPath, 'utf-8');
|
|
115
|
+
const metadata = extractAgentMetadata(content);
|
|
116
|
+
|
|
117
|
+
// Size checks
|
|
118
|
+
if (stats.size < MIN_AGENT_SIZE) {
|
|
119
|
+
errors.push(`File too small (${stats.size} bytes) — likely incomplete`);
|
|
120
|
+
}
|
|
121
|
+
if (stats.size > MAX_AGENT_SIZE) {
|
|
122
|
+
warnings.push(`File very large (${stats.size} bytes) — consider splitting`);
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
// Contract checks
|
|
126
|
+
if (!metadata.hasTitle) {
|
|
127
|
+
errors.push('Missing title header (# AgentName)');
|
|
128
|
+
}
|
|
129
|
+
if (!metadata.hasRoleDescription) {
|
|
130
|
+
warnings.push('No role/responsibility section detected');
|
|
131
|
+
}
|
|
132
|
+
if (!metadata.hasCapabilities) {
|
|
133
|
+
warnings.push('No capabilities/skills section detected');
|
|
134
|
+
}
|
|
135
|
+
if (metadata.headingCount < 2) {
|
|
136
|
+
warnings.push('Very few headings — agent file may lack structure');
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
return {
|
|
140
|
+
name: agentName,
|
|
141
|
+
valid: errors.length === 0,
|
|
142
|
+
errors,
|
|
143
|
+
warnings,
|
|
144
|
+
metadata,
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* Validates all agents registered in the manifest.
|
|
150
|
+
*
|
|
151
|
+
* @param {string} projectRoot - Root directory of the project
|
|
152
|
+
* @returns {RegistryReport}
|
|
153
|
+
*/
|
|
154
|
+
function validateAllAgents(projectRoot) {
|
|
155
|
+
const manifestPath = path.join(projectRoot, AGENT_DIR, MANIFEST_FILE);
|
|
156
|
+
const manifest = JSON.parse(fs.readFileSync(manifestPath, 'utf-8'));
|
|
157
|
+
const agents = manifest.capabilities?.agents?.items || [];
|
|
158
|
+
|
|
159
|
+
const results = agents.map((agent) => validateAgent(agent.name, projectRoot));
|
|
160
|
+
const validCount = results.filter((r) => r.valid).length;
|
|
161
|
+
|
|
162
|
+
return {
|
|
163
|
+
total: results.length,
|
|
164
|
+
valid: validCount,
|
|
165
|
+
invalid: results.length - validCount,
|
|
166
|
+
agents: results,
|
|
167
|
+
};
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
/**
|
|
171
|
+
* Loads the full agent registry from manifest + filesystem.
|
|
172
|
+
*
|
|
173
|
+
* @param {string} projectRoot - Root directory of the project
|
|
174
|
+
* @returns {{ agents: object[], totalCount: number }}
|
|
175
|
+
*/
|
|
176
|
+
function loadRegistry(projectRoot) {
|
|
177
|
+
const manifestPath = path.join(projectRoot, AGENT_DIR, MANIFEST_FILE);
|
|
178
|
+
const manifest = JSON.parse(fs.readFileSync(manifestPath, 'utf-8'));
|
|
179
|
+
const agents = manifest.capabilities?.agents?.items || [];
|
|
180
|
+
|
|
181
|
+
return {
|
|
182
|
+
agents: agents.map((agent) => ({
|
|
183
|
+
name: agent.name,
|
|
184
|
+
file: agent.file,
|
|
185
|
+
domain: agent.domain,
|
|
186
|
+
})),
|
|
187
|
+
totalCount: agents.length,
|
|
188
|
+
};
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
/**
|
|
192
|
+
* Finds agents matching a domain keyword.
|
|
193
|
+
*
|
|
194
|
+
* @param {string} domain - Domain keyword to search for
|
|
195
|
+
* @param {string} projectRoot - Root directory of the project
|
|
196
|
+
* @returns {object[]} Matching agents
|
|
197
|
+
*/
|
|
198
|
+
function getAgentByDomain(domain, projectRoot) {
|
|
199
|
+
const { agents } = loadRegistry(projectRoot);
|
|
200
|
+
const lowerDomain = domain.toLowerCase();
|
|
201
|
+
|
|
202
|
+
return agents.filter((agent) =>
|
|
203
|
+
agent.domain.toLowerCase().includes(lowerDomain) ||
|
|
204
|
+
agent.name.toLowerCase().includes(lowerDomain)
|
|
205
|
+
);
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
module.exports = {
|
|
209
|
+
validateAgent,
|
|
210
|
+
validateAllAgents,
|
|
211
|
+
loadRegistry,
|
|
212
|
+
getAgentByDomain,
|
|
213
|
+
extractAgentMetadata,
|
|
214
|
+
};
|