wisp-router 2.0.0 → 2.0.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/bin/claude-wisp.js +1 -1
- package/bin/wisp.js +71 -20
- package/package.json +5 -5
package/bin/claude-wisp.js
CHANGED
|
@@ -2,4 +2,4 @@
|
|
|
2
2
|
// ---------- claude-wisp.js — npm thin shell: same binary, claude-wisp dispatch token ---------- //
|
|
3
3
|
|
|
4
4
|
// One compiled binary serves both bins — `wisp claude-wisp …` reaches the launcher (#67).
|
|
5
|
-
require('./wisp.js').run(['claude-wisp']);
|
|
5
|
+
void require('./wisp.js').run(['claude-wisp']);
|
package/bin/wisp.js
CHANGED
|
@@ -3,44 +3,95 @@
|
|
|
3
3
|
|
|
4
4
|
/*
|
|
5
5
|
* Depends on:
|
|
6
|
-
* - child_process (node stdlib):
|
|
6
|
+
* - child_process / fs / path / os / https (node stdlib): resolve, download, and run the
|
|
7
|
+
* bun-compiled `wisp` binary with inherited stdio — the binary owns the terminal.
|
|
7
8
|
*
|
|
8
|
-
* Data shapes: none. The real program
|
|
9
|
-
*
|
|
9
|
+
* Data shapes: none. The real program ships two ways (esbuild pattern): a per-platform
|
|
10
|
+
* optionalDependency when npm serves it, else a one-time download of the same binary from the
|
|
11
|
+
* GitHub release into ~/.wisp/bin (npm's spam filter has taken the platform packages down before
|
|
12
|
+
* — the fallback keeps installs working regardless).
|
|
10
13
|
*/
|
|
11
14
|
|
|
12
15
|
const { spawnSync } = require('child_process');
|
|
16
|
+
const fs = require('fs');
|
|
17
|
+
const os = require('os');
|
|
18
|
+
const path = require('path');
|
|
13
19
|
|
|
14
|
-
|
|
20
|
+
const VERSION = require('../package.json').version;
|
|
21
|
+
const RELEASE_BASE = `https://github.com/EstarinAzx/Wisp-Router/releases/download/v${VERSION}`;
|
|
22
|
+
|
|
23
|
+
// platform-arch → optionalDependency name + GitHub release asset name.
|
|
15
24
|
// ponytail: musl (Alpine) matches linux-x64 but the glibc-linked binary fails at dlopen —
|
|
16
25
|
// add a musl probe with a plain error if it ever bites.
|
|
17
|
-
const
|
|
18
|
-
'win32-x64': '@tsd47216/wisp-router-win32-x64',
|
|
19
|
-
'darwin-arm64': '@tsd47216/wisp-router-darwin-arm64',
|
|
20
|
-
'darwin-x64': '@tsd47216/wisp-router-darwin-x64',
|
|
21
|
-
'linux-x64': '@tsd47216/wisp-router-linux-x64',
|
|
26
|
+
const PLATFORMS = {
|
|
27
|
+
'win32-x64': { pkg: '@tsd47216/wisp-router-win32-x64', asset: `wisp-v${VERSION}-win32-x64.exe` },
|
|
28
|
+
'darwin-arm64': { pkg: '@tsd47216/wisp-router-darwin-arm64', asset: `wisp-v${VERSION}-darwin-arm64` },
|
|
29
|
+
'darwin-x64': { pkg: '@tsd47216/wisp-router-darwin-x64', asset: `wisp-v${VERSION}-darwin-x64` },
|
|
30
|
+
'linux-x64': { pkg: '@tsd47216/wisp-router-linux-x64', asset: `wisp-v${VERSION}-linux-x64` },
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
const BIN_NAME = process.platform === 'win32' ? 'wisp.exe' : 'wisp';
|
|
34
|
+
|
|
35
|
+
// ----------------------------- Release-asset download (fallback) ----------------------------- //
|
|
36
|
+
|
|
37
|
+
// GET following redirects (GitHub release assets 302 to storage) onto a temp file, then rename —
|
|
38
|
+
// a killed download never leaves a half-written "binary" behind.
|
|
39
|
+
const download = (url, dest, redirects = 0) =>
|
|
40
|
+
new Promise((resolve, reject) => {
|
|
41
|
+
if (redirects > 5) return reject(new Error('too many redirects'));
|
|
42
|
+
require('https').get(url, (res) => {
|
|
43
|
+
if (res.statusCode >= 300 && res.statusCode < 400 && res.headers.location) {
|
|
44
|
+
res.resume();
|
|
45
|
+
return resolve(download(res.headers.location, dest, redirects + 1));
|
|
46
|
+
}
|
|
47
|
+
if (res.statusCode !== 200) {
|
|
48
|
+
res.resume();
|
|
49
|
+
return reject(new Error(`download failed: HTTP ${res.statusCode} for ${url}`));
|
|
50
|
+
}
|
|
51
|
+
const tmp = `${dest}.tmp-${process.pid}`;
|
|
52
|
+
const out = fs.createWriteStream(tmp);
|
|
53
|
+
res.pipe(out);
|
|
54
|
+
out.on('finish', () => out.close(() => { fs.renameSync(tmp, dest); resolve(); }));
|
|
55
|
+
out.on('error', (err) => { fs.rmSync(tmp, { force: true }); reject(err); });
|
|
56
|
+
}).on('error', reject);
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
const fetchBinary = async (platform) => {
|
|
60
|
+
const dir = path.join(os.homedir(), '.wisp', 'bin', `v${VERSION}`);
|
|
61
|
+
const file = path.join(dir, BIN_NAME);
|
|
62
|
+
if (!fs.existsSync(file)) {
|
|
63
|
+
console.error(`wisp-router: downloading ${platform.asset} from the GitHub release (one-time)…`);
|
|
64
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
65
|
+
await download(`${RELEASE_BASE}/${platform.asset}`, file);
|
|
66
|
+
if (process.platform !== 'win32') fs.chmodSync(file, 0o755);
|
|
67
|
+
}
|
|
68
|
+
return file;
|
|
22
69
|
};
|
|
23
70
|
|
|
24
|
-
|
|
71
|
+
// ----------------------------- Resolve + run ----------------------------- //
|
|
72
|
+
|
|
73
|
+
const resolveBinary = async () => {
|
|
25
74
|
const key = `${process.platform}-${process.arch}`;
|
|
26
|
-
const
|
|
27
|
-
if (!
|
|
28
|
-
console.error(`wisp-router: unsupported platform ${key} (supported: ${Object.keys(
|
|
75
|
+
const platform = PLATFORMS[key];
|
|
76
|
+
if (!platform) {
|
|
77
|
+
console.error(`wisp-router: unsupported platform ${key} (supported: ${Object.keys(PLATFORMS).join(', ')})`);
|
|
29
78
|
process.exit(1);
|
|
30
79
|
}
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
} catch {
|
|
34
|
-
console.error(`wisp-router: platform
|
|
80
|
+
// The optionalDependency wins when npm delivered it; otherwise the release download.
|
|
81
|
+
try { return require.resolve(`${platform.pkg}/bin/${BIN_NAME}`); } catch {}
|
|
82
|
+
try { return await fetchBinary(platform); } catch (err) {
|
|
83
|
+
console.error(`wisp-router: could not get the platform binary: ${err.message}`);
|
|
84
|
+
console.error(`Grab it manually: ${RELEASE_BASE}/${platform.asset}`);
|
|
35
85
|
process.exit(1);
|
|
36
86
|
}
|
|
37
87
|
};
|
|
38
88
|
|
|
39
89
|
// Run the binary with extra leading args (the claude-wisp shim passes its dispatch token here).
|
|
40
|
-
const run = (extraArgs) => {
|
|
90
|
+
const run = async (extraArgs) => {
|
|
91
|
+
const binary = await resolveBinary();
|
|
41
92
|
// Ctrl+C belongs to the child (TUI / claude handle their own); default would kill this shim first.
|
|
42
93
|
process.on('SIGINT', () => {});
|
|
43
|
-
const result = spawnSync(
|
|
94
|
+
const result = spawnSync(binary, [...extraArgs, ...process.argv.slice(2)], { stdio: 'inherit' });
|
|
44
95
|
if (result.error) {
|
|
45
96
|
console.error(`wisp-router: failed to start the platform binary: ${result.error.message}`);
|
|
46
97
|
process.exit(1);
|
|
@@ -49,4 +100,4 @@ const run = (extraArgs) => {
|
|
|
49
100
|
};
|
|
50
101
|
|
|
51
102
|
module.exports = { run };
|
|
52
|
-
if (require.main === module) run([]);
|
|
103
|
+
if (require.main === module) void run([]);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "wisp-router",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.1",
|
|
4
4
|
"description": "Wisp — BYOK model router: terminal UI, local Bridge (OpenAI + Anthropic doors), and the claude-wisp launcher for Claude Code",
|
|
5
5
|
"bin": {
|
|
6
6
|
"wisp": "bin/wisp.js",
|
|
@@ -17,9 +17,9 @@
|
|
|
17
17
|
"node": ">=16"
|
|
18
18
|
},
|
|
19
19
|
"optionalDependencies": {
|
|
20
|
-
"@tsd47216/wisp-router-win32-x64": "2.0.
|
|
21
|
-
"@tsd47216/wisp-router-darwin-arm64": "2.0.
|
|
22
|
-
"@tsd47216/wisp-router-darwin-x64": "2.0.
|
|
23
|
-
"@tsd47216/wisp-router-linux-x64": "2.0.
|
|
20
|
+
"@tsd47216/wisp-router-win32-x64": "2.0.1",
|
|
21
|
+
"@tsd47216/wisp-router-darwin-arm64": "2.0.1",
|
|
22
|
+
"@tsd47216/wisp-router-darwin-x64": "2.0.1",
|
|
23
|
+
"@tsd47216/wisp-router-linux-x64": "2.0.1"
|
|
24
24
|
}
|
|
25
25
|
}
|