@pyxmate/memory 1.26.2 → 1.26.4

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.
@@ -270,6 +270,11 @@ var MemoryClient = class {
270
270
  "enableMultiHop is embedded-only (the HTTP API does not forward it); use the embedded Memory class for iterative multi-hop retrieval"
271
271
  );
272
272
  }
273
+ if (params.namespaceIds !== void 0) {
274
+ throw new Error(
275
+ "namespaceIds is not accepted over HTTP (it is the internal AuthzPlan list); use namespaceId for an exact namespace"
276
+ );
277
+ }
273
278
  const searchParams = new URLSearchParams({ query: params.query });
274
279
  if (params.limit) searchParams.set("limit", String(params.limit));
275
280
  if (params.type) searchParams.set("type", params.type);
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  MemoryClient
3
- } from "./chunk-EHFEPWCL.mjs";
3
+ } from "./chunk-LQDQHLVP.mjs";
4
4
 
5
5
  // ../dashboard/src/aggregations/consolidation-analytics.ts
6
6
  function analyzeConsolidationLog(entries) {
@@ -866,6 +866,19 @@ function mcpJson(payload) {
866
866
 
867
867
  // src/mcp/http-client.ts
868
868
  var DEFAULT_TIMEOUT_MS = 15e3;
869
+ function parseRetryAfterSeconds(header) {
870
+ const value = header?.trim() ?? "";
871
+ return /^\d+$/.test(value) ? Number(value) : void 0;
872
+ }
873
+ var HTTP_DATE = /^(?:[A-Z][a-z]{2}, \d{2} [A-Z][a-z]{2} \d{4} \d{2}:\d{2}:\d{2} GMT|[A-Z][a-z]{5,8}, \d{2}-[A-Z][a-z]{2}-\d{2} \d{2}:\d{2}:\d{2} GMT|[A-Z][a-z]{2} [A-Z][a-z]{2} [ \d]\d \d{2}:\d{2}:\d{2} \d{4})$/;
874
+ function parseRetryAfterMs(header) {
875
+ const seconds = parseRetryAfterSeconds(header);
876
+ if (seconds !== void 0) return seconds * 1e3;
877
+ const value = header?.trim() ?? "";
878
+ if (!HTTP_DATE.test(value)) return void 0;
879
+ const at = Date.parse(value.endsWith(" GMT") ? value : `${value} GMT`);
880
+ return Number.isNaN(at) ? void 0 : Math.max(0, at - Date.now());
881
+ }
869
882
  function validateIdempotencyKey(key) {
870
883
  if (key.length === 0 || !key.isWellFormed() || new TextEncoder().encode(key).byteLength > 256) {
871
884
  throw new Error("idempotencyKey must be 1-256 well-formed UTF-8 bytes");
@@ -2126,6 +2139,7 @@ function createReadCredentials(providerFactory) {
2126
2139
  import { createHash as createHash5, randomUUID as randomUUID5 } from "crypto";
2127
2140
  import { readFile as readFile2, stat as stat2 } from "fs/promises";
2128
2141
  import { basename as basename2, isAbsolute as isAbsolute2, resolve as resolve2 } from "path";
2142
+ import { setTimeout as delay2 } from "timers/promises";
2129
2143
  import { Client as McpClient } from "@modelcontextprotocol/sdk/client/index.js";
2130
2144
  import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js";
2131
2145
  import { Server } from "@modelcontextprotocol/sdk/server/index.js";
@@ -2317,8 +2331,7 @@ async function pause(ms, signal) {
2317
2331
  });
2318
2332
  }
2319
2333
  function retryAfterMs(header) {
2320
- const value = header?.trim() ?? "";
2321
- const seconds = /^\d+$/.test(value) ? Number(value) : DEFAULT_RETRY_AFTER_S;
2334
+ const seconds = parseRetryAfterSeconds(header) ?? DEFAULT_RETRY_AFTER_S;
2322
2335
  return Math.min(seconds, MAX_RETRY_AFTER_S) * 1e3;
2323
2336
  }
2324
2337
  function formatCents(microcents, decimals) {
@@ -2736,6 +2749,67 @@ function createGuardedFetch(guard, fetchImpl = fetch) {
2736
2749
  };
2737
2750
  return Object.assign(wrapped, { preconnect: fetch.preconnect });
2738
2751
  }
2752
+ var RETRYABLE_MCP_METHODS = /* @__PURE__ */ new Set([
2753
+ "initialize",
2754
+ "notifications/initialized",
2755
+ "tools/list",
2756
+ "prompts/list"
2757
+ ]);
2758
+ var MCP_RETRY_BUDGET_MS = 2e4;
2759
+ var MIN_RESEND_SPACING_MS = 1e3;
2760
+ function isRetryableMcpMessage(input, init) {
2761
+ const method = init?.method ?? (input instanceof Request ? input.method : "GET");
2762
+ if (method.toUpperCase() !== "POST" || typeof init?.body !== "string") return false;
2763
+ let message;
2764
+ try {
2765
+ message = JSON.parse(init.body);
2766
+ } catch {
2767
+ return false;
2768
+ }
2769
+ if (typeof message !== "object" || message === null) return false;
2770
+ const { method: rpc } = message;
2771
+ return typeof rpc === "string" && RETRYABLE_MCP_METHODS.has(rpc);
2772
+ }
2773
+ function resendDelayMs(res, deadline) {
2774
+ if (res.status !== 429 && res.status !== 503) return void 0;
2775
+ const retryAfterMs2 = parseRetryAfterMs(res.headers.get("retry-after"));
2776
+ if (retryAfterMs2 === void 0) return void 0;
2777
+ const waitMs = Math.max(retryAfterMs2, MIN_RESEND_SPACING_MS);
2778
+ return Date.now() + waitMs > deadline ? void 0 : waitMs;
2779
+ }
2780
+ function createMcpRetryAfterFetch(fetchImpl = fetch, retryUntil = () => Date.now() + MCP_RETRY_BUDGET_MS) {
2781
+ const wrapped = async (input, init) => {
2782
+ if (!isRetryableMcpMessage(input, init)) return fetchImpl(input, init);
2783
+ const deadline = retryUntil();
2784
+ const signal = init?.signal ?? (input instanceof Request ? input.signal : void 0);
2785
+ for (; ; ) {
2786
+ const res = await fetchImpl(input, init);
2787
+ const waitMs = resendDelayMs(res, deadline);
2788
+ if (waitMs === void 0) return res;
2789
+ await res.body?.cancel();
2790
+ await delay2(waitMs, void 0, { signal });
2791
+ }
2792
+ };
2793
+ return Object.assign(wrapped, { preconnect: fetch.preconnect });
2794
+ }
2795
+ async function connectRemoteMcp(client, url, apiKey, fetchImpl, budgetMs = MCP_RETRY_BUDGET_MS) {
2796
+ const connectUntil = Date.now() + budgetMs;
2797
+ let connecting = true;
2798
+ const transport = new StreamableHTTPClientTransport(url, {
2799
+ requestInit: { headers: { Authorization: `Bearer ${apiKey}` } },
2800
+ fetch: createMcpIdempotentFetch(
2801
+ createMcpRetryAfterFetch(
2802
+ fetchImpl,
2803
+ () => connecting ? connectUntil : Date.now() + budgetMs
2804
+ )
2805
+ )
2806
+ });
2807
+ try {
2808
+ await client.connect(transport);
2809
+ } finally {
2810
+ connecting = false;
2811
+ }
2812
+ }
2739
2813
  function extractLocalUpload(meta) {
2740
2814
  if (meta === null || typeof meta !== "object") return void 0;
2741
2815
  const descriptor = meta[LOCAL_UPLOAD_META_KEY];
@@ -2877,7 +2951,7 @@ function createProxyServer(client, version, uploadLocalFile, hostedFileIngest) {
2877
2951
  return server;
2878
2952
  }
2879
2953
  async function runMcpProxyServer(opts) {
2880
- const version = opts.version ?? (true ? "1.26.2" : "0.0.0-dev");
2954
+ const version = opts.version ?? (true ? "1.26.4" : "0.0.0-dev");
2881
2955
  const read = await opts.readCredentials();
2882
2956
  if (!read.ok) {
2883
2957
  throw new Error(
@@ -2888,12 +2962,8 @@ async function runMcpProxyServer(opts) {
2888
2962
  const url = new URL(`${endpoint.replace(/\/+$/, "")}${REMOTE_MCP_PATH}`);
2889
2963
  const guard = createCredentialGuard(opts.readCredentials, read.credentials);
2890
2964
  const client = new McpClient({ name: "pyx-mem-proxy", version }, { capabilities: {} });
2891
- const clientTransport = new StreamableHTTPClientTransport(url, {
2892
- requestInit: { headers: { Authorization: `Bearer ${apiKey}` } },
2893
- fetch: createMcpIdempotentFetch(createGuardedFetch(guard))
2894
- });
2895
2965
  try {
2896
- await client.connect(clientTransport);
2966
+ await connectRemoteMcp(client, url, apiKey, createGuardedFetch(guard));
2897
2967
  } catch (err) {
2898
2968
  const msg = err instanceof Error ? err.message : String(err);
2899
2969
  throw new Error(
@@ -11,8 +11,8 @@ import {
11
11
  toGraphologyFormat,
12
12
  transformGraphData,
13
13
  unreachableHealth
14
- } from "./chunk-GLQGLTMK.mjs";
15
- import "./chunk-EHFEPWCL.mjs";
14
+ } from "./chunk-NDXE3TIS.mjs";
15
+ import "./chunk-LQDQHLVP.mjs";
16
16
  import "./chunk-KZKGRND2.mjs";
17
17
  import "./chunk-VXXRCAKS.mjs";
18
18
  export {
package/dist/index.d.ts CHANGED
@@ -323,7 +323,8 @@ interface MemorySearchParams {
323
323
  * legacy NULL-namespace entries are visible). `undefined` skips the
324
324
  * filter (single-tenant / pre-ReBAC compat).
325
325
  *
326
- * Callers must not set this directly; use `namespaceId` for exact scope.
326
+ * Callers must not set this directly (`MemoryClient.search` rejects it); use
327
+ * `namespaceId` for exact scope.
327
328
  */
328
329
  namespaceIds?: string[];
329
330
  /** Strict namespace equality compiled internally from `namespaceId`. */
package/dist/index.mjs CHANGED
@@ -2,7 +2,7 @@ import {
2
2
  DisabledMemory,
3
3
  MemoryClient,
4
4
  MemoryServerError
5
- } from "./chunk-EHFEPWCL.mjs";
5
+ } from "./chunk-LQDQHLVP.mjs";
6
6
  import {
7
7
  DEFAULTS,
8
8
  MEMORY_PROJECT_LABEL_MAX_CHARS,
package/dist/react.mjs CHANGED
@@ -11,8 +11,8 @@ import {
11
11
  toGraphologyFormat,
12
12
  transformGraphData,
13
13
  unreachableHealth
14
- } from "./chunk-GLQGLTMK.mjs";
15
- import "./chunk-EHFEPWCL.mjs";
14
+ } from "./chunk-NDXE3TIS.mjs";
15
+ import "./chunk-LQDQHLVP.mjs";
16
16
  import "./chunk-KZKGRND2.mjs";
17
17
  import "./chunk-VXXRCAKS.mjs";
18
18
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pyxmate/memory",
3
- "version": "1.26.2",
3
+ "version": "1.26.4",
4
4
  "type": "module",
5
5
  "description": "SDK for pyx-memory — Memory as a Service for AI agents",
6
6
  "license": "MIT",