forgemax 0.1.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.
- package/install.js +173 -0
- package/package.json +42 -0
package/install.js
ADDED
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
"use strict";
|
|
4
|
+
|
|
5
|
+
const https = require("https");
|
|
6
|
+
const http = require("http");
|
|
7
|
+
const fs = require("fs");
|
|
8
|
+
const path = require("path");
|
|
9
|
+
const { execSync } = require("child_process");
|
|
10
|
+
const os = require("os");
|
|
11
|
+
const zlib = require("zlib");
|
|
12
|
+
|
|
13
|
+
const PACKAGE = require("./package.json");
|
|
14
|
+
const VERSION = PACKAGE.version;
|
|
15
|
+
const REPO = "postrv/forgemax";
|
|
16
|
+
const BIN_DIR = path.join(__dirname, "bin");
|
|
17
|
+
|
|
18
|
+
// Platform → release archive mapping
|
|
19
|
+
const PLATFORM_MAP = {
|
|
20
|
+
"darwin-x64": "macos-x86_64",
|
|
21
|
+
"darwin-arm64": "macos-aarch64",
|
|
22
|
+
"linux-x64": "linux-x86_64",
|
|
23
|
+
"win32-x64": "windows-x86_64",
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
function getPlatformKey() {
|
|
27
|
+
const platform = os.platform();
|
|
28
|
+
const arch = os.arch();
|
|
29
|
+
return `${platform}-${arch}`;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function getDownloadUrl(platformKey) {
|
|
33
|
+
const suffix = PLATFORM_MAP[platformKey];
|
|
34
|
+
if (!suffix) {
|
|
35
|
+
throw new Error(
|
|
36
|
+
`Unsupported platform: ${platformKey}. ` +
|
|
37
|
+
`Supported: ${Object.keys(PLATFORM_MAP).join(", ")}`
|
|
38
|
+
);
|
|
39
|
+
}
|
|
40
|
+
const ext = platformKey.startsWith("win32") ? "zip" : "tar.gz";
|
|
41
|
+
return `https://github.com/${REPO}/releases/download/v${VERSION}/forgemax-v${VERSION}-${suffix}.${ext}`;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function fetch(url) {
|
|
45
|
+
return new Promise((resolve, reject) => {
|
|
46
|
+
const client = url.startsWith("https") ? https : http;
|
|
47
|
+
client
|
|
48
|
+
.get(url, { headers: { "User-Agent": "forgemax-npm-installer" } }, (res) => {
|
|
49
|
+
// Follow redirects
|
|
50
|
+
if (res.statusCode >= 300 && res.statusCode < 400 && res.headers.location) {
|
|
51
|
+
return fetch(res.headers.location).then(resolve, reject);
|
|
52
|
+
}
|
|
53
|
+
if (res.statusCode !== 200) {
|
|
54
|
+
reject(new Error(`HTTP ${res.statusCode} for ${url}`));
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
const chunks = [];
|
|
58
|
+
res.on("data", (chunk) => chunks.push(chunk));
|
|
59
|
+
res.on("end", () => resolve(Buffer.concat(chunks)));
|
|
60
|
+
res.on("error", reject);
|
|
61
|
+
})
|
|
62
|
+
.on("error", reject);
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
function extractTarGz(buffer, destDir) {
|
|
67
|
+
// Use tar command for extraction (available on macOS/Linux)
|
|
68
|
+
const tmpFile = path.join(os.tmpdir(), `forgemax-${Date.now()}.tar.gz`);
|
|
69
|
+
fs.writeFileSync(tmpFile, buffer);
|
|
70
|
+
try {
|
|
71
|
+
execSync(`tar xzf "${tmpFile}" -C "${destDir}"`, { stdio: "pipe" });
|
|
72
|
+
} finally {
|
|
73
|
+
fs.unlinkSync(tmpFile);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
function extractZip(buffer, destDir) {
|
|
78
|
+
const tmpFile = path.join(os.tmpdir(), `forgemax-${Date.now()}.zip`);
|
|
79
|
+
fs.writeFileSync(tmpFile, buffer);
|
|
80
|
+
try {
|
|
81
|
+
if (os.platform() === "win32") {
|
|
82
|
+
execSync(
|
|
83
|
+
`powershell -Command "Expand-Archive -Path '${tmpFile}' -DestinationPath '${destDir}' -Force"`,
|
|
84
|
+
{ stdio: "pipe" }
|
|
85
|
+
);
|
|
86
|
+
} else {
|
|
87
|
+
execSync(`unzip -o "${tmpFile}" -d "${destDir}"`, { stdio: "pipe" });
|
|
88
|
+
}
|
|
89
|
+
} finally {
|
|
90
|
+
fs.unlinkSync(tmpFile);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
async function install() {
|
|
95
|
+
const platformKey = getPlatformKey();
|
|
96
|
+
const url = getDownloadUrl(platformKey);
|
|
97
|
+
const isWindows = platformKey.startsWith("win32");
|
|
98
|
+
|
|
99
|
+
console.log(`Installing forgemax v${VERSION} for ${platformKey}...`);
|
|
100
|
+
console.log(`Downloading from ${url}`);
|
|
101
|
+
|
|
102
|
+
const buffer = await fetch(url);
|
|
103
|
+
|
|
104
|
+
// Ensure bin directory exists
|
|
105
|
+
fs.mkdirSync(BIN_DIR, { recursive: true });
|
|
106
|
+
|
|
107
|
+
// Extract archive
|
|
108
|
+
if (isWindows) {
|
|
109
|
+
extractZip(buffer, BIN_DIR);
|
|
110
|
+
} else {
|
|
111
|
+
extractTarGz(buffer, BIN_DIR);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
// Set executable permissions on Unix
|
|
115
|
+
if (!isWindows) {
|
|
116
|
+
const binaries = ["forgemax", "forgemax-worker"];
|
|
117
|
+
for (const bin of binaries) {
|
|
118
|
+
const binPath = path.join(BIN_DIR, bin);
|
|
119
|
+
if (fs.existsSync(binPath)) {
|
|
120
|
+
fs.chmodSync(binPath, 0o755);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
// Verify installation
|
|
126
|
+
const binaryName = isWindows ? "forgemax.exe" : "forgemax";
|
|
127
|
+
const binaryPath = path.join(BIN_DIR, binaryName);
|
|
128
|
+
|
|
129
|
+
if (!fs.existsSync(binaryPath)) {
|
|
130
|
+
throw new Error(`Binary not found after extraction: ${binaryPath}`);
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
try {
|
|
134
|
+
const version = execSync(`"${binaryPath}" --version`, {
|
|
135
|
+
encoding: "utf-8",
|
|
136
|
+
timeout: 10000,
|
|
137
|
+
}).trim();
|
|
138
|
+
console.log(`Installed: ${version}`);
|
|
139
|
+
} catch {
|
|
140
|
+
console.log("Installed forgemax (version check skipped)");
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
// Verify worker binary
|
|
144
|
+
const workerName = isWindows ? "forgemax-worker.exe" : "forgemax-worker";
|
|
145
|
+
const workerPath = path.join(BIN_DIR, workerName);
|
|
146
|
+
if (fs.existsSync(workerPath)) {
|
|
147
|
+
console.log(`Worker binary: ${workerPath}`);
|
|
148
|
+
} else {
|
|
149
|
+
console.warn("Warning: forgemax-worker not found in archive");
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
console.log(`
|
|
153
|
+
Quick start:
|
|
154
|
+
1. Copy forge.toml.example to forge.toml and configure your tokens
|
|
155
|
+
2. Add to your MCP client config:
|
|
156
|
+
{
|
|
157
|
+
"mcpServers": {
|
|
158
|
+
"forgemax": {
|
|
159
|
+
"command": "forgemax",
|
|
160
|
+
"args": []
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
`);
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
install().catch((err) => {
|
|
168
|
+
console.error(`Failed to install forgemax: ${err.message}`);
|
|
169
|
+
console.error(
|
|
170
|
+
"\nFallback: install from source with `cargo install forge-cli`"
|
|
171
|
+
);
|
|
172
|
+
process.exit(1);
|
|
173
|
+
});
|
package/package.json
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "forgemax",
|
|
3
|
+
"version": "0.1.1",
|
|
4
|
+
"description": "Code Mode MCP Gateway — collapses N servers x M tools into 2 tools",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"mcp",
|
|
7
|
+
"model-context-protocol",
|
|
8
|
+
"gateway",
|
|
9
|
+
"ai",
|
|
10
|
+
"claude",
|
|
11
|
+
"code-mode"
|
|
12
|
+
],
|
|
13
|
+
"author": "postrv",
|
|
14
|
+
"license": "FSL-1.1-ALv2",
|
|
15
|
+
"repository": {
|
|
16
|
+
"type": "git",
|
|
17
|
+
"url": "git+https://github.com/postrv/forgemax.git"
|
|
18
|
+
},
|
|
19
|
+
"bin": {
|
|
20
|
+
"forgemax": "bin/forgemax"
|
|
21
|
+
},
|
|
22
|
+
"scripts": {
|
|
23
|
+
"postinstall": "node install.js"
|
|
24
|
+
},
|
|
25
|
+
"files": [
|
|
26
|
+
"install.js",
|
|
27
|
+
"bin/",
|
|
28
|
+
"README.md"
|
|
29
|
+
],
|
|
30
|
+
"engines": {
|
|
31
|
+
"node": ">=16.0.0"
|
|
32
|
+
},
|
|
33
|
+
"os": [
|
|
34
|
+
"darwin",
|
|
35
|
+
"linux",
|
|
36
|
+
"win32"
|
|
37
|
+
],
|
|
38
|
+
"cpu": [
|
|
39
|
+
"x64",
|
|
40
|
+
"arm64"
|
|
41
|
+
]
|
|
42
|
+
}
|