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.
Files changed (114) hide show
  1. package/.agent/README.md +4 -4
  2. package/.agent/agents/README.md +16 -12
  3. package/.agent/agents/architect.md +1 -0
  4. package/.agent/agents/backend-specialist.md +11 -0
  5. package/.agent/agents/code-reviewer.md +1 -0
  6. package/.agent/agents/database-architect.md +11 -0
  7. package/.agent/agents/devops-engineer.md +11 -0
  8. package/.agent/agents/e2e-runner.md +1 -0
  9. package/.agent/agents/explorer-agent.md +11 -0
  10. package/.agent/agents/frontend-specialist.md +11 -0
  11. package/.agent/agents/mobile-developer.md +11 -0
  12. package/.agent/agents/performance-optimizer.md +11 -0
  13. package/.agent/agents/planner.md +1 -0
  14. package/.agent/agents/refactor-cleaner.md +1 -0
  15. package/.agent/agents/reliability-engineer.md +11 -0
  16. package/.agent/agents/security-reviewer.md +1 -0
  17. package/.agent/agents/sprint-orchestrator.md +10 -0
  18. package/.agent/agents/tdd-guide.md +1 -0
  19. package/.agent/commands/code-review.md +1 -0
  20. package/.agent/commands/debug.md +1 -0
  21. package/.agent/commands/deploy.md +1 -0
  22. package/.agent/commands/help.md +252 -31
  23. package/.agent/commands/plan.md +1 -0
  24. package/.agent/commands/status.md +1 -0
  25. package/.agent/commands/tdd.md +1 -0
  26. package/.agent/contexts/brainstorm.md +26 -0
  27. package/.agent/contexts/debug.md +28 -0
  28. package/.agent/contexts/implement.md +29 -0
  29. package/.agent/contexts/review.md +27 -0
  30. package/.agent/contexts/ship.md +28 -0
  31. package/.agent/engine/identity.json +13 -0
  32. package/.agent/engine/loading-rules.json +23 -1
  33. package/.agent/engine/marketplace-index.json +29 -0
  34. package/.agent/engine/reliability-config.json +14 -0
  35. package/.agent/engine/sdlc-map.json +44 -0
  36. package/.agent/engine/workflow-state.json +28 -2
  37. package/.agent/hooks/hooks.json +27 -25
  38. package/.agent/manifest.json +12 -4
  39. package/.agent/rules.md +2 -1
  40. package/.agent/skills/README.md +10 -5
  41. package/.agent/skills/i18n-localization/SKILL.md +191 -0
  42. package/.agent/skills/mcp-integration/SKILL.md +224 -0
  43. package/.agent/skills/parallel-agents/SKILL.md +1 -1
  44. package/.agent/skills/shell-conventions/SKILL.md +92 -0
  45. package/.agent/skills/ui-ux-pro-max/SKILL.md +557 -0
  46. package/.agent/skills/ui-ux-pro-max/data/charts.csv +26 -0
  47. package/.agent/skills/ui-ux-pro-max/data/colors.csv +97 -0
  48. package/.agent/skills/ui-ux-pro-max/data/icons.csv +101 -0
  49. package/.agent/skills/ui-ux-pro-max/data/landing.csv +31 -0
  50. package/.agent/skills/ui-ux-pro-max/data/products.csv +97 -0
  51. package/.agent/skills/ui-ux-pro-max/data/react-performance.csv +45 -0
  52. package/.agent/skills/ui-ux-pro-max/data/stacks/astro.csv +54 -0
  53. package/.agent/skills/ui-ux-pro-max/data/stacks/flutter.csv +53 -0
  54. package/.agent/skills/ui-ux-pro-max/data/stacks/html-tailwind.csv +56 -0
  55. package/.agent/skills/ui-ux-pro-max/data/stacks/jetpack-compose.csv +53 -0
  56. package/.agent/skills/ui-ux-pro-max/data/stacks/nextjs.csv +53 -0
  57. package/.agent/skills/ui-ux-pro-max/data/stacks/nuxt-ui.csv +51 -0
  58. package/.agent/skills/ui-ux-pro-max/data/stacks/nuxtjs.csv +59 -0
  59. package/.agent/skills/ui-ux-pro-max/data/stacks/react-native.csv +52 -0
  60. package/.agent/skills/ui-ux-pro-max/data/stacks/react.csv +54 -0
  61. package/.agent/skills/ui-ux-pro-max/data/stacks/shadcn.csv +61 -0
  62. package/.agent/skills/ui-ux-pro-max/data/stacks/svelte.csv +54 -0
  63. package/.agent/skills/ui-ux-pro-max/data/stacks/swiftui.csv +51 -0
  64. package/.agent/skills/ui-ux-pro-max/data/stacks/vue.csv +50 -0
  65. package/.agent/skills/ui-ux-pro-max/data/styles.csv +68 -0
  66. package/.agent/skills/ui-ux-pro-max/data/typography.csv +58 -0
  67. package/.agent/skills/ui-ux-pro-max/data/ui-reasoning.csv +101 -0
  68. package/.agent/skills/ui-ux-pro-max/data/ux-guidelines.csv +100 -0
  69. package/.agent/skills/ui-ux-pro-max/data/web-interface.csv +31 -0
  70. package/.agent/skills/ui-ux-pro-max/scripts/core.py +253 -0
  71. package/.agent/skills/ui-ux-pro-max/scripts/design_system.py +1067 -0
  72. package/.agent/skills/ui-ux-pro-max/scripts/search.py +114 -0
  73. package/.agent/templates/adr-template.md +32 -0
  74. package/.agent/templates/bug-report.md +37 -0
  75. package/.agent/templates/feature-request.md +32 -0
  76. package/.agent/workflows/README.md +92 -78
  77. package/.agent/workflows/brainstorm.md +154 -100
  78. package/.agent/workflows/create.md +142 -75
  79. package/.agent/workflows/debug.md +157 -98
  80. package/.agent/workflows/deploy.md +195 -144
  81. package/.agent/workflows/enhance.md +157 -65
  82. package/.agent/workflows/orchestrate.md +171 -114
  83. package/.agent/workflows/plan.md +147 -72
  84. package/.agent/workflows/preview.md +140 -83
  85. package/.agent/workflows/quality-gate.md +196 -0
  86. package/.agent/workflows/retrospective.md +197 -0
  87. package/.agent/workflows/review.md +188 -0
  88. package/.agent/workflows/status.md +142 -91
  89. package/.agent/workflows/test.md +168 -95
  90. package/.agent/workflows/ui-ux-pro-max.md +181 -127
  91. package/README.md +215 -78
  92. package/bin/ag-kit.js +344 -10
  93. package/lib/agent-registry.js +214 -0
  94. package/lib/agent-reputation.js +351 -0
  95. package/lib/cli-commands.js +235 -0
  96. package/lib/conflict-detector.js +245 -0
  97. package/lib/engineering-manager.js +354 -0
  98. package/lib/error-budget.js +294 -0
  99. package/lib/hook-system.js +252 -0
  100. package/lib/identity.js +245 -0
  101. package/lib/loading-engine.js +208 -0
  102. package/lib/marketplace.js +298 -0
  103. package/lib/plugin-system.js +604 -0
  104. package/lib/security-scanner.js +309 -0
  105. package/lib/self-healing.js +434 -0
  106. package/lib/session-manager.js +261 -0
  107. package/lib/skill-sandbox.js +244 -0
  108. package/lib/task-governance.js +523 -0
  109. package/lib/task-model.js +317 -0
  110. package/lib/updater.js +201 -0
  111. package/lib/verify.js +240 -0
  112. package/lib/workflow-engine.js +353 -0
  113. package/lib/workflow-persistence.js +160 -0
  114. package/package.json +7 -3
@@ -0,0 +1,298 @@
1
+ /**
2
+ * Antigravity AI Kit — Skill Marketplace
3
+ *
4
+ * GitHub-based hybrid marketplace for discovering, installing,
5
+ * and managing community skills and plugins.
6
+ *
7
+ * @module lib/marketplace
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
+ const { execSync } = require('child_process');
17
+
18
+ const AGENT_DIR = '.agent';
19
+ const ENGINE_DIR = 'engine';
20
+ const INDEX_FILE = 'marketplace-index.json';
21
+
22
+ /** Registry index TTL in milliseconds (24 hours) */
23
+ const INDEX_TTL_MS = 24 * 60 * 60 * 1000;
24
+
25
+ /** Git clone timeout in milliseconds */
26
+ const GIT_CLONE_TIMEOUT_MS = 30000;
27
+
28
+ /**
29
+ * @typedef {object} MarketEntry
30
+ * @property {string} name - Plugin name
31
+ * @property {string} description - Plugin description
32
+ * @property {string} repository - GitHub repository URL
33
+ * @property {string} version - Latest version
34
+ * @property {string[]} tags - Discovery tags
35
+ * @property {string} author - Author name
36
+ */
37
+
38
+ /**
39
+ * Resolves the marketplace index path.
40
+ *
41
+ * @param {string} projectRoot - Root directory
42
+ * @returns {string}
43
+ */
44
+ function resolveIndexPath(projectRoot) {
45
+ return path.join(projectRoot, AGENT_DIR, ENGINE_DIR, INDEX_FILE);
46
+ }
47
+
48
+ /**
49
+ * Loads the marketplace index from disk.
50
+ *
51
+ * @param {string} projectRoot - Root directory
52
+ * @returns {{ entries: MarketEntry[], lastUpdated: string | null }}
53
+ */
54
+ function loadIndex(projectRoot) {
55
+ const filePath = resolveIndexPath(projectRoot);
56
+
57
+ if (!fs.existsSync(filePath)) {
58
+ return { entries: [], lastUpdated: null };
59
+ }
60
+
61
+ try {
62
+ return JSON.parse(fs.readFileSync(filePath, 'utf-8'));
63
+ } catch {
64
+ return { entries: [], lastUpdated: null };
65
+ }
66
+ }
67
+
68
+ /**
69
+ * Writes the marketplace index atomically.
70
+ *
71
+ * @param {string} projectRoot - Root directory
72
+ * @param {{ entries: MarketEntry[], lastUpdated: string | null }} data
73
+ * @returns {void}
74
+ */
75
+ function writeIndex(projectRoot, data) {
76
+ const filePath = resolveIndexPath(projectRoot);
77
+ const dir = path.dirname(filePath);
78
+
79
+ if (!fs.existsSync(dir)) {
80
+ fs.mkdirSync(dir, { recursive: true });
81
+ }
82
+
83
+ const tempPath = `${filePath}.tmp`;
84
+ fs.writeFileSync(tempPath, JSON.stringify(data, null, 2) + '\n', 'utf-8');
85
+ fs.renameSync(tempPath, filePath);
86
+ }
87
+
88
+ /**
89
+ * Checks if the index is stale (older than TTL).
90
+ *
91
+ * @param {string | null} lastUpdated - ISO timestamp of last update
92
+ * @returns {boolean}
93
+ */
94
+ function isIndexStale(lastUpdated) {
95
+ if (!lastUpdated) {
96
+ return true;
97
+ }
98
+
99
+ const age = Date.now() - new Date(lastUpdated).getTime();
100
+ return age > INDEX_TTL_MS;
101
+ }
102
+
103
+ /**
104
+ * Validates file paths in a plugin manifest for path traversal (D-6).
105
+ *
106
+ * @param {object} manifest - Plugin manifest (plugin.json)
107
+ * @returns {{ valid: boolean, violations: string[] }}
108
+ */
109
+ function validateManifestPaths(manifest) {
110
+ const violations = [];
111
+
112
+ /** @type {string[]} */
113
+ const pathFields = [];
114
+
115
+ // Collect all file path references from manifest
116
+ if (manifest.file) {
117
+ pathFields.push(manifest.file);
118
+ }
119
+ if (manifest.files && Array.isArray(manifest.files)) {
120
+ pathFields.push(...manifest.files);
121
+ }
122
+ if (manifest.entry) {
123
+ pathFields.push(manifest.entry);
124
+ }
125
+
126
+ for (const filePath of pathFields) {
127
+ if (typeof filePath !== 'string') {
128
+ violations.push(`Invalid path type: ${typeof filePath}`);
129
+ continue;
130
+ }
131
+
132
+ // Reject absolute paths
133
+ if (path.isAbsolute(filePath)) {
134
+ violations.push(`Absolute path not allowed: ${filePath}`);
135
+ continue;
136
+ }
137
+
138
+ // Reject path traversal
139
+ if (filePath.includes('..')) {
140
+ violations.push(`Path traversal not allowed: ${filePath}`);
141
+ continue;
142
+ }
143
+
144
+ // Reject paths that escape .agent/
145
+ const normalized = path.normalize(filePath);
146
+ if (normalized.startsWith('..') || path.isAbsolute(normalized)) {
147
+ violations.push(`Path escapes sandbox: ${filePath}`);
148
+ }
149
+ }
150
+
151
+ return {
152
+ valid: violations.length === 0,
153
+ violations,
154
+ };
155
+ }
156
+
157
+ /**
158
+ * Searches the marketplace index.
159
+ *
160
+ * @param {string} projectRoot - Root directory
161
+ * @param {string} query - Search query
162
+ * @returns {MarketEntry[]}
163
+ */
164
+ function searchMarket(projectRoot, query) {
165
+ const index = loadIndex(projectRoot);
166
+ const search = query.toLowerCase();
167
+
168
+ return index.entries.filter((entry) => {
169
+ const searchable = [
170
+ entry.name,
171
+ entry.description,
172
+ entry.author,
173
+ ...(entry.tags || []),
174
+ ].join(' ').toLowerCase();
175
+
176
+ return searchable.includes(search);
177
+ });
178
+ }
179
+
180
+ /**
181
+ * Gets detailed info for a specific marketplace entry.
182
+ *
183
+ * @param {string} projectRoot - Root directory
184
+ * @param {string} pluginName - Plugin name
185
+ * @returns {MarketEntry | null}
186
+ */
187
+ function getMarketInfo(projectRoot, pluginName) {
188
+ const index = loadIndex(projectRoot);
189
+ return index.entries.find((e) => e.name === pluginName) || null;
190
+ }
191
+
192
+ /**
193
+ * Installs a plugin from the marketplace via git clone.
194
+ * Validates paths before installation.
195
+ *
196
+ * @param {string} projectRoot - Root directory
197
+ * @param {string} pluginName - Plugin name from the index
198
+ * @returns {{ success: boolean, message: string }}
199
+ */
200
+ function installFromMarket(projectRoot, pluginName) {
201
+ const entry = getMarketInfo(projectRoot, pluginName);
202
+
203
+ if (!entry) {
204
+ return { success: false, message: `Plugin not found in marketplace: ${pluginName}` };
205
+ }
206
+
207
+ // Validate repository URL
208
+ if (!entry.repository || (!entry.repository.startsWith('https://') && !entry.repository.startsWith('git@'))) {
209
+ return { success: false, message: `Invalid repository URL: ${entry.repository}` };
210
+ }
211
+
212
+ // Create temp directory for clone
213
+ const tempDir = path.join(projectRoot, AGENT_DIR, ENGINE_DIR, `_temp_${Date.now()}`);
214
+
215
+ try {
216
+ fs.mkdirSync(tempDir, { recursive: true });
217
+
218
+ // Shallow clone with timeout (A-4)
219
+ try {
220
+ execSync(
221
+ `git clone --depth 1 --single-branch "${entry.repository}" "${tempDir}"`,
222
+ { timeout: GIT_CLONE_TIMEOUT_MS, stdio: 'pipe' }
223
+ );
224
+ } catch (gitError) {
225
+ return { success: false, message: `Git clone failed: ${gitError.message || 'timeout or network error'}` };
226
+ }
227
+
228
+ // Validate plugin.json exists
229
+ const pluginJsonPath = path.join(tempDir, 'plugin.json');
230
+ if (!fs.existsSync(pluginJsonPath)) {
231
+ return { success: false, message: 'Plugin missing plugin.json manifest' };
232
+ }
233
+
234
+ // Parse and validate manifest paths (D-6)
235
+ let manifest;
236
+ try {
237
+ manifest = JSON.parse(fs.readFileSync(pluginJsonPath, 'utf-8'));
238
+ } catch {
239
+ return { success: false, message: 'Invalid plugin.json format' };
240
+ }
241
+
242
+ const pathValidation = validateManifestPaths(manifest);
243
+ if (!pathValidation.valid) {
244
+ return {
245
+ success: false,
246
+ message: `Security violation — path traversal detected: ${pathValidation.violations.join('; ')}`,
247
+ };
248
+ }
249
+
250
+ // Delegate to plugin system for actual installation
251
+ try {
252
+ const pluginSystem = require('./plugin-system');
253
+ const result = pluginSystem.installPlugin(projectRoot, tempDir);
254
+ return { success: result.success, message: result.message || 'Plugin installed successfully' };
255
+ } catch (installError) {
256
+ return { success: false, message: `Plugin installation failed: ${installError.message}` };
257
+ }
258
+ } finally {
259
+ // Always cleanup temp directory
260
+ try {
261
+ fs.rmSync(tempDir, { recursive: true, force: true });
262
+ } catch {
263
+ // Cleanup failure is non-critical
264
+ }
265
+ }
266
+ }
267
+
268
+ /**
269
+ * Updates the registry index from the bundled source.
270
+ *
271
+ * @param {string} projectRoot - Root directory
272
+ * @param {object} [options] - Update options
273
+ * @param {boolean} [options.force] - Force update regardless of TTL
274
+ * @returns {{ updated: boolean, entryCount: number }}
275
+ */
276
+ function updateRegistryIndex(projectRoot, options = {}) {
277
+ const currentIndex = loadIndex(projectRoot);
278
+
279
+ if (!options.force && !isIndexStale(currentIndex.lastUpdated)) {
280
+ return { updated: false, entryCount: currentIndex.entries.length };
281
+ }
282
+
283
+ // For MVP, the index is bundled — just stamp the update time
284
+ currentIndex.lastUpdated = new Date().toISOString();
285
+ writeIndex(projectRoot, currentIndex);
286
+
287
+ return { updated: true, entryCount: currentIndex.entries.length };
288
+ }
289
+
290
+ module.exports = {
291
+ searchMarket,
292
+ getMarketInfo,
293
+ installFromMarket,
294
+ updateRegistryIndex,
295
+ // Exported for testing
296
+ validateManifestPaths,
297
+ isIndexStale,
298
+ };