@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
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { AsyncLocalStorage } from 'async_hooks';
|
|
2
2
|
|
|
3
|
-
// ../core/dist/chunk-
|
|
3
|
+
// ../core/dist/chunk-3V4MIA75.js
|
|
4
4
|
function normalizeFeatureFlags(input) {
|
|
5
5
|
if (Array.isArray(input)) {
|
|
6
6
|
return Object.fromEntries(input.map((name) => [name, "true"]));
|
|
@@ -63,6 +63,311 @@ function base64Encode(bytes) {
|
|
|
63
63
|
}
|
|
64
64
|
return out;
|
|
65
65
|
}
|
|
66
|
+
function base64ToHex(value) {
|
|
67
|
+
if (!value) return "";
|
|
68
|
+
const maybeBuffer = globalThis.Buffer;
|
|
69
|
+
if (maybeBuffer) {
|
|
70
|
+
return maybeBuffer.from(value, "base64").toString("hex");
|
|
71
|
+
}
|
|
72
|
+
const atobFn = globalThis.atob;
|
|
73
|
+
if (typeof atobFn !== "function") return "";
|
|
74
|
+
try {
|
|
75
|
+
const binary = atobFn(value);
|
|
76
|
+
let hex = "";
|
|
77
|
+
for (let i = 0; i < binary.length; i++) {
|
|
78
|
+
hex += (binary.charCodeAt(i) & 255).toString(16).padStart(2, "0");
|
|
79
|
+
}
|
|
80
|
+
return hex;
|
|
81
|
+
} catch (e) {
|
|
82
|
+
return "";
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
var HANDOFF_ATTRIBUTE_SUFFIXES = {
|
|
86
|
+
mode: "raindrop.handoff.mode",
|
|
87
|
+
childEventId: "raindrop.handoff.childEventId",
|
|
88
|
+
parentEventId: "raindrop.handoff.parentEventId",
|
|
89
|
+
parentSpanId: "raindrop.handoff.parentSpanId",
|
|
90
|
+
name: "raindrop.handoff.name",
|
|
91
|
+
terminal: "raindrop.handoff.terminal",
|
|
92
|
+
agentRole: "raindrop.agent.role"
|
|
93
|
+
};
|
|
94
|
+
var HANDOFF_ATTRIBUTE_PREFIXES = [
|
|
95
|
+
"ai.telemetry.metadata.",
|
|
96
|
+
"ai.settings.context.",
|
|
97
|
+
""
|
|
98
|
+
];
|
|
99
|
+
var AI_SDK_METADATA_PREFIX = "ai.telemetry.metadata.";
|
|
100
|
+
var DETACHED_MODE = "detached";
|
|
101
|
+
var SUBAGENT_AGENT_ROLE = "subagent";
|
|
102
|
+
var HANDOFF_TERMINAL_CANCELLED = "cancelled";
|
|
103
|
+
var TOOL_EVENTS_SUFFIX = "raindrop.toolEvents";
|
|
104
|
+
var TOOL_EVENTS_ALLOW = "allow";
|
|
105
|
+
var SUBAGENT_ABORT_OPERATION_ID = "ai.subagent.failed";
|
|
106
|
+
var SUBAGENT_ABORT_SPAN_NAME = SUBAGENT_ABORT_OPERATION_ID;
|
|
107
|
+
var DEFAULT_DISPATCH_SPAN_NAME = "launch_subagent";
|
|
108
|
+
var HANDOFF_TERMINAL_PROPERTY_KEY = HANDOFF_ATTRIBUTE_SUFFIXES.terminal;
|
|
109
|
+
function defined(entries) {
|
|
110
|
+
const out = {};
|
|
111
|
+
for (const [key, value] of Object.entries(entries)) {
|
|
112
|
+
if (typeof value === "string" && value.trim().length > 0) out[key] = value;
|
|
113
|
+
}
|
|
114
|
+
return out;
|
|
115
|
+
}
|
|
116
|
+
function detachedDispatchMetadata(dispatch) {
|
|
117
|
+
return defined({
|
|
118
|
+
[HANDOFF_ATTRIBUTE_SUFFIXES.mode]: DETACHED_MODE,
|
|
119
|
+
[HANDOFF_ATTRIBUTE_SUFFIXES.childEventId]: dispatch.childEventId,
|
|
120
|
+
[HANDOFF_ATTRIBUTE_SUFFIXES.name]: dispatch.name
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
function detachedChildMetadata(link) {
|
|
124
|
+
return defined({
|
|
125
|
+
[HANDOFF_ATTRIBUTE_SUFFIXES.parentEventId]: link.parentEventId,
|
|
126
|
+
[HANDOFF_ATTRIBUTE_SUFFIXES.parentSpanId]: link.parentSpanId,
|
|
127
|
+
[HANDOFF_ATTRIBUTE_SUFFIXES.name]: link.name,
|
|
128
|
+
[HANDOFF_ATTRIBUTE_SUFFIXES.agentRole]: SUBAGENT_AGENT_ROLE
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
function cancelledTerminalMetadata() {
|
|
132
|
+
return { [HANDOFF_ATTRIBUTE_SUFFIXES.terminal]: HANDOFF_TERMINAL_CANCELLED };
|
|
133
|
+
}
|
|
134
|
+
function cancelledTerminalAttributes() {
|
|
135
|
+
const bare = cancelledTerminalMetadata();
|
|
136
|
+
return { ...bare, ...withMetadataPrefix(bare) };
|
|
137
|
+
}
|
|
138
|
+
function toolEventsAllowMetadata() {
|
|
139
|
+
return { [TOOL_EVENTS_SUFFIX]: TOOL_EVENTS_ALLOW };
|
|
140
|
+
}
|
|
141
|
+
function withMetadataPrefix(metadata) {
|
|
142
|
+
const out = {};
|
|
143
|
+
for (const [key, value] of Object.entries(metadata)) {
|
|
144
|
+
out[key.startsWith(AI_SDK_METADATA_PREFIX) ? key : `${AI_SDK_METADATA_PREFIX}${key}`] = value;
|
|
145
|
+
}
|
|
146
|
+
return out;
|
|
147
|
+
}
|
|
148
|
+
function readHandoffField(metadata, suffix) {
|
|
149
|
+
for (const prefix of HANDOFF_ATTRIBUTE_PREFIXES) {
|
|
150
|
+
const value = metadata[`${prefix}${suffix}`];
|
|
151
|
+
if (typeof value === "string" && value.trim().length > 0) return value.trim();
|
|
152
|
+
}
|
|
153
|
+
return void 0;
|
|
154
|
+
}
|
|
155
|
+
function readDetachedChildLink(metadata) {
|
|
156
|
+
if (!metadata) return void 0;
|
|
157
|
+
const parentEventId = readHandoffField(metadata, HANDOFF_ATTRIBUTE_SUFFIXES.parentEventId);
|
|
158
|
+
if (!parentEventId) return void 0;
|
|
159
|
+
return {
|
|
160
|
+
parentEventId,
|
|
161
|
+
parentSpanId: readHandoffField(metadata, HANDOFF_ATTRIBUTE_SUFFIXES.parentSpanId),
|
|
162
|
+
name: readHandoffField(metadata, HANDOFF_ATTRIBUTE_SUFFIXES.name)
|
|
163
|
+
};
|
|
164
|
+
}
|
|
165
|
+
var BAGGAGE_KEYS = {
|
|
166
|
+
eventId: "raindrop-event-id",
|
|
167
|
+
childEventId: "raindrop-child-event-id",
|
|
168
|
+
name: "raindrop-handoff-name",
|
|
169
|
+
convoId: "raindrop-convo-id",
|
|
170
|
+
userId: "raindrop-user-id",
|
|
171
|
+
// The dispatch span and its trace, carried as fields as well as in
|
|
172
|
+
// `traceparent`. Not redundant: OTel's HTTP instrumentations rewrite
|
|
173
|
+
// `traceparent` from whatever span is current as the request goes out, so by
|
|
174
|
+
// the time the child reads it the ids name the HTTP client span and its trace
|
|
175
|
+
// instead of the dispatch. The child would then point its reverse reference at
|
|
176
|
+
// a span the launcher's UI does not know as a dispatch. A field states which
|
|
177
|
+
// span it means rather than meaning "whoever wrote this header last".
|
|
178
|
+
dispatchSpanId: "raindrop-dispatch-span-id",
|
|
179
|
+
traceId: "raindrop-trace-id"
|
|
180
|
+
};
|
|
181
|
+
var TRACEPARENT_HEADER = "traceparent";
|
|
182
|
+
var BAGGAGE_HEADER = "baggage";
|
|
183
|
+
var W3C_TRACE_ID = /^[0-9a-f]{32}$/;
|
|
184
|
+
var W3C_SPAN_ID = /^[0-9a-f]{16}$/;
|
|
185
|
+
function isW3CTraceId(value) {
|
|
186
|
+
return value !== void 0 && W3C_TRACE_ID.test(value);
|
|
187
|
+
}
|
|
188
|
+
function isW3CSpanId(value) {
|
|
189
|
+
return value !== void 0 && W3C_SPAN_ID.test(value);
|
|
190
|
+
}
|
|
191
|
+
var warnedNonConformantIds = false;
|
|
192
|
+
function warnNonConformantIdsOnce(traceId, spanId) {
|
|
193
|
+
if (warnedNonConformantIds) return;
|
|
194
|
+
warnedNonConformantIds = true;
|
|
195
|
+
console.warn(
|
|
196
|
+
`[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.`
|
|
197
|
+
);
|
|
198
|
+
}
|
|
199
|
+
var HANDOFF_HEADER = "x-raindrop-handoff";
|
|
200
|
+
var LANGSMITH_TRACE_HEADER = "langsmith-trace";
|
|
201
|
+
var LANGSMITH_METADATA_BAGGAGE_KEY = "langsmith-metadata";
|
|
202
|
+
function encodeBaggage(entries) {
|
|
203
|
+
return Object.entries(entries).filter((entry) => Boolean(entry[1])).map(([key, value]) => `${key}=${encodeURIComponent(value)}`).join(",");
|
|
204
|
+
}
|
|
205
|
+
function decodeBaggage(header) {
|
|
206
|
+
if (!header) return {};
|
|
207
|
+
const parsed = {};
|
|
208
|
+
for (const part of header.split(",")) {
|
|
209
|
+
const [rawKey, ...rest] = part.split("=");
|
|
210
|
+
if (!rawKey || rest.length === 0) continue;
|
|
211
|
+
const key = rawKey.trim();
|
|
212
|
+
let value;
|
|
213
|
+
try {
|
|
214
|
+
value = decodeURIComponent(rest.join("=").trim());
|
|
215
|
+
} catch (e) {
|
|
216
|
+
value = rest.join("=").trim();
|
|
217
|
+
}
|
|
218
|
+
if (key in parsed && parsed[key] !== value) throw new ConflictingCarrierError(key);
|
|
219
|
+
parsed[key] = value;
|
|
220
|
+
}
|
|
221
|
+
return parsed;
|
|
222
|
+
}
|
|
223
|
+
function carrierBaggage(carrier) {
|
|
224
|
+
return {
|
|
225
|
+
[BAGGAGE_KEYS.eventId]: carrier.eventId,
|
|
226
|
+
[BAGGAGE_KEYS.childEventId]: carrier.childEventId,
|
|
227
|
+
[BAGGAGE_KEYS.name]: carrier.name,
|
|
228
|
+
[BAGGAGE_KEYS.convoId]: carrier.convoId,
|
|
229
|
+
[BAGGAGE_KEYS.userId]: carrier.userId,
|
|
230
|
+
[BAGGAGE_KEYS.dispatchSpanId]: carrier.spanId,
|
|
231
|
+
[BAGGAGE_KEYS.traceId]: carrier.traceId
|
|
232
|
+
};
|
|
233
|
+
}
|
|
234
|
+
function toHeaders(carrier) {
|
|
235
|
+
const fields = encodeBaggage(carrierBaggage(carrier));
|
|
236
|
+
const headers = {
|
|
237
|
+
[BAGGAGE_HEADER]: fields,
|
|
238
|
+
[HANDOFF_HEADER]: fields
|
|
239
|
+
};
|
|
240
|
+
if (isW3CTraceId(carrier.traceId) && isW3CSpanId(carrier.spanId)) {
|
|
241
|
+
headers[TRACEPARENT_HEADER] = `00-${carrier.traceId}-${carrier.spanId}-01`;
|
|
242
|
+
}
|
|
243
|
+
return headers;
|
|
244
|
+
}
|
|
245
|
+
function langsmithStamp() {
|
|
246
|
+
return (/* @__PURE__ */ new Date()).toISOString().replace(/[-:]/g, "").replace(/\.\d+Z$/, "000000");
|
|
247
|
+
}
|
|
248
|
+
function toLangSmithHeaders(carrier) {
|
|
249
|
+
const stamp = langsmithStamp();
|
|
250
|
+
const dottedOrder = `${stamp}Z${carrier.traceId}.${stamp}Z${carrier.spanId}`;
|
|
251
|
+
return {
|
|
252
|
+
[LANGSMITH_TRACE_HEADER]: dottedOrder,
|
|
253
|
+
[BAGGAGE_HEADER]: encodeBaggage({
|
|
254
|
+
[LANGSMITH_METADATA_BAGGAGE_KEY]: JSON.stringify(carrierBaggage(carrier))
|
|
255
|
+
}),
|
|
256
|
+
// Carried here too: a LangSmith-shaped carrier is rewritten in transit
|
|
257
|
+
// exactly like the native one, and an injected `traceparent` is preferred
|
|
258
|
+
// over the dotted order on read.
|
|
259
|
+
[HANDOFF_HEADER]: encodeBaggage(carrierBaggage(carrier))
|
|
260
|
+
};
|
|
261
|
+
}
|
|
262
|
+
function isHeaderLookup(headers) {
|
|
263
|
+
return "get" in headers && typeof headers.get === "function";
|
|
264
|
+
}
|
|
265
|
+
var ConflictingCarrierError = class extends Error {
|
|
266
|
+
};
|
|
267
|
+
function readHeader(headers, name) {
|
|
268
|
+
var _a, _b, _c;
|
|
269
|
+
if (isHeaderLookup(headers)) return (_a = headers.get(name)) != null ? _a : void 0;
|
|
270
|
+
const value = (_c = headers[name]) != null ? _c : (_b = Object.entries(headers).find(([key]) => key.toLowerCase() === name)) == null ? void 0 : _b[1];
|
|
271
|
+
if (!Array.isArray(value)) return value;
|
|
272
|
+
const distinct = new Set(value);
|
|
273
|
+
if (distinct.size > 1) throw new ConflictingCarrierError(name);
|
|
274
|
+
return value[0];
|
|
275
|
+
}
|
|
276
|
+
function readTraceHeader(headers, name) {
|
|
277
|
+
const value = readHeader(headers, name);
|
|
278
|
+
if (!(value == null ? void 0 : value.includes(","))) return value;
|
|
279
|
+
const copies = value.split(",").map((copy) => copy.trim());
|
|
280
|
+
if (new Set(copies).size > 1) throw new ConflictingCarrierError(name);
|
|
281
|
+
return copies[0];
|
|
282
|
+
}
|
|
283
|
+
function fromHeaders(headers) {
|
|
284
|
+
var _a, _b;
|
|
285
|
+
let baggage;
|
|
286
|
+
let handoff;
|
|
287
|
+
let traceparent;
|
|
288
|
+
let langsmithTrace;
|
|
289
|
+
try {
|
|
290
|
+
baggage = decodeBaggage(readHeader(headers, BAGGAGE_HEADER));
|
|
291
|
+
handoff = decodeBaggage(readHeader(headers, HANDOFF_HEADER));
|
|
292
|
+
traceparent = readTraceHeader(headers, TRACEPARENT_HEADER);
|
|
293
|
+
langsmithTrace = readTraceHeader(headers, LANGSMITH_TRACE_HEADER);
|
|
294
|
+
} catch (error) {
|
|
295
|
+
if (error instanceof ConflictingCarrierError) return null;
|
|
296
|
+
throw error;
|
|
297
|
+
}
|
|
298
|
+
const langsmithMetadata = baggage[LANGSMITH_METADATA_BAGGAGE_KEY];
|
|
299
|
+
const nested = langsmithMetadata ? safeParseStringRecord(langsmithMetadata) : {};
|
|
300
|
+
for (const [key, value] of Object.entries(nested)) {
|
|
301
|
+
if (key in baggage && baggage[key] !== value) return null;
|
|
302
|
+
}
|
|
303
|
+
const fields = {
|
|
304
|
+
...baggage,
|
|
305
|
+
...nested,
|
|
306
|
+
// Last, so it wins: the standard headers may have been rewritten in transit
|
|
307
|
+
// by a propagator, this one is only ever written by us.
|
|
308
|
+
...handoff
|
|
309
|
+
};
|
|
310
|
+
let traceId;
|
|
311
|
+
let spanId;
|
|
312
|
+
if (traceparent) {
|
|
313
|
+
const [, parsedTraceId, parsedSpanId] = traceparent.split("-");
|
|
314
|
+
if (isW3CTraceId(parsedTraceId) && isW3CSpanId(parsedSpanId)) {
|
|
315
|
+
traceId = parsedTraceId;
|
|
316
|
+
spanId = parsedSpanId;
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
if (!traceId && !spanId && langsmithTrace) {
|
|
320
|
+
const segments = langsmithTrace.split(".");
|
|
321
|
+
traceId = (_a = segments[0]) == null ? void 0 : _a.split("Z").pop();
|
|
322
|
+
spanId = (_b = segments[segments.length - 1]) == null ? void 0 : _b.split("Z").pop();
|
|
323
|
+
}
|
|
324
|
+
traceId = fields[BAGGAGE_KEYS.traceId] || traceId;
|
|
325
|
+
spanId = fields[BAGGAGE_KEYS.dispatchSpanId] || spanId;
|
|
326
|
+
const eventId = fields[BAGGAGE_KEYS.eventId];
|
|
327
|
+
if (!traceId || !spanId || !eventId) return null;
|
|
328
|
+
if (!isW3CTraceId(traceId) || !isW3CSpanId(spanId)) {
|
|
329
|
+
warnNonConformantIdsOnce(traceId, spanId);
|
|
330
|
+
}
|
|
331
|
+
const carrier = { traceId, spanId, eventId };
|
|
332
|
+
const childEventId = fields[BAGGAGE_KEYS.childEventId];
|
|
333
|
+
if (childEventId) carrier.childEventId = childEventId;
|
|
334
|
+
const name = fields[BAGGAGE_KEYS.name];
|
|
335
|
+
if (name) carrier.name = name;
|
|
336
|
+
const convoId = fields[BAGGAGE_KEYS.convoId];
|
|
337
|
+
if (convoId) carrier.convoId = convoId;
|
|
338
|
+
const userId = fields[BAGGAGE_KEYS.userId];
|
|
339
|
+
if (userId) carrier.userId = userId;
|
|
340
|
+
return carrier;
|
|
341
|
+
}
|
|
342
|
+
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.`;
|
|
343
|
+
var UNRESOLVED_CARRIER_WARNED_KEY = /* @__PURE__ */ Symbol.for("raindrop.handoff.warnedUnresolvedCarrier");
|
|
344
|
+
function warnedHolder() {
|
|
345
|
+
return globalThis;
|
|
346
|
+
}
|
|
347
|
+
function resetUnresolvedCarrierWarning() {
|
|
348
|
+
warnedHolder()[UNRESOLVED_CARRIER_WARNED_KEY] = false;
|
|
349
|
+
}
|
|
350
|
+
function warnUnresolvedCarrier(headers, carrier) {
|
|
351
|
+
if (carrier) return;
|
|
352
|
+
if (!headers) return;
|
|
353
|
+
const holder = warnedHolder();
|
|
354
|
+
if (holder[UNRESOLVED_CARRIER_WARNED_KEY]) return;
|
|
355
|
+
holder[UNRESOLVED_CARRIER_WARNED_KEY] = true;
|
|
356
|
+
console.warn(UNRESOLVED_CARRIER_WARNING);
|
|
357
|
+
}
|
|
358
|
+
function safeParseStringRecord(raw) {
|
|
359
|
+
try {
|
|
360
|
+
const parsed = JSON.parse(raw);
|
|
361
|
+
if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) return {};
|
|
362
|
+
const result = {};
|
|
363
|
+
for (const [key, value] of Object.entries(parsed)) {
|
|
364
|
+
if (typeof value === "string") result[key] = value;
|
|
365
|
+
}
|
|
366
|
+
return result;
|
|
367
|
+
} catch (e) {
|
|
368
|
+
return {};
|
|
369
|
+
}
|
|
370
|
+
}
|
|
66
371
|
function runWithTracingSuppressed(fn) {
|
|
67
372
|
const hook = globalThis.RAINDROP_SUPPRESS_TRACING;
|
|
68
373
|
if (typeof hook !== "function") return fn();
|
|
@@ -827,6 +1132,7 @@ var EventShipper = class {
|
|
|
827
1132
|
}
|
|
828
1133
|
};
|
|
829
1134
|
var MODEL_USAGE_ATTRIBUTES = {
|
|
1135
|
+
usageSource: "raindrop.usage.source",
|
|
830
1136
|
providerName: "gen_ai.provider.name",
|
|
831
1137
|
requestModel: "gen_ai.request.model",
|
|
832
1138
|
responseModel: "gen_ai.response.model",
|
|
@@ -835,20 +1141,22 @@ var MODEL_USAGE_ATTRIBUTES = {
|
|
|
835
1141
|
reasoningTokens: "gen_ai.usage.reasoning_tokens",
|
|
836
1142
|
cacheReadInputTokens: "gen_ai.usage.cache_read_input_tokens",
|
|
837
1143
|
cacheWriteInputTokens: "gen_ai.usage.cache_write_input_tokens",
|
|
838
|
-
|
|
839
|
-
nonReasoningOutputTokens: "raindrop.usage.output_tokens.non_reasoning",
|
|
840
|
-
reasoningOutputTokens: "raindrop.usage.output_tokens.reasoning",
|
|
841
|
-
cacheReadTokens: "raindrop.usage.input_tokens.cache_read",
|
|
842
|
-
cacheWriteTokens: "raindrop.usage.input_tokens.cache_write"
|
|
843
|
-
};
|
|
1144
|
+
providerReportedCost: "gen_ai.usage.provider_reported_cost"};
|
|
844
1145
|
var MODEL_PROVIDER_NAMES = [
|
|
1146
|
+
["google.vertex.anthropic", "google-vertex"],
|
|
1147
|
+
["google.vertex_ai", "google-vertex"],
|
|
845
1148
|
["google.vertex", "google-vertex"],
|
|
1149
|
+
["gcp.vertex_ai", "google-vertex"],
|
|
1150
|
+
["gcp.gemini", "google"],
|
|
1151
|
+
["google_vertexai", "google-vertex"],
|
|
846
1152
|
["vertex.anthropic", "google-vertex"],
|
|
847
1153
|
["amazon-bedrock", "amazon-bedrock"],
|
|
1154
|
+
["aws.bedrock", "amazon-bedrock"],
|
|
848
1155
|
["bedrock", "amazon-bedrock"],
|
|
849
1156
|
["anthropic", "anthropic"],
|
|
850
1157
|
["openai", "openai"],
|
|
851
1158
|
["google", "google"],
|
|
1159
|
+
["az.ai.openai", "azure"],
|
|
852
1160
|
["azure", "azure"],
|
|
853
1161
|
["openrouter", "openrouter"]
|
|
854
1162
|
];
|
|
@@ -859,60 +1167,20 @@ function canonicalModelProvider(provider) {
|
|
|
859
1167
|
const match = MODEL_PROVIDER_NAMES.find(
|
|
860
1168
|
([family]) => normalizedProvider === family || normalizedProvider.startsWith(`${family}.`)
|
|
861
1169
|
);
|
|
862
|
-
return (_a = match == null ? void 0 : match[1]) != null ? _a :
|
|
1170
|
+
return (_a = match == null ? void 0 : match[1]) != null ? _a : normalizedProvider;
|
|
863
1171
|
}
|
|
864
1172
|
function tokenCount(value) {
|
|
865
1173
|
return typeof value === "number" && Number.isSafeInteger(value) && value >= 0 ? value : void 0;
|
|
866
1174
|
}
|
|
867
|
-
function
|
|
868
|
-
|
|
869
|
-
total,
|
|
870
|
-
parts,
|
|
871
|
-
semantics
|
|
872
|
-
}) {
|
|
873
|
-
if (explicit !== void 0) return explicit;
|
|
874
|
-
if (total === void 0) return void 0;
|
|
875
|
-
if (semantics === "exclusive") return total;
|
|
876
|
-
const observedParts = parts.filter((part) => part !== void 0 && part > 0);
|
|
877
|
-
if (semantics === void 0 && observedParts.length > 0) return void 0;
|
|
878
|
-
const exclusive = total - observedParts.reduce((sum, part) => sum + part, 0);
|
|
879
|
-
return exclusive >= 0 ? exclusive : void 0;
|
|
880
|
-
}
|
|
881
|
-
function buildModelUsageAttributes(usage) {
|
|
882
|
-
const inputTokens = tokenCount(usage.inputTokens);
|
|
883
|
-
const outputTokens = tokenCount(usage.outputTokens);
|
|
884
|
-
const explicitNonCachedInputTokens = tokenCount(usage.nonCachedInputTokens);
|
|
885
|
-
const explicitNonReasoningOutputTokens = tokenCount(usage.nonReasoningOutputTokens);
|
|
886
|
-
const reasoningTokens = tokenCount(usage.reasoningTokens);
|
|
887
|
-
const cacheReadInputTokens = tokenCount(usage.cacheReadInputTokens);
|
|
888
|
-
const cacheWriteInputTokens = tokenCount(usage.cacheWriteInputTokens);
|
|
889
|
-
const nonCachedInputTokens = exclusiveTokens({
|
|
890
|
-
explicit: explicitNonCachedInputTokens,
|
|
891
|
-
total: inputTokens,
|
|
892
|
-
parts: [cacheReadInputTokens, cacheWriteInputTokens],
|
|
893
|
-
semantics: usage.inputTokenSemantics
|
|
894
|
-
});
|
|
895
|
-
const nonReasoningOutputTokens = exclusiveTokens({
|
|
896
|
-
explicit: explicitNonReasoningOutputTokens,
|
|
897
|
-
total: outputTokens,
|
|
898
|
-
parts: [reasoningTokens],
|
|
899
|
-
semantics: usage.outputTokenSemantics
|
|
900
|
-
});
|
|
901
|
-
const exclusivePoolAttributes = nonCachedInputTokens !== void 0 && nonReasoningOutputTokens !== void 0 ? [
|
|
902
|
-
// backend consumes this complete raindrop.* set as one atomic billing-pool contract.
|
|
903
|
-
attrInt(MODEL_USAGE_ATTRIBUTES.nonCachedInputTokens, nonCachedInputTokens),
|
|
904
|
-
attrInt(MODEL_USAGE_ATTRIBUTES.nonReasoningOutputTokens, nonReasoningOutputTokens),
|
|
905
|
-
attrInt(MODEL_USAGE_ATTRIBUTES.reasoningOutputTokens, reasoningTokens),
|
|
906
|
-
attrInt(MODEL_USAGE_ATTRIBUTES.cacheReadTokens, cacheReadInputTokens),
|
|
907
|
-
attrInt(MODEL_USAGE_ATTRIBUTES.cacheWriteTokens, cacheWriteInputTokens)
|
|
908
|
-
] : [];
|
|
1175
|
+
function buildRawModelUsageAttributes(usage) {
|
|
1176
|
+
const providerReportedCost = typeof usage.providerReportedCost === "number" && Number.isFinite(usage.providerReportedCost) && usage.providerReportedCost >= 0 ? usage.providerReportedCost : void 0;
|
|
909
1177
|
return [
|
|
910
|
-
attrInt(MODEL_USAGE_ATTRIBUTES.inputTokens, inputTokens),
|
|
911
|
-
attrInt(MODEL_USAGE_ATTRIBUTES.outputTokens, outputTokens),
|
|
912
|
-
attrInt(MODEL_USAGE_ATTRIBUTES.reasoningTokens, reasoningTokens),
|
|
913
|
-
attrInt(MODEL_USAGE_ATTRIBUTES.cacheReadInputTokens, cacheReadInputTokens),
|
|
914
|
-
attrInt(MODEL_USAGE_ATTRIBUTES.cacheWriteInputTokens, cacheWriteInputTokens),
|
|
915
|
-
|
|
1178
|
+
attrInt(MODEL_USAGE_ATTRIBUTES.inputTokens, tokenCount(usage.inputTokens)),
|
|
1179
|
+
attrInt(MODEL_USAGE_ATTRIBUTES.outputTokens, tokenCount(usage.outputTokens)),
|
|
1180
|
+
attrInt(MODEL_USAGE_ATTRIBUTES.reasoningTokens, tokenCount(usage.reasoningTokens)),
|
|
1181
|
+
attrInt(MODEL_USAGE_ATTRIBUTES.cacheReadInputTokens, tokenCount(usage.cacheReadInputTokens)),
|
|
1182
|
+
attrInt(MODEL_USAGE_ATTRIBUTES.cacheWriteInputTokens, tokenCount(usage.cacheWriteInputTokens)),
|
|
1183
|
+
attrDouble(MODEL_USAGE_ATTRIBUTES.providerReportedCost, providerReportedCost)
|
|
916
1184
|
].filter((attribute) => attribute !== void 0);
|
|
917
1185
|
}
|
|
918
1186
|
var STRING_ALIASES = {
|
|
@@ -2442,37 +2710,361 @@ function runWithParentToolContext(ctx, fn) {
|
|
|
2442
2710
|
return getStorage2().run(ctx, fn);
|
|
2443
2711
|
}
|
|
2444
2712
|
|
|
2445
|
-
// src/internal/
|
|
2446
|
-
|
|
2447
|
-
|
|
2448
|
-
|
|
2449
|
-
|
|
2713
|
+
// src/internal/subagents.ts
|
|
2714
|
+
var SUBAGENT_CANCELLED_OUTPUT = "Cancelled before producing a result.";
|
|
2715
|
+
var SUBAGENT_ABORTED_OUTPUT = "Aborted before producing a result.";
|
|
2716
|
+
var SUBAGENT_FAILED_OPERATION_ID = SUBAGENT_ABORT_OPERATION_ID;
|
|
2717
|
+
var MAX_SETTLED_EVENT_IDS = 1024;
|
|
2718
|
+
function isTraceCarrier(value) {
|
|
2719
|
+
const candidate = value;
|
|
2720
|
+
return typeof candidate.traceId === "string" && typeof candidate.spanId === "string" && typeof candidate.eventId === "string";
|
|
2721
|
+
}
|
|
2722
|
+
function attrsFrom(metadata) {
|
|
2723
|
+
return Object.entries(withMetadataPrefix(metadata)).map(([key, value]) => attrString(key, value));
|
|
2724
|
+
}
|
|
2725
|
+
function attrsExact(attributes) {
|
|
2726
|
+
return Object.entries(attributes).map(([key, value]) => attrString(key, value));
|
|
2727
|
+
}
|
|
2728
|
+
function handoffSpanAttrs(link) {
|
|
2729
|
+
if (!link) return [];
|
|
2730
|
+
return attrsFrom(detachedChildMetadata(link));
|
|
2731
|
+
}
|
|
2732
|
+
function subagentNameAttrs(name, link) {
|
|
2733
|
+
if (!name || (link == null ? void 0 : link.name)) return [];
|
|
2734
|
+
return attrsFrom({ [HANDOFF_ATTRIBUTE_SUFFIXES.name]: name });
|
|
2735
|
+
}
|
|
2736
|
+
function cancelledSpanAttrs() {
|
|
2737
|
+
return attrsExact(cancelledTerminalAttributes());
|
|
2738
|
+
}
|
|
2739
|
+
function describeAbortReason(reason) {
|
|
2740
|
+
if (reason instanceof Error) return `Aborted: ${reason.message}`;
|
|
2741
|
+
if (typeof reason === "string" && reason.trim().length > 0) return reason;
|
|
2742
|
+
if (reason === void 0 || reason === null) return SUBAGENT_ABORTED_OUTPUT;
|
|
2743
|
+
const serialized = boundedStringify(reason);
|
|
2744
|
+
return serialized ? `Aborted: ${serialized}` : SUBAGENT_ABORTED_OUTPUT;
|
|
2745
|
+
}
|
|
2746
|
+
function stampOpenSpan(span, metadata) {
|
|
2747
|
+
if (span.endTimeUnixNano) return;
|
|
2748
|
+
span.attributes.push(...attrsFrom(metadata));
|
|
2749
|
+
}
|
|
2750
|
+
function stampOpenSpanExact(span, attributes) {
|
|
2751
|
+
if (span.endTimeUnixNano) return;
|
|
2752
|
+
span.attributes.push(...attrsExact(attributes));
|
|
2753
|
+
}
|
|
2754
|
+
var SubagentApi = class {
|
|
2755
|
+
constructor(opts) {
|
|
2756
|
+
var _a;
|
|
2757
|
+
this.opts = opts;
|
|
2758
|
+
this.settledEventIds = (_a = opts.settledEventIds) != null ? _a : /* @__PURE__ */ new Set();
|
|
2759
|
+
}
|
|
2760
|
+
/** True when this child's outcome has already been reported. */
|
|
2761
|
+
wasSettledExplicitly(eventId) {
|
|
2762
|
+
return this.settledEventIds.has(eventId);
|
|
2763
|
+
}
|
|
2764
|
+
/**
|
|
2765
|
+
* Record an outcome reported somewhere other than `cancel()` / `fail()`, so
|
|
2766
|
+
* first-outcome-wins holds across every path that can state one.
|
|
2767
|
+
*
|
|
2768
|
+
* An aborted generation is such a path: an AbortSignal cancellation IS the
|
|
2769
|
+
* run's outcome, and the `fail(err)` that a catch block around the aborted
|
|
2770
|
+
* call naturally reports would otherwise error the child's spans — which is
|
|
2771
|
+
* the only thing separating `failed` from `cancelled`.
|
|
2772
|
+
*/
|
|
2773
|
+
noteSettled(eventId) {
|
|
2774
|
+
this.remember(eventId);
|
|
2775
|
+
}
|
|
2776
|
+
remember(eventId) {
|
|
2777
|
+
if (this.settledEventIds.has(eventId)) return;
|
|
2778
|
+
if (this.settledEventIds.size >= MAX_SETTLED_EVENT_IDS) {
|
|
2779
|
+
const oldest = this.settledEventIds.values().next();
|
|
2780
|
+
if (!oldest.done) this.settledEventIds.delete(oldest.value);
|
|
2450
2781
|
}
|
|
2782
|
+
this.settledEventIds.add(eventId);
|
|
2451
2783
|
}
|
|
2452
|
-
|
|
2453
|
-
|
|
2454
|
-
|
|
2455
|
-
|
|
2456
|
-
|
|
2457
|
-
|
|
2458
|
-
|
|
2459
|
-
|
|
2460
|
-
|
|
2784
|
+
/**
|
|
2785
|
+
* Record a detached sub-agent on this turn: allocate the child's event id,
|
|
2786
|
+
* stamp the dispatch, and return the headers to send with the job.
|
|
2787
|
+
*
|
|
2788
|
+
* This dispatches nothing — you do, moments later, with the returned headers.
|
|
2789
|
+
* Nothing here waits for the child either, or claims to know how it is doing.
|
|
2790
|
+
* Readers derive that from the child's own event.
|
|
2791
|
+
*/
|
|
2792
|
+
subagent(options = {}) {
|
|
2793
|
+
var _a;
|
|
2794
|
+
const childEventId = (_a = options.childEventId) != null ? _a : randomUUID();
|
|
2795
|
+
const name = options.name;
|
|
2796
|
+
try {
|
|
2797
|
+
return this.recordLaunch(childEventId, name, options);
|
|
2798
|
+
} catch (err) {
|
|
2799
|
+
if (this.opts.debug) {
|
|
2800
|
+
console.warn(
|
|
2801
|
+
`[raindrop-ai/ai-sdk] sub-agent dispatch not recorded: ${err instanceof Error ? err.message : err}`
|
|
2802
|
+
);
|
|
2803
|
+
}
|
|
2804
|
+
return { childEventId, name, headers: {}, carrier: null };
|
|
2805
|
+
}
|
|
2461
2806
|
}
|
|
2462
|
-
|
|
2463
|
-
|
|
2464
|
-
|
|
2465
|
-
|
|
2807
|
+
recordLaunch(childEventId, name, options) {
|
|
2808
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p;
|
|
2809
|
+
const active = (_a = this.opts.spanSource) == null ? void 0 : _a.activeDispatch();
|
|
2810
|
+
const inherited = getContextManager().getParentSpanIds();
|
|
2811
|
+
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;
|
|
2812
|
+
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;
|
|
2813
|
+
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;
|
|
2814
|
+
if (!eventId) {
|
|
2815
|
+
return { childEventId, name, headers: {}, carrier: null };
|
|
2816
|
+
}
|
|
2817
|
+
const dispatch = detachedDispatchMetadata({ childEventId, name });
|
|
2818
|
+
const toolEvents = toolEventsAllowMetadata();
|
|
2819
|
+
for (const span of (_l = active == null ? void 0 : active.turnSpans) != null ? _l : []) {
|
|
2820
|
+
stampOpenSpan(span, toolEvents);
|
|
2821
|
+
}
|
|
2822
|
+
let dispatchIds;
|
|
2823
|
+
if (active == null ? void 0 : active.dispatchSpan) {
|
|
2824
|
+
stampOpenSpan(active.dispatchSpan, dispatch);
|
|
2825
|
+
dispatchIds = active.dispatchSpan.ids;
|
|
2826
|
+
} else if (this.opts.sendTraces) {
|
|
2827
|
+
dispatchIds = this.synthesizeDispatchSpan({
|
|
2828
|
+
childEventId,
|
|
2829
|
+
name,
|
|
2830
|
+
toolName: options.toolName,
|
|
2831
|
+
eventId,
|
|
2832
|
+
userId,
|
|
2833
|
+
convoId,
|
|
2834
|
+
input: options.input,
|
|
2835
|
+
// No active turn means no telemetry setting to honor: `input` is then
|
|
2836
|
+
// recorded on the explicit say-so of whoever passed it.
|
|
2837
|
+
recordInputs: (_m = active == null ? void 0 : active.recordInputs) != null ? _m : true,
|
|
2838
|
+
dispatch,
|
|
2839
|
+
parent: (inherited == null ? void 0 : inherited.eventId) === eventId ? inherited : void 0
|
|
2840
|
+
}).ids;
|
|
2841
|
+
}
|
|
2842
|
+
const traceId = base64ToHex((_o = (_n = dispatchIds == null ? void 0 : dispatchIds.traceIdB64) != null ? _n : inherited == null ? void 0 : inherited.traceIdB64) != null ? _o : "");
|
|
2843
|
+
const spanId = base64ToHex((_p = dispatchIds == null ? void 0 : dispatchIds.spanIdB64) != null ? _p : "");
|
|
2844
|
+
if (!traceId || !spanId) {
|
|
2845
|
+
if (this.opts.debug) {
|
|
2846
|
+
console.warn(
|
|
2847
|
+
"[raindrop-ai/ai-sdk] sub-agent dispatch recorded without a carrier: no dispatch span to reference (traces disabled?)"
|
|
2848
|
+
);
|
|
2849
|
+
}
|
|
2850
|
+
return { childEventId, name, headers: {}, carrier: null };
|
|
2851
|
+
}
|
|
2852
|
+
const carrier = {
|
|
2853
|
+
traceId,
|
|
2854
|
+
spanId,
|
|
2855
|
+
eventId,
|
|
2856
|
+
childEventId,
|
|
2857
|
+
...name ? { name } : {},
|
|
2858
|
+
...convoId ? { convoId } : {},
|
|
2859
|
+
...userId ? { userId } : {}
|
|
2466
2860
|
};
|
|
2861
|
+
return { childEventId, name, headers: toHeaders(carrier), carrier };
|
|
2467
2862
|
}
|
|
2468
|
-
|
|
2863
|
+
/**
|
|
2864
|
+
* Record a dispatch span for a launch with no open tool-call span to decorate:
|
|
2865
|
+
* a launch from outside a tool's `execute`, or from a caller that is not an
|
|
2866
|
+
* LLM turn at all (an HTTP handler that enqueues jobs). Shaped as a tool call
|
|
2867
|
+
* so it reads identically to a model-issued launch.
|
|
2868
|
+
*/
|
|
2869
|
+
synthesizeDispatchSpan(args) {
|
|
2870
|
+
var _a;
|
|
2871
|
+
const spanName = (_a = args.toolName) != null ? _a : DEFAULT_DISPATCH_SPAN_NAME;
|
|
2872
|
+
const span = this.opts.traceShipper.startSpan({
|
|
2873
|
+
name: spanName,
|
|
2874
|
+
parent: args.parent,
|
|
2875
|
+
eventId: args.eventId,
|
|
2876
|
+
userId: args.userId,
|
|
2877
|
+
convoId: args.convoId,
|
|
2878
|
+
operationId: "ai.toolCall",
|
|
2879
|
+
attributes: [
|
|
2880
|
+
attrString("operation.name", "ai.toolCall"),
|
|
2881
|
+
attrString("resource.name", spanName),
|
|
2882
|
+
attrString("ai.toolCall.name", spanName),
|
|
2883
|
+
attrString("ai.toolCall.id", `call_${args.childEventId.replace(/-/g, "").slice(0, 12)}`),
|
|
2884
|
+
// Gated like every other input the turn's spans record: a caller that
|
|
2885
|
+
// disabled input capture must not leak the payload through the one
|
|
2886
|
+
// span this API synthesizes on its behalf.
|
|
2887
|
+
...args.recordInputs ? [attrString("ai.toolCall.args", boundedStringify(args.input))] : [],
|
|
2888
|
+
...attrsFrom(args.dispatch)
|
|
2889
|
+
]
|
|
2890
|
+
});
|
|
2891
|
+
this.opts.traceShipper.endSpan(span, {
|
|
2892
|
+
// A dispatch returns a handle, not an answer — the answer is the child's.
|
|
2893
|
+
attributes: [
|
|
2894
|
+
attrString(
|
|
2895
|
+
"ai.toolCall.result",
|
|
2896
|
+
boundedStringify({ jobId: args.childEventId, status: "accepted" })
|
|
2897
|
+
)
|
|
2898
|
+
]
|
|
2899
|
+
});
|
|
2900
|
+
return span;
|
|
2901
|
+
}
|
|
2902
|
+
/**
|
|
2903
|
+
* Adopt a carrier as the current run's parent reference.
|
|
2904
|
+
*
|
|
2905
|
+
* A missing carrier is a legitimate state — the child was invoked directly
|
|
2906
|
+
* rather than dispatched — so this always returns a usable run and leaves
|
|
2907
|
+
* `parent` null. Call sites stay unconditional.
|
|
2908
|
+
*/
|
|
2909
|
+
resume(carrierOrHeaders, options = {}) {
|
|
2910
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _i;
|
|
2911
|
+
const carrier = carrierOrHeaders ? isTraceCarrier(carrierOrHeaders) ? carrierOrHeaders : this.readCarrier(carrierOrHeaders) : null;
|
|
2912
|
+
warnUnresolvedCarrier(carrierOrHeaders, carrier);
|
|
2913
|
+
const name = (_a = carrier == null ? void 0 : carrier.name) != null ? _a : options.name;
|
|
2914
|
+
const eventId = (_c = (_b = carrier == null ? void 0 : carrier.childEventId) != null ? _b : options.eventId) != null ? _c : randomUUID();
|
|
2915
|
+
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;
|
|
2916
|
+
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;
|
|
2917
|
+
const parent = carrier ? {
|
|
2918
|
+
parentEventId: carrier.eventId,
|
|
2919
|
+
...carrier.spanId ? { parentSpanId: carrier.spanId } : {},
|
|
2920
|
+
...name ? { name } : {}
|
|
2921
|
+
} : null;
|
|
2469
2922
|
return {
|
|
2470
|
-
|
|
2471
|
-
|
|
2472
|
-
|
|
2923
|
+
eventId,
|
|
2924
|
+
name,
|
|
2925
|
+
userId,
|
|
2926
|
+
convoId,
|
|
2927
|
+
parent,
|
|
2928
|
+
metadata: {
|
|
2929
|
+
eventId,
|
|
2930
|
+
...userId ? { userId } : {},
|
|
2931
|
+
...convoId ? { convoId } : {},
|
|
2932
|
+
...parent ? { subagent: parent } : {}
|
|
2933
|
+
},
|
|
2934
|
+
cancel: (reason) => this.settle(eventId, { userId, convoId, name, cancelled: true, output: reason }),
|
|
2935
|
+
fail: (reason) => this.settle(eventId, {
|
|
2936
|
+
userId,
|
|
2937
|
+
convoId,
|
|
2938
|
+
name,
|
|
2939
|
+
handoff: parent != null ? parent : void 0,
|
|
2940
|
+
cancelled: false,
|
|
2941
|
+
output: describeAbortReason(reason),
|
|
2942
|
+
error: reason
|
|
2943
|
+
})
|
|
2473
2944
|
};
|
|
2474
2945
|
}
|
|
2475
|
-
|
|
2946
|
+
/**
|
|
2947
|
+
* A carrier arrives from outside this process, so a hostile or merely broken
|
|
2948
|
+
* header bag must cost the job its link, never its run.
|
|
2949
|
+
*/
|
|
2950
|
+
readCarrier(headers) {
|
|
2951
|
+
try {
|
|
2952
|
+
return fromHeaders(headers);
|
|
2953
|
+
} catch (err) {
|
|
2954
|
+
if (this.opts.debug) {
|
|
2955
|
+
console.warn(
|
|
2956
|
+
`[raindrop-ai/ai-sdk] sub-agent carrier ignored: ${err instanceof Error ? err.message : err}`
|
|
2957
|
+
);
|
|
2958
|
+
}
|
|
2959
|
+
return null;
|
|
2960
|
+
}
|
|
2961
|
+
}
|
|
2962
|
+
/**
|
|
2963
|
+
* Mark a failed child's own spans as errored.
|
|
2964
|
+
*
|
|
2965
|
+
* Reporting the reason as output is what gets the child an event at all, but
|
|
2966
|
+
* output alone is not enough: status is derived from span shape, and a child
|
|
2967
|
+
* with final output and no error spans derives `finished`. A failed job
|
|
2968
|
+
* reporting success is worse than one reporting nothing, so the failure has
|
|
2969
|
+
* to land on the telemetry too, not just in the text.
|
|
2970
|
+
*
|
|
2971
|
+
* This is the child describing its own run, not a caller writing a status it
|
|
2972
|
+
* cannot observe — the child's own spans are exactly where the contract puts
|
|
2973
|
+
* failure.
|
|
2974
|
+
*/
|
|
2975
|
+
recordFailureOnSpans(eventId, args, reason) {
|
|
2976
|
+
var _a, _b, _c;
|
|
2977
|
+
if (!this.opts.sendTraces) return;
|
|
2978
|
+
const failure = (_a = args.error) != null ? _a : reason;
|
|
2979
|
+
let marked = 0;
|
|
2980
|
+
for (const span2 of (_c = (_b = this.opts.spanSource) == null ? void 0 : _b.openSpansForEvent(eventId)) != null ? _c : []) {
|
|
2981
|
+
if (span2.endTimeUnixNano) continue;
|
|
2982
|
+
this.opts.traceShipper.endSpan(span2, { error: failure });
|
|
2983
|
+
marked++;
|
|
2984
|
+
}
|
|
2985
|
+
if (marked > 0) return;
|
|
2986
|
+
const spanName = SUBAGENT_ABORT_SPAN_NAME;
|
|
2987
|
+
const span = this.opts.traceShipper.startSpan({
|
|
2988
|
+
name: spanName,
|
|
2989
|
+
eventId,
|
|
2990
|
+
userId: args.userId,
|
|
2991
|
+
convoId: args.convoId,
|
|
2992
|
+
// Required, not decorative: ingest drops any span carrying no
|
|
2993
|
+
// `ai.operationId` (or traceloop / `gen_ai.*` key) and still answers 200,
|
|
2994
|
+
// so without this the failure disappears silently. The value is
|
|
2995
|
+
// deliberately none of the generate/stream/tool/embed forms, which is
|
|
2996
|
+
// what classifies the span as INTERNAL rather than mislabelling a failed
|
|
2997
|
+
// job as a model call or a tool call.
|
|
2998
|
+
operationId: SUBAGENT_FAILED_OPERATION_ID,
|
|
2999
|
+
// Carries the reverse reference like every other span the child emits:
|
|
3000
|
+
// this is often the child's ONLY span, and a span read on its own is the
|
|
3001
|
+
// whole reason the reference cannot live on the root alone. The name is
|
|
3002
|
+
// stamped even for an unlinked run, which has no caller to reference —
|
|
3003
|
+
// `span_name` no longer says which sub-agent this was, so the attribute
|
|
3004
|
+
// is the only thing that can.
|
|
3005
|
+
attributes: [
|
|
3006
|
+
attrString("resource.name", spanName),
|
|
3007
|
+
...handoffSpanAttrs(args.handoff),
|
|
3008
|
+
...subagentNameAttrs(args.name, args.handoff)
|
|
3009
|
+
]
|
|
3010
|
+
});
|
|
3011
|
+
this.opts.traceShipper.endSpan(span, { error: failure });
|
|
3012
|
+
}
|
|
3013
|
+
async settle(eventId, args) {
|
|
3014
|
+
var _a, _b;
|
|
3015
|
+
if (this.settledEventIds.has(eventId)) {
|
|
3016
|
+
if (this.opts.debug) {
|
|
3017
|
+
console.warn(
|
|
3018
|
+
`[raindrop-ai/ai-sdk] sub-agent ${eventId} already reported an outcome; ignoring the second one`
|
|
3019
|
+
);
|
|
3020
|
+
}
|
|
3021
|
+
return;
|
|
3022
|
+
}
|
|
3023
|
+
this.remember(eventId);
|
|
3024
|
+
const output = args.output && args.output.trim().length > 0 ? args.output : args.cancelled ? SUBAGENT_CANCELLED_OUTPUT : SUBAGENT_ABORTED_OUTPUT;
|
|
3025
|
+
try {
|
|
3026
|
+
if (args.cancelled) {
|
|
3027
|
+
for (const span of (_b = (_a = this.opts.spanSource) == null ? void 0 : _a.openSpansForEvent(eventId)) != null ? _b : []) {
|
|
3028
|
+
stampOpenSpanExact(span, cancelledTerminalAttributes());
|
|
3029
|
+
}
|
|
3030
|
+
} else {
|
|
3031
|
+
this.recordFailureOnSpans(eventId, args, output);
|
|
3032
|
+
}
|
|
3033
|
+
} catch (err) {
|
|
3034
|
+
if (this.opts.debug) {
|
|
3035
|
+
console.warn(
|
|
3036
|
+
`[raindrop-ai/ai-sdk] sub-agent outcome not recorded on spans: ${err instanceof Error ? err.message : err}`
|
|
3037
|
+
);
|
|
3038
|
+
}
|
|
3039
|
+
}
|
|
3040
|
+
if (!this.opts.sendEvents) return;
|
|
3041
|
+
await this.opts.eventShipper.patch(eventId, {
|
|
3042
|
+
userId: args.userId,
|
|
3043
|
+
convoId: args.convoId,
|
|
3044
|
+
// An event is only created from a run that reported something. A child
|
|
3045
|
+
// that dies silently produces no event at all, which pins the caller on
|
|
3046
|
+
// `queued` forever — indistinguishable from a job that never started.
|
|
3047
|
+
output,
|
|
3048
|
+
...args.cancelled ? { properties: { [HANDOFF_TERMINAL_PROPERTY_KEY]: HANDOFF_TERMINAL_CANCELLED } } : {},
|
|
3049
|
+
isPending: false
|
|
3050
|
+
}).catch((err) => {
|
|
3051
|
+
if (this.opts.debug) {
|
|
3052
|
+
console.warn(
|
|
3053
|
+
`[raindrop-ai/ai-sdk] sub-agent outcome patch failed: ${err instanceof Error ? err.message : err}`
|
|
3054
|
+
);
|
|
3055
|
+
}
|
|
3056
|
+
});
|
|
3057
|
+
}
|
|
3058
|
+
};
|
|
3059
|
+
|
|
3060
|
+
// src/internal/usage.ts
|
|
3061
|
+
function firstTokenCount(...values) {
|
|
3062
|
+
for (const value of values) {
|
|
3063
|
+
if (typeof value === "number" && Number.isSafeInteger(value) && value >= 0) {
|
|
3064
|
+
return value;
|
|
3065
|
+
}
|
|
3066
|
+
}
|
|
3067
|
+
return void 0;
|
|
2476
3068
|
}
|
|
2477
3069
|
var CACHE_WRITE_METADATA_KEYS = [
|
|
2478
3070
|
["anthropic", "cacheCreationInputTokens"],
|
|
@@ -2490,7 +3082,7 @@ function cacheWriteTokensFromProviderMetadata(providerMetadata) {
|
|
|
2490
3082
|
})
|
|
2491
3083
|
);
|
|
2492
3084
|
}
|
|
2493
|
-
function extractUsageMetricsFromUsage(usage,
|
|
3085
|
+
function extractUsageMetricsFromUsage(usage, _provider, providerMetadata) {
|
|
2494
3086
|
if (!isRecord(usage)) return {};
|
|
2495
3087
|
const inputTokenValue = usage["inputTokens"];
|
|
2496
3088
|
const outputTokenValue = usage["outputTokens"];
|
|
@@ -2558,7 +3150,7 @@ function extractUsageMetricsFromUsage(usage, provider, providerMetadata) {
|
|
|
2558
3150
|
cacheReadInputTokens,
|
|
2559
3151
|
cachedInputTokens: cacheReadInputTokens,
|
|
2560
3152
|
cacheWriteInputTokens,
|
|
2561
|
-
...hasStructuredUsage ? {} :
|
|
3153
|
+
...hasStructuredUsage ? { usageSource: "ai-sdk-structured" } : {}
|
|
2562
3154
|
};
|
|
2563
3155
|
}
|
|
2564
3156
|
|
|
@@ -2634,6 +3226,7 @@ var RaindropTelemetryIntegration = class {
|
|
|
2634
3226
|
eventName: (_f = callMeta.eventName) != null ? _f : (_e = this.defaultContext) == null ? void 0 : _e.eventName
|
|
2635
3227
|
};
|
|
2636
3228
|
const inherited = getContextManager().getParentSpanIds();
|
|
3229
|
+
const handoff = readDetachedChildLink(metadata);
|
|
2637
3230
|
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;
|
|
2638
3231
|
const explicitEventId = callMeta.eventId && !eventIdGenerated ? callMeta.eventId : void 0;
|
|
2639
3232
|
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();
|
|
@@ -2663,7 +3256,10 @@ var RaindropTelemetryIntegration = class {
|
|
|
2663
3256
|
attrString("ai.toolCall.name", subagentName),
|
|
2664
3257
|
attrString("raindrop.subagent.name", subagentName),
|
|
2665
3258
|
attrString("raindrop.agent.role", "subagent"),
|
|
2666
|
-
...parentAttrs
|
|
3259
|
+
...parentAttrs,
|
|
3260
|
+
// Top of this child's tree, so the reverse reference matters as much
|
|
3261
|
+
// here as on the root: these are the spans a reader lands on first.
|
|
3262
|
+
...handoffSpanAttrs(handoff)
|
|
2667
3263
|
]
|
|
2668
3264
|
});
|
|
2669
3265
|
const subagentParentRef = this.spanParentRef(subagentToolCallSpan);
|
|
@@ -2676,7 +3272,8 @@ var RaindropTelemetryIntegration = class {
|
|
|
2676
3272
|
attributes: [
|
|
2677
3273
|
attrString("operation.name", "agent.subagent"),
|
|
2678
3274
|
attrString("raindrop.span.kind", "llm_call"),
|
|
2679
|
-
attrString("raindrop.subagent.name", subagentName)
|
|
3275
|
+
attrString("raindrop.subagent.name", subagentName),
|
|
3276
|
+
...handoffSpanAttrs(handoff)
|
|
2680
3277
|
]
|
|
2681
3278
|
});
|
|
2682
3279
|
this.traceShipper.endSpan(markerSpan);
|
|
@@ -2744,7 +3341,9 @@ var RaindropTelemetryIntegration = class {
|
|
|
2744
3341
|
inputText: isEmbed ? void 0 : this.extractInputText(event),
|
|
2745
3342
|
toolCallCount: 0,
|
|
2746
3343
|
subagentName,
|
|
2747
|
-
subagentToolCallSpan
|
|
3344
|
+
subagentToolCallSpan,
|
|
3345
|
+
handoff,
|
|
3346
|
+
nestedInEvent: inheritedParent !== void 0
|
|
2748
3347
|
});
|
|
2749
3348
|
};
|
|
2750
3349
|
// ── onStepStart ─────────────────────────────────────────────────────────
|
|
@@ -2789,7 +3388,8 @@ var RaindropTelemetryIntegration = class {
|
|
|
2789
3388
|
...attrsFromModelProvider(event.provider),
|
|
2790
3389
|
attrString("ai.model.id", event.modelId),
|
|
2791
3390
|
attrString(MODEL_USAGE_ATTRIBUTES.requestModel, event.modelId),
|
|
2792
|
-
...inputAttrs
|
|
3391
|
+
...inputAttrs,
|
|
3392
|
+
...handoffSpanAttrs(state.handoff)
|
|
2793
3393
|
]
|
|
2794
3394
|
});
|
|
2795
3395
|
state.stepSpan = stepSpan;
|
|
@@ -2902,7 +3502,8 @@ var RaindropTelemetryIntegration = class {
|
|
|
2902
3502
|
attrInt("ai.usage.totalTokens", usageMetrics.totalTokens),
|
|
2903
3503
|
attrInt("ai.usage.reasoningTokens", usageMetrics.reasoningTokens),
|
|
2904
3504
|
attrInt("ai.usage.cachedInputTokens", usageMetrics.cachedInputTokens),
|
|
2905
|
-
|
|
3505
|
+
attrString(MODEL_USAGE_ATTRIBUTES.usageSource, usageMetrics.usageSource),
|
|
3506
|
+
...buildRawModelUsageAttributes(usageMetrics)
|
|
2906
3507
|
);
|
|
2907
3508
|
}
|
|
2908
3509
|
this.emitProviderExecutedToolSpans(event, state);
|
|
@@ -2928,7 +3529,8 @@ var RaindropTelemetryIntegration = class {
|
|
|
2928
3529
|
attrString("operation.name", operationName),
|
|
2929
3530
|
attrString("resource.name", resourceName),
|
|
2930
3531
|
attrString("ai.telemetry.functionId", state.functionId),
|
|
2931
|
-
...inputAttrs
|
|
3532
|
+
...inputAttrs,
|
|
3533
|
+
...handoffSpanAttrs(state.handoff)
|
|
2932
3534
|
]
|
|
2933
3535
|
});
|
|
2934
3536
|
state.embedSpans.set(event.embedCallId, embedSpan);
|
|
@@ -3000,15 +3602,26 @@ var RaindropTelemetryIntegration = class {
|
|
|
3000
3602
|
this.traceShipper.endSpan(toolSpan, { error: actualError });
|
|
3001
3603
|
}
|
|
3002
3604
|
state.toolSpans.clear();
|
|
3605
|
+
const abortReason = describeAbortReason(actualError);
|
|
3003
3606
|
if (state.rootSpan) {
|
|
3004
|
-
this.traceShipper.endSpan(state.rootSpan, {
|
|
3607
|
+
this.traceShipper.endSpan(state.rootSpan, {
|
|
3608
|
+
error: actualError,
|
|
3609
|
+
attributes: this.abortOutcomeAttrs(state, abortReason, "error")
|
|
3610
|
+
});
|
|
3005
3611
|
}
|
|
3006
3612
|
if (state.subagentToolCallSpan) {
|
|
3007
3613
|
this.traceShipper.endSpan(state.subagentToolCallSpan, { error: actualError });
|
|
3008
3614
|
}
|
|
3009
3615
|
const isEmbed = state.operationId === "ai.embed" || state.operationId === "ai.embedMany";
|
|
3010
3616
|
if (!isEmbed) {
|
|
3011
|
-
|
|
3617
|
+
const errorIsTheRunsOutcome = state.handoff !== void 0 && !state.nestedInEvent;
|
|
3618
|
+
this.finalizeGenerateEvent(
|
|
3619
|
+
state,
|
|
3620
|
+
state.accumulatedText || void 0,
|
|
3621
|
+
void 0,
|
|
3622
|
+
false,
|
|
3623
|
+
errorIsTheRunsOutcome ? { fallbackOutput: abortReason } : void 0
|
|
3624
|
+
);
|
|
3012
3625
|
}
|
|
3013
3626
|
this.cleanup(event.callId);
|
|
3014
3627
|
};
|
|
@@ -3045,9 +3658,19 @@ var RaindropTelemetryIntegration = class {
|
|
|
3045
3658
|
this.traceShipper.endSpan(toolSpan, { attributes: [abortedAttr] });
|
|
3046
3659
|
}
|
|
3047
3660
|
state.toolSpans.clear();
|
|
3661
|
+
const abortIsTheRunsOutcome = state.handoff !== void 0 && !state.nestedInEvent;
|
|
3048
3662
|
if (state.rootSpan) {
|
|
3049
3663
|
this.traceShipper.endSpan(state.rootSpan, {
|
|
3050
|
-
attributes: [
|
|
3664
|
+
attributes: [
|
|
3665
|
+
abortedAttr,
|
|
3666
|
+
attrInt("ai.toolCall.count", state.toolCallCount),
|
|
3667
|
+
// An aborted detached child IS a cancelled sub-agent, and a cancelled
|
|
3668
|
+
// run is span-for-span identical to a finished one — spans close,
|
|
3669
|
+
// nothing errors, there is just no answer. So it is the one outcome
|
|
3670
|
+
// that has to be stated, and the child states it on itself.
|
|
3671
|
+
...abortIsTheRunsOutcome ? cancelledSpanAttrs() : [],
|
|
3672
|
+
...abortIsTheRunsOutcome ? this.abortOutcomeAttrs(state, SUBAGENT_CANCELLED_OUTPUT, "stop") : []
|
|
3673
|
+
]
|
|
3051
3674
|
});
|
|
3052
3675
|
}
|
|
3053
3676
|
if (state.subagentToolCallSpan) {
|
|
@@ -3055,7 +3678,17 @@ var RaindropTelemetryIntegration = class {
|
|
|
3055
3678
|
attributes: [abortedAttr]
|
|
3056
3679
|
});
|
|
3057
3680
|
}
|
|
3058
|
-
this.finalizeGenerateEvent(
|
|
3681
|
+
this.finalizeGenerateEvent(
|
|
3682
|
+
state,
|
|
3683
|
+
state.accumulatedText || void 0,
|
|
3684
|
+
void 0,
|
|
3685
|
+
false,
|
|
3686
|
+
abortIsTheRunsOutcome ? {
|
|
3687
|
+
fallbackOutput: SUBAGENT_CANCELLED_OUTPUT,
|
|
3688
|
+
properties: { [HANDOFF_TERMINAL_PROPERTY_KEY]: HANDOFF_TERMINAL_CANCELLED }
|
|
3689
|
+
} : void 0
|
|
3690
|
+
);
|
|
3691
|
+
if (abortIsTheRunsOutcome) this.subagents.noteSettled(state.eventId);
|
|
3059
3692
|
this.cleanup(callId);
|
|
3060
3693
|
};
|
|
3061
3694
|
// ── executeTool ─────────────────────────────────────────────────────────
|
|
@@ -3083,6 +3716,97 @@ var RaindropTelemetryIntegration = class {
|
|
|
3083
3716
|
this.subagentWrapping = opts.subagentWrapping !== false;
|
|
3084
3717
|
this.debug = opts.debug === true;
|
|
3085
3718
|
this.defaultContext = opts.context;
|
|
3719
|
+
this.subagents = new SubagentApi({
|
|
3720
|
+
traceShipper: this.traceShipper,
|
|
3721
|
+
eventShipper: this.eventShipper,
|
|
3722
|
+
sendTraces: this.sendTraces,
|
|
3723
|
+
sendEvents: this.sendEvents,
|
|
3724
|
+
debug: this.debug,
|
|
3725
|
+
defaultContext: this.defaultContext,
|
|
3726
|
+
settledEventIds: opts.settledEventIds,
|
|
3727
|
+
spanSource: {
|
|
3728
|
+
activeDispatch: () => this.activeDispatch(),
|
|
3729
|
+
openSpansForEvent: (eventId) => this.openSpansForEvent(eventId)
|
|
3730
|
+
}
|
|
3731
|
+
});
|
|
3732
|
+
}
|
|
3733
|
+
/**
|
|
3734
|
+
* Record a detached sub-agent on the turn that is live right now.
|
|
3735
|
+
*
|
|
3736
|
+
* Returns the dispatch — the child's event id and the headers to send with
|
|
3737
|
+
* the job. Dispatching is still yours to do; this only states that you are
|
|
3738
|
+
* about to, so a reader can follow the link before the child exists.
|
|
3739
|
+
*/
|
|
3740
|
+
subagent(options = {}) {
|
|
3741
|
+
return this.subagents.subagent(options);
|
|
3742
|
+
}
|
|
3743
|
+
// ── detached sub-agent hand-offs ─────────────────────────────────────────
|
|
3744
|
+
/**
|
|
3745
|
+
* The turn a `subagent()` dispatch is happening inside.
|
|
3746
|
+
*
|
|
3747
|
+
* Resolved from the parent-tool context first, which is the only way to reach
|
|
3748
|
+
* the EXACT span that dispatched: the tool call the model itself issued, still
|
|
3749
|
+
* open while its `execute` runs. Falling back to the event id lets a launch
|
|
3750
|
+
* from elsewhere in the turn (a queue producer called mid-generation) still
|
|
3751
|
+
* find the turn's spans, which is where the tool-events opt-in has to land.
|
|
3752
|
+
*/
|
|
3753
|
+
activeDispatch() {
|
|
3754
|
+
var _a;
|
|
3755
|
+
const parentTool = getCurrentParentToolContext();
|
|
3756
|
+
let state = parentTool ? this.getState(parentTool.parentCallId) : void 0;
|
|
3757
|
+
const inheritedEventId = (_a = getContextManager().getParentSpanIds()) == null ? void 0 : _a.eventId;
|
|
3758
|
+
if (!state && inheritedEventId) {
|
|
3759
|
+
for (const candidate of this.callStates.values()) {
|
|
3760
|
+
if (candidate.eventId === inheritedEventId) {
|
|
3761
|
+
state = candidate;
|
|
3762
|
+
break;
|
|
3763
|
+
}
|
|
3764
|
+
}
|
|
3765
|
+
}
|
|
3766
|
+
if (!state) return void 0;
|
|
3767
|
+
return {
|
|
3768
|
+
eventId: state.eventId,
|
|
3769
|
+
userId: state.identity.userId,
|
|
3770
|
+
convoId: state.identity.convoId,
|
|
3771
|
+
dispatchSpan: parentTool ? state.toolSpans.get(parentTool.toolCallId) : void 0,
|
|
3772
|
+
turnSpans: [state.rootSpan, state.stepSpan].filter(
|
|
3773
|
+
(span) => span !== void 0
|
|
3774
|
+
),
|
|
3775
|
+
recordInputs: state.recordInputs
|
|
3776
|
+
};
|
|
3777
|
+
}
|
|
3778
|
+
/** Spans still open for an event, so a late outcome can still be stated. */
|
|
3779
|
+
openSpansForEvent(eventId) {
|
|
3780
|
+
const spans = [];
|
|
3781
|
+
for (const state of this.callStates.values()) {
|
|
3782
|
+
if (state.eventId !== eventId) continue;
|
|
3783
|
+
if (state.rootSpan) spans.push(state.rootSpan);
|
|
3784
|
+
if (state.stepSpan) spans.push(state.stepSpan);
|
|
3785
|
+
}
|
|
3786
|
+
return spans;
|
|
3787
|
+
}
|
|
3788
|
+
/**
|
|
3789
|
+
* End-attributes that keep a detached child legible when it ends without an
|
|
3790
|
+
* answer — an error, an abort, a cancellation.
|
|
3791
|
+
*
|
|
3792
|
+
* An event is created from an LLM span only when it has a finish reason and
|
|
3793
|
+
* non-empty output, so a child that dies silently produces NO event, and the
|
|
3794
|
+
* caller's hand-off pill stays on `queued` forever — indistinguishable from a
|
|
3795
|
+
* job that never started. Reporting the abort reason as the run's output is
|
|
3796
|
+
* what makes the outcome visible. Only detached children get this: an inline
|
|
3797
|
+
* generation's failure is already legible from its caller's own event.
|
|
3798
|
+
*
|
|
3799
|
+
* And only the run's OUTERMOST generation gets it (see `nestedInEvent`): an
|
|
3800
|
+
* inner sub-call ending badly is not the run ending, and since an event is
|
|
3801
|
+
* created from an LLM span with output, `ai.response.text` here would state
|
|
3802
|
+
* the run's outcome through the span while the turn is still working.
|
|
3803
|
+
*/
|
|
3804
|
+
abortOutcomeAttrs(state, reason, finishReason) {
|
|
3805
|
+
if (!state.handoff || state.nestedInEvent) return [];
|
|
3806
|
+
return [
|
|
3807
|
+
attrString("ai.response.text", capText2(state.accumulatedText || reason)),
|
|
3808
|
+
attrString("ai.response.finishReason", finishReason)
|
|
3809
|
+
];
|
|
3086
3810
|
}
|
|
3087
3811
|
// ── helpers ──────────────────────────────────────────────────────────────
|
|
3088
3812
|
getState(callId) {
|
|
@@ -3201,7 +3925,8 @@ var RaindropTelemetryIntegration = class {
|
|
|
3201
3925
|
attrString("ai.telemetry.functionId", state.functionId),
|
|
3202
3926
|
attrString("ai.toolCall.name", toolCall.toolName),
|
|
3203
3927
|
attrString("ai.toolCall.id", toolCall.toolCallId),
|
|
3204
|
-
...inputAttrs
|
|
3928
|
+
...inputAttrs,
|
|
3929
|
+
...handoffSpanAttrs(state.handoff)
|
|
3205
3930
|
]
|
|
3206
3931
|
});
|
|
3207
3932
|
state.toolSpans.set(toolCall.toolCallId, toolSpan);
|
|
@@ -3280,7 +4005,8 @@ var RaindropTelemetryIntegration = class {
|
|
|
3280
4005
|
attrString("ai.toolCall.name", call.toolName),
|
|
3281
4006
|
attrString("ai.toolCall.id", call.toolCallId),
|
|
3282
4007
|
attrString("ai.toolCall.providerExecuted", "true"),
|
|
3283
|
-
...inputAttrs
|
|
4008
|
+
...inputAttrs,
|
|
4009
|
+
...handoffSpanAttrs(state.handoff)
|
|
3284
4010
|
]
|
|
3285
4011
|
});
|
|
3286
4012
|
state.toolCallCount += 1;
|
|
@@ -3361,19 +4087,22 @@ var RaindropTelemetryIntegration = class {
|
|
|
3361
4087
|
* is finalized by that resume — otherwise each execution would finalize the
|
|
3362
4088
|
* same event ID into a separate canonical row.
|
|
3363
4089
|
*/
|
|
3364
|
-
finalizeGenerateEvent(state, output, model, keepPending = false) {
|
|
4090
|
+
finalizeGenerateEvent(state, output, model, keepPending = false, detachedOutcome) {
|
|
3365
4091
|
var _a, _b, _c, _d, _e, _f, _g, _h, _i;
|
|
3366
4092
|
const suppressSubagentEvent = state.subagentName !== void 0 && state.subagentToolCallSpan !== void 0;
|
|
3367
4093
|
if (!this.sendEvents || suppressSubagentEvent) return;
|
|
4094
|
+
if (this.subagents.wasSettledExplicitly(state.eventId)) return;
|
|
3368
4095
|
const callMeta = this.extractRaindropMetadata(state.metadata);
|
|
3369
4096
|
const userId = (_b = callMeta.userId) != null ? _b : (_a = this.defaultContext) == null ? void 0 : _a.userId;
|
|
3370
4097
|
if (!userId) return;
|
|
3371
4098
|
const eventName = (_e = (_d = callMeta.eventName) != null ? _d : (_c = this.defaultContext) == null ? void 0 : _c.eventName) != null ? _e : state.operationId;
|
|
3372
4099
|
const cappedOutput = capText2(output);
|
|
4100
|
+
const reportedOutput = state.handoff && detachedOutcome && !(cappedOutput == null ? void 0 : cappedOutput.trim()) ? detachedOutcome.fallbackOutput : cappedOutput;
|
|
3373
4101
|
const input = capText2(state.inputText);
|
|
3374
4102
|
const properties = {
|
|
3375
4103
|
...(_f = this.defaultContext) == null ? void 0 : _f.properties,
|
|
3376
|
-
...callMeta.properties
|
|
4104
|
+
...callMeta.properties,
|
|
4105
|
+
...state.handoff ? detachedOutcome == null ? void 0 : detachedOutcome.properties : void 0
|
|
3377
4106
|
};
|
|
3378
4107
|
const featureFlags = {
|
|
3379
4108
|
...((_g = this.defaultContext) == null ? void 0 : _g.featureFlags) ? normalizeFeatureFlags(this.defaultContext.featureFlags) : {},
|
|
@@ -3385,7 +4114,7 @@ var RaindropTelemetryIntegration = class {
|
|
|
3385
4114
|
userId,
|
|
3386
4115
|
convoId,
|
|
3387
4116
|
input,
|
|
3388
|
-
output:
|
|
4117
|
+
output: reportedOutput,
|
|
3389
4118
|
model,
|
|
3390
4119
|
properties: Object.keys(properties).length > 0 ? properties : void 0,
|
|
3391
4120
|
featureFlags: Object.keys(featureFlags).length > 0 ? featureFlags : void 0,
|
|
@@ -3709,9 +4438,7 @@ function extractRaindropMetadata(metadata) {
|
|
|
3709
4438
|
} catch (e) {
|
|
3710
4439
|
}
|
|
3711
4440
|
} else if (featureFlags && typeof featureFlags === "object") {
|
|
3712
|
-
result.featureFlags = normalizeFeatureFlags(
|
|
3713
|
-
featureFlags
|
|
3714
|
-
);
|
|
4441
|
+
result.featureFlags = normalizeFeatureFlags(featureFlags);
|
|
3715
4442
|
}
|
|
3716
4443
|
return result;
|
|
3717
4444
|
}
|
|
@@ -3922,12 +4649,7 @@ function setupOperation(params) {
|
|
|
3922
4649
|
...attrsFromTelemetryMetadata(telemetry == null ? void 0 : telemetry.metadata),
|
|
3923
4650
|
...attrsFromHeaders(isRecord(arg) ? arg["headers"] : void 0),
|
|
3924
4651
|
...attrsFromSettings(arg),
|
|
3925
|
-
...(telemetry == null ? void 0 : telemetry.recordInputs) === false ? [] : [
|
|
3926
|
-
attrString(
|
|
3927
|
-
"ai.prompt",
|
|
3928
|
-
safeJsonWithUint8(normalizePromptAttr(arg))
|
|
3929
|
-
)
|
|
3930
|
-
]
|
|
4652
|
+
...(telemetry == null ? void 0 : telemetry.recordInputs) === false ? [] : [attrString("ai.prompt", safeJsonWithUint8(normalizePromptAttr(arg)))]
|
|
3931
4653
|
]
|
|
3932
4654
|
}) : void 0;
|
|
3933
4655
|
const rootParentForChildren = rootSpan ? { traceIdB64: rootSpan.ids.traceIdB64, spanIdB64: rootSpan.ids.spanIdB64 } : inheritedParent;
|
|
@@ -4277,13 +4999,17 @@ function wrapAISDK(aiSDK, deps) {
|
|
|
4277
4999
|
}
|
|
4278
5000
|
const useNative = deps.options.nativeTelemetry === true;
|
|
4279
5001
|
if (useNative) {
|
|
4280
|
-
const wrapTimeCtx = resolveContext(deps.options.context, {
|
|
5002
|
+
const wrapTimeCtx = resolveContext(deps.options.context, {
|
|
5003
|
+
operation: "wrap",
|
|
5004
|
+
args: void 0
|
|
5005
|
+
});
|
|
4281
5006
|
const integration = new RaindropTelemetryIntegration({
|
|
4282
5007
|
traceShipper: deps.traceShipper,
|
|
4283
5008
|
eventShipper: deps.eventShipper,
|
|
4284
5009
|
sendTraces: ((_a = deps.options.send) == null ? void 0 : _a.traces) !== false,
|
|
4285
5010
|
sendEvents: ((_b = deps.options.send) == null ? void 0 : _b.events) !== false,
|
|
4286
5011
|
debug,
|
|
5012
|
+
settledEventIds: deps.settledEventIds,
|
|
4287
5013
|
context: {
|
|
4288
5014
|
userId: wrapTimeCtx.userId,
|
|
4289
5015
|
eventId: wrapTimeCtx.eventId,
|
|
@@ -4521,7 +5247,13 @@ function wrapAgentGenerate(generate, instance, agentSettings, className, aiSDK,
|
|
|
4521
5247
|
...(telemetry == null ? void 0 : telemetry.recordInputs) === false ? [] : [
|
|
4522
5248
|
attrString(
|
|
4523
5249
|
"ai.prompt",
|
|
4524
|
-
safeJsonWithUint8(
|
|
5250
|
+
safeJsonWithUint8(
|
|
5251
|
+
normalizePromptAttr({
|
|
5252
|
+
system: (_d = mergedArgs["system"]) != null ? _d : mergedArgs["instructions"],
|
|
5253
|
+
prompt: mergedArgs["prompt"],
|
|
5254
|
+
messages: mergedArgs["messages"]
|
|
5255
|
+
})
|
|
5256
|
+
)
|
|
4525
5257
|
)
|
|
4526
5258
|
]
|
|
4527
5259
|
]
|
|
@@ -4735,7 +5467,13 @@ function wrapAgentStream(stream, instance, agentSettings, className, aiSDK, deps
|
|
|
4735
5467
|
...(telemetry == null ? void 0 : telemetry.recordInputs) === false ? [] : [
|
|
4736
5468
|
attrString(
|
|
4737
5469
|
"ai.prompt",
|
|
4738
|
-
safeJsonWithUint8(
|
|
5470
|
+
safeJsonWithUint8(
|
|
5471
|
+
normalizePromptAttr({
|
|
5472
|
+
system: (_d = mergedArgs["system"]) != null ? _d : mergedArgs["instructions"],
|
|
5473
|
+
prompt: mergedArgs["prompt"],
|
|
5474
|
+
messages: mergedArgs["messages"]
|
|
5475
|
+
})
|
|
5476
|
+
)
|
|
4739
5477
|
)
|
|
4740
5478
|
]
|
|
4741
5479
|
]
|
|
@@ -5112,9 +5850,19 @@ function wrapModel(args, aiSDK, outerOperationId, ctx) {
|
|
|
5112
5850
|
for (const part of content) {
|
|
5113
5851
|
if (isRecord(part)) {
|
|
5114
5852
|
if ((part["type"] === "reasoning" || part["type"] === "thinking") && typeof ((_a = part["text"]) != null ? _a : part["thinking"]) === "string") {
|
|
5115
|
-
sendLocalDebuggerLiveEvent({
|
|
5853
|
+
sendLocalDebuggerLiveEvent({
|
|
5854
|
+
traceId,
|
|
5855
|
+
type: "reasoning_delta",
|
|
5856
|
+
content: (_b = part["text"]) != null ? _b : part["thinking"],
|
|
5857
|
+
metadata: liveMeta
|
|
5858
|
+
});
|
|
5116
5859
|
} else if (part["type"] === "text" && typeof part["text"] === "string") {
|
|
5117
|
-
sendLocalDebuggerLiveEvent({
|
|
5860
|
+
sendLocalDebuggerLiveEvent({
|
|
5861
|
+
traceId,
|
|
5862
|
+
type: "text_delta",
|
|
5863
|
+
content: part["text"],
|
|
5864
|
+
metadata: liveMeta
|
|
5865
|
+
});
|
|
5118
5866
|
}
|
|
5119
5867
|
}
|
|
5120
5868
|
}
|
|
@@ -5195,7 +5943,10 @@ function wrapModel(args, aiSDK, outerOperationId, ctx) {
|
|
|
5195
5943
|
attributes: [
|
|
5196
5944
|
...((_a = ctx.telemetry) == null ? void 0 : _a.recordOutputs) === false ? [] : [
|
|
5197
5945
|
attrString("ai.response.finishReason", finishReason),
|
|
5198
|
-
attrString(
|
|
5946
|
+
attrString(
|
|
5947
|
+
"ai.response.text",
|
|
5948
|
+
activeText.length ? capText2(activeText) : void 0
|
|
5949
|
+
),
|
|
5199
5950
|
attrString(
|
|
5200
5951
|
"ai.response.toolCalls",
|
|
5201
5952
|
safeJsonWithUint8(toolCallsLocal.length ? toolCallsLocal : void 0)
|
|
@@ -5213,7 +5964,8 @@ function wrapModel(args, aiSDK, outerOperationId, ctx) {
|
|
|
5213
5964
|
...finishReason ? [attrStringArray("gen_ai.response.finish_reasons", [finishReason])] : [],
|
|
5214
5965
|
attrString("gen_ai.response.id", responseId),
|
|
5215
5966
|
attrString(MODEL_USAGE_ATTRIBUTES.responseModel, finalResponseModelId),
|
|
5216
|
-
|
|
5967
|
+
attrString(MODEL_USAGE_ATTRIBUTES.usageSource, usageMetrics.usageSource),
|
|
5968
|
+
...buildRawModelUsageAttributes(usageMetrics),
|
|
5217
5969
|
...msToFirstChunk !== void 0 ? [attrInt("ai.stream.msToFirstChunk", msToFirstChunk)] : [],
|
|
5218
5970
|
...msToFinish !== void 0 ? [attrInt("ai.stream.msToFinish", msToFinish)] : [],
|
|
5219
5971
|
...avgOutTokensPerSecond !== void 0 ? [attrDouble("ai.stream.avgOutputTokensPerSecond", avgOutTokensPerSecond)] : [],
|
|
@@ -5267,19 +6019,44 @@ function wrapModel(args, aiSDK, outerOperationId, ctx) {
|
|
|
5267
6019
|
if ("providerMetadata" in value) providerMetadata = value["providerMetadata"];
|
|
5268
6020
|
if (localDebuggerEnabled() && ctx.rootParentForChildren) {
|
|
5269
6021
|
const traceId = ctx.rootParentForChildren.traceIdB64;
|
|
5270
|
-
const liveMeta = getLocalDebuggerMetadata({
|
|
6022
|
+
const liveMeta = getLocalDebuggerMetadata({
|
|
6023
|
+
...ctx.context,
|
|
6024
|
+
eventId: ctx.eventId
|
|
6025
|
+
});
|
|
5271
6026
|
if (type === "text-delta") {
|
|
5272
6027
|
const text = typeof value["delta"] === "string" ? value["delta"] : typeof value["textDelta"] === "string" ? value["textDelta"] : typeof value["text"] === "string" ? value["text"] : void 0;
|
|
5273
|
-
if (typeof text === "string" && text)
|
|
6028
|
+
if (typeof text === "string" && text)
|
|
6029
|
+
sendLocalDebuggerLiveEvent({
|
|
6030
|
+
traceId,
|
|
6031
|
+
type: "text_delta",
|
|
6032
|
+
content: text,
|
|
6033
|
+
metadata: liveMeta
|
|
6034
|
+
});
|
|
5274
6035
|
} else if (type === "reasoning" || type === "reasoning-delta") {
|
|
5275
6036
|
const text = typeof value["delta"] === "string" ? value["delta"] : typeof value["text"] === "string" ? value["text"] : typeof value["thinking"] === "string" ? value["thinking"] : void 0;
|
|
5276
|
-
if (typeof text === "string" && text)
|
|
6037
|
+
if (typeof text === "string" && text)
|
|
6038
|
+
sendLocalDebuggerLiveEvent({
|
|
6039
|
+
traceId,
|
|
6040
|
+
type: "reasoning_delta",
|
|
6041
|
+
content: text,
|
|
6042
|
+
metadata: liveMeta
|
|
6043
|
+
});
|
|
5277
6044
|
} else if (type === "tool-call") {
|
|
5278
6045
|
const toolName = typeof value["toolName"] === "string" ? value["toolName"] : "tool";
|
|
5279
|
-
sendLocalDebuggerLiveEvent({
|
|
6046
|
+
sendLocalDebuggerLiveEvent({
|
|
6047
|
+
traceId,
|
|
6048
|
+
type: "tool_start",
|
|
6049
|
+
content: toolName,
|
|
6050
|
+
metadata: { ...liveMeta, args: value["args"] }
|
|
6051
|
+
});
|
|
5280
6052
|
} else if (type === "tool-result") {
|
|
5281
6053
|
const toolName = typeof value["toolName"] === "string" ? value["toolName"] : "tool";
|
|
5282
|
-
sendLocalDebuggerLiveEvent({
|
|
6054
|
+
sendLocalDebuggerLiveEvent({
|
|
6055
|
+
traceId,
|
|
6056
|
+
type: "tool_result",
|
|
6057
|
+
content: toolName,
|
|
6058
|
+
metadata: { ...liveMeta, result: value["result"] }
|
|
6059
|
+
});
|
|
5283
6060
|
}
|
|
5284
6061
|
}
|
|
5285
6062
|
}
|
|
@@ -5359,11 +6136,7 @@ function endDoGenerateSpan(span, result, modelInfo, ctx) {
|
|
|
5359
6136
|
} else {
|
|
5360
6137
|
responseTimestampIso = (/* @__PURE__ */ new Date()).toISOString();
|
|
5361
6138
|
}
|
|
5362
|
-
const usageMetrics = extractUsageMetricsFromUsage(
|
|
5363
|
-
usage,
|
|
5364
|
-
modelInfo.provider,
|
|
5365
|
-
providerMetadata
|
|
5366
|
-
);
|
|
6139
|
+
const usageMetrics = extractUsageMetricsFromUsage(usage, modelInfo.provider, providerMetadata);
|
|
5367
6140
|
const { inputTokens, outputTokens } = usageMetrics;
|
|
5368
6141
|
ctx.traceShipper.endSpan(span, {
|
|
5369
6142
|
attributes: [
|
|
@@ -5384,7 +6157,8 @@ function endDoGenerateSpan(span, result, modelInfo, ctx) {
|
|
|
5384
6157
|
...finishReason ? [attrStringArray("gen_ai.response.finish_reasons", [finishReason])] : [],
|
|
5385
6158
|
attrString("gen_ai.response.id", responseId),
|
|
5386
6159
|
attrString(MODEL_USAGE_ATTRIBUTES.responseModel, responseModelId),
|
|
5387
|
-
|
|
6160
|
+
attrString(MODEL_USAGE_ATTRIBUTES.usageSource, usageMetrics.usageSource),
|
|
6161
|
+
...buildRawModelUsageAttributes(usageMetrics)
|
|
5388
6162
|
]
|
|
5389
6163
|
});
|
|
5390
6164
|
}
|
|
@@ -5481,7 +6255,7 @@ function mergeAttachments(...groups) {
|
|
|
5481
6255
|
// package.json
|
|
5482
6256
|
var package_default = {
|
|
5483
6257
|
name: "@raindrop-ai/ai-sdk",
|
|
5484
|
-
version: "0.
|
|
6258
|
+
version: "0.3.1"};
|
|
5485
6259
|
|
|
5486
6260
|
// src/internal/version.ts
|
|
5487
6261
|
var libraryName = package_default.name;
|
|
@@ -5528,6 +6302,8 @@ function eventMetadata(options) {
|
|
|
5528
6302
|
if (options.properties) result["raindrop.properties"] = JSON.stringify(options.properties);
|
|
5529
6303
|
if (options.featureFlags)
|
|
5530
6304
|
result["raindrop.featureFlags"] = JSON.stringify(normalizeFeatureFlags(options.featureFlags));
|
|
6305
|
+
if (options.subagent) Object.assign(result, detachedChildMetadata(options.subagent));
|
|
6306
|
+
if (options.toolEvents) result[TOOL_EVENTS_SUFFIX] = options.toolEvents;
|
|
5531
6307
|
return result;
|
|
5532
6308
|
}
|
|
5533
6309
|
function deriveChatTurnMessageId(request) {
|
|
@@ -5610,12 +6386,22 @@ function createRaindropAISDK(opts) {
|
|
|
5610
6386
|
transformSpan: (_j = opts.traces) == null ? void 0 : _j.transformSpan,
|
|
5611
6387
|
disableDefaultRedaction: (_k = opts.traces) == null ? void 0 : _k.disableDefaultRedaction
|
|
5612
6388
|
});
|
|
6389
|
+
const settledEventIds = /* @__PURE__ */ new Set();
|
|
6390
|
+
const subagentApi = new SubagentApi({
|
|
6391
|
+
traceShipper,
|
|
6392
|
+
eventShipper,
|
|
6393
|
+
sendTraces: tracesEnabled,
|
|
6394
|
+
sendEvents: eventsEnabled,
|
|
6395
|
+
debug: envDebug,
|
|
6396
|
+
settledEventIds
|
|
6397
|
+
});
|
|
5613
6398
|
return {
|
|
5614
6399
|
wrap(aiSDK, options) {
|
|
5615
6400
|
return wrapAISDK(aiSDK, {
|
|
5616
6401
|
options: options != null ? options : {},
|
|
5617
6402
|
eventShipper,
|
|
5618
|
-
traceShipper
|
|
6403
|
+
traceShipper,
|
|
6404
|
+
settledEventIds
|
|
5619
6405
|
});
|
|
5620
6406
|
},
|
|
5621
6407
|
createSelfDiagnosticsTool(options = {}) {
|
|
@@ -5652,9 +6438,14 @@ function createRaindropAISDK(opts) {
|
|
|
5652
6438
|
sendEvents: eventsEnabled,
|
|
5653
6439
|
subagentWrapping,
|
|
5654
6440
|
debug: envDebug,
|
|
6441
|
+
settledEventIds,
|
|
5655
6442
|
context
|
|
5656
6443
|
});
|
|
5657
6444
|
},
|
|
6445
|
+
subagents: subagentApi,
|
|
6446
|
+
subagent(options = {}) {
|
|
6447
|
+
return subagentApi.subagent(options);
|
|
6448
|
+
},
|
|
5658
6449
|
events: {
|
|
5659
6450
|
async patch(eventId, patch) {
|
|
5660
6451
|
await eventShipper.patch(eventId, patch);
|
|
@@ -5774,4 +6565,4 @@ function raindrop(options = {}) {
|
|
|
5774
6565
|
return client.createTelemetryIntegration({ context, subagentWrapping });
|
|
5775
6566
|
}
|
|
5776
6567
|
|
|
5777
|
-
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 };
|
|
6568
|
+
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 };
|