@rikipurpur/puru-ai 1.3.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/README.md +41 -0
- package/bin/puru.js +16 -0
- package/package.json +34 -0
- package/scripts/binary.js +44 -0
- package/scripts/install.js +81 -0
package/README.md
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# @rikipurpur/puru-ai (npm)
|
|
2
|
+
|
|
3
|
+
CLI resmi PURU-AI — **tanpa web server** secara default.
|
|
4
|
+
Binary Go di-download otomatis dari GitHub Releases saat install.
|
|
5
|
+
|
|
6
|
+
```bash
|
|
7
|
+
npm i -g @rikipurpur/puru-ai
|
|
8
|
+
puru setup # wizard → tulis ~/.puru/config.json
|
|
9
|
+
puru gateway # jalankan bot Telegram (long-polling, tanpa /health)
|
|
10
|
+
puru gateway --health --port 8080 # opt-in health check (Docker/VPS)
|
|
11
|
+
puru chat "halo" # debug lokal tanpa Telegram
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
Non-interaktif (CI):
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
TELEGRAM_BOT_TOKEN=x PURU_BASE_URL=... PURU_API_KEY=... PURU_MODEL=puru \
|
|
18
|
+
puru setup --force
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
Env installer: `PURU_AI_VERSION` (default = versi package), `PURU_AI_REPO`
|
|
22
|
+
(default `purujawa06-bot/PURU-AI`), `PURU_AI_BINARY` (pakai binary lokal),
|
|
23
|
+
`PURU_AI_SKIP_DOWNLOAD=1` (skip download).
|
|
24
|
+
|
|
25
|
+
## Termux (Android)
|
|
26
|
+
|
|
27
|
+
HP 64-bit (umum) pakai binary `puru-linux-arm64`, HP 32-bit pakai
|
|
28
|
+
`puru-linux-arm` (armv7) — installer otomatis pilih yang benar.
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
pkg install nodejs
|
|
32
|
+
npm i -g @rikipurpur/puru-ai
|
|
33
|
+
puru setup
|
|
34
|
+
puru gateway
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
Tips: jalankan di bawah `termux-wake-lock` agar bot tidak mati saat layar
|
|
38
|
+
mati. Tanpa Node pun bisa — download binary langsung dari
|
|
39
|
+
[Releases](https://github.com/purujawa06-bot/PURU-AI/releases)
|
|
40
|
+
(`puru-linux-arm64` atau `puru-linux-arm`), `chmod +x`, lalu
|
|
41
|
+
`./puru-linux-arm64 setup`.
|
package/bin/puru.js
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
'use strict';
|
|
3
|
+
// Thin launcher: forward all args to the downloaded Go binary.
|
|
4
|
+
const { spawnSync } = require('child_process');
|
|
5
|
+
const fs = require('fs');
|
|
6
|
+
const { binaryPath } = require('../scripts/binary');
|
|
7
|
+
|
|
8
|
+
const bin = binaryPath();
|
|
9
|
+
if (!fs.existsSync(bin)) {
|
|
10
|
+
console.error(`[puru-ai] binary tidak ditemukan: ${bin}`);
|
|
11
|
+
console.error('[puru-ai] Jalankan `npm rebuild -g @rikipurpur/puru-ai` atau reinstall.');
|
|
12
|
+
console.error('[puru-ai] Alternatif: set PURU_AI_BINARY=/path/ke/puru');
|
|
13
|
+
process.exit(1);
|
|
14
|
+
}
|
|
15
|
+
const res = spawnSync(bin, process.argv.slice(2), { stdio: 'inherit' });
|
|
16
|
+
process.exit(res.status == null ? 1 : res.status);
|
package/package.json
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@rikipurpur/puru-ai",
|
|
3
|
+
"version": "1.3.0",
|
|
4
|
+
"description": "PURU-AI CLI — setup & gateway Telegram bot tanpa web server. Binary Go dibungkus npm.",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"author": "Ricky",
|
|
7
|
+
"homepage": "https://github.com/purujawa06-bot/PURU-AI",
|
|
8
|
+
"repository": {
|
|
9
|
+
"type": "git",
|
|
10
|
+
"url": "git+https://github.com/purujawa06-bot/PURU-AI.git"
|
|
11
|
+
},
|
|
12
|
+
"keywords": [
|
|
13
|
+
"telegram",
|
|
14
|
+
"ai",
|
|
15
|
+
"bot",
|
|
16
|
+
"cli",
|
|
17
|
+
"gateway"
|
|
18
|
+
],
|
|
19
|
+
"engines": {
|
|
20
|
+
"node": ">=18"
|
|
21
|
+
},
|
|
22
|
+
"bin": {
|
|
23
|
+
"puru": "bin/puru.js"
|
|
24
|
+
},
|
|
25
|
+
"scripts": {
|
|
26
|
+
"postinstall": "node scripts/install.js"
|
|
27
|
+
},
|
|
28
|
+
"files": [
|
|
29
|
+
"bin/",
|
|
30
|
+
"scripts/install.js",
|
|
31
|
+
"scripts/binary.js",
|
|
32
|
+
"README.md"
|
|
33
|
+
]
|
|
34
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
// Shared helper: resolve platform/arch + vendor binary path.
|
|
3
|
+
const path = require('path');
|
|
4
|
+
const os = require('os');
|
|
5
|
+
|
|
6
|
+
function mapOS(platform = process.platform) {
|
|
7
|
+
if (platform === 'win32') return 'windows';
|
|
8
|
+
if (platform === 'darwin') return 'darwin';
|
|
9
|
+
// Termux di Android lapor 'linux' — binary linux statik (CGO_ENABLED=0) jalan langsung.
|
|
10
|
+
if (platform === 'linux' || platform === 'android') return 'linux';
|
|
11
|
+
throw new Error(`OS tidak didukung: ${platform} (didukung: linux, darwin, windows)`);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
function mapArch(arch = process.arch) {
|
|
15
|
+
if (arch === 'x64') return 'amd64';
|
|
16
|
+
if (arch === 'arm64') return 'arm64';
|
|
17
|
+
// HP Android 32-bit (armv7) — Termux lapor 'arm'.
|
|
18
|
+
if (arch === 'arm') return 'arm';
|
|
19
|
+
throw new Error(`Arch tidak didukung: ${arch} (didukung: x64, arm64, arm)`);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function assetName(goos, goarch) {
|
|
23
|
+
const base = `puru-${goos}-${goarch}`;
|
|
24
|
+
return goos === 'windows' ? `${base}.exe` : base;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function binaryPath() {
|
|
28
|
+
if (process.env.PURU_AI_BINARY) return process.env.PURU_AI_BINARY;
|
|
29
|
+
const goos = mapOS();
|
|
30
|
+
const goarch = mapArch();
|
|
31
|
+
const bin = assetName(goos, goarch);
|
|
32
|
+
// Vendor dir lives next to this file: scripts/vendor/<bin>
|
|
33
|
+
return path.join(__dirname, 'vendor', bin);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function downloadURL({ repo, tag, goos, goarch }) {
|
|
37
|
+
return `https://github.com/${repo}/releases/download/${tag}/${assetName(goos, goarch)}`;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function cacheDir() {
|
|
41
|
+
return process.env.PURU_AI_CACHE || path.join(os.homedir(), '.puru', 'bin');
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
module.exports = { mapOS, mapArch, assetName, binaryPath, downloadURL, cacheDir };
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
// postinstall: download prebuilt `puru` Go binary from GitHub Releases.
|
|
3
|
+
// Env override:
|
|
4
|
+
// PURU_AI_VERSION=v1.2.3 | 1.2.3 (default: version di package.json)
|
|
5
|
+
// PURU_AI_REPO=owner/repo (default: purujawa06-bot/PURU-AI)
|
|
6
|
+
// PURU_AI_SKIP_DOWNLOAD=1 (skip, untuk CI/offline)
|
|
7
|
+
const fs = require('fs');
|
|
8
|
+
const path = require('path');
|
|
9
|
+
const https = require('https');
|
|
10
|
+
const { mapOS, mapArch, assetName, binaryPath, downloadURL } = require('./binary');
|
|
11
|
+
|
|
12
|
+
function pkgVersion() {
|
|
13
|
+
const pkg = JSON.parse(fs.readFileSync(path.join(__dirname, '..', 'package.json'), 'utf8'));
|
|
14
|
+
return pkg.version;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
function resolveTag() {
|
|
18
|
+
const v = (process.env.PURU_AI_VERSION || pkgVersion()).trim();
|
|
19
|
+
return v.startsWith('v') ? v : `v${v}`;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function fetch(url, dest, redirects = 5) {
|
|
23
|
+
return new Promise((resolve, reject) => {
|
|
24
|
+
https.get(url, { headers: { 'User-Agent': 'puru-ai-npm-install' } }, (res) => {
|
|
25
|
+
if (res.statusCode >= 300 && res.statusCode < 400 && res.headers.location) {
|
|
26
|
+
if (redirects === 0) return reject(new Error('Terlalu banyak redirect'));
|
|
27
|
+
res.resume();
|
|
28
|
+
const next = res.headers.location.startsWith('http')
|
|
29
|
+
? res.headers.location
|
|
30
|
+
: new URL(res.headers.location, url).toString();
|
|
31
|
+
return fetch(next, dest, redirects - 1).then(resolve, reject);
|
|
32
|
+
}
|
|
33
|
+
if (res.statusCode !== 200) {
|
|
34
|
+
res.resume();
|
|
35
|
+
return reject(new Error(`Download gagal HTTP ${res.statusCode}: ${url}`));
|
|
36
|
+
}
|
|
37
|
+
const out = fs.createWriteStream(dest, { mode: 0o755 });
|
|
38
|
+
res.pipe(out);
|
|
39
|
+
out.on('finish', () => out.close(() => resolve()));
|
|
40
|
+
out.on('error', reject);
|
|
41
|
+
}).on('error', reject);
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
async function main() {
|
|
46
|
+
if (process.env.PURU_AI_SKIP_DOWNLOAD === '1') {
|
|
47
|
+
console.log('[puru-ai] skip download (PURU_AI_SKIP_DOWNLOAD=1)');
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
const repo = process.env.PURU_AI_REPO || 'purujawa06-bot/PURU-AI';
|
|
51
|
+
const tag = resolveTag();
|
|
52
|
+
const goos = mapOS();
|
|
53
|
+
const goarch = mapArch();
|
|
54
|
+
const url = downloadURL({ repo, tag, goos, goarch });
|
|
55
|
+
const dest = binaryPath();
|
|
56
|
+
fs.mkdirSync(path.dirname(dest), { recursive: true });
|
|
57
|
+
console.log(`[puru-ai] download ${assetName(goos, goarch)} ${tag} dari ${repo}...`);
|
|
58
|
+
try {
|
|
59
|
+
await fetch(url, dest);
|
|
60
|
+
} catch (err) {
|
|
61
|
+
try { fs.unlinkSync(dest); } catch (_) {}
|
|
62
|
+
console.error(`[puru-ai] GAGAL: ${err.message}`);
|
|
63
|
+
console.error(`[puru-ai] Cek release ada di https://github.com/${repo}/releases/tag/${tag}`);
|
|
64
|
+
console.error(`[puru-ai] Atau set PURU_AI_BINARY=/path/ke/puru lalu install ulang.`);
|
|
65
|
+
throw err;
|
|
66
|
+
}
|
|
67
|
+
if (goos !== 'windows') {
|
|
68
|
+
try { fs.chmodSync(dest, 0o755); } catch (_) {}
|
|
69
|
+
}
|
|
70
|
+
console.log(`[puru-ai] OK: ${dest}`);
|
|
71
|
+
console.log('[puru-ai] Lanjut: puru setup → puru gateway');
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
if (require.main === module) {
|
|
75
|
+
main().catch((e) => {
|
|
76
|
+
console.error(e.message || e);
|
|
77
|
+
process.exit(1);
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
module.exports = { resolveTag, fetch };
|