@pikaa-ai/pikaa 0.1.9 → 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 +103 -39
- package/package.json +1 -3
- package/bin/pikaa-linux-x64 +0 -0
- package/scripts/postinstall.js +0 -89
package/bin/pikaa.js
CHANGED
|
@@ -1,17 +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
|
-
*
|
|
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.
|
|
9
12
|
*/
|
|
10
13
|
|
|
11
14
|
import { spawnSync } from "node:child_process";
|
|
12
|
-
import { existsSync, chmodSync } from "node:fs";
|
|
15
|
+
import { existsSync, chmodSync, mkdirSync, createWriteStream, readFileSync } from "node:fs";
|
|
13
16
|
import { fileURLToPath } from "node:url";
|
|
14
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";
|
|
15
21
|
|
|
16
22
|
const __filename = fileURLToPath(import.meta.url);
|
|
17
23
|
const __dirname = dirname(__filename);
|
|
@@ -27,47 +33,105 @@ function getBinaryName() {
|
|
|
27
33
|
return null;
|
|
28
34
|
}
|
|
29
35
|
|
|
30
|
-
// --- 1. Native binary (postinstall should have placed it here) ---
|
|
31
36
|
const binaryName = getBinaryName();
|
|
32
|
-
|
|
33
|
-
|
|
37
|
+
const userBinDir = join(homedir(), ".pikaa", "bin");
|
|
38
|
+
const userBinaryPath = binaryName ? join(userBinDir, binaryName) : null;
|
|
39
|
+
|
|
40
|
+
// Look in package directory or user cache directory
|
|
41
|
+
function findExistingBinary() {
|
|
42
|
+
if (!binaryName) return null;
|
|
43
|
+
const candidates = [
|
|
34
44
|
join(rootDir, "bin", binaryName),
|
|
35
45
|
join(rootDir, "dist", "bin", binaryName),
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
46
|
+
userBinaryPath,
|
|
47
|
+
];
|
|
48
|
+
for (const c of candidates) {
|
|
49
|
+
if (c && existsSync(c)) return c;
|
|
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;
|
|
40
64
|
}
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
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
|
+
});
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
function launchBinary(binPath) {
|
|
76
|
+
if (platform !== "win32") {
|
|
77
|
+
try { chmodSync(binPath, 0o755); } catch {}
|
|
44
78
|
}
|
|
79
|
+
const r = spawnSync(binPath, process.argv.slice(2), {
|
|
80
|
+
stdio: "inherit",
|
|
81
|
+
env: process.env,
|
|
82
|
+
});
|
|
83
|
+
process.exit(r.status ?? (r.error ? 1 : 0));
|
|
45
84
|
}
|
|
46
85
|
|
|
47
|
-
|
|
48
|
-
const
|
|
49
|
-
if (
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
});
|
|
56
|
-
process.exit(
|
|
86
|
+
async function main() {
|
|
87
|
+
const existing = findExistingBinary();
|
|
88
|
+
if (existing) {
|
|
89
|
+
launchBinary(existing);
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
if (!binaryName || !userBinaryPath) {
|
|
94
|
+
console.error(`[pikaa] Platform not supported: ${platform}/${arch}`);
|
|
95
|
+
process.exit(1);
|
|
96
|
+
}
|
|
97
|
+
|
|
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);
|
|
57
134
|
}
|
|
58
135
|
}
|
|
59
136
|
|
|
60
|
-
|
|
61
|
-
console.error([
|
|
62
|
-
"",
|
|
63
|
-
" pikaa could not start.",
|
|
64
|
-
" The precompiled binary may have failed to download during install.",
|
|
65
|
-
"",
|
|
66
|
-
" Try reinstalling:",
|
|
67
|
-
" npm install -g @pikaa-ai/pikaa",
|
|
68
|
-
"",
|
|
69
|
-
" Or install Bun as a fallback runtime:",
|
|
70
|
-
" curl -fsSL https://bun.sh/install | bash",
|
|
71
|
-
"",
|
|
72
|
-
].join("\n"));
|
|
73
|
-
process.exit(1);
|
|
137
|
+
main();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pikaa-ai/pikaa",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "PIKAA CLI - AI coding agent that runs locally in your terminal.",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"module": "./dist/index.js",
|
|
@@ -13,7 +13,6 @@
|
|
|
13
13
|
"files": [
|
|
14
14
|
"dist",
|
|
15
15
|
"bin",
|
|
16
|
-
"scripts/postinstall.js",
|
|
17
16
|
"README.md",
|
|
18
17
|
"LICENSE"
|
|
19
18
|
],
|
|
@@ -25,7 +24,6 @@
|
|
|
25
24
|
"build:exe": "bun build ./src/cli/index.ts --compile --outfile pikaa.exe",
|
|
26
25
|
"build:binaries": "bun run scripts/build-binaries.ts",
|
|
27
26
|
"build": "bun run build:js && bun run build:exe",
|
|
28
|
-
"postinstall": "node scripts/postinstall.js",
|
|
29
27
|
"prepublishOnly": "bun run build:js"
|
|
30
28
|
},
|
|
31
29
|
"keywords": [
|
package/bin/pikaa-linux-x64
DELETED
|
File without changes
|
package/scripts/postinstall.js
DELETED
|
@@ -1,89 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Postinstall: downloads the correct precompiled pikaa binary from GitHub Releases.
|
|
5
|
-
* Runs automatically after `npm install -g @pikaa-ai/pikaa`.
|
|
6
|
-
* Uses only Node.js built-ins — no Bun required.
|
|
7
|
-
*/
|
|
8
|
-
|
|
9
|
-
import { createWriteStream, chmodSync, existsSync, mkdirSync } from "node:fs";
|
|
10
|
-
import { fileURLToPath } from "node:url";
|
|
11
|
-
import { dirname, join } from "node:path";
|
|
12
|
-
import { pipeline } from "node:stream/promises";
|
|
13
|
-
import https from "node:https";
|
|
14
|
-
|
|
15
|
-
const __filename = fileURLToPath(import.meta.url);
|
|
16
|
-
const __dirname = dirname(__filename);
|
|
17
|
-
const rootDir = join(__dirname, "..");
|
|
18
|
-
|
|
19
|
-
const pkg = JSON.parse(
|
|
20
|
-
await import("node:fs").then((fs) =>
|
|
21
|
-
fs.readFileSync(join(rootDir, "package.json"), "utf8")
|
|
22
|
-
)
|
|
23
|
-
);
|
|
24
|
-
const version = pkg.version;
|
|
25
|
-
const REPO = "Neural-Forge-AMD/agent-cli";
|
|
26
|
-
|
|
27
|
-
function getBinaryName() {
|
|
28
|
-
const platform = process.platform;
|
|
29
|
-
const arch = process.arch;
|
|
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";
|
|
33
|
-
return null;
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
const binaryName = getBinaryName();
|
|
37
|
-
|
|
38
|
-
if (!binaryName) {
|
|
39
|
-
console.warn(`[pikaa] Unsupported platform: ${process.platform}/${process.arch}. Fallback to bun required.`);
|
|
40
|
-
process.exit(0);
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
const binDir = join(rootDir, "bin");
|
|
44
|
-
const destPath = join(binDir, binaryName);
|
|
45
|
-
|
|
46
|
-
if (existsSync(destPath)) {
|
|
47
|
-
// Already downloaded (e.g. cached by npm)
|
|
48
|
-
process.exit(0);
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
mkdirSync(binDir, { recursive: true });
|
|
52
|
-
|
|
53
|
-
const url = `https://github.com/${REPO}/releases/download/v${version}/${binaryName}`;
|
|
54
|
-
|
|
55
|
-
console.log(`[pikaa] Downloading binary for ${process.platform}/${process.arch}...`);
|
|
56
|
-
console.log(`[pikaa] ${url}`);
|
|
57
|
-
|
|
58
|
-
async function download(downloadUrl, dest, redirects = 0) {
|
|
59
|
-
if (redirects > 5) throw new Error("Too many redirects");
|
|
60
|
-
|
|
61
|
-
await new Promise((resolve, reject) => {
|
|
62
|
-
const file = createWriteStream(dest);
|
|
63
|
-
https.get(downloadUrl, { headers: { "User-Agent": "pikaa-postinstall" } }, (res) => {
|
|
64
|
-
if (res.statusCode === 301 || res.statusCode === 302) {
|
|
65
|
-
file.close();
|
|
66
|
-
resolve(download(res.headers.location, dest, redirects + 1));
|
|
67
|
-
return;
|
|
68
|
-
}
|
|
69
|
-
if (res.statusCode !== 200) {
|
|
70
|
-
file.close();
|
|
71
|
-
reject(new Error(`HTTP ${res.statusCode} from ${downloadUrl}`));
|
|
72
|
-
return;
|
|
73
|
-
}
|
|
74
|
-
pipeline(res, file).then(resolve).catch(reject);
|
|
75
|
-
}).on("error", reject);
|
|
76
|
-
});
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
try {
|
|
80
|
-
await download(url, destPath);
|
|
81
|
-
if (process.platform !== "win32") {
|
|
82
|
-
chmodSync(destPath, 0o755);
|
|
83
|
-
}
|
|
84
|
-
console.log(`[pikaa] ✓ Binary installed: ${destPath}`);
|
|
85
|
-
} catch (err) {
|
|
86
|
-
// Non-fatal: user can still run via bun if installed
|
|
87
|
-
console.warn(`[pikaa] Warning: could not download binary (${err.message})`);
|
|
88
|
-
console.warn(`[pikaa] You can install Bun as a fallback: https://bun.sh/install`);
|
|
89
|
-
}
|