@qvac/ggml-rpc-server 0.1.1 → 0.3.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/CHANGELOG.md +35 -0
- package/README.md +13 -0
- package/binding.js +1 -1
- package/index.js +7 -15
- package/package.json +30 -6
- package/prebuilds/android-arm64/qvac__ggml-rpc-server.bare +0 -0
- package/prebuilds/darwin-arm64/qvac__ggml-rpc-server.bare +0 -0
- package/prebuilds/darwin-arm64/qvac__ggml-rpc-server.bare.exports +11 -2
- package/prebuilds/darwin-x64/qvac__ggml-rpc-server.bare +0 -0
- package/prebuilds/darwin-x64/qvac__ggml-rpc-server.bare.exports +11 -2
- package/prebuilds/ios-arm64/qvac__ggml-rpc-server.bare +0 -0
- package/prebuilds/ios-arm64/qvac__ggml-rpc-server.bare.exports +12 -3
- package/prebuilds/ios-arm64-simulator/qvac__ggml-rpc-server.bare +0 -0
- package/prebuilds/ios-arm64-simulator/qvac__ggml-rpc-server.bare.exports +12 -3
- package/prebuilds/ios-x64-simulator/qvac__ggml-rpc-server.bare +0 -0
- package/prebuilds/ios-x64-simulator/qvac__ggml-rpc-server.bare.exports +12 -3
- package/prebuilds/linux-arm64/qvac__ggml-rpc-server.bare +0 -0
- package/prebuilds/linux-x64/qvac__ggml-rpc-server.bare +0 -0
- package/prebuilds/win32-x64/qvac__ggml-rpc-server.bare +0 -0
- package/prebuilds/win32-x64/qvac__ggml-rpc-server.bare.exports +0 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,40 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.3.0] - 2026-10-14
|
|
4
|
+
|
|
5
|
+
### Breaking
|
|
6
|
+
|
|
7
|
+
- An explicit `backendsDir` is scanned as given. It is no longer a prebuilds
|
|
8
|
+
root with `<host>/qvac__fabric` appended. Omit it and `@qvac/fabric` locates
|
|
9
|
+
the backends it ships, next to its runtime.
|
|
10
|
+
|
|
11
|
+
### Changed
|
|
12
|
+
|
|
13
|
+
- `@qvac/fabric` dependency bumped `^0.20.0` -> `^0.21.1`, whose platform
|
|
14
|
+
packages are now ordinary addons. This package declares them itself: the
|
|
15
|
+
desktop ones as `optionalDependencies`, and `@qvac/fabric-android-arm64` and
|
|
16
|
+
`@qvac/fabric-ios` as optional `peerDependencies`.
|
|
17
|
+
- Mobile apps must move `@qvac/fabric` and `@qvac/fabric-android-arm64` or
|
|
18
|
+
`@qvac/fabric-ios` to `0.21.1` together.
|
|
19
|
+
|
|
20
|
+
## [0.2.0] - 2026-10-06
|
|
21
|
+
|
|
22
|
+
### Changed
|
|
23
|
+
|
|
24
|
+
- `@qvac/fabric` dependency bumped `^0.19.0` -> `^0.20.0`, which carries
|
|
25
|
+
`qvac-fabric` `10549.5.0` -> `11018.0.0`, the rebase onto upstream llama.cpp
|
|
26
|
+
b11018. This package consumes the shared runtime via npm rather than building
|
|
27
|
+
the vcpkg port, so the range bump is what picks up the new fabric. A caret on
|
|
28
|
+
a `0.x` version locks the minor, so `^0.19.0` would not have resolved `0.20.0`
|
|
29
|
+
on its own. The RPC protocol stays at 109, so servers and clients on
|
|
30
|
+
fabric 10549.3.0 and later still connect, and servers now keep backend
|
|
31
|
+
tensor extras. No API change.
|
|
32
|
+
- The server lifecycle moved into `rpc-server-core`, which now has C++ unit
|
|
33
|
+
tests, and the package gained desktop integration tests
|
|
34
|
+
([#4769](https://github.com/tetherto/qvac/pull/4769)).
|
|
35
|
+
- Mobile apps must move `@qvac/fabric` and `@qvac/fabric-android-arm64` or
|
|
36
|
+
`@qvac/fabric-ios` to `0.20.0` together.
|
|
37
|
+
|
|
3
38
|
## [0.1.1] - 2026-09-30
|
|
4
39
|
|
|
5
40
|
### Changed
|
package/README.md
CHANGED
|
@@ -97,3 +97,16 @@ console.log(server.rdmaCapable)
|
|
|
97
97
|
|
|
98
98
|
Without `expectRdma`, the server starts either way and reports the backend's
|
|
99
99
|
capability in `rdmaCapable`.
|
|
100
|
+
|
|
101
|
+
## Testing
|
|
102
|
+
|
|
103
|
+
```bash
|
|
104
|
+
npm run test:unit # JS unit tests against a mocked binding
|
|
105
|
+
npm run test:cpp # C++ unit tests (GoogleTest)
|
|
106
|
+
npm run test:integration # desktop integration tests against prebuilds/
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
On a PR, `on-pr-nx.yml` runs the C++ tests with the `run-cpp-addon-tests` label
|
|
110
|
+
and the desktop integration tests with the `run-desktop-addon-tests` label. Their
|
|
111
|
+
platforms and runner setup live in the `test:cpp` and `test:integration`
|
|
112
|
+
targets of `project.json`.
|
package/binding.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// Pre-load @qvac/fabric so its shared .bare module (the llama.cpp + ggml
|
|
2
2
|
// runtime) is registered with the bare runtime before our addon resolves its
|
|
3
|
-
// DT_NEEDED dependency qvac__fabric
|
|
3
|
+
// DT_NEEDED dependency qvac__fabric-<host>@0.bare (shipped by @qvac/fabric-<host>).
|
|
4
4
|
require("@qvac/fabric");
|
|
5
5
|
|
|
6
6
|
module.exports = require.addon();
|
package/index.js
CHANGED
|
@@ -16,8 +16,6 @@ exports.allocateFreePort = allocateFreePort;
|
|
|
16
16
|
exports.startRpcServer = startRpcServer;
|
|
17
17
|
/* eslint-disable @typescript-eslint/no-require-imports -- Bare modules and native bindings expose CommonJS export shapes. */
|
|
18
18
|
const net = require("bare-net");
|
|
19
|
-
const path = require("bare-path");
|
|
20
|
-
const fabricBackends = require("@qvac/fabric/backends");
|
|
21
19
|
const binding = require("./binding");
|
|
22
20
|
/* eslint-enable @typescript-eslint/no-require-imports */
|
|
23
21
|
exports.DEFAULT_RPC_SERVER_HOST = "127.0.0.1";
|
|
@@ -27,7 +25,7 @@ const TRUSTED_LAN_WARNING_CODE = "QVAC_GGML_RPC_SERVER_TRUSTED_LAN";
|
|
|
27
25
|
const activeServerHandles = new Set();
|
|
28
26
|
// Fabric never unloads its RPC module, so its RDMA build cannot change within a
|
|
29
27
|
// process. Cache the native check, which reads the module from disk.
|
|
30
|
-
|
|
28
|
+
let rdmaSupport;
|
|
31
29
|
class RpcServerPortAllocationError extends Error {
|
|
32
30
|
constructor(cause) {
|
|
33
31
|
super("Failed to allocate a free port for ggml-rpc-server", { cause });
|
|
@@ -194,17 +192,16 @@ function validateThreads(threads) {
|
|
|
194
192
|
throw new TypeError("threads must be a positive integer");
|
|
195
193
|
}
|
|
196
194
|
}
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
if (
|
|
195
|
+
// The RPC module @qvac/fabric loads, from wherever fabric ships its backends.
|
|
196
|
+
function rpcBackendSupportsRdma() {
|
|
197
|
+
if (rdmaSupport === undefined) {
|
|
200
198
|
try {
|
|
201
|
-
|
|
199
|
+
rdmaSupport = binding.rpcBackendSupportsRdma({});
|
|
202
200
|
} catch (error) {
|
|
203
201
|
throw toTypedError(error);
|
|
204
202
|
}
|
|
205
|
-
rdmaSupportByBackendsDir.set(backendsDir, supported);
|
|
206
203
|
}
|
|
207
|
-
return
|
|
204
|
+
return rdmaSupport;
|
|
208
205
|
}
|
|
209
206
|
function allocateFreePort(
|
|
210
207
|
host = exports.DEFAULT_RPC_SERVER_HOST,
|
|
@@ -234,11 +231,7 @@ async function startRpcServer(options = {}) {
|
|
|
234
231
|
assertLoopbackHost(host, options.allowNonLoopbackHost);
|
|
235
232
|
warnForTrustedLanHost(host, options.allowNonLoopbackHost);
|
|
236
233
|
validateThreads(options.threads);
|
|
237
|
-
|
|
238
|
-
// packagers stage Fabric's backends beside this addon instead.
|
|
239
|
-
const backendsDir =
|
|
240
|
-
fabricBackends.resolveBackendsDir() ?? path.join(__dirname, "prebuilds");
|
|
241
|
-
const rdmaCapable = rpcBackendSupportsRdma(backendsDir);
|
|
234
|
+
const rdmaCapable = rpcBackendSupportsRdma();
|
|
242
235
|
if (options.expectRdma === true && !rdmaCapable) {
|
|
243
236
|
throw new RpcServerRdmaUnavailableError();
|
|
244
237
|
}
|
|
@@ -255,7 +248,6 @@ async function startRpcServer(options = {}) {
|
|
|
255
248
|
device,
|
|
256
249
|
cache: options.cache ?? false,
|
|
257
250
|
threads: options.threads,
|
|
258
|
-
backendsDir,
|
|
259
251
|
}),
|
|
260
252
|
);
|
|
261
253
|
activeServerHandles.add(handle);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@qvac/ggml-rpc-server",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "Managed ggml RPC server for QVAC LLM inference",
|
|
5
5
|
"addon": true,
|
|
6
6
|
"scripts": {
|
|
@@ -13,11 +13,15 @@
|
|
|
13
13
|
"lint:js": "prettier --check \"**/*.{js,cjs,mjs}\" && lunte",
|
|
14
14
|
"lint:ts": "eslint \"src/**/*.ts\" --max-warnings=0",
|
|
15
15
|
"lint:ts:fix": "eslint \"src/**/*.ts\" --fix",
|
|
16
|
-
"lint-cpp": "clang-tidy -p build addon/binding.cpp",
|
|
16
|
+
"lint-cpp": "clang-tidy -p build addon/binding.cpp addon/rpc-server-core.cpp",
|
|
17
17
|
"format": "prettier --write \"**/*.{js,cjs,mjs}\"",
|
|
18
18
|
"test": "npm run build:ts && npm run test:node",
|
|
19
19
|
"test:node": "node --test test/node/*.test.cjs",
|
|
20
20
|
"test:unit": "npm run test:node",
|
|
21
|
+
"test:integration": "bare test/integration/rpc-server.test.js",
|
|
22
|
+
"test:cpp:build": "bare-make generate -D BUILD_TESTING=ON && bare-make build --target addon-test",
|
|
23
|
+
"test:cpp:run": "node scripts/run-cpp-tests.js",
|
|
24
|
+
"test:cpp": "npm run test:cpp:build && npm run test:cpp:run",
|
|
21
25
|
"test:types": "npm run typecheck && npm run check:generated",
|
|
22
26
|
"test:dts": "npm run test:types"
|
|
23
27
|
},
|
|
@@ -41,10 +45,11 @@
|
|
|
41
45
|
"bugs": "https://github.com/tetherto/qvac/issues",
|
|
42
46
|
"homepage": "https://github.com/tetherto/qvac/tree/main/packages/ggml-rpc-server#readme",
|
|
43
47
|
"devDependencies": {
|
|
44
|
-
"@qvac/fabric-android-arm64": "0.
|
|
45
|
-
"@qvac/fabric-ios": "0.
|
|
48
|
+
"@qvac/fabric-android-arm64": "0.21.1",
|
|
49
|
+
"@qvac/fabric-ios": "0.21.1",
|
|
46
50
|
"@types/node": "^24.2.1",
|
|
47
|
-
"
|
|
51
|
+
"brittle": "^3.17.0",
|
|
52
|
+
"cmake-bare": "^1.9.0",
|
|
48
53
|
"cmake-npm": "^1.1.0",
|
|
49
54
|
"cmake-vcpkg": "^1.1.0",
|
|
50
55
|
"eslint": "^9.39.4",
|
|
@@ -57,10 +62,29 @@
|
|
|
57
62
|
"typescript-eslint": "^8.63.0"
|
|
58
63
|
},
|
|
59
64
|
"dependencies": {
|
|
60
|
-
"@qvac/fabric": "^0.
|
|
65
|
+
"@qvac/fabric": "^0.21.1",
|
|
61
66
|
"bare-net": "^2.3.2",
|
|
62
67
|
"bare-path": "^3.0.0"
|
|
63
68
|
},
|
|
69
|
+
"optionalDependencies": {
|
|
70
|
+
"@qvac/fabric-linux-x64": "^0.21.1",
|
|
71
|
+
"@qvac/fabric-linux-arm64": "^0.21.1",
|
|
72
|
+
"@qvac/fabric-darwin-arm64": "^0.21.1",
|
|
73
|
+
"@qvac/fabric-darwin-x64": "^0.21.1",
|
|
74
|
+
"@qvac/fabric-win32-x64": "^0.21.1"
|
|
75
|
+
},
|
|
76
|
+
"peerDependencies": {
|
|
77
|
+
"@qvac/fabric-android-arm64": "^0.21.1",
|
|
78
|
+
"@qvac/fabric-ios": "^0.21.1"
|
|
79
|
+
},
|
|
80
|
+
"peerDependenciesMeta": {
|
|
81
|
+
"@qvac/fabric-android-arm64": {
|
|
82
|
+
"optional": true
|
|
83
|
+
},
|
|
84
|
+
"@qvac/fabric-ios": {
|
|
85
|
+
"optional": true
|
|
86
|
+
}
|
|
87
|
+
},
|
|
64
88
|
"engines": {
|
|
65
89
|
"bare": ">=1.24.0"
|
|
66
90
|
},
|
|
Binary file
|
|
Binary file
|
|
@@ -7,15 +7,24 @@
|
|
|
7
7
|
],
|
|
8
8
|
"current_versions": [
|
|
9
9
|
{
|
|
10
|
-
"version": "0.
|
|
10
|
+
"version": "0.3"
|
|
11
11
|
}
|
|
12
12
|
],
|
|
13
13
|
"exported_symbols": [
|
|
14
14
|
{
|
|
15
15
|
"text": {
|
|
16
16
|
"global": [
|
|
17
|
+
"__ZN10rpc_server23rpcBackendHasRdmaMarkerERKNSt3__14__fs10filesystem4pathE",
|
|
18
|
+
"__ZN10rpc_server12ServerRunner4stopEv",
|
|
19
|
+
"__ZN10rpc_server13selectDevicesERKNSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEE",
|
|
17
20
|
"_bare_register_module_v0",
|
|
18
|
-
"
|
|
21
|
+
"__ZN10rpc_server12ServerRunnerC1EP23ggml_backend_rpc_serverNS_12RpcServerApiE",
|
|
22
|
+
"__ZN10rpc_server12ServerRunnerD2Ev",
|
|
23
|
+
"__ZN10rpc_server19resolveRpcServerApiEv",
|
|
24
|
+
"_bare_get_module_name_v0",
|
|
25
|
+
"__ZN10rpc_server21defaultCacheDirectoryEv",
|
|
26
|
+
"__ZN10rpc_server12ServerRunnerC2EP23ggml_backend_rpc_serverNS_12RpcServerApiE",
|
|
27
|
+
"__ZN10rpc_server12ServerRunnerD1Ev"
|
|
19
28
|
]
|
|
20
29
|
}
|
|
21
30
|
}
|
|
Binary file
|
|
@@ -7,15 +7,24 @@
|
|
|
7
7
|
],
|
|
8
8
|
"current_versions": [
|
|
9
9
|
{
|
|
10
|
-
"version": "0.
|
|
10
|
+
"version": "0.3"
|
|
11
11
|
}
|
|
12
12
|
],
|
|
13
13
|
"exported_symbols": [
|
|
14
14
|
{
|
|
15
15
|
"text": {
|
|
16
16
|
"global": [
|
|
17
|
+
"__ZN10rpc_server23rpcBackendHasRdmaMarkerERKNSt3__14__fs10filesystem4pathE",
|
|
18
|
+
"__ZN10rpc_server12ServerRunner4stopEv",
|
|
19
|
+
"__ZN10rpc_server13selectDevicesERKNSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEE",
|
|
17
20
|
"_bare_register_module_v0",
|
|
18
|
-
"
|
|
21
|
+
"__ZN10rpc_server12ServerRunnerC1EP23ggml_backend_rpc_serverNS_12RpcServerApiE",
|
|
22
|
+
"__ZN10rpc_server12ServerRunnerD2Ev",
|
|
23
|
+
"__ZN10rpc_server19resolveRpcServerApiEv",
|
|
24
|
+
"_bare_get_module_name_v0",
|
|
25
|
+
"__ZN10rpc_server21defaultCacheDirectoryEv",
|
|
26
|
+
"__ZN10rpc_server12ServerRunnerC2EP23ggml_backend_rpc_serverNS_12RpcServerApiE",
|
|
27
|
+
"__ZN10rpc_server12ServerRunnerD1Ev"
|
|
19
28
|
]
|
|
20
29
|
}
|
|
21
30
|
}
|
|
Binary file
|
|
@@ -7,15 +7,24 @@
|
|
|
7
7
|
],
|
|
8
8
|
"current_versions": [
|
|
9
9
|
{
|
|
10
|
-
"version": "0.
|
|
10
|
+
"version": "0.3"
|
|
11
11
|
}
|
|
12
12
|
],
|
|
13
13
|
"exported_symbols": [
|
|
14
14
|
{
|
|
15
15
|
"text": {
|
|
16
16
|
"global": [
|
|
17
|
+
"__ZN10rpc_server23rpcBackendHasRdmaMarkerERKNSt3__14__fs10filesystem4pathE",
|
|
18
|
+
"__ZN10rpc_server12ServerRunner4stopEv",
|
|
19
|
+
"__ZN10rpc_server13selectDevicesERKNSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEE",
|
|
17
20
|
"_bare_register_module_v0",
|
|
18
|
-
"
|
|
21
|
+
"__ZN10rpc_server12ServerRunnerC1EP23ggml_backend_rpc_serverNS_12RpcServerApiE",
|
|
22
|
+
"__ZN10rpc_server12ServerRunnerD2Ev",
|
|
23
|
+
"__ZN10rpc_server19resolveRpcServerApiEv",
|
|
24
|
+
"_bare_get_module_name_v0",
|
|
25
|
+
"__ZN10rpc_server21defaultCacheDirectoryEv",
|
|
26
|
+
"__ZN10rpc_server12ServerRunnerC2EP23ggml_backend_rpc_serverNS_12RpcServerApiE",
|
|
27
|
+
"__ZN10rpc_server12ServerRunnerD1Ev"
|
|
19
28
|
]
|
|
20
29
|
}
|
|
21
30
|
}
|
|
@@ -34,7 +43,7 @@
|
|
|
34
43
|
],
|
|
35
44
|
"target_info": [
|
|
36
45
|
{
|
|
37
|
-
"min_deployment": "
|
|
46
|
+
"min_deployment": "15",
|
|
38
47
|
"target": "arm64-ios"
|
|
39
48
|
}
|
|
40
49
|
]
|
|
Binary file
|
|
@@ -7,15 +7,24 @@
|
|
|
7
7
|
],
|
|
8
8
|
"current_versions": [
|
|
9
9
|
{
|
|
10
|
-
"version": "0.
|
|
10
|
+
"version": "0.3"
|
|
11
11
|
}
|
|
12
12
|
],
|
|
13
13
|
"exported_symbols": [
|
|
14
14
|
{
|
|
15
15
|
"text": {
|
|
16
16
|
"global": [
|
|
17
|
+
"__ZN10rpc_server23rpcBackendHasRdmaMarkerERKNSt3__14__fs10filesystem4pathE",
|
|
18
|
+
"__ZN10rpc_server12ServerRunner4stopEv",
|
|
19
|
+
"__ZN10rpc_server13selectDevicesERKNSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEE",
|
|
17
20
|
"_bare_register_module_v0",
|
|
18
|
-
"
|
|
21
|
+
"__ZN10rpc_server12ServerRunnerC1EP23ggml_backend_rpc_serverNS_12RpcServerApiE",
|
|
22
|
+
"__ZN10rpc_server12ServerRunnerD2Ev",
|
|
23
|
+
"__ZN10rpc_server19resolveRpcServerApiEv",
|
|
24
|
+
"_bare_get_module_name_v0",
|
|
25
|
+
"__ZN10rpc_server21defaultCacheDirectoryEv",
|
|
26
|
+
"__ZN10rpc_server12ServerRunnerC2EP23ggml_backend_rpc_serverNS_12RpcServerApiE",
|
|
27
|
+
"__ZN10rpc_server12ServerRunnerD1Ev"
|
|
19
28
|
]
|
|
20
29
|
}
|
|
21
30
|
}
|
|
@@ -34,7 +43,7 @@
|
|
|
34
43
|
],
|
|
35
44
|
"target_info": [
|
|
36
45
|
{
|
|
37
|
-
"min_deployment": "
|
|
46
|
+
"min_deployment": "15",
|
|
38
47
|
"target": "arm64-ios-simulator"
|
|
39
48
|
}
|
|
40
49
|
]
|
|
Binary file
|
|
@@ -7,15 +7,24 @@
|
|
|
7
7
|
],
|
|
8
8
|
"current_versions": [
|
|
9
9
|
{
|
|
10
|
-
"version": "0.
|
|
10
|
+
"version": "0.3"
|
|
11
11
|
}
|
|
12
12
|
],
|
|
13
13
|
"exported_symbols": [
|
|
14
14
|
{
|
|
15
15
|
"text": {
|
|
16
16
|
"global": [
|
|
17
|
+
"__ZN10rpc_server23rpcBackendHasRdmaMarkerERKNSt3__14__fs10filesystem4pathE",
|
|
18
|
+
"__ZN10rpc_server12ServerRunner4stopEv",
|
|
19
|
+
"__ZN10rpc_server13selectDevicesERKNSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEE",
|
|
17
20
|
"_bare_register_module_v0",
|
|
18
|
-
"
|
|
21
|
+
"__ZN10rpc_server12ServerRunnerC1EP23ggml_backend_rpc_serverNS_12RpcServerApiE",
|
|
22
|
+
"__ZN10rpc_server12ServerRunnerD2Ev",
|
|
23
|
+
"__ZN10rpc_server19resolveRpcServerApiEv",
|
|
24
|
+
"_bare_get_module_name_v0",
|
|
25
|
+
"__ZN10rpc_server21defaultCacheDirectoryEv",
|
|
26
|
+
"__ZN10rpc_server12ServerRunnerC2EP23ggml_backend_rpc_serverNS_12RpcServerApiE",
|
|
27
|
+
"__ZN10rpc_server12ServerRunnerD1Ev"
|
|
19
28
|
]
|
|
20
29
|
}
|
|
21
30
|
}
|
|
@@ -34,7 +43,7 @@
|
|
|
34
43
|
],
|
|
35
44
|
"target_info": [
|
|
36
45
|
{
|
|
37
|
-
"min_deployment": "
|
|
46
|
+
"min_deployment": "15",
|
|
38
47
|
"target": "x86_64-ios-simulator"
|
|
39
48
|
}
|
|
40
49
|
]
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|