@raindrop-ai/ai-sdk 0.0.29 → 0.0.31
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/dist/{chunk-QGI4SABN.mjs → chunk-7VSCLQIX.mjs} +188 -15
- package/dist/{index-DKdCelJA.d.mts → index-IMe7ZUXV.d.mts} +131 -2
- package/dist/{index-DKdCelJA.d.ts → index-IMe7ZUXV.d.ts} +131 -2
- package/dist/index.browser.d.mts +131 -2
- package/dist/index.browser.d.ts +131 -2
- package/dist/index.browser.js +192 -14
- package/dist/index.browser.mjs +188 -15
- package/dist/index.node.d.mts +1 -1
- package/dist/index.node.d.ts +1 -1
- package/dist/index.node.js +192 -14
- package/dist/index.node.mjs +1 -1
- package/dist/index.workers.d.mts +1 -1
- package/dist/index.workers.d.ts +1 -1
- package/dist/index.workers.js +192 -14
- package/dist/index.workers.mjs +1 -1
- package/package.json +2 -2
|
@@ -378,7 +378,9 @@ interface TelemetryIntegration {
|
|
|
378
378
|
onStepFinish?: Listener<any>;
|
|
379
379
|
onEmbedStart?: Listener<any>;
|
|
380
380
|
onEmbedFinish?: Listener<any>;
|
|
381
|
+
onEmbedEnd?: Listener<any>;
|
|
381
382
|
onFinish?: Listener<any>;
|
|
383
|
+
onEnd?: Listener<any>;
|
|
382
384
|
onError?: Listener<any>;
|
|
383
385
|
executeTool?: <T>(params: {
|
|
384
386
|
callId: string;
|
|
@@ -391,6 +393,19 @@ type RaindropTelemetryIntegrationOptions = {
|
|
|
391
393
|
eventShipper: EventShipper;
|
|
392
394
|
sendTraces?: boolean;
|
|
393
395
|
sendEvents?: boolean;
|
|
396
|
+
/**
|
|
397
|
+
* When `true` (default), generations started inside a tool's `execute`
|
|
398
|
+
* callback on the same async branch are wrapped in a synthetic `TOOL_CALL`
|
|
399
|
+
* + `agent.subagent` LLM marker so observability backends can render them
|
|
400
|
+
* as an agent block (and so the inner LLM's `track_partial` is suppressed).
|
|
401
|
+
*
|
|
402
|
+
* This is the right semantic for any framework that lowers sub-agents to
|
|
403
|
+
* AI SDK tools (Ash, Mastra, Claude Agent SDK, hand-rolled tool loops),
|
|
404
|
+
* not Ash-specific. Set to `false` if you have a tool whose `execute`
|
|
405
|
+
* happens to call `streamText`/`generateText` for unrelated reasons (e.g.
|
|
406
|
+
* RAG enrichment) and don't want it labelled as a sub-agent.
|
|
407
|
+
*/
|
|
408
|
+
subagentWrapping?: boolean;
|
|
394
409
|
debug?: boolean;
|
|
395
410
|
context?: {
|
|
396
411
|
userId?: string;
|
|
@@ -405,9 +420,26 @@ declare class RaindropTelemetryIntegration implements TelemetryIntegration {
|
|
|
405
420
|
private readonly eventShipper;
|
|
406
421
|
private readonly sendTraces;
|
|
407
422
|
private readonly sendEvents;
|
|
423
|
+
private readonly subagentWrapping;
|
|
408
424
|
private readonly debug;
|
|
409
425
|
private readonly defaultContext;
|
|
410
426
|
private readonly callStates;
|
|
427
|
+
/**
|
|
428
|
+
* Per-tool-call snapshot of the parent-tool ALS context taken right
|
|
429
|
+
* before `enterParentToolContext` overwrites it in `toolExecutionStart`.
|
|
430
|
+
* Kept at the integration level (rather than on `CallState`) so the
|
|
431
|
+
* snapshot survives even when the parent generation has no tracked
|
|
432
|
+
* `CallState` — e.g. the AI SDK dispatches a tool callback for a
|
|
433
|
+
* `callId` we never registered via `onStart`. Without this, the
|
|
434
|
+
* unconditional ALS enter in `toolExecutionStart` would leave
|
|
435
|
+
* `toolExecutionEnd` no way to restore the prior context, so it would
|
|
436
|
+
* clear and wipe whatever the outer scope had set.
|
|
437
|
+
*
|
|
438
|
+
* Keyed by `toolCallId` because that's the only identifier guaranteed
|
|
439
|
+
* to round-trip between `toolExecutionStart` and `toolExecutionEnd`
|
|
440
|
+
* (the `event.callId` can be the same for parallel sibling tools).
|
|
441
|
+
*/
|
|
442
|
+
private readonly priorParentContexts;
|
|
411
443
|
constructor(opts: RaindropTelemetryIntegrationOptions);
|
|
412
444
|
private getState;
|
|
413
445
|
private cleanup;
|
|
@@ -433,7 +465,9 @@ declare class RaindropTelemetryIntegration implements TelemetryIntegration {
|
|
|
433
465
|
onStepFinish: (event: any) => void;
|
|
434
466
|
onEmbedStart: (event: any) => void;
|
|
435
467
|
onEmbedFinish: (event: any) => void;
|
|
468
|
+
onEmbedEnd: (event: any) => void;
|
|
436
469
|
onFinish: (event: any) => void;
|
|
470
|
+
onEnd: (event: any) => void;
|
|
437
471
|
private finishGenerate;
|
|
438
472
|
private finishEmbed;
|
|
439
473
|
onError: (error: unknown) => void;
|
|
@@ -510,6 +544,92 @@ declare function readRaindropCallMetadataFromArgs(args: readonly unknown[]): Rai
|
|
|
510
544
|
|
|
511
545
|
declare function _resetWarnedMissingUserId(): void;
|
|
512
546
|
|
|
547
|
+
/**
|
|
548
|
+
* Parent tool execution context propagation.
|
|
549
|
+
*
|
|
550
|
+
* Problem
|
|
551
|
+
* ───────
|
|
552
|
+
* When a tool's `execute` callback recursively calls `streamText` /
|
|
553
|
+
* `generateText` (which is exactly how Ash lowers sub-agents, but also a
|
|
554
|
+
* common pattern in hand-rolled agent loops, Mastra, Claude Agent SDK,
|
|
555
|
+
* etc.), the inner generation's telemetry events are dispatched with no
|
|
556
|
+
* connection back to the outer tool call. The AI SDK fires `onStart` for
|
|
557
|
+
* the inner generation with its own fresh `callId`; nothing on the event
|
|
558
|
+
* tells the integration "this generation was triggered from inside tool
|
|
559
|
+
* X's execute callback."
|
|
560
|
+
*
|
|
561
|
+
* Without that linkage, observability tools have to fall back to
|
|
562
|
+
* regex-matching the prompt to guess whether a call is a sub-agent
|
|
563
|
+
* dispatch — fragile, framework-specific, and easily spoofable by user
|
|
564
|
+
* input.
|
|
565
|
+
*
|
|
566
|
+
* Solution
|
|
567
|
+
* ────────
|
|
568
|
+
* We maintain an `AsyncLocalStorage` slot that holds the currently-active
|
|
569
|
+
* parent tool call. The integration's `onToolExecutionStart` enters the
|
|
570
|
+
* slot before the AI SDK awaits `tool.execute(...)`; the inner
|
|
571
|
+
* generation's `onStart` reads from the slot to recover parent linkage.
|
|
572
|
+
* `onToolExecutionEnd` clears the slot so subsequent code in the same
|
|
573
|
+
* async branch doesn't see stale state.
|
|
574
|
+
*
|
|
575
|
+
* Async-context scoping
|
|
576
|
+
* ─────────────────────
|
|
577
|
+
* `enterWith` modifies the *current* async context, which propagates
|
|
578
|
+
* downward into any `await` continuation and into child async resources
|
|
579
|
+
* (including the awaited `tool.execute` and anything it calls). Sibling
|
|
580
|
+
* branches are unaffected: when the AI SDK dispatches tool calls via
|
|
581
|
+
* `Promise.all(map(async (tc) => ...))`, each map callback runs in its
|
|
582
|
+
* own async branch, so `enterWith` in one branch is invisible to the
|
|
583
|
+
* others. This is exactly the behaviour we need for parallel sub-agent
|
|
584
|
+
* dispatch.
|
|
585
|
+
*
|
|
586
|
+
* On runtimes that don't expose `AsyncLocalStorage` (browser, Cloudflare
|
|
587
|
+
* Workers without `nodejs_compat`), we fall back to a synchronous stack
|
|
588
|
+
* via `runWithParentToolContext` — see the `SyncFallbackStorage` in
|
|
589
|
+
* `call-metadata.ts` for the established pattern. `enterWith` becomes a
|
|
590
|
+
* silent no-op on the sync fallback, so async tool execution on those
|
|
591
|
+
* runtimes won't have parent linkage and the inner generation will
|
|
592
|
+
* render as a top-level call instead of being grouped under its caller.
|
|
593
|
+
*/
|
|
594
|
+
type ParentToolContext = {
|
|
595
|
+
/** The `callId` of the generation whose step kicked off this tool call. */
|
|
596
|
+
parentCallId: string;
|
|
597
|
+
/** The tool-call id from the parent generation's step. */
|
|
598
|
+
toolCallId: string;
|
|
599
|
+
/** The tool name the parent generation invoked. */
|
|
600
|
+
toolName: string;
|
|
601
|
+
};
|
|
602
|
+
/** Test helper — drop the storage so tests start from a fresh slot. */
|
|
603
|
+
declare function _resetParentToolContextStorage(): void;
|
|
604
|
+
/**
|
|
605
|
+
* Returns the active parent tool context, or `undefined` if no tool is
|
|
606
|
+
* currently executing in this async branch.
|
|
607
|
+
*/
|
|
608
|
+
declare function getCurrentParentToolContext(): ParentToolContext | undefined;
|
|
609
|
+
/**
|
|
610
|
+
* Enter a parent tool context on the current async branch. Subsequent
|
|
611
|
+
* `await`-ed work (including the parent's `tool.execute` body) inherits
|
|
612
|
+
* the context until {@link clearParentToolContext} runs. No-op on
|
|
613
|
+
* runtimes without `enterWith` support (browser/edge sync fallback).
|
|
614
|
+
*/
|
|
615
|
+
declare function enterParentToolContext(ctx: ParentToolContext): void;
|
|
616
|
+
/**
|
|
617
|
+
* Clear the parent tool context on the current async branch. Pairs with
|
|
618
|
+
* {@link enterParentToolContext}. No-op on runtimes without `enterWith`
|
|
619
|
+
* support.
|
|
620
|
+
*
|
|
621
|
+
* `enterWith(undefined)` is supported by Node's `AsyncLocalStorage` at
|
|
622
|
+
* runtime; the `as never` cast bypasses TypeScript's stricter typing on
|
|
623
|
+
* the shared global declaration (`store: T`).
|
|
624
|
+
*/
|
|
625
|
+
declare function clearParentToolContext(): void;
|
|
626
|
+
/**
|
|
627
|
+
* Run `fn` with `ctx` bound as the parent tool context. The sync-fallback
|
|
628
|
+
* equivalent of `enter`/`clear` — useful in tests and any code path
|
|
629
|
+
* where you want strict block scoping.
|
|
630
|
+
*/
|
|
631
|
+
declare function runWithParentToolContext<R>(ctx: ParentToolContext, fn: () => R): R;
|
|
632
|
+
|
|
513
633
|
/**
|
|
514
634
|
* Options for creating event metadata for call-time context override.
|
|
515
635
|
*/
|
|
@@ -860,8 +980,17 @@ type RaindropAISDKClient = {
|
|
|
860
980
|
/**
|
|
861
981
|
* Create a TelemetryIntegration instance for direct registration with AI SDK v7+.
|
|
862
982
|
* Use with `registerTelemetryIntegration()` from the `ai` package.
|
|
983
|
+
*
|
|
984
|
+
* Accepts the same `context` it has always accepted, or a full options
|
|
985
|
+
* object exposing `{ context, subagentWrapping }`. Sub-agent wrapping
|
|
986
|
+
* defaults to `true`; pass `subagentWrapping: false` to opt out for
|
|
987
|
+
* consumers whose `tool.execute` happens to call `generateText` for
|
|
988
|
+
* non-agentic reasons (e.g. RAG enrichment).
|
|
863
989
|
*/
|
|
864
|
-
createTelemetryIntegration(
|
|
990
|
+
createTelemetryIntegration(contextOrOptions?: RaindropTelemetryIntegrationOptions["context"] | {
|
|
991
|
+
context?: RaindropTelemetryIntegrationOptions["context"];
|
|
992
|
+
subagentWrapping?: boolean;
|
|
993
|
+
}): RaindropTelemetryIntegration;
|
|
865
994
|
events: {
|
|
866
995
|
patch(eventId: string, patch: EventPatch): Promise<void>;
|
|
867
996
|
addAttachments(eventId: string, attachments: Attachment[]): Promise<void>;
|
|
@@ -933,4 +1062,4 @@ type RaindropAISDKClient = {
|
|
|
933
1062
|
};
|
|
934
1063
|
declare function createRaindropAISDK(opts: RaindropAISDKOptions): RaindropAISDKClient;
|
|
935
1064
|
|
|
936
|
-
export { type AISDKChatRequestLike as A, type BuildEventPatch as B, ContextManager as C, DEFAULT_REDACT_ATTRIBUTE_KEYS as D, type EndSpanArgs as E,
|
|
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 };
|
package/dist/index.browser.d.mts
CHANGED
|
@@ -378,7 +378,9 @@ interface TelemetryIntegration {
|
|
|
378
378
|
onStepFinish?: Listener<any>;
|
|
379
379
|
onEmbedStart?: Listener<any>;
|
|
380
380
|
onEmbedFinish?: Listener<any>;
|
|
381
|
+
onEmbedEnd?: Listener<any>;
|
|
381
382
|
onFinish?: Listener<any>;
|
|
383
|
+
onEnd?: Listener<any>;
|
|
382
384
|
onError?: Listener<any>;
|
|
383
385
|
executeTool?: <T>(params: {
|
|
384
386
|
callId: string;
|
|
@@ -391,6 +393,19 @@ type RaindropTelemetryIntegrationOptions = {
|
|
|
391
393
|
eventShipper: EventShipper;
|
|
392
394
|
sendTraces?: boolean;
|
|
393
395
|
sendEvents?: boolean;
|
|
396
|
+
/**
|
|
397
|
+
* When `true` (default), generations started inside a tool's `execute`
|
|
398
|
+
* callback on the same async branch are wrapped in a synthetic `TOOL_CALL`
|
|
399
|
+
* + `agent.subagent` LLM marker so observability backends can render them
|
|
400
|
+
* as an agent block (and so the inner LLM's `track_partial` is suppressed).
|
|
401
|
+
*
|
|
402
|
+
* This is the right semantic for any framework that lowers sub-agents to
|
|
403
|
+
* AI SDK tools (Ash, Mastra, Claude Agent SDK, hand-rolled tool loops),
|
|
404
|
+
* not Ash-specific. Set to `false` if you have a tool whose `execute`
|
|
405
|
+
* happens to call `streamText`/`generateText` for unrelated reasons (e.g.
|
|
406
|
+
* RAG enrichment) and don't want it labelled as a sub-agent.
|
|
407
|
+
*/
|
|
408
|
+
subagentWrapping?: boolean;
|
|
394
409
|
debug?: boolean;
|
|
395
410
|
context?: {
|
|
396
411
|
userId?: string;
|
|
@@ -405,9 +420,26 @@ declare class RaindropTelemetryIntegration implements TelemetryIntegration {
|
|
|
405
420
|
private readonly eventShipper;
|
|
406
421
|
private readonly sendTraces;
|
|
407
422
|
private readonly sendEvents;
|
|
423
|
+
private readonly subagentWrapping;
|
|
408
424
|
private readonly debug;
|
|
409
425
|
private readonly defaultContext;
|
|
410
426
|
private readonly callStates;
|
|
427
|
+
/**
|
|
428
|
+
* Per-tool-call snapshot of the parent-tool ALS context taken right
|
|
429
|
+
* before `enterParentToolContext` overwrites it in `toolExecutionStart`.
|
|
430
|
+
* Kept at the integration level (rather than on `CallState`) so the
|
|
431
|
+
* snapshot survives even when the parent generation has no tracked
|
|
432
|
+
* `CallState` — e.g. the AI SDK dispatches a tool callback for a
|
|
433
|
+
* `callId` we never registered via `onStart`. Without this, the
|
|
434
|
+
* unconditional ALS enter in `toolExecutionStart` would leave
|
|
435
|
+
* `toolExecutionEnd` no way to restore the prior context, so it would
|
|
436
|
+
* clear and wipe whatever the outer scope had set.
|
|
437
|
+
*
|
|
438
|
+
* Keyed by `toolCallId` because that's the only identifier guaranteed
|
|
439
|
+
* to round-trip between `toolExecutionStart` and `toolExecutionEnd`
|
|
440
|
+
* (the `event.callId` can be the same for parallel sibling tools).
|
|
441
|
+
*/
|
|
442
|
+
private readonly priorParentContexts;
|
|
411
443
|
constructor(opts: RaindropTelemetryIntegrationOptions);
|
|
412
444
|
private getState;
|
|
413
445
|
private cleanup;
|
|
@@ -433,7 +465,9 @@ declare class RaindropTelemetryIntegration implements TelemetryIntegration {
|
|
|
433
465
|
onStepFinish: (event: any) => void;
|
|
434
466
|
onEmbedStart: (event: any) => void;
|
|
435
467
|
onEmbedFinish: (event: any) => void;
|
|
468
|
+
onEmbedEnd: (event: any) => void;
|
|
436
469
|
onFinish: (event: any) => void;
|
|
470
|
+
onEnd: (event: any) => void;
|
|
437
471
|
private finishGenerate;
|
|
438
472
|
private finishEmbed;
|
|
439
473
|
onError: (error: unknown) => void;
|
|
@@ -510,6 +544,92 @@ declare function readRaindropCallMetadataFromArgs(args: readonly unknown[]): Rai
|
|
|
510
544
|
|
|
511
545
|
declare function _resetWarnedMissingUserId(): void;
|
|
512
546
|
|
|
547
|
+
/**
|
|
548
|
+
* Parent tool execution context propagation.
|
|
549
|
+
*
|
|
550
|
+
* Problem
|
|
551
|
+
* ───────
|
|
552
|
+
* When a tool's `execute` callback recursively calls `streamText` /
|
|
553
|
+
* `generateText` (which is exactly how Ash lowers sub-agents, but also a
|
|
554
|
+
* common pattern in hand-rolled agent loops, Mastra, Claude Agent SDK,
|
|
555
|
+
* etc.), the inner generation's telemetry events are dispatched with no
|
|
556
|
+
* connection back to the outer tool call. The AI SDK fires `onStart` for
|
|
557
|
+
* the inner generation with its own fresh `callId`; nothing on the event
|
|
558
|
+
* tells the integration "this generation was triggered from inside tool
|
|
559
|
+
* X's execute callback."
|
|
560
|
+
*
|
|
561
|
+
* Without that linkage, observability tools have to fall back to
|
|
562
|
+
* regex-matching the prompt to guess whether a call is a sub-agent
|
|
563
|
+
* dispatch — fragile, framework-specific, and easily spoofable by user
|
|
564
|
+
* input.
|
|
565
|
+
*
|
|
566
|
+
* Solution
|
|
567
|
+
* ────────
|
|
568
|
+
* We maintain an `AsyncLocalStorage` slot that holds the currently-active
|
|
569
|
+
* parent tool call. The integration's `onToolExecutionStart` enters the
|
|
570
|
+
* slot before the AI SDK awaits `tool.execute(...)`; the inner
|
|
571
|
+
* generation's `onStart` reads from the slot to recover parent linkage.
|
|
572
|
+
* `onToolExecutionEnd` clears the slot so subsequent code in the same
|
|
573
|
+
* async branch doesn't see stale state.
|
|
574
|
+
*
|
|
575
|
+
* Async-context scoping
|
|
576
|
+
* ─────────────────────
|
|
577
|
+
* `enterWith` modifies the *current* async context, which propagates
|
|
578
|
+
* downward into any `await` continuation and into child async resources
|
|
579
|
+
* (including the awaited `tool.execute` and anything it calls). Sibling
|
|
580
|
+
* branches are unaffected: when the AI SDK dispatches tool calls via
|
|
581
|
+
* `Promise.all(map(async (tc) => ...))`, each map callback runs in its
|
|
582
|
+
* own async branch, so `enterWith` in one branch is invisible to the
|
|
583
|
+
* others. This is exactly the behaviour we need for parallel sub-agent
|
|
584
|
+
* dispatch.
|
|
585
|
+
*
|
|
586
|
+
* On runtimes that don't expose `AsyncLocalStorage` (browser, Cloudflare
|
|
587
|
+
* Workers without `nodejs_compat`), we fall back to a synchronous stack
|
|
588
|
+
* via `runWithParentToolContext` — see the `SyncFallbackStorage` in
|
|
589
|
+
* `call-metadata.ts` for the established pattern. `enterWith` becomes a
|
|
590
|
+
* silent no-op on the sync fallback, so async tool execution on those
|
|
591
|
+
* runtimes won't have parent linkage and the inner generation will
|
|
592
|
+
* render as a top-level call instead of being grouped under its caller.
|
|
593
|
+
*/
|
|
594
|
+
type ParentToolContext = {
|
|
595
|
+
/** The `callId` of the generation whose step kicked off this tool call. */
|
|
596
|
+
parentCallId: string;
|
|
597
|
+
/** The tool-call id from the parent generation's step. */
|
|
598
|
+
toolCallId: string;
|
|
599
|
+
/** The tool name the parent generation invoked. */
|
|
600
|
+
toolName: string;
|
|
601
|
+
};
|
|
602
|
+
/** Test helper — drop the storage so tests start from a fresh slot. */
|
|
603
|
+
declare function _resetParentToolContextStorage(): void;
|
|
604
|
+
/**
|
|
605
|
+
* Returns the active parent tool context, or `undefined` if no tool is
|
|
606
|
+
* currently executing in this async branch.
|
|
607
|
+
*/
|
|
608
|
+
declare function getCurrentParentToolContext(): ParentToolContext | undefined;
|
|
609
|
+
/**
|
|
610
|
+
* Enter a parent tool context on the current async branch. Subsequent
|
|
611
|
+
* `await`-ed work (including the parent's `tool.execute` body) inherits
|
|
612
|
+
* the context until {@link clearParentToolContext} runs. No-op on
|
|
613
|
+
* runtimes without `enterWith` support (browser/edge sync fallback).
|
|
614
|
+
*/
|
|
615
|
+
declare function enterParentToolContext(ctx: ParentToolContext): void;
|
|
616
|
+
/**
|
|
617
|
+
* Clear the parent tool context on the current async branch. Pairs with
|
|
618
|
+
* {@link enterParentToolContext}. No-op on runtimes without `enterWith`
|
|
619
|
+
* support.
|
|
620
|
+
*
|
|
621
|
+
* `enterWith(undefined)` is supported by Node's `AsyncLocalStorage` at
|
|
622
|
+
* runtime; the `as never` cast bypasses TypeScript's stricter typing on
|
|
623
|
+
* the shared global declaration (`store: T`).
|
|
624
|
+
*/
|
|
625
|
+
declare function clearParentToolContext(): void;
|
|
626
|
+
/**
|
|
627
|
+
* Run `fn` with `ctx` bound as the parent tool context. The sync-fallback
|
|
628
|
+
* equivalent of `enter`/`clear` — useful in tests and any code path
|
|
629
|
+
* where you want strict block scoping.
|
|
630
|
+
*/
|
|
631
|
+
declare function runWithParentToolContext<R>(ctx: ParentToolContext, fn: () => R): R;
|
|
632
|
+
|
|
513
633
|
/**
|
|
514
634
|
* Options for creating event metadata for call-time context override.
|
|
515
635
|
*/
|
|
@@ -860,8 +980,17 @@ type RaindropAISDKClient = {
|
|
|
860
980
|
/**
|
|
861
981
|
* Create a TelemetryIntegration instance for direct registration with AI SDK v7+.
|
|
862
982
|
* Use with `registerTelemetryIntegration()` from the `ai` package.
|
|
983
|
+
*
|
|
984
|
+
* Accepts the same `context` it has always accepted, or a full options
|
|
985
|
+
* object exposing `{ context, subagentWrapping }`. Sub-agent wrapping
|
|
986
|
+
* defaults to `true`; pass `subagentWrapping: false` to opt out for
|
|
987
|
+
* consumers whose `tool.execute` happens to call `generateText` for
|
|
988
|
+
* non-agentic reasons (e.g. RAG enrichment).
|
|
863
989
|
*/
|
|
864
|
-
createTelemetryIntegration(
|
|
990
|
+
createTelemetryIntegration(contextOrOptions?: RaindropTelemetryIntegrationOptions["context"] | {
|
|
991
|
+
context?: RaindropTelemetryIntegrationOptions["context"];
|
|
992
|
+
subagentWrapping?: boolean;
|
|
993
|
+
}): RaindropTelemetryIntegration;
|
|
865
994
|
events: {
|
|
866
995
|
patch(eventId: string, patch: EventPatch): Promise<void>;
|
|
867
996
|
addAttachments(eventId: string, attachments: Attachment[]): Promise<void>;
|
|
@@ -933,4 +1062,4 @@ type RaindropAISDKClient = {
|
|
|
933
1062
|
};
|
|
934
1063
|
declare function createRaindropAISDK(opts: RaindropAISDKOptions): RaindropAISDKClient;
|
|
935
1064
|
|
|
936
|
-
export { type AISDKChatRequestLike, type AISDKChatRequestMessageLike, type AISDKMessage, type AgentCallMetadata, type AgentWithMetadata, type Attachment, type BuildEventPatch, ContextManager, type ContextSpan, type CreateSpanArgs, DEFAULT_REDACT_ATTRIBUTE_KEYS, DEFAULT_SECRET_KEY_NAMES, type EndSpanArgs, type EventBuilder, type EventMetadataOptions, type IdentifyInput, type OtlpAnyValue, type OtlpSpan, REDACTED_PLACEHOLDER, type RaindropAISDKClient, type RaindropAISDKContext, type RaindropAISDKOptions, type RaindropCallMetadata, RaindropTelemetryIntegration, type RaindropTelemetryIntegrationOptions, type SelfDiagnosticsOptions, type SelfDiagnosticsSignalDefinition, type SelfDiagnosticsSignalDefinitions, type StartSpanArgs, type TraceSpan, type TransformSpanHook, type WrapAISDKOptions, type WrappedAI, type WrappedAISDK, _resetRaindropCallMetadataStorage, _resetWarnedMissingUserId, createRaindropAISDK, currentSpan, defaultTransformSpan, eventMetadata, eventMetadataFromChatRequest, getContextManager, getCurrentRaindropCallMetadata, readRaindropCallMetadataFromArgs, redactJsonAttributeValue, redactSecretsInObject, runWithRaindropCallMetadata, withCurrent };
|
|
1065
|
+
export { type AISDKChatRequestLike, type AISDKChatRequestMessageLike, type AISDKMessage, type AgentCallMetadata, type AgentWithMetadata, type Attachment, type BuildEventPatch, ContextManager, type ContextSpan, type CreateSpanArgs, 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 SelfDiagnosticsOptions, type SelfDiagnosticsSignalDefinition, type SelfDiagnosticsSignalDefinitions, type StartSpanArgs, type TraceSpan, type TransformSpanHook, type WrapAISDKOptions, type WrappedAI, type WrappedAISDK, _resetParentToolContextStorage, _resetRaindropCallMetadataStorage, _resetWarnedMissingUserId, clearParentToolContext, createRaindropAISDK, currentSpan, defaultTransformSpan, enterParentToolContext, eventMetadata, eventMetadataFromChatRequest, getContextManager, getCurrentParentToolContext, getCurrentRaindropCallMetadata, readRaindropCallMetadataFromArgs, redactJsonAttributeValue, redactSecretsInObject, runWithParentToolContext, runWithRaindropCallMetadata, withCurrent };
|
package/dist/index.browser.d.ts
CHANGED
|
@@ -378,7 +378,9 @@ interface TelemetryIntegration {
|
|
|
378
378
|
onStepFinish?: Listener<any>;
|
|
379
379
|
onEmbedStart?: Listener<any>;
|
|
380
380
|
onEmbedFinish?: Listener<any>;
|
|
381
|
+
onEmbedEnd?: Listener<any>;
|
|
381
382
|
onFinish?: Listener<any>;
|
|
383
|
+
onEnd?: Listener<any>;
|
|
382
384
|
onError?: Listener<any>;
|
|
383
385
|
executeTool?: <T>(params: {
|
|
384
386
|
callId: string;
|
|
@@ -391,6 +393,19 @@ type RaindropTelemetryIntegrationOptions = {
|
|
|
391
393
|
eventShipper: EventShipper;
|
|
392
394
|
sendTraces?: boolean;
|
|
393
395
|
sendEvents?: boolean;
|
|
396
|
+
/**
|
|
397
|
+
* When `true` (default), generations started inside a tool's `execute`
|
|
398
|
+
* callback on the same async branch are wrapped in a synthetic `TOOL_CALL`
|
|
399
|
+
* + `agent.subagent` LLM marker so observability backends can render them
|
|
400
|
+
* as an agent block (and so the inner LLM's `track_partial` is suppressed).
|
|
401
|
+
*
|
|
402
|
+
* This is the right semantic for any framework that lowers sub-agents to
|
|
403
|
+
* AI SDK tools (Ash, Mastra, Claude Agent SDK, hand-rolled tool loops),
|
|
404
|
+
* not Ash-specific. Set to `false` if you have a tool whose `execute`
|
|
405
|
+
* happens to call `streamText`/`generateText` for unrelated reasons (e.g.
|
|
406
|
+
* RAG enrichment) and don't want it labelled as a sub-agent.
|
|
407
|
+
*/
|
|
408
|
+
subagentWrapping?: boolean;
|
|
394
409
|
debug?: boolean;
|
|
395
410
|
context?: {
|
|
396
411
|
userId?: string;
|
|
@@ -405,9 +420,26 @@ declare class RaindropTelemetryIntegration implements TelemetryIntegration {
|
|
|
405
420
|
private readonly eventShipper;
|
|
406
421
|
private readonly sendTraces;
|
|
407
422
|
private readonly sendEvents;
|
|
423
|
+
private readonly subagentWrapping;
|
|
408
424
|
private readonly debug;
|
|
409
425
|
private readonly defaultContext;
|
|
410
426
|
private readonly callStates;
|
|
427
|
+
/**
|
|
428
|
+
* Per-tool-call snapshot of the parent-tool ALS context taken right
|
|
429
|
+
* before `enterParentToolContext` overwrites it in `toolExecutionStart`.
|
|
430
|
+
* Kept at the integration level (rather than on `CallState`) so the
|
|
431
|
+
* snapshot survives even when the parent generation has no tracked
|
|
432
|
+
* `CallState` — e.g. the AI SDK dispatches a tool callback for a
|
|
433
|
+
* `callId` we never registered via `onStart`. Without this, the
|
|
434
|
+
* unconditional ALS enter in `toolExecutionStart` would leave
|
|
435
|
+
* `toolExecutionEnd` no way to restore the prior context, so it would
|
|
436
|
+
* clear and wipe whatever the outer scope had set.
|
|
437
|
+
*
|
|
438
|
+
* Keyed by `toolCallId` because that's the only identifier guaranteed
|
|
439
|
+
* to round-trip between `toolExecutionStart` and `toolExecutionEnd`
|
|
440
|
+
* (the `event.callId` can be the same for parallel sibling tools).
|
|
441
|
+
*/
|
|
442
|
+
private readonly priorParentContexts;
|
|
411
443
|
constructor(opts: RaindropTelemetryIntegrationOptions);
|
|
412
444
|
private getState;
|
|
413
445
|
private cleanup;
|
|
@@ -433,7 +465,9 @@ declare class RaindropTelemetryIntegration implements TelemetryIntegration {
|
|
|
433
465
|
onStepFinish: (event: any) => void;
|
|
434
466
|
onEmbedStart: (event: any) => void;
|
|
435
467
|
onEmbedFinish: (event: any) => void;
|
|
468
|
+
onEmbedEnd: (event: any) => void;
|
|
436
469
|
onFinish: (event: any) => void;
|
|
470
|
+
onEnd: (event: any) => void;
|
|
437
471
|
private finishGenerate;
|
|
438
472
|
private finishEmbed;
|
|
439
473
|
onError: (error: unknown) => void;
|
|
@@ -510,6 +544,92 @@ declare function readRaindropCallMetadataFromArgs(args: readonly unknown[]): Rai
|
|
|
510
544
|
|
|
511
545
|
declare function _resetWarnedMissingUserId(): void;
|
|
512
546
|
|
|
547
|
+
/**
|
|
548
|
+
* Parent tool execution context propagation.
|
|
549
|
+
*
|
|
550
|
+
* Problem
|
|
551
|
+
* ───────
|
|
552
|
+
* When a tool's `execute` callback recursively calls `streamText` /
|
|
553
|
+
* `generateText` (which is exactly how Ash lowers sub-agents, but also a
|
|
554
|
+
* common pattern in hand-rolled agent loops, Mastra, Claude Agent SDK,
|
|
555
|
+
* etc.), the inner generation's telemetry events are dispatched with no
|
|
556
|
+
* connection back to the outer tool call. The AI SDK fires `onStart` for
|
|
557
|
+
* the inner generation with its own fresh `callId`; nothing on the event
|
|
558
|
+
* tells the integration "this generation was triggered from inside tool
|
|
559
|
+
* X's execute callback."
|
|
560
|
+
*
|
|
561
|
+
* Without that linkage, observability tools have to fall back to
|
|
562
|
+
* regex-matching the prompt to guess whether a call is a sub-agent
|
|
563
|
+
* dispatch — fragile, framework-specific, and easily spoofable by user
|
|
564
|
+
* input.
|
|
565
|
+
*
|
|
566
|
+
* Solution
|
|
567
|
+
* ────────
|
|
568
|
+
* We maintain an `AsyncLocalStorage` slot that holds the currently-active
|
|
569
|
+
* parent tool call. The integration's `onToolExecutionStart` enters the
|
|
570
|
+
* slot before the AI SDK awaits `tool.execute(...)`; the inner
|
|
571
|
+
* generation's `onStart` reads from the slot to recover parent linkage.
|
|
572
|
+
* `onToolExecutionEnd` clears the slot so subsequent code in the same
|
|
573
|
+
* async branch doesn't see stale state.
|
|
574
|
+
*
|
|
575
|
+
* Async-context scoping
|
|
576
|
+
* ─────────────────────
|
|
577
|
+
* `enterWith` modifies the *current* async context, which propagates
|
|
578
|
+
* downward into any `await` continuation and into child async resources
|
|
579
|
+
* (including the awaited `tool.execute` and anything it calls). Sibling
|
|
580
|
+
* branches are unaffected: when the AI SDK dispatches tool calls via
|
|
581
|
+
* `Promise.all(map(async (tc) => ...))`, each map callback runs in its
|
|
582
|
+
* own async branch, so `enterWith` in one branch is invisible to the
|
|
583
|
+
* others. This is exactly the behaviour we need for parallel sub-agent
|
|
584
|
+
* dispatch.
|
|
585
|
+
*
|
|
586
|
+
* On runtimes that don't expose `AsyncLocalStorage` (browser, Cloudflare
|
|
587
|
+
* Workers without `nodejs_compat`), we fall back to a synchronous stack
|
|
588
|
+
* via `runWithParentToolContext` — see the `SyncFallbackStorage` in
|
|
589
|
+
* `call-metadata.ts` for the established pattern. `enterWith` becomes a
|
|
590
|
+
* silent no-op on the sync fallback, so async tool execution on those
|
|
591
|
+
* runtimes won't have parent linkage and the inner generation will
|
|
592
|
+
* render as a top-level call instead of being grouped under its caller.
|
|
593
|
+
*/
|
|
594
|
+
type ParentToolContext = {
|
|
595
|
+
/** The `callId` of the generation whose step kicked off this tool call. */
|
|
596
|
+
parentCallId: string;
|
|
597
|
+
/** The tool-call id from the parent generation's step. */
|
|
598
|
+
toolCallId: string;
|
|
599
|
+
/** The tool name the parent generation invoked. */
|
|
600
|
+
toolName: string;
|
|
601
|
+
};
|
|
602
|
+
/** Test helper — drop the storage so tests start from a fresh slot. */
|
|
603
|
+
declare function _resetParentToolContextStorage(): void;
|
|
604
|
+
/**
|
|
605
|
+
* Returns the active parent tool context, or `undefined` if no tool is
|
|
606
|
+
* currently executing in this async branch.
|
|
607
|
+
*/
|
|
608
|
+
declare function getCurrentParentToolContext(): ParentToolContext | undefined;
|
|
609
|
+
/**
|
|
610
|
+
* Enter a parent tool context on the current async branch. Subsequent
|
|
611
|
+
* `await`-ed work (including the parent's `tool.execute` body) inherits
|
|
612
|
+
* the context until {@link clearParentToolContext} runs. No-op on
|
|
613
|
+
* runtimes without `enterWith` support (browser/edge sync fallback).
|
|
614
|
+
*/
|
|
615
|
+
declare function enterParentToolContext(ctx: ParentToolContext): void;
|
|
616
|
+
/**
|
|
617
|
+
* Clear the parent tool context on the current async branch. Pairs with
|
|
618
|
+
* {@link enterParentToolContext}. No-op on runtimes without `enterWith`
|
|
619
|
+
* support.
|
|
620
|
+
*
|
|
621
|
+
* `enterWith(undefined)` is supported by Node's `AsyncLocalStorage` at
|
|
622
|
+
* runtime; the `as never` cast bypasses TypeScript's stricter typing on
|
|
623
|
+
* the shared global declaration (`store: T`).
|
|
624
|
+
*/
|
|
625
|
+
declare function clearParentToolContext(): void;
|
|
626
|
+
/**
|
|
627
|
+
* Run `fn` with `ctx` bound as the parent tool context. The sync-fallback
|
|
628
|
+
* equivalent of `enter`/`clear` — useful in tests and any code path
|
|
629
|
+
* where you want strict block scoping.
|
|
630
|
+
*/
|
|
631
|
+
declare function runWithParentToolContext<R>(ctx: ParentToolContext, fn: () => R): R;
|
|
632
|
+
|
|
513
633
|
/**
|
|
514
634
|
* Options for creating event metadata for call-time context override.
|
|
515
635
|
*/
|
|
@@ -860,8 +980,17 @@ type RaindropAISDKClient = {
|
|
|
860
980
|
/**
|
|
861
981
|
* Create a TelemetryIntegration instance for direct registration with AI SDK v7+.
|
|
862
982
|
* Use with `registerTelemetryIntegration()` from the `ai` package.
|
|
983
|
+
*
|
|
984
|
+
* Accepts the same `context` it has always accepted, or a full options
|
|
985
|
+
* object exposing `{ context, subagentWrapping }`. Sub-agent wrapping
|
|
986
|
+
* defaults to `true`; pass `subagentWrapping: false` to opt out for
|
|
987
|
+
* consumers whose `tool.execute` happens to call `generateText` for
|
|
988
|
+
* non-agentic reasons (e.g. RAG enrichment).
|
|
863
989
|
*/
|
|
864
|
-
createTelemetryIntegration(
|
|
990
|
+
createTelemetryIntegration(contextOrOptions?: RaindropTelemetryIntegrationOptions["context"] | {
|
|
991
|
+
context?: RaindropTelemetryIntegrationOptions["context"];
|
|
992
|
+
subagentWrapping?: boolean;
|
|
993
|
+
}): RaindropTelemetryIntegration;
|
|
865
994
|
events: {
|
|
866
995
|
patch(eventId: string, patch: EventPatch): Promise<void>;
|
|
867
996
|
addAttachments(eventId: string, attachments: Attachment[]): Promise<void>;
|
|
@@ -933,4 +1062,4 @@ type RaindropAISDKClient = {
|
|
|
933
1062
|
};
|
|
934
1063
|
declare function createRaindropAISDK(opts: RaindropAISDKOptions): RaindropAISDKClient;
|
|
935
1064
|
|
|
936
|
-
export { type AISDKChatRequestLike, type AISDKChatRequestMessageLike, type AISDKMessage, type AgentCallMetadata, type AgentWithMetadata, type Attachment, type BuildEventPatch, ContextManager, type ContextSpan, type CreateSpanArgs, DEFAULT_REDACT_ATTRIBUTE_KEYS, DEFAULT_SECRET_KEY_NAMES, type EndSpanArgs, type EventBuilder, type EventMetadataOptions, type IdentifyInput, type OtlpAnyValue, type OtlpSpan, REDACTED_PLACEHOLDER, type RaindropAISDKClient, type RaindropAISDKContext, type RaindropAISDKOptions, type RaindropCallMetadata, RaindropTelemetryIntegration, type RaindropTelemetryIntegrationOptions, type SelfDiagnosticsOptions, type SelfDiagnosticsSignalDefinition, type SelfDiagnosticsSignalDefinitions, type StartSpanArgs, type TraceSpan, type TransformSpanHook, type WrapAISDKOptions, type WrappedAI, type WrappedAISDK, _resetRaindropCallMetadataStorage, _resetWarnedMissingUserId, createRaindropAISDK, currentSpan, defaultTransformSpan, eventMetadata, eventMetadataFromChatRequest, getContextManager, getCurrentRaindropCallMetadata, readRaindropCallMetadataFromArgs, redactJsonAttributeValue, redactSecretsInObject, runWithRaindropCallMetadata, withCurrent };
|
|
1065
|
+
export { type AISDKChatRequestLike, type AISDKChatRequestMessageLike, type AISDKMessage, type AgentCallMetadata, type AgentWithMetadata, type Attachment, type BuildEventPatch, ContextManager, type ContextSpan, type CreateSpanArgs, 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 SelfDiagnosticsOptions, type SelfDiagnosticsSignalDefinition, type SelfDiagnosticsSignalDefinitions, type StartSpanArgs, type TraceSpan, type TransformSpanHook, type WrapAISDKOptions, type WrappedAI, type WrappedAISDK, _resetParentToolContextStorage, _resetRaindropCallMetadataStorage, _resetWarnedMissingUserId, clearParentToolContext, createRaindropAISDK, currentSpan, defaultTransformSpan, enterParentToolContext, eventMetadata, eventMetadataFromChatRequest, getContextManager, getCurrentParentToolContext, getCurrentRaindropCallMetadata, readRaindropCallMetadataFromArgs, redactJsonAttributeValue, redactSecretsInObject, runWithParentToolContext, runWithRaindropCallMetadata, withCurrent };
|