@raindrop-ai/ai-sdk 0.2.1 → 0.3.1
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/README.md +114 -0
- package/dist/{chunk-V636SYSR.mjs → chunk-SGSAYTKI.mjs} +917 -126
- package/dist/{index-BUWOlY-2.d.mts → index-BqXHiknB.d.mts} +532 -1
- package/dist/{index-BUWOlY-2.d.ts → index-BqXHiknB.d.ts} +532 -1
- package/dist/index.browser.d.mts +532 -1
- package/dist/index.browser.d.ts +532 -1
- package/dist/index.browser.js +929 -125
- package/dist/index.browser.mjs +917 -126
- package/dist/index.node.d.mts +1 -1
- package/dist/index.node.d.ts +1 -1
- package/dist/index.node.js +929 -125
- 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 +929 -125
- package/dist/index.workers.mjs +1 -1
- package/package.json +2 -2
package/dist/index.browser.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// ../core/dist/chunk-
|
|
1
|
+
// ../core/dist/chunk-3V4MIA75.js
|
|
2
2
|
function normalizeFeatureFlags(input) {
|
|
3
3
|
if (Array.isArray(input)) {
|
|
4
4
|
return Object.fromEntries(input.map((name) => [name, "true"]));
|
|
@@ -61,6 +61,311 @@ function base64Encode(bytes) {
|
|
|
61
61
|
}
|
|
62
62
|
return out;
|
|
63
63
|
}
|
|
64
|
+
function base64ToHex(value) {
|
|
65
|
+
if (!value) return "";
|
|
66
|
+
const maybeBuffer = globalThis.Buffer;
|
|
67
|
+
if (maybeBuffer) {
|
|
68
|
+
return maybeBuffer.from(value, "base64").toString("hex");
|
|
69
|
+
}
|
|
70
|
+
const atobFn = globalThis.atob;
|
|
71
|
+
if (typeof atobFn !== "function") return "";
|
|
72
|
+
try {
|
|
73
|
+
const binary = atobFn(value);
|
|
74
|
+
let hex = "";
|
|
75
|
+
for (let i = 0; i < binary.length; i++) {
|
|
76
|
+
hex += (binary.charCodeAt(i) & 255).toString(16).padStart(2, "0");
|
|
77
|
+
}
|
|
78
|
+
return hex;
|
|
79
|
+
} catch (e) {
|
|
80
|
+
return "";
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
var HANDOFF_ATTRIBUTE_SUFFIXES = {
|
|
84
|
+
mode: "raindrop.handoff.mode",
|
|
85
|
+
childEventId: "raindrop.handoff.childEventId",
|
|
86
|
+
parentEventId: "raindrop.handoff.parentEventId",
|
|
87
|
+
parentSpanId: "raindrop.handoff.parentSpanId",
|
|
88
|
+
name: "raindrop.handoff.name",
|
|
89
|
+
terminal: "raindrop.handoff.terminal",
|
|
90
|
+
agentRole: "raindrop.agent.role"
|
|
91
|
+
};
|
|
92
|
+
var HANDOFF_ATTRIBUTE_PREFIXES = [
|
|
93
|
+
"ai.telemetry.metadata.",
|
|
94
|
+
"ai.settings.context.",
|
|
95
|
+
""
|
|
96
|
+
];
|
|
97
|
+
var AI_SDK_METADATA_PREFIX = "ai.telemetry.metadata.";
|
|
98
|
+
var DETACHED_MODE = "detached";
|
|
99
|
+
var SUBAGENT_AGENT_ROLE = "subagent";
|
|
100
|
+
var HANDOFF_TERMINAL_CANCELLED = "cancelled";
|
|
101
|
+
var TOOL_EVENTS_SUFFIX = "raindrop.toolEvents";
|
|
102
|
+
var TOOL_EVENTS_ALLOW = "allow";
|
|
103
|
+
var SUBAGENT_ABORT_OPERATION_ID = "ai.subagent.failed";
|
|
104
|
+
var SUBAGENT_ABORT_SPAN_NAME = SUBAGENT_ABORT_OPERATION_ID;
|
|
105
|
+
var DEFAULT_DISPATCH_SPAN_NAME = "launch_subagent";
|
|
106
|
+
var HANDOFF_TERMINAL_PROPERTY_KEY = HANDOFF_ATTRIBUTE_SUFFIXES.terminal;
|
|
107
|
+
function defined(entries) {
|
|
108
|
+
const out = {};
|
|
109
|
+
for (const [key, value] of Object.entries(entries)) {
|
|
110
|
+
if (typeof value === "string" && value.trim().length > 0) out[key] = value;
|
|
111
|
+
}
|
|
112
|
+
return out;
|
|
113
|
+
}
|
|
114
|
+
function detachedDispatchMetadata(dispatch) {
|
|
115
|
+
return defined({
|
|
116
|
+
[HANDOFF_ATTRIBUTE_SUFFIXES.mode]: DETACHED_MODE,
|
|
117
|
+
[HANDOFF_ATTRIBUTE_SUFFIXES.childEventId]: dispatch.childEventId,
|
|
118
|
+
[HANDOFF_ATTRIBUTE_SUFFIXES.name]: dispatch.name
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
function detachedChildMetadata(link) {
|
|
122
|
+
return defined({
|
|
123
|
+
[HANDOFF_ATTRIBUTE_SUFFIXES.parentEventId]: link.parentEventId,
|
|
124
|
+
[HANDOFF_ATTRIBUTE_SUFFIXES.parentSpanId]: link.parentSpanId,
|
|
125
|
+
[HANDOFF_ATTRIBUTE_SUFFIXES.name]: link.name,
|
|
126
|
+
[HANDOFF_ATTRIBUTE_SUFFIXES.agentRole]: SUBAGENT_AGENT_ROLE
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
function cancelledTerminalMetadata() {
|
|
130
|
+
return { [HANDOFF_ATTRIBUTE_SUFFIXES.terminal]: HANDOFF_TERMINAL_CANCELLED };
|
|
131
|
+
}
|
|
132
|
+
function cancelledTerminalAttributes() {
|
|
133
|
+
const bare = cancelledTerminalMetadata();
|
|
134
|
+
return { ...bare, ...withMetadataPrefix(bare) };
|
|
135
|
+
}
|
|
136
|
+
function toolEventsAllowMetadata() {
|
|
137
|
+
return { [TOOL_EVENTS_SUFFIX]: TOOL_EVENTS_ALLOW };
|
|
138
|
+
}
|
|
139
|
+
function withMetadataPrefix(metadata) {
|
|
140
|
+
const out = {};
|
|
141
|
+
for (const [key, value] of Object.entries(metadata)) {
|
|
142
|
+
out[key.startsWith(AI_SDK_METADATA_PREFIX) ? key : `${AI_SDK_METADATA_PREFIX}${key}`] = value;
|
|
143
|
+
}
|
|
144
|
+
return out;
|
|
145
|
+
}
|
|
146
|
+
function readHandoffField(metadata, suffix) {
|
|
147
|
+
for (const prefix of HANDOFF_ATTRIBUTE_PREFIXES) {
|
|
148
|
+
const value = metadata[`${prefix}${suffix}`];
|
|
149
|
+
if (typeof value === "string" && value.trim().length > 0) return value.trim();
|
|
150
|
+
}
|
|
151
|
+
return void 0;
|
|
152
|
+
}
|
|
153
|
+
function readDetachedChildLink(metadata) {
|
|
154
|
+
if (!metadata) return void 0;
|
|
155
|
+
const parentEventId = readHandoffField(metadata, HANDOFF_ATTRIBUTE_SUFFIXES.parentEventId);
|
|
156
|
+
if (!parentEventId) return void 0;
|
|
157
|
+
return {
|
|
158
|
+
parentEventId,
|
|
159
|
+
parentSpanId: readHandoffField(metadata, HANDOFF_ATTRIBUTE_SUFFIXES.parentSpanId),
|
|
160
|
+
name: readHandoffField(metadata, HANDOFF_ATTRIBUTE_SUFFIXES.name)
|
|
161
|
+
};
|
|
162
|
+
}
|
|
163
|
+
var BAGGAGE_KEYS = {
|
|
164
|
+
eventId: "raindrop-event-id",
|
|
165
|
+
childEventId: "raindrop-child-event-id",
|
|
166
|
+
name: "raindrop-handoff-name",
|
|
167
|
+
convoId: "raindrop-convo-id",
|
|
168
|
+
userId: "raindrop-user-id",
|
|
169
|
+
// The dispatch span and its trace, carried as fields as well as in
|
|
170
|
+
// `traceparent`. Not redundant: OTel's HTTP instrumentations rewrite
|
|
171
|
+
// `traceparent` from whatever span is current as the request goes out, so by
|
|
172
|
+
// the time the child reads it the ids name the HTTP client span and its trace
|
|
173
|
+
// instead of the dispatch. The child would then point its reverse reference at
|
|
174
|
+
// a span the launcher's UI does not know as a dispatch. A field states which
|
|
175
|
+
// span it means rather than meaning "whoever wrote this header last".
|
|
176
|
+
dispatchSpanId: "raindrop-dispatch-span-id",
|
|
177
|
+
traceId: "raindrop-trace-id"
|
|
178
|
+
};
|
|
179
|
+
var TRACEPARENT_HEADER = "traceparent";
|
|
180
|
+
var BAGGAGE_HEADER = "baggage";
|
|
181
|
+
var W3C_TRACE_ID = /^[0-9a-f]{32}$/;
|
|
182
|
+
var W3C_SPAN_ID = /^[0-9a-f]{16}$/;
|
|
183
|
+
function isW3CTraceId(value) {
|
|
184
|
+
return value !== void 0 && W3C_TRACE_ID.test(value);
|
|
185
|
+
}
|
|
186
|
+
function isW3CSpanId(value) {
|
|
187
|
+
return value !== void 0 && W3C_SPAN_ID.test(value);
|
|
188
|
+
}
|
|
189
|
+
var warnedNonConformantIds = false;
|
|
190
|
+
function warnNonConformantIdsOnce(traceId, spanId) {
|
|
191
|
+
if (warnedNonConformantIds) return;
|
|
192
|
+
warnedNonConformantIds = true;
|
|
193
|
+
console.warn(
|
|
194
|
+
`[raindrop] hand-off carrier ids are not W3C-shaped (traceId="${traceId}", spanId="${spanId}"). The child still reports as its own event, but its reverse reference names a span id the backend does not store, so the link back to the launcher will not resolve. A LangSmith carrier reads this way \u2014 its run ids are UUIDs; propagate Raindrop's own carrier (toHeaders) to link.`
|
|
195
|
+
);
|
|
196
|
+
}
|
|
197
|
+
var HANDOFF_HEADER = "x-raindrop-handoff";
|
|
198
|
+
var LANGSMITH_TRACE_HEADER = "langsmith-trace";
|
|
199
|
+
var LANGSMITH_METADATA_BAGGAGE_KEY = "langsmith-metadata";
|
|
200
|
+
function encodeBaggage(entries) {
|
|
201
|
+
return Object.entries(entries).filter((entry) => Boolean(entry[1])).map(([key, value]) => `${key}=${encodeURIComponent(value)}`).join(",");
|
|
202
|
+
}
|
|
203
|
+
function decodeBaggage(header) {
|
|
204
|
+
if (!header) return {};
|
|
205
|
+
const parsed = {};
|
|
206
|
+
for (const part of header.split(",")) {
|
|
207
|
+
const [rawKey, ...rest] = part.split("=");
|
|
208
|
+
if (!rawKey || rest.length === 0) continue;
|
|
209
|
+
const key = rawKey.trim();
|
|
210
|
+
let value;
|
|
211
|
+
try {
|
|
212
|
+
value = decodeURIComponent(rest.join("=").trim());
|
|
213
|
+
} catch (e) {
|
|
214
|
+
value = rest.join("=").trim();
|
|
215
|
+
}
|
|
216
|
+
if (key in parsed && parsed[key] !== value) throw new ConflictingCarrierError(key);
|
|
217
|
+
parsed[key] = value;
|
|
218
|
+
}
|
|
219
|
+
return parsed;
|
|
220
|
+
}
|
|
221
|
+
function carrierBaggage(carrier) {
|
|
222
|
+
return {
|
|
223
|
+
[BAGGAGE_KEYS.eventId]: carrier.eventId,
|
|
224
|
+
[BAGGAGE_KEYS.childEventId]: carrier.childEventId,
|
|
225
|
+
[BAGGAGE_KEYS.name]: carrier.name,
|
|
226
|
+
[BAGGAGE_KEYS.convoId]: carrier.convoId,
|
|
227
|
+
[BAGGAGE_KEYS.userId]: carrier.userId,
|
|
228
|
+
[BAGGAGE_KEYS.dispatchSpanId]: carrier.spanId,
|
|
229
|
+
[BAGGAGE_KEYS.traceId]: carrier.traceId
|
|
230
|
+
};
|
|
231
|
+
}
|
|
232
|
+
function toHeaders(carrier) {
|
|
233
|
+
const fields = encodeBaggage(carrierBaggage(carrier));
|
|
234
|
+
const headers = {
|
|
235
|
+
[BAGGAGE_HEADER]: fields,
|
|
236
|
+
[HANDOFF_HEADER]: fields
|
|
237
|
+
};
|
|
238
|
+
if (isW3CTraceId(carrier.traceId) && isW3CSpanId(carrier.spanId)) {
|
|
239
|
+
headers[TRACEPARENT_HEADER] = `00-${carrier.traceId}-${carrier.spanId}-01`;
|
|
240
|
+
}
|
|
241
|
+
return headers;
|
|
242
|
+
}
|
|
243
|
+
function langsmithStamp() {
|
|
244
|
+
return (/* @__PURE__ */ new Date()).toISOString().replace(/[-:]/g, "").replace(/\.\d+Z$/, "000000");
|
|
245
|
+
}
|
|
246
|
+
function toLangSmithHeaders(carrier) {
|
|
247
|
+
const stamp = langsmithStamp();
|
|
248
|
+
const dottedOrder = `${stamp}Z${carrier.traceId}.${stamp}Z${carrier.spanId}`;
|
|
249
|
+
return {
|
|
250
|
+
[LANGSMITH_TRACE_HEADER]: dottedOrder,
|
|
251
|
+
[BAGGAGE_HEADER]: encodeBaggage({
|
|
252
|
+
[LANGSMITH_METADATA_BAGGAGE_KEY]: JSON.stringify(carrierBaggage(carrier))
|
|
253
|
+
}),
|
|
254
|
+
// Carried here too: a LangSmith-shaped carrier is rewritten in transit
|
|
255
|
+
// exactly like the native one, and an injected `traceparent` is preferred
|
|
256
|
+
// over the dotted order on read.
|
|
257
|
+
[HANDOFF_HEADER]: encodeBaggage(carrierBaggage(carrier))
|
|
258
|
+
};
|
|
259
|
+
}
|
|
260
|
+
function isHeaderLookup(headers) {
|
|
261
|
+
return "get" in headers && typeof headers.get === "function";
|
|
262
|
+
}
|
|
263
|
+
var ConflictingCarrierError = class extends Error {
|
|
264
|
+
};
|
|
265
|
+
function readHeader(headers, name) {
|
|
266
|
+
var _a, _b, _c;
|
|
267
|
+
if (isHeaderLookup(headers)) return (_a = headers.get(name)) != null ? _a : void 0;
|
|
268
|
+
const value = (_c = headers[name]) != null ? _c : (_b = Object.entries(headers).find(([key]) => key.toLowerCase() === name)) == null ? void 0 : _b[1];
|
|
269
|
+
if (!Array.isArray(value)) return value;
|
|
270
|
+
const distinct = new Set(value);
|
|
271
|
+
if (distinct.size > 1) throw new ConflictingCarrierError(name);
|
|
272
|
+
return value[0];
|
|
273
|
+
}
|
|
274
|
+
function readTraceHeader(headers, name) {
|
|
275
|
+
const value = readHeader(headers, name);
|
|
276
|
+
if (!(value == null ? void 0 : value.includes(","))) return value;
|
|
277
|
+
const copies = value.split(",").map((copy) => copy.trim());
|
|
278
|
+
if (new Set(copies).size > 1) throw new ConflictingCarrierError(name);
|
|
279
|
+
return copies[0];
|
|
280
|
+
}
|
|
281
|
+
function fromHeaders(headers) {
|
|
282
|
+
var _a, _b;
|
|
283
|
+
let baggage;
|
|
284
|
+
let handoff;
|
|
285
|
+
let traceparent;
|
|
286
|
+
let langsmithTrace;
|
|
287
|
+
try {
|
|
288
|
+
baggage = decodeBaggage(readHeader(headers, BAGGAGE_HEADER));
|
|
289
|
+
handoff = decodeBaggage(readHeader(headers, HANDOFF_HEADER));
|
|
290
|
+
traceparent = readTraceHeader(headers, TRACEPARENT_HEADER);
|
|
291
|
+
langsmithTrace = readTraceHeader(headers, LANGSMITH_TRACE_HEADER);
|
|
292
|
+
} catch (error) {
|
|
293
|
+
if (error instanceof ConflictingCarrierError) return null;
|
|
294
|
+
throw error;
|
|
295
|
+
}
|
|
296
|
+
const langsmithMetadata = baggage[LANGSMITH_METADATA_BAGGAGE_KEY];
|
|
297
|
+
const nested = langsmithMetadata ? safeParseStringRecord(langsmithMetadata) : {};
|
|
298
|
+
for (const [key, value] of Object.entries(nested)) {
|
|
299
|
+
if (key in baggage && baggage[key] !== value) return null;
|
|
300
|
+
}
|
|
301
|
+
const fields = {
|
|
302
|
+
...baggage,
|
|
303
|
+
...nested,
|
|
304
|
+
// Last, so it wins: the standard headers may have been rewritten in transit
|
|
305
|
+
// by a propagator, this one is only ever written by us.
|
|
306
|
+
...handoff
|
|
307
|
+
};
|
|
308
|
+
let traceId;
|
|
309
|
+
let spanId;
|
|
310
|
+
if (traceparent) {
|
|
311
|
+
const [, parsedTraceId, parsedSpanId] = traceparent.split("-");
|
|
312
|
+
if (isW3CTraceId(parsedTraceId) && isW3CSpanId(parsedSpanId)) {
|
|
313
|
+
traceId = parsedTraceId;
|
|
314
|
+
spanId = parsedSpanId;
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
if (!traceId && !spanId && langsmithTrace) {
|
|
318
|
+
const segments = langsmithTrace.split(".");
|
|
319
|
+
traceId = (_a = segments[0]) == null ? void 0 : _a.split("Z").pop();
|
|
320
|
+
spanId = (_b = segments[segments.length - 1]) == null ? void 0 : _b.split("Z").pop();
|
|
321
|
+
}
|
|
322
|
+
traceId = fields[BAGGAGE_KEYS.traceId] || traceId;
|
|
323
|
+
spanId = fields[BAGGAGE_KEYS.dispatchSpanId] || spanId;
|
|
324
|
+
const eventId = fields[BAGGAGE_KEYS.eventId];
|
|
325
|
+
if (!traceId || !spanId || !eventId) return null;
|
|
326
|
+
if (!isW3CTraceId(traceId) || !isW3CSpanId(spanId)) {
|
|
327
|
+
warnNonConformantIdsOnce(traceId, spanId);
|
|
328
|
+
}
|
|
329
|
+
const carrier = { traceId, spanId, eventId };
|
|
330
|
+
const childEventId = fields[BAGGAGE_KEYS.childEventId];
|
|
331
|
+
if (childEventId) carrier.childEventId = childEventId;
|
|
332
|
+
const name = fields[BAGGAGE_KEYS.name];
|
|
333
|
+
if (name) carrier.name = name;
|
|
334
|
+
const convoId = fields[BAGGAGE_KEYS.convoId];
|
|
335
|
+
if (convoId) carrier.convoId = convoId;
|
|
336
|
+
const userId = fields[BAGGAGE_KEYS.userId];
|
|
337
|
+
if (userId) carrier.userId = userId;
|
|
338
|
+
return carrier;
|
|
339
|
+
}
|
|
340
|
+
var UNRESOLVED_CARRIER_WARNING = `[raindrop] resume: headers were supplied but no hand-off carrier was found on them (searched ${HANDOFF_HEADER}, ${TRACEPARENT_HEADER}, ${BAGGAGE_HEADER}). This run reports as an UNLINKED event, and the launcher that dispatched it will stay on "queued" forever because nothing ever references its child. Passing headers means a parent handed off, so no carrier on them is almost certainly a defect: a gateway or proxy stripping ${HANDOFF_HEADER}, a middleware overwriting ${BAGGAGE_HEADER}, a request forwarded without its headers, or a hand-built carrier whose field names do not match. Send every header the launcher's dispatch returned. Logged once per process; pass no headers for a directly-invoked sub-agent to silence it.`;
|
|
341
|
+
var UNRESOLVED_CARRIER_WARNED_KEY = /* @__PURE__ */ Symbol.for("raindrop.handoff.warnedUnresolvedCarrier");
|
|
342
|
+
function warnedHolder() {
|
|
343
|
+
return globalThis;
|
|
344
|
+
}
|
|
345
|
+
function resetUnresolvedCarrierWarning() {
|
|
346
|
+
warnedHolder()[UNRESOLVED_CARRIER_WARNED_KEY] = false;
|
|
347
|
+
}
|
|
348
|
+
function warnUnresolvedCarrier(headers, carrier) {
|
|
349
|
+
if (carrier) return;
|
|
350
|
+
if (!headers) return;
|
|
351
|
+
const holder = warnedHolder();
|
|
352
|
+
if (holder[UNRESOLVED_CARRIER_WARNED_KEY]) return;
|
|
353
|
+
holder[UNRESOLVED_CARRIER_WARNED_KEY] = true;
|
|
354
|
+
console.warn(UNRESOLVED_CARRIER_WARNING);
|
|
355
|
+
}
|
|
356
|
+
function safeParseStringRecord(raw) {
|
|
357
|
+
try {
|
|
358
|
+
const parsed = JSON.parse(raw);
|
|
359
|
+
if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) return {};
|
|
360
|
+
const result = {};
|
|
361
|
+
for (const [key, value] of Object.entries(parsed)) {
|
|
362
|
+
if (typeof value === "string") result[key] = value;
|
|
363
|
+
}
|
|
364
|
+
return result;
|
|
365
|
+
} catch (e) {
|
|
366
|
+
return {};
|
|
367
|
+
}
|
|
368
|
+
}
|
|
64
369
|
function runWithTracingSuppressed(fn) {
|
|
65
370
|
const hook = globalThis.RAINDROP_SUPPRESS_TRACING;
|
|
66
371
|
if (typeof hook !== "function") return fn();
|
|
@@ -825,6 +1130,7 @@ var EventShipper = class {
|
|
|
825
1130
|
}
|
|
826
1131
|
};
|
|
827
1132
|
var MODEL_USAGE_ATTRIBUTES = {
|
|
1133
|
+
usageSource: "raindrop.usage.source",
|
|
828
1134
|
providerName: "gen_ai.provider.name",
|
|
829
1135
|
requestModel: "gen_ai.request.model",
|
|
830
1136
|
responseModel: "gen_ai.response.model",
|
|
@@ -833,20 +1139,22 @@ var MODEL_USAGE_ATTRIBUTES = {
|
|
|
833
1139
|
reasoningTokens: "gen_ai.usage.reasoning_tokens",
|
|
834
1140
|
cacheReadInputTokens: "gen_ai.usage.cache_read_input_tokens",
|
|
835
1141
|
cacheWriteInputTokens: "gen_ai.usage.cache_write_input_tokens",
|
|
836
|
-
|
|
837
|
-
nonReasoningOutputTokens: "raindrop.usage.output_tokens.non_reasoning",
|
|
838
|
-
reasoningOutputTokens: "raindrop.usage.output_tokens.reasoning",
|
|
839
|
-
cacheReadTokens: "raindrop.usage.input_tokens.cache_read",
|
|
840
|
-
cacheWriteTokens: "raindrop.usage.input_tokens.cache_write"
|
|
841
|
-
};
|
|
1142
|
+
providerReportedCost: "gen_ai.usage.provider_reported_cost"};
|
|
842
1143
|
var MODEL_PROVIDER_NAMES = [
|
|
1144
|
+
["google.vertex.anthropic", "google-vertex"],
|
|
1145
|
+
["google.vertex_ai", "google-vertex"],
|
|
843
1146
|
["google.vertex", "google-vertex"],
|
|
1147
|
+
["gcp.vertex_ai", "google-vertex"],
|
|
1148
|
+
["gcp.gemini", "google"],
|
|
1149
|
+
["google_vertexai", "google-vertex"],
|
|
844
1150
|
["vertex.anthropic", "google-vertex"],
|
|
845
1151
|
["amazon-bedrock", "amazon-bedrock"],
|
|
1152
|
+
["aws.bedrock", "amazon-bedrock"],
|
|
846
1153
|
["bedrock", "amazon-bedrock"],
|
|
847
1154
|
["anthropic", "anthropic"],
|
|
848
1155
|
["openai", "openai"],
|
|
849
1156
|
["google", "google"],
|
|
1157
|
+
["az.ai.openai", "azure"],
|
|
850
1158
|
["azure", "azure"],
|
|
851
1159
|
["openrouter", "openrouter"]
|
|
852
1160
|
];
|
|
@@ -857,60 +1165,20 @@ function canonicalModelProvider(provider) {
|
|
|
857
1165
|
const match = MODEL_PROVIDER_NAMES.find(
|
|
858
1166
|
([family]) => normalizedProvider === family || normalizedProvider.startsWith(`${family}.`)
|
|
859
1167
|
);
|
|
860
|
-
return (_a = match == null ? void 0 : match[1]) != null ? _a :
|
|
1168
|
+
return (_a = match == null ? void 0 : match[1]) != null ? _a : normalizedProvider;
|
|
861
1169
|
}
|
|
862
1170
|
function tokenCount(value) {
|
|
863
1171
|
return typeof value === "number" && Number.isSafeInteger(value) && value >= 0 ? value : void 0;
|
|
864
1172
|
}
|
|
865
|
-
function
|
|
866
|
-
|
|
867
|
-
total,
|
|
868
|
-
parts,
|
|
869
|
-
semantics
|
|
870
|
-
}) {
|
|
871
|
-
if (explicit !== void 0) return explicit;
|
|
872
|
-
if (total === void 0) return void 0;
|
|
873
|
-
if (semantics === "exclusive") return total;
|
|
874
|
-
const observedParts = parts.filter((part) => part !== void 0 && part > 0);
|
|
875
|
-
if (semantics === void 0 && observedParts.length > 0) return void 0;
|
|
876
|
-
const exclusive = total - observedParts.reduce((sum, part) => sum + part, 0);
|
|
877
|
-
return exclusive >= 0 ? exclusive : void 0;
|
|
878
|
-
}
|
|
879
|
-
function buildModelUsageAttributes(usage) {
|
|
880
|
-
const inputTokens = tokenCount(usage.inputTokens);
|
|
881
|
-
const outputTokens = tokenCount(usage.outputTokens);
|
|
882
|
-
const explicitNonCachedInputTokens = tokenCount(usage.nonCachedInputTokens);
|
|
883
|
-
const explicitNonReasoningOutputTokens = tokenCount(usage.nonReasoningOutputTokens);
|
|
884
|
-
const reasoningTokens = tokenCount(usage.reasoningTokens);
|
|
885
|
-
const cacheReadInputTokens = tokenCount(usage.cacheReadInputTokens);
|
|
886
|
-
const cacheWriteInputTokens = tokenCount(usage.cacheWriteInputTokens);
|
|
887
|
-
const nonCachedInputTokens = exclusiveTokens({
|
|
888
|
-
explicit: explicitNonCachedInputTokens,
|
|
889
|
-
total: inputTokens,
|
|
890
|
-
parts: [cacheReadInputTokens, cacheWriteInputTokens],
|
|
891
|
-
semantics: usage.inputTokenSemantics
|
|
892
|
-
});
|
|
893
|
-
const nonReasoningOutputTokens = exclusiveTokens({
|
|
894
|
-
explicit: explicitNonReasoningOutputTokens,
|
|
895
|
-
total: outputTokens,
|
|
896
|
-
parts: [reasoningTokens],
|
|
897
|
-
semantics: usage.outputTokenSemantics
|
|
898
|
-
});
|
|
899
|
-
const exclusivePoolAttributes = nonCachedInputTokens !== void 0 && nonReasoningOutputTokens !== void 0 ? [
|
|
900
|
-
// backend consumes this complete raindrop.* set as one atomic billing-pool contract.
|
|
901
|
-
attrInt(MODEL_USAGE_ATTRIBUTES.nonCachedInputTokens, nonCachedInputTokens),
|
|
902
|
-
attrInt(MODEL_USAGE_ATTRIBUTES.nonReasoningOutputTokens, nonReasoningOutputTokens),
|
|
903
|
-
attrInt(MODEL_USAGE_ATTRIBUTES.reasoningOutputTokens, reasoningTokens),
|
|
904
|
-
attrInt(MODEL_USAGE_ATTRIBUTES.cacheReadTokens, cacheReadInputTokens),
|
|
905
|
-
attrInt(MODEL_USAGE_ATTRIBUTES.cacheWriteTokens, cacheWriteInputTokens)
|
|
906
|
-
] : [];
|
|
1173
|
+
function buildRawModelUsageAttributes(usage) {
|
|
1174
|
+
const providerReportedCost = typeof usage.providerReportedCost === "number" && Number.isFinite(usage.providerReportedCost) && usage.providerReportedCost >= 0 ? usage.providerReportedCost : void 0;
|
|
907
1175
|
return [
|
|
908
|
-
attrInt(MODEL_USAGE_ATTRIBUTES.inputTokens, inputTokens),
|
|
909
|
-
attrInt(MODEL_USAGE_ATTRIBUTES.outputTokens, outputTokens),
|
|
910
|
-
attrInt(MODEL_USAGE_ATTRIBUTES.reasoningTokens, reasoningTokens),
|
|
911
|
-
attrInt(MODEL_USAGE_ATTRIBUTES.cacheReadInputTokens, cacheReadInputTokens),
|
|
912
|
-
attrInt(MODEL_USAGE_ATTRIBUTES.cacheWriteInputTokens, cacheWriteInputTokens),
|
|
913
|
-
|
|
1176
|
+
attrInt(MODEL_USAGE_ATTRIBUTES.inputTokens, tokenCount(usage.inputTokens)),
|
|
1177
|
+
attrInt(MODEL_USAGE_ATTRIBUTES.outputTokens, tokenCount(usage.outputTokens)),
|
|
1178
|
+
attrInt(MODEL_USAGE_ATTRIBUTES.reasoningTokens, tokenCount(usage.reasoningTokens)),
|
|
1179
|
+
attrInt(MODEL_USAGE_ATTRIBUTES.cacheReadInputTokens, tokenCount(usage.cacheReadInputTokens)),
|
|
1180
|
+
attrInt(MODEL_USAGE_ATTRIBUTES.cacheWriteInputTokens, tokenCount(usage.cacheWriteInputTokens)),
|
|
1181
|
+
attrDouble(MODEL_USAGE_ATTRIBUTES.providerReportedCost, providerReportedCost)
|
|
914
1182
|
].filter((attribute) => attribute !== void 0);
|
|
915
1183
|
}
|
|
916
1184
|
var STRING_ALIASES = {
|
|
@@ -1548,7 +1816,7 @@ async function* asyncGeneratorWithCurrent(span, gen) {
|
|
|
1548
1816
|
// package.json
|
|
1549
1817
|
var package_default = {
|
|
1550
1818
|
name: "@raindrop-ai/ai-sdk",
|
|
1551
|
-
version: "0.
|
|
1819
|
+
version: "0.3.1"};
|
|
1552
1820
|
|
|
1553
1821
|
// src/internal/version.ts
|
|
1554
1822
|
var libraryName = package_default.name;
|
|
@@ -2436,37 +2704,361 @@ function runWithParentToolContext(ctx, fn) {
|
|
|
2436
2704
|
return getStorage2().run(ctx, fn);
|
|
2437
2705
|
}
|
|
2438
2706
|
|
|
2439
|
-
// src/internal/
|
|
2440
|
-
|
|
2441
|
-
|
|
2442
|
-
|
|
2443
|
-
|
|
2707
|
+
// src/internal/subagents.ts
|
|
2708
|
+
var SUBAGENT_CANCELLED_OUTPUT = "Cancelled before producing a result.";
|
|
2709
|
+
var SUBAGENT_ABORTED_OUTPUT = "Aborted before producing a result.";
|
|
2710
|
+
var SUBAGENT_FAILED_OPERATION_ID = SUBAGENT_ABORT_OPERATION_ID;
|
|
2711
|
+
var MAX_SETTLED_EVENT_IDS = 1024;
|
|
2712
|
+
function isTraceCarrier(value) {
|
|
2713
|
+
const candidate = value;
|
|
2714
|
+
return typeof candidate.traceId === "string" && typeof candidate.spanId === "string" && typeof candidate.eventId === "string";
|
|
2715
|
+
}
|
|
2716
|
+
function attrsFrom(metadata) {
|
|
2717
|
+
return Object.entries(withMetadataPrefix(metadata)).map(([key, value]) => attrString(key, value));
|
|
2718
|
+
}
|
|
2719
|
+
function attrsExact(attributes) {
|
|
2720
|
+
return Object.entries(attributes).map(([key, value]) => attrString(key, value));
|
|
2721
|
+
}
|
|
2722
|
+
function handoffSpanAttrs(link) {
|
|
2723
|
+
if (!link) return [];
|
|
2724
|
+
return attrsFrom(detachedChildMetadata(link));
|
|
2725
|
+
}
|
|
2726
|
+
function subagentNameAttrs(name, link) {
|
|
2727
|
+
if (!name || (link == null ? void 0 : link.name)) return [];
|
|
2728
|
+
return attrsFrom({ [HANDOFF_ATTRIBUTE_SUFFIXES.name]: name });
|
|
2729
|
+
}
|
|
2730
|
+
function cancelledSpanAttrs() {
|
|
2731
|
+
return attrsExact(cancelledTerminalAttributes());
|
|
2732
|
+
}
|
|
2733
|
+
function describeAbortReason(reason) {
|
|
2734
|
+
if (reason instanceof Error) return `Aborted: ${reason.message}`;
|
|
2735
|
+
if (typeof reason === "string" && reason.trim().length > 0) return reason;
|
|
2736
|
+
if (reason === void 0 || reason === null) return SUBAGENT_ABORTED_OUTPUT;
|
|
2737
|
+
const serialized = boundedStringify(reason);
|
|
2738
|
+
return serialized ? `Aborted: ${serialized}` : SUBAGENT_ABORTED_OUTPUT;
|
|
2739
|
+
}
|
|
2740
|
+
function stampOpenSpan(span, metadata) {
|
|
2741
|
+
if (span.endTimeUnixNano) return;
|
|
2742
|
+
span.attributes.push(...attrsFrom(metadata));
|
|
2743
|
+
}
|
|
2744
|
+
function stampOpenSpanExact(span, attributes) {
|
|
2745
|
+
if (span.endTimeUnixNano) return;
|
|
2746
|
+
span.attributes.push(...attrsExact(attributes));
|
|
2747
|
+
}
|
|
2748
|
+
var SubagentApi = class {
|
|
2749
|
+
constructor(opts) {
|
|
2750
|
+
var _a;
|
|
2751
|
+
this.opts = opts;
|
|
2752
|
+
this.settledEventIds = (_a = opts.settledEventIds) != null ? _a : /* @__PURE__ */ new Set();
|
|
2753
|
+
}
|
|
2754
|
+
/** True when this child's outcome has already been reported. */
|
|
2755
|
+
wasSettledExplicitly(eventId) {
|
|
2756
|
+
return this.settledEventIds.has(eventId);
|
|
2757
|
+
}
|
|
2758
|
+
/**
|
|
2759
|
+
* Record an outcome reported somewhere other than `cancel()` / `fail()`, so
|
|
2760
|
+
* first-outcome-wins holds across every path that can state one.
|
|
2761
|
+
*
|
|
2762
|
+
* An aborted generation is such a path: an AbortSignal cancellation IS the
|
|
2763
|
+
* run's outcome, and the `fail(err)` that a catch block around the aborted
|
|
2764
|
+
* call naturally reports would otherwise error the child's spans — which is
|
|
2765
|
+
* the only thing separating `failed` from `cancelled`.
|
|
2766
|
+
*/
|
|
2767
|
+
noteSettled(eventId) {
|
|
2768
|
+
this.remember(eventId);
|
|
2769
|
+
}
|
|
2770
|
+
remember(eventId) {
|
|
2771
|
+
if (this.settledEventIds.has(eventId)) return;
|
|
2772
|
+
if (this.settledEventIds.size >= MAX_SETTLED_EVENT_IDS) {
|
|
2773
|
+
const oldest = this.settledEventIds.values().next();
|
|
2774
|
+
if (!oldest.done) this.settledEventIds.delete(oldest.value);
|
|
2444
2775
|
}
|
|
2776
|
+
this.settledEventIds.add(eventId);
|
|
2445
2777
|
}
|
|
2446
|
-
|
|
2447
|
-
|
|
2448
|
-
|
|
2449
|
-
|
|
2450
|
-
|
|
2451
|
-
|
|
2452
|
-
|
|
2453
|
-
|
|
2454
|
-
|
|
2778
|
+
/**
|
|
2779
|
+
* Record a detached sub-agent on this turn: allocate the child's event id,
|
|
2780
|
+
* stamp the dispatch, and return the headers to send with the job.
|
|
2781
|
+
*
|
|
2782
|
+
* This dispatches nothing — you do, moments later, with the returned headers.
|
|
2783
|
+
* Nothing here waits for the child either, or claims to know how it is doing.
|
|
2784
|
+
* Readers derive that from the child's own event.
|
|
2785
|
+
*/
|
|
2786
|
+
subagent(options = {}) {
|
|
2787
|
+
var _a;
|
|
2788
|
+
const childEventId = (_a = options.childEventId) != null ? _a : randomUUID();
|
|
2789
|
+
const name = options.name;
|
|
2790
|
+
try {
|
|
2791
|
+
return this.recordLaunch(childEventId, name, options);
|
|
2792
|
+
} catch (err) {
|
|
2793
|
+
if (this.opts.debug) {
|
|
2794
|
+
console.warn(
|
|
2795
|
+
`[raindrop-ai/ai-sdk] sub-agent dispatch not recorded: ${err instanceof Error ? err.message : err}`
|
|
2796
|
+
);
|
|
2797
|
+
}
|
|
2798
|
+
return { childEventId, name, headers: {}, carrier: null };
|
|
2799
|
+
}
|
|
2455
2800
|
}
|
|
2456
|
-
|
|
2457
|
-
|
|
2458
|
-
|
|
2459
|
-
|
|
2801
|
+
recordLaunch(childEventId, name, options) {
|
|
2802
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p;
|
|
2803
|
+
const active = (_a = this.opts.spanSource) == null ? void 0 : _a.activeDispatch();
|
|
2804
|
+
const inherited = getContextManager().getParentSpanIds();
|
|
2805
|
+
const eventId = (_e = (_c = (_b = options.eventId) != null ? _b : active == null ? void 0 : active.eventId) != null ? _c : inherited == null ? void 0 : inherited.eventId) != null ? _e : (_d = this.opts.defaultContext) == null ? void 0 : _d.eventId;
|
|
2806
|
+
const userId = (_h = (_f = options.userId) != null ? _f : active == null ? void 0 : active.userId) != null ? _h : (_g = this.opts.defaultContext) == null ? void 0 : _g.userId;
|
|
2807
|
+
const convoId = (_k = (_i = options.convoId) != null ? _i : active == null ? void 0 : active.convoId) != null ? _k : (_j = this.opts.defaultContext) == null ? void 0 : _j.convoId;
|
|
2808
|
+
if (!eventId) {
|
|
2809
|
+
return { childEventId, name, headers: {}, carrier: null };
|
|
2810
|
+
}
|
|
2811
|
+
const dispatch = detachedDispatchMetadata({ childEventId, name });
|
|
2812
|
+
const toolEvents = toolEventsAllowMetadata();
|
|
2813
|
+
for (const span of (_l = active == null ? void 0 : active.turnSpans) != null ? _l : []) {
|
|
2814
|
+
stampOpenSpan(span, toolEvents);
|
|
2815
|
+
}
|
|
2816
|
+
let dispatchIds;
|
|
2817
|
+
if (active == null ? void 0 : active.dispatchSpan) {
|
|
2818
|
+
stampOpenSpan(active.dispatchSpan, dispatch);
|
|
2819
|
+
dispatchIds = active.dispatchSpan.ids;
|
|
2820
|
+
} else if (this.opts.sendTraces) {
|
|
2821
|
+
dispatchIds = this.synthesizeDispatchSpan({
|
|
2822
|
+
childEventId,
|
|
2823
|
+
name,
|
|
2824
|
+
toolName: options.toolName,
|
|
2825
|
+
eventId,
|
|
2826
|
+
userId,
|
|
2827
|
+
convoId,
|
|
2828
|
+
input: options.input,
|
|
2829
|
+
// No active turn means no telemetry setting to honor: `input` is then
|
|
2830
|
+
// recorded on the explicit say-so of whoever passed it.
|
|
2831
|
+
recordInputs: (_m = active == null ? void 0 : active.recordInputs) != null ? _m : true,
|
|
2832
|
+
dispatch,
|
|
2833
|
+
parent: (inherited == null ? void 0 : inherited.eventId) === eventId ? inherited : void 0
|
|
2834
|
+
}).ids;
|
|
2835
|
+
}
|
|
2836
|
+
const traceId = base64ToHex((_o = (_n = dispatchIds == null ? void 0 : dispatchIds.traceIdB64) != null ? _n : inherited == null ? void 0 : inherited.traceIdB64) != null ? _o : "");
|
|
2837
|
+
const spanId = base64ToHex((_p = dispatchIds == null ? void 0 : dispatchIds.spanIdB64) != null ? _p : "");
|
|
2838
|
+
if (!traceId || !spanId) {
|
|
2839
|
+
if (this.opts.debug) {
|
|
2840
|
+
console.warn(
|
|
2841
|
+
"[raindrop-ai/ai-sdk] sub-agent dispatch recorded without a carrier: no dispatch span to reference (traces disabled?)"
|
|
2842
|
+
);
|
|
2843
|
+
}
|
|
2844
|
+
return { childEventId, name, headers: {}, carrier: null };
|
|
2845
|
+
}
|
|
2846
|
+
const carrier = {
|
|
2847
|
+
traceId,
|
|
2848
|
+
spanId,
|
|
2849
|
+
eventId,
|
|
2850
|
+
childEventId,
|
|
2851
|
+
...name ? { name } : {},
|
|
2852
|
+
...convoId ? { convoId } : {},
|
|
2853
|
+
...userId ? { userId } : {}
|
|
2460
2854
|
};
|
|
2855
|
+
return { childEventId, name, headers: toHeaders(carrier), carrier };
|
|
2461
2856
|
}
|
|
2462
|
-
|
|
2857
|
+
/**
|
|
2858
|
+
* Record a dispatch span for a launch with no open tool-call span to decorate:
|
|
2859
|
+
* a launch from outside a tool's `execute`, or from a caller that is not an
|
|
2860
|
+
* LLM turn at all (an HTTP handler that enqueues jobs). Shaped as a tool call
|
|
2861
|
+
* so it reads identically to a model-issued launch.
|
|
2862
|
+
*/
|
|
2863
|
+
synthesizeDispatchSpan(args) {
|
|
2864
|
+
var _a;
|
|
2865
|
+
const spanName = (_a = args.toolName) != null ? _a : DEFAULT_DISPATCH_SPAN_NAME;
|
|
2866
|
+
const span = this.opts.traceShipper.startSpan({
|
|
2867
|
+
name: spanName,
|
|
2868
|
+
parent: args.parent,
|
|
2869
|
+
eventId: args.eventId,
|
|
2870
|
+
userId: args.userId,
|
|
2871
|
+
convoId: args.convoId,
|
|
2872
|
+
operationId: "ai.toolCall",
|
|
2873
|
+
attributes: [
|
|
2874
|
+
attrString("operation.name", "ai.toolCall"),
|
|
2875
|
+
attrString("resource.name", spanName),
|
|
2876
|
+
attrString("ai.toolCall.name", spanName),
|
|
2877
|
+
attrString("ai.toolCall.id", `call_${args.childEventId.replace(/-/g, "").slice(0, 12)}`),
|
|
2878
|
+
// Gated like every other input the turn's spans record: a caller that
|
|
2879
|
+
// disabled input capture must not leak the payload through the one
|
|
2880
|
+
// span this API synthesizes on its behalf.
|
|
2881
|
+
...args.recordInputs ? [attrString("ai.toolCall.args", boundedStringify(args.input))] : [],
|
|
2882
|
+
...attrsFrom(args.dispatch)
|
|
2883
|
+
]
|
|
2884
|
+
});
|
|
2885
|
+
this.opts.traceShipper.endSpan(span, {
|
|
2886
|
+
// A dispatch returns a handle, not an answer — the answer is the child's.
|
|
2887
|
+
attributes: [
|
|
2888
|
+
attrString(
|
|
2889
|
+
"ai.toolCall.result",
|
|
2890
|
+
boundedStringify({ jobId: args.childEventId, status: "accepted" })
|
|
2891
|
+
)
|
|
2892
|
+
]
|
|
2893
|
+
});
|
|
2894
|
+
return span;
|
|
2895
|
+
}
|
|
2896
|
+
/**
|
|
2897
|
+
* Adopt a carrier as the current run's parent reference.
|
|
2898
|
+
*
|
|
2899
|
+
* A missing carrier is a legitimate state — the child was invoked directly
|
|
2900
|
+
* rather than dispatched — so this always returns a usable run and leaves
|
|
2901
|
+
* `parent` null. Call sites stay unconditional.
|
|
2902
|
+
*/
|
|
2903
|
+
resume(carrierOrHeaders, options = {}) {
|
|
2904
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _i;
|
|
2905
|
+
const carrier = carrierOrHeaders ? isTraceCarrier(carrierOrHeaders) ? carrierOrHeaders : this.readCarrier(carrierOrHeaders) : null;
|
|
2906
|
+
warnUnresolvedCarrier(carrierOrHeaders, carrier);
|
|
2907
|
+
const name = (_a = carrier == null ? void 0 : carrier.name) != null ? _a : options.name;
|
|
2908
|
+
const eventId = (_c = (_b = carrier == null ? void 0 : carrier.childEventId) != null ? _b : options.eventId) != null ? _c : randomUUID();
|
|
2909
|
+
const userId = (_f = (_d = carrier == null ? void 0 : carrier.userId) != null ? _d : options.userId) != null ? _f : (_e = this.opts.defaultContext) == null ? void 0 : _e.userId;
|
|
2910
|
+
const convoId = (_i = (_g = carrier == null ? void 0 : carrier.convoId) != null ? _g : options.convoId) != null ? _i : (_h = this.opts.defaultContext) == null ? void 0 : _h.convoId;
|
|
2911
|
+
const parent = carrier ? {
|
|
2912
|
+
parentEventId: carrier.eventId,
|
|
2913
|
+
...carrier.spanId ? { parentSpanId: carrier.spanId } : {},
|
|
2914
|
+
...name ? { name } : {}
|
|
2915
|
+
} : null;
|
|
2463
2916
|
return {
|
|
2464
|
-
|
|
2465
|
-
|
|
2466
|
-
|
|
2917
|
+
eventId,
|
|
2918
|
+
name,
|
|
2919
|
+
userId,
|
|
2920
|
+
convoId,
|
|
2921
|
+
parent,
|
|
2922
|
+
metadata: {
|
|
2923
|
+
eventId,
|
|
2924
|
+
...userId ? { userId } : {},
|
|
2925
|
+
...convoId ? { convoId } : {},
|
|
2926
|
+
...parent ? { subagent: parent } : {}
|
|
2927
|
+
},
|
|
2928
|
+
cancel: (reason) => this.settle(eventId, { userId, convoId, name, cancelled: true, output: reason }),
|
|
2929
|
+
fail: (reason) => this.settle(eventId, {
|
|
2930
|
+
userId,
|
|
2931
|
+
convoId,
|
|
2932
|
+
name,
|
|
2933
|
+
handoff: parent != null ? parent : void 0,
|
|
2934
|
+
cancelled: false,
|
|
2935
|
+
output: describeAbortReason(reason),
|
|
2936
|
+
error: reason
|
|
2937
|
+
})
|
|
2467
2938
|
};
|
|
2468
2939
|
}
|
|
2469
|
-
|
|
2940
|
+
/**
|
|
2941
|
+
* A carrier arrives from outside this process, so a hostile or merely broken
|
|
2942
|
+
* header bag must cost the job its link, never its run.
|
|
2943
|
+
*/
|
|
2944
|
+
readCarrier(headers) {
|
|
2945
|
+
try {
|
|
2946
|
+
return fromHeaders(headers);
|
|
2947
|
+
} catch (err) {
|
|
2948
|
+
if (this.opts.debug) {
|
|
2949
|
+
console.warn(
|
|
2950
|
+
`[raindrop-ai/ai-sdk] sub-agent carrier ignored: ${err instanceof Error ? err.message : err}`
|
|
2951
|
+
);
|
|
2952
|
+
}
|
|
2953
|
+
return null;
|
|
2954
|
+
}
|
|
2955
|
+
}
|
|
2956
|
+
/**
|
|
2957
|
+
* Mark a failed child's own spans as errored.
|
|
2958
|
+
*
|
|
2959
|
+
* Reporting the reason as output is what gets the child an event at all, but
|
|
2960
|
+
* output alone is not enough: status is derived from span shape, and a child
|
|
2961
|
+
* with final output and no error spans derives `finished`. A failed job
|
|
2962
|
+
* reporting success is worse than one reporting nothing, so the failure has
|
|
2963
|
+
* to land on the telemetry too, not just in the text.
|
|
2964
|
+
*
|
|
2965
|
+
* This is the child describing its own run, not a caller writing a status it
|
|
2966
|
+
* cannot observe — the child's own spans are exactly where the contract puts
|
|
2967
|
+
* failure.
|
|
2968
|
+
*/
|
|
2969
|
+
recordFailureOnSpans(eventId, args, reason) {
|
|
2970
|
+
var _a, _b, _c;
|
|
2971
|
+
if (!this.opts.sendTraces) return;
|
|
2972
|
+
const failure = (_a = args.error) != null ? _a : reason;
|
|
2973
|
+
let marked = 0;
|
|
2974
|
+
for (const span2 of (_c = (_b = this.opts.spanSource) == null ? void 0 : _b.openSpansForEvent(eventId)) != null ? _c : []) {
|
|
2975
|
+
if (span2.endTimeUnixNano) continue;
|
|
2976
|
+
this.opts.traceShipper.endSpan(span2, { error: failure });
|
|
2977
|
+
marked++;
|
|
2978
|
+
}
|
|
2979
|
+
if (marked > 0) return;
|
|
2980
|
+
const spanName = SUBAGENT_ABORT_SPAN_NAME;
|
|
2981
|
+
const span = this.opts.traceShipper.startSpan({
|
|
2982
|
+
name: spanName,
|
|
2983
|
+
eventId,
|
|
2984
|
+
userId: args.userId,
|
|
2985
|
+
convoId: args.convoId,
|
|
2986
|
+
// Required, not decorative: ingest drops any span carrying no
|
|
2987
|
+
// `ai.operationId` (or traceloop / `gen_ai.*` key) and still answers 200,
|
|
2988
|
+
// so without this the failure disappears silently. The value is
|
|
2989
|
+
// deliberately none of the generate/stream/tool/embed forms, which is
|
|
2990
|
+
// what classifies the span as INTERNAL rather than mislabelling a failed
|
|
2991
|
+
// job as a model call or a tool call.
|
|
2992
|
+
operationId: SUBAGENT_FAILED_OPERATION_ID,
|
|
2993
|
+
// Carries the reverse reference like every other span the child emits:
|
|
2994
|
+
// this is often the child's ONLY span, and a span read on its own is the
|
|
2995
|
+
// whole reason the reference cannot live on the root alone. The name is
|
|
2996
|
+
// stamped even for an unlinked run, which has no caller to reference —
|
|
2997
|
+
// `span_name` no longer says which sub-agent this was, so the attribute
|
|
2998
|
+
// is the only thing that can.
|
|
2999
|
+
attributes: [
|
|
3000
|
+
attrString("resource.name", spanName),
|
|
3001
|
+
...handoffSpanAttrs(args.handoff),
|
|
3002
|
+
...subagentNameAttrs(args.name, args.handoff)
|
|
3003
|
+
]
|
|
3004
|
+
});
|
|
3005
|
+
this.opts.traceShipper.endSpan(span, { error: failure });
|
|
3006
|
+
}
|
|
3007
|
+
async settle(eventId, args) {
|
|
3008
|
+
var _a, _b;
|
|
3009
|
+
if (this.settledEventIds.has(eventId)) {
|
|
3010
|
+
if (this.opts.debug) {
|
|
3011
|
+
console.warn(
|
|
3012
|
+
`[raindrop-ai/ai-sdk] sub-agent ${eventId} already reported an outcome; ignoring the second one`
|
|
3013
|
+
);
|
|
3014
|
+
}
|
|
3015
|
+
return;
|
|
3016
|
+
}
|
|
3017
|
+
this.remember(eventId);
|
|
3018
|
+
const output = args.output && args.output.trim().length > 0 ? args.output : args.cancelled ? SUBAGENT_CANCELLED_OUTPUT : SUBAGENT_ABORTED_OUTPUT;
|
|
3019
|
+
try {
|
|
3020
|
+
if (args.cancelled) {
|
|
3021
|
+
for (const span of (_b = (_a = this.opts.spanSource) == null ? void 0 : _a.openSpansForEvent(eventId)) != null ? _b : []) {
|
|
3022
|
+
stampOpenSpanExact(span, cancelledTerminalAttributes());
|
|
3023
|
+
}
|
|
3024
|
+
} else {
|
|
3025
|
+
this.recordFailureOnSpans(eventId, args, output);
|
|
3026
|
+
}
|
|
3027
|
+
} catch (err) {
|
|
3028
|
+
if (this.opts.debug) {
|
|
3029
|
+
console.warn(
|
|
3030
|
+
`[raindrop-ai/ai-sdk] sub-agent outcome not recorded on spans: ${err instanceof Error ? err.message : err}`
|
|
3031
|
+
);
|
|
3032
|
+
}
|
|
3033
|
+
}
|
|
3034
|
+
if (!this.opts.sendEvents) return;
|
|
3035
|
+
await this.opts.eventShipper.patch(eventId, {
|
|
3036
|
+
userId: args.userId,
|
|
3037
|
+
convoId: args.convoId,
|
|
3038
|
+
// An event is only created from a run that reported something. A child
|
|
3039
|
+
// that dies silently produces no event at all, which pins the caller on
|
|
3040
|
+
// `queued` forever — indistinguishable from a job that never started.
|
|
3041
|
+
output,
|
|
3042
|
+
...args.cancelled ? { properties: { [HANDOFF_TERMINAL_PROPERTY_KEY]: HANDOFF_TERMINAL_CANCELLED } } : {},
|
|
3043
|
+
isPending: false
|
|
3044
|
+
}).catch((err) => {
|
|
3045
|
+
if (this.opts.debug) {
|
|
3046
|
+
console.warn(
|
|
3047
|
+
`[raindrop-ai/ai-sdk] sub-agent outcome patch failed: ${err instanceof Error ? err.message : err}`
|
|
3048
|
+
);
|
|
3049
|
+
}
|
|
3050
|
+
});
|
|
3051
|
+
}
|
|
3052
|
+
};
|
|
3053
|
+
|
|
3054
|
+
// src/internal/usage.ts
|
|
3055
|
+
function firstTokenCount(...values) {
|
|
3056
|
+
for (const value of values) {
|
|
3057
|
+
if (typeof value === "number" && Number.isSafeInteger(value) && value >= 0) {
|
|
3058
|
+
return value;
|
|
3059
|
+
}
|
|
3060
|
+
}
|
|
3061
|
+
return void 0;
|
|
2470
3062
|
}
|
|
2471
3063
|
var CACHE_WRITE_METADATA_KEYS = [
|
|
2472
3064
|
["anthropic", "cacheCreationInputTokens"],
|
|
@@ -2484,7 +3076,7 @@ function cacheWriteTokensFromProviderMetadata(providerMetadata) {
|
|
|
2484
3076
|
})
|
|
2485
3077
|
);
|
|
2486
3078
|
}
|
|
2487
|
-
function extractUsageMetricsFromUsage(usage,
|
|
3079
|
+
function extractUsageMetricsFromUsage(usage, _provider, providerMetadata) {
|
|
2488
3080
|
if (!isRecord(usage)) return {};
|
|
2489
3081
|
const inputTokenValue = usage["inputTokens"];
|
|
2490
3082
|
const outputTokenValue = usage["outputTokens"];
|
|
@@ -2552,7 +3144,7 @@ function extractUsageMetricsFromUsage(usage, provider, providerMetadata) {
|
|
|
2552
3144
|
cacheReadInputTokens,
|
|
2553
3145
|
cachedInputTokens: cacheReadInputTokens,
|
|
2554
3146
|
cacheWriteInputTokens,
|
|
2555
|
-
...hasStructuredUsage ? {} :
|
|
3147
|
+
...hasStructuredUsage ? { usageSource: "ai-sdk-structured" } : {}
|
|
2556
3148
|
};
|
|
2557
3149
|
}
|
|
2558
3150
|
|
|
@@ -2628,6 +3220,7 @@ var RaindropTelemetryIntegration = class {
|
|
|
2628
3220
|
eventName: (_f = callMeta.eventName) != null ? _f : (_e = this.defaultContext) == null ? void 0 : _e.eventName
|
|
2629
3221
|
};
|
|
2630
3222
|
const inherited = getContextManager().getParentSpanIds();
|
|
3223
|
+
const handoff = readDetachedChildLink(metadata);
|
|
2631
3224
|
const eventIdGenerated = (metadata == null ? void 0 : metadata["raindrop.internal.eventIdGenerated"]) === "true" || (metadata == null ? void 0 : metadata["raindrop.internal.eventIdGenerated"]) === true || (callContextMetadata == null ? void 0 : callContextMetadata.eventIdGenerated) === true;
|
|
2632
3225
|
const explicitEventId = callMeta.eventId && !eventIdGenerated ? callMeta.eventId : void 0;
|
|
2633
3226
|
const eventId = (_j = (_i = (_h = explicitEventId != null ? explicitEventId : (_g = this.defaultContext) == null ? void 0 : _g.eventId) != null ? _h : inherited == null ? void 0 : inherited.eventId) != null ? _i : callMeta.eventId) != null ? _j : randomUUID();
|
|
@@ -2657,7 +3250,10 @@ var RaindropTelemetryIntegration = class {
|
|
|
2657
3250
|
attrString("ai.toolCall.name", subagentName),
|
|
2658
3251
|
attrString("raindrop.subagent.name", subagentName),
|
|
2659
3252
|
attrString("raindrop.agent.role", "subagent"),
|
|
2660
|
-
...parentAttrs
|
|
3253
|
+
...parentAttrs,
|
|
3254
|
+
// Top of this child's tree, so the reverse reference matters as much
|
|
3255
|
+
// here as on the root: these are the spans a reader lands on first.
|
|
3256
|
+
...handoffSpanAttrs(handoff)
|
|
2661
3257
|
]
|
|
2662
3258
|
});
|
|
2663
3259
|
const subagentParentRef = this.spanParentRef(subagentToolCallSpan);
|
|
@@ -2670,7 +3266,8 @@ var RaindropTelemetryIntegration = class {
|
|
|
2670
3266
|
attributes: [
|
|
2671
3267
|
attrString("operation.name", "agent.subagent"),
|
|
2672
3268
|
attrString("raindrop.span.kind", "llm_call"),
|
|
2673
|
-
attrString("raindrop.subagent.name", subagentName)
|
|
3269
|
+
attrString("raindrop.subagent.name", subagentName),
|
|
3270
|
+
...handoffSpanAttrs(handoff)
|
|
2674
3271
|
]
|
|
2675
3272
|
});
|
|
2676
3273
|
this.traceShipper.endSpan(markerSpan);
|
|
@@ -2738,7 +3335,9 @@ var RaindropTelemetryIntegration = class {
|
|
|
2738
3335
|
inputText: isEmbed ? void 0 : this.extractInputText(event),
|
|
2739
3336
|
toolCallCount: 0,
|
|
2740
3337
|
subagentName,
|
|
2741
|
-
subagentToolCallSpan
|
|
3338
|
+
subagentToolCallSpan,
|
|
3339
|
+
handoff,
|
|
3340
|
+
nestedInEvent: inheritedParent !== void 0
|
|
2742
3341
|
});
|
|
2743
3342
|
};
|
|
2744
3343
|
// ── onStepStart ─────────────────────────────────────────────────────────
|
|
@@ -2783,7 +3382,8 @@ var RaindropTelemetryIntegration = class {
|
|
|
2783
3382
|
...attrsFromModelProvider(event.provider),
|
|
2784
3383
|
attrString("ai.model.id", event.modelId),
|
|
2785
3384
|
attrString(MODEL_USAGE_ATTRIBUTES.requestModel, event.modelId),
|
|
2786
|
-
...inputAttrs
|
|
3385
|
+
...inputAttrs,
|
|
3386
|
+
...handoffSpanAttrs(state.handoff)
|
|
2787
3387
|
]
|
|
2788
3388
|
});
|
|
2789
3389
|
state.stepSpan = stepSpan;
|
|
@@ -2896,7 +3496,8 @@ var RaindropTelemetryIntegration = class {
|
|
|
2896
3496
|
attrInt("ai.usage.totalTokens", usageMetrics.totalTokens),
|
|
2897
3497
|
attrInt("ai.usage.reasoningTokens", usageMetrics.reasoningTokens),
|
|
2898
3498
|
attrInt("ai.usage.cachedInputTokens", usageMetrics.cachedInputTokens),
|
|
2899
|
-
|
|
3499
|
+
attrString(MODEL_USAGE_ATTRIBUTES.usageSource, usageMetrics.usageSource),
|
|
3500
|
+
...buildRawModelUsageAttributes(usageMetrics)
|
|
2900
3501
|
);
|
|
2901
3502
|
}
|
|
2902
3503
|
this.emitProviderExecutedToolSpans(event, state);
|
|
@@ -2922,7 +3523,8 @@ var RaindropTelemetryIntegration = class {
|
|
|
2922
3523
|
attrString("operation.name", operationName),
|
|
2923
3524
|
attrString("resource.name", resourceName),
|
|
2924
3525
|
attrString("ai.telemetry.functionId", state.functionId),
|
|
2925
|
-
...inputAttrs
|
|
3526
|
+
...inputAttrs,
|
|
3527
|
+
...handoffSpanAttrs(state.handoff)
|
|
2926
3528
|
]
|
|
2927
3529
|
});
|
|
2928
3530
|
state.embedSpans.set(event.embedCallId, embedSpan);
|
|
@@ -2994,15 +3596,26 @@ var RaindropTelemetryIntegration = class {
|
|
|
2994
3596
|
this.traceShipper.endSpan(toolSpan, { error: actualError });
|
|
2995
3597
|
}
|
|
2996
3598
|
state.toolSpans.clear();
|
|
3599
|
+
const abortReason = describeAbortReason(actualError);
|
|
2997
3600
|
if (state.rootSpan) {
|
|
2998
|
-
this.traceShipper.endSpan(state.rootSpan, {
|
|
3601
|
+
this.traceShipper.endSpan(state.rootSpan, {
|
|
3602
|
+
error: actualError,
|
|
3603
|
+
attributes: this.abortOutcomeAttrs(state, abortReason, "error")
|
|
3604
|
+
});
|
|
2999
3605
|
}
|
|
3000
3606
|
if (state.subagentToolCallSpan) {
|
|
3001
3607
|
this.traceShipper.endSpan(state.subagentToolCallSpan, { error: actualError });
|
|
3002
3608
|
}
|
|
3003
3609
|
const isEmbed = state.operationId === "ai.embed" || state.operationId === "ai.embedMany";
|
|
3004
3610
|
if (!isEmbed) {
|
|
3005
|
-
|
|
3611
|
+
const errorIsTheRunsOutcome = state.handoff !== void 0 && !state.nestedInEvent;
|
|
3612
|
+
this.finalizeGenerateEvent(
|
|
3613
|
+
state,
|
|
3614
|
+
state.accumulatedText || void 0,
|
|
3615
|
+
void 0,
|
|
3616
|
+
false,
|
|
3617
|
+
errorIsTheRunsOutcome ? { fallbackOutput: abortReason } : void 0
|
|
3618
|
+
);
|
|
3006
3619
|
}
|
|
3007
3620
|
this.cleanup(event.callId);
|
|
3008
3621
|
};
|
|
@@ -3039,9 +3652,19 @@ var RaindropTelemetryIntegration = class {
|
|
|
3039
3652
|
this.traceShipper.endSpan(toolSpan, { attributes: [abortedAttr] });
|
|
3040
3653
|
}
|
|
3041
3654
|
state.toolSpans.clear();
|
|
3655
|
+
const abortIsTheRunsOutcome = state.handoff !== void 0 && !state.nestedInEvent;
|
|
3042
3656
|
if (state.rootSpan) {
|
|
3043
3657
|
this.traceShipper.endSpan(state.rootSpan, {
|
|
3044
|
-
attributes: [
|
|
3658
|
+
attributes: [
|
|
3659
|
+
abortedAttr,
|
|
3660
|
+
attrInt("ai.toolCall.count", state.toolCallCount),
|
|
3661
|
+
// An aborted detached child IS a cancelled sub-agent, and a cancelled
|
|
3662
|
+
// run is span-for-span identical to a finished one — spans close,
|
|
3663
|
+
// nothing errors, there is just no answer. So it is the one outcome
|
|
3664
|
+
// that has to be stated, and the child states it on itself.
|
|
3665
|
+
...abortIsTheRunsOutcome ? cancelledSpanAttrs() : [],
|
|
3666
|
+
...abortIsTheRunsOutcome ? this.abortOutcomeAttrs(state, SUBAGENT_CANCELLED_OUTPUT, "stop") : []
|
|
3667
|
+
]
|
|
3045
3668
|
});
|
|
3046
3669
|
}
|
|
3047
3670
|
if (state.subagentToolCallSpan) {
|
|
@@ -3049,7 +3672,17 @@ var RaindropTelemetryIntegration = class {
|
|
|
3049
3672
|
attributes: [abortedAttr]
|
|
3050
3673
|
});
|
|
3051
3674
|
}
|
|
3052
|
-
this.finalizeGenerateEvent(
|
|
3675
|
+
this.finalizeGenerateEvent(
|
|
3676
|
+
state,
|
|
3677
|
+
state.accumulatedText || void 0,
|
|
3678
|
+
void 0,
|
|
3679
|
+
false,
|
|
3680
|
+
abortIsTheRunsOutcome ? {
|
|
3681
|
+
fallbackOutput: SUBAGENT_CANCELLED_OUTPUT,
|
|
3682
|
+
properties: { [HANDOFF_TERMINAL_PROPERTY_KEY]: HANDOFF_TERMINAL_CANCELLED }
|
|
3683
|
+
} : void 0
|
|
3684
|
+
);
|
|
3685
|
+
if (abortIsTheRunsOutcome) this.subagents.noteSettled(state.eventId);
|
|
3053
3686
|
this.cleanup(callId);
|
|
3054
3687
|
};
|
|
3055
3688
|
// ── executeTool ─────────────────────────────────────────────────────────
|
|
@@ -3077,6 +3710,97 @@ var RaindropTelemetryIntegration = class {
|
|
|
3077
3710
|
this.subagentWrapping = opts.subagentWrapping !== false;
|
|
3078
3711
|
this.debug = opts.debug === true;
|
|
3079
3712
|
this.defaultContext = opts.context;
|
|
3713
|
+
this.subagents = new SubagentApi({
|
|
3714
|
+
traceShipper: this.traceShipper,
|
|
3715
|
+
eventShipper: this.eventShipper,
|
|
3716
|
+
sendTraces: this.sendTraces,
|
|
3717
|
+
sendEvents: this.sendEvents,
|
|
3718
|
+
debug: this.debug,
|
|
3719
|
+
defaultContext: this.defaultContext,
|
|
3720
|
+
settledEventIds: opts.settledEventIds,
|
|
3721
|
+
spanSource: {
|
|
3722
|
+
activeDispatch: () => this.activeDispatch(),
|
|
3723
|
+
openSpansForEvent: (eventId) => this.openSpansForEvent(eventId)
|
|
3724
|
+
}
|
|
3725
|
+
});
|
|
3726
|
+
}
|
|
3727
|
+
/**
|
|
3728
|
+
* Record a detached sub-agent on the turn that is live right now.
|
|
3729
|
+
*
|
|
3730
|
+
* Returns the dispatch — the child's event id and the headers to send with
|
|
3731
|
+
* the job. Dispatching is still yours to do; this only states that you are
|
|
3732
|
+
* about to, so a reader can follow the link before the child exists.
|
|
3733
|
+
*/
|
|
3734
|
+
subagent(options = {}) {
|
|
3735
|
+
return this.subagents.subagent(options);
|
|
3736
|
+
}
|
|
3737
|
+
// ── detached sub-agent hand-offs ─────────────────────────────────────────
|
|
3738
|
+
/**
|
|
3739
|
+
* The turn a `subagent()` dispatch is happening inside.
|
|
3740
|
+
*
|
|
3741
|
+
* Resolved from the parent-tool context first, which is the only way to reach
|
|
3742
|
+
* the EXACT span that dispatched: the tool call the model itself issued, still
|
|
3743
|
+
* open while its `execute` runs. Falling back to the event id lets a launch
|
|
3744
|
+
* from elsewhere in the turn (a queue producer called mid-generation) still
|
|
3745
|
+
* find the turn's spans, which is where the tool-events opt-in has to land.
|
|
3746
|
+
*/
|
|
3747
|
+
activeDispatch() {
|
|
3748
|
+
var _a;
|
|
3749
|
+
const parentTool = getCurrentParentToolContext();
|
|
3750
|
+
let state = parentTool ? this.getState(parentTool.parentCallId) : void 0;
|
|
3751
|
+
const inheritedEventId = (_a = getContextManager().getParentSpanIds()) == null ? void 0 : _a.eventId;
|
|
3752
|
+
if (!state && inheritedEventId) {
|
|
3753
|
+
for (const candidate of this.callStates.values()) {
|
|
3754
|
+
if (candidate.eventId === inheritedEventId) {
|
|
3755
|
+
state = candidate;
|
|
3756
|
+
break;
|
|
3757
|
+
}
|
|
3758
|
+
}
|
|
3759
|
+
}
|
|
3760
|
+
if (!state) return void 0;
|
|
3761
|
+
return {
|
|
3762
|
+
eventId: state.eventId,
|
|
3763
|
+
userId: state.identity.userId,
|
|
3764
|
+
convoId: state.identity.convoId,
|
|
3765
|
+
dispatchSpan: parentTool ? state.toolSpans.get(parentTool.toolCallId) : void 0,
|
|
3766
|
+
turnSpans: [state.rootSpan, state.stepSpan].filter(
|
|
3767
|
+
(span) => span !== void 0
|
|
3768
|
+
),
|
|
3769
|
+
recordInputs: state.recordInputs
|
|
3770
|
+
};
|
|
3771
|
+
}
|
|
3772
|
+
/** Spans still open for an event, so a late outcome can still be stated. */
|
|
3773
|
+
openSpansForEvent(eventId) {
|
|
3774
|
+
const spans = [];
|
|
3775
|
+
for (const state of this.callStates.values()) {
|
|
3776
|
+
if (state.eventId !== eventId) continue;
|
|
3777
|
+
if (state.rootSpan) spans.push(state.rootSpan);
|
|
3778
|
+
if (state.stepSpan) spans.push(state.stepSpan);
|
|
3779
|
+
}
|
|
3780
|
+
return spans;
|
|
3781
|
+
}
|
|
3782
|
+
/**
|
|
3783
|
+
* End-attributes that keep a detached child legible when it ends without an
|
|
3784
|
+
* answer — an error, an abort, a cancellation.
|
|
3785
|
+
*
|
|
3786
|
+
* An event is created from an LLM span only when it has a finish reason and
|
|
3787
|
+
* non-empty output, so a child that dies silently produces NO event, and the
|
|
3788
|
+
* caller's hand-off pill stays on `queued` forever — indistinguishable from a
|
|
3789
|
+
* job that never started. Reporting the abort reason as the run's output is
|
|
3790
|
+
* what makes the outcome visible. Only detached children get this: an inline
|
|
3791
|
+
* generation's failure is already legible from its caller's own event.
|
|
3792
|
+
*
|
|
3793
|
+
* And only the run's OUTERMOST generation gets it (see `nestedInEvent`): an
|
|
3794
|
+
* inner sub-call ending badly is not the run ending, and since an event is
|
|
3795
|
+
* created from an LLM span with output, `ai.response.text` here would state
|
|
3796
|
+
* the run's outcome through the span while the turn is still working.
|
|
3797
|
+
*/
|
|
3798
|
+
abortOutcomeAttrs(state, reason, finishReason) {
|
|
3799
|
+
if (!state.handoff || state.nestedInEvent) return [];
|
|
3800
|
+
return [
|
|
3801
|
+
attrString("ai.response.text", capText2(state.accumulatedText || reason)),
|
|
3802
|
+
attrString("ai.response.finishReason", finishReason)
|
|
3803
|
+
];
|
|
3080
3804
|
}
|
|
3081
3805
|
// ── helpers ──────────────────────────────────────────────────────────────
|
|
3082
3806
|
getState(callId) {
|
|
@@ -3195,7 +3919,8 @@ var RaindropTelemetryIntegration = class {
|
|
|
3195
3919
|
attrString("ai.telemetry.functionId", state.functionId),
|
|
3196
3920
|
attrString("ai.toolCall.name", toolCall.toolName),
|
|
3197
3921
|
attrString("ai.toolCall.id", toolCall.toolCallId),
|
|
3198
|
-
...inputAttrs
|
|
3922
|
+
...inputAttrs,
|
|
3923
|
+
...handoffSpanAttrs(state.handoff)
|
|
3199
3924
|
]
|
|
3200
3925
|
});
|
|
3201
3926
|
state.toolSpans.set(toolCall.toolCallId, toolSpan);
|
|
@@ -3274,7 +3999,8 @@ var RaindropTelemetryIntegration = class {
|
|
|
3274
3999
|
attrString("ai.toolCall.name", call.toolName),
|
|
3275
4000
|
attrString("ai.toolCall.id", call.toolCallId),
|
|
3276
4001
|
attrString("ai.toolCall.providerExecuted", "true"),
|
|
3277
|
-
...inputAttrs
|
|
4002
|
+
...inputAttrs,
|
|
4003
|
+
...handoffSpanAttrs(state.handoff)
|
|
3278
4004
|
]
|
|
3279
4005
|
});
|
|
3280
4006
|
state.toolCallCount += 1;
|
|
@@ -3355,19 +4081,22 @@ var RaindropTelemetryIntegration = class {
|
|
|
3355
4081
|
* is finalized by that resume — otherwise each execution would finalize the
|
|
3356
4082
|
* same event ID into a separate canonical row.
|
|
3357
4083
|
*/
|
|
3358
|
-
finalizeGenerateEvent(state, output, model, keepPending = false) {
|
|
4084
|
+
finalizeGenerateEvent(state, output, model, keepPending = false, detachedOutcome) {
|
|
3359
4085
|
var _a, _b, _c, _d, _e, _f, _g, _h, _i;
|
|
3360
4086
|
const suppressSubagentEvent = state.subagentName !== void 0 && state.subagentToolCallSpan !== void 0;
|
|
3361
4087
|
if (!this.sendEvents || suppressSubagentEvent) return;
|
|
4088
|
+
if (this.subagents.wasSettledExplicitly(state.eventId)) return;
|
|
3362
4089
|
const callMeta = this.extractRaindropMetadata(state.metadata);
|
|
3363
4090
|
const userId = (_b = callMeta.userId) != null ? _b : (_a = this.defaultContext) == null ? void 0 : _a.userId;
|
|
3364
4091
|
if (!userId) return;
|
|
3365
4092
|
const eventName = (_e = (_d = callMeta.eventName) != null ? _d : (_c = this.defaultContext) == null ? void 0 : _c.eventName) != null ? _e : state.operationId;
|
|
3366
4093
|
const cappedOutput = capText2(output);
|
|
4094
|
+
const reportedOutput = state.handoff && detachedOutcome && !(cappedOutput == null ? void 0 : cappedOutput.trim()) ? detachedOutcome.fallbackOutput : cappedOutput;
|
|
3367
4095
|
const input = capText2(state.inputText);
|
|
3368
4096
|
const properties = {
|
|
3369
4097
|
...(_f = this.defaultContext) == null ? void 0 : _f.properties,
|
|
3370
|
-
...callMeta.properties
|
|
4098
|
+
...callMeta.properties,
|
|
4099
|
+
...state.handoff ? detachedOutcome == null ? void 0 : detachedOutcome.properties : void 0
|
|
3371
4100
|
};
|
|
3372
4101
|
const featureFlags = {
|
|
3373
4102
|
...((_g = this.defaultContext) == null ? void 0 : _g.featureFlags) ? normalizeFeatureFlags(this.defaultContext.featureFlags) : {},
|
|
@@ -3379,7 +4108,7 @@ var RaindropTelemetryIntegration = class {
|
|
|
3379
4108
|
userId,
|
|
3380
4109
|
convoId,
|
|
3381
4110
|
input,
|
|
3382
|
-
output:
|
|
4111
|
+
output: reportedOutput,
|
|
3383
4112
|
model,
|
|
3384
4113
|
properties: Object.keys(properties).length > 0 ? properties : void 0,
|
|
3385
4114
|
featureFlags: Object.keys(featureFlags).length > 0 ? featureFlags : void 0,
|
|
@@ -3716,9 +4445,7 @@ function extractRaindropMetadata(metadata) {
|
|
|
3716
4445
|
} catch (e) {
|
|
3717
4446
|
}
|
|
3718
4447
|
} else if (featureFlags && typeof featureFlags === "object") {
|
|
3719
|
-
result.featureFlags = normalizeFeatureFlags(
|
|
3720
|
-
featureFlags
|
|
3721
|
-
);
|
|
4448
|
+
result.featureFlags = normalizeFeatureFlags(featureFlags);
|
|
3722
4449
|
}
|
|
3723
4450
|
return result;
|
|
3724
4451
|
}
|
|
@@ -3929,12 +4656,7 @@ function setupOperation(params) {
|
|
|
3929
4656
|
...attrsFromTelemetryMetadata(telemetry == null ? void 0 : telemetry.metadata),
|
|
3930
4657
|
...attrsFromHeaders(isRecord(arg) ? arg["headers"] : void 0),
|
|
3931
4658
|
...attrsFromSettings(arg),
|
|
3932
|
-
...(telemetry == null ? void 0 : telemetry.recordInputs) === false ? [] : [
|
|
3933
|
-
attrString(
|
|
3934
|
-
"ai.prompt",
|
|
3935
|
-
safeJsonWithUint8(normalizePromptAttr(arg))
|
|
3936
|
-
)
|
|
3937
|
-
]
|
|
4659
|
+
...(telemetry == null ? void 0 : telemetry.recordInputs) === false ? [] : [attrString("ai.prompt", safeJsonWithUint8(normalizePromptAttr(arg)))]
|
|
3938
4660
|
]
|
|
3939
4661
|
}) : void 0;
|
|
3940
4662
|
const rootParentForChildren = rootSpan ? { traceIdB64: rootSpan.ids.traceIdB64, spanIdB64: rootSpan.ids.spanIdB64 } : inheritedParent;
|
|
@@ -4284,13 +5006,17 @@ function wrapAISDK(aiSDK, deps) {
|
|
|
4284
5006
|
}
|
|
4285
5007
|
const useNative = deps.options.nativeTelemetry === true;
|
|
4286
5008
|
if (useNative) {
|
|
4287
|
-
const wrapTimeCtx = resolveContext(deps.options.context, {
|
|
5009
|
+
const wrapTimeCtx = resolveContext(deps.options.context, {
|
|
5010
|
+
operation: "wrap",
|
|
5011
|
+
args: void 0
|
|
5012
|
+
});
|
|
4288
5013
|
const integration = new RaindropTelemetryIntegration({
|
|
4289
5014
|
traceShipper: deps.traceShipper,
|
|
4290
5015
|
eventShipper: deps.eventShipper,
|
|
4291
5016
|
sendTraces: ((_a = deps.options.send) == null ? void 0 : _a.traces) !== false,
|
|
4292
5017
|
sendEvents: ((_b = deps.options.send) == null ? void 0 : _b.events) !== false,
|
|
4293
5018
|
debug,
|
|
5019
|
+
settledEventIds: deps.settledEventIds,
|
|
4294
5020
|
context: {
|
|
4295
5021
|
userId: wrapTimeCtx.userId,
|
|
4296
5022
|
eventId: wrapTimeCtx.eventId,
|
|
@@ -4528,7 +5254,13 @@ function wrapAgentGenerate(generate, instance, agentSettings, className, aiSDK,
|
|
|
4528
5254
|
...(telemetry == null ? void 0 : telemetry.recordInputs) === false ? [] : [
|
|
4529
5255
|
attrString(
|
|
4530
5256
|
"ai.prompt",
|
|
4531
|
-
safeJsonWithUint8(
|
|
5257
|
+
safeJsonWithUint8(
|
|
5258
|
+
normalizePromptAttr({
|
|
5259
|
+
system: (_d = mergedArgs["system"]) != null ? _d : mergedArgs["instructions"],
|
|
5260
|
+
prompt: mergedArgs["prompt"],
|
|
5261
|
+
messages: mergedArgs["messages"]
|
|
5262
|
+
})
|
|
5263
|
+
)
|
|
4532
5264
|
)
|
|
4533
5265
|
]
|
|
4534
5266
|
]
|
|
@@ -4742,7 +5474,13 @@ function wrapAgentStream(stream, instance, agentSettings, className, aiSDK, deps
|
|
|
4742
5474
|
...(telemetry == null ? void 0 : telemetry.recordInputs) === false ? [] : [
|
|
4743
5475
|
attrString(
|
|
4744
5476
|
"ai.prompt",
|
|
4745
|
-
safeJsonWithUint8(
|
|
5477
|
+
safeJsonWithUint8(
|
|
5478
|
+
normalizePromptAttr({
|
|
5479
|
+
system: (_d = mergedArgs["system"]) != null ? _d : mergedArgs["instructions"],
|
|
5480
|
+
prompt: mergedArgs["prompt"],
|
|
5481
|
+
messages: mergedArgs["messages"]
|
|
5482
|
+
})
|
|
5483
|
+
)
|
|
4746
5484
|
)
|
|
4747
5485
|
]
|
|
4748
5486
|
]
|
|
@@ -5119,9 +5857,19 @@ function wrapModel(args, aiSDK, outerOperationId, ctx) {
|
|
|
5119
5857
|
for (const part of content) {
|
|
5120
5858
|
if (isRecord(part)) {
|
|
5121
5859
|
if ((part["type"] === "reasoning" || part["type"] === "thinking") && typeof ((_a = part["text"]) != null ? _a : part["thinking"]) === "string") {
|
|
5122
|
-
sendLocalDebuggerLiveEvent({
|
|
5860
|
+
sendLocalDebuggerLiveEvent({
|
|
5861
|
+
traceId,
|
|
5862
|
+
type: "reasoning_delta",
|
|
5863
|
+
content: (_b = part["text"]) != null ? _b : part["thinking"],
|
|
5864
|
+
metadata: liveMeta
|
|
5865
|
+
});
|
|
5123
5866
|
} else if (part["type"] === "text" && typeof part["text"] === "string") {
|
|
5124
|
-
sendLocalDebuggerLiveEvent({
|
|
5867
|
+
sendLocalDebuggerLiveEvent({
|
|
5868
|
+
traceId,
|
|
5869
|
+
type: "text_delta",
|
|
5870
|
+
content: part["text"],
|
|
5871
|
+
metadata: liveMeta
|
|
5872
|
+
});
|
|
5125
5873
|
}
|
|
5126
5874
|
}
|
|
5127
5875
|
}
|
|
@@ -5202,7 +5950,10 @@ function wrapModel(args, aiSDK, outerOperationId, ctx) {
|
|
|
5202
5950
|
attributes: [
|
|
5203
5951
|
...((_a = ctx.telemetry) == null ? void 0 : _a.recordOutputs) === false ? [] : [
|
|
5204
5952
|
attrString("ai.response.finishReason", finishReason),
|
|
5205
|
-
attrString(
|
|
5953
|
+
attrString(
|
|
5954
|
+
"ai.response.text",
|
|
5955
|
+
activeText.length ? capText2(activeText) : void 0
|
|
5956
|
+
),
|
|
5206
5957
|
attrString(
|
|
5207
5958
|
"ai.response.toolCalls",
|
|
5208
5959
|
safeJsonWithUint8(toolCallsLocal.length ? toolCallsLocal : void 0)
|
|
@@ -5220,7 +5971,8 @@ function wrapModel(args, aiSDK, outerOperationId, ctx) {
|
|
|
5220
5971
|
...finishReason ? [attrStringArray("gen_ai.response.finish_reasons", [finishReason])] : [],
|
|
5221
5972
|
attrString("gen_ai.response.id", responseId),
|
|
5222
5973
|
attrString(MODEL_USAGE_ATTRIBUTES.responseModel, finalResponseModelId),
|
|
5223
|
-
|
|
5974
|
+
attrString(MODEL_USAGE_ATTRIBUTES.usageSource, usageMetrics.usageSource),
|
|
5975
|
+
...buildRawModelUsageAttributes(usageMetrics),
|
|
5224
5976
|
...msToFirstChunk !== void 0 ? [attrInt("ai.stream.msToFirstChunk", msToFirstChunk)] : [],
|
|
5225
5977
|
...msToFinish !== void 0 ? [attrInt("ai.stream.msToFinish", msToFinish)] : [],
|
|
5226
5978
|
...avgOutTokensPerSecond !== void 0 ? [attrDouble("ai.stream.avgOutputTokensPerSecond", avgOutTokensPerSecond)] : [],
|
|
@@ -5274,19 +6026,44 @@ function wrapModel(args, aiSDK, outerOperationId, ctx) {
|
|
|
5274
6026
|
if ("providerMetadata" in value) providerMetadata = value["providerMetadata"];
|
|
5275
6027
|
if (localDebuggerEnabled() && ctx.rootParentForChildren) {
|
|
5276
6028
|
const traceId = ctx.rootParentForChildren.traceIdB64;
|
|
5277
|
-
const liveMeta = getLocalDebuggerMetadata({
|
|
6029
|
+
const liveMeta = getLocalDebuggerMetadata({
|
|
6030
|
+
...ctx.context,
|
|
6031
|
+
eventId: ctx.eventId
|
|
6032
|
+
});
|
|
5278
6033
|
if (type === "text-delta") {
|
|
5279
6034
|
const text = typeof value["delta"] === "string" ? value["delta"] : typeof value["textDelta"] === "string" ? value["textDelta"] : typeof value["text"] === "string" ? value["text"] : void 0;
|
|
5280
|
-
if (typeof text === "string" && text)
|
|
6035
|
+
if (typeof text === "string" && text)
|
|
6036
|
+
sendLocalDebuggerLiveEvent({
|
|
6037
|
+
traceId,
|
|
6038
|
+
type: "text_delta",
|
|
6039
|
+
content: text,
|
|
6040
|
+
metadata: liveMeta
|
|
6041
|
+
});
|
|
5281
6042
|
} else if (type === "reasoning" || type === "reasoning-delta") {
|
|
5282
6043
|
const text = typeof value["delta"] === "string" ? value["delta"] : typeof value["text"] === "string" ? value["text"] : typeof value["thinking"] === "string" ? value["thinking"] : void 0;
|
|
5283
|
-
if (typeof text === "string" && text)
|
|
6044
|
+
if (typeof text === "string" && text)
|
|
6045
|
+
sendLocalDebuggerLiveEvent({
|
|
6046
|
+
traceId,
|
|
6047
|
+
type: "reasoning_delta",
|
|
6048
|
+
content: text,
|
|
6049
|
+
metadata: liveMeta
|
|
6050
|
+
});
|
|
5284
6051
|
} else if (type === "tool-call") {
|
|
5285
6052
|
const toolName = typeof value["toolName"] === "string" ? value["toolName"] : "tool";
|
|
5286
|
-
sendLocalDebuggerLiveEvent({
|
|
6053
|
+
sendLocalDebuggerLiveEvent({
|
|
6054
|
+
traceId,
|
|
6055
|
+
type: "tool_start",
|
|
6056
|
+
content: toolName,
|
|
6057
|
+
metadata: { ...liveMeta, args: value["args"] }
|
|
6058
|
+
});
|
|
5287
6059
|
} else if (type === "tool-result") {
|
|
5288
6060
|
const toolName = typeof value["toolName"] === "string" ? value["toolName"] : "tool";
|
|
5289
|
-
sendLocalDebuggerLiveEvent({
|
|
6061
|
+
sendLocalDebuggerLiveEvent({
|
|
6062
|
+
traceId,
|
|
6063
|
+
type: "tool_result",
|
|
6064
|
+
content: toolName,
|
|
6065
|
+
metadata: { ...liveMeta, result: value["result"] }
|
|
6066
|
+
});
|
|
5290
6067
|
}
|
|
5291
6068
|
}
|
|
5292
6069
|
}
|
|
@@ -5366,11 +6143,7 @@ function endDoGenerateSpan(span, result, modelInfo, ctx) {
|
|
|
5366
6143
|
} else {
|
|
5367
6144
|
responseTimestampIso = (/* @__PURE__ */ new Date()).toISOString();
|
|
5368
6145
|
}
|
|
5369
|
-
const usageMetrics = extractUsageMetricsFromUsage(
|
|
5370
|
-
usage,
|
|
5371
|
-
modelInfo.provider,
|
|
5372
|
-
providerMetadata
|
|
5373
|
-
);
|
|
6146
|
+
const usageMetrics = extractUsageMetricsFromUsage(usage, modelInfo.provider, providerMetadata);
|
|
5374
6147
|
const { inputTokens, outputTokens } = usageMetrics;
|
|
5375
6148
|
ctx.traceShipper.endSpan(span, {
|
|
5376
6149
|
attributes: [
|
|
@@ -5391,7 +6164,8 @@ function endDoGenerateSpan(span, result, modelInfo, ctx) {
|
|
|
5391
6164
|
...finishReason ? [attrStringArray("gen_ai.response.finish_reasons", [finishReason])] : [],
|
|
5392
6165
|
attrString("gen_ai.response.id", responseId),
|
|
5393
6166
|
attrString(MODEL_USAGE_ATTRIBUTES.responseModel, responseModelId),
|
|
5394
|
-
|
|
6167
|
+
attrString(MODEL_USAGE_ATTRIBUTES.usageSource, usageMetrics.usageSource),
|
|
6168
|
+
...buildRawModelUsageAttributes(usageMetrics)
|
|
5395
6169
|
]
|
|
5396
6170
|
});
|
|
5397
6171
|
}
|
|
@@ -5500,6 +6274,8 @@ function eventMetadata(options) {
|
|
|
5500
6274
|
if (options.properties) result["raindrop.properties"] = JSON.stringify(options.properties);
|
|
5501
6275
|
if (options.featureFlags)
|
|
5502
6276
|
result["raindrop.featureFlags"] = JSON.stringify(normalizeFeatureFlags(options.featureFlags));
|
|
6277
|
+
if (options.subagent) Object.assign(result, detachedChildMetadata(options.subagent));
|
|
6278
|
+
if (options.toolEvents) result[TOOL_EVENTS_SUFFIX] = options.toolEvents;
|
|
5503
6279
|
return result;
|
|
5504
6280
|
}
|
|
5505
6281
|
function deriveChatTurnMessageId(request) {
|
|
@@ -5582,12 +6358,22 @@ function createRaindropAISDK(opts) {
|
|
|
5582
6358
|
transformSpan: (_j = opts.traces) == null ? void 0 : _j.transformSpan,
|
|
5583
6359
|
disableDefaultRedaction: (_k = opts.traces) == null ? void 0 : _k.disableDefaultRedaction
|
|
5584
6360
|
});
|
|
6361
|
+
const settledEventIds = /* @__PURE__ */ new Set();
|
|
6362
|
+
const subagentApi = new SubagentApi({
|
|
6363
|
+
traceShipper,
|
|
6364
|
+
eventShipper,
|
|
6365
|
+
sendTraces: tracesEnabled,
|
|
6366
|
+
sendEvents: eventsEnabled,
|
|
6367
|
+
debug: envDebug,
|
|
6368
|
+
settledEventIds
|
|
6369
|
+
});
|
|
5585
6370
|
return {
|
|
5586
6371
|
wrap(aiSDK, options) {
|
|
5587
6372
|
return wrapAISDK(aiSDK, {
|
|
5588
6373
|
options: options != null ? options : {},
|
|
5589
6374
|
eventShipper,
|
|
5590
|
-
traceShipper
|
|
6375
|
+
traceShipper,
|
|
6376
|
+
settledEventIds
|
|
5591
6377
|
});
|
|
5592
6378
|
},
|
|
5593
6379
|
createSelfDiagnosticsTool(options = {}) {
|
|
@@ -5624,9 +6410,14 @@ function createRaindropAISDK(opts) {
|
|
|
5624
6410
|
sendEvents: eventsEnabled,
|
|
5625
6411
|
subagentWrapping,
|
|
5626
6412
|
debug: envDebug,
|
|
6413
|
+
settledEventIds,
|
|
5627
6414
|
context
|
|
5628
6415
|
});
|
|
5629
6416
|
},
|
|
6417
|
+
subagents: subagentApi,
|
|
6418
|
+
subagent(options = {}) {
|
|
6419
|
+
return subagentApi.subagent(options);
|
|
6420
|
+
},
|
|
5630
6421
|
events: {
|
|
5631
6422
|
async patch(eventId, patch) {
|
|
5632
6423
|
await eventShipper.patch(eventId, patch);
|
|
@@ -5746,4 +6537,4 @@ function raindrop(options = {}) {
|
|
|
5746
6537
|
return client.createTelemetryIntegration({ context, subagentWrapping });
|
|
5747
6538
|
}
|
|
5748
6539
|
|
|
5749
|
-
export { DEFAULT_MAX_TEXT_FIELD_CHARS2 as DEFAULT_MAX_TEXT_FIELD_CHARS, DEFAULT_REDACT_ATTRIBUTE_KEYS, DEFAULT_SECRET_KEY_NAMES, REDACTED_PLACEHOLDER, RaindropTelemetryIntegration, TRUNCATION_MARKER2 as TRUNCATION_MARKER, _resetParentToolContextStorage, _resetRaindropCallMetadataStorage, _resetWarnedMissingUserId, boundedStringify, capText2 as capText, clearParentToolContext, createRaindropAISDK, currentSpan, defaultTransformSpan, enterParentToolContext, eventMetadata, eventMetadataFromChatRequest, getContextManager, getCurrentParentToolContext, getCurrentRaindropCallMetadata, normalizeFeatureFlags, raindrop, readRaindropCallMetadataFromArgs, redactJsonAttributeValue, redactSecretsInObject, runWithParentToolContext, runWithRaindropCallMetadata, withCurrent };
|
|
6540
|
+
export { DEFAULT_MAX_TEXT_FIELD_CHARS2 as DEFAULT_MAX_TEXT_FIELD_CHARS, DEFAULT_REDACT_ATTRIBUTE_KEYS, DEFAULT_SECRET_KEY_NAMES, DETACHED_MODE, HANDOFF_ATTRIBUTE_PREFIXES, HANDOFF_ATTRIBUTE_SUFFIXES, HANDOFF_TERMINAL_CANCELLED, HANDOFF_TERMINAL_PROPERTY_KEY, REDACTED_PLACEHOLDER, RaindropTelemetryIntegration, SUBAGENT_ABORTED_OUTPUT, SUBAGENT_AGENT_ROLE, SUBAGENT_CANCELLED_OUTPUT, TOOL_EVENTS_ALLOW, TRUNCATION_MARKER2 as TRUNCATION_MARKER, _resetParentToolContextStorage, _resetRaindropCallMetadataStorage, _resetWarnedMissingUserId, boundedStringify, capText2 as capText, clearParentToolContext, createRaindropAISDK, currentSpan, defaultTransformSpan, enterParentToolContext, eventMetadata, eventMetadataFromChatRequest, fromHeaders, getContextManager, getCurrentParentToolContext, getCurrentRaindropCallMetadata, normalizeFeatureFlags, raindrop, readRaindropCallMetadataFromArgs, redactJsonAttributeValue, redactSecretsInObject, resetUnresolvedCarrierWarning, runWithParentToolContext, runWithRaindropCallMetadata, toHeaders, toLangSmithHeaders, withCurrent };
|