0xray 3.3.1 → 3.4.2
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/.opencode/enforcer-config.json +1 -4
- package/.xray/codex.json +598 -0
- package/.xray/config.json +25 -0
- package/.xray/features.json +146 -0
- package/.xray/features.schema.json +33 -0
- package/AGENTS-consumer.md +127 -10
- package/AGENTS.md +172 -56
- package/README.md +159 -82
- package/SKILLS.md +79 -53
- package/dist/AGENTS.md +172 -56
- package/dist/CHANGELOG.md +90 -51
- package/dist/README.md +159 -82
- package/dist/SKILLS.md +79 -53
- package/dist/analytics/routing-refiner.js +0 -2
- package/dist/core/boot-orchestrator.js +9 -1
- package/dist/core/features-config.js +5 -1
- package/dist/integrations/grok/grok-cli.js +47 -25
- package/dist/integrations/grok/hooks/grok-hook-activity.js +53 -0
- package/dist/integrations/grok/hooks/grok-hook-utils.js +261 -0
- package/dist/integrations/grok/hooks/pre-tool-use.js +85 -115
- package/dist/integrations/grok/hooks/session-start.js +52 -0
- package/dist/integrations/grok/plugin/0xray/hooks/hooks.json +20 -3
- package/dist/integrations/hermes-agent/bridge.mjs +11 -1
- package/dist/mcps/config/server-config-registry.js +4 -3
- package/dist/mcps/orchestrator/handlers/complexity-handler.js +33 -3
- package/dist/mcps/orchestrator/server.js +1 -1
- package/dist/mcps/registry.json +0 -1
- package/dist/mcps/researcher.server.js +3 -0
- package/dist/nucleus/autonomy-kernel.js +176 -0
- package/dist/nucleus/index.js +1 -0
- package/dist/orchestrator/universal-registry-bridge.js +1 -1
- package/dist/skills/boot-orchestrator/SKILL.md +1 -5
- package/dist/skills/orchestrator/SKILL.md +35 -12
- package/dist/skills/registry.json +0 -1
- package/dist/skills/researcher/SKILL.md +17 -4
- package/dist/skills/strategist/SKILL.md +12 -0
- package/dist/skills/testing-strategy/SKILL.md +13 -2
- package/package.json +23 -8
- package/scripts/node/consumer-install-smoke.mjs +163 -0
- package/scripts/node/enforce-agents-md.mjs +0 -26
- package/scripts/node/enforce-version-compliance.sh +0 -1
- package/scripts/node/enforce-version-compliance.ts +0 -10
- package/scripts/node/install-bridges.cjs +154 -39
- package/scripts/node/pre-publish-guard.js +108 -165
- package/scripts/node/reconcile-version.mjs +147 -0
- package/scripts/node/release-gate.mjs +66 -0
- package/scripts/node/release.js +5 -147
- package/scripts/node/release.mjs +106 -181
- package/scripts/node/setup.cjs +21 -26
- package/scripts/node/sync-versions.mjs +12 -134
- package/scripts/node/universal-version-manager.js +22 -4
- package/scripts/node/validate-release-docs.mjs +299 -0
- package/scripts/node/version-manager.mjs +225 -49
- package/src/integrations/grok/plugin/0xray/hooks/hooks.json +20 -3
- package/src/mcps/config/__tests__/server-config-registry.test.ts +9 -0
- package/src/mcps/config/server-config-registry.ts +5 -3
- package/src/mcps/orchestrator/handlers/complexity-handler.ts +54 -3
- package/src/mcps/orchestrator/server.ts +1 -1
- package/src/mcps/registry.json +0 -1
- package/src/mcps/researcher.server.ts +4 -0
- package/src/opencode/enforcer-config.json +1 -4
- package/src/skills/boot-orchestrator/SKILL.md +1 -5
- package/src/skills/orchestrator/SKILL.md +35 -12
- package/src/skills/registry.json +0 -1
- package/src/skills/researcher/SKILL.md +17 -4
- package/src/skills/strategist/SKILL.md +12 -0
- package/src/skills/testing-strategy/SKILL.md +13 -2
- package/xray/config.json +25 -0
- package/xray/features.json +146 -0
- package/xray/features.schema.json +33 -0
package/scripts/node/release.js
CHANGED
|
@@ -1,159 +1,17 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
|
|
3
2
|
/**
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
* Usage:
|
|
7
|
-
* node scripts/node/release.js # patch bump
|
|
8
|
-
* node scripts/node/release.js minor # minor bump
|
|
9
|
-
* node scripts/node/release.js major # major bump
|
|
10
|
-
* node scripts/node/release.js --dry-run # preview without publishing
|
|
3
|
+
* @deprecated Use release.mjs — npm run release:patch|minor|major
|
|
11
4
|
*/
|
|
12
|
-
|
|
13
5
|
import { execSync } from "child_process";
|
|
14
|
-
import fs from "fs";
|
|
15
6
|
import path from "path";
|
|
16
7
|
import { fileURLToPath } from "url";
|
|
17
8
|
|
|
18
9
|
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
19
10
|
const rootDir = path.resolve(__dirname, "../..");
|
|
20
11
|
|
|
21
|
-
|
|
22
|
-
const GREEN = "\x1b[32m";
|
|
23
|
-
const YELLOW = "\x1b[33m";
|
|
24
|
-
const BLUE = "\x1b[36m";
|
|
25
|
-
const BOLD = "\x1b[1m";
|
|
26
|
-
const RESET = "\x1b[0m";
|
|
27
|
-
|
|
28
|
-
const dryRun = process.argv.includes("--dry-run");
|
|
29
|
-
const bumpType = process.argv.find((a) => ["patch", "minor", "major"].includes(a)) || "patch";
|
|
30
|
-
|
|
31
|
-
function run(cmd, label) {
|
|
32
|
-
console.log(`${BLUE}▸ ${label}${RESET}`);
|
|
33
|
-
try {
|
|
34
|
-
execSync(cmd, { cwd: rootDir, stdio: "pipe", encoding: "utf-8" });
|
|
35
|
-
console.log(`${GREEN} ✓ ${label} done${RESET}`);
|
|
36
|
-
return true;
|
|
37
|
-
} catch (e) {
|
|
38
|
-
console.log(`${RED} ✗ ${label} failed: ${e.message?.slice(0, 200) || e}${RESET}`);
|
|
39
|
-
return false;
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
function runInherit(cmd, label) {
|
|
44
|
-
console.log(`${BLUE}▸ ${label}${RESET}`);
|
|
45
|
-
try {
|
|
46
|
-
execSync(cmd, { cwd: rootDir, stdio: "inherit" });
|
|
47
|
-
console.log(`${GREEN} ✓ ${label} done${RESET}`);
|
|
48
|
-
return true;
|
|
49
|
-
} catch (e) {
|
|
50
|
-
console.log(`${RED} ✗ ${label} failed${RESET}`);
|
|
51
|
-
return false;
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
function main() {
|
|
56
|
-
const pkg = JSON.parse(fs.readFileSync(path.join(rootDir, "package.json"), "utf-8"));
|
|
57
|
-
const currentVersion = pkg.version;
|
|
58
|
-
|
|
59
|
-
const parts = currentVersion.split(".").map(Number);
|
|
60
|
-
if (bumpType === "major") parts[0]++;
|
|
61
|
-
else if (bumpType === "minor") parts[1]++;
|
|
62
|
-
else parts[2]++;
|
|
63
|
-
if (bumpType === "major" || bumpType === "minor") parts[2] = 0;
|
|
64
|
-
const nextVersion = parts.join(".");
|
|
65
|
-
|
|
66
|
-
console.log(`\n${BOLD}${BLUE}🚀 xray Release${RESET}`);
|
|
67
|
-
console.log(`${BOLD} ${currentVersion} → ${nextVersion} (${bumpType})${RESET}\n`);
|
|
68
|
-
|
|
69
|
-
if (dryRun) {
|
|
70
|
-
console.log(`${YELLOW}DRY RUN — no changes will be made${RESET}\n`);
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
// Step 1: Tests
|
|
74
|
-
if (!runInherit("npm run test:comprehensive", "Tests")) {
|
|
75
|
-
process.exit(1);
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
// Step 2: Version bump (version:sync runs automatically via preversion hook)
|
|
79
|
-
if (!dryRun) {
|
|
80
|
-
if (!run(`npm version ${bumpType} --no-git-tag-version`, `Bump to ${nextVersion}`)) {
|
|
81
|
-
process.exit(1);
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
// Step 3: Build
|
|
86
|
-
if (!run("npm run build", "Build")) {
|
|
87
|
-
process.exit(1);
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
// Step 4: Commit
|
|
91
|
-
if (!dryRun) {
|
|
92
|
-
if (!run("git add -A", "Stage changes")) {
|
|
93
|
-
process.exit(1);
|
|
94
|
-
}
|
|
95
|
-
const commitMsg = `v${nextVersion}`;
|
|
96
|
-
try {
|
|
97
|
-
execSync(`git commit -m "${commitMsg}"`, { cwd: rootDir, stdio: "pipe", encoding: "utf-8" });
|
|
98
|
-
console.log(`${GREEN} ✓ Committed: ${commitMsg}${RESET}`);
|
|
99
|
-
} catch (e) {
|
|
100
|
-
const output = e.stdout || e.stderr || "";
|
|
101
|
-
if (output.includes("nothing to commit")) {
|
|
102
|
-
console.log(`${YELLOW} ⚠ Nothing to commit${RESET}`);
|
|
103
|
-
} else if (output.includes("BLOCKED")) {
|
|
104
|
-
// Pre-commit hook blocked — likely version compliance
|
|
105
|
-
// Try with --no-verify since we manage versions ourselves
|
|
106
|
-
console.log(`${YELLOW} ⚠ Pre-commit blocked, retrying with --no-verify...${RESET}`);
|
|
107
|
-
try {
|
|
108
|
-
execSync(`git commit --no-verify -m "${commitMsg}"`, { cwd: rootDir, stdio: "pipe", encoding: "utf-8" });
|
|
109
|
-
console.log(`${GREEN} ✓ Committed (no-verify): ${commitMsg}${RESET}`);
|
|
110
|
-
} catch (e2) {
|
|
111
|
-
console.log(`${RED} ✗ Commit failed: ${e2.message?.slice(0, 200)}${RESET}`);
|
|
112
|
-
process.exit(1);
|
|
113
|
-
}
|
|
114
|
-
} else {
|
|
115
|
-
console.log(`${RED} ✗ Commit failed: ${output.slice(0, 200)}${RESET}`);
|
|
116
|
-
process.exit(1);
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
// Step 5: Publish
|
|
122
|
-
if (!dryRun) {
|
|
123
|
-
console.log(`${BLUE}▸ Publishing to npm${RESET}`);
|
|
124
|
-
try {
|
|
125
|
-
execSync("npm publish --access public", { cwd: rootDir, stdio: "inherit" });
|
|
126
|
-
console.log(`${GREEN} ✓ Published xray@${nextVersion}${RESET}`);
|
|
127
|
-
} catch (e) {
|
|
128
|
-
const errMsg = (e.stderr?.toString() || "") + (e.message || "");
|
|
129
|
-
if (errMsg.includes("previously published")) {
|
|
130
|
-
console.log(`${GREEN} ✓ Already published xray@${nextVersion}${RESET}`);
|
|
131
|
-
} else {
|
|
132
|
-
console.log(`${RED} ✗ Publish failed. Trying with --ignore-scripts...${RESET}`);
|
|
133
|
-
try {
|
|
134
|
-
execSync("npm publish --access public --ignore-scripts", { cwd: rootDir, stdio: "pipe", encoding: "utf-8" });
|
|
135
|
-
console.log(`${GREEN} ✓ Published xray@${nextVersion} (ignore-scripts)${RESET}`);
|
|
136
|
-
} catch (e2) {
|
|
137
|
-
const errMsg2 = (e2.stderr?.toString() || "") + (e2.message || "");
|
|
138
|
-
if (errMsg2.includes("previously published")) {
|
|
139
|
-
console.log(`${GREEN} ✓ Already published xray@${nextVersion}${RESET}`);
|
|
140
|
-
} else {
|
|
141
|
-
console.log(`${RED} ✗ Publish failed: ${errMsg2.slice(0, 200)}${RESET}`);
|
|
142
|
-
process.exit(1);
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
}
|
|
146
|
-
}
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
// Step 6: Push
|
|
150
|
-
if (!dryRun) {
|
|
151
|
-
if (!run("git push", "Push to remote")) {
|
|
152
|
-
process.exit(1);
|
|
153
|
-
}
|
|
154
|
-
}
|
|
12
|
+
console.error("\n⚠️ release.js is deprecated. Use: npm run release:patch (release.mjs)\n");
|
|
155
13
|
|
|
156
|
-
|
|
157
|
-
|
|
14
|
+
const bump = process.argv.find((a) => ["patch", "minor", "major"].includes(a)) || "patch";
|
|
15
|
+
const dry = process.argv.includes("--dry-run") ? " --dry-run" : "";
|
|
158
16
|
|
|
159
|
-
|
|
17
|
+
execSync(`node scripts/node/release.mjs ${bump}${dry}`, { cwd: rootDir, stdio: "inherit" });
|
package/scripts/node/release.mjs
CHANGED
|
@@ -1,213 +1,138 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
* 7. Generates release tweet
|
|
14
|
-
*
|
|
4
|
+
* Canonical 0xRay release script.
|
|
5
|
+
*
|
|
6
|
+
* 1. Bump version from npm registry baseline (reconcile-version)
|
|
7
|
+
* 2. Release gate once (build + test + consumer smoke)
|
|
8
|
+
* 3. Update CHANGELOG / README / AGENTS / docs (version-manager --artifacts-only)
|
|
9
|
+
* 4. Commit release artifacts → push
|
|
10
|
+
* 5. Verify gate (reconcile + git + release docs + smoke)
|
|
11
|
+
* 6. Tag → push tag → npm publish
|
|
12
|
+
*
|
|
15
13
|
* Usage:
|
|
16
14
|
* npm run release:patch
|
|
17
|
-
* npm run release:minor
|
|
15
|
+
* npm run release:minor
|
|
18
16
|
* npm run release:major
|
|
17
|
+
* node scripts/node/release.mjs patch --dry-run
|
|
19
18
|
*/
|
|
20
19
|
|
|
21
|
-
import { execSync } from
|
|
22
|
-
import fs from
|
|
23
|
-
import path from
|
|
24
|
-
import {
|
|
20
|
+
import { execSync } from "child_process";
|
|
21
|
+
import fs from "fs";
|
|
22
|
+
import path from "path";
|
|
23
|
+
import { getReleaseArtifactPaths } from "./version-manager.mjs";
|
|
25
24
|
|
|
26
|
-
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
27
25
|
const rootDir = process.cwd();
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
patch: parseInt(parts[2], 10)
|
|
40
|
-
};
|
|
26
|
+
const args = process.argv.slice(2);
|
|
27
|
+
const dryRun = args.includes("--dry-run");
|
|
28
|
+
const releaseType = args.find((a) => ["major", "minor", "patch"].includes(a)) || "patch";
|
|
29
|
+
|
|
30
|
+
function run(cmd, label) {
|
|
31
|
+
console.log(`\n> ${cmd}`);
|
|
32
|
+
if (dryRun) {
|
|
33
|
+
console.log(` (dry-run skip: ${label})`);
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
execSync(cmd, { cwd: rootDir, stdio: "inherit", encoding: "utf-8" });
|
|
41
37
|
}
|
|
42
38
|
|
|
43
|
-
function
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
switch (type) {
|
|
47
|
-
case 'major':
|
|
48
|
-
v.major++;
|
|
49
|
-
v.minor = 0;
|
|
50
|
-
v.patch = 0;
|
|
51
|
-
break;
|
|
52
|
-
case 'minor':
|
|
53
|
-
v.minor++;
|
|
54
|
-
v.patch = 0;
|
|
55
|
-
break;
|
|
56
|
-
case 'patch':
|
|
57
|
-
v.patch++;
|
|
58
|
-
break;
|
|
59
|
-
default:
|
|
60
|
-
return type;
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
return `${v.major}.${v.minor}.${v.patch}`;
|
|
39
|
+
function readVersion() {
|
|
40
|
+
return JSON.parse(fs.readFileSync(path.join(rootDir, "package.json"), "utf-8")).version;
|
|
64
41
|
}
|
|
65
42
|
|
|
66
|
-
function
|
|
67
|
-
|
|
68
|
-
console.log(`\n> ${cmd}`);
|
|
69
|
-
execSync(cmd, {
|
|
70
|
-
cwd: rootDir,
|
|
71
|
-
stdio: 'inherit',
|
|
72
|
-
encoding: 'utf-8'
|
|
73
|
-
});
|
|
74
|
-
} catch (error) {
|
|
75
|
-
console.error(`\n❌ ${errorMsg}`);
|
|
76
|
-
console.error(error.message);
|
|
77
|
-
process.exit(1);
|
|
78
|
-
}
|
|
43
|
+
function currentBranch() {
|
|
44
|
+
return execSync("git rev-parse --abbrev-ref HEAD", { cwd: rootDir, encoding: "utf-8" }).trim();
|
|
79
45
|
}
|
|
80
46
|
|
|
81
47
|
async function main() {
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
if (!['major', 'minor', 'patch'].includes(releaseType)) {
|
|
86
|
-
console.error('Usage: node scripts/node/release.mjs [major|minor|patch]');
|
|
48
|
+
if (!["major", "minor", "patch"].includes(releaseType)) {
|
|
49
|
+
console.error("Usage: node scripts/node/release.mjs [patch|minor|major] [--dry-run]");
|
|
87
50
|
process.exit(1);
|
|
88
51
|
}
|
|
89
52
|
|
|
90
|
-
console.log(
|
|
91
|
-
console.log(
|
|
92
|
-
console.log(
|
|
93
|
-
|
|
94
|
-
const currentVersion = getCurrentVersion();
|
|
95
|
-
console.log(`\n📌 Current version (local): ${currentVersion}`);
|
|
96
|
-
|
|
97
|
-
// Better design: always compute target from the *published* version on npm
|
|
98
|
-
// This removes the brittle "must be exactly one ahead" problem.
|
|
99
|
-
let publishedVersion;
|
|
100
|
-
try {
|
|
101
|
-
publishedVersion = execSync('npm view 0xray version', { encoding: 'utf-8' }).trim();
|
|
102
|
-
console.log(`📌 Latest published on npm: ${publishedVersion}`);
|
|
103
|
-
} catch {
|
|
104
|
-
publishedVersion = '0.0.0';
|
|
105
|
-
console.log('⚠️ Could not fetch published version from npm (using 0.0.0)');
|
|
106
|
-
}
|
|
53
|
+
console.log("╔════════════════════════════════════════════════════════╗");
|
|
54
|
+
console.log("║ 🚀 0xRay Release (canonical) ║");
|
|
55
|
+
console.log("╚════════════════════════════════════════════════════════╝");
|
|
56
|
+
if (dryRun) console.log("\n⚠️ DRY RUN — no writes, commits, tags, or publish\n");
|
|
107
57
|
|
|
108
|
-
|
|
109
|
-
console.log(
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
console.log(`⚠️ Local version (${currentVersion}) differs from computed target. Using computed target ${targetVersion}.`);
|
|
58
|
+
// 1. Version bump from npm SSOT
|
|
59
|
+
console.log(`\n📦 Step 1: Bump ${releaseType} from npm baseline`);
|
|
60
|
+
if (dryRun) {
|
|
61
|
+
execSync(`node scripts/node/reconcile-version.mjs ${releaseType}`, { cwd: rootDir, stdio: "inherit" });
|
|
62
|
+
} else {
|
|
63
|
+
run(`node scripts/node/reconcile-version.mjs ${releaseType} --apply`, "version bump");
|
|
115
64
|
}
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
65
|
+
const newVersion = dryRun
|
|
66
|
+
? execSync(`node scripts/node/reconcile-version.mjs ${releaseType} --print-target`, {
|
|
67
|
+
cwd: rootDir,
|
|
68
|
+
encoding: "utf-8",
|
|
69
|
+
}).trim()
|
|
70
|
+
: readVersion();
|
|
71
|
+
console.log(`📌 Release version: ${newVersion}`);
|
|
72
|
+
|
|
73
|
+
// 2. Single gate before commit
|
|
74
|
+
console.log("\n📦 Step 2: Release gate (build + test + smoke)");
|
|
75
|
+
run("node scripts/node/release-gate.mjs", "release gate");
|
|
76
|
+
|
|
77
|
+
// 3. Changelog + doc artifacts
|
|
78
|
+
console.log("\n📦 Step 3: Release artifacts (CHANGELOG, README, AGENTS, docs)");
|
|
79
|
+
run("node scripts/node/version-manager.mjs --artifacts-only", "release artifacts");
|
|
80
|
+
|
|
81
|
+
// 4. Commit + push
|
|
82
|
+
console.log("\n📦 Step 4: Commit & push");
|
|
83
|
+
const releaseFiles = getReleaseArtifactPaths();
|
|
84
|
+
if (!dryRun) {
|
|
85
|
+
run(`git add ${releaseFiles.join(" ")}`, "git add");
|
|
86
|
+
try {
|
|
87
|
+
execSync(`git commit --no-verify -m "release: v${newVersion}"`, { cwd: rootDir, stdio: "inherit" });
|
|
88
|
+
} catch (e) {
|
|
89
|
+
const out = String(e.stdout || e.stderr || "");
|
|
90
|
+
if (!out.includes("nothing to commit")) throw e;
|
|
91
|
+
console.log("ℹ️ Nothing to commit (release files unchanged)");
|
|
92
|
+
}
|
|
93
|
+
} else {
|
|
94
|
+
console.log(` would: git add ${releaseFiles.join(" ")} && git commit -m "release: v${newVersion}"`);
|
|
136
95
|
}
|
|
137
96
|
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
);
|
|
97
|
+
const branch = currentBranch();
|
|
98
|
+
run(`git push origin ${branch}`, "git push");
|
|
99
|
+
|
|
100
|
+
// 5. Post-push verify before tag
|
|
101
|
+
console.log("\n📦 Step 5: Verify gate (reconcile + git + smoke)");
|
|
102
|
+
run("node scripts/node/release-gate.mjs --verify-only", "verify gate");
|
|
103
|
+
|
|
104
|
+
// 6. Tag
|
|
105
|
+
console.log("\n📦 Step 6: Tag");
|
|
106
|
+
if (!dryRun) {
|
|
107
|
+
execSync(`git tag -a v${newVersion} -m "Release v${newVersion}"`, { cwd: rootDir, stdio: "inherit" });
|
|
150
108
|
console.log(`✅ Created tag v${newVersion}`);
|
|
151
|
-
}
|
|
152
|
-
console.log(
|
|
109
|
+
} else {
|
|
110
|
+
console.log(` would: git tag -a v${newVersion}`);
|
|
153
111
|
}
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
console.log(
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
const tweetDir = path.join(rootDir, 'tweets');
|
|
174
|
-
if (!fs.existsSync(tweetDir)) fs.mkdirSync(tweetDir, { recursive: true });
|
|
175
|
-
|
|
176
|
-
const recentCommits = (() => {
|
|
177
|
-
try {
|
|
178
|
-
const prevTag = execSync('git describe --tags --abbrev=0 HEAD~5 2>/dev/null || echo "HEAD~10"', { cwd: rootDir, encoding: 'utf-8' }).trim();
|
|
179
|
-
return execSync(`git log ${prevTag}..HEAD --oneline`, { cwd: rootDir, encoding: 'utf-8' }).trim();
|
|
180
|
-
} catch {
|
|
181
|
-
try { return execSync('git log -10 --oneline', { cwd: rootDir, encoding: 'utf-8' }).trim(); }
|
|
182
|
-
catch { return '(could not read commits)'; }
|
|
112
|
+
run(`git push origin v${newVersion}`, "push tag");
|
|
113
|
+
|
|
114
|
+
// 7. Publish
|
|
115
|
+
console.log("\n📦 Step 7: npm publish");
|
|
116
|
+
run("npm publish --access public", "npm publish");
|
|
117
|
+
|
|
118
|
+
console.log("\n╔════════════════════════════════════════════════════════╗");
|
|
119
|
+
console.log("║ ✅ Release Complete! ║");
|
|
120
|
+
console.log("╚════════════════════════════════════════════════════════╝");
|
|
121
|
+
if (!dryRun) {
|
|
122
|
+
console.log(`\n📦 0xray@${newVersion} 🏷 v${newVersion}\n`);
|
|
123
|
+
const tweetPath = path.join(rootDir, "tweets", `v${newVersion}.md`);
|
|
124
|
+
if (!fs.existsSync(tweetPath)) {
|
|
125
|
+
fs.mkdirSync(path.join(rootDir, "tweets"), { recursive: true });
|
|
126
|
+
fs.writeFileSync(
|
|
127
|
+
tweetPath,
|
|
128
|
+
`🎉 0xRay v${newVersion} is LIVE - {THEME}!\n...\n\`\`\`\nnpm install 0xray@latest\n\`\`\`\n`,
|
|
129
|
+
);
|
|
130
|
+
console.log(`📝 Tweet template: tweets/v${newVersion}.md`);
|
|
183
131
|
}
|
|
184
|
-
})();
|
|
185
|
-
|
|
186
|
-
const tweet = `🎉 xray v${newVersion} is LIVE - {THEME}!
|
|
187
|
-
{EMOJI} {feature - consumer benefit}
|
|
188
|
-
{EMOJI} {feature - consumer benefit}
|
|
189
|
-
{EMOJI} {feature - consumer benefit}
|
|
190
|
-
{EMOJI} {feature - consumer benefit}
|
|
191
|
-
{EMOJI} {feature - consumer benefit}
|
|
192
|
-
\`\`\`
|
|
193
|
-
npm install xray@latest
|
|
194
|
-
\`\`\`
|
|
195
|
-
What xray is: {one sentence positioning}
|
|
196
|
-
#xray #AIOps #DevTools #SelfHealing #NPM`;
|
|
197
|
-
|
|
198
|
-
if (!fs.existsSync(tweetPath)) {
|
|
199
|
-
fs.writeFileSync(tweetPath, tweet);
|
|
200
|
-
console.log(`\n📝 Tweet template saved to tweets/v${newVersion}.md — FILL IN THE BLANKS`);
|
|
201
|
-
} else {
|
|
202
|
-
console.log(`\n📝 Tweet already exists at tweets/v${newVersion}.md`);
|
|
203
132
|
}
|
|
204
|
-
|
|
205
|
-
console.log(`\n📋 Recent commits for tweet bullets:\n${recentCommits.split('\n').map(l => ' ' + l).join('\n')}`);
|
|
206
|
-
console.log('\n📖 Tweet format guide: tweets/FORMAT.md');
|
|
207
|
-
console.log('\n🎉 All done!\n');
|
|
208
133
|
}
|
|
209
134
|
|
|
210
|
-
main().catch(
|
|
211
|
-
console.error(
|
|
135
|
+
main().catch((err) => {
|
|
136
|
+
console.error("\n❌ Release failed:", err.message);
|
|
212
137
|
process.exit(1);
|
|
213
138
|
});
|
package/scripts/node/setup.cjs
CHANGED
|
@@ -6,7 +6,11 @@ const path = require("path");
|
|
|
6
6
|
const packageRoot = path.join(__dirname, "..", "..");
|
|
7
7
|
const homeDir = require("os").homedir();
|
|
8
8
|
|
|
9
|
-
const {
|
|
9
|
+
const {
|
|
10
|
+
resolveConsumerTargetDir,
|
|
11
|
+
isConsumerInstall,
|
|
12
|
+
deployXrayConfig,
|
|
13
|
+
} = require("./install-bridges.cjs");
|
|
10
14
|
let targetDir = resolveConsumerTargetDir(packageRoot, process.env.PWD || process.cwd());
|
|
11
15
|
|
|
12
16
|
const resolvedPackage = path.resolve(packageRoot);
|
|
@@ -155,8 +159,13 @@ if (fs.existsSync(distSource)) {
|
|
|
155
159
|
}
|
|
156
160
|
|
|
157
161
|
// 6. Convert MCP paths in consumer opencode.json
|
|
158
|
-
const isConsumer =
|
|
159
|
-
|
|
162
|
+
const isConsumer = isConsumerInstall(packageRoot, targetDir);
|
|
163
|
+
const consumerPkgName = isConsumer
|
|
164
|
+
? ["0xray", "xray"].find((name) =>
|
|
165
|
+
fs.existsSync(path.join(targetDir, "node_modules", name, "package.json"))
|
|
166
|
+
)
|
|
167
|
+
: null;
|
|
168
|
+
if (!hasHermes && isConsumer && consumerPkgName) {
|
|
160
169
|
const mainOpencodePath = path.join(targetDir, "opencode.json");
|
|
161
170
|
if (fs.existsSync(mainOpencodePath)) {
|
|
162
171
|
try {
|
|
@@ -167,13 +176,13 @@ if (!hasHermes && isConsumer) {
|
|
|
167
176
|
if (server.command && typeof server.command === "string") {
|
|
168
177
|
const normalized = server.command.replace(
|
|
169
178
|
/^[.]{0,2}\/dist\/mcps\//,
|
|
170
|
-
|
|
179
|
+
`node_modules/${consumerPkgName}/dist/mcps/`
|
|
171
180
|
);
|
|
172
181
|
if (normalized !== server.command) { server.command = normalized; modified = true; }
|
|
173
182
|
}
|
|
174
183
|
if (Array.isArray(server.command)) {
|
|
175
184
|
server.command = server.command.map(a =>
|
|
176
|
-
a.replace(/^[.]{0,2}\/dist\/mcps\//,
|
|
185
|
+
a.replace(/^[.]{0,2}\/dist\/mcps\//, `node_modules/${consumerPkgName}/dist/mcps/`)
|
|
177
186
|
);
|
|
178
187
|
modified = true;
|
|
179
188
|
}
|
|
@@ -210,29 +219,15 @@ if (fs.existsSync(hermesSkillSource)) {
|
|
|
210
219
|
} catch (e) { console.warn(`⚠️ Hermes skill: ${e.message}`); }
|
|
211
220
|
}
|
|
212
221
|
|
|
213
|
-
// 8. Deploy .xray/ config files (codex.json, features.json, config.json)
|
|
214
|
-
|
|
215
|
-
const xrayTargetDir = path.join(targetDir, ".xray");
|
|
216
|
-
const CONFIG_FILES = ["codex.json", "features.json", "config.json"];
|
|
217
|
-
|
|
218
|
-
if (fs.existsSync(xraySourceDir) && resolvedPackage !== resolvedTarget) {
|
|
222
|
+
// 8. Deploy .xray/ config files (codex.json, features.json, features.schema.json, config.json)
|
|
223
|
+
if (resolvedPackage !== resolvedTarget) {
|
|
219
224
|
try {
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
for (const file of CONFIG_FILES) {
|
|
223
|
-
const src = path.join(xraySourceDir, file);
|
|
224
|
-
const dst = path.join(xrayTargetDir, file);
|
|
225
|
-
if (!fs.existsSync(src)) continue;
|
|
226
|
-
const shouldCopy = !fs.existsSync(dst) ||
|
|
227
|
-
fs.statSync(src).mtime > fs.statSync(dst).mtime;
|
|
228
|
-
if (shouldCopy) {
|
|
229
|
-
fs.copyFileSync(src, dst);
|
|
230
|
-
copied++;
|
|
231
|
-
}
|
|
232
|
-
}
|
|
233
|
-
if (copied > 0) console.log(`✅ .xray/: ${copied} config files deployed`);
|
|
225
|
+
const deployed = deployXrayConfig(targetDir, packageRoot, () => {});
|
|
226
|
+
if (deployed > 0) console.log(`✅ .xray/: ${deployed} config files deployed`);
|
|
234
227
|
else console.log("ℹ️ .xray/: up to date");
|
|
235
|
-
} catch (e) {
|
|
228
|
+
} catch (e) {
|
|
229
|
+
console.warn(`⚠️ .xray/ deploy: ${e.message}`);
|
|
230
|
+
}
|
|
236
231
|
}
|
|
237
232
|
|
|
238
233
|
console.log("\n✅ xray setup complete.\n");
|