mycomesh-consumer 0.1.35 → 0.1.37

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mycomesh-consumer",
3
- "version": "0.1.35",
3
+ "version": "0.1.37",
4
4
  "description": "Native Node.js MycoMesh Consumer and OpenAI-compatible request CLI.",
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -84,7 +84,6 @@ const RESPONSES_REQUEST_OPTION_FIELDS = new Set([
84
84
  const RESPONSES_LOCAL_OPTION_FIELDS = new Set(["stream", "stream_options"]);
85
85
  const MAX_SHARE_MINUTES = 24 * 60;
86
86
  const TUNNEL_START_TIMEOUT_MS = 30_000;
87
- const TUNNEL_READY_TIMEOUT_MS = 90_000;
88
87
 
89
88
  const DEFAULT_NETWORK = Object.freeze({
90
89
  chain_id: DEFAULT_CHAIN_ID,
@@ -358,8 +357,11 @@ function normalizeInferenceOptions(endpoint, options) {
358
357
  if (typeof options !== "object" || Array.isArray(options)) {
359
358
  throw new Error("inference request options must be a JSON object");
360
359
  }
360
+ const requestOptions = Object.fromEntries(
361
+ Object.entries(options).filter(([key]) => !RESPONSES_LOCAL_OPTION_FIELDS.has(key)),
362
+ );
361
363
  if (endpoint !== "responses") {
362
- if (Object.keys(options).length) {
364
+ if (Object.keys(requestOptions).length) {
363
365
  throw new Error("inference request options are supported only for responses");
364
366
  }
365
367
  return null;
@@ -369,7 +371,7 @@ function normalizeInferenceOptions(endpoint, options) {
369
371
  if (unknown.length) throw new Error(`unsupported Responses request options: ${unknown.join(", ")}`);
370
372
  const normalized = {};
371
373
  for (const key of [...RESPONSES_REQUEST_OPTION_FIELDS].sort()) {
372
- if (Object.prototype.hasOwnProperty.call(options, key)) normalized[key] = options[key];
374
+ if (Object.prototype.hasOwnProperty.call(requestOptions, key)) normalized[key] = requestOptions[key];
373
375
  }
374
376
  return Object.keys(normalized).length ? normalized : null;
375
377
  }
@@ -593,7 +595,6 @@ export class NativeConsumerState {
593
595
  this.paymentAddress = paymentKeyAddress(this.paymentKey);
594
596
  this.tunnelCommand = options.tunnelCommand || env.MYCOMESH_CONSUMER_TUNNEL_COMMAND || "cloudflared";
595
597
  this.tunnelSpawn = options.tunnelSpawn || defaultSpawn;
596
- this.tunnelProbe = options.tunnelProbe || waitForTunnelReady;
597
598
  this.share = null;
598
599
  }
599
600
 
@@ -800,8 +801,6 @@ export class NativeConsumerState {
800
801
  share.process = child;
801
802
  const publicUrl = await waitForTunnelUrl(child);
802
803
  if (this.share !== share) throw new Error("temporary share was cancelled");
803
- await this.tunnelProbe(publicUrl, apiKey, this.dispatcher);
804
- if (this.share !== share) throw new Error("temporary share was cancelled");
805
804
  share.baseUrl = `${publicUrl.replace(/\/+$/, "")}/v1`;
806
805
  share.timer = setTimeout(() => { void this.stopShare(); }, minutes * 60 * 1000);
807
806
  share.timer.unref?.();
@@ -1035,6 +1034,8 @@ function writeJson(response, status, value, headers = {}) {
1035
1034
  function waitForTunnelUrl(child) {
1036
1035
  return new Promise((resolve, reject) => {
1037
1036
  let output = "";
1037
+ let publicUrl = "";
1038
+ let connected = false;
1038
1039
  const finish = (error, url) => {
1039
1040
  clearTimeout(timer);
1040
1041
  child.removeListener("error", onError);
@@ -1046,7 +1047,9 @@ function waitForTunnelUrl(child) {
1046
1047
  const onData = (chunk) => {
1047
1048
  output = `${output}${String(chunk)}`.slice(-16_384);
1048
1049
  const match = output.match(/https:\/\/[a-z0-9-]+\.trycloudflare\.com/i);
1049
- if (match) finish(null, match[0]);
1050
+ if (match) publicUrl = match[0];
1051
+ if (/Registered tunnel connection/i.test(output)) connected = true;
1052
+ if (publicUrl && connected) finish(null, publicUrl);
1050
1053
  };
1051
1054
  const onError = (error) => finish(new Error(`could not start cloudflared: ${error.message}`));
1052
1055
  const onExit = (code) => finish(new Error(`cloudflared exited before publishing a URL (${code ?? "signal"})`));
@@ -1061,26 +1064,6 @@ function waitForTunnelUrl(child) {
1061
1064
  });
1062
1065
  }
1063
1066
 
1064
- async function waitForTunnelReady(publicUrl, apiKey, dispatcher) {
1065
- const deadline = Date.now() + TUNNEL_READY_TIMEOUT_MS;
1066
- let lastError;
1067
- while (Date.now() < deadline) {
1068
- try {
1069
- const response = await fetchWithTimeout(`${publicUrl.replace(/\/+$/, "")}/v1/health`, {
1070
- headers: { authorization: `Bearer ${apiKey}` },
1071
- dispatcher,
1072
- }, Math.min(3000, deadline - Date.now()));
1073
- const payload = await readJsonResponse(response);
1074
- if (response.ok && payload.protocol === "mycomesh-temporary-share/v1") return;
1075
- lastError = new Error(`HTTP ${response.status}`);
1076
- } catch (error) {
1077
- lastError = error;
1078
- }
1079
- await new Promise((resolve) => setTimeout(resolve, 500));
1080
- }
1081
- throw new Error(`temporary HTTPS URL was not reachable: ${lastError?.message || "timed out"}`);
1082
- }
1083
-
1084
1067
  async function handleInference(state, request, response, path, alphaSearchQuery, shareOnly = false) {
1085
1068
  const authorization = String(request.headers.authorization || "");
1086
1069
  if (!state.authorizeBearer(authorization, { shareOnly })) {
package/src/consumer.mjs CHANGED
@@ -11,7 +11,7 @@ import {
11
11
  createConsumerServer,
12
12
  } from "./consumer-runtime.mjs";
13
13
 
14
- export const CONSUMER_RELEASE_VERSION = "0.1.35";
14
+ export const CONSUMER_RELEASE_VERSION = "0.1.37";
15
15
  export const API_COMMANDS = new Set(["health", "models", "responses", "chat"]);
16
16
  const API_VALUE_OPTIONS = new Set([
17
17
  "--base-url",