@brizz/sdk 0.1.17 → 0.1.19

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 CHANGED
@@ -287,10 +287,23 @@ const result = await startSession(
287
287
 
288
288
  **Session Methods:**
289
289
  - `session.updateProperties({ key: value })` - Add custom properties to the session span
290
- - `session.setInput(text)` - (Optional) Manually track input text
291
- - `session.setOutput(text)` - (Optional) Manually track output text
290
+ - `session.setInput(text, context?)` - (Optional) Manually track input text; optional context bag attaches per-turn metadata rendered in the dashboard's Context panel
291
+ - `session.setOutput(text, context?)` - (Optional) Manually track output text; optional context bag attaches per-turn metadata rendered in the dashboard's Context panel
292
292
  - `session.setTitle(text)` - Set a session title (typically used with `mode: 'title'`)
293
293
 
294
+ **Per-turn context example:**
295
+
296
+ ```typescript
297
+ await startSession('session-123', async (session) => {
298
+ session.setInput('Why is my bill high?', { selected_invoice: 'INV-9182' });
299
+ const response = await openai.chat.completions.create({ ... });
300
+ session.setOutput(response.choices[0].message.content, {
301
+ message_id: 'msg-42',
302
+ sources: ['doc-abc'],
303
+ });
304
+ });
305
+ ```
306
+
294
307
  **When to use manual input/output tracking:**
295
308
 
296
309
  In most cases, Brizz automatically captures inputs and outputs from your LLM calls. Use `setInput`/`setOutput` for special scenarios:
package/dist/index.cjs CHANGED
@@ -223,7 +223,14 @@ var exceptionLogger = (error) => {
223
223
  };
224
224
  function loadNodeAutoInstrumentations() {
225
225
  try {
226
- const nodeInstrumentations = (0, import_auto_instrumentations_node.getNodeAutoInstrumentations)();
226
+ const nodeInstrumentations = (0, import_auto_instrumentations_node.getNodeAutoInstrumentations)({
227
+ // Disabled because @traceloop/instrumentation-openai wraps the same OpenAI
228
+ // prototype with richer span attributes (gen_ai.input.messages /
229
+ // gen_ai.output.messages). Leaving both enabled lets the official one win
230
+ // and route content to log events instead of span attributes, leaving the
231
+ // Brizz backend parser with no payload to read.
232
+ "@opentelemetry/instrumentation-openai": { enabled: false }
233
+ });
227
234
  (0, import_instrumentation.registerInstrumentations)({ instrumentations: nodeInstrumentations });
228
235
  return nodeInstrumentations;
229
236
  } catch (error) {
@@ -327,6 +334,7 @@ function resolveConfig(options) {
327
334
  const resolvedConfig = {
328
335
  ...options,
329
336
  appName: process.env["BRIZZ_APP_NAME"] || options.appName || "unknown-app",
337
+ appVersion: process.env["BRIZZ_APP_VERSION"] || options.appVersion,
330
338
  baseUrl: process.env["BRIZZ_BASE_URL"] || options.baseUrl || "https://telemetry.brizz.dev",
331
339
  headers: { ...options.headers },
332
340
  apiKey: process.env["BRIZZ_API_KEY"] || options.apiKey,
@@ -497,7 +505,7 @@ var import_sdk_logs2 = require("@opentelemetry/sdk-logs");
497
505
 
498
506
  // src/internal/version.ts
499
507
  function getSDKVersion() {
500
- return "0.1.17";
508
+ return "0.1.19";
501
509
  }
502
510
 
503
511
  // src/internal/log/processors/log-processor.ts
@@ -1137,6 +1145,8 @@ var PROPERTIES_CONTEXT_KEY = (0, import_api2.createContextKey)(PROPERTIES);
1137
1145
  var SESSION_OBJECT_CONTEXT_KEY = (0, import_api2.createContextKey)("brizz.session.object");
1138
1146
  var SESSION_INPUT = "brizz.session.input";
1139
1147
  var SESSION_OUTPUT = "brizz.session.output";
1148
+ var SESSION_INPUT_CONTEXT = "brizz.session.input.context";
1149
+ var SESSION_OUTPUT_CONTEXT = "brizz.session.output.context";
1140
1150
  var SESSION_SPAN_NAME = "brizz.start_session";
1141
1151
  var SESSION_TITLE_SPAN_NAME = "brizz.session_title";
1142
1152
  var SESSION_TITLE_GENERATION = "session.title_generation";
@@ -1306,6 +1316,7 @@ var LoggingModule = class _LoggingModule {
1306
1316
  serviceName: config.appName
1307
1317
  });
1308
1318
  const resourceAttributes = {
1319
+ ...config.resourceAttributes,
1309
1320
  "service.name": config.appName,
1310
1321
  [BRIZZ_SDK_VERSION]: getSDKVersion(),
1311
1322
  [BRIZZ_SDK_LANGUAGE]: SDK_LANGUAGE
@@ -1313,6 +1324,9 @@ var LoggingModule = class _LoggingModule {
1313
1324
  if (config.environment) {
1314
1325
  resourceAttributes["deployment.environment"] = config.environment;
1315
1326
  }
1327
+ if (config.appVersion) {
1328
+ resourceAttributes["service.version"] = config.appVersion;
1329
+ }
1316
1330
  const resource = (0, import_resources.resourceFromAttributes)(resourceAttributes);
1317
1331
  logger.debug("Creating logger provider with resource");
1318
1332
  this.loggerProvider = new import_sdk_logs2.LoggerProvider({
@@ -1502,13 +1516,16 @@ function getMetricsReader() {
1502
1516
  var import_exporter_trace_otlp_proto = require("@opentelemetry/exporter-trace-otlp-proto");
1503
1517
 
1504
1518
  // src/internal/trace/exporters/span-exporter.ts
1519
+ var import_core = require("@opentelemetry/core");
1505
1520
  var import_resources2 = require("@opentelemetry/resources");
1506
1521
  var BrizzSpanExporter = class {
1507
1522
  _delegate;
1508
1523
  _brizzResource;
1524
+ _beforeSendSpan;
1509
1525
  constructor(delegate, config) {
1510
1526
  this._delegate = delegate;
1511
1527
  const resourceAttrs = {
1528
+ ...config.resourceAttributes,
1512
1529
  "service.name": config.appName,
1513
1530
  [BRIZZ_SDK_VERSION]: getSDKVersion(),
1514
1531
  [BRIZZ_SDK_LANGUAGE]: SDK_LANGUAGE
@@ -1516,15 +1533,47 @@ var BrizzSpanExporter = class {
1516
1533
  if (config.environment) {
1517
1534
  resourceAttrs["deployment.environment"] = config.environment;
1518
1535
  }
1536
+ if (config.appVersion) {
1537
+ resourceAttrs["service.version"] = config.appVersion;
1538
+ }
1519
1539
  this._brizzResource = (0, import_resources2.resourceFromAttributes)(resourceAttrs);
1540
+ this._beforeSendSpan = config.beforeSendSpan;
1520
1541
  }
1521
1542
  export(spans, resultCallback) {
1543
+ if (spans.length === 0) {
1544
+ resultCallback({ code: import_core.ExportResultCode.SUCCESS });
1545
+ return;
1546
+ }
1522
1547
  const patchedSpans = spans.map((span) => ({
1523
1548
  ...span,
1524
1549
  resource: span.resource.merge(this._brizzResource),
1525
1550
  spanContext: span.spanContext.bind(span)
1526
1551
  }));
1527
- this._delegate.export(patchedSpans, resultCallback);
1552
+ const filter = this._beforeSendSpan;
1553
+ if (!filter) {
1554
+ this._delegate.export(patchedSpans, resultCallback);
1555
+ return;
1556
+ }
1557
+ const verdicts = patchedSpans.map((span) => {
1558
+ try {
1559
+ return Promise.resolve(filter(span));
1560
+ } catch (error) {
1561
+ logger.warn("beforeSendSpan threw; span will be kept", { error });
1562
+ return Promise.resolve(true);
1563
+ }
1564
+ });
1565
+ Promise.all(verdicts).then((keep) => {
1566
+ const filtered = patchedSpans.filter((_, i) => keep[i] !== false);
1567
+ if (filtered.length === 0) {
1568
+ resultCallback({ code: import_core.ExportResultCode.SUCCESS });
1569
+ return;
1570
+ }
1571
+ this._delegate.export(filtered, resultCallback);
1572
+ return;
1573
+ }).catch((error) => {
1574
+ logger.warn("beforeSendSpan rejected; all spans will be kept", { error });
1575
+ this._delegate.export(patchedSpans, resultCallback);
1576
+ });
1528
1577
  }
1529
1578
  async shutdown() {
1530
1579
  return this._delegate.shutdown();
@@ -1537,6 +1586,14 @@ var BrizzSpanExporter = class {
1537
1586
  // src/internal/trace/processors/span-processor.ts
1538
1587
  var import_api4 = require("@opentelemetry/api");
1539
1588
  var import_sdk_trace_base = require("@opentelemetry/sdk-trace-base");
1589
+ function applyContextAttributes(span) {
1590
+ const sessionProperties = import_api4.context.active().getValue(PROPERTIES_CONTEXT_KEY);
1591
+ if (sessionProperties) {
1592
+ for (const [key, value] of Object.entries(sessionProperties)) {
1593
+ span.setAttribute(`${BRIZZ}.${key}`, value);
1594
+ }
1595
+ }
1596
+ }
1540
1597
  var DEFAULT_MASKING_RULES = [
1541
1598
  {
1542
1599
  mode: "partial",
@@ -1571,12 +1628,7 @@ var BrizzSimpleSpanProcessor = class extends import_sdk_trace_base.SimpleSpanPro
1571
1628
  if (maskingConfig) {
1572
1629
  maskSpan(span, maskingConfig);
1573
1630
  }
1574
- const associationProperties = import_api4.context.active().getValue(PROPERTIES_CONTEXT_KEY);
1575
- if (associationProperties) {
1576
- for (const [key, value] of Object.entries(associationProperties)) {
1577
- span.setAttribute(`${BRIZZ}.${key}`, value);
1578
- }
1579
- }
1631
+ applyContextAttributes(span);
1580
1632
  super.onStart(span, parentContext);
1581
1633
  }
1582
1634
  };
@@ -1591,12 +1643,7 @@ var BrizzBatchSpanProcessor = class extends import_sdk_trace_base.BatchSpanProce
1591
1643
  if (maskingConfig) {
1592
1644
  maskSpan(span, maskingConfig);
1593
1645
  }
1594
- const associationProperties = import_api4.context.active().getValue(PROPERTIES_CONTEXT_KEY);
1595
- if (associationProperties) {
1596
- for (const [key, value] of Object.entries(associationProperties)) {
1597
- span.setAttribute(`${BRIZZ}.${key}`, value);
1598
- }
1599
- }
1646
+ applyContextAttributes(span);
1600
1647
  super.onStart(span, parentContext);
1601
1648
  }
1602
1649
  };
@@ -1770,31 +1817,45 @@ var Session = class {
1770
1817
  span;
1771
1818
  inputs = [];
1772
1819
  outputs = [];
1820
+ inputContexts = [];
1821
+ outputContexts = [];
1773
1822
  constructor(sessionId, span) {
1774
1823
  this.sessionId = sessionId;
1775
1824
  this.span = span;
1776
1825
  }
1777
1826
  /**
1778
- * (Optional) Append text to session input tracking.
1779
- * Use when you need to track specific input data that differs from what's sent to the LLM.
1780
- * Multiple calls accumulate in an array.
1827
+ * Append a user turn to session input tracking.
1781
1828
  *
1782
- * @param text - Text to append to session input, or null to append null
1829
+ * Each call appends one element to `brizz.session.input` (the text) AND one
1830
+ * element to `brizz.session.input.context` (the per-turn context bag). The
1831
+ * two arrays stay index-aligned — the ingestion pipeline zips them together
1832
+ * so the i-th context bag lands on the i-th user_display conversation item's
1833
+ * `span_attributes` map.
1834
+ *
1835
+ * @param text - Text to append (null becomes a null/"hide marker")
1836
+ * @param context - Optional per-turn context bag to attach to this turn
1783
1837
  */
1784
- setInput(text) {
1838
+ setInput(text, context4) {
1785
1839
  this.inputs.push(text);
1840
+ this.inputContexts.push(context4 ?? {});
1786
1841
  this.span.setAttribute(SESSION_INPUT, JSON.stringify(this.inputs));
1842
+ this.span.setAttribute(SESSION_INPUT_CONTEXT, JSON.stringify(this.inputContexts));
1787
1843
  }
1788
1844
  /**
1789
- * (Optional) Append text to session output tracking.
1790
- * Use when you need to track specific output data that differs from what's received from the LLM.
1791
- * Multiple calls accumulate in an array.
1845
+ * Append an assistant turn to session output tracking.
1846
+ *
1847
+ * Symmetric to {@link setInput} appends one text element and one
1848
+ * context-bag element to the index-aligned `brizz.session.output` /
1849
+ * `brizz.session.output.context` arrays.
1792
1850
  *
1793
- * @param text - Text to append to session output, or null to append null
1851
+ * @param text - Text to append (null becomes a null/"hide marker")
1852
+ * @param context - Optional per-turn context bag to attach to this turn
1794
1853
  */
1795
- setOutput(text) {
1854
+ setOutput(text, context4) {
1796
1855
  this.outputs.push(text);
1856
+ this.outputContexts.push(context4 ?? {});
1797
1857
  this.span.setAttribute(SESSION_OUTPUT, JSON.stringify(this.outputs));
1858
+ this.span.setAttribute(SESSION_OUTPUT_CONTEXT, JSON.stringify(this.outputContexts));
1798
1859
  }
1799
1860
  /**
1800
1861
  * Set the session title on the span.
@@ -1991,6 +2052,7 @@ var _Brizz = class __Brizz {
1991
2052
  const registry = InstrumentationRegistry.getInstance();
1992
2053
  const manualInstrumentations = registry.getManualInstrumentations();
1993
2054
  const resourceAttributes = {
2055
+ ...resolvedConfig.resourceAttributes,
1994
2056
  "service.name": resolvedConfig.appName,
1995
2057
  [BRIZZ_SDK_VERSION]: getSDKVersion(),
1996
2058
  [BRIZZ_SDK_LANGUAGE]: SDK_LANGUAGE
@@ -1998,6 +2060,9 @@ var _Brizz = class __Brizz {
1998
2060
  if (resolvedConfig.environment) {
1999
2061
  resourceAttributes["deployment.environment"] = resolvedConfig.environment;
2000
2062
  }
2063
+ if (resolvedConfig.appVersion) {
2064
+ resourceAttributes["service.version"] = resolvedConfig.appVersion;
2065
+ }
2001
2066
  this._sdk = new import_sdk_node.NodeSDK({
2002
2067
  spanProcessors: resolvedConfig.disableSpanExporter ? [] : [getSpanProcessor()],
2003
2068
  metricReader: getMetricsReader(),