raindrop-ai 0.7.0 → 0.7.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 +25 -0
- package/dist/{chunk-4Z7UHC7X.mjs → chunk-6WL655QL.mjs} +239 -132
- package/dist/{chunk-OX6X4ZWQ.mjs → chunk-SHH4SYVY.mjs} +1470 -1015
- package/dist/evals/cli.js +1688 -1148
- package/dist/evals/cli.mjs +2 -2
- package/dist/{index-n8AIAiRR.d.mts → index-DuJkG47V.d.mts} +29 -3
- package/dist/{index-n8AIAiRR.d.ts → index-DuJkG47V.d.ts} +29 -3
- package/dist/index.d.mts +1 -2
- package/dist/index.d.ts +1 -2
- package/dist/index.js +1694 -1151
- package/dist/index.mjs +5 -6
- package/dist/tracing/index.d.mts +3 -2
- package/dist/tracing/index.d.ts +3 -2
- package/dist/tracing/index.js +1085 -973
- package/dist/tracing/index.mjs +1 -1
- package/package.json +1 -1
package/dist/tracing/index.js
CHANGED
|
@@ -101,1082 +101,1120 @@ function evalScopeAttributes() {
|
|
|
101
101
|
return { [EVAL_CORRELATION_ID_ATTRIBUTE]: scope.correlationId };
|
|
102
102
|
}
|
|
103
103
|
|
|
104
|
-
// ../core/dist/chunk-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
104
|
+
// ../core/dist/chunk-WJOR6M7H.js
|
|
105
|
+
var STATE_KEY = /* @__PURE__ */ Symbol.for("raindrop.tracing.replayTraceRoutingState");
|
|
106
|
+
function state() {
|
|
107
|
+
const holder = globalThis;
|
|
108
|
+
let current = holder[STATE_KEY];
|
|
109
|
+
if (!current) {
|
|
110
|
+
let storage = null;
|
|
111
|
+
try {
|
|
112
|
+
const Ctor = globalThis.RAINDROP_ASYNC_LOCAL_STORAGE;
|
|
113
|
+
if (Ctor) storage = new Ctor();
|
|
114
|
+
} catch (e) {
|
|
115
|
+
storage = null;
|
|
116
|
+
}
|
|
117
|
+
current = {
|
|
118
|
+
storage,
|
|
119
|
+
syncDestination: void 0,
|
|
120
|
+
spanDestinations: /* @__PURE__ */ new WeakMap()
|
|
121
|
+
};
|
|
122
|
+
holder[STATE_KEY] = current;
|
|
108
123
|
}
|
|
109
|
-
return
|
|
110
|
-
Object.entries(input).map(([k, v]) => [k, String(v)])
|
|
111
|
-
);
|
|
124
|
+
return current;
|
|
112
125
|
}
|
|
113
|
-
function
|
|
114
|
-
|
|
115
|
-
|
|
126
|
+
function currentReplayTraceDestination() {
|
|
127
|
+
var _a, _b;
|
|
128
|
+
const routing = state();
|
|
129
|
+
return (_b = (_a = routing.storage) == null ? void 0 : _a.getStore()) != null ? _b : routing.syncDestination;
|
|
116
130
|
}
|
|
117
|
-
function
|
|
118
|
-
const
|
|
119
|
-
|
|
120
|
-
if (cryptoObj && typeof cryptoObj.getRandomValues === "function") {
|
|
121
|
-
cryptoObj.getRandomValues(out);
|
|
122
|
-
return out;
|
|
123
|
-
}
|
|
124
|
-
for (let i = 0; i < out.length; i++) out[i] = Math.floor(Math.random() * 256);
|
|
125
|
-
return out;
|
|
131
|
+
function rememberReplayTraceDestination(span) {
|
|
132
|
+
const destination = currentReplayTraceDestination();
|
|
133
|
+
if (destination) state().spanDestinations.set(span, destination);
|
|
126
134
|
}
|
|
127
|
-
function
|
|
128
|
-
const
|
|
129
|
-
if (
|
|
130
|
-
return cryptoObj.randomUUID();
|
|
131
|
-
}
|
|
132
|
-
const b = randomBytes(16);
|
|
133
|
-
b[6] = b[6] & 15 | 64;
|
|
134
|
-
b[8] = b[8] & 63 | 128;
|
|
135
|
-
const hex = [...b].map((x) => x.toString(16).padStart(2, "0")).join("");
|
|
136
|
-
return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`;
|
|
135
|
+
function copyReplayTraceDestination(source, target) {
|
|
136
|
+
const destination = state().spanDestinations.get(source);
|
|
137
|
+
if (destination) state().spanDestinations.set(target, destination);
|
|
137
138
|
}
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
parentEventId: "raindrop.handoff.parentEventId",
|
|
142
|
-
parentSpanId: "raindrop.handoff.parentSpanId",
|
|
143
|
-
name: "raindrop.handoff.name",
|
|
144
|
-
terminal: "raindrop.handoff.terminal",
|
|
145
|
-
agentRole: "raindrop.agent.role"
|
|
146
|
-
};
|
|
147
|
-
var AI_SDK_METADATA_PREFIX = "ai.telemetry.metadata.";
|
|
148
|
-
var DETACHED_MODE = "detached";
|
|
149
|
-
var SUBAGENT_AGENT_ROLE = "subagent";
|
|
150
|
-
var HANDOFF_TERMINAL_CANCELLED = "cancelled";
|
|
151
|
-
var TOOL_EVENTS_SUFFIX = "raindrop.toolEvents";
|
|
152
|
-
var TOOL_EVENTS_ALLOW = "allow";
|
|
153
|
-
var OPERATION_ID_ATTRIBUTE = "ai.operationId";
|
|
154
|
-
var SUBAGENT_ABORT_OPERATION_ID = "ai.subagent.failed";
|
|
155
|
-
var SUBAGENT_ABORT_SPAN_NAME = SUBAGENT_ABORT_OPERATION_ID;
|
|
156
|
-
var DEFAULT_DISPATCH_SPAN_NAME = "launch_subagent";
|
|
157
|
-
var HANDOFF_TERMINAL_PROPERTY_KEY = HANDOFF_ATTRIBUTE_SUFFIXES.terminal;
|
|
158
|
-
function defined(entries) {
|
|
159
|
-
const out = {};
|
|
160
|
-
for (const [key, value] of Object.entries(entries)) {
|
|
161
|
-
if (typeof value === "string" && value.trim().length > 0) out[key] = value;
|
|
139
|
+
function replayTraceDestinationFor(value) {
|
|
140
|
+
if (typeof value !== "object" && typeof value !== "function" || value === null) {
|
|
141
|
+
return void 0;
|
|
162
142
|
}
|
|
163
|
-
return
|
|
164
|
-
}
|
|
165
|
-
function detachedDispatchMetadata(dispatch) {
|
|
166
|
-
return defined({
|
|
167
|
-
[HANDOFF_ATTRIBUTE_SUFFIXES.mode]: DETACHED_MODE,
|
|
168
|
-
[HANDOFF_ATTRIBUTE_SUFFIXES.childEventId]: dispatch.childEventId,
|
|
169
|
-
[HANDOFF_ATTRIBUTE_SUFFIXES.name]: dispatch.name
|
|
170
|
-
});
|
|
143
|
+
return state().spanDestinations.get(value);
|
|
171
144
|
}
|
|
172
|
-
function
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
[HANDOFF_ATTRIBUTE_SUFFIXES.agentRole]: SUBAGENT_AGENT_ROLE
|
|
178
|
-
});
|
|
145
|
+
function recordReplayExportedSpan(destination, spanId, traceId) {
|
|
146
|
+
var _a, _b;
|
|
147
|
+
if (!destination || !spanId || !traceId) return;
|
|
148
|
+
(_a = destination.exportedSpanIds) == null ? void 0 : _a.add(spanId);
|
|
149
|
+
(_b = destination.exportedTraceIds) == null ? void 0 : _b.add(traceId);
|
|
179
150
|
}
|
|
180
|
-
function
|
|
181
|
-
return {
|
|
151
|
+
function replayTraceUrl(baseUrl) {
|
|
152
|
+
return `${baseUrl.replace(/\/+$/, "")}/v1/traces`;
|
|
182
153
|
}
|
|
183
|
-
function
|
|
184
|
-
|
|
185
|
-
return { ...bare, ...withMetadataPrefix(bare) };
|
|
154
|
+
function getAsyncLocalStorageCtor() {
|
|
155
|
+
return globalThis.RAINDROP_ASYNC_LOCAL_STORAGE;
|
|
186
156
|
}
|
|
187
|
-
function
|
|
188
|
-
|
|
157
|
+
function getWeakRefCtor() {
|
|
158
|
+
const ctor = globalThis.WeakRef;
|
|
159
|
+
return typeof ctor === "function" ? ctor : void 0;
|
|
189
160
|
}
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
161
|
+
var MAX_BINDING_STACK = 128;
|
|
162
|
+
var EMPTY_STACK = [];
|
|
163
|
+
var ContextStackStorage = class {
|
|
164
|
+
/** Emitted once when this runtime cannot support an ambient push. */
|
|
165
|
+
constructor(noAmbientBindWarning) {
|
|
166
|
+
this.noAmbientBindWarning = noAmbientBindWarning;
|
|
167
|
+
this._als = null;
|
|
168
|
+
this._enterWithUsable = false;
|
|
169
|
+
this._syncStack = EMPTY_STACK;
|
|
170
|
+
this._adoptionChecked = false;
|
|
171
|
+
this._warnedNoAmbientBind = false;
|
|
194
172
|
}
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
convoId: "raindrop-convo-id",
|
|
202
|
-
userId: "raindrop-user-id",
|
|
203
|
-
// The dispatch span and its trace, carried as fields as well as in
|
|
204
|
-
// `traceparent`. Not redundant: OTel's HTTP instrumentations rewrite
|
|
205
|
-
// `traceparent` from whatever span is current as the request goes out, so by
|
|
206
|
-
// the time the child reads it the ids name the HTTP client span and its trace
|
|
207
|
-
// instead of the dispatch. The child would then point its reverse reference at
|
|
208
|
-
// a span the launcher's UI does not know as a dispatch. A field states which
|
|
209
|
-
// span it means rather than meaning "whoever wrote this header last".
|
|
210
|
-
dispatchSpanId: "raindrop-dispatch-span-id",
|
|
211
|
-
traceId: "raindrop-trace-id"
|
|
212
|
-
};
|
|
213
|
-
var TRACEPARENT_HEADER = "traceparent";
|
|
214
|
-
var BAGGAGE_HEADER = "baggage";
|
|
215
|
-
var W3C_TRACE_ID = /^[0-9a-f]{32}$/;
|
|
216
|
-
var W3C_SPAN_ID = /^[0-9a-f]{16}$/;
|
|
217
|
-
function isW3CTraceId(value) {
|
|
218
|
-
return value !== void 0 && W3C_TRACE_ID.test(value);
|
|
219
|
-
}
|
|
220
|
-
function isW3CSpanId(value) {
|
|
221
|
-
return value !== void 0 && W3C_SPAN_ID.test(value);
|
|
222
|
-
}
|
|
223
|
-
var warnedNonConformantIds = false;
|
|
224
|
-
function warnNonConformantIdsOnce(traceId, spanId) {
|
|
225
|
-
if (warnedNonConformantIds) return;
|
|
226
|
-
warnedNonConformantIds = true;
|
|
227
|
-
console.warn(
|
|
228
|
-
`[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.`
|
|
229
|
-
);
|
|
230
|
-
}
|
|
231
|
-
var HANDOFF_HEADER = "x-raindrop-handoff";
|
|
232
|
-
var LANGSMITH_TRACE_HEADER = "langsmith-trace";
|
|
233
|
-
var LANGSMITH_METADATA_BAGGAGE_KEY = "langsmith-metadata";
|
|
234
|
-
function encodeBaggage(entries) {
|
|
235
|
-
return Object.entries(entries).filter((entry) => Boolean(entry[1])).map(([key, value]) => `${key}=${encodeURIComponent(value)}`).join(",");
|
|
236
|
-
}
|
|
237
|
-
function decodeBaggage(header) {
|
|
238
|
-
if (!header) return {};
|
|
239
|
-
const parsed = {};
|
|
240
|
-
for (const part of header.split(",")) {
|
|
241
|
-
const [rawKey, ...rest] = part.split("=");
|
|
242
|
-
if (!rawKey || rest.length === 0) continue;
|
|
243
|
-
const key = rawKey.trim();
|
|
244
|
-
let value;
|
|
173
|
+
maybeAdoptAsyncLocalStorage() {
|
|
174
|
+
if (this._adoptionChecked) return;
|
|
175
|
+
this._adoptionChecked = true;
|
|
176
|
+
const Ctor = getAsyncLocalStorageCtor();
|
|
177
|
+
if (!Ctor) return;
|
|
178
|
+
const als = new Ctor();
|
|
245
179
|
try {
|
|
246
|
-
|
|
180
|
+
als.run(EMPTY_STACK, () => {
|
|
181
|
+
});
|
|
247
182
|
} catch (e) {
|
|
248
|
-
|
|
183
|
+
return;
|
|
184
|
+
}
|
|
185
|
+
this._als = als;
|
|
186
|
+
if (typeof als.enterWith === "function") {
|
|
187
|
+
try {
|
|
188
|
+
als.enterWith(EMPTY_STACK);
|
|
189
|
+
this._enterWithUsable = true;
|
|
190
|
+
} catch (e) {
|
|
191
|
+
this._enterWithUsable = false;
|
|
192
|
+
}
|
|
249
193
|
}
|
|
250
|
-
if (key in parsed && parsed[key] !== value) throw new ConflictingCarrierError(key);
|
|
251
|
-
parsed[key] = value;
|
|
252
194
|
}
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
[BAGGAGE_KEYS.childEventId]: carrier.childEventId,
|
|
259
|
-
[BAGGAGE_KEYS.name]: carrier.name,
|
|
260
|
-
[BAGGAGE_KEYS.convoId]: carrier.convoId,
|
|
261
|
-
[BAGGAGE_KEYS.userId]: carrier.userId,
|
|
262
|
-
[BAGGAGE_KEYS.dispatchSpanId]: carrier.spanId,
|
|
263
|
-
[BAGGAGE_KEYS.traceId]: carrier.traceId
|
|
264
|
-
};
|
|
265
|
-
}
|
|
266
|
-
function toHeaders(carrier) {
|
|
267
|
-
const fields = encodeBaggage(carrierBaggage(carrier));
|
|
268
|
-
const headers = {
|
|
269
|
-
[BAGGAGE_HEADER]: fields,
|
|
270
|
-
[HANDOFF_HEADER]: fields
|
|
271
|
-
};
|
|
272
|
-
if (isW3CTraceId(carrier.traceId) && isW3CSpanId(carrier.spanId)) {
|
|
273
|
-
headers[TRACEPARENT_HEADER] = `00-${carrier.traceId}-${carrier.spanId}-01`;
|
|
195
|
+
getStack() {
|
|
196
|
+
var _a;
|
|
197
|
+
this.maybeAdoptAsyncLocalStorage();
|
|
198
|
+
if (this._als) return (_a = this._als.getStore()) != null ? _a : this._syncStack;
|
|
199
|
+
return this._syncStack;
|
|
274
200
|
}
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
// Carried here too: a LangSmith-shaped carrier is rewritten in transit
|
|
289
|
-
// exactly like the native one, and an injected `traceparent` is preferred
|
|
290
|
-
// over the dotted order on read.
|
|
291
|
-
[HANDOFF_HEADER]: encodeBaggage(carrierBaggage(carrier))
|
|
292
|
-
};
|
|
293
|
-
}
|
|
294
|
-
function isHeaderLookup(headers) {
|
|
295
|
-
return "get" in headers && typeof headers.get === "function";
|
|
296
|
-
}
|
|
297
|
-
var ConflictingCarrierError = class extends Error {
|
|
298
|
-
};
|
|
299
|
-
function readHeader(headers, name) {
|
|
300
|
-
var _a, _b, _c;
|
|
301
|
-
if (isHeaderLookup(headers)) return (_a = headers.get(name)) != null ? _a : void 0;
|
|
302
|
-
const value = (_c = headers[name]) != null ? _c : (_b = Object.entries(headers).find(([key]) => key.toLowerCase() === name)) == null ? void 0 : _b[1];
|
|
303
|
-
if (!Array.isArray(value)) return value;
|
|
304
|
-
const distinct = new Set(value);
|
|
305
|
-
if (distinct.size > 1) throw new ConflictingCarrierError(name);
|
|
306
|
-
return value[0];
|
|
307
|
-
}
|
|
308
|
-
function readTraceHeader(headers, name) {
|
|
309
|
-
const value = readHeader(headers, name);
|
|
310
|
-
if (!(value == null ? void 0 : value.includes(","))) return value;
|
|
311
|
-
const copies = value.split(",").map((copy) => copy.trim());
|
|
312
|
-
if (new Set(copies).size > 1) throw new ConflictingCarrierError(name);
|
|
313
|
-
return copies[0];
|
|
314
|
-
}
|
|
315
|
-
function fromHeaders(headers) {
|
|
316
|
-
var _a, _b;
|
|
317
|
-
let baggage;
|
|
318
|
-
let handoff;
|
|
319
|
-
let traceparent;
|
|
320
|
-
let langsmithTrace;
|
|
321
|
-
try {
|
|
322
|
-
baggage = decodeBaggage(readHeader(headers, BAGGAGE_HEADER));
|
|
323
|
-
handoff = decodeBaggage(readHeader(headers, HANDOFF_HEADER));
|
|
324
|
-
traceparent = readTraceHeader(headers, TRACEPARENT_HEADER);
|
|
325
|
-
langsmithTrace = readTraceHeader(headers, LANGSMITH_TRACE_HEADER);
|
|
326
|
-
} catch (error) {
|
|
327
|
-
if (error instanceof ConflictingCarrierError) return null;
|
|
328
|
-
throw error;
|
|
201
|
+
/**
|
|
202
|
+
* Persist an ambient stack mutation. Returns false when an ALS is adopted but
|
|
203
|
+
* `enterWith` is unusable (workerd): callers must NOT fall back to the
|
|
204
|
+
* process-shared sync stack, since concurrent isolates would cross-stamp.
|
|
205
|
+
*/
|
|
206
|
+
setAmbientStack(stack) {
|
|
207
|
+
if (this._als) {
|
|
208
|
+
if (!this._enterWithUsable) return false;
|
|
209
|
+
this._als.enterWith(stack);
|
|
210
|
+
return true;
|
|
211
|
+
}
|
|
212
|
+
this._syncStack = stack;
|
|
213
|
+
return true;
|
|
329
214
|
}
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
215
|
+
push(binding) {
|
|
216
|
+
this.maybeAdoptAsyncLocalStorage();
|
|
217
|
+
if (this._als && !this._enterWithUsable) {
|
|
218
|
+
this.warnNoAmbientBindOnce();
|
|
219
|
+
return;
|
|
220
|
+
}
|
|
221
|
+
let stack = this.getStack();
|
|
222
|
+
if (stack.length >= MAX_BINDING_STACK) {
|
|
223
|
+
stack = stack.filter((b) => b.isLive());
|
|
224
|
+
if (stack.length >= MAX_BINDING_STACK) {
|
|
225
|
+
stack = stack.slice(stack.length - (MAX_BINDING_STACK - 1));
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
this.setAmbientStack([...stack, binding]);
|
|
334
229
|
}
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
};
|
|
342
|
-
let traceId;
|
|
343
|
-
let spanId;
|
|
344
|
-
if (traceparent) {
|
|
345
|
-
const [, parsedTraceId, parsedSpanId] = traceparent.split("-");
|
|
346
|
-
if (isW3CTraceId(parsedTraceId) && isW3CSpanId(parsedSpanId)) {
|
|
347
|
-
traceId = parsedTraceId;
|
|
348
|
-
spanId = parsedSpanId;
|
|
230
|
+
remove(binding) {
|
|
231
|
+
binding.markDead();
|
|
232
|
+
const stack = this.getStack();
|
|
233
|
+
const pruned = stack.filter((b) => b !== binding && b.isLive());
|
|
234
|
+
if (pruned.length !== stack.length) {
|
|
235
|
+
this.setAmbientStack(pruned);
|
|
349
236
|
}
|
|
350
237
|
}
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
238
|
+
runWith(binding, callback) {
|
|
239
|
+
this.maybeAdoptAsyncLocalStorage();
|
|
240
|
+
if (this._als) {
|
|
241
|
+
return this._als.run([...this.getStack(), binding], callback);
|
|
242
|
+
}
|
|
243
|
+
const previous = this._syncStack;
|
|
244
|
+
this._syncStack = [...previous, binding];
|
|
245
|
+
try {
|
|
246
|
+
return callback();
|
|
247
|
+
} finally {
|
|
248
|
+
this._syncStack = previous;
|
|
249
|
+
}
|
|
355
250
|
}
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
251
|
+
current() {
|
|
252
|
+
const stack = this.getStack();
|
|
253
|
+
if (stack.length === 0) return void 0;
|
|
254
|
+
const top = stack[stack.length - 1];
|
|
255
|
+
if (top.isLive()) return top;
|
|
256
|
+
const pruned = stack.filter((b) => b.isLive());
|
|
257
|
+
this.setAmbientStack(pruned);
|
|
258
|
+
return pruned.length > 0 ? pruned[pruned.length - 1] : void 0;
|
|
362
259
|
}
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
260
|
+
warnNoAmbientBindOnce() {
|
|
261
|
+
if (this._warnedNoAmbientBind) return;
|
|
262
|
+
this._warnedNoAmbientBind = true;
|
|
263
|
+
console.warn(this.noAmbientBindWarning);
|
|
264
|
+
}
|
|
265
|
+
};
|
|
266
|
+
var NO_AMBIENT_ROUTING_BIND_WARNING = "[raindrop] This runtime's AsyncLocalStorage does not implement enterWith (e.g. Cloudflare Workers), so begin()/finish() cannot scope auto-instrumented spans to a project without cross-contaminating concurrent requests. Manual events and explicit span routing are unaffected; use asCurrent()/withSpan (run-based) to route auto-instrumented spans on this runtime.";
|
|
267
|
+
var NO_AMBIENT_ATTRIBUTE_BIND_WARNING = "[raindrop] This runtime's AsyncLocalStorage does not implement enterWith (e.g. Cloudflare Workers), so contextual span attributes (the detached sub-agent hand-off reference) cannot be bound ambiently without cross-contaminating concurrent requests. The child's own event still reports; only the per-span reverse reference is skipped.";
|
|
268
|
+
var ROUTING_STORAGE_KEY = /* @__PURE__ */ Symbol.for("raindrop.tracing.routingContextStorage");
|
|
269
|
+
function routingStorage() {
|
|
270
|
+
const holder = globalThis;
|
|
271
|
+
let storage = holder[ROUTING_STORAGE_KEY];
|
|
272
|
+
if (!storage) {
|
|
273
|
+
storage = new ContextStackStorage(NO_AMBIENT_ROUTING_BIND_WARNING);
|
|
274
|
+
holder[ROUTING_STORAGE_KEY] = storage;
|
|
275
|
+
}
|
|
276
|
+
return storage;
|
|
378
277
|
}
|
|
379
|
-
function
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
278
|
+
function makeBoundContext(binding, owner) {
|
|
279
|
+
const WeakRefCtor = owner !== void 0 ? getWeakRefCtor() : void 0;
|
|
280
|
+
const ref = WeakRefCtor && owner !== void 0 ? new WeakRefCtor(owner) : void 0;
|
|
281
|
+
let dead = false;
|
|
282
|
+
return {
|
|
283
|
+
projectId: binding.projectId,
|
|
284
|
+
authHint: binding.authHint,
|
|
285
|
+
...binding.appGit ? { appGit: binding.appGit } : {},
|
|
286
|
+
...binding.appGitSource ? { appGitSource: binding.appGitSource } : {},
|
|
287
|
+
isLive() {
|
|
288
|
+
if (dead) return false;
|
|
289
|
+
return ref === void 0 || ref.deref() !== void 0;
|
|
290
|
+
},
|
|
291
|
+
markDead() {
|
|
292
|
+
dead = true;
|
|
293
|
+
}
|
|
294
|
+
};
|
|
386
295
|
}
|
|
387
|
-
function
|
|
296
|
+
function bindRoutingContext(binding, owner) {
|
|
297
|
+
const bound = makeBoundContext(binding, owner);
|
|
388
298
|
try {
|
|
389
|
-
|
|
390
|
-
if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) return {};
|
|
391
|
-
const result = {};
|
|
392
|
-
for (const [key, value] of Object.entries(parsed)) {
|
|
393
|
-
if (typeof value === "string") result[key] = value;
|
|
394
|
-
}
|
|
395
|
-
return result;
|
|
299
|
+
routingStorage().push(bound);
|
|
396
300
|
} catch (e) {
|
|
397
|
-
return {};
|
|
398
301
|
}
|
|
302
|
+
return bound;
|
|
399
303
|
}
|
|
400
|
-
function
|
|
401
|
-
|
|
402
|
-
if (typeof hook !== "function") return fn();
|
|
403
|
-
let started = false;
|
|
304
|
+
function unbindRoutingContext(bound) {
|
|
305
|
+
if (!bound || !isBoundContext(bound)) return;
|
|
404
306
|
try {
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
return fn();
|
|
408
|
-
});
|
|
409
|
-
} catch (err) {
|
|
410
|
-
if (started) throw err;
|
|
411
|
-
return fn();
|
|
307
|
+
routingStorage().remove(bound);
|
|
308
|
+
} catch (e) {
|
|
412
309
|
}
|
|
413
310
|
}
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
311
|
+
function withRoutingContext(binding, callback) {
|
|
312
|
+
const bound = makeBoundContext(binding);
|
|
313
|
+
return routingStorage().runWith(bound, callback);
|
|
418
314
|
}
|
|
419
|
-
function
|
|
420
|
-
|
|
421
|
-
|
|
315
|
+
function currentRoutingBinding() {
|
|
316
|
+
const bound = routingStorage().current();
|
|
317
|
+
if (!bound) return void 0;
|
|
318
|
+
return {
|
|
319
|
+
projectId: bound.projectId,
|
|
320
|
+
authHint: bound.authHint,
|
|
321
|
+
...bound.appGit ? { appGit: bound.appGit } : {},
|
|
322
|
+
...bound.appGitSource ? { appGitSource: bound.appGitSource } : {}
|
|
323
|
+
};
|
|
422
324
|
}
|
|
423
|
-
function
|
|
424
|
-
|
|
425
|
-
const parsed = new URL(url);
|
|
426
|
-
parsed.username = "";
|
|
427
|
-
parsed.password = "";
|
|
428
|
-
parsed.search = "";
|
|
429
|
-
parsed.hash = "";
|
|
430
|
-
return parsed.toString();
|
|
431
|
-
} catch (e) {
|
|
432
|
-
return "<unparseable-url>";
|
|
433
|
-
}
|
|
325
|
+
function isBoundContext(value) {
|
|
326
|
+
return typeof value.isLive === "function";
|
|
434
327
|
}
|
|
435
|
-
var
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
328
|
+
var ATTRIBUTE_STORAGE_KEY = /* @__PURE__ */ Symbol.for("raindrop.tracing.spanAttributeStorage");
|
|
329
|
+
function attributeStorage() {
|
|
330
|
+
const holder = globalThis;
|
|
331
|
+
let storage = holder[ATTRIBUTE_STORAGE_KEY];
|
|
332
|
+
if (!storage) {
|
|
333
|
+
storage = new ContextStackStorage(NO_AMBIENT_ATTRIBUTE_BIND_WARNING);
|
|
334
|
+
holder[ATTRIBUTE_STORAGE_KEY] = storage;
|
|
442
335
|
}
|
|
443
|
-
|
|
444
|
-
log();
|
|
445
|
-
return true;
|
|
446
|
-
}
|
|
447
|
-
async function raceWithTimeout(promise, timeoutMs) {
|
|
448
|
-
let timer;
|
|
449
|
-
const settledInTime = await Promise.race([
|
|
450
|
-
promise.then(
|
|
451
|
-
() => true,
|
|
452
|
-
() => true
|
|
453
|
-
),
|
|
454
|
-
new Promise((resolve) => {
|
|
455
|
-
var _a;
|
|
456
|
-
timer = setTimeout(() => resolve(false), Math.max(0, timeoutMs));
|
|
457
|
-
(_a = timer.unref) == null ? void 0 : _a.call(timer);
|
|
458
|
-
})
|
|
459
|
-
]);
|
|
460
|
-
if (timer) clearTimeout(timer);
|
|
461
|
-
return settledInTime;
|
|
336
|
+
return storage;
|
|
462
337
|
}
|
|
463
|
-
function
|
|
464
|
-
|
|
465
|
-
const
|
|
466
|
-
|
|
467
|
-
const
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
338
|
+
function makeAttributeFrame(attributes, owner) {
|
|
339
|
+
const snapshot = { ...attributes };
|
|
340
|
+
const WeakRefCtor = owner !== void 0 ? getWeakRefCtor() : void 0;
|
|
341
|
+
const ref = WeakRefCtor && owner !== void 0 ? new WeakRefCtor(owner) : void 0;
|
|
342
|
+
const owned = /* @__PURE__ */ new WeakSet();
|
|
343
|
+
let dead = false;
|
|
344
|
+
let sawError = false;
|
|
345
|
+
return {
|
|
346
|
+
attributes: snapshot,
|
|
347
|
+
sawErrorSpan: () => sawError,
|
|
348
|
+
ownsSpan: (span) => owned.has(span),
|
|
349
|
+
claimSpan(span) {
|
|
350
|
+
owned.add(span);
|
|
351
|
+
},
|
|
352
|
+
markErrorSpanSeen() {
|
|
353
|
+
sawError = true;
|
|
354
|
+
},
|
|
355
|
+
// A frame whose owner has been collected is dead even though nothing
|
|
356
|
+
// unbound it: a run that never settles must not keep handing its reverse
|
|
357
|
+
// reference to whatever runs next on a reused context.
|
|
358
|
+
isLive() {
|
|
359
|
+
if (dead) return false;
|
|
360
|
+
return ref === void 0 || ref.deref() !== void 0;
|
|
361
|
+
},
|
|
362
|
+
markDead() {
|
|
363
|
+
dead = true;
|
|
364
|
+
}
|
|
365
|
+
};
|
|
366
|
+
}
|
|
367
|
+
function bindSpanAttributes(attributes, owner) {
|
|
368
|
+
if (Object.keys(attributes).length === 0) return void 0;
|
|
369
|
+
const frame = makeAttributeFrame(attributes, owner);
|
|
370
|
+
try {
|
|
371
|
+
attributeStorage().push(frame);
|
|
372
|
+
} catch (e) {
|
|
373
|
+
return void 0;
|
|
473
374
|
}
|
|
474
|
-
return
|
|
375
|
+
return frame;
|
|
475
376
|
}
|
|
476
|
-
function
|
|
477
|
-
if (
|
|
478
|
-
|
|
479
|
-
|
|
377
|
+
function unbindSpanAttributes(frame) {
|
|
378
|
+
if (!frame || !isAttributeFrame(frame)) return;
|
|
379
|
+
try {
|
|
380
|
+
attributeStorage().remove(frame);
|
|
381
|
+
} catch (e) {
|
|
480
382
|
}
|
|
481
|
-
if (attemptNumber <= 1) return 0;
|
|
482
|
-
const base = 500;
|
|
483
|
-
const factor = Math.pow(2, attemptNumber - 2);
|
|
484
|
-
return Math.min(base * factor, MAX_RETRY_DELAY_MS);
|
|
485
383
|
}
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
const
|
|
492
|
-
|
|
493
|
-
console.warn(
|
|
494
|
-
`${prefix} ${opName} retry ${attemptNumber}/${opts.maxAttempts} in ${delay}ms`
|
|
495
|
-
);
|
|
496
|
-
}
|
|
497
|
-
if (delay > 0) await wait(delay);
|
|
498
|
-
} else if (opts.debug) {
|
|
499
|
-
console.log(`${prefix} ${opName} attempt ${attemptNumber}/${opts.maxAttempts}`);
|
|
500
|
-
}
|
|
501
|
-
try {
|
|
502
|
-
return await operation();
|
|
503
|
-
} catch (err) {
|
|
504
|
-
lastError = err;
|
|
505
|
-
if (opts.debug) {
|
|
506
|
-
const msg = err instanceof Error ? err.message : String(err);
|
|
507
|
-
console.warn(
|
|
508
|
-
`${prefix} ${opName} attempt ${attemptNumber} failed: ${msg}${attemptNumber === opts.maxAttempts ? " (no more retries)" : ""}`
|
|
509
|
-
);
|
|
384
|
+
function applySpanAttributeFrames(span, setAttribute) {
|
|
385
|
+
try {
|
|
386
|
+
for (const frame of attributeStorage().getStack()) {
|
|
387
|
+
if (!frame.isLive()) continue;
|
|
388
|
+
frame.claimSpan(span);
|
|
389
|
+
for (const [key, value] of Object.entries(frame.attributes)) {
|
|
390
|
+
setAttribute(key, value);
|
|
510
391
|
}
|
|
511
|
-
if (lastError && typeof lastError === "object" && "retryable" in lastError && !lastError.retryable)
|
|
512
|
-
break;
|
|
513
|
-
if (attemptNumber === opts.maxAttempts) break;
|
|
514
392
|
}
|
|
393
|
+
} catch (e) {
|
|
515
394
|
}
|
|
516
|
-
throw lastError instanceof Error ? lastError : new Error(String(lastError));
|
|
517
|
-
}
|
|
518
|
-
async function postJson(url, body, headers, opts) {
|
|
519
|
-
var _a;
|
|
520
|
-
const opName = `POST ${redactUrlForLog(url)}`;
|
|
521
|
-
const timeoutMs = (_a = opts.timeoutMs) != null ? _a : DEFAULT_REQUEST_TIMEOUT_MS;
|
|
522
|
-
await withRetry(
|
|
523
|
-
async () => {
|
|
524
|
-
const resp = await runWithTracingSuppressed(
|
|
525
|
-
() => fetch(url, {
|
|
526
|
-
method: "POST",
|
|
527
|
-
redirect: headers["X-Raindrop-Replay-Id"] !== void 0 ? "error" : "follow",
|
|
528
|
-
headers: {
|
|
529
|
-
"Content-Type": "application/json",
|
|
530
|
-
...headers
|
|
531
|
-
},
|
|
532
|
-
body: JSON.stringify(body),
|
|
533
|
-
signal: AbortSignal.timeout(timeoutMs)
|
|
534
|
-
})
|
|
535
|
-
);
|
|
536
|
-
if (!resp.ok) {
|
|
537
|
-
const text = await resp.text().catch(() => "");
|
|
538
|
-
const err = new Error(
|
|
539
|
-
`HTTP ${resp.status} ${resp.statusText}${text ? `: ${text}` : ""}`
|
|
540
|
-
);
|
|
541
|
-
const retryAfterMs = parseRetryAfter(resp.headers);
|
|
542
|
-
if (typeof retryAfterMs === "number") err.retryAfterMs = retryAfterMs;
|
|
543
|
-
err.retryable = resp.status === 429 || resp.status >= 500;
|
|
544
|
-
throw err;
|
|
545
|
-
}
|
|
546
|
-
},
|
|
547
|
-
opName,
|
|
548
|
-
opts
|
|
549
|
-
);
|
|
550
395
|
}
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
if (limit > TRUNCATION_MARKER.length) {
|
|
558
|
-
return text.slice(0, limit - TRUNCATION_MARKER.length) + TRUNCATION_MARKER;
|
|
396
|
+
function claimSpanForFrames(span) {
|
|
397
|
+
try {
|
|
398
|
+
for (const frame of attributeStorage().getStack()) {
|
|
399
|
+
if (frame.isLive()) frame.claimSpan(span);
|
|
400
|
+
}
|
|
401
|
+
} catch (e) {
|
|
559
402
|
}
|
|
560
|
-
return text.slice(0, Math.max(0, limit));
|
|
561
403
|
}
|
|
562
|
-
function
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
function boundedClone(obj, charBudget) {
|
|
569
|
-
let budget = charBudget;
|
|
570
|
-
const seen = /* @__PURE__ */ new WeakSet();
|
|
571
|
-
const walk = (node, depth) => {
|
|
572
|
-
if (budget <= 0) return TRUNCATION_MARKER;
|
|
573
|
-
if (typeof node === "string") {
|
|
574
|
-
if (node.length > budget) {
|
|
575
|
-
const taken = node.slice(0, Math.max(0, budget)) + TRUNCATION_MARKER;
|
|
576
|
-
budget = 0;
|
|
577
|
-
return taken;
|
|
578
|
-
}
|
|
579
|
-
budget -= Math.max(node.length, 1);
|
|
580
|
-
return node;
|
|
581
|
-
}
|
|
582
|
-
if (node === null || typeof node === "number" || typeof node === "boolean") {
|
|
583
|
-
budget -= 8;
|
|
584
|
-
return node;
|
|
585
|
-
}
|
|
586
|
-
if (typeof node !== "object") {
|
|
587
|
-
budget -= 8;
|
|
588
|
-
return node;
|
|
589
|
-
}
|
|
590
|
-
if (seen.has(node)) return "[CIRCULAR]";
|
|
591
|
-
if (depth >= BOUNDED_CLONE_MAX_DEPTH) {
|
|
592
|
-
budget -= 16;
|
|
593
|
-
return `<max depth>`;
|
|
594
|
-
}
|
|
595
|
-
seen.add(node);
|
|
596
|
-
if (Array.isArray(node)) {
|
|
597
|
-
const out2 = [];
|
|
598
|
-
for (const v of node) {
|
|
599
|
-
if (budget <= 0) {
|
|
600
|
-
out2.push(TRUNCATION_MARKER);
|
|
601
|
-
break;
|
|
602
|
-
}
|
|
603
|
-
out2.push(walk(v, depth + 1));
|
|
604
|
-
}
|
|
605
|
-
return out2;
|
|
606
|
-
}
|
|
607
|
-
if (typeof node.toJSON === "function") {
|
|
608
|
-
budget -= 16;
|
|
609
|
-
return node;
|
|
404
|
+
function currentSpanAttributes() {
|
|
405
|
+
const merged = {};
|
|
406
|
+
try {
|
|
407
|
+
for (const frame of attributeStorage().getStack()) {
|
|
408
|
+
if (!frame.isLive()) continue;
|
|
409
|
+
Object.assign(merged, frame.attributes);
|
|
610
410
|
}
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
out[key] = walk(node[k], depth + 1);
|
|
411
|
+
} catch (e) {
|
|
412
|
+
}
|
|
413
|
+
return merged;
|
|
414
|
+
}
|
|
415
|
+
function markErrorSpanSeen(span) {
|
|
416
|
+
try {
|
|
417
|
+
for (const frame of attributeStorage().getStack()) {
|
|
418
|
+
if (frame.ownsSpan(span)) frame.markErrorSpanSeen();
|
|
620
419
|
}
|
|
621
|
-
|
|
622
|
-
}
|
|
623
|
-
return walk(obj, 0);
|
|
420
|
+
} catch (e) {
|
|
421
|
+
}
|
|
624
422
|
}
|
|
625
|
-
function
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
423
|
+
function isAttributeFrame(value) {
|
|
424
|
+
return typeof value.isLive === "function";
|
|
425
|
+
}
|
|
426
|
+
var APP_COMMIT_SHA = "raindrop.app.commit_sha";
|
|
427
|
+
var APP_COMMIT_DIRTY = "raindrop.app.commit_dirty";
|
|
428
|
+
var APP_BRANCH = "raindrop.app.branch";
|
|
429
|
+
var APP_GIT_KEYS = [APP_COMMIT_SHA, APP_COMMIT_DIRTY, APP_BRANCH];
|
|
430
|
+
var own = (value, key) => Object.prototype.hasOwnProperty.call(value, key);
|
|
431
|
+
function withAppGitProperties(properties, snapshot) {
|
|
432
|
+
try {
|
|
433
|
+
const merged = { ...properties };
|
|
434
|
+
for (const key of APP_GIT_KEYS)
|
|
435
|
+
if (!own(merged, key) && own(snapshot, key)) merged[key] = snapshot[key];
|
|
436
|
+
return merged;
|
|
437
|
+
} catch (e) {
|
|
438
|
+
return properties != null ? properties : {};
|
|
629
439
|
}
|
|
630
|
-
|
|
631
|
-
|
|
440
|
+
}
|
|
441
|
+
function withAppGitAttributes(attributes, snapshot) {
|
|
632
442
|
try {
|
|
633
|
-
|
|
443
|
+
const present = new Set(attributes.flatMap((attr) => attr ? [attr.key] : []));
|
|
444
|
+
const added = [];
|
|
445
|
+
for (const key of APP_GIT_KEYS) {
|
|
446
|
+
if (present.has(key) || present.has(`ai.telemetry.metadata.${key}`) || present.has(`traceloop.association.properties.${key}`))
|
|
447
|
+
continue;
|
|
448
|
+
const value = snapshot[key];
|
|
449
|
+
if (typeof value === "string") added.push({ key, value: { stringValue: value } });
|
|
450
|
+
else if (typeof value === "boolean") added.push({ key, value: { boolValue: value } });
|
|
451
|
+
}
|
|
452
|
+
return added.length ? [...attributes, ...added] : attributes;
|
|
634
453
|
} catch (e) {
|
|
635
|
-
|
|
454
|
+
return attributes;
|
|
636
455
|
}
|
|
637
|
-
|
|
638
|
-
|
|
456
|
+
}
|
|
457
|
+
function normalizeFeatureFlags(input) {
|
|
458
|
+
if (Array.isArray(input)) {
|
|
459
|
+
return Object.fromEntries(input.map((name) => [name, "true"]));
|
|
639
460
|
}
|
|
640
|
-
return
|
|
461
|
+
return Object.fromEntries(
|
|
462
|
+
Object.entries(input).map(([k, v]) => [k, String(v)])
|
|
463
|
+
);
|
|
641
464
|
}
|
|
642
|
-
function
|
|
643
|
-
|
|
644
|
-
return
|
|
465
|
+
function getCrypto() {
|
|
466
|
+
const c = globalThis.crypto;
|
|
467
|
+
return c;
|
|
645
468
|
}
|
|
646
|
-
function
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
return
|
|
469
|
+
function randomBytes(length) {
|
|
470
|
+
const cryptoObj = getCrypto();
|
|
471
|
+
const out = new Uint8Array(length);
|
|
472
|
+
if (cryptoObj && typeof cryptoObj.getRandomValues === "function") {
|
|
473
|
+
cryptoObj.getRandomValues(out);
|
|
474
|
+
return out;
|
|
475
|
+
}
|
|
476
|
+
for (let i = 0; i < out.length; i++) out[i] = Math.floor(Math.random() * 256);
|
|
477
|
+
return out;
|
|
655
478
|
}
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
if (!current) {
|
|
661
|
-
let storage = null;
|
|
662
|
-
try {
|
|
663
|
-
const Ctor = globalThis.RAINDROP_ASYNC_LOCAL_STORAGE;
|
|
664
|
-
if (Ctor) storage = new Ctor();
|
|
665
|
-
} catch (e) {
|
|
666
|
-
storage = null;
|
|
667
|
-
}
|
|
668
|
-
current = {
|
|
669
|
-
storage,
|
|
670
|
-
syncDestination: void 0,
|
|
671
|
-
spanDestinations: /* @__PURE__ */ new WeakMap()
|
|
672
|
-
};
|
|
673
|
-
holder[STATE_KEY] = current;
|
|
479
|
+
function randomUUID() {
|
|
480
|
+
const cryptoObj = getCrypto();
|
|
481
|
+
if (cryptoObj && typeof cryptoObj.randomUUID === "function") {
|
|
482
|
+
return cryptoObj.randomUUID();
|
|
674
483
|
}
|
|
675
|
-
|
|
484
|
+
const b = randomBytes(16);
|
|
485
|
+
b[6] = b[6] & 15 | 64;
|
|
486
|
+
b[8] = b[8] & 63 | 128;
|
|
487
|
+
const hex = [...b].map((x) => x.toString(16).padStart(2, "0")).join("");
|
|
488
|
+
return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`;
|
|
676
489
|
}
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
490
|
+
var HANDOFF_ATTRIBUTE_SUFFIXES = {
|
|
491
|
+
mode: "raindrop.handoff.mode",
|
|
492
|
+
childEventId: "raindrop.handoff.childEventId",
|
|
493
|
+
parentEventId: "raindrop.handoff.parentEventId",
|
|
494
|
+
parentSpanId: "raindrop.handoff.parentSpanId",
|
|
495
|
+
name: "raindrop.handoff.name",
|
|
496
|
+
terminal: "raindrop.handoff.terminal",
|
|
497
|
+
agentRole: "raindrop.agent.role"
|
|
498
|
+
};
|
|
499
|
+
var AI_SDK_METADATA_PREFIX = "ai.telemetry.metadata.";
|
|
500
|
+
var DETACHED_MODE = "detached";
|
|
501
|
+
var SUBAGENT_AGENT_ROLE = "subagent";
|
|
502
|
+
var HANDOFF_TERMINAL_CANCELLED = "cancelled";
|
|
503
|
+
var TOOL_EVENTS_SUFFIX = "raindrop.toolEvents";
|
|
504
|
+
var TOOL_EVENTS_ALLOW = "allow";
|
|
505
|
+
var OPERATION_ID_ATTRIBUTE = "ai.operationId";
|
|
506
|
+
var SUBAGENT_ABORT_OPERATION_ID = "ai.subagent.failed";
|
|
507
|
+
var SUBAGENT_ABORT_SPAN_NAME = SUBAGENT_ABORT_OPERATION_ID;
|
|
508
|
+
var DEFAULT_DISPATCH_SPAN_NAME = "launch_subagent";
|
|
509
|
+
var HANDOFF_TERMINAL_PROPERTY_KEY = HANDOFF_ATTRIBUTE_SUFFIXES.terminal;
|
|
510
|
+
function defined(entries) {
|
|
511
|
+
const out = {};
|
|
512
|
+
for (const [key, value] of Object.entries(entries)) {
|
|
513
|
+
if (typeof value === "string" && value.trim().length > 0) out[key] = value;
|
|
514
|
+
}
|
|
515
|
+
return out;
|
|
681
516
|
}
|
|
682
|
-
function
|
|
683
|
-
|
|
684
|
-
|
|
517
|
+
function detachedDispatchMetadata(dispatch) {
|
|
518
|
+
return defined({
|
|
519
|
+
[HANDOFF_ATTRIBUTE_SUFFIXES.mode]: DETACHED_MODE,
|
|
520
|
+
[HANDOFF_ATTRIBUTE_SUFFIXES.childEventId]: dispatch.childEventId,
|
|
521
|
+
[HANDOFF_ATTRIBUTE_SUFFIXES.name]: dispatch.name
|
|
522
|
+
});
|
|
685
523
|
}
|
|
686
|
-
function
|
|
687
|
-
|
|
688
|
-
|
|
524
|
+
function detachedChildMetadata(link) {
|
|
525
|
+
return defined({
|
|
526
|
+
[HANDOFF_ATTRIBUTE_SUFFIXES.parentEventId]: link.parentEventId,
|
|
527
|
+
[HANDOFF_ATTRIBUTE_SUFFIXES.parentSpanId]: link.parentSpanId,
|
|
528
|
+
[HANDOFF_ATTRIBUTE_SUFFIXES.name]: link.name,
|
|
529
|
+
[HANDOFF_ATTRIBUTE_SUFFIXES.agentRole]: SUBAGENT_AGENT_ROLE
|
|
530
|
+
});
|
|
689
531
|
}
|
|
690
|
-
function
|
|
691
|
-
|
|
692
|
-
return void 0;
|
|
693
|
-
}
|
|
694
|
-
return state().spanDestinations.get(value);
|
|
532
|
+
function cancelledTerminalMetadata() {
|
|
533
|
+
return { [HANDOFF_ATTRIBUTE_SUFFIXES.terminal]: HANDOFF_TERMINAL_CANCELLED };
|
|
695
534
|
}
|
|
696
|
-
function
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
(_a = destination.exportedSpanIds) == null ? void 0 : _a.add(spanId);
|
|
700
|
-
(_b = destination.exportedTraceIds) == null ? void 0 : _b.add(traceId);
|
|
535
|
+
function cancelledTerminalAttributes() {
|
|
536
|
+
const bare = cancelledTerminalMetadata();
|
|
537
|
+
return { ...bare, ...withMetadataPrefix(bare) };
|
|
701
538
|
}
|
|
702
|
-
function
|
|
703
|
-
return
|
|
539
|
+
function toolEventsAllowMetadata() {
|
|
540
|
+
return { [TOOL_EVENTS_SUFFIX]: TOOL_EVENTS_ALLOW };
|
|
704
541
|
}
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
var _a;
|
|
710
|
-
try {
|
|
711
|
-
const env = (_a = globalThis == null ? void 0 : globalThis.process) == null ? void 0 : _a.env;
|
|
712
|
-
if (env && typeof env[name] === "string" && env[name].length > 0) {
|
|
713
|
-
return env[name];
|
|
714
|
-
}
|
|
715
|
-
} catch (e) {
|
|
542
|
+
function withMetadataPrefix(metadata) {
|
|
543
|
+
const out = {};
|
|
544
|
+
for (const [key, value] of Object.entries(metadata)) {
|
|
545
|
+
out[key.startsWith(AI_SDK_METADATA_PREFIX) ? key : `${AI_SDK_METADATA_PREFIX}${key}`] = value;
|
|
716
546
|
}
|
|
717
|
-
return
|
|
547
|
+
return out;
|
|
718
548
|
}
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
549
|
+
var BAGGAGE_KEYS = {
|
|
550
|
+
eventId: "raindrop-event-id",
|
|
551
|
+
childEventId: "raindrop-child-event-id",
|
|
552
|
+
name: "raindrop-handoff-name",
|
|
553
|
+
convoId: "raindrop-convo-id",
|
|
554
|
+
userId: "raindrop-user-id",
|
|
555
|
+
// The dispatch span and its trace, carried as fields as well as in
|
|
556
|
+
// `traceparent`. Not redundant: OTel's HTTP instrumentations rewrite
|
|
557
|
+
// `traceparent` from whatever span is current as the request goes out, so by
|
|
558
|
+
// the time the child reads it the ids name the HTTP client span and its trace
|
|
559
|
+
// instead of the dispatch. The child would then point its reverse reference at
|
|
560
|
+
// a span the launcher's UI does not know as a dispatch. A field states which
|
|
561
|
+
// span it means rather than meaning "whoever wrote this header last".
|
|
562
|
+
dispatchSpanId: "raindrop-dispatch-span-id",
|
|
563
|
+
traceId: "raindrop-trace-id"
|
|
564
|
+
};
|
|
565
|
+
var TRACEPARENT_HEADER = "traceparent";
|
|
566
|
+
var BAGGAGE_HEADER = "baggage";
|
|
567
|
+
var W3C_TRACE_ID = /^[0-9a-f]{32}$/;
|
|
568
|
+
var W3C_SPAN_ID = /^[0-9a-f]{16}$/;
|
|
569
|
+
function isW3CTraceId(value) {
|
|
570
|
+
return value !== void 0 && W3C_TRACE_ID.test(value);
|
|
728
571
|
}
|
|
729
|
-
function
|
|
730
|
-
|
|
731
|
-
if (hostname === "localhost" || hostname === "127.0.0.1" || hostname === "0.0.0.0" || hostname === "::1") {
|
|
732
|
-
return true;
|
|
733
|
-
}
|
|
734
|
-
if (hostname.endsWith(".localhost")) return true;
|
|
735
|
-
return false;
|
|
572
|
+
function isW3CSpanId(value) {
|
|
573
|
+
return value !== void 0 && W3C_SPAN_ID.test(value);
|
|
736
574
|
}
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
575
|
+
var warnedNonConformantIds = false;
|
|
576
|
+
function warnNonConformantIdsOnce(traceId, spanId) {
|
|
577
|
+
if (warnedNonConformantIds) return;
|
|
578
|
+
warnedNonConformantIds = true;
|
|
579
|
+
console.warn(
|
|
580
|
+
`[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.`
|
|
581
|
+
);
|
|
582
|
+
}
|
|
583
|
+
var HANDOFF_HEADER = "x-raindrop-handoff";
|
|
584
|
+
var LANGSMITH_TRACE_HEADER = "langsmith-trace";
|
|
585
|
+
var LANGSMITH_METADATA_BAGGAGE_KEY = "langsmith-metadata";
|
|
586
|
+
function encodeBaggage(entries) {
|
|
587
|
+
return Object.entries(entries).filter((entry) => Boolean(entry[1])).map(([key, value]) => `${key}=${encodeURIComponent(value)}`).join(",");
|
|
588
|
+
}
|
|
589
|
+
function decodeBaggage(header) {
|
|
590
|
+
if (!header) return {};
|
|
591
|
+
const parsed = {};
|
|
592
|
+
for (const part of header.split(",")) {
|
|
593
|
+
const [rawKey, ...rest] = part.split("=");
|
|
594
|
+
if (!rawKey || rest.length === 0) continue;
|
|
595
|
+
const key = rawKey.trim();
|
|
596
|
+
let value;
|
|
597
|
+
try {
|
|
598
|
+
value = decodeURIComponent(rest.join("=").trim());
|
|
599
|
+
} catch (e) {
|
|
600
|
+
value = rest.join("=").trim();
|
|
742
601
|
}
|
|
743
|
-
|
|
602
|
+
if (key in parsed && parsed[key] !== value) throw new ConflictingCarrierError(key);
|
|
603
|
+
parsed[key] = value;
|
|
744
604
|
}
|
|
745
|
-
return
|
|
605
|
+
return parsed;
|
|
746
606
|
}
|
|
747
|
-
function
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
607
|
+
function carrierBaggage(carrier) {
|
|
608
|
+
return {
|
|
609
|
+
[BAGGAGE_KEYS.eventId]: carrier.eventId,
|
|
610
|
+
[BAGGAGE_KEYS.childEventId]: carrier.childEventId,
|
|
611
|
+
[BAGGAGE_KEYS.name]: carrier.name,
|
|
612
|
+
[BAGGAGE_KEYS.convoId]: carrier.convoId,
|
|
613
|
+
[BAGGAGE_KEYS.userId]: carrier.userId,
|
|
614
|
+
[BAGGAGE_KEYS.dispatchSpanId]: carrier.spanId,
|
|
615
|
+
[BAGGAGE_KEYS.traceId]: carrier.traceId
|
|
616
|
+
};
|
|
751
617
|
}
|
|
752
|
-
function
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
618
|
+
function toHeaders(carrier) {
|
|
619
|
+
const fields = encodeBaggage(carrierBaggage(carrier));
|
|
620
|
+
const headers = {
|
|
621
|
+
[BAGGAGE_HEADER]: fields,
|
|
622
|
+
[HANDOFF_HEADER]: fields
|
|
623
|
+
};
|
|
624
|
+
if (isW3CTraceId(carrier.traceId) && isW3CSpanId(carrier.spanId)) {
|
|
625
|
+
headers[TRACEPARENT_HEADER] = `00-${carrier.traceId}-${carrier.spanId}-01`;
|
|
757
626
|
}
|
|
758
|
-
|
|
759
|
-
if (explicitUrlEnv) return (_b = formatEndpoint(explicitUrlEnv)) != null ? _b : null;
|
|
760
|
-
const workshopEnv = readWorkshopEnv();
|
|
761
|
-
if (workshopEnv === "disable") return null;
|
|
762
|
-
if (workshopEnv === "enable") return DEFAULT_LOCAL_WORKSHOP_URL;
|
|
763
|
-
if (workshopEnv && "url" in workshopEnv) return (_c = formatEndpoint(workshopEnv.url)) != null ? _c : null;
|
|
764
|
-
if (shouldAutoEnableLocalWorkshop()) return DEFAULT_LOCAL_WORKSHOP_URL;
|
|
765
|
-
return null;
|
|
766
|
-
}
|
|
767
|
-
function localDebuggerEnabled(baseUrl) {
|
|
768
|
-
return resolveLocalDebuggerBaseUrl(baseUrl) !== null;
|
|
627
|
+
return headers;
|
|
769
628
|
}
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
var _a;
|
|
773
|
-
const baseUrl = resolveLocalDebuggerBaseUrl(options.baseUrl);
|
|
774
|
-
if (!baseUrl) return Promise.resolve();
|
|
775
|
-
return postJson(`${baseUrl}traces`, body, {}, {
|
|
776
|
-
maxAttempts: 1,
|
|
777
|
-
debug: (_a = options.debug) != null ? _a : false,
|
|
778
|
-
sdkName: options.sdkName,
|
|
779
|
-
timeoutMs: LOCAL_DEBUGGER_MIRROR_TIMEOUT_MS
|
|
780
|
-
}).catch(() => {
|
|
781
|
-
});
|
|
629
|
+
function langsmithStamp() {
|
|
630
|
+
return (/* @__PURE__ */ new Date()).toISOString().replace(/[-:]/g, "").replace(/\.\d+Z$/, "000000");
|
|
782
631
|
}
|
|
783
|
-
function
|
|
632
|
+
function toLangSmithHeaders(carrier) {
|
|
633
|
+
const stamp = langsmithStamp();
|
|
634
|
+
const dottedOrder = `${stamp}Z${carrier.traceId}.${stamp}Z${carrier.spanId}`;
|
|
635
|
+
return {
|
|
636
|
+
[LANGSMITH_TRACE_HEADER]: dottedOrder,
|
|
637
|
+
[BAGGAGE_HEADER]: encodeBaggage({
|
|
638
|
+
[LANGSMITH_METADATA_BAGGAGE_KEY]: JSON.stringify(carrierBaggage(carrier))
|
|
639
|
+
}),
|
|
640
|
+
// Carried here too: a LangSmith-shaped carrier is rewritten in transit
|
|
641
|
+
// exactly like the native one, and an injected `traceparent` is preferred
|
|
642
|
+
// over the dotted order on read.
|
|
643
|
+
[HANDOFF_HEADER]: encodeBaggage(carrierBaggage(carrier))
|
|
644
|
+
};
|
|
645
|
+
}
|
|
646
|
+
function isHeaderLookup(headers) {
|
|
647
|
+
return "get" in headers && typeof headers.get === "function";
|
|
648
|
+
}
|
|
649
|
+
var ConflictingCarrierError = class extends Error {
|
|
650
|
+
};
|
|
651
|
+
function readHeader(headers, name) {
|
|
652
|
+
var _a, _b, _c;
|
|
653
|
+
if (isHeaderLookup(headers)) return (_a = headers.get(name)) != null ? _a : void 0;
|
|
654
|
+
const value = (_c = headers[name]) != null ? _c : (_b = Object.entries(headers).find(([key]) => key.toLowerCase() === name)) == null ? void 0 : _b[1];
|
|
655
|
+
if (!Array.isArray(value)) return value;
|
|
656
|
+
const distinct = new Set(value);
|
|
657
|
+
if (distinct.size > 1) throw new ConflictingCarrierError(name);
|
|
658
|
+
return value[0];
|
|
659
|
+
}
|
|
660
|
+
function readTraceHeader(headers, name) {
|
|
661
|
+
const value = readHeader(headers, name);
|
|
662
|
+
if (!(value == null ? void 0 : value.includes(","))) return value;
|
|
663
|
+
const copies = value.split(",").map((copy) => copy.trim());
|
|
664
|
+
if (new Set(copies).size > 1) throw new ConflictingCarrierError(name);
|
|
665
|
+
return copies[0];
|
|
666
|
+
}
|
|
667
|
+
function fromHeaders(headers) {
|
|
784
668
|
var _a, _b;
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
669
|
+
let baggage;
|
|
670
|
+
let handoff;
|
|
671
|
+
let traceparent;
|
|
672
|
+
let langsmithTrace;
|
|
673
|
+
try {
|
|
674
|
+
baggage = decodeBaggage(readHeader(headers, BAGGAGE_HEADER));
|
|
675
|
+
handoff = decodeBaggage(readHeader(headers, HANDOFF_HEADER));
|
|
676
|
+
traceparent = readTraceHeader(headers, TRACEPARENT_HEADER);
|
|
677
|
+
langsmithTrace = readTraceHeader(headers, LANGSMITH_TRACE_HEADER);
|
|
678
|
+
} catch (error) {
|
|
679
|
+
if (error instanceof ConflictingCarrierError) return null;
|
|
680
|
+
throw error;
|
|
681
|
+
}
|
|
682
|
+
const langsmithMetadata = baggage[LANGSMITH_METADATA_BAGGAGE_KEY];
|
|
683
|
+
const nested = langsmithMetadata ? safeParseStringRecord(langsmithMetadata) : {};
|
|
684
|
+
for (const [key, value] of Object.entries(nested)) {
|
|
685
|
+
if (key in baggage && baggage[key] !== value) return null;
|
|
686
|
+
}
|
|
687
|
+
const fields = {
|
|
688
|
+
...baggage,
|
|
689
|
+
...nested,
|
|
690
|
+
// Last, so it wins: the standard headers may have been rewritten in transit
|
|
691
|
+
// by a propagator, this one is only ever written by us.
|
|
692
|
+
...handoff
|
|
693
|
+
};
|
|
694
|
+
let traceId;
|
|
695
|
+
let spanId;
|
|
696
|
+
if (traceparent) {
|
|
697
|
+
const [, parsedTraceId, parsedSpanId] = traceparent.split("-");
|
|
698
|
+
if (isW3CTraceId(parsedTraceId) && isW3CSpanId(parsedSpanId)) {
|
|
699
|
+
traceId = parsedTraceId;
|
|
700
|
+
spanId = parsedSpanId;
|
|
801
701
|
}
|
|
802
|
-
|
|
803
|
-
|
|
702
|
+
}
|
|
703
|
+
if (!traceId && !spanId && langsmithTrace) {
|
|
704
|
+
const segments = langsmithTrace.split(".");
|
|
705
|
+
traceId = (_a = segments[0]) == null ? void 0 : _a.split("Z").pop();
|
|
706
|
+
spanId = (_b = segments[segments.length - 1]) == null ? void 0 : _b.split("Z").pop();
|
|
707
|
+
}
|
|
708
|
+
traceId = fields[BAGGAGE_KEYS.traceId] || traceId;
|
|
709
|
+
spanId = fields[BAGGAGE_KEYS.dispatchSpanId] || spanId;
|
|
710
|
+
const eventId = fields[BAGGAGE_KEYS.eventId];
|
|
711
|
+
if (!traceId || !spanId || !eventId) return null;
|
|
712
|
+
if (!isW3CTraceId(traceId) || !isW3CSpanId(spanId)) {
|
|
713
|
+
warnNonConformantIdsOnce(traceId, spanId);
|
|
714
|
+
}
|
|
715
|
+
const carrier = { traceId, spanId, eventId };
|
|
716
|
+
const childEventId = fields[BAGGAGE_KEYS.childEventId];
|
|
717
|
+
if (childEventId) carrier.childEventId = childEventId;
|
|
718
|
+
const name = fields[BAGGAGE_KEYS.name];
|
|
719
|
+
if (name) carrier.name = name;
|
|
720
|
+
const convoId = fields[BAGGAGE_KEYS.convoId];
|
|
721
|
+
if (convoId) carrier.convoId = convoId;
|
|
722
|
+
const userId = fields[BAGGAGE_KEYS.userId];
|
|
723
|
+
if (userId) carrier.userId = userId;
|
|
724
|
+
return carrier;
|
|
804
725
|
}
|
|
805
|
-
var
|
|
806
|
-
|
|
807
|
-
|
|
726
|
+
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.`;
|
|
727
|
+
var UNRESOLVED_CARRIER_WARNED_KEY = /* @__PURE__ */ Symbol.for("raindrop.handoff.warnedUnresolvedCarrier");
|
|
728
|
+
function warnedHolder() {
|
|
729
|
+
return globalThis;
|
|
808
730
|
}
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
}
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
731
|
+
function warnUnresolvedCarrier(headers, carrier) {
|
|
732
|
+
if (carrier) return;
|
|
733
|
+
if (!headers) return;
|
|
734
|
+
const holder = warnedHolder();
|
|
735
|
+
if (holder[UNRESOLVED_CARRIER_WARNED_KEY]) return;
|
|
736
|
+
holder[UNRESOLVED_CARRIER_WARNED_KEY] = true;
|
|
737
|
+
console.warn(UNRESOLVED_CARRIER_WARNING);
|
|
738
|
+
}
|
|
739
|
+
function safeParseStringRecord(raw) {
|
|
740
|
+
try {
|
|
741
|
+
const parsed = JSON.parse(raw);
|
|
742
|
+
if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) return {};
|
|
743
|
+
const result = {};
|
|
744
|
+
for (const [key, value] of Object.entries(parsed)) {
|
|
745
|
+
if (typeof value === "string") result[key] = value;
|
|
746
|
+
}
|
|
747
|
+
return result;
|
|
748
|
+
} catch (e) {
|
|
749
|
+
return {};
|
|
750
|
+
}
|
|
751
|
+
}
|
|
752
|
+
function runWithTracingSuppressed(fn) {
|
|
753
|
+
const hook = globalThis.RAINDROP_SUPPRESS_TRACING;
|
|
754
|
+
if (typeof hook !== "function") return fn();
|
|
755
|
+
let started = false;
|
|
756
|
+
try {
|
|
757
|
+
return hook(() => {
|
|
758
|
+
started = true;
|
|
759
|
+
return fn();
|
|
760
|
+
});
|
|
761
|
+
} catch (err) {
|
|
762
|
+
if (started) throw err;
|
|
763
|
+
return fn();
|
|
764
|
+
}
|
|
765
|
+
}
|
|
766
|
+
var DEFAULT_REQUEST_TIMEOUT_MS = 3e4;
|
|
767
|
+
var MAX_RETRY_DELAY_MS = 3e4;
|
|
768
|
+
function wait(ms) {
|
|
769
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
770
|
+
}
|
|
771
|
+
function formatEndpoint(endpoint) {
|
|
772
|
+
if (!endpoint) return void 0;
|
|
773
|
+
return endpoint.endsWith("/") ? endpoint : `${endpoint}/`;
|
|
774
|
+
}
|
|
775
|
+
function redactUrlForLog(url) {
|
|
776
|
+
try {
|
|
777
|
+
const parsed = new URL(url);
|
|
778
|
+
parsed.username = "";
|
|
779
|
+
parsed.password = "";
|
|
780
|
+
parsed.search = "";
|
|
781
|
+
parsed.hash = "";
|
|
782
|
+
return parsed.toString();
|
|
783
|
+
} catch (e) {
|
|
784
|
+
return "<unparseable-url>";
|
|
785
|
+
}
|
|
786
|
+
}
|
|
787
|
+
var RATE_LIMITED_LOG_INTERVAL_MS = 3e4;
|
|
788
|
+
var rateLimitedLogLast = /* @__PURE__ */ new Map();
|
|
789
|
+
function rateLimitedLog(key, log) {
|
|
790
|
+
const now = Date.now();
|
|
791
|
+
const last = rateLimitedLogLast.get(key);
|
|
792
|
+
if (last !== void 0 && now - last < RATE_LIMITED_LOG_INTERVAL_MS) {
|
|
793
|
+
return false;
|
|
794
|
+
}
|
|
795
|
+
rateLimitedLogLast.set(key, now);
|
|
796
|
+
log();
|
|
797
|
+
return true;
|
|
798
|
+
}
|
|
799
|
+
async function raceWithTimeout(promise, timeoutMs) {
|
|
800
|
+
let timer;
|
|
801
|
+
const settledInTime = await Promise.race([
|
|
802
|
+
promise.then(
|
|
803
|
+
() => true,
|
|
804
|
+
() => true
|
|
805
|
+
),
|
|
806
|
+
new Promise((resolve) => {
|
|
807
|
+
var _a;
|
|
808
|
+
timer = setTimeout(() => resolve(false), Math.max(0, timeoutMs));
|
|
809
|
+
(_a = timer.unref) == null ? void 0 : _a.call(timer);
|
|
810
|
+
})
|
|
811
|
+
]);
|
|
812
|
+
if (timer) clearTimeout(timer);
|
|
813
|
+
return settledInTime;
|
|
814
|
+
}
|
|
815
|
+
function parseRetryAfter(headers) {
|
|
848
816
|
var _a;
|
|
849
|
-
const
|
|
850
|
-
if (
|
|
851
|
-
const
|
|
852
|
-
|
|
853
|
-
);
|
|
854
|
-
|
|
817
|
+
const value = (_a = headers.get("Retry-After")) != null ? _a : headers.get("retry-after");
|
|
818
|
+
if (!value) return void 0;
|
|
819
|
+
const asNumber = Number(value);
|
|
820
|
+
if (value.trim() !== "" && !Number.isNaN(asNumber)) return asNumber * 1e3;
|
|
821
|
+
const asDate = new Date(value).getTime();
|
|
822
|
+
if (!Number.isNaN(asDate)) {
|
|
823
|
+
const delta = asDate - Date.now();
|
|
824
|
+
return delta > 0 ? delta : 0;
|
|
825
|
+
}
|
|
826
|
+
return void 0;
|
|
855
827
|
}
|
|
856
|
-
function
|
|
857
|
-
|
|
828
|
+
function getRetryDelayMs(attemptNumber, previousError) {
|
|
829
|
+
if (previousError && typeof previousError === "object" && previousError !== null && "retryAfterMs" in previousError) {
|
|
830
|
+
const v = previousError.retryAfterMs;
|
|
831
|
+
if (typeof v === "number") return Math.min(Math.max(0, v), MAX_RETRY_DELAY_MS);
|
|
832
|
+
}
|
|
833
|
+
if (attemptNumber <= 1) return 0;
|
|
834
|
+
const base = 500;
|
|
835
|
+
const factor = Math.pow(2, attemptNumber - 2);
|
|
836
|
+
return Math.min(base * factor, MAX_RETRY_DELAY_MS);
|
|
858
837
|
}
|
|
859
|
-
function
|
|
860
|
-
const
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
838
|
+
async function withRetry(operation, opName, opts) {
|
|
839
|
+
const prefix = opts.sdkName ? `[raindrop-ai/${opts.sdkName}]` : "[raindrop-ai/core]";
|
|
840
|
+
let lastError = void 0;
|
|
841
|
+
for (let attemptNumber = 1; attemptNumber <= opts.maxAttempts; attemptNumber++) {
|
|
842
|
+
if (attemptNumber > 1) {
|
|
843
|
+
const delay = getRetryDelayMs(attemptNumber, lastError);
|
|
844
|
+
if (opts.debug) {
|
|
845
|
+
console.warn(
|
|
846
|
+
`${prefix} ${opName} retry ${attemptNumber}/${opts.maxAttempts} in ${delay}ms`
|
|
847
|
+
);
|
|
848
|
+
}
|
|
849
|
+
if (delay > 0) await wait(delay);
|
|
850
|
+
} else if (opts.debug) {
|
|
851
|
+
console.log(`${prefix} ${opName} attempt ${attemptNumber}/${opts.maxAttempts}`);
|
|
852
|
+
}
|
|
853
|
+
try {
|
|
854
|
+
return await operation();
|
|
855
|
+
} catch (err) {
|
|
856
|
+
lastError = err;
|
|
857
|
+
if (opts.debug) {
|
|
858
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
859
|
+
console.warn(
|
|
860
|
+
`${prefix} ${opName} attempt ${attemptNumber} failed: ${msg}${attemptNumber === opts.maxAttempts ? " (no more retries)" : ""}`
|
|
861
|
+
);
|
|
862
|
+
}
|
|
863
|
+
if (lastError && typeof lastError === "object" && "retryable" in lastError && !lastError.retryable)
|
|
864
|
+
break;
|
|
865
|
+
if (attemptNumber === opts.maxAttempts) break;
|
|
866
|
+
}
|
|
867
|
+
}
|
|
868
|
+
throw lastError instanceof Error ? lastError : new Error(String(lastError));
|
|
869
869
|
}
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
}
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
];
|
|
914
|
-
var REDACT_JSON_ATTRIBUTE_KEYS = new Set(DEFAULT_REDACT_ATTRIBUTE_KEYS);
|
|
915
|
-
function getAsyncLocalStorageCtor() {
|
|
916
|
-
return globalThis.RAINDROP_ASYNC_LOCAL_STORAGE;
|
|
870
|
+
async function postJson(url, body, headers, opts) {
|
|
871
|
+
var _a;
|
|
872
|
+
const opName = `POST ${redactUrlForLog(url)}`;
|
|
873
|
+
const timeoutMs = (_a = opts.timeoutMs) != null ? _a : DEFAULT_REQUEST_TIMEOUT_MS;
|
|
874
|
+
await withRetry(
|
|
875
|
+
async () => {
|
|
876
|
+
const resp = await runWithTracingSuppressed(
|
|
877
|
+
() => fetch(url, {
|
|
878
|
+
method: "POST",
|
|
879
|
+
redirect: headers["X-Raindrop-Replay-Id"] !== void 0 ? "error" : "follow",
|
|
880
|
+
headers: {
|
|
881
|
+
"Content-Type": "application/json",
|
|
882
|
+
...headers
|
|
883
|
+
},
|
|
884
|
+
body: JSON.stringify(body),
|
|
885
|
+
signal: AbortSignal.timeout(timeoutMs)
|
|
886
|
+
})
|
|
887
|
+
);
|
|
888
|
+
if (!resp.ok) {
|
|
889
|
+
const text = await resp.text().catch(() => "");
|
|
890
|
+
const err = new Error(
|
|
891
|
+
`HTTP ${resp.status} ${resp.statusText}${text ? `: ${text}` : ""}`
|
|
892
|
+
);
|
|
893
|
+
const retryAfterMs = parseRetryAfter(resp.headers);
|
|
894
|
+
if (typeof retryAfterMs === "number") err.retryAfterMs = retryAfterMs;
|
|
895
|
+
err.retryable = resp.status === 429 || resp.status >= 500;
|
|
896
|
+
throw err;
|
|
897
|
+
}
|
|
898
|
+
},
|
|
899
|
+
opName,
|
|
900
|
+
opts
|
|
901
|
+
);
|
|
902
|
+
}
|
|
903
|
+
var DEFAULT_MAX_TEXT_FIELD_CHARS = 1e6;
|
|
904
|
+
var TRUNCATION_MARKER = "...[truncated by raindrop]";
|
|
905
|
+
var BOUNDED_CLONE_MAX_DEPTH = 12;
|
|
906
|
+
var BOUNDED_CLONE_SLACK = 256;
|
|
907
|
+
var currentDefaultMaxTextFieldChars = DEFAULT_MAX_TEXT_FIELD_CHARS;
|
|
908
|
+
function truncateToLimit(text, limit) {
|
|
909
|
+
if (limit > TRUNCATION_MARKER.length) {
|
|
910
|
+
return text.slice(0, limit - TRUNCATION_MARKER.length) + TRUNCATION_MARKER;
|
|
911
|
+
}
|
|
912
|
+
return text.slice(0, Math.max(0, limit));
|
|
917
913
|
}
|
|
918
|
-
function
|
|
919
|
-
|
|
920
|
-
|
|
914
|
+
function capText(value, limit) {
|
|
915
|
+
if (typeof value !== "string") return value;
|
|
916
|
+
const max = limit != null ? limit : currentDefaultMaxTextFieldChars;
|
|
917
|
+
if (value.length <= max) return value;
|
|
918
|
+
return truncateToLimit(value, max);
|
|
921
919
|
}
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
this._warnedNoAmbientBind = false;
|
|
933
|
-
}
|
|
934
|
-
maybeAdoptAsyncLocalStorage() {
|
|
935
|
-
if (this._adoptionChecked) return;
|
|
936
|
-
this._adoptionChecked = true;
|
|
937
|
-
const Ctor = getAsyncLocalStorageCtor();
|
|
938
|
-
if (!Ctor) return;
|
|
939
|
-
const als = new Ctor();
|
|
940
|
-
try {
|
|
941
|
-
als.run(EMPTY_STACK, () => {
|
|
942
|
-
});
|
|
943
|
-
} catch (e) {
|
|
944
|
-
return;
|
|
945
|
-
}
|
|
946
|
-
this._als = als;
|
|
947
|
-
if (typeof als.enterWith === "function") {
|
|
948
|
-
try {
|
|
949
|
-
als.enterWith(EMPTY_STACK);
|
|
950
|
-
this._enterWithUsable = true;
|
|
951
|
-
} catch (e) {
|
|
952
|
-
this._enterWithUsable = false;
|
|
920
|
+
function boundedClone(obj, charBudget) {
|
|
921
|
+
let budget = charBudget;
|
|
922
|
+
const seen = /* @__PURE__ */ new WeakSet();
|
|
923
|
+
const walk = (node, depth) => {
|
|
924
|
+
if (budget <= 0) return TRUNCATION_MARKER;
|
|
925
|
+
if (typeof node === "string") {
|
|
926
|
+
if (node.length > budget) {
|
|
927
|
+
const taken = node.slice(0, Math.max(0, budget)) + TRUNCATION_MARKER;
|
|
928
|
+
budget = 0;
|
|
929
|
+
return taken;
|
|
953
930
|
}
|
|
931
|
+
budget -= Math.max(node.length, 1);
|
|
932
|
+
return node;
|
|
954
933
|
}
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
this.maybeAdoptAsyncLocalStorage();
|
|
959
|
-
if (this._als) return (_a = this._als.getStore()) != null ? _a : this._syncStack;
|
|
960
|
-
return this._syncStack;
|
|
961
|
-
}
|
|
962
|
-
/**
|
|
963
|
-
* Persist an ambient stack mutation. Returns false when an ALS is adopted but
|
|
964
|
-
* `enterWith` is unusable (workerd): callers must NOT fall back to the
|
|
965
|
-
* process-shared sync stack, since concurrent isolates would cross-stamp.
|
|
966
|
-
*/
|
|
967
|
-
setAmbientStack(stack) {
|
|
968
|
-
if (this._als) {
|
|
969
|
-
if (!this._enterWithUsable) return false;
|
|
970
|
-
this._als.enterWith(stack);
|
|
971
|
-
return true;
|
|
972
|
-
}
|
|
973
|
-
this._syncStack = stack;
|
|
974
|
-
return true;
|
|
975
|
-
}
|
|
976
|
-
push(binding) {
|
|
977
|
-
this.maybeAdoptAsyncLocalStorage();
|
|
978
|
-
if (this._als && !this._enterWithUsable) {
|
|
979
|
-
this.warnNoAmbientBindOnce();
|
|
980
|
-
return;
|
|
934
|
+
if (node === null || typeof node === "number" || typeof node === "boolean") {
|
|
935
|
+
budget -= 8;
|
|
936
|
+
return node;
|
|
981
937
|
}
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
if (stack.length >= MAX_BINDING_STACK) {
|
|
986
|
-
stack = stack.slice(stack.length - (MAX_BINDING_STACK - 1));
|
|
987
|
-
}
|
|
938
|
+
if (typeof node !== "object") {
|
|
939
|
+
budget -= 8;
|
|
940
|
+
return node;
|
|
988
941
|
}
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
const stack = this.getStack();
|
|
994
|
-
const pruned = stack.filter((b) => b !== binding && b.isLive());
|
|
995
|
-
if (pruned.length !== stack.length) {
|
|
996
|
-
this.setAmbientStack(pruned);
|
|
942
|
+
if (seen.has(node)) return "[CIRCULAR]";
|
|
943
|
+
if (depth >= BOUNDED_CLONE_MAX_DEPTH) {
|
|
944
|
+
budget -= 16;
|
|
945
|
+
return `<max depth>`;
|
|
997
946
|
}
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
947
|
+
seen.add(node);
|
|
948
|
+
if (Array.isArray(node)) {
|
|
949
|
+
const out2 = [];
|
|
950
|
+
for (const v of node) {
|
|
951
|
+
if (budget <= 0) {
|
|
952
|
+
out2.push(TRUNCATION_MARKER);
|
|
953
|
+
break;
|
|
954
|
+
}
|
|
955
|
+
out2.push(walk(v, depth + 1));
|
|
956
|
+
}
|
|
957
|
+
return out2;
|
|
1003
958
|
}
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
return callback();
|
|
1008
|
-
} finally {
|
|
1009
|
-
this._syncStack = previous;
|
|
959
|
+
if (typeof node.toJSON === "function") {
|
|
960
|
+
budget -= 16;
|
|
961
|
+
return node;
|
|
1010
962
|
}
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
}
|
|
1021
|
-
warnNoAmbientBindOnce() {
|
|
1022
|
-
if (this._warnedNoAmbientBind) return;
|
|
1023
|
-
this._warnedNoAmbientBind = true;
|
|
1024
|
-
console.warn(this.noAmbientBindWarning);
|
|
1025
|
-
}
|
|
1026
|
-
};
|
|
1027
|
-
var NO_AMBIENT_ROUTING_BIND_WARNING = "[raindrop] This runtime's AsyncLocalStorage does not implement enterWith (e.g. Cloudflare Workers), so begin()/finish() cannot scope auto-instrumented spans to a project without cross-contaminating concurrent requests. Manual events and explicit span routing are unaffected; use asCurrent()/withSpan (run-based) to route auto-instrumented spans on this runtime.";
|
|
1028
|
-
var NO_AMBIENT_ATTRIBUTE_BIND_WARNING = "[raindrop] This runtime's AsyncLocalStorage does not implement enterWith (e.g. Cloudflare Workers), so contextual span attributes (the detached sub-agent hand-off reference) cannot be bound ambiently without cross-contaminating concurrent requests. The child's own event still reports; only the per-span reverse reference is skipped.";
|
|
1029
|
-
var ROUTING_STORAGE_KEY = /* @__PURE__ */ Symbol.for("raindrop.tracing.routingContextStorage");
|
|
1030
|
-
function routingStorage() {
|
|
1031
|
-
const holder = globalThis;
|
|
1032
|
-
let storage = holder[ROUTING_STORAGE_KEY];
|
|
1033
|
-
if (!storage) {
|
|
1034
|
-
storage = new ContextStackStorage(NO_AMBIENT_ROUTING_BIND_WARNING);
|
|
1035
|
-
holder[ROUTING_STORAGE_KEY] = storage;
|
|
1036
|
-
}
|
|
1037
|
-
return storage;
|
|
1038
|
-
}
|
|
1039
|
-
function makeBoundContext(binding, owner) {
|
|
1040
|
-
const WeakRefCtor = owner !== void 0 ? getWeakRefCtor() : void 0;
|
|
1041
|
-
const ref = WeakRefCtor && owner !== void 0 ? new WeakRefCtor(owner) : void 0;
|
|
1042
|
-
let dead = false;
|
|
1043
|
-
return {
|
|
1044
|
-
projectId: binding.projectId,
|
|
1045
|
-
authHint: binding.authHint,
|
|
1046
|
-
isLive() {
|
|
1047
|
-
if (dead) return false;
|
|
1048
|
-
return ref === void 0 || ref.deref() !== void 0;
|
|
1049
|
-
},
|
|
1050
|
-
markDead() {
|
|
1051
|
-
dead = true;
|
|
963
|
+
const out = {};
|
|
964
|
+
for (const k in node) {
|
|
965
|
+
if (!Object.prototype.hasOwnProperty.call(node, k)) continue;
|
|
966
|
+
if (budget <= 0) {
|
|
967
|
+
out["..."] = TRUNCATION_MARKER;
|
|
968
|
+
break;
|
|
969
|
+
}
|
|
970
|
+
const key = walk(k, depth + 1);
|
|
971
|
+
out[key] = walk(node[k], depth + 1);
|
|
1052
972
|
}
|
|
973
|
+
return out;
|
|
1053
974
|
};
|
|
975
|
+
return walk(obj, 0);
|
|
1054
976
|
}
|
|
1055
|
-
function
|
|
1056
|
-
const
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
} catch (e) {
|
|
977
|
+
function stringifyBounded(value, limit) {
|
|
978
|
+
const max = limit != null ? limit : currentDefaultMaxTextFieldChars;
|
|
979
|
+
if (typeof value === "string") {
|
|
980
|
+
return capText(value, max);
|
|
1060
981
|
}
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
function unbindRoutingContext(bound) {
|
|
1064
|
-
if (!bound || !isBoundContext(bound)) return;
|
|
982
|
+
const pruned = boundedClone(value, max + TRUNCATION_MARKER.length + BOUNDED_CLONE_SLACK);
|
|
983
|
+
let json;
|
|
1065
984
|
try {
|
|
1066
|
-
|
|
985
|
+
json = JSON.stringify(pruned);
|
|
1067
986
|
} catch (e) {
|
|
987
|
+
json = void 0;
|
|
1068
988
|
}
|
|
989
|
+
if (json === void 0) {
|
|
990
|
+
return capText(String(value), max);
|
|
991
|
+
}
|
|
992
|
+
return json.length <= max ? json : truncateToLimit(json, max);
|
|
1069
993
|
}
|
|
1070
|
-
function
|
|
1071
|
-
|
|
1072
|
-
return
|
|
1073
|
-
}
|
|
1074
|
-
function currentRoutingBinding() {
|
|
1075
|
-
const bound = routingStorage().current();
|
|
1076
|
-
if (!bound) return void 0;
|
|
1077
|
-
return { projectId: bound.projectId, authHint: bound.authHint };
|
|
1078
|
-
}
|
|
1079
|
-
function isBoundContext(value) {
|
|
1080
|
-
return typeof value.isLive === "function";
|
|
994
|
+
function attrString(key, value) {
|
|
995
|
+
if (value === void 0) return void 0;
|
|
996
|
+
return { key, value: { stringValue: value } };
|
|
1081
997
|
}
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
if (!storage) {
|
|
1087
|
-
storage = new ContextStackStorage(NO_AMBIENT_ATTRIBUTE_BIND_WARNING);
|
|
1088
|
-
holder[ATTRIBUTE_STORAGE_KEY] = storage;
|
|
1089
|
-
}
|
|
1090
|
-
return storage;
|
|
998
|
+
function attrInt(key, value) {
|
|
999
|
+
if (value === void 0) return void 0;
|
|
1000
|
+
if (!Number.isFinite(value)) return void 0;
|
|
1001
|
+
return { key, value: { intValue: String(Math.trunc(value)) } };
|
|
1091
1002
|
}
|
|
1092
|
-
function
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
const owned = /* @__PURE__ */ new WeakSet();
|
|
1097
|
-
let dead = false;
|
|
1098
|
-
let sawError = false;
|
|
1099
|
-
return {
|
|
1100
|
-
attributes: snapshot,
|
|
1101
|
-
sawErrorSpan: () => sawError,
|
|
1102
|
-
ownsSpan: (span) => owned.has(span),
|
|
1103
|
-
claimSpan(span) {
|
|
1104
|
-
owned.add(span);
|
|
1105
|
-
},
|
|
1106
|
-
markErrorSpanSeen() {
|
|
1107
|
-
sawError = true;
|
|
1108
|
-
},
|
|
1109
|
-
// A frame whose owner has been collected is dead even though nothing
|
|
1110
|
-
// unbound it: a run that never settles must not keep handing its reverse
|
|
1111
|
-
// reference to whatever runs next on a reused context.
|
|
1112
|
-
isLive() {
|
|
1113
|
-
if (dead) return false;
|
|
1114
|
-
return ref === void 0 || ref.deref() !== void 0;
|
|
1115
|
-
},
|
|
1116
|
-
markDead() {
|
|
1117
|
-
dead = true;
|
|
1118
|
-
}
|
|
1119
|
-
};
|
|
1003
|
+
function attrDouble(key, value) {
|
|
1004
|
+
if (value === void 0) return void 0;
|
|
1005
|
+
if (!Number.isFinite(value)) return void 0;
|
|
1006
|
+
return { key, value: { doubleValue: value } };
|
|
1120
1007
|
}
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1008
|
+
var LOCAL_DEBUGGER_ENV_VAR = "RAINDROP_LOCAL_DEBUGGER";
|
|
1009
|
+
var WORKSHOP_ENV_VAR = "RAINDROP_WORKSHOP";
|
|
1010
|
+
var DEFAULT_LOCAL_WORKSHOP_URL = "http://localhost:5899/v1/";
|
|
1011
|
+
function readEnvVar(name) {
|
|
1012
|
+
var _a;
|
|
1124
1013
|
try {
|
|
1125
|
-
|
|
1014
|
+
const env = (_a = globalThis == null ? void 0 : globalThis.process) == null ? void 0 : _a.env;
|
|
1015
|
+
if (env && typeof env[name] === "string" && env[name].length > 0) {
|
|
1016
|
+
return env[name];
|
|
1017
|
+
}
|
|
1126
1018
|
} catch (e) {
|
|
1127
|
-
return void 0;
|
|
1128
1019
|
}
|
|
1129
|
-
return
|
|
1020
|
+
return void 0;
|
|
1130
1021
|
}
|
|
1131
|
-
function
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
}
|
|
1022
|
+
function readWorkshopEnv() {
|
|
1023
|
+
const raw = readEnvVar(WORKSHOP_ENV_VAR);
|
|
1024
|
+
if (raw === void 0) return void 0;
|
|
1025
|
+
const trimmed = raw.trim();
|
|
1026
|
+
if (trimmed.length === 0) return void 0;
|
|
1027
|
+
if (/^https?:\/\//i.test(trimmed)) return { url: trimmed };
|
|
1028
|
+
if (/^(1|true|yes|on)$/i.test(trimmed)) return "enable";
|
|
1029
|
+
if (/^(0|false|no|off)$/i.test(trimmed)) return "disable";
|
|
1030
|
+
return void 0;
|
|
1137
1031
|
}
|
|
1138
|
-
function
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
frame.claimSpan(span);
|
|
1143
|
-
for (const [key, value] of Object.entries(frame.attributes)) {
|
|
1144
|
-
setAttribute(key, value);
|
|
1145
|
-
}
|
|
1146
|
-
}
|
|
1147
|
-
} catch (e) {
|
|
1032
|
+
function isLocalDevHost(hostname) {
|
|
1033
|
+
if (!hostname) return false;
|
|
1034
|
+
if (hostname === "localhost" || hostname === "127.0.0.1" || hostname === "0.0.0.0" || hostname === "::1") {
|
|
1035
|
+
return true;
|
|
1148
1036
|
}
|
|
1037
|
+
if (hostname.endsWith(".localhost")) return true;
|
|
1038
|
+
return false;
|
|
1149
1039
|
}
|
|
1150
|
-
function
|
|
1040
|
+
function readRuntimeHostname() {
|
|
1151
1041
|
try {
|
|
1152
|
-
|
|
1153
|
-
|
|
1042
|
+
const loc = globalThis == null ? void 0 : globalThis.location;
|
|
1043
|
+
if (loc && typeof loc.hostname === "string" && loc.hostname.length > 0) {
|
|
1044
|
+
return loc.hostname;
|
|
1154
1045
|
}
|
|
1155
1046
|
} catch (e) {
|
|
1156
1047
|
}
|
|
1048
|
+
return void 0;
|
|
1157
1049
|
}
|
|
1158
|
-
function
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1050
|
+
function shouldAutoEnableLocalWorkshop() {
|
|
1051
|
+
if (isLocalDevHost(readRuntimeHostname())) return true;
|
|
1052
|
+
if (readEnvVar("NODE_ENV") === "development") return true;
|
|
1053
|
+
return false;
|
|
1054
|
+
}
|
|
1055
|
+
function resolveLocalDebuggerBaseUrl(baseUrl) {
|
|
1056
|
+
var _a, _b, _c;
|
|
1057
|
+
if (baseUrl === null) return null;
|
|
1058
|
+
if (typeof baseUrl === "string" && baseUrl.length > 0) {
|
|
1059
|
+
return (_a = formatEndpoint(baseUrl)) != null ? _a : null;
|
|
1166
1060
|
}
|
|
1167
|
-
|
|
1061
|
+
const explicitUrlEnv = readEnvVar(LOCAL_DEBUGGER_ENV_VAR);
|
|
1062
|
+
if (explicitUrlEnv) return (_b = formatEndpoint(explicitUrlEnv)) != null ? _b : null;
|
|
1063
|
+
const workshopEnv = readWorkshopEnv();
|
|
1064
|
+
if (workshopEnv === "disable") return null;
|
|
1065
|
+
if (workshopEnv === "enable") return DEFAULT_LOCAL_WORKSHOP_URL;
|
|
1066
|
+
if (workshopEnv && "url" in workshopEnv) return (_c = formatEndpoint(workshopEnv.url)) != null ? _c : null;
|
|
1067
|
+
if (shouldAutoEnableLocalWorkshop()) return DEFAULT_LOCAL_WORKSHOP_URL;
|
|
1068
|
+
return null;
|
|
1168
1069
|
}
|
|
1169
|
-
function
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
1070
|
+
function localDebuggerEnabled(baseUrl) {
|
|
1071
|
+
return resolveLocalDebuggerBaseUrl(baseUrl) !== null;
|
|
1072
|
+
}
|
|
1073
|
+
var LOCAL_DEBUGGER_MIRROR_TIMEOUT_MS = 2e3;
|
|
1074
|
+
function mirrorTraceExportToLocalDebugger(body, options = {}) {
|
|
1075
|
+
var _a;
|
|
1076
|
+
const baseUrl = resolveLocalDebuggerBaseUrl(options.baseUrl);
|
|
1077
|
+
if (!baseUrl) return Promise.resolve();
|
|
1078
|
+
return postJson(`${baseUrl}traces`, body, {}, {
|
|
1079
|
+
maxAttempts: 1,
|
|
1080
|
+
debug: (_a = options.debug) != null ? _a : false,
|
|
1081
|
+
sdkName: options.sdkName,
|
|
1082
|
+
timeoutMs: LOCAL_DEBUGGER_MIRROR_TIMEOUT_MS
|
|
1083
|
+
}).catch(() => {
|
|
1084
|
+
});
|
|
1085
|
+
}
|
|
1086
|
+
function sendLocalDebuggerLiveEvent(event, options = {}) {
|
|
1087
|
+
var _a, _b;
|
|
1088
|
+
const destination = currentReplayTraceDestination();
|
|
1089
|
+
if (destination && destination.kind !== "workshop") return;
|
|
1090
|
+
const baseUrl = resolveLocalDebuggerBaseUrl(options.baseUrl);
|
|
1091
|
+
if (!baseUrl) return;
|
|
1092
|
+
void postJson(
|
|
1093
|
+
`${baseUrl}live`,
|
|
1094
|
+
{
|
|
1095
|
+
...event,
|
|
1096
|
+
type: event.type,
|
|
1097
|
+
timestamp: (_a = event.timestamp) != null ? _a : Date.now()
|
|
1098
|
+
},
|
|
1099
|
+
{},
|
|
1100
|
+
{
|
|
1101
|
+
maxAttempts: 1,
|
|
1102
|
+
debug: (_b = options.debug) != null ? _b : false,
|
|
1103
|
+
sdkName: options.sdkName
|
|
1173
1104
|
}
|
|
1174
|
-
|
|
1175
|
-
}
|
|
1105
|
+
).catch(() => {
|
|
1106
|
+
});
|
|
1176
1107
|
}
|
|
1177
|
-
|
|
1178
|
-
|
|
1108
|
+
var PROJECT_ID_HEADER = "X-Raindrop-Project-Id";
|
|
1109
|
+
function projectIdHeaders(projectId) {
|
|
1110
|
+
return projectId ? { [PROJECT_ID_HEADER]: projectId } : {};
|
|
1111
|
+
}
|
|
1112
|
+
var SHUTDOWN_DEADLINE_MS = 1e4;
|
|
1113
|
+
var POST_SHUTDOWN_TIMEOUT_MS = 5e3;
|
|
1114
|
+
var MODEL_USAGE_ATTRIBUTES = {
|
|
1115
|
+
usageSource: "raindrop.usage.source",
|
|
1116
|
+
providerName: "gen_ai.provider.name",
|
|
1117
|
+
requestModel: "gen_ai.request.model",
|
|
1118
|
+
responseModel: "gen_ai.response.model",
|
|
1119
|
+
inputTokens: "gen_ai.usage.input_tokens",
|
|
1120
|
+
outputTokens: "gen_ai.usage.output_tokens",
|
|
1121
|
+
reasoningTokens: "gen_ai.usage.reasoning_tokens",
|
|
1122
|
+
cacheReadInputTokens: "gen_ai.usage.cache_read_input_tokens",
|
|
1123
|
+
cacheWriteInputTokens: "gen_ai.usage.cache_write_input_tokens",
|
|
1124
|
+
providerReportedCost: "gen_ai.usage.provider_reported_cost",
|
|
1125
|
+
nonCachedInputTokens: "raindrop.usage.input_tokens.non_cached",
|
|
1126
|
+
nonReasoningOutputTokens: "raindrop.usage.output_tokens.non_reasoning",
|
|
1127
|
+
totalOutputTokens: "raindrop.usage.output_tokens.total",
|
|
1128
|
+
reasoningOutputTokens: "raindrop.usage.output_tokens.reasoning",
|
|
1129
|
+
cacheReadTokens: "raindrop.usage.input_tokens.cache_read",
|
|
1130
|
+
cacheWriteTokens: "raindrop.usage.input_tokens.cache_write"
|
|
1131
|
+
};
|
|
1132
|
+
var MODEL_PROVIDER_NAMES = [
|
|
1133
|
+
["google.vertex.anthropic", "google-vertex"],
|
|
1134
|
+
["google.vertex_ai", "google-vertex"],
|
|
1135
|
+
["google.vertex", "google-vertex"],
|
|
1136
|
+
["gcp.vertex_ai", "google-vertex"],
|
|
1137
|
+
["gcp.gemini", "google"],
|
|
1138
|
+
["google_vertexai", "google-vertex"],
|
|
1139
|
+
["vertex.anthropic", "google-vertex"],
|
|
1140
|
+
["amazon-bedrock", "amazon-bedrock"],
|
|
1141
|
+
["aws.bedrock", "amazon-bedrock"],
|
|
1142
|
+
["bedrock", "amazon-bedrock"],
|
|
1143
|
+
["anthropic", "anthropic"],
|
|
1144
|
+
["openai", "openai"],
|
|
1145
|
+
["google", "google"],
|
|
1146
|
+
["az.ai.openai", "azure"],
|
|
1147
|
+
["azure", "azure"],
|
|
1148
|
+
["openrouter", "openrouter"]
|
|
1149
|
+
];
|
|
1150
|
+
function canonicalModelProvider(provider) {
|
|
1151
|
+
var _a;
|
|
1152
|
+
const normalizedProvider = provider.trim().toLowerCase();
|
|
1153
|
+
if (normalizedProvider === "gateway") return "vercel";
|
|
1154
|
+
const match = MODEL_PROVIDER_NAMES.find(
|
|
1155
|
+
([family]) => normalizedProvider === family || normalizedProvider.startsWith(`${family}.`)
|
|
1156
|
+
);
|
|
1157
|
+
return (_a = match == null ? void 0 : match[1]) != null ? _a : normalizedProvider;
|
|
1158
|
+
}
|
|
1159
|
+
function tokenCount(value) {
|
|
1160
|
+
return typeof value === "number" && Number.isSafeInteger(value) && value >= 0 ? value : void 0;
|
|
1161
|
+
}
|
|
1162
|
+
function buildRawModelUsageAttributes(usage) {
|
|
1163
|
+
const providerReportedCost = typeof usage.providerReportedCost === "number" && Number.isFinite(usage.providerReportedCost) && usage.providerReportedCost >= 0 ? usage.providerReportedCost : void 0;
|
|
1164
|
+
return [
|
|
1165
|
+
attrInt(MODEL_USAGE_ATTRIBUTES.inputTokens, tokenCount(usage.inputTokens)),
|
|
1166
|
+
attrInt(MODEL_USAGE_ATTRIBUTES.outputTokens, tokenCount(usage.outputTokens)),
|
|
1167
|
+
attrInt(MODEL_USAGE_ATTRIBUTES.reasoningTokens, tokenCount(usage.reasoningTokens)),
|
|
1168
|
+
attrInt(MODEL_USAGE_ATTRIBUTES.cacheReadInputTokens, tokenCount(usage.cacheReadInputTokens)),
|
|
1169
|
+
attrInt(MODEL_USAGE_ATTRIBUTES.cacheWriteInputTokens, tokenCount(usage.cacheWriteInputTokens)),
|
|
1170
|
+
attrDouble(MODEL_USAGE_ATTRIBUTES.providerReportedCost, providerReportedCost)
|
|
1171
|
+
].filter((attribute) => attribute !== void 0);
|
|
1179
1172
|
}
|
|
1173
|
+
var STRING_ALIASES = {
|
|
1174
|
+
[MODEL_USAGE_ATTRIBUTES.requestModel]: ["ai.model.id", "ai.model"]
|
|
1175
|
+
};
|
|
1176
|
+
var NUMBER_ALIASES = {
|
|
1177
|
+
[MODEL_USAGE_ATTRIBUTES.inputTokens]: [
|
|
1178
|
+
"gen_ai.usage.prompt_tokens",
|
|
1179
|
+
"ai.usage.prompt_tokens",
|
|
1180
|
+
"ai.usage.promptTokens",
|
|
1181
|
+
"ai.usage.input_tokens",
|
|
1182
|
+
"ai.usage.inputTokens"
|
|
1183
|
+
],
|
|
1184
|
+
[MODEL_USAGE_ATTRIBUTES.outputTokens]: [
|
|
1185
|
+
"gen_ai.usage.completion_tokens",
|
|
1186
|
+
"ai.usage.completion_tokens",
|
|
1187
|
+
"ai.usage.completionTokens",
|
|
1188
|
+
"ai.usage.output_tokens",
|
|
1189
|
+
"ai.usage.outputTokens"
|
|
1190
|
+
],
|
|
1191
|
+
[MODEL_USAGE_ATTRIBUTES.reasoningTokens]: [
|
|
1192
|
+
"gen_ai.usage.reasoning.output_tokens",
|
|
1193
|
+
"ai.usage.reasoningTokens",
|
|
1194
|
+
"ai.usage.thoughts_tokens"
|
|
1195
|
+
],
|
|
1196
|
+
[MODEL_USAGE_ATTRIBUTES.cacheReadInputTokens]: [
|
|
1197
|
+
"gen_ai.usage.cache_read_tokens",
|
|
1198
|
+
"gen_ai.usage.cache_read.input_tokens",
|
|
1199
|
+
"ai.usage.cachedInputTokens",
|
|
1200
|
+
"ai.usage.cached_tokens",
|
|
1201
|
+
"ai.usage.cache_read_tokens",
|
|
1202
|
+
"ai.usage.cache_read_input_tokens",
|
|
1203
|
+
"ai.usage.cacheReadInputTokens"
|
|
1204
|
+
],
|
|
1205
|
+
[MODEL_USAGE_ATTRIBUTES.cacheWriteInputTokens]: [
|
|
1206
|
+
"gen_ai.usage.cache_creation_input_tokens",
|
|
1207
|
+
"gen_ai.usage.cache_creation.input_tokens",
|
|
1208
|
+
"ai.usage.cacheWriteInputTokens",
|
|
1209
|
+
"ai.usage.cache_creation_input_tokens",
|
|
1210
|
+
"ai.usage.cacheCreationInputTokens"
|
|
1211
|
+
]
|
|
1212
|
+
};
|
|
1213
|
+
var DEFAULT_REDACT_ATTRIBUTE_KEYS = [
|
|
1214
|
+
"ai.request.providerOptions",
|
|
1215
|
+
"ai.response.providerMetadata"
|
|
1216
|
+
];
|
|
1217
|
+
var REDACT_JSON_ATTRIBUTE_KEYS = new Set(DEFAULT_REDACT_ATTRIBUTE_KEYS);
|
|
1180
1218
|
|
|
1181
1219
|
// ../core/dist/index.node.js
|
|
1182
1220
|
var import_async_hooks = require("async_hooks");
|
|
@@ -1384,7 +1422,7 @@ function base64ToHex2(base64) {
|
|
|
1384
1422
|
// package.json
|
|
1385
1423
|
var package_default = {
|
|
1386
1424
|
name: "raindrop-ai",
|
|
1387
|
-
version: "0.7.
|
|
1425
|
+
version: "0.7.1",
|
|
1388
1426
|
main: "dist/index.js",
|
|
1389
1427
|
module: "dist/index.mjs",
|
|
1390
1428
|
types: "dist/index.d.ts",
|
|
@@ -1800,11 +1838,38 @@ function stampContextAttributes(span) {
|
|
|
1800
1838
|
}
|
|
1801
1839
|
}
|
|
1802
1840
|
var RaindropContextSpanProcessor = class {
|
|
1841
|
+
constructor(appGitSnapshot) {
|
|
1842
|
+
this.appGitSnapshot = appGitSnapshot;
|
|
1843
|
+
this.appGitAdded = /* @__PURE__ */ new WeakMap();
|
|
1844
|
+
}
|
|
1803
1845
|
onStart(span) {
|
|
1846
|
+
var _a, _b, _c, _d;
|
|
1804
1847
|
try {
|
|
1805
1848
|
stampContextAttributes(span);
|
|
1806
1849
|
rememberReplayTraceDestination(span);
|
|
1807
1850
|
const bound = currentRoutingBinding();
|
|
1851
|
+
const keys = ["raindrop.app.commit_sha", "raindrop.app.commit_dirty", "raindrop.app.branch"];
|
|
1852
|
+
const attrs = (_a = span.attributes) != null ? _a : {};
|
|
1853
|
+
const properties = {};
|
|
1854
|
+
for (const key of keys) {
|
|
1855
|
+
const existing = [key, `ai.telemetry.metadata.${key}`, `traceloop.association.properties.${key}`].find((name) => Object.prototype.hasOwnProperty.call(attrs, name));
|
|
1856
|
+
if (existing) properties[key] = attrs[existing];
|
|
1857
|
+
}
|
|
1858
|
+
const source = { ...(_d = (_c = (_b = this.appGitSnapshot) == null ? void 0 : _b.call(this, properties)) != null ? _c : bound == null ? void 0 : bound.appGit) != null ? _d : {} };
|
|
1859
|
+
if (Object.prototype.hasOwnProperty.call(properties, "raindrop.app.commit_sha") && properties["raindrop.app.commit_sha"] !== source["raindrop.app.commit_sha"]) {
|
|
1860
|
+
delete source["raindrop.app.commit_dirty"];
|
|
1861
|
+
delete source["raindrop.app.branch"];
|
|
1862
|
+
}
|
|
1863
|
+
const added = /* @__PURE__ */ new Map();
|
|
1864
|
+
for (const key of keys) {
|
|
1865
|
+
if ([key, `ai.telemetry.metadata.${key}`, `traceloop.association.properties.${key}`].some((name) => Object.prototype.hasOwnProperty.call(attrs, name))) continue;
|
|
1866
|
+
const value = source == null ? void 0 : source[key];
|
|
1867
|
+
if (typeof value === "string" || typeof value === "boolean") {
|
|
1868
|
+
span.setAttribute(key, value);
|
|
1869
|
+
added.set(key, value);
|
|
1870
|
+
}
|
|
1871
|
+
}
|
|
1872
|
+
this.appGitAdded.set(span, added);
|
|
1808
1873
|
if (!bound) return;
|
|
1809
1874
|
stampSpan(span, bound.projectId, bound.authHint);
|
|
1810
1875
|
} catch (e) {
|
|
@@ -1813,6 +1878,16 @@ var RaindropContextSpanProcessor = class {
|
|
|
1813
1878
|
onEnd(span) {
|
|
1814
1879
|
var _a;
|
|
1815
1880
|
try {
|
|
1881
|
+
if (span == null ? void 0 : span.attributes) {
|
|
1882
|
+
const attrs = span.attributes;
|
|
1883
|
+
const added = this.appGitAdded.get(span);
|
|
1884
|
+
const shaKey = "raindrop.app.commit_sha";
|
|
1885
|
+
const hasAlias = (key) => [`ai.telemetry.metadata.${key}`, `traceloop.association.properties.${key}`].some((name) => Object.prototype.hasOwnProperty.call(attrs, name));
|
|
1886
|
+
const shaChanged = (added == null ? void 0 : added.has(shaKey)) && (attrs[shaKey] !== added.get(shaKey) || hasAlias(shaKey));
|
|
1887
|
+
for (const [key, value] of added != null ? added : []) {
|
|
1888
|
+
if (attrs[key] === value && (hasAlias(key) || shaChanged && key !== shaKey)) delete attrs[key];
|
|
1889
|
+
}
|
|
1890
|
+
}
|
|
1816
1891
|
if (((_a = span == null ? void 0 : span.status) == null ? void 0 : _a.code) !== SPAN_STATUS_ERROR) return;
|
|
1817
1892
|
markErrorSpanSeen(span);
|
|
1818
1893
|
} catch (e) {
|
|
@@ -1938,6 +2013,7 @@ var DirectTraceShipper = class {
|
|
|
1938
2013
|
*/
|
|
1939
2014
|
this.hasShutdown = false;
|
|
1940
2015
|
var _a, _b, _c, _d, _e, _f;
|
|
2016
|
+
this.appGitSnapshot = opts.appGitSnapshot;
|
|
1941
2017
|
this.writeKey = opts.writeKey;
|
|
1942
2018
|
this.baseUrl = (_a = formatEndpoint2(opts.endpoint)) != null ? _a : "https://api.raindrop.ai/v1/";
|
|
1943
2019
|
this.enabled = (_b = opts.enabled) != null ? _b : true;
|
|
@@ -1952,6 +2028,14 @@ var DirectTraceShipper = class {
|
|
|
1952
2028
|
this.localDebuggerUrl = resolved;
|
|
1953
2029
|
}
|
|
1954
2030
|
}
|
|
2031
|
+
applicationGitSnapshot(properties) {
|
|
2032
|
+
var _a, _b, _c, _d;
|
|
2033
|
+
try {
|
|
2034
|
+
return (_d = (_c = (_a = this.appGitSnapshot) == null ? void 0 : _a.call(this, properties)) != null ? _c : (_b = currentRoutingBinding()) == null ? void 0 : _b.appGit) != null ? _d : {};
|
|
2035
|
+
} catch (e) {
|
|
2036
|
+
return {};
|
|
2037
|
+
}
|
|
2038
|
+
}
|
|
1955
2039
|
/**
|
|
1956
2040
|
* Build and enqueue an OTLP span for a trackTool call.
|
|
1957
2041
|
*
|
|
@@ -2026,7 +2110,10 @@ var DirectTraceShipper = class {
|
|
|
2026
2110
|
name: params.name,
|
|
2027
2111
|
startTimeUnixNano,
|
|
2028
2112
|
endTimeUnixNano,
|
|
2029
|
-
attributes
|
|
2113
|
+
attributes: withAppGitAttributes(
|
|
2114
|
+
attributes,
|
|
2115
|
+
params.appGitSnapshot !== void 0 ? params.appGitSnapshot : this.applicationGitSnapshot(params.properties)
|
|
2116
|
+
),
|
|
2030
2117
|
status
|
|
2031
2118
|
});
|
|
2032
2119
|
const replayDestination = currentReplayTraceDestination();
|
|
@@ -3647,7 +3734,7 @@ var LiveInteraction = class {
|
|
|
3647
3734
|
span.end();
|
|
3648
3735
|
}
|
|
3649
3736
|
async finish(resultEvent) {
|
|
3650
|
-
var _a, _b, _c, _d, _e, _f, _g;
|
|
3737
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _i;
|
|
3651
3738
|
unbindRoutingContext(this.boundContext);
|
|
3652
3739
|
this.boundContext = void 0;
|
|
3653
3740
|
unbindSpanAttributes(this.toolEventsFrame);
|
|
@@ -3657,10 +3744,19 @@ var LiveInteraction = class {
|
|
|
3657
3744
|
}
|
|
3658
3745
|
const eventId = resultEvent.eventId || this.context.eventId;
|
|
3659
3746
|
if (!this.usageEmitted) {
|
|
3660
|
-
(
|
|
3747
|
+
const appGitSnapshot = (_b = (_a = this.analytics) == null ? void 0 : _a.getAppGitSnapshot(resultEvent.properties, eventId)) != null ? _b : {};
|
|
3748
|
+
const usageProperties = {};
|
|
3749
|
+
for (const key of [APP_COMMIT_SHA, APP_COMMIT_DIRTY, APP_BRANCH]) {
|
|
3750
|
+
if (resultEvent.properties && Object.prototype.hasOwnProperty.call(resultEvent.properties, key)) {
|
|
3751
|
+
usageProperties[key] = resultEvent.properties[key];
|
|
3752
|
+
}
|
|
3753
|
+
}
|
|
3754
|
+
(_e = this.analytics) == null ? void 0 : _e._recordModelUsage(
|
|
3661
3755
|
eventId,
|
|
3662
|
-
(
|
|
3663
|
-
(
|
|
3756
|
+
(_c = resultEvent.model) != null ? _c : this.context.model,
|
|
3757
|
+
(_d = resultEvent.usage) != null ? _d : this.context.usage,
|
|
3758
|
+
withAppGitProperties(usageProperties, appGitSnapshot),
|
|
3759
|
+
appGitSnapshot
|
|
3664
3760
|
);
|
|
3665
3761
|
this.usageEmitted = true;
|
|
3666
3762
|
}
|
|
@@ -3671,20 +3767,20 @@ var LiveInteraction = class {
|
|
|
3671
3767
|
} catch (e) {
|
|
3672
3768
|
}
|
|
3673
3769
|
})();
|
|
3674
|
-
if ((
|
|
3770
|
+
if ((_g = (_f = this.analytics) == null ? void 0 : _f._shouldBlockFinishFlush()) != null ? _g : true) {
|
|
3675
3771
|
await spanFlush;
|
|
3676
3772
|
} else {
|
|
3677
3773
|
void spanFlush.catch(() => {
|
|
3678
3774
|
});
|
|
3679
3775
|
}
|
|
3680
3776
|
try {
|
|
3681
|
-
await ((
|
|
3777
|
+
await ((_h = this.analytics) == null ? void 0 : _h._drainInFlightPartials(eventId));
|
|
3682
3778
|
} catch (e) {
|
|
3683
3779
|
}
|
|
3684
3780
|
if (this.traceId) {
|
|
3685
3781
|
this.setProperty("trace_id", this.traceId);
|
|
3686
3782
|
}
|
|
3687
|
-
await ((
|
|
3783
|
+
await ((_i = this.analytics) == null ? void 0 : _i._trackAiPartial({
|
|
3688
3784
|
...resultEvent,
|
|
3689
3785
|
eventId,
|
|
3690
3786
|
isPending: false
|
|
@@ -4491,6 +4587,7 @@ var tracing = (analytics, apiUrl, writeKey, options, isDebug = false) => {
|
|
|
4491
4587
|
}
|
|
4492
4588
|
}
|
|
4493
4589
|
const directShipper = bypassOtelForTools ? new DirectTraceShipper({
|
|
4590
|
+
appGitSnapshot: (properties) => analytics.getAppGitSnapshot(properties),
|
|
4494
4591
|
writeKey,
|
|
4495
4592
|
endpoint: directEndpoint != null ? directEndpoint : apiUrl,
|
|
4496
4593
|
debug: isDebug,
|
|
@@ -4550,7 +4647,7 @@ var tracing = (analytics, apiUrl, writeKey, options, isDebug = false) => {
|
|
|
4550
4647
|
tracingEnabled: tracingEnabled !== false,
|
|
4551
4648
|
disableBatch: disableBatching,
|
|
4552
4649
|
processor: new CompositeSpanProcessor(
|
|
4553
|
-
[new RaindropContextSpanProcessor(), localDebuggerProcessor],
|
|
4650
|
+
[new RaindropContextSpanProcessor((properties) => analytics.getAppGitSnapshot(properties)), localDebuggerProcessor],
|
|
4554
4651
|
[]
|
|
4555
4652
|
),
|
|
4556
4653
|
instrumentations: createConfiguredInstrumentations(otherOptions)
|
|
@@ -4574,7 +4671,7 @@ var tracing = (analytics, apiUrl, writeKey, options, isDebug = false) => {
|
|
|
4574
4671
|
tracingEnabled: tracingEnabled !== false,
|
|
4575
4672
|
disableBatch: disableBatching,
|
|
4576
4673
|
processor: new CompositeSpanProcessor(
|
|
4577
|
-
[new RaindropContextSpanProcessor(), replayOnlyProcessor],
|
|
4674
|
+
[new RaindropContextSpanProcessor((properties) => analytics.getAppGitSnapshot(properties)), replayOnlyProcessor],
|
|
4578
4675
|
[]
|
|
4579
4676
|
),
|
|
4580
4677
|
instrumentations: createConfiguredInstrumentations(otherOptions)
|
|
@@ -4615,7 +4712,7 @@ var tracing = (analytics, apiUrl, writeKey, options, isDebug = false) => {
|
|
|
4615
4712
|
);
|
|
4616
4713
|
}
|
|
4617
4714
|
if (guardedExporter) {
|
|
4618
|
-
const contextProcessor = new RaindropContextSpanProcessor();
|
|
4715
|
+
const contextProcessor = new RaindropContextSpanProcessor((properties) => analytics.getAppGitSnapshot(properties));
|
|
4619
4716
|
const callerProcessor = otherOptions.processor;
|
|
4620
4717
|
const processor = new CompositeSpanProcessor(
|
|
4621
4718
|
callerProcessor ? [contextProcessor, callerProcessor] : [contextProcessor],
|
|
@@ -4678,9 +4775,9 @@ var tracing = (analytics, apiUrl, writeKey, options, isDebug = false) => {
|
|
|
4678
4775
|
traceId,
|
|
4679
4776
|
analytics,
|
|
4680
4777
|
directShipper,
|
|
4681
|
-
{ projectId, authHint }
|
|
4778
|
+
{ projectId, authHint, appGit: analytics.getAppGitSnapshot(traceContext.properties, traceContext.eventId) }
|
|
4682
4779
|
);
|
|
4683
|
-
const bound = bindRoutingContext({ projectId, authHint }, interaction);
|
|
4780
|
+
const bound = bindRoutingContext({ projectId, authHint, appGit: analytics.getAppGitSnapshot(traceContext.properties, traceContext.eventId) }, interaction);
|
|
4684
4781
|
interaction.setBoundContext(bound);
|
|
4685
4782
|
try {
|
|
4686
4783
|
analytics._trackAiPartial({
|
|
@@ -4757,7 +4854,8 @@ var tracing = (analytics, apiUrl, writeKey, options, isDebug = false) => {
|
|
|
4757
4854
|
directShipper.sendSpan({
|
|
4758
4855
|
name: "ai.model.usage",
|
|
4759
4856
|
spanKind: "llm",
|
|
4760
|
-
properties: { event_id: params.eventId },
|
|
4857
|
+
properties: { ...params.appGitProperties, event_id: params.eventId },
|
|
4858
|
+
appGitSnapshot: params.appGitSnapshot,
|
|
4761
4859
|
startTimeMs: timeMs,
|
|
4762
4860
|
endTimeMs: timeMs,
|
|
4763
4861
|
durationMs: 0,
|
|
@@ -4765,9 +4863,23 @@ var tracing = (analytics, apiUrl, writeKey, options, isDebug = false) => {
|
|
|
4765
4863
|
});
|
|
4766
4864
|
return;
|
|
4767
4865
|
}
|
|
4768
|
-
const
|
|
4769
|
-
|
|
4770
|
-
|
|
4866
|
+
const initialAttributes = {
|
|
4867
|
+
"traceloop.span.kind": "llm"
|
|
4868
|
+
};
|
|
4869
|
+
for (const [key, value] of Object.entries({
|
|
4870
|
+
...params.appGitProperties,
|
|
4871
|
+
event_id: params.eventId
|
|
4872
|
+
})) {
|
|
4873
|
+
if (value !== void 0) {
|
|
4874
|
+
initialAttributes[`traceloop.association.properties.${key}`] = stringifyBounded(value);
|
|
4875
|
+
}
|
|
4876
|
+
}
|
|
4877
|
+
for (const [key, value] of Object.entries(params.appGitSnapshot)) {
|
|
4878
|
+
if (typeof value === "string" || typeof value === "boolean") {
|
|
4879
|
+
initialAttributes[key] = value;
|
|
4880
|
+
}
|
|
4881
|
+
}
|
|
4882
|
+
const span = import_api6.trace.getTracer("traceloop.tracer").startSpan("ai.model.usage", { attributes: initialAttributes });
|
|
4771
4883
|
stampSpan(span, projectId, authHint);
|
|
4772
4884
|
for (const attribute of attributes) {
|
|
4773
4885
|
const value = attribute.value;
|
|
@@ -4888,7 +5000,7 @@ var tracing = (analytics, apiUrl, writeKey, options, isDebug = false) => {
|
|
|
4888
5000
|
allowedInstrumentationLibraries: processorOptions == null ? void 0 : processorOptions.allowedInstrumentationLibraries,
|
|
4889
5001
|
localDebuggerUrlOpt: localDebuggerUrl
|
|
4890
5002
|
});
|
|
4891
|
-
const contextProcessor = new RaindropContextSpanProcessor();
|
|
5003
|
+
const contextProcessor = new RaindropContextSpanProcessor((properties) => analytics.getAppGitSnapshot(properties));
|
|
4892
5004
|
return withV2SpanCompat(
|
|
4893
5005
|
new CompositeSpanProcessor(
|
|
4894
5006
|
[contextProcessor, productionProcessor],
|