@pikaa-ai/pikaa 0.1.8 → 0.2.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/pikaa.js +98 -68
- package/package.json +1 -1
package/bin/pikaa.js
CHANGED
|
@@ -1,18 +1,23 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
|
-
* Universal
|
|
4
|
+
* Universal Native Launcher for Pikaa Agent CLI.
|
|
5
5
|
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
6
|
+
* Automatically detects platform (macOS, Linux, Windows) and architecture (arm64, x64).
|
|
7
|
+
* If the native binary is already present, runs it with 0ms startup time.
|
|
8
|
+
* If not present (e.g. postinstall script skipped by npm allow-scripts), automatically
|
|
9
|
+
* downloads the native binary from GitHub Releases to ~/.pikaa/bin/ and executes it.
|
|
10
|
+
*
|
|
11
|
+
* Zero external dependencies required. Does NOT require Bun or compilation tools.
|
|
10
12
|
*/
|
|
11
13
|
|
|
12
14
|
import { spawnSync } from "node:child_process";
|
|
13
|
-
import { existsSync, chmodSync } from "node:fs";
|
|
15
|
+
import { existsSync, chmodSync, mkdirSync, createWriteStream, readFileSync } from "node:fs";
|
|
14
16
|
import { fileURLToPath } from "node:url";
|
|
15
17
|
import { dirname, join } from "node:path";
|
|
18
|
+
import { homedir } from "node:os";
|
|
19
|
+
import { pipeline } from "node:stream/promises";
|
|
20
|
+
import https from "node:https";
|
|
16
21
|
|
|
17
22
|
const __filename = fileURLToPath(import.meta.url);
|
|
18
23
|
const __dirname = dirname(__filename);
|
|
@@ -21,87 +26,112 @@ const rootDir = join(__dirname, "..");
|
|
|
21
26
|
const platform = process.platform;
|
|
22
27
|
const arch = process.arch;
|
|
23
28
|
|
|
24
|
-
// Map OS & Arch to precompiled binary filename
|
|
25
29
|
function getBinaryName() {
|
|
26
|
-
if (platform === "win32")
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
if (platform === "darwin") {
|
|
30
|
-
return arch === "arm64" ? "pikaa-darwin-arm64" : "pikaa-darwin-x64";
|
|
31
|
-
}
|
|
32
|
-
if (platform === "linux") {
|
|
33
|
-
return arch === "arm64" ? "pikaa-linux-arm64" : "pikaa-linux-x64";
|
|
34
|
-
}
|
|
30
|
+
if (platform === "win32") return arch === "arm64" ? "pikaa-windows-arm64.exe" : "pikaa-windows-x64.exe";
|
|
31
|
+
if (platform === "darwin") return arch === "arm64" ? "pikaa-darwin-arm64" : "pikaa-darwin-x64";
|
|
32
|
+
if (platform === "linux") return arch === "arm64" ? "pikaa-linux-arm64" : "pikaa-linux-x64";
|
|
35
33
|
return null;
|
|
36
34
|
}
|
|
37
35
|
|
|
38
|
-
// --- 1. Try native binary ---
|
|
39
36
|
const binaryName = getBinaryName();
|
|
40
|
-
|
|
37
|
+
const userBinDir = join(homedir(), ".pikaa", "bin");
|
|
38
|
+
const userBinaryPath = binaryName ? join(userBinDir, binaryName) : null;
|
|
41
39
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
40
|
+
// Look in package directory or user cache directory
|
|
41
|
+
function findExistingBinary() {
|
|
42
|
+
if (!binaryName) return null;
|
|
43
|
+
const candidates = [
|
|
45
44
|
join(rootDir, "bin", binaryName),
|
|
46
|
-
join(rootDir, binaryName),
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
}
|
|
45
|
+
join(rootDir, "dist", "bin", binaryName),
|
|
46
|
+
userBinaryPath,
|
|
47
|
+
];
|
|
48
|
+
for (const c of candidates) {
|
|
49
|
+
if (c && existsSync(c)) return c;
|
|
52
50
|
}
|
|
51
|
+
return null;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
async function downloadBinary(url, dest, redirects = 0) {
|
|
55
|
+
if (redirects > 5) throw new Error("Too many redirects");
|
|
56
|
+
|
|
57
|
+
await new Promise((resolve, reject) => {
|
|
58
|
+
const file = createWriteStream(dest);
|
|
59
|
+
https.get(url, { headers: { "User-Agent": "pikaa-cli-launcher" } }, (res) => {
|
|
60
|
+
if (res.statusCode === 301 || res.statusCode === 302) {
|
|
61
|
+
file.close();
|
|
62
|
+
resolve(downloadBinary(res.headers.location, dest, redirects + 1));
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
if (res.statusCode !== 200) {
|
|
66
|
+
file.close();
|
|
67
|
+
reject(new Error(`HTTP ${res.statusCode} from ${url}`));
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
pipeline(res, file).then(resolve).catch(reject);
|
|
71
|
+
}).on("error", reject);
|
|
72
|
+
});
|
|
53
73
|
}
|
|
54
74
|
|
|
55
|
-
|
|
75
|
+
function launchBinary(binPath) {
|
|
56
76
|
if (platform !== "win32") {
|
|
57
|
-
try { chmodSync(
|
|
77
|
+
try { chmodSync(binPath, 0o755); } catch {}
|
|
58
78
|
}
|
|
59
|
-
const
|
|
79
|
+
const r = spawnSync(binPath, process.argv.slice(2), {
|
|
60
80
|
stdio: "inherit",
|
|
61
81
|
env: process.env,
|
|
62
82
|
});
|
|
63
|
-
process.exit(
|
|
83
|
+
process.exit(r.status ?? (r.error ? 1 : 0));
|
|
64
84
|
}
|
|
65
85
|
|
|
66
|
-
|
|
67
|
-
const
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
}
|
|
86
|
+
async function main() {
|
|
87
|
+
const existing = findExistingBinary();
|
|
88
|
+
if (existing) {
|
|
89
|
+
launchBinary(existing);
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
73
92
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
: ["bun"];
|
|
78
|
-
|
|
79
|
-
let bunBin = null;
|
|
80
|
-
for (const candidate of bunCandidates) {
|
|
81
|
-
const probe = spawnSync(candidate, ["--version"], { encoding: "utf8" });
|
|
82
|
-
if (!probe.error) {
|
|
83
|
-
bunBin = candidate;
|
|
84
|
-
break;
|
|
93
|
+
if (!binaryName || !userBinaryPath) {
|
|
94
|
+
console.error(`[pikaa] Platform not supported: ${platform}/${arch}`);
|
|
95
|
+
process.exit(1);
|
|
85
96
|
}
|
|
86
|
-
}
|
|
87
97
|
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
98
|
+
// Auto-download binary on first run
|
|
99
|
+
let version = "0.2.0";
|
|
100
|
+
try {
|
|
101
|
+
const pkg = JSON.parse(readFileSync(join(rootDir, "package.json"), "utf8"));
|
|
102
|
+
version = pkg.version;
|
|
103
|
+
} catch {}
|
|
104
|
+
|
|
105
|
+
const downloadUrl = `https://github.com/Neural-Forge-AMD/agent-cli/releases/download/v${version}/${binaryName}`;
|
|
106
|
+
|
|
107
|
+
try {
|
|
108
|
+
mkdirSync(userBinDir, { recursive: true });
|
|
109
|
+
process.stderr.write(`\x1b[36m⚡ [pikaa] First-time setup: Downloading native binary for ${platform}/${arch}...\x1b[0m\n`);
|
|
110
|
+
await downloadBinary(downloadUrl, userBinaryPath);
|
|
111
|
+
if (platform !== "win32") {
|
|
112
|
+
chmodSync(userBinaryPath, 0o755);
|
|
113
|
+
}
|
|
114
|
+
process.stderr.write(`\x1b[32m✓ Setup complete!\x1b[0m\n\n`);
|
|
115
|
+
launchBinary(userBinaryPath);
|
|
116
|
+
} catch (err) {
|
|
117
|
+
process.stderr.write(`\x1b[33mWarning: Failed to download native binary: ${err.message}\x1b[0m\n`);
|
|
118
|
+
|
|
119
|
+
// Try bun fallback if available
|
|
120
|
+
const jsEntry = join(rootDir, "dist", "cli.js");
|
|
121
|
+
if (existsSync(jsEntry)) {
|
|
122
|
+
const probe = spawnSync("bun", ["--version"], { encoding: "utf8" });
|
|
123
|
+
if (!probe.error) {
|
|
124
|
+
const r = spawnSync("bun", ["run", jsEntry, ...process.argv.slice(2)], {
|
|
125
|
+
stdio: "inherit",
|
|
126
|
+
env: process.env,
|
|
127
|
+
});
|
|
128
|
+
process.exit(r.status ?? (r.error ? 1 : 0));
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
console.error(`\nPlease check your internet connection or install Bun (https://bun.sh) and retry.`);
|
|
133
|
+
process.exit(1);
|
|
134
|
+
}
|
|
101
135
|
}
|
|
102
136
|
|
|
103
|
-
|
|
104
|
-
stdio: "inherit",
|
|
105
|
-
env: process.env,
|
|
106
|
-
});
|
|
107
|
-
process.exit(result.status ?? (result.error ? 1 : 0));
|
|
137
|
+
main();
|