anveesa 0.2.0 → 0.2.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/.github/workflows/release.yml +68 -0
- package/bin/anveesa +0 -0
- package/bin/anveesa.js +15 -32
- package/package.json +15 -7
- package/scripts/install.js +124 -49
|
@@ -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 {
|
|
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
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
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 (
|
|
22
|
-
|
|
23
|
-
|
|
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
|
-
//
|
|
28
|
-
const
|
|
29
|
-
|
|
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('
|
|
45
|
-
console.error('
|
|
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.
|
|
3
|
+
"version": "0.2.1",
|
|
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
|
-
"
|
|
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": {
|
package/scripts/install.js
CHANGED
|
@@ -7,66 +7,141 @@
|
|
|
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
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
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
|
|
31
|
-
const
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
if (
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
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
|
-
}
|
|
52
|
-
|
|
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.
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
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
|
-
|
|
65
|
-
|
|
66
|
-
|
|
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
|
+
process.exit(1);
|
|
67
145
|
}
|
|
68
146
|
|
|
69
|
-
|
|
70
|
-
getBinaryPath,
|
|
71
|
-
checkAndInstall
|
|
72
|
-
};
|
|
147
|
+
install();
|