@raindrop-ai/ai-sdk 0.0.31 → 0.0.32

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -136,6 +136,43 @@ registerTelemetry(
136
136
  );
137
137
  ```
138
138
 
139
+ ### Standalone self-diagnostics tool
140
+
141
+ When registering the native telemetry integration directly, create the
142
+ self-diagnostics tool from the same Raindrop client:
143
+
144
+ ```ts
145
+ import { createRaindropAISDK } from "@raindrop-ai/ai-sdk";
146
+ import { generateText, registerTelemetry } from "ai";
147
+
148
+ const raindrop = createRaindropAISDK({
149
+ writeKey: process.env.RAINDROP_WRITE_KEY!,
150
+ });
151
+
152
+ registerTelemetry(raindrop.createTelemetryIntegration({ userId: "user_123" }));
153
+
154
+ const diagnostics = raindrop.createSelfDiagnosticsTool();
155
+
156
+ await generateText({
157
+ model,
158
+ prompt,
159
+ tools: {
160
+ [diagnostics.name]: diagnostics,
161
+ },
162
+ experimental_telemetry: { isEnabled: true },
163
+ });
164
+ ```
165
+
166
+ With native telemetry and tracing enabled, the tool automatically attaches its
167
+ signal to the active Raindrop event. When there is no active trace context,
168
+ provide `eventId` or `getEventId`:
169
+
170
+ ```ts
171
+ const diagnostics = raindrop.createSelfDiagnosticsTool({
172
+ getEventId: () => currentEventId,
173
+ });
174
+ ```
175
+
139
176
  Setting `nativeTelemetry: true` on pre-v7 throws a clear error. The Proxy path remains the default and supports features not yet available on the native path (`buildEvent`, output attachment extraction).
140
177
 
141
178
  #### Per-call routing on AI SDK v7 beta.94+
@@ -2065,6 +2065,7 @@ var RaindropTelemetryIntegration = class {
2065
2065
  attrInt("gen_ai.usage.output_tokens", usage.outputTokens)
2066
2066
  );
2067
2067
  }
2068
+ this.emitProviderExecutedToolSpans(event, state);
2068
2069
  this.traceShipper.endSpan(state.stepSpan, { attributes: outputAttrs });
2069
2070
  state.stepSpan = void 0;
2070
2071
  state.stepParent = void 0;
@@ -2341,6 +2342,74 @@ var RaindropTelemetryIntegration = class {
2341
2342
  this.emitLive(state, "tool_result", event.toolCall.toolName);
2342
2343
  state.toolSpans.delete(event.toolCall.toolCallId);
2343
2344
  }
2345
+ // ── provider-executed tool calls ─────────────────────────────────────────
2346
+ //
2347
+ // Provider-executed (server-side) tools — e.g. Anthropic's hosted
2348
+ // `web_search` (`anthropic.web_search_20250305`) — are run by the provider,
2349
+ // not by the AI SDK. They therefore never flow through the client
2350
+ // `onToolExecutionStart`/`onToolExecutionEnd` callbacks that emit our
2351
+ // `ai.toolCall` spans; the SDK only surfaces them as `tool-call` /
2352
+ // `tool-result` content parts on the step (carrying `providerExecuted: true`).
2353
+ // Without this, such calls are invisible in every trace backend.
2354
+ //
2355
+ // At step finish we synthesize the same `ai.toolCall` span shape we emit for
2356
+ // client tools (name `ai.toolCall`, `operationId: "ai.toolCall"`, attrs
2357
+ // `ai.toolCall.name`/`id`/`args`/`result`), parented under the step span, so
2358
+ // downstream ingestion maps them to a tool span with no special-casing.
2359
+ //
2360
+ // Client-executed tools are excluded (`providerExecuted` falsy) — they were
2361
+ // already spanned during execution, so this never double-emits.
2362
+ emitProviderExecutedToolSpans(event, state) {
2363
+ if (!state.stepParent) return;
2364
+ const content = Array.isArray(event.content) ? event.content : [];
2365
+ const providerToolCalls = content.filter(
2366
+ (part) => (part == null ? void 0 : part.type) === "tool-call" && part.providerExecuted === true
2367
+ );
2368
+ if (providerToolCalls.length === 0) return;
2369
+ const resultsByCallId = /* @__PURE__ */ new Map();
2370
+ for (const part of content) {
2371
+ if (((part == null ? void 0 : part.type) === "tool-result" || (part == null ? void 0 : part.type) === "tool-error") && typeof part.toolCallId === "string") {
2372
+ resultsByCallId.set(part.toolCallId, part);
2373
+ }
2374
+ }
2375
+ for (const call of providerToolCalls) {
2376
+ const { operationName, resourceName } = opName(
2377
+ "ai.toolCall",
2378
+ state.functionId
2379
+ );
2380
+ const inputAttrs = state.recordInputs ? [attrString("ai.toolCall.args", safeJsonWithUint8(call.input))] : [];
2381
+ const toolSpan = this.traceShipper.startSpan({
2382
+ name: "ai.toolCall",
2383
+ parent: state.stepParent,
2384
+ eventId: state.eventId,
2385
+ operationId: "ai.toolCall",
2386
+ attributes: [
2387
+ attrString("operation.name", operationName),
2388
+ attrString("resource.name", resourceName),
2389
+ attrString("ai.telemetry.functionId", state.functionId),
2390
+ attrString("ai.toolCall.name", call.toolName),
2391
+ attrString("ai.toolCall.id", call.toolCallId),
2392
+ attrString("ai.toolCall.providerExecuted", "true"),
2393
+ ...inputAttrs
2394
+ ]
2395
+ });
2396
+ state.toolCallCount += 1;
2397
+ this.emitLive(state, "tool_start", call.toolName, { args: call.input });
2398
+ const resultPart = resultsByCallId.get(call.toolCallId);
2399
+ if ((resultPart == null ? void 0 : resultPart.type) === "tool-error") {
2400
+ this.traceShipper.endSpan(toolSpan, { error: resultPart.error });
2401
+ } else {
2402
+ const outputAttrs = state.recordOutputs && resultPart && "output" in resultPart ? [
2403
+ attrString(
2404
+ "ai.toolCall.result",
2405
+ safeJsonWithUint8(resultPart.output)
2406
+ )
2407
+ ] : [];
2408
+ this.traceShipper.endSpan(toolSpan, { attributes: outputAttrs });
2409
+ }
2410
+ this.emitLive(state, "tool_result", call.toolName);
2411
+ }
2412
+ }
2344
2413
  finishGenerate(event, state) {
2345
2414
  var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n;
2346
2415
  if (state.rootSpan) {
@@ -2446,9 +2515,9 @@ var RaindropTelemetryIntegration = class {
2446
2515
  }
2447
2516
  };
2448
2517
 
2449
- // src/internal/wrap/wrapAISDK.ts
2450
- var AGENT_REPORTING_TOOL_NAME_DEFAULT = "__raindrop_report";
2451
- var AGENT_REPORTING_SIGNALS_DEFAULT = {
2518
+ // src/internal/self-diagnostics.ts
2519
+ var SELF_DIAGNOSTICS_TOOL_NAME_DEFAULT = "__raindrop_report";
2520
+ var SELF_DIAGNOSTICS_SIGNALS_DEFAULT = {
2452
2521
  missing_context: {
2453
2522
  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
2523
  sentiment: "NEGATIVE"
@@ -2466,7 +2535,181 @@ var AGENT_REPORTING_SIGNALS_DEFAULT = {
2466
2535
  sentiment: "NEGATIVE"
2467
2536
  }
2468
2537
  };
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.";
2538
+ 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.";
2539
+ function normalizeString(value) {
2540
+ if (typeof value !== "string") return void 0;
2541
+ const trimmed = value.trim();
2542
+ return trimmed || void 0;
2543
+ }
2544
+ function normalizeSelfDiagnosticsSignals(signals) {
2545
+ if (!signals) return SELF_DIAGNOSTICS_SIGNALS_DEFAULT;
2546
+ const normalizedEntries = Object.entries(signals).map(([key, value]) => {
2547
+ var _a;
2548
+ const signalKey = key.trim();
2549
+ if (!signalKey || !value || typeof value !== "object") return void 0;
2550
+ const description = (_a = value.description) == null ? void 0 : _a.trim();
2551
+ if (!description) return void 0;
2552
+ const sentiment = value.sentiment;
2553
+ return [
2554
+ signalKey,
2555
+ {
2556
+ description,
2557
+ ...sentiment === "POSITIVE" || sentiment === "NEGATIVE" ? { sentiment } : {}
2558
+ }
2559
+ ];
2560
+ }).filter(
2561
+ (entry) => entry !== void 0
2562
+ );
2563
+ if (normalizedEntries.length === 0) return SELF_DIAGNOSTICS_SIGNALS_DEFAULT;
2564
+ return Object.fromEntries(normalizedEntries);
2565
+ }
2566
+ function resolveSelfDiagnosticsConfig(options) {
2567
+ var _a, _b;
2568
+ const signalDefinitions = normalizeSelfDiagnosticsSignals(options.signals);
2569
+ const signalKeys = Object.keys(signalDefinitions);
2570
+ const signalDescriptions = {};
2571
+ const signalSentiments = {};
2572
+ for (const signalKey of signalKeys) {
2573
+ const definition = signalDefinitions[signalKey];
2574
+ if (!definition) continue;
2575
+ signalDescriptions[signalKey] = definition.description;
2576
+ signalSentiments[signalKey] = definition.sentiment;
2577
+ }
2578
+ const customGuidance = ((_a = options.guidance) == null ? void 0 : _a.trim()) || "";
2579
+ const toolName = ((_b = options.toolName) == null ? void 0 : _b.trim()) || SELF_DIAGNOSTICS_TOOL_NAME_DEFAULT;
2580
+ const signalList = signalKeys.map((signalKey) => {
2581
+ const sentiment = signalSentiments[signalKey];
2582
+ const sentimentTag = sentiment ? ` [${sentiment.toLowerCase()}]` : "";
2583
+ return `- ${signalKey}: ${signalDescriptions[signalKey]}${sentimentTag}`;
2584
+ }).join("\n");
2585
+ const guidanceBlock = customGuidance ? `
2586
+ Additional guidance: ${customGuidance}
2587
+ ` : "";
2588
+ const toolDescription = `${SELF_DIAGNOSTICS_TOOL_PREAMBLE}
2589
+
2590
+ When to call:
2591
+ - You are blocked from completing the task due to missing information or access that the user cannot provide.
2592
+ - A tool is persistently failing across multiple attempts, not just a single transient error.
2593
+ - The task requires a tool, permission, or capability you do not have.
2594
+ - You genuinely cannot deliver what the user asked for despite trying.
2595
+
2596
+ When NOT to call:
2597
+ - Normal clarifying questions or back-and-forth with the user.
2598
+ - A single tool error that you can recover from or retry.
2599
+ - You successfully completed the task, even if it was difficult.
2600
+ - Policy refusals or content filtering \u2014 those are working as intended.
2601
+
2602
+ Rules:
2603
+ 1. Pick the single best category.
2604
+ 2. Do not fabricate issues. Only report what is evident from the conversation.
2605
+ 3. Err on the side of NOT calling this tool. When in doubt, help the user instead.
2606
+ ${guidanceBlock}
2607
+ Categories:
2608
+ ` + signalList;
2609
+ return {
2610
+ toolName,
2611
+ toolDescription,
2612
+ signalKeys,
2613
+ signalKeySet: new Set(signalKeys),
2614
+ signalDescriptions,
2615
+ signalSentiments
2616
+ };
2617
+ }
2618
+ function normalizeSelfDiagnosticsConfig(options) {
2619
+ if (!(options == null ? void 0 : options.enabled)) return void 0;
2620
+ return resolveSelfDiagnosticsConfig(options);
2621
+ }
2622
+ function asVercelSchema(inputSchema) {
2623
+ const validatorSymbol = /* @__PURE__ */ Symbol.for("vercel.ai.validator");
2624
+ const schemaSymbol = /* @__PURE__ */ Symbol.for("vercel.ai.schema");
2625
+ return {
2626
+ [schemaSymbol]: true,
2627
+ [validatorSymbol]: true,
2628
+ _type: void 0,
2629
+ jsonSchema: inputSchema,
2630
+ validate: (value) => ({ success: true, value })
2631
+ };
2632
+ }
2633
+ function resolveStandaloneEventId(options) {
2634
+ var _a, _b, _c, _d, _e, _f;
2635
+ 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);
2636
+ }
2637
+ function createSelfDiagnosticsToolDefinition(args) {
2638
+ const { config, eventShipper, getEventId, aiSDKVersion, debug } = args;
2639
+ const inputJsonSchema = {
2640
+ type: "object",
2641
+ additionalProperties: false,
2642
+ properties: {
2643
+ category: {
2644
+ type: "string",
2645
+ enum: config.signalKeys,
2646
+ description: "The single best-matching category from the list above."
2647
+ },
2648
+ detail: {
2649
+ type: "string",
2650
+ description: "One sentence of factual context: what happened and why it matters. Do not include PII or secrets."
2651
+ }
2652
+ },
2653
+ required: ["category", "detail"]
2654
+ };
2655
+ const inputSchema = asVercelSchema(inputJsonSchema);
2656
+ const execute = async (rawInput) => {
2657
+ var _a, _b;
2658
+ const fallbackCategory = (_a = config.signalKeys[0]) != null ? _a : "unknown";
2659
+ const categoryCandidate = normalizeString(rawInput == null ? void 0 : rawInput.category);
2660
+ const category = categoryCandidate && config.signalKeySet.has(categoryCandidate) ? categoryCandidate : fallbackCategory;
2661
+ const detail = normalizeString(rawInput == null ? void 0 : rawInput.detail);
2662
+ const eventId = getEventId();
2663
+ if (!eventId) {
2664
+ const message = "self diagnostics signal skipped: missing eventId. Pass eventId or getEventId when creating the tool.";
2665
+ if (args.onMissingEventId === "throw") {
2666
+ throw new Error(`[raindrop-ai/ai-sdk] ${message}`);
2667
+ }
2668
+ if (((_b = args.onMissingEventId) != null ? _b : "warn") === "warn") {
2669
+ console.warn(`[raindrop-ai/ai-sdk] ${message}`);
2670
+ }
2671
+ return { acknowledged: false, category, reason: "missing_event_id" };
2672
+ }
2673
+ void eventShipper.trackSignal({
2674
+ eventId,
2675
+ name: `self diagnostics - ${category}`,
2676
+ type: "agent",
2677
+ sentiment: config.signalSentiments[category],
2678
+ properties: {
2679
+ source: "agent_reporting_tool",
2680
+ category,
2681
+ signal_description: config.signalDescriptions[category],
2682
+ ...aiSDKVersion ? { ai_sdk_version: aiSDKVersion } : {},
2683
+ ...detail ? { detail } : {}
2684
+ }
2685
+ }).catch((error) => {
2686
+ if (debug) {
2687
+ const message = error instanceof Error ? error.message : String(error);
2688
+ console.warn(`[raindrop-ai/ai-sdk] selfDiagnostics signal dispatch failed: ${message}`);
2689
+ }
2690
+ });
2691
+ return { acknowledged: true, category };
2692
+ };
2693
+ return {
2694
+ name: config.toolName,
2695
+ description: config.toolDescription,
2696
+ parameters: inputSchema,
2697
+ inputSchema,
2698
+ execute
2699
+ };
2700
+ }
2701
+ function createStandaloneSelfDiagnosticsTool(args) {
2702
+ const config = resolveSelfDiagnosticsConfig(args.options);
2703
+ return createSelfDiagnosticsToolDefinition({
2704
+ config,
2705
+ eventShipper: args.eventShipper,
2706
+ getEventId: () => resolveStandaloneEventId(args.options),
2707
+ onMissingEventId: args.options.onMissingEventId,
2708
+ debug: args.debug
2709
+ });
2710
+ }
2711
+
2712
+ // src/internal/wrap/wrapAISDK.ts
2470
2713
  var pendingStoresByShipper = /* @__PURE__ */ new WeakMap();
2471
2714
  var PendingToolSpanStore = class _PendingToolSpanStore {
2472
2715
  constructor() {
@@ -2570,85 +2813,6 @@ function mergeContexts(wrapTime, callTime) {
2570
2813
  }
2571
2814
  return result;
2572
2815
  }
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
2816
  function detectAISDKVersion(aiSDK) {
2653
2817
  if (!isRecord(aiSDK)) return "unknown";
2654
2818
  if (isFunction(aiSDK["jsonSchema"])) return "6";
@@ -2667,80 +2831,16 @@ function resolveRegisterTelemetry(aiSDK) {
2667
2831
  const fn = (_a = aiSDK["registerTelemetry"]) != null ? _a : aiSDK["registerTelemetryIntegration"];
2668
2832
  return isFunction(fn) ? fn : void 0;
2669
2833
  }
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
2834
  function createSelfDiagnosticsTool(ctx) {
2682
2835
  const config = ctx.selfDiagnostics;
2683
2836
  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
- };
2837
+ return createSelfDiagnosticsToolDefinition({
2838
+ config,
2839
+ eventShipper: ctx.eventShipper,
2840
+ getEventId: () => ctx.eventId,
2841
+ aiSDKVersion: ctx.aiSDKVersion,
2842
+ debug: ctx.debug
2843
+ });
2744
2844
  }
2745
2845
  function getCurrentParentSpanContextSync() {
2746
2846
  return getContextManager().getParentSpanIds();
@@ -2967,7 +3067,6 @@ function setupOperation(params) {
2967
3067
  eventShipper,
2968
3068
  traceShipper,
2969
3069
  rootParentForChildren,
2970
- jsonSchemaFactory: resolveJsonSchemaFactory(aiSDK),
2971
3070
  selfDiagnostics: operationSelfDiagnostics,
2972
3071
  aiSDKVersion: detectAISDKVersion(aiSDK)
2973
3072
  };
@@ -3316,7 +3415,6 @@ function wrapAISDK(aiSDK, deps) {
3316
3415
  );
3317
3416
  }
3318
3417
  const selfDiagnostics2 = normalizeSelfDiagnosticsConfig(deps.options.selfDiagnostics);
3319
- const jsonSchemaFactory = selfDiagnostics2 ? resolveJsonSchemaFactory(aiSDK) : void 0;
3320
3418
  const metadataAwareOps = /* @__PURE__ */ new Set([
3321
3419
  "generateText",
3322
3420
  "streamText",
@@ -3348,14 +3446,9 @@ function wrapAISDK(aiSDK, deps) {
3348
3446
  const perCallEventIdGenerated = !perCallEventIdExplicit;
3349
3447
  const perCallCtx = {
3350
3448
  eventId: perCallEventId,
3351
- context: wrapTimeCtx,
3352
- telemetry,
3353
- sendTraces: false,
3354
3449
  debug,
3355
3450
  eventShipper: deps.eventShipper,
3356
3451
  traceShipper: deps.traceShipper,
3357
- rootParentForChildren: void 0,
3358
- jsonSchemaFactory,
3359
3452
  selfDiagnostics: selfDiagnostics2,
3360
3453
  aiSDKVersion: "7"
3361
3454
  };
@@ -3557,7 +3650,6 @@ function wrapAgentGenerate(generate, instance, agentSettings, className, aiSDK,
3557
3650
  eventShipper: deps.eventShipper,
3558
3651
  traceShipper: deps.traceShipper,
3559
3652
  rootParentForChildren,
3560
- jsonSchemaFactory: resolveJsonSchemaFactory(aiSDK),
3561
3653
  selfDiagnostics,
3562
3654
  aiSDKVersion: detectAISDKVersion(aiSDK)
3563
3655
  };
@@ -3765,7 +3857,6 @@ function wrapAgentStream(stream, instance, agentSettings, className, aiSDK, deps
3765
3857
  eventShipper: deps.eventShipper,
3766
3858
  traceShipper: deps.traceShipper,
3767
3859
  rootParentForChildren,
3768
- jsonSchemaFactory: resolveJsonSchemaFactory(aiSDK),
3769
3860
  selfDiagnostics,
3770
3861
  aiSDKVersion: detectAISDKVersion(aiSDK)
3771
3862
  };
@@ -4484,7 +4575,7 @@ function extractNestedTokens(usage, key) {
4484
4575
  // package.json
4485
4576
  var package_default = {
4486
4577
  name: "@raindrop-ai/ai-sdk",
4487
- version: "0.0.31"};
4578
+ version: "0.0.32"};
4488
4579
 
4489
4580
  // src/internal/version.ts
4490
4581
  var libraryName = package_default.name;
@@ -4616,6 +4707,14 @@ function createRaindropAISDK(opts) {
4616
4707
  traceShipper
4617
4708
  });
4618
4709
  },
4710
+ createSelfDiagnosticsTool(options = {}) {
4711
+ var _a2;
4712
+ return createStandaloneSelfDiagnosticsTool({
4713
+ options,
4714
+ eventShipper,
4715
+ debug: ((_a2 = opts.events) == null ? void 0 : _a2.debug) === true || envDebug
4716
+ });
4717
+ },
4619
4718
  createTelemetryIntegration(contextOrOptions) {
4620
4719
  const FLAT_CONTEXT_KEYS = [
4621
4720
  "userId",
@@ -462,6 +462,7 @@ declare class RaindropTelemetryIntegration implements TelemetryIntegration {
462
462
  onLanguageModelCallStart: (_event: any) => void;
463
463
  onLanguageModelCallEnd: (_event: any) => void;
464
464
  onChunk: (event: any) => void;
465
+ private emitProviderExecutedToolSpans;
465
466
  onStepFinish: (event: any) => void;
466
467
  onEmbedStart: (event: any) => void;
467
468
  onEmbedFinish: (event: any) => void;
@@ -893,6 +894,38 @@ type SelfDiagnosticsOptions = {
893
894
  */
894
895
  toolName?: string;
895
896
  };
897
+ type SelfDiagnosticsToolOptions = Omit<SelfDiagnosticsOptions, "enabled"> & {
898
+ /** Fixed Raindrop event ID to attach diagnostic signals to. */
899
+ eventId?: string;
900
+ /** Dynamic event ID resolver, useful when one tool instance serves many runs. */
901
+ getEventId?: () => string | undefined;
902
+ /** Behavior when no event ID can be resolved. Default: "warn" */
903
+ onMissingEventId?: "warn" | "ignore" | "throw";
904
+ };
905
+ type SelfDiagnosticsToolInput = {
906
+ category: string;
907
+ detail: string;
908
+ };
909
+ type SelfDiagnosticsToolResult = {
910
+ acknowledged: true;
911
+ category: string;
912
+ } | {
913
+ acknowledged: false;
914
+ category: string;
915
+ reason: "missing_event_id";
916
+ };
917
+ type SelfDiagnosticsTool = {
918
+ name: string;
919
+ description: string;
920
+ /**
921
+ * AI SDK v4 tool schema. This is the same cross-version schema object as
922
+ * `inputSchema`; both fields are exposed so the tool works on AI SDK v4-v7.
923
+ */
924
+ parameters: any;
925
+ /** AI SDK v5+ tool schema. */
926
+ inputSchema: any;
927
+ execute(input: SelfDiagnosticsToolInput): Promise<SelfDiagnosticsToolResult>;
928
+ };
896
929
  type WrapAISDKOptions = {
897
930
  context: RaindropAISDKContext | ((info: {
898
931
  operation: string;
@@ -977,6 +1010,14 @@ type EventPatch = {
977
1010
  };
978
1011
  type RaindropAISDKClient = {
979
1012
  wrap<T extends object>(aiSDK: T, options?: WrapAISDKOptions): WrappedAISDK<T>;
1013
+ /**
1014
+ * Create a standalone AI SDK self-diagnostics tool.
1015
+ *
1016
+ * The tool automatically uses the active Raindrop event while executing
1017
+ * under `createTelemetryIntegration()` with tracing enabled. Pass `eventId`
1018
+ * or `getEventId` when no active trace context is available.
1019
+ */
1020
+ createSelfDiagnosticsTool(options?: SelfDiagnosticsToolOptions): SelfDiagnosticsTool;
980
1021
  /**
981
1022
  * Create a TelemetryIntegration instance for direct registration with AI SDK v7+.
982
1023
  * Use with `registerTelemetryIntegration()` from the `ai` package.
@@ -1062,4 +1103,4 @@ type RaindropAISDKClient = {
1062
1103
  };
1063
1104
  declare function createRaindropAISDK(opts: RaindropAISDKOptions): RaindropAISDKClient;
1064
1105
 
1065
- export { withCurrent as $, type AISDKChatRequestLike as A, type BuildEventPatch as B, ContextManager as C, DEFAULT_REDACT_ATTRIBUTE_KEYS as D, type EndSpanArgs as E, createRaindropAISDK as F, currentSpan as G, defaultTransformSpan as H, type IdentifyInput as I, enterParentToolContext as J, eventMetadata as K, eventMetadataFromChatRequest as L, getContextManager as M, getCurrentParentToolContext as N, type OtlpAnyValue as O, type ParentToolContext as P, getCurrentRaindropCallMetadata as Q, REDACTED_PLACEHOLDER as R, type SelfDiagnosticsOptions as S, type TraceSpan as T, readRaindropCallMetadataFromArgs as U, redactJsonAttributeValue as V, type WrapAISDKOptions as W, redactSecretsInObject as X, runWithParentToolContext as Y, runWithRaindropCallMetadata as Z, _resetParentToolContextStorage as _, type AISDKChatRequestMessageLike as a, type AISDKMessage as b, type AgentCallMetadata as c, type AgentWithMetadata as d, type Attachment as e, type ContextSpan as f, type CreateSpanArgs as g, DEFAULT_SECRET_KEY_NAMES as h, type EventBuilder as i, type EventMetadataOptions as j, type OtlpSpan as k, type RaindropAISDKClient as l, type RaindropAISDKContext as m, type RaindropAISDKOptions as n, type RaindropCallMetadata as o, RaindropTelemetryIntegration as p, type RaindropTelemetryIntegrationOptions as q, type SelfDiagnosticsSignalDefinition as r, type SelfDiagnosticsSignalDefinitions as s, type StartSpanArgs as t, type TransformSpanHook as u, type WrappedAI as v, type WrappedAISDK as w, _resetRaindropCallMetadataStorage as x, _resetWarnedMissingUserId as y, clearParentToolContext as z };
1106
+ export { redactJsonAttributeValue as $, type AISDKChatRequestLike as A, type BuildEventPatch as B, ContextManager as C, DEFAULT_REDACT_ATTRIBUTE_KEYS as D, type EndSpanArgs as E, type WrappedAISDK as F, _resetRaindropCallMetadataStorage as G, _resetWarnedMissingUserId as H, type IdentifyInput as I, clearParentToolContext as J, createRaindropAISDK as K, currentSpan as L, defaultTransformSpan as M, enterParentToolContext as N, type OtlpAnyValue as O, type ParentToolContext as P, eventMetadata as Q, REDACTED_PLACEHOLDER as R, type SelfDiagnosticsOptions as S, type TraceSpan as T, eventMetadataFromChatRequest as U, getContextManager as V, type WrapAISDKOptions as W, getCurrentParentToolContext as X, getCurrentRaindropCallMetadata as Y, readRaindropCallMetadataFromArgs as Z, _resetParentToolContextStorage as _, type AISDKChatRequestMessageLike as a, redactSecretsInObject as a0, runWithParentToolContext as a1, runWithRaindropCallMetadata as a2, withCurrent as a3, type AISDKMessage as b, type AgentCallMetadata as c, type AgentWithMetadata as d, type Attachment as e, type ContextSpan as f, type CreateSpanArgs as g, DEFAULT_SECRET_KEY_NAMES as h, type EventBuilder as i, type EventMetadataOptions as j, type OtlpSpan as k, type RaindropAISDKClient as l, type RaindropAISDKContext as m, type RaindropAISDKOptions as n, type RaindropCallMetadata as o, RaindropTelemetryIntegration as p, type RaindropTelemetryIntegrationOptions as q, type SelfDiagnosticsSignalDefinition as r, type SelfDiagnosticsSignalDefinitions as s, type SelfDiagnosticsTool as t, type SelfDiagnosticsToolInput as u, type SelfDiagnosticsToolOptions as v, type SelfDiagnosticsToolResult as w, type StartSpanArgs as x, type TransformSpanHook as y, type WrappedAI as z };