@raindrop-ai/ai-sdk 0.0.40 → 0.1.0

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.
@@ -1,3 +1,14 @@
1
+ type FeatureFlagValue = string | number | boolean;
2
+ type FeatureFlags = string[] | Record<string, FeatureFlagValue>;
3
+ /**
4
+ * Normalizes feature flags from the two accepted input forms into a
5
+ * canonical `Record<string, string>` ready for the wire payload.
6
+ *
7
+ * - Array form: `["a", "b"]` → `{"a": "true", "b": "true"}`
8
+ * - Object form: `{ a: "v2", b: true, c: 3 }` → `{"a": "v2", "b": "true", "c": "3"}`
9
+ */
10
+ declare function normalizeFeatureFlags(input: FeatureFlags): Record<string, string>;
11
+
1
12
  type OtlpAnyValue = {
2
13
  stringValue?: string;
3
14
  intValue?: string;
@@ -53,6 +64,7 @@ type Patch = {
53
64
  output?: string;
54
65
  model?: string;
55
66
  properties?: Record<string, unknown>;
67
+ featureFlags?: Record<string, string>;
56
68
  attachments?: Attachment$1[];
57
69
  isPending?: boolean;
58
70
  timestamp?: string;
@@ -153,6 +165,7 @@ declare class EventShipper$1 {
153
165
  output?: string;
154
166
  model?: string;
155
167
  properties?: Record<string, unknown>;
168
+ featureFlags?: Record<string, string>;
156
169
  userId?: string;
157
170
  }): Promise<void>;
158
171
  flush(): Promise<void>;
@@ -416,6 +429,42 @@ declare class TraceShipper$1 {
416
429
  shutdown(): Promise<void>;
417
430
  }
418
431
 
432
+ /**
433
+ * Run telemetry egress with OpenTelemetry tracing suppressed.
434
+ *
435
+ * Why this exists
436
+ * ---------------
437
+ * Raindrop integrations ship spans/events over HTTP with the global `fetch`
438
+ * (see {@link ../http.ts `postJson`}). When the host app also runs an OTel
439
+ * fetch/undici instrumentation — e.g. `@vercel/otel`'s `registerOTel`, which
440
+ * every Eve agent installs — that instrumentation wraps *our own* telemetry
441
+ * POSTs in a `fetch POST <endpoint>` span. Those spans are then handed to the
442
+ * very exporter that issued the request, so they get shipped right back to
443
+ * Raindrop and Workshop as standalone "runs" (and, because each export issues
444
+ * another fetch, they feed back on themselves). The result is a run list
445
+ * flooded with `fetch POST .../v1/traces`, `.../events/track_partial` and
446
+ * `.../live` entries that drown out the real agent turns — especially with
447
+ * sub-agents, where every sandbox runs its own instrumentation.
448
+ *
449
+ * The OTel-blessed fix is to mark the active context as "tracing suppressed"
450
+ * around the request; instrumentations check `isTracingSuppressed` and return
451
+ * a no-op span instead of recording one. We do this through a hook stashed on
452
+ * `globalThis` by the Node entrypoint ({@link ../index.node.ts}) so that:
453
+ * - `@opentelemetry/api` / `@opentelemetry/core` stay *optional* — core never
454
+ * hard-depends on them, and the hook is simply absent when they (and thus
455
+ * any instrumentation to suppress) are not installed; and
456
+ * - the browser bundle never pulls in `node:module`, mirroring how core
457
+ * injects `AsyncLocalStorage` via `RAINDROP_ASYNC_LOCAL_STORAGE`.
458
+ *
459
+ * When no hook is present the callback runs unchanged, so suppression is a
460
+ * best-effort no-op rather than a hard requirement.
461
+ */
462
+ /** Hook signature: run `fn` with OTel tracing suppressed, returning its value. */
463
+ type SuppressTracingHook = <T>(fn: () => T) => T;
464
+ declare global {
465
+ var RAINDROP_SUPPRESS_TRACING: SuppressTracingHook | undefined;
466
+ }
467
+
419
468
  type ParentSpanContext = {
420
469
  traceIdB64: string;
421
470
  spanIdB64: string;
@@ -527,6 +576,7 @@ type RaindropTelemetryIntegrationOptions = {
527
576
  eventName?: string;
528
577
  convoId?: string;
529
578
  properties?: Record<string, unknown>;
579
+ featureFlags?: Record<string, string>;
530
580
  };
531
581
  };
532
582
  declare class RaindropTelemetryIntegration implements TelemetryIntegration {
@@ -803,6 +853,8 @@ type EventMetadataOptions = {
803
853
  eventName?: string;
804
854
  /** Additional properties to merge with wrap-time properties */
805
855
  properties?: Record<string, unknown>;
856
+ /** Feature flags to attach to this event (merged with wrap-time flags; call-time wins) */
857
+ featureFlags?: FeatureFlags;
806
858
  };
807
859
  /**
808
860
  * Creates metadata for use with the AI SDK's `experimental_telemetry.metadata` option.
@@ -1006,6 +1058,7 @@ type RaindropAISDKContext = {
1006
1058
  eventName?: string;
1007
1059
  convoId?: string;
1008
1060
  properties?: Record<string, unknown>;
1061
+ featureFlags?: FeatureFlags;
1009
1062
  attachments?: Attachment[];
1010
1063
  };
1011
1064
 
@@ -1015,6 +1068,7 @@ type BuildEventPatch = {
1015
1068
  output?: string;
1016
1069
  model?: string;
1017
1070
  properties?: Record<string, unknown>;
1071
+ featureFlags?: Record<string, string>;
1018
1072
  attachments?: Attachment[];
1019
1073
  };
1020
1074
  /**
@@ -1179,6 +1233,7 @@ type EventPatch = {
1179
1233
  output?: string;
1180
1234
  model?: string;
1181
1235
  properties?: Record<string, unknown>;
1236
+ featureFlags?: Record<string, string>;
1182
1237
  attachments?: Attachment[];
1183
1238
  isPending?: boolean;
1184
1239
  timestamp?: string;
@@ -1211,10 +1266,12 @@ type RaindropAISDKClient = {
1211
1266
  patch(eventId: string, patch: EventPatch): Promise<void>;
1212
1267
  addAttachments(eventId: string, attachments: Attachment[]): Promise<void>;
1213
1268
  setProperties(eventId: string, properties: Record<string, unknown>): Promise<void>;
1269
+ setFeatureFlags(eventId: string, featureFlags: FeatureFlags): Promise<void>;
1214
1270
  finish(eventId: string, patch: {
1215
1271
  output?: string;
1216
1272
  model?: string;
1217
1273
  properties?: Record<string, unknown>;
1274
+ featureFlags?: Record<string, string>;
1218
1275
  }): Promise<void>;
1219
1276
  };
1220
1277
  /**
@@ -1325,4 +1382,4 @@ type RaindropTelemetryOptions = RaindropAISDKOptions & {
1325
1382
  */
1326
1383
  declare function raindrop(options?: RaindropTelemetryOptions): RaindropTelemetryIntegration;
1327
1384
 
1328
- export { type AISDKChatRequestLike, type AISDKChatRequestMessageLike, type AISDKMessage, type AgentCallMetadata, type AgentWithMetadata, type Attachment, type BuildEventPatch, ContextManager, type ContextSpan, type CreateSpanArgs, DEFAULT_MAX_TEXT_FIELD_CHARS, DEFAULT_REDACT_ATTRIBUTE_KEYS, DEFAULT_SECRET_KEY_NAMES, type EndSpanArgs, type EventBuilder, type EventMetadataOptions, type IdentifyInput, type OtlpAnyValue, type OtlpSpan, type ParentToolContext, REDACTED_PLACEHOLDER, type RaindropAISDKClient, type RaindropAISDKContext, type RaindropAISDKOptions, type RaindropCallMetadata, RaindropTelemetryIntegration, type RaindropTelemetryIntegrationOptions, type RaindropTelemetryOptions, type SelfDiagnosticsOptions, type SelfDiagnosticsSignalDefinition, type SelfDiagnosticsSignalDefinitions, type SelfDiagnosticsTool, type SelfDiagnosticsToolInput, type SelfDiagnosticsToolOptions, type SelfDiagnosticsToolResult, type StartSpanArgs, TRUNCATION_MARKER, type TraceSpan, type TransformSpanHook, type WrapAISDKOptions, type WrappedAI, type WrappedAISDK, _resetParentToolContextStorage, _resetRaindropCallMetadataStorage, _resetWarnedMissingUserId, boundedStringify, capText, clearParentToolContext, createRaindropAISDK, currentSpan, defaultTransformSpan, enterParentToolContext, eventMetadata, eventMetadataFromChatRequest, getContextManager, getCurrentParentToolContext, getCurrentRaindropCallMetadata, raindrop, readRaindropCallMetadataFromArgs, redactJsonAttributeValue, redactSecretsInObject, runWithParentToolContext, runWithRaindropCallMetadata, withCurrent };
1385
+ export { type AISDKChatRequestLike, type AISDKChatRequestMessageLike, type AISDKMessage, type AgentCallMetadata, type AgentWithMetadata, type Attachment, type BuildEventPatch, ContextManager, type ContextSpan, type CreateSpanArgs, DEFAULT_MAX_TEXT_FIELD_CHARS, DEFAULT_REDACT_ATTRIBUTE_KEYS, DEFAULT_SECRET_KEY_NAMES, type EndSpanArgs, type EventBuilder, type EventMetadataOptions, type FeatureFlagValue, type FeatureFlags, type IdentifyInput, type OtlpAnyValue, type OtlpSpan, type ParentToolContext, REDACTED_PLACEHOLDER, type RaindropAISDKClient, type RaindropAISDKContext, type RaindropAISDKOptions, type RaindropCallMetadata, RaindropTelemetryIntegration, type RaindropTelemetryIntegrationOptions, type RaindropTelemetryOptions, type SelfDiagnosticsOptions, type SelfDiagnosticsSignalDefinition, type SelfDiagnosticsSignalDefinitions, type SelfDiagnosticsTool, type SelfDiagnosticsToolInput, type SelfDiagnosticsToolOptions, type SelfDiagnosticsToolResult, type StartSpanArgs, TRUNCATION_MARKER, type TraceSpan, type TransformSpanHook, type WrapAISDKOptions, type WrappedAI, type WrappedAISDK, _resetParentToolContextStorage, _resetRaindropCallMetadataStorage, _resetWarnedMissingUserId, boundedStringify, capText, clearParentToolContext, createRaindropAISDK, currentSpan, defaultTransformSpan, enterParentToolContext, eventMetadata, eventMetadataFromChatRequest, getContextManager, getCurrentParentToolContext, getCurrentRaindropCallMetadata, normalizeFeatureFlags, raindrop, readRaindropCallMetadataFromArgs, redactJsonAttributeValue, redactSecretsInObject, runWithParentToolContext, runWithRaindropCallMetadata, withCurrent };
@@ -1,3 +1,14 @@
1
+ type FeatureFlagValue = string | number | boolean;
2
+ type FeatureFlags = string[] | Record<string, FeatureFlagValue>;
3
+ /**
4
+ * Normalizes feature flags from the two accepted input forms into a
5
+ * canonical `Record<string, string>` ready for the wire payload.
6
+ *
7
+ * - Array form: `["a", "b"]` → `{"a": "true", "b": "true"}`
8
+ * - Object form: `{ a: "v2", b: true, c: 3 }` → `{"a": "v2", "b": "true", "c": "3"}`
9
+ */
10
+ declare function normalizeFeatureFlags(input: FeatureFlags): Record<string, string>;
11
+
1
12
  type OtlpAnyValue = {
2
13
  stringValue?: string;
3
14
  intValue?: string;
@@ -53,6 +64,7 @@ type Patch = {
53
64
  output?: string;
54
65
  model?: string;
55
66
  properties?: Record<string, unknown>;
67
+ featureFlags?: Record<string, string>;
56
68
  attachments?: Attachment$1[];
57
69
  isPending?: boolean;
58
70
  timestamp?: string;
@@ -153,6 +165,7 @@ declare class EventShipper$1 {
153
165
  output?: string;
154
166
  model?: string;
155
167
  properties?: Record<string, unknown>;
168
+ featureFlags?: Record<string, string>;
156
169
  userId?: string;
157
170
  }): Promise<void>;
158
171
  flush(): Promise<void>;
@@ -416,6 +429,42 @@ declare class TraceShipper$1 {
416
429
  shutdown(): Promise<void>;
417
430
  }
418
431
 
432
+ /**
433
+ * Run telemetry egress with OpenTelemetry tracing suppressed.
434
+ *
435
+ * Why this exists
436
+ * ---------------
437
+ * Raindrop integrations ship spans/events over HTTP with the global `fetch`
438
+ * (see {@link ../http.ts `postJson`}). When the host app also runs an OTel
439
+ * fetch/undici instrumentation — e.g. `@vercel/otel`'s `registerOTel`, which
440
+ * every Eve agent installs — that instrumentation wraps *our own* telemetry
441
+ * POSTs in a `fetch POST <endpoint>` span. Those spans are then handed to the
442
+ * very exporter that issued the request, so they get shipped right back to
443
+ * Raindrop and Workshop as standalone "runs" (and, because each export issues
444
+ * another fetch, they feed back on themselves). The result is a run list
445
+ * flooded with `fetch POST .../v1/traces`, `.../events/track_partial` and
446
+ * `.../live` entries that drown out the real agent turns — especially with
447
+ * sub-agents, where every sandbox runs its own instrumentation.
448
+ *
449
+ * The OTel-blessed fix is to mark the active context as "tracing suppressed"
450
+ * around the request; instrumentations check `isTracingSuppressed` and return
451
+ * a no-op span instead of recording one. We do this through a hook stashed on
452
+ * `globalThis` by the Node entrypoint ({@link ../index.node.ts}) so that:
453
+ * - `@opentelemetry/api` / `@opentelemetry/core` stay *optional* — core never
454
+ * hard-depends on them, and the hook is simply absent when they (and thus
455
+ * any instrumentation to suppress) are not installed; and
456
+ * - the browser bundle never pulls in `node:module`, mirroring how core
457
+ * injects `AsyncLocalStorage` via `RAINDROP_ASYNC_LOCAL_STORAGE`.
458
+ *
459
+ * When no hook is present the callback runs unchanged, so suppression is a
460
+ * best-effort no-op rather than a hard requirement.
461
+ */
462
+ /** Hook signature: run `fn` with OTel tracing suppressed, returning its value. */
463
+ type SuppressTracingHook = <T>(fn: () => T) => T;
464
+ declare global {
465
+ var RAINDROP_SUPPRESS_TRACING: SuppressTracingHook | undefined;
466
+ }
467
+
419
468
  type ParentSpanContext = {
420
469
  traceIdB64: string;
421
470
  spanIdB64: string;
@@ -527,6 +576,7 @@ type RaindropTelemetryIntegrationOptions = {
527
576
  eventName?: string;
528
577
  convoId?: string;
529
578
  properties?: Record<string, unknown>;
579
+ featureFlags?: Record<string, string>;
530
580
  };
531
581
  };
532
582
  declare class RaindropTelemetryIntegration implements TelemetryIntegration {
@@ -803,6 +853,8 @@ type EventMetadataOptions = {
803
853
  eventName?: string;
804
854
  /** Additional properties to merge with wrap-time properties */
805
855
  properties?: Record<string, unknown>;
856
+ /** Feature flags to attach to this event (merged with wrap-time flags; call-time wins) */
857
+ featureFlags?: FeatureFlags;
806
858
  };
807
859
  /**
808
860
  * Creates metadata for use with the AI SDK's `experimental_telemetry.metadata` option.
@@ -1006,6 +1058,7 @@ type RaindropAISDKContext = {
1006
1058
  eventName?: string;
1007
1059
  convoId?: string;
1008
1060
  properties?: Record<string, unknown>;
1061
+ featureFlags?: FeatureFlags;
1009
1062
  attachments?: Attachment[];
1010
1063
  };
1011
1064
 
@@ -1015,6 +1068,7 @@ type BuildEventPatch = {
1015
1068
  output?: string;
1016
1069
  model?: string;
1017
1070
  properties?: Record<string, unknown>;
1071
+ featureFlags?: Record<string, string>;
1018
1072
  attachments?: Attachment[];
1019
1073
  };
1020
1074
  /**
@@ -1179,6 +1233,7 @@ type EventPatch = {
1179
1233
  output?: string;
1180
1234
  model?: string;
1181
1235
  properties?: Record<string, unknown>;
1236
+ featureFlags?: Record<string, string>;
1182
1237
  attachments?: Attachment[];
1183
1238
  isPending?: boolean;
1184
1239
  timestamp?: string;
@@ -1211,10 +1266,12 @@ type RaindropAISDKClient = {
1211
1266
  patch(eventId: string, patch: EventPatch): Promise<void>;
1212
1267
  addAttachments(eventId: string, attachments: Attachment[]): Promise<void>;
1213
1268
  setProperties(eventId: string, properties: Record<string, unknown>): Promise<void>;
1269
+ setFeatureFlags(eventId: string, featureFlags: FeatureFlags): Promise<void>;
1214
1270
  finish(eventId: string, patch: {
1215
1271
  output?: string;
1216
1272
  model?: string;
1217
1273
  properties?: Record<string, unknown>;
1274
+ featureFlags?: Record<string, string>;
1218
1275
  }): Promise<void>;
1219
1276
  };
1220
1277
  /**
@@ -1325,4 +1382,4 @@ type RaindropTelemetryOptions = RaindropAISDKOptions & {
1325
1382
  */
1326
1383
  declare function raindrop(options?: RaindropTelemetryOptions): RaindropTelemetryIntegration;
1327
1384
 
1328
- export { type AISDKChatRequestLike, type AISDKChatRequestMessageLike, type AISDKMessage, type AgentCallMetadata, type AgentWithMetadata, type Attachment, type BuildEventPatch, ContextManager, type ContextSpan, type CreateSpanArgs, DEFAULT_MAX_TEXT_FIELD_CHARS, DEFAULT_REDACT_ATTRIBUTE_KEYS, DEFAULT_SECRET_KEY_NAMES, type EndSpanArgs, type EventBuilder, type EventMetadataOptions, type IdentifyInput, type OtlpAnyValue, type OtlpSpan, type ParentToolContext, REDACTED_PLACEHOLDER, type RaindropAISDKClient, type RaindropAISDKContext, type RaindropAISDKOptions, type RaindropCallMetadata, RaindropTelemetryIntegration, type RaindropTelemetryIntegrationOptions, type RaindropTelemetryOptions, type SelfDiagnosticsOptions, type SelfDiagnosticsSignalDefinition, type SelfDiagnosticsSignalDefinitions, type SelfDiagnosticsTool, type SelfDiagnosticsToolInput, type SelfDiagnosticsToolOptions, type SelfDiagnosticsToolResult, type StartSpanArgs, TRUNCATION_MARKER, type TraceSpan, type TransformSpanHook, type WrapAISDKOptions, type WrappedAI, type WrappedAISDK, _resetParentToolContextStorage, _resetRaindropCallMetadataStorage, _resetWarnedMissingUserId, boundedStringify, capText, clearParentToolContext, createRaindropAISDK, currentSpan, defaultTransformSpan, enterParentToolContext, eventMetadata, eventMetadataFromChatRequest, getContextManager, getCurrentParentToolContext, getCurrentRaindropCallMetadata, raindrop, readRaindropCallMetadataFromArgs, redactJsonAttributeValue, redactSecretsInObject, runWithParentToolContext, runWithRaindropCallMetadata, withCurrent };
1385
+ export { type AISDKChatRequestLike, type AISDKChatRequestMessageLike, type AISDKMessage, type AgentCallMetadata, type AgentWithMetadata, type Attachment, type BuildEventPatch, ContextManager, type ContextSpan, type CreateSpanArgs, DEFAULT_MAX_TEXT_FIELD_CHARS, DEFAULT_REDACT_ATTRIBUTE_KEYS, DEFAULT_SECRET_KEY_NAMES, type EndSpanArgs, type EventBuilder, type EventMetadataOptions, type FeatureFlagValue, type FeatureFlags, type IdentifyInput, type OtlpAnyValue, type OtlpSpan, type ParentToolContext, REDACTED_PLACEHOLDER, type RaindropAISDKClient, type RaindropAISDKContext, type RaindropAISDKOptions, type RaindropCallMetadata, RaindropTelemetryIntegration, type RaindropTelemetryIntegrationOptions, type RaindropTelemetryOptions, type SelfDiagnosticsOptions, type SelfDiagnosticsSignalDefinition, type SelfDiagnosticsSignalDefinitions, type SelfDiagnosticsTool, type SelfDiagnosticsToolInput, type SelfDiagnosticsToolOptions, type SelfDiagnosticsToolResult, type StartSpanArgs, TRUNCATION_MARKER, type TraceSpan, type TransformSpanHook, type WrapAISDKOptions, type WrappedAI, type WrappedAISDK, _resetParentToolContextStorage, _resetRaindropCallMetadataStorage, _resetWarnedMissingUserId, boundedStringify, capText, clearParentToolContext, createRaindropAISDK, currentSpan, defaultTransformSpan, enterParentToolContext, eventMetadata, eventMetadataFromChatRequest, getContextManager, getCurrentParentToolContext, getCurrentRaindropCallMetadata, normalizeFeatureFlags, raindrop, readRaindropCallMetadataFromArgs, redactJsonAttributeValue, redactSecretsInObject, runWithParentToolContext, runWithRaindropCallMetadata, withCurrent };
@@ -1,6 +1,14 @@
1
1
  'use strict';
2
2
 
3
- // ../core/dist/chunk-SK6EJEO7.js
3
+ // ../core/dist/chunk-Y5LUB7OE.js
4
+ function normalizeFeatureFlags(input) {
5
+ if (Array.isArray(input)) {
6
+ return Object.fromEntries(input.map((name) => [name, "true"]));
7
+ }
8
+ return Object.fromEntries(
9
+ Object.entries(input).map(([k, v]) => [k, String(v)])
10
+ );
11
+ }
4
12
  function getCrypto() {
5
13
  const c = globalThis.crypto;
6
14
  return c;
@@ -55,6 +63,20 @@ function base64Encode(bytes) {
55
63
  }
56
64
  return out;
57
65
  }
66
+ function runWithTracingSuppressed(fn) {
67
+ const hook = globalThis.RAINDROP_SUPPRESS_TRACING;
68
+ if (typeof hook !== "function") return fn();
69
+ let started = false;
70
+ try {
71
+ return hook(() => {
72
+ started = true;
73
+ return fn();
74
+ });
75
+ } catch (err) {
76
+ if (started) throw err;
77
+ return fn();
78
+ }
79
+ }
58
80
  var DEFAULT_REQUEST_TIMEOUT_MS = 3e4;
59
81
  var MAX_RETRY_DELAY_MS = 3e4;
60
82
  function wait(ms) {
@@ -165,15 +187,17 @@ async function postJson(url, body, headers, opts) {
165
187
  const timeoutMs = (_a = opts.timeoutMs) != null ? _a : DEFAULT_REQUEST_TIMEOUT_MS;
166
188
  await withRetry(
167
189
  async () => {
168
- const resp = await fetch(url, {
169
- method: "POST",
170
- headers: {
171
- "Content-Type": "application/json",
172
- ...headers
173
- },
174
- body: JSON.stringify(body),
175
- signal: AbortSignal.timeout(timeoutMs)
176
- });
190
+ const resp = await runWithTracingSuppressed(
191
+ () => fetch(url, {
192
+ method: "POST",
193
+ headers: {
194
+ "Content-Type": "application/json",
195
+ ...headers
196
+ },
197
+ body: JSON.stringify(body),
198
+ signal: AbortSignal.timeout(timeoutMs)
199
+ })
200
+ );
177
201
  if (!resp.ok) {
178
202
  const text = await resp.text().catch(() => "");
179
203
  const err = new Error(
@@ -419,13 +443,16 @@ function projectIdHeaders(projectId) {
419
443
  var SHUTDOWN_DEADLINE_MS = 1e4;
420
444
  var POST_SHUTDOWN_TIMEOUT_MS = 5e3;
421
445
  function mergePatches(target, source) {
422
- var _a, _b, _c, _d;
446
+ var _a, _b, _c, _d, _e, _f;
423
447
  const out = { ...target, ...source };
424
448
  if (target.properties || source.properties) {
425
449
  out.properties = { ...(_a = target.properties) != null ? _a : {}, ...(_b = source.properties) != null ? _b : {} };
426
450
  }
451
+ if (target.featureFlags || source.featureFlags) {
452
+ out.featureFlags = { ...(_c = target.featureFlags) != null ? _c : {}, ...(_d = source.featureFlags) != null ? _d : {} };
453
+ }
427
454
  if (target.attachments || source.attachments) {
428
- out.attachments = [...(_c = target.attachments) != null ? _c : [], ...(_d = source.attachments) != null ? _d : []];
455
+ out.attachments = [...(_e = target.attachments) != null ? _e : [], ...(_f = source.attachments) != null ? _f : []];
429
456
  }
430
457
  return out;
431
458
  }
@@ -695,6 +722,7 @@ var EventShipper = class {
695
722
  ...wizardSession ? { "raindrop.wizardSession": wizardSession } : {},
696
723
  $context: this.context
697
724
  },
725
+ ...accumulated.featureFlags && Object.keys(accumulated.featureFlags).length > 0 ? { feature_flags: accumulated.featureFlags } : {},
698
726
  attachments: accumulated.attachments,
699
727
  is_pending: isPending
700
728
  };
@@ -1283,7 +1311,7 @@ async function* asyncGeneratorWithCurrent(span, gen) {
1283
1311
  // package.json
1284
1312
  var package_default = {
1285
1313
  name: "@raindrop-ai/ai-sdk",
1286
- version: "0.0.40"};
1314
+ version: "0.1.0"};
1287
1315
 
1288
1316
  // src/internal/version.ts
1289
1317
  var libraryName = package_default.name;
@@ -2705,6 +2733,20 @@ var RaindropTelemetryIntegration = class {
2705
2733
  } else if (properties && typeof properties === "object") {
2706
2734
  result.properties = properties;
2707
2735
  }
2736
+ const featureFlags = metadata["raindrop.featureFlags"];
2737
+ if (typeof featureFlags === "string") {
2738
+ try {
2739
+ const parsed = JSON.parse(featureFlags);
2740
+ if (parsed && typeof parsed === "object") {
2741
+ result.featureFlags = normalizeFeatureFlags(parsed);
2742
+ }
2743
+ } catch (e) {
2744
+ }
2745
+ } else if (featureFlags && typeof featureFlags === "object") {
2746
+ result.featureFlags = normalizeFeatureFlags(
2747
+ featureFlags
2748
+ );
2749
+ }
2708
2750
  return result;
2709
2751
  }
2710
2752
  /**
@@ -2919,7 +2961,7 @@ var RaindropTelemetryIntegration = class {
2919
2961
  * same event ID into a separate canonical row.
2920
2962
  */
2921
2963
  finalizeGenerateEvent(state, output, model, keepPending = false) {
2922
- var _a, _b, _c, _d, _e, _f, _g, _h;
2964
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i;
2923
2965
  const suppressSubagentEvent = state.subagentName !== void 0 && state.subagentToolCallSpan !== void 0;
2924
2966
  if (!this.sendEvents || suppressSubagentEvent) return;
2925
2967
  const callMeta = this.extractRaindropMetadata(state.metadata);
@@ -2932,7 +2974,11 @@ var RaindropTelemetryIntegration = class {
2932
2974
  ...(_f = this.defaultContext) == null ? void 0 : _f.properties,
2933
2975
  ...callMeta.properties
2934
2976
  };
2935
- const convoId = (_h = callMeta.convoId) != null ? _h : (_g = this.defaultContext) == null ? void 0 : _g.convoId;
2977
+ const featureFlags = {
2978
+ ...(_g = this.defaultContext) == null ? void 0 : _g.featureFlags,
2979
+ ...callMeta.featureFlags
2980
+ };
2981
+ const convoId = (_i = callMeta.convoId) != null ? _i : (_h = this.defaultContext) == null ? void 0 : _h.convoId;
2936
2982
  void this.eventShipper.patch(state.eventId, {
2937
2983
  eventName,
2938
2984
  userId,
@@ -2941,6 +2987,7 @@ var RaindropTelemetryIntegration = class {
2941
2987
  output: cappedOutput,
2942
2988
  model,
2943
2989
  properties: Object.keys(properties).length > 0 ? properties : void 0,
2990
+ featureFlags: Object.keys(featureFlags).length > 0 ? featureFlags : void 0,
2944
2991
  isPending: keepPending
2945
2992
  }).catch((err) => {
2946
2993
  if (this.debug) {
@@ -3264,6 +3311,20 @@ function extractRaindropMetadata(metadata) {
3264
3311
  } else if (properties && typeof properties === "object") {
3265
3312
  result.properties = properties;
3266
3313
  }
3314
+ const featureFlags = metadata["raindrop.featureFlags"];
3315
+ if (typeof featureFlags === "string") {
3316
+ try {
3317
+ const parsed = JSON.parse(featureFlags);
3318
+ if (parsed && typeof parsed === "object") {
3319
+ result.featureFlags = normalizeFeatureFlags(parsed);
3320
+ }
3321
+ } catch (e) {
3322
+ }
3323
+ } else if (featureFlags && typeof featureFlags === "object") {
3324
+ result.featureFlags = normalizeFeatureFlags(
3325
+ featureFlags
3326
+ );
3327
+ }
3267
3328
  return result;
3268
3329
  }
3269
3330
  function mergeContexts(wrapTime, callTime) {
@@ -3278,6 +3339,10 @@ function mergeContexts(wrapTime, callTime) {
3278
3339
  ...callTime.properties
3279
3340
  };
3280
3341
  }
3342
+ if (callTime.featureFlags) {
3343
+ const wrapTimeFlags = wrapTime.featureFlags ? normalizeFeatureFlags(wrapTime.featureFlags) : {};
3344
+ result.featureFlags = { ...wrapTimeFlags, ...callTime.featureFlags };
3345
+ }
3281
3346
  return result;
3282
3347
  }
3283
3348
  function detectAISDKVersion(aiSDK) {
@@ -3590,6 +3655,7 @@ function createFinalize(params) {
3590
3655
  output: defaultOutput,
3591
3656
  model,
3592
3657
  properties: setup.ctx.properties,
3658
+ featureFlags: setup.ctx.featureFlags ? normalizeFeatureFlags(setup.ctx.featureFlags) : void 0,
3593
3659
  attachments: mergeAttachments(setup.ctx.attachments, inputAttachments, outputAttachments)
3594
3660
  };
3595
3661
  const built = await maybeBuildEvent(options.buildEvent, allMessages);
@@ -3643,6 +3709,7 @@ function createFinalize(params) {
3643
3709
  output,
3644
3710
  model: finalModel,
3645
3711
  properties: patch.properties,
3712
+ featureFlags: patch.featureFlags,
3646
3713
  attachments: patch.attachments,
3647
3714
  isPending: keepEventPending
3648
3715
  }).catch((err) => {
@@ -3874,7 +3941,8 @@ function wrapAISDK(aiSDK, deps) {
3874
3941
  eventId: wrapTimeCtx.eventId,
3875
3942
  eventName: wrapTimeCtx.eventName,
3876
3943
  convoId: wrapTimeCtx.convoId,
3877
- properties: wrapTimeCtx.properties
3944
+ properties: wrapTimeCtx.properties,
3945
+ featureFlags: wrapTimeCtx.featureFlags ? normalizeFeatureFlags(wrapTimeCtx.featureFlags) : void 0
3878
3946
  }
3879
3947
  });
3880
3948
  const registerFn = resolveRegisterTelemetry(aiSDK);
@@ -4150,6 +4218,7 @@ function wrapAgentGenerate(generate, instance, agentSettings, className, aiSDK,
4150
4218
  output: outputText,
4151
4219
  model,
4152
4220
  properties: ctx.properties,
4221
+ featureFlags: ctx.featureFlags ? normalizeFeatureFlags(ctx.featureFlags) : void 0,
4153
4222
  attachments: mergeAttachments(ctx.attachments, inputAttachments, outputAttachments)
4154
4223
  };
4155
4224
  const built = await maybeBuildEvent(deps.options.buildEvent, allMessages);
@@ -4217,6 +4286,7 @@ function wrapAgentGenerate(generate, instance, agentSettings, className, aiSDK,
4217
4286
  output,
4218
4287
  model: finalModel,
4219
4288
  properties: patch.properties,
4289
+ featureFlags: patch.featureFlags,
4220
4290
  attachments: patch.attachments,
4221
4291
  isPending: false
4222
4292
  }).catch((err) => {
@@ -4358,6 +4428,7 @@ function wrapAgentStream(stream, instance, agentSettings, className, aiSDK, deps
4358
4428
  output: outputText,
4359
4429
  model,
4360
4430
  properties: ctx.properties,
4431
+ featureFlags: ctx.featureFlags ? normalizeFeatureFlags(ctx.featureFlags) : void 0,
4361
4432
  attachments: mergeAttachments(ctx.attachments, inputAttachments, outputAttachments)
4362
4433
  };
4363
4434
  const built = await maybeBuildEvent(deps.options.buildEvent, allMessages);
@@ -4425,6 +4496,7 @@ function wrapAgentStream(stream, instance, agentSettings, className, aiSDK, deps
4425
4496
  output,
4426
4497
  model: finalModel,
4427
4498
  properties: patch.properties,
4499
+ featureFlags: patch.featureFlags,
4428
4500
  attachments: patch.attachments,
4429
4501
  isPending: false
4430
4502
  }).catch((err) => {
@@ -5022,7 +5094,7 @@ async function maybeBuildEvent(buildEvent, messages) {
5022
5094
  }
5023
5095
  }
5024
5096
  function mergeBuildEventPatch(defaults, override) {
5025
- var _a, _b, _c, _d, _e, _f, _g, _h;
5097
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j;
5026
5098
  if (!override) return defaults;
5027
5099
  return {
5028
5100
  eventName: (_a = override.eventName) != null ? _a : defaults.eventName,
@@ -5030,7 +5102,8 @@ function mergeBuildEventPatch(defaults, override) {
5030
5102
  output: (_c = override.output) != null ? _c : defaults.output,
5031
5103
  model: (_d = override.model) != null ? _d : defaults.model,
5032
5104
  properties: override.properties !== void 0 ? { ...(_e = defaults.properties) != null ? _e : {}, ...(_f = override.properties) != null ? _f : {} } : defaults.properties,
5033
- attachments: override.attachments !== void 0 ? [...(_g = defaults.attachments) != null ? _g : [], ...(_h = override.attachments) != null ? _h : []] : defaults.attachments
5105
+ featureFlags: override.featureFlags !== void 0 ? { ...(_g = defaults.featureFlags) != null ? _g : {}, ...(_h = override.featureFlags) != null ? _h : {} } : defaults.featureFlags,
5106
+ attachments: override.attachments !== void 0 ? [...(_i = defaults.attachments) != null ? _i : [], ...(_j = override.attachments) != null ? _j : []] : defaults.attachments
5034
5107
  };
5035
5108
  }
5036
5109
  function mergeAttachments(...groups) {
@@ -5061,6 +5134,8 @@ function eventMetadata(options) {
5061
5134
  if (options.convoId) result["raindrop.convoId"] = options.convoId;
5062
5135
  if (options.eventName) result["raindrop.eventName"] = options.eventName;
5063
5136
  if (options.properties) result["raindrop.properties"] = JSON.stringify(options.properties);
5137
+ if (options.featureFlags)
5138
+ result["raindrop.featureFlags"] = JSON.stringify(normalizeFeatureFlags(options.featureFlags));
5064
5139
  return result;
5065
5140
  }
5066
5141
  function deriveChatTurnMessageId(request) {
@@ -5165,7 +5240,8 @@ function createRaindropAISDK(opts) {
5165
5240
  "eventId",
5166
5241
  "eventName",
5167
5242
  "convoId",
5168
- "properties"
5243
+ "properties",
5244
+ "featureFlags"
5169
5245
  ];
5170
5246
  let context;
5171
5247
  let subagentWrapping;
@@ -5197,6 +5273,9 @@ function createRaindropAISDK(opts) {
5197
5273
  async setProperties(eventId, properties) {
5198
5274
  await eventShipper.patch(eventId, { properties });
5199
5275
  },
5276
+ async setFeatureFlags(eventId, featureFlags) {
5277
+ await eventShipper.patch(eventId, { featureFlags: normalizeFeatureFlags(featureFlags) });
5278
+ },
5200
5279
  async finish(eventId, patch) {
5201
5280
  await eventShipper.finish(eventId, patch);
5202
5281
  }
@@ -5318,6 +5397,7 @@ exports.eventMetadataFromChatRequest = eventMetadataFromChatRequest;
5318
5397
  exports.getContextManager = getContextManager;
5319
5398
  exports.getCurrentParentToolContext = getCurrentParentToolContext;
5320
5399
  exports.getCurrentRaindropCallMetadata = getCurrentRaindropCallMetadata;
5400
+ exports.normalizeFeatureFlags = normalizeFeatureFlags;
5321
5401
  exports.raindrop = raindrop;
5322
5402
  exports.readRaindropCallMetadataFromArgs = readRaindropCallMetadataFromArgs;
5323
5403
  exports.redactJsonAttributeValue = redactJsonAttributeValue;