@morsehq-dev/sdk 0.5.0-rc.2 → 0.5.0-rc.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +34 -0
- 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-63ZI6PGP.cjs → chunk-255AHH2W.cjs} +15 -15
- package/dist/browser/{chunk-63ZI6PGP.cjs.map → chunk-255AHH2W.cjs.map} +1 -1
- package/dist/browser/{chunk-T4NHSVXH.cjs → chunk-36QTJJT7.cjs} +12 -12
- package/dist/browser/{chunk-T4NHSVXH.cjs.map → chunk-36QTJJT7.cjs.map} +1 -1
- package/dist/browser/{chunk-A5EYWAOT.cjs → chunk-3H2OJLC2.cjs} +13 -6
- package/dist/browser/chunk-3H2OJLC2.cjs.map +1 -0
- package/dist/browser/{chunk-YMEU6XQQ.cjs → chunk-3STFITZF.cjs} +6 -6
- package/dist/browser/{chunk-YMEU6XQQ.cjs.map → chunk-3STFITZF.cjs.map} +1 -1
- package/dist/{chunk-Y2QHMV6H.cjs → browser/chunk-6J6F5LJI.cjs} +7 -7
- package/dist/browser/{chunk-N3PXJCOE.cjs.map → chunk-6J6F5LJI.cjs.map} +1 -1
- package/dist/{chunk-ZWOSPXS4.js → browser/chunk-E2OVLWAF.js} +3 -3
- package/dist/browser/{chunk-AM6LMQCT.js.map → chunk-E2OVLWAF.js.map} +1 -1
- package/dist/browser/{chunk-L6FWDEGJ.js → chunk-JR6JN7IZ.js} +4 -4
- package/dist/browser/{chunk-L6FWDEGJ.js.map → chunk-JR6JN7IZ.js.map} +1 -1
- package/dist/browser/{chunk-NH54DAJP.js → chunk-KXVSMY6L.js} +3 -3
- package/dist/browser/{chunk-NH54DAJP.js.map → chunk-KXVSMY6L.js.map} +1 -1
- package/dist/browser/{chunk-3MTJGZGX.js → chunk-PIWO5L5N.js} +5 -5
- package/dist/browser/{chunk-3MTJGZGX.js.map → chunk-PIWO5L5N.js.map} +1 -1
- package/dist/browser/{chunk-SOJYLXCR.cjs → chunk-VOZBYSWK.cjs} +5 -5
- package/dist/browser/{chunk-SOJYLXCR.cjs.map → chunk-VOZBYSWK.cjs.map} +1 -1
- package/dist/browser/{chunk-FDE32B3R.js → chunk-VZA2EPY3.js} +4 -4
- package/dist/browser/{chunk-FDE32B3R.js.map → chunk-VZA2EPY3.js.map} +1 -1
- package/dist/browser/{chunk-NRYB5GJT.js → chunk-WIWUEI5Z.js} +3 -3
- package/dist/browser/{chunk-NRYB5GJT.js.map → chunk-WIWUEI5Z.js.map} +1 -1
- package/dist/browser/{chunk-OOGAYEJF.js → chunk-XD4VWCAC.js} +12 -7
- package/dist/browser/chunk-XD4VWCAC.js.map +1 -0
- package/dist/browser/{chunk-YR2FCEWM.cjs → chunk-YD7TO4PD.cjs} +18 -18
- package/dist/browser/{chunk-YR2FCEWM.cjs.map → chunk-YD7TO4PD.cjs.map} +1 -1
- package/dist/browser/index.cjs +91 -89
- package/dist/browser/index.cjs.map +1 -1
- package/dist/browser/index.js +10 -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/{chunk-YJYF4NSA.js → chunk-2O2FFJLK.js} +5 -5
- package/dist/{chunk-YJYF4NSA.js.map → chunk-2O2FFJLK.js.map} +1 -1
- package/dist/{browser/chunk-N3PXJCOE.cjs → chunk-7ZNGY236.cjs} +7 -7
- package/dist/{chunk-Y2QHMV6H.cjs.map → chunk-7ZNGY236.cjs.map} +1 -1
- package/dist/{chunk-FCAPLB7A.js → chunk-BNMTY7PE.js} +4 -4
- package/dist/{chunk-FCAPLB7A.js.map → chunk-BNMTY7PE.js.map} +1 -1
- package/dist/{chunk-3IGQWLWE.js → chunk-ELBY4SJ7.js} +12 -7
- package/dist/chunk-ELBY4SJ7.js.map +1 -0
- package/dist/{chunk-XCOZIFHC.cjs → chunk-HA5RY4N5.cjs} +13 -6
- package/dist/chunk-HA5RY4N5.cjs.map +1 -0
- package/dist/{chunk-VHF4GWJ4.cjs → chunk-HZKXILBF.cjs} +5 -5
- package/dist/{chunk-VHF4GWJ4.cjs.map → chunk-HZKXILBF.cjs.map} +1 -1
- package/dist/{browser/chunk-AM6LMQCT.js → chunk-JFFZBCTP.js} +3 -3
- package/dist/{chunk-ZWOSPXS4.js.map → chunk-JFFZBCTP.js.map} +1 -1
- package/dist/{chunk-SHK2XEPB.js → chunk-MBOISGKD.js} +4 -4
- package/dist/{chunk-SHK2XEPB.js.map → chunk-MBOISGKD.js.map} +1 -1
- package/dist/{chunk-S4WUABAU.js → chunk-Q6NQQ2LO.js} +3 -3
- package/dist/{chunk-S4WUABAU.js.map → chunk-Q6NQQ2LO.js.map} +1 -1
- package/dist/{chunk-6DZNK4VX.cjs → chunk-RDFDPK2X.cjs} +6 -6
- package/dist/{chunk-6DZNK4VX.cjs.map → chunk-RDFDPK2X.cjs.map} +1 -1
- package/dist/{chunk-ZIER4DGK.cjs → chunk-ULWGK6F5.cjs} +12 -12
- package/dist/{chunk-ZIER4DGK.cjs.map → chunk-ULWGK6F5.cjs.map} +1 -1
- package/dist/{chunk-SNGYSP7Z.cjs → chunk-VM3QM22Z.cjs} +18 -18
- package/dist/{chunk-SNGYSP7Z.cjs.map → chunk-VM3QM22Z.cjs.map} +1 -1
- package/dist/{chunk-Z2IYSTRT.cjs → chunk-WLNADB4J.cjs} +15 -15
- package/dist/{chunk-Z2IYSTRT.cjs.map → chunk-WLNADB4J.cjs.map} +1 -1
- package/dist/{chunk-XJUH6PR5.js → chunk-YPP5DDPO.js} +3 -3
- package/dist/{chunk-XJUH6PR5.js.map → chunk-YPP5DDPO.js.map} +1 -1
- package/dist/index.cjs +98 -96
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +11 -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 +14 -13
- 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
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/_internal/auto-detect.browser.ts","../../src/index.ts","../../src/_internal/db-capture.browser.ts","../../src/_internal/transport.ts"],"names":["run","span","setContext","startSpan","spanAsync","quotaState","_resetForTesting"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * Browser replacement for `auto-detect.ts` (MHQ-482 follow-up).\n *\n * `auto-detect.ts` already no-ops at RUNTIME outside Node — its own\n * docstring says so — but it reaches for `node:module`'s `createRequire` /\n * `Module` in a static top-level import, so a bundler still had to resolve\n * `module` for the browser graph. The runtime guard was never the problem;\n * the import was.\n *\n * Nothing here is a behaviour change: zero-config adapter auto-detect works\n * by hooking `require()` to patch LLM SDKs as they load, and a browser has\n * no `require` to hook. See `otel-provider.browser.ts` for the full\n * rationale and the build wiring.\n */\n\n/** No-op: there is no `require` to hook in a browser. */\nexport async function installAdapters(): Promise<void> {}\n\n/** No state to reset in the browser build. */\nexport function _resetForTesting(): void {}\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 * Browser replacement for `db-capture.ts` (MHQ-482 follow-up).\n *\n * `db-capture.ts` statically imports `@opentelemetry/instrumentation-pg`,\n * `-mysql2` and `@opentelemetry/instrumentation` (which reaches for node's\n * `module` via require-in-the-middle). A browser has no pg/mysql2 driver to\n * patch, so the whole module is inert there — but the static imports still\n * dragged those packages, and node `module`, into the browser graph.\n *\n * Swapped in by the esbuild plugin in `tsup.config.ts`; see\n * `otel-provider.browser.ts` for the full rationale. Only the symbols\n * `index.ts` imports need to exist here.\n */\n\n/**\n * No-op: there is no database driver to instrument in a browser.\n *\n * Deliberately silent. `otel-provider.browser.ts::noteBrowserRuntime()`\n * already states that DB capture is Node-only, and it fires on\n * `configure()` — which `index.ts` always calls before this. A second\n * message would be noise, and this function runs even when the customer\n * never asked for DB capture.\n */\nexport function maybeEnableDbCaptureFromEnv(): void {}\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.browser.ts","../../src/index.ts","../../src/_internal/db-capture.browser.ts","../../src/_internal/transport.ts"],"names":["run","span","setContext","startSpan","spanAsync","quotaState","_resetForTesting"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * Browser replacement for `auto-detect.ts` (MHQ-482 follow-up).\n *\n * `auto-detect.ts` already no-ops at RUNTIME outside Node — its own\n * docstring says so — but it reaches for `node:module`'s `createRequire` /\n * `Module` in a static top-level import, so a bundler still had to resolve\n * `module` for the browser graph. The runtime guard was never the problem;\n * the import was.\n *\n * Nothing here is a behaviour change: zero-config adapter auto-detect works\n * by hooking `require()` to patch LLM SDKs as they load, and a browser has\n * no `require` to hook. See `otel-provider.browser.ts` for the full\n * rationale and the build wiring.\n */\n\n/** No-op: there is no `require` to hook in a browser. */\nexport async function installAdapters(): Promise<void> {}\n\n/** No state to reset in the browser build. */\nexport function _resetForTesting(): void {}\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 flushOnce as flushDiagnosticsOnce,\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 // MHQ-927: diagnostics has its OWN buffer and timer, deliberately\n // separate from the transport so a diagnostic storm can never evict\n // customer telemetry. The timer fires every 5s and is `unref()`d so it\n // cannot hold the event loop open — which means a short-lived process\n // (a script, a CLI, a serverless invocation, every driver in the\n // adapter matrix) exits with its buffer unsent. Nothing else drains it,\n // so those diagnostics were simply lost.\n //\n // Drained AFTER the transport and OTel shutdown above: those can\n // themselves report internal errors, and this is the last chance to\n // send them.\n await flushDiagnosticsOnce();\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 * Browser replacement for `db-capture.ts` (MHQ-482 follow-up).\n *\n * `db-capture.ts` statically imports `@opentelemetry/instrumentation-pg`,\n * `-mysql2` and `@opentelemetry/instrumentation` (which reaches for node's\n * `module` via require-in-the-middle). A browser has no pg/mysql2 driver to\n * patch, so the whole module is inert there — but the static imports still\n * dragged those packages, and node `module`, into the browser graph.\n *\n * Swapped in by the esbuild plugin in `tsup.config.ts`; see\n * `otel-provider.browser.ts` for the full rationale. Only the symbols\n * `index.ts` imports need to exist here.\n */\n\n/**\n * No-op: there is no database driver to instrument in a browser.\n *\n * Deliberately silent. `otel-provider.browser.ts::noteBrowserRuntime()`\n * already states that DB capture is Node-only, and it fires on\n * `configure()` — which `index.ts` always calls before this. A second\n * message would be noise, and this function runs even when the customer\n * never asked for DB capture.\n */\nexport function maybeEnableDbCaptureFromEnv(): void {}\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 chunk36QTJJT7_cjs = require('../chunk-36QTJJT7.cjs');
|
|
4
|
+
require('../chunk-3STFITZF.cjs');
|
|
5
|
+
require('../chunk-3H2OJLC2.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
|
+
chunk36QTJJT7_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-JR6JN7IZ.js';
|
|
2
|
+
import '../chunk-WIWUEI5Z.js';
|
|
3
|
+
import '../chunk-XD4VWCAC.js';
|
|
4
4
|
import { Writable } from 'stream';
|
|
5
5
|
|
|
6
6
|
function pinoLevelToSeverity(level) {
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
3
|
+
var chunk3STFITZF_cjs = require('../chunk-3STFITZF.cjs');
|
|
4
4
|
var chunkRBNCTHK3_cjs = require('../chunk-RBNCTHK3.cjs');
|
|
5
|
-
var
|
|
5
|
+
var chunk3H2OJLC2_cjs = require('../chunk-3H2OJLC2.cjs');
|
|
6
6
|
|
|
7
7
|
// src/langchain/callback-handler.ts
|
|
8
|
-
|
|
8
|
+
chunk3H2OJLC2_cjs.init_tracing();
|
|
9
9
|
var ADAPTER = "langchain-js";
|
|
10
10
|
var HANDLER_NAME = "morse_callback_handler";
|
|
11
11
|
var DEFAULT_AGENT_NAME = "langchain-agent";
|
|
@@ -205,7 +205,7 @@ var MorseCallbackHandler = class {
|
|
|
205
205
|
openSpan(runId, name, type, inputData, extraMetadata) {
|
|
206
206
|
if (typeof runId !== "string" || runId.length === 0) return null;
|
|
207
207
|
const metadata = { ...extraMetadata ?? {}, adapter: ADAPTER };
|
|
208
|
-
const handle =
|
|
208
|
+
const handle = chunk3H2OJLC2_cjs.startSpan({ name, type, metadata });
|
|
209
209
|
if (handle === null) return null;
|
|
210
210
|
const wrapped = coerceStateValue(inputData);
|
|
211
211
|
if (wrapped !== void 0) handle.span.input_data = wrapped;
|
|
@@ -302,26 +302,26 @@ var MorseCallbackHandler = class {
|
|
|
302
302
|
return this.spanStack.get(runId);
|
|
303
303
|
}
|
|
304
304
|
};
|
|
305
|
-
var _handleChainStart =
|
|
305
|
+
var _handleChainStart = chunk3STFITZF_cjs.absorbErrorsSync(
|
|
306
306
|
(self, chain, inputs, runId) => {
|
|
307
307
|
const chainName = resolveNameIdFirst(chain, "chain");
|
|
308
308
|
self._openSpan(runId, chainName, "agent", inputs);
|
|
309
309
|
},
|
|
310
310
|
{ fingerprint: "morse.langchain.handleChainStart" }
|
|
311
311
|
);
|
|
312
|
-
var _handleChainEnd =
|
|
312
|
+
var _handleChainEnd = chunk3STFITZF_cjs.absorbErrorsSync(
|
|
313
313
|
(self, outputs, runId) => {
|
|
314
314
|
self._closeSpan(runId, outputs);
|
|
315
315
|
},
|
|
316
316
|
{ fingerprint: "morse.langchain.handleChainEnd" }
|
|
317
317
|
);
|
|
318
|
-
var _handleChainError =
|
|
318
|
+
var _handleChainError = chunk3STFITZF_cjs.absorbErrorsSync(
|
|
319
319
|
(self, err, runId) => {
|
|
320
320
|
self._closeSpan(runId, void 0, err ?? new Error("langchain chain error"));
|
|
321
321
|
},
|
|
322
322
|
{ fingerprint: "morse.langchain.handleChainError" }
|
|
323
323
|
);
|
|
324
|
-
var _handleLLMStart =
|
|
324
|
+
var _handleLLMStart = chunk3STFITZF_cjs.absorbErrorsSync(
|
|
325
325
|
(self, llm, prompts, runId, extraParams) => {
|
|
326
326
|
const llmName = resolveNameIdFirst(llm, "llm");
|
|
327
327
|
const invocationParams = extraParams?.invocation_params;
|
|
@@ -354,7 +354,7 @@ function toolsFromExtra(extra) {
|
|
|
354
354
|
const invocationParams = extra?.invocation_params;
|
|
355
355
|
return invocationParams?.tools;
|
|
356
356
|
}
|
|
357
|
-
var _handleChatModelStart =
|
|
357
|
+
var _handleChatModelStart = chunk3STFITZF_cjs.absorbErrorsSync(
|
|
358
358
|
(self, llm, messages, runId, extraParams) => {
|
|
359
359
|
const llmName = resolveNameIdFirst(llm, "llm");
|
|
360
360
|
const invocationParams = extraParams?.invocation_params;
|
|
@@ -369,7 +369,7 @@ var _handleChatModelStart = chunkYMEU6XQQ_cjs.absorbErrorsSync(
|
|
|
369
369
|
},
|
|
370
370
|
{ fingerprint: "morse.langchain.handleChatModelStart" }
|
|
371
371
|
);
|
|
372
|
-
var _handleLLMEnd =
|
|
372
|
+
var _handleLLMEnd = chunk3STFITZF_cjs.absorbErrorsSync(
|
|
373
373
|
(self, response, runId) => {
|
|
374
374
|
const handle = self._getSpan(runId);
|
|
375
375
|
const outputText = extractOutputText(response);
|
|
@@ -392,32 +392,32 @@ var _handleLLMEnd = chunkYMEU6XQQ_cjs.absorbErrorsSync(
|
|
|
392
392
|
},
|
|
393
393
|
{ fingerprint: "morse.langchain.handleLLMEnd" }
|
|
394
394
|
);
|
|
395
|
-
var _handleLLMError =
|
|
395
|
+
var _handleLLMError = chunk3STFITZF_cjs.absorbErrorsSync(
|
|
396
396
|
(self, err, runId) => {
|
|
397
397
|
self._closeSpan(runId, void 0, err ?? new Error("langchain llm error"));
|
|
398
398
|
},
|
|
399
399
|
{ fingerprint: "morse.langchain.handleLLMError" }
|
|
400
400
|
);
|
|
401
|
-
var _handleToolStart =
|
|
401
|
+
var _handleToolStart = chunk3STFITZF_cjs.absorbErrorsSync(
|
|
402
402
|
(self, tool, input, runId) => {
|
|
403
403
|
const toolName = resolveNameNameFirst(tool, "tool");
|
|
404
404
|
self._openSpan(runId, toolName, "tool", { input });
|
|
405
405
|
},
|
|
406
406
|
{ fingerprint: "morse.langchain.handleToolStart" }
|
|
407
407
|
);
|
|
408
|
-
var _handleToolEnd =
|
|
408
|
+
var _handleToolEnd = chunk3STFITZF_cjs.absorbErrorsSync(
|
|
409
409
|
(self, output, runId) => {
|
|
410
410
|
self._closeSpan(runId, { output: String(output) });
|
|
411
411
|
},
|
|
412
412
|
{ fingerprint: "morse.langchain.handleToolEnd" }
|
|
413
413
|
);
|
|
414
|
-
var _handleToolError =
|
|
414
|
+
var _handleToolError = chunk3STFITZF_cjs.absorbErrorsSync(
|
|
415
415
|
(self, err, runId) => {
|
|
416
416
|
self._closeSpan(runId, void 0, err ?? new Error("langchain tool error"));
|
|
417
417
|
},
|
|
418
418
|
{ fingerprint: "morse.langchain.handleToolError" }
|
|
419
419
|
);
|
|
420
|
-
var _handleRetrieverStart =
|
|
420
|
+
var _handleRetrieverStart = chunk3STFITZF_cjs.absorbErrorsSync(
|
|
421
421
|
(self, retriever, query, runId) => {
|
|
422
422
|
const idPath = retriever?.id;
|
|
423
423
|
const retrieverName = (Array.isArray(idPath) && idPath.length > 0 ? idPath[idPath.length - 1] : void 0) || "retriever";
|
|
@@ -425,7 +425,7 @@ var _handleRetrieverStart = chunkYMEU6XQQ_cjs.absorbErrorsSync(
|
|
|
425
425
|
},
|
|
426
426
|
{ fingerprint: "morse.langchain.handleRetrieverStart" }
|
|
427
427
|
);
|
|
428
|
-
var _handleRetrieverEnd =
|
|
428
|
+
var _handleRetrieverEnd = chunk3STFITZF_cjs.absorbErrorsSync(
|
|
429
429
|
(self, documents, runId) => {
|
|
430
430
|
const docsOut = [];
|
|
431
431
|
for (const doc of documents ?? []) {
|
|
@@ -455,7 +455,7 @@ var _handleRetrieverEnd = chunkYMEU6XQQ_cjs.absorbErrorsSync(
|
|
|
455
455
|
},
|
|
456
456
|
{ fingerprint: "morse.langchain.handleRetrieverEnd" }
|
|
457
457
|
);
|
|
458
|
-
var _handleRetrieverError =
|
|
458
|
+
var _handleRetrieverError = chunk3STFITZF_cjs.absorbErrorsSync(
|
|
459
459
|
(self, err, runId) => {
|
|
460
460
|
self._closeSpan(runId, void 0, err ?? new Error("langchain retriever error"));
|
|
461
461
|
},
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { absorbErrorsSync } from '../chunk-
|
|
1
|
+
import { absorbErrorsSync } from '../chunk-WIWUEI5Z.js';
|
|
2
2
|
import { decomposeOpenAiMessages } from '../chunk-MLDVXMQD.js';
|
|
3
|
-
import { init_tracing, startSpan } from '../chunk-
|
|
3
|
+
import { init_tracing, startSpan } from '../chunk-XD4VWCAC.js';
|
|
4
4
|
|
|
5
5
|
// src/langchain/callback-handler.ts
|
|
6
6
|
init_tracing();
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
4
|
-
var
|
|
5
|
-
var
|
|
6
|
-
var
|
|
3
|
+
var chunkVOZBYSWK_cjs = require('../chunk-VOZBYSWK.cjs');
|
|
4
|
+
var chunk6J6F5LJI_cjs = require('../chunk-6J6F5LJI.cjs');
|
|
5
|
+
var chunk255AHH2W_cjs = require('../chunk-255AHH2W.cjs');
|
|
6
|
+
var chunk3STFITZF_cjs = require('../chunk-3STFITZF.cjs');
|
|
7
7
|
var chunkSWQOPFE4_cjs = require('../chunk-SWQOPFE4.cjs');
|
|
8
8
|
var chunkRBNCTHK3_cjs = require('../chunk-RBNCTHK3.cjs');
|
|
9
|
-
require('../chunk-
|
|
9
|
+
require('../chunk-3H2OJLC2.cjs');
|
|
10
10
|
|
|
11
11
|
// src/langgraph/callback-handler.ts
|
|
12
12
|
var ADAPTER = "langgraph-js";
|
|
@@ -49,24 +49,24 @@ var MorseCallbackHandler = class {
|
|
|
49
49
|
return DEFAULT_AGENT_NAME_FALLBACK;
|
|
50
50
|
}
|
|
51
51
|
};
|
|
52
|
-
var _handleChainStartImpl =
|
|
52
|
+
var _handleChainStartImpl = chunk3STFITZF_cjs.absorbErrorsSync(
|
|
53
53
|
(self, chain, runId, runName) => {
|
|
54
54
|
if (typeof runId !== "string" || runId.length === 0) return;
|
|
55
55
|
if (self._takeSpan(runId)) ;
|
|
56
56
|
const agentName = self._resolveAgentName(chain, runName);
|
|
57
|
-
const handle =
|
|
57
|
+
const handle = chunk255AHH2W_cjs.emitAgentSpan({ adapter: ADAPTER, agentName });
|
|
58
58
|
if (handle) self._setSpan(runId, handle);
|
|
59
59
|
},
|
|
60
60
|
{ fingerprint: "morse.langgraph.handleChainStart" }
|
|
61
61
|
);
|
|
62
|
-
var _handleChainEndImpl =
|
|
62
|
+
var _handleChainEndImpl = chunk3STFITZF_cjs.absorbErrorsSync(
|
|
63
63
|
(self, runId) => {
|
|
64
64
|
const handle = self._takeSpan(runId);
|
|
65
65
|
if (handle) handle.end();
|
|
66
66
|
},
|
|
67
67
|
{ fingerprint: "morse.langgraph.handleChainEnd" }
|
|
68
68
|
);
|
|
69
|
-
var _handleChainErrorImpl =
|
|
69
|
+
var _handleChainErrorImpl = chunk3STFITZF_cjs.absorbErrorsSync(
|
|
70
70
|
(self, err, runId) => {
|
|
71
71
|
const handle = self._takeSpan(runId);
|
|
72
72
|
if (handle) handle.end(err ?? new Error("langgraph chain error"));
|
|
@@ -205,12 +205,12 @@ function createLlmAndToolHandlers(state, options = {}) {
|
|
|
205
205
|
const toolInputOpts = options.toolInputMaxBytes ? { maxBytes: options.toolInputMaxBytes } : void 0;
|
|
206
206
|
const toolOutputOpts = options.toolOutputMaxBytes ? { maxBytes: options.toolOutputMaxBytes } : void 0;
|
|
207
207
|
const _handleLLMStart = (llm, prompts, runId, _parentRunId, extraParams) => {
|
|
208
|
-
|
|
209
|
-
const handle =
|
|
208
|
+
chunkVOZBYSWK_cjs.setActiveFramework(FRAMEWORK);
|
|
209
|
+
const handle = chunk255AHH2W_cjs.emitLlmSpan({
|
|
210
210
|
adapter: ADAPTER2,
|
|
211
211
|
model: llmModelOf(llm, extraParams),
|
|
212
212
|
provider: extractProvider(llm?.id),
|
|
213
|
-
inputData:
|
|
213
|
+
inputData: chunkVOZBYSWK_cjs.capturePrompts(prompts)
|
|
214
214
|
});
|
|
215
215
|
if (handle !== null) {
|
|
216
216
|
state.llmSpans.set(runId, handle);
|
|
@@ -219,13 +219,13 @@ function createLlmAndToolHandlers(state, options = {}) {
|
|
|
219
219
|
const _handleChatModelStart = (llm, messages, runId, _parentRunId, extraParams) => {
|
|
220
220
|
const flatMessages = flattenMessages(messages);
|
|
221
221
|
const contextSegments = chunkRBNCTHK3_cjs.decomposeOpenAiMessages(flatMessages, toolsFromExtra(extraParams));
|
|
222
|
-
|
|
223
|
-
const handle =
|
|
222
|
+
chunkVOZBYSWK_cjs.setActiveFramework(FRAMEWORK);
|
|
223
|
+
const handle = chunk255AHH2W_cjs.emitLlmSpan({
|
|
224
224
|
adapter: ADAPTER2,
|
|
225
225
|
model: llmModelOf(llm, extraParams),
|
|
226
226
|
provider: extractProvider(llm?.id),
|
|
227
227
|
contextSegments: contextSegments.length > 0 ? contextSegments : void 0,
|
|
228
|
-
inputData:
|
|
228
|
+
inputData: chunkVOZBYSWK_cjs.captureLangChainMessages(flatMessages)
|
|
229
229
|
});
|
|
230
230
|
if (handle !== null) {
|
|
231
231
|
state.llmSpans.set(runId, handle);
|
|
@@ -234,7 +234,7 @@ function createLlmAndToolHandlers(state, options = {}) {
|
|
|
234
234
|
const _handleLLMEnd = (output, runId) => {
|
|
235
235
|
popAndEnd(state.llmSpans, runId, void 0, (handle) => {
|
|
236
236
|
applyTokenUsage(handle, output);
|
|
237
|
-
const outputText =
|
|
237
|
+
const outputText = chunkVOZBYSWK_cjs.extractLangChainOutputText(output?.generations);
|
|
238
238
|
if (outputText !== void 0) handle.span.output_data = { content: outputText };
|
|
239
239
|
});
|
|
240
240
|
};
|
|
@@ -242,10 +242,10 @@ function createLlmAndToolHandlers(state, options = {}) {
|
|
|
242
242
|
popAndEnd(state.llmSpans, runId, err);
|
|
243
243
|
};
|
|
244
244
|
const _handleToolStart = (tool, input, runId) => {
|
|
245
|
-
const handle =
|
|
245
|
+
const handle = chunk255AHH2W_cjs.emitToolSpan({
|
|
246
246
|
adapter: ADAPTER2,
|
|
247
247
|
toolName: toolNameOf(tool),
|
|
248
|
-
inputSummary:
|
|
248
|
+
inputSummary: chunk6J6F5LJI_cjs.summarizeToolInput(input, toolInputOpts)
|
|
249
249
|
});
|
|
250
250
|
if (handle !== null) {
|
|
251
251
|
state.toolSpans.set(runId, handle);
|
|
@@ -254,7 +254,7 @@ function createLlmAndToolHandlers(state, options = {}) {
|
|
|
254
254
|
const _handleToolEnd = (output, runId) => {
|
|
255
255
|
popAndEnd(state.toolSpans, runId, void 0, (handle) => {
|
|
256
256
|
const md = handle.span.metadata ??= {};
|
|
257
|
-
md.tool_output_summary =
|
|
257
|
+
md.tool_output_summary = chunk6J6F5LJI_cjs.summarizeToolOutput(output, toolOutputOpts);
|
|
258
258
|
md.success = true;
|
|
259
259
|
});
|
|
260
260
|
};
|
|
@@ -266,15 +266,15 @@ function createLlmAndToolHandlers(state, options = {}) {
|
|
|
266
266
|
};
|
|
267
267
|
const fp = "morse.adapters.langgraph.llm-and-tool";
|
|
268
268
|
return {
|
|
269
|
-
handleLLMStart:
|
|
270
|
-
handleChatModelStart:
|
|
269
|
+
handleLLMStart: chunk3STFITZF_cjs.absorbErrorsSync(_handleLLMStart, { fingerprint: `${fp}.handleLLMStart` }),
|
|
270
|
+
handleChatModelStart: chunk3STFITZF_cjs.absorbErrorsSync(_handleChatModelStart, {
|
|
271
271
|
fingerprint: `${fp}.handleChatModelStart`
|
|
272
272
|
}),
|
|
273
|
-
handleLLMEnd:
|
|
274
|
-
handleLLMError:
|
|
275
|
-
handleToolStart:
|
|
276
|
-
handleToolEnd:
|
|
277
|
-
handleToolError:
|
|
273
|
+
handleLLMEnd: chunk3STFITZF_cjs.absorbErrorsSync(_handleLLMEnd, { fingerprint: `${fp}.handleLLMEnd` }),
|
|
274
|
+
handleLLMError: chunk3STFITZF_cjs.absorbErrorsSync(_handleLLMError, { fingerprint: `${fp}.handleLLMError` }),
|
|
275
|
+
handleToolStart: chunk3STFITZF_cjs.absorbErrorsSync(_handleToolStart, { fingerprint: `${fp}.handleToolStart` }),
|
|
276
|
+
handleToolEnd: chunk3STFITZF_cjs.absorbErrorsSync(_handleToolEnd, { fingerprint: `${fp}.handleToolEnd` }),
|
|
277
|
+
handleToolError: chunk3STFITZF_cjs.absorbErrorsSync(_handleToolError, { fingerprint: `${fp}.handleToolError` })
|
|
278
278
|
};
|
|
279
279
|
}
|
|
280
280
|
|
|
@@ -282,7 +282,7 @@ function createLlmAndToolHandlers(state, options = {}) {
|
|
|
282
282
|
var ADAPTER_FINGERPRINT = "langgraph.streaming";
|
|
283
283
|
function createStreamingHandlers(state, options) {
|
|
284
284
|
const trackStreamingTokens = options?.trackStreamingTokens ?? true;
|
|
285
|
-
const handleLLMNewToken =
|
|
285
|
+
const handleLLMNewToken = chunk3STFITZF_cjs.absorbErrorsSync(
|
|
286
286
|
(_token, _idx, runId) => {
|
|
287
287
|
if (!trackStreamingTokens) return;
|
|
288
288
|
const handle = state.llmSpans.get(runId);
|