@lka09/wisp 0.1.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/wisp.js +59 -0
- package/dist/wisp.exe +0 -0
- package/package.json +34 -0
- package/scripts/build.js +59 -0
- package/scripts/postinstall.js +120 -0
package/bin/wisp.js
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
const path = require('path');
|
|
5
|
+
const { spawnSync } = require('child_process');
|
|
6
|
+
|
|
7
|
+
const platform = process.platform;
|
|
8
|
+
const arch = process.arch;
|
|
9
|
+
|
|
10
|
+
// Map platform/arch to the release asset name used in GitHub Releases.
|
|
11
|
+
const ASSET_NAMES = {
|
|
12
|
+
win32: { x64: 'wisp-windows-x86_64.exe', arm64: 'wisp-windows-aarch64.exe' },
|
|
13
|
+
linux: { x64: 'wisp-linux-x86_64', arm64: 'wisp-linux-aarch64' },
|
|
14
|
+
darwin: { x64: 'wisp-darwin-x86_64', arm64: 'wisp-darwin-aarch64' },
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
const binaryName = platform === 'win32' ? 'wisp.exe' : 'wisp';
|
|
18
|
+
const binaryPath = path.join(__dirname, '..', 'dist', binaryName);
|
|
19
|
+
|
|
20
|
+
const result = spawnSync(binaryPath, process.argv.slice(2), {
|
|
21
|
+
stdio: 'inherit',
|
|
22
|
+
env: process.env,
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
if (result.error) {
|
|
26
|
+
if (result.error.code === 'ENOENT') {
|
|
27
|
+
const assetName = (ASSET_NAMES[platform] || {})[arch] || '<asset-name>';
|
|
28
|
+
const pkg = require('../package.json');
|
|
29
|
+
const version = pkg.version;
|
|
30
|
+
|
|
31
|
+
console.error('Error: Wisp binary not found.');
|
|
32
|
+
console.error('');
|
|
33
|
+
console.error(' Expected path: ' + binaryPath);
|
|
34
|
+
console.error('');
|
|
35
|
+
console.error('The GitHub Release asset for v' + version + ' may be missing for this platform.');
|
|
36
|
+
console.error('Expected release asset: ' + assetName);
|
|
37
|
+
console.error('');
|
|
38
|
+
console.error('Build from source (Windows PowerShell):');
|
|
39
|
+
console.error(' cd wisp');
|
|
40
|
+
console.error(' cargo build --release');
|
|
41
|
+
console.error(' New-Item -ItemType Directory -Force -Path ..\\npm\\dist | Out-Null');
|
|
42
|
+
console.error(' Copy-Item target\\release\\wisp.exe ..\\npm\\dist\\wisp.exe');
|
|
43
|
+
console.error('');
|
|
44
|
+
console.error('Build from source (Linux / macOS):');
|
|
45
|
+
console.error(' cd wisp && cargo build --release');
|
|
46
|
+
console.error(' mkdir -p ../npm/dist');
|
|
47
|
+
console.error(' cp target/release/wisp ../npm/dist/wisp');
|
|
48
|
+
console.error('');
|
|
49
|
+
console.error('Expected release asset names:');
|
|
50
|
+
console.error(' wisp-windows-x86_64.exe wisp-windows-aarch64.exe');
|
|
51
|
+
console.error(' wisp-linux-x86_64 wisp-linux-aarch64');
|
|
52
|
+
console.error(' wisp-darwin-x86_64 wisp-darwin-aarch64');
|
|
53
|
+
process.exit(1);
|
|
54
|
+
}
|
|
55
|
+
console.error('Error: ' + result.error.message);
|
|
56
|
+
process.exit(1);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
process.exit(result.status !== null ? result.status : 0);
|
package/dist/wisp.exe
ADDED
|
Binary file
|
package/package.json
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@lka09/wisp",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "A local personal coding agent for Claude and Codex CLI.",
|
|
5
|
+
"bin": {
|
|
6
|
+
"wisp": "./bin/wisp.js"
|
|
7
|
+
},
|
|
8
|
+
"scripts": {
|
|
9
|
+
"postinstall": "node scripts/postinstall.js",
|
|
10
|
+
"build": "node scripts/build.js"
|
|
11
|
+
},
|
|
12
|
+
"files": [
|
|
13
|
+
"bin",
|
|
14
|
+
"dist",
|
|
15
|
+
"scripts",
|
|
16
|
+
"README.md"
|
|
17
|
+
],
|
|
18
|
+
"engines": {
|
|
19
|
+
"node": ">=16"
|
|
20
|
+
},
|
|
21
|
+
"license": "MIT",
|
|
22
|
+
"repository": {
|
|
23
|
+
"type": "git",
|
|
24
|
+
"url": "https://github.com/LKA09/Wisp"
|
|
25
|
+
},
|
|
26
|
+
"keywords": [
|
|
27
|
+
"ai",
|
|
28
|
+
"agent",
|
|
29
|
+
"claude",
|
|
30
|
+
"codex",
|
|
31
|
+
"coding-agent",
|
|
32
|
+
"orchestrator"
|
|
33
|
+
]
|
|
34
|
+
}
|
package/scripts/build.js
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Build helper — compiles the Rust binary and copies it into npm/dist/.
|
|
6
|
+
* Run from the repo root: node npm/scripts/build.js
|
|
7
|
+
* Or via: npm run build
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
const { execSync } = require('child_process');
|
|
11
|
+
const fs = require('fs');
|
|
12
|
+
const path = require('path');
|
|
13
|
+
|
|
14
|
+
const repoRoot = path.join(__dirname, '..', '..');
|
|
15
|
+
const crateDir = path.join(repoRoot, 'wisp');
|
|
16
|
+
const distDir = path.join(__dirname, '..', 'dist');
|
|
17
|
+
|
|
18
|
+
const isWin = process.platform === 'win32';
|
|
19
|
+
const binaryName = isWin ? 'wisp.exe' : 'wisp';
|
|
20
|
+
const releaseBin = path.join(crateDir, 'target', 'release', binaryName);
|
|
21
|
+
|
|
22
|
+
// 1. Build
|
|
23
|
+
console.log('[wisp] Building Rust binary (cargo build --release)...');
|
|
24
|
+
try {
|
|
25
|
+
execSync('cargo build --release', { cwd: crateDir, stdio: 'inherit' });
|
|
26
|
+
} catch (e) {
|
|
27
|
+
console.error('[wisp] cargo build failed. Is Rust installed? https://rustup.rs/');
|
|
28
|
+
process.exit(1);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// 2. Copy (retry on Windows EBUSY — antivirus/linker may briefly lock the file)
|
|
32
|
+
fs.mkdirSync(distDir, { recursive: true });
|
|
33
|
+
const dest = path.join(distDir, binaryName);
|
|
34
|
+
|
|
35
|
+
function copyWithRetry(src, dst, attempts = 5, delayMs = 500) {
|
|
36
|
+
for (let i = 0; i < attempts; i++) {
|
|
37
|
+
try {
|
|
38
|
+
fs.copyFileSync(src, dst);
|
|
39
|
+
return;
|
|
40
|
+
} catch (e) {
|
|
41
|
+
if (e.code === 'EBUSY' && i < attempts - 1) {
|
|
42
|
+
const wait = delayMs * (i + 1);
|
|
43
|
+
console.log(`[wisp] File busy, retrying in ${wait}ms... (${i + 1}/${attempts - 1})`);
|
|
44
|
+
Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, wait);
|
|
45
|
+
} else {
|
|
46
|
+
throw e;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
copyWithRetry(releaseBin, dest);
|
|
53
|
+
|
|
54
|
+
if (!isWin) {
|
|
55
|
+
fs.chmodSync(dest, 0o755);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
console.log(`[wisp] Binary copied to ${path.relative(repoRoot, dest)}`);
|
|
59
|
+
console.log('[wisp] Done. Run `wisp` or `cd npm && npm link` to install globally.');
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Wisp postinstall — downloads the platform-appropriate binary from GitHub Releases.
|
|
6
|
+
* Skips silently if the binary already exists (local development / manual build).
|
|
7
|
+
* Never hard-fails npm install; only warns on download errors.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
const https = require('https');
|
|
11
|
+
const fs = require('fs');
|
|
12
|
+
const path = require('path');
|
|
13
|
+
|
|
14
|
+
const pkg = require('../package.json');
|
|
15
|
+
const version = pkg.version;
|
|
16
|
+
const distDir = path.join(__dirname, '..', 'dist');
|
|
17
|
+
const binaryName = process.platform === 'win32' ? 'wisp.exe' : 'wisp';
|
|
18
|
+
const binaryPath = path.join(distDir, binaryName);
|
|
19
|
+
|
|
20
|
+
// Already installed (local dev or previous run) — skip.
|
|
21
|
+
if (fs.existsSync(binaryPath)) {
|
|
22
|
+
console.log('[wisp] Binary already present, skipping download.');
|
|
23
|
+
process.exit(0);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// Map Node platform/arch to Rust target triples used in release asset names.
|
|
27
|
+
const PLATFORM_MAP = {
|
|
28
|
+
darwin: 'darwin',
|
|
29
|
+
linux: 'linux',
|
|
30
|
+
win32: 'windows',
|
|
31
|
+
};
|
|
32
|
+
const ARCH_MAP = {
|
|
33
|
+
x64: 'x86_64',
|
|
34
|
+
arm64: 'aarch64',
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
const plat = PLATFORM_MAP[process.platform];
|
|
38
|
+
const arch = ARCH_MAP[process.arch];
|
|
39
|
+
|
|
40
|
+
if (!plat || !arch) {
|
|
41
|
+
warn(`Unsupported platform: ${process.platform}-${process.arch}`);
|
|
42
|
+
process.exit(0);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const ext = process.platform === 'win32' ? '.exe' : '';
|
|
46
|
+
const assetName = `wisp-${plat}-${arch}${ext}`;
|
|
47
|
+
const repoOwner = 'LKA09';
|
|
48
|
+
const repoName = 'Wisp';
|
|
49
|
+
const downloadUrl =
|
|
50
|
+
`https://github.com/${repoOwner}/${repoName}/releases/download/v${version}/${assetName}`;
|
|
51
|
+
|
|
52
|
+
console.log(`[wisp] Downloading v${version} for ${process.platform}-${process.arch}...`);
|
|
53
|
+
console.log(`[wisp] ${downloadUrl}`);
|
|
54
|
+
|
|
55
|
+
fs.mkdirSync(distDir, { recursive: true });
|
|
56
|
+
|
|
57
|
+
get(downloadUrl, (err, data) => {
|
|
58
|
+
if (err) {
|
|
59
|
+
warn(`Download failed: ${err.message}`);
|
|
60
|
+
warn('');
|
|
61
|
+
warn(`Expected release asset: ${assetName}`);
|
|
62
|
+
warn(`Release URL checked: ${downloadUrl}`);
|
|
63
|
+
warn('');
|
|
64
|
+
warn('The GitHub Release asset may be missing for this version/platform.');
|
|
65
|
+
warn('');
|
|
66
|
+
warn('Build from source (Windows PowerShell):');
|
|
67
|
+
warn(' cd wisp');
|
|
68
|
+
warn(' cargo build --release');
|
|
69
|
+
warn(' New-Item -ItemType Directory -Force -Path ..\\npm\\dist | Out-Null');
|
|
70
|
+
warn(' Copy-Item target\\release\\wisp.exe ..\\npm\\dist\\wisp.exe');
|
|
71
|
+
warn('');
|
|
72
|
+
warn('Build from source (Linux / macOS):');
|
|
73
|
+
warn(' cd wisp && cargo build --release');
|
|
74
|
+
warn(' mkdir -p ../npm/dist && cp target/release/wisp ../npm/dist/wisp');
|
|
75
|
+
warn('');
|
|
76
|
+
warn('Expected release asset names:');
|
|
77
|
+
warn(' wisp-windows-x86_64.exe wisp-windows-aarch64.exe');
|
|
78
|
+
warn(' wisp-linux-x86_64 wisp-linux-aarch64');
|
|
79
|
+
warn(' wisp-darwin-x86_64 wisp-darwin-aarch64');
|
|
80
|
+
process.exit(0);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
fs.writeFileSync(binaryPath, data);
|
|
84
|
+
|
|
85
|
+
if (process.platform !== 'win32') {
|
|
86
|
+
fs.chmodSync(binaryPath, 0o755);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
console.log('[wisp] Installed successfully.');
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
// ─── helpers ──────────────────────────────────────────────────────────────────
|
|
93
|
+
|
|
94
|
+
function warn(msg) {
|
|
95
|
+
console.warn('[wisp] ' + msg);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/** HTTP GET with redirect following (GitHub releases redirect to S3). */
|
|
99
|
+
function get(url, callback, redirects = 0) {
|
|
100
|
+
if (redirects > 5) {
|
|
101
|
+
callback(new Error('Too many redirects'));
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
https.get(url, { headers: { 'User-Agent': 'wisp-postinstall' } }, (res) => {
|
|
106
|
+
if (res.statusCode === 301 || res.statusCode === 302) {
|
|
107
|
+
get(res.headers.location, callback, redirects + 1);
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
if (res.statusCode !== 200) {
|
|
111
|
+
callback(new Error(`HTTP ${res.statusCode} from ${url}`));
|
|
112
|
+
return;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
const chunks = [];
|
|
116
|
+
res.on('data', (c) => chunks.push(c));
|
|
117
|
+
res.on('end', () => callback(null, Buffer.concat(chunks)));
|
|
118
|
+
res.on('error', callback);
|
|
119
|
+
}).on('error', callback);
|
|
120
|
+
}
|