@morsehq-dev/sdk 0.5.0-rc.2 → 0.5.0-rc.3
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/dist/anthropic/index.cjs +11 -11
- package/dist/anthropic/index.js +4 -4
- package/dist/anthropic-agent-sdk/index.cjs +37 -37
- package/dist/anthropic-agent-sdk/index.js +6 -6
- package/dist/browser/anthropic/index.cjs +11 -11
- package/dist/browser/anthropic/index.js +4 -4
- package/dist/browser/anthropic-agent-sdk/index.cjs +37 -37
- package/dist/browser/anthropic-agent-sdk/index.js +6 -6
- package/dist/browser/{chunk-SOJYLXCR.cjs → chunk-KFWCOUL3.cjs} +5 -5
- package/dist/browser/{chunk-SOJYLXCR.cjs.map → chunk-KFWCOUL3.cjs.map} +1 -1
- package/dist/browser/{chunk-L6FWDEGJ.js → chunk-KGSLJLWW.js} +4 -4
- package/dist/browser/{chunk-L6FWDEGJ.js.map → chunk-KGSLJLWW.js.map} +1 -1
- package/dist/{chunk-ZWOSPXS4.js → browser/chunk-LGG5PL5U.js} +3 -3
- package/dist/browser/{chunk-AM6LMQCT.js.map → chunk-LGG5PL5U.js.map} +1 -1
- package/dist/browser/{chunk-NRYB5GJT.js → chunk-MI4OUWUZ.js} +3 -3
- package/dist/browser/{chunk-NRYB5GJT.js.map → chunk-MI4OUWUZ.js.map} +1 -1
- package/dist/browser/{chunk-FDE32B3R.js → chunk-MOBYR3AP.js} +4 -4
- package/dist/browser/{chunk-FDE32B3R.js.map → chunk-MOBYR3AP.js.map} +1 -1
- package/dist/browser/{chunk-3MTJGZGX.js → chunk-N4Q2WMOE.js} +5 -5
- package/dist/browser/{chunk-3MTJGZGX.js.map → chunk-N4Q2WMOE.js.map} +1 -1
- package/dist/browser/{chunk-YMEU6XQQ.cjs → chunk-P7XWSMFX.cjs} +6 -6
- package/dist/browser/{chunk-YMEU6XQQ.cjs.map → chunk-P7XWSMFX.cjs.map} +1 -1
- package/dist/browser/{chunk-A5EYWAOT.cjs → chunk-PM5D6VXF.cjs} +12 -6
- package/dist/browser/chunk-PM5D6VXF.cjs.map +1 -0
- package/dist/browser/{chunk-T4NHSVXH.cjs → chunk-QCI2ZDQS.cjs} +12 -12
- package/dist/browser/{chunk-T4NHSVXH.cjs.map → chunk-QCI2ZDQS.cjs.map} +1 -1
- package/dist/browser/{chunk-YR2FCEWM.cjs → chunk-VSG4EWNL.cjs} +18 -18
- package/dist/browser/{chunk-YR2FCEWM.cjs.map → chunk-VSG4EWNL.cjs.map} +1 -1
- package/dist/browser/{chunk-NH54DAJP.js → chunk-WUQXNRD3.js} +3 -3
- package/dist/browser/{chunk-NH54DAJP.js.map → chunk-WUQXNRD3.js.map} +1 -1
- package/dist/{chunk-Z2IYSTRT.cjs → browser/chunk-XLQSSJUZ.cjs} +15 -15
- package/dist/browser/{chunk-63ZI6PGP.cjs.map → chunk-XLQSSJUZ.cjs.map} +1 -1
- package/dist/browser/{chunk-OOGAYEJF.js → chunk-Y3BOPSM3.js} +12 -7
- package/dist/browser/chunk-Y3BOPSM3.js.map +1 -0
- package/dist/{chunk-Y2QHMV6H.cjs → browser/chunk-YSJVJ3Z3.cjs} +7 -7
- package/dist/browser/{chunk-N3PXJCOE.cjs.map → chunk-YSJVJ3Z3.cjs.map} +1 -1
- package/dist/browser/index.cjs +90 -89
- package/dist/browser/index.cjs.map +1 -1
- package/dist/browser/index.js +9 -8
- package/dist/browser/index.js.map +1 -1
- package/dist/browser/integrations/pino.cjs +4 -4
- package/dist/browser/integrations/pino.js +3 -3
- package/dist/browser/langchain/index.cjs +17 -17
- package/dist/browser/langchain/index.js +2 -2
- package/dist/browser/langgraph/index.cjs +27 -27
- package/dist/browser/langgraph/index.js +5 -5
- package/dist/browser/openai/index.cjs +11 -11
- package/dist/browser/openai/index.js +2 -2
- package/dist/browser/openai-agents/index.cjs +38 -36
- package/dist/browser/openai-agents/index.cjs.map +1 -1
- package/dist/browser/openai-agents/index.js +8 -6
- package/dist/browser/openai-agents/index.js.map +1 -1
- package/dist/browser/vercel-ai/index.cjs +14 -14
- package/dist/browser/vercel-ai/index.js +3 -3
- package/dist/{browser/chunk-N3PXJCOE.cjs → chunk-3XQOZXJM.cjs} +7 -7
- package/dist/{chunk-Y2QHMV6H.cjs.map → chunk-3XQOZXJM.cjs.map} +1 -1
- package/dist/{chunk-FCAPLB7A.js → chunk-7PGR4NJG.js} +4 -4
- package/dist/{chunk-FCAPLB7A.js.map → chunk-7PGR4NJG.js.map} +1 -1
- package/dist/{browser/chunk-63ZI6PGP.cjs → chunk-DPGUBZVO.cjs} +15 -15
- package/dist/{chunk-Z2IYSTRT.cjs.map → chunk-DPGUBZVO.cjs.map} +1 -1
- package/dist/{chunk-XCOZIFHC.cjs → chunk-E3G3IE6Y.cjs} +12 -6
- package/dist/chunk-E3G3IE6Y.cjs.map +1 -0
- package/dist/{chunk-SHK2XEPB.js → chunk-HCEKAVDR.js} +4 -4
- package/dist/{chunk-SHK2XEPB.js.map → chunk-HCEKAVDR.js.map} +1 -1
- package/dist/{chunk-VHF4GWJ4.cjs → chunk-NGBJJGOC.cjs} +5 -5
- package/dist/{chunk-VHF4GWJ4.cjs.map → chunk-NGBJJGOC.cjs.map} +1 -1
- package/dist/{chunk-ZIER4DGK.cjs → chunk-RK3JPX27.cjs} +12 -12
- package/dist/{chunk-ZIER4DGK.cjs.map → chunk-RK3JPX27.cjs.map} +1 -1
- package/dist/{chunk-XJUH6PR5.js → chunk-T2NESDMT.js} +3 -3
- package/dist/{chunk-XJUH6PR5.js.map → chunk-T2NESDMT.js.map} +1 -1
- package/dist/{chunk-6DZNK4VX.cjs → chunk-TGHDV5MC.cjs} +6 -6
- package/dist/{chunk-6DZNK4VX.cjs.map → chunk-TGHDV5MC.cjs.map} +1 -1
- package/dist/{chunk-S4WUABAU.js → chunk-UAJO6JM7.js} +3 -3
- package/dist/{chunk-S4WUABAU.js.map → chunk-UAJO6JM7.js.map} +1 -1
- package/dist/{chunk-YJYF4NSA.js → chunk-XHOLQGN6.js} +5 -5
- package/dist/{chunk-YJYF4NSA.js.map → chunk-XHOLQGN6.js.map} +1 -1
- package/dist/{chunk-3IGQWLWE.js → chunk-XZRJXJFA.js} +12 -7
- package/dist/chunk-XZRJXJFA.js.map +1 -0
- package/dist/{chunk-SNGYSP7Z.cjs → chunk-YQ6ZA7OE.cjs} +18 -18
- package/dist/{chunk-SNGYSP7Z.cjs.map → chunk-YQ6ZA7OE.cjs.map} +1 -1
- package/dist/{browser/chunk-AM6LMQCT.js → chunk-ZFE75G7S.js} +3 -3
- package/dist/{chunk-ZWOSPXS4.js.map → chunk-ZFE75G7S.js.map} +1 -1
- package/dist/index.cjs +97 -96
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +10 -9
- package/dist/index.js.map +1 -1
- package/dist/integrations/pino.cjs +4 -4
- package/dist/integrations/pino.js +3 -3
- package/dist/langchain/index.cjs +17 -17
- package/dist/langchain/index.js +2 -2
- package/dist/langgraph/index.cjs +27 -27
- package/dist/langgraph/index.js +5 -5
- package/dist/openai/index.cjs +11 -11
- package/dist/openai/index.js +2 -2
- package/dist/openai-agents/index.cjs +38 -36
- package/dist/openai-agents/index.cjs.map +1 -1
- package/dist/openai-agents/index.d.cts +4 -0
- package/dist/openai-agents/index.d.ts +4 -0
- package/dist/openai-agents/index.js +8 -6
- package/dist/openai-agents/index.js.map +1 -1
- package/dist/vercel-ai/index.cjs +14 -14
- package/dist/vercel-ai/index.js +3 -3
- package/package.json +1 -1
- package/dist/browser/chunk-A5EYWAOT.cjs.map +0 -1
- package/dist/browser/chunk-OOGAYEJF.js.map +0 -1
- package/dist/chunk-3IGQWLWE.js.map +0 -1
- package/dist/chunk-XCOZIFHC.cjs.map +0 -1
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/_internal/auto-detect.ts","../src/index.ts","../src/_internal/db-capture.ts","../src/_internal/db-capture-sqlite.ts","../src/_internal/transport.ts"],"names":["_resetForTesting","span","otelContext","traceApi","logger","run","setContext","startSpan","spanAsync","quotaState"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * Auto-detect installed AI SDKs and install the matching adapter.\n *\n * Node port of the Python SDK's `_internal/auto_detect.py` (auto-instrumentation\n * zero-config instrumentation): when the Morse SDK initializes, scan for\n * already-loaded target packages and install each detected adapter. For\n * packages not yet loaded, register a hook so the adapter installs as soon\n * as the customer's code requires it.\n *\n * Customer flow becomes:\n *\n * npm install @morsehq-dev/sdk\n * export MORSE_API_KEY=mhq_...\n * // ... existing @anthropic-ai/sdk / ai code is now traced ...\n *\n * No `morse.wrapAnthropic()` / `morse.instrumentAnthropic()` call required.\n *\n * ---------------------------------------------------------------------\n * Node vs. Python — why this module's SCOPE is narrower than auto_detect.py\n * ---------------------------------------------------------------------\n *\n * Python's `sys.modules` is a single global dict of every imported module,\n * and `importlib.abc.MetaPathFinder` gives a clean, built-in hook that\n * fires for BOTH `import x` and `from x import y`, regardless of package\n * shape. Node has no equivalent: there is no single \"loaded modules\"\n * registry that covers both CJS and ESM, and Node's ESM loader hook\n * (`node:module`'s `register()`) runs the customization hook in a\n * dedicated loader thread with structured-clone message-passing back to\n * the main thread — it cannot synchronously call back into an adapter's\n * `install()` in the main realm, and building an async message-passing\n * bridge just for this is disproportionate to what a v1 zero-config port\n * needs. So this port targets Node's CommonJS `require` machinery only:\n *\n * - \"Already loaded\" scan: `require.resolve(name)` (no side effect,\n * mirrors `importlib.util.find_spec`) + membership in `require.cache`\n * (mirrors `name in sys.modules`).\n * - \"Not yet loaded\" hook: patch `Module.prototype.require` so any\n * `require(name)` call — including the one Node performs internally\n * when a CJS-authored package is `import`-ed from an ESM file, which\n * is how `@anthropic-ai/sdk` and `ai` are typically consumed — fires\n * the adapter's install() once the module body has finished\n * evaluating. Pure-ESM packages loaded via the native ESM loader\n * (no CJS `require` in the chain) are NOT observed by this hook; for\n * those, `wrapX()` / `instrumentX()` remain the documented manual path.\n *\n * A second, orthogonal scope narrowing: not every Morse TS adapter has a\n * module-level monkey-patch entry point the way Python's adapters do.\n * `instrumentAnthropic()` patches `Messages.prototype.create` — a plain\n * mutable property on a class, present regardless of module system — so\n * auto-detect can install it exactly like Python's `install()` functions.\n * `ai` (Vercel AI SDK) CANNOT be silently patched this way: its exports are\n * plain functions (no prototype), and ships pure-ESM, so Node exposes\n * `streamText`/`generateText`/`generateObject` as non-configurable\n * getter-only properties even through the CJS interop `require()` path —\n * reassigning them throws. Confirmed via a bare Node repro during MHQ-482\n * OSS dogfooding (`bizops/dogfood/ai-sdk-preview-rag.md`); see\n * `../vercel-ai/index.ts`'s module doc for the full story. `ai` is a\n * `DETECT_ONLY_TARGETS` entry pointing at `createTracedVercelAI()`. The\n * `openai-agents`, `langgraph`, and `anthropic-agent-sdk` TS adapters are\n * per-instance only (`wrapRunnerWithFullInstrumentation(runner)`, `new\n * MorseCallbackHandler()`, `wrapClaudeAgentSDKWithFullInstrumentation(\n * client)`) — there is no global hook point to patch without the\n * customer's own `Runner` / `ClaudeSDKClient` instance in hand. Auto-detect\n * still DETECTS these (a one-time informational log pointing at the manual\n * wrap call) but cannot silently instrument them. See `DETECT_ONLY_TARGETS`\n * below.\n *\n * Idempotency: each `FULL_INSTALL_TARGETS[...].install()` call delegates to\n * an adapter function that is itself idempotent (checks a sentinel on the\n * target module). Calling `installAdapters()` repeatedly is safe.\n *\n * Opt-out: `MORSE_DISABLE_AUTO_DETECT=1` skips this step entirely.\n * Customers can still call the adapter `wrapX()` / `instrumentX()`\n * functions directly.\n *\n * Implementation note on the `node:module` import: unlike the optional\n * peer-dependency imports elsewhere in this SDK (e.g. `@anthropic-ai/sdk`\n * in `anthropic/index.ts`, dynamic-imported via a `Function`-eval trick so\n * bundlers never try to statically resolve a package the customer may not\n * have installed), `node:module` is a Node CORE builtin — always present in\n * any Node runtime, nothing to dodge at bundle time. It's imported\n * statically here and every call site is still runtime-guarded by a\n * `typeof process !== \"undefined\" && process.versions?.node` check, so\n * this module is a safe no-op outside Node (browser bundles, edge\n * runtimes). A dynamic-`import()`-via-`Function`-eval was tried first but\n * rejected: it throws `ERR_VM_DYNAMIC_IMPORT_CALLBACK_MISSING` under\n * Vitest's VM-sandboxed test execution, making the require/hook mechanics\n * untestable — a static import has no such problem.\n */\n\nimport { createRequire, Module } from \"node:module\";\n\nimport { instrumentAnthropic } from \"../anthropic\";\nimport { isAutoDetectDisabled } from \"./env\";\n\n/* ------------------------------------------------------------------------ */\n/* Target catalogues */\n/* ------------------------------------------------------------------------ */\n\ninterface FullInstallTarget {\n /** Best-effort installer given the resolved module namespace object. */\n install: (mod: unknown) => Promise<unknown>;\n}\n\n/**\n * Packages with a genuine module-level install entry point — auto-detect\n * can silently instrument these without any customer-supplied instance.\n */\nconst FULL_INSTALL_TARGETS: Record<string, FullInstallTarget> = {\n \"@anthropic-ai/sdk\": {\n install: (mod) => instrumentAnthropic({ anthropicModule: mod }),\n },\n};\n\n/**\n * Packages whose Morse adapter only works against a customer-supplied\n * instance (Runner, ClaudeSDKClient, a LangGraph callback handler). These\n * are detected (best-effort, package-presence only) so we can point the\n * customer at the right manual call — see the module doc comment above for\n * why silent auto-install isn't possible for these yet.\n */\nconst DETECT_ONLY_TARGETS: Record<string, string> = {\n \"@openai/agents\":\n \"wrapRunnerWithFullInstrumentation(runner) from '@morsehq-dev/sdk/openai-agents'\",\n \"@langchain/langgraph\":\n \"new MorseCallbackHandler() from '@morsehq-dev/sdk/langgraph', passed via { callbacks: [...] }\",\n \"@anthropic-ai/claude-agent-sdk\":\n \"wrapClaudeAgentSDKWithFullInstrumentation(client) from '@morsehq-dev/sdk/anthropic-agent-sdk'\",\n // MHQ-758: `ai`'s exports can't be patched in place (frozen ESM getters,\n // no prototype to patch) — createTracedVercelAI() returns replacement\n // functions instead. See `../vercel-ai/index.ts`'s module doc.\n ai: \"createTracedVercelAI() from '@morsehq-dev/sdk/vercel-ai' — use its returned streamText/generateText/generateObject in place of ai's own\",\n};\n\n/* ------------------------------------------------------------------------ */\n/* Node `require` access */\n/* ------------------------------------------------------------------------ */\n\ninterface NodeRequireLike {\n (id: string): unknown;\n resolve: (id: string) => string;\n cache: Record<string, unknown>;\n}\n\n/** True when running under real Node (not a browser bundle / edge runtime). */\nfunction isNodeRuntime(): boolean {\n return typeof process !== \"undefined\" && !!process.versions?.node;\n}\n\nfunction getNodeRequire(): NodeRequireLike | null {\n if (!isNodeRuntime()) return null;\n try {\n // `import.meta.url` is standard ESM syntax (not a Node built-in) —\n // safe for bundlers to see statically. When this file is compiled to\n // CJS (tsup's CJS output target), esbuild shims it automatically.\n return createRequire(import.meta.url) as unknown as NodeRequireLike;\n } catch {\n return null;\n }\n}\n\n/* ------------------------------------------------------------------------ */\n/* Module-level state */\n/* ------------------------------------------------------------------------ */\n\nconst firedFullInstall = new Set<string>();\nconst loggedDetectOnly = new Set<string>();\nconst lazyTargets = new Set<string>();\nlet hookInstalled = false;\ntype RequireFn = (this: unknown, id: string) => unknown;\nlet originalRequire: RequireFn | null = null;\n\nfunction logger(message: string): void {\n console.info(message);\n}\n\n/* ------------------------------------------------------------------------ */\n/* Install one full-install target, guarding against a double-fire */\n/* ------------------------------------------------------------------------ */\n\nasync function installFullTarget(name: string, mod: unknown): Promise<void> {\n if (firedFullInstall.has(name)) return;\n firedFullInstall.add(name);\n const target = FULL_INSTALL_TARGETS[name];\n if (!target) return;\n try {\n await target.install(mod);\n } catch {\n // Never let a single adapter's install failure break the others —\n // the adapter's own install() is already absorbErrors-wrapped, this\n // is a defensive extra layer mirroring Python's `_install_one`.\n }\n}\n\nfunction logDetectOnlyIfPresent(nodeRequire: NodeRequireLike, name: string): void {\n if (loggedDetectOnly.has(name)) return;\n try {\n nodeRequire.resolve(name);\n } catch {\n return; // not installed — nothing to log\n }\n loggedDetectOnly.add(name);\n logger(\n `morse: detected \"${name}\" — no zero-config path for this SDK yet. ` +\n `Call ${DETECT_ONLY_TARGETS[name]} to instrument it.`,\n );\n}\n\n/* ------------------------------------------------------------------------ */\n/* Lazy hook — fires installFullTarget() when a target is `require()`d */\n/* for the first time after installAdapters() ran. */\n/* ------------------------------------------------------------------------ */\n\nfunction installLazyHook(): void {\n if (hookInstalled) return;\n originalRequire = Module.prototype.require as RequireFn;\n const original = originalRequire;\n Module.prototype.require = function patchedRequire(this: unknown, id: string): unknown {\n const result = original.call(this, id);\n if (lazyTargets.has(id) && !firedFullInstall.has(id)) {\n // Fire-and-forget — telemetry install must never block or throw back\n // at the customer's require() call.\n void installFullTarget(id, result);\n }\n return result;\n } as typeof Module.prototype.require;\n hookInstalled = true;\n}\n\nfunction uninstallLazyHook(): void {\n if (hookInstalled && originalRequire) {\n Module.prototype.require = originalRequire as typeof Module.prototype.require;\n }\n hookInstalled = false;\n originalRequire = null;\n}\n\n/* ------------------------------------------------------------------------ */\n/* Public entry point */\n/* ------------------------------------------------------------------------ */\n\n/**\n * Scan for already-loaded target packages and install adapters for any\n * that are present. For packages not yet loaded, register a lazy hook so\n * they get instrumented the moment the customer's code requires them.\n *\n * Idempotent and safe to call repeatedly — every `morse.init()` (and the\n * env-based lazy auto-init path) goes through here.\n *\n * Honors `MORSE_DISABLE_AUTO_DETECT=1` and returns immediately. No-ops\n * outside Node (e.g. a browser bundle) since there is no `require` to hook.\n */\nexport async function installAdapters(): Promise<void> {\n if (isAutoDetectDisabled()) return;\n\n const nodeRequire = getNodeRequire();\n if (!nodeRequire) return;\n\n const installPromises: Array<Promise<void>> = [];\n\n for (const name of Object.keys(FULL_INSTALL_TARGETS)) {\n if (firedFullInstall.has(name)) continue;\n let resolvedPath: string | undefined;\n try {\n resolvedPath = nodeRequire.resolve(name);\n } catch {\n continue; // package not installed at all — nothing to detect or hook\n }\n if (resolvedPath in nodeRequire.cache) {\n // Already loaded — install now.\n try {\n const mod = nodeRequire(name);\n installPromises.push(installFullTarget(name, mod));\n } catch {\n // Loading a cached module should never throw, but stay defensive.\n }\n } else {\n // Not loaded yet — register for the lazy require() hook.\n lazyTargets.add(name);\n }\n }\n\n if (lazyTargets.size > 0) {\n installLazyHook();\n }\n\n for (const name of Object.keys(DETECT_ONLY_TARGETS)) {\n logDetectOnlyIfPresent(nodeRequire, name);\n }\n\n await Promise.all(installPromises);\n}\n\n/**\n * Reset all auto-detect state for tests: unpatches `Module.prototype\n * .require`, clears the fired/logged/lazy sets. Not part of the public API.\n * @internal\n */\nexport function _resetForTesting(): void {\n uninstallLazyHook();\n firedFullInstall.clear();\n loggedDetectOnly.clear();\n lazyTargets.clear();\n}\n\n/** @internal test-only accessors */\nexport const _internalsForTesting = {\n FULL_INSTALL_TARGETS,\n DETECT_ONLY_TARGETS,\n get lazyTargets(): ReadonlySet<string> {\n return lazyTargets;\n },\n get hookInstalled(): boolean {\n return hookInstalled;\n },\n};\n","/**\n * `@morsehq-dev/sdk` — TypeScript SDK for Morse observability.\n *\n * V2 module-level singleton API:\n *\n * ```ts\n * import * as morse from \"@morsehq-dev/sdk\";\n *\n * // Three-step zero-setup integration:\n * // 1. Generate an API key in the Morse dashboard.\n * // 2. npm install @morsehq-dev/sdk\n * // 3. Set MORSE_API_KEY in your environment.\n *\n * morse.track({ agentId: \"lead-qualifier\", runData: { success: true } });\n *\n * // Or call init() explicitly to override env-var resolution:\n * morse.init({\n * apiKey: \"mhq_xxx\", // pragma: allowlist secret — placeholder, not a key\n * endpoint: \"https://api.morsehq.dev/api/v1/traces/batch\",\n * flushIntervalSeconds: 2,\n * });\n * ```\n *\n * Non-invasive guarantee: every public function is wrapped with\n * `absorbErrors`. Telemetry never throws back at the caller; internal\n * errors are reported out-of-band to Morse's own diagnostics endpoint.\n *\n * The internal `BatchTransport` and `TraceState` types back the singleton\n * but are NOT part of the public API. Customers should never reach into\n * the `_internal` directory.\n */\n\nimport {\n installAdapters as _installAdapters,\n _resetForTesting as _resetAutoDetectForTesting,\n} from \"./_internal/auto-detect\";\nimport { absorbErrorsAsync, absorbErrorsSync } from \"./_internal/errors\";\nimport {\n DEFAULT_ENDPOINT,\n getApiKey as readApiKeyFromEnv,\n getEndpoint as readEndpointFromEnv,\n getFlushIntervalSeconds,\n getInternalSource as readInternalSourceFromEnv,\n getMaxBatchSize,\n getMaxFieldBytes,\n getMaxQueueSize,\n getSampleRate,\n isDisabled as readIsDisabled,\n isValidInternalSource,\n} from \"./_internal/env\";\nimport { maybeEnableDbCaptureFromEnv } from \"./_internal/db-capture\";\nimport { getEngine as getOtelEngine } from \"./_internal/otel-provider\";\nimport {\n buildRedactionConfig,\n type RedactionConfig,\n type RedactionOptions,\n redactValue,\n} from \"./_internal/redaction\";\nimport {\n BatchTransport,\n SDK_VERSION,\n type TelemetryEvent,\n getQuotaState as _getQuotaState,\n _resetQuotaStateForTesting,\n type QuotaState,\n} from \"./_internal/transport\";\nimport {\n getActiveTraceState as _getActiveTraceState,\n getLastTrace as _getLastTrace,\n runAsync as _runAsync,\n runSync as _runSync,\n sendTrace as _sendTrace,\n setContext as _setContext,\n setRedactionConfig,\n setSource as _setSource,\n setTransport,\n startSpan as _startSpan,\n type RunHandle,\n type RunOptions,\n type SpanHandle,\n type SpanOptions,\n spanAsync as _spanAsync,\n spanSync as _spanSync,\n _resetForTesting as _resetTracingForTesting,\n} from \"./_internal/tracing\";\nimport { report, _resetForTesting as _resetDiagnosticsForTesting } from \"./_internal/diagnostics\";\nimport { _setEnsureInitialized as _setLogEnsureInitialized } from \"./log\";\nimport {\n buildTraceEntry,\n generateSpanId,\n generateTraceId,\n nowIso,\n SpanType,\n type SpanData,\n type TraceFields,\n} from \"./_internal/spans\";\n\nexport type { SpanData, SpanType, SpanStatus, ContextSegment } from \"./_internal/spans\";\nexport type { RunHandle, RunOptions, SpanHandle, SpanOptions };\nexport type { QuotaState };\nexport type { RedactionOptions, RedactionConfig } from \"./_internal/redaction\";\nexport {\n extractTraceparent,\n formatTraceparent,\n injectTraceparent,\n injectIntoRequestInit,\n W3C_TRACEPARENT_HEADER,\n} from \"./propagation\";\nexport {\n extractAnthropicSegments,\n instrumentAnthropic,\n isAnthropicWrapped,\n uninstallAnthropic,\n wrapAnthropic,\n MAX_SEGMENT_CONTENT_BYTES,\n} from \"./anthropic\";\nexport type {\n AnthropicClientLike,\n AnthropicContentBlockParam,\n AnthropicMessageCreateParams,\n AnthropicMessageParam,\n AnthropicMessageResponse,\n AnthropicTextBlockParam,\n AnthropicToolParam,\n AnthropicToolResultBlockParam,\n AnthropicToolUseBlockParam,\n AnthropicUsage,\n InstrumentAnthropicOptions,\n} from \"./anthropic\";\nexport { log } from \"./log\";\nexport type { LogOptions, LogSeverity } from \"./log\";\n\nexport const version = SDK_VERSION;\n\n/* ------------------------------------------------------------------------ */\n/* Public types */\n/* ------------------------------------------------------------------------ */\n\n/** Options accepted by `init()`. Mirrors Python's `init(...)` kwargs. */\nexport interface InitOptions {\n /** API key (starts with \"mhq_\"). Required if no `MORSE_API_KEY` env var. */\n apiKey?: string;\n /** Full ingestion URL. Defaults to the production Railway endpoint. */\n endpoint?: string;\n /** Seconds between batch flushes. Default: 2. */\n flushIntervalSeconds?: number;\n /**\n * Client-side PII redaction. Default-on with the canonical eight-pattern\n * catalogue. Set `enabled: false` to opt out (the server-side mandatory\n * floor still applies). Mandatory patterns (`api_key_prefixed`, `jwt`,\n * `credit_card`, `ssn_us`) cannot be added to `disabledPatterns` —\n * `init()` throws on that.\n */\n redaction?: RedactionOptions;\n /**\n * INTERNAL USE ONLY — resource-level source label for Morse's own\n * dogfood emitters. Mirrors the Python SDK's `init(source=...)` kwarg\n * (PR #90). Accepted values: `\"copilot\" | \"investigator\" | \"refagent\"\n * | \"ui-bot\"`. Any other value (including misspellings) is silently\n * dropped — falls back to the `MORSE_INTERNAL_SOURCE` env var.\n * Customers should not set this.\n */\n source?: string;\n}\n\n/** Single agent-run payload accepted by `track()`. */\nexport interface TrackOptions {\n /** User-defined agent name (e.g., \"lead-qualifier\"). */\n agentId: string;\n /** Run-data dict. Shape mirrors backend Run model. */\n runData: Record<string, unknown>;\n}\n\n/** High-level outcome shape accepted by `record()` (V1 ergonomic API). */\nexport interface RunRecord {\n agent: string;\n success?: boolean;\n outcome?: string;\n cost?: number;\n model?: string;\n inputTokens?: number;\n outputTokens?: number;\n totalTokens?: number;\n durationMs?: number;\n errorMessage?: string;\n metadata?: Record<string, unknown>;\n status?: \"completed\" | \"failed\" | \"timed_out\";\n}\n\n/* ------------------------------------------------------------------------ */\n/* Module-level singleton state */\n/* ------------------------------------------------------------------------ */\n\ninterface SingletonState {\n apiKey: string;\n endpoint: string;\n transport: BatchTransport;\n redaction: RedactionConfig;\n}\n\nlet singleton: SingletonState | null = null;\nlet transportFactory: (opts: {\n apiKey: string;\n endpoint: string;\n flushIntervalSeconds: number;\n}) => BatchTransport = (opts) => new BatchTransport(opts);\n\nlet noApiKeyWarningEmitted = false;\nlet lastLoggedEndpoint: string | null = null;\n\nfunction logger(level: \"info\" | \"warn\", message: string): void {\n const out = level === \"warn\" ? console.warn : console.info;\n out.call(console, message);\n}\n\nfunction logDestinationOnce(endpoint: string): void {\n if (endpoint === lastLoggedEndpoint) return;\n lastLoggedEndpoint = endpoint;\n logger(\n \"info\",\n `morse: Morse SDK initialized — sending to ${endpoint} (sdk version ${SDK_VERSION})`,\n );\n}\n\nfunction resolveEndpoint(explicit?: string): string {\n if (explicit && explicit.length > 0) return explicit;\n const fromEnv = readEndpointFromEnv();\n if (fromEnv) return fromEnv;\n return DEFAULT_ENDPOINT;\n}\n\nconst OTLP_TRACES_PATH = \"/api/v1/otlp/v1/traces\";\n\n/**\n * Derive the OTLP ingest URL from the legacy JSON traces batch URL. Keeps\n * host/scheme; replaces the path — mirrors the Python SDK's\n * `client.py::_derive_otlp_endpoint` and this file's own\n * `transport.ts::deriveLogsEndpoint`.\n */\nfunction deriveOtlpEndpoint(tracesEndpoint: string): string {\n try {\n const u = new URL(tracesEndpoint);\n u.pathname = OTLP_TRACES_PATH;\n u.search = \"\";\n u.hash = \"\";\n return u.toString();\n } catch {\n return tracesEndpoint.replace(/\\/api\\/v1\\/.*$/, OTLP_TRACES_PATH);\n }\n}\n\nfunction buildSingleton(opts: InitOptions, redaction: RedactionConfig): SingletonState | null {\n if (readIsDisabled()) {\n return null;\n }\n const apiKey = opts.apiKey ?? readApiKeyFromEnv();\n if (!apiKey) {\n if (!noApiKeyWarningEmitted) {\n logger(\n \"warn\",\n \"morse: not initialized — set MORSE_API_KEY or call morse.init({ apiKey }) (this warning prints once per process; SDK calls are silent no-ops)\",\n );\n noApiKeyWarningEmitted = true;\n }\n return null;\n }\n const endpoint = resolveEndpoint(opts.endpoint);\n const flushIntervalSeconds = opts.flushIntervalSeconds ?? getFlushIntervalSeconds();\n const transport = transportFactory({ apiKey, endpoint, flushIntervalSeconds });\n setTransport(transport);\n setRedactionConfig(redaction);\n // Resolve the internal source label: explicit kwarg wins, then env.\n // Invalid values are silently dropped so a typo never tags customer\n // data as dogfood.\n const explicitSource = isValidInternalSource(opts.source) ? opts.source! : undefined;\n const resolvedSource = explicitSource ?? readInternalSourceFromEnv() ?? null;\n _setSource(resolvedSource);\n logDestinationOnce(endpoint);\n\n // MHQ-482: run()/span()/runTraced()'s real emission pipeline — real OTel\n // spans over OTLP protobuf+gzip. Configured unconditionally (even under\n // MORSE_LEGACY_TRANSPORT=1) so the engine is ready if the flag flips at\n // runtime; the flag only affects which pipeline `tracing.ts::sendTrace()`\n // feeds. Mirrors the Python SDK's `_Client.__init__`.\n try {\n getOtelEngine().configure({\n endpoint: deriveOtlpEndpoint(endpoint),\n apiKey,\n sampleRate: getSampleRate(),\n scheduleDelayMillis: flushIntervalSeconds * 1000,\n maxQueueSize: getMaxQueueSize(),\n maxExportBatchSize: getMaxBatchSize(),\n maxFieldBytes: getMaxFieldBytes(),\n // 10s (not the exporter's un-overridden 30s ceiling): a genuine\n // network blip still gets several retries with backoff; a fully dead\n // endpoint fails within a bounded, shutdown-friendly window instead\n // of the library's full 30s ceiling. Mirrors the Python SDK.\n timeoutMillis: 10_000,\n redactionConfig: redaction,\n });\n } catch (err) {\n report(err, { fingerprint: \"morse.otel_provider.configure\" });\n }\n\n // MHQ-482: zero-config adapter auto-detect (mirrors Python's\n // `auto_detect.install_adapters()` call in `_ensure_initialized` /\n // `_init_impl`). Fire-and-forget — telemetry setup must never block or\n // throw back into the customer's init() / first SDK call. Runs AFTER the\n // OTel engine above is configured so any span an auto-installed adapter\n // emits immediately has a working pipeline to flow through.\n void _installAdapters().catch(() => {\n // installAdapters() already absorbs adapter-level failures; this is a\n // defensive backstop so a totally unexpected rejection never surfaces.\n });\n\n // MHQ-482: DB auto-capture (opt-in — MORSE_CAPTURE_DB / MORSE_CAPTURE_INFRA,\n // mirrors the Python SDK's `infra_capture.py::maybe_enable_from_env`).\n // MUST run after `getOtelEngine().configure()` above — instrumentation\n // registration needs the `NodeTracerProvider` that call just built.\n try {\n maybeEnableDbCaptureFromEnv();\n } catch (err) {\n report(err, { fingerprint: \"morse.db_capture.register\" });\n }\n\n return { apiKey, endpoint, transport, redaction };\n}\n\nfunction ensureInitialized(): SingletonState | null {\n if (readIsDisabled()) return null;\n if (singleton !== null) return singleton;\n // Lazy default-init: defaults are safe (default-on redaction).\n singleton = buildSingleton({}, buildRedactionConfig());\n return singleton;\n}\n\n// Wire the lazy-init hook into log.ts so `log()` participates in the\n// same env-driven auto-init flow as `track()` / `record()`. Discards\n// the return value — log.ts only needs the side-effect of populating\n// the module-level singleton + transport.\n_setLogEnsureInitialized(() => {\n ensureInitialized();\n});\n\n/* ------------------------------------------------------------------------ */\n/* Public API — wrapped at the module surface */\n/* ------------------------------------------------------------------------ */\n\n/**\n * Initialize the Morse SDK singleton. Call once at application\n * startup. After this call, `track()`, `batchTrack()`, `run()`, and\n * `flush()` are wired up to the configured endpoint.\n *\n * `endpoint` is optional — when omitted, the SDK resolves in this order:\n * 1. `MORSE_ENDPOINT` env var (if set)\n * 2. The default Railway production URL.\n *\n * `MORSE_DISABLED=1` overrides everything: `init()` is a no-op.\n *\n * Calling `init()` a second time replaces the singleton — the previous\n * transport is shut down cleanly and a new one is constructed.\n *\n * Validation errors (e.g., disabling a mandatory redaction pattern, an\n * uncompilable extra pattern) are deliberately NOT absorbed — they\n * propagate as `Error`s so the developer sees the misconfiguration at\n * application startup. All other errors raised from internal SDK paths\n * are absorbed via the per-call wrappers downstream.\n */\nexport function init(options: InitOptions = {}): void {\n if (readIsDisabled()) {\n logger(\"info\", \"morse: MORSE_DISABLED=1 — SDK is a no-op\");\n return;\n }\n // Validate redaction options FIRST — must throw before we mutate any\n // singleton state, so a misconfigured init leaves the previous client\n // intact and the spec scenario \"no Client is constructed\" holds.\n const redaction = buildRedactionConfig(options.redaction);\n\n try {\n if (singleton !== null) {\n void singleton.transport.shutdown();\n singleton = null;\n }\n singleton = buildSingleton(options, redaction);\n } catch (err) {\n report(err, { fingerprint: \"morse.init\" });\n }\n}\n\n/**\n * Submit a single agent run to the ingestion endpoint. Non-blocking;\n * returns immediately. Silently no-ops if the SDK isn't initialised.\n */\nexport const track = absorbErrorsSync(\n (options: TrackOptions): void => {\n const state = ensureInitialized();\n if (!state) return;\n const payload = {\n agent_id: options.agentId,\n ...options.runData,\n };\n const redacted = redactValue(payload, state.redaction) as TelemetryEvent;\n state.transport.track(redacted);\n },\n { fingerprint: \"morse.track\" },\n);\n\n/** Submit multiple agent runs in bulk. Silently no-ops if uninitialised. */\nexport const batchTrack = absorbErrorsSync(\n (runs: Array<Record<string, unknown>>): void => {\n const state = ensureInitialized();\n if (!state) return;\n for (const run of runs) {\n const redacted = redactValue(run, state.redaction) as TelemetryEvent;\n state.transport.track(redacted);\n }\n },\n { fingerprint: \"morse.batch_track\" },\n);\n\n/**\n * High-level convenience: record an agent outcome with named fields.\n *\n * Builds a synthetic single-span `agent`-type trace and submits it through\n * the same `traces`-shaped emission path `run()`/`span()` use (MHQ-746) —\n * mirrors Python's `client.py::record()`. The live dev-api backend has no\n * `runs` ingest route; sending through `state.transport.track()` (the\n * shape `track()`/`batchTrack()` still use, matching Python's equally\n * unmigrated `track()`/`batch_track()`) 422s silently. See MHQ-746.\n */\nexport const record = absorbErrorsSync(\n (rec: RunRecord): void => {\n const state = ensureInitialized();\n if (!state) return;\n\n const traceId = generateTraceId();\n const now = nowIso();\n const resolvedStatus = rec.errorMessage ? \"failed\" : (rec.status ?? \"completed\");\n\n const span: SpanData = {\n trace_id: traceId,\n span_id: generateSpanId(),\n type: SpanType.AGENT,\n name: rec.agent,\n started_at: now,\n ended_at: now,\n status: resolvedStatus,\n duration_ms: rec.durationMs,\n model: rec.model,\n input_tokens: rec.inputTokens,\n output_tokens: rec.outputTokens,\n total_tokens: rec.totalTokens,\n cost_usd: rec.cost,\n error_message: rec.errorMessage,\n metadata: rec.metadata,\n };\n\n const traceFields: TraceFields = {\n trace_id: traceId,\n agent: rec.agent,\n status: resolvedStatus,\n started_at: now,\n ended_at: now,\n duration_ms: rec.durationMs,\n error_message: rec.errorMessage,\n success: rec.success,\n outcome: rec.outcome,\n };\n\n const entry = buildTraceEntry(traceFields, [span]);\n const redacted = redactValue(entry, state.redaction) as {\n trace: Record<string, unknown>;\n spans: Record<string, unknown>[];\n };\n _sendTrace(redacted);\n },\n { fingerprint: \"morse.record\" },\n);\n\n/**\n * Open a traced agent run, executing `fn` inside the trace context.\n * Mirrors Python's `morse.run(...)` context manager.\n *\n * Two overloads are supported:\n * - `run(name, fn)` — quick form with default options.\n * - `run({ agentName, incomingTraceparent }, fn)` — full options.\n *\n * Async callers receive a Promise; sync callers receive the value\n * directly. The function's return value is forwarded to the caller.\n */\nexport function run<T>(name: string, fn: (handle: RunHandle) => T): T | undefined;\nexport function run<T>(options: RunOptions, fn: (handle: RunHandle) => T): T | undefined;\nexport function run<T>(\n nameOrOpts: string | RunOptions,\n fn: (handle: RunHandle) => T,\n): T | undefined {\n const opts = typeof nameOrOpts === \"string\" ? { agentName: nameOrOpts } : nameOrOpts;\n // Make sure the SDK is initialised so spans get sent. Failure to init\n // is fine — `_runSync` records to `lastTrace` regardless, useful for tests.\n ensureInitialized();\n // We can't reliably detect async vs sync up front in TypeScript, so we\n // route through `_runSync` and, if the user's `fn` returns a promise,\n // the wrapping trace ends synchronously after the promise is created.\n // For correct async lifecycle, callers should use `runTraced` instead\n // (it awaits the promise inside the `als.run` scope so the trace\n // closes when the promise resolves).\n return _runSync(opts, fn);\n}\n\n/** Async variant of `run` — exported for callers who want explicit typing. */\nexport function runTraced<T>(\n options: RunOptions,\n fn: (handle: RunHandle) => Promise<T>,\n): Promise<T | undefined> {\n ensureInitialized();\n return _runAsync(options, fn);\n}\n\n/**\n * Attach cost-attribution dimensions to the active trace (MHQ-751). Call\n * once per request (e.g. in middleware) to propagate `customerId`,\n * `feature`, `env`, `team`, etc. to all child spans downstream. Values are\n * coerced to strings. No-op outside an active trace — never throws.\n * Mirrors Python's `morse_ai.set_context(**dims)`.\n */\nexport function setContext(dims: Record<string, unknown>): void {\n _setContext(dims);\n}\n\n/** Start a child span under the active trace. Returns null if no trace. */\nexport function startSpan(options: SpanOptions): SpanHandle | null {\n return _startSpan(options);\n}\n\n/** Run `fn` inside a child span. No-op if no trace is active. */\nexport function span<T>(options: SpanOptions, fn: (handle: SpanHandle | null) => T): T {\n return _spanSync(options, fn);\n}\n\n/** Async variant of `span`. */\nexport function spanAsync<T>(\n options: SpanOptions,\n fn: (handle: SpanHandle | null) => Promise<T>,\n): Promise<T> {\n return _spanAsync(options, fn);\n}\n\n/** Block until all queued events have been sent. Silent on uninit / errors. */\nexport const flush = absorbErrorsAsync(\n async (): Promise<void> => {\n if (singleton !== null) {\n await singleton.transport.flush();\n await getOtelEngine().flush();\n }\n },\n { fingerprint: \"morse.flush\" },\n);\n\n/**\n * Latest ingest quota / rate-limit state observed by the SDK, or `null`.\n *\n * TQE-04 (MHQ-676/MHQ-749): when the Morse backend answers a telemetry\n * batch with HTTP 429 — the monthly event limit (`event_limit_exceeded`)\n * or the per-second ingest rate limit (`RATE_LIMIT_INGEST`) — the\n * transport parses the response and stores it. This function exposes\n * that state so host applications can alert on quota exhaustion instead\n * of discovering it from missing telemetry. Mirrors Python's\n * `morse_ai.quota_state()`.\n *\n * Returns `null` when the SDK is uninitialized or no 429 has been\n * observed. The object includes at least `kind` (`\"event_limit\"`,\n * `\"rate_limit\"`, or `\"unknown\"`), `status`, and `receivedAt` (epoch\n * seconds); event-limit states add `currentCount` / `limitCount` /\n * `planId` / `periodStart` / `upgradeUrl`.\n */\nexport const quotaState = absorbErrorsSync(\n (): QuotaState | null => {\n if (singleton === null) return null;\n return _getQuotaState();\n },\n { fingerprint: \"morse.quota_state\" },\n);\n\n/** Flush and stop the background transport. Call on app exit. */\nexport const shutdown = absorbErrorsAsync(\n async (): Promise<void> => {\n if (singleton !== null) {\n await singleton.transport.shutdown();\n await getOtelEngine().flush();\n getOtelEngine().shutdown();\n singleton = null;\n setTransport(null);\n }\n },\n { fingerprint: \"morse.shutdown\" },\n);\n\n/* ------------------------------------------------------------------------ */\n/* Test-only hooks (private) */\n/* ------------------------------------------------------------------------ */\n\n/**\n * Reset the module-level singleton for tests. Customer code must NOT\n * call this — the singleton is meant to live for the process lifetime.\n *\n * @internal\n */\nexport function _resetForTesting(): void {\n if (singleton !== null) {\n void singleton.transport.shutdown();\n singleton = null;\n setTransport(null);\n }\n getOtelEngine().resetForTesting();\n noApiKeyWarningEmitted = false;\n lastLoggedEndpoint = null;\n _setSource(null);\n _resetTracingForTesting();\n _resetDiagnosticsForTesting();\n _resetAutoDetectForTesting();\n _resetQuotaStateForTesting();\n // Reset the transport factory back to the default.\n transportFactory = (opts) => new BatchTransport(opts);\n}\n\n/**\n * Inject an alternate transport factory for tests (e.g., a mock that\n * captures sent payloads instead of opening a fetch).\n *\n * @internal\n */\nexport function _setTransportFactoryForTesting(\n factory: (opts: {\n apiKey: string;\n endpoint: string;\n flushIntervalSeconds: number;\n }) => BatchTransport,\n): void {\n transportFactory = factory;\n}\n\n/**\n * Read the most recently completed trace entry, for test assertions.\n *\n * @internal\n */\nexport function _getLastTraceForTesting(): { trace: unknown; spans: unknown[] } | null {\n return _getLastTrace();\n}\n\n/**\n * Read the active trace state, for test assertions.\n *\n * @internal\n */\nexport function _getActiveTraceStateForTesting(): unknown {\n return _getActiveTraceState();\n}\n","/**\n * DB auto-capture (MHQ-482) — TypeScript SDK parity port of the Python\n * SDK's `infra_capture.py` `db` span coverage.\n *\n * NOT a straight port. Python hand-patches PEP-249 driver methods\n * (`sqlite3.connect`, `psycopg2.connect`) because there's no other way to\n * intercept a C-extension cursor type. Node has no PEP-249 equivalent, and\n * — per the founder's standing decision on this gap — no reason to\n * hand-roll driver patching when OpenTelemetry's own community\n * instrumentation packages already do it, robustly, for the two most\n * common Node SQL drivers:\n *\n * - `pg` -> `@opentelemetry/instrumentation-pg` (verified on\n * npm: real package, current version 0.73.0)\n * - `mysql2` -> `@opentelemetry/instrumentation-mysql2` (verified on\n * npm: real package, current version 0.67.0)\n * - `better-sqlite3` -> NO community package exists (verified: neither\n * `@opentelemetry/instrumentation-better-sqlite3` nor\n * `@opentelemetry/instrumentation-sqlite3` are published,\n * and the OTel JS contrib repo's instrumentation list has\n * no sqlite entry at all). `./db-capture-sqlite.ts` is a\n * small hand-rolled instrumentation following the exact\n * same `InstrumentationNodeModuleDefinition` hook pattern\n * the community packages use, so it degrades identically\n * (silent no-op) when `better-sqlite3` isn't installed.\n *\n * Attribute shape — no translation layer needed\n * ----------------------------------------------\n * Unlike `otel-provider.ts::emitTraceEntry` (which translates Morse's own\n * `SpanData` dicts into `av.*`/`gen_ai.*`-namespaced OTel attributes because\n * THAT data has no OTel-native shape), these instrumentation packages\n * build real OTel spans directly and already emit the current stable OTel\n * semantic-convention DB attributes — `db.system.name`, `db.namespace`,\n * `db.query.text` (confirmed by reading `@opentelemetry/instrumentation-pg`\n * 0.73.0's `utils.js` / `semconv.js`). These are the same key names\n * `./db-capture-sqlite.ts`'s custom sqlite instrumentation uses, and are\n * standard, documented OTel semconv — the backend's generic OTLP ingestion\n * path (out of this gap's scope — owned by `apps/api/`) is the right place\n * for any further server-side mapping, not this SDK. No `spanDictToOtelAttributes`-\n * style translation is added here.\n *\n * Registration, not patching\n * ---------------------------\n * `registerDbInstrumentation()` builds instrumentation instances and hands\n * them to `otel-provider.ts::OtelEngine.registerInstrumentations()`, which\n * wires them to the SAME `NodeTracerProvider` (and therefore the same\n * `BatchSpanProcessor` -> `RedactingSpanExporter` -> `OTLPTraceExporter`\n * pipeline) the rest of the SDK's spans flow through — see that module's\n * docstring. Each instrumentation package internally uses\n * `require-in-the-middle` hooks (`InstrumentationNodeModuleDefinition`), so\n * constructing/registering them is always safe even when the target driver\n * isn't installed in the host app: the hook simply never fires.\n *\n * Correlation with `morse.span()` / `morse.run()`\n * -------------------------------------------------\n * These instrumentations read OTel's GLOBAL `context.active()` to find\n * their parent span. `tracing.ts`'s `runSync`/`runAsync`/`spanSync`/\n * `spanAsync` now set that global active context to a synthetic\n * `SpanContext` carrying the current Morse trace id + span id for the\n * duration of the wrapped callback (see `otel-provider.ts::withOtelSpanContext`)\n * — so a query made inside a `morse.span()` block nests under it via the\n * normal OTel parent/child mechanism, the same way it would in any other\n * OTel-instrumented Node app.\n *\n * Opt-in (`MORSE_CAPTURE_DB` / `MORSE_CAPTURE_INFRA`, mirrors Python's\n * `infra_capture.py::maybe_enable_from_env`) — not default-on while the\n * approach is proven, same posture as the Python SDK.\n */\n\nimport type { Instrumentation } from \"@opentelemetry/instrumentation\";\nimport { PgInstrumentation } from \"@opentelemetry/instrumentation-pg\";\nimport { MySQL2Instrumentation } from \"@opentelemetry/instrumentation-mysql2\";\n\nimport { isDbCaptureEnabled } from \"./env\";\nimport { getEngine } from \"./otel-provider\";\nimport { BetterSqlite3Instrumentation } from \"./db-capture-sqlite\";\n\nlet unregister: (() => void) | null = null;\nlet registeredInstrumentations: Instrumentation[] | null = null;\n\n/**\n * Build one instance of each supported driver's `Instrumentation`. Exposed\n * separately from `registerDbInstrumentation()` so tests can construct them\n * without touching the module-level registration state.\n */\nexport function buildDbInstrumentations(): Instrumentation[] {\n return [\n new PgInstrumentation() as unknown as Instrumentation,\n new MySQL2Instrumentation() as unknown as Instrumentation,\n new BetterSqlite3Instrumentation() as unknown as Instrumentation,\n ];\n}\n\n/**\n * Register DB auto-capture against the engine's `NodeTracerProvider`.\n * Idempotent — calling this again first unregisters the previous set (same\n * \"re-init replaces\" contract `index.ts::init()` uses for the rest of the\n * singleton). No-op (returns `false`) if the OTel engine hasn't been\n * `configure()`-d yet — callers MUST invoke this after\n * `getOtelEngine().configure()` (see `index.ts::buildSingleton`).\n *\n * Never throws — construction/registration errors are swallowed, mirroring\n * the rest of this SDK's non-invasive guarantee (a driver-instrumentation\n * bug must never break the host app's DB calls).\n */\nexport function registerDbInstrumentation(): boolean {\n disableDbCapture();\n try {\n const instrumentations = buildDbInstrumentations();\n const off = getEngine().registerInstrumentations(instrumentations);\n if (off === null) return false;\n unregister = off;\n registeredInstrumentations = instrumentations;\n return true;\n } catch {\n unregister = null;\n registeredInstrumentations = null;\n return false;\n }\n}\n\n/** Unregister DB auto-capture (idempotent). Primarily for tests. */\nexport function disableDbCapture(): void {\n if (unregister !== null) {\n try {\n unregister();\n } catch {\n // Best-effort.\n }\n }\n unregister = null;\n registeredInstrumentations = null;\n}\n\n/** @internal test hook — the currently-registered instrumentation instances, or null. */\nexport function _getRegisteredInstrumentationsForTesting(): Instrumentation[] | null {\n return registeredInstrumentations;\n}\n\n/**\n * Called from `index.ts::buildSingleton()` after `getOtelEngine().configure()`.\n * Enables DB capture per env flags — mirrors Python's\n * `infra_capture.py::maybe_enable_from_env`:\n *\n * - `MORSE_CAPTURE_DB=1` -> DB capture\n * - `MORSE_CAPTURE_INFRA=1` -> DB capture (convenience alias; Python's HTTP\n * half of this flag has no TS-side port yet)\n */\nexport function maybeEnableDbCaptureFromEnv(): void {\n if (isDbCaptureEnabled()) {\n registerDbInstrumentation();\n }\n}\n","/**\n * Custom `better-sqlite3` OTel instrumentation (MHQ-482).\n *\n * There is no `@opentelemetry/instrumentation-better-sqlite3` (or any\n * community equivalent) on npm — verified against the npm registry while\n * building this module: `@opentelemetry/instrumentation-sqlite3` doesn't\n * exist either, and the OTel JS contrib repo's package list has no sqlite\n * entry at all. `better-sqlite3` is a common lightweight/embedded driver\n * (used heavily in tests, scripts, and small services — mirrors the\n * Python SDK's stdlib `sqlite3` coverage in `infra_capture.py`), so rather\n * than drop sqlite coverage entirely, this is a small hand-rolled\n * `InstrumentationBase` subclass following the exact same\n * `InstrumentationNodeModuleDefinition` hook-based patching pattern the\n * community `pg`/`mysql2` packages use (see `./db-capture.ts`) — it only\n * patches when a host app actually `require()`s `better-sqlite3`, and is a\n * transparent no-op otherwise.\n *\n * Span attribute naming mirrors the same stable OTel semantic-convention\n * keys `@opentelemetry/instrumentation-pg` / `-mysql2` emit\n * (`db.system.name`, `db.query.text`, `db.namespace`) — see `./db-capture.ts`'s\n * module docstring for why no translation layer is needed.\n *\n * better-sqlite3 is fully synchronous, so there's no async/callback\n * variant to cover (unlike `pg`/`mysql2`).\n */\n\nimport {\n InstrumentationBase,\n InstrumentationNodeModuleDefinition,\n isWrapped,\n type InstrumentationConfig,\n} from \"@opentelemetry/instrumentation\";\nimport {\n context as otelContext,\n SpanKind,\n SpanStatusCode,\n trace as traceApi,\n} from \"@opentelemetry/api\";\n\nconst SEMCONV_DB_SYSTEM_NAME = \"db.system.name\";\nconst SEMCONV_DB_QUERY_TEXT = \"db.query.text\";\nconst DB_SYSTEM_NAME_SQLITE = \"sqlite\";\n\n// Mirrors the Python SDK's `infra_capture.py::_MAX_STATEMENT_LEN` — a\n// giant IN (...) clause shouldn't bloat the span; truncated with the same\n// marker style `otel-provider.ts::capBytes` uses elsewhere in this SDK.\nconst MAX_STATEMENT_CHARS = 2048;\nconst TRUNCATION_MARKER = \"…[truncated]\";\n\nfunction sqlVerb(sql: unknown): string {\n try {\n const first = String(sql).trim().split(/\\s+/, 1)[0];\n return first ? first.toUpperCase() : \"QUERY\";\n } catch {\n return \"QUERY\";\n }\n}\n\nfunction safeStatement(sql: unknown): string | undefined {\n let text: string;\n try {\n text = String(sql).trim();\n } catch {\n return undefined;\n }\n if (!text) return undefined;\n if (text.length > MAX_STATEMENT_CHARS) {\n return text.slice(0, MAX_STATEMENT_CHARS) + \" \" + TRUNCATION_MARKER;\n }\n return text;\n}\n\n// `Statement`/`Database` instances from better-sqlite3 — kept loosely typed\n// (the package is an optional peer the SDK never imports types from).\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\ntype AnyRecord = Record<string, any>;\n\nconst SYNC_STATEMENT_METHODS = [\"run\", \"get\", \"all\", \"iterate\"] as const;\n\nexport class BetterSqlite3Instrumentation extends InstrumentationBase<InstrumentationConfig> {\n constructor(config: InstrumentationConfig = {}) {\n super(\"@morsehq/instrumentation-better-sqlite3\", \"0.1.0\", config);\n }\n\n protected init(): InstrumentationNodeModuleDefinition[] {\n return [\n new InstrumentationNodeModuleDefinition(\n \"better-sqlite3\",\n [\">=7.0.0 <14\"],\n (moduleExports: AnyRecord) => this._patch(moduleExports),\n (moduleExports: AnyRecord) => this._unpatch(moduleExports),\n ),\n ];\n }\n\n private _withSpan<T>(sql: unknown, fn: () => T): T {\n const span = this.tracer.startSpan(sqlVerb(sql), { kind: SpanKind.CLIENT });\n const stmt = safeStatement(sql);\n span.setAttribute(SEMCONV_DB_SYSTEM_NAME, DB_SYSTEM_NAME_SQLITE);\n if (stmt) span.setAttribute(SEMCONV_DB_QUERY_TEXT, stmt);\n return otelContext.with(traceApi.setSpan(otelContext.active(), span), () => {\n try {\n const result = fn();\n span.end();\n return result;\n } catch (err) {\n span.recordException(err as Error);\n span.setStatus({ code: SpanStatusCode.ERROR, message: (err as Error)?.message });\n span.end();\n throw err;\n }\n });\n }\n\n /** Wrap one already-`prepare()`d statement's sync execution methods. */\n private _wrapStatementInstance(stmt: AnyRecord): AnyRecord {\n const sql = stmt?.source;\n for (const method of SYNC_STATEMENT_METHODS) {\n const original = stmt[method];\n if (typeof original !== \"function\") continue;\n const bound = original.bind(stmt);\n // Own-property override (not a prototype patch) — each `prepare()`\n // call returns a distinct Statement instance, so this never leaks\n // across statements or requires finding/patching a shared class.\n stmt[method] = (...args: unknown[]) => this._withSpan(sql, () => bound(...args));\n }\n return stmt;\n }\n\n private _patch(moduleExports: AnyRecord): AnyRecord {\n const DatabaseCtor = moduleExports as AnyRecord;\n const proto = DatabaseCtor?.prototype;\n if (!proto) return moduleExports;\n\n if (isWrapped(proto.prepare)) this._unwrap(proto, \"prepare\");\n this._wrap(proto, \"prepare\", (original: (...a: unknown[]) => AnyRecord) => {\n const wrapStatement = (stmt: AnyRecord): AnyRecord => this._wrapStatementInstance(stmt);\n return function (this: unknown, ...args: unknown[]): AnyRecord {\n const stmt = original.apply(this, args);\n return wrapStatement(stmt);\n };\n });\n\n if (isWrapped(proto.exec)) this._unwrap(proto, \"exec\");\n this._wrap(proto, \"exec\", (original: (...a: unknown[]) => unknown) => {\n const withSpan = <T>(sql: unknown, fn: () => T): T => this._withSpan(sql, fn);\n return function (this: unknown, ...args: unknown[]): unknown {\n return withSpan(args[0], () => original.apply(this, args));\n };\n });\n\n return moduleExports;\n }\n\n private _unpatch(moduleExports: AnyRecord): void {\n const proto = moduleExports?.prototype;\n if (!proto) return;\n if (isWrapped(proto.prepare)) this._unwrap(proto, \"prepare\");\n if (isWrapped(proto.exec)) this._unwrap(proto, \"exec\");\n }\n}\n","/**\n * Background batched HTTP transport.\n *\n * Mirrors the Python SDK's `transport.py` semantics:\n *\n * - Async batching: 2-second flush interval (configurable), 100-event\n * max batch size (configurable). Whichever fires first triggers a\n * flush.\n * - Network failures are silently dropped with a debug log — never\n * thrown to the caller.\n * - The caller's thread / event loop is never blocked: `track()`\n * enqueues and returns immediately.\n *\n * The transport speaks two payload shapes (matching Python):\n *\n * - V2 trace events: `{ traces: [{ trace, spans }, ...] }`\n * - V1 legacy runs: `{ runs: [{ ... }, ...] }`\n *\n * Wire-format routing checks for a `traces` key on each enqueued event.\n *\n * Browser vs Node:\n * - Both runtimes ship `fetch` (Node 18+ / all evergreens).\n * - In Node we can run a `setInterval` and call it a day.\n * - In the browser the same approach works; we don't currently flush\n * on `pagehide` / `beforeunload` — Phase 6c spec doesn't require it.\n * A future change can add `navigator.sendBeacon` for last-gasp delivery.\n */\n\nimport {\n recordDrop,\n report,\n setLevel,\n REASON_QUEUE_FULL,\n REASON_QUOTA_REJECTED,\n REASON_RETRY_EXHAUSTED,\n REASON_SHUTDOWN_DROP,\n} from \"./diagnostics\";\n\n// Injected at build time by tsup from package.json — see tsup.config.ts.\n// The version is declared in exactly one place (package.json); a copy here\n// would drift the moment a release bumped one and not the other, and the\n// stale value rides out on the User-Agent and on every span's `sdk_version`.\n// `__SDK_VERSION__` is undefined when running straight from source (vitest,\n// ts-node), hence the fallback.\ndeclare const __SDK_VERSION__: string | undefined;\n\nexport const SDK_VERSION = typeof __SDK_VERSION__ === \"string\" ? __SDK_VERSION__ : \"0.0.0-dev\";\n\nexport interface BatchTransportOptions {\n endpoint: string;\n apiKey: string;\n /** Max wait between flushes, in seconds. Default: 2.0. */\n flushIntervalSeconds?: number;\n /** Max events per batch. Default: 100. */\n maxBatchSize?: number;\n /** Max queued events before drop. Default: 10_000. */\n maxQueueSize?: number;\n /** Timeout for the underlying fetch, in ms. Default: 5_000. */\n fetchTimeoutMs?: number;\n /**\n * Pluggable fetch implementation. Defaults to `globalThis.fetch`.\n * Useful for tests.\n */\n fetchImpl?: typeof fetch;\n}\n\n/**\n * Wire shape for a single log record. Mirrors the Python SDK payload at\n * `apps/sdk/python/src/morse/client.py:191-211` and the backend\n * `SimpleLogsIngestController.ingest` contract\n * (`apps/api/apps/logs/controllers.py:66-134`).\n */\nexport interface LogRecordPayload {\n timestamp: string;\n severity: string;\n service_name: string;\n body: string;\n attributes: Record<string, unknown>;\n trace_id: string | null;\n span_id: string | null;\n}\n\nexport type TelemetryEvent =\n | { traces: unknown[] }\n | { logs: LogRecordPayload[] }\n | Record<string, unknown>;\n\n/**\n * Quota / rate-limit state parsed from a 429 batch-POST response.\n *\n * Mirrors Python's `transport.py::BatchTransport._record_quota_state` /\n * `quota_state()` (TQE-04 / MHQ-676) field-for-field, camelCased per this\n * codebase's convention (`received_at` -> `receivedAt`, etc.). Two known\n * body shapes:\n *\n * - `event_limit_exceeded` (traces controllers) — flat body with\n * `current_count` / `limit_count` / `plan_id` / `period_start` /\n * `upgrade_url` / `sample_rate_url`.\n * - `RATE_LIMIT_INGEST` (ingest rate-limit middleware) — nested\n * `{ error: { code, message, details: { limit, plan } } }`.\n *\n * Anything else is recorded as `kind: \"unknown\"` so the state surface\n * still reflects that ingest is throttled even when the body doesn't\n * parse into a known shape.\n */\nexport interface QuotaState {\n kind: \"event_limit\" | \"rate_limit\" | \"unknown\";\n status: number;\n /** Epoch seconds, matching Python's `time.time()`. */\n receivedAt: number;\n message?: string;\n currentCount?: number;\n limitCount?: number;\n planId?: string;\n periodStart?: string;\n upgradeUrl?: string;\n sampleRateUrl?: string;\n quotaLimit?: number;\n quotaRemaining?: number;\n quotaReset?: number;\n retryAfterSeconds?: number;\n}\n\n// `Retry-After` values above this are clamped, mirroring Python's\n// `_RETRY_AFTER_CAP_SECONDS` — a background flush loop must never commit\n// to reporting minutes-long waits from one batch.\nconst RETRY_AFTER_CAP_SECONDS = 30.0;\n\n/**\n * Parse a `Retry-After` header (seconds form only), capped.\n *\n * Mirrors Python's `transport.py::_parse_retry_after`. HTTP-date form\n * isn't worth supporting — Morse's own 429s always use the seconds form.\n * Unparseable / negative values return `null`.\n */\nfunction parseRetryAfter(value: string | null): number | null {\n if (!value) return null;\n const seconds = Number(value);\n if (!Number.isFinite(seconds) || seconds < 0) return null;\n return Math.min(seconds, RETRY_AFTER_CAP_SECONDS);\n}\n\n// Module-level, matching the `lastTrace` test-introspection pattern in\n// `_internal/tracing.ts` — the latest quota/rate-limit state observed on\n// a 429 response, exposed via `quotaState()` / `morse.quotaState()`. Not\n// cleared on a subsequent successful POST (mirrors Python: it persists\n// until overwritten by a newer 429, so a host app can see \"quota was\n// exceeded recently\" even after the queue drains — see\n// `test_429_recovers_when_retry_succeeds` in the Python test suite,\n// which only asserts no drop-warning, never that state was cleared).\nlet quotaState: QuotaState | null = null;\n\n/**\n * Latest quota/rate-limit state observed on a 429, or `null` if none has\n * been observed yet. Returns a shallow copy — callers can't mutate\n * transport-internal state. Mirrors Python's `BatchTransport.quota_state()`.\n *\n * @internal\n */\nexport function getQuotaState(): QuotaState | null {\n return quotaState ? { ...quotaState } : null;\n}\n\n/**\n * Reset the module-level quota state between test files/cases.\n *\n * @internal\n */\nexport function _resetQuotaStateForTesting(): void {\n quotaState = null;\n}\n\nfunction asString(value: unknown): string | undefined {\n return typeof value === \"string\" ? value : undefined;\n}\n\nfunction asNumber(value: unknown): number | undefined {\n return typeof value === \"number\" && Number.isFinite(value) ? value : undefined;\n}\n\nfunction numberFromHeader(raw: string | null): number | undefined {\n if (raw === null) return undefined;\n const n = Number(raw);\n return Number.isFinite(n) ? n : undefined;\n}\n\n/**\n * Parse a 429 response into the module-level quota state. Never throws —\n * defensively parses two known body shapes (see `QuotaState`), falling\n * back to `kind: \"unknown\"` for anything else. Mirrors Python's\n * `_record_quota_state`.\n */\nasync function recordQuotaState(resp: Response): Promise<void> {\n try {\n const state: QuotaState = {\n kind: \"unknown\",\n status: 429,\n receivedAt: Date.now() / 1000,\n };\n\n let data: unknown = null;\n try {\n data = await resp.clone().json();\n } catch {\n data = null;\n }\n\n if (data !== null && typeof data === \"object\") {\n const body = data as Record<string, unknown>;\n const err = body.error;\n if (err === \"event_limit_exceeded\") {\n state.kind = \"event_limit\";\n state.message = asString(body.message);\n state.currentCount = asNumber(body.current_count);\n state.limitCount = asNumber(body.limit_count);\n state.planId = asString(body.plan_id);\n state.periodStart = asString(body.period_start);\n state.upgradeUrl = asString(body.upgrade_url);\n state.sampleRateUrl = asString(body.sample_rate_url);\n } else if (\n err !== null &&\n typeof err === \"object\" &&\n (err as Record<string, unknown>).code === \"RATE_LIMIT_INGEST\"\n ) {\n const errObj = err as Record<string, unknown>;\n const details =\n errObj.details !== null && typeof errObj.details === \"object\"\n ? (errObj.details as Record<string, unknown>)\n : {};\n state.kind = \"rate_limit\";\n state.message = asString(errObj.message);\n state.limitCount = asNumber(details.limit);\n state.planId = asString(details.plan);\n }\n }\n\n // TQE-05 headers, emitted by the server on every ingest response.\n const quotaLimit = numberFromHeader(resp.headers.get(\"X-Morse-Quota-Limit\"));\n if (quotaLimit !== undefined) state.quotaLimit = quotaLimit;\n const quotaRemaining = numberFromHeader(resp.headers.get(\"X-Morse-Quota-Remaining\"));\n if (quotaRemaining !== undefined) state.quotaRemaining = quotaRemaining;\n const quotaReset = numberFromHeader(resp.headers.get(\"X-Morse-Quota-Reset\"));\n if (quotaReset !== undefined) state.quotaReset = quotaReset;\n const retryAfter = parseRetryAfter(resp.headers.get(\"Retry-After\"));\n if (retryAfter !== null) state.retryAfterSeconds = retryAfter;\n\n quotaState = state;\n } catch {\n // Never let state capture break the send path.\n }\n}\n\nexport class BatchTransport {\n private readonly endpoint: string;\n private readonly apiKey: string;\n private readonly flushIntervalSeconds: number;\n private readonly maxBatchSize: number;\n private readonly maxQueueSize: number;\n private readonly fetchTimeoutMs: number;\n private readonly fetchImpl: typeof fetch;\n\n private queue: TelemetryEvent[] = [];\n private timer: ReturnType<typeof setInterval> | null = null;\n private flushing = false;\n private closed = false;\n private inflight: Promise<void> | null = null;\n\n constructor(opts: BatchTransportOptions) {\n this.endpoint = opts.endpoint;\n this.apiKey = opts.apiKey;\n this.flushIntervalSeconds = opts.flushIntervalSeconds ?? 2.0;\n this.maxBatchSize = opts.maxBatchSize ?? 100;\n this.maxQueueSize = opts.maxQueueSize ?? 10_000;\n this.fetchTimeoutMs = opts.fetchTimeoutMs ?? 5_000;\n this.fetchImpl = opts.fetchImpl ?? globalThis.fetch.bind(globalThis);\n\n // setInterval keeps the Node event loop alive. We mark it `unref`\n // when available so a process-exit isn't blocked by a quiet flusher.\n const intervalMs = Math.max(50, Math.round(this.flushIntervalSeconds * 1000));\n this.timer = setInterval(() => {\n void this.tick();\n }, intervalMs);\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const t = this.timer as any;\n if (typeof t?.unref === \"function\") {\n t.unref();\n }\n }\n\n /** Enqueue an event. Non-blocking. Returns false if the queue is full. */\n track(event: TelemetryEvent): boolean {\n if (this.closed) {\n recordDrop(REASON_SHUTDOWN_DROP, \"trace\");\n return false;\n }\n if (this.queue.length >= this.maxQueueSize) {\n // SDKDIAG-09: previously a bare `return false` — sustained telemetry loss\n // was invisible to both us and the customer. Now counted and logged.\n recordDrop(REASON_QUEUE_FULL, \"trace\");\n return false;\n }\n this.queue.push(event);\n if (this.queue.length >= this.maxBatchSize) {\n void this.tick();\n }\n return true;\n }\n\n /** Block until all currently-queued events have been sent. */\n async flush(): Promise<void> {\n // Drain in one-batch chunks until empty, then await the in-flight send.\n while (this.queue.length > 0) {\n await this.tick();\n }\n if (this.inflight) {\n try {\n await this.inflight;\n } catch {\n // Swallow — caller observes nothing.\n }\n }\n }\n\n /** Stop the background timer. After this call, `track()` is a no-op. */\n async shutdown(): Promise<void> {\n if (this.closed) return;\n this.closed = true;\n if (this.timer !== null) {\n clearInterval(this.timer);\n this.timer = null;\n }\n await this.flush();\n }\n\n private async tick(): Promise<void> {\n if (this.flushing) return;\n if (this.queue.length === 0) return;\n this.flushing = true;\n try {\n const batch = this.queue.splice(0, this.maxBatchSize);\n this.inflight = this.sendBatch(batch);\n await this.inflight;\n this.inflight = null;\n } finally {\n this.flushing = false;\n }\n }\n\n private async sendBatch(batch: TelemetryEvent[]): Promise<void> {\n const traceEntries: unknown[] = [];\n const runEntries: Record<string, unknown>[] = [];\n const logEntries: LogRecordPayload[] = [];\n for (const event of batch) {\n if (typeof event === \"object\" && event !== null && \"traces\" in event) {\n const e = event as { traces: unknown[] };\n if (Array.isArray(e.traces)) {\n traceEntries.push(...e.traces);\n }\n } else if (typeof event === \"object\" && event !== null && \"logs\" in event) {\n const e = event as { logs: LogRecordPayload[] };\n if (Array.isArray(e.logs)) {\n logEntries.push(...e.logs);\n }\n } else {\n runEntries.push(event as Record<string, unknown>);\n }\n }\n if (traceEntries.length > 0) {\n await this.post(this.endpoint, { traces: traceEntries });\n }\n if (runEntries.length > 0) {\n await this.post(this.endpoint, { runs: runEntries });\n }\n if (logEntries.length > 0) {\n // Phase 12.5 Tier 1.2 — logs go to a derived `/api/v1/logs/ingest`\n // endpoint on the same host as the traces batch URL. Mirrors the\n // Python SDK's URL derivation in\n // `apps/sdk/python/src/morse/client.py:187-190`.\n await this.post(deriveLogsEndpoint(this.endpoint), { logs: logEntries });\n }\n }\n\n private async post(url: string, payload: Record<string, unknown>): Promise<void> {\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.fetchTimeoutMs);\n try {\n const resp = await this.fetchImpl(url, {\n method: \"POST\",\n headers: {\n Authorization: `Bearer ${this.apiKey}`,\n \"Content-Type\": \"application/json\",\n \"User-Agent\": `morse-typescript/${SDK_VERSION}`,\n },\n body: JSON.stringify(payload),\n signal: controller.signal,\n });\n // SDKDIAG-05: the server pushes the SDK's self-reporting verbosity on a\n // response we are already receiving — no config round-trip.\n setLevel(resp.headers.get(\"X-Morse-Diagnostics\"));\n\n const droppedCount = countPayloadEntries(payload);\n const droppedCategory = categoryOf(payload);\n\n if (resp.status === 429) {\n // TQE-04 (MHQ-676) parity: surface quota/rate-limit state instead\n // of silently dropping telemetry. `resp.clone()` inside so the\n // body-snippet read below still works off the original response.\n await recordQuotaState(resp);\n recordDrop(REASON_QUOTA_REJECTED, droppedCategory, droppedCount);\n }\n if (!resp.ok) {\n // Drain a few hundred chars of the body for diagnostics.\n let bodySnippet = \"\";\n try {\n const text = await resp.text();\n bodySnippet = text.slice(0, 200);\n } catch {\n // ignore\n }\n if (resp.status !== 429) {\n recordDrop(REASON_RETRY_EXHAUSTED, droppedCategory, droppedCount);\n }\n report(new Error(`morse: batch POST returned ${resp.status} ${bodySnippet}`), {\n fingerprint: \"morse.transport.post.non_2xx\",\n extra: {\n endpoint_host: hostnameOf(url),\n sdk_version: SDK_VERSION,\n },\n });\n }\n } catch (err) {\n // Network errors / aborts / timeouts — silent drop, out-of-band report.\n recordDrop(REASON_RETRY_EXHAUSTED, categoryOf(payload), countPayloadEntries(payload));\n report(err, {\n fingerprint: \"morse.transport.post.network\",\n extra: {\n endpoint_host: hostnameOf(url),\n sdk_version: SDK_VERSION,\n },\n });\n } finally {\n clearTimeout(timeoutId);\n }\n }\n}\n\nfunction hostnameOf(url: string): string {\n try {\n return new URL(url).host;\n } catch {\n return \"<invalid>\";\n }\n}\n\n/**\n * Derive the logs ingest URL from the traces batch endpoint. Mirrors the\n * Python SDK helper: replace the path with `/api/v1/logs/ingest` and drop\n * any query/fragment.\n *\n * Exported for tests. Customer code should not call this directly.\n *\n * @internal\n */\nexport function deriveLogsEndpoint(tracesEndpoint: string): string {\n try {\n const u = new URL(tracesEndpoint);\n u.pathname = \"/api/v1/logs/ingest\";\n u.search = \"\";\n u.hash = \"\";\n return u.toString();\n } catch {\n // Fall back to a string replace on the most common shape.\n return tracesEndpoint.replace(/\\/api\\/v1\\/.*$/, \"/api/v1/logs/ingest\");\n }\n}\n\n/** How many telemetry entries a failed POST just cost the customer. */\nfunction countPayloadEntries(payload: Record<string, unknown>): number {\n let total = 0;\n for (const value of Object.values(payload)) {\n if (Array.isArray(value)) total += value.length;\n }\n return total || 1;\n}\n\n/** Which counter category a payload belongs to (SDKDIAG-09). */\nfunction categoryOf(payload: Record<string, unknown>): string {\n if (\"traces\" in payload) return \"trace\";\n if (\"logs\" in payload) return \"log\";\n return \"record\";\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/_internal/auto-detect.ts","../src/index.ts","../src/_internal/db-capture.ts","../src/_internal/db-capture-sqlite.ts","../src/_internal/transport.ts"],"names":["_resetForTesting","span","otelContext","traceApi","logger","run","setContext","startSpan","spanAsync","quotaState"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * Auto-detect installed AI SDKs and install the matching adapter.\n *\n * Node port of the Python SDK's `_internal/auto_detect.py` (auto-instrumentation\n * zero-config instrumentation): when the Morse SDK initializes, scan for\n * already-loaded target packages and install each detected adapter. For\n * packages not yet loaded, register a hook so the adapter installs as soon\n * as the customer's code requires it.\n *\n * Customer flow becomes:\n *\n * npm install @morsehq-dev/sdk\n * export MORSE_API_KEY=mhq_...\n * // ... existing @anthropic-ai/sdk / ai code is now traced ...\n *\n * No `morse.wrapAnthropic()` / `morse.instrumentAnthropic()` call required.\n *\n * ---------------------------------------------------------------------\n * Node vs. Python — why this module's SCOPE is narrower than auto_detect.py\n * ---------------------------------------------------------------------\n *\n * Python's `sys.modules` is a single global dict of every imported module,\n * and `importlib.abc.MetaPathFinder` gives a clean, built-in hook that\n * fires for BOTH `import x` and `from x import y`, regardless of package\n * shape. Node has no equivalent: there is no single \"loaded modules\"\n * registry that covers both CJS and ESM, and Node's ESM loader hook\n * (`node:module`'s `register()`) runs the customization hook in a\n * dedicated loader thread with structured-clone message-passing back to\n * the main thread — it cannot synchronously call back into an adapter's\n * `install()` in the main realm, and building an async message-passing\n * bridge just for this is disproportionate to what a v1 zero-config port\n * needs. So this port targets Node's CommonJS `require` machinery only:\n *\n * - \"Already loaded\" scan: `require.resolve(name)` (no side effect,\n * mirrors `importlib.util.find_spec`) + membership in `require.cache`\n * (mirrors `name in sys.modules`).\n * - \"Not yet loaded\" hook: patch `Module.prototype.require` so any\n * `require(name)` call — including the one Node performs internally\n * when a CJS-authored package is `import`-ed from an ESM file, which\n * is how `@anthropic-ai/sdk` and `ai` are typically consumed — fires\n * the adapter's install() once the module body has finished\n * evaluating. Pure-ESM packages loaded via the native ESM loader\n * (no CJS `require` in the chain) are NOT observed by this hook; for\n * those, `wrapX()` / `instrumentX()` remain the documented manual path.\n *\n * A second, orthogonal scope narrowing: not every Morse TS adapter has a\n * module-level monkey-patch entry point the way Python's adapters do.\n * `instrumentAnthropic()` patches `Messages.prototype.create` — a plain\n * mutable property on a class, present regardless of module system — so\n * auto-detect can install it exactly like Python's `install()` functions.\n * `ai` (Vercel AI SDK) CANNOT be silently patched this way: its exports are\n * plain functions (no prototype), and ships pure-ESM, so Node exposes\n * `streamText`/`generateText`/`generateObject` as non-configurable\n * getter-only properties even through the CJS interop `require()` path —\n * reassigning them throws. Confirmed via a bare Node repro during MHQ-482\n * OSS dogfooding (`bizops/dogfood/ai-sdk-preview-rag.md`); see\n * `../vercel-ai/index.ts`'s module doc for the full story. `ai` is a\n * `DETECT_ONLY_TARGETS` entry pointing at `createTracedVercelAI()`. The\n * `openai-agents`, `langgraph`, and `anthropic-agent-sdk` TS adapters are\n * per-instance only (`wrapRunnerWithFullInstrumentation(runner)`, `new\n * MorseCallbackHandler()`, `wrapClaudeAgentSDKWithFullInstrumentation(\n * client)`) — there is no global hook point to patch without the\n * customer's own `Runner` / `ClaudeSDKClient` instance in hand. Auto-detect\n * still DETECTS these (a one-time informational log pointing at the manual\n * wrap call) but cannot silently instrument them. See `DETECT_ONLY_TARGETS`\n * below.\n *\n * Idempotency: each `FULL_INSTALL_TARGETS[...].install()` call delegates to\n * an adapter function that is itself idempotent (checks a sentinel on the\n * target module). Calling `installAdapters()` repeatedly is safe.\n *\n * Opt-out: `MORSE_DISABLE_AUTO_DETECT=1` skips this step entirely.\n * Customers can still call the adapter `wrapX()` / `instrumentX()`\n * functions directly.\n *\n * Implementation note on the `node:module` import: unlike the optional\n * peer-dependency imports elsewhere in this SDK (e.g. `@anthropic-ai/sdk`\n * in `anthropic/index.ts`, dynamic-imported via a `Function`-eval trick so\n * bundlers never try to statically resolve a package the customer may not\n * have installed), `node:module` is a Node CORE builtin — always present in\n * any Node runtime, nothing to dodge at bundle time. It's imported\n * statically here and every call site is still runtime-guarded by a\n * `typeof process !== \"undefined\" && process.versions?.node` check, so\n * this module is a safe no-op outside Node (browser bundles, edge\n * runtimes). A dynamic-`import()`-via-`Function`-eval was tried first but\n * rejected: it throws `ERR_VM_DYNAMIC_IMPORT_CALLBACK_MISSING` under\n * Vitest's VM-sandboxed test execution, making the require/hook mechanics\n * untestable — a static import has no such problem.\n */\n\nimport { createRequire, Module } from \"node:module\";\n\nimport { instrumentAnthropic } from \"../anthropic\";\nimport { isAutoDetectDisabled } from \"./env\";\n\n/* ------------------------------------------------------------------------ */\n/* Target catalogues */\n/* ------------------------------------------------------------------------ */\n\ninterface FullInstallTarget {\n /** Best-effort installer given the resolved module namespace object. */\n install: (mod: unknown) => Promise<unknown>;\n}\n\n/**\n * Packages with a genuine module-level install entry point — auto-detect\n * can silently instrument these without any customer-supplied instance.\n */\nconst FULL_INSTALL_TARGETS: Record<string, FullInstallTarget> = {\n \"@anthropic-ai/sdk\": {\n install: (mod) => instrumentAnthropic({ anthropicModule: mod }),\n },\n};\n\n/**\n * Packages whose Morse adapter only works against a customer-supplied\n * instance (Runner, ClaudeSDKClient, a LangGraph callback handler). These\n * are detected (best-effort, package-presence only) so we can point the\n * customer at the right manual call — see the module doc comment above for\n * why silent auto-install isn't possible for these yet.\n */\nconst DETECT_ONLY_TARGETS: Record<string, string> = {\n \"@openai/agents\":\n \"wrapRunnerWithFullInstrumentation(runner) from '@morsehq-dev/sdk/openai-agents'\",\n \"@langchain/langgraph\":\n \"new MorseCallbackHandler() from '@morsehq-dev/sdk/langgraph', passed via { callbacks: [...] }\",\n \"@anthropic-ai/claude-agent-sdk\":\n \"wrapClaudeAgentSDKWithFullInstrumentation(client) from '@morsehq-dev/sdk/anthropic-agent-sdk'\",\n // MHQ-758: `ai`'s exports can't be patched in place (frozen ESM getters,\n // no prototype to patch) — createTracedVercelAI() returns replacement\n // functions instead. See `../vercel-ai/index.ts`'s module doc.\n ai: \"createTracedVercelAI() from '@morsehq-dev/sdk/vercel-ai' — use its returned streamText/generateText/generateObject in place of ai's own\",\n};\n\n/* ------------------------------------------------------------------------ */\n/* Node `require` access */\n/* ------------------------------------------------------------------------ */\n\ninterface NodeRequireLike {\n (id: string): unknown;\n resolve: (id: string) => string;\n cache: Record<string, unknown>;\n}\n\n/** True when running under real Node (not a browser bundle / edge runtime). */\nfunction isNodeRuntime(): boolean {\n return typeof process !== \"undefined\" && !!process.versions?.node;\n}\n\nfunction getNodeRequire(): NodeRequireLike | null {\n if (!isNodeRuntime()) return null;\n try {\n // `import.meta.url` is standard ESM syntax (not a Node built-in) —\n // safe for bundlers to see statically. When this file is compiled to\n // CJS (tsup's CJS output target), esbuild shims it automatically.\n return createRequire(import.meta.url) as unknown as NodeRequireLike;\n } catch {\n return null;\n }\n}\n\n/* ------------------------------------------------------------------------ */\n/* Module-level state */\n/* ------------------------------------------------------------------------ */\n\nconst firedFullInstall = new Set<string>();\nconst loggedDetectOnly = new Set<string>();\nconst lazyTargets = new Set<string>();\nlet hookInstalled = false;\ntype RequireFn = (this: unknown, id: string) => unknown;\nlet originalRequire: RequireFn | null = null;\n\nfunction logger(message: string): void {\n console.info(message);\n}\n\n/* ------------------------------------------------------------------------ */\n/* Install one full-install target, guarding against a double-fire */\n/* ------------------------------------------------------------------------ */\n\nasync function installFullTarget(name: string, mod: unknown): Promise<void> {\n if (firedFullInstall.has(name)) return;\n firedFullInstall.add(name);\n const target = FULL_INSTALL_TARGETS[name];\n if (!target) return;\n try {\n await target.install(mod);\n } catch {\n // Never let a single adapter's install failure break the others —\n // the adapter's own install() is already absorbErrors-wrapped, this\n // is a defensive extra layer mirroring Python's `_install_one`.\n }\n}\n\nfunction logDetectOnlyIfPresent(nodeRequire: NodeRequireLike, name: string): void {\n if (loggedDetectOnly.has(name)) return;\n try {\n nodeRequire.resolve(name);\n } catch {\n return; // not installed — nothing to log\n }\n loggedDetectOnly.add(name);\n logger(\n `morse: detected \"${name}\" — no zero-config path for this SDK yet. ` +\n `Call ${DETECT_ONLY_TARGETS[name]} to instrument it.`,\n );\n}\n\n/* ------------------------------------------------------------------------ */\n/* Lazy hook — fires installFullTarget() when a target is `require()`d */\n/* for the first time after installAdapters() ran. */\n/* ------------------------------------------------------------------------ */\n\nfunction installLazyHook(): void {\n if (hookInstalled) return;\n originalRequire = Module.prototype.require as RequireFn;\n const original = originalRequire;\n Module.prototype.require = function patchedRequire(this: unknown, id: string): unknown {\n const result = original.call(this, id);\n if (lazyTargets.has(id) && !firedFullInstall.has(id)) {\n // Fire-and-forget — telemetry install must never block or throw back\n // at the customer's require() call.\n void installFullTarget(id, result);\n }\n return result;\n } as typeof Module.prototype.require;\n hookInstalled = true;\n}\n\nfunction uninstallLazyHook(): void {\n if (hookInstalled && originalRequire) {\n Module.prototype.require = originalRequire as typeof Module.prototype.require;\n }\n hookInstalled = false;\n originalRequire = null;\n}\n\n/* ------------------------------------------------------------------------ */\n/* Public entry point */\n/* ------------------------------------------------------------------------ */\n\n/**\n * Scan for already-loaded target packages and install adapters for any\n * that are present. For packages not yet loaded, register a lazy hook so\n * they get instrumented the moment the customer's code requires them.\n *\n * Idempotent and safe to call repeatedly — every `morse.init()` (and the\n * env-based lazy auto-init path) goes through here.\n *\n * Honors `MORSE_DISABLE_AUTO_DETECT=1` and returns immediately. No-ops\n * outside Node (e.g. a browser bundle) since there is no `require` to hook.\n */\nexport async function installAdapters(): Promise<void> {\n if (isAutoDetectDisabled()) return;\n\n const nodeRequire = getNodeRequire();\n if (!nodeRequire) return;\n\n const installPromises: Array<Promise<void>> = [];\n\n for (const name of Object.keys(FULL_INSTALL_TARGETS)) {\n if (firedFullInstall.has(name)) continue;\n let resolvedPath: string | undefined;\n try {\n resolvedPath = nodeRequire.resolve(name);\n } catch {\n continue; // package not installed at all — nothing to detect or hook\n }\n if (resolvedPath in nodeRequire.cache) {\n // Already loaded — install now.\n try {\n const mod = nodeRequire(name);\n installPromises.push(installFullTarget(name, mod));\n } catch {\n // Loading a cached module should never throw, but stay defensive.\n }\n } else {\n // Not loaded yet — register for the lazy require() hook.\n lazyTargets.add(name);\n }\n }\n\n if (lazyTargets.size > 0) {\n installLazyHook();\n }\n\n for (const name of Object.keys(DETECT_ONLY_TARGETS)) {\n logDetectOnlyIfPresent(nodeRequire, name);\n }\n\n await Promise.all(installPromises);\n}\n\n/**\n * Reset all auto-detect state for tests: unpatches `Module.prototype\n * .require`, clears the fired/logged/lazy sets. Not part of the public API.\n * @internal\n */\nexport function _resetForTesting(): void {\n uninstallLazyHook();\n firedFullInstall.clear();\n loggedDetectOnly.clear();\n lazyTargets.clear();\n}\n\n/** @internal test-only accessors */\nexport const _internalsForTesting = {\n FULL_INSTALL_TARGETS,\n DETECT_ONLY_TARGETS,\n get lazyTargets(): ReadonlySet<string> {\n return lazyTargets;\n },\n get hookInstalled(): boolean {\n return hookInstalled;\n },\n};\n","/**\n * `@morsehq-dev/sdk` — TypeScript SDK for Morse observability.\n *\n * V2 module-level singleton API:\n *\n * ```ts\n * import * as morse from \"@morsehq-dev/sdk\";\n *\n * // Three-step zero-setup integration:\n * // 1. Generate an API key in the Morse dashboard.\n * // 2. npm install @morsehq-dev/sdk\n * // 3. Set MORSE_API_KEY in your environment.\n *\n * morse.track({ agentId: \"lead-qualifier\", runData: { success: true } });\n *\n * // Or call init() explicitly to override env-var resolution:\n * morse.init({\n * apiKey: \"mhq_xxx\", // pragma: allowlist secret — placeholder, not a key\n * endpoint: \"https://api.morsehq.dev/api/v1/traces/batch\",\n * flushIntervalSeconds: 2,\n * });\n * ```\n *\n * Non-invasive guarantee: every public function is wrapped with\n * `absorbErrors`. Telemetry never throws back at the caller; internal\n * errors are reported out-of-band to Morse's own diagnostics endpoint.\n *\n * The internal `BatchTransport` and `TraceState` types back the singleton\n * but are NOT part of the public API. Customers should never reach into\n * the `_internal` directory.\n */\n\nimport {\n installAdapters as _installAdapters,\n _resetForTesting as _resetAutoDetectForTesting,\n} from \"./_internal/auto-detect\";\nimport { absorbErrorsAsync, absorbErrorsSync } from \"./_internal/errors\";\nimport {\n DEFAULT_ENDPOINT,\n getApiKey as readApiKeyFromEnv,\n getEndpoint as readEndpointFromEnv,\n getFlushIntervalSeconds,\n getInternalSource as readInternalSourceFromEnv,\n getMaxBatchSize,\n getMaxFieldBytes,\n getMaxQueueSize,\n getSampleRate,\n isDisabled as readIsDisabled,\n isValidInternalSource,\n} from \"./_internal/env\";\nimport { maybeEnableDbCaptureFromEnv } from \"./_internal/db-capture\";\nimport { getEngine as getOtelEngine } from \"./_internal/otel-provider\";\nimport {\n buildRedactionConfig,\n type RedactionConfig,\n type RedactionOptions,\n redactValue,\n} from \"./_internal/redaction\";\nimport {\n BatchTransport,\n SDK_VERSION,\n type TelemetryEvent,\n getQuotaState as _getQuotaState,\n _resetQuotaStateForTesting,\n type QuotaState,\n} from \"./_internal/transport\";\nimport {\n getActiveTraceState as _getActiveTraceState,\n getLastTrace as _getLastTrace,\n runAsync as _runAsync,\n runSync as _runSync,\n sendTrace as _sendTrace,\n setContext as _setContext,\n setRedactionConfig,\n setSource as _setSource,\n setTransport,\n startSpan as _startSpan,\n type RunHandle,\n type RunOptions,\n type SpanHandle,\n type SpanOptions,\n spanAsync as _spanAsync,\n spanSync as _spanSync,\n _resetForTesting as _resetTracingForTesting,\n} from \"./_internal/tracing\";\nimport {\n report,\n setDiagnosticsClientConfig,\n _resetForTesting as _resetDiagnosticsForTesting,\n} from \"./_internal/diagnostics\";\nimport { _setEnsureInitialized as _setLogEnsureInitialized } from \"./log\";\nimport {\n buildTraceEntry,\n generateSpanId,\n generateTraceId,\n nowIso,\n SpanType,\n type SpanData,\n type TraceFields,\n} from \"./_internal/spans\";\n\nexport type { SpanData, SpanType, SpanStatus, ContextSegment } from \"./_internal/spans\";\nexport type { RunHandle, RunOptions, SpanHandle, SpanOptions };\nexport type { QuotaState };\nexport type { RedactionOptions, RedactionConfig } from \"./_internal/redaction\";\nexport {\n extractTraceparent,\n formatTraceparent,\n injectTraceparent,\n injectIntoRequestInit,\n W3C_TRACEPARENT_HEADER,\n} from \"./propagation\";\nexport {\n extractAnthropicSegments,\n instrumentAnthropic,\n isAnthropicWrapped,\n uninstallAnthropic,\n wrapAnthropic,\n MAX_SEGMENT_CONTENT_BYTES,\n} from \"./anthropic\";\nexport type {\n AnthropicClientLike,\n AnthropicContentBlockParam,\n AnthropicMessageCreateParams,\n AnthropicMessageParam,\n AnthropicMessageResponse,\n AnthropicTextBlockParam,\n AnthropicToolParam,\n AnthropicToolResultBlockParam,\n AnthropicToolUseBlockParam,\n AnthropicUsage,\n InstrumentAnthropicOptions,\n} from \"./anthropic\";\nexport { log } from \"./log\";\nexport type { LogOptions, LogSeverity } from \"./log\";\n\nexport const version = SDK_VERSION;\n\n/* ------------------------------------------------------------------------ */\n/* Public types */\n/* ------------------------------------------------------------------------ */\n\n/** Options accepted by `init()`. Mirrors Python's `init(...)` kwargs. */\nexport interface InitOptions {\n /** API key (starts with \"mhq_\"). Required if no `MORSE_API_KEY` env var. */\n apiKey?: string;\n /** Full ingestion URL. Defaults to the production Railway endpoint. */\n endpoint?: string;\n /** Seconds between batch flushes. Default: 2. */\n flushIntervalSeconds?: number;\n /**\n * Client-side PII redaction. Default-on with the canonical eight-pattern\n * catalogue. Set `enabled: false` to opt out (the server-side mandatory\n * floor still applies). Mandatory patterns (`api_key_prefixed`, `jwt`,\n * `credit_card`, `ssn_us`) cannot be added to `disabledPatterns` —\n * `init()` throws on that.\n */\n redaction?: RedactionOptions;\n /**\n * INTERNAL USE ONLY — resource-level source label for Morse's own\n * dogfood emitters. Mirrors the Python SDK's `init(source=...)` kwarg\n * (PR #90). Accepted values: `\"copilot\" | \"investigator\" | \"refagent\"\n * | \"ui-bot\"`. Any other value (including misspellings) is silently\n * dropped — falls back to the `MORSE_INTERNAL_SOURCE` env var.\n * Customers should not set this.\n */\n source?: string;\n}\n\n/** Single agent-run payload accepted by `track()`. */\nexport interface TrackOptions {\n /** User-defined agent name (e.g., \"lead-qualifier\"). */\n agentId: string;\n /** Run-data dict. Shape mirrors backend Run model. */\n runData: Record<string, unknown>;\n}\n\n/** High-level outcome shape accepted by `record()` (V1 ergonomic API). */\nexport interface RunRecord {\n agent: string;\n success?: boolean;\n outcome?: string;\n cost?: number;\n model?: string;\n inputTokens?: number;\n outputTokens?: number;\n totalTokens?: number;\n durationMs?: number;\n errorMessage?: string;\n metadata?: Record<string, unknown>;\n status?: \"completed\" | \"failed\" | \"timed_out\";\n}\n\n/* ------------------------------------------------------------------------ */\n/* Module-level singleton state */\n/* ------------------------------------------------------------------------ */\n\ninterface SingletonState {\n apiKey: string;\n endpoint: string;\n transport: BatchTransport;\n redaction: RedactionConfig;\n}\n\nlet singleton: SingletonState | null = null;\nlet transportFactory: (opts: {\n apiKey: string;\n endpoint: string;\n flushIntervalSeconds: number;\n}) => BatchTransport = (opts) => new BatchTransport(opts);\n\nlet noApiKeyWarningEmitted = false;\nlet lastLoggedEndpoint: string | null = null;\n\nfunction logger(level: \"info\" | \"warn\", message: string): void {\n const out = level === \"warn\" ? console.warn : console.info;\n out.call(console, message);\n}\n\nfunction logDestinationOnce(endpoint: string): void {\n if (endpoint === lastLoggedEndpoint) return;\n lastLoggedEndpoint = endpoint;\n logger(\n \"info\",\n `morse: Morse SDK initialized — sending to ${endpoint} (sdk version ${SDK_VERSION})`,\n );\n}\n\nfunction resolveEndpoint(explicit?: string): string {\n if (explicit && explicit.length > 0) return explicit;\n const fromEnv = readEndpointFromEnv();\n if (fromEnv) return fromEnv;\n return DEFAULT_ENDPOINT;\n}\n\nconst OTLP_TRACES_PATH = \"/api/v1/otlp/v1/traces\";\n\n/**\n * Derive the OTLP ingest URL from the legacy JSON traces batch URL. Keeps\n * host/scheme; replaces the path — mirrors the Python SDK's\n * `client.py::_derive_otlp_endpoint` and this file's own\n * `transport.ts::deriveLogsEndpoint`.\n */\nfunction deriveOtlpEndpoint(tracesEndpoint: string): string {\n try {\n const u = new URL(tracesEndpoint);\n u.pathname = OTLP_TRACES_PATH;\n u.search = \"\";\n u.hash = \"\";\n return u.toString();\n } catch {\n return tracesEndpoint.replace(/\\/api\\/v1\\/.*$/, OTLP_TRACES_PATH);\n }\n}\n\nfunction buildSingleton(opts: InitOptions, redaction: RedactionConfig): SingletonState | null {\n if (readIsDisabled()) {\n return null;\n }\n const apiKey = opts.apiKey ?? readApiKeyFromEnv();\n if (!apiKey) {\n if (!noApiKeyWarningEmitted) {\n logger(\n \"warn\",\n \"morse: not initialized — set MORSE_API_KEY or call morse.init({ apiKey }) (this warning prints once per process; SDK calls are silent no-ops)\",\n );\n noApiKeyWarningEmitted = true;\n }\n return null;\n }\n const endpoint = resolveEndpoint(opts.endpoint);\n const flushIntervalSeconds = opts.flushIntervalSeconds ?? getFlushIntervalSeconds();\n const transport = transportFactory({ apiKey, endpoint, flushIntervalSeconds });\n setTransport(transport);\n setRedactionConfig(redaction);\n // MHQ-927: diagnostics resolves its own target and cannot see this config\n // otherwise — env-only resolution silently dropped every diagnostic for\n // consumers who call init({ apiKey, endpoint }) without env vars.\n setDiagnosticsClientConfig({ apiKey, endpoint });\n // Resolve the internal source label: explicit kwarg wins, then env.\n // Invalid values are silently dropped so a typo never tags customer\n // data as dogfood.\n const explicitSource = isValidInternalSource(opts.source) ? opts.source! : undefined;\n const resolvedSource = explicitSource ?? readInternalSourceFromEnv() ?? null;\n _setSource(resolvedSource);\n logDestinationOnce(endpoint);\n\n // MHQ-482: run()/span()/runTraced()'s real emission pipeline — real OTel\n // spans over OTLP protobuf+gzip. Configured unconditionally (even under\n // MORSE_LEGACY_TRANSPORT=1) so the engine is ready if the flag flips at\n // runtime; the flag only affects which pipeline `tracing.ts::sendTrace()`\n // feeds. Mirrors the Python SDK's `_Client.__init__`.\n try {\n getOtelEngine().configure({\n endpoint: deriveOtlpEndpoint(endpoint),\n apiKey,\n sampleRate: getSampleRate(),\n scheduleDelayMillis: flushIntervalSeconds * 1000,\n maxQueueSize: getMaxQueueSize(),\n maxExportBatchSize: getMaxBatchSize(),\n maxFieldBytes: getMaxFieldBytes(),\n // 10s (not the exporter's un-overridden 30s ceiling): a genuine\n // network blip still gets several retries with backoff; a fully dead\n // endpoint fails within a bounded, shutdown-friendly window instead\n // of the library's full 30s ceiling. Mirrors the Python SDK.\n timeoutMillis: 10_000,\n redactionConfig: redaction,\n });\n } catch (err) {\n report(err, { fingerprint: \"morse.otel_provider.configure\" });\n }\n\n // MHQ-482: zero-config adapter auto-detect (mirrors Python's\n // `auto_detect.install_adapters()` call in `_ensure_initialized` /\n // `_init_impl`). Fire-and-forget — telemetry setup must never block or\n // throw back into the customer's init() / first SDK call. Runs AFTER the\n // OTel engine above is configured so any span an auto-installed adapter\n // emits immediately has a working pipeline to flow through.\n void _installAdapters().catch(() => {\n // installAdapters() already absorbs adapter-level failures; this is a\n // defensive backstop so a totally unexpected rejection never surfaces.\n });\n\n // MHQ-482: DB auto-capture (opt-in — MORSE_CAPTURE_DB / MORSE_CAPTURE_INFRA,\n // mirrors the Python SDK's `infra_capture.py::maybe_enable_from_env`).\n // MUST run after `getOtelEngine().configure()` above — instrumentation\n // registration needs the `NodeTracerProvider` that call just built.\n try {\n maybeEnableDbCaptureFromEnv();\n } catch (err) {\n report(err, { fingerprint: \"morse.db_capture.register\" });\n }\n\n return { apiKey, endpoint, transport, redaction };\n}\n\nfunction ensureInitialized(): SingletonState | null {\n if (readIsDisabled()) return null;\n if (singleton !== null) return singleton;\n // Lazy default-init: defaults are safe (default-on redaction).\n singleton = buildSingleton({}, buildRedactionConfig());\n return singleton;\n}\n\n// Wire the lazy-init hook into log.ts so `log()` participates in the\n// same env-driven auto-init flow as `track()` / `record()`. Discards\n// the return value — log.ts only needs the side-effect of populating\n// the module-level singleton + transport.\n_setLogEnsureInitialized(() => {\n ensureInitialized();\n});\n\n/* ------------------------------------------------------------------------ */\n/* Public API — wrapped at the module surface */\n/* ------------------------------------------------------------------------ */\n\n/**\n * Initialize the Morse SDK singleton. Call once at application\n * startup. After this call, `track()`, `batchTrack()`, `run()`, and\n * `flush()` are wired up to the configured endpoint.\n *\n * `endpoint` is optional — when omitted, the SDK resolves in this order:\n * 1. `MORSE_ENDPOINT` env var (if set)\n * 2. The default Railway production URL.\n *\n * `MORSE_DISABLED=1` overrides everything: `init()` is a no-op.\n *\n * Calling `init()` a second time replaces the singleton — the previous\n * transport is shut down cleanly and a new one is constructed.\n *\n * Validation errors (e.g., disabling a mandatory redaction pattern, an\n * uncompilable extra pattern) are deliberately NOT absorbed — they\n * propagate as `Error`s so the developer sees the misconfiguration at\n * application startup. All other errors raised from internal SDK paths\n * are absorbed via the per-call wrappers downstream.\n */\nexport function init(options: InitOptions = {}): void {\n if (readIsDisabled()) {\n logger(\"info\", \"morse: MORSE_DISABLED=1 — SDK is a no-op\");\n return;\n }\n // Validate redaction options FIRST — must throw before we mutate any\n // singleton state, so a misconfigured init leaves the previous client\n // intact and the spec scenario \"no Client is constructed\" holds.\n const redaction = buildRedactionConfig(options.redaction);\n\n try {\n if (singleton !== null) {\n void singleton.transport.shutdown();\n singleton = null;\n }\n singleton = buildSingleton(options, redaction);\n } catch (err) {\n report(err, { fingerprint: \"morse.init\" });\n }\n}\n\n/**\n * Submit a single agent run to the ingestion endpoint. Non-blocking;\n * returns immediately. Silently no-ops if the SDK isn't initialised.\n */\nexport const track = absorbErrorsSync(\n (options: TrackOptions): void => {\n const state = ensureInitialized();\n if (!state) return;\n const payload = {\n agent_id: options.agentId,\n ...options.runData,\n };\n const redacted = redactValue(payload, state.redaction) as TelemetryEvent;\n state.transport.track(redacted);\n },\n { fingerprint: \"morse.track\" },\n);\n\n/** Submit multiple agent runs in bulk. Silently no-ops if uninitialised. */\nexport const batchTrack = absorbErrorsSync(\n (runs: Array<Record<string, unknown>>): void => {\n const state = ensureInitialized();\n if (!state) return;\n for (const run of runs) {\n const redacted = redactValue(run, state.redaction) as TelemetryEvent;\n state.transport.track(redacted);\n }\n },\n { fingerprint: \"morse.batch_track\" },\n);\n\n/**\n * High-level convenience: record an agent outcome with named fields.\n *\n * Builds a synthetic single-span `agent`-type trace and submits it through\n * the same `traces`-shaped emission path `run()`/`span()` use (MHQ-746) —\n * mirrors Python's `client.py::record()`. The live dev-api backend has no\n * `runs` ingest route; sending through `state.transport.track()` (the\n * shape `track()`/`batchTrack()` still use, matching Python's equally\n * unmigrated `track()`/`batch_track()`) 422s silently. See MHQ-746.\n */\nexport const record = absorbErrorsSync(\n (rec: RunRecord): void => {\n const state = ensureInitialized();\n if (!state) return;\n\n const traceId = generateTraceId();\n const now = nowIso();\n const resolvedStatus = rec.errorMessage ? \"failed\" : (rec.status ?? \"completed\");\n\n const span: SpanData = {\n trace_id: traceId,\n span_id: generateSpanId(),\n type: SpanType.AGENT,\n name: rec.agent,\n started_at: now,\n ended_at: now,\n status: resolvedStatus,\n duration_ms: rec.durationMs,\n model: rec.model,\n input_tokens: rec.inputTokens,\n output_tokens: rec.outputTokens,\n total_tokens: rec.totalTokens,\n cost_usd: rec.cost,\n error_message: rec.errorMessage,\n metadata: rec.metadata,\n };\n\n const traceFields: TraceFields = {\n trace_id: traceId,\n agent: rec.agent,\n status: resolvedStatus,\n started_at: now,\n ended_at: now,\n duration_ms: rec.durationMs,\n error_message: rec.errorMessage,\n success: rec.success,\n outcome: rec.outcome,\n };\n\n const entry = buildTraceEntry(traceFields, [span]);\n const redacted = redactValue(entry, state.redaction) as {\n trace: Record<string, unknown>;\n spans: Record<string, unknown>[];\n };\n _sendTrace(redacted);\n },\n { fingerprint: \"morse.record\" },\n);\n\n/**\n * Open a traced agent run, executing `fn` inside the trace context.\n * Mirrors Python's `morse.run(...)` context manager.\n *\n * Two overloads are supported:\n * - `run(name, fn)` — quick form with default options.\n * - `run({ agentName, incomingTraceparent }, fn)` — full options.\n *\n * Async callers receive a Promise; sync callers receive the value\n * directly. The function's return value is forwarded to the caller.\n */\nexport function run<T>(name: string, fn: (handle: RunHandle) => T): T | undefined;\nexport function run<T>(options: RunOptions, fn: (handle: RunHandle) => T): T | undefined;\nexport function run<T>(\n nameOrOpts: string | RunOptions,\n fn: (handle: RunHandle) => T,\n): T | undefined {\n const opts = typeof nameOrOpts === \"string\" ? { agentName: nameOrOpts } : nameOrOpts;\n // Make sure the SDK is initialised so spans get sent. Failure to init\n // is fine — `_runSync` records to `lastTrace` regardless, useful for tests.\n ensureInitialized();\n // We can't reliably detect async vs sync up front in TypeScript, so we\n // route through `_runSync` and, if the user's `fn` returns a promise,\n // the wrapping trace ends synchronously after the promise is created.\n // For correct async lifecycle, callers should use `runTraced` instead\n // (it awaits the promise inside the `als.run` scope so the trace\n // closes when the promise resolves).\n return _runSync(opts, fn);\n}\n\n/** Async variant of `run` — exported for callers who want explicit typing. */\nexport function runTraced<T>(\n options: RunOptions,\n fn: (handle: RunHandle) => Promise<T>,\n): Promise<T | undefined> {\n ensureInitialized();\n return _runAsync(options, fn);\n}\n\n/**\n * Attach cost-attribution dimensions to the active trace (MHQ-751). Call\n * once per request (e.g. in middleware) to propagate `customerId`,\n * `feature`, `env`, `team`, etc. to all child spans downstream. Values are\n * coerced to strings. No-op outside an active trace — never throws.\n * Mirrors Python's `morse_ai.set_context(**dims)`.\n */\nexport function setContext(dims: Record<string, unknown>): void {\n _setContext(dims);\n}\n\n/** Start a child span under the active trace. Returns null if no trace. */\nexport function startSpan(options: SpanOptions): SpanHandle | null {\n return _startSpan(options);\n}\n\n/** Run `fn` inside a child span. No-op if no trace is active. */\nexport function span<T>(options: SpanOptions, fn: (handle: SpanHandle | null) => T): T {\n return _spanSync(options, fn);\n}\n\n/** Async variant of `span`. */\nexport function spanAsync<T>(\n options: SpanOptions,\n fn: (handle: SpanHandle | null) => Promise<T>,\n): Promise<T> {\n return _spanAsync(options, fn);\n}\n\n/** Block until all queued events have been sent. Silent on uninit / errors. */\nexport const flush = absorbErrorsAsync(\n async (): Promise<void> => {\n if (singleton !== null) {\n await singleton.transport.flush();\n await getOtelEngine().flush();\n }\n },\n { fingerprint: \"morse.flush\" },\n);\n\n/**\n * Latest ingest quota / rate-limit state observed by the SDK, or `null`.\n *\n * TQE-04 (MHQ-676/MHQ-749): when the Morse backend answers a telemetry\n * batch with HTTP 429 — the monthly event limit (`event_limit_exceeded`)\n * or the per-second ingest rate limit (`RATE_LIMIT_INGEST`) — the\n * transport parses the response and stores it. This function exposes\n * that state so host applications can alert on quota exhaustion instead\n * of discovering it from missing telemetry. Mirrors Python's\n * `morse_ai.quota_state()`.\n *\n * Returns `null` when the SDK is uninitialized or no 429 has been\n * observed. The object includes at least `kind` (`\"event_limit\"`,\n * `\"rate_limit\"`, or `\"unknown\"`), `status`, and `receivedAt` (epoch\n * seconds); event-limit states add `currentCount` / `limitCount` /\n * `planId` / `periodStart` / `upgradeUrl`.\n */\nexport const quotaState = absorbErrorsSync(\n (): QuotaState | null => {\n if (singleton === null) return null;\n return _getQuotaState();\n },\n { fingerprint: \"morse.quota_state\" },\n);\n\n/** Flush and stop the background transport. Call on app exit. */\nexport const shutdown = absorbErrorsAsync(\n async (): Promise<void> => {\n if (singleton !== null) {\n await singleton.transport.shutdown();\n await getOtelEngine().flush();\n getOtelEngine().shutdown();\n singleton = null;\n setTransport(null);\n }\n },\n { fingerprint: \"morse.shutdown\" },\n);\n\n/* ------------------------------------------------------------------------ */\n/* Test-only hooks (private) */\n/* ------------------------------------------------------------------------ */\n\n/**\n * Reset the module-level singleton for tests. Customer code must NOT\n * call this — the singleton is meant to live for the process lifetime.\n *\n * @internal\n */\nexport function _resetForTesting(): void {\n if (singleton !== null) {\n void singleton.transport.shutdown();\n singleton = null;\n setTransport(null);\n }\n getOtelEngine().resetForTesting();\n noApiKeyWarningEmitted = false;\n lastLoggedEndpoint = null;\n _setSource(null);\n _resetTracingForTesting();\n _resetDiagnosticsForTesting();\n _resetAutoDetectForTesting();\n _resetQuotaStateForTesting();\n // Reset the transport factory back to the default.\n transportFactory = (opts) => new BatchTransport(opts);\n}\n\n/**\n * Inject an alternate transport factory for tests (e.g., a mock that\n * captures sent payloads instead of opening a fetch).\n *\n * @internal\n */\nexport function _setTransportFactoryForTesting(\n factory: (opts: {\n apiKey: string;\n endpoint: string;\n flushIntervalSeconds: number;\n }) => BatchTransport,\n): void {\n transportFactory = factory;\n}\n\n/**\n * Read the most recently completed trace entry, for test assertions.\n *\n * @internal\n */\nexport function _getLastTraceForTesting(): { trace: unknown; spans: unknown[] } | null {\n return _getLastTrace();\n}\n\n/**\n * Read the active trace state, for test assertions.\n *\n * @internal\n */\nexport function _getActiveTraceStateForTesting(): unknown {\n return _getActiveTraceState();\n}\n","/**\n * DB auto-capture (MHQ-482) — TypeScript SDK parity port of the Python\n * SDK's `infra_capture.py` `db` span coverage.\n *\n * NOT a straight port. Python hand-patches PEP-249 driver methods\n * (`sqlite3.connect`, `psycopg2.connect`) because there's no other way to\n * intercept a C-extension cursor type. Node has no PEP-249 equivalent, and\n * — per the founder's standing decision on this gap — no reason to\n * hand-roll driver patching when OpenTelemetry's own community\n * instrumentation packages already do it, robustly, for the two most\n * common Node SQL drivers:\n *\n * - `pg` -> `@opentelemetry/instrumentation-pg` (verified on\n * npm: real package, current version 0.73.0)\n * - `mysql2` -> `@opentelemetry/instrumentation-mysql2` (verified on\n * npm: real package, current version 0.67.0)\n * - `better-sqlite3` -> NO community package exists (verified: neither\n * `@opentelemetry/instrumentation-better-sqlite3` nor\n * `@opentelemetry/instrumentation-sqlite3` are published,\n * and the OTel JS contrib repo's instrumentation list has\n * no sqlite entry at all). `./db-capture-sqlite.ts` is a\n * small hand-rolled instrumentation following the exact\n * same `InstrumentationNodeModuleDefinition` hook pattern\n * the community packages use, so it degrades identically\n * (silent no-op) when `better-sqlite3` isn't installed.\n *\n * Attribute shape — no translation layer needed\n * ----------------------------------------------\n * Unlike `otel-provider.ts::emitTraceEntry` (which translates Morse's own\n * `SpanData` dicts into `av.*`/`gen_ai.*`-namespaced OTel attributes because\n * THAT data has no OTel-native shape), these instrumentation packages\n * build real OTel spans directly and already emit the current stable OTel\n * semantic-convention DB attributes — `db.system.name`, `db.namespace`,\n * `db.query.text` (confirmed by reading `@opentelemetry/instrumentation-pg`\n * 0.73.0's `utils.js` / `semconv.js`). These are the same key names\n * `./db-capture-sqlite.ts`'s custom sqlite instrumentation uses, and are\n * standard, documented OTel semconv — the backend's generic OTLP ingestion\n * path (out of this gap's scope — owned by `apps/api/`) is the right place\n * for any further server-side mapping, not this SDK. No `spanDictToOtelAttributes`-\n * style translation is added here.\n *\n * Registration, not patching\n * ---------------------------\n * `registerDbInstrumentation()` builds instrumentation instances and hands\n * them to `otel-provider.ts::OtelEngine.registerInstrumentations()`, which\n * wires them to the SAME `NodeTracerProvider` (and therefore the same\n * `BatchSpanProcessor` -> `RedactingSpanExporter` -> `OTLPTraceExporter`\n * pipeline) the rest of the SDK's spans flow through — see that module's\n * docstring. Each instrumentation package internally uses\n * `require-in-the-middle` hooks (`InstrumentationNodeModuleDefinition`), so\n * constructing/registering them is always safe even when the target driver\n * isn't installed in the host app: the hook simply never fires.\n *\n * Correlation with `morse.span()` / `morse.run()`\n * -------------------------------------------------\n * These instrumentations read OTel's GLOBAL `context.active()` to find\n * their parent span. `tracing.ts`'s `runSync`/`runAsync`/`spanSync`/\n * `spanAsync` now set that global active context to a synthetic\n * `SpanContext` carrying the current Morse trace id + span id for the\n * duration of the wrapped callback (see `otel-provider.ts::withOtelSpanContext`)\n * — so a query made inside a `morse.span()` block nests under it via the\n * normal OTel parent/child mechanism, the same way it would in any other\n * OTel-instrumented Node app.\n *\n * Opt-in (`MORSE_CAPTURE_DB` / `MORSE_CAPTURE_INFRA`, mirrors Python's\n * `infra_capture.py::maybe_enable_from_env`) — not default-on while the\n * approach is proven, same posture as the Python SDK.\n */\n\nimport type { Instrumentation } from \"@opentelemetry/instrumentation\";\nimport { PgInstrumentation } from \"@opentelemetry/instrumentation-pg\";\nimport { MySQL2Instrumentation } from \"@opentelemetry/instrumentation-mysql2\";\n\nimport { isDbCaptureEnabled } from \"./env\";\nimport { getEngine } from \"./otel-provider\";\nimport { BetterSqlite3Instrumentation } from \"./db-capture-sqlite\";\n\nlet unregister: (() => void) | null = null;\nlet registeredInstrumentations: Instrumentation[] | null = null;\n\n/**\n * Build one instance of each supported driver's `Instrumentation`. Exposed\n * separately from `registerDbInstrumentation()` so tests can construct them\n * without touching the module-level registration state.\n */\nexport function buildDbInstrumentations(): Instrumentation[] {\n return [\n new PgInstrumentation() as unknown as Instrumentation,\n new MySQL2Instrumentation() as unknown as Instrumentation,\n new BetterSqlite3Instrumentation() as unknown as Instrumentation,\n ];\n}\n\n/**\n * Register DB auto-capture against the engine's `NodeTracerProvider`.\n * Idempotent — calling this again first unregisters the previous set (same\n * \"re-init replaces\" contract `index.ts::init()` uses for the rest of the\n * singleton). No-op (returns `false`) if the OTel engine hasn't been\n * `configure()`-d yet — callers MUST invoke this after\n * `getOtelEngine().configure()` (see `index.ts::buildSingleton`).\n *\n * Never throws — construction/registration errors are swallowed, mirroring\n * the rest of this SDK's non-invasive guarantee (a driver-instrumentation\n * bug must never break the host app's DB calls).\n */\nexport function registerDbInstrumentation(): boolean {\n disableDbCapture();\n try {\n const instrumentations = buildDbInstrumentations();\n const off = getEngine().registerInstrumentations(instrumentations);\n if (off === null) return false;\n unregister = off;\n registeredInstrumentations = instrumentations;\n return true;\n } catch {\n unregister = null;\n registeredInstrumentations = null;\n return false;\n }\n}\n\n/** Unregister DB auto-capture (idempotent). Primarily for tests. */\nexport function disableDbCapture(): void {\n if (unregister !== null) {\n try {\n unregister();\n } catch {\n // Best-effort.\n }\n }\n unregister = null;\n registeredInstrumentations = null;\n}\n\n/** @internal test hook — the currently-registered instrumentation instances, or null. */\nexport function _getRegisteredInstrumentationsForTesting(): Instrumentation[] | null {\n return registeredInstrumentations;\n}\n\n/**\n * Called from `index.ts::buildSingleton()` after `getOtelEngine().configure()`.\n * Enables DB capture per env flags — mirrors Python's\n * `infra_capture.py::maybe_enable_from_env`:\n *\n * - `MORSE_CAPTURE_DB=1` -> DB capture\n * - `MORSE_CAPTURE_INFRA=1` -> DB capture (convenience alias; Python's HTTP\n * half of this flag has no TS-side port yet)\n */\nexport function maybeEnableDbCaptureFromEnv(): void {\n if (isDbCaptureEnabled()) {\n registerDbInstrumentation();\n }\n}\n","/**\n * Custom `better-sqlite3` OTel instrumentation (MHQ-482).\n *\n * There is no `@opentelemetry/instrumentation-better-sqlite3` (or any\n * community equivalent) on npm — verified against the npm registry while\n * building this module: `@opentelemetry/instrumentation-sqlite3` doesn't\n * exist either, and the OTel JS contrib repo's package list has no sqlite\n * entry at all. `better-sqlite3` is a common lightweight/embedded driver\n * (used heavily in tests, scripts, and small services — mirrors the\n * Python SDK's stdlib `sqlite3` coverage in `infra_capture.py`), so rather\n * than drop sqlite coverage entirely, this is a small hand-rolled\n * `InstrumentationBase` subclass following the exact same\n * `InstrumentationNodeModuleDefinition` hook-based patching pattern the\n * community `pg`/`mysql2` packages use (see `./db-capture.ts`) — it only\n * patches when a host app actually `require()`s `better-sqlite3`, and is a\n * transparent no-op otherwise.\n *\n * Span attribute naming mirrors the same stable OTel semantic-convention\n * keys `@opentelemetry/instrumentation-pg` / `-mysql2` emit\n * (`db.system.name`, `db.query.text`, `db.namespace`) — see `./db-capture.ts`'s\n * module docstring for why no translation layer is needed.\n *\n * better-sqlite3 is fully synchronous, so there's no async/callback\n * variant to cover (unlike `pg`/`mysql2`).\n */\n\nimport {\n InstrumentationBase,\n InstrumentationNodeModuleDefinition,\n isWrapped,\n type InstrumentationConfig,\n} from \"@opentelemetry/instrumentation\";\nimport {\n context as otelContext,\n SpanKind,\n SpanStatusCode,\n trace as traceApi,\n} from \"@opentelemetry/api\";\n\nconst SEMCONV_DB_SYSTEM_NAME = \"db.system.name\";\nconst SEMCONV_DB_QUERY_TEXT = \"db.query.text\";\nconst DB_SYSTEM_NAME_SQLITE = \"sqlite\";\n\n// Mirrors the Python SDK's `infra_capture.py::_MAX_STATEMENT_LEN` — a\n// giant IN (...) clause shouldn't bloat the span; truncated with the same\n// marker style `otel-provider.ts::capBytes` uses elsewhere in this SDK.\nconst MAX_STATEMENT_CHARS = 2048;\nconst TRUNCATION_MARKER = \"…[truncated]\";\n\nfunction sqlVerb(sql: unknown): string {\n try {\n const first = String(sql).trim().split(/\\s+/, 1)[0];\n return first ? first.toUpperCase() : \"QUERY\";\n } catch {\n return \"QUERY\";\n }\n}\n\nfunction safeStatement(sql: unknown): string | undefined {\n let text: string;\n try {\n text = String(sql).trim();\n } catch {\n return undefined;\n }\n if (!text) return undefined;\n if (text.length > MAX_STATEMENT_CHARS) {\n return text.slice(0, MAX_STATEMENT_CHARS) + \" \" + TRUNCATION_MARKER;\n }\n return text;\n}\n\n// `Statement`/`Database` instances from better-sqlite3 — kept loosely typed\n// (the package is an optional peer the SDK never imports types from).\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\ntype AnyRecord = Record<string, any>;\n\nconst SYNC_STATEMENT_METHODS = [\"run\", \"get\", \"all\", \"iterate\"] as const;\n\nexport class BetterSqlite3Instrumentation extends InstrumentationBase<InstrumentationConfig> {\n constructor(config: InstrumentationConfig = {}) {\n super(\"@morsehq/instrumentation-better-sqlite3\", \"0.1.0\", config);\n }\n\n protected init(): InstrumentationNodeModuleDefinition[] {\n return [\n new InstrumentationNodeModuleDefinition(\n \"better-sqlite3\",\n [\">=7.0.0 <14\"],\n (moduleExports: AnyRecord) => this._patch(moduleExports),\n (moduleExports: AnyRecord) => this._unpatch(moduleExports),\n ),\n ];\n }\n\n private _withSpan<T>(sql: unknown, fn: () => T): T {\n const span = this.tracer.startSpan(sqlVerb(sql), { kind: SpanKind.CLIENT });\n const stmt = safeStatement(sql);\n span.setAttribute(SEMCONV_DB_SYSTEM_NAME, DB_SYSTEM_NAME_SQLITE);\n if (stmt) span.setAttribute(SEMCONV_DB_QUERY_TEXT, stmt);\n return otelContext.with(traceApi.setSpan(otelContext.active(), span), () => {\n try {\n const result = fn();\n span.end();\n return result;\n } catch (err) {\n span.recordException(err as Error);\n span.setStatus({ code: SpanStatusCode.ERROR, message: (err as Error)?.message });\n span.end();\n throw err;\n }\n });\n }\n\n /** Wrap one already-`prepare()`d statement's sync execution methods. */\n private _wrapStatementInstance(stmt: AnyRecord): AnyRecord {\n const sql = stmt?.source;\n for (const method of SYNC_STATEMENT_METHODS) {\n const original = stmt[method];\n if (typeof original !== \"function\") continue;\n const bound = original.bind(stmt);\n // Own-property override (not a prototype patch) — each `prepare()`\n // call returns a distinct Statement instance, so this never leaks\n // across statements or requires finding/patching a shared class.\n stmt[method] = (...args: unknown[]) => this._withSpan(sql, () => bound(...args));\n }\n return stmt;\n }\n\n private _patch(moduleExports: AnyRecord): AnyRecord {\n const DatabaseCtor = moduleExports as AnyRecord;\n const proto = DatabaseCtor?.prototype;\n if (!proto) return moduleExports;\n\n if (isWrapped(proto.prepare)) this._unwrap(proto, \"prepare\");\n this._wrap(proto, \"prepare\", (original: (...a: unknown[]) => AnyRecord) => {\n const wrapStatement = (stmt: AnyRecord): AnyRecord => this._wrapStatementInstance(stmt);\n return function (this: unknown, ...args: unknown[]): AnyRecord {\n const stmt = original.apply(this, args);\n return wrapStatement(stmt);\n };\n });\n\n if (isWrapped(proto.exec)) this._unwrap(proto, \"exec\");\n this._wrap(proto, \"exec\", (original: (...a: unknown[]) => unknown) => {\n const withSpan = <T>(sql: unknown, fn: () => T): T => this._withSpan(sql, fn);\n return function (this: unknown, ...args: unknown[]): unknown {\n return withSpan(args[0], () => original.apply(this, args));\n };\n });\n\n return moduleExports;\n }\n\n private _unpatch(moduleExports: AnyRecord): void {\n const proto = moduleExports?.prototype;\n if (!proto) return;\n if (isWrapped(proto.prepare)) this._unwrap(proto, \"prepare\");\n if (isWrapped(proto.exec)) this._unwrap(proto, \"exec\");\n }\n}\n","/**\n * Background batched HTTP transport.\n *\n * Mirrors the Python SDK's `transport.py` semantics:\n *\n * - Async batching: 2-second flush interval (configurable), 100-event\n * max batch size (configurable). Whichever fires first triggers a\n * flush.\n * - Network failures are silently dropped with a debug log — never\n * thrown to the caller.\n * - The caller's thread / event loop is never blocked: `track()`\n * enqueues and returns immediately.\n *\n * The transport speaks two payload shapes (matching Python):\n *\n * - V2 trace events: `{ traces: [{ trace, spans }, ...] }`\n * - V1 legacy runs: `{ runs: [{ ... }, ...] }`\n *\n * Wire-format routing checks for a `traces` key on each enqueued event.\n *\n * Browser vs Node:\n * - Both runtimes ship `fetch` (Node 18+ / all evergreens).\n * - In Node we can run a `setInterval` and call it a day.\n * - In the browser the same approach works; we don't currently flush\n * on `pagehide` / `beforeunload` — Phase 6c spec doesn't require it.\n * A future change can add `navigator.sendBeacon` for last-gasp delivery.\n */\n\nimport {\n recordDrop,\n report,\n setLevel,\n REASON_QUEUE_FULL,\n REASON_QUOTA_REJECTED,\n REASON_RETRY_EXHAUSTED,\n REASON_SHUTDOWN_DROP,\n} from \"./diagnostics\";\n\n// Injected at build time by tsup from package.json — see tsup.config.ts.\n// The version is declared in exactly one place (package.json); a copy here\n// would drift the moment a release bumped one and not the other, and the\n// stale value rides out on the User-Agent and on every span's `sdk_version`.\n// `__SDK_VERSION__` is undefined when running straight from source (vitest,\n// ts-node), hence the fallback.\ndeclare const __SDK_VERSION__: string | undefined;\n\nexport const SDK_VERSION = typeof __SDK_VERSION__ === \"string\" ? __SDK_VERSION__ : \"0.0.0-dev\";\n\nexport interface BatchTransportOptions {\n endpoint: string;\n apiKey: string;\n /** Max wait between flushes, in seconds. Default: 2.0. */\n flushIntervalSeconds?: number;\n /** Max events per batch. Default: 100. */\n maxBatchSize?: number;\n /** Max queued events before drop. Default: 10_000. */\n maxQueueSize?: number;\n /** Timeout for the underlying fetch, in ms. Default: 5_000. */\n fetchTimeoutMs?: number;\n /**\n * Pluggable fetch implementation. Defaults to `globalThis.fetch`.\n * Useful for tests.\n */\n fetchImpl?: typeof fetch;\n}\n\n/**\n * Wire shape for a single log record. Mirrors the Python SDK payload at\n * `apps/sdk/python/src/morse/client.py:191-211` and the backend\n * `SimpleLogsIngestController.ingest` contract\n * (`apps/api/apps/logs/controllers.py:66-134`).\n */\nexport interface LogRecordPayload {\n timestamp: string;\n severity: string;\n service_name: string;\n body: string;\n attributes: Record<string, unknown>;\n trace_id: string | null;\n span_id: string | null;\n}\n\nexport type TelemetryEvent =\n | { traces: unknown[] }\n | { logs: LogRecordPayload[] }\n | Record<string, unknown>;\n\n/**\n * Quota / rate-limit state parsed from a 429 batch-POST response.\n *\n * Mirrors Python's `transport.py::BatchTransport._record_quota_state` /\n * `quota_state()` (TQE-04 / MHQ-676) field-for-field, camelCased per this\n * codebase's convention (`received_at` -> `receivedAt`, etc.). Two known\n * body shapes:\n *\n * - `event_limit_exceeded` (traces controllers) — flat body with\n * `current_count` / `limit_count` / `plan_id` / `period_start` /\n * `upgrade_url` / `sample_rate_url`.\n * - `RATE_LIMIT_INGEST` (ingest rate-limit middleware) — nested\n * `{ error: { code, message, details: { limit, plan } } }`.\n *\n * Anything else is recorded as `kind: \"unknown\"` so the state surface\n * still reflects that ingest is throttled even when the body doesn't\n * parse into a known shape.\n */\nexport interface QuotaState {\n kind: \"event_limit\" | \"rate_limit\" | \"unknown\";\n status: number;\n /** Epoch seconds, matching Python's `time.time()`. */\n receivedAt: number;\n message?: string;\n currentCount?: number;\n limitCount?: number;\n planId?: string;\n periodStart?: string;\n upgradeUrl?: string;\n sampleRateUrl?: string;\n quotaLimit?: number;\n quotaRemaining?: number;\n quotaReset?: number;\n retryAfterSeconds?: number;\n}\n\n// `Retry-After` values above this are clamped, mirroring Python's\n// `_RETRY_AFTER_CAP_SECONDS` — a background flush loop must never commit\n// to reporting minutes-long waits from one batch.\nconst RETRY_AFTER_CAP_SECONDS = 30.0;\n\n/**\n * Parse a `Retry-After` header (seconds form only), capped.\n *\n * Mirrors Python's `transport.py::_parse_retry_after`. HTTP-date form\n * isn't worth supporting — Morse's own 429s always use the seconds form.\n * Unparseable / negative values return `null`.\n */\nfunction parseRetryAfter(value: string | null): number | null {\n if (!value) return null;\n const seconds = Number(value);\n if (!Number.isFinite(seconds) || seconds < 0) return null;\n return Math.min(seconds, RETRY_AFTER_CAP_SECONDS);\n}\n\n// Module-level, matching the `lastTrace` test-introspection pattern in\n// `_internal/tracing.ts` — the latest quota/rate-limit state observed on\n// a 429 response, exposed via `quotaState()` / `morse.quotaState()`. Not\n// cleared on a subsequent successful POST (mirrors Python: it persists\n// until overwritten by a newer 429, so a host app can see \"quota was\n// exceeded recently\" even after the queue drains — see\n// `test_429_recovers_when_retry_succeeds` in the Python test suite,\n// which only asserts no drop-warning, never that state was cleared).\nlet quotaState: QuotaState | null = null;\n\n/**\n * Latest quota/rate-limit state observed on a 429, or `null` if none has\n * been observed yet. Returns a shallow copy — callers can't mutate\n * transport-internal state. Mirrors Python's `BatchTransport.quota_state()`.\n *\n * @internal\n */\nexport function getQuotaState(): QuotaState | null {\n return quotaState ? { ...quotaState } : null;\n}\n\n/**\n * Reset the module-level quota state between test files/cases.\n *\n * @internal\n */\nexport function _resetQuotaStateForTesting(): void {\n quotaState = null;\n}\n\nfunction asString(value: unknown): string | undefined {\n return typeof value === \"string\" ? value : undefined;\n}\n\nfunction asNumber(value: unknown): number | undefined {\n return typeof value === \"number\" && Number.isFinite(value) ? value : undefined;\n}\n\nfunction numberFromHeader(raw: string | null): number | undefined {\n if (raw === null) return undefined;\n const n = Number(raw);\n return Number.isFinite(n) ? n : undefined;\n}\n\n/**\n * Parse a 429 response into the module-level quota state. Never throws —\n * defensively parses two known body shapes (see `QuotaState`), falling\n * back to `kind: \"unknown\"` for anything else. Mirrors Python's\n * `_record_quota_state`.\n */\nasync function recordQuotaState(resp: Response): Promise<void> {\n try {\n const state: QuotaState = {\n kind: \"unknown\",\n status: 429,\n receivedAt: Date.now() / 1000,\n };\n\n let data: unknown = null;\n try {\n data = await resp.clone().json();\n } catch {\n data = null;\n }\n\n if (data !== null && typeof data === \"object\") {\n const body = data as Record<string, unknown>;\n const err = body.error;\n if (err === \"event_limit_exceeded\") {\n state.kind = \"event_limit\";\n state.message = asString(body.message);\n state.currentCount = asNumber(body.current_count);\n state.limitCount = asNumber(body.limit_count);\n state.planId = asString(body.plan_id);\n state.periodStart = asString(body.period_start);\n state.upgradeUrl = asString(body.upgrade_url);\n state.sampleRateUrl = asString(body.sample_rate_url);\n } else if (\n err !== null &&\n typeof err === \"object\" &&\n (err as Record<string, unknown>).code === \"RATE_LIMIT_INGEST\"\n ) {\n const errObj = err as Record<string, unknown>;\n const details =\n errObj.details !== null && typeof errObj.details === \"object\"\n ? (errObj.details as Record<string, unknown>)\n : {};\n state.kind = \"rate_limit\";\n state.message = asString(errObj.message);\n state.limitCount = asNumber(details.limit);\n state.planId = asString(details.plan);\n }\n }\n\n // TQE-05 headers, emitted by the server on every ingest response.\n const quotaLimit = numberFromHeader(resp.headers.get(\"X-Morse-Quota-Limit\"));\n if (quotaLimit !== undefined) state.quotaLimit = quotaLimit;\n const quotaRemaining = numberFromHeader(resp.headers.get(\"X-Morse-Quota-Remaining\"));\n if (quotaRemaining !== undefined) state.quotaRemaining = quotaRemaining;\n const quotaReset = numberFromHeader(resp.headers.get(\"X-Morse-Quota-Reset\"));\n if (quotaReset !== undefined) state.quotaReset = quotaReset;\n const retryAfter = parseRetryAfter(resp.headers.get(\"Retry-After\"));\n if (retryAfter !== null) state.retryAfterSeconds = retryAfter;\n\n quotaState = state;\n } catch {\n // Never let state capture break the send path.\n }\n}\n\nexport class BatchTransport {\n private readonly endpoint: string;\n private readonly apiKey: string;\n private readonly flushIntervalSeconds: number;\n private readonly maxBatchSize: number;\n private readonly maxQueueSize: number;\n private readonly fetchTimeoutMs: number;\n private readonly fetchImpl: typeof fetch;\n\n private queue: TelemetryEvent[] = [];\n private timer: ReturnType<typeof setInterval> | null = null;\n private flushing = false;\n private closed = false;\n private inflight: Promise<void> | null = null;\n\n constructor(opts: BatchTransportOptions) {\n this.endpoint = opts.endpoint;\n this.apiKey = opts.apiKey;\n this.flushIntervalSeconds = opts.flushIntervalSeconds ?? 2.0;\n this.maxBatchSize = opts.maxBatchSize ?? 100;\n this.maxQueueSize = opts.maxQueueSize ?? 10_000;\n this.fetchTimeoutMs = opts.fetchTimeoutMs ?? 5_000;\n this.fetchImpl = opts.fetchImpl ?? globalThis.fetch.bind(globalThis);\n\n // setInterval keeps the Node event loop alive. We mark it `unref`\n // when available so a process-exit isn't blocked by a quiet flusher.\n const intervalMs = Math.max(50, Math.round(this.flushIntervalSeconds * 1000));\n this.timer = setInterval(() => {\n void this.tick();\n }, intervalMs);\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const t = this.timer as any;\n if (typeof t?.unref === \"function\") {\n t.unref();\n }\n }\n\n /** Enqueue an event. Non-blocking. Returns false if the queue is full. */\n track(event: TelemetryEvent): boolean {\n if (this.closed) {\n recordDrop(REASON_SHUTDOWN_DROP, \"trace\");\n return false;\n }\n if (this.queue.length >= this.maxQueueSize) {\n // SDKDIAG-09: previously a bare `return false` — sustained telemetry loss\n // was invisible to both us and the customer. Now counted and logged.\n recordDrop(REASON_QUEUE_FULL, \"trace\");\n return false;\n }\n this.queue.push(event);\n if (this.queue.length >= this.maxBatchSize) {\n void this.tick();\n }\n return true;\n }\n\n /** Block until all currently-queued events have been sent. */\n async flush(): Promise<void> {\n // Drain in one-batch chunks until empty, then await the in-flight send.\n while (this.queue.length > 0) {\n await this.tick();\n }\n if (this.inflight) {\n try {\n await this.inflight;\n } catch {\n // Swallow — caller observes nothing.\n }\n }\n }\n\n /** Stop the background timer. After this call, `track()` is a no-op. */\n async shutdown(): Promise<void> {\n if (this.closed) return;\n this.closed = true;\n if (this.timer !== null) {\n clearInterval(this.timer);\n this.timer = null;\n }\n await this.flush();\n }\n\n private async tick(): Promise<void> {\n if (this.flushing) return;\n if (this.queue.length === 0) return;\n this.flushing = true;\n try {\n const batch = this.queue.splice(0, this.maxBatchSize);\n this.inflight = this.sendBatch(batch);\n await this.inflight;\n this.inflight = null;\n } finally {\n this.flushing = false;\n }\n }\n\n private async sendBatch(batch: TelemetryEvent[]): Promise<void> {\n const traceEntries: unknown[] = [];\n const runEntries: Record<string, unknown>[] = [];\n const logEntries: LogRecordPayload[] = [];\n for (const event of batch) {\n if (typeof event === \"object\" && event !== null && \"traces\" in event) {\n const e = event as { traces: unknown[] };\n if (Array.isArray(e.traces)) {\n traceEntries.push(...e.traces);\n }\n } else if (typeof event === \"object\" && event !== null && \"logs\" in event) {\n const e = event as { logs: LogRecordPayload[] };\n if (Array.isArray(e.logs)) {\n logEntries.push(...e.logs);\n }\n } else {\n runEntries.push(event as Record<string, unknown>);\n }\n }\n if (traceEntries.length > 0) {\n await this.post(this.endpoint, { traces: traceEntries });\n }\n if (runEntries.length > 0) {\n await this.post(this.endpoint, { runs: runEntries });\n }\n if (logEntries.length > 0) {\n // Phase 12.5 Tier 1.2 — logs go to a derived `/api/v1/logs/ingest`\n // endpoint on the same host as the traces batch URL. Mirrors the\n // Python SDK's URL derivation in\n // `apps/sdk/python/src/morse/client.py:187-190`.\n await this.post(deriveLogsEndpoint(this.endpoint), { logs: logEntries });\n }\n }\n\n private async post(url: string, payload: Record<string, unknown>): Promise<void> {\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.fetchTimeoutMs);\n try {\n const resp = await this.fetchImpl(url, {\n method: \"POST\",\n headers: {\n Authorization: `Bearer ${this.apiKey}`,\n \"Content-Type\": \"application/json\",\n \"User-Agent\": `morse-typescript/${SDK_VERSION}`,\n },\n body: JSON.stringify(payload),\n signal: controller.signal,\n });\n // SDKDIAG-05: the server pushes the SDK's self-reporting verbosity on a\n // response we are already receiving — no config round-trip.\n setLevel(resp.headers.get(\"X-Morse-Diagnostics\"));\n\n const droppedCount = countPayloadEntries(payload);\n const droppedCategory = categoryOf(payload);\n\n if (resp.status === 429) {\n // TQE-04 (MHQ-676) parity: surface quota/rate-limit state instead\n // of silently dropping telemetry. `resp.clone()` inside so the\n // body-snippet read below still works off the original response.\n await recordQuotaState(resp);\n recordDrop(REASON_QUOTA_REJECTED, droppedCategory, droppedCount);\n }\n if (!resp.ok) {\n // Drain a few hundred chars of the body for diagnostics.\n let bodySnippet = \"\";\n try {\n const text = await resp.text();\n bodySnippet = text.slice(0, 200);\n } catch {\n // ignore\n }\n if (resp.status !== 429) {\n recordDrop(REASON_RETRY_EXHAUSTED, droppedCategory, droppedCount);\n }\n report(new Error(`morse: batch POST returned ${resp.status} ${bodySnippet}`), {\n fingerprint: \"morse.transport.post.non_2xx\",\n extra: {\n endpoint_host: hostnameOf(url),\n sdk_version: SDK_VERSION,\n },\n });\n }\n } catch (err) {\n // Network errors / aborts / timeouts — silent drop, out-of-band report.\n recordDrop(REASON_RETRY_EXHAUSTED, categoryOf(payload), countPayloadEntries(payload));\n report(err, {\n fingerprint: \"morse.transport.post.network\",\n extra: {\n endpoint_host: hostnameOf(url),\n sdk_version: SDK_VERSION,\n },\n });\n } finally {\n clearTimeout(timeoutId);\n }\n }\n}\n\nfunction hostnameOf(url: string): string {\n try {\n return new URL(url).host;\n } catch {\n return \"<invalid>\";\n }\n}\n\n/**\n * Derive the logs ingest URL from the traces batch endpoint. Mirrors the\n * Python SDK helper: replace the path with `/api/v1/logs/ingest` and drop\n * any query/fragment.\n *\n * Exported for tests. Customer code should not call this directly.\n *\n * @internal\n */\nexport function deriveLogsEndpoint(tracesEndpoint: string): string {\n try {\n const u = new URL(tracesEndpoint);\n u.pathname = \"/api/v1/logs/ingest\";\n u.search = \"\";\n u.hash = \"\";\n return u.toString();\n } catch {\n // Fall back to a string replace on the most common shape.\n return tracesEndpoint.replace(/\\/api\\/v1\\/.*$/, \"/api/v1/logs/ingest\");\n }\n}\n\n/** How many telemetry entries a failed POST just cost the customer. */\nfunction countPayloadEntries(payload: Record<string, unknown>): number {\n let total = 0;\n for (const value of Object.values(payload)) {\n if (Array.isArray(value)) total += value.length;\n }\n return total || 1;\n}\n\n/** Which counter category a payload belongs to (SDKDIAG-09). */\nfunction categoryOf(payload: Record<string, unknown>): string {\n if (\"traces\" in payload) return \"trace\";\n if (\"logs\" in payload) return \"log\";\n return \"record\";\n}\n"]}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
4
|
-
require('../chunk-
|
|
5
|
-
require('../chunk-
|
|
3
|
+
var chunkRK3JPX27_cjs = require('../chunk-RK3JPX27.cjs');
|
|
4
|
+
require('../chunk-TGHDV5MC.cjs');
|
|
5
|
+
require('../chunk-E3G3IE6Y.cjs');
|
|
6
6
|
var stream = require('stream');
|
|
7
7
|
|
|
8
8
|
function pinoLevelToSeverity(level) {
|
|
@@ -36,7 +36,7 @@ function forwardPinoRecord(record) {
|
|
|
36
36
|
const msg = typeof record.msg === "string" ? record.msg : "";
|
|
37
37
|
const serviceName = typeof record.name === "string" && record.name.length > 0 ? record.name : void 0;
|
|
38
38
|
const attributes = pickAttributes(record);
|
|
39
|
-
|
|
39
|
+
chunkRK3JPX27_cjs.log(msg, {
|
|
40
40
|
severity,
|
|
41
41
|
attributes,
|
|
42
42
|
...serviceName ? { serviceName } : {}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { log } from '../chunk-
|
|
2
|
-
import '../chunk-
|
|
3
|
-
import '../chunk-
|
|
1
|
+
import { log } from '../chunk-HCEKAVDR.js';
|
|
2
|
+
import '../chunk-UAJO6JM7.js';
|
|
3
|
+
import '../chunk-XZRJXJFA.js';
|
|
4
4
|
import { Writable } from 'stream';
|
|
5
5
|
|
|
6
6
|
function pinoLevelToSeverity(level) {
|