@morsehq-dev/sdk 0.4.0-rc.1

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.
Files changed (161) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +294 -0
  3. package/dist/anthropic/index.cjs +39 -0
  4. package/dist/anthropic/index.cjs.map +1 -0
  5. package/dist/anthropic/index.d.cts +213 -0
  6. package/dist/anthropic/index.d.ts +213 -0
  7. package/dist/anthropic/index.js +6 -0
  8. package/dist/anthropic/index.js.map +1 -0
  9. package/dist/anthropic-agent-sdk/index.cjs +744 -0
  10. package/dist/anthropic-agent-sdk/index.cjs.map +1 -0
  11. package/dist/anthropic-agent-sdk/index.d.cts +371 -0
  12. package/dist/anthropic-agent-sdk/index.d.ts +371 -0
  13. package/dist/anthropic-agent-sdk/index.js +735 -0
  14. package/dist/anthropic-agent-sdk/index.js.map +1 -0
  15. package/dist/browser/anthropic/index.cjs +39 -0
  16. package/dist/browser/anthropic/index.cjs.map +1 -0
  17. package/dist/browser/anthropic/index.js +6 -0
  18. package/dist/browser/anthropic/index.js.map +1 -0
  19. package/dist/browser/anthropic-agent-sdk/index.cjs +744 -0
  20. package/dist/browser/anthropic-agent-sdk/index.cjs.map +1 -0
  21. package/dist/browser/anthropic-agent-sdk/index.js +735 -0
  22. package/dist/browser/anthropic-agent-sdk/index.js.map +1 -0
  23. package/dist/browser/chunk-3643DC7K.cjs +365 -0
  24. package/dist/browser/chunk-3643DC7K.cjs.map +1 -0
  25. package/dist/browser/chunk-4FALQMOZ.js +232 -0
  26. package/dist/browser/chunk-4FALQMOZ.js.map +1 -0
  27. package/dist/browser/chunk-5J2QBK75.js +884 -0
  28. package/dist/browser/chunk-5J2QBK75.js.map +1 -0
  29. package/dist/browser/chunk-7MSXWGAH.js +53 -0
  30. package/dist/browser/chunk-7MSXWGAH.js.map +1 -0
  31. package/dist/browser/chunk-A24L5N5N.js +596 -0
  32. package/dist/browser/chunk-A24L5N5N.js.map +1 -0
  33. package/dist/browser/chunk-B7DEUDP6.cjs +177 -0
  34. package/dist/browser/chunk-B7DEUDP6.cjs.map +1 -0
  35. package/dist/browser/chunk-F6CJACNH.cjs +604 -0
  36. package/dist/browser/chunk-F6CJACNH.cjs.map +1 -0
  37. package/dist/browser/chunk-JBOYFQSB.js +412 -0
  38. package/dist/browser/chunk-JBOYFQSB.js.map +1 -0
  39. package/dist/browser/chunk-KRBADE6R.cjs +183 -0
  40. package/dist/browser/chunk-KRBADE6R.cjs.map +1 -0
  41. package/dist/browser/chunk-MCJYZH6W.cjs +415 -0
  42. package/dist/browser/chunk-MCJYZH6W.cjs.map +1 -0
  43. package/dist/browser/chunk-NQG2IAQS.js +178 -0
  44. package/dist/browser/chunk-NQG2IAQS.js.map +1 -0
  45. package/dist/browser/chunk-O4HG3OSK.cjs +929 -0
  46. package/dist/browser/chunk-O4HG3OSK.cjs.map +1 -0
  47. package/dist/browser/chunk-QWRQJO57.js +363 -0
  48. package/dist/browser/chunk-QWRQJO57.js.map +1 -0
  49. package/dist/browser/chunk-SWQOPFE4.cjs +234 -0
  50. package/dist/browser/chunk-SWQOPFE4.cjs.map +1 -0
  51. package/dist/browser/chunk-TYDG747E.js +171 -0
  52. package/dist/browser/chunk-TYDG747E.js.map +1 -0
  53. package/dist/browser/chunk-TZRSDDFP.cjs +56 -0
  54. package/dist/browser/chunk-TZRSDDFP.cjs.map +1 -0
  55. package/dist/browser/index.cjs +587 -0
  56. package/dist/browser/index.cjs.map +1 -0
  57. package/dist/browser/index.js +522 -0
  58. package/dist/browser/index.js.map +1 -0
  59. package/dist/browser/integrations/pino.cjs +89 -0
  60. package/dist/browser/integrations/pino.cjs.map +1 -0
  61. package/dist/browser/integrations/pino.js +86 -0
  62. package/dist/browser/integrations/pino.js.map +1 -0
  63. package/dist/browser/langchain/index.cjs +535 -0
  64. package/dist/browser/langchain/index.cjs.map +1 -0
  65. package/dist/browser/langchain/index.js +528 -0
  66. package/dist/browser/langchain/index.js.map +1 -0
  67. package/dist/browser/langgraph/index.cjs +377 -0
  68. package/dist/browser/langgraph/index.cjs.map +1 -0
  69. package/dist/browser/langgraph/index.js +371 -0
  70. package/dist/browser/langgraph/index.js.map +1 -0
  71. package/dist/browser/openai/index.cjs +125 -0
  72. package/dist/browser/openai/index.cjs.map +1 -0
  73. package/dist/browser/openai/index.js +122 -0
  74. package/dist/browser/openai/index.js.map +1 -0
  75. package/dist/browser/openai-agents/index.cjs +689 -0
  76. package/dist/browser/openai-agents/index.cjs.map +1 -0
  77. package/dist/browser/openai-agents/index.js +678 -0
  78. package/dist/browser/openai-agents/index.js.map +1 -0
  79. package/dist/browser/vercel-ai/index.cjs +233 -0
  80. package/dist/browser/vercel-ai/index.cjs.map +1 -0
  81. package/dist/browser/vercel-ai/index.js +231 -0
  82. package/dist/browser/vercel-ai/index.js.map +1 -0
  83. package/dist/chunk-4R4SHGOK.js +363 -0
  84. package/dist/chunk-4R4SHGOK.js.map +1 -0
  85. package/dist/chunk-7EO7MQBA.cjs +183 -0
  86. package/dist/chunk-7EO7MQBA.cjs.map +1 -0
  87. package/dist/chunk-7YCENA54.cjs +604 -0
  88. package/dist/chunk-7YCENA54.cjs.map +1 -0
  89. package/dist/chunk-CKFOGDUF.js +596 -0
  90. package/dist/chunk-CKFOGDUF.js.map +1 -0
  91. package/dist/chunk-FJUNILZT.cjs +1324 -0
  92. package/dist/chunk-FJUNILZT.cjs.map +1 -0
  93. package/dist/chunk-HDAFUKQ3.js +171 -0
  94. package/dist/chunk-HDAFUKQ3.js.map +1 -0
  95. package/dist/chunk-KBWPNIH4.cjs +234 -0
  96. package/dist/chunk-KBWPNIH4.cjs.map +1 -0
  97. package/dist/chunk-KJEO52QS.cjs +365 -0
  98. package/dist/chunk-KJEO52QS.cjs.map +1 -0
  99. package/dist/chunk-KZBCOZIQ.cjs +177 -0
  100. package/dist/chunk-KZBCOZIQ.cjs.map +1 -0
  101. package/dist/chunk-ME5JALGT.js +53 -0
  102. package/dist/chunk-ME5JALGT.js.map +1 -0
  103. package/dist/chunk-PVHDEPRE.cjs +56 -0
  104. package/dist/chunk-PVHDEPRE.cjs.map +1 -0
  105. package/dist/chunk-RTL23YOQ.js +178 -0
  106. package/dist/chunk-RTL23YOQ.js.map +1 -0
  107. package/dist/chunk-TQWI4UYO.js +1277 -0
  108. package/dist/chunk-TQWI4UYO.js.map +1 -0
  109. package/dist/chunk-VXDBDPDR.cjs +415 -0
  110. package/dist/chunk-VXDBDPDR.cjs.map +1 -0
  111. package/dist/chunk-XTKMUJWI.js +232 -0
  112. package/dist/chunk-XTKMUJWI.js.map +1 -0
  113. package/dist/chunk-ZKUGOWER.js +412 -0
  114. package/dist/chunk-ZKUGOWER.js.map +1 -0
  115. package/dist/index.cjs +843 -0
  116. package/dist/index.cjs.map +1 -0
  117. package/dist/index.d.cts +464 -0
  118. package/dist/index.d.ts +464 -0
  119. package/dist/index.js +778 -0
  120. package/dist/index.js.map +1 -0
  121. package/dist/integrations/pino.cjs +89 -0
  122. package/dist/integrations/pino.cjs.map +1 -0
  123. package/dist/integrations/pino.d.cts +65 -0
  124. package/dist/integrations/pino.d.ts +65 -0
  125. package/dist/integrations/pino.js +86 -0
  126. package/dist/integrations/pino.js.map +1 -0
  127. package/dist/langchain/index.cjs +535 -0
  128. package/dist/langchain/index.cjs.map +1 -0
  129. package/dist/langchain/index.d.cts +265 -0
  130. package/dist/langchain/index.d.ts +265 -0
  131. package/dist/langchain/index.js +528 -0
  132. package/dist/langchain/index.js.map +1 -0
  133. package/dist/langgraph/index.cjs +377 -0
  134. package/dist/langgraph/index.cjs.map +1 -0
  135. package/dist/langgraph/index.d.cts +324 -0
  136. package/dist/langgraph/index.d.ts +324 -0
  137. package/dist/langgraph/index.js +371 -0
  138. package/dist/langgraph/index.js.map +1 -0
  139. package/dist/openai/index.cjs +125 -0
  140. package/dist/openai/index.cjs.map +1 -0
  141. package/dist/openai/index.d.cts +136 -0
  142. package/dist/openai/index.d.ts +136 -0
  143. package/dist/openai/index.js +122 -0
  144. package/dist/openai/index.js.map +1 -0
  145. package/dist/openai-agents/index.cjs +689 -0
  146. package/dist/openai-agents/index.cjs.map +1 -0
  147. package/dist/openai-agents/index.d.cts +502 -0
  148. package/dist/openai-agents/index.d.ts +502 -0
  149. package/dist/openai-agents/index.js +678 -0
  150. package/dist/openai-agents/index.js.map +1 -0
  151. package/dist/spans-DZtMuBvc.d.cts +73 -0
  152. package/dist/spans-DZtMuBvc.d.ts +73 -0
  153. package/dist/tracing-BYAqjT5Q.d.cts +114 -0
  154. package/dist/tracing-rz9cWQ8d.d.ts +114 -0
  155. package/dist/vercel-ai/index.cjs +233 -0
  156. package/dist/vercel-ai/index.cjs.map +1 -0
  157. package/dist/vercel-ai/index.d.cts +93 -0
  158. package/dist/vercel-ai/index.d.ts +93 -0
  159. package/dist/vercel-ai/index.js +231 -0
  160. package/dist/vercel-ai/index.js.map +1 -0
  161. package/package.json +182 -0
@@ -0,0 +1,1277 @@
1
+ import { createHash } from 'crypto';
2
+ import { TraceFlags, trace, ROOT_CONTEXT, SpanKind, SpanStatusCode, context } from '@opentelemetry/api';
3
+ import { ExportResultCode } from '@opentelemetry/core';
4
+ import { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-proto';
5
+ import { CompressionAlgorithm } from '@opentelemetry/otlp-exporter-base';
6
+ import { ParentBasedSampler, TraceIdRatioBasedSampler, BatchSpanProcessor } from '@opentelemetry/sdk-trace-base';
7
+ import { NodeTracerProvider } from '@opentelemetry/sdk-trace-node';
8
+ import { registerInstrumentations } from '@opentelemetry/instrumentation';
9
+ import { AsyncHooksContextManager } from '@opentelemetry/context-async-hooks';
10
+
11
+ var __defProp = Object.defineProperty;
12
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
13
+ var __getOwnPropNames = Object.getOwnPropertyNames;
14
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
15
+ var __esm = (fn, res, err) => function __init() {
16
+ if (err) throw err[0];
17
+ try {
18
+ return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
19
+ } catch (e) {
20
+ throw err = [e], e;
21
+ }
22
+ };
23
+ var __export = (target, all) => {
24
+ for (var name in all)
25
+ __defProp(target, name, { get: all[name], enumerable: true });
26
+ };
27
+ var __copyProps = (to, from, except, desc) => {
28
+ if (from && typeof from === "object" || typeof from === "function") {
29
+ for (let key of __getOwnPropNames(from))
30
+ if (!__hasOwnProp.call(to, key) && key !== except)
31
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
32
+ }
33
+ return to;
34
+ };
35
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
36
+
37
+ // src/_internal/env.ts
38
+ function readEnv(key) {
39
+ if (typeof process !== "undefined" && process.env) {
40
+ const v = process.env[key];
41
+ if (typeof v === "string") return v;
42
+ }
43
+ const denoGlobal = globalThis.Deno;
44
+ if (denoGlobal?.env?.get) {
45
+ try {
46
+ const v = denoGlobal.env.get(key);
47
+ if (typeof v === "string") return v;
48
+ } catch {
49
+ }
50
+ }
51
+ return void 0;
52
+ }
53
+ function truthy(value) {
54
+ if (!value) return false;
55
+ return ["1", "true", "yes", "on"].includes(value.trim().toLowerCase());
56
+ }
57
+ function getApiKey() {
58
+ const raw = readEnv("MORSE_API_KEY");
59
+ if (!raw) return void 0;
60
+ const trimmed = raw.trim();
61
+ return trimmed || void 0;
62
+ }
63
+ function getEndpoint() {
64
+ const raw = readEnv("MORSE_ENDPOINT");
65
+ if (!raw) return void 0;
66
+ const trimmed = raw.trim();
67
+ return trimmed || void 0;
68
+ }
69
+ function getFlushIntervalSeconds(defaultSeconds = 2) {
70
+ const raw = readEnv("MORSE_FLUSH_INTERVAL_SECONDS");
71
+ if (!raw) return defaultSeconds;
72
+ const parsed = Number.parseFloat(raw.trim());
73
+ if (!Number.isFinite(parsed) || parsed <= 0) return defaultSeconds;
74
+ return parsed;
75
+ }
76
+ function isDisabled() {
77
+ return truthy(readEnv("MORSE_DISABLED"));
78
+ }
79
+ function isDebug() {
80
+ return truthy(readEnv("MORSE_SDK_DEBUG"));
81
+ }
82
+ function isTelemetryDisabled() {
83
+ return truthy(readEnv("MORSE_SDK_DISABLE_TELEMETRY"));
84
+ }
85
+ function isAutoDetectDisabled() {
86
+ return truthy(readEnv("MORSE_DISABLE_AUTO_DETECT"));
87
+ }
88
+ function getInternalSource() {
89
+ const raw = readEnv("MORSE_INTERNAL_SOURCE");
90
+ if (!raw) return void 0;
91
+ const trimmed = raw.trim().toLowerCase();
92
+ if (!trimmed) return void 0;
93
+ return VALID_INTERNAL_SOURCES.has(trimmed) ? trimmed : void 0;
94
+ }
95
+ function isValidInternalSource(value) {
96
+ return typeof value === "string" && VALID_INTERNAL_SOURCES.has(value);
97
+ }
98
+ function getSampleRate(defaultRate = 1) {
99
+ const raw = readEnv("MORSE_SAMPLE_RATE");
100
+ if (!raw) return defaultRate;
101
+ const parsed = Number.parseFloat(raw.trim());
102
+ if (!Number.isFinite(parsed) || parsed < 0 || parsed > 1) return defaultRate;
103
+ return parsed;
104
+ }
105
+ function getMaxFieldBytes(defaultBytes = 65536) {
106
+ const raw = readEnv("MORSE_MAX_FIELD_BYTES");
107
+ if (!raw) return defaultBytes;
108
+ const parsed = Number.parseInt(raw.trim(), 10);
109
+ return Number.isFinite(parsed) && parsed > 0 ? parsed : defaultBytes;
110
+ }
111
+ function getMaxQueueSize(defaultSize = 2048) {
112
+ const raw = readEnv("MORSE_MAX_QUEUE_SIZE");
113
+ if (!raw) return defaultSize;
114
+ const parsed = Number.parseInt(raw.trim(), 10);
115
+ return Number.isFinite(parsed) && parsed > 0 ? parsed : defaultSize;
116
+ }
117
+ function getMaxBatchSize(defaultSize = 512) {
118
+ const raw = readEnv("MORSE_MAX_BATCH_SIZE");
119
+ if (!raw) return defaultSize;
120
+ const parsed = Number.parseInt(raw.trim(), 10);
121
+ return Number.isFinite(parsed) && parsed > 0 ? parsed : defaultSize;
122
+ }
123
+ function isLegacyTransport() {
124
+ return truthy(readEnv("MORSE_LEGACY_TRANSPORT"));
125
+ }
126
+ function isDbCaptureEnabled() {
127
+ return truthy(readEnv("MORSE_CAPTURE_DB")) || truthy(readEnv("MORSE_CAPTURE_INFRA"));
128
+ }
129
+ var DEFAULT_ENDPOINT, VALID_INTERNAL_SOURCES;
130
+ var init_env = __esm({
131
+ "src/_internal/env.ts"() {
132
+ DEFAULT_ENDPOINT = "https://api.morsehq.dev/api/v1/traces/batch";
133
+ VALID_INTERNAL_SOURCES = /* @__PURE__ */ new Set(["copilot", "investigator", "refagent", "ui-bot"]);
134
+ }
135
+ });
136
+
137
+ // src/_internal/spans.ts
138
+ function generateTraceId() {
139
+ return randomHex(32);
140
+ }
141
+ function generateSpanId() {
142
+ return randomHex(32);
143
+ }
144
+ function randomHex(chars) {
145
+ const bytes = new Uint8Array(Math.ceil(chars / 2));
146
+ const cryptoObj = globalThis.crypto;
147
+ if (cryptoObj?.getRandomValues) {
148
+ cryptoObj.getRandomValues(bytes);
149
+ } else {
150
+ for (let i = 0; i < bytes.length; i++) {
151
+ bytes[i] = Math.floor(Math.random() * 256);
152
+ }
153
+ }
154
+ let hex = "";
155
+ for (const b of bytes) {
156
+ hex += b.toString(16).padStart(2, "0");
157
+ }
158
+ return hex.slice(0, chars);
159
+ }
160
+ function nowIso() {
161
+ return (/* @__PURE__ */ new Date()).toISOString();
162
+ }
163
+ function spanToWire(span) {
164
+ const out = {};
165
+ for (const [k, v] of Object.entries(span)) {
166
+ if (v !== void 0 && v !== null) {
167
+ out[k] = v;
168
+ }
169
+ }
170
+ return out;
171
+ }
172
+ function buildTraceEntry(fields, spans) {
173
+ return {
174
+ trace: fields,
175
+ spans: spans.map(spanToWire)
176
+ };
177
+ }
178
+ var SpanType;
179
+ var init_spans = __esm({
180
+ "src/_internal/spans.ts"() {
181
+ SpanType = {
182
+ AGENT: "agent",
183
+ LLM: "llm",
184
+ TOOL: "tool",
185
+ HTTP: "http",
186
+ DB: "db",
187
+ CUSTOM: "custom",
188
+ MEMORY: "memory",
189
+ // MHQ-482: matches Python's `SpanType.RETRIEVER` (apps/sdk/python/src/morse_ai/spans.py).
190
+ // @beta — retriever span type is subject to change before SDK v1.0 (see
191
+ // the plain-LangChain adapter's on_retriever_* callbacks in src/langchain/).
192
+ RETRIEVER: "retriever"
193
+ };
194
+ }
195
+ });
196
+
197
+ // src/_internal/redaction.ts
198
+ function buildRedactionConfig(options) {
199
+ const opts = options ?? {};
200
+ const enabled = opts.enabled !== false;
201
+ if (!enabled) {
202
+ return {
203
+ enabled: false,
204
+ enabledPatterns: /* @__PURE__ */ new Set(),
205
+ extraCompiled: []
206
+ };
207
+ }
208
+ const disabled = new Set(opts.disabledPatterns ?? []);
209
+ for (const key of disabled) {
210
+ if (MANDATORY_PATTERNS.has(key)) {
211
+ throw new Error(`redaction pattern '${key}' cannot be disabled (server-side mandatory)`);
212
+ }
213
+ }
214
+ const active = /* @__PURE__ */ new Set();
215
+ for (const key of PATTERN_ORDER) {
216
+ if (DEFAULT_OFF_PATTERNS.has(key)) continue;
217
+ if (disabled.has(key)) continue;
218
+ active.add(key);
219
+ }
220
+ const extraInput = opts.extraPatterns ?? [];
221
+ if (extraInput.length > EXTRA_PATTERN_CAP) {
222
+ throw new Error(
223
+ `too many redaction extra patterns: ${extraInput.length} (max ${EXTRA_PATTERN_CAP})`
224
+ );
225
+ }
226
+ const extraCompiled = [];
227
+ for (const raw of extraInput) {
228
+ if (typeof raw !== "string") {
229
+ throw new Error(`redaction extra pattern must be a string, got ${typeof raw}`);
230
+ }
231
+ if (raw.length > EXTRA_PATTERN_CHAR_CAP) {
232
+ throw new Error(`redaction extra pattern exceeds ${EXTRA_PATTERN_CHAR_CAP} chars`);
233
+ }
234
+ let compiled;
235
+ try {
236
+ compiled = new RegExp(raw, "g");
237
+ } catch (err) {
238
+ const msg = err instanceof Error ? err.message : String(err);
239
+ throw new Error(`redaction extra pattern failed to compile: ${JSON.stringify(raw)} \u2014 ${msg}`);
240
+ }
241
+ extraCompiled.push(compiled);
242
+ }
243
+ return {
244
+ enabled: true,
245
+ enabledPatterns: active,
246
+ extraCompiled
247
+ };
248
+ }
249
+ function luhnValid(s) {
250
+ let sum = 0;
251
+ let alt = false;
252
+ let digits = 0;
253
+ for (let i = s.length - 1; i >= 0; i--) {
254
+ const ch = s.charCodeAt(i);
255
+ if (ch < 48 || ch > 57) continue;
256
+ let n = ch - 48;
257
+ if (alt) {
258
+ n *= 2;
259
+ if (n > 9) n -= 9;
260
+ }
261
+ sum += n;
262
+ alt = !alt;
263
+ digits++;
264
+ }
265
+ if (digits < 13 || digits > 19) return false;
266
+ return sum % 10 === 0;
267
+ }
268
+ function resolveEnabled(config, override) {
269
+ return config.enabledPatterns;
270
+ }
271
+ function redactString(s, config, enabledOverride) {
272
+ if (!config.enabled && enabledOverride === void 0) {
273
+ return s;
274
+ }
275
+ if (s.length === 0) return s;
276
+ const enabled = resolveEnabled(config);
277
+ let out = s;
278
+ for (const key of PATTERN_ORDER) {
279
+ if (!enabled.has(key)) continue;
280
+ const re = PATTERNS[key];
281
+ if (re === void 0) continue;
282
+ re.lastIndex = 0;
283
+ const replacement = `[REDACTED:${SHORT_KEYS[key]}]`;
284
+ if (key === "credit_card") {
285
+ out = out.replace(re, (m) => luhnValid(m) ? replacement : m);
286
+ } else {
287
+ out = out.replace(re, replacement);
288
+ }
289
+ }
290
+ for (const re of config.extraCompiled) {
291
+ re.lastIndex = 0;
292
+ out = out.replace(re, "[REDACTED:custom]");
293
+ }
294
+ return out;
295
+ }
296
+ function redactValue(value, config, depth = 0) {
297
+ if (!config.enabled) return value;
298
+ if (value === null || value === void 0) return value;
299
+ if (typeof value === "string") return redactString(value, config);
300
+ if (typeof value === "number" || typeof value === "boolean") return value;
301
+ if (depth >= MAX_DEPTH) return value;
302
+ if (Array.isArray(value)) {
303
+ return value.map((item) => redactValue(item, config, depth + 1));
304
+ }
305
+ if (typeof value === "object") {
306
+ const proto = Object.getPrototypeOf(value);
307
+ if (proto === Object.prototype || proto === null) {
308
+ const out = {};
309
+ for (const [k, v] of Object.entries(value)) {
310
+ out[k] = redactValue(v, config, depth + 1);
311
+ }
312
+ return out;
313
+ }
314
+ }
315
+ return value;
316
+ }
317
+ var PATTERN_ORDER, MANDATORY_PATTERNS, DEFAULT_OFF_PATTERNS, SHORT_KEYS, PATTERNS, EXTRA_PATTERN_CAP, EXTRA_PATTERN_CHAR_CAP, MAX_DEPTH;
318
+ var init_redaction = __esm({
319
+ "src/_internal/redaction.ts"() {
320
+ PATTERN_ORDER = [
321
+ "api_key_prefixed",
322
+ "jwt",
323
+ "credit_card",
324
+ "email",
325
+ "phone_us",
326
+ "phone_e164",
327
+ "ssn_us",
328
+ "ip_address"
329
+ ];
330
+ MANDATORY_PATTERNS = /* @__PURE__ */ new Set([
331
+ "api_key_prefixed",
332
+ "jwt",
333
+ "credit_card",
334
+ "ssn_us"
335
+ ]);
336
+ DEFAULT_OFF_PATTERNS = /* @__PURE__ */ new Set(["ip_address"]);
337
+ SHORT_KEYS = {
338
+ api_key_prefixed: "api_key",
339
+ jwt: "jwt",
340
+ credit_card: "credit_card",
341
+ email: "email",
342
+ phone_us: "phone",
343
+ phone_e164: "phone",
344
+ ssn_us: "ssn",
345
+ ip_address: "ip"
346
+ };
347
+ PATTERNS = {
348
+ api_key_prefixed: new RegExp(
349
+ "\\b(?:sk-[A-Za-z0-9_-]{20,}|sk_(?:live|test)_[A-Za-z0-9]{20,}|mhq_[A-Za-z0-9]{20,}|av_[A-Za-z0-9]{20,}|ghp_[A-Za-z0-9]{36}|gho_[A-Za-z0-9]{36}|ghu_[A-Za-z0-9]{36}|ghs_[A-Za-z0-9]{36}|ghr_[A-Za-z0-9]{36}|xox[bopsa]-[0-9A-Za-z\\-]{10,}|(?:AKIA|ASIA|AGPA|AIDA|AROA|AIPA|ANPA|ANVA|ASCA)[0-9A-Z]{16})\\b",
350
+ "g"
351
+ ),
352
+ jwt: new RegExp(
353
+ "\\beyJ[A-Za-z0-9_=-]{16,}\\.eyJ[A-Za-z0-9_=-]{16,}\\.[A-Za-z0-9_=-]{16,}\\b",
354
+ "g"
355
+ ),
356
+ credit_card: new RegExp("\\b(?:\\d[ -]?){12,18}\\d\\b", "g"),
357
+ email: new RegExp("\\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,}\\b", "gi"),
358
+ // The leading `(?<!\d)` and trailing `(?!\d)` lookarounds prevent
359
+ // the phone matcher from carving a 10-digit substring out of a longer
360
+ // continuous digit run (e.g., a 16-digit credit-card-shaped number that
361
+ // failed Luhn). Without them, `1234567890123456` would emit a
362
+ // `[REDACTED:phone]` for digits 7-16 even though the whole run was
363
+ // never a real phone number. The canonical Python regex needs the same
364
+ // shim — see redaction.py.
365
+ phone_us: new RegExp(
366
+ "(?<!\\d)(?:\\+?1[ \\-.])?\\(?[2-9]\\d{2}\\)?[ \\-.]?\\d{3}[ \\-.]?\\d{4}(?!\\d)",
367
+ "g"
368
+ ),
369
+ phone_e164: new RegExp("(?<!\\d)\\+(?:[0-9][ \\-.]?){8,14}[0-9](?!\\d)", "g"),
370
+ ssn_us: new RegExp(
371
+ "\\b(?!000|666|9\\d{2})\\d{3}[ \\-.](?!00)\\d{2}[ \\-.](?!0000)\\d{4}\\b",
372
+ "g"
373
+ ),
374
+ ip_address: new RegExp(
375
+ "\\b(?:(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(?:\\.(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}|(?:[A-F0-9]{1,4}:){2,7}[A-F0-9]{1,4})\\b",
376
+ "gi"
377
+ )
378
+ };
379
+ EXTRA_PATTERN_CAP = 10;
380
+ EXTRA_PATTERN_CHAR_CAP = 256;
381
+ MAX_DEPTH = 10;
382
+ }
383
+ });
384
+ function ensureGlobalContextManager() {
385
+ if (contextManagerRegistered) return;
386
+ contextManagerRegistered = true;
387
+ try {
388
+ context.setGlobalContextManager(new AsyncHooksContextManager().enable());
389
+ } catch {
390
+ }
391
+ }
392
+ function withOtelSpanContext(traceIdHex, spanIdHex, fn) {
393
+ const eng = getEngine();
394
+ if (eng.provider === null) return fn();
395
+ ensureGlobalContextManager();
396
+ const sampled = eng.resolveSampled(traceIdHex);
397
+ const spanCtx = {
398
+ traceId: traceIdHex,
399
+ spanId: spanIdHex,
400
+ isRemote: true,
401
+ traceFlags: sampled ? TraceFlags.SAMPLED : TraceFlags.NONE
402
+ };
403
+ const withCtx = trace.setSpanContext(context.active(), spanCtx);
404
+ return context.with(withCtx, fn);
405
+ }
406
+ function capBytes(value, maxBytes) {
407
+ if (maxBytes <= 0) return value;
408
+ const encoded = Buffer.from(value, "utf-8");
409
+ if (encoded.length <= maxBytes) return value;
410
+ const markerBytes = Buffer.byteLength(TRUNCATION_MARKER, "utf-8");
411
+ const budget = Math.max(maxBytes - markerBytes, 0);
412
+ let truncated = encoded.subarray(0, budget);
413
+ const decoder = new TextDecoder("utf-8", { fatal: true });
414
+ while (truncated.length > 0) {
415
+ try {
416
+ return decoder.decode(truncated) + TRUNCATION_MARKER;
417
+ } catch {
418
+ truncated = truncated.subarray(0, truncated.length - 1);
419
+ }
420
+ }
421
+ return TRUNCATION_MARKER;
422
+ }
423
+ function jsonCapped(value, maxBytes) {
424
+ if (value === null || value === void 0) return null;
425
+ if (typeof value === "string") {
426
+ return JSON.stringify(capBytes(value, maxBytes));
427
+ }
428
+ let encoded;
429
+ try {
430
+ encoded = JSON.stringify(value, (_k, v) => typeof v === "bigint" ? String(v) : v) ?? "null";
431
+ } catch {
432
+ encoded = JSON.stringify(String(value));
433
+ }
434
+ return capBytes(encoded, maxBytes);
435
+ }
436
+ function decorrelateTraceIdForSampling(traceIdHex) {
437
+ const traceIdBytes = Buffer.from(traceIdHex.padStart(32, "0").slice(0, 32), "hex");
438
+ return createHash("sha256").update(traceIdBytes).digest();
439
+ }
440
+ function ratioSample(traceIdHex, rate) {
441
+ if (rate <= 0) return false;
442
+ if (rate >= 1) return true;
443
+ const digest = decorrelateTraceIdForSampling(traceIdHex);
444
+ const low64 = digest.subarray(8, 16).readBigUInt64BE();
445
+ const threshold = BigInt(Math.round(rate * Number(MAX_U64)));
446
+ return low64 < threshold;
447
+ }
448
+ function redactAttrValue(value, config) {
449
+ if (typeof value === "string") return redactString(value, config);
450
+ if (Array.isArray(value)) {
451
+ return value.map((v) => typeof v === "string" ? redactString(v, config) : v);
452
+ }
453
+ return value;
454
+ }
455
+ function getEngine() {
456
+ if (engine === null) engine = new OtelEngine();
457
+ return engine;
458
+ }
459
+ function spanDictToOtelAttributes(spanDict, traceDict, resourceDict, opts) {
460
+ const attrs = {};
461
+ const spanType = spanDict.type;
462
+ if (typeof spanType === "string" && spanType) attrs["av.span_type"] = spanType;
463
+ const model = spanDict.model;
464
+ if (model !== void 0 && model !== null) attrs["gen_ai.request.model"] = String(model);
465
+ const tokenFields = [
466
+ ["input_tokens", "gen_ai.usage.input_tokens"],
467
+ ["output_tokens", "gen_ai.usage.output_tokens"],
468
+ ["cached_input_tokens", "gen_ai.usage.cache_read_input_tokens"],
469
+ ["cache_write_tokens", "gen_ai.usage.cache_creation_input_tokens"],
470
+ ["reasoning_tokens", "gen_ai.usage.reasoning_tokens"]
471
+ ];
472
+ for (const [src, otelKey] of tokenFields) {
473
+ const v = spanDict[src];
474
+ if (v !== void 0 && v !== null) {
475
+ const n = Number(v);
476
+ if (Number.isFinite(n)) attrs[otelKey] = Math.trunc(n);
477
+ }
478
+ }
479
+ const costUsd = spanDict.cost_usd;
480
+ if (costUsd !== void 0 && costUsd !== null) {
481
+ attrs["av.cost_usd"] = String(costUsd);
482
+ }
483
+ for (const [src, otelKey] of [
484
+ ["input_data", "av.input_data"],
485
+ ["output_data", "av.output_data"],
486
+ ["context_segments", "av.context_segments"]
487
+ ]) {
488
+ const v = spanDict[src];
489
+ if (v !== void 0 && v !== null) {
490
+ const encoded = jsonCapped(v, opts.maxFieldBytes);
491
+ if (encoded !== null) attrs[otelKey] = encoded;
492
+ }
493
+ }
494
+ const metadata = spanDict.metadata;
495
+ if (metadata && typeof metadata === "object") {
496
+ for (const [key, value] of Object.entries(metadata)) {
497
+ const encoded = jsonCapped(value, opts.maxFieldBytes);
498
+ if (encoded !== null) attrs[`av.metadata.${key}`] = encoded;
499
+ }
500
+ }
501
+ const errorMessage = spanDict.error_message;
502
+ if (opts.isRoot) {
503
+ const threadId = traceDict.thread_id;
504
+ if (threadId !== void 0 && threadId !== null) attrs["av.thread_id"] = String(threadId);
505
+ const userId = traceDict.user_id;
506
+ if (userId !== void 0 && userId !== null) attrs["av.user_id"] = String(userId);
507
+ const userMetadata = traceDict.user_metadata;
508
+ if (userMetadata && typeof userMetadata === "object") {
509
+ const entries = Object.entries(userMetadata);
510
+ if (entries.length > 0) {
511
+ attrs["av.user_metadata"] = JSON.stringify(
512
+ Object.fromEntries(entries.map(([k, v]) => [k, String(v)]))
513
+ );
514
+ }
515
+ }
516
+ const success = traceDict.success;
517
+ if (success !== void 0 && success !== null) attrs["av.outcome.success"] = Boolean(success);
518
+ const outcome = traceDict.outcome;
519
+ if (outcome !== void 0 && outcome !== null) attrs["av.outcome.label"] = String(outcome);
520
+ const framework = resourceDict["morse_ai.framework"];
521
+ if (typeof framework === "string" && framework) attrs["av.framework"] = framework;
522
+ const source = resourceDict["morse_ai.source"];
523
+ if (typeof source === "string" && source) attrs["av.source"] = source;
524
+ }
525
+ if (errorMessage && spanDict.status === "failed") {
526
+ attrs["av.error_message"] = String(errorMessage);
527
+ }
528
+ return attrs;
529
+ }
530
+ function isoToTimeInputMillis(value) {
531
+ if (typeof value !== "string" || !value) return void 0;
532
+ const ms = Date.parse(value);
533
+ return Number.isNaN(ms) ? void 0 : ms;
534
+ }
535
+ function emitTraceEntry(entry) {
536
+ const eng = getEngine();
537
+ const tracer = eng.tracer;
538
+ if (tracer === null) return;
539
+ const traceDict = entry.trace ?? {};
540
+ const spanDicts = entry.spans ?? [];
541
+ const resourceDict = entry.resource ?? {};
542
+ if (spanDicts.length === 0) return;
543
+ const traceIdHexRaw = traceDict.trace_id;
544
+ if (typeof traceIdHexRaw !== "string" || traceIdHexRaw.length === 0) return;
545
+ const traceIdHex = traceIdHexRaw.toLowerCase().padStart(32, "0").slice(0, 32);
546
+ if (!/^[0-9a-f]{32}$/.test(traceIdHex) || /^0+$/.test(traceIdHex)) return;
547
+ const sampled = eng.resolveSampled(traceIdHex);
548
+ const syntheticParentContext = {
549
+ traceId: traceIdHex,
550
+ // Placeholder — only traceId/traceFlags matter here; every real span
551
+ // in the trace gets its own OTel-minted spanId via startSpan().
552
+ spanId: "0000000000000001",
553
+ isRemote: true,
554
+ traceFlags: sampled ? TraceFlags.SAMPLED : TraceFlags.NONE
555
+ };
556
+ const rootParentCtx = trace.setSpanContext(ROOT_CONTEXT, syntheticParentContext);
557
+ let rootSpanId;
558
+ for (const s of spanDicts) {
559
+ if (!s.parent_span_id) {
560
+ rootSpanId = s.span_id;
561
+ break;
562
+ }
563
+ }
564
+ if (rootSpanId === void 0 && spanDicts.length > 0) {
565
+ rootSpanId = spanDicts[0].span_id;
566
+ }
567
+ const ordered = [...spanDicts].sort((a, b) => {
568
+ const aIsRoot = a.span_id === rootSpanId ? 0 : 1;
569
+ const bIsRoot = b.span_id === rootSpanId ? 0 : 1;
570
+ return aIsRoot - bIsRoot;
571
+ });
572
+ const spanCtxById = /* @__PURE__ */ new Map();
573
+ const maxFieldBytes = eng.maxFieldBytes;
574
+ for (const spanDict of ordered) {
575
+ const spanIdHex = typeof spanDict.span_id === "string" ? spanDict.span_id : void 0;
576
+ const parentIdHex = typeof spanDict.parent_span_id === "string" ? spanDict.parent_span_id : void 0;
577
+ let parentCtx = rootParentCtx;
578
+ if (parentIdHex && spanCtxById.has(parentIdHex)) {
579
+ parentCtx = trace.setSpanContext(ROOT_CONTEXT, spanCtxById.get(parentIdHex));
580
+ }
581
+ const attributes = spanDictToOtelAttributes(spanDict, traceDict, resourceDict, {
582
+ isRoot: spanDict.span_id === rootSpanId,
583
+ maxFieldBytes
584
+ });
585
+ const startTime = isoToTimeInputMillis(spanDict.started_at);
586
+ const endTime = isoToTimeInputMillis(spanDict.ended_at) ?? startTime;
587
+ try {
588
+ const otelSpan = tracer.startSpan(
589
+ typeof spanDict.name === "string" && spanDict.name ? spanDict.name : "span",
590
+ {
591
+ kind: SpanKind.INTERNAL,
592
+ attributes,
593
+ startTime
594
+ },
595
+ parentCtx
596
+ );
597
+ if (spanIdHex) {
598
+ spanCtxById.set(spanIdHex, otelSpan.spanContext());
599
+ }
600
+ if (spanDict.status === "failed") {
601
+ otelSpan.setStatus({
602
+ code: SpanStatusCode.ERROR,
603
+ message: String(spanDict.error_message ?? "")
604
+ });
605
+ }
606
+ otelSpan.end(endTime);
607
+ } catch {
608
+ }
609
+ }
610
+ }
611
+ var INSTRUMENTATION_NAME, DEFAULT_MAX_FIELD_BYTES, TRUNCATION_MARKER, contextManagerRegistered, MAX_U64, RedactingSpanExporter, RecordingSpanExporter, ResultCapturingExporter, OtelEngine, engine;
612
+ var init_otel_provider = __esm({
613
+ "src/_internal/otel-provider.ts"() {
614
+ init_redaction();
615
+ INSTRUMENTATION_NAME = "morse-typescript";
616
+ DEFAULT_MAX_FIELD_BYTES = 65536;
617
+ TRUNCATION_MARKER = "\u2026[truncated]";
618
+ contextManagerRegistered = false;
619
+ MAX_U64 = (1n << 64n) - 1n;
620
+ RedactingSpanExporter = class {
621
+ constructor(inner, redactionConfig2) {
622
+ this.inner = inner;
623
+ this.redactionConfig = redactionConfig2;
624
+ }
625
+ inner;
626
+ redactionConfig;
627
+ export(spans, resultCallback) {
628
+ const config = this.redactionConfig;
629
+ if (config && (config.enabled || config.extraCompiled.length > 0)) {
630
+ for (const span of spans) {
631
+ const attrs = span.attributes;
632
+ if (!attrs) continue;
633
+ for (const key of Object.keys(attrs)) {
634
+ attrs[key] = redactAttrValue(attrs[key], config);
635
+ }
636
+ }
637
+ }
638
+ this.inner.export(spans, resultCallback);
639
+ }
640
+ shutdown() {
641
+ return this.inner.shutdown();
642
+ }
643
+ forceFlush() {
644
+ return this.inner.forceFlush ? this.inner.forceFlush() : Promise.resolve();
645
+ }
646
+ };
647
+ RecordingSpanExporter = class {
648
+ spans = [];
649
+ export(spans, resultCallback) {
650
+ this.spans.push(...spans);
651
+ resultCallback({ code: ExportResultCode.SUCCESS });
652
+ }
653
+ shutdown() {
654
+ return Promise.resolve();
655
+ }
656
+ forceFlush() {
657
+ return Promise.resolve();
658
+ }
659
+ clear() {
660
+ this.spans = [];
661
+ }
662
+ };
663
+ ResultCapturingExporter = class {
664
+ constructor(inner, sink) {
665
+ this.inner = inner;
666
+ this.sink = sink;
667
+ }
668
+ inner;
669
+ sink;
670
+ export(spans, resultCallback) {
671
+ this.inner.export(spans, (result) => {
672
+ this.sink(result);
673
+ resultCallback(result);
674
+ });
675
+ }
676
+ shutdown() {
677
+ return this.inner.shutdown();
678
+ }
679
+ forceFlush() {
680
+ return this.inner.forceFlush ? this.inner.forceFlush() : Promise.resolve();
681
+ }
682
+ };
683
+ OtelEngine = class {
684
+ provider = null;
685
+ tracer = null;
686
+ sampleRate = 1;
687
+ recorder = null;
688
+ maxFieldBytes = DEFAULT_MAX_FIELD_BYTES;
689
+ exitHookRegistered = false;
690
+ /**
691
+ * (Re)build the provider. Mirrors Python's `_Client.__init__` semantics:
692
+ * calling this again (e.g. a second `init()`) tears down the previous
693
+ * provider first (fire-and-forget — Node has no synchronous blocking
694
+ * shutdown equivalent to Python's `atexit`).
695
+ */
696
+ configure(opts) {
697
+ if (this.provider !== null) {
698
+ const prior = this.provider;
699
+ void prior.shutdown().catch(() => {
700
+ });
701
+ }
702
+ this.maxFieldBytes = opts.maxFieldBytes;
703
+ this.sampleRate = Math.min(1, Math.max(0, opts.sampleRate));
704
+ const sampler = new ParentBasedSampler({
705
+ root: new TraceIdRatioBasedSampler(this.sampleRate)
706
+ });
707
+ const otlpExporter = new OTLPTraceExporter({
708
+ url: opts.endpoint,
709
+ headers: { Authorization: `Bearer ${opts.apiKey}` },
710
+ compression: CompressionAlgorithm.GZIP,
711
+ timeoutMillis: opts.timeoutMillis
712
+ });
713
+ let exporter = new RedactingSpanExporter(otlpExporter, opts.redactionConfig);
714
+ if (opts.resultSink) {
715
+ exporter = new ResultCapturingExporter(exporter, opts.resultSink);
716
+ }
717
+ this.recorder = opts.captureForTests ? new RecordingSpanExporter() : null;
718
+ const spanProcessors = [
719
+ new BatchSpanProcessor(exporter, {
720
+ maxQueueSize: opts.maxQueueSize,
721
+ scheduledDelayMillis: opts.scheduleDelayMillis,
722
+ maxExportBatchSize: opts.maxExportBatchSize
723
+ })
724
+ ];
725
+ if (this.recorder !== null) {
726
+ spanProcessors.push(new BatchSpanProcessor(this.recorder));
727
+ }
728
+ this.provider = new NodeTracerProvider({ sampler, spanProcessors });
729
+ this.tracer = this.provider.getTracer(INSTRUMENTATION_NAME);
730
+ if (!this.exitHookRegistered) {
731
+ process.once("beforeExit", () => {
732
+ this.shutdown();
733
+ });
734
+ this.exitHookRegistered = true;
735
+ }
736
+ }
737
+ shutdown() {
738
+ if (this.provider !== null) {
739
+ const provider = this.provider;
740
+ void provider.shutdown().catch(() => {
741
+ });
742
+ this.provider = null;
743
+ this.tracer = null;
744
+ }
745
+ }
746
+ /**
747
+ * Test-only fast reset: drop the provider reference WITHOUT blocking on
748
+ * `shutdown()`. Mirrors Python's `reset_for_testing` — the OTLP
749
+ * exporter's retry-with-backoff behavior against an unreachable test
750
+ * endpoint would otherwise make every test file's teardown slow. The
751
+ * queued background work is not awaited; it either finishes or is
752
+ * abandoned with the process, same trade-off as Python's daemon worker
753
+ * thread.
754
+ */
755
+ resetForTesting() {
756
+ this.provider = null;
757
+ this.tracer = null;
758
+ this.recorder = null;
759
+ }
760
+ /** Block until in-flight exports finish (or the timeout elapses). */
761
+ async flush() {
762
+ const provider = this.provider;
763
+ if (provider !== null) {
764
+ try {
765
+ await provider.forceFlush();
766
+ } catch {
767
+ }
768
+ }
769
+ }
770
+ /**
771
+ * Run the deterministic ratio sampler directly for a trace id with no
772
+ * real parent. See `ratioSample` for the decorrelation rationale — feeding
773
+ * a raw uuid4 trace id straight to a ratio sampler produces a hard
774
+ * 0%/100% step function because of uuid4's fixed variant bits.
775
+ */
776
+ resolveSampled(traceIdHex) {
777
+ return ratioSample(traceIdHex, this.sampleRate);
778
+ }
779
+ /**
780
+ * Register OTel `Instrumentation` instances (e.g. the community DB-driver
781
+ * auto-instrumentation packages, see `./db-capture.ts`, MHQ-482) against
782
+ * THIS engine's `NodeTracerProvider` — so spans they emit flow through
783
+ * the same `BatchSpanProcessor` -> `RedactingSpanExporter` ->
784
+ * `OTLPTraceExporter` pipeline `configure()` built, landing in the same
785
+ * OTLP stream (and, when nested inside an active OTel context, the same
786
+ * trace) as the rest of the SDK's spans.
787
+ *
788
+ * No-op (silently, returns `null`) if `configure()` hasn't run yet —
789
+ * mirrors `emitTraceEntry`'s "no transport configured -> silent"
790
+ * contract. Callers (`index.ts::buildSingleton`) must call this AFTER
791
+ * `configure()`.
792
+ */
793
+ registerInstrumentations(instrumentations) {
794
+ if (this.provider === null) return null;
795
+ return registerInstrumentations({
796
+ tracerProvider: this.provider,
797
+ instrumentations
798
+ });
799
+ }
800
+ };
801
+ engine = null;
802
+ }
803
+ });
804
+
805
+ // src/_internal/tracing.ts
806
+ function tryLoadAls() {
807
+ if (alsLoaded) return als;
808
+ alsLoaded = true;
809
+ if (typeof process === "undefined" || !process.versions?.node) {
810
+ als = null;
811
+ return als;
812
+ }
813
+ try {
814
+ const dynamicRequire = Function("m", "return require(m)");
815
+ const mod = dynamicRequire("node:async_hooks");
816
+ if (mod?.AsyncLocalStorage) {
817
+ als = new mod.AsyncLocalStorage();
818
+ return als;
819
+ }
820
+ } catch {
821
+ }
822
+ als = null;
823
+ return als;
824
+ }
825
+ function getActiveTraceState() {
826
+ const store = tryLoadAls();
827
+ if (store) {
828
+ return store.getStore() ?? null;
829
+ }
830
+ return browserState;
831
+ }
832
+ function setActiveTraceState(state) {
833
+ const previous = browserState;
834
+ browserState = state;
835
+ return () => {
836
+ browserState = previous;
837
+ };
838
+ }
839
+ function setTransport(t) {
840
+ transport = t;
841
+ }
842
+ function getTransport() {
843
+ return transport;
844
+ }
845
+ function setRedactionConfig(config) {
846
+ redactionConfig = config;
847
+ }
848
+ function getRedactionConfig() {
849
+ return redactionConfig;
850
+ }
851
+ function setSource(value) {
852
+ _source = value && value.length > 0 ? value : null;
853
+ }
854
+ function getLastTrace() {
855
+ return lastTrace;
856
+ }
857
+ function nowMonotonic() {
858
+ if (typeof performance !== "undefined" && typeof performance.now === "function") {
859
+ return performance.now();
860
+ }
861
+ return Date.now();
862
+ }
863
+ function elapsedMs(startMonotonic) {
864
+ return Math.max(0, Math.round(nowMonotonic() - startMonotonic));
865
+ }
866
+ function finalizeSpan(span, startMono, status = "completed", errorMessage) {
867
+ span.ended_at = nowIso();
868
+ span.duration_ms = elapsedMs(startMono);
869
+ span.status = status;
870
+ if (errorMessage !== void 0) {
871
+ span.error_message = errorMessage;
872
+ }
873
+ }
874
+ function redactSpanDict(raw, config) {
875
+ if (!config.enabled) return raw;
876
+ const out = {};
877
+ for (const [k, v] of Object.entries(raw)) {
878
+ if (SPAN_REDACTABLE_FIELDS.has(k)) {
879
+ out[k] = redactValue(v, config);
880
+ } else {
881
+ out[k] = v;
882
+ }
883
+ }
884
+ return out;
885
+ }
886
+ function redactTraceDict(raw, config) {
887
+ if (!config.enabled) return raw;
888
+ const out = {};
889
+ for (const [k, v] of Object.entries(raw)) {
890
+ if (TRACE_REDACTABLE_FIELDS.has(k)) {
891
+ out[k] = redactValue(v, config);
892
+ } else {
893
+ out[k] = v;
894
+ }
895
+ }
896
+ return out;
897
+ }
898
+ function buildTraceDict(state, rootSpan) {
899
+ const trace = {
900
+ trace_id: state.traceId,
901
+ // Wire-format field is `agent` (matches backend TracePayloadIn schema +
902
+ // sibling Python SDK). Was `agent_name` historically — the mismatch
903
+ // caused dev ingest to reject every TS-emitted trace with a 422
904
+ // until Phase 13 Option A dogfood surfaced it.
905
+ agent: state.agentName,
906
+ status: rootSpan.status,
907
+ started_at: rootSpan.started_at
908
+ };
909
+ if (rootSpan.ended_at) trace.ended_at = rootSpan.ended_at;
910
+ if (rootSpan.duration_ms !== void 0) trace.duration_ms = rootSpan.duration_ms;
911
+ if (rootSpan.error_message) trace.error_message = rootSpan.error_message;
912
+ if (state.success !== void 0) trace.success = state.success;
913
+ if (state.outcome !== void 0) trace.outcome = state.outcome;
914
+ if (state.threadId !== void 0) trace.thread_id = state.threadId;
915
+ if (state.userId !== void 0) trace.user_id = state.userId;
916
+ if (state.userMetadata && Object.keys(state.userMetadata).length > 0) {
917
+ trace.user_metadata = state.userMetadata;
918
+ }
919
+ const allSpans = [rootSpan, ...state.completedSpans];
920
+ const spans = allSpans.map((s) => {
921
+ const out2 = {};
922
+ for (const [k, v] of Object.entries(s)) {
923
+ if (v !== void 0 && v !== null) {
924
+ out2[k] = v;
925
+ }
926
+ }
927
+ return out2;
928
+ });
929
+ const config = redactionConfig;
930
+ const out = {
931
+ trace: redactTraceDict(trace, config),
932
+ spans: spans.map((s) => redactSpanDict(s, config))
933
+ };
934
+ const effectiveSource = state.sourceOverride || _source;
935
+ if (effectiveSource) {
936
+ out.resource = { "morse_ai.source": effectiveSource };
937
+ }
938
+ return out;
939
+ }
940
+ function sendTrace(entry) {
941
+ lastTrace = entry;
942
+ if (isLegacyTransport() || false) {
943
+ if (transport !== null) {
944
+ try {
945
+ transport.track({ traces: [entry] });
946
+ } catch {
947
+ }
948
+ }
949
+ return;
950
+ }
951
+ try {
952
+ emitTraceEntry(entry);
953
+ } catch {
954
+ }
955
+ }
956
+ function withDbCaptureContext(traceId, spanIdHex, fn) {
957
+ try {
958
+ return withOtelSpanContext(traceId, spanIdHex.slice(0, 16), fn);
959
+ } catch {
960
+ return fn();
961
+ }
962
+ }
963
+ function buildRunHandle(state) {
964
+ return {
965
+ setOutcome(success, outcome) {
966
+ state.success = success;
967
+ if (outcome !== void 0) state.outcome = outcome;
968
+ },
969
+ setError(message) {
970
+ state.errorMessage = message;
971
+ state.success = false;
972
+ },
973
+ _state: state
974
+ };
975
+ }
976
+ function startTrace(opts) {
977
+ let traceId;
978
+ if (opts.incomingTraceparent) {
979
+ const { extractTraceparent: extractTraceparent2 } = (init_propagation(), __toCommonJS(propagation_exports));
980
+ const ctx = extractTraceparent2(opts.incomingTraceparent);
981
+ if (ctx) {
982
+ traceId = ctx.traceId;
983
+ }
984
+ }
985
+ if (!traceId) traceId = generateTraceId();
986
+ const state = {
987
+ traceId,
988
+ agentName: opts.agentName,
989
+ spanStack: [],
990
+ completedSpans: []
991
+ };
992
+ if (opts.threadId !== void 0) state.threadId = opts.threadId;
993
+ if (opts.userId !== void 0) state.userId = opts.userId;
994
+ if (opts.userMetadata) {
995
+ state.userMetadata = Object.fromEntries(
996
+ Object.entries(opts.userMetadata).map(([k, v]) => [k, String(v)])
997
+ );
998
+ }
999
+ if (isValidInternalSource(opts.source)) {
1000
+ state.sourceOverride = opts.source;
1001
+ }
1002
+ const rootSpan = {
1003
+ trace_id: traceId,
1004
+ span_id: generateSpanId(),
1005
+ type: "agent",
1006
+ name: opts.agentName,
1007
+ started_at: nowIso(),
1008
+ status: "completed"
1009
+ };
1010
+ state.spanStack.push(rootSpan);
1011
+ return { state, rootSpan, startMono: nowMonotonic() };
1012
+ }
1013
+ function endTrace(state, rootSpan, startMono, threwError) {
1014
+ state.spanStack.pop();
1015
+ if (threwError !== void 0) {
1016
+ const msg = state.errorMessage ?? errToString(threwError);
1017
+ finalizeSpan(rootSpan, startMono, "failed", msg);
1018
+ if (state.success === void 0) state.success = false;
1019
+ } else if (state.errorMessage !== void 0) {
1020
+ finalizeSpan(rootSpan, startMono, "failed", state.errorMessage);
1021
+ } else {
1022
+ finalizeSpan(rootSpan, startMono);
1023
+ if (state.success === void 0) state.success = true;
1024
+ }
1025
+ const dict = buildTraceDict(state, rootSpan);
1026
+ sendTrace(dict);
1027
+ }
1028
+ function errToString(e) {
1029
+ if (e instanceof Error) return e.message;
1030
+ return String(e);
1031
+ }
1032
+ function runSync(opts, fn) {
1033
+ const { state, rootSpan, startMono } = startTrace(opts);
1034
+ const handle = buildRunHandle(state);
1035
+ const store = tryLoadAls();
1036
+ const runFn = () => withDbCaptureContext(state.traceId, rootSpan.span_id, () => fn(handle));
1037
+ if (store) {
1038
+ try {
1039
+ const result = store.run(state, runFn);
1040
+ endTrace(state, rootSpan, startMono, void 0);
1041
+ return result;
1042
+ } catch (err) {
1043
+ endTrace(state, rootSpan, startMono, err);
1044
+ throw err;
1045
+ }
1046
+ } else {
1047
+ const reset = setActiveTraceState(state);
1048
+ try {
1049
+ const result = runFn();
1050
+ endTrace(state, rootSpan, startMono, void 0);
1051
+ return result;
1052
+ } catch (err) {
1053
+ endTrace(state, rootSpan, startMono, err);
1054
+ throw err;
1055
+ } finally {
1056
+ reset();
1057
+ }
1058
+ }
1059
+ }
1060
+ async function runAsync(opts, fn) {
1061
+ const { state, rootSpan, startMono } = startTrace(opts);
1062
+ const handle = buildRunHandle(state);
1063
+ const store = tryLoadAls();
1064
+ const runFn = () => withDbCaptureContext(state.traceId, rootSpan.span_id, () => fn(handle));
1065
+ if (store) {
1066
+ try {
1067
+ const result = await store.run(state, runFn);
1068
+ endTrace(state, rootSpan, startMono, void 0);
1069
+ return result;
1070
+ } catch (err) {
1071
+ endTrace(state, rootSpan, startMono, err);
1072
+ throw err;
1073
+ }
1074
+ } else {
1075
+ const reset = setActiveTraceState(state);
1076
+ try {
1077
+ const result = await runFn();
1078
+ endTrace(state, rootSpan, startMono, void 0);
1079
+ return result;
1080
+ } catch (err) {
1081
+ endTrace(state, rootSpan, startMono, err);
1082
+ throw err;
1083
+ } finally {
1084
+ reset();
1085
+ }
1086
+ }
1087
+ }
1088
+ function setContext(dims) {
1089
+ const state = getActiveTraceState();
1090
+ if (state === null) return;
1091
+ if (state.userMetadata === void 0) state.userMetadata = {};
1092
+ for (const [k, v] of Object.entries(dims)) {
1093
+ state.userMetadata[k] = String(v);
1094
+ }
1095
+ }
1096
+ function startSpan(opts) {
1097
+ const state = getActiveTraceState();
1098
+ if (state === null) return null;
1099
+ const parent = state.spanStack[state.spanStack.length - 1];
1100
+ const span = {
1101
+ trace_id: state.traceId,
1102
+ span_id: generateSpanId(),
1103
+ type: opts.type ?? "custom",
1104
+ name: opts.name,
1105
+ parent_span_id: parent?.span_id,
1106
+ started_at: nowIso(),
1107
+ status: "completed",
1108
+ metadata: opts.metadata
1109
+ };
1110
+ const startMono = nowMonotonic();
1111
+ state.spanStack.push(span);
1112
+ return {
1113
+ span,
1114
+ end(error) {
1115
+ if (state.spanStack[state.spanStack.length - 1] === span) {
1116
+ state.spanStack.pop();
1117
+ }
1118
+ if (error !== void 0) {
1119
+ finalizeSpan(span, startMono, "failed", errToString(error));
1120
+ } else {
1121
+ finalizeSpan(span, startMono);
1122
+ }
1123
+ state.completedSpans.push(span);
1124
+ }
1125
+ };
1126
+ }
1127
+ function spanSync(opts, fn) {
1128
+ const handle = startSpan(opts);
1129
+ try {
1130
+ const result = handle ? withDbCaptureContext(handle.span.trace_id, handle.span.span_id, () => fn(handle)) : fn(handle);
1131
+ handle?.end();
1132
+ return result;
1133
+ } catch (err) {
1134
+ handle?.end(err);
1135
+ throw err;
1136
+ }
1137
+ }
1138
+ async function spanAsync(opts, fn) {
1139
+ const handle = startSpan(opts);
1140
+ try {
1141
+ const result = handle ? await withDbCaptureContext(handle.span.trace_id, handle.span.span_id, () => fn(handle)) : await fn(handle);
1142
+ handle?.end();
1143
+ return result;
1144
+ } catch (err) {
1145
+ handle?.end(err);
1146
+ throw err;
1147
+ }
1148
+ }
1149
+ function _resetForTesting() {
1150
+ browserState = null;
1151
+ lastTrace = null;
1152
+ redactionConfig = buildRedactionConfig();
1153
+ }
1154
+ var als, alsLoaded, browserState, transport, redactionConfig, _source, lastTrace, SPAN_REDACTABLE_FIELDS, TRACE_REDACTABLE_FIELDS;
1155
+ var init_tracing = __esm({
1156
+ "src/_internal/tracing.ts"() {
1157
+ init_env();
1158
+ init_otel_provider();
1159
+ init_redaction();
1160
+ init_spans();
1161
+ als = null;
1162
+ alsLoaded = false;
1163
+ browserState = null;
1164
+ transport = null;
1165
+ redactionConfig = buildRedactionConfig();
1166
+ _source = null;
1167
+ lastTrace = null;
1168
+ SPAN_REDACTABLE_FIELDS = /* @__PURE__ */ new Set([
1169
+ "name",
1170
+ "input_data",
1171
+ "output_data",
1172
+ "error_message",
1173
+ "metadata"
1174
+ ]);
1175
+ TRACE_REDACTABLE_FIELDS = /* @__PURE__ */ new Set(["agent", "outcome", "error_message"]);
1176
+ }
1177
+ });
1178
+
1179
+ // src/propagation.ts
1180
+ var propagation_exports = {};
1181
+ __export(propagation_exports, {
1182
+ W3C_FLAGS_SAMPLED: () => W3C_FLAGS_SAMPLED,
1183
+ W3C_TRACEPARENT_HEADER: () => W3C_TRACEPARENT_HEADER,
1184
+ W3C_VERSION: () => W3C_VERSION,
1185
+ extractFromRequest: () => extractFromRequest,
1186
+ extractTraceparent: () => extractTraceparent,
1187
+ formatTraceparent: () => formatTraceparent,
1188
+ injectIntoRequestInit: () => injectIntoRequestInit,
1189
+ injectTraceparent: () => injectTraceparent
1190
+ });
1191
+ function formatTraceparent(traceId, spanId) {
1192
+ const tid = traceId.slice(0, TRACE_ID_LEN).padStart(TRACE_ID_LEN, "0").toLowerCase();
1193
+ const sid = spanId.slice(0, SPAN_ID_LEN).padStart(SPAN_ID_LEN, "0").toLowerCase();
1194
+ return `${W3C_VERSION}-${tid}-${sid}-${W3C_FLAGS_SAMPLED}`;
1195
+ }
1196
+ function injectTraceparent(headers) {
1197
+ const state = getActiveTraceState();
1198
+ if (state === null) return headers;
1199
+ const traceId = state.traceId;
1200
+ const span = state.spanStack.length > 0 ? state.spanStack[state.spanStack.length - 1] : state.completedSpans[state.completedSpans.length - 1];
1201
+ const rawSpanId = span?.span_id ?? traceId;
1202
+ const spanId = rawSpanId.slice(0, SPAN_ID_LEN);
1203
+ const value = formatTraceparent(traceId, spanId);
1204
+ setHeader(headers, W3C_TRACEPARENT_HEADER, value);
1205
+ return headers;
1206
+ }
1207
+ function extractTraceparent(headers) {
1208
+ if (headers === null || headers === void 0) return null;
1209
+ const raw = typeof headers === "string" ? headers : getHeader(headers, W3C_TRACEPARENT_HEADER);
1210
+ if (!raw) return null;
1211
+ const parts = raw.split("-");
1212
+ if (parts.length !== 4) return null;
1213
+ const [version, traceId, spanId] = parts;
1214
+ if (version !== W3C_VERSION) return null;
1215
+ if (traceId.length !== TRACE_ID_LEN) return null;
1216
+ if (spanId.length !== SPAN_ID_LEN) return null;
1217
+ if (!/^[0-9a-f]+$/.test(traceId)) return null;
1218
+ if (!/^[0-9a-f]+$/.test(spanId)) return null;
1219
+ if (/^0+$/.test(traceId)) return null;
1220
+ if (/^0+$/.test(spanId)) return null;
1221
+ return { traceId, parentSpanId: spanId };
1222
+ }
1223
+ function extractFromRequest(req) {
1224
+ return extractTraceparent(req.headers);
1225
+ }
1226
+ function injectIntoRequestInit(init) {
1227
+ const merged = new Headers(init?.headers ?? {});
1228
+ injectTraceparent(merged);
1229
+ return { ...init ?? {}, headers: merged };
1230
+ }
1231
+ function getHeader(headers, name) {
1232
+ if (headers instanceof Headers) {
1233
+ return headers.get(name);
1234
+ }
1235
+ const maybeGet = headers.get;
1236
+ if (typeof maybeGet === "function") {
1237
+ const v = maybeGet.call(headers, name);
1238
+ if (typeof v === "string") return v;
1239
+ if (v === null || v === void 0) return null;
1240
+ }
1241
+ const lower = name.toLowerCase();
1242
+ for (const [k, v] of Object.entries(headers)) {
1243
+ if (k.toLowerCase() === lower) {
1244
+ if (typeof v === "string") return v;
1245
+ if (Array.isArray(v) && v.length > 0 && typeof v[0] === "string") return v[0];
1246
+ return null;
1247
+ }
1248
+ }
1249
+ return null;
1250
+ }
1251
+ function setHeader(headers, name, value) {
1252
+ if (headers instanceof Headers) {
1253
+ headers.set(name, value);
1254
+ return;
1255
+ }
1256
+ const maybeSet = headers.set;
1257
+ if (typeof maybeSet === "function") {
1258
+ maybeSet.call(headers, name, value);
1259
+ return;
1260
+ }
1261
+ headers[name] = value;
1262
+ }
1263
+ var W3C_TRACEPARENT_HEADER, W3C_VERSION, W3C_FLAGS_SAMPLED, TRACE_ID_LEN, SPAN_ID_LEN;
1264
+ var init_propagation = __esm({
1265
+ "src/propagation.ts"() {
1266
+ init_tracing();
1267
+ W3C_TRACEPARENT_HEADER = "traceparent";
1268
+ W3C_VERSION = "00";
1269
+ W3C_FLAGS_SAMPLED = "01";
1270
+ TRACE_ID_LEN = 32;
1271
+ SPAN_ID_LEN = 16;
1272
+ }
1273
+ });
1274
+
1275
+ export { DEFAULT_ENDPOINT, SpanType, W3C_TRACEPARENT_HEADER, _resetForTesting, buildRedactionConfig, buildTraceEntry, extractTraceparent, formatTraceparent, generateSpanId, generateTraceId, getActiveTraceState, getApiKey, getEndpoint, getEngine, getFlushIntervalSeconds, getInternalSource, getLastTrace, getMaxBatchSize, getMaxFieldBytes, getMaxQueueSize, getRedactionConfig, getSampleRate, getTransport, init_env, init_otel_provider, init_propagation, init_redaction, init_spans, init_tracing, injectIntoRequestInit, injectTraceparent, isAutoDetectDisabled, isDbCaptureEnabled, isDebug, isDisabled, isTelemetryDisabled, isValidInternalSource, nowIso, redactValue, runAsync, runSync, sendTrace, setContext, setRedactionConfig, setSource, setTransport, spanAsync, spanSync, startSpan };
1276
+ //# sourceMappingURL=chunk-TQWI4UYO.js.map
1277
+ //# sourceMappingURL=chunk-TQWI4UYO.js.map