@kocoro/shanclaw 0.0.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/bin/shan +3 -0
- package/install.js +103 -0
- package/package.json +33 -0
package/bin/shan
ADDED
package/install.js
ADDED
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
const { execFileSync } = require("child_process");
|
|
2
|
+
const fs = require("fs");
|
|
3
|
+
const path = require("path");
|
|
4
|
+
const https = require("https");
|
|
5
|
+
const crypto = require("crypto");
|
|
6
|
+
|
|
7
|
+
const REPO = "Kocoro-lab/ShanClaw";
|
|
8
|
+
const BIN_DIR = path.join(__dirname, "bin");
|
|
9
|
+
|
|
10
|
+
function getPlatform() {
|
|
11
|
+
const p = process.platform;
|
|
12
|
+
if (p !== "darwin" && p !== "linux") {
|
|
13
|
+
throw new Error("Unsupported platform: " + p + ". shan supports macOS and Linux.");
|
|
14
|
+
}
|
|
15
|
+
return p;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
function getArch() {
|
|
19
|
+
const map = { x64: "amd64", arm64: "arm64" };
|
|
20
|
+
const a = map[process.arch];
|
|
21
|
+
if (!a) {
|
|
22
|
+
throw new Error("Unsupported architecture: " + process.arch);
|
|
23
|
+
}
|
|
24
|
+
return a;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function fetch(url) {
|
|
28
|
+
return new Promise((resolve, reject) => {
|
|
29
|
+
https.get(url, { headers: { "User-Agent": "shan-cli-npm" } }, (res) => {
|
|
30
|
+
if (res.statusCode >= 300 && res.statusCode < 400 && res.headers.location) {
|
|
31
|
+
return fetch(res.headers.location).then(resolve, reject);
|
|
32
|
+
}
|
|
33
|
+
if (res.statusCode !== 200) {
|
|
34
|
+
return reject(new Error("HTTP " + res.statusCode + " for " + url));
|
|
35
|
+
}
|
|
36
|
+
const chunks = [];
|
|
37
|
+
res.on("data", (c) => chunks.push(c));
|
|
38
|
+
res.on("end", () => resolve(Buffer.concat(chunks)));
|
|
39
|
+
res.on("error", reject);
|
|
40
|
+
}).on("error", reject);
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
async function main() {
|
|
45
|
+
const platform = getPlatform();
|
|
46
|
+
const arch = getArch();
|
|
47
|
+
console.log("shan: detecting platform " + platform + "/" + arch);
|
|
48
|
+
|
|
49
|
+
// Get latest release
|
|
50
|
+
const releaseData = await fetch(
|
|
51
|
+
"https://api.github.com/repos/" + REPO + "/releases/latest"
|
|
52
|
+
);
|
|
53
|
+
const release = JSON.parse(releaseData.toString());
|
|
54
|
+
const version = release.tag_name.replace(/^v/, "");
|
|
55
|
+
console.log("shan: installing v" + version + "...");
|
|
56
|
+
|
|
57
|
+
const filename = "shan_" + version + "_" + platform + "_" + arch + ".tar.gz";
|
|
58
|
+
const asset = release.assets.find((a) => a.name === filename);
|
|
59
|
+
if (!asset) {
|
|
60
|
+
throw new Error("No release asset found for " + filename);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// Download binary
|
|
64
|
+
const tarball = await fetch(asset.browser_download_url);
|
|
65
|
+
|
|
66
|
+
// Verify checksum
|
|
67
|
+
const checksumAsset = release.assets.find((a) => a.name === "checksums.txt");
|
|
68
|
+
if (checksumAsset) {
|
|
69
|
+
const checksumData = await fetch(checksumAsset.browser_download_url);
|
|
70
|
+
const line = checksumData.toString().split("\n").find((l) => l.includes(filename));
|
|
71
|
+
if (line) {
|
|
72
|
+
const expected = line.split(/\s+/)[0];
|
|
73
|
+
const actual = crypto.createHash("sha256").update(tarball).digest("hex");
|
|
74
|
+
if (actual !== expected) {
|
|
75
|
+
throw new Error("Checksum mismatch for " + filename);
|
|
76
|
+
}
|
|
77
|
+
console.log("shan: checksum verified");
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// Extract with system tar
|
|
82
|
+
fs.mkdirSync(BIN_DIR, { recursive: true });
|
|
83
|
+
const tmpTar = path.join(BIN_DIR, "_shan.tar.gz");
|
|
84
|
+
fs.writeFileSync(tmpTar, tarball);
|
|
85
|
+
try {
|
|
86
|
+
execFileSync("tar", ["-xzf", "_shan.tar.gz", "shan"], { cwd: BIN_DIR });
|
|
87
|
+
// ax_server is only present in darwin archives — not an error on linux
|
|
88
|
+
try {
|
|
89
|
+
execFileSync("tar", ["-xzf", "_shan.tar.gz", "ax_server"], { cwd: BIN_DIR });
|
|
90
|
+
fs.chmodSync(path.join(BIN_DIR, "ax_server"), 0o755);
|
|
91
|
+
} catch (_) {}
|
|
92
|
+
} finally {
|
|
93
|
+
fs.unlinkSync(tmpTar);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
fs.chmodSync(path.join(BIN_DIR, "shan"), 0o755);
|
|
97
|
+
console.log("shan: v" + version + " installed successfully");
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
main().catch((err) => {
|
|
101
|
+
console.error("shan install failed: " + err.message);
|
|
102
|
+
process.exit(1);
|
|
103
|
+
});
|
package/package.json
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@kocoro/shanclaw",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"description": "AI-powered CLI agent with local tools, permissions, and session management",
|
|
5
|
+
"bin": {
|
|
6
|
+
"shan": "bin/shan"
|
|
7
|
+
},
|
|
8
|
+
"scripts": {
|
|
9
|
+
"postinstall": "node install.js"
|
|
10
|
+
},
|
|
11
|
+
"os": [
|
|
12
|
+
"darwin",
|
|
13
|
+
"linux"
|
|
14
|
+
],
|
|
15
|
+
"cpu": [
|
|
16
|
+
"x64",
|
|
17
|
+
"arm64"
|
|
18
|
+
],
|
|
19
|
+
"repository": {
|
|
20
|
+
"type": "git",
|
|
21
|
+
"url": "https://github.com/Kocoro-lab/ShanClaw"
|
|
22
|
+
},
|
|
23
|
+
"homepage": "https://github.com/Kocoro-lab/ShanClaw",
|
|
24
|
+
"keywords": [
|
|
25
|
+
"cli",
|
|
26
|
+
"ai",
|
|
27
|
+
"agent",
|
|
28
|
+
"shannon",
|
|
29
|
+
"llm"
|
|
30
|
+
],
|
|
31
|
+
"license": "Apache-2.0",
|
|
32
|
+
"author": "Kocoro-lab"
|
|
33
|
+
}
|