settlemesh 0.1.34

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 ADDED
@@ -0,0 +1,178 @@
1
+ # SettleMesh CLI
2
+
3
+ SettleMesh is a CLI-first tool platform for developers, scripts, and AI agents. The npm package and primary command are both `settlemesh`.
4
+
5
+ ## Install
6
+
7
+ For AI agents, clean terminals, and project-specific deploys, prefer a project-local latest install. This avoids stale global binaries:
8
+
9
+ ```bash
10
+ npm install settlemesh@latest --prefer-online
11
+ ./node_modules/.bin/settlemesh doctor --require-latest
12
+ ./node_modules/.bin/settlemesh recipes
13
+ ```
14
+
15
+ Global install is also supported for interactive use:
16
+
17
+ ```bash
18
+ npm install -g settlemesh
19
+ settlemesh doctor
20
+ ```
21
+
22
+ The package exposes compatibility aliases:
23
+
24
+ ```bash
25
+ settlemesh --version
26
+ settle --version
27
+ settlekit --version
28
+ kit --version
29
+ ```
30
+
31
+ Project-local install also works:
32
+
33
+ ```bash
34
+ npm install settlemesh@latest --prefer-online
35
+ ./node_modules/.bin/settlemesh help
36
+ ```
37
+
38
+ ## Login
39
+
40
+ ```bash
41
+ settlemesh login
42
+ ```
43
+
44
+ For CI, scripts, and hosted agents:
45
+
46
+ ```bash
47
+ export SETTLE_API_KEY="sk_..."
48
+ ```
49
+
50
+ Use `SETTLE_BASE_URL=http://localhost:8080` for local development, and `SETTLE_REQUEST_TIMEOUT=90s` for slow provider calls.
51
+
52
+ ## Use Tools
53
+
54
+ Always use discovery before calling tools:
55
+
56
+ ```bash
57
+ settlemesh help --json
58
+ settlemesh recipes
59
+ settlemesh tool list --json
60
+ settlemesh tool show web.search --json
61
+ ```
62
+
63
+ For a no-context agent, start with the built-in golden paths:
64
+
65
+ ```bash
66
+ npm install settlemesh@latest --prefer-online
67
+ ./node_modules/.bin/settlemesh doctor --require-latest
68
+ ./node_modules/.bin/settlemesh recipes
69
+ ./node_modules/.bin/settlemesh search "build app with login database api command"
70
+ ./node_modules/.bin/settlemesh services show app-project-backends --json
71
+ ```
72
+
73
+ `settlemesh recipes` covers the shortest flows for full-stack app deploys, App API/CLI commands, browser bridge URLs, hosted agents, and local worker offers.
74
+
75
+ Call a tool with JSON input:
76
+
77
+ ```bash
78
+ settlemesh tool call web.search \
79
+ --input '{"q":"SettleMesh","count":5}' \
80
+ --json
81
+ ```
82
+
83
+ Generate an image task:
84
+
85
+ ```bash
86
+ settlemesh tool call image.gpt-image-2 \
87
+ --input '{"prompt":"A clean product photo of a ceramic tea cup","size":"1:1"}' \
88
+ --json
89
+ ```
90
+
91
+ Poll async media:
92
+
93
+ ```bash
94
+ settlemesh tool events image_... --json
95
+ ```
96
+
97
+ Upload a local image for image-to-image:
98
+
99
+ ```bash
100
+ settlemesh files upload ./input.png --json
101
+ settlemesh tool call image.gpt-image-2 \
102
+ --input '{"prompt":"Turn this into a clean product photo","size":"1:1"}' \
103
+ --image-file ./input.png \
104
+ --json
105
+ ```
106
+
107
+ ## Credits
108
+
109
+ ```bash
110
+ settlemesh credits balance --json
111
+ settlemesh credits ledger --json
112
+ settlemesh credits topup --credits 100 --json
113
+ ```
114
+
115
+ ## Hosted Agents
116
+
117
+ Create from a built-in template and make it callable by other accounts:
118
+
119
+ ```bash
120
+ settlemesh agents templates --json
121
+ settlemesh agents create \
122
+ --name research-helper \
123
+ --template hermes \
124
+ --public \
125
+ --max-budget 50 \
126
+ --allowed-capabilities web.search,web.scrape,llm.chat \
127
+ --json
128
+ settlemesh agents invoke agent_... --input '{"prompt":"Find three primary sources."}' --json
129
+ ```
130
+
131
+ You can share the returned `agent_id`; other users can call public agents directly by id with `settlemesh agents invoke` or `settlemesh tool call agent.invoke`.
132
+
133
+ ## Managed Backends
134
+
135
+ Create a SettleMesh project with database + app auth:
136
+
137
+ ```bash
138
+ settlemesh projects create --name demo --db sqlite --auth email_password,magic_link
139
+ settlemesh db query proj_... --sql "select 1"
140
+ settlemesh db migrate proj_... --file schema.sql
141
+ settlemesh db connection proj_...
142
+ settlemesh auth users proj_...
143
+ ```
144
+
145
+ `settlemesh db connection` is redacted by default. Add `--reveal` only in a trusted terminal. Database SQL endpoints accept a developer key or the one-time project server key returned by `projects create`; browser/public project keys are only for app auth.
146
+
147
+ ## Full-stack Apps, App APIs, and CLI Commands
148
+
149
+ Deploy a local app project with SettleMesh auth, database, runtime API keys, and optional payment bindings:
150
+
151
+ ```bash
152
+ ./node_modules/.bin/settlemesh deploy ./my-next-app --name my-next-app --full-stack --wait --json
153
+ ```
154
+
155
+ Expose selected routes from that app as APIs and CLI commands:
156
+
157
+ ```bash
158
+ settlemesh apps api publish app_... --file app-api.json --json
159
+ settlemesh apps api call app_... summarize --input '{"topic":"shipping"}' --json
160
+ settlemesh apps commands publish app_... --file app-commands.json --json
161
+ settlemesh run app:app_....summarize --input '{"topic":"shipping"}' --open --json
162
+ ```
163
+
164
+ When a command has a web binding, `--open` can return a short-lived URL that opens the app in the browser using the caller's Settle login, without a second manual login.
165
+
166
+ ## Local Worker Offers
167
+
168
+ Share a local OpenAI-compatible endpoint as a callable service:
169
+
170
+ ```bash
171
+ settlemesh search "lend local compute worker offer"
172
+ settlemesh worker start --name local-model --public --model local/model --endpoint http://localhost:11434/v1/chat/completions --credits-per-second 0.05
173
+ settlemesh worker-offers list --json
174
+ ```
175
+
176
+ ## Public Tool Surface
177
+
178
+ The public CLI surface includes discovery, tools, full-stack app deployment, App APIs/commands, hosted agents, local worker offers, credits, files, and managed project/database/auth operations. Provider-specific operations may still be gated on a given deployment. Inspect each tool's `availability`, `policy`, and `input_schema` before side-effecting or costly calls.
package/bin/settle.js ADDED
@@ -0,0 +1,80 @@
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 pkg = require(path.join(__dirname, "..", "package.json"));
8
+ const binaryOverride = process.env.SETTLEKIT_CLI_BINARY;
9
+ const binaryName = process.platform === "win32" ? "settle.exe" : "settle";
10
+ const binaryPath = binaryOverride || path.join(__dirname, "..", "vendor", binaryName);
11
+ const commandName = path.basename(process.argv[1] || "settlemesh").replace(/\.cmd$/i, "");
12
+
13
+ if (!fs.existsSync(binaryPath)) {
14
+ console.error(`${commandName}: CLI binary was not found.`);
15
+ console.error("Run `npm rebuild -g settlemesh` or reinstall with `npm install -g settlemesh`.");
16
+ if (process.env.SETTLEKIT_CLI_RELEASE_BASE || process.env.SETTLEKIT_CLI_RELEASE_TAG) {
17
+ console.error("Check SETTLEKIT_CLI_RELEASE_BASE and SETTLEKIT_CLI_RELEASE_TAG.");
18
+ }
19
+ process.exit(1);
20
+ }
21
+
22
+ maybeWarnForStalePackage();
23
+
24
+ const env = {
25
+ ...process.env,
26
+ SETTLEKIT_NPM_PACKAGE_VERSION: process.env.SETTLEKIT_NPM_PACKAGE_VERSION || pkg.version,
27
+ SETTLEKIT_NPM_PACKAGE_ROOT: process.env.SETTLEKIT_NPM_PACKAGE_ROOT || path.join(__dirname, ".."),
28
+ SETTLE_CLI_NAME: process.env.SETTLE_CLI_NAME || commandName,
29
+ };
30
+
31
+ const result = spawnSync(binaryPath, process.argv.slice(2), {
32
+ stdio: "inherit",
33
+ env,
34
+ });
35
+
36
+ if (result.error) {
37
+ console.error(`${commandName}: ${result.error.message}`);
38
+ process.exit(1);
39
+ }
40
+
41
+ process.exit(result.status ?? 0);
42
+
43
+ function maybeWarnForStalePackage() {
44
+ if (process.env.SETTLEKIT_SKIP_VERSION_CHECK === "1") {
45
+ return;
46
+ }
47
+ const command = process.argv[2] || "";
48
+ const shouldCheck = new Set(["deploy", "recipes", "quickstart", "doctor", "version", "--version", "-v"]);
49
+ if (!shouldCheck.has(command)) {
50
+ return;
51
+ }
52
+ const npm = process.platform === "win32" ? "npm.cmd" : "npm";
53
+ const result = spawnSync(npm, ["view", pkg.name || "settlemesh", "version", "--silent"], {
54
+ encoding: "utf8",
55
+ timeout: 2500,
56
+ stdio: ["ignore", "pipe", "ignore"],
57
+ });
58
+ if (result.error || result.status !== 0) {
59
+ return;
60
+ }
61
+ const latest = String(result.stdout || "").trim().split(/\s+/)[0];
62
+ if (!latest || compareVersions(pkg.version, latest) >= 0) {
63
+ return;
64
+ }
65
+ console.error(`${commandName}: warning: npm package ${pkg.name}@${pkg.version} is older than latest ${latest}.`);
66
+ console.error(`${commandName}: for agent/bootstrap flows, run \`npm install settlemesh@latest --prefer-online\` and use \`./node_modules/.bin/settlemesh\`.`);
67
+ }
68
+
69
+ function compareVersions(left, right) {
70
+ const a = String(left || "").split(".").map((part) => parseInt(part, 10) || 0);
71
+ const b = String(right || "").split(".").map((part) => parseInt(part, 10) || 0);
72
+ const n = Math.max(a.length, b.length);
73
+ for (let i = 0; i < n; i++) {
74
+ const diff = (a[i] || 0) - (b[i] || 0);
75
+ if (diff !== 0) {
76
+ return diff;
77
+ }
78
+ }
79
+ return 0;
80
+ }
package/package.json ADDED
@@ -0,0 +1,58 @@
1
+ {
2
+ "name": "settlemesh",
3
+ "version": "0.1.34",
4
+ "description": "SettleMesh CLI for services, models, apps, agents, workers, and credits",
5
+ "license": "UNLICENSED",
6
+ "homepage": "https://settlemesh.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
+ "settlemesh",
17
+ "settlekit",
18
+ "cli",
19
+ "agent",
20
+ "ai",
21
+ "tools"
22
+ ],
23
+ "publishConfig": {
24
+ "access": "public"
25
+ },
26
+ "bin": {
27
+ "kit": "bin/settle.js",
28
+ "settle": "bin/settle.js",
29
+ "settlemesh": "bin/settle.js",
30
+ "settlekit": "bin/settle.js"
31
+ },
32
+ "scripts": {
33
+ "prepack": "node scripts/stage-binaries.js",
34
+ "postpack": "node scripts/clean-staged-binaries.js",
35
+ "postinstall": "node scripts/install.js"
36
+ },
37
+ "files": [
38
+ "bin/",
39
+ "scripts/",
40
+ "vendor/",
41
+ "README.md"
42
+ ],
43
+ "config": {
44
+ "release_base": "https://github.com/CalLeeLQY/SettleKit/releases/download"
45
+ },
46
+ "engines": {
47
+ "node": ">=18"
48
+ },
49
+ "os": [
50
+ "darwin",
51
+ "linux",
52
+ "win32"
53
+ ],
54
+ "cpu": [
55
+ "x64",
56
+ "arm64"
57
+ ]
58
+ }
@@ -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("settlemesh: 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(`settlemesh: installed bundled ${assetName}`);
45
+ process.exit(0);
46
+ } catch (err) {
47
+ console.error(`settlemesh: bundled ${assetName} failed verification`);
48
+ console.error(`settlemesh: ${err.message}`);
49
+ process.exit(1);
50
+ }
51
+ }
52
+
53
+ download(url, tmp, 0, (err) => {
54
+ if (err) {
55
+ console.error(`settlemesh: failed to download ${assetName}`);
56
+ console.error(`settlemesh: ${err.message}`);
57
+ console.error(`settlemesh: attempted ${url}`);
58
+ console.error("settlemesh: 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(`settlemesh: failed to download checksum for ${assetName}`);
66
+ console.error(`settlemesh: ${checksumErr.message}`);
67
+ console.error(`settlemesh: attempted ${checksumURL}`);
68
+ console.error("settlemesh: 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(`settlemesh: checksum mismatch for ${assetName}`);
78
+ console.error(`settlemesh: expected ${expected || "(missing checksum)"}`);
79
+ console.error(`settlemesh: 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(`settlemesh: 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("settlemesh: skipping bundled binary staging because SETTLEKIT_SKIP_VENDOR_STAGE=1");
21
+ process.exit(0);
22
+ }
23
+
24
+ if (!fs.existsSync(distDir)) {
25
+ console.warn("settlemesh: 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(`settlemesh: 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
+ 1033476dad68da250fc04a53b6326d6ff4a8fa7a784c037087e12b1e7fd17736
Binary file
@@ -0,0 +1 @@
1
+ c2485074a305314022001f47539836c0c9683fea74752ef945dec74a8553bbfe
Binary file
@@ -0,0 +1 @@
1
+ 6983bdd99ed0b9dd12cecff5e514a3b56d83489f5ce5635944254063680f4311
Binary file
@@ -0,0 +1 @@
1
+ 1284edd5a9d437970f0b60c7d05c3a76e8091061668d7daea7dc7ebb1da35dc5
Binary file
@@ -0,0 +1 @@
1
+ 4d31f80b34a44dcff12f42b0b153c740c0d41082f5b8bc54fa083837f9e17e86
Binary file
@@ -0,0 +1 @@
1
+ de63eaaf0c9edde24ab4607ab167a7733ee43e6f9940cb1fbbfdb516ddd2aede