symmetry-cli 1.0.6 → 1.0.7
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/__test__/cli.test.ts +1 -1
- package/dist/constants.js +2 -1
- package/dist/provider.js +57 -44
- package/install.ps1 +2 -2
- package/install.sh +1 -1
- package/package.json +1 -1
- package/readme.md +2 -2
- package/src/constants.ts +2 -0
- package/src/provider.ts +73 -53
package/__test__/cli.test.ts
CHANGED
package/dist/constants.js
CHANGED
@@ -1,7 +1,8 @@
|
|
1
1
|
"use strict";
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
-
exports.apiProviders = exports.serverMessageKeys = exports.NORMALIZE_REGEX = void 0;
|
3
|
+
exports.apiProviders = exports.serverMessageKeys = exports.PROVIDER_HELLO_TIMEOUT = exports.NORMALIZE_REGEX = void 0;
|
4
4
|
exports.NORMALIZE_REGEX = /\s*\r?\n|\r/g;
|
5
|
+
exports.PROVIDER_HELLO_TIMEOUT = 15000;
|
5
6
|
exports.serverMessageKeys = {
|
6
7
|
challenge: "challenge",
|
7
8
|
conectionSize: "conectionSize",
|
package/dist/provider.js
CHANGED
@@ -22,6 +22,7 @@ class SymmetryProvider {
|
|
22
22
|
this._isPublic = false;
|
23
23
|
this._providerConnections = 0;
|
24
24
|
this._providerSwarm = null;
|
25
|
+
this._serverSwarm = null;
|
25
26
|
this._serverPeer = null;
|
26
27
|
logger_1.logger.info(`🔗 Initializing client using config file: ${configPath}`);
|
27
28
|
this._config = new config_1.ConfigManager(configPath);
|
@@ -50,7 +51,7 @@ class SymmetryProvider {
|
|
50
51
|
if (this._isPublic) {
|
51
52
|
logger_1.logger.info(chalk_1.default.white(`🔑 Server key: ${this._config.get("serverKey")}`));
|
52
53
|
logger_1.logger.info(chalk_1.default.white("🔗 Joining server, please wait."));
|
53
|
-
this.
|
54
|
+
this.joinServer();
|
54
55
|
}
|
55
56
|
process.on("SIGINT", async () => {
|
56
57
|
var _a;
|
@@ -63,62 +64,74 @@ class SymmetryProvider {
|
|
63
64
|
}
|
64
65
|
});
|
65
66
|
}
|
67
|
+
async destroySwarms() {
|
68
|
+
var _a, _b;
|
69
|
+
await ((_a = this._providerSwarm) === null || _a === void 0 ? void 0 : _a.destroy());
|
70
|
+
await ((_b = this._serverSwarm) === null || _b === void 0 ? void 0 : _b.destroy());
|
71
|
+
}
|
66
72
|
async testProviderCall() {
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
const { requestOptions, requestBody } = req;
|
77
|
-
const { protocol, hostname, port, path, method, headers } = requestOptions;
|
78
|
-
const url = `${protocol}://${hostname}:${port}${path}`;
|
79
|
-
logger_1.logger.info(chalk_1.default.white(`🚀 Sending test request to ${url}`));
|
80
|
-
try {
|
81
|
-
const response = await fetch(url, {
|
82
|
-
method,
|
83
|
-
headers,
|
84
|
-
body: JSON.stringify(requestBody),
|
85
|
-
});
|
86
|
-
if (!response.ok) {
|
87
|
-
logger_1.logger.error(chalk_1.default.red(`❌ Server responded with status code: ${response.status}`));
|
88
|
-
throw new Error(`Server responded with status code: ${response.status}`);
|
73
|
+
const testCall = async () => {
|
74
|
+
logger_1.logger.info(chalk_1.default.white(`👋 Saying hello to your provider...`));
|
75
|
+
const testMessages = [
|
76
|
+
{ role: "user", content: "Hello, this is a test message." },
|
77
|
+
];
|
78
|
+
const req = this.buildStreamRequest(testMessages);
|
79
|
+
if (!req) {
|
80
|
+
logger_1.logger.error(chalk_1.default.red("❌ Failed to build test request"));
|
81
|
+
throw new Error("Failed to build test request");
|
89
82
|
}
|
90
|
-
|
91
|
-
|
92
|
-
|
83
|
+
const { requestOptions, requestBody } = req;
|
84
|
+
const { protocol, hostname, port, path, method, headers } = requestOptions;
|
85
|
+
const url = `${protocol}://${hostname}:${port}${path}`;
|
86
|
+
logger_1.logger.info(chalk_1.default.white(`🚀 Sending test request to ${url}`));
|
87
|
+
try {
|
88
|
+
const response = await fetch(url, {
|
89
|
+
method,
|
90
|
+
headers,
|
91
|
+
body: JSON.stringify(requestBody),
|
92
|
+
});
|
93
|
+
if (!response.ok) {
|
94
|
+
logger_1.logger.error(chalk_1.default.red(`❌ Server responded with status code: ${response.status}`));
|
95
|
+
this.destroySwarms();
|
96
|
+
throw new Error(`Server responded with status code: ${response.status}`);
|
97
|
+
}
|
98
|
+
if (!response.body) {
|
99
|
+
logger_1.logger.error(chalk_1.default.red("❌ Failed to get a ReadableStream from the response"));
|
100
|
+
this.destroySwarms();
|
101
|
+
throw new Error("Failed to get a ReadableStream from the response");
|
102
|
+
}
|
103
|
+
logger_1.logger.info(chalk_1.default.white(`📡 Got response, checking stream...`));
|
104
|
+
const reader = response.body.getReader();
|
105
|
+
const { done } = await reader.read();
|
106
|
+
if (done) {
|
107
|
+
logger_1.logger.error(chalk_1.default.red("❌ Stream ended without data"));
|
108
|
+
this.destroySwarms();
|
109
|
+
throw new Error("Stream ended without data");
|
110
|
+
}
|
111
|
+
logger_1.logger.info(chalk_1.default.green(`✅ Test inference call successful!`));
|
93
112
|
}
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
logger_1.logger.error(chalk_1.default.red("❌ Stream ended without data"));
|
99
|
-
throw new Error("Stream ended without data");
|
113
|
+
catch (error) {
|
114
|
+
this.destroySwarms();
|
115
|
+
logger_1.logger.error(chalk_1.default.red(`❌ Error during test inference call: ${error}`));
|
116
|
+
throw error;
|
100
117
|
}
|
101
|
-
logger_1.logger.info(chalk_1.default.
|
102
|
-
}
|
103
|
-
|
104
|
-
logger_1.logger.error(chalk_1.default.red(`❌ Error during test inference call: ${error}`));
|
105
|
-
throw error;
|
106
|
-
}
|
107
|
-
logger_1.logger.info(chalk_1.default.white(`🔗 Proceeding to join server...`));
|
108
|
-
await this.joinServer();
|
118
|
+
logger_1.logger.info(chalk_1.default.white(`🔗 Test call successful!`));
|
119
|
+
};
|
120
|
+
setTimeout(() => testCall(), constants_1.PROVIDER_HELLO_TIMEOUT);
|
109
121
|
}
|
110
122
|
async joinServer() {
|
111
|
-
|
123
|
+
this._serverSwarm = new hyperswarm_1.default();
|
112
124
|
const serverKey = Buffer.from(this._config.get("serverKey"));
|
113
|
-
|
125
|
+
this._serverSwarm.join(hypercore_crypto_1.default.discoveryKey(serverKey), {
|
114
126
|
client: true,
|
115
127
|
server: false,
|
116
128
|
});
|
117
|
-
|
118
|
-
|
129
|
+
this._serverSwarm.flush();
|
130
|
+
this._serverSwarm.on("connection", (peer) => {
|
119
131
|
var _a;
|
120
132
|
this._serverPeer = peer;
|
121
133
|
logger_1.logger.info(chalk_1.default.green("🔗 Connected to server."));
|
134
|
+
this.testProviderCall();
|
122
135
|
this._challenge = hypercore_crypto_1.default.randomBytes(32);
|
123
136
|
this._serverPeer.write((0, utils_1.createMessage)(constants_1.serverMessageKeys.challenge, {
|
124
137
|
challenge: this._challenge,
|
package/install.ps1
CHANGED
@@ -16,7 +16,7 @@ if (!(Get-Command npm -ErrorAction SilentlyContinue)) {
|
|
16
16
|
}
|
17
17
|
|
18
18
|
Print-Color $YELLOW "Installing symmetry-cli globally..."
|
19
|
-
if (npm install -g
|
19
|
+
if (npm install -g symmetry-cli) {
|
20
20
|
Print-Color $GREEN "symmetry-cli installed successfully!"
|
21
21
|
} else {
|
22
22
|
Print-Color $RED "Failed to install symmetry-cli. Please check your npm configuration and try again."
|
@@ -56,4 +56,4 @@ Print-Color $GREEN "Installation complete! You can now run 'symmetry-cli' to sta
|
|
56
56
|
Print-Color $YELLOW "Please edit $provider_yaml to customize your provider settings, especially:"
|
57
57
|
Print-Color $YELLOW " - apiKey: Add your API key if required"
|
58
58
|
Print-Color $YELLOW " - name: Currently set to your system username, change if needed"
|
59
|
-
Print-Color $YELLOW " - public: Set to true by default, change to false if you don't want to be publicly accessible"
|
59
|
+
Print-Color $YELLOW " - public: Set to true by default, change to false if you don't want to be publicly accessible"
|
package/install.sh
CHANGED
@@ -18,7 +18,7 @@ if ! command -v npm >/dev/null 2>&1; then
|
|
18
18
|
fi
|
19
19
|
|
20
20
|
print_color "$YELLOW" "Installing symmetry-cli globally..."
|
21
|
-
if npm install -g
|
21
|
+
if npm install -g symmetry-cli; then
|
22
22
|
print_color "$GREEN" "symmetry-cli installed successfully!"
|
23
23
|
else
|
24
24
|
print_color "$RED" "Failed to install symmetry-cli. Please check your npm configuration and try again."
|
package/package.json
CHANGED
package/readme.md
CHANGED
@@ -18,12 +18,12 @@ To install Symmetry, use the following commands:
|
|
18
18
|
|
19
19
|
For Linux and macOS:
|
20
20
|
```bash
|
21
|
-
curl -fsSL https://
|
21
|
+
curl -fsSL https://www.twinny.dev/symmetry-unix.sh | sh
|
22
22
|
```
|
23
23
|
|
24
24
|
For Windows:
|
25
25
|
```powershell
|
26
|
-
iwr -useb https://
|
26
|
+
iwr -useb https://www.twinny.dev/symmetry-windows.ps1 | iex
|
27
27
|
```
|
28
28
|
|
29
29
|
## Usage
|
package/src/constants.ts
CHANGED
package/src/provider.ts
CHANGED
@@ -14,7 +14,7 @@ import {
|
|
14
14
|
} from "./utils";
|
15
15
|
import { logger } from "./logger";
|
16
16
|
import { Peer, ProviderMessage, InferenceRequest, Message } from "./types";
|
17
|
-
import { serverMessageKeys } from "./constants";
|
17
|
+
import { PROVIDER_HELLO_TIMEOUT, serverMessageKeys } from "./constants";
|
18
18
|
|
19
19
|
export class SymmetryProvider {
|
20
20
|
private _challenge: Buffer | null = null;
|
@@ -24,6 +24,7 @@ export class SymmetryProvider {
|
|
24
24
|
private _isPublic = false;
|
25
25
|
private _providerConnections: number = 0;
|
26
26
|
private _providerSwarm: Hyperswarm | null = null;
|
27
|
+
private _serverSwarm: Hyperswarm | null = null;
|
27
28
|
private _serverPeer: Peer | null = null;
|
28
29
|
|
29
30
|
constructor(configPath: string) {
|
@@ -63,7 +64,7 @@ export class SymmetryProvider {
|
|
63
64
|
chalk.white(`🔑 Server key: ${this._config.get("serverKey")}`)
|
64
65
|
);
|
65
66
|
logger.info(chalk.white("🔗 Joining server, please wait."));
|
66
|
-
this.
|
67
|
+
this.joinServer();
|
67
68
|
}
|
68
69
|
|
69
70
|
process.on("SIGINT", async () => {
|
@@ -78,78 +79,97 @@ export class SymmetryProvider {
|
|
78
79
|
});
|
79
80
|
}
|
80
81
|
|
82
|
+
async destroySwarms() {
|
83
|
+
await this._providerSwarm?.destroy();
|
84
|
+
await this._serverSwarm?.destroy();
|
85
|
+
}
|
86
|
+
|
81
87
|
private async testProviderCall(): Promise<void> {
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
88
|
+
const testCall = async () => {
|
89
|
+
logger.info(chalk.white(`👋 Saying hello to your provider...`));
|
90
|
+
const testMessages: Message[] = [
|
91
|
+
{ role: "user", content: "Hello, this is a test message." },
|
92
|
+
];
|
93
|
+
const req = this.buildStreamRequest(testMessages);
|
94
|
+
|
95
|
+
if (!req) {
|
96
|
+
logger.error(chalk.red("❌ Failed to build test request"));
|
97
|
+
throw new Error("Failed to build test request");
|
98
|
+
}
|
92
99
|
|
93
|
-
|
94
|
-
|
95
|
-
|
100
|
+
const { requestOptions, requestBody } = req;
|
101
|
+
const { protocol, hostname, port, path, method, headers } =
|
102
|
+
requestOptions;
|
103
|
+
const url = `${protocol}://${hostname}:${port}${path}`;
|
104
|
+
|
105
|
+
logger.info(chalk.white(`🚀 Sending test request to ${url}`));
|
106
|
+
|
107
|
+
try {
|
108
|
+
const response = await fetch(url, {
|
109
|
+
method,
|
110
|
+
headers,
|
111
|
+
body: JSON.stringify(requestBody),
|
112
|
+
});
|
113
|
+
|
114
|
+
if (!response.ok) {
|
115
|
+
logger.error(
|
116
|
+
chalk.red(
|
117
|
+
`❌ Server responded with status code: ${response.status}`
|
118
|
+
)
|
119
|
+
);
|
120
|
+
this.destroySwarms();
|
121
|
+
throw new Error(
|
122
|
+
`Server responded with status code: ${response.status}`
|
123
|
+
);
|
124
|
+
}
|
96
125
|
|
97
|
-
|
126
|
+
if (!response.body) {
|
127
|
+
logger.error(
|
128
|
+
chalk.red("❌ Failed to get a ReadableStream from the response")
|
129
|
+
);
|
130
|
+
this.destroySwarms();
|
131
|
+
throw new Error("Failed to get a ReadableStream from the response");
|
132
|
+
}
|
98
133
|
|
99
|
-
|
100
|
-
const response = await fetch(url, {
|
101
|
-
method,
|
102
|
-
headers,
|
103
|
-
body: JSON.stringify(requestBody),
|
104
|
-
});
|
134
|
+
logger.info(chalk.white(`📡 Got response, checking stream...`));
|
105
135
|
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
}
|
136
|
+
const reader = response.body.getReader();
|
137
|
+
const { done } = await reader.read();
|
138
|
+
if (done) {
|
139
|
+
logger.error(chalk.red("❌ Stream ended without data"));
|
140
|
+
this.destroySwarms();
|
141
|
+
throw new Error("Stream ended without data");
|
142
|
+
}
|
114
143
|
|
115
|
-
|
144
|
+
logger.info(chalk.green(`✅ Test inference call successful!`));
|
145
|
+
} catch (error) {
|
146
|
+
this.destroySwarms();
|
116
147
|
logger.error(
|
117
|
-
chalk.red(
|
148
|
+
chalk.red(`❌ Error during test inference call: ${error}`)
|
118
149
|
);
|
119
|
-
throw
|
150
|
+
throw error;
|
120
151
|
}
|
121
152
|
|
122
|
-
logger.info(chalk.white(
|
123
|
-
|
124
|
-
const reader = response.body.getReader();
|
125
|
-
const { done } = await reader.read();
|
126
|
-
if (done) {
|
127
|
-
logger.error(chalk.red("❌ Stream ended without data"));
|
128
|
-
throw new Error("Stream ended without data");
|
129
|
-
}
|
130
|
-
|
131
|
-
logger.info(chalk.green(`✅ Test inference call successful!`));
|
132
|
-
} catch (error) {
|
133
|
-
logger.error(chalk.red(`❌ Error during test inference call: ${error}`));
|
134
|
-
throw error;
|
135
|
-
}
|
153
|
+
logger.info(chalk.white(`🔗 Test call successful!`));
|
154
|
+
};
|
136
155
|
|
137
|
-
|
138
|
-
await this.joinServer();
|
156
|
+
setTimeout(() => testCall(), PROVIDER_HELLO_TIMEOUT)
|
139
157
|
}
|
140
158
|
|
141
159
|
async joinServer(): Promise<void> {
|
142
|
-
|
160
|
+
this._serverSwarm = new Hyperswarm();
|
143
161
|
const serverKey = Buffer.from(this._config.get("serverKey"));
|
144
|
-
|
162
|
+
this._serverSwarm.join(crypto.discoveryKey(serverKey), {
|
145
163
|
client: true,
|
146
164
|
server: false,
|
147
165
|
});
|
148
|
-
|
149
|
-
|
166
|
+
this._serverSwarm.flush();
|
167
|
+
this._serverSwarm.on("connection", (peer: Peer) => {
|
150
168
|
this._serverPeer = peer;
|
151
169
|
logger.info(chalk.green("🔗 Connected to server."));
|
152
170
|
|
171
|
+
this.testProviderCall();
|
172
|
+
|
153
173
|
this._challenge = crypto.randomBytes(32);
|
154
174
|
|
155
175
|
this._serverPeer.write(
|