@brizz/sdk 0.1.27 → 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/README.md CHANGED
@@ -21,6 +21,7 @@ libraries including OpenAI, Anthropic, Vercel AI SDK, and more.
21
21
  - [Custom Events & Logging](#custom-events--logging)
22
22
  - [Environment Variables](#environment-variables)
23
23
  - [Disable Span Export](#disable-span-export)
24
+ - [Dropping Spans](#dropping-spans)
24
25
  - [Advanced Configuration](#advanced-configuration)
25
26
  - [Testing & Development](#testing--development)
26
27
  - [Package.json Examples](#packagejson-examples)
@@ -290,6 +291,7 @@ const result = await startSession(
290
291
  - `session.setOutput(text, context?)` - (Optional) Manually track output text; optional context bag
291
292
  attaches per-turn metadata rendered in the dashboard's Context panel
292
293
  - `session.setTitle(text)` - Set a session title (typically used with `mode: 'title'`)
294
+ - `session.addExternalLink(url, options?)` - (Optional) Attach an external link (e.g. a Datadog trace or dashboard) to the session; it appears on the session detail panel. Also available as the top-level `addExternalLink(url, options?)`.
293
295
 
294
296
  **Per-turn context example:**
295
297
 
@@ -495,7 +497,7 @@ Brizz.initialize({
495
497
  Emit custom events and structured logs:
496
498
 
497
499
  ```typescript
498
- import { emitEvent, logger } from '@brizz/sdk';
500
+ import { emitEvent, emitEventWithSessionId, logger } from '@brizz/sdk';
499
501
 
500
502
  // Emit custom events
501
503
  emitEvent('user.signup', {
@@ -510,6 +512,11 @@ emitEvent('ai.request.completed', {
510
512
  latency: 1200,
511
513
  });
512
514
 
515
+ // Emit with a known session ID, outside any session scope
516
+ emitEventWithSessionId('session-123', 'user.feedback.submitted', {
517
+ rating: 5,
518
+ });
519
+
513
520
  // Structured logging
514
521
  logger.info('Processing user request', { userId: '123', requestId: 'req-456' });
515
522
  logger.error('AI request failed', { error: err.message, model: 'gpt-4' });
@@ -546,6 +553,37 @@ Brizz.initialize({ apiKey: 'your-api-key', disableSpanExporter: true });
546
553
 
547
554
  Or via env var: `BRIZZ_DISABLE_SPAN_EXPORTER=true`.
548
555
 
556
+ ## Dropping Spans
557
+
558
+ Filter spans before export with `beforeSendSpan`. Return `false` to drop a span, `true` to keep it. Useful for stripping noisy paths (health checks, internal tooling) or excluding telemetry for specific end-users.
559
+
560
+ ```typescript
561
+ Brizz.initialize({
562
+ apiKey: 'your-api-key',
563
+ beforeSendSpan: (span) => {
564
+ // OpenInference (LangChain JS, LangGraph JS) packs per-call
565
+ // `config.metadata` into a JSON-stringified `metadata` attribute.
566
+ const raw = span.attributes['metadata'];
567
+ if (typeof raw !== 'string') return true;
568
+ try {
569
+ return JSON.parse(raw).customer_id !== 'cust_42';
570
+ } catch {
571
+ return true;
572
+ }
573
+ },
574
+ });
575
+ ```
576
+
577
+ Tag the call so the filter has something to match on:
578
+
579
+ ```typescript
580
+ await llm.invoke([new HumanMessage('Hello')], {
581
+ metadata: { customer_id: 'cust_42' },
582
+ });
583
+ ```
584
+
585
+ Both sync and async filters are supported. Exceptions are caught and the span passes through.
586
+
549
587
  ## Advanced Configuration
550
588
 
551
589
  ```typescript
package/dist/index.cjs CHANGED
@@ -305,7 +305,7 @@ var init_schemas = __esm({
305
305
  });
306
306
 
307
307
  // src/internal/semantic-conventions.ts
308
- var import_api3, 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, INTERRUPT_TOOLS;
308
+ var import_api3, 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;
309
309
  var init_semantic_conventions2 = __esm({
310
310
  "src/internal/semantic-conventions.ts"() {
311
311
  "use strict";
@@ -320,10 +320,17 @@ var init_semantic_conventions2 = __esm({
320
320
  SESSION_INPUT_CONTEXT = "brizz.session.input.context";
321
321
  SESSION_OUTPUT_CONTEXT = "brizz.session.output.context";
322
322
  SESSION_SPAN_NAME = "brizz.start_session";
323
+ MUTE_INPUT = "mute.input";
324
+ MUTE_OUTPUT = "mute.output";
323
325
  SESSION_TITLE_SPAN_NAME = "brizz.session_title";
324
326
  SESSION_TITLE_GENERATION = "session.title_generation";
325
327
  SESSION_TITLE = "brizz.session.title";
326
328
  INTERRUPT_TOOLS = "brizz.internal.interrupt";
329
+ INTERNAL_EVENT_PREFIX = "brizz.internal.";
330
+ EXTERNAL_LINK_EVENT_NAME = "brizz.internal.external_link";
331
+ EXTERNAL_LINK_URL = "brizz.internal.external_link.url";
332
+ EXTERNAL_LINK_TITLE = "brizz.internal.external_link.title";
333
+ EXTERNAL_LINK_TYPE = "brizz.internal.external_link.type";
327
334
  }
328
335
  });
329
336
 
@@ -791,7 +798,7 @@ var init_protocol = __esm({
791
798
 
792
799
  // src/internal/version.ts
793
800
  function getSDKVersion() {
794
- return "0.1.27";
801
+ return "0.1.28";
795
802
  }
796
803
  var init_version = __esm({
797
804
  "src/internal/version.ts"() {
@@ -1076,10 +1083,13 @@ __export(src_exports, {
1076
1083
  Session: () => Session,
1077
1084
  SessionTitle: () => SessionTitle,
1078
1085
  SeverityNumber: () => import_api_logs2.SeverityNumber,
1086
+ addExternalLink: () => addExternalLink,
1087
+ callWithMute: () => callWithMute,
1079
1088
  callWithProperties: () => callWithProperties,
1080
1089
  callWithSessionId: () => callWithSessionId,
1081
1090
  detectRuntime: () => detectRuntime,
1082
1091
  emitEvent: () => emitEvent,
1092
+ emitEventWithSessionId: () => emitEventWithSessionId,
1083
1093
  getActiveSession: () => getActiveSession,
1084
1094
  getLogLevel: () => getLogLevel,
1085
1095
  getMetricsExporter: () => getMetricsExporter,
@@ -1094,6 +1104,7 @@ __export(src_exports, {
1094
1104
  setLogLevel: () => setLogLevel,
1095
1105
  startSession: () => startSession,
1096
1106
  startSessionTitle: () => startSessionTitle,
1107
+ withMute: () => withMute,
1097
1108
  withProperties: () => withProperties,
1098
1109
  withSessionId: () => withSessionId
1099
1110
  });
@@ -1531,10 +1542,282 @@ var import_exporter_logs_otlp_http = require("@opentelemetry/exporter-logs-otlp-
1531
1542
  var import_resources = require("@opentelemetry/resources");
1532
1543
  var import_sdk_logs2 = require("@opentelemetry/sdk-logs");
1533
1544
  init_logger();
1545
+
1546
+ // src/internal/trace/session.ts
1547
+ var import_api9 = require("@opentelemetry/api");
1548
+ init_logger();
1549
+ init_semantic_conventions2();
1550
+ function setCurrentSpanCustomProperties(properties) {
1551
+ const current = import_api9.trace.getActiveSpan();
1552
+ if (!current || !current.isRecording()) {
1553
+ return;
1554
+ }
1555
+ for (const [key, value] of Object.entries(properties)) {
1556
+ try {
1557
+ current.setAttribute(`${BRIZZ}.${key}`, value);
1558
+ } catch {
1559
+ }
1560
+ }
1561
+ }
1562
+ function callWithProperties(properties, fn, thisArg, ...args) {
1563
+ const base = import_api9.context.active();
1564
+ const prev = base.getValue(PROPERTIES_CONTEXT_KEY);
1565
+ const merged = prev ? { ...prev, ...properties } : properties;
1566
+ const next = base.setValue(PROPERTIES_CONTEXT_KEY, merged);
1567
+ return import_api9.context.with(next, fn, thisArg, ...args);
1568
+ }
1569
+ function withProperties(properties, fn, thisArg) {
1570
+ return function wrapped(...args) {
1571
+ return callWithProperties(
1572
+ properties,
1573
+ fn,
1574
+ thisArg !== void 0 ? thisArg : this,
1575
+ ...args
1576
+ );
1577
+ };
1578
+ }
1579
+ function muteProperties(options) {
1580
+ const { input = true, output = true } = options;
1581
+ const properties = {};
1582
+ if (input) {
1583
+ properties[MUTE_INPUT] = "true";
1584
+ }
1585
+ if (output) {
1586
+ properties[MUTE_OUTPUT] = "true";
1587
+ }
1588
+ return properties;
1589
+ }
1590
+ function callWithMute(options, fn, thisArg, ...args) {
1591
+ return callWithProperties(muteProperties(options), fn, thisArg, ...args);
1592
+ }
1593
+ function withMute(options, fn, thisArg) {
1594
+ return withProperties(muteProperties(options), fn, thisArg);
1595
+ }
1596
+ function withSessionId(sessionId, fn, thisArg, extraProperties) {
1597
+ const properties = { [SESSION_ID]: sessionId, ...extraProperties };
1598
+ return withProperties(properties, fn, thisArg);
1599
+ }
1600
+ function callWithSessionId(sessionId, fn, thisArg, ...args) {
1601
+ return callWithProperties({ [SESSION_ID]: sessionId }, fn, thisArg, ...args);
1602
+ }
1603
+ var Session = class {
1604
+ sessionId;
1605
+ span;
1606
+ inputs = [];
1607
+ outputs = [];
1608
+ inputContexts = [];
1609
+ outputContexts = [];
1610
+ constructor(sessionId, span) {
1611
+ this.sessionId = sessionId;
1612
+ this.span = span;
1613
+ }
1614
+ /**
1615
+ * Append a user turn to session input tracking.
1616
+ *
1617
+ * Each call appends one element to `brizz.session.input` (the text) AND one
1618
+ * element to `brizz.session.input.context` (the per-turn context bag). The
1619
+ * two arrays stay index-aligned — the ingestion pipeline zips them together
1620
+ * so the i-th context bag lands on the i-th user_display conversation item's
1621
+ * `span_attributes` map.
1622
+ *
1623
+ * @param text - Text to append (null becomes a null/"hide marker")
1624
+ * @param context - Optional per-turn context bag to attach to this turn
1625
+ */
1626
+ setInput(text, context6) {
1627
+ this.inputs.push(text);
1628
+ this.inputContexts.push(context6 ?? {});
1629
+ this.span.setAttribute(SESSION_INPUT, JSON.stringify(this.inputs));
1630
+ this.span.setAttribute(SESSION_INPUT_CONTEXT, JSON.stringify(this.inputContexts));
1631
+ }
1632
+ /**
1633
+ * Append an assistant turn to session output tracking.
1634
+ *
1635
+ * Symmetric to {@link setInput} — appends one text element and one
1636
+ * context-bag element to the index-aligned `brizz.session.output` /
1637
+ * `brizz.session.output.context` arrays.
1638
+ *
1639
+ * @param text - Text to append (null becomes a null/"hide marker")
1640
+ * @param context - Optional per-turn context bag to attach to this turn
1641
+ */
1642
+ setOutput(text, context6) {
1643
+ this.outputs.push(text);
1644
+ this.outputContexts.push(context6 ?? {});
1645
+ this.span.setAttribute(SESSION_OUTPUT, JSON.stringify(this.outputs));
1646
+ this.span.setAttribute(SESSION_OUTPUT_CONTEXT, JSON.stringify(this.outputContexts));
1647
+ }
1648
+ /**
1649
+ * Set the session title on the span.
1650
+ *
1651
+ * @param title - The generated title string
1652
+ */
1653
+ setTitle(title) {
1654
+ this.span.setAttribute(SESSION_TITLE, title);
1655
+ }
1656
+ /**
1657
+ * Update custom properties on the session span.
1658
+ * Properties are prefixed with 'brizz.'.
1659
+ *
1660
+ * @param properties - Key-value properties to set on the session
1661
+ */
1662
+ updateProperties(properties) {
1663
+ for (const [key, value] of Object.entries(properties)) {
1664
+ this.span.setAttribute(`${BRIZZ}.${key}`, value);
1665
+ }
1666
+ }
1667
+ /**
1668
+ * Attach an external link (URL) to this session.
1669
+ *
1670
+ * The link surfaces on the session's detail panel in Brizz — use it to
1671
+ * correlate a session with an external record such as a Datadog trace,
1672
+ * Sentry issue, or internal dashboard. Re-sending the same URL is idempotent;
1673
+ * distinct URLs add separate links.
1674
+ *
1675
+ * @param url - The link target
1676
+ * @param options - Optional `title` (defaults to the URL host) and `linkType`
1677
+ * (free-form category, defaults to `'generic'`)
1678
+ */
1679
+ addExternalLink(url, options) {
1680
+ emitExternalLink(this.sessionId, url, options?.title, options?.linkType);
1681
+ }
1682
+ };
1683
+ var SessionTitle = class {
1684
+ span;
1685
+ constructor(span) {
1686
+ this.span = span;
1687
+ }
1688
+ /**
1689
+ * Set the generated title on the wrapper span.
1690
+ *
1691
+ * @param title - The generated title string
1692
+ */
1693
+ setTitle(title) {
1694
+ this.span.setAttribute(SESSION_TITLE, title);
1695
+ }
1696
+ };
1697
+ function getActiveSession() {
1698
+ return import_api9.context.active().getValue(SESSION_OBJECT_CONTEXT_KEY);
1699
+ }
1700
+ function resolveSessionIdFromContext() {
1701
+ const active = getActiveSession();
1702
+ if (active) {
1703
+ return active.sessionId;
1704
+ }
1705
+ const props = import_api9.context.active().getValue(PROPERTIES_CONTEXT_KEY);
1706
+ return props?.[SESSION_ID];
1707
+ }
1708
+ function emitExternalLink(sessionId, url, title, linkType) {
1709
+ try {
1710
+ emitEventWithSessionId(sessionId, EXTERNAL_LINK_EVENT_NAME, {
1711
+ [EXTERNAL_LINK_URL]: url,
1712
+ [EXTERNAL_LINK_TITLE]: title ?? "",
1713
+ [EXTERNAL_LINK_TYPE]: linkType ?? "generic"
1714
+ });
1715
+ } catch (error) {
1716
+ logger.warn("addExternalLink: failed to emit external link", error);
1717
+ }
1718
+ }
1719
+ function addExternalLink(url, options) {
1720
+ const sessionId = options?.sessionId ?? resolveSessionIdFromContext();
1721
+ if (!sessionId) {
1722
+ logger.warn(
1723
+ "addExternalLink called without a resolvable session id; link dropped. Pass options.sessionId or call inside a startSession/callWithSessionId scope."
1724
+ );
1725
+ return;
1726
+ }
1727
+ emitExternalLink(sessionId, url, options?.title, options?.linkType);
1728
+ }
1729
+ function startSession(sessionId, callback, extraProperties, options) {
1730
+ const isTitle = options?.mode === "title";
1731
+ const spanName = isTitle ? SESSION_TITLE_SPAN_NAME : SESSION_SPAN_NAME;
1732
+ const tracer = import_api9.trace.getTracer("@brizz/sdk");
1733
+ return tracer.startActiveSpan(spanName, (span) => {
1734
+ span.setAttribute(`${BRIZZ}.${SESSION_ID}`, sessionId);
1735
+ if (extraProperties) {
1736
+ for (const [key, value] of Object.entries(extraProperties)) {
1737
+ span.setAttribute(`${BRIZZ}.${key}`, value);
1738
+ }
1739
+ }
1740
+ const session = new Session(sessionId, span);
1741
+ const contextProperties = { [SESSION_ID]: sessionId };
1742
+ if (isTitle) {
1743
+ contextProperties[SESSION_TITLE_GENERATION] = "true";
1744
+ }
1745
+ if (extraProperties) {
1746
+ for (const [key, value] of Object.entries(extraProperties)) {
1747
+ contextProperties[key] = String(value);
1748
+ }
1749
+ }
1750
+ return callWithProperties(contextProperties, () => {
1751
+ const sessionCtx = import_api9.context.active().setValue(SESSION_OBJECT_CONTEXT_KEY, session);
1752
+ return import_api9.context.with(sessionCtx, () => {
1753
+ try {
1754
+ const result = callback(session);
1755
+ if (result && typeof result.then === "function") {
1756
+ return result.then((value) => {
1757
+ span.end();
1758
+ return value;
1759
+ }).catch((error) => {
1760
+ span.recordException(error);
1761
+ span.setStatus({ code: import_api9.SpanStatusCode.ERROR });
1762
+ span.end();
1763
+ throw error;
1764
+ });
1765
+ }
1766
+ span.end();
1767
+ return result;
1768
+ } catch (error) {
1769
+ span.recordException(error);
1770
+ span.setStatus({ code: import_api9.SpanStatusCode.ERROR });
1771
+ span.end();
1772
+ throw error;
1773
+ }
1774
+ });
1775
+ });
1776
+ });
1777
+ }
1778
+ function startSessionTitle(callback, options) {
1779
+ const resolvedSessionId = options?.sessionId ?? getActiveSession()?.sessionId;
1780
+ const tracer = import_api9.trace.getTracer("@brizz/sdk");
1781
+ return tracer.startActiveSpan(SESSION_TITLE_SPAN_NAME, (span) => {
1782
+ if (resolvedSessionId) {
1783
+ span.setAttribute(`${BRIZZ}.${SESSION_ID}`, resolvedSessionId);
1784
+ }
1785
+ const sessionTitle = new SessionTitle(span);
1786
+ const properties = { [SESSION_TITLE_GENERATION]: "true" };
1787
+ if (resolvedSessionId) {
1788
+ properties[SESSION_ID] = resolvedSessionId;
1789
+ }
1790
+ return callWithProperties(properties, () => {
1791
+ try {
1792
+ const result = callback(sessionTitle);
1793
+ if (result && typeof result.then === "function") {
1794
+ return result.then((value) => {
1795
+ span.end();
1796
+ return value;
1797
+ }).catch((error) => {
1798
+ span.recordException(error);
1799
+ span.setStatus({ code: import_api9.SpanStatusCode.ERROR });
1800
+ span.end();
1801
+ throw error;
1802
+ });
1803
+ }
1804
+ span.end();
1805
+ return result;
1806
+ } catch (error) {
1807
+ span.recordException(error);
1808
+ span.setStatus({ code: import_api9.SpanStatusCode.ERROR });
1809
+ span.end();
1810
+ throw error;
1811
+ }
1812
+ });
1813
+ });
1814
+ }
1815
+
1816
+ // src/internal/log/logging.ts
1534
1817
  init_version();
1535
1818
 
1536
1819
  // src/internal/log/processors/log-processor.ts
1537
- var import_api9 = require("@opentelemetry/api");
1820
+ var import_api10 = require("@opentelemetry/api");
1538
1821
  var import_sdk_logs = require("@opentelemetry/sdk-logs");
1539
1822
  init_logger();
1540
1823
 
@@ -1966,7 +2249,7 @@ var BrizzSimpleLogRecordProcessor = class extends import_sdk_logs.SimpleLogRecor
1966
2249
  if (maskingConfig) {
1967
2250
  maskLog(logRecord, maskingConfig);
1968
2251
  }
1969
- const associationProperties = import_api9.context.active().getValue(PROPERTIES_CONTEXT_KEY);
2252
+ const associationProperties = import_api10.context.active().getValue(PROPERTIES_CONTEXT_KEY);
1970
2253
  if (associationProperties) {
1971
2254
  for (const [key, value] of Object.entries(associationProperties)) {
1972
2255
  logRecord.setAttribute(`${BRIZZ}.${key}`, value);
@@ -1986,7 +2269,7 @@ var BrizzBatchLogRecordProcessor = class extends import_sdk_logs.BatchLogRecordP
1986
2269
  if (maskingConfig) {
1987
2270
  maskLog(logRecord, maskingConfig);
1988
2271
  }
1989
- const associationProperties = import_api9.context.active().getValue(PROPERTIES_CONTEXT_KEY);
2272
+ const associationProperties = import_api10.context.active().getValue(PROPERTIES_CONTEXT_KEY);
1990
2273
  if (associationProperties) {
1991
2274
  for (const [key, value] of Object.entries(associationProperties)) {
1992
2275
  logRecord.setAttribute(`${BRIZZ}.${key}`, value);
@@ -2015,6 +2298,11 @@ function maskLog(logRecord, config) {
2015
2298
  for (const [key, value] of Object.entries(maskedAttributes)) {
2016
2299
  newAttributes[key] = value;
2017
2300
  }
2301
+ for (const [key, value] of Object.entries(logRecord.attributes)) {
2302
+ if (key.startsWith(INTERNAL_EVENT_PREFIX)) {
2303
+ newAttributes[key] = value;
2304
+ }
2305
+ }
2018
2306
  logRecord.setAttributes(newAttributes);
2019
2307
  }
2020
2308
  }
@@ -2204,6 +2492,11 @@ var LoggingModule = class _LoggingModule {
2204
2492
  function emitEvent(name, attributes, body, severityNumber = import_api_logs.SeverityNumber.INFO) {
2205
2493
  return LoggingModule.getInstance().emitEvent(name, attributes, body, severityNumber);
2206
2494
  }
2495
+ function emitEventWithSessionId(sessionId, name, attributes, body, severityNumber = import_api_logs.SeverityNumber.INFO) {
2496
+ return callWithSessionId(sessionId, () => {
2497
+ LoggingModule.getInstance().emitEvent(name, attributes, body, severityNumber);
2498
+ });
2499
+ }
2207
2500
 
2208
2501
  // src/internal/sdk.ts
2209
2502
  init_logger();
@@ -2386,12 +2679,12 @@ var BrizzSpanExporter = class {
2386
2679
  };
2387
2680
 
2388
2681
  // src/internal/trace/processors/span-processor.ts
2389
- var import_api10 = require("@opentelemetry/api");
2682
+ var import_api11 = require("@opentelemetry/api");
2390
2683
  var import_sdk_trace_base = require("@opentelemetry/sdk-trace-base");
2391
2684
  init_logger();
2392
2685
  init_semantic_conventions2();
2393
2686
  function applyContextAttributes(span) {
2394
- const sessionProperties = import_api10.context.active().getValue(PROPERTIES_CONTEXT_KEY);
2687
+ const sessionProperties = import_api11.context.active().getValue(PROPERTIES_CONTEXT_KEY);
2395
2688
  if (sessionProperties) {
2396
2689
  for (const [key, value] of Object.entries(sessionProperties)) {
2397
2690
  span.setAttribute(`${BRIZZ}.${key}`, value);
@@ -2576,214 +2869,6 @@ function getSpanProcessor() {
2576
2869
  return TracingModule.getInstance().getSpanProcessor();
2577
2870
  }
2578
2871
 
2579
- // src/internal/trace/session.ts
2580
- var import_api11 = require("@opentelemetry/api");
2581
- init_semantic_conventions2();
2582
- function setCurrentSpanCustomProperties(properties) {
2583
- const current = import_api11.trace.getActiveSpan();
2584
- if (!current || !current.isRecording()) {
2585
- return;
2586
- }
2587
- for (const [key, value] of Object.entries(properties)) {
2588
- try {
2589
- current.setAttribute(`${BRIZZ}.${key}`, value);
2590
- } catch {
2591
- }
2592
- }
2593
- }
2594
- function callWithProperties(properties, fn, thisArg, ...args) {
2595
- const base = import_api11.context.active();
2596
- const prev = base.getValue(PROPERTIES_CONTEXT_KEY);
2597
- const merged = prev ? { ...prev, ...properties } : properties;
2598
- const next = base.setValue(PROPERTIES_CONTEXT_KEY, merged);
2599
- return import_api11.context.with(next, fn, thisArg, ...args);
2600
- }
2601
- function withProperties(properties, fn, thisArg) {
2602
- return function wrapped(...args) {
2603
- return callWithProperties(
2604
- properties,
2605
- fn,
2606
- thisArg !== void 0 ? thisArg : this,
2607
- ...args
2608
- );
2609
- };
2610
- }
2611
- function withSessionId(sessionId, fn, thisArg, extraProperties) {
2612
- const properties = { [SESSION_ID]: sessionId, ...extraProperties };
2613
- return withProperties(properties, fn, thisArg);
2614
- }
2615
- function callWithSessionId(sessionId, fn, thisArg, ...args) {
2616
- return callWithProperties({ [SESSION_ID]: sessionId }, fn, thisArg, ...args);
2617
- }
2618
- var Session = class {
2619
- sessionId;
2620
- span;
2621
- inputs = [];
2622
- outputs = [];
2623
- inputContexts = [];
2624
- outputContexts = [];
2625
- constructor(sessionId, span) {
2626
- this.sessionId = sessionId;
2627
- this.span = span;
2628
- }
2629
- /**
2630
- * Append a user turn to session input tracking.
2631
- *
2632
- * Each call appends one element to `brizz.session.input` (the text) AND one
2633
- * element to `brizz.session.input.context` (the per-turn context bag). The
2634
- * two arrays stay index-aligned — the ingestion pipeline zips them together
2635
- * so the i-th context bag lands on the i-th user_display conversation item's
2636
- * `span_attributes` map.
2637
- *
2638
- * @param text - Text to append (null becomes a null/"hide marker")
2639
- * @param context - Optional per-turn context bag to attach to this turn
2640
- */
2641
- setInput(text, context6) {
2642
- this.inputs.push(text);
2643
- this.inputContexts.push(context6 ?? {});
2644
- this.span.setAttribute(SESSION_INPUT, JSON.stringify(this.inputs));
2645
- this.span.setAttribute(SESSION_INPUT_CONTEXT, JSON.stringify(this.inputContexts));
2646
- }
2647
- /**
2648
- * Append an assistant turn to session output tracking.
2649
- *
2650
- * Symmetric to {@link setInput} — appends one text element and one
2651
- * context-bag element to the index-aligned `brizz.session.output` /
2652
- * `brizz.session.output.context` arrays.
2653
- *
2654
- * @param text - Text to append (null becomes a null/"hide marker")
2655
- * @param context - Optional per-turn context bag to attach to this turn
2656
- */
2657
- setOutput(text, context6) {
2658
- this.outputs.push(text);
2659
- this.outputContexts.push(context6 ?? {});
2660
- this.span.setAttribute(SESSION_OUTPUT, JSON.stringify(this.outputs));
2661
- this.span.setAttribute(SESSION_OUTPUT_CONTEXT, JSON.stringify(this.outputContexts));
2662
- }
2663
- /**
2664
- * Set the session title on the span.
2665
- *
2666
- * @param title - The generated title string
2667
- */
2668
- setTitle(title) {
2669
- this.span.setAttribute(SESSION_TITLE, title);
2670
- }
2671
- /**
2672
- * Update custom properties on the session span.
2673
- * Properties are prefixed with 'brizz.'.
2674
- *
2675
- * @param properties - Key-value properties to set on the session
2676
- */
2677
- updateProperties(properties) {
2678
- for (const [key, value] of Object.entries(properties)) {
2679
- this.span.setAttribute(`${BRIZZ}.${key}`, value);
2680
- }
2681
- }
2682
- };
2683
- var SessionTitle = class {
2684
- span;
2685
- constructor(span) {
2686
- this.span = span;
2687
- }
2688
- /**
2689
- * Set the generated title on the wrapper span.
2690
- *
2691
- * @param title - The generated title string
2692
- */
2693
- setTitle(title) {
2694
- this.span.setAttribute(SESSION_TITLE, title);
2695
- }
2696
- };
2697
- function getActiveSession() {
2698
- return import_api11.context.active().getValue(SESSION_OBJECT_CONTEXT_KEY);
2699
- }
2700
- function startSession(sessionId, callback, extraProperties, options) {
2701
- const isTitle = options?.mode === "title";
2702
- const spanName = isTitle ? SESSION_TITLE_SPAN_NAME : SESSION_SPAN_NAME;
2703
- const tracer = import_api11.trace.getTracer("@brizz/sdk");
2704
- return tracer.startActiveSpan(spanName, (span) => {
2705
- span.setAttribute(`${BRIZZ}.${SESSION_ID}`, sessionId);
2706
- if (extraProperties) {
2707
- for (const [key, value] of Object.entries(extraProperties)) {
2708
- span.setAttribute(`${BRIZZ}.${key}`, value);
2709
- }
2710
- }
2711
- const session = new Session(sessionId, span);
2712
- const contextProperties = { [SESSION_ID]: sessionId };
2713
- if (isTitle) {
2714
- contextProperties[SESSION_TITLE_GENERATION] = "true";
2715
- }
2716
- if (extraProperties) {
2717
- for (const [key, value] of Object.entries(extraProperties)) {
2718
- contextProperties[key] = String(value);
2719
- }
2720
- }
2721
- return callWithProperties(contextProperties, () => {
2722
- const sessionCtx = import_api11.context.active().setValue(SESSION_OBJECT_CONTEXT_KEY, session);
2723
- return import_api11.context.with(sessionCtx, () => {
2724
- try {
2725
- const result = callback(session);
2726
- if (result && typeof result.then === "function") {
2727
- return result.then((value) => {
2728
- span.end();
2729
- return value;
2730
- }).catch((error) => {
2731
- span.recordException(error);
2732
- span.setStatus({ code: import_api11.SpanStatusCode.ERROR });
2733
- span.end();
2734
- throw error;
2735
- });
2736
- }
2737
- span.end();
2738
- return result;
2739
- } catch (error) {
2740
- span.recordException(error);
2741
- span.setStatus({ code: import_api11.SpanStatusCode.ERROR });
2742
- span.end();
2743
- throw error;
2744
- }
2745
- });
2746
- });
2747
- });
2748
- }
2749
- function startSessionTitle(callback, options) {
2750
- const resolvedSessionId = options?.sessionId ?? getActiveSession()?.sessionId;
2751
- const tracer = import_api11.trace.getTracer("@brizz/sdk");
2752
- return tracer.startActiveSpan(SESSION_TITLE_SPAN_NAME, (span) => {
2753
- if (resolvedSessionId) {
2754
- span.setAttribute(`${BRIZZ}.${SESSION_ID}`, resolvedSessionId);
2755
- }
2756
- const sessionTitle = new SessionTitle(span);
2757
- const properties = { [SESSION_TITLE_GENERATION]: "true" };
2758
- if (resolvedSessionId) {
2759
- properties[SESSION_ID] = resolvedSessionId;
2760
- }
2761
- return callWithProperties(properties, () => {
2762
- try {
2763
- const result = callback(sessionTitle);
2764
- if (result && typeof result.then === "function") {
2765
- return result.then((value) => {
2766
- span.end();
2767
- return value;
2768
- }).catch((error) => {
2769
- span.recordException(error);
2770
- span.setStatus({ code: import_api11.SpanStatusCode.ERROR });
2771
- span.end();
2772
- throw error;
2773
- });
2774
- }
2775
- span.end();
2776
- return result;
2777
- } catch (error) {
2778
- span.recordException(error);
2779
- span.setStatus({ code: import_api11.SpanStatusCode.ERROR });
2780
- span.end();
2781
- throw error;
2782
- }
2783
- });
2784
- });
2785
- }
2786
-
2787
2872
  // src/internal/sdk.ts
2788
2873
  init_version();
2789
2874
  var _Brizz = class __Brizz {
@@ -3043,10 +3128,13 @@ var init_exports = {};
3043
3128
  Session,
3044
3129
  SessionTitle,
3045
3130
  SeverityNumber,
3131
+ addExternalLink,
3132
+ callWithMute,
3046
3133
  callWithProperties,
3047
3134
  callWithSessionId,
3048
3135
  detectRuntime,
3049
3136
  emitEvent,
3137
+ emitEventWithSessionId,
3050
3138
  getActiveSession,
3051
3139
  getLogLevel,
3052
3140
  getMetricsExporter,
@@ -3061,6 +3149,7 @@ var init_exports = {};
3061
3149
  setLogLevel,
3062
3150
  startSession,
3063
3151
  startSessionTitle,
3152
+ withMute,
3064
3153
  withProperties,
3065
3154
  withSessionId
3066
3155
  });