autotel-cloudflare 3.0.0 → 3.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 +1 @@
1
- {"version":3,"file":"agents.d.ts","names":[],"sources":["../src/agents/types.ts","../src/agents/otel-observability.ts"],"mappings":";;;;;;;UAUiB,cAAA,mCAEC,MAAA,oBAA0B,MAAA;EAE1C,IAAA,EAAM,CAAA;EAMG;EAJT,EAAA;EAIyB;EAFzB,cAAA;EAPA;EASA,OAAA,EAAS,OAAA,GAAU,MAAA;EARH;EAUhB,SAAA;AAAA;;;;KAMU,uBAAA,GACR,cAAA,iBAA+B,MAAA,qBAC/B,cAAA;EAGI,MAAA;EACA,SAAA;AAAA,KAGJ,cAAA,yCAAuD,MAAA,qBACvD,cAAA,oBACA,cAAA;EAGI,QAAA;EACA,EAAA;AAAA,KAGJ,cAAA,cACA,cAAA;EAGI,YAAA;AAAA;;;;KAOI,qBAAA,GACR,cAAA;EAA0C,QAAA;AAAA,KAC1C,cAAA;EAEI,GAAA;EAAa,SAAA;EAAmB,KAAA;EAAe,KAAA;AAAA,KAEnD,cAAA;EAGI,QAAA;EACA,OAAA;EACA,QAAA;AAAA,KAGJ,cAAA,wBAAsC,MAAA;;;;KAK9B,kBAAA,GAAqB,uBAAA,GAA0B,qBAAqB;;;;UAK/D,aAAA;EAlCb;;;AAGgB;AAOpB;EA8BE,IAAA,CAAK,KAAA,EAAO,kBAAA,EAAoB,GAAA,GAAM,kBAAkB;AAAA;;;;UAMzC,2BAAA;EAtBb;;;;EA2BF,QAAA;EAvCE;;;;EA6CF,aAAA;EAzCE;;;;EA+CF,QAAA;EAvCwC;;AAAM;AAKhD;EAwCE,iBAAA;;;AAxC8E;AAKhF;EAyCE,aAAA;;;;;EAMA,cAAA;EAzCsC;;;EA8CtC,kBAAA,IAAsB,KAAA,EAAO,kBAAA,KAAuB,UAAA;EAxCrC;;;EA6Cf,iBAAA,IAAqB,KAAA,EAAO,kBAAA;AAAA;;;;KAMlB,uBAAA,GAA0B,mBAAA;EAxCpC;;;EA4CA,MAAA,GAAS,2BAA2B;AAAA;;;;UAMrB,mBAAA;EACf,kBAAA;EACA,gBAAA;EACA,kBAAA;EACA,qBAAA;EACA,yBAAA;EACA,mBAAA;EACA,qBAAA;EACA,qBAAA;EACA,eAAA;EACA,qBAAA;EACA,iBAAA;AAAA;;;;;AA/IS;AAMX;;;cCwSa,iBAAA,YAA6B,aAAA;EAAA,QAChC,MAAA;EAAA,QACA,OAAA;EAAA,QACA,WAAA;cAEI,MAAA,EAAQ,uBAAA;EDnSlB;;;EAAA,QC6SM,UAAA;EDpSQ;;;;;EC+ShB,IAAA,CAAK,KAAA,EAAO,kBAAA,EAAoB,GAAA,GAAM,kBAAA;AAAA;;;;;;;;;;;AD5SpB;AAOpB;;;;;iBC0WgB,uBAAA,CAAwB,MAAA,EAAQ,uBAAA,GAA0B,iBAAiB;;;;;;;;;;;;;;;;;;;AD5V3C;AAKhD;iBC+WgB,8BAAA,CACd,GAAA,EAAK,MAAA,mBACL,OAAA,GAAU,2BAAA,GACT,iBAAA"}
1
+ {"version":3,"file":"agents.d.ts","names":[],"sources":["../src/agents/base.ts","../src/agents/agent.ts","../src/agents/mcp.ts","../src/agents/observability.ts","../src/agents/types.ts","../src/agents/otel-observability.ts"],"mappings":"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"}
package/dist/agents.js CHANGED
@@ -7,38 +7,8 @@ import { resourceFromAttributes } from "@opentelemetry/resources";
7
7
  * OpenTelemetry-based Observability implementation for Cloudflare Agents SDK
8
8
  *
9
9
  * Converts Agent events into OpenTelemetry spans for distributed tracing.
10
- *
11
- * @example
12
- * ```typescript
13
- * import { Agent } from 'agents'
14
- * import { createOtelObservability } from 'autotel-cloudflare/agents'
15
- *
16
- * class MyAgent extends Agent<Env> {
17
- * observability = createOtelObservability({
18
- * service: { name: 'my-agent' },
19
- * exporter: { url: env.OTLP_ENDPOINT }
20
- * })
21
- *
22
- * @callable()
23
- * async doSomething() {
24
- * // This RPC call will be automatically traced
25
- * return 'done'
26
- * }
27
- * }
28
- * ```
29
- */
30
- /**
31
- * Map of active spans keyed by event ID
32
- * Used to correlate start/end events
33
- */
34
- const activeSpans = /* @__PURE__ */ new Map();
35
- /**
36
- * Whether the provider has been initialized
37
10
  */
38
11
  let providerInitialized = false;
39
- /**
40
- * Initialize the tracer provider for Agents
41
- */
42
12
  function initProvider(config) {
43
13
  if (providerInitialized) return;
44
14
  const resource = resourceFromAttributes({
@@ -55,128 +25,221 @@ function initProvider(config) {
55
25
  trace.getTracer("autotel-cloudflare/agents").setHeadSampler(config.sampling.headSampler);
56
26
  providerInitialized = true;
57
27
  }
58
- /**
59
- * Get default span name for an event
60
- */
28
+ function classifyEvent(type) {
29
+ if (type.startsWith("mcp:")) return "mcp";
30
+ if (type.startsWith("workflow:")) return "workflow";
31
+ if (type.startsWith("fiber:")) return "fiber";
32
+ if (type.startsWith("agent_tool:")) return "agentTool";
33
+ if (type.startsWith("chat:transcript:")) return "transcript";
34
+ if (type.startsWith("chat:")) return "chat";
35
+ if (type.startsWith("submission:")) return "submission";
36
+ if (type.startsWith("queue:")) return "queue";
37
+ if (type.startsWith("schedule:")) return "schedule";
38
+ if (type.startsWith("message:") || type.startsWith("tool:") || type === "rpc:error") return "message";
39
+ if (type === "rpc") return "rpc";
40
+ if (type.startsWith("state:")) return "state";
41
+ if (type.startsWith("email:")) return "email";
42
+ if (type === "connect" || type === "disconnect" || type === "destroy") return "lifecycle";
43
+ return "message";
44
+ }
45
+ function shouldTraceEvent(event, options) {
46
+ const merged = {
47
+ traceRpc: true,
48
+ traceSchedule: true,
49
+ traceQueue: true,
50
+ traceSubmissions: true,
51
+ traceMcp: true,
52
+ traceStateUpdates: false,
53
+ traceMessages: true,
54
+ traceLifecycle: true,
55
+ traceChat: true,
56
+ traceTranscripts: true,
57
+ traceFibers: true,
58
+ traceToolRecovery: true,
59
+ traceWorkflow: true,
60
+ traceEmail: true,
61
+ ...options
62
+ };
63
+ switch (classifyEvent(event.type)) {
64
+ case "rpc": return merged.traceRpc;
65
+ case "schedule": return merged.traceSchedule;
66
+ case "queue": return merged.traceQueue;
67
+ case "submission": return merged.traceSubmissions;
68
+ case "mcp": return merged.traceMcp;
69
+ case "state": return merged.traceStateUpdates;
70
+ case "message": return merged.traceMessages;
71
+ case "lifecycle": return merged.traceLifecycle;
72
+ case "chat": return merged.traceChat;
73
+ case "transcript": return merged.traceTranscripts;
74
+ case "fiber": return merged.traceFibers;
75
+ case "agentTool": return merged.traceToolRecovery;
76
+ case "workflow": return merged.traceWorkflow;
77
+ case "email": return merged.traceEmail;
78
+ }
79
+ }
80
+ function formatTypeSegment(value) {
81
+ return value.replaceAll(/[:_]/g, ".");
82
+ }
83
+ function getPayloadName(payload, ...keys) {
84
+ for (const key of keys) {
85
+ const value = payload[key];
86
+ if (typeof value === "string" && value.length > 0) return value;
87
+ }
88
+ }
61
89
  function getDefaultSpanName(event) {
90
+ const payload = event.payload;
62
91
  switch (event.type) {
63
- case "rpc": return `agent.rpc ${event.payload.method}`;
64
- case "schedule:create": return `agent.schedule.create ${event.payload.callback}`;
65
- case "schedule:execute": return `agent.schedule.execute ${event.payload.callback}`;
66
- case "schedule:cancel": return `agent.schedule.cancel ${event.payload.callback}`;
67
- case "connect": return `agent.connect`;
68
- case "destroy": return `agent.destroy`;
69
- case "state:update": return `agent.state.update`;
70
- case "message:request": return `agent.message.request`;
71
- case "message:response": return `agent.message.response`;
72
- case "message:clear": return `agent.message.clear`;
73
- case "mcp:client:preconnect": return `mcp.preconnect ${event.payload.serverId}`;
74
- case "mcp:client:connect": return `mcp.connect ${event.payload.url}`;
75
- case "mcp:client:authorize": return `mcp.authorize ${event.payload.serverId}`;
76
- case "mcp:client:discover": return `mcp.discover`;
77
- default: return `agent.${event.type}`;
92
+ case "rpc":
93
+ case "rpc:error": return `agent.rpc ${payload.method}`;
94
+ case "schedule:create":
95
+ case "schedule:execute":
96
+ case "schedule:cancel":
97
+ case "schedule:retry":
98
+ case "schedule:error":
99
+ case "schedule:duplicate_warning": return `agent.${formatTypeSegment(event.type)} ${getPayloadName(payload, "callback") ?? "unknown"}`;
100
+ case "queue:create":
101
+ case "queue:retry":
102
+ case "queue:error": return `agent.${formatTypeSegment(event.type)} ${getPayloadName(payload, "callback") ?? "unknown"}`;
103
+ case "submission:create":
104
+ case "submission:status":
105
+ case "submission:error": return `agent.${formatTypeSegment(event.type)} ${getPayloadName(payload, "submissionId") ?? "unknown"}`;
106
+ case "connect":
107
+ case "disconnect": return `agent.${event.type} ${getPayloadName(payload, "connectionId") ?? "unknown"}`;
108
+ case "mcp:client:preconnect": return `mcp.client.preconnect ${getPayloadName(payload, "serverId") ?? "unknown"}`;
109
+ case "mcp:client:authorize": return `mcp.client.authorize ${getPayloadName(payload, "serverId") ?? "unknown"}`;
110
+ case "mcp:client:connect":
111
+ case "mcp:client:discover":
112
+ case "mcp:client:close": return `mcp.client.${formatTypeSegment(event.type).split(".").slice(-1)[0]} ${getPayloadName(payload, "url", "capability", "state") ?? "unknown"}`;
113
+ case "workflow:start":
114
+ case "workflow:event":
115
+ case "workflow:approved":
116
+ case "workflow:rejected":
117
+ case "workflow:terminated":
118
+ case "workflow:paused":
119
+ case "workflow:resumed":
120
+ case "workflow:restarted": return `agent.${formatTypeSegment(event.type)} ${getPayloadName(payload, "workflowName", "workflowId", "eventType") ?? "unknown"}`;
121
+ case "email:receive":
122
+ case "email:reply":
123
+ case "email:send": return `agent.${formatTypeSegment(event.type)} ${getPayloadName(payload, "subject") ?? "message"}`;
124
+ case "destroy": return "agent.destroy";
125
+ default: return `agent.${formatTypeSegment(event.type)}`;
78
126
  }
79
127
  }
80
- /**
81
- * Get default attributes for an event
82
- */
128
+ function isPrimitiveAttributeValue(value) {
129
+ if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") return true;
130
+ if (!Array.isArray(value)) return false;
131
+ return value.every((entry) => typeof entry === "string" || typeof entry === "number" || typeof entry === "boolean");
132
+ }
133
+ function setIfPresent(attrs, key, value) {
134
+ if (value === void 0 || value === null) return;
135
+ if (isPrimitiveAttributeValue(value)) attrs[key] = value;
136
+ }
83
137
  function getDefaultAttributes(event) {
84
- const attrs = {
85
- "agent.event.type": event.type,
86
- "agent.event.id": event.id
87
- };
138
+ const attrs = { "agent.event.type": event.type };
139
+ setIfPresent(attrs, "agent.event.id", event.id);
140
+ setIfPresent(attrs, "agent.display_message", event.displayMessage);
141
+ setIfPresent(attrs, "agent.class", event.agent);
142
+ setIfPresent(attrs, "agent.instance.name", event.name);
143
+ setIfPresent(attrs, "gen_ai.agent.name", event.agent);
88
144
  switch (event.type) {
89
145
  case "rpc":
90
146
  attrs["agent.rpc.method"] = event.payload.method;
91
- if (event.payload.streaming !== void 0) attrs["agent.rpc.streaming"] = event.payload.streaming;
147
+ setIfPresent(attrs, "agent.rpc.streaming", event.payload.streaming);
148
+ break;
149
+ case "rpc:error":
150
+ attrs["agent.rpc.method"] = event.payload.method;
92
151
  break;
93
152
  case "schedule:create":
94
153
  case "schedule:execute":
95
154
  case "schedule:cancel":
96
- attrs["agent.schedule.callback"] = event.payload.callback;
97
- attrs["agent.schedule.id"] = event.payload.id;
155
+ case "schedule:retry":
156
+ case "schedule:error":
157
+ case "queue:create":
158
+ case "queue:retry":
159
+ case "queue:error":
160
+ setIfPresent(attrs, "agent.schedule.callback", event.payload.callback);
161
+ setIfPresent(attrs, "agent.schedule.id", event.payload.id);
162
+ break;
163
+ case "schedule:duplicate_warning":
164
+ setIfPresent(attrs, "agent.schedule.callback", event.payload.callback);
98
165
  break;
99
166
  case "connect":
100
- attrs["agent.connection.id"] = event.payload.connectionId;
167
+ case "disconnect":
168
+ setIfPresent(attrs, "agent.connection.id", event.payload.connectionId);
101
169
  break;
102
170
  case "mcp:client:preconnect":
103
- attrs["agent.mcp.server_id"] = event.payload.serverId;
171
+ setIfPresent(attrs, "agent.mcp.server_id", event.payload.serverId);
104
172
  break;
105
173
  case "mcp:client:connect":
106
- attrs["agent.mcp.url"] = event.payload.url;
107
- attrs["agent.mcp.transport"] = event.payload.transport;
108
- attrs["agent.mcp.state"] = event.payload.state;
109
- if (event.payload.error) attrs["agent.mcp.error"] = event.payload.error;
174
+ case "mcp:client:close":
175
+ setIfPresent(attrs, "agent.mcp.url", event.payload.url);
176
+ setIfPresent(attrs, "agent.mcp.transport", event.payload.transport);
177
+ setIfPresent(attrs, "agent.mcp.state", event.payload.state);
110
178
  break;
111
179
  case "mcp:client:authorize":
112
- attrs["agent.mcp.server_id"] = event.payload.serverId;
113
- attrs["agent.mcp.auth_url"] = event.payload.authUrl;
114
- if (event.payload.clientId) attrs["agent.mcp.client_id"] = event.payload.clientId;
180
+ setIfPresent(attrs, "agent.mcp.server_id", event.payload.serverId);
181
+ setIfPresent(attrs, "agent.mcp.auth_url", event.payload.authUrl);
182
+ setIfPresent(attrs, "agent.mcp.client_id", event.payload.clientId);
183
+ break;
184
+ case "mcp:client:discover":
185
+ setIfPresent(attrs, "agent.mcp.url", event.payload.url);
186
+ setIfPresent(attrs, "agent.mcp.state", event.payload.state);
187
+ setIfPresent(attrs, "agent.mcp.capability", event.payload.capability);
115
188
  break;
116
189
  }
117
- for (const [key, value] of Object.entries(event.payload)) if (attrs[`agent.${key}`] === void 0 && (typeof value === "string" || typeof value === "number" || typeof value === "boolean")) attrs[`agent.payload.${key}`] = value;
190
+ for (const [key, value] of Object.entries(event.payload)) setIfPresent(attrs, `agent.payload.${key}`, value);
118
191
  return attrs;
119
192
  }
120
- /**
121
- * Determine span kind based on event type
122
- */
123
193
  function getSpanKind(event) {
124
- switch (event.type) {
125
- case "rpc": return SpanKind.SERVER;
126
- case "connect": return SpanKind.SERVER;
127
- case "mcp:client:connect":
128
- case "mcp:client:preconnect":
129
- case "mcp:client:authorize":
130
- case "mcp:client:discover": return SpanKind.CLIENT;
194
+ switch (classifyEvent(event.type)) {
195
+ case "rpc":
196
+ case "lifecycle":
197
+ case "email": return SpanKind.SERVER;
198
+ case "mcp": return SpanKind.CLIENT;
199
+ case "schedule":
200
+ case "queue": return SpanKind.CONSUMER;
131
201
  default: return SpanKind.INTERNAL;
132
202
  }
133
203
  }
134
- /**
135
- * Check if an event type should be traced based on options
136
- */
137
- function shouldTraceEvent(event, options) {
138
- const opts = {
139
- traceRpc: true,
140
- traceSchedule: true,
141
- traceMcp: true,
142
- traceStateUpdates: false,
143
- traceMessages: true,
144
- traceLifecycle: true,
145
- ...options
146
- };
147
- switch (event.type) {
148
- case "rpc": return opts.traceRpc ?? true;
149
- case "schedule:create":
150
- case "schedule:execute":
151
- case "schedule:cancel": return opts.traceSchedule ?? true;
152
- case "mcp:client:preconnect":
153
- case "mcp:client:connect":
154
- case "mcp:client:authorize":
155
- case "mcp:client:discover": return opts.traceMcp ?? true;
156
- case "state:update": return opts.traceStateUpdates ?? false;
157
- case "message:request":
158
- case "message:response":
159
- case "message:clear": return opts.traceMessages ?? true;
160
- case "connect":
161
- case "destroy": return opts.traceLifecycle ?? true;
162
- default: return true;
204
+ function inferErrorMessage(event) {
205
+ const payload = event.payload;
206
+ const direct = payload.error;
207
+ if (typeof direct === "string" && direct.length > 0) return direct;
208
+ if (event.type === "workflow:rejected") {
209
+ const reason = payload.reason;
210
+ if (typeof reason === "string" && reason.length > 0) return reason;
211
+ return "workflow rejected";
163
212
  }
213
+ if (event.type.endsWith(":failed") || event.type.endsWith(":error")) return event.type;
214
+ }
215
+ function isErrorEvent(event) {
216
+ if (event.type === "workflow:rejected") return true;
217
+ if (event.type.endsWith(":error") || event.type.endsWith(":failed")) return true;
218
+ if ("error" in event.payload) return typeof event.payload.error === "string";
219
+ return false;
220
+ }
221
+ function applyEventStatus(span, event) {
222
+ if (!isErrorEvent(event)) {
223
+ span.setStatus({ code: SpanStatusCode.OK });
224
+ return;
225
+ }
226
+ const message = inferErrorMessage(event);
227
+ span.setStatus({
228
+ code: SpanStatusCode.ERROR,
229
+ message
230
+ });
231
+ span.setAttribute("error", true);
232
+ if (message) span.setAttribute("exception.message", message);
164
233
  }
165
- /**
166
- * Export spans asynchronously
167
- */
168
234
  async function exportSpans(traceId, ctx) {
169
235
  const tracer = trace.getTracer("autotel-cloudflare/agents");
170
236
  if (tracer instanceof WorkerTracer) try {
171
- if (ctx && "scheduler" in ctx) {
172
- const ctxWithScheduler = ctx;
173
- if (ctxWithScheduler.scheduler) await ctxWithScheduler.scheduler.wait(1);
174
- }
237
+ const scheduler = ctx && "scheduler" in ctx ? ctx.scheduler : void 0;
238
+ if (scheduler?.wait) await scheduler.wait(1);
175
239
  await tracer.forceFlush(traceId);
176
240
  } catch (error) {
177
241
  console.error("[autotel-cloudflare/agents] Failed to export spans:", error);
178
242
  }
179
- if (ctx && "waitUntil" in ctx) {}
180
243
  }
181
244
  /**
182
245
  * OpenTelemetry-based Observability implementation
@@ -193,19 +256,11 @@ var OtelObservability = class {
193
256
  this.config = initialiser({}, void 0);
194
257
  this.options = config.agents ?? {};
195
258
  }
196
- /**
197
- * Initialize the tracer provider (called lazily on first emit)
198
- */
199
259
  initialize() {
200
260
  if (this.initialized) return;
201
261
  initProvider(this.config);
202
262
  this.initialized = true;
203
263
  }
204
- /**
205
- * Emit an observability event
206
- *
207
- * Converts the event to an OpenTelemetry span based on the event type.
208
- */
209
264
  emit(event, ctx) {
210
265
  this.initialize();
211
266
  if (!shouldTraceEvent(event, this.options)) return;
@@ -213,63 +268,27 @@ var OtelObservability = class {
213
268
  const spanName = this.options.spanNameFormatter ? this.options.spanNameFormatter(event) : getDefaultSpanName(event);
214
269
  const defaultAttrs = getDefaultAttributes(event);
215
270
  const customAttrs = this.options.attributeExtractor ? this.options.attributeExtractor(event) : {};
216
- const attributes = {
217
- ...defaultAttrs,
218
- ...customAttrs
219
- };
220
- const kind = getSpanKind(event);
221
271
  const span = tracer.startSpan(spanName, {
222
- kind,
223
- attributes,
272
+ kind: getSpanKind(event),
273
+ attributes: {
274
+ ...defaultAttrs,
275
+ ...customAttrs
276
+ },
224
277
  startTime: event.timestamp
225
278
  });
226
- span.setStatus({ code: SpanStatusCode.OK });
279
+ applyEventStatus(span, event);
227
280
  span.end(event.timestamp + 1);
228
- activeSpans.set(event.id, span);
229
281
  const traceId = span.spanContext().traceId;
230
- if (ctx && "waitUntil" in ctx && typeof ctx.waitUntil === "function") ctx.waitUntil(exportSpans(traceId, ctx));
231
- else exportSpans(traceId, ctx);
282
+ if (ctx && "waitUntil" in ctx && typeof ctx.waitUntil === "function") {
283
+ ctx.waitUntil(exportSpans(traceId, ctx));
284
+ return;
285
+ }
286
+ exportSpans(traceId, ctx);
232
287
  }
233
288
  };
234
- /**
235
- * Create an OtelObservability instance
236
- *
237
- * @example
238
- * ```typescript
239
- * import { Agent } from 'agents'
240
- * import { createOtelObservability } from 'autotel-cloudflare/agents'
241
- *
242
- * class MyAgent extends Agent<Env> {
243
- * observability = createOtelObservability({
244
- * service: { name: 'my-agent' },
245
- * exporter: { url: env.OTLP_ENDPOINT }
246
- * })
247
- * }
248
- * ```
249
- */
250
289
  function createOtelObservability(config) {
251
290
  return new OtelObservability(config);
252
291
  }
253
- /**
254
- * Create an OtelObservability instance with environment-based config
255
- *
256
- * Use this when you need to access environment variables for configuration.
257
- *
258
- * @example
259
- * ```typescript
260
- * import { Agent } from 'agents'
261
- * import { createOtelObservabilityFromEnv } from 'autotel-cloudflare/agents'
262
- *
263
- * class MyAgent extends Agent<Env> {
264
- * observability?: OtelObservability
265
- *
266
- * constructor(state: DurableObjectState, env: Env) {
267
- * super(state, env)
268
- * this.observability = createOtelObservabilityFromEnv(env)
269
- * }
270
- * }
271
- * ```
272
- */
273
292
  function createOtelObservabilityFromEnv(env, options) {
274
293
  const endpoint = env.OTEL_EXPORTER_OTLP_ENDPOINT || void 0;
275
294
  const serviceName = env.OTEL_SERVICE_NAME || "cloudflare-agent";
@@ -293,5 +312,68 @@ function createOtelObservabilityFromEnv(env, options) {
293
312
  }
294
313
 
295
314
  //#endregion
296
- export { OtelObservability, createOtelObservability, createOtelObservabilityFromEnv };
315
+ //#region src/agents/observability.ts
316
+ const listeners = {
317
+ state: /* @__PURE__ */ new Set(),
318
+ rpc: /* @__PURE__ */ new Set(),
319
+ message: /* @__PURE__ */ new Set(),
320
+ chat: /* @__PURE__ */ new Set(),
321
+ transcript: /* @__PURE__ */ new Set(),
322
+ fiber: /* @__PURE__ */ new Set(),
323
+ agentTool: /* @__PURE__ */ new Set(),
324
+ schedule: /* @__PURE__ */ new Set(),
325
+ lifecycle: /* @__PURE__ */ new Set(),
326
+ workflow: /* @__PURE__ */ new Set(),
327
+ mcp: /* @__PURE__ */ new Set(),
328
+ email: /* @__PURE__ */ new Set()
329
+ };
330
+ function createChannel(key, name) {
331
+ return {
332
+ name,
333
+ publish(event) {
334
+ for (const callback of listeners[key]) callback(event);
335
+ }
336
+ };
337
+ }
338
+ const channels = {
339
+ state: createChannel("state", "agents:state"),
340
+ rpc: createChannel("rpc", "agents:rpc"),
341
+ message: createChannel("message", "agents:message"),
342
+ chat: createChannel("chat", "agents:chat"),
343
+ transcript: createChannel("transcript", "agents:transcript"),
344
+ fiber: createChannel("fiber", "agents:fiber"),
345
+ agentTool: createChannel("agentTool", "agents:agent_tool"),
346
+ schedule: createChannel("schedule", "agents:schedule"),
347
+ lifecycle: createChannel("lifecycle", "agents:lifecycle"),
348
+ workflow: createChannel("workflow", "agents:workflow"),
349
+ mcp: createChannel("mcp", "agents:mcp"),
350
+ email: createChannel("email", "agents:email")
351
+ };
352
+ function getChannel(type) {
353
+ if (type.startsWith("mcp:")) return channels.mcp;
354
+ if (type.startsWith("workflow:")) return channels.workflow;
355
+ if (type.startsWith("fiber:")) return channels.fiber;
356
+ if (type.startsWith("transcript:") || type.startsWith("chat:transcript:")) return channels.transcript;
357
+ if (type.startsWith("chat:")) return channels.chat;
358
+ if (type.startsWith("agent_tool:")) return channels.agentTool;
359
+ if (type.startsWith("schedule:") || type.startsWith("queue:")) return channels.schedule;
360
+ if (type.startsWith("message:") || type.startsWith("tool:") || type.startsWith("submission:")) return channels.message;
361
+ if (type === "rpc" || type.startsWith("rpc:")) return channels.rpc;
362
+ if (type.startsWith("state:")) return channels.state;
363
+ if (type.startsWith("email:")) return channels.email;
364
+ return channels.lifecycle;
365
+ }
366
+ const genericObservability = { emit(event) {
367
+ getChannel(event.type).publish(event);
368
+ } };
369
+ function subscribe(channelKey, callback) {
370
+ const bucket = listeners[channelKey];
371
+ bucket.add(callback);
372
+ return () => {
373
+ bucket.delete(callback);
374
+ };
375
+ }
376
+
377
+ //#endregion
378
+ export { OtelObservability, channels, createOtelObservability, createOtelObservabilityFromEnv, genericObservability, subscribe };
297
379
  //# sourceMappingURL=agents.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"agents.js","names":[],"sources":["../src/agents/otel-observability.ts"],"sourcesContent":["/**\n * OpenTelemetry-based Observability implementation for Cloudflare Agents SDK\n *\n * Converts Agent events into OpenTelemetry spans for distributed tracing.\n *\n * @example\n * ```typescript\n * import { Agent } from 'agents'\n * import { createOtelObservability } from 'autotel-cloudflare/agents'\n *\n * class MyAgent extends Agent<Env> {\n * observability = createOtelObservability({\n * service: { name: 'my-agent' },\n * exporter: { url: env.OTLP_ENDPOINT }\n * })\n *\n * @callable()\n * async doSomething() {\n * // This RPC call will be automatically traced\n * return 'done'\n * }\n * }\n * ```\n */\n\nimport {\n trace,\n SpanStatusCode,\n SpanKind,\n type Span,\n type Attributes,\n} from '@opentelemetry/api';\nimport { resourceFromAttributes } from '@opentelemetry/resources';\nimport {\n createInitialiser,\n WorkerTracerProvider,\n WorkerTracer,\n type ResolvedEdgeConfig,\n} from 'autotel-edge';\nimport type {\n Observability,\n ObservabilityEvent,\n OtelObservabilityConfig,\n AgentInstrumentationOptions,\n} from './types';\n\n/**\n * Map of active spans keyed by event ID\n * Used to correlate start/end events\n */\nconst activeSpans = new Map<string, Span>();\n\n/**\n * Whether the provider has been initialized\n */\nlet providerInitialized = false;\n\n/**\n * Initialize the tracer provider for Agents\n */\nfunction initProvider(config: ResolvedEdgeConfig): void {\n if (providerInitialized) return;\n\n // Create resource with agent-specific attributes\n const resource = resourceFromAttributes({\n 'service.name': config.service.name,\n 'service.version': config.service.version,\n 'service.namespace': config.service.namespace,\n 'cloud.provider': 'cloudflare',\n 'cloud.platform': 'cloudflare.workers',\n 'telemetry.sdk.name': 'autotel-cloudflare',\n 'telemetry.sdk.language': 'js',\n 'agent.framework': 'cloudflare-agents',\n });\n\n // Create and register provider\n const provider = new WorkerTracerProvider(config.spanProcessors, resource);\n provider.register();\n\n // Set head sampler on tracer\n const tracer = trace.getTracer('autotel-cloudflare/agents') as WorkerTracer;\n tracer.setHeadSampler(config.sampling.headSampler);\n\n providerInitialized = true;\n}\n\n/**\n * Get default span name for an event\n */\nfunction getDefaultSpanName(event: ObservabilityEvent): string {\n switch (event.type) {\n case 'rpc': {\n return `agent.rpc ${event.payload.method}`;\n }\n case 'schedule:create': {\n return `agent.schedule.create ${event.payload.callback}`;\n }\n case 'schedule:execute': {\n return `agent.schedule.execute ${event.payload.callback}`;\n }\n case 'schedule:cancel': {\n return `agent.schedule.cancel ${event.payload.callback}`;\n }\n case 'connect': {\n return `agent.connect`;\n }\n case 'destroy': {\n return `agent.destroy`;\n }\n case 'state:update': {\n return `agent.state.update`;\n }\n case 'message:request': {\n return `agent.message.request`;\n }\n case 'message:response': {\n return `agent.message.response`;\n }\n case 'message:clear': {\n return `agent.message.clear`;\n }\n case 'mcp:client:preconnect': {\n return `mcp.preconnect ${event.payload.serverId}`;\n }\n case 'mcp:client:connect': {\n return `mcp.connect ${event.payload.url}`;\n }\n case 'mcp:client:authorize': {\n return `mcp.authorize ${event.payload.serverId}`;\n }\n case 'mcp:client:discover': {\n return `mcp.discover`;\n }\n default: {\n return `agent.${(event as ObservabilityEvent).type}`;\n }\n }\n}\n\n/**\n * Get default attributes for an event\n */\nfunction getDefaultAttributes(event: ObservabilityEvent): Attributes {\n const attrs: Attributes = {\n 'agent.event.type': event.type,\n 'agent.event.id': event.id,\n };\n\n // Add type-specific attributes\n switch (event.type) {\n case 'rpc': {\n attrs['agent.rpc.method'] = event.payload.method;\n if (event.payload.streaming !== undefined) {\n attrs['agent.rpc.streaming'] = event.payload.streaming;\n }\n break;\n }\n\n case 'schedule:create':\n case 'schedule:execute':\n case 'schedule:cancel': {\n attrs['agent.schedule.callback'] = event.payload.callback;\n attrs['agent.schedule.id'] = event.payload.id;\n break;\n }\n\n case 'connect': {\n attrs['agent.connection.id'] = event.payload.connectionId;\n break;\n }\n\n case 'mcp:client:preconnect': {\n attrs['agent.mcp.server_id'] = event.payload.serverId;\n break;\n }\n\n case 'mcp:client:connect': {\n attrs['agent.mcp.url'] = event.payload.url;\n attrs['agent.mcp.transport'] = event.payload.transport;\n attrs['agent.mcp.state'] = event.payload.state;\n if (event.payload.error) {\n attrs['agent.mcp.error'] = event.payload.error;\n }\n break;\n }\n\n case 'mcp:client:authorize': {\n attrs['agent.mcp.server_id'] = event.payload.serverId;\n attrs['agent.mcp.auth_url'] = event.payload.authUrl;\n if (event.payload.clientId) {\n attrs['agent.mcp.client_id'] = event.payload.clientId;\n }\n break;\n }\n }\n\n // Add any additional payload properties as attributes\n for (const [key, value] of Object.entries(event.payload)) {\n if (\n attrs[`agent.${key}`] === undefined &&\n (typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean')\n ) {\n attrs[`agent.payload.${key}`] = value;\n }\n }\n\n return attrs;\n}\n\n/**\n * Determine span kind based on event type\n */\nfunction getSpanKind(event: ObservabilityEvent): SpanKind {\n switch (event.type) {\n case 'rpc': {\n return SpanKind.SERVER;\n }\n case 'connect': {\n return SpanKind.SERVER;\n }\n case 'mcp:client:connect':\n case 'mcp:client:preconnect':\n case 'mcp:client:authorize':\n case 'mcp:client:discover': {\n return SpanKind.CLIENT;\n }\n default: {\n return SpanKind.INTERNAL;\n }\n }\n}\n\n/**\n * Check if an event type should be traced based on options\n */\nfunction shouldTraceEvent(\n event: ObservabilityEvent,\n options: AgentInstrumentationOptions,\n): boolean {\n const defaults: AgentInstrumentationOptions = {\n traceRpc: true,\n traceSchedule: true,\n traceMcp: true,\n traceStateUpdates: false,\n traceMessages: true,\n traceLifecycle: true,\n };\n\n const opts = { ...defaults, ...options };\n\n switch (event.type) {\n case 'rpc': {\n return opts.traceRpc ?? true;\n }\n\n case 'schedule:create':\n case 'schedule:execute':\n case 'schedule:cancel': {\n return opts.traceSchedule ?? true;\n }\n\n case 'mcp:client:preconnect':\n case 'mcp:client:connect':\n case 'mcp:client:authorize':\n case 'mcp:client:discover': {\n return opts.traceMcp ?? true;\n }\n\n case 'state:update': {\n return opts.traceStateUpdates ?? false;\n }\n\n case 'message:request':\n case 'message:response':\n case 'message:clear': {\n return opts.traceMessages ?? true;\n }\n\n case 'connect':\n case 'destroy': {\n return opts.traceLifecycle ?? true;\n }\n\n default: {\n return true;\n }\n }\n}\n\n/**\n * Export spans asynchronously\n */\nasync function exportSpans(\n traceId: string,\n ctx?: DurableObjectState | ExecutionContext,\n): Promise<void> {\n const tracer = trace.getTracer('autotel-cloudflare/agents');\n if (tracer instanceof WorkerTracer) {\n try {\n // scheduler is only available on ExecutionContext, not DurableObjectState\n if (ctx && 'scheduler' in ctx) {\n const ctxWithScheduler = ctx as ExecutionContext & { scheduler?: { wait(ms: number): Promise<void> } };\n if (ctxWithScheduler.scheduler) {\n await ctxWithScheduler.scheduler.wait(1);\n }\n }\n await tracer.forceFlush(traceId);\n } catch (error) {\n console.error('[autotel-cloudflare/agents] Failed to export spans:', error);\n }\n }\n\n // If we have a DurableObject context, use waitUntil for export\n if (ctx && 'waitUntil' in ctx) {\n // Already exported above, but could defer more work here\n }\n}\n\n/**\n * OpenTelemetry-based Observability implementation\n *\n * Implements the Agents SDK Observability interface and converts\n * events into OpenTelemetry spans.\n */\nexport class OtelObservability implements Observability {\n private config: ResolvedEdgeConfig;\n private options: AgentInstrumentationOptions;\n private initialized = false;\n\n constructor(config: OtelObservabilityConfig) {\n // Use createInitialiser to resolve the config\n const initialiser = createInitialiser(config);\n this.config = initialiser({}, undefined);\n this.options = config.agents ?? {};\n }\n\n /**\n * Initialize the tracer provider (called lazily on first emit)\n */\n private initialize(): void {\n if (this.initialized) return;\n initProvider(this.config);\n this.initialized = true;\n }\n\n /**\n * Emit an observability event\n *\n * Converts the event to an OpenTelemetry span based on the event type.\n */\n emit(event: ObservabilityEvent, ctx?: DurableObjectState): void {\n // Initialize provider on first emit\n this.initialize();\n\n // Check if this event type should be traced\n if (!shouldTraceEvent(event, this.options)) {\n return;\n }\n\n const tracer = trace.getTracer('autotel-cloudflare/agents');\n\n // Get span name (custom or default)\n const spanName = this.options.spanNameFormatter\n ? this.options.spanNameFormatter(event)\n : getDefaultSpanName(event);\n\n // Get attributes (custom + default)\n const defaultAttrs = getDefaultAttributes(event);\n const customAttrs = this.options.attributeExtractor\n ? this.options.attributeExtractor(event)\n : {};\n const attributes = { ...defaultAttrs, ...customAttrs };\n\n // Determine span kind\n const kind = getSpanKind(event);\n\n // Create span with event timestamp\n const span = tracer.startSpan(spanName, {\n kind,\n attributes,\n startTime: event.timestamp,\n });\n\n // For short-lived events, end immediately\n // For events that have duration (like RPC), we would ideally track start/end\n // But the Agents SDK emits single events, so we create point-in-time spans\n span.setStatus({ code: SpanStatusCode.OK });\n span.end(event.timestamp + 1); // End 1ms after start\n\n // Store span for potential correlation\n activeSpans.set(event.id, span);\n\n // Schedule span export\n const traceId = span.spanContext().traceId;\n if (ctx && 'waitUntil' in ctx && typeof (ctx as any).waitUntil === 'function') {\n (ctx as any).waitUntil(exportSpans(traceId, ctx));\n } else {\n // In environments without waitUntil, export synchronously-ish\n void exportSpans(traceId, ctx);\n }\n }\n}\n\n/**\n * Create an OtelObservability instance\n *\n * @example\n * ```typescript\n * import { Agent } from 'agents'\n * import { createOtelObservability } from 'autotel-cloudflare/agents'\n *\n * class MyAgent extends Agent<Env> {\n * observability = createOtelObservability({\n * service: { name: 'my-agent' },\n * exporter: { url: env.OTLP_ENDPOINT }\n * })\n * }\n * ```\n */\nexport function createOtelObservability(config: OtelObservabilityConfig): OtelObservability {\n return new OtelObservability(config);\n}\n\n/**\n * Create an OtelObservability instance with environment-based config\n *\n * Use this when you need to access environment variables for configuration.\n *\n * @example\n * ```typescript\n * import { Agent } from 'agents'\n * import { createOtelObservabilityFromEnv } from 'autotel-cloudflare/agents'\n *\n * class MyAgent extends Agent<Env> {\n * observability?: OtelObservability\n *\n * constructor(state: DurableObjectState, env: Env) {\n * super(state, env)\n * this.observability = createOtelObservabilityFromEnv(env)\n * }\n * }\n * ```\n */\nexport function createOtelObservabilityFromEnv(\n env: Record<string, unknown>,\n options?: AgentInstrumentationOptions,\n): OtelObservability {\n // Extract standard OTLP env vars\n const endpoint = (env.OTEL_EXPORTER_OTLP_ENDPOINT as string) || undefined;\n const serviceName = (env.OTEL_SERVICE_NAME as string) || 'cloudflare-agent';\n\n // Parse headers if present\n let headers: Record<string, string> | undefined;\n const headersStr = env.OTEL_EXPORTER_OTLP_HEADERS as string;\n if (headersStr) {\n headers = {};\n for (const pair of headersStr.split(',')) {\n const [key, value] = pair.split('=');\n if (key && value) {\n headers[key.trim()] = value.trim();\n }\n }\n }\n\n // If no endpoint is configured, use a default localhost endpoint\n // In production, users should set OTEL_EXPORTER_OTLP_ENDPOINT\n const exporterUrl = endpoint || 'http://localhost:4318/v1/traces';\n\n return createOtelObservability({\n service: { name: serviceName },\n exporter: { url: exporterUrl, headers },\n agents: options,\n });\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"agents.js","names":[],"sources":["../src/agents/otel-observability.ts","../src/agents/observability.ts"],"sourcesContent":["/**\n * OpenTelemetry-based Observability implementation for Cloudflare Agents SDK\n *\n * Converts Agent events into OpenTelemetry spans for distributed tracing.\n */\n\nimport {\n SpanKind,\n SpanStatusCode,\n trace,\n type Attributes,\n type Span,\n} from '@opentelemetry/api';\nimport { resourceFromAttributes } from '@opentelemetry/resources';\nimport {\n WorkerTracer,\n WorkerTracerProvider,\n createInitialiser,\n type ResolvedEdgeConfig,\n} from 'autotel-edge';\nimport type {\n AgentInstrumentationOptions,\n MCPObservabilityEvent,\n Observability,\n ObservabilityEvent,\n ObservabilityExecutionContext,\n OtelObservabilityConfig,\n} from './types';\n\nlet providerInitialized = false;\n\ntype EventCategory =\n | 'state'\n | 'rpc'\n | 'schedule'\n | 'queue'\n | 'submission'\n | 'message'\n | 'chat'\n | 'transcript'\n | 'fiber'\n | 'agentTool'\n | 'lifecycle'\n | 'workflow'\n | 'mcp'\n | 'email';\n\nfunction initProvider(config: ResolvedEdgeConfig): void {\n if (providerInitialized) return;\n\n const resource = resourceFromAttributes({\n 'service.name': config.service.name,\n 'service.version': config.service.version,\n 'service.namespace': config.service.namespace,\n 'cloud.provider': 'cloudflare',\n 'cloud.platform': 'cloudflare.workers',\n 'telemetry.sdk.name': 'autotel-cloudflare',\n 'telemetry.sdk.language': 'js',\n 'agent.framework': 'cloudflare-agents',\n });\n\n const provider = new WorkerTracerProvider(config.spanProcessors, resource);\n provider.register();\n\n const tracer = trace.getTracer('autotel-cloudflare/agents') as WorkerTracer;\n tracer.setHeadSampler(config.sampling.headSampler);\n\n providerInitialized = true;\n}\n\nfunction classifyEvent(type: ObservabilityEvent['type']): EventCategory {\n if (type.startsWith('mcp:')) return 'mcp';\n if (type.startsWith('workflow:')) return 'workflow';\n if (type.startsWith('fiber:')) return 'fiber';\n if (type.startsWith('agent_tool:')) return 'agentTool';\n if (type.startsWith('chat:transcript:')) return 'transcript';\n if (type.startsWith('chat:')) return 'chat';\n if (type.startsWith('submission:')) return 'submission';\n if (type.startsWith('queue:')) return 'queue';\n if (type.startsWith('schedule:')) return 'schedule';\n if (\n type.startsWith('message:') ||\n type.startsWith('tool:') ||\n type === 'rpc:error'\n ) {\n return 'message';\n }\n if (type === 'rpc') return 'rpc';\n if (type.startsWith('state:')) return 'state';\n if (type.startsWith('email:')) return 'email';\n if (type === 'connect' || type === 'disconnect' || type === 'destroy') {\n return 'lifecycle';\n }\n return 'message';\n}\n\nfunction shouldTraceEvent(\n event: ObservabilityEvent,\n options: AgentInstrumentationOptions,\n): boolean {\n const opts: Required<\n Pick<\n AgentInstrumentationOptions,\n | 'traceRpc'\n | 'traceSchedule'\n | 'traceQueue'\n | 'traceSubmissions'\n | 'traceMcp'\n | 'traceStateUpdates'\n | 'traceMessages'\n | 'traceLifecycle'\n | 'traceChat'\n | 'traceTranscripts'\n | 'traceFibers'\n | 'traceToolRecovery'\n | 'traceWorkflow'\n | 'traceEmail'\n >\n > = {\n traceRpc: true,\n traceSchedule: true,\n traceQueue: true,\n traceSubmissions: true,\n traceMcp: true,\n traceStateUpdates: false,\n traceMessages: true,\n traceLifecycle: true,\n traceChat: true,\n traceTranscripts: true,\n traceFibers: true,\n traceToolRecovery: true,\n traceWorkflow: true,\n traceEmail: true,\n };\n const merged = { ...opts, ...options };\n\n switch (classifyEvent(event.type)) {\n case 'rpc': {\n return merged.traceRpc;\n }\n case 'schedule': {\n return merged.traceSchedule;\n }\n case 'queue': {\n return merged.traceQueue;\n }\n case 'submission': {\n return merged.traceSubmissions;\n }\n case 'mcp': {\n return merged.traceMcp;\n }\n case 'state': {\n return merged.traceStateUpdates;\n }\n case 'message': {\n return merged.traceMessages;\n }\n case 'lifecycle': {\n return merged.traceLifecycle;\n }\n case 'chat': {\n return merged.traceChat;\n }\n case 'transcript': {\n return merged.traceTranscripts;\n }\n case 'fiber': {\n return merged.traceFibers;\n }\n case 'agentTool': {\n return merged.traceToolRecovery;\n }\n case 'workflow': {\n return merged.traceWorkflow;\n }\n case 'email': {\n return merged.traceEmail;\n }\n }\n}\n\nfunction formatTypeSegment(value: string): string {\n return value.replaceAll(/[:_]/g, '.');\n}\n\nfunction getPayloadName(\n payload: Record<string, unknown>,\n ...keys: string[]\n): string | undefined {\n for (const key of keys) {\n const value = payload[key];\n if (typeof value === 'string' && value.length > 0) {\n return value;\n }\n }\n return undefined;\n}\n\nfunction getDefaultSpanName(event: ObservabilityEvent): string {\n const payload = event.payload;\n\n switch (event.type) {\n case 'rpc':\n case 'rpc:error': {\n return `agent.rpc ${(payload as { method: string }).method}`;\n }\n case 'schedule:create':\n case 'schedule:execute':\n case 'schedule:cancel':\n case 'schedule:retry':\n case 'schedule:error':\n case 'schedule:duplicate_warning': {\n return `agent.${formatTypeSegment(event.type)} ${getPayloadName(payload, 'callback') ?? 'unknown'}`;\n }\n case 'queue:create':\n case 'queue:retry':\n case 'queue:error': {\n return `agent.${formatTypeSegment(event.type)} ${getPayloadName(payload, 'callback') ?? 'unknown'}`;\n }\n case 'submission:create':\n case 'submission:status':\n case 'submission:error': {\n return `agent.${formatTypeSegment(event.type)} ${getPayloadName(payload, 'submissionId') ?? 'unknown'}`;\n }\n case 'connect':\n case 'disconnect': {\n return `agent.${event.type} ${getPayloadName(payload, 'connectionId') ?? 'unknown'}`;\n }\n case 'mcp:client:preconnect': {\n return `mcp.client.preconnect ${getPayloadName(payload, 'serverId') ?? 'unknown'}`;\n }\n case 'mcp:client:authorize': {\n return `mcp.client.authorize ${getPayloadName(payload, 'serverId') ?? 'unknown'}`;\n }\n case 'mcp:client:connect':\n case 'mcp:client:discover':\n case 'mcp:client:close': {\n return `mcp.client.${formatTypeSegment(event.type).split('.').slice(-1)[0]} ${\n getPayloadName(payload, 'url', 'capability', 'state') ?? 'unknown'\n }`;\n }\n case 'workflow:start':\n case 'workflow:event':\n case 'workflow:approved':\n case 'workflow:rejected':\n case 'workflow:terminated':\n case 'workflow:paused':\n case 'workflow:resumed':\n case 'workflow:restarted': {\n return `agent.${formatTypeSegment(event.type)} ${\n getPayloadName(payload, 'workflowName', 'workflowId', 'eventType') ?? 'unknown'\n }`;\n }\n case 'email:receive':\n case 'email:reply':\n case 'email:send': {\n return `agent.${formatTypeSegment(event.type)} ${getPayloadName(payload, 'subject') ?? 'message'}`;\n }\n case 'destroy': {\n return 'agent.destroy';\n }\n default: {\n return `agent.${formatTypeSegment(event.type)}`;\n }\n }\n}\n\nfunction isPrimitiveAttributeValue(\n value: unknown,\n): value is string | number | boolean | string[] | number[] | boolean[] {\n if (\n typeof value === 'string' ||\n typeof value === 'number' ||\n typeof value === 'boolean'\n ) {\n return true;\n }\n\n if (!Array.isArray(value)) {\n return false;\n }\n\n return value.every(\n (entry) =>\n typeof entry === 'string' ||\n typeof entry === 'number' ||\n typeof entry === 'boolean',\n );\n}\n\nfunction setIfPresent(\n attrs: Attributes,\n key: string,\n value: unknown,\n): void {\n if (value === undefined || value === null) return;\n if (isPrimitiveAttributeValue(value)) {\n attrs[key] = value;\n }\n}\n\nfunction getDefaultAttributes(event: ObservabilityEvent): Attributes {\n const attrs: Attributes = {\n 'agent.event.type': event.type,\n };\n\n setIfPresent(attrs, 'agent.event.id', event.id);\n setIfPresent(attrs, 'agent.display_message', event.displayMessage);\n setIfPresent(attrs, 'agent.class', event.agent);\n setIfPresent(attrs, 'agent.instance.name', event.name);\n setIfPresent(attrs, 'gen_ai.agent.name', event.agent);\n\n switch (event.type) {\n case 'rpc': {\n attrs['agent.rpc.method'] = event.payload.method;\n setIfPresent(attrs, 'agent.rpc.streaming', event.payload.streaming);\n break;\n }\n case 'rpc:error': {\n attrs['agent.rpc.method'] = event.payload.method;\n break;\n }\n case 'schedule:create':\n case 'schedule:execute':\n case 'schedule:cancel':\n case 'schedule:retry':\n case 'schedule:error':\n case 'queue:create':\n case 'queue:retry':\n case 'queue:error': {\n setIfPresent(attrs, 'agent.schedule.callback', event.payload.callback);\n setIfPresent(attrs, 'agent.schedule.id', event.payload.id);\n break;\n }\n case 'schedule:duplicate_warning': {\n setIfPresent(attrs, 'agent.schedule.callback', event.payload.callback);\n break;\n }\n case 'connect':\n case 'disconnect': {\n setIfPresent(attrs, 'agent.connection.id', event.payload.connectionId);\n break;\n }\n case 'mcp:client:preconnect': {\n setIfPresent(attrs, 'agent.mcp.server_id', event.payload.serverId);\n break;\n }\n case 'mcp:client:connect':\n case 'mcp:client:close': {\n setIfPresent(attrs, 'agent.mcp.url', event.payload.url);\n setIfPresent(attrs, 'agent.mcp.transport', event.payload.transport);\n setIfPresent(attrs, 'agent.mcp.state', event.payload.state);\n break;\n }\n case 'mcp:client:authorize': {\n setIfPresent(attrs, 'agent.mcp.server_id', event.payload.serverId);\n setIfPresent(attrs, 'agent.mcp.auth_url', event.payload.authUrl);\n setIfPresent(attrs, 'agent.mcp.client_id', event.payload.clientId);\n break;\n }\n case 'mcp:client:discover': {\n setIfPresent(attrs, 'agent.mcp.url', event.payload.url);\n setIfPresent(attrs, 'agent.mcp.state', event.payload.state);\n setIfPresent(attrs, 'agent.mcp.capability', event.payload.capability);\n break;\n }\n }\n\n for (const [key, value] of Object.entries(event.payload)) {\n setIfPresent(attrs, `agent.payload.${key}`, value);\n }\n\n return attrs;\n}\n\nfunction getSpanKind(event: ObservabilityEvent): SpanKind {\n switch (classifyEvent(event.type)) {\n case 'rpc':\n case 'lifecycle':\n case 'email': {\n return SpanKind.SERVER;\n }\n case 'mcp': {\n return SpanKind.CLIENT;\n }\n case 'schedule':\n case 'queue': {\n return SpanKind.CONSUMER;\n }\n default: {\n return SpanKind.INTERNAL;\n }\n }\n}\n\nfunction inferErrorMessage(event: ObservabilityEvent): string | undefined {\n const payload = event.payload as Record<string, unknown>;\n const direct = payload.error;\n if (typeof direct === 'string' && direct.length > 0) {\n return direct;\n }\n\n if (event.type === 'workflow:rejected') {\n const reason = payload.reason;\n if (typeof reason === 'string' && reason.length > 0) {\n return reason;\n }\n return 'workflow rejected';\n }\n\n if (event.type.endsWith(':failed') || event.type.endsWith(':error')) {\n return event.type;\n }\n\n return undefined;\n}\n\nfunction isErrorEvent(event: ObservabilityEvent): boolean {\n if (event.type === 'workflow:rejected') return true;\n if (event.type.endsWith(':error') || event.type.endsWith(':failed')) return true;\n\n if ('error' in event.payload) {\n return typeof (event.payload as Record<string, unknown>).error === 'string';\n }\n\n return false;\n}\n\nfunction applyEventStatus(span: Span, event: ObservabilityEvent): void {\n if (!isErrorEvent(event)) {\n span.setStatus({ code: SpanStatusCode.OK });\n return;\n }\n\n const message = inferErrorMessage(event);\n span.setStatus({\n code: SpanStatusCode.ERROR,\n message,\n });\n span.setAttribute('error', true);\n\n if (message) {\n span.setAttribute('exception.message', message);\n }\n}\n\nasync function exportSpans(\n traceId: string,\n ctx?: ObservabilityExecutionContext,\n): Promise<void> {\n const tracer = trace.getTracer('autotel-cloudflare/agents');\n if (tracer instanceof WorkerTracer) {\n try {\n const scheduler = ctx && 'scheduler' in ctx\n ? (ctx.scheduler as { wait?: (ms: number) => Promise<void> } | undefined)\n : undefined;\n if (scheduler?.wait) {\n await scheduler.wait(1);\n }\n await tracer.forceFlush(traceId);\n } catch (error) {\n console.error('[autotel-cloudflare/agents] Failed to export spans:', error);\n }\n }\n}\n\n/**\n * OpenTelemetry-based Observability implementation\n *\n * Implements the Agents SDK Observability interface and converts\n * events into OpenTelemetry spans.\n */\nexport class OtelObservability implements Observability {\n private readonly config: ResolvedEdgeConfig;\n private readonly options: AgentInstrumentationOptions;\n private initialized = false;\n\n constructor(config: OtelObservabilityConfig) {\n const initialiser = createInitialiser(config);\n this.config = initialiser({}, undefined);\n this.options = config.agents ?? {};\n }\n\n private initialize(): void {\n if (this.initialized) return;\n initProvider(this.config);\n this.initialized = true;\n }\n\n emit(event: ObservabilityEvent, ctx?: ObservabilityExecutionContext): void {\n this.initialize();\n\n if (!shouldTraceEvent(event, this.options)) {\n return;\n }\n\n const tracer = trace.getTracer('autotel-cloudflare/agents');\n const spanName = this.options.spanNameFormatter\n ? this.options.spanNameFormatter(event)\n : getDefaultSpanName(event);\n const defaultAttrs = getDefaultAttributes(event);\n const customAttrs = this.options.attributeExtractor\n ? this.options.attributeExtractor(event)\n : {};\n const span = tracer.startSpan(spanName, {\n kind: getSpanKind(event),\n attributes: { ...defaultAttrs, ...customAttrs },\n startTime: event.timestamp,\n });\n\n applyEventStatus(span, event);\n span.end(event.timestamp + 1);\n\n const traceId = span.spanContext().traceId;\n if (ctx && 'waitUntil' in ctx && typeof ctx.waitUntil === 'function') {\n ctx.waitUntil(exportSpans(traceId, ctx));\n return;\n }\n\n void exportSpans(traceId, ctx);\n }\n}\n\nexport function createOtelObservability(\n config: OtelObservabilityConfig,\n): OtelObservability {\n return new OtelObservability(config);\n}\n\nexport function createOtelObservabilityFromEnv(\n env: Record<string, unknown>,\n options?: AgentInstrumentationOptions,\n): OtelObservability {\n const endpoint = (env.OTEL_EXPORTER_OTLP_ENDPOINT as string) || undefined;\n const serviceName = (env.OTEL_SERVICE_NAME as string) || 'cloudflare-agent';\n\n let headers: Record<string, string> | undefined;\n const headersStr = env.OTEL_EXPORTER_OTLP_HEADERS as string;\n if (headersStr) {\n headers = {};\n for (const pair of headersStr.split(',')) {\n const [key, value] = pair.split('=');\n if (key && value) {\n headers[key.trim()] = value.trim();\n }\n }\n }\n\n return createOtelObservability({\n service: { name: serviceName },\n exporter: { url: endpoint || 'http://localhost:4318/v1/traces', headers },\n agents: options,\n });\n}\n\nexport type { MCPObservabilityEvent };\n","import type { AgentObservabilityEvent } from './agent';\nimport type { MCPObservabilityEvent } from './mcp';\n\nexport type ObservabilityEvent = AgentObservabilityEvent | MCPObservabilityEvent;\n\nexport interface Observability {\n emit(event: ObservabilityEvent, ctx?: DurableObjectState | ExecutionContext): void;\n}\n\ntype ChannelKey =\n | 'state'\n | 'rpc'\n | 'message'\n | 'chat'\n | 'transcript'\n | 'fiber'\n | 'agentTool'\n | 'schedule'\n | 'lifecycle'\n | 'workflow'\n | 'mcp'\n | 'email';\n\nexport type ChannelEventMap = {\n state: Extract<ObservabilityEvent, { type: `state:${string}` }>;\n rpc: Extract<ObservabilityEvent, { type: 'rpc' | `rpc:${string}` }>;\n message: Extract<\n ObservabilityEvent,\n { type: `message:${string}` | `tool:${string}` | `submission:${string}` }\n >;\n chat: Exclude<\n Extract<ObservabilityEvent, { type: `chat:${string}` }>,\n { type: `chat:transcript:${string}` }\n >;\n transcript: Extract<\n ObservabilityEvent,\n { type: `transcript:${string}` | `chat:transcript:${string}` }\n >;\n fiber: Extract<ObservabilityEvent, { type: `fiber:${string}` }>;\n agentTool: Extract<ObservabilityEvent, { type: `agent_tool:${string}` }>;\n schedule: Extract<\n ObservabilityEvent,\n { type: `schedule:${string}` | `queue:${string}` }\n >;\n lifecycle: Extract<\n ObservabilityEvent,\n { type: 'connect' | 'disconnect' | 'destroy' }\n >;\n workflow: Extract<ObservabilityEvent, { type: `workflow:${string}` }>;\n mcp: Extract<ObservabilityEvent, { type: `mcp:${string}` }>;\n email: Extract<ObservabilityEvent, { type: `email:${string}` }>;\n};\n\nexport interface ObservabilityChannel<TEvent extends ObservabilityEvent = ObservabilityEvent> {\n name: string;\n publish(event: TEvent): void;\n}\n\nconst listeners: {\n [K in ChannelKey]: Set<(event: ChannelEventMap[K]) => void>;\n} = {\n state: new Set(),\n rpc: new Set(),\n message: new Set(),\n chat: new Set(),\n transcript: new Set(),\n fiber: new Set(),\n agentTool: new Set(),\n schedule: new Set(),\n lifecycle: new Set(),\n workflow: new Set(),\n mcp: new Set(),\n email: new Set(),\n};\n\nfunction createChannel<K extends ChannelKey>(\n key: K,\n name: string,\n): ObservabilityChannel<ChannelEventMap[K]> {\n return {\n name,\n publish(event) {\n for (const callback of listeners[key]) {\n callback(event);\n }\n },\n };\n}\n\nexport const channels = {\n state: createChannel('state', 'agents:state'),\n rpc: createChannel('rpc', 'agents:rpc'),\n message: createChannel('message', 'agents:message'),\n chat: createChannel('chat', 'agents:chat'),\n transcript: createChannel('transcript', 'agents:transcript'),\n fiber: createChannel('fiber', 'agents:fiber'),\n agentTool: createChannel('agentTool', 'agents:agent_tool'),\n schedule: createChannel('schedule', 'agents:schedule'),\n lifecycle: createChannel('lifecycle', 'agents:lifecycle'),\n workflow: createChannel('workflow', 'agents:workflow'),\n mcp: createChannel('mcp', 'agents:mcp'),\n email: createChannel('email', 'agents:email'),\n} as const;\n\nfunction getChannel(type: string): ObservabilityChannel {\n if (type.startsWith('mcp:')) return channels.mcp;\n if (type.startsWith('workflow:')) return channels.workflow;\n if (type.startsWith('fiber:')) return channels.fiber;\n if (type.startsWith('transcript:') || type.startsWith('chat:transcript:')) {\n return channels.transcript;\n }\n if (type.startsWith('chat:')) return channels.chat;\n if (type.startsWith('agent_tool:')) return channels.agentTool;\n if (type.startsWith('schedule:') || type.startsWith('queue:')) {\n return channels.schedule;\n }\n if (\n type.startsWith('message:') ||\n type.startsWith('tool:') ||\n type.startsWith('submission:')\n ) {\n return channels.message;\n }\n if (type === 'rpc' || type.startsWith('rpc:')) return channels.rpc;\n if (type.startsWith('state:')) return channels.state;\n if (type.startsWith('email:')) return channels.email;\n return channels.lifecycle;\n}\n\nexport const genericObservability: Observability = {\n emit(event) {\n getChannel(event.type).publish(event);\n },\n};\n\nexport function subscribe<K extends keyof ChannelEventMap>(\n channelKey: K,\n callback: (event: ChannelEventMap[K]) => void,\n): () => void {\n const bucket = listeners[channelKey];\n bucket.add(callback);\n return () => {\n bucket.delete(callback);\n };\n}\n"],"mappings":"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"}