antigravity-seo-kit 2.7.4 → 2.9.8
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/README.md +5 -2
- package/bin/cli.js +6 -0
- package/lib/downloader.js +1 -0
- package/lib/installer.js +251 -68
- package/lib/utils.js +2 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -14,7 +14,7 @@ npx antigravity-seo-kit install-plugin --key=SK-XXXX-XXXX-XXXX
|
|
|
14
14
|
# OR: npx antigravity-seo-kit install --global --key=SK-XXXX-XXXX-XXXX
|
|
15
15
|
```
|
|
16
16
|
|
|
17
|
-
When you start work in a new workspace, run the following command to sync the
|
|
17
|
+
When you start work in a new workspace, run the following command to sync the `.agents/` structure locally:
|
|
18
18
|
```bash
|
|
19
19
|
npx antigravity-seo-kit setup-workspace
|
|
20
20
|
```
|
|
@@ -45,12 +45,15 @@ npx antigravity-seo-kit install --key=SK-XXXX-XXXX-XXXX
|
|
|
45
45
|
# Install globally as a plugin (recommended)
|
|
46
46
|
npx antigravity-seo-kit install-plugin --key=SK-XXXX-XXXX-XXXX
|
|
47
47
|
|
|
48
|
-
# Replicate .
|
|
48
|
+
# Replicate .agents/ workspace structure from global plugin
|
|
49
49
|
npx antigravity-seo-kit setup-workspace
|
|
50
50
|
|
|
51
51
|
# Install locally into current workspace
|
|
52
52
|
npx antigravity-seo-kit install --key=SK-XXXX-XXXX-XXXX
|
|
53
53
|
|
|
54
|
+
# Migrate from v2.x (.agent/) to v3.0 (.agents/)
|
|
55
|
+
npx antigravity-seo-kit migrate
|
|
56
|
+
|
|
54
57
|
# Update to latest version
|
|
55
58
|
npx antigravity-seo-kit update
|
|
56
59
|
|
package/bin/cli.js
CHANGED
package/lib/downloader.js
CHANGED
|
@@ -149,6 +149,7 @@ function extractTarGz(gzBuffer, targetDir) {
|
|
|
149
149
|
const isConfigJson = fullName.endsWith('.json') &&
|
|
150
150
|
(fullName.startsWith('config/') ||
|
|
151
151
|
fullName.startsWith('.agent/config/') ||
|
|
152
|
+
fullName.startsWith('.agents/config/') ||
|
|
152
153
|
fullName.includes('/config/'));
|
|
153
154
|
|
|
154
155
|
fs.mkdirSync(path.dirname(targetPath), { recursive: true });
|
package/lib/installer.js
CHANGED
|
@@ -69,7 +69,46 @@ async function install(licenseKey, cwd) {
|
|
|
69
69
|
process.exit(1);
|
|
70
70
|
}
|
|
71
71
|
|
|
72
|
-
// Step 3:
|
|
72
|
+
// Step 3: Restructure into .agents/ flat format if server sent legacy .agent/
|
|
73
|
+
const legacyAgentDir = path.join(cwd, '.agent');
|
|
74
|
+
const newAgentsDir = path.join(cwd, '.agents');
|
|
75
|
+
|
|
76
|
+
if (fs.existsSync(legacyAgentDir) && !fs.existsSync(newAgentsDir)) {
|
|
77
|
+
const spinMigrate = spinner('Restructuring to .agents/ format...').start();
|
|
78
|
+
try {
|
|
79
|
+
fs.mkdirSync(newAgentsDir, { recursive: true });
|
|
80
|
+
|
|
81
|
+
// ALL dirs go directly into .agents/ (flat workspace structure)
|
|
82
|
+
const allDirs = ['skills', 'rules', 'agents', 'workflows', 'scripts', 'config', 'dashboard', 'docs', '.shared'];
|
|
83
|
+
let migrateCount = 0;
|
|
84
|
+
for (const dir of allDirs) {
|
|
85
|
+
const src = path.join(legacyAgentDir, dir);
|
|
86
|
+
const dest = path.join(newAgentsDir, dir);
|
|
87
|
+
if (fs.existsSync(src)) {
|
|
88
|
+
migrateCount += copyRecursive(src, dest, { overwrite: true });
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// Root-level files (.md, .json) → .agents/
|
|
93
|
+
for (const f of fs.readdirSync(legacyAgentDir)) {
|
|
94
|
+
const src = path.join(legacyAgentDir, f);
|
|
95
|
+
if (fs.statSync(src).isFile()) {
|
|
96
|
+
fs.copyFileSync(src, path.join(newAgentsDir, f));
|
|
97
|
+
migrateCount++;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// Remove legacy .agent/
|
|
102
|
+
removeRecursive(legacyAgentDir);
|
|
103
|
+
|
|
104
|
+
spinMigrate.succeed(`Restructured to .agents/ format (${migrateCount} files)`);
|
|
105
|
+
} catch (err) {
|
|
106
|
+
spinMigrate.fail('Restructuring failed, keeping .agent/ as-is');
|
|
107
|
+
warn(`You can manually run: npx antigravity-seo-kit migrate`);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// Step 4: Save license info + manifest
|
|
73
112
|
writeLicenseFile(cwd, {
|
|
74
113
|
key: licenseKey,
|
|
75
114
|
deviceId,
|
|
@@ -122,6 +161,10 @@ async function update(cwd) {
|
|
|
122
161
|
process.exit(1);
|
|
123
162
|
}
|
|
124
163
|
|
|
164
|
+
// Detect structure: v3.0 (.agents/) or v2.x (.agent/)
|
|
165
|
+
const isV3 = fs.existsSync(path.join(cwd, '.agents'));
|
|
166
|
+
const isV2 = fs.existsSync(path.join(cwd, '.agent'));
|
|
167
|
+
|
|
125
168
|
// Download latest assets from server
|
|
126
169
|
console.log('');
|
|
127
170
|
const spinDl = spinner('Downloading latest SEO Kit assets...').start();
|
|
@@ -136,6 +179,13 @@ async function update(cwd) {
|
|
|
136
179
|
process.exit(1);
|
|
137
180
|
}
|
|
138
181
|
|
|
182
|
+
// If user was on v2 (.agent/) and download brings v3 (.agents/), inform about migrate
|
|
183
|
+
if (isV2 && !isV3 && fs.existsSync(path.join(cwd, '.agents'))) {
|
|
184
|
+
console.log('');
|
|
185
|
+
info('v3.0 structure detected in update. Run migrate to complete:');
|
|
186
|
+
console.log(` ${colorize('cyan', 'npx antigravity-seo-kit migrate')}`);
|
|
187
|
+
}
|
|
188
|
+
|
|
139
189
|
// Update license file
|
|
140
190
|
config.version = PACKAGE_VERSION;
|
|
141
191
|
config.updatedAt = new Date().toISOString();
|
|
@@ -160,7 +210,7 @@ async function uninstall(cwd) {
|
|
|
160
210
|
let totalRemoved = 0;
|
|
161
211
|
|
|
162
212
|
if (config.installedFiles && config.installedFiles.length > 0) {
|
|
163
|
-
//
|
|
213
|
+
// Manifest-based removal
|
|
164
214
|
for (const filePath of config.installedFiles) {
|
|
165
215
|
const target = path.join(cwd, filePath);
|
|
166
216
|
if (fs.existsSync(target)) {
|
|
@@ -168,10 +218,11 @@ async function uninstall(cwd) {
|
|
|
168
218
|
totalRemoved++;
|
|
169
219
|
}
|
|
170
220
|
}
|
|
171
|
-
// Clean up empty directories
|
|
221
|
+
// Clean up empty directories for both v2 and v3 structures
|
|
172
222
|
cleanEmptyDirsUp(path.join(cwd, '.agent'));
|
|
223
|
+
cleanEmptyDirsUp(path.join(cwd, '.agents'));
|
|
173
224
|
} else {
|
|
174
|
-
// Legacy fallback: use
|
|
225
|
+
// Legacy fallback: use prefix scan
|
|
175
226
|
totalRemoved += legacyUninstall(cwd);
|
|
176
227
|
}
|
|
177
228
|
|
|
@@ -253,24 +304,36 @@ async function status(cwd) {
|
|
|
253
304
|
|
|
254
305
|
// Count installed files
|
|
255
306
|
if (config.installedFiles && config.installedFiles.length > 0) {
|
|
256
|
-
//
|
|
307
|
+
// Manifest-based count
|
|
257
308
|
let existingFiles = 0;
|
|
258
309
|
for (const f of config.installedFiles) {
|
|
259
310
|
if (fs.existsSync(path.join(cwd, f))) existingFiles++;
|
|
260
311
|
}
|
|
261
312
|
console.log(` ${colorize('cyan', 'Files:')} ${existingFiles}/${config.installedFiles.length} present`);
|
|
262
313
|
} else {
|
|
263
|
-
// Legacy: scan for seo-* prefixed entries
|
|
264
|
-
const agentDir = path.join(cwd, '.agent');
|
|
314
|
+
// Legacy: scan for seo-* prefixed entries in both .agent/ and .agents/
|
|
265
315
|
let totalLegacy = 0;
|
|
266
|
-
for (const
|
|
267
|
-
const
|
|
268
|
-
if (!fs.existsSync(
|
|
269
|
-
for (const
|
|
270
|
-
|
|
316
|
+
for (const baseDir of ['.agent', '.agents']) {
|
|
317
|
+
const agentDir = path.join(cwd, baseDir);
|
|
318
|
+
if (!fs.existsSync(agentDir)) continue;
|
|
319
|
+
for (const subDir of LEGACY_DIRS) {
|
|
320
|
+
const dirPath = path.join(agentDir, subDir);
|
|
321
|
+
if (!fs.existsSync(dirPath)) continue;
|
|
322
|
+
for (const entry of fs.readdirSync(dirPath)) {
|
|
323
|
+
if (entry.startsWith(LEGACY_SEO_PREFIX) || entry === 'seo') totalLegacy++;
|
|
324
|
+
}
|
|
271
325
|
}
|
|
272
326
|
}
|
|
273
|
-
console.log(` ${colorize('cyan', 'Components:')} ${totalLegacy} installed
|
|
327
|
+
console.log(` ${colorize('cyan', 'Components:')} ${totalLegacy} installed`);
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
// Detect structure version
|
|
331
|
+
const hasV3 = fs.existsSync(path.join(cwd, '.agents'));
|
|
332
|
+
const hasV2 = fs.existsSync(path.join(cwd, '.agent'));
|
|
333
|
+
const structureVersion = hasV3 ? 'v3.0 (.agents/)' : hasV2 ? 'v2.x (.agent/)' : 'unknown';
|
|
334
|
+
console.log(` ${colorize('cyan', 'Structure:')} ${structureVersion}`);
|
|
335
|
+
if (hasV2 && !hasV3) {
|
|
336
|
+
warn('Using legacy v2.x structure. Run: npx antigravity-seo-kit migrate');
|
|
274
337
|
}
|
|
275
338
|
console.log('');
|
|
276
339
|
|
|
@@ -436,51 +499,72 @@ async function installPlugin(licenseKey) {
|
|
|
436
499
|
process.exit(1);
|
|
437
500
|
}
|
|
438
501
|
|
|
439
|
-
// Step 3:
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
502
|
+
// Step 3: Restructure into .agents/ plugin format
|
|
503
|
+
// v3.0: Downloaded assets arrive in .agents/ structure already
|
|
504
|
+
// Handle legacy .agent/ if server still serves old format
|
|
505
|
+
const legacyAgentDir = path.join(globalPluginDir, '.agent');
|
|
506
|
+
const newAgentsDir = path.join(globalPluginDir, '.agents');
|
|
507
|
+
|
|
508
|
+
if (fs.existsSync(legacyAgentDir) && !fs.existsSync(newAgentsDir)) {
|
|
509
|
+
// Legacy format: flatten .agent/ into plugin root
|
|
510
|
+
const entries = fs.readdirSync(legacyAgentDir);
|
|
443
511
|
for (const entry of entries) {
|
|
444
|
-
const srcPath = path.join(
|
|
512
|
+
const srcPath = path.join(legacyAgentDir, entry);
|
|
445
513
|
const destPath = path.join(globalPluginDir, entry);
|
|
446
514
|
if (fs.existsSync(destPath)) {
|
|
447
515
|
removeRecursive(destPath);
|
|
448
516
|
}
|
|
449
517
|
fs.renameSync(srcPath, destPath);
|
|
450
518
|
}
|
|
451
|
-
removeRecursive(
|
|
519
|
+
removeRecursive(legacyAgentDir);
|
|
520
|
+
} else if (fs.existsSync(newAgentsDir)) {
|
|
521
|
+
// v3.0 format: move plugin contents (skills, rules) to plugin root
|
|
522
|
+
const pluginSrcDir = path.join(newAgentsDir, 'plugins', 'antigravity-seo-kit');
|
|
523
|
+
if (fs.existsSync(pluginSrcDir)) {
|
|
524
|
+
for (const entry of fs.readdirSync(pluginSrcDir)) {
|
|
525
|
+
const srcPath = path.join(pluginSrcDir, entry);
|
|
526
|
+
const destPath = path.join(globalPluginDir, entry);
|
|
527
|
+
if (fs.existsSync(destPath)) {
|
|
528
|
+
removeRecursive(destPath);
|
|
529
|
+
}
|
|
530
|
+
fs.renameSync(srcPath, destPath);
|
|
531
|
+
}
|
|
532
|
+
}
|
|
533
|
+
// Keep workspace-level dirs (agents, workflows) for setupWorkspace
|
|
534
|
+
const workspaceDirs = ['agents', 'workflows', 'scripts', 'config', 'dashboard', 'docs', '.shared'];
|
|
535
|
+
for (const dir of workspaceDirs) {
|
|
536
|
+
const srcDir = path.join(newAgentsDir, dir);
|
|
537
|
+
const destDir = path.join(globalPluginDir, `_workspace_${dir}`);
|
|
538
|
+
if (fs.existsSync(srcDir)) {
|
|
539
|
+
if (fs.existsSync(destDir)) removeRecursive(destDir);
|
|
540
|
+
fs.renameSync(srcDir, destDir);
|
|
541
|
+
}
|
|
542
|
+
}
|
|
543
|
+
// Copy seo-architecture.md
|
|
544
|
+
const archFile = path.join(newAgentsDir, 'seo-architecture.md');
|
|
545
|
+
if (fs.existsSync(archFile)) {
|
|
546
|
+
fs.copyFileSync(archFile, path.join(globalPluginDir, '_workspace_seo-architecture.md'));
|
|
547
|
+
}
|
|
548
|
+
removeRecursive(newAgentsDir);
|
|
452
549
|
}
|
|
453
550
|
|
|
454
|
-
// Step 4:
|
|
455
|
-
const
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
email: "admin@solann.io",
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
"ai-agent",
|
|
469
|
-
"antigravity",
|
|
470
|
-
"seo-geo",
|
|
471
|
-
"seo-audit",
|
|
472
|
-
"seo-toolkit",
|
|
473
|
-
"agent-skills",
|
|
474
|
-
"seo-analysis",
|
|
475
|
-
"technical-seo",
|
|
476
|
-
"eeat"
|
|
477
|
-
]
|
|
478
|
-
};
|
|
479
|
-
fs.writeFileSync(path.join(globalPluginDir, 'plugin.json'), JSON.stringify(pluginJson, null, 2), 'utf-8');
|
|
551
|
+
// Step 4: Ensure plugin.json and installed_version.json
|
|
552
|
+
const pluginJsonPath = path.join(globalPluginDir, 'plugin.json');
|
|
553
|
+
if (!fs.existsSync(pluginJsonPath)) {
|
|
554
|
+
const pluginJson = {
|
|
555
|
+
name: "antigravity-seo-kit",
|
|
556
|
+
version: PACKAGE_VERSION,
|
|
557
|
+
description: "Professional Agentic SEO Platform — 44+ specialized skills",
|
|
558
|
+
author: { name: "Solann", email: "admin@solann.io" },
|
|
559
|
+
repository: "https://solann.io/antigravity-seo-kit",
|
|
560
|
+
license: "SEE LICENSE IN LICENSE",
|
|
561
|
+
keywords: ["seo", "agentic-seo", "ai-agent", "antigravity"]
|
|
562
|
+
};
|
|
563
|
+
fs.writeFileSync(pluginJsonPath, JSON.stringify(pluginJson, null, 2), 'utf-8');
|
|
564
|
+
}
|
|
480
565
|
fs.writeFileSync(path.join(globalPluginDir, 'installed_version.json'), JSON.stringify({ version: PACKAGE_VERSION }), 'utf-8');
|
|
481
566
|
|
|
482
567
|
// Step 5: Save global license info + manifest
|
|
483
|
-
const LICENSE_FILE = '.seo-kit-license';
|
|
484
568
|
writeLicenseFile(globalPluginDir, {
|
|
485
569
|
key: licenseKey,
|
|
486
570
|
deviceId,
|
|
@@ -488,19 +572,19 @@ async function installPlugin(licenseKey) {
|
|
|
488
572
|
version: PACKAGE_VERSION,
|
|
489
573
|
installedAt: new Date().toISOString(),
|
|
490
574
|
plan: verifyResult?.license?.planName || verifyResult?.license?.plan || 'unknown',
|
|
491
|
-
installedFiles: downloadResult.files.map(f => f.replace(/^\.
|
|
575
|
+
installedFiles: downloadResult.files.map(f => f.replace(/^\.agents?\//, '')),
|
|
492
576
|
});
|
|
493
577
|
|
|
494
578
|
// Done!
|
|
495
579
|
console.log('');
|
|
496
580
|
console.log(colorize('green', '═══════════════════════════════════════════════════════'));
|
|
497
|
-
success(`SEO Kit v${PACKAGE_VERSION} installed
|
|
581
|
+
success(`SEO Kit v${PACKAGE_VERSION} installed as global Antigravity plugin!`);
|
|
498
582
|
console.log(colorize('green', '═══════════════════════════════════════════════════════'));
|
|
499
583
|
console.log('');
|
|
500
584
|
|
|
501
585
|
info('Next steps:');
|
|
502
586
|
console.log(` ${colorize('yellow', '1.')} Restart or open any workspace in ${colorize('bold', 'Google Antigravity')}`);
|
|
503
|
-
console.log(` ${colorize('yellow', '2.')}
|
|
587
|
+
console.log(` ${colorize('yellow', '2.')} Plugin loads globally. Run ${colorize('cyan', 'npx antigravity-seo-kit setup-workspace')} in a project.`);
|
|
504
588
|
console.log('');
|
|
505
589
|
|
|
506
590
|
if (verifyResult?.devicesUsed != null) {
|
|
@@ -511,10 +595,10 @@ async function installPlugin(licenseKey) {
|
|
|
511
595
|
|
|
512
596
|
function setupWorkspace(cwd) {
|
|
513
597
|
const globalDir = getGlobalPluginDir();
|
|
514
|
-
const
|
|
598
|
+
const localAgentsDir = path.join(cwd, '.agents');
|
|
515
599
|
|
|
516
|
-
if (fs.existsSync(
|
|
517
|
-
info('Existing .
|
|
600
|
+
if (fs.existsSync(localAgentsDir)) {
|
|
601
|
+
info('Existing .agents directory found. Re-synchronizing...');
|
|
518
602
|
}
|
|
519
603
|
|
|
520
604
|
if (!fs.existsSync(globalDir)) {
|
|
@@ -523,40 +607,82 @@ function setupWorkspace(cwd) {
|
|
|
523
607
|
process.exit(1);
|
|
524
608
|
}
|
|
525
609
|
|
|
526
|
-
const spin = spinner('
|
|
610
|
+
const spin = spinner('Setting up .agents/ workspace structure...').start();
|
|
527
611
|
try {
|
|
528
|
-
fs.mkdirSync(
|
|
612
|
+
fs.mkdirSync(localAgentsDir, { recursive: true });
|
|
529
613
|
|
|
530
|
-
//
|
|
531
|
-
//
|
|
532
|
-
const
|
|
533
|
-
const
|
|
614
|
+
// Copy workspace-level dirs from global plugin to local .agents/
|
|
615
|
+
// Skills & rules are NOT copied — Antigravity loads them from global plugin
|
|
616
|
+
const workspaceDirs = ['agents', 'workflows', 'scripts', 'config', 'dashboard', 'docs', '.shared'];
|
|
617
|
+
const rootFiles = ['seo-architecture.md'];
|
|
534
618
|
|
|
535
619
|
let count = 0;
|
|
536
|
-
for (const dir of
|
|
537
|
-
|
|
538
|
-
|
|
620
|
+
for (const dir of workspaceDirs) {
|
|
621
|
+
// Try _workspace_ prefixed dirs first (v3.0 install format)
|
|
622
|
+
let src = path.join(globalDir, `_workspace_${dir}`);
|
|
623
|
+
if (!fs.existsSync(src)) {
|
|
624
|
+
src = path.join(globalDir, dir);
|
|
625
|
+
}
|
|
626
|
+
const dest = path.join(localAgentsDir, dir);
|
|
539
627
|
if (fs.existsSync(src)) {
|
|
540
628
|
count += copyRecursive(src, dest, { overwrite: true });
|
|
541
629
|
}
|
|
542
630
|
}
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
631
|
+
|
|
632
|
+
// Copy root-level files
|
|
633
|
+
for (const f of rootFiles) {
|
|
634
|
+
let src = path.join(globalDir, `_workspace_${f}`);
|
|
635
|
+
if (!fs.existsSync(src)) {
|
|
636
|
+
src = path.join(globalDir, f);
|
|
637
|
+
}
|
|
638
|
+
const dest = path.join(localAgentsDir, f);
|
|
546
639
|
if (fs.existsSync(src)) {
|
|
547
640
|
fs.copyFileSync(src, dest);
|
|
548
641
|
count++;
|
|
549
642
|
}
|
|
550
643
|
}
|
|
551
644
|
|
|
552
|
-
|
|
553
|
-
const
|
|
554
|
-
const
|
|
645
|
+
// Copy hooks.json to .agents/ root if exists in global plugin
|
|
646
|
+
const hooksFiles = ['hooks.json', '_workspace_hooks.json'];
|
|
647
|
+
for (const hf of hooksFiles) {
|
|
648
|
+
const hooksSrc = path.join(globalDir, hf);
|
|
649
|
+
if (fs.existsSync(hooksSrc)) {
|
|
650
|
+
const hooksDest = path.join(localAgentsDir, 'hooks.json');
|
|
651
|
+
if (!fs.existsSync(hooksDest)) {
|
|
652
|
+
fs.copyFileSync(hooksSrc, hooksDest);
|
|
653
|
+
count++;
|
|
654
|
+
}
|
|
655
|
+
break;
|
|
656
|
+
}
|
|
657
|
+
}
|
|
658
|
+
|
|
659
|
+
// Copy mcp_config.json to .agents/ root if exists in global plugin
|
|
660
|
+
const mcpFiles = ['mcp_config.json', '_workspace_mcp_config.json'];
|
|
661
|
+
for (const mf of mcpFiles) {
|
|
662
|
+
const mcpSrc = path.join(globalDir, mf);
|
|
663
|
+
if (fs.existsSync(mcpSrc)) {
|
|
664
|
+
const mcpDest = path.join(localAgentsDir, 'mcp_config.json');
|
|
665
|
+
if (!fs.existsSync(mcpDest)) {
|
|
666
|
+
fs.copyFileSync(mcpSrc, mcpDest);
|
|
667
|
+
count++;
|
|
668
|
+
}
|
|
669
|
+
break;
|
|
670
|
+
}
|
|
671
|
+
}
|
|
672
|
+
|
|
673
|
+
// Copy license file to workspace
|
|
674
|
+
const LICENSE_FILE_NAME = '.seo-kit-license';
|
|
675
|
+
const globalLicense = path.join(globalDir, LICENSE_FILE_NAME);
|
|
676
|
+
const localLicense = path.join(cwd, LICENSE_FILE_NAME);
|
|
555
677
|
if (fs.existsSync(globalLicense) && !fs.existsSync(localLicense)) {
|
|
556
678
|
fs.copyFileSync(globalLicense, localLicense);
|
|
557
679
|
}
|
|
558
680
|
|
|
559
|
-
spin.succeed(`Workspace setup complete! Copied ${count} files to .
|
|
681
|
+
spin.succeed(`Workspace setup complete! Copied ${count} files to .agents/`);
|
|
682
|
+
console.log('');
|
|
683
|
+
info('Skills and rules are loaded from global plugin automatically.');
|
|
684
|
+
info('Workspace-level files (workflows, agents, scripts) are now local.');
|
|
685
|
+
console.log('');
|
|
560
686
|
} catch (err) {
|
|
561
687
|
spin.fail('Workspace setup failed');
|
|
562
688
|
error(err.message);
|
|
@@ -564,6 +690,62 @@ function setupWorkspace(cwd) {
|
|
|
564
690
|
}
|
|
565
691
|
}
|
|
566
692
|
|
|
693
|
+
// ─── Migrate Command (v2.x → v3.0) ─────────────────────────────────────────
|
|
694
|
+
|
|
695
|
+
function migrate(cwd) {
|
|
696
|
+
const oldAgentDir = path.join(cwd, '.agent');
|
|
697
|
+
const newAgentsDir = path.join(cwd, '.agents');
|
|
698
|
+
|
|
699
|
+
if (!fs.existsSync(oldAgentDir)) {
|
|
700
|
+
if (fs.existsSync(newAgentsDir)) {
|
|
701
|
+
info('Already using v3.0 .agents/ structure. No migration needed.');
|
|
702
|
+
return;
|
|
703
|
+
}
|
|
704
|
+
error('No .agent/ directory found. Nothing to migrate.');
|
|
705
|
+
process.exit(1);
|
|
706
|
+
}
|
|
707
|
+
|
|
708
|
+
if (fs.existsSync(newAgentsDir)) {
|
|
709
|
+
warn('.agents/ already exists. Migration will merge/overwrite.');
|
|
710
|
+
}
|
|
711
|
+
|
|
712
|
+
const spin = spinner('Migrating .agent/ → .agents/ (v2.x → v3.0)...').start();
|
|
713
|
+
try {
|
|
714
|
+
fs.mkdirSync(newAgentsDir, { recursive: true });
|
|
715
|
+
let count = 0;
|
|
716
|
+
|
|
717
|
+
// Copy ALL directories directly into .agents/ (flat workspace structure)
|
|
718
|
+
const allDirs = ['skills', 'rules', 'agents', 'workflows', 'scripts', 'config', 'dashboard', 'docs', '.shared'];
|
|
719
|
+
for (const dir of allDirs) {
|
|
720
|
+
const src = path.join(oldAgentDir, dir);
|
|
721
|
+
const dest = path.join(newAgentsDir, dir);
|
|
722
|
+
if (fs.existsSync(src)) {
|
|
723
|
+
count += copyRecursive(src, dest, { overwrite: true, mergeJson: true });
|
|
724
|
+
}
|
|
725
|
+
}
|
|
726
|
+
|
|
727
|
+
// Copy root-level files (.md, .json, etc.)
|
|
728
|
+
for (const f of fs.readdirSync(oldAgentDir)) {
|
|
729
|
+
const src = path.join(oldAgentDir, f);
|
|
730
|
+
if (fs.statSync(src).isFile()) {
|
|
731
|
+
fs.copyFileSync(src, path.join(newAgentsDir, f));
|
|
732
|
+
count++;
|
|
733
|
+
}
|
|
734
|
+
}
|
|
735
|
+
|
|
736
|
+
spin.succeed(`Migration complete! ${count} files moved to .agents/`);
|
|
737
|
+
console.log('');
|
|
738
|
+
info('The old .agent/ directory has been preserved as backup.');
|
|
739
|
+
info('After verifying everything works, you can remove it:');
|
|
740
|
+
console.log(` ${colorize('gray', 'rm -rf .agent/')}`);
|
|
741
|
+
console.log('');
|
|
742
|
+
} catch (err) {
|
|
743
|
+
spin.fail('Migration failed');
|
|
744
|
+
error(err.message);
|
|
745
|
+
process.exit(1);
|
|
746
|
+
}
|
|
747
|
+
}
|
|
748
|
+
|
|
567
749
|
// ─── Exports ────────────────────────────────────────────────────────────────
|
|
568
750
|
|
|
569
751
|
module.exports = {
|
|
@@ -575,4 +757,5 @@ module.exports = {
|
|
|
575
757
|
deviceRemove,
|
|
576
758
|
installPlugin,
|
|
577
759
|
setupWorkspace,
|
|
760
|
+
migrate,
|
|
578
761
|
};
|
package/lib/utils.js
CHANGED
|
@@ -307,7 +307,8 @@ function showHelp() {
|
|
|
307
307
|
console.log(`${colorize('bold', 'Commands:')}`);
|
|
308
308
|
console.log(` ${colorize('green', 'install')} --key=SK-XXXX-XXXX-XXXX Install SEO Kit into current workspace`);
|
|
309
309
|
console.log(` ${colorize('green', 'install-plugin')} --key=SK-XXXX-XXXX-XXXX Install SEO Kit globally as an Antigravity plugin`);
|
|
310
|
-
console.log(` ${colorize('green', 'setup-workspace')} Replicate .
|
|
310
|
+
console.log(` ${colorize('green', 'setup-workspace')} Replicate .agents config directory to current workspace`);
|
|
311
|
+
console.log(` ${colorize('green', 'migrate')} Migrate .agent/ to .agents/ (v2.x → v3.0)`);
|
|
311
312
|
console.log(` ${colorize('green', 'update')} Update to latest version`);
|
|
312
313
|
console.log(` ${colorize('green', 'uninstall')} Remove SEO Kit from workspace`);
|
|
313
314
|
console.log(` ${colorize('green', 'status')} Show license & installation info`);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "antigravity-seo-kit",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.9.8",
|
|
4
4
|
"description": "Professional Agentic SEO Platform for Google Antigravity 2 AI Agent — 44 specialized skills covering technical audit, E-E-A-T, schema, GEO, local SEO & more",
|
|
5
5
|
"main": "lib/installer.js",
|
|
6
6
|
"bin": {
|