mycomesh-consumer 0.1.31 → 0.1.33
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 +55 -108
- package/package.json +6 -5
- package/src/cli.mjs +1 -1
- package/src/consumer-runtime.mjs +1180 -0
- package/src/consumer.mjs +202 -121
- package/consumer.compose.yml +0 -90
- package/scripts/start-consumer.sh +0 -223
package/src/consumer.mjs
CHANGED
|
@@ -1,11 +1,18 @@
|
|
|
1
1
|
import { spawn as defaultSpawn } from "node:child_process";
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
2
|
+
import { existsSync, readFileSync, rmSync, unlinkSync, writeFileSync } from "node:fs";
|
|
3
|
+
import { join } from "node:path";
|
|
4
|
+
import * as readline from "node:readline/promises";
|
|
4
5
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
6
|
+
import {
|
|
7
|
+
DEFAULT_BASE_URL,
|
|
8
|
+
DEFAULT_MAX_FEE_UNITS,
|
|
9
|
+
DEFAULT_RELAY_URL,
|
|
10
|
+
NativeConsumerState,
|
|
11
|
+
createConsumerServer,
|
|
12
|
+
} from "./consumer-runtime.mjs";
|
|
13
|
+
|
|
14
|
+
export const CONSUMER_RELEASE_VERSION = "0.1.33";
|
|
15
|
+
export const API_COMMANDS = new Set(["health", "models", "responses", "chat"]);
|
|
9
16
|
const API_VALUE_OPTIONS = new Set([
|
|
10
17
|
"--base-url",
|
|
11
18
|
"--api-key",
|
|
@@ -21,35 +28,33 @@ const API_VALUE_OPTIONS = new Set([
|
|
|
21
28
|
"--max-completion-tokens",
|
|
22
29
|
]);
|
|
23
30
|
|
|
24
|
-
const
|
|
25
|
-
|
|
26
|
-
Start the local MycoMesh Consumer. No options are needed.
|
|
31
|
+
export const CONSUMER_HELP = `Usage: mycomesh-consumer [options] [-- codex-options]
|
|
27
32
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
33
|
+
Start the local MycoMesh Consumer without Docker, Python, or a public Gateway.
|
|
34
|
+
The process owns one persisted V8 payment key, selects healthy Relays, and
|
|
35
|
+
exposes an OpenAI-compatible loopback API.
|
|
31
36
|
|
|
32
37
|
Options:
|
|
33
|
-
--no-browser Print the credentials URL without opening it
|
|
34
|
-
--
|
|
35
|
-
--
|
|
36
|
-
--
|
|
37
|
-
--
|
|
38
|
+
--no-browser Print the local credentials URL without opening it
|
|
39
|
+
--codex Start an optional Codex client after Relay readiness
|
|
40
|
+
--no-codex Keep only the Consumer API running (default)
|
|
41
|
+
--stop Stop a previously started native Consumer
|
|
42
|
+
--reset-local Confirm and delete the local Consumer data directory
|
|
43
|
+
--codex-command PATH Codex executable for --codex (default: codex on PATH)
|
|
38
44
|
--ready-timeout SEC Relay readiness timeout (default: 1800)
|
|
39
|
-
--
|
|
40
|
-
--
|
|
41
|
-
--
|
|
45
|
+
--data-dir DIR Payment key and history directory
|
|
46
|
+
--relay URLS Comma-separated Relay URLs for automatic failover
|
|
47
|
+
--proxy URL Optional outbound HTTP proxy
|
|
48
|
+
--host HOST Listen address (default: 127.0.0.1)
|
|
49
|
+
--port PORT Listen port (default: 8110)
|
|
50
|
+
--max-fee UNITS Maximum fee per request (default: 100000)
|
|
51
|
+
--dry-run Print the native startup plan
|
|
42
52
|
-h, --help Show this help
|
|
43
53
|
-v, --version Show the package version
|
|
44
54
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
mycomesh-consumer responses "hello"
|
|
49
|
-
mycomesh-consumer chat "hello"
|
|
50
|
-
|
|
51
|
-
Docker Desktop/Engine is required. The payment key and Consumer state remain
|
|
52
|
-
in a protected Docker volume; no wallet signature or browser session is used.`;
|
|
55
|
+
The browser page displays only the export URL/key, prepaid balance, key
|
|
56
|
+
operations, and local consumption history. No browser conversation state is
|
|
57
|
+
created.`;
|
|
53
58
|
|
|
54
59
|
class ConsumerCliError extends Error {
|
|
55
60
|
constructor(message, exitCode = 1) {
|
|
@@ -66,22 +71,61 @@ export async function main(argv, dependencies = {}) {
|
|
|
66
71
|
try {
|
|
67
72
|
const parsed = parseArguments(argv, env);
|
|
68
73
|
if (parsed.help) {
|
|
69
|
-
stdout.write(`${
|
|
74
|
+
stdout.write(`${CONSUMER_HELP}\n`);
|
|
70
75
|
return 0;
|
|
71
76
|
}
|
|
72
77
|
if (parsed.version) {
|
|
73
78
|
stdout.write(`${CONSUMER_RELEASE_VERSION}\n`);
|
|
74
79
|
return 0;
|
|
75
80
|
}
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
81
|
+
if (parsed.dryRun) {
|
|
82
|
+
stdout.write(`Native Consumer: ${parsed.host}:${parsed.port}\n`);
|
|
83
|
+
stdout.write(`Data directory: ${parsed.dataDir}\n`);
|
|
84
|
+
stdout.write(`Relays: ${parsed.relayUrls}\n`);
|
|
85
|
+
stdout.write("Docker: disabled\n");
|
|
86
|
+
return 0;
|
|
87
|
+
}
|
|
88
|
+
if (parsed.stop) return stopConsumer(parsed, stdout, stderr);
|
|
89
|
+
if (parsed.resetLocal) return await resetConsumer(parsed, env, stdout, stderr);
|
|
90
|
+
|
|
91
|
+
const state = dependencies.createState
|
|
92
|
+
? dependencies.createState(parsed, env)
|
|
93
|
+
: new NativeConsumerState({
|
|
94
|
+
env: { ...env, MYCOMESH_CONSUMER_DATA_DIR: parsed.dataDir },
|
|
95
|
+
dataDir: parsed.dataDir,
|
|
96
|
+
relayUrls: parsed.relayUrls,
|
|
97
|
+
proxy: parsed.proxy,
|
|
98
|
+
baseUrl: parsed.baseUrl,
|
|
99
|
+
maxFeeUnits: parsed.maxFeeUnits,
|
|
100
|
+
});
|
|
101
|
+
const runtime = dependencies.createServer
|
|
102
|
+
? dependencies.createServer(state, parsed)
|
|
103
|
+
: createConsumerServer(state, { host: parsed.host, port: parsed.port });
|
|
104
|
+
await runtime.listen();
|
|
105
|
+
const rootUrl = `${parsed.scheme}://${parsed.hostForUrl}:${parsed.port}`;
|
|
106
|
+
const credentialsUrl = `${rootUrl}/`;
|
|
107
|
+
writePid(parsed.dataDir);
|
|
108
|
+
stdout.write(`MycoMesh Consumer credentials: ${credentialsUrl}\n`);
|
|
109
|
+
stdout.write(`OpenAI API: ${state.baseUrl}\n`);
|
|
110
|
+
if (!parsed.noBrowser) openBrowser(credentialsUrl, stderr);
|
|
111
|
+
|
|
112
|
+
const shutdown = async () => {
|
|
113
|
+
clearPid(parsed.dataDir);
|
|
114
|
+
await runtime.close();
|
|
115
|
+
};
|
|
116
|
+
if (parsed.noCodex) {
|
|
117
|
+
await waitForSignal(shutdown);
|
|
118
|
+
return 0;
|
|
119
|
+
}
|
|
120
|
+
await waitUntilReady(state, parsed.readyTimeout, stdout);
|
|
121
|
+
const code = await runCodex(parsed, state, dependencies.spawn ?? defaultSpawn, stdout, stderr);
|
|
122
|
+
await shutdown();
|
|
123
|
+
return code;
|
|
82
124
|
} catch (error) {
|
|
83
125
|
const exitCode = error instanceof ConsumerCliError ? error.exitCode : 1;
|
|
84
|
-
const message = error
|
|
126
|
+
const message = error?.code === "EADDRINUSE"
|
|
127
|
+
? `port ${error.port || "requested"} is already in use; stop the old Consumer or choose --port with a matching --base-url`
|
|
128
|
+
: error instanceof Error ? error.message : String(error);
|
|
85
129
|
stderr.write(`mycomesh consumer: ${message}\n`);
|
|
86
130
|
return exitCode;
|
|
87
131
|
}
|
|
@@ -89,12 +133,20 @@ export async function main(argv, dependencies = {}) {
|
|
|
89
133
|
|
|
90
134
|
export function parseArguments(argv, env = process.env) {
|
|
91
135
|
const parsed = {
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
136
|
+
baseUrl: env.MYCOMESH_CONSUMER_PUBLIC_BASE_URL || DEFAULT_BASE_URL,
|
|
137
|
+
baseUrlExplicit: Boolean(env.MYCOMESH_CONSUMER_PUBLIC_BASE_URL),
|
|
138
|
+
dataDir: env.MYCOMESH_CONSUMER_DATA_DIR || join(env.HOME || process.cwd(), ".mycomesh", "consumer"),
|
|
139
|
+
relayUrls: env.MYCOMESH_V8_RELAY_URLS || env.MYCOMESH_CONSUMER_RELAY_URL || DEFAULT_RELAY_URL,
|
|
140
|
+
proxy: env.MYCOMESH_CONSUMER_PROXY || "",
|
|
141
|
+
codexCommand: env.MYCOMESH_CODEX_COMMAND || "codex",
|
|
142
|
+
readyTimeout: parsePositive(env.MYCOMESH_CONSUMER_READY_TIMEOUT_SECONDS || "1800", "ready timeout", 86400),
|
|
143
|
+
maxFeeUnits: parsePositive(env.MYCOMESH_V8_MAX_FEE_UNITS || String(DEFAULT_MAX_FEE_UNITS), "max fee"),
|
|
144
|
+
host: env.MYCOMESH_CONSUMER_HOST || "127.0.0.1",
|
|
145
|
+
hostForUrl: env.MYCOMESH_CONSUMER_HOST || "127.0.0.1",
|
|
146
|
+
port: parsePositive(env.MYCOMESH_CONSUMER_PORT || "8110", "port", 65535),
|
|
147
|
+
scheme: "http",
|
|
96
148
|
noBrowser: false,
|
|
97
|
-
noCodex:
|
|
149
|
+
noCodex: env.MYCOMESH_CONSUMER_START_CODEX !== "1",
|
|
98
150
|
stop: false,
|
|
99
151
|
resetLocal: false,
|
|
100
152
|
dryRun: false,
|
|
@@ -102,72 +154,44 @@ export function parseArguments(argv, env = process.env) {
|
|
|
102
154
|
version: false,
|
|
103
155
|
codexArgs: [],
|
|
104
156
|
};
|
|
105
|
-
|
|
106
157
|
for (let index = 0; index < argv.length; index += 1) {
|
|
107
158
|
const token = argv[index];
|
|
108
|
-
if (token === "--") {
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
}
|
|
112
|
-
if (token === "
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
}
|
|
116
|
-
if (token === "-
|
|
117
|
-
parsed.version = true;
|
|
118
|
-
continue;
|
|
119
|
-
}
|
|
120
|
-
if (token === "--no-browser") {
|
|
121
|
-
parsed.noBrowser = true;
|
|
122
|
-
continue;
|
|
123
|
-
}
|
|
124
|
-
if (token === "--no-codex") {
|
|
125
|
-
parsed.noCodex = true;
|
|
126
|
-
continue;
|
|
127
|
-
}
|
|
128
|
-
if (token === "--stop") {
|
|
129
|
-
parsed.stop = true;
|
|
130
|
-
continue;
|
|
131
|
-
}
|
|
132
|
-
if (token === "--reset-local") {
|
|
133
|
-
parsed.resetLocal = true;
|
|
134
|
-
continue;
|
|
135
|
-
}
|
|
136
|
-
if (token === "--dry-run") {
|
|
137
|
-
parsed.dryRun = true;
|
|
138
|
-
continue;
|
|
139
|
-
}
|
|
159
|
+
if (token === "--") { parsed.codexArgs = argv.slice(index + 1); break; }
|
|
160
|
+
if (token === "-h" || token === "--help") { parsed.help = true; continue; }
|
|
161
|
+
if (token === "-v" || token === "--version") { parsed.version = true; continue; }
|
|
162
|
+
if (token === "--no-browser") { parsed.noBrowser = true; continue; }
|
|
163
|
+
if (token === "--codex") { parsed.noCodex = false; continue; }
|
|
164
|
+
if (token === "--no-codex") { parsed.noCodex = true; continue; }
|
|
165
|
+
if (token === "--stop") { parsed.stop = true; continue; }
|
|
166
|
+
if (token === "--reset-local") { parsed.resetLocal = true; continue; }
|
|
167
|
+
if (token === "--dry-run") { parsed.dryRun = true; continue; }
|
|
140
168
|
const separator = token.indexOf("=");
|
|
141
169
|
const name = separator === -1 ? token : token.slice(0, separator);
|
|
142
170
|
let value = separator === -1 ? undefined : token.slice(separator + 1);
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
}
|
|
146
|
-
if (value === undefined) {
|
|
147
|
-
index += 1;
|
|
148
|
-
value = argv[index];
|
|
149
|
-
}
|
|
171
|
+
const options = new Set(["--base-url", "--data-dir", "--relay", "--proxy", "--codex-command", "--ready-timeout", "--host", "--port", "--max-fee"]);
|
|
172
|
+
if (!options.has(name)) throw new ConsumerCliError(`unknown option: ${token}`, 2);
|
|
173
|
+
if (value === undefined) { index += 1; value = argv[index]; }
|
|
150
174
|
if (!value) throw new ConsumerCliError(`${name} requires a value`, 2);
|
|
151
|
-
if (name === "--
|
|
152
|
-
if (name === "--
|
|
153
|
-
if (name === "--
|
|
175
|
+
if (name === "--base-url") { parsed.baseUrl = value; parsed.baseUrlExplicit = true; }
|
|
176
|
+
if (name === "--data-dir") parsed.dataDir = value;
|
|
177
|
+
if (name === "--relay") parsed.relayUrls = value;
|
|
154
178
|
if (name === "--proxy") parsed.proxy = value;
|
|
179
|
+
if (name === "--codex-command") parsed.codexCommand = value;
|
|
180
|
+
if (name === "--ready-timeout") parsed.readyTimeout = parsePositive(value, name, 86400);
|
|
181
|
+
if (name === "--host") { parsed.host = value; parsed.hostForUrl = value.includes(":") ? `[${value}]` : value; }
|
|
182
|
+
if (name === "--port") parsed.port = parsePositive(value, name, 65535);
|
|
183
|
+
if (name === "--max-fee") parsed.maxFeeUnits = parsePositive(value, name);
|
|
155
184
|
}
|
|
156
|
-
if (
|
|
157
|
-
|
|
158
|
-
}
|
|
159
|
-
if (parsed.readyTimeout && !/^[1-9][0-9]*$/.test(parsed.readyTimeout)) {
|
|
160
|
-
throw new ConsumerCliError("--ready-timeout must be a positive integer", 2);
|
|
161
|
-
}
|
|
185
|
+
if (!parsed.baseUrlExplicit) parsed.baseUrl = `http://${parsed.hostForUrl}:${parsed.port}/v1`;
|
|
186
|
+
try { new URL(parsed.baseUrl); } catch { throw new ConsumerCliError("--base-url must be an absolute URL", 2); }
|
|
162
187
|
return parsed;
|
|
163
188
|
}
|
|
164
189
|
|
|
165
|
-
function
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
}
|
|
190
|
+
function parsePositive(value, label, maximum = Number.MAX_SAFE_INTEGER) {
|
|
191
|
+
if (!/^[1-9][0-9]*$/.test(String(value))) throw new ConsumerCliError(`${label} must be a positive integer`, 2);
|
|
192
|
+
const parsed = Number(value);
|
|
193
|
+
if (!Number.isSafeInteger(parsed) || parsed > maximum) throw new ConsumerCliError(`${label} is too large`, 2);
|
|
194
|
+
return parsed;
|
|
171
195
|
}
|
|
172
196
|
|
|
173
197
|
export function isApiInvocation(argv) {
|
|
@@ -185,34 +209,91 @@ export function isApiInvocation(argv) {
|
|
|
185
209
|
return false;
|
|
186
210
|
}
|
|
187
211
|
|
|
188
|
-
|
|
189
|
-
const
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
if (parsed.dryRun) args.push("--dry-run");
|
|
198
|
-
if (parsed.codexArgs.length) args.push("--", ...parsed.codexArgs);
|
|
199
|
-
return args;
|
|
212
|
+
async function waitUntilReady(state, timeoutSeconds, stdout) {
|
|
213
|
+
const started = Date.now();
|
|
214
|
+
stdout.write("Waiting for a healthy Settlement V8 Relay...\n");
|
|
215
|
+
while (true) {
|
|
216
|
+
try { await state.chooseRelay(); return; } catch (error) {
|
|
217
|
+
if (Date.now() - started >= timeoutSeconds * 1000) throw new ConsumerCliError(`timed out waiting for a healthy Relay: ${error.message}`);
|
|
218
|
+
await new Promise((resolve) => setTimeout(resolve, 2000));
|
|
219
|
+
}
|
|
220
|
+
}
|
|
200
221
|
}
|
|
201
222
|
|
|
202
|
-
function
|
|
203
|
-
return new Promise((resolve
|
|
223
|
+
function runCodex(parsed, state, spawn, stdout, stderr) {
|
|
224
|
+
return new Promise((resolve) => {
|
|
225
|
+
const args = [
|
|
226
|
+
"-c", 'model="gpt-5.5"',
|
|
227
|
+
"-c", 'model_provider="mycomesh"',
|
|
228
|
+
"-c", 'model_providers.mycomesh.name="MycoMesh"',
|
|
229
|
+
"-c", `model_providers.mycomesh.base_url="${state.baseUrl}"`,
|
|
230
|
+
"-c", 'model_providers.mycomesh.env_key="OPENAI_API_KEY"',
|
|
231
|
+
"-c", 'model_providers.mycomesh.wire_api="responses"',
|
|
232
|
+
...parsed.codexArgs,
|
|
233
|
+
];
|
|
234
|
+
const env = { ...process.env, OPENAI_BASE_URL: state.baseUrl, OPENAI_API_KEY: state.paymentKey };
|
|
204
235
|
let child;
|
|
205
|
-
try {
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
}
|
|
211
|
-
child.once("error", (error) => reject(new ConsumerCliError(`could not start bash: ${error.message}`)));
|
|
212
|
-
child.once("exit", (code, signal) => {
|
|
213
|
-
resolve(typeof code === "number" ? code : 128 + ({ SIGHUP: 1, SIGINT: 2, SIGTERM: 15 }[signal] ?? 1));
|
|
214
|
-
});
|
|
236
|
+
try { child = spawn(parsed.codexCommand, args, { env, stdio: "inherit" }); }
|
|
237
|
+
catch (error) { stderr.write(`mycomesh consumer: could not start Codex: ${error.message}\n`); resolve(127); return; }
|
|
238
|
+
stdout.write("Opening Codex through the native MycoMesh Consumer.\n");
|
|
239
|
+
child.once("error", (error) => { stderr.write(`mycomesh consumer: Codex failed: ${error.message}\n`); resolve(127); });
|
|
240
|
+
child.once("exit", (code, signal) => resolve(typeof code === "number" ? code : 128 + ({ SIGINT: 2, SIGTERM: 15 }[signal] || 1)));
|
|
215
241
|
});
|
|
216
242
|
}
|
|
217
243
|
|
|
218
|
-
|
|
244
|
+
function writePid(dataDir) {
|
|
245
|
+
try { writeFileSync(join(dataDir, "consumer.pid"), `${process.pid}\n`, { mode: 0o600 }); } catch {}
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
function clearPid(dataDir) {
|
|
249
|
+
try { unlinkSync(join(dataDir, "consumer.pid")); } catch {}
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
function stopConsumer(parsed, stdout, stderr) {
|
|
253
|
+
const pidPath = join(parsed.dataDir, "consumer.pid");
|
|
254
|
+
if (!existsSync(pidPath)) { stdout.write("No native Consumer is running.\n"); return 0; }
|
|
255
|
+
const pid = Number(readFileSync(pidPath, "utf8").trim());
|
|
256
|
+
if (!Number.isInteger(pid) || pid <= 1) { clearPid(parsed.dataDir); stderr.write("Removed an invalid Consumer pid file.\n"); return 0; }
|
|
257
|
+
try { process.kill(pid, "SIGTERM"); stdout.write(`Stopped native Consumer process ${pid}.\n`); }
|
|
258
|
+
catch (error) { if (error.code !== "ESRCH") throw error; stdout.write("Native Consumer was already stopped.\n"); }
|
|
259
|
+
clearPid(parsed.dataDir);
|
|
260
|
+
return 0;
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
async function resetConsumer(parsed, env, stdout, stderr) {
|
|
264
|
+
const confirmed = env.MYCOMESH_CONFIRM_RESET === "RESET";
|
|
265
|
+
if (!confirmed && process.stdin.isTTY) {
|
|
266
|
+
const prompt = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
267
|
+
const answer = await prompt.question("This removes the local payment key and history. Type RESET to continue: ");
|
|
268
|
+
prompt.close();
|
|
269
|
+
if (answer !== "RESET") throw new ConsumerCliError("local Consumer reset cancelled", 2);
|
|
270
|
+
} else if (!confirmed) {
|
|
271
|
+
throw new ConsumerCliError("set MYCOMESH_CONFIRM_RESET=RESET to reset a non-interactive Consumer", 2);
|
|
272
|
+
}
|
|
273
|
+
clearPid(parsed.dataDir);
|
|
274
|
+
rmSync(parsed.dataDir, { recursive: true, force: true });
|
|
275
|
+
stdout.write("Native Consumer local state removed.\n");
|
|
276
|
+
return 0;
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
function openBrowser(url, stderr) {
|
|
280
|
+
const platform = process.platform;
|
|
281
|
+
let command;
|
|
282
|
+
let args;
|
|
283
|
+
if (platform === "darwin") { command = "open"; args = [url]; }
|
|
284
|
+
else if (platform === "win32") { command = "cmd"; args = ["/c", "start", "", url]; }
|
|
285
|
+
else { command = "xdg-open"; args = [url]; }
|
|
286
|
+
try {
|
|
287
|
+
const child = defaultSpawn(command, args, { stdio: "ignore", detached: true });
|
|
288
|
+
child.unref?.();
|
|
289
|
+
} catch { stderr.write(`Open ${url} in a browser.\n`); }
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
function waitForSignal(shutdown) {
|
|
293
|
+
return new Promise((resolve) => {
|
|
294
|
+
let closed = false;
|
|
295
|
+
const finish = async () => { if (closed) return; closed = true; process.removeListener("SIGINT", finish); process.removeListener("SIGTERM", finish); await shutdown(); resolve(); };
|
|
296
|
+
process.once("SIGINT", finish);
|
|
297
|
+
process.once("SIGTERM", finish);
|
|
298
|
+
});
|
|
299
|
+
}
|
package/consumer.compose.yml
DELETED
|
@@ -1,90 +0,0 @@
|
|
|
1
|
-
services:
|
|
2
|
-
consumer-volume-init:
|
|
3
|
-
image: ${MYCOMESH_NODE_IMAGE:?MYCOMESH_NODE_IMAGE is required}
|
|
4
|
-
user: "0:0"
|
|
5
|
-
network_mode: none
|
|
6
|
-
restart: "no"
|
|
7
|
-
read_only: true
|
|
8
|
-
security_opt:
|
|
9
|
-
- no-new-privileges:true
|
|
10
|
-
cap_drop:
|
|
11
|
-
- ALL
|
|
12
|
-
cap_add:
|
|
13
|
-
- CHOWN
|
|
14
|
-
- DAC_OVERRIDE
|
|
15
|
-
volumes:
|
|
16
|
-
- mycomesh-consumer-data:/volumes/consumer
|
|
17
|
-
entrypoint: ["/bin/sh", "-ec", "chown -R 10001:10001 /volumes/consumer"]
|
|
18
|
-
|
|
19
|
-
consumer:
|
|
20
|
-
image: ${MYCOMESH_NODE_IMAGE:?MYCOMESH_NODE_IMAGE is required}
|
|
21
|
-
user: "10001:10001"
|
|
22
|
-
restart: unless-stopped
|
|
23
|
-
pids_limit: 128
|
|
24
|
-
mem_limit: 256m
|
|
25
|
-
cpus: "1.0"
|
|
26
|
-
logging:
|
|
27
|
-
driver: json-file
|
|
28
|
-
options:
|
|
29
|
-
max-size: 10m
|
|
30
|
-
max-file: "3"
|
|
31
|
-
init: true
|
|
32
|
-
read_only: true
|
|
33
|
-
security_opt:
|
|
34
|
-
- no-new-privileges:true
|
|
35
|
-
cap_drop:
|
|
36
|
-
- ALL
|
|
37
|
-
working_dir: /data
|
|
38
|
-
environment:
|
|
39
|
-
MYCOMESH_CONSUMER_DATA_DIR: /data
|
|
40
|
-
MYCOMESH_CONSUMER_PROTOCOL_VERSION: ${MYCOMESH_CONSUMER_PROTOCOL_VERSION:-8}
|
|
41
|
-
MYCOMESH_CONSUMER_NETWORK_CONFIG: ${MYCOMESH_CONSUMER_NETWORK_CONFIG:-/app/deployments/sepolia-provider-network-v8.json}
|
|
42
|
-
MYCOMESH_CONSUMER_PUBLIC_BASE_URL: http://127.0.0.1:8110/v1
|
|
43
|
-
MYCOMESH_V7_RELAY_URLS: ${MYCOMESH_V7_RELAY_URLS:-https://bridge.mycomesh.xyz}
|
|
44
|
-
MYCOMESH_V7_MAX_FEE_UNITS: ${MYCOMESH_V7_MAX_FEE_UNITS:-100000}
|
|
45
|
-
MYCOMESH_V7_REQUEST_TIMEOUT_SECONDS: ${MYCOMESH_V7_REQUEST_TIMEOUT_SECONDS:-300}
|
|
46
|
-
MYCOMESH_V8_RELAY_URLS: ${MYCOMESH_V8_RELAY_URLS:-https://bridge.mycomesh.xyz}
|
|
47
|
-
MYCOMESH_V8_MAX_FEE_UNITS: ${MYCOMESH_V8_MAX_FEE_UNITS:-100000}
|
|
48
|
-
HTTP_PROXY: ${MYCOMESH_CONSUMER_HTTP_PROXY:-}
|
|
49
|
-
HTTPS_PROXY: ${MYCOMESH_CONSUMER_HTTPS_PROXY:-}
|
|
50
|
-
ALL_PROXY: ${MYCOMESH_CONSUMER_ALL_PROXY:-}
|
|
51
|
-
NO_PROXY: ${MYCOMESH_CONSUMER_NO_PROXY:-127.0.0.1,localhost,::1}
|
|
52
|
-
http_proxy: ${MYCOMESH_CONSUMER_HTTP_PROXY:-}
|
|
53
|
-
https_proxy: ${MYCOMESH_CONSUMER_HTTPS_PROXY:-}
|
|
54
|
-
all_proxy: ${MYCOMESH_CONSUMER_ALL_PROXY:-}
|
|
55
|
-
no_proxy: ${MYCOMESH_CONSUMER_NO_PROXY:-127.0.0.1,localhost,::1}
|
|
56
|
-
extra_hosts:
|
|
57
|
-
- host.docker.internal:host-gateway
|
|
58
|
-
ports:
|
|
59
|
-
- "127.0.0.1:8110:8110"
|
|
60
|
-
volumes:
|
|
61
|
-
- mycomesh-consumer-data:/data
|
|
62
|
-
tmpfs:
|
|
63
|
-
- /tmp:size=32m,mode=1777
|
|
64
|
-
depends_on:
|
|
65
|
-
consumer-volume-init:
|
|
66
|
-
condition: service_completed_successfully
|
|
67
|
-
stop_grace_period: 15s
|
|
68
|
-
healthcheck:
|
|
69
|
-
test:
|
|
70
|
-
- CMD
|
|
71
|
-
- python
|
|
72
|
-
- -c
|
|
73
|
-
- "import json, urllib.request; value=json.load(urllib.request.urlopen('http://127.0.0.1:8110/health', timeout=3)); assert value.get('ok') is True; assert value.get('gateway_dependency') is False; assert value.get('browser_app_ready') is True"
|
|
74
|
-
interval: 15s
|
|
75
|
-
timeout: 5s
|
|
76
|
-
retries: 4
|
|
77
|
-
start_period: 10s
|
|
78
|
-
entrypoint: ["sh", "-ec"]
|
|
79
|
-
command:
|
|
80
|
-
- >-
|
|
81
|
-
if [ "$${MYCOMESH_CONSUMER_PROTOCOL_VERSION:-8}" = "8" ]; then
|
|
82
|
-
exec python -m gateway.consumer_v8 serve --host 0.0.0.0 --port 8110;
|
|
83
|
-
elif [ "$${MYCOMESH_CONSUMER_PROTOCOL_VERSION:-8}" = "7" ]; then
|
|
84
|
-
exec python -m gateway.consumer_v7 serve --host 0.0.0.0 --port 8110;
|
|
85
|
-
else
|
|
86
|
-
exec python -m gateway.local_consumer serve --host 0.0.0.0 --port 8110;
|
|
87
|
-
fi
|
|
88
|
-
|
|
89
|
-
volumes:
|
|
90
|
-
mycomesh-consumer-data:
|