0xray 4.0.1 โ†’ 4.0.3

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 (59) hide show
  1. package/.xray/features.json +1 -1
  2. package/AGENTS-consumer.md +4 -4
  3. package/AGENTS.md +3 -3
  4. package/README.md +1 -1
  5. package/SKILLS.md +1 -1
  6. package/dist/AGENTS.md +3 -3
  7. package/dist/CHANGELOG.md +43 -0
  8. package/dist/README.md +1 -1
  9. package/dist/SKILLS.md +1 -1
  10. package/dist/cli/commands/foundry-mint-wear.d.ts +3 -0
  11. package/dist/cli/commands/foundry-mint-wear.js +17 -0
  12. package/dist/cli/commands/hermes-install.js +2 -0
  13. package/dist/cli/commands/openclaw-install.js +2 -0
  14. package/dist/cli/commands/opencode-install.js +10 -2
  15. package/dist/cli/commands/skill-install.js +4 -0
  16. package/dist/enforcement/enforcer-tools.d.ts +7 -0
  17. package/dist/enforcement/enforcer-tools.js +18 -109
  18. package/dist/integrations/grok/grok-cli.js +2 -0
  19. package/dist/integrations/openclaw/plugin/xray-pre-tool/package.json +1 -1
  20. package/dist/processors/implementations/version-compliance-processor.d.ts +3 -34
  21. package/dist/processors/implementations/version-compliance-processor.js +8 -135
  22. package/package.json +15 -14
  23. package/scripts/foundry/CHANGELOG.md +38 -0
  24. package/scripts/foundry/LICENSE +21 -0
  25. package/scripts/foundry/README.md +69 -0
  26. package/scripts/foundry/ci-monitor.mjs +115 -0
  27. package/scripts/foundry/cli.js +2 -0
  28. package/scripts/foundry/cli.mjs +55 -0
  29. package/scripts/foundry/docs-build.mjs +38 -0
  30. package/scripts/foundry/hooks.mjs +36 -0
  31. package/scripts/foundry/mill-root.mjs +62 -0
  32. package/scripts/foundry/mint-suit.cjs +397 -0
  33. package/scripts/foundry/mint.mjs +33 -0
  34. package/scripts/foundry/package.json +54 -0
  35. package/scripts/foundry/plant/agents/mill.yml +5 -0
  36. package/scripts/foundry/plant/skills/mill/SKILL.md +22 -0
  37. package/scripts/foundry/reconcile-version.mjs +150 -0
  38. package/scripts/foundry/release-gate.mjs +100 -0
  39. package/scripts/foundry/release.mjs +266 -0
  40. package/scripts/foundry/validate-release-docs.mjs +316 -0
  41. package/scripts/foundry/version-manager.mjs +444 -0
  42. package/scripts/node/ci-cd-auto-fix.cjs +12 -257
  43. package/scripts/node/consumer-install-smoke.mjs +17 -0
  44. package/scripts/node/enforce-version-compliance.sh +5 -20
  45. package/scripts/node/enforce-version-compliance.ts +13 -113
  46. package/scripts/node/foundry-shim.mjs +19 -0
  47. package/scripts/node/github-actions-monitor.cjs +13 -18
  48. package/scripts/node/install-bridges.cjs +43 -29
  49. package/scripts/node/postinstall.cjs +36 -1
  50. package/scripts/node/reconcile-version.mjs +3 -142
  51. package/scripts/node/release-gate.mjs +3 -74
  52. package/scripts/node/release.mjs +3 -171
  53. package/scripts/node/validate-release-docs.mjs +3 -285
  54. package/scripts/node/version-manager.mjs +3 -738
  55. package/src/integrations/openclaw/plugin/xray-pre-tool/package.json +1 -1
  56. package/xray/features.json +1 -1
  57. package/scripts/node/release.js +0 -17
  58. package/scripts/node/sync-versions.mjs +0 -18
  59. package/scripts/node/universal-version-manager.js +0 -1043
@@ -1,739 +1,4 @@
1
1
  #!/usr/bin/env node
2
-
3
- /**
4
- * Version Manager for xray
5
- *
6
- * Updates version in:
7
- * - package.json
8
- * - CHANGELOG.md (auto-generates from git commits since last tag)
9
- * - README.md (updates agent/MCP/skill counts)
10
- * - AGENTS.md (updates agent/MCP/skill counts)
11
- *
12
- * Auto-generates changelog from git commits using conventional commit format.
13
- * Usage:
14
- * node scripts/node/version-manager.mjs [major|minor|patch]
15
- * node scripts/node/version-manager.mjs [major|minor|patch] "Custom description"
16
- * node scripts/node/version-manager.mjs [major|minor|patch] --tag
17
- */
18
-
19
- import fs from 'fs';
20
- import path from 'path';
21
- import { fileURLToPath } from 'url';
22
- import { execSync } from 'child_process';
23
-
24
- const __dirname = path.dirname(fileURLToPath(import.meta.url));
25
- const rootDir = path.resolve(__dirname, '../..');
26
-
27
- // Files to update with version
28
- const VERSION_FILES = [
29
- { file: 'package.json', field: 'version', pattern: /"version":\s*"[^"]+"/ }
30
- ];
31
-
32
- // Commit types for changelog grouping
33
- const COMMIT_TYPES = {
34
- feat: { emoji: 'โœจ', title: 'Features', prefix: 'feat:' },
35
- fix: { emoji: '๐Ÿ›', title: 'Bug Fixes', prefix: 'fix:' },
36
- docs: { emoji: '๐Ÿ“š', title: 'Documentation', prefix: 'docs:' },
37
- chore: { emoji: '๐Ÿ”ง', title: 'Maintenance', prefix: 'chore:' },
38
- refactor: { emoji: 'โ™ป๏ธ', title: 'Refactoring', prefix: 'refactor:' },
39
- perf: { emoji: 'โšก', title: 'Performance', prefix: 'perf:' },
40
- test: { emoji: '๐Ÿงช', title: 'Tests', prefix: 'test:' },
41
- style: { emoji: '๐Ÿ’Ž', title: 'Styles', prefix: 'style:' },
42
- ci: { emoji: '๐Ÿ‘ท', title: 'CI/CD', prefix: 'ci:' },
43
- build: { emoji: '๐Ÿ“ฆ', title: 'Builds', prefix: 'build:' },
44
- revert: { emoji: 'โช', title: 'Reverts', prefix: 'revert:' }
45
- };
46
-
47
- /**
48
- * Get the last git tag (most recent version)
49
- */
50
- function getLastGitTag() {
51
- try {
52
- const tag = execSync('git describe --tags --abbrev=0 2>/dev/null || echo "v0.0.0"', {
53
- cwd: rootDir,
54
- encoding: 'utf-8'
55
- }).trim();
56
- return tag || 'v0.0.0';
57
- } catch {
58
- return 'v0.0.0';
59
- }
60
- }
61
-
62
- /**
63
- * Extract commits since the last tag
64
- */
65
- function getCommitsSinceLastTag() {
66
- const lastTag = getLastGitTag();
67
- console.log(`๐Ÿ“Š Found last tag: ${lastTag}`);
68
-
69
- try {
70
- // Get commits since last tag with conventional format
71
- const commits = execSync(
72
- `git log ${lastTag}..HEAD --oneline --format="%s||%h"`,
73
- { cwd: rootDir, encoding: 'utf-8' }
74
- ).trim().split('\n').filter(Boolean);
75
-
76
- return commits.map(commit => {
77
- const [message, hash] = commit.split('||');
78
- return { message: message.trim(), hash: hash.trim() };
79
- });
80
- } catch (error) {
81
- // If no tags or error, get all commits from initial commit
82
- console.log('โš ๏ธ Could not get commits from tag, using all commits');
83
- const commits = execSync(
84
- `git log --oneline --format="%s||%h" -n 50`,
85
- { cwd: rootDir, encoding: 'utf-8' }
86
- ).trim().split('\n').filter(Boolean);
87
-
88
- return commits.map(commit => {
89
- const [message, hash] = commit.split('||');
90
- return { message: message.trim(), hash: hash.trim() };
91
- });
92
- }
93
- }
94
-
95
- /**
96
- * Parse commits and group by type
97
- */
98
- function parseCommitsByType(commits) {
99
- const grouped = {
100
- feat: [],
101
- fix: [],
102
- docs: [],
103
- chore: [],
104
- refactor: [],
105
- perf: [],
106
- test: [],
107
- style: [],
108
- ci: [],
109
- build: [],
110
- revert: [],
111
- other: []
112
- };
113
-
114
- for (const commit of commits) {
115
- const message = commit.message.toLowerCase();
116
- let matched = false;
117
-
118
- for (const [type, config] of Object.entries(COMMIT_TYPES)) {
119
- if (message.startsWith(config.prefix)) {
120
- grouped[type].push(commit);
121
- matched = true;
122
- break;
123
- }
124
- }
125
-
126
- if (!matched) {
127
- grouped.other.push(commit);
128
- }
129
- }
130
-
131
- return grouped;
132
- }
133
-
134
- /**
135
- * Generate changelog content from commits
136
- */
137
- function generateChangelogFromCommits(commits) {
138
- const grouped = parseCommitsByType(commits);
139
- const sections = [];
140
-
141
- // Build sections in preferred order
142
- const typeOrder = ['feat', 'fix', 'perf', 'refactor', 'docs', 'test', 'style', 'ci', 'build', 'chore', 'revert'];
143
-
144
- for (const type of typeOrder) {
145
- if (grouped[type].length > 0) {
146
- const config = COMMIT_TYPES[type];
147
- const items = grouped[type].map(c => `- ${c.message} (${c.hash})`).join('\n');
148
- sections.push(`### ${config.emoji} ${config.title}\n${items}`);
149
- }
150
- }
151
-
152
- // Add other/unclassified if any
153
- if (grouped.other.length > 0 && grouped.other.length <= 5) {
154
- const items = grouped.other.map(c => `- ${c.message} (${c.hash})`).join('\n');
155
- sections.push(`### ๐Ÿ”Ž Other Changes\n${items}`);
156
- }
157
-
158
- return sections.join('\n\n') || '- Version bump';
159
- }
160
-
161
- /**
162
- * Count actual framework components
163
- * @param {string} [baseDir]
164
- */
165
- export function getFrameworkCounts(baseDir = rootDir) {
166
- const counts = {
167
- agents: 0,
168
- mcps: 0,
169
- skills: 0,
170
- codexTerms: 68,
171
- };
172
-
173
- // Count agents (.yml files in src/opencode/agents/ โ€” source of truth)
174
- const agentsDir = path.join(baseDir, 'src/opencode/agents');
175
- if (fs.existsSync(agentsDir)) {
176
- counts.agents = fs.readdirSync(agentsDir)
177
- .filter(f => f.endsWith('.yml'))
178
- .length;
179
- }
180
-
181
- // Consumer MCP count from .mcp.json SSOT (7 servers), not internal dist/mcps inventory
182
- const mcpJsonPath = path.join(baseDir, '.mcp.json');
183
- if (fs.existsSync(mcpJsonPath)) {
184
- try {
185
- const mcpJson = JSON.parse(fs.readFileSync(mcpJsonPath, 'utf-8'));
186
- const servers = mcpJson.mcpServers || mcpJson.servers || {};
187
- const xrayServers = Object.keys(servers).filter((name) => name.startsWith('xray-'));
188
- counts.mcps = xrayServers.length || 7;
189
- } catch {
190
- counts.mcps = 7;
191
- }
192
- } else {
193
- counts.mcps = 7;
194
- }
195
-
196
- // Count skills (directories in src/skills/ with SKILL.md)
197
- const skillsDir = path.join(baseDir, 'src/skills');
198
- if (fs.existsSync(skillsDir)) {
199
- counts.skills = fs.readdirSync(skillsDir)
200
- .filter(f => fs.statSync(path.join(skillsDir, f)).isDirectory())
201
- .filter(f => fs.existsSync(path.join(skillsDir, f, 'SKILL.md')))
202
- .length;
203
- }
204
-
205
- const codexPath = path.join(baseDir, 'xray/codex.json');
206
- if (fs.existsSync(codexPath)) {
207
- try {
208
- const codex = JSON.parse(fs.readFileSync(codexPath, 'utf-8'));
209
- const terms = codex.terms && typeof codex.terms === 'object' ? Object.keys(codex.terms) : [];
210
- if (terms.length > 0) counts.codexTerms = terms.length;
211
- } catch {
212
- /* keep default */
213
- }
214
- }
215
-
216
- return counts;
217
- }
218
-
219
- function getChangelogEntry(newVersion, changeDescription) {
220
- const date = new Date().toISOString().split('T')[0];
221
-
222
- // If manual description provided, use it; otherwise auto-generate from commits
223
- let content;
224
- if (changeDescription) {
225
- content = changeDescription;
226
- } else {
227
- // Auto-generate from git commits
228
- console.log('๐Ÿ“ No description provided, auto-generating from git commits...');
229
- const commits = getCommitsSinceLastTag();
230
- console.log(`๐Ÿ“Š Found ${commits.length} commits since last release`);
231
- content = generateChangelogFromCommits(commits);
232
- }
233
-
234
- return `## [${newVersion}] - ${date}
235
-
236
- ### ๐Ÿ”„ Changes
237
-
238
- ${content}
239
-
240
- ---
241
-
242
- `;
243
- }
244
-
245
- function changelogHasVersion(newVersion) {
246
- const changelogPath = path.join(rootDir, 'CHANGELOG.md');
247
- if (!fs.existsSync(changelogPath)) return false;
248
- const changelog = fs.readFileSync(changelogPath, 'utf-8');
249
- return new RegExp(`^## \\[${newVersion.replace(/\./g, '\\.')}\\]`, 'm').test(changelog);
250
- }
251
-
252
- function updateChangelog(newVersion, changeDescription) {
253
- const changelogPath = path.join(rootDir, 'CHANGELOG.md');
254
- let changelog = fs.readFileSync(changelogPath, 'utf-8');
255
-
256
- if (changelogHasVersion(newVersion)) {
257
- console.log(`โ„น๏ธ CHANGELOG.md already has [${newVersion}] โ€” skipping duplicate entry`);
258
- return;
259
- }
260
-
261
- // Find the position after the header and insert new entry
262
- const headerEnd = changelog.indexOf('## [');
263
- if (headerEnd === -1) {
264
- console.log('โš ๏ธ Could not find version header in CHANGELOG.md');
265
- return;
266
- }
267
-
268
- const newEntry = getChangelogEntry(newVersion, changeDescription);
269
- const newChangelog = changelog.slice(0, headerEnd) + newEntry + changelog.slice(headerEnd);
270
-
271
- fs.writeFileSync(changelogPath, newChangelog);
272
- console.log(`โœ… Updated CHANGELOG.md`);
273
- }
274
-
275
- /**
276
- * Update README.md with actual framework counts and version
277
- */
278
- function updateReadme(counts, newVersion) {
279
- const readmePath = path.join(rootDir, 'README.md');
280
- if (!fs.existsSync(readmePath)) {
281
- console.log(`โš ๏ธ README.md not found, skipping`);
282
- return;
283
- }
284
-
285
- let readme = fs.readFileSync(readmePath, 'utf-8');
286
-
287
- // Kernel header (4.0): exo, not catalog counts
288
- const kernel = buildDocsHeader(counts, newVersion);
289
- readme = readme.replace(
290
- /^\*\*v[\d.]+\*\* โ€” (?:\d+ agents ยท \d+ skills ยท \d+ MCP servers? ยท \d+ codex terms(?: ยท [\d,]+ tests)?|a suit that survives the context window.*)$/m,
291
- kernel,
292
- );
293
-
294
- // Update version badge: [![Version](https://img.shields.io/badge/version-1.6.x-blue...)]
295
- readme = readme.replace(
296
- /img.shields.io\/badge\/version-[\d.]+/,
297
- `img.shields.io/badge/version-${newVersion}`
298
- );
299
-
300
- // Update agent count: [View all 23 agents โ†’](AGENTS.md)
301
- readme = readme.replace(
302
- /\[View all \d+ agents โ†’]\(AGENTS\.md\)/,
303
- `[View all ${counts.agents} agents โ†’](AGENTS.md)`
304
- );
305
-
306
- // Update skills count
307
- readme = readme.replace(
308
- /(\d+)\s+Skills?/g,
309
- (match, num) => `${counts.skills} Skills`
310
- );
311
-
312
- // Update components line like "9 agents, 28 MCP servers, 8 interconnected pipelines"
313
- readme = readme.replace(
314
- /(\d+)\s+agents,\s*(\d+)\s+MCP servers/,
315
- `${counts.agents} agents, ${counts.mcps} MCP servers`
316
- );
317
-
318
- fs.writeFileSync(readmePath, readme);
319
- console.log(`โœ… Updated README.md (version: ${newVersion}, agents: ${counts.agents}, mcps: ${counts.mcps}, skills: ${counts.skills})`);
320
- }
321
-
322
- export const DOCS_SITE_HEADER_FILES = [
323
- 'docs-site/docs/index.md',
324
- 'docs-site/docs/introduction.md',
325
- 'docs-site/docs/guides/getting-started.md',
326
- 'docs-site/docs/full-reference.md',
327
- 'docs-site/docs/architecture/GROK_GUIDE.md',
328
- 'docs-site/docs/mcp/README.md',
329
- 'docs-site/docs/agents/README.md',
330
- ];
331
-
332
- export function buildDocsHeader(_counts, newVersion) {
333
- return `**v${newVersion}** โ€” a suit that survives the context window`;
334
- }
335
-
336
- function syncDocsSiteHeaders(counts, newVersion) {
337
- const header = buildDocsHeader(counts, newVersion);
338
- const headerRe =
339
- /^\*{0,2}v?[\d.]*\*{0,2}\s*โ€”?\s*(?:\d+ agents ยท \d+ skills ยท \d+ MCP servers? ยท \d+ codex terms(?: ยท [\d,]+ tests)?|a suit that survives the context window.*|exo, not toolset.*|wear the exo.*)/im;
340
- for (const rel of DOCS_SITE_HEADER_FILES) {
341
- const filePath = path.join(rootDir, rel);
342
- if (!fs.existsSync(filePath)) continue;
343
- let content = fs.readFileSync(filePath, 'utf-8');
344
- if (headerRe.test(content)) {
345
- content = content.replace(headerRe, header);
346
- fs.writeFileSync(filePath, content);
347
- console.log(`โœ… Updated ${rel} header`);
348
- }
349
- }
350
- }
351
-
352
- function updatePluginJsonVersion(newVersion) {
353
- const pluginPath = path.join(rootDir, '.grok-plugin/plugin.json');
354
- if (!fs.existsSync(pluginPath)) return;
355
- const plugin = JSON.parse(fs.readFileSync(pluginPath, 'utf-8'));
356
- plugin.version = newVersion;
357
- fs.writeFileSync(pluginPath, JSON.stringify(plugin, null, 2) + '\n');
358
- console.log(`โœ… Updated .grok-plugin/plugin.json (version: ${newVersion})`);
359
- }
360
-
361
- function updateJsonVersionField(relPath, newVersion) {
362
- const full = path.join(rootDir, relPath);
363
- if (!fs.existsSync(full)) return;
364
- const data = JSON.parse(fs.readFileSync(full, 'utf-8'));
365
- data.version = newVersion;
366
- fs.writeFileSync(full, JSON.stringify(data, null, 2) + '\n');
367
- }
368
-
369
- function updateFeaturesJsonVersion(newVersion) {
370
- updateJsonVersionField('xray/features.json', newVersion);
371
- }
372
-
373
- function updateOpenclawPluginVersion(newVersion) {
374
- updateJsonVersionField('src/integrations/openclaw/plugin/xray-pre-tool/package.json', newVersion);
375
- }
376
-
377
- function updateConsumerAgentsHeader(newVersion, counts) {
378
- const consumerPath = path.join(rootDir, 'AGENTS-consumer.md');
379
- if (!fs.existsSync(consumerPath)) return;
380
- let content = fs.readFileSync(consumerPath, 'utf-8');
381
- content = content.replace(
382
- /^\*\*v[\d.]+\*\* โ€” .+$/m,
383
- buildDocsHeader(counts, newVersion),
384
- );
385
- fs.writeFileSync(consumerPath, content);
386
- console.log(`โœ… Updated AGENTS-consumer.md version header`);
387
- }
388
-
389
- function updateSkillsMd(counts, newVersion) {
390
- const skillsPath = path.join(rootDir, 'SKILLS.md');
391
- if (!fs.existsSync(skillsPath)) {
392
- console.log(`โš ๏ธ SKILLS.md not found, skipping`);
393
- return;
394
- }
395
- let content = fs.readFileSync(skillsPath, 'utf-8');
396
- content = content.replace(
397
- /^\*\*v[\d.]+\*\* โ€” \*\*\d+ skills\*\*/m,
398
- `**v${newVersion}** โ€” **${counts.skills} skills**`
399
- );
400
- fs.writeFileSync(skillsPath, content);
401
- console.log(`โœ… Updated SKILLS.md version header`);
402
- }
403
-
404
- function applyAgentCountUpdates(content, counts) {
405
- let agentsMd = content;
406
-
407
- // Legacy header count update (min compat for old consumer AGENTS.md files only; xray v2 YML SSOT primary)
408
- agentsMd = agentsMd.replace(
409
- /0xRay\s*2\.0\s*-\s*\d+\s+Agents|0xRay\s*-\s*\d+\s+Agents/,
410
- `xray v2 - ${counts.agents} Agents`
411
- );
412
-
413
- agentsMd = agentsMd.replace(/\d+\s+MCP servers/g, `${counts.mcps} MCP servers`);
414
- agentsMd = agentsMd.replace(/\d+\s+Skills?/g, `${counts.skills} Skills`);
415
-
416
- return agentsMd;
417
- }
418
-
419
- /**
420
- * Update AGENTS.md with actual framework counts
421
- */
422
- function updateAgentsMd(counts, newVersion = getCurrentVersion()) {
423
- const agentsPath = path.join(rootDir, 'AGENTS.md');
424
- if (!fs.existsSync(agentsPath)) {
425
- return;
426
- }
427
-
428
- let agentsMd = applyAgentCountUpdates(fs.readFileSync(agentsPath, 'utf-8'), counts);
429
- agentsMd = agentsMd.replace(/\(\*\*v[\d.]+\*\*\)/, `(**v${newVersion}**)`);
430
- agentsMd = agentsMd.replace(
431
- /^\*\*v[\d.]+\*\* โ€” a suit that survives the context window\.?$/m,
432
- buildDocsHeader(counts, newVersion),
433
- );
434
- agentsMd = agentsMd.replace(/^## Postinstall \(v[\d.]+\)$/m, `## Postinstall (v${newVersion})`);
435
- fs.writeFileSync(agentsPath, agentsMd);
436
- }
437
-
438
- function updateAgentsConsumerMd(counts) {
439
- const agentsPath = path.join(rootDir, 'AGENTS-consumer.md');
440
- if (!fs.existsSync(agentsPath)) {
441
- console.log(`โš ๏ธ AGENTS-consumer.md not found, skipping`);
442
- return;
443
- }
444
-
445
- fs.writeFileSync(agentsPath, applyAgentCountUpdates(fs.readFileSync(agentsPath, 'utf-8'), counts));
446
- console.log(`โœ… Updated AGENTS-consumer.md`);
447
- }
448
-
449
- function updateDocsReadme(newVersion) {
450
- const docsReadmePath = path.join(rootDir, 'docs/README.md');
451
- if (!fs.existsSync(docsReadmePath)) {
452
- console.log(`โš ๏ธ docs/README.md not found, skipping`);
453
- return;
454
- }
455
-
456
- let readme = fs.readFileSync(docsReadmePath, 'utf-8');
457
- readme = readme.replace(
458
- /img.shields.io\/badge\/version-[\d.]+/,
459
- `img.shields.io/badge/version-${newVersion}`
460
- );
461
- fs.writeFileSync(docsReadmePath, readme);
462
- console.log(`โœ… Updated docs/README.md (version: ${newVersion})`);
463
- }
464
-
465
- function getCurrentVersion() {
466
- const pkg = JSON.parse(fs.readFileSync(path.join(rootDir, 'package.json'), 'utf-8'));
467
- return pkg.version;
468
- }
469
-
470
- function parseVersion(version) {
471
- const parts = version.split('.');
472
- return {
473
- major: parseInt(parts[0], 10),
474
- minor: parseInt(parts[1], 10),
475
- patch: parseInt(parts[2], 10)
476
- };
477
- }
478
-
479
- function bumpVersion(current, type) {
480
- const v = parseVersion(current);
481
-
482
- switch (type) {
483
- case 'major':
484
- v.major++;
485
- v.minor = 0;
486
- v.patch = 0;
487
- break;
488
- case 'minor':
489
- v.minor++;
490
- v.patch = 0;
491
- break;
492
- case 'patch':
493
- v.patch++;
494
- break;
495
- default:
496
- // Assume it's a specific version
497
- return type;
498
- }
499
-
500
- return `${v.major}.${v.minor}.${v.patch}`;
501
- }
502
-
503
- function updateVersion(newVersion, changeDescription = '') {
504
- console.log(`\n๐Ÿ“ฆ Updating version to ${newVersion}\n`);
505
-
506
- // Update package.json
507
- const pkgPath = path.join(rootDir, 'package.json');
508
- const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf-8'));
509
- pkg.version = newVersion;
510
- fs.writeFileSync(pkgPath, JSON.stringify(pkg, null, 2) + '\n');
511
- console.log(`โœ… Updated package.json`);
512
-
513
- // init.sh legacy version key no longer updated (final xray cutover - no historical scaffolding)
514
- updateDocsReadme(newVersion);
515
-
516
- // Update UVM's own version string
517
- const uvmPath = path.join(rootDir, 'scripts/node/universal-version-manager.js');
518
- if (fs.existsSync(uvmPath)) {
519
- let uvmContent = fs.readFileSync(uvmPath, 'utf-8');
520
- uvmContent = uvmContent.replace(
521
- /version:\s*"[0-9]+\.[0-9]+\.[0-9]+"/,
522
- `version: "${newVersion}"`
523
- );
524
- uvmContent = uvmContent.replace(
525
- /lastUpdated:\s*"[0-9]{4}-[0-9]{2}-[0-9]{2}"/,
526
- `lastUpdated: "${new Date().toISOString().split('T')[0]}"`
527
- );
528
- fs.writeFileSync(uvmPath, uvmContent);
529
- console.log(`โœ… Updated UVM version: ${newVersion}`);
530
- }
531
-
532
- // Update CHANGELOG.md
533
- updateChangelog(newVersion, changeDescription);
534
-
535
- // Get actual framework counts and update documentation
536
- const counts = getFrameworkCounts();
537
- console.log(`\n๐Ÿ“Š Framework counts: ${counts.agents} agents, ${counts.mcps} MCPs, ${counts.skills} skills`);
538
-
539
- updateReadme(counts, newVersion);
540
- syncDocsSiteHeaders(counts, newVersion);
541
- updatePluginJsonVersion(newVersion);
542
- updateFeaturesJsonVersion(newVersion);
543
- updateOpenclawPluginVersion(newVersion);
544
- updateConsumerAgentsHeader(newVersion, counts);
545
- updateAgentsMd(counts, newVersion);
546
- updateAgentsConsumerMd(counts);
547
- updateSkillsMd(counts, newVersion);
548
-
549
- console.log(`\n๐ŸŽ‰ Version updated to ${newVersion}\n`);
550
- }
551
-
552
- function createGitTag(version, message) {
553
- try {
554
- // Create annotated tag
555
- const tagName = `v${version}`;
556
- const tagMessage = message || `Release ${version}`;
557
-
558
- execSync(`git tag -a ${tagName} -m "${tagMessage}"`, { cwd: rootDir, stdio: 'inherit' });
559
- console.log(`โœ… Created git tag: ${tagName}`);
560
-
561
- // Push tag to remote
562
- execSync(`git push origin ${tagName}`, { cwd: rootDir, stdio: 'inherit' });
563
- console.log(`โœ… Pushed tag to origin: ${tagName}`);
564
-
565
- return true;
566
- } catch (error) {
567
- console.log(`โš ๏ธ Failed to create git tag: ${error.message}`);
568
- return false;
569
- }
570
- }
571
-
572
- /** Paths written by release artifact updates (existing files only). */
573
- export function getReleaseArtifactPaths() {
574
- const candidates = [
575
- 'package.json',
576
- 'CHANGELOG.md',
577
- 'README.md',
578
- 'AGENTS.md',
579
- 'AGENTS-consumer.md',
580
- 'SKILLS.md',
581
- '.grok-plugin/plugin.json',
582
- 'docs/README.md',
583
- 'docs-site/docs/index.md',
584
- 'docs-site/docs/introduction.md',
585
- 'docs-site/docs/guides/getting-started.md',
586
- 'docs-site/docs/full-reference.md',
587
- 'docs-site/docs/guides/integrations.md',
588
- 'docs-site/docs/guides/features-since-3.1.md',
589
- 'docs-site/docs/guides/features-json.md',
590
- 'docs-site/docs/guides/memory-routing.md',
591
- 'docs-site/docs/guides/aside-context.md',
592
- 'docs-site/docs/guides/repertoire.md',
593
- 'docs-site/docs/guides/consumer-migration.md',
594
- 'docs-site/docs/mcp/README.md',
595
- 'docs-site/docs/agents/README.md',
596
- 'docs-site/docs/architecture/GROK_GUIDE.md',
597
- 'docs-site/sidebars.ts',
598
- 'xray/features.json',
599
- ];
600
- return candidates.filter((rel) => fs.existsSync(path.join(rootDir, rel)));
601
- }
602
-
603
- /** Update CHANGELOG + README + AGENTS (+ consumer/docs) for current package.json version (no bump). */
604
- function updateReleaseArtifactsOnly(changeDescription = '') {
605
- const current = getCurrentVersion();
606
- console.log(`\n๐Ÿ“Œ Release artifacts for v${current}\n`);
607
- const counts = getFrameworkCounts();
608
- console.log(`๐Ÿ“Š Framework counts: ${counts.agents} agents, ${counts.mcps} MCPs, ${counts.skills} skills`);
609
- updateChangelog(current, changeDescription);
610
- updateReadme(counts, current);
611
- syncDocsSiteHeaders(counts, current);
612
- updatePluginJsonVersion(current);
613
- updateFeaturesJsonVersion(current);
614
- updateOpenclawPluginVersion(current);
615
- updateConsumerAgentsHeader(current, counts);
616
- updateDocsReadme(current);
617
- updateAgentsMd(counts, current);
618
- updateAgentsConsumerMd(counts);
619
- updateSkillsMd(counts, current);
620
- runReleaseDocsValidation();
621
- console.log(`\nโœ… Release artifacts updated for v${current}\n`);
622
- }
623
-
624
- function runReleaseDocsValidation() {
625
- try {
626
- execSync('node scripts/node/validate-release-docs.mjs', {
627
- cwd: rootDir,
628
- stdio: 'inherit',
629
- });
630
- } catch {
631
- console.error('\nโŒ Release artifact docs failed validation โ€” fix before tagging\n');
632
- process.exit(1);
633
- }
634
- }
635
-
636
- function main() {
637
- const args = process.argv.slice(2);
638
-
639
- if (args.includes('--artifacts-only')) {
640
- updateReleaseArtifactsOnly('');
641
- return;
642
- }
643
-
644
- // Handle --help flag first
645
- if (args.includes('--help') || args.includes('-h')) {
646
- const current = getCurrentVersion();
647
- console.log(`\n๐Ÿ“Œ Current version: ${current}`);
648
- console.log(`\nUsage:`);
649
- console.log(` node scripts/node/version-manager.mjs [major|minor|patch] [description]`);
650
- console.log(` node scripts/node/version-manager.mjs 1.6.9 "Description of changes"`);
651
- console.log(` node scripts/node/version-manager.mjs patch --tag # auto-changelog + git tag`);
652
- console.log(` node scripts/node/version-manager.mjs --artifacts-only # CHANGELOG/README/AGENTS/docs`);
653
- console.log(`\nExamples:`);
654
- console.log(` node scripts/node/version-manager.mjs patch # 1.6.8 -> 1.6.9 (auto-generates changelog from git)`);
655
- console.log(` node scripts/node/version-manager.mjs minor # 1.6.8 -> 1.7.0`);
656
- console.log(` node scripts/node/version-manager.mjs major # 1.6.8 -> 2.0.0`);
657
- console.log(` node scripts/node/version-manager.mjs patch "Manual description" # use custom changelog`);
658
- console.log(` node scripts/node/version-manager.mjs patch --tag # changelog + git tag`);
659
- process.exit(0);
660
- }
661
-
662
- // When called with no arguments (npm version lifecycle hook), npm has already
663
- // bumped package.json. Just propagate the current version to other files.
664
- const current = getCurrentVersion();
665
- let type = args[0];
666
- let changeDescription = '';
667
- let createTag = false;
668
-
669
- if (!type) {
670
- // No bump type โ€” this is a lifecycle hook call. Don't re-bump.
671
- // Just update CHANGELOG, README, AGENTS.md with the current version.
672
- console.log(`\n๐Ÿ“Œ Lifecycle mode โ€” propagating current version: ${current}\n`);
673
- const counts = getFrameworkCounts();
674
- console.log(`๐Ÿ“Š Framework counts: ${counts.agents} agents, ${counts.mcps} MCPs, ${counts.skills} skills`);
675
- updateChangelog(current, '');
676
- updateReadme(counts, current);
677
- syncDocsSiteHeaders(counts, current);
678
- updatePluginJsonVersion(current);
679
- updateFeaturesJsonVersion(current);
680
- updateOpenclawPluginVersion(current);
681
- updateConsumerAgentsHeader(current, counts);
682
- updateDocsReadme(current);
683
- updateAgentsMd(counts);
684
- updateAgentsConsumerMd(counts);
685
- updateSkillsMd(counts, current);
686
-
687
- // Update UVM's own version string to match package.json
688
- const uvmPath = path.join(rootDir, 'scripts/node/universal-version-manager.js');
689
- if (fs.existsSync(uvmPath)) {
690
- let uvmContent = fs.readFileSync(uvmPath, 'utf-8');
691
- uvmContent = uvmContent.replace(
692
- /version:\s*"[0-9]+\.[0-9]+\.[0-9]+"/,
693
- `version: "${current}"`
694
- );
695
- uvmContent = uvmContent.replace(
696
- /lastUpdated:\s*"[0-9]{4}-[0-9]{2}-[0-9]{2}"/,
697
- `lastUpdated: "${new Date().toISOString().split('T')[0]}"`
698
- );
699
- fs.writeFileSync(uvmPath, uvmContent);
700
- console.log(`โœ… Updated UVM version: ${current}`);
701
- }
702
-
703
- console.log(`\n๐ŸŽ‰ Version propagated: ${current}\n`);
704
- return;
705
- }
706
-
707
- for (let i = 1; i < args.length; i++) {
708
- if (args[i] === '--tag' || args[i] === '-t') {
709
- createTag = true;
710
- } else {
711
- changeDescription = args[i];
712
- }
713
- }
714
-
715
- const newVersion = bumpVersion(current, type);
716
-
717
- console.log(`\n๐Ÿ“Œ Current version: ${current}`);
718
- console.log(`๐Ÿ“Œ Bumping: ${type}`);
719
- if (changeDescription) {
720
- console.log(`๐Ÿ“Œ Changes: ${changeDescription}`);
721
- }
722
- if (createTag) {
723
- console.log(`๐Ÿ“Œ Will create git tag`);
724
- }
725
-
726
- updateVersion(newVersion, changeDescription);
727
-
728
- // Create git tag if requested
729
- if (createTag) {
730
- createGitTag(newVersion, changeDescription);
731
- }
732
- }
733
-
734
- const isMainModule =
735
- process.argv[1] && path.resolve(process.argv[1]) === fileURLToPath(import.meta.url);
736
-
737
- if (isMainModule) {
738
- main();
739
- }
2
+ export * from "../foundry/version-manager.mjs";
3
+ import { millMain } from "./foundry-shim.mjs";
4
+ millMain(import.meta.url, "version-manager.mjs");