@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.
@@ -1781,6 +1781,25 @@ var RaindropTelemetryIntegration = class {
1781
1781
  * (the `event.callId` can be the same for parallel sibling tools).
1782
1782
  */
1783
1783
  this.priorParentContexts = /* @__PURE__ */ new Map();
1784
+ // ── lifecycle ─────────────────────────────────────────────────────────────
1785
+ //
1786
+ // The shippers buffer spans/events and flush on a timer, so a short-lived
1787
+ // script (e.g. a single `generateText` then `process.exit`) can exit before
1788
+ // anything ships. Expose `flush`/`shutdown` on the integration itself so the
1789
+ // value returned by `raindrop()` is self-sufficient — callers can keep the
1790
+ // reference they pass to `registerTelemetry` and `await rd.flush()` before
1791
+ // exiting, without also constructing a separate client.
1792
+ /** Flush any buffered events and trace spans to their destinations. */
1793
+ this.flush = async () => {
1794
+ await Promise.all([this.eventShipper.flush(), this.traceShipper.flush()]);
1795
+ };
1796
+ /** Flush and stop the background flush timers. */
1797
+ this.shutdown = async () => {
1798
+ await Promise.all([
1799
+ this.eventShipper.shutdown(),
1800
+ this.traceShipper.shutdown()
1801
+ ]);
1802
+ };
1784
1803
  // ── onStart ─────────────────────────────────────────────────────────────
1785
1804
  this.onStart = (event) => {
1786
1805
  var _a, _b, _c, _d, _e;
@@ -2065,6 +2084,7 @@ var RaindropTelemetryIntegration = class {
2065
2084
  attrInt("gen_ai.usage.output_tokens", usage.outputTokens)
2066
2085
  );
2067
2086
  }
2087
+ this.emitProviderExecutedToolSpans(event, state);
2068
2088
  this.traceShipper.endSpan(state.stepSpan, { attributes: outputAttrs });
2069
2089
  state.stepSpan = void 0;
2070
2090
  state.stepParent = void 0;
@@ -2173,8 +2193,56 @@ var RaindropTelemetryIntegration = class {
2173
2193
  if (state.subagentToolCallSpan) {
2174
2194
  this.traceShipper.endSpan(state.subagentToolCallSpan, { error: actualError });
2175
2195
  }
2196
+ const isEmbed = state.operationId === "ai.embed" || state.operationId === "ai.embedMany";
2197
+ if (!isEmbed) {
2198
+ this.finalizeGenerateEvent(state, state.accumulatedText || void 0, void 0);
2199
+ }
2176
2200
  this.cleanup(event.callId);
2177
2201
  };
2202
+ // ── onAbort ─────────────────────────────────────────────────────────────
2203
+ //
2204
+ // Dispatched by the v7 canary line (post-beta.116) when a `streamText` call
2205
+ // is cancelled via its `AbortSignal`. On abort the SDK fires neither `onEnd`
2206
+ // nor `onError`, so without this every open span would leak and the event
2207
+ // would hang forever in its `isPending` state. We close every open span with
2208
+ // an `ai.response.aborted` marker (no error status — an abort is not a model
2209
+ // failure) and flush the partial event.
2210
+ this.onAbort = (event) => {
2211
+ const callId = event == null ? void 0 : event.callId;
2212
+ if (!callId) return;
2213
+ const state = this.getState(callId);
2214
+ if (!state) return;
2215
+ const abortedAttr = attrString("ai.response.aborted", "true");
2216
+ if (state.stepSpan) {
2217
+ this.traceShipper.endSpan(state.stepSpan, { attributes: [abortedAttr] });
2218
+ state.stepSpan = void 0;
2219
+ state.stepParent = void 0;
2220
+ }
2221
+ for (const embedSpan of state.embedSpans.values()) {
2222
+ this.traceShipper.endSpan(embedSpan, { attributes: [abortedAttr] });
2223
+ }
2224
+ state.embedSpans.clear();
2225
+ for (const toolCallId of state.parentContextToolCallIds) {
2226
+ this.priorParentContexts.delete(toolCallId);
2227
+ }
2228
+ state.parentContextToolCallIds.clear();
2229
+ for (const toolSpan of state.toolSpans.values()) {
2230
+ this.traceShipper.endSpan(toolSpan, { attributes: [abortedAttr] });
2231
+ }
2232
+ state.toolSpans.clear();
2233
+ if (state.rootSpan) {
2234
+ this.traceShipper.endSpan(state.rootSpan, {
2235
+ attributes: [abortedAttr, attrInt("ai.toolCall.count", state.toolCallCount)]
2236
+ });
2237
+ }
2238
+ if (state.subagentToolCallSpan) {
2239
+ this.traceShipper.endSpan(state.subagentToolCallSpan, {
2240
+ attributes: [abortedAttr]
2241
+ });
2242
+ }
2243
+ this.finalizeGenerateEvent(state, state.accumulatedText || void 0, void 0);
2244
+ this.cleanup(callId);
2245
+ };
2178
2246
  // ── executeTool ─────────────────────────────────────────────────────────
2179
2247
  this.executeTool = async ({
2180
2248
  callId,
@@ -2332,17 +2400,86 @@ var RaindropTelemetryIntegration = class {
2332
2400
  const toolSpan = state.toolSpans.get(event.toolCall.toolCallId);
2333
2401
  if (!toolSpan) return;
2334
2402
  state.toolCallCount += 1;
2335
- if (event.success) {
2336
- const outputAttrs = state.recordOutputs ? [attrString("ai.toolCall.result", safeJsonWithUint8(event.output))] : [];
2403
+ 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 };
2404
+ if (outcome.success) {
2405
+ const outputAttrs = state.recordOutputs ? [attrString("ai.toolCall.result", safeJsonWithUint8(outcome.output))] : [];
2337
2406
  this.traceShipper.endSpan(toolSpan, { attributes: outputAttrs });
2338
2407
  } else {
2339
- this.traceShipper.endSpan(toolSpan, { error: event.error });
2408
+ this.traceShipper.endSpan(toolSpan, { error: outcome.error });
2340
2409
  }
2341
2410
  this.emitLive(state, "tool_result", event.toolCall.toolName);
2342
2411
  state.toolSpans.delete(event.toolCall.toolCallId);
2343
2412
  }
2413
+ // ── provider-executed tool calls ─────────────────────────────────────────
2414
+ //
2415
+ // Provider-executed (server-side) tools — e.g. Anthropic's hosted
2416
+ // `web_search` (`anthropic.web_search_20250305`) — are run by the provider,
2417
+ // not by the AI SDK. They therefore never flow through the client
2418
+ // `onToolExecutionStart`/`onToolExecutionEnd` callbacks that emit our
2419
+ // `ai.toolCall` spans; the SDK only surfaces them as `tool-call` /
2420
+ // `tool-result` content parts on the step (carrying `providerExecuted: true`).
2421
+ // Without this, such calls are invisible in every trace backend.
2422
+ //
2423
+ // At step finish we synthesize the same `ai.toolCall` span shape we emit for
2424
+ // client tools (name `ai.toolCall`, `operationId: "ai.toolCall"`, attrs
2425
+ // `ai.toolCall.name`/`id`/`args`/`result`), parented under the step span, so
2426
+ // downstream ingestion maps them to a tool span with no special-casing.
2427
+ //
2428
+ // Client-executed tools are excluded (`providerExecuted` falsy) — they were
2429
+ // already spanned during execution, so this never double-emits.
2430
+ emitProviderExecutedToolSpans(event, state) {
2431
+ if (!state.stepParent) return;
2432
+ const content = Array.isArray(event.content) ? event.content : [];
2433
+ const providerToolCalls = content.filter(
2434
+ (part) => (part == null ? void 0 : part.type) === "tool-call" && part.providerExecuted === true
2435
+ );
2436
+ if (providerToolCalls.length === 0) return;
2437
+ const resultsByCallId = /* @__PURE__ */ new Map();
2438
+ for (const part of content) {
2439
+ if (((part == null ? void 0 : part.type) === "tool-result" || (part == null ? void 0 : part.type) === "tool-error") && typeof part.toolCallId === "string") {
2440
+ resultsByCallId.set(part.toolCallId, part);
2441
+ }
2442
+ }
2443
+ for (const call of providerToolCalls) {
2444
+ const { operationName, resourceName } = opName(
2445
+ "ai.toolCall",
2446
+ state.functionId
2447
+ );
2448
+ const inputAttrs = state.recordInputs ? [attrString("ai.toolCall.args", safeJsonWithUint8(call.input))] : [];
2449
+ const toolSpan = this.traceShipper.startSpan({
2450
+ name: "ai.toolCall",
2451
+ parent: state.stepParent,
2452
+ eventId: state.eventId,
2453
+ operationId: "ai.toolCall",
2454
+ attributes: [
2455
+ attrString("operation.name", operationName),
2456
+ attrString("resource.name", resourceName),
2457
+ attrString("ai.telemetry.functionId", state.functionId),
2458
+ attrString("ai.toolCall.name", call.toolName),
2459
+ attrString("ai.toolCall.id", call.toolCallId),
2460
+ attrString("ai.toolCall.providerExecuted", "true"),
2461
+ ...inputAttrs
2462
+ ]
2463
+ });
2464
+ state.toolCallCount += 1;
2465
+ this.emitLive(state, "tool_start", call.toolName, { args: call.input });
2466
+ const resultPart = resultsByCallId.get(call.toolCallId);
2467
+ if ((resultPart == null ? void 0 : resultPart.type) === "tool-error") {
2468
+ this.traceShipper.endSpan(toolSpan, { error: resultPart.error });
2469
+ } else {
2470
+ const outputAttrs = state.recordOutputs && resultPart && "output" in resultPart ? [
2471
+ attrString(
2472
+ "ai.toolCall.result",
2473
+ safeJsonWithUint8(resultPart.output)
2474
+ )
2475
+ ] : [];
2476
+ this.traceShipper.endSpan(toolSpan, { attributes: outputAttrs });
2477
+ }
2478
+ this.emitLive(state, "tool_result", call.toolName);
2479
+ }
2480
+ }
2344
2481
  finishGenerate(event, state) {
2345
- var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n;
2482
+ var _a, _b, _c, _d, _e, _f;
2346
2483
  if (state.rootSpan) {
2347
2484
  const outputAttrs = [];
2348
2485
  if (state.recordOutputs) {
@@ -2390,38 +2527,47 @@ var RaindropTelemetryIntegration = class {
2390
2527
  );
2391
2528
  this.traceShipper.endSpan(state.rootSpan, { attributes: outputAttrs });
2392
2529
  }
2530
+ this.finalizeGenerateEvent(
2531
+ state,
2532
+ (_e = event.text) != null ? _e : state.accumulatedText || void 0,
2533
+ (_f = event.response) == null ? void 0 : _f.modelId
2534
+ );
2535
+ }
2536
+ /**
2537
+ * Patch the Raindrop event for a completed, aborted, or errored text
2538
+ * generation so it leaves the `isPending` state. Shared by `onFinish`/`onEnd`,
2539
+ * `onAbort`, and `onError`.
2540
+ */
2541
+ finalizeGenerateEvent(state, output, model) {
2542
+ var _a, _b, _c, _d, _e, _f, _g, _h;
2393
2543
  const suppressSubagentEvent = state.subagentName !== void 0 && state.subagentToolCallSpan !== void 0;
2394
- if (this.sendEvents && !suppressSubagentEvent) {
2395
- const callMeta = this.extractRaindropMetadata(state.metadata);
2396
- const userId = (_f = callMeta.userId) != null ? _f : (_e = this.defaultContext) == null ? void 0 : _e.userId;
2397
- if (userId) {
2398
- const eventName = (_i = (_h = callMeta.eventName) != null ? _h : (_g = this.defaultContext) == null ? void 0 : _g.eventName) != null ? _i : state.operationId;
2399
- const output = (_j = event.text) != null ? _j : state.accumulatedText || void 0;
2400
- const input = state.inputText;
2401
- const model = (_k = event.response) == null ? void 0 : _k.modelId;
2402
- const properties = {
2403
- ...(_l = this.defaultContext) == null ? void 0 : _l.properties,
2404
- ...callMeta.properties
2405
- };
2406
- const convoId = (_n = callMeta.convoId) != null ? _n : (_m = this.defaultContext) == null ? void 0 : _m.convoId;
2407
- void this.eventShipper.patch(state.eventId, {
2408
- eventName,
2409
- userId,
2410
- convoId,
2411
- input,
2412
- output,
2413
- model,
2414
- properties: Object.keys(properties).length > 0 ? properties : void 0,
2415
- isPending: false
2416
- }).catch((err) => {
2417
- if (this.debug) {
2418
- console.warn(
2419
- `[raindrop-ai/ai-sdk] event patch failed: ${err instanceof Error ? err.message : err}`
2420
- );
2421
- }
2422
- });
2544
+ if (!this.sendEvents || suppressSubagentEvent) return;
2545
+ const callMeta = this.extractRaindropMetadata(state.metadata);
2546
+ const userId = (_b = callMeta.userId) != null ? _b : (_a = this.defaultContext) == null ? void 0 : _a.userId;
2547
+ if (!userId) return;
2548
+ const eventName = (_e = (_d = callMeta.eventName) != null ? _d : (_c = this.defaultContext) == null ? void 0 : _c.eventName) != null ? _e : state.operationId;
2549
+ const input = state.inputText;
2550
+ const properties = {
2551
+ ...(_f = this.defaultContext) == null ? void 0 : _f.properties,
2552
+ ...callMeta.properties
2553
+ };
2554
+ const convoId = (_h = callMeta.convoId) != null ? _h : (_g = this.defaultContext) == null ? void 0 : _g.convoId;
2555
+ void this.eventShipper.patch(state.eventId, {
2556
+ eventName,
2557
+ userId,
2558
+ convoId,
2559
+ input,
2560
+ output,
2561
+ model,
2562
+ properties: Object.keys(properties).length > 0 ? properties : void 0,
2563
+ isPending: false
2564
+ }).catch((err) => {
2565
+ if (this.debug) {
2566
+ console.warn(
2567
+ `[raindrop-ai/ai-sdk] event patch failed: ${err instanceof Error ? err.message : err}`
2568
+ );
2423
2569
  }
2424
- }
2570
+ });
2425
2571
  }
2426
2572
  finishEmbed(event, state) {
2427
2573
  var _a;
@@ -2446,9 +2592,9 @@ var RaindropTelemetryIntegration = class {
2446
2592
  }
2447
2593
  };
2448
2594
 
2449
- // src/internal/wrap/wrapAISDK.ts
2450
- var AGENT_REPORTING_TOOL_NAME_DEFAULT = "__raindrop_report";
2451
- var AGENT_REPORTING_SIGNALS_DEFAULT = {
2595
+ // src/internal/self-diagnostics.ts
2596
+ var SELF_DIAGNOSTICS_TOOL_NAME_DEFAULT = "__raindrop_report";
2597
+ var SELF_DIAGNOSTICS_SIGNALS_DEFAULT = {
2452
2598
  missing_context: {
2453
2599
  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.",
2454
2600
  sentiment: "NEGATIVE"
@@ -2466,7 +2612,181 @@ var AGENT_REPORTING_SIGNALS_DEFAULT = {
2466
2612
  sentiment: "NEGATIVE"
2467
2613
  }
2468
2614
  };
2469
- 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.";
2615
+ 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.";
2616
+ function normalizeString(value) {
2617
+ if (typeof value !== "string") return void 0;
2618
+ const trimmed = value.trim();
2619
+ return trimmed || void 0;
2620
+ }
2621
+ function normalizeSelfDiagnosticsSignals(signals) {
2622
+ if (!signals) return SELF_DIAGNOSTICS_SIGNALS_DEFAULT;
2623
+ const normalizedEntries = Object.entries(signals).map(([key, value]) => {
2624
+ var _a;
2625
+ const signalKey = key.trim();
2626
+ if (!signalKey || !value || typeof value !== "object") return void 0;
2627
+ const description = (_a = value.description) == null ? void 0 : _a.trim();
2628
+ if (!description) return void 0;
2629
+ const sentiment = value.sentiment;
2630
+ return [
2631
+ signalKey,
2632
+ {
2633
+ description,
2634
+ ...sentiment === "POSITIVE" || sentiment === "NEGATIVE" ? { sentiment } : {}
2635
+ }
2636
+ ];
2637
+ }).filter(
2638
+ (entry) => entry !== void 0
2639
+ );
2640
+ if (normalizedEntries.length === 0) return SELF_DIAGNOSTICS_SIGNALS_DEFAULT;
2641
+ return Object.fromEntries(normalizedEntries);
2642
+ }
2643
+ function resolveSelfDiagnosticsConfig(options) {
2644
+ var _a, _b;
2645
+ const signalDefinitions = normalizeSelfDiagnosticsSignals(options.signals);
2646
+ const signalKeys = Object.keys(signalDefinitions);
2647
+ const signalDescriptions = {};
2648
+ const signalSentiments = {};
2649
+ for (const signalKey of signalKeys) {
2650
+ const definition = signalDefinitions[signalKey];
2651
+ if (!definition) continue;
2652
+ signalDescriptions[signalKey] = definition.description;
2653
+ signalSentiments[signalKey] = definition.sentiment;
2654
+ }
2655
+ const customGuidance = ((_a = options.guidance) == null ? void 0 : _a.trim()) || "";
2656
+ const toolName = ((_b = options.toolName) == null ? void 0 : _b.trim()) || SELF_DIAGNOSTICS_TOOL_NAME_DEFAULT;
2657
+ const signalList = signalKeys.map((signalKey) => {
2658
+ const sentiment = signalSentiments[signalKey];
2659
+ const sentimentTag = sentiment ? ` [${sentiment.toLowerCase()}]` : "";
2660
+ return `- ${signalKey}: ${signalDescriptions[signalKey]}${sentimentTag}`;
2661
+ }).join("\n");
2662
+ const guidanceBlock = customGuidance ? `
2663
+ Additional guidance: ${customGuidance}
2664
+ ` : "";
2665
+ const toolDescription = `${SELF_DIAGNOSTICS_TOOL_PREAMBLE}
2666
+
2667
+ When to call:
2668
+ - You are blocked from completing the task due to missing information or access that the user cannot provide.
2669
+ - A tool is persistently failing across multiple attempts, not just a single transient error.
2670
+ - The task requires a tool, permission, or capability you do not have.
2671
+ - You genuinely cannot deliver what the user asked for despite trying.
2672
+
2673
+ When NOT to call:
2674
+ - Normal clarifying questions or back-and-forth with the user.
2675
+ - A single tool error that you can recover from or retry.
2676
+ - You successfully completed the task, even if it was difficult.
2677
+ - Policy refusals or content filtering \u2014 those are working as intended.
2678
+
2679
+ Rules:
2680
+ 1. Pick the single best category.
2681
+ 2. Do not fabricate issues. Only report what is evident from the conversation.
2682
+ 3. Err on the side of NOT calling this tool. When in doubt, help the user instead.
2683
+ ${guidanceBlock}
2684
+ Categories:
2685
+ ` + signalList;
2686
+ return {
2687
+ toolName,
2688
+ toolDescription,
2689
+ signalKeys,
2690
+ signalKeySet: new Set(signalKeys),
2691
+ signalDescriptions,
2692
+ signalSentiments
2693
+ };
2694
+ }
2695
+ function normalizeSelfDiagnosticsConfig(options) {
2696
+ if (!(options == null ? void 0 : options.enabled)) return void 0;
2697
+ return resolveSelfDiagnosticsConfig(options);
2698
+ }
2699
+ function asVercelSchema(inputSchema) {
2700
+ const validatorSymbol = /* @__PURE__ */ Symbol.for("vercel.ai.validator");
2701
+ const schemaSymbol = /* @__PURE__ */ Symbol.for("vercel.ai.schema");
2702
+ return {
2703
+ [schemaSymbol]: true,
2704
+ [validatorSymbol]: true,
2705
+ _type: void 0,
2706
+ jsonSchema: inputSchema,
2707
+ validate: (value) => ({ success: true, value })
2708
+ };
2709
+ }
2710
+ function resolveStandaloneEventId(options) {
2711
+ var _a, _b, _c, _d, _e, _f;
2712
+ 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);
2713
+ }
2714
+ function createSelfDiagnosticsToolDefinition(args) {
2715
+ const { config, eventShipper, getEventId, aiSDKVersion, debug } = args;
2716
+ const inputJsonSchema = {
2717
+ type: "object",
2718
+ additionalProperties: false,
2719
+ properties: {
2720
+ category: {
2721
+ type: "string",
2722
+ enum: config.signalKeys,
2723
+ description: "The single best-matching category from the list above."
2724
+ },
2725
+ detail: {
2726
+ type: "string",
2727
+ description: "One sentence of factual context: what happened and why it matters. Do not include PII or secrets."
2728
+ }
2729
+ },
2730
+ required: ["category", "detail"]
2731
+ };
2732
+ const inputSchema = asVercelSchema(inputJsonSchema);
2733
+ const execute = async (rawInput) => {
2734
+ var _a, _b;
2735
+ const fallbackCategory = (_a = config.signalKeys[0]) != null ? _a : "unknown";
2736
+ const categoryCandidate = normalizeString(rawInput == null ? void 0 : rawInput.category);
2737
+ const category = categoryCandidate && config.signalKeySet.has(categoryCandidate) ? categoryCandidate : fallbackCategory;
2738
+ const detail = normalizeString(rawInput == null ? void 0 : rawInput.detail);
2739
+ const eventId = getEventId();
2740
+ if (!eventId) {
2741
+ const message = "self diagnostics signal skipped: missing eventId. Pass eventId or getEventId when creating the tool.";
2742
+ if (args.onMissingEventId === "throw") {
2743
+ throw new Error(`[raindrop-ai/ai-sdk] ${message}`);
2744
+ }
2745
+ if (((_b = args.onMissingEventId) != null ? _b : "warn") === "warn") {
2746
+ console.warn(`[raindrop-ai/ai-sdk] ${message}`);
2747
+ }
2748
+ return { acknowledged: false, category, reason: "missing_event_id" };
2749
+ }
2750
+ void eventShipper.trackSignal({
2751
+ eventId,
2752
+ name: `self diagnostics - ${category}`,
2753
+ type: "agent",
2754
+ sentiment: config.signalSentiments[category],
2755
+ properties: {
2756
+ source: "agent_reporting_tool",
2757
+ category,
2758
+ signal_description: config.signalDescriptions[category],
2759
+ ...aiSDKVersion ? { ai_sdk_version: aiSDKVersion } : {},
2760
+ ...detail ? { detail } : {}
2761
+ }
2762
+ }).catch((error) => {
2763
+ if (debug) {
2764
+ const message = error instanceof Error ? error.message : String(error);
2765
+ console.warn(`[raindrop-ai/ai-sdk] selfDiagnostics signal dispatch failed: ${message}`);
2766
+ }
2767
+ });
2768
+ return { acknowledged: true, category };
2769
+ };
2770
+ return {
2771
+ name: config.toolName,
2772
+ description: config.toolDescription,
2773
+ parameters: inputSchema,
2774
+ inputSchema,
2775
+ execute
2776
+ };
2777
+ }
2778
+ function createStandaloneSelfDiagnosticsTool(args) {
2779
+ const config = resolveSelfDiagnosticsConfig(args.options);
2780
+ return createSelfDiagnosticsToolDefinition({
2781
+ config,
2782
+ eventShipper: args.eventShipper,
2783
+ getEventId: () => resolveStandaloneEventId(args.options),
2784
+ onMissingEventId: args.options.onMissingEventId,
2785
+ debug: args.debug
2786
+ });
2787
+ }
2788
+
2789
+ // src/internal/wrap/wrapAISDK.ts
2470
2790
  var pendingStoresByShipper = /* @__PURE__ */ new WeakMap();
2471
2791
  var PendingToolSpanStore = class _PendingToolSpanStore {
2472
2792
  constructor() {
@@ -2570,85 +2890,6 @@ function mergeContexts(wrapTime, callTime) {
2570
2890
  }
2571
2891
  return result;
2572
2892
  }
2573
- function normalizeSelfDiagnosticsSignals(signals) {
2574
- if (!signals) return AGENT_REPORTING_SIGNALS_DEFAULT;
2575
- const normalizedEntries = Object.entries(signals).map(([key, value]) => {
2576
- var _a;
2577
- const signalKey = key.trim();
2578
- if (!signalKey || !value || typeof value !== "object") return void 0;
2579
- const description = (_a = value.description) == null ? void 0 : _a.trim();
2580
- if (!description) return void 0;
2581
- const sentiment = value.sentiment;
2582
- return [
2583
- signalKey,
2584
- {
2585
- description,
2586
- ...sentiment === "POSITIVE" || sentiment === "NEGATIVE" ? { sentiment } : {}
2587
- }
2588
- ];
2589
- }).filter(
2590
- (entry) => entry !== void 0
2591
- );
2592
- if (normalizedEntries.length === 0) return AGENT_REPORTING_SIGNALS_DEFAULT;
2593
- return Object.fromEntries(normalizedEntries);
2594
- }
2595
- function normalizeSelfDiagnosticsConfig(options) {
2596
- var _a, _b;
2597
- if (!(options == null ? void 0 : options.enabled)) return void 0;
2598
- const signalDefinitions = normalizeSelfDiagnosticsSignals(options.signals);
2599
- const signalKeys = Object.keys(signalDefinitions);
2600
- const signalDescriptions = {};
2601
- const signalSentiments = {};
2602
- for (const signalKey of signalKeys) {
2603
- const def = signalDefinitions[signalKey];
2604
- if (!def) continue;
2605
- signalDescriptions[signalKey] = def.description;
2606
- signalSentiments[signalKey] = def.sentiment;
2607
- }
2608
- const customGuidanceText = ((_a = options.guidance) == null ? void 0 : _a.trim()) || "";
2609
- const toolName = ((_b = options.toolName) == null ? void 0 : _b.trim()) || AGENT_REPORTING_TOOL_NAME_DEFAULT;
2610
- const signalList = signalKeys.map((signalKey) => {
2611
- const sentiment = signalSentiments[signalKey];
2612
- const sentimentTag = sentiment ? ` [${sentiment.toLowerCase()}]` : "";
2613
- return `- ${signalKey}: ${signalDescriptions[signalKey]}${sentimentTag}`;
2614
- }).join("\n");
2615
- const guidanceBlock = customGuidanceText ? `
2616
- Additional guidance: ${customGuidanceText}
2617
- ` : "";
2618
- const toolDescription = `${AGENT_REPORTING_TOOL_PREAMBLE}
2619
-
2620
- When to call:
2621
- - You are blocked from completing the task due to missing information or access that the user cannot provide.
2622
- - A tool is persistently failing across multiple attempts, not just a single transient error.
2623
- - The task requires a tool, permission, or capability you do not have.
2624
- - You genuinely cannot deliver what the user asked for despite trying.
2625
-
2626
- When NOT to call:
2627
- - Normal clarifying questions or back-and-forth with the user.
2628
- - A single tool error that you can recover from or retry.
2629
- - You successfully completed the task, even if it was difficult.
2630
- - Policy refusals or content filtering \u2014 those are working as intended.
2631
-
2632
- Rules:
2633
- 1. Pick the single best category.
2634
- 2. Do not fabricate issues. Only report what is evident from the conversation.
2635
- 3. Err on the side of NOT calling this tool. When in doubt, help the user instead.
2636
- ${guidanceBlock}
2637
- Categories:
2638
- ${signalList}`;
2639
- return {
2640
- toolName,
2641
- toolDescription,
2642
- signalKeys,
2643
- signalKeySet: new Set(signalKeys),
2644
- signalDescriptions,
2645
- signalSentiments
2646
- };
2647
- }
2648
- function resolveJsonSchemaFactory(aiSDK) {
2649
- if (!isRecord(aiSDK) || !isFunction(aiSDK["jsonSchema"])) return void 0;
2650
- return aiSDK["jsonSchema"];
2651
- }
2652
2893
  function detectAISDKVersion(aiSDK) {
2653
2894
  if (!isRecord(aiSDK)) return "unknown";
2654
2895
  if (isFunction(aiSDK["jsonSchema"])) return "6";
@@ -2667,80 +2908,16 @@ function resolveRegisterTelemetry(aiSDK) {
2667
2908
  const fn = (_a = aiSDK["registerTelemetry"]) != null ? _a : aiSDK["registerTelemetryIntegration"];
2668
2909
  return isFunction(fn) ? fn : void 0;
2669
2910
  }
2670
- function asVercelSchema(jsonSchemaObj) {
2671
- const validatorSymbol = /* @__PURE__ */ Symbol.for("vercel.ai.validator");
2672
- const schemaSymbol = /* @__PURE__ */ Symbol.for("vercel.ai.schema");
2673
- return {
2674
- [schemaSymbol]: true,
2675
- [validatorSymbol]: true,
2676
- _type: void 0,
2677
- jsonSchema: jsonSchemaObj,
2678
- validate: (value) => ({ success: true, value })
2679
- };
2680
- }
2681
2911
  function createSelfDiagnosticsTool(ctx) {
2682
2912
  const config = ctx.selfDiagnostics;
2683
2913
  if (!config) return void 0;
2684
- const schema = {
2685
- type: "object",
2686
- additionalProperties: false,
2687
- properties: {
2688
- category: {
2689
- type: "string",
2690
- enum: config.signalKeys,
2691
- description: "The single best-matching category from the list above."
2692
- },
2693
- detail: {
2694
- type: "string",
2695
- description: "One sentence of factual context: what happened and why it matters. Do not include PII or secrets."
2696
- }
2697
- },
2698
- required: ["category", "detail"]
2699
- };
2700
- const parameters = asVercelSchema(schema);
2701
- let inputSchema = parameters;
2702
- if (ctx.jsonSchemaFactory) {
2703
- try {
2704
- inputSchema = ctx.jsonSchemaFactory(schema);
2705
- } catch (e) {
2706
- inputSchema = parameters;
2707
- }
2708
- }
2709
- const execute = async (rawInput) => {
2710
- var _a;
2711
- const input = isRecord(rawInput) ? rawInput : void 0;
2712
- const fallbackCategory = (_a = config.signalKeys[0]) != null ? _a : "unknown";
2713
- const categoryCandidate = typeof (input == null ? void 0 : input["category"]) === "string" ? input["category"].trim() : void 0;
2714
- const category = categoryCandidate && config.signalKeySet.has(categoryCandidate) ? categoryCandidate : fallbackCategory;
2715
- const detail = typeof (input == null ? void 0 : input["detail"]) === "string" ? input["detail"].trim() : "";
2716
- const signalDescription = config.signalDescriptions[category];
2717
- const signalSentiment = config.signalSentiments[category];
2718
- void ctx.eventShipper.trackSignal({
2719
- eventId: ctx.eventId,
2720
- name: `self diagnostics - ${category}`,
2721
- type: "agent",
2722
- sentiment: signalSentiment,
2723
- properties: {
2724
- source: "agent_reporting_tool",
2725
- category,
2726
- signal_description: signalDescription,
2727
- ai_sdk_version: ctx.aiSDKVersion,
2728
- ...detail ? { detail } : {}
2729
- }
2730
- }).catch((err) => {
2731
- if (ctx.debug) {
2732
- const msg = err instanceof Error ? err.message : String(err);
2733
- console.warn(`[raindrop-ai/ai-sdk] selfDiagnostics signal dispatch failed: ${msg}`);
2734
- }
2735
- });
2736
- return { acknowledged: true, category };
2737
- };
2738
- return {
2739
- description: config.toolDescription,
2740
- execute,
2741
- parameters,
2742
- inputSchema
2743
- };
2914
+ return createSelfDiagnosticsToolDefinition({
2915
+ config,
2916
+ eventShipper: ctx.eventShipper,
2917
+ getEventId: () => ctx.eventId,
2918
+ aiSDKVersion: ctx.aiSDKVersion,
2919
+ debug: ctx.debug
2920
+ });
2744
2921
  }
2745
2922
  function getCurrentParentSpanContextSync() {
2746
2923
  return getContextManager().getParentSpanIds();
@@ -2967,7 +3144,6 @@ function setupOperation(params) {
2967
3144
  eventShipper,
2968
3145
  traceShipper,
2969
3146
  rootParentForChildren,
2970
- jsonSchemaFactory: resolveJsonSchemaFactory(aiSDK),
2971
3147
  selfDiagnostics: operationSelfDiagnostics,
2972
3148
  aiSDKVersion: detectAISDKVersion(aiSDK)
2973
3149
  };
@@ -3316,7 +3492,6 @@ function wrapAISDK(aiSDK, deps) {
3316
3492
  );
3317
3493
  }
3318
3494
  const selfDiagnostics2 = normalizeSelfDiagnosticsConfig(deps.options.selfDiagnostics);
3319
- const jsonSchemaFactory = selfDiagnostics2 ? resolveJsonSchemaFactory(aiSDK) : void 0;
3320
3495
  const metadataAwareOps = /* @__PURE__ */ new Set([
3321
3496
  "generateText",
3322
3497
  "streamText",
@@ -3348,14 +3523,9 @@ function wrapAISDK(aiSDK, deps) {
3348
3523
  const perCallEventIdGenerated = !perCallEventIdExplicit;
3349
3524
  const perCallCtx = {
3350
3525
  eventId: perCallEventId,
3351
- context: wrapTimeCtx,
3352
- telemetry,
3353
- sendTraces: false,
3354
3526
  debug,
3355
3527
  eventShipper: deps.eventShipper,
3356
3528
  traceShipper: deps.traceShipper,
3357
- rootParentForChildren: void 0,
3358
- jsonSchemaFactory,
3359
3529
  selfDiagnostics: selfDiagnostics2,
3360
3530
  aiSDKVersion: "7"
3361
3531
  };
@@ -3557,7 +3727,6 @@ function wrapAgentGenerate(generate, instance, agentSettings, className, aiSDK,
3557
3727
  eventShipper: deps.eventShipper,
3558
3728
  traceShipper: deps.traceShipper,
3559
3729
  rootParentForChildren,
3560
- jsonSchemaFactory: resolveJsonSchemaFactory(aiSDK),
3561
3730
  selfDiagnostics,
3562
3731
  aiSDKVersion: detectAISDKVersion(aiSDK)
3563
3732
  };
@@ -3765,7 +3934,6 @@ function wrapAgentStream(stream, instance, agentSettings, className, aiSDK, deps
3765
3934
  eventShipper: deps.eventShipper,
3766
3935
  traceShipper: deps.traceShipper,
3767
3936
  rootParentForChildren,
3768
- jsonSchemaFactory: resolveJsonSchemaFactory(aiSDK),
3769
3937
  selfDiagnostics,
3770
3938
  aiSDKVersion: detectAISDKVersion(aiSDK)
3771
3939
  };
@@ -4484,7 +4652,7 @@ function extractNestedTokens(usage, key) {
4484
4652
  // package.json
4485
4653
  var package_default = {
4486
4654
  name: "@raindrop-ai/ai-sdk",
4487
- version: "0.0.31"};
4655
+ version: "0.0.33"};
4488
4656
 
4489
4657
  // src/internal/version.ts
4490
4658
  var libraryName = package_default.name;
@@ -4616,6 +4784,14 @@ function createRaindropAISDK(opts) {
4616
4784
  traceShipper
4617
4785
  });
4618
4786
  },
4787
+ createSelfDiagnosticsTool(options = {}) {
4788
+ var _a2;
4789
+ return createStandaloneSelfDiagnosticsTool({
4790
+ options,
4791
+ eventShipper,
4792
+ debug: ((_a2 = opts.events) == null ? void 0 : _a2.debug) === true || envDebug
4793
+ });
4794
+ },
4619
4795
  createTelemetryIntegration(contextOrOptions) {
4620
4796
  const FLAT_CONTEXT_KEYS = [
4621
4797
  "userId",
@@ -4746,5 +4922,12 @@ function createRaindropAISDK(opts) {
4746
4922
  }
4747
4923
  };
4748
4924
  }
4925
+ function raindrop(options = {}) {
4926
+ var _a;
4927
+ const { context, subagentWrapping, writeKey, ...rest } = options;
4928
+ const resolvedWriteKey = writeKey != null ? writeKey : typeof process !== "undefined" ? (_a = process.env) == null ? void 0 : _a.RAINDROP_WRITE_KEY : void 0;
4929
+ const client = createRaindropAISDK({ ...rest, writeKey: resolvedWriteKey });
4930
+ return client.createTelemetryIntegration({ context, subagentWrapping });
4931
+ }
4749
4932
 
4750
- export { DEFAULT_REDACT_ATTRIBUTE_KEYS, DEFAULT_SECRET_KEY_NAMES, REDACTED_PLACEHOLDER, RaindropTelemetryIntegration, _resetParentToolContextStorage, _resetRaindropCallMetadataStorage, _resetWarnedMissingUserId, clearParentToolContext, createRaindropAISDK, currentSpan, defaultTransformSpan, enterParentToolContext, eventMetadata, eventMetadataFromChatRequest, getContextManager, getCurrentParentToolContext, getCurrentRaindropCallMetadata, readRaindropCallMetadataFromArgs, redactJsonAttributeValue, redactSecretsInObject, runWithParentToolContext, runWithRaindropCallMetadata, withCurrent };
4933
+ export { DEFAULT_REDACT_ATTRIBUTE_KEYS, DEFAULT_SECRET_KEY_NAMES, REDACTED_PLACEHOLDER, RaindropTelemetryIntegration, _resetParentToolContextStorage, _resetRaindropCallMetadataStorage, _resetWarnedMissingUserId, clearParentToolContext, createRaindropAISDK, currentSpan, defaultTransformSpan, enterParentToolContext, eventMetadata, eventMetadataFromChatRequest, getContextManager, getCurrentParentToolContext, getCurrentRaindropCallMetadata, raindrop, readRaindropCallMetadataFromArgs, redactJsonAttributeValue, redactSecretsInObject, runWithParentToolContext, runWithRaindropCallMetadata, withCurrent };