@series-inc/rundot-game-sdk 5.1.3 → 5.2.0
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 +32 -32
- package/dist/{SandboxHost-5K4EMDXV.js → SandboxHost-OSPEPZ37.js} +4 -4
- package/dist/SandboxHost-OSPEPZ37.js.map +1 -0
- package/dist/{chunk-UWRHIZXS.js → chunk-4ROGEXJO.js} +4 -4
- package/dist/chunk-4ROGEXJO.js.map +1 -0
- package/dist/chunk-7J5IQAUF.js +12 -0
- package/dist/chunk-7J5IQAUF.js.map +1 -0
- package/dist/{chunk-3GKY3LY5.js → chunk-CJU2J3S6.js} +2 -2
- package/dist/chunk-CJU2J3S6.js.map +1 -0
- package/dist/{chunk-KDS2ISWM.js → chunk-SUVDXAJ6.js} +8 -6
- package/dist/chunk-SUVDXAJ6.js.map +1 -0
- package/dist/core-Z4AOFL5J.js +3 -0
- package/dist/{core-6DQFSOBL.js.map → core-Z4AOFL5J.js.map} +1 -1
- package/dist/index.js +4 -4
- package/dist/rundot-game-api/index.d.ts +9 -9
- package/dist/rundot-game-api/index.js +10 -4
- package/dist/rundot-game-api/index.js.map +1 -1
- package/dist/vite/index.css +1 -1
- package/dist/vite/index.css.map +1 -1
- package/dist/vite/index.js +2 -2
- package/dist/vite/index.js.map +1 -1
- package/dist/webview/index.js +1 -1
- package/package.json +79 -79
- package/scripts/postinstall.mjs +377 -377
- package/dist/SandboxHost-5K4EMDXV.js.map +0 -1
- package/dist/chunk-3GKY3LY5.js.map +0 -1
- package/dist/chunk-74OSND3B.js +0 -12
- package/dist/chunk-74OSND3B.js.map +0 -1
- package/dist/chunk-KDS2ISWM.js.map +0 -1
- package/dist/chunk-UWRHIZXS.js.map +0 -1
- package/dist/core-6DQFSOBL.js +0 -3
package/scripts/postinstall.mjs
CHANGED
|
@@ -1,377 +1,377 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
import { existsSync, rmSync, readFileSync, writeFileSync, createWriteStream, renameSync, readdirSync, statSync } from 'fs';
|
|
4
|
-
import { resolve as resolvePath, dirname, join } from 'path';
|
|
5
|
-
import { fileURLToPath } from 'url';
|
|
6
|
-
import https from 'https';
|
|
7
|
-
import AdmZip from 'adm-zip';
|
|
8
|
-
|
|
9
|
-
const DOCS_ZIP_URL = 'https://github.com/series-ai/venus-sdk-docs/archive/refs/heads/main.zip';
|
|
10
|
-
const DOCS_FOLDER = '.rundot-docs';
|
|
11
|
-
const VERSION_FILE = '.sdk-version';
|
|
12
|
-
const TEMP_ZIP_FILE = '.docs-temp.zip';
|
|
13
|
-
|
|
14
|
-
/**
|
|
15
|
-
* Get the current package version
|
|
16
|
-
*/
|
|
17
|
-
function getCurrentVersion() {
|
|
18
|
-
try {
|
|
19
|
-
const __filename = fileURLToPath(import.meta.url);
|
|
20
|
-
const __dirname = dirname(__filename);
|
|
21
|
-
const packageJsonPath = resolvePath(__dirname, '..', 'package.json');
|
|
22
|
-
const packageJson = JSON.parse(readFileSync(packageJsonPath, 'utf-8'));
|
|
23
|
-
return packageJson.version;
|
|
24
|
-
} catch (error) {
|
|
25
|
-
console.warn(' Could not read package version:', error.message);
|
|
26
|
-
return null;
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
/**
|
|
31
|
-
* Get the previously installed version
|
|
32
|
-
*/
|
|
33
|
-
function getInstalledVersion(projectRoot) {
|
|
34
|
-
try {
|
|
35
|
-
const targetPath = resolvePath(projectRoot, DOCS_FOLDER);
|
|
36
|
-
const versionFilePath = resolvePath(targetPath, VERSION_FILE);
|
|
37
|
-
|
|
38
|
-
if (!existsSync(versionFilePath)) {
|
|
39
|
-
return null;
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
return readFileSync(versionFilePath, 'utf-8').trim();
|
|
43
|
-
} catch (error) {
|
|
44
|
-
return null;
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
/**
|
|
49
|
-
* Save the current version to the version file
|
|
50
|
-
*/
|
|
51
|
-
function saveInstalledVersion(version, projectRoot) {
|
|
52
|
-
try {
|
|
53
|
-
const targetPath = resolvePath(projectRoot, DOCS_FOLDER);
|
|
54
|
-
const versionFilePath = resolvePath(targetPath, VERSION_FILE);
|
|
55
|
-
writeFileSync(versionFilePath, version, 'utf-8');
|
|
56
|
-
} catch (error) {
|
|
57
|
-
console.warn(' Could not save version file:', error.message);
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
/**
|
|
62
|
-
* Check if docs need to be downloaded
|
|
63
|
-
*/
|
|
64
|
-
function shouldDownloadDocs(currentVersion, installedVersion, projectRoot) {
|
|
65
|
-
// First install - no version file exists
|
|
66
|
-
if (!installedVersion) {
|
|
67
|
-
return true;
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
// Version has changed
|
|
71
|
-
if (currentVersion && installedVersion !== currentVersion) {
|
|
72
|
-
return true;
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
// Docs folder doesn't exist (somehow deleted)
|
|
76
|
-
const targetPath = resolvePath(projectRoot, DOCS_FOLDER);
|
|
77
|
-
if (!existsSync(targetPath)) {
|
|
78
|
-
return true;
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
return false;
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
/**
|
|
85
|
-
* Download a file from a URL
|
|
86
|
-
*/
|
|
87
|
-
async function downloadFile(url, dest) {
|
|
88
|
-
return new Promise((resolve, reject) => {
|
|
89
|
-
const file = createWriteStream(dest);
|
|
90
|
-
|
|
91
|
-
https.get(url, (response) => {
|
|
92
|
-
// Follow redirects
|
|
93
|
-
if (response.statusCode === 302 || response.statusCode === 301) {
|
|
94
|
-
file.close();
|
|
95
|
-
rmSync(dest, { force: true });
|
|
96
|
-
return downloadFile(response.headers.location, dest).then(resolve).catch(reject);
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
if (response.statusCode !== 200) {
|
|
100
|
-
file.close();
|
|
101
|
-
rmSync(dest, { force: true });
|
|
102
|
-
return reject(new Error(`Failed to download: HTTP ${response.statusCode}`));
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
response.pipe(file);
|
|
106
|
-
|
|
107
|
-
file.on('finish', () => {
|
|
108
|
-
file.close();
|
|
109
|
-
resolve();
|
|
110
|
-
});
|
|
111
|
-
|
|
112
|
-
file.on('error', (err) => {
|
|
113
|
-
file.close();
|
|
114
|
-
rmSync(dest, { force: true });
|
|
115
|
-
reject(err);
|
|
116
|
-
});
|
|
117
|
-
}).on('error', (err) => {
|
|
118
|
-
file.close();
|
|
119
|
-
rmSync(dest, { force: true });
|
|
120
|
-
reject(err);
|
|
121
|
-
});
|
|
122
|
-
});
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
/**
|
|
126
|
-
* Extract zip file and handle GitHub's nested folder structure
|
|
127
|
-
*/
|
|
128
|
-
function extractZip(zipPath, targetPath) {
|
|
129
|
-
const zip = new AdmZip(zipPath);
|
|
130
|
-
const tempExtractPath = resolvePath(process.cwd(), '.docs-temp-extract');
|
|
131
|
-
|
|
132
|
-
// Clean up temp folder if it exists from a previous failed run
|
|
133
|
-
if (existsSync(tempExtractPath)) {
|
|
134
|
-
rmSync(tempExtractPath, { recursive: true, force: true });
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
// Extract to temporary location
|
|
138
|
-
zip.extractAllTo(tempExtractPath, true);
|
|
139
|
-
|
|
140
|
-
// GitHub creates a folder like "venus-sdk-docs-main" inside the zip
|
|
141
|
-
// We need to find it and move its contents to the target path
|
|
142
|
-
const extractedContents = readdirSync(tempExtractPath);
|
|
143
|
-
|
|
144
|
-
if (extractedContents.length === 1) {
|
|
145
|
-
// Move the nested folder contents to target
|
|
146
|
-
const nestedFolder = resolvePath(tempExtractPath, extractedContents[0]);
|
|
147
|
-
renameSync(nestedFolder, targetPath);
|
|
148
|
-
} else {
|
|
149
|
-
// Unexpected structure, just move everything
|
|
150
|
-
renameSync(tempExtractPath, targetPath);
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
// Clean up temp folder if it still exists
|
|
154
|
-
if (existsSync(tempExtractPath)) {
|
|
155
|
-
rmSync(tempExtractPath, { recursive: true, force: true });
|
|
156
|
-
}
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
/**
|
|
160
|
-
* Find all AGENTS.md and CLAUDE.md files (case insensitive) in a directory
|
|
161
|
-
*/
|
|
162
|
-
function findAgentFiles(dir, results = []) {
|
|
163
|
-
if (!existsSync(dir)) {
|
|
164
|
-
return results;
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
const entries = readdirSync(dir, { withFileTypes: true });
|
|
168
|
-
|
|
169
|
-
for (const entry of entries) {
|
|
170
|
-
const fullPath = join(dir, entry.name);
|
|
171
|
-
|
|
172
|
-
// Skip .git directories
|
|
173
|
-
if (entry.name === '.git') {
|
|
174
|
-
continue;
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
if (entry.isDirectory()) {
|
|
178
|
-
findAgentFiles(fullPath, results);
|
|
179
|
-
} else if (entry.isFile()) {
|
|
180
|
-
const nameLower = entry.name.toLowerCase();
|
|
181
|
-
if (nameLower === 'agents.md' || nameLower === 'claude.md') {
|
|
182
|
-
results.push(fullPath);
|
|
183
|
-
}
|
|
184
|
-
}
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
return results;
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
/**
|
|
191
|
-
* Inject agents-index.txt content into a file between <agents-index> tags
|
|
192
|
-
*/
|
|
193
|
-
function injectAgentsIndex(filePath, agentsIndexContent) {
|
|
194
|
-
const content = readFileSync(filePath, 'utf-8');
|
|
195
|
-
const openTag = '<agents-index>';
|
|
196
|
-
const closeTag = '</agents-index>';
|
|
197
|
-
|
|
198
|
-
const openIndex = content.indexOf(openTag);
|
|
199
|
-
const closeIndex = content.indexOf(closeTag);
|
|
200
|
-
|
|
201
|
-
let newContent;
|
|
202
|
-
|
|
203
|
-
if (openIndex !== -1 && closeIndex !== -1 && closeIndex > openIndex) {
|
|
204
|
-
// Tags exist, replace content between them
|
|
205
|
-
const before = content.substring(0, openIndex + openTag.length);
|
|
206
|
-
const after = content.substring(closeIndex);
|
|
207
|
-
newContent = `${before}\n${agentsIndexContent}${after}`;
|
|
208
|
-
} else {
|
|
209
|
-
// Tags don't exist, prepend them with the content
|
|
210
|
-
newContent = `${openTag}\n${agentsIndexContent}${closeTag}\n\n${content}`;
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
writeFileSync(filePath, newContent, 'utf-8');
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
/**
|
|
217
|
-
* Process all AGENTS.md and CLAUDE.md files in the project directory
|
|
218
|
-
*/
|
|
219
|
-
function processAgentFiles(docsPath, projectRoot) {
|
|
220
|
-
const agentsIndexPath = join(docsPath, 'agents-index.txt');
|
|
221
|
-
|
|
222
|
-
// Check if agents-index.txt exists
|
|
223
|
-
if (!existsSync(agentsIndexPath)) {
|
|
224
|
-
console.log(' No agents-index.txt found, skipping agent files injection');
|
|
225
|
-
return;
|
|
226
|
-
}
|
|
227
|
-
|
|
228
|
-
// Read the agents-index.txt content
|
|
229
|
-
const agentsIndexContent = readFileSync(agentsIndexPath, 'utf-8').trim();
|
|
230
|
-
|
|
231
|
-
// Find all AGENTS.md and CLAUDE.md files in the project root
|
|
232
|
-
const agentFiles = findAgentFiles(projectRoot);
|
|
233
|
-
|
|
234
|
-
if (agentFiles.length === 0) {
|
|
235
|
-
console.log(' No AGENTS.md or CLAUDE.md files found in project, creating them...');
|
|
236
|
-
|
|
237
|
-
const files = ['AGENTS.md', 'CLAUDE.md', 'GEMINI.md'];
|
|
238
|
-
|
|
239
|
-
try {
|
|
240
|
-
for (const file of files) {
|
|
241
|
-
writeFileSync(join(projectRoot, file), '', 'utf-8');
|
|
242
|
-
console.log(` Created ${file}`);
|
|
243
|
-
agentFiles.push(join(projectRoot, file));
|
|
244
|
-
}
|
|
245
|
-
} catch (error) {
|
|
246
|
-
console.warn(' Failed to create agent files:', error.message);
|
|
247
|
-
return;
|
|
248
|
-
}
|
|
249
|
-
}
|
|
250
|
-
|
|
251
|
-
console.log(` Found ${agentFiles.length} agent file(s), injecting agents-index...`);
|
|
252
|
-
|
|
253
|
-
for (const filePath of agentFiles) {
|
|
254
|
-
try {
|
|
255
|
-
injectAgentsIndex(filePath, agentsIndexContent);
|
|
256
|
-
const relativePath = filePath.replace(projectRoot + '/', '');
|
|
257
|
-
console.log(` Injected into ${relativePath}`);
|
|
258
|
-
} catch (error) {
|
|
259
|
-
console.warn(` Failed to inject into ${filePath}:`, error.message);
|
|
260
|
-
}
|
|
261
|
-
}
|
|
262
|
-
}
|
|
263
|
-
|
|
264
|
-
/**
|
|
265
|
-
* Add .rundot-docs to .gitignore if it exists and isn't already there
|
|
266
|
-
*/
|
|
267
|
-
function updateGitignore(projectRoot) {
|
|
268
|
-
const gitignorePath = join(projectRoot, '.gitignore');
|
|
269
|
-
|
|
270
|
-
if (!existsSync(gitignorePath)) {
|
|
271
|
-
return;
|
|
272
|
-
}
|
|
273
|
-
|
|
274
|
-
try {
|
|
275
|
-
const content = readFileSync(gitignorePath, 'utf-8');
|
|
276
|
-
|
|
277
|
-
// Check if .rundot-docs is already in .gitignore
|
|
278
|
-
if (content.includes('.rundot-docs')) {
|
|
279
|
-
return;
|
|
280
|
-
}
|
|
281
|
-
|
|
282
|
-
// Add .rundot-docs to .gitignore
|
|
283
|
-
const newContent = content.endsWith('\n')
|
|
284
|
-
? `${content}.rundot-docs\n`
|
|
285
|
-
: `${content}\n.rundot-docs\n`;
|
|
286
|
-
|
|
287
|
-
writeFileSync(gitignorePath, newContent, 'utf-8');
|
|
288
|
-
console.log(' Added .rundot-docs to .gitignore');
|
|
289
|
-
} catch (error) {
|
|
290
|
-
console.warn(' Failed to update .gitignore:', error.message);
|
|
291
|
-
}
|
|
292
|
-
}
|
|
293
|
-
|
|
294
|
-
/**
|
|
295
|
-
* Find the project root directory (where package.json with this package as a dependency exists)
|
|
296
|
-
*/
|
|
297
|
-
function findProjectRoot() {
|
|
298
|
-
let currentDir = process.cwd();
|
|
299
|
-
|
|
300
|
-
// If we're already in node_modules, go up to find the project root
|
|
301
|
-
if (currentDir.includes('node_modules')) {
|
|
302
|
-
const parts = currentDir.split('node_modules');
|
|
303
|
-
return parts[0];
|
|
304
|
-
}
|
|
305
|
-
|
|
306
|
-
return currentDir;
|
|
307
|
-
}
|
|
308
|
-
|
|
309
|
-
/**
|
|
310
|
-
* Post-install script to download venus-sdk-docs repository
|
|
311
|
-
* into a .docs folder in the current working directory
|
|
312
|
-
*/
|
|
313
|
-
async function postInstall() {
|
|
314
|
-
const projectRoot = findProjectRoot();
|
|
315
|
-
const zipPath = resolvePath(projectRoot, TEMP_ZIP_FILE);
|
|
316
|
-
|
|
317
|
-
try {
|
|
318
|
-
const currentVersion = getCurrentVersion();
|
|
319
|
-
const installedVersion = getInstalledVersion(projectRoot);
|
|
320
|
-
|
|
321
|
-
if (!shouldDownloadDocs(currentVersion, installedVersion, projectRoot)) {
|
|
322
|
-
console.log('venus-sdk-docs is already up to date (version:', installedVersion || 'unknown', ')');
|
|
323
|
-
return;
|
|
324
|
-
}
|
|
325
|
-
|
|
326
|
-
// Use project root to store the docs
|
|
327
|
-
const targetPath = resolvePath(projectRoot, DOCS_FOLDER);
|
|
328
|
-
|
|
329
|
-
console.log('Downloading venus-sdk-docs...');
|
|
330
|
-
|
|
331
|
-
// Check if the .docs folder already exists
|
|
332
|
-
if (existsSync(targetPath)) {
|
|
333
|
-
console.log(' Removing old version...');
|
|
334
|
-
rmSync(targetPath, { recursive: true, force: true });
|
|
335
|
-
}
|
|
336
|
-
|
|
337
|
-
// Download the zip file
|
|
338
|
-
await downloadFile(DOCS_ZIP_URL, zipPath);
|
|
339
|
-
console.log(' Download complete, extracting...');
|
|
340
|
-
|
|
341
|
-
// Extract the zip file
|
|
342
|
-
extractZip(zipPath, targetPath);
|
|
343
|
-
|
|
344
|
-
// Clean up zip file
|
|
345
|
-
if (existsSync(zipPath)) {
|
|
346
|
-
rmSync(zipPath, { force: true });
|
|
347
|
-
}
|
|
348
|
-
|
|
349
|
-
// Save the current version
|
|
350
|
-
if (currentVersion) {
|
|
351
|
-
saveInstalledVersion(currentVersion, projectRoot);
|
|
352
|
-
}
|
|
353
|
-
|
|
354
|
-
// Process AGENTS.md and CLAUDE.md files in the project root
|
|
355
|
-
processAgentFiles(targetPath, projectRoot);
|
|
356
|
-
|
|
357
|
-
// Add .rundot-docs to .gitignore if it exists
|
|
358
|
-
updateGitignore(projectRoot);
|
|
359
|
-
|
|
360
|
-
console.log('venus-sdk-docs downloaded successfully!');
|
|
361
|
-
console.log(` Documentation available at: ${targetPath}`);
|
|
362
|
-
} catch (error) {
|
|
363
|
-
console.warn('Warning: Failed to download venus-sdk-docs');
|
|
364
|
-
console.warn(' Error:', error.message);
|
|
365
|
-
console.warn(' You can manually download the docs from:', DOCS_ZIP_URL);
|
|
366
|
-
|
|
367
|
-
// Clean up any partial downloads
|
|
368
|
-
if (existsSync(zipPath)) {
|
|
369
|
-
rmSync(zipPath, { force: true });
|
|
370
|
-
}
|
|
371
|
-
|
|
372
|
-
// Don't fail the installation if docs download fails
|
|
373
|
-
process.exit(0);
|
|
374
|
-
}
|
|
375
|
-
}
|
|
376
|
-
|
|
377
|
-
postInstall();
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import { existsSync, rmSync, readFileSync, writeFileSync, createWriteStream, renameSync, readdirSync, statSync } from 'fs';
|
|
4
|
+
import { resolve as resolvePath, dirname, join } from 'path';
|
|
5
|
+
import { fileURLToPath } from 'url';
|
|
6
|
+
import https from 'https';
|
|
7
|
+
import AdmZip from 'adm-zip';
|
|
8
|
+
|
|
9
|
+
const DOCS_ZIP_URL = 'https://github.com/series-ai/venus-sdk-docs/archive/refs/heads/main.zip';
|
|
10
|
+
const DOCS_FOLDER = '.rundot-docs';
|
|
11
|
+
const VERSION_FILE = '.sdk-version';
|
|
12
|
+
const TEMP_ZIP_FILE = '.docs-temp.zip';
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Get the current package version
|
|
16
|
+
*/
|
|
17
|
+
function getCurrentVersion() {
|
|
18
|
+
try {
|
|
19
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
20
|
+
const __dirname = dirname(__filename);
|
|
21
|
+
const packageJsonPath = resolvePath(__dirname, '..', 'package.json');
|
|
22
|
+
const packageJson = JSON.parse(readFileSync(packageJsonPath, 'utf-8'));
|
|
23
|
+
return packageJson.version;
|
|
24
|
+
} catch (error) {
|
|
25
|
+
console.warn(' Could not read package version:', error.message);
|
|
26
|
+
return null;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Get the previously installed version
|
|
32
|
+
*/
|
|
33
|
+
function getInstalledVersion(projectRoot) {
|
|
34
|
+
try {
|
|
35
|
+
const targetPath = resolvePath(projectRoot, DOCS_FOLDER);
|
|
36
|
+
const versionFilePath = resolvePath(targetPath, VERSION_FILE);
|
|
37
|
+
|
|
38
|
+
if (!existsSync(versionFilePath)) {
|
|
39
|
+
return null;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
return readFileSync(versionFilePath, 'utf-8').trim();
|
|
43
|
+
} catch (error) {
|
|
44
|
+
return null;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Save the current version to the version file
|
|
50
|
+
*/
|
|
51
|
+
function saveInstalledVersion(version, projectRoot) {
|
|
52
|
+
try {
|
|
53
|
+
const targetPath = resolvePath(projectRoot, DOCS_FOLDER);
|
|
54
|
+
const versionFilePath = resolvePath(targetPath, VERSION_FILE);
|
|
55
|
+
writeFileSync(versionFilePath, version, 'utf-8');
|
|
56
|
+
} catch (error) {
|
|
57
|
+
console.warn(' Could not save version file:', error.message);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Check if docs need to be downloaded
|
|
63
|
+
*/
|
|
64
|
+
function shouldDownloadDocs(currentVersion, installedVersion, projectRoot) {
|
|
65
|
+
// First install - no version file exists
|
|
66
|
+
if (!installedVersion) {
|
|
67
|
+
return true;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// Version has changed
|
|
71
|
+
if (currentVersion && installedVersion !== currentVersion) {
|
|
72
|
+
return true;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// Docs folder doesn't exist (somehow deleted)
|
|
76
|
+
const targetPath = resolvePath(projectRoot, DOCS_FOLDER);
|
|
77
|
+
if (!existsSync(targetPath)) {
|
|
78
|
+
return true;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
return false;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Download a file from a URL
|
|
86
|
+
*/
|
|
87
|
+
async function downloadFile(url, dest) {
|
|
88
|
+
return new Promise((resolve, reject) => {
|
|
89
|
+
const file = createWriteStream(dest);
|
|
90
|
+
|
|
91
|
+
https.get(url, (response) => {
|
|
92
|
+
// Follow redirects
|
|
93
|
+
if (response.statusCode === 302 || response.statusCode === 301) {
|
|
94
|
+
file.close();
|
|
95
|
+
rmSync(dest, { force: true });
|
|
96
|
+
return downloadFile(response.headers.location, dest).then(resolve).catch(reject);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
if (response.statusCode !== 200) {
|
|
100
|
+
file.close();
|
|
101
|
+
rmSync(dest, { force: true });
|
|
102
|
+
return reject(new Error(`Failed to download: HTTP ${response.statusCode}`));
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
response.pipe(file);
|
|
106
|
+
|
|
107
|
+
file.on('finish', () => {
|
|
108
|
+
file.close();
|
|
109
|
+
resolve();
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
file.on('error', (err) => {
|
|
113
|
+
file.close();
|
|
114
|
+
rmSync(dest, { force: true });
|
|
115
|
+
reject(err);
|
|
116
|
+
});
|
|
117
|
+
}).on('error', (err) => {
|
|
118
|
+
file.close();
|
|
119
|
+
rmSync(dest, { force: true });
|
|
120
|
+
reject(err);
|
|
121
|
+
});
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* Extract zip file and handle GitHub's nested folder structure
|
|
127
|
+
*/
|
|
128
|
+
function extractZip(zipPath, targetPath) {
|
|
129
|
+
const zip = new AdmZip(zipPath);
|
|
130
|
+
const tempExtractPath = resolvePath(process.cwd(), '.docs-temp-extract');
|
|
131
|
+
|
|
132
|
+
// Clean up temp folder if it exists from a previous failed run
|
|
133
|
+
if (existsSync(tempExtractPath)) {
|
|
134
|
+
rmSync(tempExtractPath, { recursive: true, force: true });
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
// Extract to temporary location
|
|
138
|
+
zip.extractAllTo(tempExtractPath, true);
|
|
139
|
+
|
|
140
|
+
// GitHub creates a folder like "venus-sdk-docs-main" inside the zip
|
|
141
|
+
// We need to find it and move its contents to the target path
|
|
142
|
+
const extractedContents = readdirSync(tempExtractPath);
|
|
143
|
+
|
|
144
|
+
if (extractedContents.length === 1) {
|
|
145
|
+
// Move the nested folder contents to target
|
|
146
|
+
const nestedFolder = resolvePath(tempExtractPath, extractedContents[0]);
|
|
147
|
+
renameSync(nestedFolder, targetPath);
|
|
148
|
+
} else {
|
|
149
|
+
// Unexpected structure, just move everything
|
|
150
|
+
renameSync(tempExtractPath, targetPath);
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
// Clean up temp folder if it still exists
|
|
154
|
+
if (existsSync(tempExtractPath)) {
|
|
155
|
+
rmSync(tempExtractPath, { recursive: true, force: true });
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* Find all AGENTS.md and CLAUDE.md files (case insensitive) in a directory
|
|
161
|
+
*/
|
|
162
|
+
function findAgentFiles(dir, results = []) {
|
|
163
|
+
if (!existsSync(dir)) {
|
|
164
|
+
return results;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
const entries = readdirSync(dir, { withFileTypes: true });
|
|
168
|
+
|
|
169
|
+
for (const entry of entries) {
|
|
170
|
+
const fullPath = join(dir, entry.name);
|
|
171
|
+
|
|
172
|
+
// Skip .git directories
|
|
173
|
+
if (entry.name === '.git') {
|
|
174
|
+
continue;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
if (entry.isDirectory()) {
|
|
178
|
+
findAgentFiles(fullPath, results);
|
|
179
|
+
} else if (entry.isFile()) {
|
|
180
|
+
const nameLower = entry.name.toLowerCase();
|
|
181
|
+
if (nameLower === 'agents.md' || nameLower === 'claude.md') {
|
|
182
|
+
results.push(fullPath);
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
return results;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
/**
|
|
191
|
+
* Inject agents-index.txt content into a file between <agents-index> tags
|
|
192
|
+
*/
|
|
193
|
+
function injectAgentsIndex(filePath, agentsIndexContent) {
|
|
194
|
+
const content = readFileSync(filePath, 'utf-8');
|
|
195
|
+
const openTag = '<agents-index>';
|
|
196
|
+
const closeTag = '</agents-index>';
|
|
197
|
+
|
|
198
|
+
const openIndex = content.indexOf(openTag);
|
|
199
|
+
const closeIndex = content.indexOf(closeTag);
|
|
200
|
+
|
|
201
|
+
let newContent;
|
|
202
|
+
|
|
203
|
+
if (openIndex !== -1 && closeIndex !== -1 && closeIndex > openIndex) {
|
|
204
|
+
// Tags exist, replace content between them
|
|
205
|
+
const before = content.substring(0, openIndex + openTag.length);
|
|
206
|
+
const after = content.substring(closeIndex);
|
|
207
|
+
newContent = `${before}\n${agentsIndexContent}${after}`;
|
|
208
|
+
} else {
|
|
209
|
+
// Tags don't exist, prepend them with the content
|
|
210
|
+
newContent = `${openTag}\n${agentsIndexContent}${closeTag}\n\n${content}`;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
writeFileSync(filePath, newContent, 'utf-8');
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
/**
|
|
217
|
+
* Process all AGENTS.md and CLAUDE.md files in the project directory
|
|
218
|
+
*/
|
|
219
|
+
function processAgentFiles(docsPath, projectRoot) {
|
|
220
|
+
const agentsIndexPath = join(docsPath, 'agents-index.txt');
|
|
221
|
+
|
|
222
|
+
// Check if agents-index.txt exists
|
|
223
|
+
if (!existsSync(agentsIndexPath)) {
|
|
224
|
+
console.log(' No agents-index.txt found, skipping agent files injection');
|
|
225
|
+
return;
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
// Read the agents-index.txt content
|
|
229
|
+
const agentsIndexContent = readFileSync(agentsIndexPath, 'utf-8').trim();
|
|
230
|
+
|
|
231
|
+
// Find all AGENTS.md and CLAUDE.md files in the project root
|
|
232
|
+
const agentFiles = findAgentFiles(projectRoot);
|
|
233
|
+
|
|
234
|
+
if (agentFiles.length === 0) {
|
|
235
|
+
console.log(' No AGENTS.md or CLAUDE.md files found in project, creating them...');
|
|
236
|
+
|
|
237
|
+
const files = ['AGENTS.md', 'CLAUDE.md', 'GEMINI.md'];
|
|
238
|
+
|
|
239
|
+
try {
|
|
240
|
+
for (const file of files) {
|
|
241
|
+
writeFileSync(join(projectRoot, file), '', 'utf-8');
|
|
242
|
+
console.log(` Created ${file}`);
|
|
243
|
+
agentFiles.push(join(projectRoot, file));
|
|
244
|
+
}
|
|
245
|
+
} catch (error) {
|
|
246
|
+
console.warn(' Failed to create agent files:', error.message);
|
|
247
|
+
return;
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
console.log(` Found ${agentFiles.length} agent file(s), injecting agents-index...`);
|
|
252
|
+
|
|
253
|
+
for (const filePath of agentFiles) {
|
|
254
|
+
try {
|
|
255
|
+
injectAgentsIndex(filePath, agentsIndexContent);
|
|
256
|
+
const relativePath = filePath.replace(projectRoot + '/', '');
|
|
257
|
+
console.log(` Injected into ${relativePath}`);
|
|
258
|
+
} catch (error) {
|
|
259
|
+
console.warn(` Failed to inject into ${filePath}:`, error.message);
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
/**
|
|
265
|
+
* Add .rundot-docs to .gitignore if it exists and isn't already there
|
|
266
|
+
*/
|
|
267
|
+
function updateGitignore(projectRoot) {
|
|
268
|
+
const gitignorePath = join(projectRoot, '.gitignore');
|
|
269
|
+
|
|
270
|
+
if (!existsSync(gitignorePath)) {
|
|
271
|
+
return;
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
try {
|
|
275
|
+
const content = readFileSync(gitignorePath, 'utf-8');
|
|
276
|
+
|
|
277
|
+
// Check if .rundot-docs is already in .gitignore
|
|
278
|
+
if (content.includes('.rundot-docs')) {
|
|
279
|
+
return;
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
// Add .rundot-docs to .gitignore
|
|
283
|
+
const newContent = content.endsWith('\n')
|
|
284
|
+
? `${content}.rundot-docs\n`
|
|
285
|
+
: `${content}\n.rundot-docs\n`;
|
|
286
|
+
|
|
287
|
+
writeFileSync(gitignorePath, newContent, 'utf-8');
|
|
288
|
+
console.log(' Added .rundot-docs to .gitignore');
|
|
289
|
+
} catch (error) {
|
|
290
|
+
console.warn(' Failed to update .gitignore:', error.message);
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
/**
|
|
295
|
+
* Find the project root directory (where package.json with this package as a dependency exists)
|
|
296
|
+
*/
|
|
297
|
+
function findProjectRoot() {
|
|
298
|
+
let currentDir = process.cwd();
|
|
299
|
+
|
|
300
|
+
// If we're already in node_modules, go up to find the project root
|
|
301
|
+
if (currentDir.includes('node_modules')) {
|
|
302
|
+
const parts = currentDir.split('node_modules');
|
|
303
|
+
return parts[0];
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
return currentDir;
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
/**
|
|
310
|
+
* Post-install script to download venus-sdk-docs repository
|
|
311
|
+
* into a .docs folder in the current working directory
|
|
312
|
+
*/
|
|
313
|
+
async function postInstall() {
|
|
314
|
+
const projectRoot = findProjectRoot();
|
|
315
|
+
const zipPath = resolvePath(projectRoot, TEMP_ZIP_FILE);
|
|
316
|
+
|
|
317
|
+
try {
|
|
318
|
+
const currentVersion = getCurrentVersion();
|
|
319
|
+
const installedVersion = getInstalledVersion(projectRoot);
|
|
320
|
+
|
|
321
|
+
if (!shouldDownloadDocs(currentVersion, installedVersion, projectRoot)) {
|
|
322
|
+
console.log('venus-sdk-docs is already up to date (version:', installedVersion || 'unknown', ')');
|
|
323
|
+
return;
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
// Use project root to store the docs
|
|
327
|
+
const targetPath = resolvePath(projectRoot, DOCS_FOLDER);
|
|
328
|
+
|
|
329
|
+
console.log('Downloading venus-sdk-docs...');
|
|
330
|
+
|
|
331
|
+
// Check if the .docs folder already exists
|
|
332
|
+
if (existsSync(targetPath)) {
|
|
333
|
+
console.log(' Removing old version...');
|
|
334
|
+
rmSync(targetPath, { recursive: true, force: true });
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
// Download the zip file
|
|
338
|
+
await downloadFile(DOCS_ZIP_URL, zipPath);
|
|
339
|
+
console.log(' Download complete, extracting...');
|
|
340
|
+
|
|
341
|
+
// Extract the zip file
|
|
342
|
+
extractZip(zipPath, targetPath);
|
|
343
|
+
|
|
344
|
+
// Clean up zip file
|
|
345
|
+
if (existsSync(zipPath)) {
|
|
346
|
+
rmSync(zipPath, { force: true });
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
// Save the current version
|
|
350
|
+
if (currentVersion) {
|
|
351
|
+
saveInstalledVersion(currentVersion, projectRoot);
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
// Process AGENTS.md and CLAUDE.md files in the project root
|
|
355
|
+
processAgentFiles(targetPath, projectRoot);
|
|
356
|
+
|
|
357
|
+
// Add .rundot-docs to .gitignore if it exists
|
|
358
|
+
updateGitignore(projectRoot);
|
|
359
|
+
|
|
360
|
+
console.log('venus-sdk-docs downloaded successfully!');
|
|
361
|
+
console.log(` Documentation available at: ${targetPath}`);
|
|
362
|
+
} catch (error) {
|
|
363
|
+
console.warn('Warning: Failed to download venus-sdk-docs');
|
|
364
|
+
console.warn(' Error:', error.message);
|
|
365
|
+
console.warn(' You can manually download the docs from:', DOCS_ZIP_URL);
|
|
366
|
+
|
|
367
|
+
// Clean up any partial downloads
|
|
368
|
+
if (existsSync(zipPath)) {
|
|
369
|
+
rmSync(zipPath, { force: true });
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
// Don't fail the installation if docs download fails
|
|
373
|
+
process.exit(0);
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
postInstall();
|