atlascloud-cli 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/README.md +27 -0
- package/bin/atlas-mcp.js +2 -0
- package/bin/atlas.js +2 -0
- package/bin/run.js +56 -0
- package/install.js +162 -0
- package/package.json +37 -0
package/README.md
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# @atlascloud/cli
|
|
2
|
+
|
|
3
|
+
AtlasCloud CLI — call LLM, image, and video models from your terminal.
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install -g @atlascloud/cli
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
The postinstall step downloads the prebuilt `atlas` and `atlas-mcp` binaries for your platform from the public GitHub release and verifies the archive against `checksums.txt`.
|
|
12
|
+
|
|
13
|
+
Supported npm platforms: macOS and Linux on x64 or arm64. Windows package-manager support will be added separately.
|
|
14
|
+
|
|
15
|
+
## Usage
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
atlas auth login
|
|
19
|
+
atlas chat "explain UUID v7"
|
|
20
|
+
atlas generate image google/nano-banana-2/text-to-image -p "a cat"
|
|
21
|
+
atlas --help
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## Links
|
|
25
|
+
|
|
26
|
+
- Releases: https://github.com/AtlasCloudAI/cli/releases
|
|
27
|
+
- AtlasCloud: https://atlascloud.ai
|
package/bin/atlas-mcp.js
ADDED
package/bin/atlas.js
ADDED
package/bin/run.js
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
const fs = require("fs");
|
|
2
|
+
const path = require("path");
|
|
3
|
+
const { spawn } = require("child_process");
|
|
4
|
+
|
|
5
|
+
function detectPackageManager() {
|
|
6
|
+
const ua = process.env.npm_config_user_agent || "";
|
|
7
|
+
if (ua.startsWith("pnpm/")) return "pnpm";
|
|
8
|
+
if (ua.startsWith("yarn/")) return "yarn";
|
|
9
|
+
if (ua.startsWith("bun/")) return "bun";
|
|
10
|
+
if (ua.startsWith("npm/")) return "npm";
|
|
11
|
+
return "";
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
function readInstallMetadata(vendorDir) {
|
|
15
|
+
const metadataPath = path.join(vendorDir, "install.json");
|
|
16
|
+
if (!fs.existsSync(metadataPath)) {
|
|
17
|
+
return {};
|
|
18
|
+
}
|
|
19
|
+
return JSON.parse(fs.readFileSync(metadataPath, "utf8"));
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
module.exports = function run(binaryName) {
|
|
23
|
+
const vendorDir = path.join(__dirname, "..", "vendor");
|
|
24
|
+
const bin = path.join(vendorDir, binaryName);
|
|
25
|
+
|
|
26
|
+
if (!fs.existsSync(bin)) {
|
|
27
|
+
console.error(
|
|
28
|
+
`@atlascloud/cli: binary not found at ${bin}. Reinstall: npm i -g @atlascloud/cli`
|
|
29
|
+
);
|
|
30
|
+
process.exit(1);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const metadata = readInstallMetadata(vendorDir);
|
|
34
|
+
const child = spawn(bin, process.argv.slice(2), {
|
|
35
|
+
stdio: "inherit",
|
|
36
|
+
env: {
|
|
37
|
+
...process.env,
|
|
38
|
+
ATLAS_INSTALL_METHOD: "npm",
|
|
39
|
+
ATLAS_PACKAGE_MANAGER:
|
|
40
|
+
metadata.package_manager || detectPackageManager() || "npm"
|
|
41
|
+
}
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
child.on("exit", (code, signal) => {
|
|
45
|
+
if (signal) {
|
|
46
|
+
process.kill(process.pid, signal);
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
process.exit(code == null ? 0 : code);
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
child.on("error", (err) => {
|
|
53
|
+
console.error("@atlascloud/cli: failed to exec:", err.message);
|
|
54
|
+
process.exit(1);
|
|
55
|
+
});
|
|
56
|
+
};
|
package/install.js
ADDED
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
const crypto = require("crypto");
|
|
3
|
+
const fs = require("fs");
|
|
4
|
+
const https = require("https");
|
|
5
|
+
const path = require("path");
|
|
6
|
+
const { execFileSync } = require("child_process");
|
|
7
|
+
|
|
8
|
+
const pkg = require("./package.json");
|
|
9
|
+
|
|
10
|
+
const REPO = process.env.ATLAS_RELEASE_REPO || "AtlasCloudAI/cli";
|
|
11
|
+
const VERSION = process.env.ATLAS_CLI_VERSION || pkg.version;
|
|
12
|
+
|
|
13
|
+
const PLATFORM_MAP = {
|
|
14
|
+
darwin: "darwin",
|
|
15
|
+
linux: "linux"
|
|
16
|
+
};
|
|
17
|
+
const ARCH_MAP = {
|
|
18
|
+
x64: "amd64",
|
|
19
|
+
arm64: "arm64"
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
const platform = PLATFORM_MAP[process.platform];
|
|
23
|
+
const arch = ARCH_MAP[process.arch];
|
|
24
|
+
|
|
25
|
+
if (!platform || !arch) {
|
|
26
|
+
console.error(
|
|
27
|
+
`@atlascloud/cli: unsupported platform ${process.platform}/${process.arch}`
|
|
28
|
+
);
|
|
29
|
+
console.error("Supported: darwin|linux x x64|arm64");
|
|
30
|
+
process.exit(1);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
if (VERSION === "0.0.0") {
|
|
34
|
+
console.error(
|
|
35
|
+
"@atlascloud/cli: package version is 0.0.0; publish with the release tag version"
|
|
36
|
+
);
|
|
37
|
+
process.exit(1);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
const tag = `v${VERSION}`;
|
|
41
|
+
const archiveName = `cli_${VERSION}_${platform}_${arch}.tar.gz`;
|
|
42
|
+
const releaseBase = `https://github.com/${REPO}/releases/download/${tag}`;
|
|
43
|
+
const archiveURL = `${releaseBase}/${archiveName}`;
|
|
44
|
+
const checksumsURL = `${releaseBase}/checksums.txt`;
|
|
45
|
+
|
|
46
|
+
const vendorDir = path.join(__dirname, "vendor");
|
|
47
|
+
const archivePath = path.join(vendorDir, archiveName);
|
|
48
|
+
const checksumsPath = path.join(vendorDir, "checksums.txt");
|
|
49
|
+
const metadataPath = path.join(vendorDir, "install.json");
|
|
50
|
+
|
|
51
|
+
function detectPackageManager() {
|
|
52
|
+
const ua = process.env.npm_config_user_agent || "";
|
|
53
|
+
if (ua.startsWith("pnpm/")) return "pnpm";
|
|
54
|
+
if (ua.startsWith("yarn/")) return "yarn";
|
|
55
|
+
if (ua.startsWith("bun/")) return "bun";
|
|
56
|
+
if (ua.startsWith("npm/")) return "npm";
|
|
57
|
+
return "npm";
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
function download(url, dest, redirects = 0) {
|
|
61
|
+
return new Promise((resolve, reject) => {
|
|
62
|
+
if (redirects > 5) {
|
|
63
|
+
reject(new Error("too many redirects"));
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
const file = fs.createWriteStream(dest);
|
|
68
|
+
https
|
|
69
|
+
.get(url, (res) => {
|
|
70
|
+
if (res.statusCode >= 300 && res.statusCode < 400 && res.headers.location) {
|
|
71
|
+
file.close(() => {
|
|
72
|
+
fs.rmSync(dest, { force: true });
|
|
73
|
+
download(res.headers.location, dest, redirects + 1)
|
|
74
|
+
.then(resolve)
|
|
75
|
+
.catch(reject);
|
|
76
|
+
});
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
if (res.statusCode !== 200) {
|
|
81
|
+
file.close(() => {
|
|
82
|
+
fs.rmSync(dest, { force: true });
|
|
83
|
+
reject(new Error(`HTTP ${res.statusCode} for ${url}`));
|
|
84
|
+
});
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
res.pipe(file);
|
|
89
|
+
file.on("finish", () => file.close(resolve));
|
|
90
|
+
})
|
|
91
|
+
.on("error", (err) => {
|
|
92
|
+
file.close(() => {
|
|
93
|
+
fs.rmSync(dest, { force: true });
|
|
94
|
+
reject(err);
|
|
95
|
+
});
|
|
96
|
+
});
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
function expectedChecksum(checksumsText, fileName) {
|
|
101
|
+
const line = checksumsText
|
|
102
|
+
.split(/\r?\n/)
|
|
103
|
+
.find((entry) => entry.trim().split(/\s+/).slice(-1)[0] === fileName);
|
|
104
|
+
|
|
105
|
+
if (!line) {
|
|
106
|
+
throw new Error(`checksum for ${fileName} not found`);
|
|
107
|
+
}
|
|
108
|
+
return line.trim().split(/\s+/)[0];
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
function actualChecksum(filePath) {
|
|
112
|
+
return crypto
|
|
113
|
+
.createHash("sha256")
|
|
114
|
+
.update(fs.readFileSync(filePath))
|
|
115
|
+
.digest("hex");
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
function verifyChecksum() {
|
|
119
|
+
const expected = expectedChecksum(fs.readFileSync(checksumsPath, "utf8"), archiveName);
|
|
120
|
+
const actual = actualChecksum(archivePath);
|
|
121
|
+
if (actual !== expected) {
|
|
122
|
+
throw new Error(
|
|
123
|
+
`checksum mismatch for ${archiveName}: expected ${expected}, got ${actual}`
|
|
124
|
+
);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
(async () => {
|
|
129
|
+
fs.mkdirSync(vendorDir, { recursive: true });
|
|
130
|
+
|
|
131
|
+
console.log(`@atlascloud/cli: downloading ${archiveURL}`);
|
|
132
|
+
await download(archiveURL, archivePath);
|
|
133
|
+
await download(checksumsURL, checksumsPath);
|
|
134
|
+
verifyChecksum();
|
|
135
|
+
|
|
136
|
+
execFileSync("tar", ["-xzf", archivePath, "-C", vendorDir], {
|
|
137
|
+
stdio: "inherit"
|
|
138
|
+
});
|
|
139
|
+
fs.chmodSync(path.join(vendorDir, "atlas"), 0o755);
|
|
140
|
+
fs.chmodSync(path.join(vendorDir, "atlas-mcp"), 0o755);
|
|
141
|
+
|
|
142
|
+
fs.writeFileSync(
|
|
143
|
+
metadataPath,
|
|
144
|
+
JSON.stringify(
|
|
145
|
+
{
|
|
146
|
+
install_method: "npm",
|
|
147
|
+
package_manager: detectPackageManager(),
|
|
148
|
+
package_name: pkg.name,
|
|
149
|
+
release_repo: REPO,
|
|
150
|
+
version: VERSION
|
|
151
|
+
},
|
|
152
|
+
null,
|
|
153
|
+
2
|
|
154
|
+
) + "\n"
|
|
155
|
+
);
|
|
156
|
+
fs.rmSync(archivePath, { force: true });
|
|
157
|
+
fs.rmSync(checksumsPath, { force: true });
|
|
158
|
+
console.log("@atlascloud/cli: installed atlas and atlas-mcp");
|
|
159
|
+
})().catch((err) => {
|
|
160
|
+
console.error("@atlascloud/cli: install failed:", err.message);
|
|
161
|
+
process.exit(1);
|
|
162
|
+
});
|
package/package.json
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "atlascloud-cli",
|
|
3
|
+
"version": "0.1.1",
|
|
4
|
+
"description": "AtlasCloud CLI — call LLM, image, and video models from your terminal.",
|
|
5
|
+
"bin": {
|
|
6
|
+
"atlas": "bin/atlas.js",
|
|
7
|
+
"atlas-mcp": "bin/atlas-mcp.js"
|
|
8
|
+
},
|
|
9
|
+
"scripts": {
|
|
10
|
+
"postinstall": "node install.js"
|
|
11
|
+
},
|
|
12
|
+
"files": [
|
|
13
|
+
"bin/",
|
|
14
|
+
"install.js",
|
|
15
|
+
"README.md"
|
|
16
|
+
],
|
|
17
|
+
"engines": {
|
|
18
|
+
"node": ">=14"
|
|
19
|
+
},
|
|
20
|
+
"os": [
|
|
21
|
+
"darwin",
|
|
22
|
+
"linux"
|
|
23
|
+
],
|
|
24
|
+
"cpu": [
|
|
25
|
+
"x64",
|
|
26
|
+
"arm64"
|
|
27
|
+
],
|
|
28
|
+
"license": "MIT",
|
|
29
|
+
"homepage": "https://atlascloud.ai",
|
|
30
|
+
"repository": {
|
|
31
|
+
"type": "git",
|
|
32
|
+
"url": "git+https://github.com/AtlasCloudAI/cli.git"
|
|
33
|
+
},
|
|
34
|
+
"publishConfig": {
|
|
35
|
+
"access": "public"
|
|
36
|
+
}
|
|
37
|
+
}
|