@raindrop-ai/ai-sdk 0.0.8 → 0.0.10

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.
@@ -84,7 +84,7 @@ async function postJson(url, body, headers, opts) {
84
84
  // package.json
85
85
  var package_default = {
86
86
  name: "@raindrop-ai/ai-sdk",
87
- version: "0.0.8"};
87
+ version: "0.0.10"};
88
88
 
89
89
  // src/internal/version.ts
90
90
  var libraryName = package_default.name;
@@ -118,13 +118,15 @@ var EventShipper = class {
118
118
  this.sticky = /* @__PURE__ */ new Map();
119
119
  this.timers = /* @__PURE__ */ new Map();
120
120
  this.inFlight = /* @__PURE__ */ new Set();
121
- var _a, _b;
122
- if (!opts.writeKey) throw new Error("[raindrop-ai/ai-sdk] writeKey is required");
123
- this.writeKey = opts.writeKey;
124
- this.baseUrl = (_a = formatEndpoint(opts.endpoint)) != null ? _a : "https://api.raindrop.ai/v1/";
121
+ var _a, _b, _c;
122
+ if (opts.enabled && !opts.writeKey) {
123
+ throw new Error("[raindrop-ai/ai-sdk] writeKey is required when events are enabled");
124
+ }
125
+ this.writeKey = (_a = opts.writeKey) != null ? _a : "";
126
+ this.baseUrl = (_b = formatEndpoint(opts.endpoint)) != null ? _b : "https://api.raindrop.ai/v1/";
125
127
  this.enabled = opts.enabled;
126
128
  this.debug = opts.debug;
127
- this.partialFlushMs = (_b = opts.partialFlushMs) != null ? _b : 1e3;
129
+ this.partialFlushMs = (_c = opts.partialFlushMs) != null ? _c : 1e3;
128
130
  this.context = getRuntimeContext();
129
131
  }
130
132
  isDebugEnabled() {
@@ -472,16 +474,18 @@ var TraceShipper = class {
472
474
  constructor(opts) {
473
475
  this.queue = [];
474
476
  this.inFlight = /* @__PURE__ */ new Set();
475
- var _a, _b, _c, _d;
476
- if (!opts.writeKey) throw new Error("[raindrop-ai/ai-sdk] writeKey is required");
477
- this.writeKey = opts.writeKey;
478
- this.baseUrl = (_a = formatEndpoint(opts.endpoint)) != null ? _a : "https://api.raindrop.ai/v1/";
477
+ var _a, _b, _c, _d, _e;
478
+ if (opts.enabled && !opts.writeKey) {
479
+ throw new Error("[raindrop-ai/ai-sdk] writeKey is required when traces are enabled");
480
+ }
481
+ this.writeKey = (_a = opts.writeKey) != null ? _a : "";
482
+ this.baseUrl = (_b = formatEndpoint(opts.endpoint)) != null ? _b : "https://api.raindrop.ai/v1/";
479
483
  this.enabled = opts.enabled;
480
484
  this.debug = opts.debug;
481
485
  this.debugSpans = opts.debugSpans === true;
482
- this.flushIntervalMs = (_b = opts.flushIntervalMs) != null ? _b : 1e3;
483
- this.maxBatchSize = (_c = opts.maxBatchSize) != null ? _c : 50;
484
- this.maxQueueSize = (_d = opts.maxQueueSize) != null ? _d : 5e3;
486
+ this.flushIntervalMs = (_c = opts.flushIntervalMs) != null ? _c : 1e3;
487
+ this.maxBatchSize = (_d = opts.maxBatchSize) != null ? _d : 50;
488
+ this.maxQueueSize = (_e = opts.maxQueueSize) != null ? _e : 5e3;
485
489
  }
486
490
  isDebugEnabled() {
487
491
  return this.debug;
@@ -1241,6 +1245,23 @@ function attrsFromGenAiRequest(options) {
1241
1245
  }
1242
1246
 
1243
1247
  // src/internal/wrap/wrapAISDK.ts
1248
+ var AGENT_REPORTING_TOOL_NAME_DEFAULT = "__raindrop_report";
1249
+ var AGENT_REPORTING_SIGNALS_DEFAULT = {
1250
+ tool_failure: {
1251
+ description: "A tool call returned an error, timed out, or produced output that cannot be used to make progress.",
1252
+ sentiment: "NEGATIVE"
1253
+ },
1254
+ stuck_in_loop: {
1255
+ description: "The same approach has been attempted multiple times without meaningful progress.",
1256
+ sentiment: "NEGATIVE"
1257
+ },
1258
+ capability_gap: {
1259
+ description: "The task requires a tool, permission, or capability that is not available to the agent."
1260
+ }
1261
+ };
1262
+ var AGENT_REPORTING_TOOL_PREAMBLE = "IMPORTANT: Before responding to the user, scan the conversation for any issues listed in the categories below. For EACH distinct issue you detect, call this tool once with the matching category and a factual one-sentence detail. Multiple issues = multiple calls. This tool is invisible to the user \u2014 never mention it or its output.";
1263
+ var AGENT_REPORTING_NOTEWORTHY_SIGNAL_KEY = "noteworthy";
1264
+ var AGENT_REPORTING_NOTEWORTHY_DESCRIPTION = "Only when no specific category applies: flag that this turn is noteworthy for developer review.";
1244
1265
  var warnedMissingUserId = false;
1245
1266
  function warnMissingUserIdOnce() {
1246
1267
  if (warnedMissingUserId) return;
@@ -1252,6 +1273,14 @@ function warnMissingUserIdOnce() {
1252
1273
  function _resetWarnedMissingUserId() {
1253
1274
  warnedMissingUserId = false;
1254
1275
  }
1276
+ function extractRaindropCallOptions(options) {
1277
+ if (!isRecord(options)) return {};
1278
+ const em = options["metadata"];
1279
+ if (isRecord(em)) return extractRaindropMetadata(em);
1280
+ const telemetry = extractExperimentalTelemetry(options);
1281
+ if (telemetry == null ? void 0 : telemetry.metadata) return extractRaindropMetadata(telemetry.metadata);
1282
+ return {};
1283
+ }
1255
1284
  function extractRaindropMetadata(metadata) {
1256
1285
  if (!metadata || typeof metadata !== "object") return {};
1257
1286
  const result = {};
@@ -1288,6 +1317,188 @@ function mergeContexts(wrapTime, callTime) {
1288
1317
  }
1289
1318
  return result;
1290
1319
  }
1320
+ function normalizeSelfDiagnosticsSignals(signals) {
1321
+ if (!signals) return AGENT_REPORTING_SIGNALS_DEFAULT;
1322
+ const normalizedEntries = Object.entries(signals).map(([key, value]) => {
1323
+ var _a;
1324
+ const signalKey = key.trim();
1325
+ if (!signalKey || !value || typeof value !== "object") return void 0;
1326
+ const description = (_a = value.description) == null ? void 0 : _a.trim();
1327
+ if (!description) return void 0;
1328
+ const sentiment = value.sentiment;
1329
+ return [
1330
+ signalKey,
1331
+ {
1332
+ description,
1333
+ ...sentiment === "POSITIVE" || sentiment === "NEGATIVE" ? { sentiment } : {}
1334
+ }
1335
+ ];
1336
+ }).filter(
1337
+ (entry) => entry !== void 0
1338
+ );
1339
+ if (normalizedEntries.length === 0) return AGENT_REPORTING_SIGNALS_DEFAULT;
1340
+ return Object.fromEntries(normalizedEntries);
1341
+ }
1342
+ function normalizeSelfDiagnosticsConfig(options) {
1343
+ var _a, _b, _c;
1344
+ if (!(options == null ? void 0 : options.enabled)) return void 0;
1345
+ const signalDefinitions = normalizeSelfDiagnosticsSignals(options.signals);
1346
+ const configuredSignalKeys = Object.keys(signalDefinitions).filter(
1347
+ (signalKey) => signalKey !== AGENT_REPORTING_NOTEWORTHY_SIGNAL_KEY
1348
+ );
1349
+ const signalKeys = [...configuredSignalKeys, AGENT_REPORTING_NOTEWORTHY_SIGNAL_KEY];
1350
+ const signalDescriptions = {};
1351
+ const signalSentiments = {};
1352
+ for (const signalKey of signalKeys) {
1353
+ if (signalKey === AGENT_REPORTING_NOTEWORTHY_SIGNAL_KEY) {
1354
+ const noteworthyDefinition = signalDefinitions[AGENT_REPORTING_NOTEWORTHY_SIGNAL_KEY];
1355
+ signalDescriptions[signalKey] = ((_a = noteworthyDefinition == null ? void 0 : noteworthyDefinition.description) == null ? void 0 : _a.trim()) || AGENT_REPORTING_NOTEWORTHY_DESCRIPTION;
1356
+ signalSentiments[signalKey] = noteworthyDefinition == null ? void 0 : noteworthyDefinition.sentiment;
1357
+ continue;
1358
+ }
1359
+ const def = signalDefinitions[signalKey];
1360
+ if (!def) continue;
1361
+ signalDescriptions[signalKey] = def.description;
1362
+ signalSentiments[signalKey] = def.sentiment;
1363
+ }
1364
+ const customGuidanceText = ((_b = options.guidance) == null ? void 0 : _b.trim()) || "";
1365
+ const toolName = ((_c = options.toolName) == null ? void 0 : _c.trim()) || AGENT_REPORTING_TOOL_NAME_DEFAULT;
1366
+ const signalList = signalKeys.map((signalKey) => {
1367
+ const sentiment = signalSentiments[signalKey];
1368
+ const sentimentTag = sentiment ? ` [${sentiment.toLowerCase()}]` : "";
1369
+ return `- ${signalKey}: ${signalDescriptions[signalKey]}${sentimentTag}`;
1370
+ }).join("\n");
1371
+ const guidanceBlock = customGuidanceText ? `
1372
+ Additional guidance: ${customGuidanceText}
1373
+ ` : "";
1374
+ const toolDescription = `${AGENT_REPORTING_TOOL_PREAMBLE}
1375
+
1376
+ When to call:
1377
+ - The user reports something broken, failing, or not working as expected.
1378
+ - The user expresses frustration, anger, or threatens escalation.
1379
+ - You observe a product issue, billing problem, or data concern based on context.
1380
+ - The conversation reveals something unusual worth flagging for developer review.
1381
+
1382
+ Rules:
1383
+ 1. Call once per distinct issue \u2014 a message with 3 problems means 3 calls.
1384
+ 2. Pick the single best category per issue. Use noteworthy only when no specific category fits.
1385
+ 3. Do not fabricate issues. Only report what is evident from the conversation.
1386
+ ${guidanceBlock}
1387
+ Categories:
1388
+ ${signalList}`;
1389
+ return {
1390
+ toolName,
1391
+ toolDescription,
1392
+ signalKeys,
1393
+ signalKeySet: new Set(signalKeys),
1394
+ signalDescriptions,
1395
+ signalSentiments
1396
+ };
1397
+ }
1398
+ function resolveJsonSchemaFactory(aiSDK) {
1399
+ if (!isRecord(aiSDK) || !isFunction(aiSDK["jsonSchema"])) return void 0;
1400
+ return aiSDK["jsonSchema"];
1401
+ }
1402
+ function detectAISDKVersion(aiSDK) {
1403
+ if (!isRecord(aiSDK)) return "unknown";
1404
+ if (isFunction(aiSDK["jsonSchema"])) return "6";
1405
+ if (isFunction(aiSDK["tool"])) return "5";
1406
+ return "4";
1407
+ }
1408
+ function asVercelSchema(jsonSchemaObj) {
1409
+ const validatorSymbol = /* @__PURE__ */ Symbol.for("vercel.ai.validator");
1410
+ const schemaSymbol = /* @__PURE__ */ Symbol.for("vercel.ai.schema");
1411
+ return {
1412
+ [schemaSymbol]: true,
1413
+ [validatorSymbol]: true,
1414
+ _type: void 0,
1415
+ jsonSchema: jsonSchemaObj,
1416
+ validate: (value) => ({ success: true, value })
1417
+ };
1418
+ }
1419
+ function createSelfDiagnosticsTool(ctx) {
1420
+ const config = ctx.selfDiagnostics;
1421
+ if (!config) return void 0;
1422
+ const schema = {
1423
+ type: "object",
1424
+ additionalProperties: false,
1425
+ properties: {
1426
+ category: {
1427
+ type: "string",
1428
+ enum: config.signalKeys,
1429
+ description: "The single best-matching category from the list above."
1430
+ },
1431
+ detail: {
1432
+ type: "string",
1433
+ description: "One sentence of factual context: what happened and why it matters. Do not include PII or secrets."
1434
+ }
1435
+ },
1436
+ required: ["category", "detail"]
1437
+ };
1438
+ const parameters = asVercelSchema(schema);
1439
+ let inputSchema = parameters;
1440
+ if (ctx.jsonSchemaFactory) {
1441
+ try {
1442
+ inputSchema = ctx.jsonSchemaFactory(schema);
1443
+ } catch (e) {
1444
+ inputSchema = parameters;
1445
+ }
1446
+ }
1447
+ const execute = async (rawInput) => {
1448
+ var _a;
1449
+ const input = isRecord(rawInput) ? rawInput : void 0;
1450
+ const fallbackCategory = (_a = config.signalKeys[0]) != null ? _a : "unknown";
1451
+ const categoryCandidate = typeof (input == null ? void 0 : input["category"]) === "string" ? input["category"].trim() : void 0;
1452
+ const category = categoryCandidate && config.signalKeySet.has(categoryCandidate) ? categoryCandidate : fallbackCategory;
1453
+ const detail = typeof (input == null ? void 0 : input["detail"]) === "string" ? input["detail"].trim() : "";
1454
+ const signalDescription = config.signalDescriptions[category];
1455
+ const signalSentiment = config.signalSentiments[category];
1456
+ if (category === AGENT_REPORTING_NOTEWORTHY_SIGNAL_KEY) {
1457
+ void ctx.eventShipper.trackSignal({
1458
+ eventId: ctx.eventId,
1459
+ name: "agent:noteworthy",
1460
+ type: "agent_internal",
1461
+ properties: {
1462
+ source: "agent_flag_event_tool",
1463
+ reason: detail,
1464
+ severity: "medium",
1465
+ ai_sdk_version: ctx.aiSDKVersion
1466
+ }
1467
+ }).catch((err) => {
1468
+ if (ctx.debug) {
1469
+ const msg = err instanceof Error ? err.message : String(err);
1470
+ console.warn(`[raindrop-ai/ai-sdk] agentFlagEvent signal dispatch failed: ${msg}`);
1471
+ }
1472
+ });
1473
+ return { acknowledged: true, category };
1474
+ }
1475
+ void ctx.eventShipper.trackSignal({
1476
+ eventId: ctx.eventId,
1477
+ name: `agent:${category}`,
1478
+ type: "agent",
1479
+ sentiment: signalSentiment,
1480
+ properties: {
1481
+ source: "agent_reporting_tool",
1482
+ category,
1483
+ signal_description: signalDescription,
1484
+ ai_sdk_version: ctx.aiSDKVersion,
1485
+ ...detail ? { detail } : {}
1486
+ }
1487
+ }).catch((err) => {
1488
+ if (ctx.debug) {
1489
+ const msg = err instanceof Error ? err.message : String(err);
1490
+ console.warn(`[raindrop-ai/ai-sdk] selfDiagnostics signal dispatch failed: ${msg}`);
1491
+ }
1492
+ });
1493
+ return { acknowledged: true, category };
1494
+ };
1495
+ return {
1496
+ description: config.toolDescription,
1497
+ execute,
1498
+ parameters,
1499
+ inputSchema
1500
+ };
1501
+ }
1291
1502
  function getCurrentParentSpanContextSync() {
1292
1503
  return getContextManager().getParentSpanIds();
1293
1504
  }
@@ -1417,7 +1628,18 @@ function teeStreamObjectBaseStream(result) {
1417
1628
  }
1418
1629
  function setupOperation(params) {
1419
1630
  var _a, _b, _c;
1420
- const { operation, arg, inherited, aiSDK, options, traceShipper, sendTraces } = params;
1631
+ const {
1632
+ operation,
1633
+ arg,
1634
+ inherited,
1635
+ aiSDK,
1636
+ options,
1637
+ eventShipper,
1638
+ traceShipper,
1639
+ debug,
1640
+ selfDiagnostics,
1641
+ sendTraces
1642
+ } = params;
1421
1643
  const wrapTimeCtx = resolveContext(options.context, { operation, args: arg });
1422
1644
  const telemetry = extractExperimentalTelemetry(arg);
1423
1645
  const callTimeCtx = extractRaindropMetadata(telemetry == null ? void 0 : telemetry.metadata);
@@ -1456,12 +1678,18 @@ function setupOperation(params) {
1456
1678
  ]
1457
1679
  }) : void 0;
1458
1680
  const rootParentForChildren = rootSpan ? { traceIdB64: rootSpan.ids.traceIdB64, spanIdB64: rootSpan.ids.spanIdB64 } : inheritedParent;
1681
+ const operationSelfDiagnostics = isObjectOperation(operation) ? void 0 : selfDiagnostics;
1459
1682
  const wrapCtx = {
1460
1683
  eventId,
1461
1684
  telemetry,
1462
1685
  sendTraces,
1686
+ debug,
1687
+ eventShipper,
1463
1688
  traceShipper,
1464
- rootParentForChildren
1689
+ rootParentForChildren,
1690
+ jsonSchemaFactory: resolveJsonSchemaFactory(aiSDK),
1691
+ selfDiagnostics: operationSelfDiagnostics,
1692
+ aiSDKVersion: detectAISDKVersion(aiSDK)
1465
1693
  };
1466
1694
  const toolCalls = [];
1467
1695
  const argsWithWrappedTools = wrapTools(arg, wrapCtx, toolCalls);
@@ -1531,12 +1759,7 @@ function createFinalize(params) {
1531
1759
  attrInt("ai.usage.reasoningTokens", usage == null ? void 0 : usage.reasoningTokens),
1532
1760
  attrInt("ai.usage.cachedInputTokens", usage == null ? void 0 : usage.cachedInputTokens),
1533
1761
  attrInt("ai.toolCall.count", setup.toolCalls.length),
1534
- ...error ? [
1535
- attrString(
1536
- "error.message",
1537
- error instanceof Error ? error.message : String(error)
1538
- )
1539
- ] : []
1762
+ ...error ? [attrString("error.message", error instanceof Error ? error.message : String(error))] : []
1540
1763
  ]
1541
1764
  });
1542
1765
  }
@@ -1571,6 +1794,7 @@ function executeStreamingOperation(params) {
1571
1794
  deps,
1572
1795
  sendEvents,
1573
1796
  sendTraces,
1797
+ selfDiagnostics,
1574
1798
  autoAttachmentEnabled,
1575
1799
  debug
1576
1800
  } = params;
@@ -1580,7 +1804,10 @@ function executeStreamingOperation(params) {
1580
1804
  inherited: getCurrentParentSpanContextSync(),
1581
1805
  aiSDK,
1582
1806
  options: deps.options,
1807
+ eventShipper: deps.eventShipper,
1583
1808
  traceShipper: deps.traceShipper,
1809
+ debug,
1810
+ selfDiagnostics,
1584
1811
  sendTraces
1585
1812
  });
1586
1813
  const finalize = createFinalize({
@@ -1625,6 +1852,7 @@ async function executeNonStreamingOperation(params) {
1625
1852
  deps,
1626
1853
  sendEvents,
1627
1854
  sendTraces,
1855
+ selfDiagnostics,
1628
1856
  autoAttachmentEnabled,
1629
1857
  debug
1630
1858
  } = params;
@@ -1635,7 +1863,10 @@ async function executeNonStreamingOperation(params) {
1635
1863
  inherited,
1636
1864
  aiSDK,
1637
1865
  options: deps.options,
1866
+ eventShipper: deps.eventShipper,
1638
1867
  traceShipper: deps.traceShipper,
1868
+ debug,
1869
+ selfDiagnostics,
1639
1870
  sendTraces
1640
1871
  });
1641
1872
  const finalize = createFinalize({
@@ -1678,13 +1909,14 @@ function wrapAISDK(aiSDK, deps) {
1678
1909
  const sendEvents = ((_a = deps.options.send) == null ? void 0 : _a.events) !== false;
1679
1910
  const sendTraces = ((_b = deps.options.send) == null ? void 0 : _b.traces) !== false;
1680
1911
  const autoAttachmentEnabled = deps.options.autoAttachment !== false;
1912
+ const selfDiagnostics = normalizeSelfDiagnosticsConfig(deps.options.selfDiagnostics);
1681
1913
  const proxyTarget = isModuleNamespace(aiSDK) ? Object.setPrototypeOf({}, aiSDK) : aiSDK;
1682
1914
  return new Proxy(proxyTarget, {
1683
1915
  get(target, prop, receiver) {
1684
1916
  const original = Reflect.get(target, prop, receiver);
1685
1917
  if (typeof prop === "string" && agentClasses.has(prop) && isAgentClass(original)) {
1686
1918
  if (debug) console.log(`[raindrop-ai/ai-sdk] Wrapping Agent class: ${prop}`);
1687
- return wrapAgentClass(original, aiSDK, deps, debug);
1919
+ return wrapAgentClass(original, aiSDK, deps, debug, selfDiagnostics);
1688
1920
  }
1689
1921
  if (typeof prop !== "string" || !instrumentedOps.has(prop) || !isFunction(original)) {
1690
1922
  return original;
@@ -1702,6 +1934,7 @@ function wrapAISDK(aiSDK, deps) {
1702
1934
  deps,
1703
1935
  sendEvents,
1704
1936
  sendTraces,
1937
+ selfDiagnostics,
1705
1938
  autoAttachmentEnabled,
1706
1939
  debug
1707
1940
  });
@@ -1715,6 +1948,7 @@ function wrapAISDK(aiSDK, deps) {
1715
1948
  deps,
1716
1949
  sendEvents,
1717
1950
  sendTraces,
1951
+ selfDiagnostics,
1718
1952
  autoAttachmentEnabled,
1719
1953
  debug
1720
1954
  });
@@ -1722,7 +1956,7 @@ function wrapAISDK(aiSDK, deps) {
1722
1956
  }
1723
1957
  });
1724
1958
  }
1725
- function wrapAgentClass(AgentClass, aiSDK, deps, debug) {
1959
+ function wrapAgentClass(AgentClass, aiSDK, deps, debug, selfDiagnostics) {
1726
1960
  return new Proxy(AgentClass, {
1727
1961
  construct(target, args, newTarget) {
1728
1962
  const instance = Reflect.construct(target, args, newTarget);
@@ -1741,7 +1975,8 @@ function wrapAgentClass(AgentClass, aiSDK, deps, debug) {
1741
1975
  className,
1742
1976
  aiSDK,
1743
1977
  deps,
1744
- debug
1978
+ debug,
1979
+ selfDiagnostics
1745
1980
  );
1746
1981
  }
1747
1982
  if (prop === "stream" && isFunction(original)) {
@@ -1753,7 +1988,8 @@ function wrapAgentClass(AgentClass, aiSDK, deps, debug) {
1753
1988
  className,
1754
1989
  aiSDK,
1755
1990
  deps,
1756
- debug
1991
+ debug,
1992
+ selfDiagnostics
1757
1993
  );
1758
1994
  }
1759
1995
  return original;
@@ -1762,7 +1998,7 @@ function wrapAgentClass(AgentClass, aiSDK, deps, debug) {
1762
1998
  }
1763
1999
  });
1764
2000
  }
1765
- function wrapAgentGenerate(generate, instance, agentSettings, className, aiSDK, deps, debug) {
2001
+ function wrapAgentGenerate(generate, instance, agentSettings, className, aiSDK, deps, debug, selfDiagnostics) {
1766
2002
  var _a, _b;
1767
2003
  const sendEvents = ((_a = deps.options.send) == null ? void 0 : _a.events) !== false;
1768
2004
  const sendTraces = ((_b = deps.options.send) == null ? void 0 : _b.traces) !== false;
@@ -1774,7 +2010,7 @@ function wrapAgentGenerate(generate, instance, agentSettings, className, aiSDK,
1774
2010
  const operation = `${className}.generate`;
1775
2011
  const wrapTimeCtx = resolveContext(deps.options.context, { operation, args: mergedArgs });
1776
2012
  const telemetry = extractExperimentalTelemetry(mergedArgs);
1777
- const callTimeCtx = extractRaindropMetadata(telemetry == null ? void 0 : telemetry.metadata);
2013
+ const callTimeCtx = extractRaindropCallOptions(mergedArgs);
1778
2014
  const mergedCtx = mergeContexts(wrapTimeCtx, callTimeCtx);
1779
2015
  if (!mergedCtx.userId) warnMissingUserIdOnce();
1780
2016
  const inherited = await getCurrentParentSpanContext();
@@ -1815,8 +2051,13 @@ function wrapAgentGenerate(generate, instance, agentSettings, className, aiSDK,
1815
2051
  eventId,
1816
2052
  telemetry,
1817
2053
  sendTraces,
2054
+ debug,
2055
+ eventShipper: deps.eventShipper,
1818
2056
  traceShipper: deps.traceShipper,
1819
- rootParentForChildren
2057
+ rootParentForChildren,
2058
+ jsonSchemaFactory: resolveJsonSchemaFactory(aiSDK),
2059
+ selfDiagnostics,
2060
+ aiSDKVersion: detectAISDKVersion(aiSDK)
1820
2061
  };
1821
2062
  const toolCalls = [];
1822
2063
  const mergedArgsWithWrappedTools = wrapTools(mergedArgs, wrapCtx, toolCalls);
@@ -1950,7 +2191,7 @@ function wrapAgentGenerate(generate, instance, agentSettings, className, aiSDK,
1950
2191
  }
1951
2192
  };
1952
2193
  }
1953
- function wrapAgentStream(stream, instance, agentSettings, className, aiSDK, deps, debug) {
2194
+ function wrapAgentStream(stream, instance, agentSettings, className, aiSDK, deps, debug, selfDiagnostics) {
1954
2195
  var _a, _b;
1955
2196
  const sendEvents = ((_a = deps.options.send) == null ? void 0 : _a.events) !== false;
1956
2197
  const sendTraces = ((_b = deps.options.send) == null ? void 0 : _b.traces) !== false;
@@ -1962,7 +2203,7 @@ function wrapAgentStream(stream, instance, agentSettings, className, aiSDK, deps
1962
2203
  const operation = `${className}.stream`;
1963
2204
  const wrapTimeCtx = resolveContext(deps.options.context, { operation, args: mergedArgs });
1964
2205
  const telemetry = extractExperimentalTelemetry(mergedArgs);
1965
- const callTimeCtx = extractRaindropMetadata(telemetry == null ? void 0 : telemetry.metadata);
2206
+ const callTimeCtx = extractRaindropCallOptions(mergedArgs);
1966
2207
  const mergedCtx = mergeContexts(wrapTimeCtx, callTimeCtx);
1967
2208
  if (!mergedCtx.userId) warnMissingUserIdOnce();
1968
2209
  const inherited = await getCurrentParentSpanContext();
@@ -2003,8 +2244,13 @@ function wrapAgentStream(stream, instance, agentSettings, className, aiSDK, deps
2003
2244
  eventId,
2004
2245
  telemetry,
2005
2246
  sendTraces,
2247
+ debug,
2248
+ eventShipper: deps.eventShipper,
2006
2249
  traceShipper: deps.traceShipper,
2007
- rootParentForChildren
2250
+ rootParentForChildren,
2251
+ jsonSchemaFactory: resolveJsonSchemaFactory(aiSDK),
2252
+ selfDiagnostics,
2253
+ aiSDKVersion: detectAISDKVersion(aiSDK)
2008
2254
  };
2009
2255
  const toolCalls = [];
2010
2256
  const mergedArgsWithWrappedTools = wrapTools(mergedArgs, wrapCtx, toolCalls);
@@ -2144,8 +2390,22 @@ function wrapAgentStream(stream, instance, agentSettings, className, aiSDK, deps
2144
2390
  };
2145
2391
  }
2146
2392
  function wrapTools(args, ctx, toolCalls) {
2147
- if (!isRecord(args) || !("tools" in args) || !isRecord(args["tools"])) return args;
2148
- const tools = args["tools"];
2393
+ if (!isRecord(args)) return args;
2394
+ const tools = isRecord(args["tools"]) ? { ...args["tools"] } : {};
2395
+ if (ctx.selfDiagnostics) {
2396
+ const reportToolName = ctx.selfDiagnostics.toolName;
2397
+ if (!(reportToolName in tools)) {
2398
+ const reportTool = createSelfDiagnosticsTool(ctx);
2399
+ if (reportTool !== void 0) {
2400
+ tools[reportToolName] = reportTool;
2401
+ }
2402
+ } else if (ctx.debug) {
2403
+ console.warn(
2404
+ `[raindrop-ai/ai-sdk] selfDiagnostics skipped: tool name collision for "${reportToolName}"`
2405
+ );
2406
+ }
2407
+ }
2408
+ if (Object.keys(tools).length === 0) return args;
2149
2409
  const wrapped = {};
2150
2410
  for (const [name, tool] of Object.entries(tools)) {
2151
2411
  wrapped[name] = wrapToolExecute(name, tool, ctx, toolCalls);
@@ -2632,18 +2892,26 @@ function envDebugEnabled() {
2632
2892
  }
2633
2893
  function createRaindropAISDK(opts) {
2634
2894
  var _a, _b, _c, _d, _e, _f, _g, _h, _i;
2635
- const eventsEnabled = ((_a = opts.events) == null ? void 0 : _a.enabled) !== false;
2636
- const tracesEnabled = ((_b = opts.traces) == null ? void 0 : _b.enabled) !== false;
2895
+ const writeKey = opts.writeKey;
2896
+ const eventsRequested = ((_a = opts.events) == null ? void 0 : _a.enabled) !== false;
2897
+ const tracesRequested = ((_b = opts.traces) == null ? void 0 : _b.enabled) !== false;
2898
+ const eventsEnabled = eventsRequested && !!writeKey;
2899
+ const tracesEnabled = tracesRequested && !!writeKey;
2637
2900
  const envDebug = envDebugEnabled();
2901
+ if (!writeKey && (eventsRequested || tracesRequested)) {
2902
+ console.warn(
2903
+ "[raindrop-ai/ai-sdk] writeKey not provided; telemetry shipping is disabled"
2904
+ );
2905
+ }
2638
2906
  const eventShipper = new EventShipper({
2639
- writeKey: opts.writeKey,
2907
+ writeKey,
2640
2908
  endpoint: opts.endpoint,
2641
2909
  enabled: eventsEnabled,
2642
2910
  debug: ((_c = opts.events) == null ? void 0 : _c.debug) === true || envDebug,
2643
2911
  partialFlushMs: (_d = opts.events) == null ? void 0 : _d.partialFlushMs
2644
2912
  });
2645
2913
  const traceShipper = new TraceShipper({
2646
- writeKey: opts.writeKey,
2914
+ writeKey,
2647
2915
  endpoint: opts.endpoint,
2648
2916
  enabled: tracesEnabled,
2649
2917
  debug: ((_e = opts.traces) == null ? void 0 : _e.debug) === true || envDebug,
package/dist/index.d.mts CHANGED
@@ -127,6 +127,48 @@ type EventMetadataOptions = {
127
127
  * ```
128
128
  */
129
129
  declare function eventMetadata(options: EventMetadataOptions): Record<string, string>;
130
+ type AgentCallMetadata = ReturnType<typeof eventMetadata>;
131
+ type NormalizeUnknownAgentOptions<T> = T extends {
132
+ options: infer CallOptions;
133
+ } ? unknown extends CallOptions ? Omit<T, "options"> & {
134
+ options?: never;
135
+ } : T : T;
136
+ /**
137
+ * Wraps an agent instance type so `generate()` and `stream()` accept optional
138
+ * Raindrop call metadata while preserving original return types.
139
+ */
140
+ type AgentWithMetadata<A> = A extends {
141
+ generate: (...args: infer GenerateArgs) => infer GenerateReturn;
142
+ stream: (...args: infer StreamArgs) => infer StreamReturn;
143
+ } ? Omit<A, "generate" | "stream"> & {
144
+ generate(...args: GenerateArgs extends [infer Options, ...infer Rest] ? [NormalizeUnknownAgentOptions<Options> & {
145
+ metadata?: AgentCallMetadata;
146
+ }, ...Rest] : GenerateArgs): GenerateReturn;
147
+ stream(...args: StreamArgs extends [infer Options, ...infer Rest] ? [NormalizeUnknownAgentOptions<Options> & {
148
+ metadata?: AgentCallMetadata;
149
+ }, ...Rest] : StreamArgs): StreamReturn;
150
+ } : A;
151
+ /**
152
+ * Structural wrapper type for AI SDK modules.
153
+ *
154
+ * - AI SDK v6: rewrites `ToolLoopAgent` constructor instance methods to accept
155
+ * `metadata` on `generate/stream`.
156
+ * - AI SDK v4/v5: no `ToolLoopAgent` export, so the type is unchanged.
157
+ */
158
+ type WrappedAISDK<T extends object> = T extends {
159
+ ToolLoopAgent: abstract new (...args: any[]) => any;
160
+ } ? Omit<T, "ToolLoopAgent"> & {
161
+ ToolLoopAgent: new (...args: ConstructorParameters<T["ToolLoopAgent"]>) => AgentWithMetadata<InstanceType<T["ToolLoopAgent"]>>;
162
+ } : T;
163
+ /**
164
+ * Backward-compatible alias for wrapped AI SDK module types.
165
+ *
166
+ * This alias intentionally avoids referencing `import("ai")` to satisfy type
167
+ * resolution without requiring `ai` to be installed.
168
+ *
169
+ * Prefer `WrappedAISDK<typeof ai>` in app code when you have an `ai` import.
170
+ */
171
+ type WrappedAI<T extends object = any> = WrappedAISDK<T>;
130
172
  type Attachment = {
131
173
  attachment_id?: string;
132
174
  name?: string;
@@ -139,7 +181,11 @@ type Attachment = {
139
181
  type: "text" | "image" | "iframe";
140
182
  });
141
183
  type RaindropAISDKOptions = {
142
- writeKey: string;
184
+ /**
185
+ * API write key. If omitted, telemetry shipping is disabled but `wrap()` is
186
+ * still available for a consistent integration surface.
187
+ */
188
+ writeKey?: string;
143
189
  endpoint?: string;
144
190
  traces?: {
145
191
  enabled?: boolean;
@@ -192,6 +238,38 @@ type AISDKMessage = {
192
238
  * - at the end with appended response messages (assistant/tool, incl tool-call + tool-result parts)
193
239
  */
194
240
  type EventBuilder = (messages: AISDKMessage[]) => void | BuildEventPatch;
241
+ type SelfDiagnosticsSignalDefinition = {
242
+ /**
243
+ * Human-readable meaning of this signal.
244
+ * Used in the injected tool schema and stored in signal properties.
245
+ */
246
+ description: string;
247
+ /**
248
+ * Optional default sentiment for this signal key.
249
+ * This can help dashboards classify negative/positive programmatic signals.
250
+ */
251
+ sentiment?: "POSITIVE" | "NEGATIVE";
252
+ };
253
+ type SelfDiagnosticsSignalDefinitions = Record<string, SelfDiagnosticsSignalDefinition>;
254
+ type SelfDiagnosticsOptions = {
255
+ /** Enable automatic injection of the self diagnostics tool. Default: false */
256
+ enabled?: boolean;
257
+ /**
258
+ * Signal keys and descriptions exposed to the model.
259
+ * Defaults to a built-in set when omitted.
260
+ */
261
+ signals?: SelfDiagnosticsSignalDefinitions;
262
+ /**
263
+ * Optional extra guidance for when the model should emit self diagnostics.
264
+ * The SDK still generates a full tool prompt from `signals`.
265
+ */
266
+ guidance?: string;
267
+ /**
268
+ * Optional tool name override for the injected self diagnostics tool.
269
+ * Defaults to "__raindrop_report".
270
+ */
271
+ toolName?: string;
272
+ };
195
273
  type WrapAISDKOptions = {
196
274
  context: RaindropAISDKContext | ((info: {
197
275
  operation: string;
@@ -199,6 +277,7 @@ type WrapAISDKOptions = {
199
277
  }) => RaindropAISDKContext);
200
278
  buildEvent?: EventBuilder;
201
279
  autoAttachment?: boolean;
280
+ selfDiagnostics?: SelfDiagnosticsOptions;
202
281
  send?: {
203
282
  events?: boolean;
204
283
  traces?: boolean;
@@ -217,7 +296,7 @@ type EventPatch = {
217
296
  timestamp?: string;
218
297
  };
219
298
  type RaindropAISDKClient = {
220
- wrap<T extends object>(aiSDK: T, options?: WrapAISDKOptions): T;
299
+ wrap<T extends object>(aiSDK: T, options?: WrapAISDKOptions): WrappedAISDK<T>;
221
300
  events: {
222
301
  patch(eventId: string, patch: EventPatch): Promise<void>;
223
302
  addAttachments(eventId: string, attachments: Attachment[]): Promise<void>;
@@ -235,7 +314,7 @@ type RaindropAISDKClient = {
235
314
  track(signal: {
236
315
  eventId: string;
237
316
  name: "thumbs_up" | "thumbs_down" | string;
238
- type?: "default" | "feedback" | "edit";
317
+ type?: "default" | "feedback" | "edit" | "standard" | "agent" | "agent_internal";
239
318
  sentiment?: "POSITIVE" | "NEGATIVE";
240
319
  timestamp?: string;
241
320
  properties?: Record<string, unknown>;
@@ -249,4 +328,4 @@ type RaindropAISDKClient = {
249
328
  };
250
329
  declare function createRaindropAISDK(opts: RaindropAISDKOptions): RaindropAISDKClient;
251
330
 
252
- export { type AISDKMessage, type Attachment, type BuildEventPatch, ContextManager, type ContextSpan, type EventBuilder, type EventMetadataOptions, type IdentifyInput, type RaindropAISDKClient, type RaindropAISDKContext, type RaindropAISDKOptions, type WrapAISDKOptions, _resetWarnedMissingUserId, createRaindropAISDK, currentSpan, eventMetadata, getContextManager, withCurrent };
331
+ export { type AISDKMessage, type AgentCallMetadata, type AgentWithMetadata, type Attachment, type BuildEventPatch, ContextManager, type ContextSpan, type EventBuilder, type EventMetadataOptions, type IdentifyInput, type RaindropAISDKClient, type RaindropAISDKContext, type RaindropAISDKOptions, type SelfDiagnosticsOptions, type SelfDiagnosticsSignalDefinition, type SelfDiagnosticsSignalDefinitions, type WrapAISDKOptions, type WrappedAI, type WrappedAISDK, _resetWarnedMissingUserId, createRaindropAISDK, currentSpan, eventMetadata, getContextManager, withCurrent };