@sentry/cloudflare 10.69.0 → 10.70.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.
- package/build/cjs/durableobject.js +114 -36
- package/build/cjs/durableobject.js.map +1 -1
- package/build/cjs/flush.js.map +1 -1
- package/build/cjs/instrumentations/agents/index.js +2 -0
- package/build/cjs/instrumentations/agents/index.js.map +1 -1
- package/build/cjs/instrumentations/agents/instrumentAgentCallableRpc.js +2 -2
- package/build/cjs/instrumentations/agents/instrumentAgentCallableRpc.js.map +1 -1
- package/build/cjs/instrumentations/agents/instrumentAgentRequestConversation.js +19 -0
- package/build/cjs/instrumentations/agents/instrumentAgentRequestConversation.js.map +1 -0
- package/build/cjs/instrumentations/agents/instrumentChatAgentConversation.js +3 -3
- package/build/cjs/instrumentations/agents/instrumentChatAgentConversation.js.map +1 -1
- package/build/cjs/instrumentations/agents/types.js +58 -13
- package/build/cjs/instrumentations/agents/types.js.map +1 -1
- package/build/cjs/request.js +3 -2
- package/build/cjs/request.js.map +1 -1
- package/build/cjs/utils/invocationScope.js +12 -0
- package/build/cjs/utils/invocationScope.js.map +1 -0
- package/build/cjs/utils/rpcMeta.js +4 -0
- package/build/cjs/utils/rpcMeta.js.map +1 -1
- package/build/cjs/workflows.js +1 -1
- package/build/cjs/workflows.js.map +1 -1
- package/build/cjs/wrapMethodWithSentry.js +2 -3
- package/build/cjs/wrapMethodWithSentry.js.map +1 -1
- package/build/esm/durableobject.js +117 -39
- package/build/esm/durableobject.js.map +1 -1
- package/build/esm/flush.js.map +1 -1
- package/build/esm/instrumentations/agents/index.js +2 -0
- package/build/esm/instrumentations/agents/index.js.map +1 -1
- package/build/esm/instrumentations/agents/instrumentAgentCallableRpc.js +2 -2
- package/build/esm/instrumentations/agents/instrumentAgentCallableRpc.js.map +1 -1
- package/build/esm/instrumentations/agents/instrumentAgentRequestConversation.js +17 -0
- package/build/esm/instrumentations/agents/instrumentAgentRequestConversation.js.map +1 -0
- package/build/esm/instrumentations/agents/instrumentChatAgentConversation.js +4 -4
- package/build/esm/instrumentations/agents/instrumentChatAgentConversation.js.map +1 -1
- package/build/esm/instrumentations/agents/types.js +56 -13
- package/build/esm/instrumentations/agents/types.js.map +1 -1
- package/build/esm/package.json +1 -1
- package/build/esm/request.js +4 -3
- package/build/esm/request.js.map +1 -1
- package/build/esm/utils/invocationScope.js +10 -0
- package/build/esm/utils/invocationScope.js.map +1 -0
- package/build/esm/utils/rpcMeta.js +4 -1
- package/build/esm/utils/rpcMeta.js.map +1 -1
- package/build/esm/workflows.js +2 -2
- package/build/esm/workflows.js.map +1 -1
- package/build/esm/wrapMethodWithSentry.js +3 -4
- package/build/esm/wrapMethodWithSentry.js.map +1 -1
- package/build/types/durableobject.d.ts +17 -8
- package/build/types/durableobject.d.ts.map +1 -1
- package/build/types/flush.d.ts +1 -1
- package/build/types/flush.d.ts.map +1 -1
- package/build/types/instrumentations/agents/index.d.ts +4 -3
- package/build/types/instrumentations/agents/index.d.ts.map +1 -1
- package/build/types/instrumentations/agents/instrumentAgentCallableRpc.d.ts +4 -1
- package/build/types/instrumentations/agents/instrumentAgentCallableRpc.d.ts.map +1 -1
- package/build/types/instrumentations/agents/instrumentAgentRequestConversation.d.ts +16 -0
- package/build/types/instrumentations/agents/instrumentAgentRequestConversation.d.ts.map +1 -0
- package/build/types/instrumentations/agents/instrumentChatAgentConversation.d.ts +10 -9
- package/build/types/instrumentations/agents/instrumentChatAgentConversation.d.ts.map +1 -1
- package/build/types/instrumentations/agents/types.d.ts +63 -18
- package/build/types/instrumentations/agents/types.d.ts.map +1 -1
- package/build/types/request.d.ts.map +1 -1
- package/build/types/utils/invocationScope.d.ts +24 -0
- package/build/types/utils/invocationScope.d.ts.map +1 -0
- package/build/types/utils/rpcMeta.d.ts +8 -0
- package/build/types/utils/rpcMeta.d.ts.map +1 -1
- package/build/types/wrapMethodWithSentry.d.ts +1 -1
- package/build/types/wrapMethodWithSentry.d.ts.map +1 -1
- package/build/types-ts3.8/durableobject.d.ts +17 -8
- package/build/types-ts3.8/flush.d.ts +1 -1
- package/build/types-ts3.8/instrumentations/agents/index.d.ts +4 -3
- package/build/types-ts3.8/instrumentations/agents/instrumentAgentCallableRpc.d.ts +4 -1
- package/build/types-ts3.8/instrumentations/agents/instrumentAgentRequestConversation.d.ts +16 -0
- package/build/types-ts3.8/instrumentations/agents/instrumentChatAgentConversation.d.ts +10 -9
- package/build/types-ts3.8/instrumentations/agents/types.d.ts +63 -18
- package/build/types-ts3.8/utils/invocationScope.d.ts +24 -0
- package/build/types-ts3.8/utils/rpcMeta.d.ts +8 -0
- package/build/types-ts3.8/wrapMethodWithSentry.d.ts +1 -1
- package/package.json +3 -3
|
@@ -4,9 +4,10 @@
|
|
|
4
4
|
*
|
|
5
5
|
* - **Callable RPC spans** — a span (op `rpc`) for each `@callable()` method invoked over WebSocket.
|
|
6
6
|
* - **Conversation correlation** — sets the conversation id on the scope for each unit of agent
|
|
7
|
-
* work — chat turn
|
|
8
|
-
* chat and plain agents alike.
|
|
9
|
-
* cleared (the `message:clear` observability event)
|
|
7
|
+
* work — chat turn, callable RPC call, or HTTP request — so `gen_ai` spans created within it are
|
|
8
|
+
* correlated, for chat and plain agents alike. The id is minted once per agent instance and
|
|
9
|
+
* rotated when the chat is cleared (the `message:clear` observability event); it is persisted to
|
|
10
|
+
* Durable Object storage so it survives hibernation.
|
|
10
11
|
*
|
|
11
12
|
* It only hooks the `agents` package internals and uses Sentry's tracing primitives. On Cloudflare
|
|
12
13
|
* Workers, prefer `instrumentAgentWithSentry`, which additionally instruments the Durable Object
|
|
@@ -5,7 +5,10 @@ import { AgentInternals } from './types';
|
|
|
5
5
|
* the WebSocket message (on Cloudflare, the instrumented Durable Object `webSocketMessage` hook).
|
|
6
6
|
*
|
|
7
7
|
* Also sets the conversation id on the scope for the duration of the call: callable methods are the
|
|
8
|
-
* unit of work for plain (non-chat) agents, which run LLM calls just like chat turns do.
|
|
8
|
+
* unit of work for plain (non-chat) agents, which run LLM calls just like chat turns do. It is
|
|
9
|
+
* awaited so the id is on the scope before the method body creates any span; the `agents`
|
|
10
|
+
* `onMessage` own property this wraps is already `async`, so the promise return is nothing new to
|
|
11
|
+
* the WebSocket dispatch upstream.
|
|
9
12
|
*/
|
|
10
13
|
export declare function instrumentAgentCallableRpc(obj: AgentInternals): void;
|
|
11
14
|
//# sourceMappingURL=instrumentAgentCallableRpc.d.ts.map
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { AgentInternals } from './types';
|
|
2
|
+
/**
|
|
3
|
+
* Correlates the AI spans of an HTTP-driven agent turn with a conversation id on the active scope.
|
|
4
|
+
*
|
|
5
|
+
* `onRequest` is the third unit of agent work, alongside chat turns and `@callable()` RPC: the
|
|
6
|
+
* `agents` router sends every non-WebSocket request to it, which is how REST endpoints and webhooks
|
|
7
|
+
* reach an agent.
|
|
8
|
+
*
|
|
9
|
+
* `agents` installs `onRequest` as an own property in the `Agent` constructor (as it does
|
|
10
|
+
* `onMessage`), and we instrument after construction, so wrapping the own property is what the
|
|
11
|
+
* router ends up calling. That own property is already `async`, and partyserver's `fetch` awaits it,
|
|
12
|
+
* so returning a promise from this wrapper — to get the conversation id onto the scope before the
|
|
13
|
+
* request handler creates any span — keeps the existing contract.
|
|
14
|
+
*/
|
|
15
|
+
export declare function instrumentAgentRequestConversation(obj: AgentInternals): void;
|
|
16
|
+
//# sourceMappingURL=instrumentAgentRequestConversation.d.ts.map
|
|
@@ -3,16 +3,17 @@ import { AgentInternals } from './types';
|
|
|
3
3
|
* For chat agents (`AIChatAgent` from `@cloudflare/ai-chat`), correlates each chat turn's AI spans
|
|
4
4
|
* with a conversation id on the active scope.
|
|
5
5
|
*
|
|
6
|
-
* In the Agents model one agent instance is one long-lived conversation, so the
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
* the
|
|
6
|
+
* In the Agents model one agent instance is one long-lived conversation, so the conversation id is
|
|
7
|
+
* minted once per instance and persisted to Durable Object storage, which is what carries it across
|
|
8
|
+
* hibernation (that destroys the in-memory instance). When the user clears the chat, they expect a
|
|
9
|
+
* fresh conversation — but recreating the Durable Object for that would also drop the MCP/OAuth
|
|
10
|
+
* state stored per instance (GitHub/Sentry sign-in). To get a fresh conversation id *without*
|
|
11
|
+
* losing that state, we rotate the persisted id when the SDK reports a cleared chat.
|
|
12
12
|
*
|
|
13
|
-
* The id itself is not attached to spans here —
|
|
14
|
-
*
|
|
15
|
-
*
|
|
13
|
+
* The id itself is not attached to spans here — `setAgentConversationId` resolves it, and the SDK's
|
|
14
|
+
* `conversationIdIntegration` picks it off the scope at `spanStart` to stamp
|
|
15
|
+
* `gen_ai.conversation.id` onto the AI spans created inside the turn (e.g. by the Workers AI
|
|
16
|
+
* instrumentation), which correlates a turn's model and tool calls.
|
|
16
17
|
*
|
|
17
18
|
* Plain (non-chat) `Agent`s do not define `onChatMessage`, so they are skipped here — their unit
|
|
18
19
|
* of work is the callable RPC method, where `instrumentAgentCallableRpc` sets the conversation id
|
|
@@ -1,6 +1,14 @@
|
|
|
1
|
+
import { InstrumentedDurableObjectState } from '../../wrapMethodWithSentry';
|
|
1
2
|
export declare const AGENT_SPAN_ORIGIN = "auto.faas.cloudflare.agents";
|
|
2
|
-
|
|
3
|
-
export declare const
|
|
3
|
+
/** DO storage key under which the conversation id is persisted so it survives hibernation. */
|
|
4
|
+
export declare const AGENT_CONVERSATION_ID_STORAGE_KEY = "__SENTRY_AGENT_CONVERSATION_ID__";
|
|
5
|
+
/**
|
|
6
|
+
* Instance keys for our conversation-id bookkeeping, keyed by symbol so the state stays invisible
|
|
7
|
+
* to anything enumerating the user-owned agent instance (`Object.keys`, `JSON.stringify`, spread).
|
|
8
|
+
* Exported because the exported `AgentInternals` interface references them.
|
|
9
|
+
*/
|
|
10
|
+
export declare const AGENT_CONVERSATION_ID_SYMBOL: unique symbol;
|
|
11
|
+
export declare const AGENT_APPLIED_CONVERSATION_ID_SYMBOL: unique symbol;
|
|
4
12
|
/**
|
|
5
13
|
* The subset of the `agents` `Agent` instance internals that we instrument. These are runtime
|
|
6
14
|
* implementation details of the `agents` package (v0.13.x) rather than part of its public type
|
|
@@ -16,34 +24,71 @@ export interface AgentInternals {
|
|
|
16
24
|
* does not, so its presence discriminates a chat agent.
|
|
17
25
|
*/
|
|
18
26
|
onChatMessage?: (...args: unknown[]) => unknown;
|
|
27
|
+
/** HTTP request handler; the router sends every non-WebSocket request here. */
|
|
28
|
+
onRequest?: (...args: unknown[]) => unknown;
|
|
19
29
|
/** The user's Agent class (used by the SDK for the observability event `agent` field). */
|
|
20
30
|
_ParentClass?: {
|
|
21
31
|
name?: string;
|
|
22
32
|
};
|
|
23
|
-
/** The Agent instance name,
|
|
33
|
+
/** The Agent instance name, reported as the `cloudflare.agent.name` span attribute. */
|
|
24
34
|
name?: string;
|
|
25
35
|
/**
|
|
26
|
-
*
|
|
27
|
-
*
|
|
28
|
-
|
|
29
|
-
|
|
36
|
+
* The Durable Object state of the instance. Present on every real Agent; guarded like the other
|
|
37
|
+
* internals so partially-mocked instances keep working.
|
|
38
|
+
*/
|
|
39
|
+
ctx?: InstrumentedDurableObjectState;
|
|
40
|
+
/**
|
|
41
|
+
* The current conversation id for this agent instance. It is cached in memory after being loaded
|
|
42
|
+
* from Durable Object storage and updated when the conversation rotates. `undefined` means storage
|
|
43
|
+
* has not been read yet.
|
|
44
|
+
*/
|
|
45
|
+
[AGENT_CONVERSATION_ID_SYMBOL]?: string;
|
|
46
|
+
/**
|
|
47
|
+
* The conversation id this instrumentation most recently applied to the isolation scope. It lets
|
|
48
|
+
* subsequent units of work distinguish an SDK-applied id, which may be replaced after rotation,
|
|
49
|
+
* from an id explicitly set by the user, which must be preserved.
|
|
30
50
|
*/
|
|
31
|
-
|
|
51
|
+
[AGENT_APPLIED_CONVERSATION_ID_SYMBOL]?: string;
|
|
32
52
|
}
|
|
33
53
|
/** Reads best-effort agent identity attributes from the instance, tolerating missing internals. */
|
|
34
54
|
export declare function getAgentAttributes(instance: AgentInternals): Record<string, string>;
|
|
35
55
|
/**
|
|
36
|
-
*
|
|
37
|
-
*
|
|
38
|
-
*
|
|
39
|
-
*
|
|
40
|
-
*
|
|
41
|
-
*
|
|
56
|
+
* Persists the conversation id to Durable Object storage, so it survives hibernation, and updates
|
|
57
|
+
* the in-memory cache synchronously so the current wake is immediately consistent even if the
|
|
58
|
+
* write fails. Uses the async storage API, which exists on KV- and SQLite-backed DOs alike.
|
|
59
|
+
* The write is fire-and-forget: DO storage writes are tracked by the runtime and land without
|
|
60
|
+
* awaiting (`waitUntil` is a no-op in Durable Objects), and the catch keeps a rejection from
|
|
61
|
+
* surfacing as unhandled — a failed write just means the next wake starts a new conversation,
|
|
62
|
+
* which must never throw into user code. Uses the original uninstrumented storage so internal
|
|
63
|
+
* bookkeeping doesn't create spans.
|
|
64
|
+
*/
|
|
65
|
+
export declare function storeAgentConversationId(instance: AgentInternals, conversationId: string): void;
|
|
66
|
+
/**
|
|
67
|
+
* Sets the agent instance's conversation id on the active scope for the duration of the
|
|
68
|
+
* surrounding unit of work (chat turn, callable RPC call, HTTP request). In the Agents model one
|
|
69
|
+
* instance is one long-lived conversation, so the id is minted once per instance and persisted to
|
|
70
|
+
* DO storage — for chat and plain agents alike, since plain agents run LLM calls too (e.g. inside
|
|
71
|
+
* `@callable()` methods). The instance `name` is deliberately not used: it is caller-chosen and can
|
|
72
|
+
* be a stable, guessable, or shared value, whereas a conversation id should identify exactly one
|
|
73
|
+
* conversation. Clearing the chat rotates it (see `storeAgentConversationId`) so subsequent LLM
|
|
74
|
+
* calls group under the fresh conversation.
|
|
75
|
+
*
|
|
76
|
+
* Every handler wrapper awaits this before invoking the original, so the id is on the scope before
|
|
77
|
+
* the unit of work — and any `gen_ai` span it creates — starts. Only the first unit of work per wake
|
|
78
|
+
* pays the storage read; the rest resolve from the in-memory cache. Awaiting is safe on all three
|
|
79
|
+
* paths because the `agents` `Agent` constructor already replaces `onMessage` and `onRequest` with
|
|
80
|
+
* `async` wrappers of its own, and `onChatMessage` is async by contract, so every caller upstream
|
|
81
|
+
* already handles a promise.
|
|
82
|
+
*
|
|
83
|
+
* An id the user set explicitly outranks this inferred one, in either order: a `setConversationId()`
|
|
84
|
+
* call that already happened is detected here and left alone, and one made inside the handler lands
|
|
85
|
+
* on the same scope afterwards and therefore wins. That is why the write targets the isolation scope
|
|
86
|
+
* — it is the scope the public `Sentry.setConversationId()` writes to, and `conversationIdIntegration`
|
|
87
|
+
* prefers the current scope over it, so writing there would make a user's call unoverridable.
|
|
42
88
|
*
|
|
43
89
|
* `conversationIdIntegration` reads the id off the scope at `spanStart` and stamps
|
|
44
|
-
* `gen_ai.conversation.id` onto AI spans created within the unit of work, correlating its model
|
|
45
|
-
*
|
|
46
|
-
* does not leak into unrelated events.
|
|
90
|
+
* `gen_ai.conversation.id` onto AI spans created within the unit of work, correlating its model and
|
|
91
|
+
* tool calls.
|
|
47
92
|
*/
|
|
48
|
-
export declare function setAgentConversationId(instance: AgentInternals): void
|
|
93
|
+
export declare function setAgentConversationId(instance: AgentInternals): Promise<void>;
|
|
49
94
|
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { Scope } from '@sentry/core';
|
|
2
|
+
/**
|
|
3
|
+
* Runs `callback` on the isolation scope for the current invocation.
|
|
4
|
+
*
|
|
5
|
+
* An instrumented handler is either the entry point of an invocation or reentrant — reached from
|
|
6
|
+
* another instrumented handler already serving the same invocation (a Durable Object method calling
|
|
7
|
+
* its own `fetch`, an RPC method reaching a sibling method). Only the entry point may fork:
|
|
8
|
+
*
|
|
9
|
+
* - Forking at the entry point is mandatory. `setUser`/`setTag` write to the isolation scope, and a
|
|
10
|
+
* Durable Object's isolation scope outlives the invocation that touched it, so without a fork one
|
|
11
|
+
* invocation's user and tags reappear on the next invocation's events in the same isolate.
|
|
12
|
+
* Forking clones, so request data set by an enclosing wrapper is still inherited.
|
|
13
|
+
* - Forking again when reentrant would be wrong. Everything below the entry point is one logical
|
|
14
|
+
* unit of work: a nested call must see what the caller set and be able to add to it, the way it
|
|
15
|
+
* would if the SDK were not wrapping it at all.
|
|
16
|
+
*
|
|
17
|
+
* The AsyncLocalStorage strategy hands the default isolation scope back whenever no invocation is in
|
|
18
|
+
* flight, and a forked one while inside `withIsolationScope`. Reference-comparing against the default
|
|
19
|
+
* is therefore enough to tell the two cases apart. The stack fallback does not fork, so it reports the
|
|
20
|
+
* default scope even inside an invocation; there the fork degrades to a no-op, which the stack strategy
|
|
21
|
+
* tolerates. This matches the approach used by `patchEventHandler` in Nuxt.
|
|
22
|
+
*/
|
|
23
|
+
export declare function withInvocationIsolationScope<T>(callback: (scope: Scope) => T): T;
|
|
24
|
+
//# sourceMappingURL=invocationScope.d.ts.map
|
|
@@ -4,6 +4,14 @@ import { SerializedTraceData } from '@sentry/core';
|
|
|
4
4
|
* If no active trace exists, returns the original args unchanged.
|
|
5
5
|
*/
|
|
6
6
|
export declare function appendRpcMeta(args: unknown[]): unknown[];
|
|
7
|
+
/**
|
|
8
|
+
* Whether the trailing argument carries Sentry RPC metadata.
|
|
9
|
+
*
|
|
10
|
+
* Separate from {@link extractRpcMeta} because the RPC method wrappers run this check on every
|
|
11
|
+
* call — including the instance's own internal method calls, which never carry metadata — and
|
|
12
|
+
* must not allocate on that path.
|
|
13
|
+
*/
|
|
14
|
+
export declare function hasRpcMeta(args: unknown[]): boolean;
|
|
7
15
|
/**
|
|
8
16
|
* Extracts Sentry RPC metadata from the trailing argument of an args array.
|
|
9
17
|
* Returns cleaned args (without meta) and the extracted trace data if found.
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { DurableObjectStorage } from '@cloudflare/workers-types';
|
|
2
2
|
import { CloudflareOptions } from './client';
|
|
3
3
|
/** Extended DurableObjectState with originalStorage exposed by instrumentContext */
|
|
4
|
-
interface InstrumentedDurableObjectState extends DurableObjectState {
|
|
4
|
+
export interface InstrumentedDurableObjectState extends DurableObjectState {
|
|
5
5
|
originalStorage?: DurableObjectStorage;
|
|
6
6
|
}
|
|
7
7
|
type MethodWrapperOptions = {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sentry/cloudflare",
|
|
3
|
-
"version": "10.
|
|
3
|
+
"version": "10.70.0",
|
|
4
4
|
"description": "Official Sentry SDK for Cloudflare Workers and Pages",
|
|
5
5
|
"repository": "git://github.com/getsentry/sentry-javascript.git",
|
|
6
6
|
"homepage": "https://github.com/getsentry/sentry-javascript/tree/master/packages/cloudflare",
|
|
@@ -70,8 +70,8 @@
|
|
|
70
70
|
},
|
|
71
71
|
"dependencies": {
|
|
72
72
|
"@opentelemetry/api": "^1.9.1",
|
|
73
|
-
"@sentry/core": "10.
|
|
74
|
-
"@sentry/server-utils": "10.
|
|
73
|
+
"@sentry/core": "10.70.0",
|
|
74
|
+
"@sentry/server-utils": "10.70.0",
|
|
75
75
|
"magic-string": "~0.30.21"
|
|
76
76
|
},
|
|
77
77
|
"peerDependencies": {
|