@hona/ralph-cli 0.1.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/bin/ralph +134 -0
- package/package.json +29 -0
- package/postinstall.mjs +145 -0
package/bin/ralph
ADDED
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Ralph CLI Launcher
|
|
4
|
+
*
|
|
5
|
+
* This is a thin JavaScript wrapper that finds and executes the correct
|
|
6
|
+
* platform-specific binary for the current OS/architecture.
|
|
7
|
+
*
|
|
8
|
+
* The binary is located in one of the optional dependency packages:
|
|
9
|
+
* - ralph-opencode-darwin-arm64
|
|
10
|
+
* - ralph-opencode-darwin-x64
|
|
11
|
+
* - ralph-opencode-linux-arm64
|
|
12
|
+
* - ralph-opencode-linux-x64
|
|
13
|
+
* - ralph-opencode-windows-x64
|
|
14
|
+
*
|
|
15
|
+
* Environment variables:
|
|
16
|
+
* RALPH_BIN_PATH - Override path to the ralph binary
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
const childProcess = require("child_process");
|
|
20
|
+
const fs = require("fs");
|
|
21
|
+
const path = require("path");
|
|
22
|
+
const os = require("os");
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Run the binary with inherited stdio
|
|
26
|
+
*/
|
|
27
|
+
function run(target) {
|
|
28
|
+
const result = childProcess.spawnSync(target, process.argv.slice(2), {
|
|
29
|
+
stdio: "inherit",
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
if (result.error) {
|
|
33
|
+
console.error(result.error.message);
|
|
34
|
+
process.exit(1);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const code = typeof result.status === "number" ? result.status : 0;
|
|
38
|
+
process.exit(code);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// Check for environment variable override
|
|
42
|
+
const envPath = process.env.RALPH_BIN_PATH;
|
|
43
|
+
if (envPath) {
|
|
44
|
+
run(envPath);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// Get the real path of this script (resolves symlinks)
|
|
48
|
+
const scriptPath = fs.realpathSync(__filename);
|
|
49
|
+
const scriptDir = path.dirname(scriptPath);
|
|
50
|
+
|
|
51
|
+
// Map OS and architecture to package naming conventions
|
|
52
|
+
const platformMap = {
|
|
53
|
+
darwin: "darwin",
|
|
54
|
+
linux: "linux",
|
|
55
|
+
win32: "windows",
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
const archMap = {
|
|
59
|
+
x64: "x64",
|
|
60
|
+
arm64: "arm64",
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
let platform = platformMap[os.platform()];
|
|
64
|
+
if (!platform) {
|
|
65
|
+
platform = os.platform();
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
let arch = archMap[os.arch()];
|
|
69
|
+
if (!arch) {
|
|
70
|
+
arch = os.arch();
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// Construct package and binary names
|
|
74
|
+
const packageBase = "@hona/ralph-cli-" + platform + "-" + arch;
|
|
75
|
+
const binaryName = platform === "windows" ? "ralph.exe" : "ralph";
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Search for the binary in node_modules hierarchy
|
|
79
|
+
*/
|
|
80
|
+
function findBinary(startDir) {
|
|
81
|
+
let current = startDir;
|
|
82
|
+
|
|
83
|
+
for (;;) {
|
|
84
|
+
const modules = path.join(current, "node_modules");
|
|
85
|
+
|
|
86
|
+
if (fs.existsSync(modules)) {
|
|
87
|
+
const entries = fs.readdirSync(modules);
|
|
88
|
+
|
|
89
|
+
for (const entry of entries) {
|
|
90
|
+
// Match package name (could have version suffix in some package managers)
|
|
91
|
+
if (!entry.startsWith(packageBase)) {
|
|
92
|
+
continue;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
const candidate = path.join(modules, entry, "bin", binaryName);
|
|
96
|
+
if (fs.existsSync(candidate)) {
|
|
97
|
+
return candidate;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// Move up to parent directory
|
|
103
|
+
const parent = path.dirname(current);
|
|
104
|
+
if (parent === current) {
|
|
105
|
+
// Reached filesystem root
|
|
106
|
+
return;
|
|
107
|
+
}
|
|
108
|
+
current = parent;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
// Try to find the binary
|
|
113
|
+
const resolved = findBinary(scriptDir);
|
|
114
|
+
|
|
115
|
+
if (!resolved) {
|
|
116
|
+
console.error(
|
|
117
|
+
"Error: Could not find the ralph binary for your platform.\n\n" +
|
|
118
|
+
"It seems that your package manager failed to install the correct version\n" +
|
|
119
|
+
"of the ralph CLI for your platform (" +
|
|
120
|
+
platform +
|
|
121
|
+
"-" +
|
|
122
|
+
arch +
|
|
123
|
+
").\n\n" +
|
|
124
|
+
'You can try manually installing the "' +
|
|
125
|
+
packageBase +
|
|
126
|
+
'" package:\n\n' +
|
|
127
|
+
" npm install " +
|
|
128
|
+
packageBase +
|
|
129
|
+
"\n"
|
|
130
|
+
);
|
|
131
|
+
process.exit(1);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
run(resolved);
|
package/package.json
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@hona/ralph-cli",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Ralph - AI coding assistant CLI",
|
|
5
|
+
"bin": {
|
|
6
|
+
"ralph": "./bin/ralph"
|
|
7
|
+
},
|
|
8
|
+
"scripts": {
|
|
9
|
+
"postinstall": "node ./postinstall.mjs"
|
|
10
|
+
},
|
|
11
|
+
"optionalDependencies": {
|
|
12
|
+
"@hona/ralph-cli-darwin-arm64": "0.1.0",
|
|
13
|
+
"@hona/ralph-cli-darwin-x64": "0.1.0",
|
|
14
|
+
"@hona/ralph-cli-linux-arm64": "0.1.0",
|
|
15
|
+
"@hona/ralph-cli-linux-x64": "0.1.0",
|
|
16
|
+
"@hona/ralph-cli-windows-x64": "0.1.0"
|
|
17
|
+
},
|
|
18
|
+
"repository": {
|
|
19
|
+
"type": "git",
|
|
20
|
+
"url": "git+https://github.com/hona/opencode-ralph.git"
|
|
21
|
+
},
|
|
22
|
+
"keywords": [
|
|
23
|
+
"cli",
|
|
24
|
+
"ai",
|
|
25
|
+
"coding",
|
|
26
|
+
"assistant"
|
|
27
|
+
],
|
|
28
|
+
"license": "MIT"
|
|
29
|
+
}
|
package/postinstall.mjs
ADDED
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Postinstall script for ralph-opencode
|
|
4
|
+
*
|
|
5
|
+
* This script runs after `npm install ralph-opencode` and symlinks the
|
|
6
|
+
* platform-specific binary to the bin directory.
|
|
7
|
+
*
|
|
8
|
+
* On Windows, npm handles the .exe directly so we skip symlinking.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import fs from "fs";
|
|
12
|
+
import path from "path";
|
|
13
|
+
import os from "os";
|
|
14
|
+
import { fileURLToPath } from "url";
|
|
15
|
+
import { createRequire } from "module";
|
|
16
|
+
|
|
17
|
+
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
18
|
+
const require = createRequire(import.meta.url);
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Detect the current platform and architecture
|
|
22
|
+
*/
|
|
23
|
+
function detectPlatformAndArch() {
|
|
24
|
+
let platform;
|
|
25
|
+
switch (os.platform()) {
|
|
26
|
+
case "darwin":
|
|
27
|
+
platform = "darwin";
|
|
28
|
+
break;
|
|
29
|
+
case "linux":
|
|
30
|
+
platform = "linux";
|
|
31
|
+
break;
|
|
32
|
+
case "win32":
|
|
33
|
+
platform = "windows";
|
|
34
|
+
break;
|
|
35
|
+
default:
|
|
36
|
+
platform = os.platform();
|
|
37
|
+
break;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
let arch;
|
|
41
|
+
switch (os.arch()) {
|
|
42
|
+
case "x64":
|
|
43
|
+
arch = "x64";
|
|
44
|
+
break;
|
|
45
|
+
case "arm64":
|
|
46
|
+
arch = "arm64";
|
|
47
|
+
break;
|
|
48
|
+
default:
|
|
49
|
+
arch = os.arch();
|
|
50
|
+
break;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
return { platform, arch };
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Find the platform-specific binary package
|
|
58
|
+
*/
|
|
59
|
+
function findBinary() {
|
|
60
|
+
const { platform, arch } = detectPlatformAndArch();
|
|
61
|
+
const packageName = `@hona/ralph-cli-${platform}-${arch}`;
|
|
62
|
+
const binaryName = platform === "windows" ? "ralph.exe" : "ralph";
|
|
63
|
+
|
|
64
|
+
try {
|
|
65
|
+
// Use require.resolve to find the package
|
|
66
|
+
const packageJsonPath = require.resolve(`${packageName}/package.json`);
|
|
67
|
+
const packageDir = path.dirname(packageJsonPath);
|
|
68
|
+
const binaryPath = path.join(packageDir, "bin", binaryName);
|
|
69
|
+
|
|
70
|
+
if (!fs.existsSync(binaryPath)) {
|
|
71
|
+
throw new Error(`Binary not found at ${binaryPath}`);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
return { binaryPath, binaryName, packageName };
|
|
75
|
+
} catch (error) {
|
|
76
|
+
throw new Error(`Could not find package ${packageName}: ${error.message}`);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Prepare the bin directory and return paths
|
|
82
|
+
*/
|
|
83
|
+
function prepareBinDirectory(binaryName) {
|
|
84
|
+
const binDir = path.join(__dirname, "bin");
|
|
85
|
+
const targetPath = path.join(binDir, binaryName);
|
|
86
|
+
|
|
87
|
+
// Ensure bin directory exists
|
|
88
|
+
if (!fs.existsSync(binDir)) {
|
|
89
|
+
fs.mkdirSync(binDir, { recursive: true });
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// Remove existing binary/symlink if it exists
|
|
93
|
+
if (fs.existsSync(targetPath)) {
|
|
94
|
+
fs.unlinkSync(targetPath);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
return { binDir, targetPath };
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* Create symlink to the platform binary
|
|
102
|
+
*/
|
|
103
|
+
function symlinkBinary(sourcePath, binaryName) {
|
|
104
|
+
const { targetPath } = prepareBinDirectory(binaryName);
|
|
105
|
+
|
|
106
|
+
fs.symlinkSync(sourcePath, targetPath);
|
|
107
|
+
console.log(`ralph binary symlinked: ${targetPath} -> ${sourcePath}`);
|
|
108
|
+
|
|
109
|
+
// Verify the file exists after operation
|
|
110
|
+
if (!fs.existsSync(targetPath)) {
|
|
111
|
+
throw new Error(`Failed to symlink binary to ${targetPath}`);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* Main function
|
|
117
|
+
*/
|
|
118
|
+
async function main() {
|
|
119
|
+
try {
|
|
120
|
+
// On Windows, npm handles the .exe directly via the bin field
|
|
121
|
+
// No postinstall symlinking needed
|
|
122
|
+
if (os.platform() === "win32") {
|
|
123
|
+
console.log(
|
|
124
|
+
"Windows detected: binary setup not needed (using packaged .exe)"
|
|
125
|
+
);
|
|
126
|
+
return;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
const { binaryPath, binaryName, packageName } = findBinary();
|
|
130
|
+
console.log(`Found ${packageName} at ${binaryPath}`);
|
|
131
|
+
symlinkBinary(binaryPath, binaryName);
|
|
132
|
+
} catch (error) {
|
|
133
|
+
console.error("Failed to setup ralph binary:", error.message);
|
|
134
|
+
// Don't fail the install - the JS launcher will handle finding the binary
|
|
135
|
+
process.exit(0);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
try {
|
|
140
|
+
main();
|
|
141
|
+
} catch (error) {
|
|
142
|
+
console.error("Postinstall script error:", error.message);
|
|
143
|
+
// Exit gracefully - don't break npm install
|
|
144
|
+
process.exit(0);
|
|
145
|
+
}
|