@ai-matrx/data 0.18.36 → 0.18.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/CHANGELOG.md +6 -0
- package/README.md +1 -1
- package/dist/db.cjs.map +1 -1
- package/dist/db.d.cts +1 -1
- package/dist/db.d.ts +1 -1
- package/dist/db.js.map +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/net.cjs.map +1 -1
- package/dist/net.d.cts +1 -1
- package/dist/net.d.ts +1 -1
- package/dist/net.js.map +1 -1
- package/package.json +1 -1
package/dist/net.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/net/errors.ts","../src/net/retry.ts","../src/net/resilient-fetch.ts","../src/net/stream-monitor.ts"],"sourcesContent":["/**\n * Structured errors for the resilience layer.\n *\n * Every network-layer failure resolves to one of these classes so callers\n * (and any recovery UI) can branch on error type, not on string matching.\n *\n * Ported verbatim from matrx-frontend `lib/net/errors.ts` — the origin of the\n * trio. The one coupling seam removed: `extractErrorMessage` (previously the\n * app's `utils/errors`) is pure logic and ships inside the package.\n */\n\nexport type NetErrorCode =\n | \"connect-timeout\"\n | \"total-timeout\"\n | \"heartbeat-timeout\"\n | \"network\"\n | \"http\"\n | \"aborted\"\n | \"offline\"\n | \"unknown\";\n\nexport class NetError extends Error {\n readonly code: NetErrorCode;\n override readonly cause?: unknown;\n readonly status?: number;\n readonly retryable: boolean;\n\n constructor(\n code: NetErrorCode,\n message: string,\n opts: { cause?: unknown; status?: number; retryable?: boolean } = {},\n ) {\n super(message);\n this.name = \"NetError\";\n this.code = code;\n this.cause = opts.cause;\n // Conditional only for `exactOptionalPropertyTypes` — same runtime shape.\n if (opts.status !== undefined) this.status = opts.status;\n this.retryable = opts.retryable ?? false;\n }\n}\n\nexport class ConnectTimeoutError extends NetError {\n constructor(ms: number, cause?: unknown) {\n super(\"connect-timeout\", `Connection timed out after ${ms}ms`, {\n cause,\n retryable: true,\n });\n this.name = \"ConnectTimeoutError\";\n }\n}\n\nexport class TotalTimeoutError extends NetError {\n constructor(ms: number, cause?: unknown) {\n super(\"total-timeout\", `Request exceeded ${ms}ms total budget`, {\n cause,\n retryable: false,\n });\n this.name = \"TotalTimeoutError\";\n }\n}\n\nexport class HeartbeatTimeoutError extends NetError {\n constructor(ms: number, cause?: unknown) {\n super(\n \"heartbeat-timeout\",\n `No server activity for ${ms}ms — stream considered dead`,\n { cause, retryable: false },\n );\n this.name = \"HeartbeatTimeoutError\";\n }\n}\n\nexport class NetworkError extends NetError {\n constructor(message: string, cause?: unknown) {\n super(\"network\", message, { cause, retryable: true });\n this.name = \"NetworkError\";\n }\n}\n\nexport class HttpError extends NetError {\n constructor(status: number, message: string, cause?: unknown) {\n // 408/429/5xx are generally safe to retry for idempotent ops.\n const retryable = status === 408 || status === 429 || status >= 500;\n super(\"http\", message, { cause, status, retryable });\n this.name = \"HttpError\";\n }\n}\n\nexport class AbortedError extends NetError {\n constructor(cause?: unknown) {\n super(\"aborted\", \"Request was aborted\", { cause, retryable: false });\n this.name = \"AbortedError\";\n }\n}\n\nexport class OfflineError extends NetError {\n constructor() {\n super(\"offline\", \"Browser is offline\", { retryable: true });\n this.name = \"OfflineError\";\n }\n}\n\nexport function isNetError(err: unknown): err is NetError {\n return err instanceof NetError;\n}\n\n/**\n * Folds any thrown value into a descriptive message string — THE one reader\n * for every failure shape this platform actually emits.\n *\n * 2026-09-07 (duplication census rows 9, 10, 21): this body had DRIFTED BEHIND\n * three host copies, which is the campaign's failure mode running in the\n * package's favour-direction. Each host had learned something the package\n * never did, so every non-frontend consumer of `@ai-matrx/data/net` was\n * flattening a server's own sentence into \"An unexpected error occurred\". All\n * three are folded in here, with a named regression test per shape:\n *\n * 1. **FastAPI's `detail`** (matrx-frontend `utils/errors.ts`, learned\n * 2026-08-31 as V2 finding G5). Our server refuses in `detail` — a string,\n * or an object carrying `message` — and every reader checked\n * `message`/`details` only. The server's sentence is the whole point of\n * catching this.\n * 2. **A `fallback` argument** (matrx-frontend `ShortcutForm.tsx`). A caller\n * who knows what it was doing can say \"Failed to save shortcut\" instead of\n * the generic sentence. Optional; the default is unchanged, so every\n * existing single-argument call behaves exactly as before.\n * 3. **Recursion into nested error objects** (aidream `workflow-studio`, two\n * byte-identical copies). The run pipeline nests: `{error: {type, message}}`\n * and `{error: {error: ...}}` and `{exception: {...}}` are all real shapes,\n * and a non-recursive reader answers \"An unexpected error occurred\" while\n * holding the actual reason two levels down. Depth-capped at 4 — a cyclic\n * or absurdly deep object must not hang a render.\n *\n * PostgREST-style errors are plain objects carrying\n * `message`/`details`/`hint`/`code`; a bare `String(err)` on those yields\n * \"[object Object]\", which is why this exists at all.\n */\nexport function extractErrorMessage(\n err: unknown,\n fallback = \"An unexpected error occurred\",\n): string {\n if (!err) return \"Unknown error\";\n if (typeof err === \"string\") return err;\n if (err instanceof Error) return err.message;\n if (typeof err === \"object\") {\n const e = err as Record<string, unknown>;\n const parts: string[] = [];\n if (typeof e.message === \"string\" && e.message) parts.push(e.message);\n // FastAPI's own word for the reason — only when nothing said `message`,\n // so a PostgREST error keeps its exact composed sentence.\n if (parts.length === 0) {\n if (typeof e.detail === \"string\" && e.detail) parts.push(e.detail);\n else if (e.detail && typeof e.detail === \"object\") {\n const d = e.detail as Record<string, unknown>;\n if (typeof d.message === \"string\" && d.message) parts.push(d.message);\n }\n }\n if (typeof e.details === \"string\" && e.details) parts.push(e.details);\n if (typeof e.hint === \"string\" && e.hint) parts.push(`Hint: ${e.hint}`);\n if (typeof e.code === \"string\" && e.code) parts.push(`Code: ${e.code}`);\n if (parts.length > 0) return parts.join(\" · \");\n\n const nested = extractNestedErrorMessage(e, 0);\n if (nested !== null) return nested;\n\n try {\n const s = JSON.stringify(err);\n if (s && s !== \"{}\") return s;\n } catch {\n /* ignore */\n }\n }\n return fallback;\n}\n\n/** Depth-capped walk into `error` / `exception` / `cause`. See above. */\nfunction extractNestedErrorMessage(\n e: Record<string, unknown>,\n depth: number,\n): string | null {\n if (depth > 4) return null;\n for (const key of [\"error\", \"exception\", \"cause\"] as const) {\n const value = e[key];\n if (typeof value === \"string\" && value) return value;\n if (value && typeof value === \"object\") {\n const inner = value as Record<string, unknown>;\n if (typeof inner.message === \"string\" && inner.message) return inner.message;\n if (typeof inner.detail === \"string\" && inner.detail) return inner.detail;\n const deeper = extractNestedErrorMessage(inner, depth + 1);\n if (deeper !== null) return deeper;\n }\n }\n return null;\n}\n\n/**\n * True when a failure is the TRANSPORT dying, not the server answering: the\n * browser is offline, asleep, mid-wifi-handoff, or DNS/TLS failed. It also\n * covers the bounded Envoy/Supabase gateway shape emitted when the upstream\n * database connection dies before response headers. `fetch`\n * rejects with a bare `TypeError: Failed to fetch` in every browser, and\n * supabase-js surfaces that verbatim (message only — no code, no hint).\n *\n * Use it to decide how LOUD a failure is, never whether to handle it. A\n * transport failure carries nothing an engineer can act on, so logging it at\n * error level buries the failures that do — that is how a notes surface filed\n * a system_error every time a laptop slept (2026-08-11). Anything with a\n * Postgres code, an HTTP status, or a server message is NOT this: keep those\n * loud.\n */\nexport function isTransportFailure(err: unknown): boolean {\n if (err instanceof NetworkError || err instanceof OfflineError) return true;\n if (typeof navigator !== \"undefined\" && navigator.onLine === false) return true;\n if (err instanceof TypeError) return true;\n if (err && typeof err === \"object\") {\n const e = err as { code?: unknown; status?: unknown; message?: unknown; name?: unknown };\n // A real PostgREST/Postgres failure always carries a code or status.\n if (e.code || e.status) return false;\n const text = `${typeof e.name === \"string\" ? e.name : \"\"} ${\n typeof e.message === \"string\" ? e.message : \"\"\n }`.toLowerCase();\n return (\n text.includes(\"failed to fetch\") ||\n text.includes(\"networkerror\") ||\n text.includes(\"network request failed\") ||\n text.includes(\"load failed\") || // Safari's wording for the same condition\n text.includes(\"upstream connect error or disconnect/reset before headers\")\n );\n }\n return false;\n}\n\nexport function toNetError(err: unknown): NetError {\n if (isNetError(err)) return err;\n if (err instanceof DOMException && err.name === \"AbortError\") {\n return new AbortedError(err);\n }\n if (err instanceof TypeError) {\n // fetch() throws TypeError on DNS/connection failure in every browser.\n return new NetworkError(err.message || \"Network request failed\", err);\n }\n return new NetError(\n \"unknown\",\n extractErrorMessage(err),\n { cause: err },\n );\n}\n","/**\n * withRetry — exponential backoff retry for idempotent operations.\n *\n * IMPORTANT: only wrap operations that are safe to repeat (GETs, cache\n * lookups, agent-definition fetches). Never wrap user-authored submissions —\n * recovery UX handles those via explicit user-initiated retry.\n *\n * Ported verbatim from matrx-frontend `lib/net/retry.ts`.\n */\n\nimport { isNetError, NetError } from \"./errors\";\n\nexport interface RetryOptions {\n /** Total attempts including the first. Default 3. */\n attempts?: number;\n /** Initial delay ms before the first retry. Default 250. */\n initialDelayMs?: number;\n /** Max delay ms cap between retries. Default 4_000. */\n maxDelayMs?: number;\n /** Multiplier applied after each failure. Default 2. */\n backoffFactor?: number;\n /** Jitter factor 0-1 applied to each delay. Default 0.25. */\n jitter?: number;\n /** Predicate deciding whether a given error should trigger a retry. Default: NetError.retryable. */\n retryOn?: (err: unknown) => boolean;\n /** Caller-provided signal. If aborted, no further retries are attempted. */\n signal?: AbortSignal;\n /** Fires before each retry; useful for logging/telemetry. */\n onRetry?: (attempt: number, err: unknown, delayMs: number) => void;\n}\n\nfunction defaultRetryOn(err: unknown): boolean {\n return isNetError(err) && (err as NetError).retryable;\n}\n\nfunction sleep(ms: number, signal?: AbortSignal): Promise<void> {\n return new Promise((resolve, reject) => {\n const timer = setTimeout(() => {\n resolve();\n if (signal) signal.removeEventListener(\"abort\", onAbort);\n }, ms);\n const onAbort = () => {\n clearTimeout(timer);\n reject(signal?.reason ?? new Error(\"Aborted\"));\n };\n if (signal) {\n if (signal.aborted) {\n clearTimeout(timer);\n reject(signal.reason);\n } else {\n signal.addEventListener(\"abort\", onAbort, { once: true });\n }\n }\n });\n}\n\nexport async function withRetry<T>(\n fn: (attempt: number) => Promise<T>,\n opts: RetryOptions = {},\n): Promise<T> {\n const attempts = Math.max(1, opts.attempts ?? 3);\n const initialDelayMs = opts.initialDelayMs ?? 250;\n const maxDelayMs = opts.maxDelayMs ?? 4_000;\n const factor = opts.backoffFactor ?? 2;\n const jitter = Math.max(0, Math.min(1, opts.jitter ?? 0.25));\n const retryOn = opts.retryOn ?? defaultRetryOn;\n\n let lastErr: unknown;\n for (let attempt = 1; attempt <= attempts; attempt++) {\n if (opts.signal?.aborted) throw opts.signal.reason;\n try {\n return await fn(attempt);\n } catch (err) {\n lastErr = err;\n if (attempt === attempts || !retryOn(err)) throw err;\n\n const base = Math.min(\n maxDelayMs,\n initialDelayMs * Math.pow(factor, attempt - 1),\n );\n const jitterAmount = base * jitter * (Math.random() * 2 - 1);\n const delayMs = Math.max(0, Math.round(base + jitterAmount));\n opts.onRetry?.(attempt, err, delayMs);\n await sleep(delayMs, opts.signal);\n }\n }\n\n // Unreachable — the loop always either returns or throws.\n throw lastErr;\n}\n","/**\n * resilientFetch — `fetch` with connect + total timeouts and composed abort.\n *\n * Every outbound HTTP call should go through this, not raw fetch. The\n * two-stage timeout (connect + total) lets callers allow long-streaming\n * responses without giving up the ability to fail fast when the server is\n * simply unreachable.\n *\n * Ported verbatim from matrx-frontend `lib/net/resilient-fetch.ts`. `fetch`\n * comes from the environment (Node 20+, browsers, React Native/Hermes) —\n * there is deliberately no injected transport here.\n */\n\nimport {\n AbortedError,\n ConnectTimeoutError,\n extractErrorMessage,\n HttpError,\n NetworkError,\n OfflineError,\n TotalTimeoutError,\n} from \"./errors\";\n\nexport interface ResilientFetchOptions {\n /** Max ms from request start → response headers received. Default 15_000. */\n connectTimeoutMs?: number;\n /**\n * Max ms from request start → fetch() promise resolves.\n * For streaming endpoints the response arrives quickly and the stream body\n * is read by the caller, so this bound only guards the handshake itself.\n * `null` disables the ceiling. Default 120_000.\n */\n totalTimeoutMs?: number | null;\n /** Caller-provided signal; composed with our internal timeout signals. */\n signal?: AbortSignal;\n /**\n * If true, throw on non-2xx responses instead of returning them. Default true.\n * Callers that need to read structured error bodies can set this to false.\n */\n throwOnHttpError?: boolean;\n}\n\nexport interface ResilientFetchResult {\n response: Response;\n /**\n * Composed AbortController tied to the fetch. Callers reading the body\n * (e.g. streaming) can call `.abort()` from this controller to cancel\n * in-flight reads. Already aborted on connect/total timeout.\n */\n controller: AbortController;\n}\n\nconst DEFAULTS = {\n connectTimeoutMs: 15_000,\n totalTimeoutMs: 120_000,\n} as const;\n\nfunction linkAbort(target: AbortController, signal: AbortSignal): () => void {\n if (signal.aborted) {\n target.abort(signal.reason);\n return () => {};\n }\n const onAbort = () => target.abort(signal.reason);\n signal.addEventListener(\"abort\", onAbort, { once: true });\n return () => signal.removeEventListener(\"abort\", onAbort);\n}\n\nexport async function resilientFetch(\n url: string,\n init: RequestInit = {},\n opts: ResilientFetchOptions = {},\n): Promise<ResilientFetchResult> {\n const connectTimeoutMs = opts.connectTimeoutMs ?? DEFAULTS.connectTimeoutMs;\n const totalTimeoutMs =\n opts.totalTimeoutMs === undefined\n ? DEFAULTS.totalTimeoutMs\n : opts.totalTimeoutMs;\n const throwOnHttpError = opts.throwOnHttpError ?? true;\n\n // NOTE: we deliberately do NOT hard-block on `navigator.onLine === false`\n // here. That flag is only a HINT — it is unreliable in both directions\n // (VPNs, virtual network adapters, browser network-service hiccups, sleep/\n // wake, and some corporate stacks leave it stuck at `false` while the\n // machine is fully online). Trusting it as a pre-flight gate produced a\n // real production outage: the Agent Builder (this path) threw OfflineError\n // on every submit while the Run path — which uses plain fetch() and never\n // consults the flag — worked fine on the same network. We now let the\n // fetch actually run and only classify the result as \"offline\" if a genuine\n // network failure ALSO corroborates the flag (see the catch below).\n\n const controller = new AbortController();\n const unlinkCaller = opts.signal\n ? linkAbort(controller, opts.signal)\n : () => {};\n\n let connectTimedOut = false;\n let totalTimedOut = false;\n\n const connectTimer = setTimeout(() => {\n connectTimedOut = true;\n controller.abort(\"connect-timeout\");\n }, connectTimeoutMs);\n\n const totalTimer =\n totalTimeoutMs !== null\n ? setTimeout(() => {\n totalTimedOut = true;\n controller.abort(\"total-timeout\");\n }, totalTimeoutMs)\n : null;\n\n try {\n const response = await fetch(url, { ...init, signal: controller.signal });\n clearTimeout(connectTimer);\n // Both timers end with the handshake: `totalTimeoutMs` bounds request\n // start → fetch() resolution (headers), exactly as documented on the\n // option. Body reads are guarded by the caller (stream monitor /\n // heartbeats), not by this timer — clearing it here is what lets a\n // long-streaming body outlive the handshake budget.\n if (totalTimer !== null) clearTimeout(totalTimer);\n\n if (throwOnHttpError && !response.ok) {\n throw new HttpError(\n response.status,\n `HTTP ${response.status} ${response.statusText}`,\n );\n }\n\n return { response, controller };\n } catch (err) {\n clearTimeout(connectTimer);\n if (totalTimer !== null) clearTimeout(totalTimer);\n\n if (connectTimedOut) throw new ConnectTimeoutError(connectTimeoutMs, err);\n if (totalTimedOut)\n throw new TotalTimeoutError(totalTimeoutMs as number, err);\n if (err instanceof DOMException && err.name === \"AbortError\") {\n throw new AbortedError(err);\n }\n if (opts.signal?.aborted) {\n // Caller aborted with a CUSTOM reason: fetch rejects with that reason\n // verbatim (not an AbortError DOMException). Without this check the\n // abort fell through to the generic classifiers and could surface as a\n // retryable NetworkError — an aborted request must never be retried.\n throw new AbortedError(err);\n }\n if (err instanceof TypeError) {\n // fetch() throws TypeError on DNS/connection failure. If the browser\n // ALSO reports offline, the flag is now corroborated by an actual\n // failure — surface the more specific OfflineError. Absent a real\n // failure, `navigator.onLine === false` is never allowed to block.\n if (typeof navigator !== \"undefined\" && navigator.onLine === false) {\n throw new OfflineError();\n }\n throw new NetworkError(err.message || \"Network request failed\", err);\n }\n if (err instanceof HttpError) throw err;\n throw new NetworkError(extractErrorMessage(err), err);\n } finally {\n unlinkCaller();\n }\n}\n","/**\n * Stream liveness monitor.\n *\n * Wraps an async iterable of server events and enforces two guarantees:\n * 1. Heartbeat deadline — fail if no event arrives within `heartbeatTimeoutMs`.\n * 2. Absolute ceiling — fail if total wall-clock time exceeds `maxLifetimeMs`.\n *\n * The wrapper is transparent: events pass through in order, with the same\n * shape. The only observable difference is that a stuck stream throws\n * `HeartbeatTimeoutError` or `TotalTimeoutError` instead of awaiting forever.\n *\n * The wrapped iterable should be driven by NDJSON parsing; the server MUST\n * emit `{kind:\"heartbeat\"}` at least every `heartbeatTimeoutMs / 2` ms for\n * long-running operations (the Matrx stream contract:\n * common-docs/systems/agents/execution-runtime/STREAM-CONTRACT.md).\n *\n * Ported verbatim from matrx-frontend `lib/net/stream-monitor.ts`, with one\n * defect fixed: cleanup of the underlying iterator after a watchdog timeout\n * is now fire-and-forget (see the note in the catch below).\n */\n\nimport { HeartbeatTimeoutError, TotalTimeoutError } from \"./errors\";\n\nexport interface StreamMonitorOptions {\n /** Max ms between any two events before the stream is considered dead. Default 30_000. */\n heartbeatTimeoutMs?: number;\n /** Max ms from wrap-start before throwing regardless of heartbeats. Default 600_000 (10min). */\n maxLifetimeMs?: number;\n /** Optional callback, fired every time a fresh event resets the deadline. */\n onHeartbeat?: (now: number) => void;\n /** Controller whose `.abort()` should be called on monitor-level timeout, so the underlying fetch is cancelled. */\n abortController?: AbortController;\n}\n\nconst DEFAULTS = {\n heartbeatTimeoutMs: 30_000,\n maxLifetimeMs: 600_000,\n} as const;\n\n/**\n * Wraps an async iterable so that it throws on stalled or overlong streams.\n *\n * Usage:\n * const live = monitorStream(events, { heartbeatTimeoutMs, abortController });\n * for await (const ev of live) { ... }\n */\nexport async function* monitorStream<T>(\n source: AsyncIterable<T>,\n opts: StreamMonitorOptions = {},\n): AsyncGenerator<T, void, undefined> {\n const heartbeatTimeoutMs =\n opts.heartbeatTimeoutMs ?? DEFAULTS.heartbeatTimeoutMs;\n const maxLifetimeMs = opts.maxLifetimeMs ?? DEFAULTS.maxLifetimeMs;\n const abort = opts.abortController;\n\n const startedAt = Date.now();\n const iter = source[Symbol.asyncIterator]() as AsyncIterator<T>;\n\n while (true) {\n const elapsed = Date.now() - startedAt;\n const remainingLifetime = maxLifetimeMs - elapsed;\n if (remainingLifetime <= 0) {\n abort?.abort(\"total-timeout\");\n throw new TotalTimeoutError(maxLifetimeMs);\n }\n\n const deadline = Math.min(heartbeatTimeoutMs, remainingLifetime);\n\n let timer: ReturnType<typeof setTimeout> | null = null;\n let timedOutKind: \"heartbeat\" | \"total\" | null = null;\n const timeoutPromise = new Promise<never>((_, reject) => {\n timer = setTimeout(() => {\n timedOutKind =\n deadline === remainingLifetime ? \"total\" : \"heartbeat\";\n abort?.abort(\n timedOutKind === \"total\" ? \"total-timeout\" : \"heartbeat-timeout\",\n );\n reject(\n timedOutKind === \"total\"\n ? new TotalTimeoutError(maxLifetimeMs)\n : new HeartbeatTimeoutError(heartbeatTimeoutMs),\n );\n }, deadline);\n });\n\n let result: IteratorResult<T>;\n try {\n result = await Promise.race([iter.next(), timeoutPromise]);\n } catch (err) {\n if (timer !== null) clearTimeout(timer);\n // Best-effort: let the underlying iterator clean up — WITHOUT awaiting\n // it. The original awaited `iter.return()`, but on an async generator\n // `return()` queues behind the still-pending `next()`; if the stream is\n // stuck and no abortController was provided to settle that read, the\n // await never resolves and the monitor hangs forever — the exact\n // failure mode this module exists to prevent. Fire-and-forget keeps\n // the timeout guarantee while still requesting cleanup.\n try {\n const cleanup = iter.return?.(undefined as never);\n if (cleanup) {\n void Promise.resolve(cleanup).catch(() => {\n /* ignore */\n });\n }\n } catch {\n /* ignore */\n }\n throw err;\n }\n\n if (timer !== null) clearTimeout(timer);\n if (result.done) return;\n\n opts.onHeartbeat?.(Date.now());\n yield result.value;\n }\n}\n"],"mappings":"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","names":["DEFAULTS"]}
|
|
1
|
+
{"version":3,"sources":["../src/net/errors.ts","../src/net/retry.ts","../src/net/resilient-fetch.ts","../src/net/stream-monitor.ts"],"sourcesContent":["/**\n * Structured errors for the resilience layer.\n *\n * Every network-layer failure resolves to one of these classes so callers\n * (and any recovery UI) can branch on error type, not on string matching.\n *\n * Ported verbatim from matrx-frontend `lib/net/errors.ts` — the origin of the\n * trio. The one coupling seam removed: `extractErrorMessage` (previously the\n * app's `utils/errors`) is pure logic and ships inside the package.\n */\n\nexport type NetErrorCode =\n | \"connect-timeout\"\n | \"total-timeout\"\n | \"heartbeat-timeout\"\n | \"network\"\n | \"http\"\n | \"aborted\"\n | \"offline\"\n | \"unknown\";\n\nexport class NetError extends Error {\n readonly code: NetErrorCode;\n override readonly cause?: unknown;\n readonly status?: number;\n readonly retryable: boolean;\n\n constructor(\n code: NetErrorCode,\n message: string,\n opts: { cause?: unknown; status?: number; retryable?: boolean } = {},\n ) {\n super(message);\n this.name = \"NetError\";\n this.code = code;\n this.cause = opts.cause;\n // Conditional only for `exactOptionalPropertyTypes` — same runtime shape.\n if (opts.status !== undefined) this.status = opts.status;\n this.retryable = opts.retryable ?? false;\n }\n}\n\nexport class ConnectTimeoutError extends NetError {\n constructor(ms: number, cause?: unknown) {\n super(\"connect-timeout\", `Connection timed out after ${ms}ms`, {\n cause,\n retryable: true,\n });\n this.name = \"ConnectTimeoutError\";\n }\n}\n\nexport class TotalTimeoutError extends NetError {\n constructor(ms: number, cause?: unknown) {\n super(\"total-timeout\", `Request exceeded ${ms}ms total budget`, {\n cause,\n retryable: false,\n });\n this.name = \"TotalTimeoutError\";\n }\n}\n\nexport class HeartbeatTimeoutError extends NetError {\n constructor(ms: number, cause?: unknown) {\n super(\n \"heartbeat-timeout\",\n `No server activity for ${ms}ms — stream considered dead`,\n { cause, retryable: false },\n );\n this.name = \"HeartbeatTimeoutError\";\n }\n}\n\nexport class NetworkError extends NetError {\n constructor(message: string, cause?: unknown) {\n super(\"network\", message, { cause, retryable: true });\n this.name = \"NetworkError\";\n }\n}\n\nexport class HttpError extends NetError {\n constructor(status: number, message: string, cause?: unknown) {\n // 408/429/5xx are generally safe to retry for idempotent ops.\n const retryable = status === 408 || status === 429 || status >= 500;\n super(\"http\", message, { cause, status, retryable });\n this.name = \"HttpError\";\n }\n}\n\nexport class AbortedError extends NetError {\n constructor(cause?: unknown) {\n super(\"aborted\", \"Request was aborted\", { cause, retryable: false });\n this.name = \"AbortedError\";\n }\n}\n\nexport class OfflineError extends NetError {\n constructor() {\n super(\"offline\", \"Browser is offline\", { retryable: true });\n this.name = \"OfflineError\";\n }\n}\n\nexport function isNetError(err: unknown): err is NetError {\n return err instanceof NetError;\n}\n\n/**\n * Folds any thrown value into a descriptive message string — THE one reader\n * for every failure shape this platform actually emits.\n *\n * 2026-09-07 (duplication census rows 9, 10, 21): this body had DRIFTED BEHIND\n * three host copies, which is the campaign's failure mode running in the\n * package's favour-direction. Each host had learned something the package\n * never did, so every non-frontend consumer of `@ai-matrx/data/net` was\n * flattening a server's own sentence into \"An unexpected error occurred\". All\n * three are folded in here, with a named regression test per shape:\n *\n * 1. **FastAPI's `detail`** (matrx-frontend `utils/errors.ts`, learned\n * 2026-08-31 as V2 finding G5). Our server refuses in `detail` — a string,\n * or an object carrying `message` — and every reader checked\n * `message`/`details` only. The server's sentence is the whole point of\n * catching this.\n * 2. **A `fallback` argument** (matrx-frontend `ShortcutForm.tsx`). A caller\n * who knows what it was doing can say \"Failed to save shortcut\" instead of\n * the generic sentence. Optional; the default is unchanged, so every\n * existing single-argument call behaves exactly as before.\n * 3. **Recursion into nested error objects** (aidream `workflow-studio`, two\n * byte-identical copies). The run pipeline nests: `{error: {type, message}}`\n * and `{error: {error: ...}}` and `{exception: {...}}` are all real shapes,\n * and a non-recursive reader answers \"An unexpected error occurred\" while\n * holding the actual reason two levels down. Depth-capped at 4 — a cyclic\n * or absurdly deep object must not hang a render.\n *\n * PostgREST-style errors are plain objects carrying\n * `message`/`details`/`hint`/`code`; a bare `String(err)` on those yields\n * \"[object Object]\", which is why this exists at all.\n */\nexport function extractErrorMessage(\n err: unknown,\n fallback = \"An unexpected error occurred\",\n): string {\n if (!err) return \"Unknown error\";\n if (typeof err === \"string\") return err;\n if (err instanceof Error) return err.message;\n if (typeof err === \"object\") {\n const e = err as Record<string, unknown>;\n const parts: string[] = [];\n if (typeof e.message === \"string\" && e.message) parts.push(e.message);\n // FastAPI's own word for the reason — only when nothing said `message`,\n // so a PostgREST error keeps its exact composed sentence.\n if (parts.length === 0) {\n if (typeof e.detail === \"string\" && e.detail) parts.push(e.detail);\n else if (e.detail && typeof e.detail === \"object\") {\n const d = e.detail as Record<string, unknown>;\n if (typeof d.message === \"string\" && d.message) parts.push(d.message);\n }\n }\n if (typeof e.details === \"string\" && e.details) parts.push(e.details);\n if (typeof e.hint === \"string\" && e.hint) parts.push(`Hint: ${e.hint}`);\n if (typeof e.code === \"string\" && e.code) parts.push(`Code: ${e.code}`);\n if (parts.length > 0) return parts.join(\" · \");\n\n const nested = extractNestedErrorMessage(e, 0);\n if (nested !== null) return nested;\n\n try {\n const s = JSON.stringify(err);\n if (s && s !== \"{}\") return s;\n } catch {\n /* ignore */\n }\n }\n return fallback;\n}\n\n/** Depth-capped walk into `error` / `exception` / `cause`. See above. */\nfunction extractNestedErrorMessage(\n e: Record<string, unknown>,\n depth: number,\n): string | null {\n if (depth > 4) return null;\n for (const key of [\"error\", \"exception\", \"cause\"] as const) {\n const value = e[key];\n if (typeof value === \"string\" && value) return value;\n if (value && typeof value === \"object\") {\n const inner = value as Record<string, unknown>;\n if (typeof inner.message === \"string\" && inner.message) return inner.message;\n if (typeof inner.detail === \"string\" && inner.detail) return inner.detail;\n const deeper = extractNestedErrorMessage(inner, depth + 1);\n if (deeper !== null) return deeper;\n }\n }\n return null;\n}\n\n/**\n * True when a failure is the TRANSPORT dying, not the server answering: the\n * browser is offline, asleep, mid-wifi-handoff, or DNS/TLS failed. It also\n * covers the bounded Envoy/Supabase gateway shape emitted when the upstream\n * database connection dies before response headers. `fetch`\n * rejects with a bare `TypeError: Failed to fetch` in every browser, and\n * supabase-js surfaces that verbatim (message only — no code, no hint).\n *\n * Use it to decide how LOUD a failure is, never whether to handle it. A\n * transport failure carries nothing an engineer can act on, so logging it at\n * error level buries the failures that do — that is how a notes surface filed\n * a system_error every time a laptop slept (2026-08-11). Anything with a\n * Postgres code, an HTTP status, or a server message is NOT this: keep those\n * loud.\n */\nexport function isTransportFailure(err: unknown): boolean {\n if (err instanceof NetworkError || err instanceof OfflineError) return true;\n if (typeof navigator !== \"undefined\" && navigator.onLine === false) return true;\n if (err instanceof TypeError) return true;\n if (err && typeof err === \"object\") {\n const e = err as { code?: unknown; status?: unknown; message?: unknown; name?: unknown };\n // A real PostgREST/Postgres failure always carries a code or status.\n if (e.code || e.status) return false;\n const text = `${typeof e.name === \"string\" ? e.name : \"\"} ${\n typeof e.message === \"string\" ? e.message : \"\"\n }`.toLowerCase();\n return (\n text.includes(\"failed to fetch\") ||\n text.includes(\"networkerror\") ||\n text.includes(\"network request failed\") ||\n text.includes(\"load failed\") || // Safari's wording for the same condition\n text.includes(\"upstream connect error or disconnect/reset before headers\")\n );\n }\n return false;\n}\n\nexport function toNetError(err: unknown): NetError {\n if (isNetError(err)) return err;\n if (err instanceof DOMException && err.name === \"AbortError\") {\n return new AbortedError(err);\n }\n if (err instanceof TypeError) {\n // fetch() throws TypeError on DNS/connection failure in every browser.\n return new NetworkError(err.message || \"Network request failed\", err);\n }\n return new NetError(\n \"unknown\",\n extractErrorMessage(err),\n { cause: err },\n );\n}\n","/**\n * withRetry — exponential backoff retry for idempotent operations.\n *\n * IMPORTANT: only wrap operations that are safe to repeat (GETs, cache\n * lookups, agent-definition fetches). Never wrap user-authored submissions —\n * recovery UX handles those via explicit user-initiated retry.\n *\n * Ported verbatim from matrx-frontend `lib/net/retry.ts`.\n */\n\nimport { isNetError, NetError } from \"./errors\";\n\nexport interface RetryOptions {\n /** Total attempts including the first. Default 3. */\n attempts?: number;\n /** Initial delay ms before the first retry. Default 250. */\n initialDelayMs?: number;\n /** Max delay ms cap between retries. Default 4_000. */\n maxDelayMs?: number;\n /** Multiplier applied after each failure. Default 2. */\n backoffFactor?: number;\n /** Jitter factor 0-1 applied to each delay. Default 0.25. */\n jitter?: number;\n /** Predicate deciding whether a given error should trigger a retry. Default: NetError.retryable. */\n retryOn?: (err: unknown) => boolean;\n /** Caller-provided signal. If aborted, no further retries are attempted. */\n signal?: AbortSignal;\n /** Fires before each retry; useful for logging/telemetry. */\n onRetry?: (attempt: number, err: unknown, delayMs: number) => void;\n}\n\nfunction defaultRetryOn(err: unknown): boolean {\n return isNetError(err) && (err as NetError).retryable;\n}\n\nfunction sleep(ms: number, signal?: AbortSignal): Promise<void> {\n return new Promise((resolve, reject) => {\n const timer = setTimeout(() => {\n resolve();\n if (signal) signal.removeEventListener(\"abort\", onAbort);\n }, ms);\n const onAbort = () => {\n clearTimeout(timer);\n reject(signal?.reason ?? new Error(\"Aborted\"));\n };\n if (signal) {\n if (signal.aborted) {\n clearTimeout(timer);\n reject(signal.reason);\n } else {\n signal.addEventListener(\"abort\", onAbort, { once: true });\n }\n }\n });\n}\n\nexport async function withRetry<T>(\n fn: (attempt: number) => Promise<T>,\n opts: RetryOptions = {},\n): Promise<T> {\n const attempts = Math.max(1, opts.attempts ?? 3);\n const initialDelayMs = opts.initialDelayMs ?? 250;\n const maxDelayMs = opts.maxDelayMs ?? 4_000;\n const factor = opts.backoffFactor ?? 2;\n const jitter = Math.max(0, Math.min(1, opts.jitter ?? 0.25));\n const retryOn = opts.retryOn ?? defaultRetryOn;\n\n let lastErr: unknown;\n for (let attempt = 1; attempt <= attempts; attempt++) {\n if (opts.signal?.aborted) throw opts.signal.reason;\n try {\n return await fn(attempt);\n } catch (err) {\n lastErr = err;\n if (attempt === attempts || !retryOn(err)) throw err;\n\n const base = Math.min(\n maxDelayMs,\n initialDelayMs * Math.pow(factor, attempt - 1),\n );\n const jitterAmount = base * jitter * (Math.random() * 2 - 1);\n const delayMs = Math.max(0, Math.round(base + jitterAmount));\n opts.onRetry?.(attempt, err, delayMs);\n await sleep(delayMs, opts.signal);\n }\n }\n\n // Unreachable — the loop always either returns or throws.\n throw lastErr;\n}\n","/**\n * resilientFetch — `fetch` with connect + total timeouts and composed abort.\n *\n * Every outbound HTTP call should go through this, not raw fetch. The\n * two-stage timeout (connect + total) lets callers allow long-streaming\n * responses without giving up the ability to fail fast when the server is\n * simply unreachable.\n *\n * Ported verbatim from matrx-frontend `lib/net/resilient-fetch.ts`. `fetch`\n * comes from the environment (Node 20+, browsers, React Native/Hermes) —\n * there is deliberately no injected transport here.\n */\n\nimport {\n AbortedError,\n ConnectTimeoutError,\n extractErrorMessage,\n HttpError,\n NetworkError,\n OfflineError,\n TotalTimeoutError,\n} from \"./errors\";\n\nexport interface ResilientFetchOptions {\n /** Max ms from request start → response headers received. Default 15_000. */\n connectTimeoutMs?: number;\n /**\n * Max ms from request start → fetch() promise resolves.\n * For streaming endpoints the response arrives quickly and the stream body\n * is read by the caller, so this bound only guards the handshake itself.\n * `null` disables the ceiling. Default 120_000.\n */\n totalTimeoutMs?: number | null;\n /** Caller-provided signal; composed with our internal timeout signals. */\n signal?: AbortSignal;\n /**\n * If true, throw on non-2xx responses instead of returning them. Default true.\n * Callers that need to read structured error bodies can set this to false.\n */\n throwOnHttpError?: boolean;\n}\n\nexport interface ResilientFetchResult {\n response: Response;\n /**\n * Composed AbortController tied to the fetch. Callers reading the body\n * (e.g. streaming) can call `.abort()` from this controller to cancel\n * in-flight reads. Already aborted on connect/total timeout.\n */\n controller: AbortController;\n}\n\nconst DEFAULTS = {\n connectTimeoutMs: 15_000,\n totalTimeoutMs: 120_000,\n} as const;\n\nfunction linkAbort(target: AbortController, signal: AbortSignal): () => void {\n if (signal.aborted) {\n target.abort(signal.reason);\n return () => {};\n }\n const onAbort = () => target.abort(signal.reason);\n signal.addEventListener(\"abort\", onAbort, { once: true });\n return () => signal.removeEventListener(\"abort\", onAbort);\n}\n\nexport async function resilientFetch(\n url: string,\n init: RequestInit = {},\n opts: ResilientFetchOptions = {},\n): Promise<ResilientFetchResult> {\n const connectTimeoutMs = opts.connectTimeoutMs ?? DEFAULTS.connectTimeoutMs;\n const totalTimeoutMs =\n opts.totalTimeoutMs === undefined\n ? DEFAULTS.totalTimeoutMs\n : opts.totalTimeoutMs;\n const throwOnHttpError = opts.throwOnHttpError ?? true;\n\n // NOTE: we deliberately do NOT hard-block on `navigator.onLine === false`\n // here. That flag is only a HINT — it is unreliable in both directions\n // (VPNs, virtual network adapters, browser network-service hiccups, sleep/\n // wake, and some corporate stacks leave it stuck at `false` while the\n // machine is fully online). Trusting it as a pre-flight gate produced a\n // real production outage: the Agent Builder (this path) threw OfflineError\n // on every submit while the Run path — which uses plain fetch() and never\n // consults the flag — worked fine on the same network. We now let the\n // fetch actually run and only classify the result as \"offline\" if a genuine\n // network failure ALSO corroborates the flag (see the catch below).\n\n const controller = new AbortController();\n const unlinkCaller = opts.signal\n ? linkAbort(controller, opts.signal)\n : () => {};\n\n let connectTimedOut = false;\n let totalTimedOut = false;\n\n const connectTimer = setTimeout(() => {\n connectTimedOut = true;\n controller.abort(\"connect-timeout\");\n }, connectTimeoutMs);\n\n const totalTimer =\n totalTimeoutMs !== null\n ? setTimeout(() => {\n totalTimedOut = true;\n controller.abort(\"total-timeout\");\n }, totalTimeoutMs)\n : null;\n\n try {\n const response = await fetch(url, { ...init, signal: controller.signal });\n clearTimeout(connectTimer);\n // Both timers end with the handshake: `totalTimeoutMs` bounds request\n // start → fetch() resolution (headers), exactly as documented on the\n // option. Body reads are guarded by the caller (stream monitor /\n // heartbeats), not by this timer — clearing it here is what lets a\n // long-streaming body outlive the handshake budget.\n if (totalTimer !== null) clearTimeout(totalTimer);\n\n if (throwOnHttpError && !response.ok) {\n throw new HttpError(\n response.status,\n `HTTP ${response.status} ${response.statusText}`,\n );\n }\n\n return { response, controller };\n } catch (err) {\n clearTimeout(connectTimer);\n if (totalTimer !== null) clearTimeout(totalTimer);\n\n if (connectTimedOut) throw new ConnectTimeoutError(connectTimeoutMs, err);\n if (totalTimedOut)\n throw new TotalTimeoutError(totalTimeoutMs as number, err);\n if (err instanceof DOMException && err.name === \"AbortError\") {\n throw new AbortedError(err);\n }\n if (opts.signal?.aborted) {\n // Caller aborted with a CUSTOM reason: fetch rejects with that reason\n // verbatim (not an AbortError DOMException). Without this check the\n // abort fell through to the generic classifiers and could surface as a\n // retryable NetworkError — an aborted request must never be retried.\n throw new AbortedError(err);\n }\n if (err instanceof TypeError) {\n // fetch() throws TypeError on DNS/connection failure. If the browser\n // ALSO reports offline, the flag is now corroborated by an actual\n // failure — surface the more specific OfflineError. Absent a real\n // failure, `navigator.onLine === false` is never allowed to block.\n if (typeof navigator !== \"undefined\" && navigator.onLine === false) {\n throw new OfflineError();\n }\n throw new NetworkError(err.message || \"Network request failed\", err);\n }\n if (err instanceof HttpError) throw err;\n throw new NetworkError(extractErrorMessage(err), err);\n } finally {\n unlinkCaller();\n }\n}\n","/**\n * Stream liveness monitor.\n *\n * Wraps an async iterable of server events and enforces two guarantees:\n * 1. Heartbeat deadline — fail if no event arrives within `heartbeatTimeoutMs`.\n * 2. Absolute ceiling — fail if total wall-clock time exceeds `maxLifetimeMs`.\n *\n * The wrapper is transparent: events pass through in order, with the same\n * shape. The only observable difference is that a stuck stream throws\n * `HeartbeatTimeoutError` or `TotalTimeoutError` instead of awaiting forever.\n *\n * The wrapped iterable should be driven by NDJSON parsing; the server MUST\n * emit `{kind:\"heartbeat\"}` at least every `heartbeatTimeoutMs / 2` ms for\n * long-running operations (the Matrx stream contract:\n * common-docs/systems/architecture/execution-runtime/STREAM-CONTRACT.md).\n *\n * Ported verbatim from matrx-frontend `lib/net/stream-monitor.ts`, with one\n * defect fixed: cleanup of the underlying iterator after a watchdog timeout\n * is now fire-and-forget (see the note in the catch below).\n */\n\nimport { HeartbeatTimeoutError, TotalTimeoutError } from \"./errors\";\n\nexport interface StreamMonitorOptions {\n /** Max ms between any two events before the stream is considered dead. Default 30_000. */\n heartbeatTimeoutMs?: number;\n /** Max ms from wrap-start before throwing regardless of heartbeats. Default 600_000 (10min). */\n maxLifetimeMs?: number;\n /** Optional callback, fired every time a fresh event resets the deadline. */\n onHeartbeat?: (now: number) => void;\n /** Controller whose `.abort()` should be called on monitor-level timeout, so the underlying fetch is cancelled. */\n abortController?: AbortController;\n}\n\nconst DEFAULTS = {\n heartbeatTimeoutMs: 30_000,\n maxLifetimeMs: 600_000,\n} as const;\n\n/**\n * Wraps an async iterable so that it throws on stalled or overlong streams.\n *\n * Usage:\n * const live = monitorStream(events, { heartbeatTimeoutMs, abortController });\n * for await (const ev of live) { ... }\n */\nexport async function* monitorStream<T>(\n source: AsyncIterable<T>,\n opts: StreamMonitorOptions = {},\n): AsyncGenerator<T, void, undefined> {\n const heartbeatTimeoutMs =\n opts.heartbeatTimeoutMs ?? DEFAULTS.heartbeatTimeoutMs;\n const maxLifetimeMs = opts.maxLifetimeMs ?? DEFAULTS.maxLifetimeMs;\n const abort = opts.abortController;\n\n const startedAt = Date.now();\n const iter = source[Symbol.asyncIterator]() as AsyncIterator<T>;\n\n while (true) {\n const elapsed = Date.now() - startedAt;\n const remainingLifetime = maxLifetimeMs - elapsed;\n if (remainingLifetime <= 0) {\n abort?.abort(\"total-timeout\");\n throw new TotalTimeoutError(maxLifetimeMs);\n }\n\n const deadline = Math.min(heartbeatTimeoutMs, remainingLifetime);\n\n let timer: ReturnType<typeof setTimeout> | null = null;\n let timedOutKind: \"heartbeat\" | \"total\" | null = null;\n const timeoutPromise = new Promise<never>((_, reject) => {\n timer = setTimeout(() => {\n timedOutKind =\n deadline === remainingLifetime ? \"total\" : \"heartbeat\";\n abort?.abort(\n timedOutKind === \"total\" ? \"total-timeout\" : \"heartbeat-timeout\",\n );\n reject(\n timedOutKind === \"total\"\n ? new TotalTimeoutError(maxLifetimeMs)\n : new HeartbeatTimeoutError(heartbeatTimeoutMs),\n );\n }, deadline);\n });\n\n let result: IteratorResult<T>;\n try {\n result = await Promise.race([iter.next(), timeoutPromise]);\n } catch (err) {\n if (timer !== null) clearTimeout(timer);\n // Best-effort: let the underlying iterator clean up — WITHOUT awaiting\n // it. The original awaited `iter.return()`, but on an async generator\n // `return()` queues behind the still-pending `next()`; if the stream is\n // stuck and no abortController was provided to settle that read, the\n // await never resolves and the monitor hangs forever — the exact\n // failure mode this module exists to prevent. Fire-and-forget keeps\n // the timeout guarantee while still requesting cleanup.\n try {\n const cleanup = iter.return?.(undefined as never);\n if (cleanup) {\n void Promise.resolve(cleanup).catch(() => {\n /* ignore */\n });\n }\n } catch {\n /* ignore */\n }\n throw err;\n }\n\n if (timer !== null) clearTimeout(timer);\n if (result.done) return;\n\n opts.onHeartbeat?.(Date.now());\n yield result.value;\n }\n}\n"],"mappings":"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","names":["DEFAULTS"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ai-matrx/data",
|
|
3
|
-
"version": "0.18.
|
|
3
|
+
"version": "0.18.37",
|
|
4
4
|
"description": "The opinionated AI Matrx data layer: the /db tier's hard-won Supabase primitives — optimistic concurrency, complete-list reads, JSONB merge, session-retry, the domain-wide auth cookie, realtime channel hygiene — the /net resilience trio, and the /files lane: the Matrx file-communication client (durable-ref resolution, the mx_files_session bootstrap, authenticated blob fetch, uploads, the public-link door).",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.cjs",
|