settlekit 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/README.md +43 -0
- package/bin/settle.js +30 -0
- package/package.json +56 -0
- package/scripts/clean-staged-binaries.js +27 -0
- package/scripts/install.js +189 -0
- package/scripts/stage-binaries.js +49 -0
- package/vendor/settle-darwin-arm64 +0 -0
- package/vendor/settle-darwin-arm64.sha256 +1 -0
- package/vendor/settle-darwin-x64 +0 -0
- package/vendor/settle-darwin-x64.sha256 +1 -0
- package/vendor/settle-linux-arm64 +0 -0
- package/vendor/settle-linux-arm64.sha256 +1 -0
- package/vendor/settle-linux-x64 +0 -0
- package/vendor/settle-linux-x64.sha256 +1 -0
- package/vendor/settle-win32-arm64.exe +0 -0
- package/vendor/settle-win32-arm64.exe.sha256 +1 -0
- package/vendor/settle-win32-x64.exe +0 -0
- package/vendor/settle-win32-x64.exe.sha256 +1 -0
package/README.md
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
# SettleKit CLI
|
|
2
|
+
|
|
3
|
+
Install globally:
|
|
4
|
+
|
|
5
|
+
```bash
|
|
6
|
+
npm install -g settlekit
|
|
7
|
+
settle login
|
|
8
|
+
```
|
|
9
|
+
|
|
10
|
+
Or install in a project:
|
|
11
|
+
|
|
12
|
+
```bash
|
|
13
|
+
npm install settlekit
|
|
14
|
+
npx settlekit login
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
One-off usage also works without adding it to `package.json`:
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
npx settlekit login
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
`settle login` opens the SettleKit website, lets you authorize the CLI, and stores a local CLI config. After that:
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
settle tool list
|
|
27
|
+
settle tool call web.search --input '{"q":"SettleKit","count":5}'
|
|
28
|
+
settle credits balance
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
For staging or self-hosted deployments:
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
SETTLE_PLATFORM_URL=https://app.example.com SETTLE_BASE_URL=https://api.example.com settle login
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
The npm package bundles platform binaries and verifies the matching `.sha256` file during `postinstall`. If a bundled binary is unavailable, installation falls back to downloading the binary and checksum from GitHub Releases. Private release channels can override:
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
SETTLEKIT_CLI_RELEASE_BASE=https://github.com/your-org/your-repo/releases/download \
|
|
41
|
+
SETTLEKIT_CLI_RELEASE_TAG=v0.1.0 \
|
|
42
|
+
npm install -g settlekit
|
|
43
|
+
```
|
package/bin/settle.js
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
const { spawnSync } = require("node:child_process");
|
|
4
|
+
const fs = require("node:fs");
|
|
5
|
+
const path = require("node:path");
|
|
6
|
+
|
|
7
|
+
const binaryOverride = process.env.SETTLEKIT_CLI_BINARY;
|
|
8
|
+
const binaryName = process.platform === "win32" ? "settle.exe" : "settle";
|
|
9
|
+
const binaryPath = binaryOverride || path.join(__dirname, "..", "vendor", binaryName);
|
|
10
|
+
|
|
11
|
+
if (!fs.existsSync(binaryPath)) {
|
|
12
|
+
console.error("settle: CLI binary was not found.");
|
|
13
|
+
console.error("Run `npm rebuild -g settlekit` or reinstall with `npm install -g settlekit`.");
|
|
14
|
+
if (process.env.SETTLEKIT_CLI_RELEASE_BASE || process.env.SETTLEKIT_CLI_RELEASE_TAG) {
|
|
15
|
+
console.error("Check SETTLEKIT_CLI_RELEASE_BASE and SETTLEKIT_CLI_RELEASE_TAG.");
|
|
16
|
+
}
|
|
17
|
+
process.exit(1);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const result = spawnSync(binaryPath, process.argv.slice(2), {
|
|
21
|
+
stdio: "inherit",
|
|
22
|
+
env: process.env,
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
if (result.error) {
|
|
26
|
+
console.error(`settle: ${result.error.message}`);
|
|
27
|
+
process.exit(1);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
process.exit(result.status ?? 0);
|
package/package.json
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "settlekit",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "SettleKit CLI",
|
|
5
|
+
"license": "UNLICENSED",
|
|
6
|
+
"homepage": "https://settlekit.io",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "git+https://github.com/CalLeeLQY/SettleKit.git",
|
|
10
|
+
"directory": "npm/settlekit"
|
|
11
|
+
},
|
|
12
|
+
"bugs": {
|
|
13
|
+
"url": "https://github.com/CalLeeLQY/SettleKit/issues"
|
|
14
|
+
},
|
|
15
|
+
"keywords": [
|
|
16
|
+
"settlekit",
|
|
17
|
+
"cli",
|
|
18
|
+
"agent",
|
|
19
|
+
"ai",
|
|
20
|
+
"tools"
|
|
21
|
+
],
|
|
22
|
+
"publishConfig": {
|
|
23
|
+
"access": "public"
|
|
24
|
+
},
|
|
25
|
+
"bin": {
|
|
26
|
+
"kit": "bin/settle.js",
|
|
27
|
+
"settle": "bin/settle.js",
|
|
28
|
+
"settlekit": "bin/settle.js"
|
|
29
|
+
},
|
|
30
|
+
"scripts": {
|
|
31
|
+
"prepack": "node scripts/stage-binaries.js",
|
|
32
|
+
"postpack": "node scripts/clean-staged-binaries.js",
|
|
33
|
+
"postinstall": "node scripts/install.js"
|
|
34
|
+
},
|
|
35
|
+
"files": [
|
|
36
|
+
"bin/",
|
|
37
|
+
"scripts/",
|
|
38
|
+
"vendor/",
|
|
39
|
+
"README.md"
|
|
40
|
+
],
|
|
41
|
+
"config": {
|
|
42
|
+
"release_base": "https://github.com/CalLeeLQY/SettleKit/releases/download"
|
|
43
|
+
},
|
|
44
|
+
"engines": {
|
|
45
|
+
"node": ">=18"
|
|
46
|
+
},
|
|
47
|
+
"os": [
|
|
48
|
+
"darwin",
|
|
49
|
+
"linux",
|
|
50
|
+
"win32"
|
|
51
|
+
],
|
|
52
|
+
"cpu": [
|
|
53
|
+
"x64",
|
|
54
|
+
"arm64"
|
|
55
|
+
]
|
|
56
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
const fs = require("node:fs");
|
|
4
|
+
const path = require("node:path");
|
|
5
|
+
|
|
6
|
+
const vendorDir = path.resolve(__dirname, "..", "vendor");
|
|
7
|
+
const assets = [
|
|
8
|
+
"settle-darwin-arm64",
|
|
9
|
+
"settle-darwin-x64",
|
|
10
|
+
"settle-linux-arm64",
|
|
11
|
+
"settle-linux-x64",
|
|
12
|
+
"settle-win32-arm64.exe",
|
|
13
|
+
"settle-win32-x64.exe",
|
|
14
|
+
];
|
|
15
|
+
|
|
16
|
+
for (const asset of assets) {
|
|
17
|
+
fs.rmSync(path.join(vendorDir, asset), { force: true });
|
|
18
|
+
fs.rmSync(path.join(vendorDir, `${asset}.sha256`), { force: true });
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
try {
|
|
22
|
+
if (fs.existsSync(vendorDir) && fs.readdirSync(vendorDir).length === 0) {
|
|
23
|
+
fs.rmdirSync(vendorDir);
|
|
24
|
+
}
|
|
25
|
+
} catch {
|
|
26
|
+
// Best-effort cleanup only.
|
|
27
|
+
}
|
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
const fs = require("node:fs");
|
|
4
|
+
const crypto = require("node:crypto");
|
|
5
|
+
const http = require("node:http");
|
|
6
|
+
const https = require("node:https");
|
|
7
|
+
const os = require("node:os");
|
|
8
|
+
const path = require("node:path");
|
|
9
|
+
const { fileURLToPath } = require("node:url");
|
|
10
|
+
|
|
11
|
+
const root = path.resolve(__dirname, "..");
|
|
12
|
+
const pkg = require(path.join(root, "package.json"));
|
|
13
|
+
|
|
14
|
+
if (process.env.SETTLEKIT_SKIP_BINARY_INSTALL === "1") {
|
|
15
|
+
console.log("settle: skipping binary install because SETTLEKIT_SKIP_BINARY_INSTALL=1");
|
|
16
|
+
process.exit(0);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const platform = platformName(process.platform);
|
|
20
|
+
const arch = archName(process.arch);
|
|
21
|
+
const binaryName = process.platform === "win32" ? "settle.exe" : "settle";
|
|
22
|
+
const assetName = process.platform === "win32" ? `settle-${platform}-${arch}.exe` : `settle-${platform}-${arch}`;
|
|
23
|
+
const vendorDir = path.join(root, "vendor");
|
|
24
|
+
const target = path.join(vendorDir, binaryName);
|
|
25
|
+
const bundledAsset = path.join(vendorDir, assetName);
|
|
26
|
+
const bundledChecksum = `${bundledAsset}.sha256`;
|
|
27
|
+
const tmp = path.join(os.tmpdir(), `settle-${process.pid}-${Date.now()}`);
|
|
28
|
+
const checksumTmp = `${tmp}.sha256`;
|
|
29
|
+
const releaseBase = stripTrailingSlash(
|
|
30
|
+
process.env.SETTLEKIT_CLI_RELEASE_BASE ||
|
|
31
|
+
process.env.npm_package_config_release_base ||
|
|
32
|
+
pkg.config?.release_base ||
|
|
33
|
+
"https://github.com/CalLeeLQY/SettleKit/releases/download",
|
|
34
|
+
);
|
|
35
|
+
const releaseTag = process.env.SETTLEKIT_CLI_RELEASE_TAG || `v${pkg.version}`;
|
|
36
|
+
const url = `${releaseBase}/${releaseTag}/${assetName}`;
|
|
37
|
+
const checksumURL = `${url}.sha256`;
|
|
38
|
+
|
|
39
|
+
fs.mkdirSync(vendorDir, { recursive: true });
|
|
40
|
+
|
|
41
|
+
if (fs.existsSync(bundledAsset)) {
|
|
42
|
+
try {
|
|
43
|
+
installFromLocalAsset(bundledAsset, bundledChecksum, target);
|
|
44
|
+
console.log(`settle: installed bundled ${assetName}`);
|
|
45
|
+
process.exit(0);
|
|
46
|
+
} catch (err) {
|
|
47
|
+
console.error(`settle: bundled ${assetName} failed verification`);
|
|
48
|
+
console.error(`settle: ${err.message}`);
|
|
49
|
+
process.exit(1);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
download(url, tmp, 0, (err) => {
|
|
54
|
+
if (err) {
|
|
55
|
+
console.error(`settle: failed to download ${assetName}`);
|
|
56
|
+
console.error(`settle: ${err.message}`);
|
|
57
|
+
console.error(`settle: attempted ${url}`);
|
|
58
|
+
console.error("settle: set SETTLEKIT_CLI_RELEASE_BASE or SETTLEKIT_CLI_RELEASE_TAG for private/staging releases.");
|
|
59
|
+
process.exit(1);
|
|
60
|
+
}
|
|
61
|
+
download(checksumURL, checksumTmp, 0, (checksumErr) => {
|
|
62
|
+
if (checksumErr && process.env.SETTLEKIT_SKIP_CHECKSUM !== "1") {
|
|
63
|
+
fs.rmSync(tmp, { force: true });
|
|
64
|
+
fs.rmSync(checksumTmp, { force: true });
|
|
65
|
+
console.error(`settle: failed to download checksum for ${assetName}`);
|
|
66
|
+
console.error(`settle: ${checksumErr.message}`);
|
|
67
|
+
console.error(`settle: attempted ${checksumURL}`);
|
|
68
|
+
console.error("settle: set SETTLEKIT_SKIP_CHECKSUM=1 only for trusted private test releases.");
|
|
69
|
+
process.exit(1);
|
|
70
|
+
}
|
|
71
|
+
if (!checksumErr && process.env.SETTLEKIT_SKIP_CHECKSUM !== "1") {
|
|
72
|
+
const expected = parseChecksum(fs.readFileSync(checksumTmp, "utf8"));
|
|
73
|
+
const actual = sha256File(tmp);
|
|
74
|
+
if (!expected || expected !== actual) {
|
|
75
|
+
fs.rmSync(tmp, { force: true });
|
|
76
|
+
fs.rmSync(checksumTmp, { force: true });
|
|
77
|
+
console.error(`settle: checksum mismatch for ${assetName}`);
|
|
78
|
+
console.error(`settle: expected ${expected || "(missing checksum)"}`);
|
|
79
|
+
console.error(`settle: actual ${actual}`);
|
|
80
|
+
process.exit(1);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
fs.copyFileSync(tmp, target);
|
|
84
|
+
fs.rmSync(tmp, { force: true });
|
|
85
|
+
fs.rmSync(checksumTmp, { force: true });
|
|
86
|
+
if (process.platform !== "win32") {
|
|
87
|
+
fs.chmodSync(target, 0o755);
|
|
88
|
+
}
|
|
89
|
+
console.log(`settle: installed ${assetName}`);
|
|
90
|
+
});
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
function installFromLocalAsset(source, checksumPath, destination) {
|
|
94
|
+
if (process.env.SETTLEKIT_SKIP_CHECKSUM !== "1") {
|
|
95
|
+
if (!fs.existsSync(checksumPath)) {
|
|
96
|
+
throw new Error(`missing checksum ${path.basename(checksumPath)}`);
|
|
97
|
+
}
|
|
98
|
+
const expected = parseChecksum(fs.readFileSync(checksumPath, "utf8"));
|
|
99
|
+
const actual = sha256File(source);
|
|
100
|
+
if (!expected || expected !== actual) {
|
|
101
|
+
throw new Error(`checksum mismatch: expected ${expected || "(missing checksum)"}, actual ${actual}`);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
fs.copyFileSync(source, destination);
|
|
105
|
+
if (process.platform !== "win32") {
|
|
106
|
+
fs.chmodSync(destination, 0o755);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
function parseChecksum(value) {
|
|
111
|
+
const match = String(value || "").match(/[a-fA-F0-9]{64}/);
|
|
112
|
+
return match ? match[0].toLowerCase() : "";
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
function sha256File(filePath) {
|
|
116
|
+
const hash = crypto.createHash("sha256");
|
|
117
|
+
const data = fs.readFileSync(filePath);
|
|
118
|
+
hash.update(data);
|
|
119
|
+
return hash.digest("hex");
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
function platformName(value) {
|
|
123
|
+
switch (value) {
|
|
124
|
+
case "darwin":
|
|
125
|
+
case "linux":
|
|
126
|
+
case "win32":
|
|
127
|
+
return value;
|
|
128
|
+
default:
|
|
129
|
+
throw new Error(`unsupported platform ${value}`);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
function archName(value) {
|
|
134
|
+
switch (value) {
|
|
135
|
+
case "x64":
|
|
136
|
+
case "arm64":
|
|
137
|
+
return value;
|
|
138
|
+
default:
|
|
139
|
+
throw new Error(`unsupported architecture ${value}`);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
function stripTrailingSlash(value) {
|
|
144
|
+
return String(value || "").replace(/\/+$/, "");
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
function download(rawURL, destination, redirectCount, done) {
|
|
148
|
+
if (redirectCount > 5) {
|
|
149
|
+
done(new Error("too many redirects"));
|
|
150
|
+
return;
|
|
151
|
+
}
|
|
152
|
+
let parsed;
|
|
153
|
+
try {
|
|
154
|
+
parsed = new URL(rawURL);
|
|
155
|
+
} catch (err) {
|
|
156
|
+
done(err);
|
|
157
|
+
return;
|
|
158
|
+
}
|
|
159
|
+
if (parsed.protocol === "file:") {
|
|
160
|
+
try {
|
|
161
|
+
fs.copyFileSync(fileURLToPath(parsed), destination);
|
|
162
|
+
done();
|
|
163
|
+
} catch (err) {
|
|
164
|
+
done(err);
|
|
165
|
+
}
|
|
166
|
+
return;
|
|
167
|
+
}
|
|
168
|
+
const client = parsed.protocol === "http:" ? http : https;
|
|
169
|
+
const request = client.get(rawURL, (response) => {
|
|
170
|
+
const status = response.statusCode || 0;
|
|
171
|
+
const location = response.headers.location;
|
|
172
|
+
if (status >= 300 && status < 400 && location) {
|
|
173
|
+
response.resume();
|
|
174
|
+
download(new URL(location, rawURL).toString(), destination, redirectCount + 1, done);
|
|
175
|
+
return;
|
|
176
|
+
}
|
|
177
|
+
if (status !== 200) {
|
|
178
|
+
response.resume();
|
|
179
|
+
done(new Error(`HTTP ${status}`));
|
|
180
|
+
return;
|
|
181
|
+
}
|
|
182
|
+
const file = fs.createWriteStream(destination, { mode: 0o755 });
|
|
183
|
+
response.pipe(file);
|
|
184
|
+
file.on("finish", () => file.close(done));
|
|
185
|
+
file.on("error", done);
|
|
186
|
+
});
|
|
187
|
+
request.on("error", done);
|
|
188
|
+
request.setTimeout(120000, () => request.destroy(new Error("download timed out")));
|
|
189
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
const fs = require("node:fs");
|
|
4
|
+
const path = require("node:path");
|
|
5
|
+
|
|
6
|
+
const root = path.resolve(__dirname, "..", "..", "..");
|
|
7
|
+
const pkgRoot = path.resolve(__dirname, "..");
|
|
8
|
+
const distDir = path.join(root, "dist");
|
|
9
|
+
const vendorDir = path.join(pkgRoot, "vendor");
|
|
10
|
+
const assets = [
|
|
11
|
+
"settle-darwin-arm64",
|
|
12
|
+
"settle-darwin-x64",
|
|
13
|
+
"settle-linux-arm64",
|
|
14
|
+
"settle-linux-x64",
|
|
15
|
+
"settle-win32-arm64.exe",
|
|
16
|
+
"settle-win32-x64.exe",
|
|
17
|
+
];
|
|
18
|
+
|
|
19
|
+
if (process.env.SETTLEKIT_SKIP_VENDOR_STAGE === "1") {
|
|
20
|
+
console.log("settle: skipping bundled binary staging because SETTLEKIT_SKIP_VENDOR_STAGE=1");
|
|
21
|
+
process.exit(0);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
if (!fs.existsSync(distDir)) {
|
|
25
|
+
console.warn("settle: dist/ was not found; npm package will rely on release download fallback");
|
|
26
|
+
process.exit(0);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
fs.mkdirSync(vendorDir, { recursive: true });
|
|
30
|
+
cleanupVendor();
|
|
31
|
+
|
|
32
|
+
for (const asset of assets) {
|
|
33
|
+
const source = path.join(distDir, asset);
|
|
34
|
+
const checksum = `${source}.sha256`;
|
|
35
|
+
if (!fs.existsSync(source) || !fs.existsSync(checksum)) {
|
|
36
|
+
throw new Error(`missing release asset or checksum for ${asset}; run make cli-release first`);
|
|
37
|
+
}
|
|
38
|
+
fs.copyFileSync(source, path.join(vendorDir, asset));
|
|
39
|
+
fs.copyFileSync(checksum, path.join(vendorDir, `${asset}.sha256`));
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
console.log(`settle: staged ${assets.length} bundled CLI binaries`);
|
|
43
|
+
|
|
44
|
+
function cleanupVendor() {
|
|
45
|
+
for (const asset of assets) {
|
|
46
|
+
fs.rmSync(path.join(vendorDir, asset), { force: true });
|
|
47
|
+
fs.rmSync(path.join(vendorDir, `${asset}.sha256`), { force: true });
|
|
48
|
+
}
|
|
49
|
+
}
|
|
Binary file
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
31e93db71c2ad07319f827a675e65caaa5193a7a94430016bc1f8ca2f08a1345
|
|
Binary file
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
1532c4535ce91c58517731da64431b844651f57158a54de7a78f4d603f5fd127
|
|
Binary file
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
c2c5e1496f78fdd2a7ec0ecbea1b352dd73be617aacb3691f6345690cb6db443
|
|
Binary file
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
fdeb89c62e701963b8b87f8413bcc3f4b6efb885d5872e47719079d1ea892b97
|
|
Binary file
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
6fc51dd2dadf7543dee4786d147a9ef2a34a6ff03f84be177ebd1776715e25de
|
|
Binary file
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
98f51ba91d2ec9a7937ed7426c079145fddf730ff7bb912793b535171d657889
|