anveesa 0.2.0 → 0.2.2

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.
@@ -0,0 +1,68 @@
1
+ name: Release Binaries
2
+
3
+ on:
4
+ push:
5
+ tags:
6
+ - 'v*'
7
+
8
+ permissions:
9
+ contents: write
10
+
11
+ jobs:
12
+ build:
13
+ strategy:
14
+ matrix:
15
+ include:
16
+ - os: ubuntu-latest
17
+ target: x86_64-unknown-linux-gnu
18
+ - os: ubuntu-latest
19
+ target: aarch64-unknown-linux-gnu
20
+ - os: macos-latest
21
+ target: x86_64-apple-darwin
22
+ - os: macos-latest
23
+ target: aarch64-apple-darwin
24
+ - os: windows-latest
25
+ target: x86_64-pc-windows-msvc
26
+
27
+ runs-on: ${{ matrix.os }}
28
+
29
+ steps:
30
+ - uses: actions/checkout@v4
31
+
32
+ - name: Install Rust
33
+ uses: dtolnay/rust-action@stable
34
+ with:
35
+ targets: ${{ matrix.target }}
36
+
37
+ - name: Install cross-compilation tools (Linux ARM64)
38
+ if: matrix.target == 'aarch64-unknown-linux-gnu'
39
+ run: |
40
+ sudo apt-get update
41
+ sudo apt-get install -y gcc-aarch64-linux-gnu
42
+ echo 'CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER=aarch64-linux-gnu-gcc' >> $GITHUB_ENV
43
+
44
+ - name: Build
45
+ run: cargo build --release --target ${{ matrix.target }}
46
+
47
+ - name: Package binary
48
+ shell: bash
49
+ run: |
50
+ VERSION=${GITHUB_REF_NAME#v}
51
+ BIN_DIR=release-artifacts
52
+ mkdir -p $BIN_DIR
53
+
54
+ if [[ "${{ matrix.os }}" == "windows-latest" ]]; then
55
+ cp target/${{ matrix.target }}/release/anveesa.exe $BIN_DIR/anveesa.exe
56
+ cd $BIN_DIR && tar czf ../anveesa-$VERSION-${{ matrix.target }}.tar.gz anveesa.exe
57
+ else
58
+ cp target/${{ matrix.target }}/release/anveesa $BIN_DIR/anveesa
59
+ chmod +x $BIN_DIR/anveesa
60
+ cd $BIN_DIR && tar czf ../anveesa-$VERSION-${{ matrix.target }}.tar.gz anveesa
61
+ fi
62
+
63
+ - name: Upload to Release
64
+ uses: softprops/action-gh-release@v2
65
+ with:
66
+ files: anveesa-*.tar.gz
67
+ env:
68
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
package/bin/anveesa ADDED
Binary file
package/bin/anveesa.js CHANGED
@@ -1,37 +1,24 @@
1
1
  #!/usr/bin/env node
2
2
 
3
- const { execFile } = require('child_process');
3
+ const { spawn } = require('child_process');
4
4
  const path = require('path');
5
5
  const fs = require('fs');
6
6
 
7
- // Cari binary di beberapa kemungkinan lokasi
8
7
  function findBinary() {
9
- const candidates = [
10
- // Installed via npm (global) - binary di samping script
11
- path.join(__dirname, 'target', 'release', 'anveesa'),
12
- path.join(__dirname, 'target', 'debug', 'anveesa'),
13
- // Installed via npm local (node_modules/.bin)
14
- path.join(__dirname, '..', '..', 'target', 'release', 'anveesa'),
15
- path.join(__dirname, '..', '..', 'target', 'debug', 'anveesa'),
16
- // Development mode (cargo build)
17
- path.join(process.cwd(), 'target', 'release', 'anveesa'),
18
- path.join(process.cwd(), 'target', 'debug', 'anveesa'),
19
- ];
8
+ const platform = process.platform;
9
+ const ext = platform === 'win32' ? '.exe' : '';
10
+
11
+ // Binary is shipped in the package bin/ directory
12
+ const bundled = path.join(__dirname, 'anveesa' + ext);
13
+ if (fs.existsSync(bundled)) return bundled;
20
14
 
21
- for (const p of candidates) {
22
- if (fs.existsSync(p)) {
23
- return p;
24
- }
25
- }
15
+ // Also check for target/release (dev mode)
16
+ const devPath = path.join(__dirname, '..', 'target', 'release', 'anveesa' + ext);
17
+ if (fs.existsSync(devPath)) return devPath;
26
18
 
27
- // Cek PATH environment
28
- const paths = process.env.PATH.split(path.delimiter);
29
- for (const p of paths) {
30
- const full = path.join(p, 'anveesa');
31
- if (fs.existsSync(full)) {
32
- return full;
33
- }
34
- }
19
+ // Check if there's a sibling directory with the binary
20
+ const sibling = path.join(__dirname, 'target', 'release', 'anveesa' + ext);
21
+ if (fs.existsSync(sibling)) return sibling;
35
22
 
36
23
  return null;
37
24
  }
@@ -41,15 +28,11 @@ const binaryPath = findBinary();
41
28
  if (!binaryPath) {
42
29
  console.error('❌ anveesa binary not found.');
43
30
  console.error('');
44
- console.error('Build the Rust binary first:');
45
- console.error(' cd ' + __dirname + ' && npm run build');
46
- console.error(' # or: cargo build --release');
47
- console.error('');
31
+ console.error('Try reinstalling: npm install -g anveesa');
32
+ console.error('Or build from source: cargo build --release');
48
33
  process.exit(1);
49
34
  }
50
35
 
51
- // Spawn the Rust binary with proper TTY support
52
- const { spawn } = require('child_process');
53
36
  const args = process.argv.slice(2);
54
37
  const child = spawn(binaryPath, args, {
55
38
  cwd: process.cwd(),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "anveesa",
3
- "version": "0.2.0",
3
+ "version": "0.2.2",
4
4
  "description": "A terminal CLI that wraps AI providers (OpenAI-compatible APIs and local CLIs) into a single unified command",
5
5
  "main": "bin/anveesa.js",
6
6
  "bin": {
@@ -8,9 +8,8 @@
8
8
  },
9
9
  "scripts": {
10
10
  "build": "cargo build --release",
11
- "install": "node scripts/install.js",
12
- "prepublishOnly": "npm run build",
13
- "install:bin": "cargo build --release"
11
+ "postinstall": "node scripts/install.js",
12
+ "prepublishOnly": "npm run build"
14
13
  },
15
14
  "files": [
16
15
  "bin/",
@@ -18,16 +17,25 @@
18
17
  "Cargo.toml",
19
18
  "Cargo.lock",
20
19
  "src/",
21
- "README.md"
20
+ "README.md",
21
+ ".github/"
22
+ ],
23
+ "keywords": [
24
+ "ai",
25
+ "cli",
26
+ "terminal",
27
+ "rust",
28
+ "openai",
29
+ "agent",
30
+ "copilot"
22
31
  ],
23
- "keywords": ["ai", "cli", "terminal", "rust", "openai", "agent", "copilot"],
24
32
  "license": "MIT",
25
33
  "engines": {
26
34
  "node": ">=16"
27
35
  },
28
36
  "repository": {
29
37
  "type": "git",
30
- "url": "https://github.com/pandhuwibowo/anveesa-cli.git"
38
+ "url": "git+https://github.com/pandhuwibowo/anveesa-cli.git"
31
39
  },
32
40
  "homepage": "https://github.com/pandhuwibowo/anveesa-cli",
33
41
  "bugs": {
@@ -7,66 +7,144 @@
7
7
 
8
8
  const fs = require('fs');
9
9
  const path = require('path');
10
+ const https = require('https');
10
11
  const { execSync } = require('child_process');
11
12
 
12
- function getBinaryPath() {
13
- const pkgDir = __dirname;
14
- const possiblePaths = [
15
- path.join(pkgDir, '..', 'target', 'debug', 'anveesa'),
16
- path.join(pkgDir, '..', 'target', 'release', 'anveesa'),
17
- path.join(pkgDir, 'target', 'debug', 'anveesa'),
18
- path.join(pkgDir, 'target', 'release', 'anveesa'),
19
- ];
20
-
21
- for (const p of possiblePaths) {
22
- if (fs.existsSync(p)) {
23
- return p;
24
- }
25
- }
26
-
13
+ const PACKAGE = require(path.join(__dirname, '..', 'package.json'));
14
+ const REPO = 'pandhuwibowo/anveesa-cli';
15
+ const BIN_DIR = path.join(__dirname, '..', 'bin');
16
+
17
+ function getPlatformInfo() {
18
+ const platform = process.platform;
19
+ const arch = process.arch;
20
+
21
+ if (platform === 'darwin' && arch === 'arm64')
22
+ return { platform: 'macos', target: 'aarch64-apple-darwin', ext: '' };
23
+ if (platform === 'darwin' && arch === 'x64')
24
+ return { platform: 'macos', target: 'x86_64-apple-darwin', ext: '' };
25
+ if (platform === 'linux' && arch === 'x64')
26
+ return { platform: 'linux', target: 'x86_64-unknown-linux-gnu', ext: '' };
27
+ if (platform === 'linux' && arch === 'arm64')
28
+ return { platform: 'linux', target: 'aarch64-unknown-linux-gnu', ext: '' };
29
+ if (platform === 'win32' && arch === 'x64')
30
+ return { platform: 'windows', target: 'x86_64-pc-windows-msvc', ext: '.exe' };
31
+
27
32
  return null;
28
33
  }
29
34
 
30
- function checkAndInstall() {
31
- const binaryPath = getBinaryPath();
32
-
33
- if (binaryPath) {
34
- console.log('✓ Anveesa binary found at:', binaryPath);
35
- console.log('✓ Installation complete!');
36
- return true;
37
- } else {
38
- // Try to build automatically
39
- try {
40
- console.log('⚙ Building anveesa binary from source...');
41
- execSync('cargo build --release', {
42
- cwd: path.join(__dirname, '..'),
43
- stdio: 'inherit'
44
- });
45
- const rebuilt = getBinaryPath();
46
- if (rebuilt) {
47
- console.log('✓ Binary built successfully at:', rebuilt);
48
- console.log(' Installation complete!');
49
- return true;
35
+ function getBinaryUrl() {
36
+ const info = getPlatformInfo();
37
+ if (!info) return null;
38
+ const version = PACKAGE.version;
39
+ return `https://github.com/${REPO}/releases/download/v${version}/anveesa-${version}-${info.target}.tar.gz`;
40
+ }
41
+
42
+ function download(url, dest) {
43
+ return new Promise((resolve, reject) => {
44
+ const file = fs.createWriteStream(dest);
45
+ https.get(url, { followAllRedirects: true }, (res) => {
46
+ if (res.statusCode === 302 || res.statusCode === 301) {
47
+ https.get(res.headers.location, (res2) => {
48
+ res2.pipe(file);
49
+ file.on('finish', () => { file.close(); resolve(); });
50
+ }).on('error', reject);
51
+ } else if (res.statusCode === 200) {
52
+ res.pipe(file);
53
+ file.on('finish', () => { file.close(); resolve(); });
54
+ } else if (res.statusCode === 404) {
55
+ file.close();
56
+ fs.unlink(dest, () => {});
57
+ reject(new Error('404'));
58
+ } else {
59
+ file.close();
60
+ fs.unlink(dest, () => {});
61
+ reject(new Error(`HTTP ${res.statusCode}`));
50
62
  }
51
- } catch (e) {
52
- // cargo not available or build failed
63
+ }).on('error', (err) => {
64
+ fs.unlink(dest, () => {});
65
+ reject(err);
66
+ });
67
+ });
68
+ }
69
+
70
+ async function tryDownloadBinary() {
71
+ const url = getBinaryUrl();
72
+ if (!url) {
73
+ console.log('⚠ Unsupported platform:', process.platform, process.arch);
74
+ return false;
75
+ }
76
+
77
+ console.log('⬇ Downloading prebuilt binary for', process.platform, process.arch);
78
+
79
+ try {
80
+ const tarPath = path.join(__dirname, 'anveesa-bin.tar.gz');
81
+ await download(url, tarPath);
82
+
83
+ // Extract
84
+ execSync(`tar xzf "${tarPath}" -C "${BIN_DIR}"`, { stdio: 'inherit' });
85
+ fs.unlinkSync(tarPath);
86
+
87
+ // Make executable
88
+ const binary = path.join(BIN_DIR, 'anveesa');
89
+ if (fs.existsSync(binary)) {
90
+ fs.chmodSync(binary, 0o755);
53
91
  }
54
92
 
55
- console.error(' Anveesa binary not found and could not be built.');
56
- console.error('');
57
- console.error('Make sure Rust is installed: https://rustup.rs/');
58
- console.error('Then run:');
59
- console.error(' cargo build --release');
93
+ console.log(' Binary downloaded successfully');
94
+ return true;
95
+ } catch (e) {
96
+ if (e.message === '404') {
97
+ console.log(' No prebuilt binary for this version yet');
98
+ }
60
99
  return false;
61
100
  }
62
101
  }
63
102
 
64
- // If run directly
65
- if (require.main === module) {
66
- checkAndInstall();
103
+ function tryBuildFromSource() {
104
+ try {
105
+ console.log('⚙ Building from source (requires Rust)...');
106
+ execSync('cargo build --release', { cwd: path.join(__dirname, '..'), stdio: 'inherit' });
107
+
108
+ const src = path.join(__dirname, '..', 'target', 'release', 'anveesa');
109
+ const dest = path.join(BIN_DIR, 'anveesa');
110
+
111
+ if (fs.existsSync(src)) {
112
+ if (!fs.existsSync(BIN_DIR)) fs.mkdirSync(BIN_DIR, { recursive: true });
113
+ fs.copyFileSync(src, dest);
114
+ fs.chmodSync(dest, 0o755);
115
+ console.log('✓ Built from source successfully');
116
+ return true;
117
+ }
118
+ } catch (e) {
119
+ console.log('⚠ Build from source failed (Rust not installed?)');
120
+ }
121
+ return false;
122
+ }
123
+
124
+ async function install() {
125
+ // Check if binary already exists
126
+ const existing = path.join(BIN_DIR, 'anveesa');
127
+ const existingExe = path.join(BIN_DIR, 'anveesa.exe');
128
+ if (fs.existsSync(existing) || fs.existsSync(existingExe)) {
129
+ console.log('✓ anveesa binary already installed');
130
+ return;
131
+ }
132
+
133
+ // Try download first
134
+ if (await tryDownloadBinary()) return;
135
+
136
+ // Fallback to build from source
137
+ if (tryBuildFromSource()) return;
138
+
139
+ console.error('');
140
+ console.error('✗ Could not install anveesa binary.');
141
+ console.error('');
142
+ console.error('Install Rust: https://rustup.rs/');
143
+ console.error('Then run: npm install -g anveesa');
144
+ console.error('');
145
+ console.error('Or grab a prebuilt binary from:');
146
+ console.error(' https://github.com/pandhuwibowo/anveesa-cli/releases');
147
+ process.exit(1);
67
148
  }
68
149
 
69
- module.exports = {
70
- getBinaryPath,
71
- checkAndInstall
72
- };
150
+ install();