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/src/consumer.mjs CHANGED
@@ -1,11 +1,18 @@
1
1
  import { spawn as defaultSpawn } from "node:child_process";
2
- import { createRequire } from "node:module";
3
- import { fileURLToPath } from "node:url";
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
- const CONSUMER_RELEASE_VERSION = "0.1.31";
6
- const DEFAULT_NODE_IMAGE =
7
- "ghcr.io/charleslzp/mycomesh-node@sha256:ba6746dcfe3c3a8cfe49eece9ac1d5c39a088ea1f8d4601f61de23c15b7f5943";
8
- const API_COMMANDS = new Set(["health", "models", "responses", "chat"]);
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 HELP = `Usage: mycomesh-consumer [options] [-- codex-options]
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
- The default command starts the pinned Docker runtime, opens the local
29
- credentials page with the export URL and payment key, then opens Codex through
30
- the loopback Consumer at http://127.0.0.1:8110/v1.
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
- --no-codex Start the Consumer and credentials page without Codex
35
- --stop Stop the Consumer without deleting its payment key
36
- --reset-local Confirm and delete the local Consumer volume
37
- --codex-command PATH Codex executable (default: codex)
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
- --proxy URL Optional proxy for Consumer network traffic
40
- --node-image IMAGE Advanced: override the pinned Consumer image
41
- --dry-run Print the planned Docker operations
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
- Existing API commands remain available:
46
- mycomesh-consumer health
47
- mycomesh-consumer models
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(`${HELP}\n`);
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
- const script = dependencies.scriptPath
77
- ?? fileURLToPath(new URL("../scripts/start-consumer.sh", import.meta.url));
78
- return await runScript(script, toScriptArgs(parsed), {
79
- env,
80
- spawn: dependencies.spawn ?? defaultSpawn,
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 instanceof Error ? error.message : String(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
- nodeImage: env.MYCOMESH_NODE_IMAGE || DEFAULT_NODE_IMAGE,
93
- codexCommand: env.MYCOMESH_CODEX_COMMAND || bundledCodexCommand(),
94
- readyTimeout: env.MYCOMESH_CONSUMER_READY_TIMEOUT_SECONDS || undefined,
95
- proxy: env.MYCOMESH_CONSUMER_PROXY || undefined,
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: false,
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
- parsed.codexArgs = argv.slice(index + 1);
110
- break;
111
- }
112
- if (token === "-h" || token === "--help") {
113
- parsed.help = true;
114
- continue;
115
- }
116
- if (token === "-v" || token === "--version") {
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
- if (!["--node-image", "--codex-command", "--ready-timeout", "--proxy"].includes(name)) {
144
- throw new ConsumerCliError(`unknown option: ${token}`, 2);
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 === "--node-image") parsed.nodeImage = value;
152
- if (name === "--codex-command") parsed.codexCommand = value;
153
- if (name === "--ready-timeout") parsed.readyTimeout = value;
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 (!/^[A-Za-z0-9][A-Za-z0-9._/-]*@sha256:[a-f0-9]{64}$/.test(parsed.nodeImage)) {
157
- throw new ConsumerCliError("Consumer image must be pinned by digest", 2);
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 bundledCodexCommand() {
166
- try {
167
- return createRequire(import.meta.url).resolve("@openai/codex/bin/codex.js");
168
- } catch {
169
- return "codex";
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
- export function toScriptArgs(parsed) {
189
- const args = ["--node-image", parsed.nodeImage];
190
- if (parsed.codexCommand) args.push("--codex-command", parsed.codexCommand);
191
- if (parsed.readyTimeout) args.push("--ready-timeout", parsed.readyTimeout);
192
- if (parsed.proxy) args.push("--proxy", parsed.proxy);
193
- if (parsed.noBrowser) args.push("--no-browser");
194
- if (parsed.noCodex) args.push("--no-codex");
195
- if (parsed.stop) args.push("--stop");
196
- if (parsed.resetLocal) args.push("--reset-local");
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 runScript(script, args, { env, spawn }) {
203
- return new Promise((resolve, reject) => {
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
- child = spawn("bash", [script, ...args], { env: { ...env }, stdio: "inherit" });
207
- } catch (error) {
208
- reject(new ConsumerCliError(`could not start bash: ${error.message}`));
209
- return;
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
- export { CONSUMER_RELEASE_VERSION, DEFAULT_NODE_IMAGE, HELP as CONSUMER_HELP };
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
+ }
@@ -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: