@raindrop-ai/ai-sdk 0.0.18 → 0.0.19-beta.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.
@@ -785,7 +785,7 @@ async function* asyncGeneratorWithCurrent(span, gen) {
785
785
  // package.json
786
786
  var package_default = {
787
787
  name: "@raindrop-ai/ai-sdk",
788
- version: "0.0.18"};
788
+ version: "0.0.19-beta.1"};
789
789
 
790
790
  // src/internal/version.ts
791
791
  var libraryName = package_default.name;
@@ -804,19 +804,6 @@ var EventShipper2 = class extends EventShipper {
804
804
  }
805
805
  };
806
806
 
807
- // src/internal/traces.ts
808
- var TraceShipper2 = class extends TraceShipper {
809
- constructor(opts) {
810
- var _a, _b, _c;
811
- super({
812
- ...opts,
813
- sdkName: (_a = opts.sdkName) != null ? _a : "ai-sdk",
814
- serviceName: (_b = opts.serviceName) != null ? _b : "raindrop.ai-sdk",
815
- serviceVersion: (_c = opts.serviceVersion) != null ? _c : libraryVersion
816
- });
817
- }
818
- };
819
-
820
807
  // src/internal/wrap/helpers.ts
821
808
  function isRecord(value) {
822
809
  return typeof value === "object" && value !== null;
@@ -1432,6 +1419,538 @@ function attrsFromGenAiRequest(options) {
1432
1419
  ];
1433
1420
  }
1434
1421
 
1422
+ // src/internal/raindrop-telemetry-integration.ts
1423
+ var RaindropTelemetryIntegration = class {
1424
+ constructor(opts) {
1425
+ this.callStates = /* @__PURE__ */ new Map();
1426
+ // ── onStart ─────────────────────────────────────────────────────────────
1427
+ this.onStart = (event) => {
1428
+ var _a, _b, _c;
1429
+ if (event.isEnabled !== true) return;
1430
+ const isEmbed = event.operationId === "ai.embed" || event.operationId === "ai.embedMany";
1431
+ const recordInputs = event.recordInputs !== false;
1432
+ const recordOutputs = event.recordOutputs !== false;
1433
+ const functionId = event.functionId;
1434
+ const metadata = event.metadata;
1435
+ const callMeta = this.extractRaindropMetadata(metadata);
1436
+ const eventId = (_c = (_b = callMeta.eventId) != null ? _b : (_a = this.defaultContext) == null ? void 0 : _a.eventId) != null ? _c : randomUUID();
1437
+ const inherited = getContextManager().getParentSpanIds();
1438
+ const inheritedParent = inherited && inherited.eventId === eventId ? { traceIdB64: inherited.traceIdB64, spanIdB64: inherited.spanIdB64 } : void 0;
1439
+ const { operationName, resourceName } = opName(
1440
+ event.operationId,
1441
+ functionId
1442
+ );
1443
+ let rootSpan;
1444
+ if (this.sendTraces) {
1445
+ const promptAttrs = !isEmbed && recordInputs ? [
1446
+ attrString(
1447
+ "ai.prompt",
1448
+ safeJsonWithUint8({
1449
+ system: event.system,
1450
+ prompt: event.prompt,
1451
+ messages: event.messages
1452
+ })
1453
+ )
1454
+ ] : [];
1455
+ const embedAttrs = isEmbed && recordInputs ? event.operationId === "ai.embedMany" ? [
1456
+ attrString(
1457
+ "ai.values",
1458
+ safeJsonWithUint8(event.value)
1459
+ )
1460
+ ] : [attrString("ai.value", safeJsonWithUint8(event.value))] : [];
1461
+ rootSpan = this.traceShipper.startSpan({
1462
+ name: event.operationId,
1463
+ parent: inheritedParent,
1464
+ eventId,
1465
+ operationId: event.operationId,
1466
+ attributes: [
1467
+ attrString("operation.name", operationName),
1468
+ attrString("resource.name", resourceName),
1469
+ attrString("ai.telemetry.functionId", functionId),
1470
+ attrString("ai.model.provider", event.provider),
1471
+ attrString("ai.model.id", event.modelId),
1472
+ ...attrsFromTelemetryMetadata(metadata),
1473
+ ...promptAttrs,
1474
+ ...embedAttrs
1475
+ ]
1476
+ });
1477
+ }
1478
+ this.callStates.set(event.callId, {
1479
+ operationId: event.operationId,
1480
+ eventId,
1481
+ rootSpan,
1482
+ rootParent: rootSpan ? this.spanParentRef(rootSpan) : inheritedParent,
1483
+ stepSpan: void 0,
1484
+ stepParent: void 0,
1485
+ toolSpans: /* @__PURE__ */ new Map(),
1486
+ embedSpans: /* @__PURE__ */ new Map(),
1487
+ recordInputs,
1488
+ recordOutputs,
1489
+ functionId,
1490
+ metadata,
1491
+ accumulatedText: "",
1492
+ inputText: isEmbed ? void 0 : this.extractInputText(event),
1493
+ toolCallCount: 0
1494
+ });
1495
+ };
1496
+ // ── onStepStart ─────────────────────────────────────────────────────────
1497
+ this.onStepStart = (event) => {
1498
+ const state = this.getState(event.callId);
1499
+ if (!(state == null ? void 0 : state.rootSpan) || !state.rootParent) return;
1500
+ const isStream = state.operationId === "ai.streamText" || state.operationId === "ai.streamObject";
1501
+ const stepOperationId = isStream ? `${state.operationId}.doStream` : `${state.operationId}.doGenerate`;
1502
+ const { operationName, resourceName } = opName(
1503
+ stepOperationId,
1504
+ state.functionId
1505
+ );
1506
+ const inputAttrs = [];
1507
+ if (state.recordInputs) {
1508
+ if (event.promptMessages) {
1509
+ inputAttrs.push(
1510
+ attrString(
1511
+ "ai.prompt.messages",
1512
+ safeJsonWithUint8(event.promptMessages)
1513
+ )
1514
+ );
1515
+ }
1516
+ if (event.stepTools) {
1517
+ inputAttrs.push(
1518
+ attrStringArray(
1519
+ "ai.prompt.tools",
1520
+ event.stepTools.map((t) => JSON.stringify(t))
1521
+ )
1522
+ );
1523
+ }
1524
+ if (event.stepToolChoice != null) {
1525
+ inputAttrs.push(
1526
+ attrString(
1527
+ "ai.prompt.toolChoice",
1528
+ JSON.stringify(event.stepToolChoice)
1529
+ )
1530
+ );
1531
+ }
1532
+ }
1533
+ const stepSpan = this.traceShipper.startSpan({
1534
+ name: stepOperationId,
1535
+ parent: state.rootParent,
1536
+ eventId: state.eventId,
1537
+ operationId: stepOperationId,
1538
+ attributes: [
1539
+ attrString("operation.name", operationName),
1540
+ attrString("resource.name", resourceName),
1541
+ attrString("ai.telemetry.functionId", state.functionId),
1542
+ attrString("ai.model.provider", event.provider),
1543
+ attrString("ai.model.id", event.modelId),
1544
+ attrString("gen_ai.system", event.provider),
1545
+ attrString("gen_ai.request.model", event.modelId),
1546
+ ...inputAttrs
1547
+ ]
1548
+ });
1549
+ state.stepSpan = stepSpan;
1550
+ state.stepParent = this.spanParentRef(stepSpan);
1551
+ };
1552
+ // ── onToolCallStart ─────────────────────────────────────────────────────
1553
+ this.onToolCallStart = (event) => {
1554
+ const state = this.getState(event.callId);
1555
+ if (!(state == null ? void 0 : state.stepParent)) return;
1556
+ const { toolCall } = event;
1557
+ const { operationName, resourceName } = opName(
1558
+ "ai.toolCall",
1559
+ state.functionId
1560
+ );
1561
+ const inputAttrs = state.recordInputs ? [attrString("ai.toolCall.args", safeJsonWithUint8(toolCall.input))] : [];
1562
+ const toolSpan = this.traceShipper.startSpan({
1563
+ name: "ai.toolCall",
1564
+ parent: state.stepParent,
1565
+ eventId: state.eventId,
1566
+ operationId: "ai.toolCall",
1567
+ attributes: [
1568
+ attrString("operation.name", operationName),
1569
+ attrString("resource.name", resourceName),
1570
+ attrString("ai.telemetry.functionId", state.functionId),
1571
+ attrString("ai.toolCall.name", toolCall.toolName),
1572
+ attrString("ai.toolCall.id", toolCall.toolCallId),
1573
+ ...inputAttrs
1574
+ ]
1575
+ });
1576
+ state.toolSpans.set(toolCall.toolCallId, toolSpan);
1577
+ };
1578
+ // ── onToolCallFinish ────────────────────────────────────────────────────
1579
+ this.onToolCallFinish = (event) => {
1580
+ const state = this.getState(event.callId);
1581
+ if (!state) return;
1582
+ const toolSpan = state.toolSpans.get(event.toolCall.toolCallId);
1583
+ if (!toolSpan) return;
1584
+ state.toolCallCount += 1;
1585
+ if (event.success) {
1586
+ const outputAttrs = state.recordOutputs ? [attrString("ai.toolCall.result", safeJsonWithUint8(event.output))] : [];
1587
+ this.traceShipper.endSpan(toolSpan, { attributes: outputAttrs });
1588
+ } else {
1589
+ this.traceShipper.endSpan(toolSpan, { error: event.error });
1590
+ }
1591
+ state.toolSpans.delete(event.toolCall.toolCallId);
1592
+ };
1593
+ // ── onChunk (streaming) ─────────────────────────────────────────────────
1594
+ this.onChunk = (event) => {
1595
+ var _a, _b, _c;
1596
+ const callId = (_b = event.callId) != null ? _b : (_a = event.chunk) == null ? void 0 : _a.callId;
1597
+ if (!callId) return;
1598
+ const state = this.getState(callId);
1599
+ if (!state) return;
1600
+ const chunk = event.chunk;
1601
+ if (!chunk || typeof chunk !== "object") return;
1602
+ if (chunk.type === "text-delta") {
1603
+ const delta = (_c = chunk.textDelta) != null ? _c : chunk.delta;
1604
+ if (typeof delta === "string") {
1605
+ state.accumulatedText += delta;
1606
+ }
1607
+ }
1608
+ };
1609
+ // ── onStepFinish ────────────────────────────────────────────────────────
1610
+ this.onStepFinish = (event) => {
1611
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i;
1612
+ const state = this.getState(event.callId);
1613
+ if (!(state == null ? void 0 : state.stepSpan)) return;
1614
+ const outputAttrs = [];
1615
+ if (state.recordOutputs) {
1616
+ outputAttrs.push(
1617
+ attrString("ai.response.finishReason", event.finishReason),
1618
+ attrString("ai.response.text", (_a = event.text) != null ? _a : void 0),
1619
+ attrString("ai.response.id", (_b = event.response) == null ? void 0 : _b.id),
1620
+ attrString("ai.response.model", (_c = event.response) == null ? void 0 : _c.modelId),
1621
+ attrString(
1622
+ "ai.response.timestamp",
1623
+ ((_d = event.response) == null ? void 0 : _d.timestamp) instanceof Date ? event.response.timestamp.toISOString() : (_e = event.response) == null ? void 0 : _e.timestamp
1624
+ ),
1625
+ attrString(
1626
+ "ai.response.providerMetadata",
1627
+ event.providerMetadata ? safeJsonWithUint8(event.providerMetadata) : void 0
1628
+ )
1629
+ );
1630
+ if (((_f = event.toolCalls) == null ? void 0 : _f.length) > 0) {
1631
+ outputAttrs.push(
1632
+ attrString(
1633
+ "ai.response.toolCalls",
1634
+ JSON.stringify(
1635
+ event.toolCalls.map((tc) => ({
1636
+ toolCallId: tc.toolCallId,
1637
+ toolName: tc.toolName,
1638
+ input: tc.input
1639
+ }))
1640
+ )
1641
+ )
1642
+ );
1643
+ }
1644
+ if (((_g = event.reasoning) == null ? void 0 : _g.length) > 0) {
1645
+ const reasoningText = event.reasoning.filter((part) => "text" in part).map((part) => part.text).join("\n");
1646
+ if (reasoningText) {
1647
+ outputAttrs.push(attrString("ai.response.reasoning", reasoningText));
1648
+ }
1649
+ }
1650
+ }
1651
+ outputAttrs.push(
1652
+ attrStringArray("gen_ai.response.finish_reasons", [event.finishReason]),
1653
+ attrString("gen_ai.response.id", (_h = event.response) == null ? void 0 : _h.id),
1654
+ attrString("gen_ai.response.model", (_i = event.response) == null ? void 0 : _i.modelId)
1655
+ );
1656
+ const usage = event.usage;
1657
+ if (usage) {
1658
+ outputAttrs.push(
1659
+ attrInt("ai.usage.inputTokens", usage.inputTokens),
1660
+ attrInt("ai.usage.outputTokens", usage.outputTokens),
1661
+ attrInt("ai.usage.totalTokens", usage.totalTokens),
1662
+ attrInt("ai.usage.reasoningTokens", usage.reasoningTokens),
1663
+ attrInt("ai.usage.cachedInputTokens", usage.cachedInputTokens),
1664
+ attrInt("gen_ai.usage.input_tokens", usage.inputTokens),
1665
+ attrInt("gen_ai.usage.output_tokens", usage.outputTokens)
1666
+ );
1667
+ }
1668
+ this.traceShipper.endSpan(state.stepSpan, { attributes: outputAttrs });
1669
+ state.stepSpan = void 0;
1670
+ state.stepParent = void 0;
1671
+ };
1672
+ // ── onEmbedStart ────────────────────────────────────────────────────────
1673
+ this.onEmbedStart = (event) => {
1674
+ const state = this.getState(event.callId);
1675
+ if (!(state == null ? void 0 : state.rootSpan) || !state.rootParent) return;
1676
+ const { operationName, resourceName } = opName(
1677
+ event.operationId,
1678
+ state.functionId
1679
+ );
1680
+ const inputAttrs = state.recordInputs ? [
1681
+ attrString(
1682
+ "ai.values",
1683
+ safeJsonWithUint8(event.values)
1684
+ )
1685
+ ] : [];
1686
+ const embedSpan = this.traceShipper.startSpan({
1687
+ name: event.operationId,
1688
+ parent: state.rootParent,
1689
+ eventId: state.eventId,
1690
+ operationId: event.operationId,
1691
+ attributes: [
1692
+ attrString("operation.name", operationName),
1693
+ attrString("resource.name", resourceName),
1694
+ attrString("ai.telemetry.functionId", state.functionId),
1695
+ ...inputAttrs
1696
+ ]
1697
+ });
1698
+ state.embedSpans.set(event.embedCallId, embedSpan);
1699
+ };
1700
+ // ── onEmbedFinish ───────────────────────────────────────────────────────
1701
+ this.onEmbedFinish = (event) => {
1702
+ var _a;
1703
+ const state = this.getState(event.callId);
1704
+ if (!state) return;
1705
+ const embedSpan = state.embedSpans.get(event.embedCallId);
1706
+ if (!embedSpan) return;
1707
+ const outputAttrs = [];
1708
+ if (state.recordOutputs) {
1709
+ outputAttrs.push(
1710
+ attrString(
1711
+ "ai.embeddings",
1712
+ safeJsonWithUint8(event.embeddings)
1713
+ )
1714
+ );
1715
+ }
1716
+ if (((_a = event.usage) == null ? void 0 : _a.tokens) != null) {
1717
+ outputAttrs.push(attrInt("ai.usage.tokens", event.usage.tokens));
1718
+ }
1719
+ this.traceShipper.endSpan(embedSpan, { attributes: outputAttrs });
1720
+ state.embedSpans.delete(event.embedCallId);
1721
+ };
1722
+ // ── onFinish ────────────────────────────────────────────────────────────
1723
+ this.onFinish = (event) => {
1724
+ const state = this.getState(event.callId);
1725
+ if (!state) return;
1726
+ const isEmbed = state.operationId === "ai.embed" || state.operationId === "ai.embedMany";
1727
+ if (isEmbed) {
1728
+ this.finishEmbed(event, state);
1729
+ } else {
1730
+ this.finishGenerate(event, state);
1731
+ }
1732
+ this.cleanup(event.callId);
1733
+ };
1734
+ // ── onError ─────────────────────────────────────────────────────────────
1735
+ this.onError = (error) => {
1736
+ var _a;
1737
+ const event = error;
1738
+ if (!(event == null ? void 0 : event.callId)) return;
1739
+ const state = this.getState(event.callId);
1740
+ if (!state) return;
1741
+ const actualError = (_a = event.error) != null ? _a : error;
1742
+ if (state.stepSpan) {
1743
+ this.traceShipper.endSpan(state.stepSpan, { error: actualError });
1744
+ }
1745
+ for (const embedSpan of state.embedSpans.values()) {
1746
+ this.traceShipper.endSpan(embedSpan, { error: actualError });
1747
+ }
1748
+ state.embedSpans.clear();
1749
+ for (const toolSpan of state.toolSpans.values()) {
1750
+ this.traceShipper.endSpan(toolSpan, { error: actualError });
1751
+ }
1752
+ state.toolSpans.clear();
1753
+ if (state.rootSpan) {
1754
+ this.traceShipper.endSpan(state.rootSpan, { error: actualError });
1755
+ }
1756
+ this.cleanup(event.callId);
1757
+ };
1758
+ // ── executeTool ─────────────────────────────────────────────────────────
1759
+ this.executeTool = async ({
1760
+ callId,
1761
+ toolCallId,
1762
+ execute
1763
+ }) => {
1764
+ const state = this.getState(callId);
1765
+ const toolSpan = state == null ? void 0 : state.toolSpans.get(toolCallId);
1766
+ if (!toolSpan) return execute();
1767
+ return runWithParentSpanContext(
1768
+ {
1769
+ traceIdB64: toolSpan.ids.traceIdB64,
1770
+ spanIdB64: toolSpan.ids.spanIdB64,
1771
+ eventId: state.eventId
1772
+ },
1773
+ () => execute()
1774
+ );
1775
+ };
1776
+ this.traceShipper = opts.traceShipper;
1777
+ this.eventShipper = opts.eventShipper;
1778
+ this.sendTraces = opts.sendTraces !== false;
1779
+ this.sendEvents = opts.sendEvents !== false;
1780
+ this.debug = opts.debug === true;
1781
+ this.defaultContext = opts.context;
1782
+ }
1783
+ // ── helpers ──────────────────────────────────────────────────────────────
1784
+ getState(callId) {
1785
+ return this.callStates.get(callId);
1786
+ }
1787
+ cleanup(callId) {
1788
+ this.callStates.delete(callId);
1789
+ }
1790
+ spanParentRef(span) {
1791
+ return { traceIdB64: span.ids.traceIdB64, spanIdB64: span.ids.spanIdB64 };
1792
+ }
1793
+ extractRaindropMetadata(metadata) {
1794
+ if (!metadata) return {};
1795
+ const result = {};
1796
+ const userId = metadata["raindrop.userId"];
1797
+ if (typeof userId === "string" && userId) result.userId = userId;
1798
+ const eventId = metadata["raindrop.eventId"];
1799
+ if (typeof eventId === "string" && eventId) result.eventId = eventId;
1800
+ const convoId = metadata["raindrop.convoId"];
1801
+ if (typeof convoId === "string" && convoId) result.convoId = convoId;
1802
+ const eventName = metadata["raindrop.eventName"];
1803
+ if (typeof eventName === "string" && eventName) result.eventName = eventName;
1804
+ const properties = metadata["raindrop.properties"];
1805
+ if (typeof properties === "string") {
1806
+ try {
1807
+ result.properties = JSON.parse(properties);
1808
+ } catch (e) {
1809
+ }
1810
+ } else if (properties && typeof properties === "object") {
1811
+ result.properties = properties;
1812
+ }
1813
+ return result;
1814
+ }
1815
+ /**
1816
+ * Extract the user-facing input text from an onStart event.
1817
+ * Mirrors the logic in the v4-v6 Proxy path (lastUserMessageTextFromArgs / extractInputFromArgs).
1818
+ */
1819
+ extractInputText(event) {
1820
+ if (typeof event.prompt === "string") return event.prompt;
1821
+ if (Array.isArray(event.messages)) {
1822
+ for (let i = event.messages.length - 1; i >= 0; i--) {
1823
+ const msg = event.messages[i];
1824
+ if ((msg == null ? void 0 : msg.role) === "user") {
1825
+ if (typeof msg.content === "string") return msg.content;
1826
+ if (Array.isArray(msg.content)) {
1827
+ const textPart = msg.content.find(
1828
+ (p) => (p == null ? void 0 : p.type) === "text" && typeof p.text === "string"
1829
+ );
1830
+ if (textPart) return textPart.text;
1831
+ }
1832
+ }
1833
+ }
1834
+ }
1835
+ return void 0;
1836
+ }
1837
+ finishGenerate(event, state) {
1838
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n;
1839
+ if (state.rootSpan) {
1840
+ const outputAttrs = [];
1841
+ if (state.recordOutputs) {
1842
+ outputAttrs.push(
1843
+ attrString("ai.response.finishReason", event.finishReason),
1844
+ attrString("ai.response.text", (_a = event.text) != null ? _a : void 0),
1845
+ attrString(
1846
+ "ai.response.providerMetadata",
1847
+ event.providerMetadata ? safeJsonWithUint8(event.providerMetadata) : void 0
1848
+ )
1849
+ );
1850
+ if (((_b = event.toolCalls) == null ? void 0 : _b.length) > 0) {
1851
+ outputAttrs.push(
1852
+ attrString(
1853
+ "ai.response.toolCalls",
1854
+ JSON.stringify(
1855
+ event.toolCalls.map((tc) => ({
1856
+ toolCallId: tc.toolCallId,
1857
+ toolName: tc.toolName,
1858
+ input: tc.input
1859
+ }))
1860
+ )
1861
+ )
1862
+ );
1863
+ }
1864
+ if (((_c = event.reasoning) == null ? void 0 : _c.length) > 0) {
1865
+ const reasoningText = event.reasoning.filter((part) => "text" in part).map((part) => part.text).join("\n");
1866
+ if (reasoningText) {
1867
+ outputAttrs.push(attrString("ai.response.reasoning", reasoningText));
1868
+ }
1869
+ }
1870
+ }
1871
+ const usage = (_d = event.totalUsage) != null ? _d : event.usage;
1872
+ if (usage) {
1873
+ outputAttrs.push(
1874
+ attrInt("ai.usage.inputTokens", usage.inputTokens),
1875
+ attrInt("ai.usage.outputTokens", usage.outputTokens),
1876
+ attrInt("ai.usage.totalTokens", usage.totalTokens),
1877
+ attrInt("ai.usage.reasoningTokens", usage.reasoningTokens),
1878
+ attrInt("ai.usage.cachedInputTokens", usage.cachedInputTokens)
1879
+ );
1880
+ }
1881
+ outputAttrs.push(
1882
+ attrInt("ai.toolCall.count", state.toolCallCount)
1883
+ );
1884
+ this.traceShipper.endSpan(state.rootSpan, { attributes: outputAttrs });
1885
+ }
1886
+ if (this.sendEvents) {
1887
+ const callMeta = this.extractRaindropMetadata(state.metadata);
1888
+ const userId = (_f = callMeta.userId) != null ? _f : (_e = this.defaultContext) == null ? void 0 : _e.userId;
1889
+ if (userId) {
1890
+ const eventName = (_i = (_h = callMeta.eventName) != null ? _h : (_g = this.defaultContext) == null ? void 0 : _g.eventName) != null ? _i : state.operationId;
1891
+ const output = (_j = event.text) != null ? _j : state.accumulatedText || void 0;
1892
+ const input = state.inputText;
1893
+ const model = (_k = event.response) == null ? void 0 : _k.modelId;
1894
+ const properties = {
1895
+ ...(_l = this.defaultContext) == null ? void 0 : _l.properties,
1896
+ ...callMeta.properties
1897
+ };
1898
+ const convoId = (_n = callMeta.convoId) != null ? _n : (_m = this.defaultContext) == null ? void 0 : _m.convoId;
1899
+ void this.eventShipper.patch(state.eventId, {
1900
+ eventName,
1901
+ userId,
1902
+ convoId,
1903
+ input,
1904
+ output,
1905
+ model,
1906
+ properties: Object.keys(properties).length > 0 ? properties : void 0,
1907
+ isPending: false
1908
+ }).catch((err) => {
1909
+ if (this.debug) {
1910
+ console.warn(
1911
+ `[raindrop-ai/ai-sdk] event patch failed: ${err instanceof Error ? err.message : err}`
1912
+ );
1913
+ }
1914
+ });
1915
+ }
1916
+ }
1917
+ }
1918
+ finishEmbed(event, state) {
1919
+ var _a;
1920
+ if (!state.rootSpan) return;
1921
+ const outputAttrs = [];
1922
+ const isMany = state.operationId === "ai.embedMany";
1923
+ if (state.recordOutputs) {
1924
+ if (isMany) {
1925
+ outputAttrs.push(
1926
+ attrString("ai.embeddings", safeJsonWithUint8(event.embedding))
1927
+ );
1928
+ } else {
1929
+ outputAttrs.push(
1930
+ attrString("ai.embedding", safeJsonWithUint8(event.embedding))
1931
+ );
1932
+ }
1933
+ }
1934
+ if (((_a = event.usage) == null ? void 0 : _a.tokens) != null) {
1935
+ outputAttrs.push(attrInt("ai.usage.tokens", event.usage.tokens));
1936
+ }
1937
+ this.traceShipper.endSpan(state.rootSpan, { attributes: outputAttrs });
1938
+ }
1939
+ };
1940
+
1941
+ // src/internal/traces.ts
1942
+ var TraceShipper2 = class extends TraceShipper {
1943
+ constructor(opts) {
1944
+ var _a, _b, _c;
1945
+ super({
1946
+ ...opts,
1947
+ sdkName: (_a = opts.sdkName) != null ? _a : "ai-sdk",
1948
+ serviceName: (_b = opts.serviceName) != null ? _b : "raindrop.ai-sdk",
1949
+ serviceVersion: (_c = opts.serviceVersion) != null ? _c : libraryVersion
1950
+ });
1951
+ }
1952
+ };
1953
+
1435
1954
  // src/internal/wrap/wrapAISDK.ts
1436
1955
  var AGENT_REPORTING_TOOL_NAME_DEFAULT = "__raindrop_report";
1437
1956
  var AGENT_REPORTING_SIGNALS_DEFAULT = {
@@ -1641,6 +2160,9 @@ function detectAISDKVersion(aiSDK) {
1641
2160
  if (isFunction(aiSDK["tool"])) return "5";
1642
2161
  return "4";
1643
2162
  }
2163
+ function hasStructuredTelemetryEvents(aiSDK) {
2164
+ return isRecord(aiSDK) && isFunction(aiSDK["registerTelemetryIntegration"]) && isFunction(aiSDK["experimental_streamModelCall"]);
2165
+ }
1644
2166
  function asVercelSchema(jsonSchemaObj) {
1645
2167
  const validatorSymbol = /* @__PURE__ */ Symbol.for("vercel.ai.validator");
1646
2168
  const schemaSymbol = /* @__PURE__ */ Symbol.for("vercel.ai.schema");
@@ -2223,8 +2745,93 @@ async function executeNonStreamingOperation(params) {
2223
2745
  }
2224
2746
  }
2225
2747
  function wrapAISDK(aiSDK, deps) {
2226
- var _a, _b;
2748
+ var _a, _b, _c, _d;
2227
2749
  const debug = deps.eventShipper.isDebugEnabled() || deps.traceShipper.isDebugEnabled();
2750
+ if (deps.options.nativeTelemetry === true) {
2751
+ if (!hasStructuredTelemetryEvents(aiSDK)) {
2752
+ throw new Error(
2753
+ "[raindrop-ai/ai-sdk] nativeTelemetry requires AI SDK v7+. The AI SDK module passed to wrap() does not support structured telemetry events. Remove nativeTelemetry or upgrade to AI SDK v7."
2754
+ );
2755
+ }
2756
+ }
2757
+ const useNative = deps.options.nativeTelemetry === true;
2758
+ if (useNative) {
2759
+ const wrapTimeCtx = resolveContext(deps.options.context, { operation: "wrap", args: void 0 });
2760
+ const integration = new RaindropTelemetryIntegration({
2761
+ traceShipper: deps.traceShipper,
2762
+ eventShipper: deps.eventShipper,
2763
+ sendTraces: ((_a = deps.options.send) == null ? void 0 : _a.traces) !== false,
2764
+ sendEvents: ((_b = deps.options.send) == null ? void 0 : _b.events) !== false,
2765
+ debug,
2766
+ context: {
2767
+ userId: wrapTimeCtx.userId,
2768
+ eventId: wrapTimeCtx.eventId,
2769
+ eventName: wrapTimeCtx.eventName,
2770
+ convoId: wrapTimeCtx.convoId,
2771
+ properties: wrapTimeCtx.properties
2772
+ }
2773
+ });
2774
+ const registerFn = aiSDK["registerTelemetryIntegration"];
2775
+ if (isFunction(registerFn)) {
2776
+ registerFn(integration);
2777
+ }
2778
+ if (debug) {
2779
+ console.log("[raindrop-ai/ai-sdk] nativeTelemetry: registered RaindropTelemetryIntegration (no Proxy)");
2780
+ }
2781
+ const selfDiagnostics2 = normalizeSelfDiagnosticsConfig(deps.options.selfDiagnostics);
2782
+ if (selfDiagnostics2) {
2783
+ const textOps = /* @__PURE__ */ new Set(["generateText", "streamText"]);
2784
+ const jsonSchemaFactory = resolveJsonSchemaFactory(aiSDK);
2785
+ const proxyTarget2 = isModuleNamespace(aiSDK) ? Object.setPrototypeOf({}, aiSDK) : aiSDK;
2786
+ return new Proxy(proxyTarget2, {
2787
+ get(target, prop, receiver) {
2788
+ const original = Reflect.get(target, prop, receiver);
2789
+ if (typeof prop !== "string" || !textOps.has(prop) || !isFunction(original)) {
2790
+ return original;
2791
+ }
2792
+ return (...callArgs) => {
2793
+ var _a2, _b2;
2794
+ const arg = callArgs[0];
2795
+ if (!isRecord(arg)) return original.call(aiSDK, ...callArgs);
2796
+ const telemetry = extractExperimentalTelemetry(arg);
2797
+ const callMeta = (telemetry == null ? void 0 : telemetry.metadata) ? extractRaindropMetadata(telemetry.metadata) : {};
2798
+ const perCallEventId = (_b2 = (_a2 = callMeta.eventId) != null ? _a2 : wrapTimeCtx.eventId) != null ? _b2 : randomUUID();
2799
+ const perCallCtx = {
2800
+ eventId: perCallEventId,
2801
+ telemetry,
2802
+ sendTraces: false,
2803
+ debug,
2804
+ eventShipper: deps.eventShipper,
2805
+ traceShipper: deps.traceShipper,
2806
+ rootParentForChildren: void 0,
2807
+ jsonSchemaFactory,
2808
+ selfDiagnostics: selfDiagnostics2,
2809
+ aiSDKVersion: "7"
2810
+ };
2811
+ const tools = isRecord(arg["tools"]) ? { ...arg["tools"] } : {};
2812
+ const toolName = selfDiagnostics2.toolName;
2813
+ if (!(toolName in tools)) {
2814
+ const reportTool = createSelfDiagnosticsTool(perCallCtx);
2815
+ if (reportTool) tools[toolName] = reportTool;
2816
+ }
2817
+ const existingTelemetry = isRecord(arg["experimental_telemetry"]) ? arg["experimental_telemetry"] : {};
2818
+ const existingMetadata = isRecord(existingTelemetry["metadata"]) ? existingTelemetry["metadata"] : {};
2819
+ const mergedMetadata = existingMetadata["raindrop.eventId"] ? existingMetadata : { ...existingMetadata, "raindrop.eventId": perCallEventId };
2820
+ callArgs[0] = {
2821
+ ...arg,
2822
+ tools,
2823
+ experimental_telemetry: {
2824
+ ...existingTelemetry,
2825
+ metadata: mergedMetadata
2826
+ }
2827
+ };
2828
+ return original.call(aiSDK, ...callArgs);
2829
+ };
2830
+ }
2831
+ });
2832
+ }
2833
+ return aiSDK;
2834
+ }
2228
2835
  const instrumentedOps = /* @__PURE__ */ new Set([
2229
2836
  "generateText",
2230
2837
  "streamText",
@@ -2232,8 +2839,8 @@ function wrapAISDK(aiSDK, deps) {
2232
2839
  "streamObject"
2233
2840
  ]);
2234
2841
  const agentClasses = /* @__PURE__ */ new Set(["Agent", "Experimental_Agent", "ToolLoopAgent"]);
2235
- const sendEvents = ((_a = deps.options.send) == null ? void 0 : _a.events) !== false;
2236
- const sendTraces = ((_b = deps.options.send) == null ? void 0 : _b.traces) !== false;
2842
+ const sendEvents = ((_c = deps.options.send) == null ? void 0 : _c.events) !== false;
2843
+ const sendTraces = ((_d = deps.options.send) == null ? void 0 : _d.traces) !== false;
2237
2844
  const autoAttachmentEnabled = deps.options.autoAttachment !== false;
2238
2845
  const selfDiagnostics = normalizeSelfDiagnosticsConfig(deps.options.selfDiagnostics);
2239
2846
  const proxyTarget = isModuleNamespace(aiSDK) ? Object.setPrototypeOf({}, aiSDK) : aiSDK;
@@ -3327,6 +3934,16 @@ function createRaindropAISDK(opts) {
3327
3934
  traceShipper
3328
3935
  });
3329
3936
  },
3937
+ createTelemetryIntegration(context) {
3938
+ return new RaindropTelemetryIntegration({
3939
+ traceShipper,
3940
+ eventShipper,
3941
+ sendTraces: tracesEnabled,
3942
+ sendEvents: eventsEnabled,
3943
+ debug: envDebug,
3944
+ context
3945
+ });
3946
+ },
3330
3947
  events: {
3331
3948
  async patch(eventId, patch) {
3332
3949
  await eventShipper.patch(eventId, patch);
@@ -3360,4 +3977,4 @@ function createRaindropAISDK(opts) {
3360
3977
  };
3361
3978
  }
3362
3979
 
3363
- export { _resetWarnedMissingUserId, createRaindropAISDK, currentSpan, eventMetadata, eventMetadataFromChatRequest, getContextManager, withCurrent };
3980
+ export { RaindropTelemetryIntegration, _resetWarnedMissingUserId, createRaindropAISDK, currentSpan, eventMetadata, eventMetadataFromChatRequest, getContextManager, withCurrent };