@brizz/sdk 0.1.26 → 0.1.28

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -290,7 +290,7 @@ var init_schemas = __esm({
290
290
 
291
291
  // src/internal/semantic-conventions.ts
292
292
  import { createContextKey } from "@opentelemetry/api";
293
- var BRIZZ, PROPERTIES, SESSION_ID, PROPERTIES_CONTEXT_KEY, SESSION_OBJECT_CONTEXT_KEY, SESSION_INPUT, SESSION_OUTPUT, SESSION_INPUT_CONTEXT, SESSION_OUTPUT_CONTEXT, SESSION_SPAN_NAME, SESSION_TITLE_SPAN_NAME, SESSION_TITLE_GENERATION, SESSION_TITLE;
293
+ var BRIZZ, PROPERTIES, SESSION_ID, PROPERTIES_CONTEXT_KEY, SESSION_OBJECT_CONTEXT_KEY, SESSION_INPUT, SESSION_OUTPUT, SESSION_INPUT_CONTEXT, SESSION_OUTPUT_CONTEXT, SESSION_SPAN_NAME, MUTE_INPUT, MUTE_OUTPUT, SESSION_TITLE_SPAN_NAME, SESSION_TITLE_GENERATION, SESSION_TITLE, INTERRUPT_TOOLS, INTERNAL_EVENT_PREFIX, EXTERNAL_LINK_EVENT_NAME, EXTERNAL_LINK_URL, EXTERNAL_LINK_TITLE, EXTERNAL_LINK_TYPE;
294
294
  var init_semantic_conventions2 = __esm({
295
295
  "src/internal/semantic-conventions.ts"() {
296
296
  "use strict";
@@ -304,9 +304,17 @@ var init_semantic_conventions2 = __esm({
304
304
  SESSION_INPUT_CONTEXT = "brizz.session.input.context";
305
305
  SESSION_OUTPUT_CONTEXT = "brizz.session.output.context";
306
306
  SESSION_SPAN_NAME = "brizz.start_session";
307
+ MUTE_INPUT = "mute.input";
308
+ MUTE_OUTPUT = "mute.output";
307
309
  SESSION_TITLE_SPAN_NAME = "brizz.session_title";
308
310
  SESSION_TITLE_GENERATION = "session.title_generation";
309
311
  SESSION_TITLE = "brizz.session.title";
312
+ INTERRUPT_TOOLS = "brizz.internal.interrupt";
313
+ INTERNAL_EVENT_PREFIX = "brizz.internal.";
314
+ EXTERNAL_LINK_EVENT_NAME = "brizz.internal.external_link";
315
+ EXTERNAL_LINK_URL = "brizz.internal.external_link.url";
316
+ EXTERNAL_LINK_TITLE = "brizz.internal.external_link.title";
317
+ EXTERNAL_LINK_TYPE = "brizz.internal.external_link.type";
310
318
  }
311
319
  });
312
320
 
@@ -772,7 +780,7 @@ var init_protocol = __esm({
772
780
 
773
781
  // src/internal/version.ts
774
782
  function getSDKVersion() {
775
- return "0.1.26";
783
+ return "0.1.28";
776
784
  }
777
785
  var init_version = __esm({
778
786
  "src/internal/version.ts"() {
@@ -954,6 +962,100 @@ var init_mcp = __esm({
954
962
  }
955
963
  });
956
964
 
965
+ // src/internal/instrumentation/vercel-ai/interrupt.ts
966
+ var interrupt_exports = {};
967
+ __export(interrupt_exports, {
968
+ InterruptPropagator: () => InterruptPropagator,
969
+ _resetInterruptState: () => _resetInterruptState,
970
+ createInterruptIntegration: () => createInterruptIntegration
971
+ });
972
+ import { trace as trace3 } from "@opentelemetry/api";
973
+ function isInnerLLMSpan(span) {
974
+ if (INNER_OPERATION_IDS.has(span.name)) {
975
+ return true;
976
+ }
977
+ const opId = span.attributes["ai.operationId"];
978
+ return typeof opId === "string" && INNER_OPERATION_IDS.has(opId);
979
+ }
980
+ function setPending(parentSpanId, value) {
981
+ pendingByParentSpanId.set(parentSpanId, value);
982
+ while (pendingByParentSpanId.size > MAX_PENDING_ENTRIES) {
983
+ const oldest = pendingByParentSpanId.keys().next().value;
984
+ if (oldest === void 0) {
985
+ break;
986
+ }
987
+ pendingByParentSpanId.delete(oldest);
988
+ }
989
+ }
990
+ function extractInterruptTools(tools) {
991
+ if (!tools || typeof tools !== "object") {
992
+ return [];
993
+ }
994
+ return Object.entries(tools).filter(
995
+ ([, t]) => !!t && typeof t === "object" && t.needsApproval
996
+ ).map(([name]) => name);
997
+ }
998
+ function createInterruptIntegration() {
999
+ const onStepStart = (event) => {
1000
+ const names = extractInterruptTools(event.tools);
1001
+ if (names.length === 0) {
1002
+ return;
1003
+ }
1004
+ const value = JSON.stringify(names);
1005
+ const span = trace3.getActiveSpan();
1006
+ if (!span) {
1007
+ return;
1008
+ }
1009
+ span.setAttribute(INTERRUPT_TOOLS, value);
1010
+ setPending(span.spanContext().spanId, value);
1011
+ };
1012
+ return {
1013
+ onStepStart
1014
+ };
1015
+ }
1016
+ function _resetInterruptState() {
1017
+ if (process.env["NODE_ENV"] !== "test") {
1018
+ return;
1019
+ }
1020
+ pendingByParentSpanId.clear();
1021
+ }
1022
+ var INNER_OPERATION_IDS, MAX_PENDING_ENTRIES, pendingByParentSpanId, InterruptPropagator;
1023
+ var init_interrupt = __esm({
1024
+ "src/internal/instrumentation/vercel-ai/interrupt.ts"() {
1025
+ "use strict";
1026
+ init_semantic_conventions2();
1027
+ INNER_OPERATION_IDS = /* @__PURE__ */ new Set([
1028
+ "ai.generateText.doGenerate",
1029
+ "ai.streamText.doStream"
1030
+ ]);
1031
+ MAX_PENDING_ENTRIES = 1024;
1032
+ pendingByParentSpanId = /* @__PURE__ */ new Map();
1033
+ InterruptPropagator = class {
1034
+ onStart(span, _parentContext) {
1035
+ if (!isInnerLLMSpan(span)) {
1036
+ return;
1037
+ }
1038
+ const parentSpanId = span.parentSpanContext?.spanId;
1039
+ if (!parentSpanId) {
1040
+ return;
1041
+ }
1042
+ const value = pendingByParentSpanId.get(parentSpanId);
1043
+ if (!value) {
1044
+ return;
1045
+ }
1046
+ span.setAttribute(INTERRUPT_TOOLS, value);
1047
+ pendingByParentSpanId.delete(parentSpanId);
1048
+ }
1049
+ onEnd() {
1050
+ }
1051
+ async shutdown() {
1052
+ }
1053
+ async forceFlush() {
1054
+ }
1055
+ };
1056
+ }
1057
+ });
1058
+
957
1059
  // src/internal/instrumentation/auto-init.ts
958
1060
  init_logger();
959
1061
  import { getNodeAutoInstrumentations } from "@opentelemetry/auto-instrumentations-node";
@@ -1034,6 +1136,26 @@ function loadMCPInstrumentation() {
1034
1136
  }
1035
1137
  })();
1036
1138
  }
1139
+ function loadVercelAIInterruptIntegration() {
1140
+ void (async () => {
1141
+ try {
1142
+ const ai = await import("ai");
1143
+ if (typeof ai.registerTelemetryIntegration !== "function") {
1144
+ logger.debug(
1145
+ "AI SDK present but lacks registerTelemetryIntegration (needs ai@>=6); skipping interrupt bridge"
1146
+ );
1147
+ return;
1148
+ }
1149
+ const { createInterruptIntegration: createInterruptIntegration2 } = await Promise.resolve().then(() => (init_interrupt(), interrupt_exports));
1150
+ ai.registerTelemetryIntegration(createInterruptIntegration2());
1151
+ logger.debug("Auto-loaded Vercel AI interrupt bridge");
1152
+ } catch (error) {
1153
+ logger.debug(
1154
+ `Vercel AI interrupt bridge not loaded (install ai@>=6 if you want HITL attribution): ${String(error)}`
1155
+ );
1156
+ }
1157
+ })();
1158
+ }
1037
1159
  function autoInitializeInstrumentations() {
1038
1160
  if (autoInstrumentationsLoaded) {
1039
1161
  return;
@@ -1042,6 +1164,7 @@ function autoInitializeInstrumentations() {
1042
1164
  const nodeInstrumentations = loadNodeAutoInstrumentations();
1043
1165
  const genAIInstrumentations = loadGenAIInstrumentations();
1044
1166
  loadMCPInstrumentation();
1167
+ loadVercelAIInterruptIntegration();
1045
1168
  autoInstrumentationsLoaded = true;
1046
1169
  logger.info(
1047
1170
  `Auto-initialization complete: ${nodeInstrumentations.length} node + ${genAIInstrumentations.length} GenAI instrumentations`
@@ -1356,6 +1479,9 @@ var InstrumentationRegistry = class _InstrumentationRegistry {
1356
1479
  }
1357
1480
  };
1358
1481
 
1482
+ // src/internal/sdk.ts
1483
+ init_interrupt();
1484
+
1359
1485
  // src/internal/log/logging.ts
1360
1486
  import { SeverityNumber } from "@opentelemetry/api-logs";
1361
1487
  import { OTLPLogExporter } from "@opentelemetry/exporter-logs-otlp-http";
@@ -1364,11 +1490,283 @@ import {
1364
1490
  LoggerProvider
1365
1491
  } from "@opentelemetry/sdk-logs";
1366
1492
  init_logger();
1493
+
1494
+ // src/internal/trace/session.ts
1495
+ import { context as context3, trace as trace4, SpanStatusCode as SpanStatusCode3 } from "@opentelemetry/api";
1496
+ init_logger();
1497
+ init_semantic_conventions2();
1498
+ function setCurrentSpanCustomProperties(properties) {
1499
+ const current = trace4.getActiveSpan();
1500
+ if (!current || !current.isRecording()) {
1501
+ return;
1502
+ }
1503
+ for (const [key, value] of Object.entries(properties)) {
1504
+ try {
1505
+ current.setAttribute(`${BRIZZ}.${key}`, value);
1506
+ } catch {
1507
+ }
1508
+ }
1509
+ }
1510
+ function callWithProperties(properties, fn, thisArg, ...args) {
1511
+ const base = context3.active();
1512
+ const prev = base.getValue(PROPERTIES_CONTEXT_KEY);
1513
+ const merged = prev ? { ...prev, ...properties } : properties;
1514
+ const next = base.setValue(PROPERTIES_CONTEXT_KEY, merged);
1515
+ return context3.with(next, fn, thisArg, ...args);
1516
+ }
1517
+ function withProperties(properties, fn, thisArg) {
1518
+ return function wrapped(...args) {
1519
+ return callWithProperties(
1520
+ properties,
1521
+ fn,
1522
+ thisArg !== void 0 ? thisArg : this,
1523
+ ...args
1524
+ );
1525
+ };
1526
+ }
1527
+ function muteProperties(options) {
1528
+ const { input = true, output = true } = options;
1529
+ const properties = {};
1530
+ if (input) {
1531
+ properties[MUTE_INPUT] = "true";
1532
+ }
1533
+ if (output) {
1534
+ properties[MUTE_OUTPUT] = "true";
1535
+ }
1536
+ return properties;
1537
+ }
1538
+ function callWithMute(options, fn, thisArg, ...args) {
1539
+ return callWithProperties(muteProperties(options), fn, thisArg, ...args);
1540
+ }
1541
+ function withMute(options, fn, thisArg) {
1542
+ return withProperties(muteProperties(options), fn, thisArg);
1543
+ }
1544
+ function withSessionId(sessionId, fn, thisArg, extraProperties) {
1545
+ const properties = { [SESSION_ID]: sessionId, ...extraProperties };
1546
+ return withProperties(properties, fn, thisArg);
1547
+ }
1548
+ function callWithSessionId(sessionId, fn, thisArg, ...args) {
1549
+ return callWithProperties({ [SESSION_ID]: sessionId }, fn, thisArg, ...args);
1550
+ }
1551
+ var Session = class {
1552
+ sessionId;
1553
+ span;
1554
+ inputs = [];
1555
+ outputs = [];
1556
+ inputContexts = [];
1557
+ outputContexts = [];
1558
+ constructor(sessionId, span) {
1559
+ this.sessionId = sessionId;
1560
+ this.span = span;
1561
+ }
1562
+ /**
1563
+ * Append a user turn to session input tracking.
1564
+ *
1565
+ * Each call appends one element to `brizz.session.input` (the text) AND one
1566
+ * element to `brizz.session.input.context` (the per-turn context bag). The
1567
+ * two arrays stay index-aligned — the ingestion pipeline zips them together
1568
+ * so the i-th context bag lands on the i-th user_display conversation item's
1569
+ * `span_attributes` map.
1570
+ *
1571
+ * @param text - Text to append (null becomes a null/"hide marker")
1572
+ * @param context - Optional per-turn context bag to attach to this turn
1573
+ */
1574
+ setInput(text, context6) {
1575
+ this.inputs.push(text);
1576
+ this.inputContexts.push(context6 ?? {});
1577
+ this.span.setAttribute(SESSION_INPUT, JSON.stringify(this.inputs));
1578
+ this.span.setAttribute(SESSION_INPUT_CONTEXT, JSON.stringify(this.inputContexts));
1579
+ }
1580
+ /**
1581
+ * Append an assistant turn to session output tracking.
1582
+ *
1583
+ * Symmetric to {@link setInput} — appends one text element and one
1584
+ * context-bag element to the index-aligned `brizz.session.output` /
1585
+ * `brizz.session.output.context` arrays.
1586
+ *
1587
+ * @param text - Text to append (null becomes a null/"hide marker")
1588
+ * @param context - Optional per-turn context bag to attach to this turn
1589
+ */
1590
+ setOutput(text, context6) {
1591
+ this.outputs.push(text);
1592
+ this.outputContexts.push(context6 ?? {});
1593
+ this.span.setAttribute(SESSION_OUTPUT, JSON.stringify(this.outputs));
1594
+ this.span.setAttribute(SESSION_OUTPUT_CONTEXT, JSON.stringify(this.outputContexts));
1595
+ }
1596
+ /**
1597
+ * Set the session title on the span.
1598
+ *
1599
+ * @param title - The generated title string
1600
+ */
1601
+ setTitle(title) {
1602
+ this.span.setAttribute(SESSION_TITLE, title);
1603
+ }
1604
+ /**
1605
+ * Update custom properties on the session span.
1606
+ * Properties are prefixed with 'brizz.'.
1607
+ *
1608
+ * @param properties - Key-value properties to set on the session
1609
+ */
1610
+ updateProperties(properties) {
1611
+ for (const [key, value] of Object.entries(properties)) {
1612
+ this.span.setAttribute(`${BRIZZ}.${key}`, value);
1613
+ }
1614
+ }
1615
+ /**
1616
+ * Attach an external link (URL) to this session.
1617
+ *
1618
+ * The link surfaces on the session's detail panel in Brizz — use it to
1619
+ * correlate a session with an external record such as a Datadog trace,
1620
+ * Sentry issue, or internal dashboard. Re-sending the same URL is idempotent;
1621
+ * distinct URLs add separate links.
1622
+ *
1623
+ * @param url - The link target
1624
+ * @param options - Optional `title` (defaults to the URL host) and `linkType`
1625
+ * (free-form category, defaults to `'generic'`)
1626
+ */
1627
+ addExternalLink(url, options) {
1628
+ emitExternalLink(this.sessionId, url, options?.title, options?.linkType);
1629
+ }
1630
+ };
1631
+ var SessionTitle = class {
1632
+ span;
1633
+ constructor(span) {
1634
+ this.span = span;
1635
+ }
1636
+ /**
1637
+ * Set the generated title on the wrapper span.
1638
+ *
1639
+ * @param title - The generated title string
1640
+ */
1641
+ setTitle(title) {
1642
+ this.span.setAttribute(SESSION_TITLE, title);
1643
+ }
1644
+ };
1645
+ function getActiveSession() {
1646
+ return context3.active().getValue(SESSION_OBJECT_CONTEXT_KEY);
1647
+ }
1648
+ function resolveSessionIdFromContext() {
1649
+ const active = getActiveSession();
1650
+ if (active) {
1651
+ return active.sessionId;
1652
+ }
1653
+ const props = context3.active().getValue(PROPERTIES_CONTEXT_KEY);
1654
+ return props?.[SESSION_ID];
1655
+ }
1656
+ function emitExternalLink(sessionId, url, title, linkType) {
1657
+ try {
1658
+ emitEventWithSessionId(sessionId, EXTERNAL_LINK_EVENT_NAME, {
1659
+ [EXTERNAL_LINK_URL]: url,
1660
+ [EXTERNAL_LINK_TITLE]: title ?? "",
1661
+ [EXTERNAL_LINK_TYPE]: linkType ?? "generic"
1662
+ });
1663
+ } catch (error) {
1664
+ logger.warn("addExternalLink: failed to emit external link", error);
1665
+ }
1666
+ }
1667
+ function addExternalLink(url, options) {
1668
+ const sessionId = options?.sessionId ?? resolveSessionIdFromContext();
1669
+ if (!sessionId) {
1670
+ logger.warn(
1671
+ "addExternalLink called without a resolvable session id; link dropped. Pass options.sessionId or call inside a startSession/callWithSessionId scope."
1672
+ );
1673
+ return;
1674
+ }
1675
+ emitExternalLink(sessionId, url, options?.title, options?.linkType);
1676
+ }
1677
+ function startSession(sessionId, callback, extraProperties, options) {
1678
+ const isTitle = options?.mode === "title";
1679
+ const spanName = isTitle ? SESSION_TITLE_SPAN_NAME : SESSION_SPAN_NAME;
1680
+ const tracer = trace4.getTracer("@brizz/sdk");
1681
+ return tracer.startActiveSpan(spanName, (span) => {
1682
+ span.setAttribute(`${BRIZZ}.${SESSION_ID}`, sessionId);
1683
+ if (extraProperties) {
1684
+ for (const [key, value] of Object.entries(extraProperties)) {
1685
+ span.setAttribute(`${BRIZZ}.${key}`, value);
1686
+ }
1687
+ }
1688
+ const session = new Session(sessionId, span);
1689
+ const contextProperties = { [SESSION_ID]: sessionId };
1690
+ if (isTitle) {
1691
+ contextProperties[SESSION_TITLE_GENERATION] = "true";
1692
+ }
1693
+ if (extraProperties) {
1694
+ for (const [key, value] of Object.entries(extraProperties)) {
1695
+ contextProperties[key] = String(value);
1696
+ }
1697
+ }
1698
+ return callWithProperties(contextProperties, () => {
1699
+ const sessionCtx = context3.active().setValue(SESSION_OBJECT_CONTEXT_KEY, session);
1700
+ return context3.with(sessionCtx, () => {
1701
+ try {
1702
+ const result = callback(session);
1703
+ if (result && typeof result.then === "function") {
1704
+ return result.then((value) => {
1705
+ span.end();
1706
+ return value;
1707
+ }).catch((error) => {
1708
+ span.recordException(error);
1709
+ span.setStatus({ code: SpanStatusCode3.ERROR });
1710
+ span.end();
1711
+ throw error;
1712
+ });
1713
+ }
1714
+ span.end();
1715
+ return result;
1716
+ } catch (error) {
1717
+ span.recordException(error);
1718
+ span.setStatus({ code: SpanStatusCode3.ERROR });
1719
+ span.end();
1720
+ throw error;
1721
+ }
1722
+ });
1723
+ });
1724
+ });
1725
+ }
1726
+ function startSessionTitle(callback, options) {
1727
+ const resolvedSessionId = options?.sessionId ?? getActiveSession()?.sessionId;
1728
+ const tracer = trace4.getTracer("@brizz/sdk");
1729
+ return tracer.startActiveSpan(SESSION_TITLE_SPAN_NAME, (span) => {
1730
+ if (resolvedSessionId) {
1731
+ span.setAttribute(`${BRIZZ}.${SESSION_ID}`, resolvedSessionId);
1732
+ }
1733
+ const sessionTitle = new SessionTitle(span);
1734
+ const properties = { [SESSION_TITLE_GENERATION]: "true" };
1735
+ if (resolvedSessionId) {
1736
+ properties[SESSION_ID] = resolvedSessionId;
1737
+ }
1738
+ return callWithProperties(properties, () => {
1739
+ try {
1740
+ const result = callback(sessionTitle);
1741
+ if (result && typeof result.then === "function") {
1742
+ return result.then((value) => {
1743
+ span.end();
1744
+ return value;
1745
+ }).catch((error) => {
1746
+ span.recordException(error);
1747
+ span.setStatus({ code: SpanStatusCode3.ERROR });
1748
+ span.end();
1749
+ throw error;
1750
+ });
1751
+ }
1752
+ span.end();
1753
+ return result;
1754
+ } catch (error) {
1755
+ span.recordException(error);
1756
+ span.setStatus({ code: SpanStatusCode3.ERROR });
1757
+ span.end();
1758
+ throw error;
1759
+ }
1760
+ });
1761
+ });
1762
+ }
1763
+
1764
+ // src/internal/log/logging.ts
1367
1765
  init_version();
1368
1766
 
1369
1767
  // src/internal/log/processors/log-processor.ts
1370
1768
  init_logger();
1371
- import { context as context3 } from "@opentelemetry/api";
1769
+ import { context as context4 } from "@opentelemetry/api";
1372
1770
  import { BatchLogRecordProcessor, SimpleLogRecordProcessor } from "@opentelemetry/sdk-logs";
1373
1771
 
1374
1772
  // src/internal/masking/patterns.ts
@@ -1799,7 +2197,7 @@ var BrizzSimpleLogRecordProcessor = class extends SimpleLogRecordProcessor {
1799
2197
  if (maskingConfig) {
1800
2198
  maskLog(logRecord, maskingConfig);
1801
2199
  }
1802
- const associationProperties = context3.active().getValue(PROPERTIES_CONTEXT_KEY);
2200
+ const associationProperties = context4.active().getValue(PROPERTIES_CONTEXT_KEY);
1803
2201
  if (associationProperties) {
1804
2202
  for (const [key, value] of Object.entries(associationProperties)) {
1805
2203
  logRecord.setAttribute(`${BRIZZ}.${key}`, value);
@@ -1819,7 +2217,7 @@ var BrizzBatchLogRecordProcessor = class extends BatchLogRecordProcessor {
1819
2217
  if (maskingConfig) {
1820
2218
  maskLog(logRecord, maskingConfig);
1821
2219
  }
1822
- const associationProperties = context3.active().getValue(PROPERTIES_CONTEXT_KEY);
2220
+ const associationProperties = context4.active().getValue(PROPERTIES_CONTEXT_KEY);
1823
2221
  if (associationProperties) {
1824
2222
  for (const [key, value] of Object.entries(associationProperties)) {
1825
2223
  logRecord.setAttribute(`${BRIZZ}.${key}`, value);
@@ -1848,6 +2246,11 @@ function maskLog(logRecord, config) {
1848
2246
  for (const [key, value] of Object.entries(maskedAttributes)) {
1849
2247
  newAttributes[key] = value;
1850
2248
  }
2249
+ for (const [key, value] of Object.entries(logRecord.attributes)) {
2250
+ if (key.startsWith(INTERNAL_EVENT_PREFIX)) {
2251
+ newAttributes[key] = value;
2252
+ }
2253
+ }
1851
2254
  logRecord.setAttributes(newAttributes);
1852
2255
  }
1853
2256
  }
@@ -2037,6 +2440,11 @@ var LoggingModule = class _LoggingModule {
2037
2440
  function emitEvent(name, attributes, body, severityNumber = SeverityNumber.INFO) {
2038
2441
  return LoggingModule.getInstance().emitEvent(name, attributes, body, severityNumber);
2039
2442
  }
2443
+ function emitEventWithSessionId(sessionId, name, attributes, body, severityNumber = SeverityNumber.INFO) {
2444
+ return callWithSessionId(sessionId, () => {
2445
+ LoggingModule.getInstance().emitEvent(name, attributes, body, severityNumber);
2446
+ });
2447
+ }
2040
2448
 
2041
2449
  // src/internal/sdk.ts
2042
2450
  init_logger();
@@ -2220,14 +2628,14 @@ var BrizzSpanExporter = class {
2220
2628
 
2221
2629
  // src/internal/trace/processors/span-processor.ts
2222
2630
  init_logger();
2223
- import { context as context4 } from "@opentelemetry/api";
2631
+ import { context as context5 } from "@opentelemetry/api";
2224
2632
  import {
2225
2633
  BatchSpanProcessor,
2226
2634
  SimpleSpanProcessor
2227
2635
  } from "@opentelemetry/sdk-trace-base";
2228
2636
  init_semantic_conventions2();
2229
2637
  function applyContextAttributes(span) {
2230
- const sessionProperties = context4.active().getValue(PROPERTIES_CONTEXT_KEY);
2638
+ const sessionProperties = context5.active().getValue(PROPERTIES_CONTEXT_KEY);
2231
2639
  if (sessionProperties) {
2232
2640
  for (const [key, value] of Object.entries(sessionProperties)) {
2233
2641
  span.setAttribute(`${BRIZZ}.${key}`, value);
@@ -2412,214 +2820,6 @@ function getSpanProcessor() {
2412
2820
  return TracingModule.getInstance().getSpanProcessor();
2413
2821
  }
2414
2822
 
2415
- // src/internal/trace/session.ts
2416
- init_semantic_conventions2();
2417
- import { context as context5, trace as trace3, SpanStatusCode as SpanStatusCode3 } from "@opentelemetry/api";
2418
- function setCurrentSpanCustomProperties(properties) {
2419
- const current = trace3.getActiveSpan();
2420
- if (!current || !current.isRecording()) {
2421
- return;
2422
- }
2423
- for (const [key, value] of Object.entries(properties)) {
2424
- try {
2425
- current.setAttribute(`${BRIZZ}.${key}`, value);
2426
- } catch {
2427
- }
2428
- }
2429
- }
2430
- function callWithProperties(properties, fn, thisArg, ...args) {
2431
- const base = context5.active();
2432
- const prev = base.getValue(PROPERTIES_CONTEXT_KEY);
2433
- const merged = prev ? { ...prev, ...properties } : properties;
2434
- const next = base.setValue(PROPERTIES_CONTEXT_KEY, merged);
2435
- return context5.with(next, fn, thisArg, ...args);
2436
- }
2437
- function withProperties(properties, fn, thisArg) {
2438
- return function wrapped(...args) {
2439
- return callWithProperties(
2440
- properties,
2441
- fn,
2442
- thisArg !== void 0 ? thisArg : this,
2443
- ...args
2444
- );
2445
- };
2446
- }
2447
- function withSessionId(sessionId, fn, thisArg, extraProperties) {
2448
- const properties = { [SESSION_ID]: sessionId, ...extraProperties };
2449
- return withProperties(properties, fn, thisArg);
2450
- }
2451
- function callWithSessionId(sessionId, fn, thisArg, ...args) {
2452
- return callWithProperties({ [SESSION_ID]: sessionId }, fn, thisArg, ...args);
2453
- }
2454
- var Session = class {
2455
- sessionId;
2456
- span;
2457
- inputs = [];
2458
- outputs = [];
2459
- inputContexts = [];
2460
- outputContexts = [];
2461
- constructor(sessionId, span) {
2462
- this.sessionId = sessionId;
2463
- this.span = span;
2464
- }
2465
- /**
2466
- * Append a user turn to session input tracking.
2467
- *
2468
- * Each call appends one element to `brizz.session.input` (the text) AND one
2469
- * element to `brizz.session.input.context` (the per-turn context bag). The
2470
- * two arrays stay index-aligned — the ingestion pipeline zips them together
2471
- * so the i-th context bag lands on the i-th user_display conversation item's
2472
- * `span_attributes` map.
2473
- *
2474
- * @param text - Text to append (null becomes a null/"hide marker")
2475
- * @param context - Optional per-turn context bag to attach to this turn
2476
- */
2477
- setInput(text, context6) {
2478
- this.inputs.push(text);
2479
- this.inputContexts.push(context6 ?? {});
2480
- this.span.setAttribute(SESSION_INPUT, JSON.stringify(this.inputs));
2481
- this.span.setAttribute(SESSION_INPUT_CONTEXT, JSON.stringify(this.inputContexts));
2482
- }
2483
- /**
2484
- * Append an assistant turn to session output tracking.
2485
- *
2486
- * Symmetric to {@link setInput} — appends one text element and one
2487
- * context-bag element to the index-aligned `brizz.session.output` /
2488
- * `brizz.session.output.context` arrays.
2489
- *
2490
- * @param text - Text to append (null becomes a null/"hide marker")
2491
- * @param context - Optional per-turn context bag to attach to this turn
2492
- */
2493
- setOutput(text, context6) {
2494
- this.outputs.push(text);
2495
- this.outputContexts.push(context6 ?? {});
2496
- this.span.setAttribute(SESSION_OUTPUT, JSON.stringify(this.outputs));
2497
- this.span.setAttribute(SESSION_OUTPUT_CONTEXT, JSON.stringify(this.outputContexts));
2498
- }
2499
- /**
2500
- * Set the session title on the span.
2501
- *
2502
- * @param title - The generated title string
2503
- */
2504
- setTitle(title) {
2505
- this.span.setAttribute(SESSION_TITLE, title);
2506
- }
2507
- /**
2508
- * Update custom properties on the session span.
2509
- * Properties are prefixed with 'brizz.'.
2510
- *
2511
- * @param properties - Key-value properties to set on the session
2512
- */
2513
- updateProperties(properties) {
2514
- for (const [key, value] of Object.entries(properties)) {
2515
- this.span.setAttribute(`${BRIZZ}.${key}`, value);
2516
- }
2517
- }
2518
- };
2519
- var SessionTitle = class {
2520
- span;
2521
- constructor(span) {
2522
- this.span = span;
2523
- }
2524
- /**
2525
- * Set the generated title on the wrapper span.
2526
- *
2527
- * @param title - The generated title string
2528
- */
2529
- setTitle(title) {
2530
- this.span.setAttribute(SESSION_TITLE, title);
2531
- }
2532
- };
2533
- function getActiveSession() {
2534
- return context5.active().getValue(SESSION_OBJECT_CONTEXT_KEY);
2535
- }
2536
- function startSession(sessionId, callback, extraProperties, options) {
2537
- const isTitle = options?.mode === "title";
2538
- const spanName = isTitle ? SESSION_TITLE_SPAN_NAME : SESSION_SPAN_NAME;
2539
- const tracer = trace3.getTracer("@brizz/sdk");
2540
- return tracer.startActiveSpan(spanName, (span) => {
2541
- span.setAttribute(`${BRIZZ}.${SESSION_ID}`, sessionId);
2542
- if (extraProperties) {
2543
- for (const [key, value] of Object.entries(extraProperties)) {
2544
- span.setAttribute(`${BRIZZ}.${key}`, value);
2545
- }
2546
- }
2547
- const session = new Session(sessionId, span);
2548
- const contextProperties = { [SESSION_ID]: sessionId };
2549
- if (isTitle) {
2550
- contextProperties[SESSION_TITLE_GENERATION] = "true";
2551
- }
2552
- if (extraProperties) {
2553
- for (const [key, value] of Object.entries(extraProperties)) {
2554
- contextProperties[key] = String(value);
2555
- }
2556
- }
2557
- return callWithProperties(contextProperties, () => {
2558
- const sessionCtx = context5.active().setValue(SESSION_OBJECT_CONTEXT_KEY, session);
2559
- return context5.with(sessionCtx, () => {
2560
- try {
2561
- const result = callback(session);
2562
- if (result && typeof result.then === "function") {
2563
- return result.then((value) => {
2564
- span.end();
2565
- return value;
2566
- }).catch((error) => {
2567
- span.recordException(error);
2568
- span.setStatus({ code: SpanStatusCode3.ERROR });
2569
- span.end();
2570
- throw error;
2571
- });
2572
- }
2573
- span.end();
2574
- return result;
2575
- } catch (error) {
2576
- span.recordException(error);
2577
- span.setStatus({ code: SpanStatusCode3.ERROR });
2578
- span.end();
2579
- throw error;
2580
- }
2581
- });
2582
- });
2583
- });
2584
- }
2585
- function startSessionTitle(callback, options) {
2586
- const resolvedSessionId = options?.sessionId ?? getActiveSession()?.sessionId;
2587
- const tracer = trace3.getTracer("@brizz/sdk");
2588
- return tracer.startActiveSpan(SESSION_TITLE_SPAN_NAME, (span) => {
2589
- if (resolvedSessionId) {
2590
- span.setAttribute(`${BRIZZ}.${SESSION_ID}`, resolvedSessionId);
2591
- }
2592
- const sessionTitle = new SessionTitle(span);
2593
- const properties = { [SESSION_TITLE_GENERATION]: "true" };
2594
- if (resolvedSessionId) {
2595
- properties[SESSION_ID] = resolvedSessionId;
2596
- }
2597
- return callWithProperties(properties, () => {
2598
- try {
2599
- const result = callback(sessionTitle);
2600
- if (result && typeof result.then === "function") {
2601
- return result.then((value) => {
2602
- span.end();
2603
- return value;
2604
- }).catch((error) => {
2605
- span.recordException(error);
2606
- span.setStatus({ code: SpanStatusCode3.ERROR });
2607
- span.end();
2608
- throw error;
2609
- });
2610
- }
2611
- span.end();
2612
- return result;
2613
- } catch (error) {
2614
- span.recordException(error);
2615
- span.setStatus({ code: SpanStatusCode3.ERROR });
2616
- span.end();
2617
- throw error;
2618
- }
2619
- });
2620
- });
2621
- }
2622
-
2623
2823
  // src/internal/sdk.ts
2624
2824
  init_version();
2625
2825
  var _Brizz = class __Brizz {
@@ -2704,7 +2904,7 @@ var _Brizz = class __Brizz {
2704
2904
  resourceAttributes["service.version"] = resolvedConfig.appVersion;
2705
2905
  }
2706
2906
  this._sdk = new NodeSDK({
2707
- spanProcessors: resolvedConfig.disableSpanExporter ? [] : [getSpanProcessor()],
2907
+ spanProcessors: resolvedConfig.disableSpanExporter ? [] : [new InterruptPropagator(), getSpanProcessor()],
2708
2908
  metricReader: getMetricsReader(),
2709
2909
  resource: resourceFromAttributes3(resourceAttributes),
2710
2910
  instrumentations: manualInstrumentations
@@ -2878,10 +3078,13 @@ export {
2878
3078
  Session,
2879
3079
  SessionTitle,
2880
3080
  SeverityNumber2 as SeverityNumber,
3081
+ addExternalLink,
3082
+ callWithMute,
2881
3083
  callWithProperties,
2882
3084
  callWithSessionId,
2883
3085
  detectRuntime,
2884
3086
  emitEvent,
3087
+ emitEventWithSessionId,
2885
3088
  getActiveSession,
2886
3089
  getLogLevel,
2887
3090
  getMetricsExporter,
@@ -2896,6 +3099,7 @@ export {
2896
3099
  setLogLevel,
2897
3100
  startSession,
2898
3101
  startSessionTitle,
3102
+ withMute,
2899
3103
  withProperties,
2900
3104
  withSessionId
2901
3105
  };