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.
@@ -45,7 +45,7 @@ describe("Symmetry", () => {
45
45
  apiProvider: "test-provider",
46
46
  modelName: "test-model",
47
47
  name: "test",
48
- public: true,
48
+ public: false,
49
49
  serverKey: "test-server-key",
50
50
  systemMessage: "test-system-message",
51
51
  };
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.testProviderCall();
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
- logger_1.logger.info(chalk_1.default.white(`👋 Saying hello to your provider...`));
68
- const testMessages = [
69
- { role: "user", content: "Hello, this is a test message." },
70
- ];
71
- const req = this.buildStreamRequest(testMessages);
72
- if (!req) {
73
- logger_1.logger.error(chalk_1.default.red("❌ Failed to build test request"));
74
- throw new Error("Failed to build test request");
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
- if (!response.body) {
91
- logger_1.logger.error(chalk_1.default.red("❌ Failed to get a ReadableStream from the response"));
92
- throw new Error("Failed to get a ReadableStream from the response");
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
- logger_1.logger.info(chalk_1.default.white(`📡 Got response, checking stream...`));
95
- const reader = response.body.getReader();
96
- const { done } = await reader.read();
97
- if (done) {
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.green(`✅ Test inference call successful!`));
102
- }
103
- catch (error) {
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
- const serverSwarm = new hyperswarm_1.default();
123
+ this._serverSwarm = new hyperswarm_1.default();
112
124
  const serverKey = Buffer.from(this._config.get("serverKey"));
113
- serverSwarm.join(hypercore_crypto_1.default.discoveryKey(serverKey), {
125
+ this._serverSwarm.join(hypercore_crypto_1.default.discoveryKey(serverKey), {
114
126
  client: true,
115
127
  server: false,
116
128
  });
117
- serverSwarm.flush();
118
- serverSwarm.on("connection", (peer) => {
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 .; then
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "symmetry-cli",
3
- "version": "1.0.6",
3
+ "version": "1.0.7",
4
4
  "description": "",
5
5
  "main": "dist/symmetry.js",
6
6
  "bin": "dist/symmetry.js",
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://raw.githubusercontent.com/twinnydotdev/symmetry/master/install.sh | sh
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://raw.githubusercontent.com/twinnydotdev/symmetry/master/install.ps1 | iex
26
+ iwr -useb https://www.twinny.dev/symmetry-windows.ps1 | iex
27
27
  ```
28
28
 
29
29
  ## Usage
package/src/constants.ts CHANGED
@@ -1,5 +1,7 @@
1
1
  export const NORMALIZE_REGEX = /\s*\r?\n|\r/g;
2
2
 
3
+ export const PROVIDER_HELLO_TIMEOUT = 30000
4
+
3
5
  export const serverMessageKeys = {
4
6
  challenge: "challenge",
5
7
  conectionSize: "conectionSize",
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.testProviderCall();
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
- logger.info(chalk.white(`👋 Saying hello to your provider...`));
83
- const testMessages: Message[] = [
84
- { role: "user", content: "Hello, this is a test message." },
85
- ];
86
- const req = this.buildStreamRequest(testMessages);
87
-
88
- if (!req) {
89
- logger.error(chalk.red("❌ Failed to build test request"));
90
- throw new Error("Failed to build test request");
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
- const { requestOptions, requestBody } = req;
94
- const { protocol, hostname, port, path, method, headers } = requestOptions;
95
- const url = `${protocol}://${hostname}:${port}${path}`;
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
- logger.info(chalk.white(`🚀 Sending test request to ${url}`));
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
- try {
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
- if (!response.ok) {
107
- logger.error(
108
- chalk.red(`❌ Server responded with status code: ${response.status}`)
109
- );
110
- throw new Error(
111
- `Server responded with status code: ${response.status}`
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
- if (!response.body) {
144
+ logger.info(chalk.green(`✅ Test inference call successful!`));
145
+ } catch (error) {
146
+ this.destroySwarms();
116
147
  logger.error(
117
- chalk.red("❌ Failed to get a ReadableStream from the response")
148
+ chalk.red(`❌ Error during test inference call: ${error}`)
118
149
  );
119
- throw new Error("Failed to get a ReadableStream from the response");
150
+ throw error;
120
151
  }
121
152
 
122
- logger.info(chalk.white(`📡 Got response, checking stream...`));
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
- logger.info(chalk.white(`🔗 Proceeding to join server...`));
138
- await this.joinServer();
156
+ setTimeout(() => testCall(), PROVIDER_HELLO_TIMEOUT)
139
157
  }
140
158
 
141
159
  async joinServer(): Promise<void> {
142
- const serverSwarm = new Hyperswarm();
160
+ this._serverSwarm = new Hyperswarm();
143
161
  const serverKey = Buffer.from(this._config.get("serverKey"));
144
- serverSwarm.join(crypto.discoveryKey(serverKey), {
162
+ this._serverSwarm.join(crypto.discoveryKey(serverKey), {
145
163
  client: true,
146
164
  server: false,
147
165
  });
148
- serverSwarm.flush();
149
- serverSwarm.on("connection", (peer: Peer) => {
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(