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
|
@@ -79,1135 +79,1509 @@ function evalScopeAttributes() {
|
|
|
79
79
|
return { [EVAL_CORRELATION_ID_ATTRIBUTE]: scope.correlationId };
|
|
80
80
|
}
|
|
81
81
|
|
|
82
|
-
// ../core/dist/chunk-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
}
|
|
102
|
-
for (let i = 0; i < out.length; i++) out[i] = Math.floor(Math.random() * 256);
|
|
103
|
-
return out;
|
|
104
|
-
}
|
|
105
|
-
function randomUUID() {
|
|
106
|
-
const cryptoObj = getCrypto();
|
|
107
|
-
if (cryptoObj && typeof cryptoObj.randomUUID === "function") {
|
|
108
|
-
return cryptoObj.randomUUID();
|
|
82
|
+
// ../core/dist/chunk-WJOR6M7H.js
|
|
83
|
+
var STATE_KEY = /* @__PURE__ */ Symbol.for("raindrop.tracing.replayTraceRoutingState");
|
|
84
|
+
function state() {
|
|
85
|
+
const holder = globalThis;
|
|
86
|
+
let current = holder[STATE_KEY];
|
|
87
|
+
if (!current) {
|
|
88
|
+
let storage = null;
|
|
89
|
+
try {
|
|
90
|
+
const Ctor = globalThis.RAINDROP_ASYNC_LOCAL_STORAGE;
|
|
91
|
+
if (Ctor) storage = new Ctor();
|
|
92
|
+
} catch (e) {
|
|
93
|
+
storage = null;
|
|
94
|
+
}
|
|
95
|
+
current = {
|
|
96
|
+
storage,
|
|
97
|
+
syncDestination: void 0,
|
|
98
|
+
spanDestinations: /* @__PURE__ */ new WeakMap()
|
|
99
|
+
};
|
|
100
|
+
holder[STATE_KEY] = current;
|
|
109
101
|
}
|
|
110
|
-
|
|
111
|
-
b[6] = b[6] & 15 | 64;
|
|
112
|
-
b[8] = b[8] & 63 | 128;
|
|
113
|
-
const hex = [...b].map((x) => x.toString(16).padStart(2, "0")).join("");
|
|
114
|
-
return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`;
|
|
102
|
+
return current;
|
|
115
103
|
}
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
var AI_SDK_METADATA_PREFIX = "ai.telemetry.metadata.";
|
|
126
|
-
var DETACHED_MODE = "detached";
|
|
127
|
-
var SUBAGENT_AGENT_ROLE = "subagent";
|
|
128
|
-
var HANDOFF_TERMINAL_CANCELLED = "cancelled";
|
|
129
|
-
var TOOL_EVENTS_SUFFIX = "raindrop.toolEvents";
|
|
130
|
-
var TOOL_EVENTS_ALLOW = "allow";
|
|
131
|
-
var OPERATION_ID_ATTRIBUTE = "ai.operationId";
|
|
132
|
-
var SUBAGENT_ABORT_OPERATION_ID = "ai.subagent.failed";
|
|
133
|
-
var SUBAGENT_ABORT_SPAN_NAME = SUBAGENT_ABORT_OPERATION_ID;
|
|
134
|
-
var DEFAULT_DISPATCH_SPAN_NAME = "launch_subagent";
|
|
135
|
-
var HANDOFF_TERMINAL_PROPERTY_KEY = HANDOFF_ATTRIBUTE_SUFFIXES.terminal;
|
|
136
|
-
function defined(entries) {
|
|
137
|
-
const out = {};
|
|
138
|
-
for (const [key, value] of Object.entries(entries)) {
|
|
139
|
-
if (typeof value === "string" && value.trim().length > 0) out[key] = value;
|
|
104
|
+
function withReplayTraceDestination(destination, callback) {
|
|
105
|
+
const routing = state();
|
|
106
|
+
if (routing.storage) return routing.storage.run(destination, callback);
|
|
107
|
+
const previous = routing.syncDestination;
|
|
108
|
+
routing.syncDestination = destination;
|
|
109
|
+
try {
|
|
110
|
+
return callback();
|
|
111
|
+
} finally {
|
|
112
|
+
routing.syncDestination = previous;
|
|
140
113
|
}
|
|
141
|
-
return out;
|
|
142
|
-
}
|
|
143
|
-
function detachedDispatchMetadata(dispatch) {
|
|
144
|
-
return defined({
|
|
145
|
-
[HANDOFF_ATTRIBUTE_SUFFIXES.mode]: DETACHED_MODE,
|
|
146
|
-
[HANDOFF_ATTRIBUTE_SUFFIXES.childEventId]: dispatch.childEventId,
|
|
147
|
-
[HANDOFF_ATTRIBUTE_SUFFIXES.name]: dispatch.name
|
|
148
|
-
});
|
|
149
|
-
}
|
|
150
|
-
function detachedChildMetadata(link) {
|
|
151
|
-
return defined({
|
|
152
|
-
[HANDOFF_ATTRIBUTE_SUFFIXES.parentEventId]: link.parentEventId,
|
|
153
|
-
[HANDOFF_ATTRIBUTE_SUFFIXES.parentSpanId]: link.parentSpanId,
|
|
154
|
-
[HANDOFF_ATTRIBUTE_SUFFIXES.name]: link.name,
|
|
155
|
-
[HANDOFF_ATTRIBUTE_SUFFIXES.agentRole]: SUBAGENT_AGENT_ROLE
|
|
156
|
-
});
|
|
157
114
|
}
|
|
158
|
-
function
|
|
159
|
-
|
|
115
|
+
function currentReplayTraceDestination() {
|
|
116
|
+
var _a, _b;
|
|
117
|
+
const routing = state();
|
|
118
|
+
return (_b = (_a = routing.storage) == null ? void 0 : _a.getStore()) != null ? _b : routing.syncDestination;
|
|
160
119
|
}
|
|
161
|
-
function
|
|
162
|
-
const
|
|
163
|
-
|
|
120
|
+
function rememberReplayTraceDestination(span) {
|
|
121
|
+
const destination = currentReplayTraceDestination();
|
|
122
|
+
if (destination) state().spanDestinations.set(span, destination);
|
|
164
123
|
}
|
|
165
|
-
function
|
|
166
|
-
|
|
124
|
+
function copyReplayTraceDestination(source, target) {
|
|
125
|
+
const destination = state().spanDestinations.get(source);
|
|
126
|
+
if (destination) state().spanDestinations.set(target, destination);
|
|
167
127
|
}
|
|
168
|
-
function
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
out[key.startsWith(AI_SDK_METADATA_PREFIX) ? key : `${AI_SDK_METADATA_PREFIX}${key}`] = value;
|
|
128
|
+
function replayTraceDestinationFor(value) {
|
|
129
|
+
if (typeof value !== "object" && typeof value !== "function" || value === null) {
|
|
130
|
+
return void 0;
|
|
172
131
|
}
|
|
173
|
-
return
|
|
132
|
+
return state().spanDestinations.get(value);
|
|
174
133
|
}
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
userId: "raindrop-user-id",
|
|
181
|
-
// The dispatch span and its trace, carried as fields as well as in
|
|
182
|
-
// `traceparent`. Not redundant: OTel's HTTP instrumentations rewrite
|
|
183
|
-
// `traceparent` from whatever span is current as the request goes out, so by
|
|
184
|
-
// the time the child reads it the ids name the HTTP client span and its trace
|
|
185
|
-
// instead of the dispatch. The child would then point its reverse reference at
|
|
186
|
-
// a span the launcher's UI does not know as a dispatch. A field states which
|
|
187
|
-
// span it means rather than meaning "whoever wrote this header last".
|
|
188
|
-
dispatchSpanId: "raindrop-dispatch-span-id",
|
|
189
|
-
traceId: "raindrop-trace-id"
|
|
190
|
-
};
|
|
191
|
-
var TRACEPARENT_HEADER = "traceparent";
|
|
192
|
-
var BAGGAGE_HEADER = "baggage";
|
|
193
|
-
var W3C_TRACE_ID = /^[0-9a-f]{32}$/;
|
|
194
|
-
var W3C_SPAN_ID = /^[0-9a-f]{16}$/;
|
|
195
|
-
function isW3CTraceId(value) {
|
|
196
|
-
return value !== void 0 && W3C_TRACE_ID.test(value);
|
|
134
|
+
function recordReplayExportedSpan(destination, spanId, traceId) {
|
|
135
|
+
var _a, _b;
|
|
136
|
+
if (!destination || !spanId || !traceId) return;
|
|
137
|
+
(_a = destination.exportedSpanIds) == null ? void 0 : _a.add(spanId);
|
|
138
|
+
(_b = destination.exportedTraceIds) == null ? void 0 : _b.add(traceId);
|
|
197
139
|
}
|
|
198
|
-
function
|
|
199
|
-
return
|
|
140
|
+
function replayTraceUrl(baseUrl) {
|
|
141
|
+
return `${baseUrl.replace(/\/+$/, "")}/v1/traces`;
|
|
200
142
|
}
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
if (warnedNonConformantIds) return;
|
|
204
|
-
warnedNonConformantIds = true;
|
|
205
|
-
console.warn(
|
|
206
|
-
`[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.`
|
|
207
|
-
);
|
|
143
|
+
function getAsyncLocalStorageCtor() {
|
|
144
|
+
return globalThis.RAINDROP_ASYNC_LOCAL_STORAGE;
|
|
208
145
|
}
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
function encodeBaggage(entries) {
|
|
213
|
-
return Object.entries(entries).filter((entry) => Boolean(entry[1])).map(([key, value]) => `${key}=${encodeURIComponent(value)}`).join(",");
|
|
146
|
+
function getWeakRefCtor() {
|
|
147
|
+
const ctor = globalThis.WeakRef;
|
|
148
|
+
return typeof ctor === "function" ? ctor : void 0;
|
|
214
149
|
}
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
150
|
+
var MAX_BINDING_STACK = 128;
|
|
151
|
+
var EMPTY_STACK = [];
|
|
152
|
+
var ContextStackStorage = class {
|
|
153
|
+
/** Emitted once when this runtime cannot support an ambient push. */
|
|
154
|
+
constructor(noAmbientBindWarning) {
|
|
155
|
+
this.noAmbientBindWarning = noAmbientBindWarning;
|
|
156
|
+
this._als = null;
|
|
157
|
+
this._enterWithUsable = false;
|
|
158
|
+
this._syncStack = EMPTY_STACK;
|
|
159
|
+
this._adoptionChecked = false;
|
|
160
|
+
this._warnedNoAmbientBind = false;
|
|
161
|
+
}
|
|
162
|
+
maybeAdoptAsyncLocalStorage() {
|
|
163
|
+
if (this._adoptionChecked) return;
|
|
164
|
+
this._adoptionChecked = true;
|
|
165
|
+
const Ctor = getAsyncLocalStorageCtor();
|
|
166
|
+
if (!Ctor) return;
|
|
167
|
+
const als = new Ctor();
|
|
223
168
|
try {
|
|
224
|
-
|
|
169
|
+
als.run(EMPTY_STACK, () => {
|
|
170
|
+
});
|
|
225
171
|
} catch (e) {
|
|
226
|
-
|
|
172
|
+
return;
|
|
173
|
+
}
|
|
174
|
+
this._als = als;
|
|
175
|
+
if (typeof als.enterWith === "function") {
|
|
176
|
+
try {
|
|
177
|
+
als.enterWith(EMPTY_STACK);
|
|
178
|
+
this._enterWithUsable = true;
|
|
179
|
+
} catch (e) {
|
|
180
|
+
this._enterWithUsable = false;
|
|
181
|
+
}
|
|
227
182
|
}
|
|
228
|
-
if (key in parsed && parsed[key] !== value) throw new ConflictingCarrierError(key);
|
|
229
|
-
parsed[key] = value;
|
|
230
183
|
}
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
[BAGGAGE_KEYS.childEventId]: carrier.childEventId,
|
|
237
|
-
[BAGGAGE_KEYS.name]: carrier.name,
|
|
238
|
-
[BAGGAGE_KEYS.convoId]: carrier.convoId,
|
|
239
|
-
[BAGGAGE_KEYS.userId]: carrier.userId,
|
|
240
|
-
[BAGGAGE_KEYS.dispatchSpanId]: carrier.spanId,
|
|
241
|
-
[BAGGAGE_KEYS.traceId]: carrier.traceId
|
|
242
|
-
};
|
|
243
|
-
}
|
|
244
|
-
function toHeaders(carrier) {
|
|
245
|
-
const fields = encodeBaggage(carrierBaggage(carrier));
|
|
246
|
-
const headers = {
|
|
247
|
-
[BAGGAGE_HEADER]: fields,
|
|
248
|
-
[HANDOFF_HEADER]: fields
|
|
249
|
-
};
|
|
250
|
-
if (isW3CTraceId(carrier.traceId) && isW3CSpanId(carrier.spanId)) {
|
|
251
|
-
headers[TRACEPARENT_HEADER] = `00-${carrier.traceId}-${carrier.spanId}-01`;
|
|
184
|
+
getStack() {
|
|
185
|
+
var _a;
|
|
186
|
+
this.maybeAdoptAsyncLocalStorage();
|
|
187
|
+
if (this._als) return (_a = this._als.getStore()) != null ? _a : this._syncStack;
|
|
188
|
+
return this._syncStack;
|
|
252
189
|
}
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
// Carried here too: a LangSmith-shaped carrier is rewritten in transit
|
|
267
|
-
// exactly like the native one, and an injected `traceparent` is preferred
|
|
268
|
-
// over the dotted order on read.
|
|
269
|
-
[HANDOFF_HEADER]: encodeBaggage(carrierBaggage(carrier))
|
|
270
|
-
};
|
|
271
|
-
}
|
|
272
|
-
function isHeaderLookup(headers) {
|
|
273
|
-
return "get" in headers && typeof headers.get === "function";
|
|
274
|
-
}
|
|
275
|
-
var ConflictingCarrierError = class extends Error {
|
|
276
|
-
};
|
|
277
|
-
function readHeader(headers, name) {
|
|
278
|
-
var _a, _b, _c;
|
|
279
|
-
if (isHeaderLookup(headers)) return (_a = headers.get(name)) != null ? _a : void 0;
|
|
280
|
-
const value = (_c = headers[name]) != null ? _c : (_b = Object.entries(headers).find(([key]) => key.toLowerCase() === name)) == null ? void 0 : _b[1];
|
|
281
|
-
if (!Array.isArray(value)) return value;
|
|
282
|
-
const distinct = new Set(value);
|
|
283
|
-
if (distinct.size > 1) throw new ConflictingCarrierError(name);
|
|
284
|
-
return value[0];
|
|
285
|
-
}
|
|
286
|
-
function readTraceHeader(headers, name) {
|
|
287
|
-
const value = readHeader(headers, name);
|
|
288
|
-
if (!(value == null ? void 0 : value.includes(","))) return value;
|
|
289
|
-
const copies = value.split(",").map((copy) => copy.trim());
|
|
290
|
-
if (new Set(copies).size > 1) throw new ConflictingCarrierError(name);
|
|
291
|
-
return copies[0];
|
|
292
|
-
}
|
|
293
|
-
function fromHeaders(headers) {
|
|
294
|
-
var _a, _b;
|
|
295
|
-
let baggage;
|
|
296
|
-
let handoff;
|
|
297
|
-
let traceparent;
|
|
298
|
-
let langsmithTrace;
|
|
299
|
-
try {
|
|
300
|
-
baggage = decodeBaggage(readHeader(headers, BAGGAGE_HEADER));
|
|
301
|
-
handoff = decodeBaggage(readHeader(headers, HANDOFF_HEADER));
|
|
302
|
-
traceparent = readTraceHeader(headers, TRACEPARENT_HEADER);
|
|
303
|
-
langsmithTrace = readTraceHeader(headers, LANGSMITH_TRACE_HEADER);
|
|
304
|
-
} catch (error) {
|
|
305
|
-
if (error instanceof ConflictingCarrierError) return null;
|
|
306
|
-
throw error;
|
|
190
|
+
/**
|
|
191
|
+
* Persist an ambient stack mutation. Returns false when an ALS is adopted but
|
|
192
|
+
* `enterWith` is unusable (workerd): callers must NOT fall back to the
|
|
193
|
+
* process-shared sync stack, since concurrent isolates would cross-stamp.
|
|
194
|
+
*/
|
|
195
|
+
setAmbientStack(stack) {
|
|
196
|
+
if (this._als) {
|
|
197
|
+
if (!this._enterWithUsable) return false;
|
|
198
|
+
this._als.enterWith(stack);
|
|
199
|
+
return true;
|
|
200
|
+
}
|
|
201
|
+
this._syncStack = stack;
|
|
202
|
+
return true;
|
|
307
203
|
}
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
204
|
+
push(binding) {
|
|
205
|
+
this.maybeAdoptAsyncLocalStorage();
|
|
206
|
+
if (this._als && !this._enterWithUsable) {
|
|
207
|
+
this.warnNoAmbientBindOnce();
|
|
208
|
+
return;
|
|
209
|
+
}
|
|
210
|
+
let stack = this.getStack();
|
|
211
|
+
if (stack.length >= MAX_BINDING_STACK) {
|
|
212
|
+
stack = stack.filter((b) => b.isLive());
|
|
213
|
+
if (stack.length >= MAX_BINDING_STACK) {
|
|
214
|
+
stack = stack.slice(stack.length - (MAX_BINDING_STACK - 1));
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
this.setAmbientStack([...stack, binding]);
|
|
312
218
|
}
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
};
|
|
320
|
-
let traceId;
|
|
321
|
-
let spanId;
|
|
322
|
-
if (traceparent) {
|
|
323
|
-
const [, parsedTraceId, parsedSpanId] = traceparent.split("-");
|
|
324
|
-
if (isW3CTraceId(parsedTraceId) && isW3CSpanId(parsedSpanId)) {
|
|
325
|
-
traceId = parsedTraceId;
|
|
326
|
-
spanId = parsedSpanId;
|
|
219
|
+
remove(binding) {
|
|
220
|
+
binding.markDead();
|
|
221
|
+
const stack = this.getStack();
|
|
222
|
+
const pruned = stack.filter((b) => b !== binding && b.isLive());
|
|
223
|
+
if (pruned.length !== stack.length) {
|
|
224
|
+
this.setAmbientStack(pruned);
|
|
327
225
|
}
|
|
328
226
|
}
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
227
|
+
runWith(binding, callback) {
|
|
228
|
+
this.maybeAdoptAsyncLocalStorage();
|
|
229
|
+
if (this._als) {
|
|
230
|
+
return this._als.run([...this.getStack(), binding], callback);
|
|
231
|
+
}
|
|
232
|
+
const previous = this._syncStack;
|
|
233
|
+
this._syncStack = [...previous, binding];
|
|
234
|
+
try {
|
|
235
|
+
return callback();
|
|
236
|
+
} finally {
|
|
237
|
+
this._syncStack = previous;
|
|
238
|
+
}
|
|
333
239
|
}
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
240
|
+
current() {
|
|
241
|
+
const stack = this.getStack();
|
|
242
|
+
if (stack.length === 0) return void 0;
|
|
243
|
+
const top = stack[stack.length - 1];
|
|
244
|
+
if (top.isLive()) return top;
|
|
245
|
+
const pruned = stack.filter((b) => b.isLive());
|
|
246
|
+
this.setAmbientStack(pruned);
|
|
247
|
+
return pruned.length > 0 ? pruned[pruned.length - 1] : void 0;
|
|
340
248
|
}
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
249
|
+
warnNoAmbientBindOnce() {
|
|
250
|
+
if (this._warnedNoAmbientBind) return;
|
|
251
|
+
this._warnedNoAmbientBind = true;
|
|
252
|
+
console.warn(this.noAmbientBindWarning);
|
|
253
|
+
}
|
|
254
|
+
};
|
|
255
|
+
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.";
|
|
256
|
+
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.";
|
|
257
|
+
var ROUTING_STORAGE_KEY = /* @__PURE__ */ Symbol.for("raindrop.tracing.routingContextStorage");
|
|
258
|
+
function routingStorage() {
|
|
259
|
+
const holder = globalThis;
|
|
260
|
+
let storage = holder[ROUTING_STORAGE_KEY];
|
|
261
|
+
if (!storage) {
|
|
262
|
+
storage = new ContextStackStorage(NO_AMBIENT_ROUTING_BIND_WARNING);
|
|
263
|
+
holder[ROUTING_STORAGE_KEY] = storage;
|
|
264
|
+
}
|
|
265
|
+
return storage;
|
|
356
266
|
}
|
|
357
|
-
function
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
267
|
+
function makeBoundContext(binding, owner) {
|
|
268
|
+
const WeakRefCtor = owner !== void 0 ? getWeakRefCtor() : void 0;
|
|
269
|
+
const ref = WeakRefCtor && owner !== void 0 ? new WeakRefCtor(owner) : void 0;
|
|
270
|
+
let dead = false;
|
|
271
|
+
return {
|
|
272
|
+
projectId: binding.projectId,
|
|
273
|
+
authHint: binding.authHint,
|
|
274
|
+
...binding.appGit ? { appGit: binding.appGit } : {},
|
|
275
|
+
...binding.appGitSource ? { appGitSource: binding.appGitSource } : {},
|
|
276
|
+
isLive() {
|
|
277
|
+
if (dead) return false;
|
|
278
|
+
return ref === void 0 || ref.deref() !== void 0;
|
|
279
|
+
},
|
|
280
|
+
markDead() {
|
|
281
|
+
dead = true;
|
|
282
|
+
}
|
|
283
|
+
};
|
|
364
284
|
}
|
|
365
|
-
function
|
|
285
|
+
function bindRoutingContext(binding, owner) {
|
|
286
|
+
const bound = makeBoundContext(binding, owner);
|
|
366
287
|
try {
|
|
367
|
-
|
|
368
|
-
if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) return {};
|
|
369
|
-
const result = {};
|
|
370
|
-
for (const [key, value] of Object.entries(parsed)) {
|
|
371
|
-
if (typeof value === "string") result[key] = value;
|
|
372
|
-
}
|
|
373
|
-
return result;
|
|
288
|
+
routingStorage().push(bound);
|
|
374
289
|
} catch (e) {
|
|
375
|
-
return {};
|
|
376
290
|
}
|
|
291
|
+
return bound;
|
|
377
292
|
}
|
|
378
|
-
function
|
|
379
|
-
|
|
380
|
-
if (typeof hook !== "function") return fn();
|
|
381
|
-
let started = false;
|
|
293
|
+
function unbindRoutingContext(bound) {
|
|
294
|
+
if (!bound || !isBoundContext(bound)) return;
|
|
382
295
|
try {
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
return fn();
|
|
386
|
-
});
|
|
387
|
-
} catch (err) {
|
|
388
|
-
if (started) throw err;
|
|
389
|
-
return fn();
|
|
296
|
+
routingStorage().remove(bound);
|
|
297
|
+
} catch (e) {
|
|
390
298
|
}
|
|
391
299
|
}
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
300
|
+
function withRoutingContext(binding, callback) {
|
|
301
|
+
const bound = makeBoundContext(binding);
|
|
302
|
+
return routingStorage().runWith(bound, callback);
|
|
396
303
|
}
|
|
397
|
-
function
|
|
398
|
-
|
|
399
|
-
|
|
304
|
+
function currentRoutingBinding() {
|
|
305
|
+
const bound = routingStorage().current();
|
|
306
|
+
if (!bound) return void 0;
|
|
307
|
+
return {
|
|
308
|
+
projectId: bound.projectId,
|
|
309
|
+
authHint: bound.authHint,
|
|
310
|
+
...bound.appGit ? { appGit: bound.appGit } : {},
|
|
311
|
+
...bound.appGitSource ? { appGitSource: bound.appGitSource } : {}
|
|
312
|
+
};
|
|
400
313
|
}
|
|
401
|
-
function
|
|
402
|
-
|
|
403
|
-
const parsed = new URL(url);
|
|
404
|
-
parsed.username = "";
|
|
405
|
-
parsed.password = "";
|
|
406
|
-
parsed.search = "";
|
|
407
|
-
parsed.hash = "";
|
|
408
|
-
return parsed.toString();
|
|
409
|
-
} catch (e) {
|
|
410
|
-
return "<unparseable-url>";
|
|
411
|
-
}
|
|
314
|
+
function isBoundContext(value) {
|
|
315
|
+
return typeof value.isLive === "function";
|
|
412
316
|
}
|
|
413
|
-
var
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
317
|
+
var ATTRIBUTE_STORAGE_KEY = /* @__PURE__ */ Symbol.for("raindrop.tracing.spanAttributeStorage");
|
|
318
|
+
function attributeStorage() {
|
|
319
|
+
const holder = globalThis;
|
|
320
|
+
let storage = holder[ATTRIBUTE_STORAGE_KEY];
|
|
321
|
+
if (!storage) {
|
|
322
|
+
storage = new ContextStackStorage(NO_AMBIENT_ATTRIBUTE_BIND_WARNING);
|
|
323
|
+
holder[ATTRIBUTE_STORAGE_KEY] = storage;
|
|
420
324
|
}
|
|
421
|
-
|
|
422
|
-
log();
|
|
423
|
-
return true;
|
|
325
|
+
return storage;
|
|
424
326
|
}
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
const
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
327
|
+
function makeAttributeFrame(attributes, owner) {
|
|
328
|
+
const snapshot = { ...attributes };
|
|
329
|
+
const WeakRefCtor = owner !== void 0 ? getWeakRefCtor() : void 0;
|
|
330
|
+
const ref = WeakRefCtor && owner !== void 0 ? new WeakRefCtor(owner) : void 0;
|
|
331
|
+
const owned = /* @__PURE__ */ new WeakSet();
|
|
332
|
+
let dead = false;
|
|
333
|
+
let sawError = false;
|
|
334
|
+
return {
|
|
335
|
+
attributes: snapshot,
|
|
336
|
+
sawErrorSpan: () => sawError,
|
|
337
|
+
ownsSpan: (span) => owned.has(span),
|
|
338
|
+
claimSpan(span) {
|
|
339
|
+
owned.add(span);
|
|
340
|
+
},
|
|
341
|
+
markErrorSpanSeen() {
|
|
342
|
+
sawError = true;
|
|
343
|
+
},
|
|
344
|
+
// A frame whose owner has been collected is dead even though nothing
|
|
345
|
+
// unbound it: a run that never settles must not keep handing its reverse
|
|
346
|
+
// reference to whatever runs next on a reused context.
|
|
347
|
+
isLive() {
|
|
348
|
+
if (dead) return false;
|
|
349
|
+
return ref === void 0 || ref.deref() !== void 0;
|
|
350
|
+
},
|
|
351
|
+
markDead() {
|
|
352
|
+
dead = true;
|
|
353
|
+
}
|
|
354
|
+
};
|
|
440
355
|
}
|
|
441
|
-
function
|
|
442
|
-
|
|
443
|
-
const
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
if (!Number.isNaN(asDate)) {
|
|
449
|
-
const delta = asDate - Date.now();
|
|
450
|
-
return delta > 0 ? delta : 0;
|
|
356
|
+
function bindSpanAttributes(attributes, owner) {
|
|
357
|
+
if (Object.keys(attributes).length === 0) return void 0;
|
|
358
|
+
const frame = makeAttributeFrame(attributes, owner);
|
|
359
|
+
try {
|
|
360
|
+
attributeStorage().push(frame);
|
|
361
|
+
} catch (e) {
|
|
362
|
+
return void 0;
|
|
451
363
|
}
|
|
452
|
-
return
|
|
364
|
+
return frame;
|
|
453
365
|
}
|
|
454
|
-
function
|
|
455
|
-
if (
|
|
456
|
-
|
|
457
|
-
|
|
366
|
+
function unbindSpanAttributes(frame) {
|
|
367
|
+
if (!frame || !isAttributeFrame(frame)) return;
|
|
368
|
+
try {
|
|
369
|
+
attributeStorage().remove(frame);
|
|
370
|
+
} catch (e) {
|
|
458
371
|
}
|
|
459
|
-
if (attemptNumber <= 1) return 0;
|
|
460
|
-
const base = 500;
|
|
461
|
-
const factor = Math.pow(2, attemptNumber - 2);
|
|
462
|
-
return Math.min(base * factor, MAX_RETRY_DELAY_MS);
|
|
463
372
|
}
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
const
|
|
470
|
-
|
|
471
|
-
console.warn(
|
|
472
|
-
`${prefix} ${opName} retry ${attemptNumber}/${opts.maxAttempts} in ${delay}ms`
|
|
473
|
-
);
|
|
474
|
-
}
|
|
475
|
-
if (delay > 0) await wait(delay);
|
|
476
|
-
} else if (opts.debug) {
|
|
477
|
-
console.log(`${prefix} ${opName} attempt ${attemptNumber}/${opts.maxAttempts}`);
|
|
478
|
-
}
|
|
479
|
-
try {
|
|
480
|
-
return await operation();
|
|
481
|
-
} catch (err) {
|
|
482
|
-
lastError = err;
|
|
483
|
-
if (opts.debug) {
|
|
484
|
-
const msg = err instanceof Error ? err.message : String(err);
|
|
485
|
-
console.warn(
|
|
486
|
-
`${prefix} ${opName} attempt ${attemptNumber} failed: ${msg}${attemptNumber === opts.maxAttempts ? " (no more retries)" : ""}`
|
|
487
|
-
);
|
|
373
|
+
function applySpanAttributeFrames(span, setAttribute) {
|
|
374
|
+
try {
|
|
375
|
+
for (const frame of attributeStorage().getStack()) {
|
|
376
|
+
if (!frame.isLive()) continue;
|
|
377
|
+
frame.claimSpan(span);
|
|
378
|
+
for (const [key, value] of Object.entries(frame.attributes)) {
|
|
379
|
+
setAttribute(key, value);
|
|
488
380
|
}
|
|
489
|
-
if (lastError && typeof lastError === "object" && "retryable" in lastError && !lastError.retryable)
|
|
490
|
-
break;
|
|
491
|
-
if (attemptNumber === opts.maxAttempts) break;
|
|
492
381
|
}
|
|
382
|
+
} catch (e) {
|
|
493
383
|
}
|
|
494
|
-
throw lastError instanceof Error ? lastError : new Error(String(lastError));
|
|
495
|
-
}
|
|
496
|
-
async function postJson(url, body, headers, opts) {
|
|
497
|
-
var _a;
|
|
498
|
-
const opName = `POST ${redactUrlForLog(url)}`;
|
|
499
|
-
const timeoutMs = (_a = opts.timeoutMs) != null ? _a : DEFAULT_REQUEST_TIMEOUT_MS;
|
|
500
|
-
await withRetry(
|
|
501
|
-
async () => {
|
|
502
|
-
const resp = await runWithTracingSuppressed(
|
|
503
|
-
() => fetch(url, {
|
|
504
|
-
method: "POST",
|
|
505
|
-
redirect: headers["X-Raindrop-Replay-Id"] !== void 0 ? "error" : "follow",
|
|
506
|
-
headers: {
|
|
507
|
-
"Content-Type": "application/json",
|
|
508
|
-
...headers
|
|
509
|
-
},
|
|
510
|
-
body: JSON.stringify(body),
|
|
511
|
-
signal: AbortSignal.timeout(timeoutMs)
|
|
512
|
-
})
|
|
513
|
-
);
|
|
514
|
-
if (!resp.ok) {
|
|
515
|
-
const text = await resp.text().catch(() => "");
|
|
516
|
-
const err = new Error(
|
|
517
|
-
`HTTP ${resp.status} ${resp.statusText}${text ? `: ${text}` : ""}`
|
|
518
|
-
);
|
|
519
|
-
const retryAfterMs = parseRetryAfter(resp.headers);
|
|
520
|
-
if (typeof retryAfterMs === "number") err.retryAfterMs = retryAfterMs;
|
|
521
|
-
err.retryable = resp.status === 429 || resp.status >= 500;
|
|
522
|
-
throw err;
|
|
523
|
-
}
|
|
524
|
-
},
|
|
525
|
-
opName,
|
|
526
|
-
opts
|
|
527
|
-
);
|
|
528
384
|
}
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
if (typeof value === "number" && Number.isFinite(value) && value > 0) {
|
|
536
|
-
currentDefaultMaxTextFieldChars = Math.floor(value);
|
|
385
|
+
function claimSpanForFrames(span) {
|
|
386
|
+
try {
|
|
387
|
+
for (const frame of attributeStorage().getStack()) {
|
|
388
|
+
if (frame.isLive()) frame.claimSpan(span);
|
|
389
|
+
}
|
|
390
|
+
} catch (e) {
|
|
537
391
|
}
|
|
538
392
|
}
|
|
539
|
-
function
|
|
540
|
-
|
|
541
|
-
|
|
393
|
+
function currentSpanAttributes() {
|
|
394
|
+
const merged = {};
|
|
395
|
+
try {
|
|
396
|
+
for (const frame of attributeStorage().getStack()) {
|
|
397
|
+
if (!frame.isLive()) continue;
|
|
398
|
+
Object.assign(merged, frame.attributes);
|
|
399
|
+
}
|
|
400
|
+
} catch (e) {
|
|
542
401
|
}
|
|
543
|
-
return
|
|
402
|
+
return merged;
|
|
544
403
|
}
|
|
545
|
-
function
|
|
546
|
-
|
|
547
|
-
|
|
404
|
+
function markErrorSpanSeen(span) {
|
|
405
|
+
try {
|
|
406
|
+
for (const frame of attributeStorage().getStack()) {
|
|
407
|
+
if (frame.ownsSpan(span)) frame.markErrorSpanSeen();
|
|
408
|
+
}
|
|
409
|
+
} catch (e) {
|
|
548
410
|
}
|
|
549
|
-
return text.slice(0, Math.max(0, limit));
|
|
550
411
|
}
|
|
551
|
-
function
|
|
552
|
-
|
|
553
|
-
const max = limit != null ? limit : currentDefaultMaxTextFieldChars;
|
|
554
|
-
if (value.length <= max) return value;
|
|
555
|
-
return truncateToLimit(value, max);
|
|
412
|
+
function isAttributeFrame(value) {
|
|
413
|
+
return typeof value.isLive === "function";
|
|
556
414
|
}
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
415
|
+
var APP_COMMIT_SHA = "raindrop.app.commit_sha";
|
|
416
|
+
var APP_COMMIT_DIRTY = "raindrop.app.commit_dirty";
|
|
417
|
+
var APP_BRANCH = "raindrop.app.branch";
|
|
418
|
+
var APP_GIT_KEYS = [APP_COMMIT_SHA, APP_COMMIT_DIRTY, APP_BRANCH];
|
|
419
|
+
var own = (value, key) => Object.prototype.hasOwnProperty.call(value, key);
|
|
420
|
+
function appGitExplicitKeys(properties) {
|
|
421
|
+
const keys = /* @__PURE__ */ new Set();
|
|
422
|
+
if (!properties) return keys;
|
|
423
|
+
for (const key of APP_GIT_KEYS) {
|
|
424
|
+
if (own(properties, key)) keys.add(key);
|
|
425
|
+
}
|
|
426
|
+
return keys;
|
|
427
|
+
}
|
|
428
|
+
function mergeAppGitSnapshot(base, properties, explicitKeys = /* @__PURE__ */ new Set()) {
|
|
429
|
+
try {
|
|
430
|
+
const result = { ...base };
|
|
431
|
+
if (properties && own(properties, APP_COMMIT_SHA) && properties[APP_COMMIT_SHA] !== result[APP_COMMIT_SHA]) {
|
|
432
|
+
if (!explicitKeys.has(APP_COMMIT_DIRTY) && !own(properties, APP_COMMIT_DIRTY)) {
|
|
433
|
+
delete result[APP_COMMIT_DIRTY];
|
|
567
434
|
}
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
}
|
|
571
|
-
if (node === null || typeof node === "number" || typeof node === "boolean") {
|
|
572
|
-
budget -= 8;
|
|
573
|
-
return node;
|
|
574
|
-
}
|
|
575
|
-
if (typeof node !== "object") {
|
|
576
|
-
budget -= 8;
|
|
577
|
-
return node;
|
|
578
|
-
}
|
|
579
|
-
if (seen.has(node)) return "[CIRCULAR]";
|
|
580
|
-
if (depth >= BOUNDED_CLONE_MAX_DEPTH) {
|
|
581
|
-
budget -= 16;
|
|
582
|
-
return `<max depth>`;
|
|
583
|
-
}
|
|
584
|
-
seen.add(node);
|
|
585
|
-
if (Array.isArray(node)) {
|
|
586
|
-
const out2 = [];
|
|
587
|
-
for (const v of node) {
|
|
588
|
-
if (budget <= 0) {
|
|
589
|
-
out2.push(TRUNCATION_MARKER);
|
|
590
|
-
break;
|
|
591
|
-
}
|
|
592
|
-
out2.push(walk(v, depth + 1));
|
|
435
|
+
if (!explicitKeys.has(APP_BRANCH) && !own(properties, APP_BRANCH)) {
|
|
436
|
+
delete result[APP_BRANCH];
|
|
593
437
|
}
|
|
594
|
-
return out2;
|
|
595
438
|
}
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
return node;
|
|
599
|
-
}
|
|
600
|
-
const out = {};
|
|
601
|
-
for (const k in node) {
|
|
602
|
-
if (!Object.prototype.hasOwnProperty.call(node, k)) continue;
|
|
603
|
-
if (budget <= 0) {
|
|
604
|
-
out["..."] = TRUNCATION_MARKER;
|
|
605
|
-
break;
|
|
606
|
-
}
|
|
607
|
-
const key = walk(k, depth + 1);
|
|
608
|
-
out[key] = walk(node[k], depth + 1);
|
|
439
|
+
for (const key of APP_GIT_KEYS) {
|
|
440
|
+
if (properties && own(properties, key)) result[key] = properties[key];
|
|
609
441
|
}
|
|
610
|
-
return
|
|
611
|
-
};
|
|
612
|
-
return walk(obj, 0);
|
|
613
|
-
}
|
|
614
|
-
function stringifyBounded(value, limit) {
|
|
615
|
-
const max = limit != null ? limit : currentDefaultMaxTextFieldChars;
|
|
616
|
-
if (typeof value === "string") {
|
|
617
|
-
return capText(value, max);
|
|
618
|
-
}
|
|
619
|
-
const pruned = boundedClone(value, max + TRUNCATION_MARKER.length + BOUNDED_CLONE_SLACK);
|
|
620
|
-
let json;
|
|
621
|
-
try {
|
|
622
|
-
json = JSON.stringify(pruned);
|
|
442
|
+
return Object.freeze(result);
|
|
623
443
|
} catch (e) {
|
|
624
|
-
|
|
625
|
-
}
|
|
626
|
-
if (json === void 0) {
|
|
627
|
-
return capText(String(value), max);
|
|
444
|
+
return Object.freeze({});
|
|
628
445
|
}
|
|
629
|
-
return json.length <= max ? json : truncateToLimit(json, max);
|
|
630
446
|
}
|
|
631
|
-
function
|
|
632
|
-
if (value
|
|
633
|
-
|
|
447
|
+
function validAppCommitSha(value) {
|
|
448
|
+
if (typeof value !== "string" || value.length > 128) return void 0;
|
|
449
|
+
const cleaned = value.trim();
|
|
450
|
+
return /^(?:[a-fA-F0-9]{40}|[a-fA-F0-9]{64})$/.test(cleaned) ? cleaned.toLowerCase() : void 0;
|
|
634
451
|
}
|
|
635
|
-
function
|
|
636
|
-
if (value
|
|
637
|
-
|
|
638
|
-
return
|
|
452
|
+
function shortString(value) {
|
|
453
|
+
if (typeof value !== "string" || value.length > 1024) return void 0;
|
|
454
|
+
const cleaned = value.trim();
|
|
455
|
+
return cleaned.length > 0 ? cleaned : void 0;
|
|
639
456
|
}
|
|
640
|
-
function
|
|
641
|
-
if (value ===
|
|
642
|
-
if (
|
|
643
|
-
return
|
|
457
|
+
function flag(value) {
|
|
458
|
+
if (value === true || value === "true" || value === "1") return true;
|
|
459
|
+
if (value === false || value === "false" || value === "0") return false;
|
|
460
|
+
return void 0;
|
|
644
461
|
}
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
462
|
+
function environment() {
|
|
463
|
+
try {
|
|
464
|
+
return typeof process === "undefined" ? {} : process.env;
|
|
465
|
+
} catch (e) {
|
|
466
|
+
return {};
|
|
467
|
+
}
|
|
468
|
+
}
|
|
469
|
+
var DEPLOYMENTS = [
|
|
470
|
+
["VERCEL", "VERCEL_GIT_COMMIT_SHA", "VERCEL_GIT_COMMIT_REF"],
|
|
471
|
+
["NETLIFY", "COMMIT_REF", "BRANCH"],
|
|
472
|
+
["RAILWAY_ENVIRONMENT_NAME", "RAILWAY_GIT_COMMIT_SHA", "RAILWAY_GIT_BRANCH"],
|
|
473
|
+
["RAILWAY_ENVIRONMENT", "RAILWAY_GIT_COMMIT_SHA", "RAILWAY_GIT_BRANCH"],
|
|
474
|
+
["RENDER", "RENDER_GIT_COMMIT", "RENDER_GIT_BRANCH"],
|
|
475
|
+
["DYNO", "HEROKU_BUILD_COMMIT", ""],
|
|
476
|
+
["DYNO", "HEROKU_SLUG_COMMIT", ""],
|
|
477
|
+
["AWS_APP_ID", "AWS_COMMIT_ID", "AWS_BRANCH"],
|
|
478
|
+
["WORKERS_CI", "WORKERS_CI_COMMIT_SHA", "WORKERS_CI_BRANCH"]
|
|
479
|
+
];
|
|
480
|
+
var CI_SOURCES = [
|
|
481
|
+
["GITHUB_ACTIONS", "GITHUB_SHA", "GITHUB_REF_NAME"],
|
|
482
|
+
["GITLAB_CI", "CI_COMMIT_SHA", "CI_COMMIT_REF_NAME"],
|
|
483
|
+
["CIRCLECI", "CIRCLE_SHA1", "CIRCLE_BRANCH"]
|
|
484
|
+
];
|
|
485
|
+
function detectedSource(env, table, detectBranch) {
|
|
486
|
+
for (const row of table) {
|
|
487
|
+
const [marker, shaKey, branchKey] = row;
|
|
488
|
+
if (!marker || !shaKey || !shortString(env[marker]) || flag(env[marker]) === false) continue;
|
|
489
|
+
const commitSha = validAppCommitSha(env[shaKey]);
|
|
490
|
+
if (commitSha)
|
|
491
|
+
return {
|
|
492
|
+
commitSha,
|
|
493
|
+
...detectBranch && branchKey ? { branch: shortString(env[branchKey]) } : {}
|
|
494
|
+
};
|
|
495
|
+
}
|
|
496
|
+
return {};
|
|
497
|
+
}
|
|
498
|
+
var AppGitContextImpl = class {
|
|
499
|
+
constructor(options, runtime = {}) {
|
|
500
|
+
this.defaults = {};
|
|
501
|
+
this.explicit = {};
|
|
502
|
+
this.explicitKeys = /* @__PURE__ */ new Set();
|
|
503
|
+
this.disposed = false;
|
|
504
|
+
this.operations = /* @__PURE__ */ new Map();
|
|
505
|
+
this.operationOverflow = false;
|
|
506
|
+
this.detectBranch = false;
|
|
507
|
+
this.disabled = false;
|
|
508
|
+
var _a, _b, _c, _d, _e, _f;
|
|
651
509
|
try {
|
|
652
|
-
|
|
653
|
-
|
|
510
|
+
if (options === false) {
|
|
511
|
+
this.disabled = true;
|
|
512
|
+
return;
|
|
513
|
+
}
|
|
514
|
+
const opts = options != null ? options : {};
|
|
515
|
+
const env = (_a = runtime.env) != null ? _a : environment();
|
|
516
|
+
const detectBranch = (_c = (_b = flag(opts.detectBranch)) != null ? _b : flag(env.RAINDROP_GIT_DETECT_BRANCH)) != null ? _c : false;
|
|
517
|
+
this.detectBranch = detectBranch;
|
|
518
|
+
const collectBranch = detectBranch || runtime.captureLegacyReplayBranch === true;
|
|
519
|
+
const autoDetect = runtime.allowDiscovery === false ? false : (_e = (_d = flag(opts.autoDetect)) != null ? _d : flag(env.RAINDROP_GIT_AUTO_DETECT)) != null ? _e : true;
|
|
520
|
+
const configuredSha = opts.commitSha;
|
|
521
|
+
const explicitSha = configuredSha === void 0 ? env.RAINDROP_COMMIT_SHA : configuredSha;
|
|
522
|
+
if (explicitSha === null) this.explicit[APP_COMMIT_SHA] = null;
|
|
523
|
+
else if (typeof explicitSha === "string" && validAppCommitSha(explicitSha))
|
|
524
|
+
this.explicit[APP_COMMIT_SHA] = explicitSha;
|
|
525
|
+
const configuredDirty = opts.commitDirty;
|
|
526
|
+
const explicitDirty = configuredDirty === void 0 ? flag(env.RAINDROP_COMMIT_DIRTY) : configuredDirty;
|
|
527
|
+
if (explicitDirty === null || typeof explicitDirty === "boolean")
|
|
528
|
+
this.explicit[APP_COMMIT_DIRTY] = explicitDirty;
|
|
529
|
+
const configuredBranch = opts.branch;
|
|
530
|
+
const explicitBranch = configuredBranch === void 0 ? env.RAINDROP_BRANCH : configuredBranch;
|
|
531
|
+
if (explicitBranch === null) this.explicit[APP_BRANCH] = null;
|
|
532
|
+
else if (typeof explicitBranch === "string" && explicitBranch.length <= 1024)
|
|
533
|
+
this.explicit[APP_BRANCH] = explicitBranch;
|
|
534
|
+
this.explicitKeys = appGitExplicitKeys(this.explicit);
|
|
535
|
+
this.defaults = { ...this.explicit };
|
|
536
|
+
if (!autoDetect || explicitSha !== void 0) return;
|
|
537
|
+
const sourceDirectory = (_f = shortString(opts.sourceDirectory)) != null ? _f : shortString(env.RAINDROP_GIT_SOURCE_DIRECTORY);
|
|
538
|
+
if (runtime.allowLocalGit === false && !sourceDirectory) return;
|
|
539
|
+
const deploy = sourceDirectory ? {} : detectedSource(env, DEPLOYMENTS, collectBranch);
|
|
540
|
+
if (deploy.commitSha) {
|
|
541
|
+
this.accept(deploy);
|
|
542
|
+
return;
|
|
543
|
+
}
|
|
544
|
+
const fallback = sourceDirectory ? {} : detectedSource(env, CI_SOURCES, collectBranch);
|
|
545
|
+
if (runtime.resolveLocal && (runtime.allowLocalGit !== false || sourceDirectory)) {
|
|
546
|
+
this.cancel = runtime.resolveLocal(sourceDirectory, collectBranch, (result) => {
|
|
547
|
+
try {
|
|
548
|
+
if (!this.disposed) this.accept(result.commitSha ? result : fallback);
|
|
549
|
+
} catch (e) {
|
|
550
|
+
}
|
|
551
|
+
});
|
|
552
|
+
} else this.accept(fallback);
|
|
654
553
|
} catch (e) {
|
|
655
|
-
storage = null;
|
|
656
554
|
}
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
555
|
+
}
|
|
556
|
+
accept(result) {
|
|
557
|
+
const sha = validAppCommitSha(result.commitSha);
|
|
558
|
+
if (!sha) return;
|
|
559
|
+
this.replayBranch = shortString(result.branch);
|
|
560
|
+
this.defaults = {
|
|
561
|
+
[APP_COMMIT_SHA]: sha,
|
|
562
|
+
...typeof result.commitDirty === "boolean" ? { [APP_COMMIT_DIRTY]: result.commitDirty } : {},
|
|
563
|
+
...this.detectBranch && this.replayBranch ? { [APP_BRANCH]: this.replayBranch } : {},
|
|
564
|
+
...this.explicit
|
|
661
565
|
};
|
|
662
|
-
holder[STATE_KEY] = current;
|
|
663
566
|
}
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
} finally {
|
|
674
|
-
routing.syncDestination = previous;
|
|
567
|
+
snapshot(properties) {
|
|
568
|
+
var _a;
|
|
569
|
+
try {
|
|
570
|
+
const binding = currentRoutingBinding();
|
|
571
|
+
const base = this.disabled && (binding == null ? void 0 : binding.appGitSource) !== "replay-override" ? {} : (_a = binding == null ? void 0 : binding.appGit) != null ? _a : this.defaults;
|
|
572
|
+
return this.mergeSnapshot(base, properties);
|
|
573
|
+
} catch (e) {
|
|
574
|
+
return Object.freeze({});
|
|
575
|
+
}
|
|
675
576
|
}
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
}
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
577
|
+
/** Safe defaults when no operation/span start was observed; never infer identity. */
|
|
578
|
+
snapshotExplicit(properties, eventId) {
|
|
579
|
+
try {
|
|
580
|
+
const base = { ...this.explicit };
|
|
581
|
+
const operation = eventId ? this.operations.get(eventId) : void 0;
|
|
582
|
+
if (operation) {
|
|
583
|
+
for (const key of operation.explicitKeys) base[key] = operation.snapshot[key];
|
|
584
|
+
}
|
|
585
|
+
return this.mergeSnapshot(base, properties, new Set(Object.keys(base)));
|
|
586
|
+
} catch (e) {
|
|
587
|
+
return mergeAppGitSnapshot({}, properties);
|
|
588
|
+
}
|
|
589
|
+
}
|
|
590
|
+
/** Existing replay branch reporting stays separate from opt-in event properties. */
|
|
591
|
+
snapshotForReplay() {
|
|
592
|
+
const snapshot = this.snapshot();
|
|
593
|
+
if (this.replayBranch && !own(snapshot, APP_BRANCH) && snapshot[APP_COMMIT_SHA] === this.defaults[APP_COMMIT_SHA]) {
|
|
594
|
+
return Object.freeze({ ...snapshot, [APP_BRANCH]: this.replayBranch });
|
|
595
|
+
}
|
|
596
|
+
return snapshot;
|
|
597
|
+
}
|
|
598
|
+
/** Merge a frozen span snapshot without losing client-authored provenance. */
|
|
599
|
+
mergeSnapshot(base, properties, explicitKeys = this.explicitKeys) {
|
|
600
|
+
return mergeAppGitSnapshot(base, properties, /* @__PURE__ */ new Set([...this.explicitKeys, ...explicitKeys]));
|
|
601
|
+
}
|
|
602
|
+
/** Shippers belonging to one client share this bounded operation registry. */
|
|
603
|
+
forOperation(eventId, properties, owner) {
|
|
604
|
+
if (!eventId) return this.snapshot(properties);
|
|
605
|
+
let operation = this.operations.get(eventId);
|
|
606
|
+
if (!operation) {
|
|
607
|
+
if (this.operations.size >= 1e4) this.operationOverflow = true;
|
|
608
|
+
if (this.operationOverflow) return this.mergeSnapshot({}, properties);
|
|
609
|
+
operation = {
|
|
610
|
+
snapshot: this.snapshot(properties),
|
|
611
|
+
owners: /* @__PURE__ */ new Set(),
|
|
612
|
+
unowned: owner === void 0,
|
|
613
|
+
explicitKeys: appGitExplicitKeys(properties)
|
|
614
|
+
};
|
|
615
|
+
this.operations.set(eventId, operation);
|
|
616
|
+
} else if (properties && APP_GIT_KEYS.some((key) => own(properties, key))) {
|
|
617
|
+
const explicitKeys = /* @__PURE__ */ new Set([...this.explicitKeys, ...operation.explicitKeys]);
|
|
618
|
+
operation.snapshot = this.mergeSnapshot(operation.snapshot, properties, explicitKeys);
|
|
619
|
+
for (const key of appGitExplicitKeys(properties)) operation.explicitKeys.add(key);
|
|
620
|
+
}
|
|
621
|
+
if (!owner) operation.unowned = true;
|
|
622
|
+
if (owner) operation.owners.add(owner);
|
|
623
|
+
return operation.snapshot;
|
|
624
|
+
}
|
|
625
|
+
releaseOperation(eventId, owner) {
|
|
626
|
+
const operation = this.operations.get(eventId);
|
|
627
|
+
if (!operation) return;
|
|
628
|
+
operation.owners.delete(owner);
|
|
629
|
+
if (operation.owners.size === 0 && !operation.unowned) this.operations.delete(eventId);
|
|
630
|
+
}
|
|
631
|
+
finishOperation(eventId) {
|
|
632
|
+
this.operations.delete(eventId);
|
|
633
|
+
}
|
|
634
|
+
dispose() {
|
|
635
|
+
var _a;
|
|
636
|
+
this.disposed = true;
|
|
637
|
+
try {
|
|
638
|
+
(_a = this.cancel) == null ? void 0 : _a.call(this);
|
|
639
|
+
} catch (e) {
|
|
640
|
+
}
|
|
693
641
|
}
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
function
|
|
697
|
-
var _a, _b;
|
|
698
|
-
if (!destination || !spanId || !traceId) return;
|
|
699
|
-
(_a = destination.exportedSpanIds) == null ? void 0 : _a.add(spanId);
|
|
700
|
-
(_b = destination.exportedTraceIds) == null ? void 0 : _b.add(traceId);
|
|
701
|
-
}
|
|
702
|
-
function replayTraceUrl(baseUrl) {
|
|
703
|
-
return `${baseUrl.replace(/\/+$/, "")}/v1/traces`;
|
|
704
|
-
}
|
|
705
|
-
var LOCAL_DEBUGGER_ENV_VAR = "RAINDROP_LOCAL_DEBUGGER";
|
|
706
|
-
var WORKSHOP_ENV_VAR = "RAINDROP_WORKSHOP";
|
|
707
|
-
var DEFAULT_LOCAL_WORKSHOP_URL = "http://localhost:5899/v1/";
|
|
708
|
-
function readEnvVar(name) {
|
|
709
|
-
var _a;
|
|
642
|
+
};
|
|
643
|
+
var AppGitContext = AppGitContextImpl;
|
|
644
|
+
function withAppGitProperties(properties, snapshot) {
|
|
710
645
|
try {
|
|
711
|
-
const
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
646
|
+
const merged = { ...properties };
|
|
647
|
+
for (const key of APP_GIT_KEYS)
|
|
648
|
+
if (!own(merged, key) && own(snapshot, key)) merged[key] = snapshot[key];
|
|
649
|
+
return merged;
|
|
715
650
|
} catch (e) {
|
|
651
|
+
return properties != null ? properties : {};
|
|
716
652
|
}
|
|
717
|
-
return void 0;
|
|
718
|
-
}
|
|
719
|
-
function readWorkshopEnv() {
|
|
720
|
-
const raw = readEnvVar(WORKSHOP_ENV_VAR);
|
|
721
|
-
if (raw === void 0) return void 0;
|
|
722
|
-
const trimmed = raw.trim();
|
|
723
|
-
if (trimmed.length === 0) return void 0;
|
|
724
|
-
if (/^https?:\/\//i.test(trimmed)) return { url: trimmed };
|
|
725
|
-
if (/^(1|true|yes|on)$/i.test(trimmed)) return "enable";
|
|
726
|
-
if (/^(0|false|no|off)$/i.test(trimmed)) return "disable";
|
|
727
|
-
return void 0;
|
|
728
|
-
}
|
|
729
|
-
function isLocalDevHost(hostname) {
|
|
730
|
-
if (!hostname) return false;
|
|
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;
|
|
736
653
|
}
|
|
737
|
-
function
|
|
654
|
+
function withAppGitAttributes(attributes, snapshot) {
|
|
738
655
|
try {
|
|
739
|
-
const
|
|
740
|
-
|
|
741
|
-
|
|
656
|
+
const present = new Set(attributes.flatMap((attr) => attr ? [attr.key] : []));
|
|
657
|
+
const added = [];
|
|
658
|
+
for (const key of APP_GIT_KEYS) {
|
|
659
|
+
if (present.has(key) || present.has(`ai.telemetry.metadata.${key}`) || present.has(`traceloop.association.properties.${key}`))
|
|
660
|
+
continue;
|
|
661
|
+
const value = snapshot[key];
|
|
662
|
+
if (typeof value === "string") added.push({ key, value: { stringValue: value } });
|
|
663
|
+
else if (typeof value === "boolean") added.push({ key, value: { boolValue: value } });
|
|
742
664
|
}
|
|
665
|
+
return added.length ? [...attributes, ...added] : attributes;
|
|
743
666
|
} catch (e) {
|
|
667
|
+
return attributes;
|
|
744
668
|
}
|
|
745
|
-
return void 0;
|
|
746
669
|
}
|
|
747
|
-
function
|
|
748
|
-
if (
|
|
749
|
-
|
|
750
|
-
|
|
670
|
+
function normalizeFeatureFlags(input) {
|
|
671
|
+
if (Array.isArray(input)) {
|
|
672
|
+
return Object.fromEntries(input.map((name) => [name, "true"]));
|
|
673
|
+
}
|
|
674
|
+
return Object.fromEntries(
|
|
675
|
+
Object.entries(input).map(([k, v]) => [k, String(v)])
|
|
676
|
+
);
|
|
751
677
|
}
|
|
752
|
-
function
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
678
|
+
function getCrypto() {
|
|
679
|
+
const c = globalThis.crypto;
|
|
680
|
+
return c;
|
|
681
|
+
}
|
|
682
|
+
function randomBytes(length) {
|
|
683
|
+
const cryptoObj = getCrypto();
|
|
684
|
+
const out = new Uint8Array(length);
|
|
685
|
+
if (cryptoObj && typeof cryptoObj.getRandomValues === "function") {
|
|
686
|
+
cryptoObj.getRandomValues(out);
|
|
687
|
+
return out;
|
|
757
688
|
}
|
|
758
|
-
|
|
759
|
-
|
|
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;
|
|
689
|
+
for (let i = 0; i < out.length; i++) out[i] = Math.floor(Math.random() * 256);
|
|
690
|
+
return out;
|
|
766
691
|
}
|
|
767
|
-
function
|
|
768
|
-
|
|
692
|
+
function randomUUID() {
|
|
693
|
+
const cryptoObj = getCrypto();
|
|
694
|
+
if (cryptoObj && typeof cryptoObj.randomUUID === "function") {
|
|
695
|
+
return cryptoObj.randomUUID();
|
|
696
|
+
}
|
|
697
|
+
const b = randomBytes(16);
|
|
698
|
+
b[6] = b[6] & 15 | 64;
|
|
699
|
+
b[8] = b[8] & 63 | 128;
|
|
700
|
+
const hex = [...b].map((x) => x.toString(16).padStart(2, "0")).join("");
|
|
701
|
+
return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`;
|
|
769
702
|
}
|
|
770
|
-
var
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
703
|
+
var HANDOFF_ATTRIBUTE_SUFFIXES = {
|
|
704
|
+
mode: "raindrop.handoff.mode",
|
|
705
|
+
childEventId: "raindrop.handoff.childEventId",
|
|
706
|
+
parentEventId: "raindrop.handoff.parentEventId",
|
|
707
|
+
parentSpanId: "raindrop.handoff.parentSpanId",
|
|
708
|
+
name: "raindrop.handoff.name",
|
|
709
|
+
terminal: "raindrop.handoff.terminal",
|
|
710
|
+
agentRole: "raindrop.agent.role"
|
|
711
|
+
};
|
|
712
|
+
var AI_SDK_METADATA_PREFIX = "ai.telemetry.metadata.";
|
|
713
|
+
var DETACHED_MODE = "detached";
|
|
714
|
+
var SUBAGENT_AGENT_ROLE = "subagent";
|
|
715
|
+
var HANDOFF_TERMINAL_CANCELLED = "cancelled";
|
|
716
|
+
var TOOL_EVENTS_SUFFIX = "raindrop.toolEvents";
|
|
717
|
+
var TOOL_EVENTS_ALLOW = "allow";
|
|
718
|
+
var OPERATION_ID_ATTRIBUTE = "ai.operationId";
|
|
719
|
+
var SUBAGENT_ABORT_OPERATION_ID = "ai.subagent.failed";
|
|
720
|
+
var SUBAGENT_ABORT_SPAN_NAME = SUBAGENT_ABORT_OPERATION_ID;
|
|
721
|
+
var DEFAULT_DISPATCH_SPAN_NAME = "launch_subagent";
|
|
722
|
+
var HANDOFF_TERMINAL_PROPERTY_KEY = HANDOFF_ATTRIBUTE_SUFFIXES.terminal;
|
|
723
|
+
function defined(entries) {
|
|
724
|
+
const out = {};
|
|
725
|
+
for (const [key, value] of Object.entries(entries)) {
|
|
726
|
+
if (typeof value === "string" && value.trim().length > 0) out[key] = value;
|
|
727
|
+
}
|
|
728
|
+
return out;
|
|
782
729
|
}
|
|
783
|
-
function
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
return postJson(`${baseUrl}events/track_partial`, event, headers, {
|
|
789
|
-
maxAttempts: 1,
|
|
790
|
-
debug: (_a = options.debug) != null ? _a : false,
|
|
791
|
-
sdkName: options.sdkName,
|
|
792
|
-
timeoutMs: LOCAL_DEBUGGER_MIRROR_TIMEOUT_MS
|
|
793
|
-
}).catch(() => {
|
|
730
|
+
function detachedDispatchMetadata(dispatch) {
|
|
731
|
+
return defined({
|
|
732
|
+
[HANDOFF_ATTRIBUTE_SUFFIXES.mode]: DETACHED_MODE,
|
|
733
|
+
[HANDOFF_ATTRIBUTE_SUFFIXES.childEventId]: dispatch.childEventId,
|
|
734
|
+
[HANDOFF_ATTRIBUTE_SUFFIXES.name]: dispatch.name
|
|
794
735
|
});
|
|
795
736
|
}
|
|
796
|
-
function
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
void postJson(
|
|
803
|
-
`${baseUrl}live`,
|
|
804
|
-
{
|
|
805
|
-
...event,
|
|
806
|
-
type: event.type,
|
|
807
|
-
timestamp: (_a = event.timestamp) != null ? _a : Date.now()
|
|
808
|
-
},
|
|
809
|
-
{},
|
|
810
|
-
{
|
|
811
|
-
maxAttempts: 1,
|
|
812
|
-
debug: (_b = options.debug) != null ? _b : false,
|
|
813
|
-
sdkName: options.sdkName
|
|
814
|
-
}
|
|
815
|
-
).catch(() => {
|
|
737
|
+
function detachedChildMetadata(link) {
|
|
738
|
+
return defined({
|
|
739
|
+
[HANDOFF_ATTRIBUTE_SUFFIXES.parentEventId]: link.parentEventId,
|
|
740
|
+
[HANDOFF_ATTRIBUTE_SUFFIXES.parentSpanId]: link.parentSpanId,
|
|
741
|
+
[HANDOFF_ATTRIBUTE_SUFFIXES.name]: link.name,
|
|
742
|
+
[HANDOFF_ATTRIBUTE_SUFFIXES.agentRole]: SUBAGENT_AGENT_ROLE
|
|
816
743
|
});
|
|
817
744
|
}
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
function isValidProjectIdSlug(value) {
|
|
821
|
-
return PROJECT_ID_SLUG_PATTERN.test(value);
|
|
822
|
-
}
|
|
823
|
-
function normalizeProjectId(raw, opts) {
|
|
824
|
-
if (typeof raw !== "string") return void 0;
|
|
825
|
-
const trimmed = raw.trim();
|
|
826
|
-
if (!trimmed) return void 0;
|
|
827
|
-
if (!isValidProjectIdSlug(trimmed) && opts.debug) {
|
|
828
|
-
console.warn(
|
|
829
|
-
`${opts.prefix} projectId "${trimmed}" does not match slug ${PROJECT_ID_SLUG_PATTERN.source}; sending anyway \u2014 backend may reject with HTTP 400`
|
|
830
|
-
);
|
|
831
|
-
}
|
|
832
|
-
return trimmed;
|
|
833
|
-
}
|
|
834
|
-
function projectIdHeaders(projectId) {
|
|
835
|
-
return projectId ? { [PROJECT_ID_HEADER]: projectId } : {};
|
|
745
|
+
function cancelledTerminalMetadata() {
|
|
746
|
+
return { [HANDOFF_ATTRIBUTE_SUFFIXES.terminal]: HANDOFF_TERMINAL_CANCELLED };
|
|
836
747
|
}
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
usageSource: "raindrop.usage.source",
|
|
841
|
-
providerName: "gen_ai.provider.name",
|
|
842
|
-
requestModel: "gen_ai.request.model",
|
|
843
|
-
responseModel: "gen_ai.response.model",
|
|
844
|
-
inputTokens: "gen_ai.usage.input_tokens",
|
|
845
|
-
outputTokens: "gen_ai.usage.output_tokens",
|
|
846
|
-
reasoningTokens: "gen_ai.usage.reasoning_tokens",
|
|
847
|
-
cacheReadInputTokens: "gen_ai.usage.cache_read_input_tokens",
|
|
848
|
-
cacheWriteInputTokens: "gen_ai.usage.cache_write_input_tokens",
|
|
849
|
-
providerReportedCost: "gen_ai.usage.provider_reported_cost",
|
|
850
|
-
nonCachedInputTokens: "raindrop.usage.input_tokens.non_cached",
|
|
851
|
-
nonReasoningOutputTokens: "raindrop.usage.output_tokens.non_reasoning",
|
|
852
|
-
totalOutputTokens: "raindrop.usage.output_tokens.total",
|
|
853
|
-
reasoningOutputTokens: "raindrop.usage.output_tokens.reasoning",
|
|
854
|
-
cacheReadTokens: "raindrop.usage.input_tokens.cache_read",
|
|
855
|
-
cacheWriteTokens: "raindrop.usage.input_tokens.cache_write"
|
|
856
|
-
};
|
|
857
|
-
var MODEL_PROVIDER_NAMES = [
|
|
858
|
-
["google.vertex.anthropic", "google-vertex"],
|
|
859
|
-
["google.vertex_ai", "google-vertex"],
|
|
860
|
-
["google.vertex", "google-vertex"],
|
|
861
|
-
["gcp.vertex_ai", "google-vertex"],
|
|
862
|
-
["gcp.gemini", "google"],
|
|
863
|
-
["google_vertexai", "google-vertex"],
|
|
864
|
-
["vertex.anthropic", "google-vertex"],
|
|
865
|
-
["amazon-bedrock", "amazon-bedrock"],
|
|
866
|
-
["aws.bedrock", "amazon-bedrock"],
|
|
867
|
-
["bedrock", "amazon-bedrock"],
|
|
868
|
-
["anthropic", "anthropic"],
|
|
869
|
-
["openai", "openai"],
|
|
870
|
-
["google", "google"],
|
|
871
|
-
["az.ai.openai", "azure"],
|
|
872
|
-
["azure", "azure"],
|
|
873
|
-
["openrouter", "openrouter"]
|
|
874
|
-
];
|
|
875
|
-
function canonicalModelProvider(provider) {
|
|
876
|
-
var _a;
|
|
877
|
-
const normalizedProvider = provider.trim().toLowerCase();
|
|
878
|
-
if (normalizedProvider === "gateway") return "vercel";
|
|
879
|
-
const match = MODEL_PROVIDER_NAMES.find(
|
|
880
|
-
([family]) => normalizedProvider === family || normalizedProvider.startsWith(`${family}.`)
|
|
881
|
-
);
|
|
882
|
-
return (_a = match == null ? void 0 : match[1]) != null ? _a : normalizedProvider;
|
|
748
|
+
function cancelledTerminalAttributes() {
|
|
749
|
+
const bare = cancelledTerminalMetadata();
|
|
750
|
+
return { ...bare, ...withMetadataPrefix(bare) };
|
|
883
751
|
}
|
|
884
|
-
function
|
|
885
|
-
return
|
|
752
|
+
function toolEventsAllowMetadata() {
|
|
753
|
+
return { [TOOL_EVENTS_SUFFIX]: TOOL_EVENTS_ALLOW };
|
|
886
754
|
}
|
|
887
|
-
function
|
|
888
|
-
const
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
attrInt(MODEL_USAGE_ATTRIBUTES.cacheReadInputTokens, tokenCount(usage.cacheReadInputTokens)),
|
|
894
|
-
attrInt(MODEL_USAGE_ATTRIBUTES.cacheWriteInputTokens, tokenCount(usage.cacheWriteInputTokens)),
|
|
895
|
-
attrDouble(MODEL_USAGE_ATTRIBUTES.providerReportedCost, providerReportedCost)
|
|
896
|
-
].filter((attribute) => attribute !== void 0);
|
|
755
|
+
function withMetadataPrefix(metadata) {
|
|
756
|
+
const out = {};
|
|
757
|
+
for (const [key, value] of Object.entries(metadata)) {
|
|
758
|
+
out[key.startsWith(AI_SDK_METADATA_PREFIX) ? key : `${AI_SDK_METADATA_PREFIX}${key}`] = value;
|
|
759
|
+
}
|
|
760
|
+
return out;
|
|
897
761
|
}
|
|
898
|
-
var
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
"ai.usage.output_tokens",
|
|
914
|
-
"ai.usage.outputTokens"
|
|
915
|
-
],
|
|
916
|
-
[MODEL_USAGE_ATTRIBUTES.reasoningTokens]: [
|
|
917
|
-
"gen_ai.usage.reasoning.output_tokens",
|
|
918
|
-
"ai.usage.reasoningTokens",
|
|
919
|
-
"ai.usage.thoughts_tokens"
|
|
920
|
-
],
|
|
921
|
-
[MODEL_USAGE_ATTRIBUTES.cacheReadInputTokens]: [
|
|
922
|
-
"gen_ai.usage.cache_read_tokens",
|
|
923
|
-
"gen_ai.usage.cache_read.input_tokens",
|
|
924
|
-
"ai.usage.cachedInputTokens",
|
|
925
|
-
"ai.usage.cached_tokens",
|
|
926
|
-
"ai.usage.cache_read_tokens",
|
|
927
|
-
"ai.usage.cache_read_input_tokens",
|
|
928
|
-
"ai.usage.cacheReadInputTokens"
|
|
929
|
-
],
|
|
930
|
-
[MODEL_USAGE_ATTRIBUTES.cacheWriteInputTokens]: [
|
|
931
|
-
"gen_ai.usage.cache_creation_input_tokens",
|
|
932
|
-
"gen_ai.usage.cache_creation.input_tokens",
|
|
933
|
-
"ai.usage.cacheWriteInputTokens",
|
|
934
|
-
"ai.usage.cache_creation_input_tokens",
|
|
935
|
-
"ai.usage.cacheCreationInputTokens"
|
|
936
|
-
]
|
|
762
|
+
var BAGGAGE_KEYS = {
|
|
763
|
+
eventId: "raindrop-event-id",
|
|
764
|
+
childEventId: "raindrop-child-event-id",
|
|
765
|
+
name: "raindrop-handoff-name",
|
|
766
|
+
convoId: "raindrop-convo-id",
|
|
767
|
+
userId: "raindrop-user-id",
|
|
768
|
+
// The dispatch span and its trace, carried as fields as well as in
|
|
769
|
+
// `traceparent`. Not redundant: OTel's HTTP instrumentations rewrite
|
|
770
|
+
// `traceparent` from whatever span is current as the request goes out, so by
|
|
771
|
+
// the time the child reads it the ids name the HTTP client span and its trace
|
|
772
|
+
// instead of the dispatch. The child would then point its reverse reference at
|
|
773
|
+
// a span the launcher's UI does not know as a dispatch. A field states which
|
|
774
|
+
// span it means rather than meaning "whoever wrote this header last".
|
|
775
|
+
dispatchSpanId: "raindrop-dispatch-span-id",
|
|
776
|
+
traceId: "raindrop-trace-id"
|
|
937
777
|
};
|
|
938
|
-
var
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
]
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
return globalThis.RAINDROP_ASYNC_LOCAL_STORAGE;
|
|
778
|
+
var TRACEPARENT_HEADER = "traceparent";
|
|
779
|
+
var BAGGAGE_HEADER = "baggage";
|
|
780
|
+
var W3C_TRACE_ID = /^[0-9a-f]{32}$/;
|
|
781
|
+
var W3C_SPAN_ID = /^[0-9a-f]{16}$/;
|
|
782
|
+
function isW3CTraceId(value) {
|
|
783
|
+
return value !== void 0 && W3C_TRACE_ID.test(value);
|
|
945
784
|
}
|
|
946
|
-
function
|
|
947
|
-
|
|
948
|
-
return typeof ctor === "function" ? ctor : void 0;
|
|
785
|
+
function isW3CSpanId(value) {
|
|
786
|
+
return value !== void 0 && W3C_SPAN_ID.test(value);
|
|
949
787
|
}
|
|
950
|
-
var
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
788
|
+
var warnedNonConformantIds = false;
|
|
789
|
+
function warnNonConformantIdsOnce(traceId, spanId) {
|
|
790
|
+
if (warnedNonConformantIds) return;
|
|
791
|
+
warnedNonConformantIds = true;
|
|
792
|
+
console.warn(
|
|
793
|
+
`[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.`
|
|
794
|
+
);
|
|
795
|
+
}
|
|
796
|
+
var HANDOFF_HEADER = "x-raindrop-handoff";
|
|
797
|
+
var LANGSMITH_TRACE_HEADER = "langsmith-trace";
|
|
798
|
+
var LANGSMITH_METADATA_BAGGAGE_KEY = "langsmith-metadata";
|
|
799
|
+
function encodeBaggage(entries) {
|
|
800
|
+
return Object.entries(entries).filter((entry) => Boolean(entry[1])).map(([key, value]) => `${key}=${encodeURIComponent(value)}`).join(",");
|
|
801
|
+
}
|
|
802
|
+
function decodeBaggage(header) {
|
|
803
|
+
if (!header) return {};
|
|
804
|
+
const parsed = {};
|
|
805
|
+
for (const part of header.split(",")) {
|
|
806
|
+
const [rawKey, ...rest] = part.split("=");
|
|
807
|
+
if (!rawKey || rest.length === 0) continue;
|
|
808
|
+
const key = rawKey.trim();
|
|
809
|
+
let value;
|
|
968
810
|
try {
|
|
969
|
-
|
|
970
|
-
});
|
|
811
|
+
value = decodeURIComponent(rest.join("=").trim());
|
|
971
812
|
} catch (e) {
|
|
972
|
-
|
|
973
|
-
}
|
|
974
|
-
this._als = als;
|
|
975
|
-
if (typeof als.enterWith === "function") {
|
|
976
|
-
try {
|
|
977
|
-
als.enterWith(EMPTY_STACK);
|
|
978
|
-
this._enterWithUsable = true;
|
|
979
|
-
} catch (e) {
|
|
980
|
-
this._enterWithUsable = false;
|
|
981
|
-
}
|
|
813
|
+
value = rest.join("=").trim();
|
|
982
814
|
}
|
|
815
|
+
if (key in parsed && parsed[key] !== value) throw new ConflictingCarrierError(key);
|
|
816
|
+
parsed[key] = value;
|
|
983
817
|
}
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
818
|
+
return parsed;
|
|
819
|
+
}
|
|
820
|
+
function carrierBaggage(carrier) {
|
|
821
|
+
return {
|
|
822
|
+
[BAGGAGE_KEYS.eventId]: carrier.eventId,
|
|
823
|
+
[BAGGAGE_KEYS.childEventId]: carrier.childEventId,
|
|
824
|
+
[BAGGAGE_KEYS.name]: carrier.name,
|
|
825
|
+
[BAGGAGE_KEYS.convoId]: carrier.convoId,
|
|
826
|
+
[BAGGAGE_KEYS.userId]: carrier.userId,
|
|
827
|
+
[BAGGAGE_KEYS.dispatchSpanId]: carrier.spanId,
|
|
828
|
+
[BAGGAGE_KEYS.traceId]: carrier.traceId
|
|
829
|
+
};
|
|
830
|
+
}
|
|
831
|
+
function toHeaders(carrier) {
|
|
832
|
+
const fields = encodeBaggage(carrierBaggage(carrier));
|
|
833
|
+
const headers = {
|
|
834
|
+
[BAGGAGE_HEADER]: fields,
|
|
835
|
+
[HANDOFF_HEADER]: fields
|
|
836
|
+
};
|
|
837
|
+
if (isW3CTraceId(carrier.traceId) && isW3CSpanId(carrier.spanId)) {
|
|
838
|
+
headers[TRACEPARENT_HEADER] = `00-${carrier.traceId}-${carrier.spanId}-01`;
|
|
989
839
|
}
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
840
|
+
return headers;
|
|
841
|
+
}
|
|
842
|
+
function langsmithStamp() {
|
|
843
|
+
return (/* @__PURE__ */ new Date()).toISOString().replace(/[-:]/g, "").replace(/\.\d+Z$/, "000000");
|
|
844
|
+
}
|
|
845
|
+
function toLangSmithHeaders(carrier) {
|
|
846
|
+
const stamp = langsmithStamp();
|
|
847
|
+
const dottedOrder = `${stamp}Z${carrier.traceId}.${stamp}Z${carrier.spanId}`;
|
|
848
|
+
return {
|
|
849
|
+
[LANGSMITH_TRACE_HEADER]: dottedOrder,
|
|
850
|
+
[BAGGAGE_HEADER]: encodeBaggage({
|
|
851
|
+
[LANGSMITH_METADATA_BAGGAGE_KEY]: JSON.stringify(carrierBaggage(carrier))
|
|
852
|
+
}),
|
|
853
|
+
// Carried here too: a LangSmith-shaped carrier is rewritten in transit
|
|
854
|
+
// exactly like the native one, and an injected `traceparent` is preferred
|
|
855
|
+
// over the dotted order on read.
|
|
856
|
+
[HANDOFF_HEADER]: encodeBaggage(carrierBaggage(carrier))
|
|
857
|
+
};
|
|
858
|
+
}
|
|
859
|
+
function isHeaderLookup(headers) {
|
|
860
|
+
return "get" in headers && typeof headers.get === "function";
|
|
861
|
+
}
|
|
862
|
+
var ConflictingCarrierError = class extends Error {
|
|
863
|
+
};
|
|
864
|
+
function readHeader(headers, name) {
|
|
865
|
+
var _a, _b, _c;
|
|
866
|
+
if (isHeaderLookup(headers)) return (_a = headers.get(name)) != null ? _a : void 0;
|
|
867
|
+
const value = (_c = headers[name]) != null ? _c : (_b = Object.entries(headers).find(([key]) => key.toLowerCase() === name)) == null ? void 0 : _b[1];
|
|
868
|
+
if (!Array.isArray(value)) return value;
|
|
869
|
+
const distinct = new Set(value);
|
|
870
|
+
if (distinct.size > 1) throw new ConflictingCarrierError(name);
|
|
871
|
+
return value[0];
|
|
872
|
+
}
|
|
873
|
+
function readTraceHeader(headers, name) {
|
|
874
|
+
const value = readHeader(headers, name);
|
|
875
|
+
if (!(value == null ? void 0 : value.includes(","))) return value;
|
|
876
|
+
const copies = value.split(",").map((copy) => copy.trim());
|
|
877
|
+
if (new Set(copies).size > 1) throw new ConflictingCarrierError(name);
|
|
878
|
+
return copies[0];
|
|
879
|
+
}
|
|
880
|
+
function fromHeaders(headers) {
|
|
881
|
+
var _a, _b;
|
|
882
|
+
let baggage;
|
|
883
|
+
let handoff;
|
|
884
|
+
let traceparent;
|
|
885
|
+
let langsmithTrace;
|
|
886
|
+
try {
|
|
887
|
+
baggage = decodeBaggage(readHeader(headers, BAGGAGE_HEADER));
|
|
888
|
+
handoff = decodeBaggage(readHeader(headers, HANDOFF_HEADER));
|
|
889
|
+
traceparent = readTraceHeader(headers, TRACEPARENT_HEADER);
|
|
890
|
+
langsmithTrace = readTraceHeader(headers, LANGSMITH_TRACE_HEADER);
|
|
891
|
+
} catch (error) {
|
|
892
|
+
if (error instanceof ConflictingCarrierError) return null;
|
|
893
|
+
throw error;
|
|
894
|
+
}
|
|
895
|
+
const langsmithMetadata = baggage[LANGSMITH_METADATA_BAGGAGE_KEY];
|
|
896
|
+
const nested = langsmithMetadata ? safeParseStringRecord(langsmithMetadata) : {};
|
|
897
|
+
for (const [key, value] of Object.entries(nested)) {
|
|
898
|
+
if (key in baggage && baggage[key] !== value) return null;
|
|
899
|
+
}
|
|
900
|
+
const fields = {
|
|
901
|
+
...baggage,
|
|
902
|
+
...nested,
|
|
903
|
+
// Last, so it wins: the standard headers may have been rewritten in transit
|
|
904
|
+
// by a propagator, this one is only ever written by us.
|
|
905
|
+
...handoff
|
|
906
|
+
};
|
|
907
|
+
let traceId;
|
|
908
|
+
let spanId;
|
|
909
|
+
if (traceparent) {
|
|
910
|
+
const [, parsedTraceId, parsedSpanId] = traceparent.split("-");
|
|
911
|
+
if (isW3CTraceId(parsedTraceId) && isW3CSpanId(parsedSpanId)) {
|
|
912
|
+
traceId = parsedTraceId;
|
|
913
|
+
spanId = parsedSpanId;
|
|
914
|
+
}
|
|
915
|
+
}
|
|
916
|
+
if (!traceId && !spanId && langsmithTrace) {
|
|
917
|
+
const segments = langsmithTrace.split(".");
|
|
918
|
+
traceId = (_a = segments[0]) == null ? void 0 : _a.split("Z").pop();
|
|
919
|
+
spanId = (_b = segments[segments.length - 1]) == null ? void 0 : _b.split("Z").pop();
|
|
920
|
+
}
|
|
921
|
+
traceId = fields[BAGGAGE_KEYS.traceId] || traceId;
|
|
922
|
+
spanId = fields[BAGGAGE_KEYS.dispatchSpanId] || spanId;
|
|
923
|
+
const eventId = fields[BAGGAGE_KEYS.eventId];
|
|
924
|
+
if (!traceId || !spanId || !eventId) return null;
|
|
925
|
+
if (!isW3CTraceId(traceId) || !isW3CSpanId(spanId)) {
|
|
926
|
+
warnNonConformantIdsOnce(traceId, spanId);
|
|
927
|
+
}
|
|
928
|
+
const carrier = { traceId, spanId, eventId };
|
|
929
|
+
const childEventId = fields[BAGGAGE_KEYS.childEventId];
|
|
930
|
+
if (childEventId) carrier.childEventId = childEventId;
|
|
931
|
+
const name = fields[BAGGAGE_KEYS.name];
|
|
932
|
+
if (name) carrier.name = name;
|
|
933
|
+
const convoId = fields[BAGGAGE_KEYS.convoId];
|
|
934
|
+
if (convoId) carrier.convoId = convoId;
|
|
935
|
+
const userId = fields[BAGGAGE_KEYS.userId];
|
|
936
|
+
if (userId) carrier.userId = userId;
|
|
937
|
+
return carrier;
|
|
938
|
+
}
|
|
939
|
+
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.`;
|
|
940
|
+
var UNRESOLVED_CARRIER_WARNED_KEY = /* @__PURE__ */ Symbol.for("raindrop.handoff.warnedUnresolvedCarrier");
|
|
941
|
+
function warnedHolder() {
|
|
942
|
+
return globalThis;
|
|
943
|
+
}
|
|
944
|
+
function warnUnresolvedCarrier(headers, carrier) {
|
|
945
|
+
if (carrier) return;
|
|
946
|
+
if (!headers) return;
|
|
947
|
+
const holder = warnedHolder();
|
|
948
|
+
if (holder[UNRESOLVED_CARRIER_WARNED_KEY]) return;
|
|
949
|
+
holder[UNRESOLVED_CARRIER_WARNED_KEY] = true;
|
|
950
|
+
console.warn(UNRESOLVED_CARRIER_WARNING);
|
|
951
|
+
}
|
|
952
|
+
function safeParseStringRecord(raw) {
|
|
953
|
+
try {
|
|
954
|
+
const parsed = JSON.parse(raw);
|
|
955
|
+
if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) return {};
|
|
956
|
+
const result = {};
|
|
957
|
+
for (const [key, value] of Object.entries(parsed)) {
|
|
958
|
+
if (typeof value === "string") result[key] = value;
|
|
959
|
+
}
|
|
960
|
+
return result;
|
|
961
|
+
} catch (e) {
|
|
962
|
+
return {};
|
|
963
|
+
}
|
|
964
|
+
}
|
|
965
|
+
function runWithTracingSuppressed(fn) {
|
|
966
|
+
const hook = globalThis.RAINDROP_SUPPRESS_TRACING;
|
|
967
|
+
if (typeof hook !== "function") return fn();
|
|
968
|
+
let started = false;
|
|
969
|
+
try {
|
|
970
|
+
return hook(() => {
|
|
971
|
+
started = true;
|
|
972
|
+
return fn();
|
|
973
|
+
});
|
|
974
|
+
} catch (err) {
|
|
975
|
+
if (started) throw err;
|
|
976
|
+
return fn();
|
|
977
|
+
}
|
|
978
|
+
}
|
|
979
|
+
var DEFAULT_REQUEST_TIMEOUT_MS = 3e4;
|
|
980
|
+
var MAX_RETRY_DELAY_MS = 3e4;
|
|
981
|
+
function wait(ms) {
|
|
982
|
+
return new Promise((resolve2) => setTimeout(resolve2, ms));
|
|
983
|
+
}
|
|
984
|
+
function formatEndpoint(endpoint) {
|
|
985
|
+
if (!endpoint) return void 0;
|
|
986
|
+
return endpoint.endsWith("/") ? endpoint : `${endpoint}/`;
|
|
987
|
+
}
|
|
988
|
+
function redactUrlForLog(url) {
|
|
989
|
+
try {
|
|
990
|
+
const parsed = new URL(url);
|
|
991
|
+
parsed.username = "";
|
|
992
|
+
parsed.password = "";
|
|
993
|
+
parsed.search = "";
|
|
994
|
+
parsed.hash = "";
|
|
995
|
+
return parsed.toString();
|
|
996
|
+
} catch (e) {
|
|
997
|
+
return "<unparseable-url>";
|
|
998
|
+
}
|
|
999
|
+
}
|
|
1000
|
+
var RATE_LIMITED_LOG_INTERVAL_MS = 3e4;
|
|
1001
|
+
var rateLimitedLogLast = /* @__PURE__ */ new Map();
|
|
1002
|
+
function rateLimitedLog(key, log) {
|
|
1003
|
+
const now = Date.now();
|
|
1004
|
+
const last = rateLimitedLogLast.get(key);
|
|
1005
|
+
if (last !== void 0 && now - last < RATE_LIMITED_LOG_INTERVAL_MS) {
|
|
1006
|
+
return false;
|
|
1007
|
+
}
|
|
1008
|
+
rateLimitedLogLast.set(key, now);
|
|
1009
|
+
log();
|
|
1010
|
+
return true;
|
|
1011
|
+
}
|
|
1012
|
+
async function raceWithTimeout(promise, timeoutMs) {
|
|
1013
|
+
let timer;
|
|
1014
|
+
const settledInTime = await Promise.race([
|
|
1015
|
+
promise.then(
|
|
1016
|
+
() => true,
|
|
1017
|
+
() => true
|
|
1018
|
+
),
|
|
1019
|
+
new Promise((resolve2) => {
|
|
1020
|
+
var _a;
|
|
1021
|
+
timer = setTimeout(() => resolve2(false), Math.max(0, timeoutMs));
|
|
1022
|
+
(_a = timer.unref) == null ? void 0 : _a.call(timer);
|
|
1023
|
+
})
|
|
1024
|
+
]);
|
|
1025
|
+
if (timer) clearTimeout(timer);
|
|
1026
|
+
return settledInTime;
|
|
1027
|
+
}
|
|
1028
|
+
function parseRetryAfter(headers) {
|
|
1029
|
+
var _a;
|
|
1030
|
+
const value = (_a = headers.get("Retry-After")) != null ? _a : headers.get("retry-after");
|
|
1031
|
+
if (!value) return void 0;
|
|
1032
|
+
const asNumber = Number(value);
|
|
1033
|
+
if (value.trim() !== "" && !Number.isNaN(asNumber)) return asNumber * 1e3;
|
|
1034
|
+
const asDate = new Date(value).getTime();
|
|
1035
|
+
if (!Number.isNaN(asDate)) {
|
|
1036
|
+
const delta = asDate - Date.now();
|
|
1037
|
+
return delta > 0 ? delta : 0;
|
|
1038
|
+
}
|
|
1039
|
+
return void 0;
|
|
1040
|
+
}
|
|
1041
|
+
function getRetryDelayMs(attemptNumber, previousError) {
|
|
1042
|
+
if (previousError && typeof previousError === "object" && previousError !== null && "retryAfterMs" in previousError) {
|
|
1043
|
+
const v = previousError.retryAfterMs;
|
|
1044
|
+
if (typeof v === "number") return Math.min(Math.max(0, v), MAX_RETRY_DELAY_MS);
|
|
1045
|
+
}
|
|
1046
|
+
if (attemptNumber <= 1) return 0;
|
|
1047
|
+
const base = 500;
|
|
1048
|
+
const factor = Math.pow(2, attemptNumber - 2);
|
|
1049
|
+
return Math.min(base * factor, MAX_RETRY_DELAY_MS);
|
|
1050
|
+
}
|
|
1051
|
+
async function withRetry(operation, opName, opts) {
|
|
1052
|
+
const prefix = opts.sdkName ? `[raindrop-ai/${opts.sdkName}]` : "[raindrop-ai/core]";
|
|
1053
|
+
let lastError = void 0;
|
|
1054
|
+
for (let attemptNumber = 1; attemptNumber <= opts.maxAttempts; attemptNumber++) {
|
|
1055
|
+
if (attemptNumber > 1) {
|
|
1056
|
+
const delay = getRetryDelayMs(attemptNumber, lastError);
|
|
1057
|
+
if (opts.debug) {
|
|
1058
|
+
console.warn(
|
|
1059
|
+
`${prefix} ${opName} retry ${attemptNumber}/${opts.maxAttempts} in ${delay}ms`
|
|
1060
|
+
);
|
|
1061
|
+
}
|
|
1062
|
+
if (delay > 0) await wait(delay);
|
|
1063
|
+
} else if (opts.debug) {
|
|
1064
|
+
console.log(`${prefix} ${opName} attempt ${attemptNumber}/${opts.maxAttempts}`);
|
|
1065
|
+
}
|
|
1066
|
+
try {
|
|
1067
|
+
return await operation();
|
|
1068
|
+
} catch (err) {
|
|
1069
|
+
lastError = err;
|
|
1070
|
+
if (opts.debug) {
|
|
1071
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
1072
|
+
console.warn(
|
|
1073
|
+
`${prefix} ${opName} attempt ${attemptNumber} failed: ${msg}${attemptNumber === opts.maxAttempts ? " (no more retries)" : ""}`
|
|
1074
|
+
);
|
|
1075
|
+
}
|
|
1076
|
+
if (lastError && typeof lastError === "object" && "retryable" in lastError && !lastError.retryable)
|
|
1077
|
+
break;
|
|
1078
|
+
if (attemptNumber === opts.maxAttempts) break;
|
|
1079
|
+
}
|
|
1080
|
+
}
|
|
1081
|
+
throw lastError instanceof Error ? lastError : new Error(String(lastError));
|
|
1082
|
+
}
|
|
1083
|
+
async function postJson(url, body, headers, opts) {
|
|
1084
|
+
var _a;
|
|
1085
|
+
const opName = `POST ${redactUrlForLog(url)}`;
|
|
1086
|
+
const timeoutMs = (_a = opts.timeoutMs) != null ? _a : DEFAULT_REQUEST_TIMEOUT_MS;
|
|
1087
|
+
await withRetry(
|
|
1088
|
+
async () => {
|
|
1089
|
+
const resp = await runWithTracingSuppressed(
|
|
1090
|
+
() => fetch(url, {
|
|
1091
|
+
method: "POST",
|
|
1092
|
+
redirect: headers["X-Raindrop-Replay-Id"] !== void 0 ? "error" : "follow",
|
|
1093
|
+
headers: {
|
|
1094
|
+
"Content-Type": "application/json",
|
|
1095
|
+
...headers
|
|
1096
|
+
},
|
|
1097
|
+
body: JSON.stringify(body),
|
|
1098
|
+
signal: AbortSignal.timeout(timeoutMs)
|
|
1099
|
+
})
|
|
1100
|
+
);
|
|
1101
|
+
if (!resp.ok) {
|
|
1102
|
+
const text = await resp.text().catch(() => "");
|
|
1103
|
+
const err = new Error(
|
|
1104
|
+
`HTTP ${resp.status} ${resp.statusText}${text ? `: ${text}` : ""}`
|
|
1105
|
+
);
|
|
1106
|
+
const retryAfterMs = parseRetryAfter(resp.headers);
|
|
1107
|
+
if (typeof retryAfterMs === "number") err.retryAfterMs = retryAfterMs;
|
|
1108
|
+
err.retryable = resp.status === 429 || resp.status >= 500;
|
|
1109
|
+
throw err;
|
|
1110
|
+
}
|
|
1111
|
+
},
|
|
1112
|
+
opName,
|
|
1113
|
+
opts
|
|
1114
|
+
);
|
|
1115
|
+
}
|
|
1116
|
+
var DEFAULT_MAX_TEXT_FIELD_CHARS = 1e6;
|
|
1117
|
+
var TRUNCATION_MARKER = "...[truncated by raindrop]";
|
|
1118
|
+
var BOUNDED_CLONE_MAX_DEPTH = 12;
|
|
1119
|
+
var BOUNDED_CLONE_SLACK = 256;
|
|
1120
|
+
var currentDefaultMaxTextFieldChars = DEFAULT_MAX_TEXT_FIELD_CHARS;
|
|
1121
|
+
function setDefaultMaxTextFieldChars(value) {
|
|
1122
|
+
if (typeof value === "number" && Number.isFinite(value) && value > 0) {
|
|
1123
|
+
currentDefaultMaxTextFieldChars = Math.floor(value);
|
|
1124
|
+
}
|
|
1125
|
+
}
|
|
1126
|
+
function resolveMaxTextFieldChars(value) {
|
|
1127
|
+
if (typeof value === "number" && Number.isFinite(value) && value > 0) {
|
|
1128
|
+
return Math.floor(value);
|
|
1129
|
+
}
|
|
1130
|
+
return currentDefaultMaxTextFieldChars;
|
|
1131
|
+
}
|
|
1132
|
+
function truncateToLimit(text, limit) {
|
|
1133
|
+
if (limit > TRUNCATION_MARKER.length) {
|
|
1134
|
+
return text.slice(0, limit - TRUNCATION_MARKER.length) + TRUNCATION_MARKER;
|
|
1135
|
+
}
|
|
1136
|
+
return text.slice(0, Math.max(0, limit));
|
|
1137
|
+
}
|
|
1138
|
+
function capText(value, limit) {
|
|
1139
|
+
if (typeof value !== "string") return value;
|
|
1140
|
+
const max = limit != null ? limit : currentDefaultMaxTextFieldChars;
|
|
1141
|
+
if (value.length <= max) return value;
|
|
1142
|
+
return truncateToLimit(value, max);
|
|
1143
|
+
}
|
|
1144
|
+
function boundedClone(obj, charBudget) {
|
|
1145
|
+
let budget = charBudget;
|
|
1146
|
+
const seen = /* @__PURE__ */ new WeakSet();
|
|
1147
|
+
const walk = (node, depth) => {
|
|
1148
|
+
if (budget <= 0) return TRUNCATION_MARKER;
|
|
1149
|
+
if (typeof node === "string") {
|
|
1150
|
+
if (node.length > budget) {
|
|
1151
|
+
const taken = node.slice(0, Math.max(0, budget)) + TRUNCATION_MARKER;
|
|
1152
|
+
budget = 0;
|
|
1153
|
+
return taken;
|
|
1154
|
+
}
|
|
1155
|
+
budget -= Math.max(node.length, 1);
|
|
1156
|
+
return node;
|
|
1000
1157
|
}
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
push(binding) {
|
|
1005
|
-
this.maybeAdoptAsyncLocalStorage();
|
|
1006
|
-
if (this._als && !this._enterWithUsable) {
|
|
1007
|
-
this.warnNoAmbientBindOnce();
|
|
1008
|
-
return;
|
|
1158
|
+
if (node === null || typeof node === "number" || typeof node === "boolean") {
|
|
1159
|
+
budget -= 8;
|
|
1160
|
+
return node;
|
|
1009
1161
|
}
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
if (stack.length >= MAX_BINDING_STACK) {
|
|
1014
|
-
stack = stack.slice(stack.length - (MAX_BINDING_STACK - 1));
|
|
1015
|
-
}
|
|
1162
|
+
if (typeof node !== "object") {
|
|
1163
|
+
budget -= 8;
|
|
1164
|
+
return node;
|
|
1016
1165
|
}
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
const stack = this.getStack();
|
|
1022
|
-
const pruned = stack.filter((b) => b !== binding && b.isLive());
|
|
1023
|
-
if (pruned.length !== stack.length) {
|
|
1024
|
-
this.setAmbientStack(pruned);
|
|
1166
|
+
if (seen.has(node)) return "[CIRCULAR]";
|
|
1167
|
+
if (depth >= BOUNDED_CLONE_MAX_DEPTH) {
|
|
1168
|
+
budget -= 16;
|
|
1169
|
+
return `<max depth>`;
|
|
1025
1170
|
}
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1171
|
+
seen.add(node);
|
|
1172
|
+
if (Array.isArray(node)) {
|
|
1173
|
+
const out2 = [];
|
|
1174
|
+
for (const v of node) {
|
|
1175
|
+
if (budget <= 0) {
|
|
1176
|
+
out2.push(TRUNCATION_MARKER);
|
|
1177
|
+
break;
|
|
1178
|
+
}
|
|
1179
|
+
out2.push(walk(v, depth + 1));
|
|
1180
|
+
}
|
|
1181
|
+
return out2;
|
|
1031
1182
|
}
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
return callback();
|
|
1036
|
-
} finally {
|
|
1037
|
-
this._syncStack = previous;
|
|
1183
|
+
if (typeof node.toJSON === "function") {
|
|
1184
|
+
budget -= 16;
|
|
1185
|
+
return node;
|
|
1038
1186
|
}
|
|
1187
|
+
const out = {};
|
|
1188
|
+
for (const k in node) {
|
|
1189
|
+
if (!Object.prototype.hasOwnProperty.call(node, k)) continue;
|
|
1190
|
+
if (budget <= 0) {
|
|
1191
|
+
out["..."] = TRUNCATION_MARKER;
|
|
1192
|
+
break;
|
|
1193
|
+
}
|
|
1194
|
+
const key = walk(k, depth + 1);
|
|
1195
|
+
out[key] = walk(node[k], depth + 1);
|
|
1196
|
+
}
|
|
1197
|
+
return out;
|
|
1198
|
+
};
|
|
1199
|
+
return walk(obj, 0);
|
|
1200
|
+
}
|
|
1201
|
+
function stringifyBounded(value, limit) {
|
|
1202
|
+
const max = limit != null ? limit : currentDefaultMaxTextFieldChars;
|
|
1203
|
+
if (typeof value === "string") {
|
|
1204
|
+
return capText(value, max);
|
|
1039
1205
|
}
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
this.setAmbientStack(pruned);
|
|
1047
|
-
return pruned.length > 0 ? pruned[pruned.length - 1] : void 0;
|
|
1048
|
-
}
|
|
1049
|
-
warnNoAmbientBindOnce() {
|
|
1050
|
-
if (this._warnedNoAmbientBind) return;
|
|
1051
|
-
this._warnedNoAmbientBind = true;
|
|
1052
|
-
console.warn(this.noAmbientBindWarning);
|
|
1206
|
+
const pruned = boundedClone(value, max + TRUNCATION_MARKER.length + BOUNDED_CLONE_SLACK);
|
|
1207
|
+
let json;
|
|
1208
|
+
try {
|
|
1209
|
+
json = JSON.stringify(pruned);
|
|
1210
|
+
} catch (e) {
|
|
1211
|
+
json = void 0;
|
|
1053
1212
|
}
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
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.";
|
|
1057
|
-
var ROUTING_STORAGE_KEY = /* @__PURE__ */ Symbol.for("raindrop.tracing.routingContextStorage");
|
|
1058
|
-
function routingStorage() {
|
|
1059
|
-
const holder = globalThis;
|
|
1060
|
-
let storage = holder[ROUTING_STORAGE_KEY];
|
|
1061
|
-
if (!storage) {
|
|
1062
|
-
storage = new ContextStackStorage(NO_AMBIENT_ROUTING_BIND_WARNING);
|
|
1063
|
-
holder[ROUTING_STORAGE_KEY] = storage;
|
|
1213
|
+
if (json === void 0) {
|
|
1214
|
+
return capText(String(value), max);
|
|
1064
1215
|
}
|
|
1065
|
-
return
|
|
1216
|
+
return json.length <= max ? json : truncateToLimit(json, max);
|
|
1066
1217
|
}
|
|
1067
|
-
function
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
let dead = false;
|
|
1071
|
-
return {
|
|
1072
|
-
projectId: binding.projectId,
|
|
1073
|
-
authHint: binding.authHint,
|
|
1074
|
-
isLive() {
|
|
1075
|
-
if (dead) return false;
|
|
1076
|
-
return ref === void 0 || ref.deref() !== void 0;
|
|
1077
|
-
},
|
|
1078
|
-
markDead() {
|
|
1079
|
-
dead = true;
|
|
1080
|
-
}
|
|
1081
|
-
};
|
|
1218
|
+
function attrString(key, value) {
|
|
1219
|
+
if (value === void 0) return void 0;
|
|
1220
|
+
return { key, value: { stringValue: value } };
|
|
1082
1221
|
}
|
|
1083
|
-
function
|
|
1084
|
-
|
|
1222
|
+
function attrInt(key, value) {
|
|
1223
|
+
if (value === void 0) return void 0;
|
|
1224
|
+
if (!Number.isFinite(value)) return void 0;
|
|
1225
|
+
return { key, value: { intValue: String(Math.trunc(value)) } };
|
|
1226
|
+
}
|
|
1227
|
+
function attrDouble(key, value) {
|
|
1228
|
+
if (value === void 0) return void 0;
|
|
1229
|
+
if (!Number.isFinite(value)) return void 0;
|
|
1230
|
+
return { key, value: { doubleValue: value } };
|
|
1231
|
+
}
|
|
1232
|
+
var LOCAL_DEBUGGER_ENV_VAR = "RAINDROP_LOCAL_DEBUGGER";
|
|
1233
|
+
var WORKSHOP_ENV_VAR = "RAINDROP_WORKSHOP";
|
|
1234
|
+
var DEFAULT_LOCAL_WORKSHOP_URL = "http://localhost:5899/v1/";
|
|
1235
|
+
function readEnvVar(name) {
|
|
1236
|
+
var _a;
|
|
1085
1237
|
try {
|
|
1086
|
-
|
|
1238
|
+
const env = (_a = globalThis == null ? void 0 : globalThis.process) == null ? void 0 : _a.env;
|
|
1239
|
+
if (env && typeof env[name] === "string" && env[name].length > 0) {
|
|
1240
|
+
return env[name];
|
|
1241
|
+
}
|
|
1087
1242
|
} catch (e) {
|
|
1088
1243
|
}
|
|
1089
|
-
return
|
|
1244
|
+
return void 0;
|
|
1090
1245
|
}
|
|
1091
|
-
function
|
|
1092
|
-
|
|
1246
|
+
function readWorkshopEnv() {
|
|
1247
|
+
const raw = readEnvVar(WORKSHOP_ENV_VAR);
|
|
1248
|
+
if (raw === void 0) return void 0;
|
|
1249
|
+
const trimmed = raw.trim();
|
|
1250
|
+
if (trimmed.length === 0) return void 0;
|
|
1251
|
+
if (/^https?:\/\//i.test(trimmed)) return { url: trimmed };
|
|
1252
|
+
if (/^(1|true|yes|on)$/i.test(trimmed)) return "enable";
|
|
1253
|
+
if (/^(0|false|no|off)$/i.test(trimmed)) return "disable";
|
|
1254
|
+
return void 0;
|
|
1255
|
+
}
|
|
1256
|
+
function isLocalDevHost(hostname) {
|
|
1257
|
+
if (!hostname) return false;
|
|
1258
|
+
if (hostname === "localhost" || hostname === "127.0.0.1" || hostname === "0.0.0.0" || hostname === "::1") {
|
|
1259
|
+
return true;
|
|
1260
|
+
}
|
|
1261
|
+
if (hostname.endsWith(".localhost")) return true;
|
|
1262
|
+
return false;
|
|
1263
|
+
}
|
|
1264
|
+
function readRuntimeHostname() {
|
|
1093
1265
|
try {
|
|
1094
|
-
|
|
1266
|
+
const loc = globalThis == null ? void 0 : globalThis.location;
|
|
1267
|
+
if (loc && typeof loc.hostname === "string" && loc.hostname.length > 0) {
|
|
1268
|
+
return loc.hostname;
|
|
1269
|
+
}
|
|
1095
1270
|
} catch (e) {
|
|
1096
1271
|
}
|
|
1272
|
+
return void 0;
|
|
1097
1273
|
}
|
|
1098
|
-
function
|
|
1099
|
-
|
|
1100
|
-
|
|
1274
|
+
function shouldAutoEnableLocalWorkshop() {
|
|
1275
|
+
if (isLocalDevHost(readRuntimeHostname())) return true;
|
|
1276
|
+
if (readEnvVar("NODE_ENV") === "development") return true;
|
|
1277
|
+
return false;
|
|
1101
1278
|
}
|
|
1102
|
-
function
|
|
1103
|
-
|
|
1104
|
-
if (
|
|
1105
|
-
|
|
1279
|
+
function resolveLocalDebuggerBaseUrl(baseUrl) {
|
|
1280
|
+
var _a, _b, _c;
|
|
1281
|
+
if (baseUrl === null) return null;
|
|
1282
|
+
if (typeof baseUrl === "string" && baseUrl.length > 0) {
|
|
1283
|
+
return (_a = formatEndpoint(baseUrl)) != null ? _a : null;
|
|
1284
|
+
}
|
|
1285
|
+
const explicitUrlEnv = readEnvVar(LOCAL_DEBUGGER_ENV_VAR);
|
|
1286
|
+
if (explicitUrlEnv) return (_b = formatEndpoint(explicitUrlEnv)) != null ? _b : null;
|
|
1287
|
+
const workshopEnv = readWorkshopEnv();
|
|
1288
|
+
if (workshopEnv === "disable") return null;
|
|
1289
|
+
if (workshopEnv === "enable") return DEFAULT_LOCAL_WORKSHOP_URL;
|
|
1290
|
+
if (workshopEnv && "url" in workshopEnv) return (_c = formatEndpoint(workshopEnv.url)) != null ? _c : null;
|
|
1291
|
+
if (shouldAutoEnableLocalWorkshop()) return DEFAULT_LOCAL_WORKSHOP_URL;
|
|
1292
|
+
return null;
|
|
1106
1293
|
}
|
|
1107
|
-
function
|
|
1108
|
-
return
|
|
1294
|
+
function localDebuggerEnabled(baseUrl) {
|
|
1295
|
+
return resolveLocalDebuggerBaseUrl(baseUrl) !== null;
|
|
1109
1296
|
}
|
|
1110
|
-
var
|
|
1111
|
-
function
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
if (!
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1297
|
+
var LOCAL_DEBUGGER_MIRROR_TIMEOUT_MS = 2e3;
|
|
1298
|
+
function mirrorTraceExportToLocalDebugger(body, options = {}) {
|
|
1299
|
+
var _a;
|
|
1300
|
+
const baseUrl = resolveLocalDebuggerBaseUrl(options.baseUrl);
|
|
1301
|
+
if (!baseUrl) return Promise.resolve();
|
|
1302
|
+
return postJson(`${baseUrl}traces`, body, {}, {
|
|
1303
|
+
maxAttempts: 1,
|
|
1304
|
+
debug: (_a = options.debug) != null ? _a : false,
|
|
1305
|
+
sdkName: options.sdkName,
|
|
1306
|
+
timeoutMs: LOCAL_DEBUGGER_MIRROR_TIMEOUT_MS
|
|
1307
|
+
}).catch(() => {
|
|
1308
|
+
});
|
|
1119
1309
|
}
|
|
1120
|
-
function
|
|
1121
|
-
|
|
1122
|
-
const
|
|
1123
|
-
|
|
1124
|
-
const
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1310
|
+
function mirrorPartialEventToLocalDebugger(event, options = {}) {
|
|
1311
|
+
var _a;
|
|
1312
|
+
const baseUrl = resolveLocalDebuggerBaseUrl(options.baseUrl);
|
|
1313
|
+
if (!baseUrl) return Promise.resolve();
|
|
1314
|
+
const headers = options.writeKey ? { Authorization: `Bearer ${options.writeKey}` } : {};
|
|
1315
|
+
return postJson(`${baseUrl}events/track_partial`, event, headers, {
|
|
1316
|
+
maxAttempts: 1,
|
|
1317
|
+
debug: (_a = options.debug) != null ? _a : false,
|
|
1318
|
+
sdkName: options.sdkName,
|
|
1319
|
+
timeoutMs: LOCAL_DEBUGGER_MIRROR_TIMEOUT_MS
|
|
1320
|
+
}).catch(() => {
|
|
1321
|
+
});
|
|
1322
|
+
}
|
|
1323
|
+
function sendLocalDebuggerLiveEvent(event, options = {}) {
|
|
1324
|
+
var _a, _b;
|
|
1325
|
+
const destination = currentReplayTraceDestination();
|
|
1326
|
+
if (destination && destination.kind !== "workshop") return;
|
|
1327
|
+
const baseUrl = resolveLocalDebuggerBaseUrl(options.baseUrl);
|
|
1328
|
+
if (!baseUrl) return;
|
|
1329
|
+
void postJson(
|
|
1330
|
+
`${baseUrl}live`,
|
|
1331
|
+
{
|
|
1332
|
+
...event,
|
|
1333
|
+
type: event.type,
|
|
1334
|
+
timestamp: (_a = event.timestamp) != null ? _a : Date.now()
|
|
1143
1335
|
},
|
|
1144
|
-
|
|
1145
|
-
|
|
1336
|
+
{},
|
|
1337
|
+
{
|
|
1338
|
+
maxAttempts: 1,
|
|
1339
|
+
debug: (_b = options.debug) != null ? _b : false,
|
|
1340
|
+
sdkName: options.sdkName
|
|
1146
1341
|
}
|
|
1147
|
-
|
|
1148
|
-
}
|
|
1149
|
-
function bindSpanAttributes(attributes, owner) {
|
|
1150
|
-
if (Object.keys(attributes).length === 0) return void 0;
|
|
1151
|
-
const frame = makeAttributeFrame(attributes, owner);
|
|
1152
|
-
try {
|
|
1153
|
-
attributeStorage().push(frame);
|
|
1154
|
-
} catch (e) {
|
|
1155
|
-
return void 0;
|
|
1156
|
-
}
|
|
1157
|
-
return frame;
|
|
1342
|
+
).catch(() => {
|
|
1343
|
+
});
|
|
1158
1344
|
}
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
} catch (e) {
|
|
1164
|
-
}
|
|
1345
|
+
var PROJECT_ID_HEADER = "X-Raindrop-Project-Id";
|
|
1346
|
+
var PROJECT_ID_SLUG_PATTERN = /^[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?$/;
|
|
1347
|
+
function isValidProjectIdSlug(value) {
|
|
1348
|
+
return PROJECT_ID_SLUG_PATTERN.test(value);
|
|
1165
1349
|
}
|
|
1166
|
-
function
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
}
|
|
1175
|
-
} catch (e) {
|
|
1350
|
+
function normalizeProjectId(raw, opts) {
|
|
1351
|
+
if (typeof raw !== "string") return void 0;
|
|
1352
|
+
const trimmed = raw.trim();
|
|
1353
|
+
if (!trimmed) return void 0;
|
|
1354
|
+
if (!isValidProjectIdSlug(trimmed) && opts.debug) {
|
|
1355
|
+
console.warn(
|
|
1356
|
+
`${opts.prefix} projectId "${trimmed}" does not match slug ${PROJECT_ID_SLUG_PATTERN.source}; sending anyway \u2014 backend may reject with HTTP 400`
|
|
1357
|
+
);
|
|
1176
1358
|
}
|
|
1359
|
+
return trimmed;
|
|
1177
1360
|
}
|
|
1178
|
-
function
|
|
1179
|
-
|
|
1180
|
-
for (const frame of attributeStorage().getStack()) {
|
|
1181
|
-
if (frame.isLive()) frame.claimSpan(span);
|
|
1182
|
-
}
|
|
1183
|
-
} catch (e) {
|
|
1184
|
-
}
|
|
1361
|
+
function projectIdHeaders(projectId) {
|
|
1362
|
+
return projectId ? { [PROJECT_ID_HEADER]: projectId } : {};
|
|
1185
1363
|
}
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1364
|
+
var SHUTDOWN_DEADLINE_MS = 1e4;
|
|
1365
|
+
var POST_SHUTDOWN_TIMEOUT_MS = 5e3;
|
|
1366
|
+
var MODEL_USAGE_ATTRIBUTES = {
|
|
1367
|
+
usageSource: "raindrop.usage.source",
|
|
1368
|
+
providerName: "gen_ai.provider.name",
|
|
1369
|
+
requestModel: "gen_ai.request.model",
|
|
1370
|
+
responseModel: "gen_ai.response.model",
|
|
1371
|
+
inputTokens: "gen_ai.usage.input_tokens",
|
|
1372
|
+
outputTokens: "gen_ai.usage.output_tokens",
|
|
1373
|
+
reasoningTokens: "gen_ai.usage.reasoning_tokens",
|
|
1374
|
+
cacheReadInputTokens: "gen_ai.usage.cache_read_input_tokens",
|
|
1375
|
+
cacheWriteInputTokens: "gen_ai.usage.cache_write_input_tokens",
|
|
1376
|
+
providerReportedCost: "gen_ai.usage.provider_reported_cost",
|
|
1377
|
+
nonCachedInputTokens: "raindrop.usage.input_tokens.non_cached",
|
|
1378
|
+
nonReasoningOutputTokens: "raindrop.usage.output_tokens.non_reasoning",
|
|
1379
|
+
totalOutputTokens: "raindrop.usage.output_tokens.total",
|
|
1380
|
+
reasoningOutputTokens: "raindrop.usage.output_tokens.reasoning",
|
|
1381
|
+
cacheReadTokens: "raindrop.usage.input_tokens.cache_read",
|
|
1382
|
+
cacheWriteTokens: "raindrop.usage.input_tokens.cache_write"
|
|
1383
|
+
};
|
|
1384
|
+
var MODEL_PROVIDER_NAMES = [
|
|
1385
|
+
["google.vertex.anthropic", "google-vertex"],
|
|
1386
|
+
["google.vertex_ai", "google-vertex"],
|
|
1387
|
+
["google.vertex", "google-vertex"],
|
|
1388
|
+
["gcp.vertex_ai", "google-vertex"],
|
|
1389
|
+
["gcp.gemini", "google"],
|
|
1390
|
+
["google_vertexai", "google-vertex"],
|
|
1391
|
+
["vertex.anthropic", "google-vertex"],
|
|
1392
|
+
["amazon-bedrock", "amazon-bedrock"],
|
|
1393
|
+
["aws.bedrock", "amazon-bedrock"],
|
|
1394
|
+
["bedrock", "amazon-bedrock"],
|
|
1395
|
+
["anthropic", "anthropic"],
|
|
1396
|
+
["openai", "openai"],
|
|
1397
|
+
["google", "google"],
|
|
1398
|
+
["az.ai.openai", "azure"],
|
|
1399
|
+
["azure", "azure"],
|
|
1400
|
+
["openrouter", "openrouter"]
|
|
1401
|
+
];
|
|
1402
|
+
function canonicalModelProvider(provider) {
|
|
1403
|
+
var _a;
|
|
1404
|
+
const normalizedProvider = provider.trim().toLowerCase();
|
|
1405
|
+
if (normalizedProvider === "gateway") return "vercel";
|
|
1406
|
+
const match = MODEL_PROVIDER_NAMES.find(
|
|
1407
|
+
([family]) => normalizedProvider === family || normalizedProvider.startsWith(`${family}.`)
|
|
1408
|
+
);
|
|
1409
|
+
return (_a = match == null ? void 0 : match[1]) != null ? _a : normalizedProvider;
|
|
1196
1410
|
}
|
|
1197
|
-
function
|
|
1198
|
-
|
|
1199
|
-
for (const frame of attributeStorage().getStack()) {
|
|
1200
|
-
if (frame.ownsSpan(span)) frame.markErrorSpanSeen();
|
|
1201
|
-
}
|
|
1202
|
-
} catch (e) {
|
|
1203
|
-
}
|
|
1411
|
+
function tokenCount(value) {
|
|
1412
|
+
return typeof value === "number" && Number.isSafeInteger(value) && value >= 0 ? value : void 0;
|
|
1204
1413
|
}
|
|
1205
|
-
function
|
|
1206
|
-
|
|
1414
|
+
function buildRawModelUsageAttributes(usage) {
|
|
1415
|
+
const providerReportedCost = typeof usage.providerReportedCost === "number" && Number.isFinite(usage.providerReportedCost) && usage.providerReportedCost >= 0 ? usage.providerReportedCost : void 0;
|
|
1416
|
+
return [
|
|
1417
|
+
attrInt(MODEL_USAGE_ATTRIBUTES.inputTokens, tokenCount(usage.inputTokens)),
|
|
1418
|
+
attrInt(MODEL_USAGE_ATTRIBUTES.outputTokens, tokenCount(usage.outputTokens)),
|
|
1419
|
+
attrInt(MODEL_USAGE_ATTRIBUTES.reasoningTokens, tokenCount(usage.reasoningTokens)),
|
|
1420
|
+
attrInt(MODEL_USAGE_ATTRIBUTES.cacheReadInputTokens, tokenCount(usage.cacheReadInputTokens)),
|
|
1421
|
+
attrInt(MODEL_USAGE_ATTRIBUTES.cacheWriteInputTokens, tokenCount(usage.cacheWriteInputTokens)),
|
|
1422
|
+
attrDouble(MODEL_USAGE_ATTRIBUTES.providerReportedCost, providerReportedCost)
|
|
1423
|
+
].filter((attribute) => attribute !== void 0);
|
|
1207
1424
|
}
|
|
1425
|
+
var STRING_ALIASES = {
|
|
1426
|
+
[MODEL_USAGE_ATTRIBUTES.requestModel]: ["ai.model.id", "ai.model"]
|
|
1427
|
+
};
|
|
1428
|
+
var NUMBER_ALIASES = {
|
|
1429
|
+
[MODEL_USAGE_ATTRIBUTES.inputTokens]: [
|
|
1430
|
+
"gen_ai.usage.prompt_tokens",
|
|
1431
|
+
"ai.usage.prompt_tokens",
|
|
1432
|
+
"ai.usage.promptTokens",
|
|
1433
|
+
"ai.usage.input_tokens",
|
|
1434
|
+
"ai.usage.inputTokens"
|
|
1435
|
+
],
|
|
1436
|
+
[MODEL_USAGE_ATTRIBUTES.outputTokens]: [
|
|
1437
|
+
"gen_ai.usage.completion_tokens",
|
|
1438
|
+
"ai.usage.completion_tokens",
|
|
1439
|
+
"ai.usage.completionTokens",
|
|
1440
|
+
"ai.usage.output_tokens",
|
|
1441
|
+
"ai.usage.outputTokens"
|
|
1442
|
+
],
|
|
1443
|
+
[MODEL_USAGE_ATTRIBUTES.reasoningTokens]: [
|
|
1444
|
+
"gen_ai.usage.reasoning.output_tokens",
|
|
1445
|
+
"ai.usage.reasoningTokens",
|
|
1446
|
+
"ai.usage.thoughts_tokens"
|
|
1447
|
+
],
|
|
1448
|
+
[MODEL_USAGE_ATTRIBUTES.cacheReadInputTokens]: [
|
|
1449
|
+
"gen_ai.usage.cache_read_tokens",
|
|
1450
|
+
"gen_ai.usage.cache_read.input_tokens",
|
|
1451
|
+
"ai.usage.cachedInputTokens",
|
|
1452
|
+
"ai.usage.cached_tokens",
|
|
1453
|
+
"ai.usage.cache_read_tokens",
|
|
1454
|
+
"ai.usage.cache_read_input_tokens",
|
|
1455
|
+
"ai.usage.cacheReadInputTokens"
|
|
1456
|
+
],
|
|
1457
|
+
[MODEL_USAGE_ATTRIBUTES.cacheWriteInputTokens]: [
|
|
1458
|
+
"gen_ai.usage.cache_creation_input_tokens",
|
|
1459
|
+
"gen_ai.usage.cache_creation.input_tokens",
|
|
1460
|
+
"ai.usage.cacheWriteInputTokens",
|
|
1461
|
+
"ai.usage.cache_creation_input_tokens",
|
|
1462
|
+
"ai.usage.cacheCreationInputTokens"
|
|
1463
|
+
]
|
|
1464
|
+
};
|
|
1465
|
+
var DEFAULT_REDACT_ATTRIBUTE_KEYS = [
|
|
1466
|
+
"ai.request.providerOptions",
|
|
1467
|
+
"ai.response.providerMetadata"
|
|
1468
|
+
];
|
|
1469
|
+
var REDACT_JSON_ATTRIBUTE_KEYS = new Set(DEFAULT_REDACT_ATTRIBUTE_KEYS);
|
|
1208
1470
|
|
|
1209
1471
|
// ../core/dist/index.node.js
|
|
1210
1472
|
import { AsyncLocalStorage as AsyncLocalStorage2 } from "async_hooks";
|
|
1473
|
+
import { execFile } from "child_process";
|
|
1474
|
+
import { resolve } from "path";
|
|
1475
|
+
var resolveLocal = (sourceDirectory, detectBranch, completed) => {
|
|
1476
|
+
const cwd = sourceDirectory ? resolve(sourceDirectory) : process.cwd();
|
|
1477
|
+
let cancelled = false;
|
|
1478
|
+
let active;
|
|
1479
|
+
let deadlineTimer;
|
|
1480
|
+
const deadline = Date.now() + 1e3;
|
|
1481
|
+
const run = (args, done) => {
|
|
1482
|
+
if (cancelled) return;
|
|
1483
|
+
const remaining = deadline - Date.now();
|
|
1484
|
+
if (remaining <= 0) {
|
|
1485
|
+
done(void 0);
|
|
1486
|
+
return;
|
|
1487
|
+
}
|
|
1488
|
+
try {
|
|
1489
|
+
active = execFile(
|
|
1490
|
+
"git",
|
|
1491
|
+
args,
|
|
1492
|
+
{
|
|
1493
|
+
cwd,
|
|
1494
|
+
encoding: "utf8",
|
|
1495
|
+
maxBuffer: 4096,
|
|
1496
|
+
windowsHide: true,
|
|
1497
|
+
env: {
|
|
1498
|
+
...process.env,
|
|
1499
|
+
// The selected application cwd, not the invoking shell's Git plumbing, owns identity.
|
|
1500
|
+
GIT_DIR: void 0,
|
|
1501
|
+
GIT_WORK_TREE: void 0,
|
|
1502
|
+
GIT_COMMON_DIR: void 0,
|
|
1503
|
+
GIT_NAMESPACE: void 0,
|
|
1504
|
+
GIT_INDEX_FILE: void 0,
|
|
1505
|
+
GIT_OBJECT_DIRECTORY: void 0,
|
|
1506
|
+
GIT_ALTERNATE_OBJECT_DIRECTORIES: void 0,
|
|
1507
|
+
GIT_CONFIG_PARAMETERS: void 0,
|
|
1508
|
+
GIT_CONFIG_COUNT: "0",
|
|
1509
|
+
GIT_TERMINAL_PROMPT: "0",
|
|
1510
|
+
GIT_OPTIONAL_LOCKS: "0"
|
|
1511
|
+
}
|
|
1512
|
+
},
|
|
1513
|
+
(error, stdout) => {
|
|
1514
|
+
clearTimeout(deadlineTimer);
|
|
1515
|
+
deadlineTimer = void 0;
|
|
1516
|
+
active = void 0;
|
|
1517
|
+
if (!cancelled) {
|
|
1518
|
+
try {
|
|
1519
|
+
done(error ? void 0 : stdout.trim());
|
|
1520
|
+
} catch (e) {
|
|
1521
|
+
}
|
|
1522
|
+
}
|
|
1523
|
+
}
|
|
1524
|
+
);
|
|
1525
|
+
active.unref();
|
|
1526
|
+
if (active.stdout && "unref" in active.stdout && typeof active.stdout.unref === "function")
|
|
1527
|
+
active.stdout.unref();
|
|
1528
|
+
if (active.stderr && "unref" in active.stderr && typeof active.stderr.unref === "function")
|
|
1529
|
+
active.stderr.unref();
|
|
1530
|
+
deadlineTimer = setTimeout(() => {
|
|
1531
|
+
try {
|
|
1532
|
+
active == null ? void 0 : active.kill("SIGKILL");
|
|
1533
|
+
} catch (e) {
|
|
1534
|
+
}
|
|
1535
|
+
}, remaining);
|
|
1536
|
+
deadlineTimer.unref();
|
|
1537
|
+
} catch (e) {
|
|
1538
|
+
try {
|
|
1539
|
+
done(void 0);
|
|
1540
|
+
} catch (e2) {
|
|
1541
|
+
}
|
|
1542
|
+
}
|
|
1543
|
+
};
|
|
1544
|
+
const scheduled = setTimeout(() => {
|
|
1545
|
+
try {
|
|
1546
|
+
run(["rev-parse", "HEAD"], (rawSha) => {
|
|
1547
|
+
const commitSha = validAppCommitSha(rawSha);
|
|
1548
|
+
if (!commitSha) {
|
|
1549
|
+
completed({});
|
|
1550
|
+
return;
|
|
1551
|
+
}
|
|
1552
|
+
run(["-c", "core.fsmonitor=false", "status", "--porcelain"], (status) => {
|
|
1553
|
+
const finish = (branch) => {
|
|
1554
|
+
run(["rev-parse", "HEAD"], (finalSha) => {
|
|
1555
|
+
const coherent = validAppCommitSha(finalSha) === commitSha;
|
|
1556
|
+
completed({
|
|
1557
|
+
commitSha,
|
|
1558
|
+
...coherent && status !== void 0 ? { commitDirty: status !== "" } : {},
|
|
1559
|
+
...coherent && branch && branch !== "HEAD" ? { branch } : {}
|
|
1560
|
+
});
|
|
1561
|
+
});
|
|
1562
|
+
};
|
|
1563
|
+
if (detectBranch) run(["symbolic-ref", "--quiet", "--short", "HEAD"], finish);
|
|
1564
|
+
else finish();
|
|
1565
|
+
});
|
|
1566
|
+
});
|
|
1567
|
+
} catch (e) {
|
|
1568
|
+
completed({});
|
|
1569
|
+
}
|
|
1570
|
+
}, 0);
|
|
1571
|
+
scheduled.unref();
|
|
1572
|
+
return () => {
|
|
1573
|
+
cancelled = true;
|
|
1574
|
+
clearTimeout(scheduled);
|
|
1575
|
+
clearTimeout(deadlineTimer);
|
|
1576
|
+
try {
|
|
1577
|
+
active == null ? void 0 : active.kill("SIGKILL");
|
|
1578
|
+
} catch (e) {
|
|
1579
|
+
}
|
|
1580
|
+
};
|
|
1581
|
+
};
|
|
1582
|
+
function createAppGitContext(options, runtime = {}) {
|
|
1583
|
+
return new AppGitContext(options, { ...runtime, resolveLocal });
|
|
1584
|
+
}
|
|
1211
1585
|
globalThis.RAINDROP_ASYNC_LOCAL_STORAGE = AsyncLocalStorage2;
|
|
1212
1586
|
var SUPPRESS_TRACING_KEY = /* @__PURE__ */ Symbol.for(
|
|
1213
1587
|
"OpenTelemetry SDK Context Key SUPPRESS_TRACING"
|
|
@@ -1238,7 +1612,7 @@ installTracingSuppressionHook();
|
|
|
1238
1612
|
// package.json
|
|
1239
1613
|
var package_default = {
|
|
1240
1614
|
name: "raindrop-ai",
|
|
1241
|
-
version: "0.7.
|
|
1615
|
+
version: "0.7.1",
|
|
1242
1616
|
main: "dist/index.js",
|
|
1243
1617
|
module: "dist/index.mjs",
|
|
1244
1618
|
types: "dist/index.d.ts",
|
|
@@ -1577,11 +1951,38 @@ function stampContextAttributes(span) {
|
|
|
1577
1951
|
}
|
|
1578
1952
|
}
|
|
1579
1953
|
var RaindropContextSpanProcessor = class {
|
|
1954
|
+
constructor(appGitSnapshot) {
|
|
1955
|
+
this.appGitSnapshot = appGitSnapshot;
|
|
1956
|
+
this.appGitAdded = /* @__PURE__ */ new WeakMap();
|
|
1957
|
+
}
|
|
1580
1958
|
onStart(span) {
|
|
1959
|
+
var _a, _b, _c, _d;
|
|
1581
1960
|
try {
|
|
1582
1961
|
stampContextAttributes(span);
|
|
1583
1962
|
rememberReplayTraceDestination(span);
|
|
1584
1963
|
const bound = currentRoutingBinding();
|
|
1964
|
+
const keys = ["raindrop.app.commit_sha", "raindrop.app.commit_dirty", "raindrop.app.branch"];
|
|
1965
|
+
const attrs = (_a = span.attributes) != null ? _a : {};
|
|
1966
|
+
const properties = {};
|
|
1967
|
+
for (const key of keys) {
|
|
1968
|
+
const existing = [key, `ai.telemetry.metadata.${key}`, `traceloop.association.properties.${key}`].find((name) => Object.prototype.hasOwnProperty.call(attrs, name));
|
|
1969
|
+
if (existing) properties[key] = attrs[existing];
|
|
1970
|
+
}
|
|
1971
|
+
const source = { ...(_d = (_c = (_b = this.appGitSnapshot) == null ? void 0 : _b.call(this, properties)) != null ? _c : bound == null ? void 0 : bound.appGit) != null ? _d : {} };
|
|
1972
|
+
if (Object.prototype.hasOwnProperty.call(properties, "raindrop.app.commit_sha") && properties["raindrop.app.commit_sha"] !== source["raindrop.app.commit_sha"]) {
|
|
1973
|
+
delete source["raindrop.app.commit_dirty"];
|
|
1974
|
+
delete source["raindrop.app.branch"];
|
|
1975
|
+
}
|
|
1976
|
+
const added = /* @__PURE__ */ new Map();
|
|
1977
|
+
for (const key of keys) {
|
|
1978
|
+
if ([key, `ai.telemetry.metadata.${key}`, `traceloop.association.properties.${key}`].some((name) => Object.prototype.hasOwnProperty.call(attrs, name))) continue;
|
|
1979
|
+
const value = source == null ? void 0 : source[key];
|
|
1980
|
+
if (typeof value === "string" || typeof value === "boolean") {
|
|
1981
|
+
span.setAttribute(key, value);
|
|
1982
|
+
added.set(key, value);
|
|
1983
|
+
}
|
|
1984
|
+
}
|
|
1985
|
+
this.appGitAdded.set(span, added);
|
|
1585
1986
|
if (!bound) return;
|
|
1586
1987
|
stampSpan(span, bound.projectId, bound.authHint);
|
|
1587
1988
|
} catch (e) {
|
|
@@ -1590,6 +1991,16 @@ var RaindropContextSpanProcessor = class {
|
|
|
1590
1991
|
onEnd(span) {
|
|
1591
1992
|
var _a;
|
|
1592
1993
|
try {
|
|
1994
|
+
if (span == null ? void 0 : span.attributes) {
|
|
1995
|
+
const attrs = span.attributes;
|
|
1996
|
+
const added = this.appGitAdded.get(span);
|
|
1997
|
+
const shaKey = "raindrop.app.commit_sha";
|
|
1998
|
+
const hasAlias = (key) => [`ai.telemetry.metadata.${key}`, `traceloop.association.properties.${key}`].some((name) => Object.prototype.hasOwnProperty.call(attrs, name));
|
|
1999
|
+
const shaChanged = (added == null ? void 0 : added.has(shaKey)) && (attrs[shaKey] !== added.get(shaKey) || hasAlias(shaKey));
|
|
2000
|
+
for (const [key, value] of added != null ? added : []) {
|
|
2001
|
+
if (attrs[key] === value && (hasAlias(key) || shaChanged && key !== shaKey)) delete attrs[key];
|
|
2002
|
+
}
|
|
2003
|
+
}
|
|
1593
2004
|
if (((_a = span == null ? void 0 : span.status) == null ? void 0 : _a.code) !== SPAN_STATUS_ERROR) return;
|
|
1594
2005
|
markErrorSpanSeen(span);
|
|
1595
2006
|
} catch (e) {
|
|
@@ -1720,7 +2131,7 @@ import { WeakValueMap } from "weakref";
|
|
|
1720
2131
|
|
|
1721
2132
|
// src/tracing/direct/http.ts
|
|
1722
2133
|
function wait2(ms) {
|
|
1723
|
-
return new Promise((
|
|
2134
|
+
return new Promise((resolve2) => setTimeout(resolve2, ms));
|
|
1724
2135
|
}
|
|
1725
2136
|
function formatEndpoint2(endpoint) {
|
|
1726
2137
|
if (!endpoint) return void 0;
|
|
@@ -1965,6 +2376,7 @@ var DirectTraceShipper = class {
|
|
|
1965
2376
|
*/
|
|
1966
2377
|
this.hasShutdown = false;
|
|
1967
2378
|
var _a, _b, _c, _d, _e, _f;
|
|
2379
|
+
this.appGitSnapshot = opts.appGitSnapshot;
|
|
1968
2380
|
this.writeKey = opts.writeKey;
|
|
1969
2381
|
this.baseUrl = (_a = formatEndpoint2(opts.endpoint)) != null ? _a : "https://api.raindrop.ai/v1/";
|
|
1970
2382
|
this.enabled = (_b = opts.enabled) != null ? _b : true;
|
|
@@ -1979,6 +2391,14 @@ var DirectTraceShipper = class {
|
|
|
1979
2391
|
this.localDebuggerUrl = resolved;
|
|
1980
2392
|
}
|
|
1981
2393
|
}
|
|
2394
|
+
applicationGitSnapshot(properties) {
|
|
2395
|
+
var _a, _b, _c, _d;
|
|
2396
|
+
try {
|
|
2397
|
+
return (_d = (_c = (_a = this.appGitSnapshot) == null ? void 0 : _a.call(this, properties)) != null ? _c : (_b = currentRoutingBinding()) == null ? void 0 : _b.appGit) != null ? _d : {};
|
|
2398
|
+
} catch (e) {
|
|
2399
|
+
return {};
|
|
2400
|
+
}
|
|
2401
|
+
}
|
|
1982
2402
|
/**
|
|
1983
2403
|
* Build and enqueue an OTLP span for a trackTool call.
|
|
1984
2404
|
*
|
|
@@ -2053,7 +2473,10 @@ var DirectTraceShipper = class {
|
|
|
2053
2473
|
name: params.name,
|
|
2054
2474
|
startTimeUnixNano,
|
|
2055
2475
|
endTimeUnixNano,
|
|
2056
|
-
attributes
|
|
2476
|
+
attributes: withAppGitAttributes(
|
|
2477
|
+
attributes,
|
|
2478
|
+
params.appGitSnapshot !== void 0 ? params.appGitSnapshot : this.applicationGitSnapshot(params.properties)
|
|
2479
|
+
),
|
|
2057
2480
|
status
|
|
2058
2481
|
});
|
|
2059
2482
|
const replayDestination = currentReplayTraceDestination();
|
|
@@ -3694,7 +4117,7 @@ var LiveInteraction = class {
|
|
|
3694
4117
|
span.end();
|
|
3695
4118
|
}
|
|
3696
4119
|
async finish(resultEvent) {
|
|
3697
|
-
var _a, _b, _c, _d, _e, _f, _g;
|
|
4120
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _i;
|
|
3698
4121
|
unbindRoutingContext(this.boundContext);
|
|
3699
4122
|
this.boundContext = void 0;
|
|
3700
4123
|
unbindSpanAttributes(this.toolEventsFrame);
|
|
@@ -3704,10 +4127,19 @@ var LiveInteraction = class {
|
|
|
3704
4127
|
}
|
|
3705
4128
|
const eventId = resultEvent.eventId || this.context.eventId;
|
|
3706
4129
|
if (!this.usageEmitted) {
|
|
3707
|
-
(
|
|
4130
|
+
const appGitSnapshot = (_b = (_a = this.analytics) == null ? void 0 : _a.getAppGitSnapshot(resultEvent.properties, eventId)) != null ? _b : {};
|
|
4131
|
+
const usageProperties = {};
|
|
4132
|
+
for (const key of [APP_COMMIT_SHA, APP_COMMIT_DIRTY, APP_BRANCH]) {
|
|
4133
|
+
if (resultEvent.properties && Object.prototype.hasOwnProperty.call(resultEvent.properties, key)) {
|
|
4134
|
+
usageProperties[key] = resultEvent.properties[key];
|
|
4135
|
+
}
|
|
4136
|
+
}
|
|
4137
|
+
(_e = this.analytics) == null ? void 0 : _e._recordModelUsage(
|
|
3708
4138
|
eventId,
|
|
3709
|
-
(
|
|
3710
|
-
(
|
|
4139
|
+
(_c = resultEvent.model) != null ? _c : this.context.model,
|
|
4140
|
+
(_d = resultEvent.usage) != null ? _d : this.context.usage,
|
|
4141
|
+
withAppGitProperties(usageProperties, appGitSnapshot),
|
|
4142
|
+
appGitSnapshot
|
|
3711
4143
|
);
|
|
3712
4144
|
this.usageEmitted = true;
|
|
3713
4145
|
}
|
|
@@ -3718,20 +4150,20 @@ var LiveInteraction = class {
|
|
|
3718
4150
|
} catch (e) {
|
|
3719
4151
|
}
|
|
3720
4152
|
})();
|
|
3721
|
-
if ((
|
|
4153
|
+
if ((_g = (_f = this.analytics) == null ? void 0 : _f._shouldBlockFinishFlush()) != null ? _g : true) {
|
|
3722
4154
|
await spanFlush;
|
|
3723
4155
|
} else {
|
|
3724
4156
|
void spanFlush.catch(() => {
|
|
3725
4157
|
});
|
|
3726
4158
|
}
|
|
3727
4159
|
try {
|
|
3728
|
-
await ((
|
|
4160
|
+
await ((_h = this.analytics) == null ? void 0 : _h._drainInFlightPartials(eventId));
|
|
3729
4161
|
} catch (e) {
|
|
3730
4162
|
}
|
|
3731
4163
|
if (this.traceId) {
|
|
3732
4164
|
this.setProperty("trace_id", this.traceId);
|
|
3733
4165
|
}
|
|
3734
|
-
await ((
|
|
4166
|
+
await ((_i = this.analytics) == null ? void 0 : _i._trackAiPartial({
|
|
3735
4167
|
...resultEvent,
|
|
3736
4168
|
eventId,
|
|
3737
4169
|
isPending: false
|
|
@@ -4538,6 +4970,7 @@ var tracing = (analytics, apiUrl, writeKey, options, isDebug = false) => {
|
|
|
4538
4970
|
}
|
|
4539
4971
|
}
|
|
4540
4972
|
const directShipper = bypassOtelForTools ? new DirectTraceShipper({
|
|
4973
|
+
appGitSnapshot: (properties) => analytics.getAppGitSnapshot(properties),
|
|
4541
4974
|
writeKey,
|
|
4542
4975
|
endpoint: directEndpoint != null ? directEndpoint : apiUrl,
|
|
4543
4976
|
debug: isDebug,
|
|
@@ -4597,7 +5030,7 @@ var tracing = (analytics, apiUrl, writeKey, options, isDebug = false) => {
|
|
|
4597
5030
|
tracingEnabled: tracingEnabled !== false,
|
|
4598
5031
|
disableBatch: disableBatching,
|
|
4599
5032
|
processor: new CompositeSpanProcessor(
|
|
4600
|
-
[new RaindropContextSpanProcessor(), localDebuggerProcessor],
|
|
5033
|
+
[new RaindropContextSpanProcessor((properties) => analytics.getAppGitSnapshot(properties)), localDebuggerProcessor],
|
|
4601
5034
|
[]
|
|
4602
5035
|
),
|
|
4603
5036
|
instrumentations: createConfiguredInstrumentations(otherOptions)
|
|
@@ -4621,7 +5054,7 @@ var tracing = (analytics, apiUrl, writeKey, options, isDebug = false) => {
|
|
|
4621
5054
|
tracingEnabled: tracingEnabled !== false,
|
|
4622
5055
|
disableBatch: disableBatching,
|
|
4623
5056
|
processor: new CompositeSpanProcessor(
|
|
4624
|
-
[new RaindropContextSpanProcessor(), replayOnlyProcessor],
|
|
5057
|
+
[new RaindropContextSpanProcessor((properties) => analytics.getAppGitSnapshot(properties)), replayOnlyProcessor],
|
|
4625
5058
|
[]
|
|
4626
5059
|
),
|
|
4627
5060
|
instrumentations: createConfiguredInstrumentations(otherOptions)
|
|
@@ -4662,7 +5095,7 @@ var tracing = (analytics, apiUrl, writeKey, options, isDebug = false) => {
|
|
|
4662
5095
|
);
|
|
4663
5096
|
}
|
|
4664
5097
|
if (guardedExporter) {
|
|
4665
|
-
const contextProcessor = new RaindropContextSpanProcessor();
|
|
5098
|
+
const contextProcessor = new RaindropContextSpanProcessor((properties) => analytics.getAppGitSnapshot(properties));
|
|
4666
5099
|
const callerProcessor = otherOptions.processor;
|
|
4667
5100
|
const processor = new CompositeSpanProcessor(
|
|
4668
5101
|
callerProcessor ? [contextProcessor, callerProcessor] : [contextProcessor],
|
|
@@ -4725,9 +5158,9 @@ var tracing = (analytics, apiUrl, writeKey, options, isDebug = false) => {
|
|
|
4725
5158
|
traceId,
|
|
4726
5159
|
analytics,
|
|
4727
5160
|
directShipper,
|
|
4728
|
-
{ projectId, authHint }
|
|
5161
|
+
{ projectId, authHint, appGit: analytics.getAppGitSnapshot(traceContext.properties, traceContext.eventId) }
|
|
4729
5162
|
);
|
|
4730
|
-
const bound = bindRoutingContext({ projectId, authHint }, interaction);
|
|
5163
|
+
const bound = bindRoutingContext({ projectId, authHint, appGit: analytics.getAppGitSnapshot(traceContext.properties, traceContext.eventId) }, interaction);
|
|
4731
5164
|
interaction.setBoundContext(bound);
|
|
4732
5165
|
try {
|
|
4733
5166
|
analytics._trackAiPartial({
|
|
@@ -4804,7 +5237,8 @@ var tracing = (analytics, apiUrl, writeKey, options, isDebug = false) => {
|
|
|
4804
5237
|
directShipper.sendSpan({
|
|
4805
5238
|
name: "ai.model.usage",
|
|
4806
5239
|
spanKind: "llm",
|
|
4807
|
-
properties: { event_id: params.eventId },
|
|
5240
|
+
properties: { ...params.appGitProperties, event_id: params.eventId },
|
|
5241
|
+
appGitSnapshot: params.appGitSnapshot,
|
|
4808
5242
|
startTimeMs: timeMs,
|
|
4809
5243
|
endTimeMs: timeMs,
|
|
4810
5244
|
durationMs: 0,
|
|
@@ -4812,9 +5246,23 @@ var tracing = (analytics, apiUrl, writeKey, options, isDebug = false) => {
|
|
|
4812
5246
|
});
|
|
4813
5247
|
return;
|
|
4814
5248
|
}
|
|
4815
|
-
const
|
|
4816
|
-
|
|
4817
|
-
|
|
5249
|
+
const initialAttributes = {
|
|
5250
|
+
"traceloop.span.kind": "llm"
|
|
5251
|
+
};
|
|
5252
|
+
for (const [key, value] of Object.entries({
|
|
5253
|
+
...params.appGitProperties,
|
|
5254
|
+
event_id: params.eventId
|
|
5255
|
+
})) {
|
|
5256
|
+
if (value !== void 0) {
|
|
5257
|
+
initialAttributes[`traceloop.association.properties.${key}`] = stringifyBounded(value);
|
|
5258
|
+
}
|
|
5259
|
+
}
|
|
5260
|
+
for (const [key, value] of Object.entries(params.appGitSnapshot)) {
|
|
5261
|
+
if (typeof value === "string" || typeof value === "boolean") {
|
|
5262
|
+
initialAttributes[key] = value;
|
|
5263
|
+
}
|
|
5264
|
+
}
|
|
5265
|
+
const span = trace6.getTracer("traceloop.tracer").startSpan("ai.model.usage", { attributes: initialAttributes });
|
|
4818
5266
|
stampSpan(span, projectId, authHint);
|
|
4819
5267
|
for (const attribute of attributes) {
|
|
4820
5268
|
const value = attribute.value;
|
|
@@ -4935,7 +5383,7 @@ var tracing = (analytics, apiUrl, writeKey, options, isDebug = false) => {
|
|
|
4935
5383
|
allowedInstrumentationLibraries: processorOptions == null ? void 0 : processorOptions.allowedInstrumentationLibraries,
|
|
4936
5384
|
localDebuggerUrlOpt: localDebuggerUrl
|
|
4937
5385
|
});
|
|
4938
|
-
const contextProcessor = new RaindropContextSpanProcessor();
|
|
5386
|
+
const contextProcessor = new RaindropContextSpanProcessor((properties) => analytics.getAppGitSnapshot(properties));
|
|
4939
5387
|
return withV2SpanCompat(
|
|
4940
5388
|
new CompositeSpanProcessor(
|
|
4941
5389
|
[contextProcessor, productionProcessor],
|
|
@@ -5013,6 +5461,15 @@ export {
|
|
|
5013
5461
|
withEvalScope,
|
|
5014
5462
|
currentEvalScope,
|
|
5015
5463
|
evalScopeAttributes,
|
|
5464
|
+
withReplayTraceDestination,
|
|
5465
|
+
currentReplayTraceDestination,
|
|
5466
|
+
withRoutingContext,
|
|
5467
|
+
currentRoutingBinding,
|
|
5468
|
+
APP_COMMIT_SHA,
|
|
5469
|
+
APP_COMMIT_DIRTY,
|
|
5470
|
+
APP_BRANCH,
|
|
5471
|
+
validAppCommitSha,
|
|
5472
|
+
withAppGitProperties,
|
|
5016
5473
|
normalizeFeatureFlags,
|
|
5017
5474
|
randomUUID,
|
|
5018
5475
|
runWithTracingSuppressed,
|
|
@@ -5026,8 +5483,6 @@ export {
|
|
|
5026
5483
|
capText,
|
|
5027
5484
|
boundedClone,
|
|
5028
5485
|
stringifyBounded,
|
|
5029
|
-
withReplayTraceDestination,
|
|
5030
|
-
currentReplayTraceDestination,
|
|
5031
5486
|
resolveLocalDebuggerBaseUrl,
|
|
5032
5487
|
localDebuggerEnabled,
|
|
5033
5488
|
mirrorPartialEventToLocalDebugger,
|
|
@@ -5035,7 +5490,7 @@ export {
|
|
|
5035
5490
|
projectIdHeaders,
|
|
5036
5491
|
SHUTDOWN_DEADLINE_MS,
|
|
5037
5492
|
POST_SHUTDOWN_TIMEOUT_MS,
|
|
5038
|
-
|
|
5493
|
+
createAppGitContext,
|
|
5039
5494
|
package_default,
|
|
5040
5495
|
authHintForKey,
|
|
5041
5496
|
withTask,
|