@raindrop-ai/ai-sdk 0.0.32 → 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.
@@ -1024,7 +1024,7 @@ globalThis.RAINDROP_ASYNC_LOCAL_STORAGE = async_hooks.AsyncLocalStorage;
1024
1024
  // package.json
1025
1025
  var package_default = {
1026
1026
  name: "@raindrop-ai/ai-sdk",
1027
- version: "0.0.32"};
1027
+ version: "0.0.33"};
1028
1028
 
1029
1029
  // src/internal/version.ts
1030
1030
  var libraryName = package_default.name;
@@ -1807,6 +1807,25 @@ var RaindropTelemetryIntegration = class {
1807
1807
  * (the `event.callId` can be the same for parallel sibling tools).
1808
1808
  */
1809
1809
  this.priorParentContexts = /* @__PURE__ */ new Map();
1810
+ // ── lifecycle ─────────────────────────────────────────────────────────────
1811
+ //
1812
+ // The shippers buffer spans/events and flush on a timer, so a short-lived
1813
+ // script (e.g. a single `generateText` then `process.exit`) can exit before
1814
+ // anything ships. Expose `flush`/`shutdown` on the integration itself so the
1815
+ // value returned by `raindrop()` is self-sufficient — callers can keep the
1816
+ // reference they pass to `registerTelemetry` and `await rd.flush()` before
1817
+ // exiting, without also constructing a separate client.
1818
+ /** Flush any buffered events and trace spans to their destinations. */
1819
+ this.flush = async () => {
1820
+ await Promise.all([this.eventShipper.flush(), this.traceShipper.flush()]);
1821
+ };
1822
+ /** Flush and stop the background flush timers. */
1823
+ this.shutdown = async () => {
1824
+ await Promise.all([
1825
+ this.eventShipper.shutdown(),
1826
+ this.traceShipper.shutdown()
1827
+ ]);
1828
+ };
1810
1829
  // ── onStart ─────────────────────────────────────────────────────────────
1811
1830
  this.onStart = (event) => {
1812
1831
  var _a, _b, _c, _d, _e;
@@ -2200,8 +2219,56 @@ var RaindropTelemetryIntegration = class {
2200
2219
  if (state.subagentToolCallSpan) {
2201
2220
  this.traceShipper.endSpan(state.subagentToolCallSpan, { error: actualError });
2202
2221
  }
2222
+ const isEmbed = state.operationId === "ai.embed" || state.operationId === "ai.embedMany";
2223
+ if (!isEmbed) {
2224
+ this.finalizeGenerateEvent(state, state.accumulatedText || void 0, void 0);
2225
+ }
2203
2226
  this.cleanup(event.callId);
2204
2227
  };
2228
+ // ── onAbort ─────────────────────────────────────────────────────────────
2229
+ //
2230
+ // Dispatched by the v7 canary line (post-beta.116) when a `streamText` call
2231
+ // is cancelled via its `AbortSignal`. On abort the SDK fires neither `onEnd`
2232
+ // nor `onError`, so without this every open span would leak and the event
2233
+ // would hang forever in its `isPending` state. We close every open span with
2234
+ // an `ai.response.aborted` marker (no error status — an abort is not a model
2235
+ // failure) and flush the partial event.
2236
+ this.onAbort = (event) => {
2237
+ const callId = event == null ? void 0 : event.callId;
2238
+ if (!callId) return;
2239
+ const state = this.getState(callId);
2240
+ if (!state) return;
2241
+ const abortedAttr = attrString("ai.response.aborted", "true");
2242
+ if (state.stepSpan) {
2243
+ this.traceShipper.endSpan(state.stepSpan, { attributes: [abortedAttr] });
2244
+ state.stepSpan = void 0;
2245
+ state.stepParent = void 0;
2246
+ }
2247
+ for (const embedSpan of state.embedSpans.values()) {
2248
+ this.traceShipper.endSpan(embedSpan, { attributes: [abortedAttr] });
2249
+ }
2250
+ state.embedSpans.clear();
2251
+ for (const toolCallId of state.parentContextToolCallIds) {
2252
+ this.priorParentContexts.delete(toolCallId);
2253
+ }
2254
+ state.parentContextToolCallIds.clear();
2255
+ for (const toolSpan of state.toolSpans.values()) {
2256
+ this.traceShipper.endSpan(toolSpan, { attributes: [abortedAttr] });
2257
+ }
2258
+ state.toolSpans.clear();
2259
+ if (state.rootSpan) {
2260
+ this.traceShipper.endSpan(state.rootSpan, {
2261
+ attributes: [abortedAttr, attrInt("ai.toolCall.count", state.toolCallCount)]
2262
+ });
2263
+ }
2264
+ if (state.subagentToolCallSpan) {
2265
+ this.traceShipper.endSpan(state.subagentToolCallSpan, {
2266
+ attributes: [abortedAttr]
2267
+ });
2268
+ }
2269
+ this.finalizeGenerateEvent(state, state.accumulatedText || void 0, void 0);
2270
+ this.cleanup(callId);
2271
+ };
2205
2272
  // ── executeTool ─────────────────────────────────────────────────────────
2206
2273
  this.executeTool = async ({
2207
2274
  callId,
@@ -2359,11 +2426,12 @@ var RaindropTelemetryIntegration = class {
2359
2426
  const toolSpan = state.toolSpans.get(event.toolCall.toolCallId);
2360
2427
  if (!toolSpan) return;
2361
2428
  state.toolCallCount += 1;
2362
- if (event.success) {
2363
- const outputAttrs = state.recordOutputs ? [attrString("ai.toolCall.result", safeJsonWithUint8(event.output))] : [];
2429
+ 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 };
2430
+ if (outcome.success) {
2431
+ const outputAttrs = state.recordOutputs ? [attrString("ai.toolCall.result", safeJsonWithUint8(outcome.output))] : [];
2364
2432
  this.traceShipper.endSpan(toolSpan, { attributes: outputAttrs });
2365
2433
  } else {
2366
- this.traceShipper.endSpan(toolSpan, { error: event.error });
2434
+ this.traceShipper.endSpan(toolSpan, { error: outcome.error });
2367
2435
  }
2368
2436
  this.emitLive(state, "tool_result", event.toolCall.toolName);
2369
2437
  state.toolSpans.delete(event.toolCall.toolCallId);
@@ -2437,7 +2505,7 @@ var RaindropTelemetryIntegration = class {
2437
2505
  }
2438
2506
  }
2439
2507
  finishGenerate(event, state) {
2440
- var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n;
2508
+ var _a, _b, _c, _d, _e, _f;
2441
2509
  if (state.rootSpan) {
2442
2510
  const outputAttrs = [];
2443
2511
  if (state.recordOutputs) {
@@ -2485,38 +2553,47 @@ var RaindropTelemetryIntegration = class {
2485
2553
  );
2486
2554
  this.traceShipper.endSpan(state.rootSpan, { attributes: outputAttrs });
2487
2555
  }
2556
+ this.finalizeGenerateEvent(
2557
+ state,
2558
+ (_e = event.text) != null ? _e : state.accumulatedText || void 0,
2559
+ (_f = event.response) == null ? void 0 : _f.modelId
2560
+ );
2561
+ }
2562
+ /**
2563
+ * Patch the Raindrop event for a completed, aborted, or errored text
2564
+ * generation so it leaves the `isPending` state. Shared by `onFinish`/`onEnd`,
2565
+ * `onAbort`, and `onError`.
2566
+ */
2567
+ finalizeGenerateEvent(state, output, model) {
2568
+ var _a, _b, _c, _d, _e, _f, _g, _h;
2488
2569
  const suppressSubagentEvent = state.subagentName !== void 0 && state.subagentToolCallSpan !== void 0;
2489
- if (this.sendEvents && !suppressSubagentEvent) {
2490
- const callMeta = this.extractRaindropMetadata(state.metadata);
2491
- const userId = (_f = callMeta.userId) != null ? _f : (_e = this.defaultContext) == null ? void 0 : _e.userId;
2492
- if (userId) {
2493
- const eventName = (_i = (_h = callMeta.eventName) != null ? _h : (_g = this.defaultContext) == null ? void 0 : _g.eventName) != null ? _i : state.operationId;
2494
- const output = (_j = event.text) != null ? _j : state.accumulatedText || void 0;
2495
- const input = state.inputText;
2496
- const model = (_k = event.response) == null ? void 0 : _k.modelId;
2497
- const properties = {
2498
- ...(_l = this.defaultContext) == null ? void 0 : _l.properties,
2499
- ...callMeta.properties
2500
- };
2501
- const convoId = (_n = callMeta.convoId) != null ? _n : (_m = this.defaultContext) == null ? void 0 : _m.convoId;
2502
- void this.eventShipper.patch(state.eventId, {
2503
- eventName,
2504
- userId,
2505
- convoId,
2506
- input,
2507
- output,
2508
- model,
2509
- properties: Object.keys(properties).length > 0 ? properties : void 0,
2510
- isPending: false
2511
- }).catch((err) => {
2512
- if (this.debug) {
2513
- console.warn(
2514
- `[raindrop-ai/ai-sdk] event patch failed: ${err instanceof Error ? err.message : err}`
2515
- );
2516
- }
2517
- });
2570
+ if (!this.sendEvents || suppressSubagentEvent) return;
2571
+ const callMeta = this.extractRaindropMetadata(state.metadata);
2572
+ const userId = (_b = callMeta.userId) != null ? _b : (_a = this.defaultContext) == null ? void 0 : _a.userId;
2573
+ if (!userId) return;
2574
+ const eventName = (_e = (_d = callMeta.eventName) != null ? _d : (_c = this.defaultContext) == null ? void 0 : _c.eventName) != null ? _e : state.operationId;
2575
+ const input = state.inputText;
2576
+ const properties = {
2577
+ ...(_f = this.defaultContext) == null ? void 0 : _f.properties,
2578
+ ...callMeta.properties
2579
+ };
2580
+ const convoId = (_h = callMeta.convoId) != null ? _h : (_g = this.defaultContext) == null ? void 0 : _g.convoId;
2581
+ void this.eventShipper.patch(state.eventId, {
2582
+ eventName,
2583
+ userId,
2584
+ convoId,
2585
+ input,
2586
+ output,
2587
+ model,
2588
+ properties: Object.keys(properties).length > 0 ? properties : void 0,
2589
+ isPending: false
2590
+ }).catch((err) => {
2591
+ if (this.debug) {
2592
+ console.warn(
2593
+ `[raindrop-ai/ai-sdk] event patch failed: ${err instanceof Error ? err.message : err}`
2594
+ );
2518
2595
  }
2519
- }
2596
+ });
2520
2597
  }
2521
2598
  finishEmbed(event, state) {
2522
2599
  var _a;
@@ -4849,6 +4926,13 @@ function createRaindropAISDK(opts) {
4849
4926
  }
4850
4927
  };
4851
4928
  }
4929
+ function raindrop(options = {}) {
4930
+ var _a;
4931
+ const { context, subagentWrapping, writeKey, ...rest } = options;
4932
+ const resolvedWriteKey = writeKey != null ? writeKey : typeof process !== "undefined" ? (_a = process.env) == null ? void 0 : _a.RAINDROP_WRITE_KEY : void 0;
4933
+ const client = createRaindropAISDK({ ...rest, writeKey: resolvedWriteKey });
4934
+ return client.createTelemetryIntegration({ context, subagentWrapping });
4935
+ }
4852
4936
 
4853
4937
  // src/index.workers.ts
4854
4938
  if (!globalThis.RAINDROP_ASYNC_LOCAL_STORAGE) {
@@ -4872,6 +4956,7 @@ exports.eventMetadataFromChatRequest = eventMetadataFromChatRequest;
4872
4956
  exports.getContextManager = getContextManager;
4873
4957
  exports.getCurrentParentToolContext = getCurrentParentToolContext;
4874
4958
  exports.getCurrentRaindropCallMetadata = getCurrentRaindropCallMetadata;
4959
+ exports.raindrop = raindrop;
4875
4960
  exports.readRaindropCallMetadataFromArgs = readRaindropCallMetadataFromArgs;
4876
4961
  exports.redactJsonAttributeValue = redactJsonAttributeValue;
4877
4962
  exports.redactSecretsInObject = redactSecretsInObject;
@@ -1,4 +1,4 @@
1
- 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 } from './chunk-YDMJ6ABM.mjs';
1
+ 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 } from './chunk-FIX66Y7M.mjs';
2
2
  import { AsyncLocalStorage } from 'async_hooks';
3
3
 
4
4
  if (!globalThis.RAINDROP_ASYNC_LOCAL_STORAGE) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@raindrop-ai/ai-sdk",
3
- "version": "0.0.32",
3
+ "version": "0.0.33",
4
4
  "description": "Standalone Vercel AI SDK integration for Raindrop (events + OTLP/HTTP JSON traces, no OTEL runtime)",
5
5
  "main": "dist/index.node.js",
6
6
  "module": "dist/index.node.mjs",
@@ -62,7 +62,7 @@
62
62
  "test:v4": "pnpm build && cd tests/v4 && pnpm install --ignore-workspace --lockfile=false && pnpm test",
63
63
  "test:v5": "pnpm build && cd tests/v5 && pnpm install --ignore-workspace --lockfile=false && pnpm test",
64
64
  "test:v6": "pnpm build && cd tests/v6 && pnpm install --ignore-workspace --lockfile=false && pnpm test",
65
- "test:v7": "pnpm build && cd tests/v7 && pnpm install --ignore-workspace --lockfile=false && pnpm test",
65
+ "test:v7": "pnpm build && cd tests/v7 && npm_config_minimum_release_age=0 pnpm install --ignore-workspace --lockfile=false && pnpm test",
66
66
  "test:install": "cd tests/v4 && pnpm install --ignore-workspace --lockfile=false && cd ../v5 && pnpm install --ignore-workspace --lockfile=false && cd ../v6 && pnpm install --ignore-workspace --lockfile=false && cd ../v7 && pnpm install --ignore-workspace --lockfile=false"
67
67
  }
68
68
  }