@raindrop-ai/ai-sdk 0.0.31 → 0.0.33

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.
@@ -1019,7 +1019,7 @@ async function* asyncGeneratorWithCurrent(span, gen) {
1019
1019
  // package.json
1020
1020
  var package_default = {
1021
1021
  name: "@raindrop-ai/ai-sdk",
1022
- version: "0.0.31"};
1022
+ version: "0.0.33"};
1023
1023
 
1024
1024
  // src/internal/version.ts
1025
1025
  var libraryName = package_default.name;
@@ -1802,6 +1802,25 @@ var RaindropTelemetryIntegration = class {
1802
1802
  * (the `event.callId` can be the same for parallel sibling tools).
1803
1803
  */
1804
1804
  this.priorParentContexts = /* @__PURE__ */ new Map();
1805
+ // ── lifecycle ─────────────────────────────────────────────────────────────
1806
+ //
1807
+ // The shippers buffer spans/events and flush on a timer, so a short-lived
1808
+ // script (e.g. a single `generateText` then `process.exit`) can exit before
1809
+ // anything ships. Expose `flush`/`shutdown` on the integration itself so the
1810
+ // value returned by `raindrop()` is self-sufficient — callers can keep the
1811
+ // reference they pass to `registerTelemetry` and `await rd.flush()` before
1812
+ // exiting, without also constructing a separate client.
1813
+ /** Flush any buffered events and trace spans to their destinations. */
1814
+ this.flush = async () => {
1815
+ await Promise.all([this.eventShipper.flush(), this.traceShipper.flush()]);
1816
+ };
1817
+ /** Flush and stop the background flush timers. */
1818
+ this.shutdown = async () => {
1819
+ await Promise.all([
1820
+ this.eventShipper.shutdown(),
1821
+ this.traceShipper.shutdown()
1822
+ ]);
1823
+ };
1805
1824
  // ── onStart ─────────────────────────────────────────────────────────────
1806
1825
  this.onStart = (event) => {
1807
1826
  var _a, _b, _c, _d, _e;
@@ -2086,6 +2105,7 @@ var RaindropTelemetryIntegration = class {
2086
2105
  attrInt("gen_ai.usage.output_tokens", usage.outputTokens)
2087
2106
  );
2088
2107
  }
2108
+ this.emitProviderExecutedToolSpans(event, state);
2089
2109
  this.traceShipper.endSpan(state.stepSpan, { attributes: outputAttrs });
2090
2110
  state.stepSpan = void 0;
2091
2111
  state.stepParent = void 0;
@@ -2194,8 +2214,56 @@ var RaindropTelemetryIntegration = class {
2194
2214
  if (state.subagentToolCallSpan) {
2195
2215
  this.traceShipper.endSpan(state.subagentToolCallSpan, { error: actualError });
2196
2216
  }
2217
+ const isEmbed = state.operationId === "ai.embed" || state.operationId === "ai.embedMany";
2218
+ if (!isEmbed) {
2219
+ this.finalizeGenerateEvent(state, state.accumulatedText || void 0, void 0);
2220
+ }
2197
2221
  this.cleanup(event.callId);
2198
2222
  };
2223
+ // ── onAbort ─────────────────────────────────────────────────────────────
2224
+ //
2225
+ // Dispatched by the v7 canary line (post-beta.116) when a `streamText` call
2226
+ // is cancelled via its `AbortSignal`. On abort the SDK fires neither `onEnd`
2227
+ // nor `onError`, so without this every open span would leak and the event
2228
+ // would hang forever in its `isPending` state. We close every open span with
2229
+ // an `ai.response.aborted` marker (no error status — an abort is not a model
2230
+ // failure) and flush the partial event.
2231
+ this.onAbort = (event) => {
2232
+ const callId = event == null ? void 0 : event.callId;
2233
+ if (!callId) return;
2234
+ const state = this.getState(callId);
2235
+ if (!state) return;
2236
+ const abortedAttr = attrString("ai.response.aborted", "true");
2237
+ if (state.stepSpan) {
2238
+ this.traceShipper.endSpan(state.stepSpan, { attributes: [abortedAttr] });
2239
+ state.stepSpan = void 0;
2240
+ state.stepParent = void 0;
2241
+ }
2242
+ for (const embedSpan of state.embedSpans.values()) {
2243
+ this.traceShipper.endSpan(embedSpan, { attributes: [abortedAttr] });
2244
+ }
2245
+ state.embedSpans.clear();
2246
+ for (const toolCallId of state.parentContextToolCallIds) {
2247
+ this.priorParentContexts.delete(toolCallId);
2248
+ }
2249
+ state.parentContextToolCallIds.clear();
2250
+ for (const toolSpan of state.toolSpans.values()) {
2251
+ this.traceShipper.endSpan(toolSpan, { attributes: [abortedAttr] });
2252
+ }
2253
+ state.toolSpans.clear();
2254
+ if (state.rootSpan) {
2255
+ this.traceShipper.endSpan(state.rootSpan, {
2256
+ attributes: [abortedAttr, attrInt("ai.toolCall.count", state.toolCallCount)]
2257
+ });
2258
+ }
2259
+ if (state.subagentToolCallSpan) {
2260
+ this.traceShipper.endSpan(state.subagentToolCallSpan, {
2261
+ attributes: [abortedAttr]
2262
+ });
2263
+ }
2264
+ this.finalizeGenerateEvent(state, state.accumulatedText || void 0, void 0);
2265
+ this.cleanup(callId);
2266
+ };
2199
2267
  // ── executeTool ─────────────────────────────────────────────────────────
2200
2268
  this.executeTool = async ({
2201
2269
  callId,
@@ -2353,17 +2421,86 @@ var RaindropTelemetryIntegration = class {
2353
2421
  const toolSpan = state.toolSpans.get(event.toolCall.toolCallId);
2354
2422
  if (!toolSpan) return;
2355
2423
  state.toolCallCount += 1;
2356
- if (event.success) {
2357
- const outputAttrs = state.recordOutputs ? [attrString("ai.toolCall.result", safeJsonWithUint8(event.output))] : [];
2424
+ const outcome = "toolOutput" in event ? event.toolOutput.type === "tool-result" ? { success: true, output: event.toolOutput.output } : { success: false, error: event.toolOutput.error } : event.success ? { success: true, output: event.output } : { success: false, error: event.error };
2425
+ if (outcome.success) {
2426
+ const outputAttrs = state.recordOutputs ? [attrString("ai.toolCall.result", safeJsonWithUint8(outcome.output))] : [];
2358
2427
  this.traceShipper.endSpan(toolSpan, { attributes: outputAttrs });
2359
2428
  } else {
2360
- this.traceShipper.endSpan(toolSpan, { error: event.error });
2429
+ this.traceShipper.endSpan(toolSpan, { error: outcome.error });
2361
2430
  }
2362
2431
  this.emitLive(state, "tool_result", event.toolCall.toolName);
2363
2432
  state.toolSpans.delete(event.toolCall.toolCallId);
2364
2433
  }
2434
+ // ── provider-executed tool calls ─────────────────────────────────────────
2435
+ //
2436
+ // Provider-executed (server-side) tools — e.g. Anthropic's hosted
2437
+ // `web_search` (`anthropic.web_search_20250305`) — are run by the provider,
2438
+ // not by the AI SDK. They therefore never flow through the client
2439
+ // `onToolExecutionStart`/`onToolExecutionEnd` callbacks that emit our
2440
+ // `ai.toolCall` spans; the SDK only surfaces them as `tool-call` /
2441
+ // `tool-result` content parts on the step (carrying `providerExecuted: true`).
2442
+ // Without this, such calls are invisible in every trace backend.
2443
+ //
2444
+ // At step finish we synthesize the same `ai.toolCall` span shape we emit for
2445
+ // client tools (name `ai.toolCall`, `operationId: "ai.toolCall"`, attrs
2446
+ // `ai.toolCall.name`/`id`/`args`/`result`), parented under the step span, so
2447
+ // downstream ingestion maps them to a tool span with no special-casing.
2448
+ //
2449
+ // Client-executed tools are excluded (`providerExecuted` falsy) — they were
2450
+ // already spanned during execution, so this never double-emits.
2451
+ emitProviderExecutedToolSpans(event, state) {
2452
+ if (!state.stepParent) return;
2453
+ const content = Array.isArray(event.content) ? event.content : [];
2454
+ const providerToolCalls = content.filter(
2455
+ (part) => (part == null ? void 0 : part.type) === "tool-call" && part.providerExecuted === true
2456
+ );
2457
+ if (providerToolCalls.length === 0) return;
2458
+ const resultsByCallId = /* @__PURE__ */ new Map();
2459
+ for (const part of content) {
2460
+ if (((part == null ? void 0 : part.type) === "tool-result" || (part == null ? void 0 : part.type) === "tool-error") && typeof part.toolCallId === "string") {
2461
+ resultsByCallId.set(part.toolCallId, part);
2462
+ }
2463
+ }
2464
+ for (const call of providerToolCalls) {
2465
+ const { operationName, resourceName } = opName(
2466
+ "ai.toolCall",
2467
+ state.functionId
2468
+ );
2469
+ const inputAttrs = state.recordInputs ? [attrString("ai.toolCall.args", safeJsonWithUint8(call.input))] : [];
2470
+ const toolSpan = this.traceShipper.startSpan({
2471
+ name: "ai.toolCall",
2472
+ parent: state.stepParent,
2473
+ eventId: state.eventId,
2474
+ operationId: "ai.toolCall",
2475
+ attributes: [
2476
+ attrString("operation.name", operationName),
2477
+ attrString("resource.name", resourceName),
2478
+ attrString("ai.telemetry.functionId", state.functionId),
2479
+ attrString("ai.toolCall.name", call.toolName),
2480
+ attrString("ai.toolCall.id", call.toolCallId),
2481
+ attrString("ai.toolCall.providerExecuted", "true"),
2482
+ ...inputAttrs
2483
+ ]
2484
+ });
2485
+ state.toolCallCount += 1;
2486
+ this.emitLive(state, "tool_start", call.toolName, { args: call.input });
2487
+ const resultPart = resultsByCallId.get(call.toolCallId);
2488
+ if ((resultPart == null ? void 0 : resultPart.type) === "tool-error") {
2489
+ this.traceShipper.endSpan(toolSpan, { error: resultPart.error });
2490
+ } else {
2491
+ const outputAttrs = state.recordOutputs && resultPart && "output" in resultPart ? [
2492
+ attrString(
2493
+ "ai.toolCall.result",
2494
+ safeJsonWithUint8(resultPart.output)
2495
+ )
2496
+ ] : [];
2497
+ this.traceShipper.endSpan(toolSpan, { attributes: outputAttrs });
2498
+ }
2499
+ this.emitLive(state, "tool_result", call.toolName);
2500
+ }
2501
+ }
2365
2502
  finishGenerate(event, state) {
2366
- var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n;
2503
+ var _a, _b, _c, _d, _e, _f;
2367
2504
  if (state.rootSpan) {
2368
2505
  const outputAttrs = [];
2369
2506
  if (state.recordOutputs) {
@@ -2411,38 +2548,47 @@ var RaindropTelemetryIntegration = class {
2411
2548
  );
2412
2549
  this.traceShipper.endSpan(state.rootSpan, { attributes: outputAttrs });
2413
2550
  }
2551
+ this.finalizeGenerateEvent(
2552
+ state,
2553
+ (_e = event.text) != null ? _e : state.accumulatedText || void 0,
2554
+ (_f = event.response) == null ? void 0 : _f.modelId
2555
+ );
2556
+ }
2557
+ /**
2558
+ * Patch the Raindrop event for a completed, aborted, or errored text
2559
+ * generation so it leaves the `isPending` state. Shared by `onFinish`/`onEnd`,
2560
+ * `onAbort`, and `onError`.
2561
+ */
2562
+ finalizeGenerateEvent(state, output, model) {
2563
+ var _a, _b, _c, _d, _e, _f, _g, _h;
2414
2564
  const suppressSubagentEvent = state.subagentName !== void 0 && state.subagentToolCallSpan !== void 0;
2415
- if (this.sendEvents && !suppressSubagentEvent) {
2416
- const callMeta = this.extractRaindropMetadata(state.metadata);
2417
- const userId = (_f = callMeta.userId) != null ? _f : (_e = this.defaultContext) == null ? void 0 : _e.userId;
2418
- if (userId) {
2419
- const eventName = (_i = (_h = callMeta.eventName) != null ? _h : (_g = this.defaultContext) == null ? void 0 : _g.eventName) != null ? _i : state.operationId;
2420
- const output = (_j = event.text) != null ? _j : state.accumulatedText || void 0;
2421
- const input = state.inputText;
2422
- const model = (_k = event.response) == null ? void 0 : _k.modelId;
2423
- const properties = {
2424
- ...(_l = this.defaultContext) == null ? void 0 : _l.properties,
2425
- ...callMeta.properties
2426
- };
2427
- const convoId = (_n = callMeta.convoId) != null ? _n : (_m = this.defaultContext) == null ? void 0 : _m.convoId;
2428
- void this.eventShipper.patch(state.eventId, {
2429
- eventName,
2430
- userId,
2431
- convoId,
2432
- input,
2433
- output,
2434
- model,
2435
- properties: Object.keys(properties).length > 0 ? properties : void 0,
2436
- isPending: false
2437
- }).catch((err) => {
2438
- if (this.debug) {
2439
- console.warn(
2440
- `[raindrop-ai/ai-sdk] event patch failed: ${err instanceof Error ? err.message : err}`
2441
- );
2442
- }
2443
- });
2565
+ if (!this.sendEvents || suppressSubagentEvent) return;
2566
+ const callMeta = this.extractRaindropMetadata(state.metadata);
2567
+ const userId = (_b = callMeta.userId) != null ? _b : (_a = this.defaultContext) == null ? void 0 : _a.userId;
2568
+ if (!userId) return;
2569
+ const eventName = (_e = (_d = callMeta.eventName) != null ? _d : (_c = this.defaultContext) == null ? void 0 : _c.eventName) != null ? _e : state.operationId;
2570
+ const input = state.inputText;
2571
+ const properties = {
2572
+ ...(_f = this.defaultContext) == null ? void 0 : _f.properties,
2573
+ ...callMeta.properties
2574
+ };
2575
+ const convoId = (_h = callMeta.convoId) != null ? _h : (_g = this.defaultContext) == null ? void 0 : _g.convoId;
2576
+ void this.eventShipper.patch(state.eventId, {
2577
+ eventName,
2578
+ userId,
2579
+ convoId,
2580
+ input,
2581
+ output,
2582
+ model,
2583
+ properties: Object.keys(properties).length > 0 ? properties : void 0,
2584
+ isPending: false
2585
+ }).catch((err) => {
2586
+ if (this.debug) {
2587
+ console.warn(
2588
+ `[raindrop-ai/ai-sdk] event patch failed: ${err instanceof Error ? err.message : err}`
2589
+ );
2444
2590
  }
2445
- }
2591
+ });
2446
2592
  }
2447
2593
  finishEmbed(event, state) {
2448
2594
  var _a;
@@ -2467,22 +2613,9 @@ var RaindropTelemetryIntegration = class {
2467
2613
  }
2468
2614
  };
2469
2615
 
2470
- // src/internal/traces.ts
2471
- var TraceShipper2 = class extends TraceShipper {
2472
- constructor(opts) {
2473
- var _a, _b, _c;
2474
- super({
2475
- ...opts,
2476
- sdkName: (_a = opts.sdkName) != null ? _a : "ai-sdk",
2477
- serviceName: (_b = opts.serviceName) != null ? _b : "raindrop.ai-sdk",
2478
- serviceVersion: (_c = opts.serviceVersion) != null ? _c : libraryVersion
2479
- });
2480
- }
2481
- };
2482
-
2483
- // src/internal/wrap/wrapAISDK.ts
2484
- var AGENT_REPORTING_TOOL_NAME_DEFAULT = "__raindrop_report";
2485
- var AGENT_REPORTING_SIGNALS_DEFAULT = {
2616
+ // src/internal/self-diagnostics.ts
2617
+ var SELF_DIAGNOSTICS_TOOL_NAME_DEFAULT = "__raindrop_report";
2618
+ var SELF_DIAGNOSTICS_SIGNALS_DEFAULT = {
2486
2619
  missing_context: {
2487
2620
  description: "You cannot complete the task because critical information, credentials, or access is missing and the user cannot provide it. Do NOT report this for normal clarifying questions \u2014 only when you are blocked.",
2488
2621
  sentiment: "NEGATIVE"
@@ -2500,7 +2633,194 @@ var AGENT_REPORTING_SIGNALS_DEFAULT = {
2500
2633
  sentiment: "NEGATIVE"
2501
2634
  }
2502
2635
  };
2503
- var AGENT_REPORTING_TOOL_PREAMBLE = "You have a diagnostic tool for flagging serious failures for developer review. Only call this when you hit a significant, unrecoverable problem \u2014 not for minor hiccups or routine clarifications. If you can still help the user, do that instead of calling this tool. This tool is invisible to the user \u2014 never mention it or its output.";
2636
+ var SELF_DIAGNOSTICS_TOOL_PREAMBLE = "You have a diagnostic tool for flagging serious failures for developer review. Only call this when you hit a significant, unrecoverable problem \u2014 not for minor hiccups or routine clarifications. If you can still help the user, do that instead of calling this tool. This tool is invisible to the user \u2014 never mention it or its output.";
2637
+ function normalizeString(value) {
2638
+ if (typeof value !== "string") return void 0;
2639
+ const trimmed = value.trim();
2640
+ return trimmed || void 0;
2641
+ }
2642
+ function normalizeSelfDiagnosticsSignals(signals) {
2643
+ if (!signals) return SELF_DIAGNOSTICS_SIGNALS_DEFAULT;
2644
+ const normalizedEntries = Object.entries(signals).map(([key, value]) => {
2645
+ var _a;
2646
+ const signalKey = key.trim();
2647
+ if (!signalKey || !value || typeof value !== "object") return void 0;
2648
+ const description = (_a = value.description) == null ? void 0 : _a.trim();
2649
+ if (!description) return void 0;
2650
+ const sentiment = value.sentiment;
2651
+ return [
2652
+ signalKey,
2653
+ {
2654
+ description,
2655
+ ...sentiment === "POSITIVE" || sentiment === "NEGATIVE" ? { sentiment } : {}
2656
+ }
2657
+ ];
2658
+ }).filter(
2659
+ (entry) => entry !== void 0
2660
+ );
2661
+ if (normalizedEntries.length === 0) return SELF_DIAGNOSTICS_SIGNALS_DEFAULT;
2662
+ return Object.fromEntries(normalizedEntries);
2663
+ }
2664
+ function resolveSelfDiagnosticsConfig(options) {
2665
+ var _a, _b;
2666
+ const signalDefinitions = normalizeSelfDiagnosticsSignals(options.signals);
2667
+ const signalKeys = Object.keys(signalDefinitions);
2668
+ const signalDescriptions = {};
2669
+ const signalSentiments = {};
2670
+ for (const signalKey of signalKeys) {
2671
+ const definition = signalDefinitions[signalKey];
2672
+ if (!definition) continue;
2673
+ signalDescriptions[signalKey] = definition.description;
2674
+ signalSentiments[signalKey] = definition.sentiment;
2675
+ }
2676
+ const customGuidance = ((_a = options.guidance) == null ? void 0 : _a.trim()) || "";
2677
+ const toolName = ((_b = options.toolName) == null ? void 0 : _b.trim()) || SELF_DIAGNOSTICS_TOOL_NAME_DEFAULT;
2678
+ const signalList = signalKeys.map((signalKey) => {
2679
+ const sentiment = signalSentiments[signalKey];
2680
+ const sentimentTag = sentiment ? ` [${sentiment.toLowerCase()}]` : "";
2681
+ return `- ${signalKey}: ${signalDescriptions[signalKey]}${sentimentTag}`;
2682
+ }).join("\n");
2683
+ const guidanceBlock = customGuidance ? `
2684
+ Additional guidance: ${customGuidance}
2685
+ ` : "";
2686
+ const toolDescription = `${SELF_DIAGNOSTICS_TOOL_PREAMBLE}
2687
+
2688
+ When to call:
2689
+ - You are blocked from completing the task due to missing information or access that the user cannot provide.
2690
+ - A tool is persistently failing across multiple attempts, not just a single transient error.
2691
+ - The task requires a tool, permission, or capability you do not have.
2692
+ - You genuinely cannot deliver what the user asked for despite trying.
2693
+
2694
+ When NOT to call:
2695
+ - Normal clarifying questions or back-and-forth with the user.
2696
+ - A single tool error that you can recover from or retry.
2697
+ - You successfully completed the task, even if it was difficult.
2698
+ - Policy refusals or content filtering \u2014 those are working as intended.
2699
+
2700
+ Rules:
2701
+ 1. Pick the single best category.
2702
+ 2. Do not fabricate issues. Only report what is evident from the conversation.
2703
+ 3. Err on the side of NOT calling this tool. When in doubt, help the user instead.
2704
+ ${guidanceBlock}
2705
+ Categories:
2706
+ ` + signalList;
2707
+ return {
2708
+ toolName,
2709
+ toolDescription,
2710
+ signalKeys,
2711
+ signalKeySet: new Set(signalKeys),
2712
+ signalDescriptions,
2713
+ signalSentiments
2714
+ };
2715
+ }
2716
+ function normalizeSelfDiagnosticsConfig(options) {
2717
+ if (!(options == null ? void 0 : options.enabled)) return void 0;
2718
+ return resolveSelfDiagnosticsConfig(options);
2719
+ }
2720
+ function asVercelSchema(inputSchema) {
2721
+ const validatorSymbol = /* @__PURE__ */ Symbol.for("vercel.ai.validator");
2722
+ const schemaSymbol = /* @__PURE__ */ Symbol.for("vercel.ai.schema");
2723
+ return {
2724
+ [schemaSymbol]: true,
2725
+ [validatorSymbol]: true,
2726
+ _type: void 0,
2727
+ jsonSchema: inputSchema,
2728
+ validate: (value) => ({ success: true, value })
2729
+ };
2730
+ }
2731
+ function resolveStandaloneEventId(options) {
2732
+ var _a, _b, _c, _d, _e, _f;
2733
+ return (_f = (_d = (_b = normalizeString((_a = options.getEventId) == null ? void 0 : _a.call(options))) != null ? _b : normalizeString(options.eventId)) != null ? _d : normalizeString((_c = getContextManager().getParentSpanIds()) == null ? void 0 : _c.eventId)) != null ? _f : normalizeString((_e = getCurrentRaindropCallMetadata()) == null ? void 0 : _e.eventId);
2734
+ }
2735
+ function createSelfDiagnosticsToolDefinition(args) {
2736
+ const { config, eventShipper, getEventId, aiSDKVersion, debug } = args;
2737
+ const inputJsonSchema = {
2738
+ type: "object",
2739
+ additionalProperties: false,
2740
+ properties: {
2741
+ category: {
2742
+ type: "string",
2743
+ enum: config.signalKeys,
2744
+ description: "The single best-matching category from the list above."
2745
+ },
2746
+ detail: {
2747
+ type: "string",
2748
+ description: "One sentence of factual context: what happened and why it matters. Do not include PII or secrets."
2749
+ }
2750
+ },
2751
+ required: ["category", "detail"]
2752
+ };
2753
+ const inputSchema = asVercelSchema(inputJsonSchema);
2754
+ const execute = async (rawInput) => {
2755
+ var _a, _b;
2756
+ const fallbackCategory = (_a = config.signalKeys[0]) != null ? _a : "unknown";
2757
+ const categoryCandidate = normalizeString(rawInput == null ? void 0 : rawInput.category);
2758
+ const category = categoryCandidate && config.signalKeySet.has(categoryCandidate) ? categoryCandidate : fallbackCategory;
2759
+ const detail = normalizeString(rawInput == null ? void 0 : rawInput.detail);
2760
+ const eventId = getEventId();
2761
+ if (!eventId) {
2762
+ const message = "self diagnostics signal skipped: missing eventId. Pass eventId or getEventId when creating the tool.";
2763
+ if (args.onMissingEventId === "throw") {
2764
+ throw new Error(`[raindrop-ai/ai-sdk] ${message}`);
2765
+ }
2766
+ if (((_b = args.onMissingEventId) != null ? _b : "warn") === "warn") {
2767
+ console.warn(`[raindrop-ai/ai-sdk] ${message}`);
2768
+ }
2769
+ return { acknowledged: false, category, reason: "missing_event_id" };
2770
+ }
2771
+ void eventShipper.trackSignal({
2772
+ eventId,
2773
+ name: `self diagnostics - ${category}`,
2774
+ type: "agent",
2775
+ sentiment: config.signalSentiments[category],
2776
+ properties: {
2777
+ source: "agent_reporting_tool",
2778
+ category,
2779
+ signal_description: config.signalDescriptions[category],
2780
+ ...aiSDKVersion ? { ai_sdk_version: aiSDKVersion } : {},
2781
+ ...detail ? { detail } : {}
2782
+ }
2783
+ }).catch((error) => {
2784
+ if (debug) {
2785
+ const message = error instanceof Error ? error.message : String(error);
2786
+ console.warn(`[raindrop-ai/ai-sdk] selfDiagnostics signal dispatch failed: ${message}`);
2787
+ }
2788
+ });
2789
+ return { acknowledged: true, category };
2790
+ };
2791
+ return {
2792
+ name: config.toolName,
2793
+ description: config.toolDescription,
2794
+ parameters: inputSchema,
2795
+ inputSchema,
2796
+ execute
2797
+ };
2798
+ }
2799
+ function createStandaloneSelfDiagnosticsTool(args) {
2800
+ const config = resolveSelfDiagnosticsConfig(args.options);
2801
+ return createSelfDiagnosticsToolDefinition({
2802
+ config,
2803
+ eventShipper: args.eventShipper,
2804
+ getEventId: () => resolveStandaloneEventId(args.options),
2805
+ onMissingEventId: args.options.onMissingEventId,
2806
+ debug: args.debug
2807
+ });
2808
+ }
2809
+
2810
+ // src/internal/traces.ts
2811
+ var TraceShipper2 = class extends TraceShipper {
2812
+ constructor(opts) {
2813
+ var _a, _b, _c;
2814
+ super({
2815
+ ...opts,
2816
+ sdkName: (_a = opts.sdkName) != null ? _a : "ai-sdk",
2817
+ serviceName: (_b = opts.serviceName) != null ? _b : "raindrop.ai-sdk",
2818
+ serviceVersion: (_c = opts.serviceVersion) != null ? _c : libraryVersion
2819
+ });
2820
+ }
2821
+ };
2822
+
2823
+ // src/internal/wrap/wrapAISDK.ts
2504
2824
  var pendingStoresByShipper = /* @__PURE__ */ new WeakMap();
2505
2825
  var PendingToolSpanStore = class _PendingToolSpanStore {
2506
2826
  constructor() {
@@ -2604,85 +2924,6 @@ function mergeContexts(wrapTime, callTime) {
2604
2924
  }
2605
2925
  return result;
2606
2926
  }
2607
- function normalizeSelfDiagnosticsSignals(signals) {
2608
- if (!signals) return AGENT_REPORTING_SIGNALS_DEFAULT;
2609
- const normalizedEntries = Object.entries(signals).map(([key, value]) => {
2610
- var _a;
2611
- const signalKey = key.trim();
2612
- if (!signalKey || !value || typeof value !== "object") return void 0;
2613
- const description = (_a = value.description) == null ? void 0 : _a.trim();
2614
- if (!description) return void 0;
2615
- const sentiment = value.sentiment;
2616
- return [
2617
- signalKey,
2618
- {
2619
- description,
2620
- ...sentiment === "POSITIVE" || sentiment === "NEGATIVE" ? { sentiment } : {}
2621
- }
2622
- ];
2623
- }).filter(
2624
- (entry) => entry !== void 0
2625
- );
2626
- if (normalizedEntries.length === 0) return AGENT_REPORTING_SIGNALS_DEFAULT;
2627
- return Object.fromEntries(normalizedEntries);
2628
- }
2629
- function normalizeSelfDiagnosticsConfig(options) {
2630
- var _a, _b;
2631
- if (!(options == null ? void 0 : options.enabled)) return void 0;
2632
- const signalDefinitions = normalizeSelfDiagnosticsSignals(options.signals);
2633
- const signalKeys = Object.keys(signalDefinitions);
2634
- const signalDescriptions = {};
2635
- const signalSentiments = {};
2636
- for (const signalKey of signalKeys) {
2637
- const def = signalDefinitions[signalKey];
2638
- if (!def) continue;
2639
- signalDescriptions[signalKey] = def.description;
2640
- signalSentiments[signalKey] = def.sentiment;
2641
- }
2642
- const customGuidanceText = ((_a = options.guidance) == null ? void 0 : _a.trim()) || "";
2643
- const toolName = ((_b = options.toolName) == null ? void 0 : _b.trim()) || AGENT_REPORTING_TOOL_NAME_DEFAULT;
2644
- const signalList = signalKeys.map((signalKey) => {
2645
- const sentiment = signalSentiments[signalKey];
2646
- const sentimentTag = sentiment ? ` [${sentiment.toLowerCase()}]` : "";
2647
- return `- ${signalKey}: ${signalDescriptions[signalKey]}${sentimentTag}`;
2648
- }).join("\n");
2649
- const guidanceBlock = customGuidanceText ? `
2650
- Additional guidance: ${customGuidanceText}
2651
- ` : "";
2652
- const toolDescription = `${AGENT_REPORTING_TOOL_PREAMBLE}
2653
-
2654
- When to call:
2655
- - You are blocked from completing the task due to missing information or access that the user cannot provide.
2656
- - A tool is persistently failing across multiple attempts, not just a single transient error.
2657
- - The task requires a tool, permission, or capability you do not have.
2658
- - You genuinely cannot deliver what the user asked for despite trying.
2659
-
2660
- When NOT to call:
2661
- - Normal clarifying questions or back-and-forth with the user.
2662
- - A single tool error that you can recover from or retry.
2663
- - You successfully completed the task, even if it was difficult.
2664
- - Policy refusals or content filtering \u2014 those are working as intended.
2665
-
2666
- Rules:
2667
- 1. Pick the single best category.
2668
- 2. Do not fabricate issues. Only report what is evident from the conversation.
2669
- 3. Err on the side of NOT calling this tool. When in doubt, help the user instead.
2670
- ${guidanceBlock}
2671
- Categories:
2672
- ${signalList}`;
2673
- return {
2674
- toolName,
2675
- toolDescription,
2676
- signalKeys,
2677
- signalKeySet: new Set(signalKeys),
2678
- signalDescriptions,
2679
- signalSentiments
2680
- };
2681
- }
2682
- function resolveJsonSchemaFactory(aiSDK) {
2683
- if (!isRecord(aiSDK) || !isFunction(aiSDK["jsonSchema"])) return void 0;
2684
- return aiSDK["jsonSchema"];
2685
- }
2686
2927
  function detectAISDKVersion(aiSDK) {
2687
2928
  if (!isRecord(aiSDK)) return "unknown";
2688
2929
  if (isFunction(aiSDK["jsonSchema"])) return "6";
@@ -2701,80 +2942,16 @@ function resolveRegisterTelemetry(aiSDK) {
2701
2942
  const fn = (_a = aiSDK["registerTelemetry"]) != null ? _a : aiSDK["registerTelemetryIntegration"];
2702
2943
  return isFunction(fn) ? fn : void 0;
2703
2944
  }
2704
- function asVercelSchema(jsonSchemaObj) {
2705
- const validatorSymbol = /* @__PURE__ */ Symbol.for("vercel.ai.validator");
2706
- const schemaSymbol = /* @__PURE__ */ Symbol.for("vercel.ai.schema");
2707
- return {
2708
- [schemaSymbol]: true,
2709
- [validatorSymbol]: true,
2710
- _type: void 0,
2711
- jsonSchema: jsonSchemaObj,
2712
- validate: (value) => ({ success: true, value })
2713
- };
2714
- }
2715
2945
  function createSelfDiagnosticsTool(ctx) {
2716
2946
  const config = ctx.selfDiagnostics;
2717
2947
  if (!config) return void 0;
2718
- const schema = {
2719
- type: "object",
2720
- additionalProperties: false,
2721
- properties: {
2722
- category: {
2723
- type: "string",
2724
- enum: config.signalKeys,
2725
- description: "The single best-matching category from the list above."
2726
- },
2727
- detail: {
2728
- type: "string",
2729
- description: "One sentence of factual context: what happened and why it matters. Do not include PII or secrets."
2730
- }
2731
- },
2732
- required: ["category", "detail"]
2733
- };
2734
- const parameters = asVercelSchema(schema);
2735
- let inputSchema = parameters;
2736
- if (ctx.jsonSchemaFactory) {
2737
- try {
2738
- inputSchema = ctx.jsonSchemaFactory(schema);
2739
- } catch (e) {
2740
- inputSchema = parameters;
2741
- }
2742
- }
2743
- const execute = async (rawInput) => {
2744
- var _a;
2745
- const input = isRecord(rawInput) ? rawInput : void 0;
2746
- const fallbackCategory = (_a = config.signalKeys[0]) != null ? _a : "unknown";
2747
- const categoryCandidate = typeof (input == null ? void 0 : input["category"]) === "string" ? input["category"].trim() : void 0;
2748
- const category = categoryCandidate && config.signalKeySet.has(categoryCandidate) ? categoryCandidate : fallbackCategory;
2749
- const detail = typeof (input == null ? void 0 : input["detail"]) === "string" ? input["detail"].trim() : "";
2750
- const signalDescription = config.signalDescriptions[category];
2751
- const signalSentiment = config.signalSentiments[category];
2752
- void ctx.eventShipper.trackSignal({
2753
- eventId: ctx.eventId,
2754
- name: `self diagnostics - ${category}`,
2755
- type: "agent",
2756
- sentiment: signalSentiment,
2757
- properties: {
2758
- source: "agent_reporting_tool",
2759
- category,
2760
- signal_description: signalDescription,
2761
- ai_sdk_version: ctx.aiSDKVersion,
2762
- ...detail ? { detail } : {}
2763
- }
2764
- }).catch((err) => {
2765
- if (ctx.debug) {
2766
- const msg = err instanceof Error ? err.message : String(err);
2767
- console.warn(`[raindrop-ai/ai-sdk] selfDiagnostics signal dispatch failed: ${msg}`);
2768
- }
2769
- });
2770
- return { acknowledged: true, category };
2771
- };
2772
- return {
2773
- description: config.toolDescription,
2774
- execute,
2775
- parameters,
2776
- inputSchema
2777
- };
2948
+ return createSelfDiagnosticsToolDefinition({
2949
+ config,
2950
+ eventShipper: ctx.eventShipper,
2951
+ getEventId: () => ctx.eventId,
2952
+ aiSDKVersion: ctx.aiSDKVersion,
2953
+ debug: ctx.debug
2954
+ });
2778
2955
  }
2779
2956
  function getCurrentParentSpanContextSync() {
2780
2957
  return getContextManager().getParentSpanIds();
@@ -3001,7 +3178,6 @@ function setupOperation(params) {
3001
3178
  eventShipper,
3002
3179
  traceShipper,
3003
3180
  rootParentForChildren,
3004
- jsonSchemaFactory: resolveJsonSchemaFactory(aiSDK),
3005
3181
  selfDiagnostics: operationSelfDiagnostics,
3006
3182
  aiSDKVersion: detectAISDKVersion(aiSDK)
3007
3183
  };
@@ -3350,7 +3526,6 @@ function wrapAISDK(aiSDK, deps) {
3350
3526
  );
3351
3527
  }
3352
3528
  const selfDiagnostics2 = normalizeSelfDiagnosticsConfig(deps.options.selfDiagnostics);
3353
- const jsonSchemaFactory = selfDiagnostics2 ? resolveJsonSchemaFactory(aiSDK) : void 0;
3354
3529
  const metadataAwareOps = /* @__PURE__ */ new Set([
3355
3530
  "generateText",
3356
3531
  "streamText",
@@ -3382,14 +3557,9 @@ function wrapAISDK(aiSDK, deps) {
3382
3557
  const perCallEventIdGenerated = !perCallEventIdExplicit;
3383
3558
  const perCallCtx = {
3384
3559
  eventId: perCallEventId,
3385
- context: wrapTimeCtx,
3386
- telemetry,
3387
- sendTraces: false,
3388
3560
  debug,
3389
3561
  eventShipper: deps.eventShipper,
3390
3562
  traceShipper: deps.traceShipper,
3391
- rootParentForChildren: void 0,
3392
- jsonSchemaFactory,
3393
3563
  selfDiagnostics: selfDiagnostics2,
3394
3564
  aiSDKVersion: "7"
3395
3565
  };
@@ -3591,7 +3761,6 @@ function wrapAgentGenerate(generate, instance, agentSettings, className, aiSDK,
3591
3761
  eventShipper: deps.eventShipper,
3592
3762
  traceShipper: deps.traceShipper,
3593
3763
  rootParentForChildren,
3594
- jsonSchemaFactory: resolveJsonSchemaFactory(aiSDK),
3595
3764
  selfDiagnostics,
3596
3765
  aiSDKVersion: detectAISDKVersion(aiSDK)
3597
3766
  };
@@ -3799,7 +3968,6 @@ function wrapAgentStream(stream, instance, agentSettings, className, aiSDK, deps
3799
3968
  eventShipper: deps.eventShipper,
3800
3969
  traceShipper: deps.traceShipper,
3801
3970
  rootParentForChildren,
3802
- jsonSchemaFactory: resolveJsonSchemaFactory(aiSDK),
3803
3971
  selfDiagnostics,
3804
3972
  aiSDKVersion: detectAISDKVersion(aiSDK)
3805
3973
  };
@@ -4615,6 +4783,14 @@ function createRaindropAISDK(opts) {
4615
4783
  traceShipper
4616
4784
  });
4617
4785
  },
4786
+ createSelfDiagnosticsTool(options = {}) {
4787
+ var _a2;
4788
+ return createStandaloneSelfDiagnosticsTool({
4789
+ options,
4790
+ eventShipper,
4791
+ debug: ((_a2 = opts.events) == null ? void 0 : _a2.debug) === true || envDebug
4792
+ });
4793
+ },
4618
4794
  createTelemetryIntegration(contextOrOptions) {
4619
4795
  const FLAT_CONTEXT_KEYS = [
4620
4796
  "userId",
@@ -4745,6 +4921,13 @@ function createRaindropAISDK(opts) {
4745
4921
  }
4746
4922
  };
4747
4923
  }
4924
+ function raindrop(options = {}) {
4925
+ var _a;
4926
+ const { context, subagentWrapping, writeKey, ...rest } = options;
4927
+ const resolvedWriteKey = writeKey != null ? writeKey : typeof process !== "undefined" ? (_a = process.env) == null ? void 0 : _a.RAINDROP_WRITE_KEY : void 0;
4928
+ const client = createRaindropAISDK({ ...rest, writeKey: resolvedWriteKey });
4929
+ return client.createTelemetryIntegration({ context, subagentWrapping });
4930
+ }
4748
4931
 
4749
4932
  exports.DEFAULT_REDACT_ATTRIBUTE_KEYS = DEFAULT_REDACT_ATTRIBUTE_KEYS;
4750
4933
  exports.DEFAULT_SECRET_KEY_NAMES = DEFAULT_SECRET_KEY_NAMES;
@@ -4763,6 +4946,7 @@ exports.eventMetadataFromChatRequest = eventMetadataFromChatRequest;
4763
4946
  exports.getContextManager = getContextManager;
4764
4947
  exports.getCurrentParentToolContext = getCurrentParentToolContext;
4765
4948
  exports.getCurrentRaindropCallMetadata = getCurrentRaindropCallMetadata;
4949
+ exports.raindrop = raindrop;
4766
4950
  exports.readRaindropCallMetadataFromArgs = readRaindropCallMetadataFromArgs;
4767
4951
  exports.redactJsonAttributeValue = redactJsonAttributeValue;
4768
4952
  exports.redactSecretsInObject = redactSecretsInObject;