@wordbricks/cva 0.1.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/README.md +22 -0
- package/bin/cva.js +35 -0
- package/lib/install.js +78 -0
- package/lib/platform.js +66 -0
- package/package.json +42 -0
package/README.md
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# @wordbricks/cva
|
|
2
|
+
|
|
3
|
+
Install the Codex Virtual Assistant CLI:
|
|
4
|
+
|
|
5
|
+
```bash
|
|
6
|
+
npm install -g @wordbricks/cva
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
This package installs a small Node wrapper and downloads the native `cva` binary for the current platform from GitHub Releases.
|
|
10
|
+
|
|
11
|
+
After installation:
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
cva version
|
|
15
|
+
cva start
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
Notes:
|
|
19
|
+
|
|
20
|
+
- The package name is scoped because the unscoped `cva` package is already taken on npm.
|
|
21
|
+
- The installed command is still `cva`.
|
|
22
|
+
- The downloader expects a matching GitHub release tag in the form `v<package-version>`.
|
package/bin/cva.js
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
const { spawnSync } = require("node:child_process");
|
|
4
|
+
const fs = require("node:fs");
|
|
5
|
+
|
|
6
|
+
const { binaryPath, currentTarget } = require("../lib/platform");
|
|
7
|
+
const { ensureBinary } = require("../lib/install");
|
|
8
|
+
|
|
9
|
+
async function main() {
|
|
10
|
+
const target = currentTarget();
|
|
11
|
+
let executable = binaryPath(target);
|
|
12
|
+
if (!fs.existsSync(executable)) {
|
|
13
|
+
executable = await ensureBinary({ quiet: false });
|
|
14
|
+
}
|
|
15
|
+
if (!executable || !fs.existsSync(executable)) {
|
|
16
|
+
console.error("The native cva binary is not installed.");
|
|
17
|
+
console.error("Try reinstalling the package or run with CVA_SKIP_DOWNLOAD unset.");
|
|
18
|
+
process.exit(1);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const result = spawnSync(executable, process.argv.slice(2), {
|
|
22
|
+
stdio: "inherit",
|
|
23
|
+
env: process.env
|
|
24
|
+
});
|
|
25
|
+
if (result.error) {
|
|
26
|
+
console.error(result.error.message);
|
|
27
|
+
process.exit(1);
|
|
28
|
+
}
|
|
29
|
+
process.exit(result.status === null ? 1 : result.status);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
main().catch((error) => {
|
|
33
|
+
console.error(error.message);
|
|
34
|
+
process.exit(1);
|
|
35
|
+
});
|
package/lib/install.js
ADDED
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
const fs = require("node:fs");
|
|
2
|
+
const path = require("node:path");
|
|
3
|
+
const https = require("node:https");
|
|
4
|
+
const { pipeline } = require("node:stream/promises");
|
|
5
|
+
|
|
6
|
+
const {
|
|
7
|
+
binaryPath,
|
|
8
|
+
currentTarget,
|
|
9
|
+
downloadURL,
|
|
10
|
+
packageRoot
|
|
11
|
+
} = require("./platform");
|
|
12
|
+
|
|
13
|
+
async function downloadFile(url, destination) {
|
|
14
|
+
const tempFile = `${destination}.tmp`;
|
|
15
|
+
await new Promise((resolve, reject) => {
|
|
16
|
+
const request = https.get(url, (response) => {
|
|
17
|
+
if (response.statusCode >= 300 && response.statusCode < 400 && response.headers.location) {
|
|
18
|
+
response.resume();
|
|
19
|
+
downloadFile(response.headers.location, destination).then(resolve).catch(reject);
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
if (response.statusCode !== 200) {
|
|
23
|
+
response.resume();
|
|
24
|
+
reject(new Error(`Download failed with HTTP ${response.statusCode}: ${url}`));
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const output = fs.createWriteStream(tempFile, { mode: 0o755 });
|
|
29
|
+
pipeline(response, output)
|
|
30
|
+
.then(resolve)
|
|
31
|
+
.catch(reject);
|
|
32
|
+
});
|
|
33
|
+
request.on("error", reject);
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
fs.renameSync(tempFile, destination);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
async function ensureBinary(options = {}) {
|
|
40
|
+
const { force = false, quiet = false } = options;
|
|
41
|
+
if (process.env.CVA_SKIP_DOWNLOAD === "1") {
|
|
42
|
+
if (!quiet) {
|
|
43
|
+
console.warn("Skipping cva binary download because CVA_SKIP_DOWNLOAD=1.");
|
|
44
|
+
}
|
|
45
|
+
return null;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
const target = currentTarget();
|
|
49
|
+
const destination = binaryPath(target);
|
|
50
|
+
if (!force && fs.existsSync(destination)) {
|
|
51
|
+
return destination;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
fs.mkdirSync(path.dirname(destination), { recursive: true });
|
|
55
|
+
const url = downloadURL(target);
|
|
56
|
+
if (!quiet) {
|
|
57
|
+
console.log(`Downloading cva binary from ${url}`);
|
|
58
|
+
}
|
|
59
|
+
await downloadFile(url, destination);
|
|
60
|
+
if (target.platform !== "win32") {
|
|
61
|
+
fs.chmodSync(destination, 0o755);
|
|
62
|
+
}
|
|
63
|
+
return destination;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
if (require.main === module) {
|
|
67
|
+
ensureBinary()
|
|
68
|
+
.catch((error) => {
|
|
69
|
+
const relativeRoot = packageRoot();
|
|
70
|
+
console.error(`Failed to install the native cva binary into ${relativeRoot}`);
|
|
71
|
+
console.error(error.message);
|
|
72
|
+
process.exit(1);
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
module.exports = {
|
|
77
|
+
ensureBinary
|
|
78
|
+
};
|
package/lib/platform.js
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
const os = require("node:os");
|
|
2
|
+
const path = require("node:path");
|
|
3
|
+
|
|
4
|
+
function packageRoot() {
|
|
5
|
+
return path.resolve(__dirname, "..");
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
function readPackageMetadata() {
|
|
9
|
+
// eslint-disable-next-line global-require, import/no-dynamic-require
|
|
10
|
+
return require(path.join(packageRoot(), "package.json"));
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
function currentTarget() {
|
|
14
|
+
const platform = os.platform();
|
|
15
|
+
const arch = os.arch();
|
|
16
|
+
|
|
17
|
+
const supported = new Set([
|
|
18
|
+
"linux:x64",
|
|
19
|
+
"linux:arm64",
|
|
20
|
+
"darwin:x64",
|
|
21
|
+
"darwin:arm64",
|
|
22
|
+
"win32:x64",
|
|
23
|
+
"win32:arm64"
|
|
24
|
+
]);
|
|
25
|
+
|
|
26
|
+
if (!supported.has(`${platform}:${arch}`)) {
|
|
27
|
+
throw new Error(`Unsupported platform for cva: ${platform}/${arch}`);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
return { platform, arch };
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function executableName(platform) {
|
|
34
|
+
return platform === "win32" ? "cva.exe" : "cva";
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function assetName(target) {
|
|
38
|
+
const metadata = readPackageMetadata();
|
|
39
|
+
const prefix = metadata.cva && metadata.cva.assetPrefix ? metadata.cva.assetPrefix : "cva";
|
|
40
|
+
return `${prefix}-${target.platform}-${target.arch}${target.platform === "win32" ? ".exe" : ""}`;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function binaryPath(target = currentTarget()) {
|
|
44
|
+
return path.join(packageRoot(), "vendor", target.platform, target.arch, executableName(target.platform));
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function releaseTag(metadata = readPackageMetadata()) {
|
|
48
|
+
return `v${metadata.version}`;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function downloadURL(target = currentTarget(), metadata = readPackageMetadata()) {
|
|
52
|
+
const owner = metadata.cva && metadata.cva.owner ? metadata.cva.owner : "wordbricks";
|
|
53
|
+
const repo = metadata.cva && metadata.cva.repo ? metadata.cva.repo : "codex-virtual-assistant";
|
|
54
|
+
return `https://github.com/${owner}/${repo}/releases/download/${releaseTag(metadata)}/${assetName(target)}`;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
module.exports = {
|
|
58
|
+
assetName,
|
|
59
|
+
binaryPath,
|
|
60
|
+
currentTarget,
|
|
61
|
+
downloadURL,
|
|
62
|
+
executableName,
|
|
63
|
+
packageRoot,
|
|
64
|
+
readPackageMetadata,
|
|
65
|
+
releaseTag
|
|
66
|
+
};
|
package/package.json
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@wordbricks/cva",
|
|
3
|
+
"version": "0.1.1",
|
|
4
|
+
"description": "Codex Virtual Assistant CLI wrapper that installs the native cva binary.",
|
|
5
|
+
"homepage": "https://github.com/wordbricks/codex-virtual-assistant",
|
|
6
|
+
"bugs": {
|
|
7
|
+
"url": "https://github.com/wordbricks/codex-virtual-assistant/issues"
|
|
8
|
+
},
|
|
9
|
+
"repository": {
|
|
10
|
+
"type": "git",
|
|
11
|
+
"url": "git+https://github.com/wordbricks/codex-virtual-assistant.git"
|
|
12
|
+
},
|
|
13
|
+
"engines": {
|
|
14
|
+
"node": ">=18"
|
|
15
|
+
},
|
|
16
|
+
"publishConfig": {
|
|
17
|
+
"access": "public"
|
|
18
|
+
},
|
|
19
|
+
"bin": {
|
|
20
|
+
"cva": "bin/cva.js"
|
|
21
|
+
},
|
|
22
|
+
"scripts": {
|
|
23
|
+
"postinstall": "node ./lib/install.js"
|
|
24
|
+
},
|
|
25
|
+
"files": [
|
|
26
|
+
"README.md",
|
|
27
|
+
"bin",
|
|
28
|
+
"lib"
|
|
29
|
+
],
|
|
30
|
+
"keywords": [
|
|
31
|
+
"agent",
|
|
32
|
+
"assistant",
|
|
33
|
+
"cli",
|
|
34
|
+
"codex",
|
|
35
|
+
"cva"
|
|
36
|
+
],
|
|
37
|
+
"cva": {
|
|
38
|
+
"owner": "wordbricks",
|
|
39
|
+
"repo": "codex-virtual-assistant",
|
|
40
|
+
"assetPrefix": "cva"
|
|
41
|
+
}
|
|
42
|
+
}
|