@raindrop-ai/deep-agents 0.1.1 → 0.1.3
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 +29 -1
- package/dist/index.d.mts +97 -0
- package/dist/index.d.ts +97 -0
- package/dist/index.js +1333 -180
- package/dist/index.mjs +1338 -180
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -90,7 +90,459 @@ function evalScopeAttributes() {
|
|
|
90
90
|
return { [EVAL_CORRELATION_ID_ATTRIBUTE]: scope.correlationId };
|
|
91
91
|
}
|
|
92
92
|
|
|
93
|
-
// ../core/dist/chunk-
|
|
93
|
+
// ../core/dist/chunk-WJOR6M7H.js
|
|
94
|
+
var STATE_KEY = /* @__PURE__ */ Symbol.for("raindrop.tracing.replayTraceRoutingState");
|
|
95
|
+
function state() {
|
|
96
|
+
const holder = globalThis;
|
|
97
|
+
let current = holder[STATE_KEY];
|
|
98
|
+
if (!current) {
|
|
99
|
+
let storage = null;
|
|
100
|
+
try {
|
|
101
|
+
const Ctor = globalThis.RAINDROP_ASYNC_LOCAL_STORAGE;
|
|
102
|
+
if (Ctor) storage = new Ctor();
|
|
103
|
+
} catch (e) {
|
|
104
|
+
storage = null;
|
|
105
|
+
}
|
|
106
|
+
current = {
|
|
107
|
+
storage,
|
|
108
|
+
syncDestination: void 0,
|
|
109
|
+
spanDestinations: /* @__PURE__ */ new WeakMap()
|
|
110
|
+
};
|
|
111
|
+
holder[STATE_KEY] = current;
|
|
112
|
+
}
|
|
113
|
+
return current;
|
|
114
|
+
}
|
|
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;
|
|
119
|
+
}
|
|
120
|
+
function rememberReplayTraceDestination(span) {
|
|
121
|
+
const destination = currentReplayTraceDestination();
|
|
122
|
+
if (destination) state().spanDestinations.set(span, destination);
|
|
123
|
+
}
|
|
124
|
+
function copyReplayTraceDestination(source, target) {
|
|
125
|
+
const destination = state().spanDestinations.get(source);
|
|
126
|
+
if (destination) state().spanDestinations.set(target, destination);
|
|
127
|
+
}
|
|
128
|
+
function replayTraceDestinationFor(value) {
|
|
129
|
+
if (typeof value !== "object" && typeof value !== "function" || value === null) {
|
|
130
|
+
return void 0;
|
|
131
|
+
}
|
|
132
|
+
return state().spanDestinations.get(value);
|
|
133
|
+
}
|
|
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);
|
|
139
|
+
}
|
|
140
|
+
function replayTraceUrl(baseUrl) {
|
|
141
|
+
return `${baseUrl.replace(/\/+$/, "")}/v1/traces`;
|
|
142
|
+
}
|
|
143
|
+
function getAsyncLocalStorageCtor() {
|
|
144
|
+
return globalThis.RAINDROP_ASYNC_LOCAL_STORAGE;
|
|
145
|
+
}
|
|
146
|
+
var MAX_BINDING_STACK = 128;
|
|
147
|
+
var EMPTY_STACK = [];
|
|
148
|
+
var ContextStackStorage = class {
|
|
149
|
+
/** Emitted once when this runtime cannot support an ambient push. */
|
|
150
|
+
constructor(noAmbientBindWarning) {
|
|
151
|
+
this.noAmbientBindWarning = noAmbientBindWarning;
|
|
152
|
+
this._als = null;
|
|
153
|
+
this._enterWithUsable = false;
|
|
154
|
+
this._syncStack = EMPTY_STACK;
|
|
155
|
+
this._adoptionChecked = false;
|
|
156
|
+
this._warnedNoAmbientBind = false;
|
|
157
|
+
}
|
|
158
|
+
maybeAdoptAsyncLocalStorage() {
|
|
159
|
+
if (this._adoptionChecked) return;
|
|
160
|
+
this._adoptionChecked = true;
|
|
161
|
+
const Ctor = getAsyncLocalStorageCtor();
|
|
162
|
+
if (!Ctor) return;
|
|
163
|
+
const als = new Ctor();
|
|
164
|
+
try {
|
|
165
|
+
als.run(EMPTY_STACK, () => {
|
|
166
|
+
});
|
|
167
|
+
} catch (e) {
|
|
168
|
+
return;
|
|
169
|
+
}
|
|
170
|
+
this._als = als;
|
|
171
|
+
if (typeof als.enterWith === "function") {
|
|
172
|
+
try {
|
|
173
|
+
als.enterWith(EMPTY_STACK);
|
|
174
|
+
this._enterWithUsable = true;
|
|
175
|
+
} catch (e) {
|
|
176
|
+
this._enterWithUsable = false;
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
getStack() {
|
|
181
|
+
var _a;
|
|
182
|
+
this.maybeAdoptAsyncLocalStorage();
|
|
183
|
+
if (this._als) return (_a = this._als.getStore()) != null ? _a : this._syncStack;
|
|
184
|
+
return this._syncStack;
|
|
185
|
+
}
|
|
186
|
+
/**
|
|
187
|
+
* Persist an ambient stack mutation. Returns false when an ALS is adopted but
|
|
188
|
+
* `enterWith` is unusable (workerd): callers must NOT fall back to the
|
|
189
|
+
* process-shared sync stack, since concurrent isolates would cross-stamp.
|
|
190
|
+
*/
|
|
191
|
+
setAmbientStack(stack) {
|
|
192
|
+
if (this._als) {
|
|
193
|
+
if (!this._enterWithUsable) return false;
|
|
194
|
+
this._als.enterWith(stack);
|
|
195
|
+
return true;
|
|
196
|
+
}
|
|
197
|
+
this._syncStack = stack;
|
|
198
|
+
return true;
|
|
199
|
+
}
|
|
200
|
+
push(binding) {
|
|
201
|
+
this.maybeAdoptAsyncLocalStorage();
|
|
202
|
+
if (this._als && !this._enterWithUsable) {
|
|
203
|
+
this.warnNoAmbientBindOnce();
|
|
204
|
+
return;
|
|
205
|
+
}
|
|
206
|
+
let stack = this.getStack();
|
|
207
|
+
if (stack.length >= MAX_BINDING_STACK) {
|
|
208
|
+
stack = stack.filter((b) => b.isLive());
|
|
209
|
+
if (stack.length >= MAX_BINDING_STACK) {
|
|
210
|
+
stack = stack.slice(stack.length - (MAX_BINDING_STACK - 1));
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
this.setAmbientStack([...stack, binding]);
|
|
214
|
+
}
|
|
215
|
+
remove(binding) {
|
|
216
|
+
binding.markDead();
|
|
217
|
+
const stack = this.getStack();
|
|
218
|
+
const pruned = stack.filter((b) => b !== binding && b.isLive());
|
|
219
|
+
if (pruned.length !== stack.length) {
|
|
220
|
+
this.setAmbientStack(pruned);
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
runWith(binding, callback) {
|
|
224
|
+
this.maybeAdoptAsyncLocalStorage();
|
|
225
|
+
if (this._als) {
|
|
226
|
+
return this._als.run([...this.getStack(), binding], callback);
|
|
227
|
+
}
|
|
228
|
+
const previous = this._syncStack;
|
|
229
|
+
this._syncStack = [...previous, binding];
|
|
230
|
+
try {
|
|
231
|
+
return callback();
|
|
232
|
+
} finally {
|
|
233
|
+
this._syncStack = previous;
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
current() {
|
|
237
|
+
const stack = this.getStack();
|
|
238
|
+
if (stack.length === 0) return void 0;
|
|
239
|
+
const top = stack[stack.length - 1];
|
|
240
|
+
if (top.isLive()) return top;
|
|
241
|
+
const pruned = stack.filter((b) => b.isLive());
|
|
242
|
+
this.setAmbientStack(pruned);
|
|
243
|
+
return pruned.length > 0 ? pruned[pruned.length - 1] : void 0;
|
|
244
|
+
}
|
|
245
|
+
warnNoAmbientBindOnce() {
|
|
246
|
+
if (this._warnedNoAmbientBind) return;
|
|
247
|
+
this._warnedNoAmbientBind = true;
|
|
248
|
+
console.warn(this.noAmbientBindWarning);
|
|
249
|
+
}
|
|
250
|
+
};
|
|
251
|
+
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.";
|
|
252
|
+
var ROUTING_STORAGE_KEY = /* @__PURE__ */ Symbol.for("raindrop.tracing.routingContextStorage");
|
|
253
|
+
function routingStorage() {
|
|
254
|
+
const holder = globalThis;
|
|
255
|
+
let storage = holder[ROUTING_STORAGE_KEY];
|
|
256
|
+
if (!storage) {
|
|
257
|
+
storage = new ContextStackStorage(NO_AMBIENT_ROUTING_BIND_WARNING);
|
|
258
|
+
holder[ROUTING_STORAGE_KEY] = storage;
|
|
259
|
+
}
|
|
260
|
+
return storage;
|
|
261
|
+
}
|
|
262
|
+
function currentRoutingBinding() {
|
|
263
|
+
const bound = routingStorage().current();
|
|
264
|
+
if (!bound) return void 0;
|
|
265
|
+
return {
|
|
266
|
+
projectId: bound.projectId,
|
|
267
|
+
authHint: bound.authHint,
|
|
268
|
+
...bound.appGit ? { appGit: bound.appGit } : {},
|
|
269
|
+
...bound.appGitSource ? { appGitSource: bound.appGitSource } : {}
|
|
270
|
+
};
|
|
271
|
+
}
|
|
272
|
+
var APP_COMMIT_SHA = "raindrop.app.commit_sha";
|
|
273
|
+
var APP_COMMIT_DIRTY = "raindrop.app.commit_dirty";
|
|
274
|
+
var APP_BRANCH = "raindrop.app.branch";
|
|
275
|
+
var APP_GIT_KEYS = [APP_COMMIT_SHA, APP_COMMIT_DIRTY, APP_BRANCH];
|
|
276
|
+
var own = (value, key) => Object.prototype.hasOwnProperty.call(value, key);
|
|
277
|
+
function appGitExplicitKeys(properties) {
|
|
278
|
+
const keys = /* @__PURE__ */ new Set();
|
|
279
|
+
if (!properties) return keys;
|
|
280
|
+
for (const key of APP_GIT_KEYS) {
|
|
281
|
+
if (own(properties, key)) keys.add(key);
|
|
282
|
+
}
|
|
283
|
+
return keys;
|
|
284
|
+
}
|
|
285
|
+
function mergeAppGitSnapshot(base, properties, explicitKeys = /* @__PURE__ */ new Set()) {
|
|
286
|
+
try {
|
|
287
|
+
const result = { ...base };
|
|
288
|
+
if (properties && own(properties, APP_COMMIT_SHA) && properties[APP_COMMIT_SHA] !== result[APP_COMMIT_SHA]) {
|
|
289
|
+
if (!explicitKeys.has(APP_COMMIT_DIRTY) && !own(properties, APP_COMMIT_DIRTY)) {
|
|
290
|
+
delete result[APP_COMMIT_DIRTY];
|
|
291
|
+
}
|
|
292
|
+
if (!explicitKeys.has(APP_BRANCH) && !own(properties, APP_BRANCH)) {
|
|
293
|
+
delete result[APP_BRANCH];
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
for (const key of APP_GIT_KEYS) {
|
|
297
|
+
if (properties && own(properties, key)) result[key] = properties[key];
|
|
298
|
+
}
|
|
299
|
+
return Object.freeze(result);
|
|
300
|
+
} catch (e) {
|
|
301
|
+
return Object.freeze({});
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
function validAppCommitSha(value) {
|
|
305
|
+
if (typeof value !== "string" || value.length > 128) return void 0;
|
|
306
|
+
const cleaned = value.trim();
|
|
307
|
+
return /^(?:[a-fA-F0-9]{40}|[a-fA-F0-9]{64})$/.test(cleaned) ? cleaned.toLowerCase() : void 0;
|
|
308
|
+
}
|
|
309
|
+
function shortString(value) {
|
|
310
|
+
if (typeof value !== "string" || value.length > 1024) return void 0;
|
|
311
|
+
const cleaned = value.trim();
|
|
312
|
+
return cleaned.length > 0 ? cleaned : void 0;
|
|
313
|
+
}
|
|
314
|
+
function flag(value) {
|
|
315
|
+
if (value === true || value === "true" || value === "1") return true;
|
|
316
|
+
if (value === false || value === "false" || value === "0") return false;
|
|
317
|
+
return void 0;
|
|
318
|
+
}
|
|
319
|
+
function environment() {
|
|
320
|
+
try {
|
|
321
|
+
return typeof process === "undefined" ? {} : process.env;
|
|
322
|
+
} catch (e) {
|
|
323
|
+
return {};
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
var DEPLOYMENTS = [
|
|
327
|
+
["VERCEL", "VERCEL_GIT_COMMIT_SHA", "VERCEL_GIT_COMMIT_REF"],
|
|
328
|
+
["NETLIFY", "COMMIT_REF", "BRANCH"],
|
|
329
|
+
["RAILWAY_ENVIRONMENT_NAME", "RAILWAY_GIT_COMMIT_SHA", "RAILWAY_GIT_BRANCH"],
|
|
330
|
+
["RAILWAY_ENVIRONMENT", "RAILWAY_GIT_COMMIT_SHA", "RAILWAY_GIT_BRANCH"],
|
|
331
|
+
["RENDER", "RENDER_GIT_COMMIT", "RENDER_GIT_BRANCH"],
|
|
332
|
+
["DYNO", "HEROKU_BUILD_COMMIT", ""],
|
|
333
|
+
["DYNO", "HEROKU_SLUG_COMMIT", ""],
|
|
334
|
+
["AWS_APP_ID", "AWS_COMMIT_ID", "AWS_BRANCH"],
|
|
335
|
+
["WORKERS_CI", "WORKERS_CI_COMMIT_SHA", "WORKERS_CI_BRANCH"]
|
|
336
|
+
];
|
|
337
|
+
var CI_SOURCES = [
|
|
338
|
+
["GITHUB_ACTIONS", "GITHUB_SHA", "GITHUB_REF_NAME"],
|
|
339
|
+
["GITLAB_CI", "CI_COMMIT_SHA", "CI_COMMIT_REF_NAME"],
|
|
340
|
+
["CIRCLECI", "CIRCLE_SHA1", "CIRCLE_BRANCH"]
|
|
341
|
+
];
|
|
342
|
+
function detectedSource(env, table, detectBranch) {
|
|
343
|
+
for (const row of table) {
|
|
344
|
+
const [marker, shaKey, branchKey] = row;
|
|
345
|
+
if (!marker || !shaKey || !shortString(env[marker]) || flag(env[marker]) === false) continue;
|
|
346
|
+
const commitSha = validAppCommitSha(env[shaKey]);
|
|
347
|
+
if (commitSha)
|
|
348
|
+
return {
|
|
349
|
+
commitSha,
|
|
350
|
+
...detectBranch && branchKey ? { branch: shortString(env[branchKey]) } : {}
|
|
351
|
+
};
|
|
352
|
+
}
|
|
353
|
+
return {};
|
|
354
|
+
}
|
|
355
|
+
var AppGitContextImpl = class {
|
|
356
|
+
constructor(options, runtime = {}) {
|
|
357
|
+
this.defaults = {};
|
|
358
|
+
this.explicit = {};
|
|
359
|
+
this.explicitKeys = /* @__PURE__ */ new Set();
|
|
360
|
+
this.disposed = false;
|
|
361
|
+
this.operations = /* @__PURE__ */ new Map();
|
|
362
|
+
this.operationOverflow = false;
|
|
363
|
+
this.detectBranch = false;
|
|
364
|
+
this.disabled = false;
|
|
365
|
+
var _a, _b, _c, _d, _e, _f;
|
|
366
|
+
try {
|
|
367
|
+
if (options === false) {
|
|
368
|
+
this.disabled = true;
|
|
369
|
+
return;
|
|
370
|
+
}
|
|
371
|
+
const opts = options != null ? options : {};
|
|
372
|
+
const env = (_a = runtime.env) != null ? _a : environment();
|
|
373
|
+
const detectBranch = (_c = (_b = flag(opts.detectBranch)) != null ? _b : flag(env.RAINDROP_GIT_DETECT_BRANCH)) != null ? _c : false;
|
|
374
|
+
this.detectBranch = detectBranch;
|
|
375
|
+
const collectBranch = detectBranch || runtime.captureLegacyReplayBranch === true;
|
|
376
|
+
const autoDetect = runtime.allowDiscovery === false ? false : (_e = (_d = flag(opts.autoDetect)) != null ? _d : flag(env.RAINDROP_GIT_AUTO_DETECT)) != null ? _e : true;
|
|
377
|
+
const configuredSha = opts.commitSha;
|
|
378
|
+
const explicitSha = configuredSha === void 0 ? env.RAINDROP_COMMIT_SHA : configuredSha;
|
|
379
|
+
if (explicitSha === null) this.explicit[APP_COMMIT_SHA] = null;
|
|
380
|
+
else if (typeof explicitSha === "string" && validAppCommitSha(explicitSha))
|
|
381
|
+
this.explicit[APP_COMMIT_SHA] = explicitSha;
|
|
382
|
+
const configuredDirty = opts.commitDirty;
|
|
383
|
+
const explicitDirty = configuredDirty === void 0 ? flag(env.RAINDROP_COMMIT_DIRTY) : configuredDirty;
|
|
384
|
+
if (explicitDirty === null || typeof explicitDirty === "boolean")
|
|
385
|
+
this.explicit[APP_COMMIT_DIRTY] = explicitDirty;
|
|
386
|
+
const configuredBranch = opts.branch;
|
|
387
|
+
const explicitBranch = configuredBranch === void 0 ? env.RAINDROP_BRANCH : configuredBranch;
|
|
388
|
+
if (explicitBranch === null) this.explicit[APP_BRANCH] = null;
|
|
389
|
+
else if (typeof explicitBranch === "string" && explicitBranch.length <= 1024)
|
|
390
|
+
this.explicit[APP_BRANCH] = explicitBranch;
|
|
391
|
+
this.explicitKeys = appGitExplicitKeys(this.explicit);
|
|
392
|
+
this.defaults = { ...this.explicit };
|
|
393
|
+
if (!autoDetect || explicitSha !== void 0) return;
|
|
394
|
+
const sourceDirectory = (_f = shortString(opts.sourceDirectory)) != null ? _f : shortString(env.RAINDROP_GIT_SOURCE_DIRECTORY);
|
|
395
|
+
if (runtime.allowLocalGit === false && !sourceDirectory) return;
|
|
396
|
+
const deploy = sourceDirectory ? {} : detectedSource(env, DEPLOYMENTS, collectBranch);
|
|
397
|
+
if (deploy.commitSha) {
|
|
398
|
+
this.accept(deploy);
|
|
399
|
+
return;
|
|
400
|
+
}
|
|
401
|
+
const fallback = sourceDirectory ? {} : detectedSource(env, CI_SOURCES, collectBranch);
|
|
402
|
+
if (runtime.resolveLocal && (runtime.allowLocalGit !== false || sourceDirectory)) {
|
|
403
|
+
this.cancel = runtime.resolveLocal(sourceDirectory, collectBranch, (result) => {
|
|
404
|
+
try {
|
|
405
|
+
if (!this.disposed) this.accept(result.commitSha ? result : fallback);
|
|
406
|
+
} catch (e) {
|
|
407
|
+
}
|
|
408
|
+
});
|
|
409
|
+
} else this.accept(fallback);
|
|
410
|
+
} catch (e) {
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
accept(result) {
|
|
414
|
+
const sha = validAppCommitSha(result.commitSha);
|
|
415
|
+
if (!sha) return;
|
|
416
|
+
this.replayBranch = shortString(result.branch);
|
|
417
|
+
this.defaults = {
|
|
418
|
+
[APP_COMMIT_SHA]: sha,
|
|
419
|
+
...typeof result.commitDirty === "boolean" ? { [APP_COMMIT_DIRTY]: result.commitDirty } : {},
|
|
420
|
+
...this.detectBranch && this.replayBranch ? { [APP_BRANCH]: this.replayBranch } : {},
|
|
421
|
+
...this.explicit
|
|
422
|
+
};
|
|
423
|
+
}
|
|
424
|
+
snapshot(properties) {
|
|
425
|
+
var _a;
|
|
426
|
+
try {
|
|
427
|
+
const binding = currentRoutingBinding();
|
|
428
|
+
const base = this.disabled && (binding == null ? void 0 : binding.appGitSource) !== "replay-override" ? {} : (_a = binding == null ? void 0 : binding.appGit) != null ? _a : this.defaults;
|
|
429
|
+
return this.mergeSnapshot(base, properties);
|
|
430
|
+
} catch (e) {
|
|
431
|
+
return Object.freeze({});
|
|
432
|
+
}
|
|
433
|
+
}
|
|
434
|
+
/** Safe defaults when no operation/span start was observed; never infer identity. */
|
|
435
|
+
snapshotExplicit(properties, eventId) {
|
|
436
|
+
try {
|
|
437
|
+
const base = { ...this.explicit };
|
|
438
|
+
const operation = eventId ? this.operations.get(eventId) : void 0;
|
|
439
|
+
if (operation) {
|
|
440
|
+
for (const key of operation.explicitKeys) base[key] = operation.snapshot[key];
|
|
441
|
+
}
|
|
442
|
+
return this.mergeSnapshot(base, properties, new Set(Object.keys(base)));
|
|
443
|
+
} catch (e) {
|
|
444
|
+
return mergeAppGitSnapshot({}, properties);
|
|
445
|
+
}
|
|
446
|
+
}
|
|
447
|
+
/** Existing replay branch reporting stays separate from opt-in event properties. */
|
|
448
|
+
snapshotForReplay() {
|
|
449
|
+
const snapshot = this.snapshot();
|
|
450
|
+
if (this.replayBranch && !own(snapshot, APP_BRANCH) && snapshot[APP_COMMIT_SHA] === this.defaults[APP_COMMIT_SHA]) {
|
|
451
|
+
return Object.freeze({ ...snapshot, [APP_BRANCH]: this.replayBranch });
|
|
452
|
+
}
|
|
453
|
+
return snapshot;
|
|
454
|
+
}
|
|
455
|
+
/** Merge a frozen span snapshot without losing client-authored provenance. */
|
|
456
|
+
mergeSnapshot(base, properties, explicitKeys = this.explicitKeys) {
|
|
457
|
+
return mergeAppGitSnapshot(base, properties, /* @__PURE__ */ new Set([...this.explicitKeys, ...explicitKeys]));
|
|
458
|
+
}
|
|
459
|
+
/** Shippers belonging to one client share this bounded operation registry. */
|
|
460
|
+
forOperation(eventId, properties, owner) {
|
|
461
|
+
if (!eventId) return this.snapshot(properties);
|
|
462
|
+
let operation = this.operations.get(eventId);
|
|
463
|
+
if (!operation) {
|
|
464
|
+
if (this.operations.size >= 1e4) this.operationOverflow = true;
|
|
465
|
+
if (this.operationOverflow) return this.mergeSnapshot({}, properties);
|
|
466
|
+
operation = {
|
|
467
|
+
snapshot: this.snapshot(properties),
|
|
468
|
+
owners: /* @__PURE__ */ new Set(),
|
|
469
|
+
unowned: owner === void 0,
|
|
470
|
+
explicitKeys: appGitExplicitKeys(properties)
|
|
471
|
+
};
|
|
472
|
+
this.operations.set(eventId, operation);
|
|
473
|
+
} else if (properties && APP_GIT_KEYS.some((key) => own(properties, key))) {
|
|
474
|
+
const explicitKeys = /* @__PURE__ */ new Set([...this.explicitKeys, ...operation.explicitKeys]);
|
|
475
|
+
operation.snapshot = this.mergeSnapshot(operation.snapshot, properties, explicitKeys);
|
|
476
|
+
for (const key of appGitExplicitKeys(properties)) operation.explicitKeys.add(key);
|
|
477
|
+
}
|
|
478
|
+
if (!owner) operation.unowned = true;
|
|
479
|
+
if (owner) operation.owners.add(owner);
|
|
480
|
+
return operation.snapshot;
|
|
481
|
+
}
|
|
482
|
+
releaseOperation(eventId, owner) {
|
|
483
|
+
const operation = this.operations.get(eventId);
|
|
484
|
+
if (!operation) return;
|
|
485
|
+
operation.owners.delete(owner);
|
|
486
|
+
if (operation.owners.size === 0 && !operation.unowned) this.operations.delete(eventId);
|
|
487
|
+
}
|
|
488
|
+
finishOperation(eventId) {
|
|
489
|
+
this.operations.delete(eventId);
|
|
490
|
+
}
|
|
491
|
+
dispose() {
|
|
492
|
+
var _a;
|
|
493
|
+
this.disposed = true;
|
|
494
|
+
try {
|
|
495
|
+
(_a = this.cancel) == null ? void 0 : _a.call(this);
|
|
496
|
+
} catch (e) {
|
|
497
|
+
}
|
|
498
|
+
}
|
|
499
|
+
};
|
|
500
|
+
var AppGitContext = AppGitContextImpl;
|
|
501
|
+
function createAppGitContext(options, runtime = {}) {
|
|
502
|
+
return new AppGitContext(options, runtime);
|
|
503
|
+
}
|
|
504
|
+
function withAppGitProperties(properties, snapshot) {
|
|
505
|
+
try {
|
|
506
|
+
const merged = { ...properties };
|
|
507
|
+
for (const key of APP_GIT_KEYS)
|
|
508
|
+
if (!own(merged, key) && own(snapshot, key)) merged[key] = snapshot[key];
|
|
509
|
+
return merged;
|
|
510
|
+
} catch (e) {
|
|
511
|
+
return properties != null ? properties : {};
|
|
512
|
+
}
|
|
513
|
+
}
|
|
514
|
+
function withAppGitAttributes(attributes, snapshot) {
|
|
515
|
+
try {
|
|
516
|
+
const present = new Set(attributes.flatMap((attr) => attr ? [attr.key] : []));
|
|
517
|
+
const added = [];
|
|
518
|
+
for (const key of APP_GIT_KEYS) {
|
|
519
|
+
if (present.has(key) || present.has(`ai.telemetry.metadata.${key}`) || present.has(`traceloop.association.properties.${key}`))
|
|
520
|
+
continue;
|
|
521
|
+
const value = snapshot[key];
|
|
522
|
+
if (typeof value === "string") added.push({ key, value: { stringValue: value } });
|
|
523
|
+
else if (typeof value === "boolean") added.push({ key, value: { boolValue: value } });
|
|
524
|
+
}
|
|
525
|
+
return added.length ? [...attributes, ...added] : attributes;
|
|
526
|
+
} catch (e) {
|
|
527
|
+
return attributes;
|
|
528
|
+
}
|
|
529
|
+
}
|
|
530
|
+
function appGitPropertiesFromAttributes(attributes) {
|
|
531
|
+
var _a, _b, _c;
|
|
532
|
+
const properties = {};
|
|
533
|
+
try {
|
|
534
|
+
for (const attr of attributes) {
|
|
535
|
+
if (!attr) continue;
|
|
536
|
+
for (const key of APP_GIT_KEYS) {
|
|
537
|
+
if (attr.key === key || attr.key === `ai.telemetry.metadata.${key}` || attr.key === `traceloop.association.properties.${key}`) {
|
|
538
|
+
properties[key] = (_c = (_b = (_a = attr.value.stringValue) != null ? _a : attr.value.boolValue) != null ? _b : attr.value.intValue) != null ? _c : null;
|
|
539
|
+
}
|
|
540
|
+
}
|
|
541
|
+
}
|
|
542
|
+
} catch (e) {
|
|
543
|
+
}
|
|
544
|
+
return properties;
|
|
545
|
+
}
|
|
94
546
|
function getCrypto() {
|
|
95
547
|
const c = globalThis.crypto;
|
|
96
548
|
return c;
|
|
@@ -195,7 +647,7 @@ function runWithTracingSuppressed(fn) {
|
|
|
195
647
|
var DEFAULT_REQUEST_TIMEOUT_MS = 3e4;
|
|
196
648
|
var MAX_RETRY_DELAY_MS = 3e4;
|
|
197
649
|
function wait(ms) {
|
|
198
|
-
return new Promise((
|
|
650
|
+
return new Promise((resolve2) => setTimeout(resolve2, ms));
|
|
199
651
|
}
|
|
200
652
|
function formatEndpoint(endpoint) {
|
|
201
653
|
if (!endpoint) return void 0;
|
|
@@ -232,9 +684,9 @@ async function raceWithTimeout(promise, timeoutMs) {
|
|
|
232
684
|
() => true,
|
|
233
685
|
() => true
|
|
234
686
|
),
|
|
235
|
-
new Promise((
|
|
687
|
+
new Promise((resolve2) => {
|
|
236
688
|
var _a;
|
|
237
|
-
timer = setTimeout(() =>
|
|
689
|
+
timer = setTimeout(() => resolve2(false), Math.max(0, timeoutMs));
|
|
238
690
|
(_a = timer.unref) == null ? void 0 : _a.call(timer);
|
|
239
691
|
})
|
|
240
692
|
]);
|
|
@@ -407,55 +859,6 @@ function buildExportTraceServiceRequest(spans, serviceName = "raindrop.core", se
|
|
|
407
859
|
]
|
|
408
860
|
};
|
|
409
861
|
}
|
|
410
|
-
var STATE_KEY = /* @__PURE__ */ Symbol.for("raindrop.tracing.replayTraceRoutingState");
|
|
411
|
-
function state() {
|
|
412
|
-
const holder = globalThis;
|
|
413
|
-
let current = holder[STATE_KEY];
|
|
414
|
-
if (!current) {
|
|
415
|
-
let storage = null;
|
|
416
|
-
try {
|
|
417
|
-
const Ctor = globalThis.RAINDROP_ASYNC_LOCAL_STORAGE;
|
|
418
|
-
if (Ctor) storage = new Ctor();
|
|
419
|
-
} catch (e) {
|
|
420
|
-
storage = null;
|
|
421
|
-
}
|
|
422
|
-
current = {
|
|
423
|
-
storage,
|
|
424
|
-
syncDestination: void 0,
|
|
425
|
-
spanDestinations: /* @__PURE__ */ new WeakMap()
|
|
426
|
-
};
|
|
427
|
-
holder[STATE_KEY] = current;
|
|
428
|
-
}
|
|
429
|
-
return current;
|
|
430
|
-
}
|
|
431
|
-
function currentReplayTraceDestination() {
|
|
432
|
-
var _a, _b;
|
|
433
|
-
const routing = state();
|
|
434
|
-
return (_b = (_a = routing.storage) == null ? void 0 : _a.getStore()) != null ? _b : routing.syncDestination;
|
|
435
|
-
}
|
|
436
|
-
function rememberReplayTraceDestination(span) {
|
|
437
|
-
const destination = currentReplayTraceDestination();
|
|
438
|
-
if (destination) state().spanDestinations.set(span, destination);
|
|
439
|
-
}
|
|
440
|
-
function copyReplayTraceDestination(source, target) {
|
|
441
|
-
const destination = state().spanDestinations.get(source);
|
|
442
|
-
if (destination) state().spanDestinations.set(target, destination);
|
|
443
|
-
}
|
|
444
|
-
function replayTraceDestinationFor(value) {
|
|
445
|
-
if (typeof value !== "object" && typeof value !== "function" || value === null) {
|
|
446
|
-
return void 0;
|
|
447
|
-
}
|
|
448
|
-
return state().spanDestinations.get(value);
|
|
449
|
-
}
|
|
450
|
-
function recordReplayExportedSpan(destination, spanId, traceId) {
|
|
451
|
-
var _a, _b;
|
|
452
|
-
if (!destination || !spanId || !traceId) return;
|
|
453
|
-
(_a = destination.exportedSpanIds) == null ? void 0 : _a.add(spanId);
|
|
454
|
-
(_b = destination.exportedTraceIds) == null ? void 0 : _b.add(traceId);
|
|
455
|
-
}
|
|
456
|
-
function replayTraceUrl(baseUrl) {
|
|
457
|
-
return `${baseUrl.replace(/\/+$/, "")}/v1/traces`;
|
|
458
|
-
}
|
|
459
862
|
var LOCAL_DEBUGGER_ENV_VAR = "RAINDROP_LOCAL_DEBUGGER";
|
|
460
863
|
var WORKSHOP_ENV_VAR = "RAINDROP_WORKSHOP";
|
|
461
864
|
var DEFAULT_LOCAL_WORKSHOP_URL = "http://localhost:5899/v1/";
|
|
@@ -565,6 +968,13 @@ function projectIdHeaders(projectId) {
|
|
|
565
968
|
}
|
|
566
969
|
var SHUTDOWN_DEADLINE_MS = 1e4;
|
|
567
970
|
var POST_SHUTDOWN_TIMEOUT_MS = 5e3;
|
|
971
|
+
function appGitOwnerId(prefix) {
|
|
972
|
+
try {
|
|
973
|
+
return `${prefix}:${randomUUID()}`;
|
|
974
|
+
} catch (e) {
|
|
975
|
+
return `${prefix}:${Date.now().toString(36)}:${Math.random().toString(36).slice(2)}`;
|
|
976
|
+
}
|
|
977
|
+
}
|
|
568
978
|
function mergePatches(target, source) {
|
|
569
979
|
var _a, _b, _c, _d, _e, _f, _g, _h, _i;
|
|
570
980
|
const out = { ...target, ...source };
|
|
@@ -614,22 +1024,25 @@ function eventTelemetryProperties(patch) {
|
|
|
614
1024
|
}
|
|
615
1025
|
var EventShipper = class {
|
|
616
1026
|
constructor(opts) {
|
|
1027
|
+
this.appGitOwner = appGitOwnerId("event");
|
|
617
1028
|
this.buffers = /* @__PURE__ */ new Map();
|
|
618
1029
|
this.sticky = /* @__PURE__ */ new Map();
|
|
619
1030
|
this.timers = /* @__PURE__ */ new Map();
|
|
620
1031
|
this.inFlight = /* @__PURE__ */ new Set();
|
|
621
1032
|
this.hasShutdown = false;
|
|
622
|
-
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
623
|
-
this.
|
|
624
|
-
this.
|
|
1033
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _i;
|
|
1034
|
+
this.appGitContext = (_a = opts.appGitContext) != null ? _a : createAppGitContext(opts.appGit);
|
|
1035
|
+
this.ownsAppGitContext = opts.appGitContext === void 0;
|
|
1036
|
+
this.writeKey = (_b = opts.writeKey) == null ? void 0 : _b.trim();
|
|
1037
|
+
this.baseUrl = (_c = formatEndpoint(opts.endpoint)) != null ? _c : "https://api.raindrop.ai/v1/";
|
|
625
1038
|
this.enabled = opts.enabled !== false;
|
|
626
1039
|
this.debug = opts.debug;
|
|
627
|
-
this.partialFlushMs = (
|
|
628
|
-
this.sdkName = (
|
|
1040
|
+
this.partialFlushMs = (_d = opts.partialFlushMs) != null ? _d : 1e3;
|
|
1041
|
+
this.sdkName = (_e = opts.sdkName) != null ? _e : "core";
|
|
629
1042
|
this.prefix = `[raindrop-ai/${this.sdkName}]`;
|
|
630
|
-
this.defaultEventName = (
|
|
1043
|
+
this.defaultEventName = (_f = opts.defaultEventName) != null ? _f : "ai_generation";
|
|
631
1044
|
this.maxTextFieldCharsOpt = opts.maxTextFieldChars;
|
|
632
|
-
this.localDebuggerUrl = (
|
|
1045
|
+
this.localDebuggerUrl = (_g = resolveLocalDebuggerBaseUrl(opts.localDebuggerUrl)) != null ? _g : void 0;
|
|
633
1046
|
if (this.debug && this.localDebuggerUrl) {
|
|
634
1047
|
console.log(`${this.prefix} Local debugger mirroring: ${this.localDebuggerUrl}`);
|
|
635
1048
|
}
|
|
@@ -640,8 +1053,8 @@ var EventShipper = class {
|
|
|
640
1053
|
const isNode = typeof process !== "undefined" && typeof process.version === "string";
|
|
641
1054
|
this.context = {
|
|
642
1055
|
library: {
|
|
643
|
-
name: (
|
|
644
|
-
version: (
|
|
1056
|
+
name: (_h = opts.libraryName) != null ? _h : "@raindrop-ai/core",
|
|
1057
|
+
version: (_i = opts.libraryVersion) != null ? _i : "0.0.0"
|
|
645
1058
|
},
|
|
646
1059
|
metadata: {
|
|
647
1060
|
jsRuntime: isNode ? "node" : "web",
|
|
@@ -649,6 +1062,9 @@ var EventShipper = class {
|
|
|
649
1062
|
}
|
|
650
1063
|
};
|
|
651
1064
|
}
|
|
1065
|
+
ownAppGitContextForShutdown() {
|
|
1066
|
+
this.ownsAppGitContext = true;
|
|
1067
|
+
}
|
|
652
1068
|
isDebugEnabled() {
|
|
653
1069
|
return this.debug;
|
|
654
1070
|
}
|
|
@@ -727,6 +1143,13 @@ var EventShipper = class {
|
|
|
727
1143
|
}
|
|
728
1144
|
const sticky = (_c = this.sticky.get(eventId)) != null ? _c : {};
|
|
729
1145
|
const existing = (_d = this.buffers.get(eventId)) != null ? _d : {};
|
|
1146
|
+
patch = {
|
|
1147
|
+
...patch,
|
|
1148
|
+
properties: withAppGitProperties(
|
|
1149
|
+
patch.properties,
|
|
1150
|
+
this.appGitContext.forOperation(eventId, patch.properties, this.appGitOwner)
|
|
1151
|
+
)
|
|
1152
|
+
};
|
|
730
1153
|
const merged = mergePatches(existing, patch);
|
|
731
1154
|
merged.isPending = (_g = (_f = (_e = patch.isPending) != null ? _e : existing.isPending) != null ? _f : sticky.isPending) != null ? _g : true;
|
|
732
1155
|
this.buffers.set(eventId, merged);
|
|
@@ -740,6 +1163,8 @@ var EventShipper = class {
|
|
|
740
1163
|
if (t) clearTimeout(t);
|
|
741
1164
|
if (merged.isPending === false) {
|
|
742
1165
|
await this.flushOne(eventId);
|
|
1166
|
+
if (this.appGitContext.releaseOperation) this.appGitContext.releaseOperation(eventId, this.appGitOwner);
|
|
1167
|
+
else this.appGitContext.finishOperation(eventId);
|
|
743
1168
|
return;
|
|
744
1169
|
}
|
|
745
1170
|
const timeout = setTimeout(() => {
|
|
@@ -771,6 +1196,7 @@ var EventShipper = class {
|
|
|
771
1196
|
if (!settled) this.warnShutdownDrop("in-flight request(s) at shutdown");
|
|
772
1197
|
} finally {
|
|
773
1198
|
this.shutdownDeadlineAt = void 0;
|
|
1199
|
+
if (this.ownsAppGitContext) this.appGitContext.dispose();
|
|
774
1200
|
}
|
|
775
1201
|
}
|
|
776
1202
|
async trackSignal(signal) {
|
|
@@ -1198,6 +1624,13 @@ function redactJsonAttributeValue(key, value) {
|
|
|
1198
1624
|
if (scrubbedJson === json) return void 0;
|
|
1199
1625
|
return { stringValue: scrubbedJson };
|
|
1200
1626
|
}
|
|
1627
|
+
function appGitOwnerId2(prefix) {
|
|
1628
|
+
try {
|
|
1629
|
+
return `${prefix}:${randomUUID()}`;
|
|
1630
|
+
} catch (e) {
|
|
1631
|
+
return `${prefix}:${Date.now().toString(36)}:${Math.random().toString(36).slice(2)}`;
|
|
1632
|
+
}
|
|
1633
|
+
}
|
|
1201
1634
|
function identityAttrs(args) {
|
|
1202
1635
|
return [
|
|
1203
1636
|
attrString("ai.telemetry.metadata.raindrop.ai.userId", args.userId),
|
|
@@ -1220,23 +1653,30 @@ function applyOtelSpanAttributeLimit(limit) {
|
|
|
1220
1653
|
}
|
|
1221
1654
|
var TraceShipper = class {
|
|
1222
1655
|
constructor(opts) {
|
|
1656
|
+
this.appGitOwner = appGitOwnerId2("trace");
|
|
1657
|
+
this.appGitEventIds = /* @__PURE__ */ new WeakMap();
|
|
1658
|
+
this.appGitActiveSpans = /* @__PURE__ */ new Map();
|
|
1659
|
+
this.appGitCaptured = /* @__PURE__ */ new WeakSet();
|
|
1660
|
+
this.appGitAdded = /* @__PURE__ */ new WeakMap();
|
|
1223
1661
|
this.queue = [];
|
|
1224
1662
|
this.inFlight = /* @__PURE__ */ new Set();
|
|
1225
1663
|
this.hasShutdown = false;
|
|
1226
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _i;
|
|
1227
|
-
this.
|
|
1228
|
-
this.
|
|
1664
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j;
|
|
1665
|
+
this.appGitContext = (_a = opts.appGitContext) != null ? _a : createAppGitContext(opts.appGit);
|
|
1666
|
+
this.ownsAppGitContext = opts.appGitContext === void 0;
|
|
1667
|
+
this.writeKey = (_b = opts.writeKey) == null ? void 0 : _b.trim();
|
|
1668
|
+
this.baseUrl = (_c = formatEndpoint(opts.endpoint)) != null ? _c : "https://api.raindrop.ai/v1/";
|
|
1229
1669
|
this.enabled = opts.enabled !== false;
|
|
1230
1670
|
this.debug = opts.debug;
|
|
1231
1671
|
this.debugSpans = opts.debugSpans === true;
|
|
1232
|
-
this.flushIntervalMs = (
|
|
1233
|
-
this.maxBatchSize = (
|
|
1234
|
-
this.maxQueueSize = (
|
|
1235
|
-
this.sdkName = (
|
|
1672
|
+
this.flushIntervalMs = (_d = opts.flushIntervalMs) != null ? _d : 1e3;
|
|
1673
|
+
this.maxBatchSize = (_e = opts.maxBatchSize) != null ? _e : 50;
|
|
1674
|
+
this.maxQueueSize = (_f = opts.maxQueueSize) != null ? _f : 5e3;
|
|
1675
|
+
this.sdkName = (_g = opts.sdkName) != null ? _g : "core";
|
|
1236
1676
|
this.prefix = `[raindrop-ai/${this.sdkName}]`;
|
|
1237
|
-
this.serviceName = (
|
|
1238
|
-
this.serviceVersion = (
|
|
1239
|
-
this.localDebuggerUrl = (
|
|
1677
|
+
this.serviceName = (_h = opts.serviceName) != null ? _h : "raindrop.core";
|
|
1678
|
+
this.serviceVersion = (_i = opts.serviceVersion) != null ? _i : "0.0.0";
|
|
1679
|
+
this.localDebuggerUrl = (_j = resolveLocalDebuggerBaseUrl(opts.localDebuggerUrl)) != null ? _j : void 0;
|
|
1240
1680
|
if (this.debug && this.localDebuggerUrl) {
|
|
1241
1681
|
console.log(`${this.prefix} Local debugger mirroring: ${this.localDebuggerUrl}`);
|
|
1242
1682
|
}
|
|
@@ -1337,7 +1777,7 @@ var TraceShipper = class {
|
|
|
1337
1777
|
return { ...this.authHeaders(), ...projectIdHeaders(this.projectId) };
|
|
1338
1778
|
}
|
|
1339
1779
|
startSpan(args) {
|
|
1340
|
-
var _a, _b;
|
|
1780
|
+
var _a, _b, _c;
|
|
1341
1781
|
const ids = createSpanIds(args.parent);
|
|
1342
1782
|
const started = (_a = args.startTimeUnixNano) != null ? _a : nowUnixNanoString();
|
|
1343
1783
|
const attrs = [
|
|
@@ -1347,13 +1787,24 @@ var TraceShipper = class {
|
|
|
1347
1787
|
...Object.entries(evalScopeAttributes()).map(([key, value]) => attrString(key, value))
|
|
1348
1788
|
];
|
|
1349
1789
|
if ((_b = args.attributes) == null ? void 0 : _b.length) attrs.push(...args.attributes);
|
|
1790
|
+
const tracksAppGit = this.appGitActiveSpans.has(args.eventId) || this.appGitActiveSpans.size < 1e4;
|
|
1791
|
+
const appGitOverrides = appGitPropertiesFromAttributes(attrs);
|
|
1350
1792
|
const span = {
|
|
1351
1793
|
ids,
|
|
1352
1794
|
name: args.name,
|
|
1353
1795
|
startTimeUnixNano: started,
|
|
1354
|
-
attributes:
|
|
1796
|
+
attributes: withAppGitAttributes(
|
|
1797
|
+
attrs,
|
|
1798
|
+
this.appGitContext.forOperation(args.eventId, appGitOverrides, this.appGitOwner)
|
|
1799
|
+
)
|
|
1355
1800
|
};
|
|
1356
1801
|
rememberReplayTraceDestination(span);
|
|
1802
|
+
this.appGitCaptured.add(span);
|
|
1803
|
+
this.appGitEventIds.set(span, args.eventId);
|
|
1804
|
+
if (tracksAppGit) {
|
|
1805
|
+
this.appGitActiveSpans.set(args.eventId, ((_c = this.appGitActiveSpans.get(args.eventId)) != null ? _c : 0) + 1);
|
|
1806
|
+
}
|
|
1807
|
+
this.appGitAdded.set(span, new Set(span.attributes.filter((attr) => !attrs.includes(attr))));
|
|
1357
1808
|
const openSpan = buildOtlpSpan({
|
|
1358
1809
|
ids: span.ids,
|
|
1359
1810
|
name: span.name,
|
|
@@ -1393,11 +1844,17 @@ var TraceShipper = class {
|
|
|
1393
1844
|
});
|
|
1394
1845
|
}
|
|
1395
1846
|
endSpan(span, extra) {
|
|
1396
|
-
var _a, _b;
|
|
1847
|
+
var _a, _b, _c;
|
|
1397
1848
|
if (span.endTimeUnixNano) return;
|
|
1398
1849
|
span.endTimeUnixNano = (_a = extra == null ? void 0 : extra.endTimeUnixNano) != null ? _a : nowUnixNanoString();
|
|
1399
1850
|
if ((_b = extra == null ? void 0 : extra.attributes) == null ? void 0 : _b.length) {
|
|
1851
|
+
const overrides = appGitPropertiesFromAttributes(extra.attributes);
|
|
1852
|
+
const eventId2 = this.appGitEventIds.get(span);
|
|
1853
|
+
const snapshot = eventId2 ? this.appGitContext.forOperation(eventId2, overrides, this.appGitOwner) : overrides;
|
|
1854
|
+
const added = this.appGitAdded.get(span);
|
|
1855
|
+
span.attributes = span.attributes.filter((attr) => !(added == null ? void 0 : added.has(attr)) || !attr || !Object.prototype.hasOwnProperty.call(overrides, APP_COMMIT_SHA) && !Object.prototype.hasOwnProperty.call(overrides, attr.key));
|
|
1400
1856
|
span.attributes.push(...extra.attributes);
|
|
1857
|
+
span.attributes = withAppGitAttributes(span.attributes, snapshot);
|
|
1401
1858
|
}
|
|
1402
1859
|
let status = extra == null ? void 0 : extra.status;
|
|
1403
1860
|
if (!status && (extra == null ? void 0 : extra.error) !== void 0) {
|
|
@@ -1413,8 +1870,19 @@ var TraceShipper = class {
|
|
|
1413
1870
|
status
|
|
1414
1871
|
});
|
|
1415
1872
|
copyReplayTraceDestination(span, otlp);
|
|
1873
|
+
this.appGitCaptured.add(otlp);
|
|
1416
1874
|
this.enqueue(otlp);
|
|
1417
1875
|
this.mirrorToLocalDebugger(otlp, true);
|
|
1876
|
+
const eventId = this.appGitEventIds.get(span);
|
|
1877
|
+
if (eventId && this.appGitActiveSpans.has(eventId)) {
|
|
1878
|
+
const remaining = ((_c = this.appGitActiveSpans.get(eventId)) != null ? _c : 1) - 1;
|
|
1879
|
+
if (remaining > 0) this.appGitActiveSpans.set(eventId, remaining);
|
|
1880
|
+
else {
|
|
1881
|
+
this.appGitActiveSpans.delete(eventId);
|
|
1882
|
+
if (this.appGitContext.releaseOperation) this.appGitContext.releaseOperation(eventId, this.appGitOwner);
|
|
1883
|
+
else if (this.ownsAppGitContext) this.appGitContext.finishOperation(eventId);
|
|
1884
|
+
}
|
|
1885
|
+
}
|
|
1418
1886
|
}
|
|
1419
1887
|
createSpan(args) {
|
|
1420
1888
|
var _a;
|
|
@@ -1425,20 +1893,41 @@ var TraceShipper = class {
|
|
|
1425
1893
|
...Object.entries(evalScopeAttributes()).map(([key, value]) => attrString(key, value))
|
|
1426
1894
|
];
|
|
1427
1895
|
if ((_a = args.attributes) == null ? void 0 : _a.length) attrs.push(...args.attributes);
|
|
1896
|
+
const tracksAppGit = !this.appGitActiveSpans.has(args.eventId);
|
|
1428
1897
|
const otlp = buildOtlpSpan({
|
|
1429
1898
|
ids,
|
|
1430
1899
|
name: args.name,
|
|
1431
1900
|
startTimeUnixNano: args.startTimeUnixNano,
|
|
1432
1901
|
endTimeUnixNano: args.endTimeUnixNano,
|
|
1433
|
-
attributes:
|
|
1902
|
+
attributes: withAppGitAttributes(
|
|
1903
|
+
attrs,
|
|
1904
|
+
this.appGitContext.forOperation(
|
|
1905
|
+
args.eventId,
|
|
1906
|
+
appGitPropertiesFromAttributes(attrs),
|
|
1907
|
+
this.appGitOwner
|
|
1908
|
+
)
|
|
1909
|
+
),
|
|
1434
1910
|
status: args.status
|
|
1435
1911
|
});
|
|
1436
1912
|
rememberReplayTraceDestination(otlp);
|
|
1913
|
+
this.appGitCaptured.add(otlp);
|
|
1914
|
+
if (tracksAppGit) {
|
|
1915
|
+
if (this.appGitContext.releaseOperation) this.appGitContext.releaseOperation(args.eventId, this.appGitOwner);
|
|
1916
|
+
else if (this.ownsAppGitContext) this.appGitContext.finishOperation(args.eventId);
|
|
1917
|
+
}
|
|
1437
1918
|
this.enqueue(otlp);
|
|
1438
1919
|
this.mirrorToLocalDebugger(otlp, true);
|
|
1439
1920
|
}
|
|
1440
1921
|
enqueue(span) {
|
|
1922
|
+
var _a;
|
|
1441
1923
|
if (!this.enabled) return;
|
|
1924
|
+
const attributes = (_a = span.attributes) != null ? _a : [];
|
|
1925
|
+
const enriched = this.appGitCaptured.has(span) ? attributes : withAppGitAttributes(attributes, this.appGitContext.snapshot(appGitPropertiesFromAttributes(attributes)));
|
|
1926
|
+
if (enriched !== attributes) {
|
|
1927
|
+
const original = span;
|
|
1928
|
+
span = { ...span, attributes: enriched.filter((attr) => attr !== void 0) };
|
|
1929
|
+
copyReplayTraceDestination(original, span);
|
|
1930
|
+
}
|
|
1442
1931
|
if (this.debugSpans) {
|
|
1443
1932
|
const short = (s) => s ? s.slice(-8) : "none";
|
|
1444
1933
|
console.log(
|
|
@@ -1584,12 +2073,158 @@ var TraceShipper = class {
|
|
|
1584
2073
|
}
|
|
1585
2074
|
} finally {
|
|
1586
2075
|
this.shutdownDeadlineAt = void 0;
|
|
2076
|
+
if (this.ownsAppGitContext) this.appGitContext.dispose();
|
|
1587
2077
|
}
|
|
1588
2078
|
}
|
|
1589
2079
|
};
|
|
1590
2080
|
|
|
1591
2081
|
// ../core/dist/index.node.js
|
|
1592
2082
|
var import_async_hooks = require("async_hooks");
|
|
2083
|
+
var import_child_process = require("child_process");
|
|
2084
|
+
var import_path = require("path");
|
|
2085
|
+
var resolveLocal = (sourceDirectory, detectBranch, completed) => {
|
|
2086
|
+
const cwd = sourceDirectory ? (0, import_path.resolve)(sourceDirectory) : process.cwd();
|
|
2087
|
+
let cancelled = false;
|
|
2088
|
+
let active;
|
|
2089
|
+
let deadlineTimer;
|
|
2090
|
+
const deadline = Date.now() + 1e3;
|
|
2091
|
+
const run = (args, done) => {
|
|
2092
|
+
if (cancelled) return;
|
|
2093
|
+
const remaining = deadline - Date.now();
|
|
2094
|
+
if (remaining <= 0) {
|
|
2095
|
+
done(void 0);
|
|
2096
|
+
return;
|
|
2097
|
+
}
|
|
2098
|
+
try {
|
|
2099
|
+
active = (0, import_child_process.execFile)(
|
|
2100
|
+
"git",
|
|
2101
|
+
args,
|
|
2102
|
+
{
|
|
2103
|
+
cwd,
|
|
2104
|
+
encoding: "utf8",
|
|
2105
|
+
maxBuffer: 4096,
|
|
2106
|
+
windowsHide: true,
|
|
2107
|
+
env: {
|
|
2108
|
+
...process.env,
|
|
2109
|
+
// The selected application cwd, not the invoking shell's Git plumbing, owns identity.
|
|
2110
|
+
GIT_DIR: void 0,
|
|
2111
|
+
GIT_WORK_TREE: void 0,
|
|
2112
|
+
GIT_COMMON_DIR: void 0,
|
|
2113
|
+
GIT_NAMESPACE: void 0,
|
|
2114
|
+
GIT_INDEX_FILE: void 0,
|
|
2115
|
+
GIT_OBJECT_DIRECTORY: void 0,
|
|
2116
|
+
GIT_ALTERNATE_OBJECT_DIRECTORIES: void 0,
|
|
2117
|
+
GIT_CONFIG_PARAMETERS: void 0,
|
|
2118
|
+
GIT_CONFIG_COUNT: "0",
|
|
2119
|
+
GIT_TERMINAL_PROMPT: "0",
|
|
2120
|
+
GIT_OPTIONAL_LOCKS: "0"
|
|
2121
|
+
}
|
|
2122
|
+
},
|
|
2123
|
+
(error, stdout) => {
|
|
2124
|
+
clearTimeout(deadlineTimer);
|
|
2125
|
+
deadlineTimer = void 0;
|
|
2126
|
+
active = void 0;
|
|
2127
|
+
if (!cancelled) {
|
|
2128
|
+
try {
|
|
2129
|
+
done(error ? void 0 : stdout.trim());
|
|
2130
|
+
} catch (e) {
|
|
2131
|
+
}
|
|
2132
|
+
}
|
|
2133
|
+
}
|
|
2134
|
+
);
|
|
2135
|
+
active.unref();
|
|
2136
|
+
if (active.stdout && "unref" in active.stdout && typeof active.stdout.unref === "function")
|
|
2137
|
+
active.stdout.unref();
|
|
2138
|
+
if (active.stderr && "unref" in active.stderr && typeof active.stderr.unref === "function")
|
|
2139
|
+
active.stderr.unref();
|
|
2140
|
+
deadlineTimer = setTimeout(() => {
|
|
2141
|
+
try {
|
|
2142
|
+
active == null ? void 0 : active.kill("SIGKILL");
|
|
2143
|
+
} catch (e) {
|
|
2144
|
+
}
|
|
2145
|
+
}, remaining);
|
|
2146
|
+
deadlineTimer.unref();
|
|
2147
|
+
} catch (e) {
|
|
2148
|
+
try {
|
|
2149
|
+
done(void 0);
|
|
2150
|
+
} catch (e2) {
|
|
2151
|
+
}
|
|
2152
|
+
}
|
|
2153
|
+
};
|
|
2154
|
+
const scheduled = setTimeout(() => {
|
|
2155
|
+
try {
|
|
2156
|
+
run(["rev-parse", "HEAD"], (rawSha) => {
|
|
2157
|
+
const commitSha = validAppCommitSha(rawSha);
|
|
2158
|
+
if (!commitSha) {
|
|
2159
|
+
completed({});
|
|
2160
|
+
return;
|
|
2161
|
+
}
|
|
2162
|
+
run(["-c", "core.fsmonitor=false", "status", "--porcelain"], (status) => {
|
|
2163
|
+
const finish = (branch) => {
|
|
2164
|
+
run(["rev-parse", "HEAD"], (finalSha) => {
|
|
2165
|
+
const coherent = validAppCommitSha(finalSha) === commitSha;
|
|
2166
|
+
completed({
|
|
2167
|
+
commitSha,
|
|
2168
|
+
...coherent && status !== void 0 ? { commitDirty: status !== "" } : {},
|
|
2169
|
+
...coherent && branch && branch !== "HEAD" ? { branch } : {}
|
|
2170
|
+
});
|
|
2171
|
+
});
|
|
2172
|
+
};
|
|
2173
|
+
if (detectBranch) run(["symbolic-ref", "--quiet", "--short", "HEAD"], finish);
|
|
2174
|
+
else finish();
|
|
2175
|
+
});
|
|
2176
|
+
});
|
|
2177
|
+
} catch (e) {
|
|
2178
|
+
completed({});
|
|
2179
|
+
}
|
|
2180
|
+
}, 0);
|
|
2181
|
+
scheduled.unref();
|
|
2182
|
+
return () => {
|
|
2183
|
+
cancelled = true;
|
|
2184
|
+
clearTimeout(scheduled);
|
|
2185
|
+
clearTimeout(deadlineTimer);
|
|
2186
|
+
try {
|
|
2187
|
+
active == null ? void 0 : active.kill("SIGKILL");
|
|
2188
|
+
} catch (e) {
|
|
2189
|
+
}
|
|
2190
|
+
};
|
|
2191
|
+
};
|
|
2192
|
+
function createAppGitContext2(options, runtime = {}) {
|
|
2193
|
+
return new AppGitContext(options, { ...runtime, resolveLocal });
|
|
2194
|
+
}
|
|
2195
|
+
function hasDestination(options) {
|
|
2196
|
+
var _a;
|
|
2197
|
+
if (options.enabled === false) return false;
|
|
2198
|
+
return Boolean(((_a = options.writeKey) == null ? void 0 : _a.trim()) || resolveLocalDebuggerBaseUrl(options.localDebuggerUrl));
|
|
2199
|
+
}
|
|
2200
|
+
var EventShipper2 = class extends EventShipper {
|
|
2201
|
+
constructor(options) {
|
|
2202
|
+
var _a;
|
|
2203
|
+
const ownsAppGitContext = options.appGitContext === void 0;
|
|
2204
|
+
const appGitContext = (_a = options.appGitContext) != null ? _a : createAppGitContext2(options.appGit, { allowDiscovery: hasDestination(options) });
|
|
2205
|
+
try {
|
|
2206
|
+
super({ ...options, appGitContext });
|
|
2207
|
+
} catch (error) {
|
|
2208
|
+
if (ownsAppGitContext) appGitContext.dispose();
|
|
2209
|
+
throw error;
|
|
2210
|
+
}
|
|
2211
|
+
if (ownsAppGitContext) this.ownAppGitContextForShutdown();
|
|
2212
|
+
}
|
|
2213
|
+
};
|
|
2214
|
+
var TraceShipper2 = class extends TraceShipper {
|
|
2215
|
+
constructor(options) {
|
|
2216
|
+
var _a;
|
|
2217
|
+
const ownsAppGitContext = options.appGitContext === void 0;
|
|
2218
|
+
const appGitContext = (_a = options.appGitContext) != null ? _a : createAppGitContext2(options.appGit, { allowDiscovery: hasDestination(options) });
|
|
2219
|
+
try {
|
|
2220
|
+
super({ ...options, appGitContext });
|
|
2221
|
+
} catch (error) {
|
|
2222
|
+
if (ownsAppGitContext) appGitContext.dispose();
|
|
2223
|
+
throw error;
|
|
2224
|
+
}
|
|
2225
|
+
this.ownsAppGitContext = ownsAppGitContext;
|
|
2226
|
+
}
|
|
2227
|
+
};
|
|
1593
2228
|
globalThis.RAINDROP_ASYNC_LOCAL_STORAGE = import_async_hooks.AsyncLocalStorage;
|
|
1594
2229
|
var SUPPRESS_TRACING_KEY = /* @__PURE__ */ Symbol.for(
|
|
1595
2230
|
"OpenTelemetry SDK Context Key SUPPRESS_TRACING"
|
|
@@ -1617,6 +2252,463 @@ function installTracingSuppressionHook() {
|
|
|
1617
2252
|
}
|
|
1618
2253
|
installTracingSuppressionHook();
|
|
1619
2254
|
|
|
2255
|
+
// src/conversation.ts
|
|
2256
|
+
var import_messages = require("@langchain/core/messages");
|
|
2257
|
+
|
|
2258
|
+
// src/truncation.ts
|
|
2259
|
+
var TRUNCATION_MARKER2 = "...[truncated by raindrop]";
|
|
2260
|
+
var DEFAULT_MAX_TEXT_FIELD_CHARS2 = 1e6;
|
|
2261
|
+
var MAX_DEPTH = 12;
|
|
2262
|
+
var configuredMaxTextFieldChars;
|
|
2263
|
+
function setMaxTextFieldChars(limit) {
|
|
2264
|
+
if (limit === void 0) return;
|
|
2265
|
+
if (typeof limit === "number" && Number.isFinite(limit) && limit > 0) {
|
|
2266
|
+
configuredMaxTextFieldChars = Math.floor(limit);
|
|
2267
|
+
} else {
|
|
2268
|
+
console.warn(`[raindrop-ai] maxTextFieldChars=${String(limit)} ignored; must be > 0`);
|
|
2269
|
+
}
|
|
2270
|
+
}
|
|
2271
|
+
function otelEnvLimit() {
|
|
2272
|
+
if (typeof process === "undefined") return void 0;
|
|
2273
|
+
const raw = process.env?.OTEL_SPAN_ATTRIBUTE_VALUE_LENGTH_LIMIT;
|
|
2274
|
+
if (!raw) return void 0;
|
|
2275
|
+
const parsed = Number.parseInt(raw, 10);
|
|
2276
|
+
return Number.isFinite(parsed) && parsed > 0 ? parsed : void 0;
|
|
2277
|
+
}
|
|
2278
|
+
function eventMaxTextFieldChars() {
|
|
2279
|
+
return configuredMaxTextFieldChars ?? DEFAULT_MAX_TEXT_FIELD_CHARS2;
|
|
2280
|
+
}
|
|
2281
|
+
function spanAttributeLimit(limit) {
|
|
2282
|
+
const env = otelEnvLimit();
|
|
2283
|
+
return env !== void 0 && env < limit ? env : limit;
|
|
2284
|
+
}
|
|
2285
|
+
function effectiveMaxTextFieldChars() {
|
|
2286
|
+
return spanAttributeLimit(eventMaxTextFieldChars());
|
|
2287
|
+
}
|
|
2288
|
+
function truncateToLimit2(text, limit) {
|
|
2289
|
+
if (limit > TRUNCATION_MARKER2.length) {
|
|
2290
|
+
return text.slice(0, limit - TRUNCATION_MARKER2.length) + TRUNCATION_MARKER2;
|
|
2291
|
+
}
|
|
2292
|
+
return text.slice(0, limit);
|
|
2293
|
+
}
|
|
2294
|
+
function capText2(value, limit) {
|
|
2295
|
+
if (typeof value !== "string") return value;
|
|
2296
|
+
const max = limit ?? effectiveMaxTextFieldChars();
|
|
2297
|
+
if (value.length <= max) return value;
|
|
2298
|
+
return truncateToLimit2(value, max);
|
|
2299
|
+
}
|
|
2300
|
+
function boundedClone2(value, budget, depth) {
|
|
2301
|
+
if (budget.remaining <= 0) return TRUNCATION_MARKER2;
|
|
2302
|
+
if (typeof value === "string") {
|
|
2303
|
+
if (value.length > budget.remaining) {
|
|
2304
|
+
const taken = value.slice(0, Math.max(0, budget.remaining)) + TRUNCATION_MARKER2;
|
|
2305
|
+
budget.remaining = 0;
|
|
2306
|
+
return taken;
|
|
2307
|
+
}
|
|
2308
|
+
budget.remaining -= Math.max(value.length, 1);
|
|
2309
|
+
return value;
|
|
2310
|
+
}
|
|
2311
|
+
if (value === null || typeof value === "number" || typeof value === "boolean") {
|
|
2312
|
+
budget.remaining -= 8;
|
|
2313
|
+
return value;
|
|
2314
|
+
}
|
|
2315
|
+
if (typeof value === "bigint") return boundedClone2(value.toString(), budget, depth);
|
|
2316
|
+
if (typeof value !== "object") {
|
|
2317
|
+
budget.remaining -= 1;
|
|
2318
|
+
return value;
|
|
2319
|
+
}
|
|
2320
|
+
if (value instanceof Uint8Array) {
|
|
2321
|
+
const maxBytes = Math.max(0, Math.ceil(budget.remaining * 3 / 4));
|
|
2322
|
+
if (value.byteLength > maxBytes) {
|
|
2323
|
+
const taken = base64Encode(value.subarray(0, maxBytes)) + TRUNCATION_MARKER2;
|
|
2324
|
+
budget.remaining = 0;
|
|
2325
|
+
return taken;
|
|
2326
|
+
}
|
|
2327
|
+
const encoded = base64Encode(value);
|
|
2328
|
+
budget.remaining -= Math.max(encoded.length, 1);
|
|
2329
|
+
return encoded;
|
|
2330
|
+
}
|
|
2331
|
+
if (depth >= MAX_DEPTH) {
|
|
2332
|
+
budget.remaining -= 16;
|
|
2333
|
+
const name = value.constructor?.name ?? "object";
|
|
2334
|
+
return `<max depth: ${name}>`;
|
|
2335
|
+
}
|
|
2336
|
+
const toJSON = value.toJSON;
|
|
2337
|
+
if (typeof toJSON === "function") {
|
|
2338
|
+
budget.remaining -= 2;
|
|
2339
|
+
return boundedClone2(toJSON.call(value), budget, depth + 1);
|
|
2340
|
+
}
|
|
2341
|
+
if (Array.isArray(value)) {
|
|
2342
|
+
budget.remaining -= 2;
|
|
2343
|
+
const out2 = [];
|
|
2344
|
+
for (const item of value) {
|
|
2345
|
+
if (budget.remaining <= 0) {
|
|
2346
|
+
out2.push(TRUNCATION_MARKER2);
|
|
2347
|
+
break;
|
|
2348
|
+
}
|
|
2349
|
+
out2.push(boundedClone2(item, budget, depth + 1));
|
|
2350
|
+
}
|
|
2351
|
+
return out2;
|
|
2352
|
+
}
|
|
2353
|
+
budget.remaining -= 2;
|
|
2354
|
+
const out = {};
|
|
2355
|
+
for (const key in value) {
|
|
2356
|
+
if (!Object.prototype.hasOwnProperty.call(value, key)) continue;
|
|
2357
|
+
if (budget.remaining <= 0) {
|
|
2358
|
+
out["..."] = TRUNCATION_MARKER2;
|
|
2359
|
+
break;
|
|
2360
|
+
}
|
|
2361
|
+
let cappedKey = key;
|
|
2362
|
+
if (key.length > budget.remaining) {
|
|
2363
|
+
cappedKey = key.slice(0, Math.max(0, budget.remaining)) + TRUNCATION_MARKER2;
|
|
2364
|
+
budget.remaining = 0;
|
|
2365
|
+
out[cappedKey] = TRUNCATION_MARKER2;
|
|
2366
|
+
break;
|
|
2367
|
+
}
|
|
2368
|
+
budget.remaining -= Math.max(key.length, 1);
|
|
2369
|
+
out[cappedKey] = boundedClone2(value[key], budget, depth + 1);
|
|
2370
|
+
}
|
|
2371
|
+
return out;
|
|
2372
|
+
}
|
|
2373
|
+
function boundedStringify(value, limit) {
|
|
2374
|
+
const max = limit ?? effectiveMaxTextFieldChars();
|
|
2375
|
+
try {
|
|
2376
|
+
if (typeof value === "string") {
|
|
2377
|
+
const text2 = JSON.stringify(capText2(value, max));
|
|
2378
|
+
return text2.length <= max ? text2 : truncateToLimit2(text2, max);
|
|
2379
|
+
}
|
|
2380
|
+
const pruned = boundedClone2(value, { remaining: max + TRUNCATION_MARKER2.length + 256 }, 0);
|
|
2381
|
+
const text = JSON.stringify(pruned);
|
|
2382
|
+
if (text === void 0) return void 0;
|
|
2383
|
+
return text.length <= max ? text : truncateToLimit2(text, max);
|
|
2384
|
+
} catch {
|
|
2385
|
+
return void 0;
|
|
2386
|
+
}
|
|
2387
|
+
}
|
|
2388
|
+
|
|
2389
|
+
// src/conversation.ts
|
|
2390
|
+
var CAPTURE_TRUNCATED_ROLE = "raindrop";
|
|
2391
|
+
var MESSAGE_OVERHEAD = 32;
|
|
2392
|
+
var PART_OVERHEAD = 24;
|
|
2393
|
+
var MAX_DEPTH2 = 12;
|
|
2394
|
+
function isRecord(value) {
|
|
2395
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
2396
|
+
}
|
|
2397
|
+
function stringField(record, key) {
|
|
2398
|
+
const value = record[key];
|
|
2399
|
+
return typeof value === "string" ? value : void 0;
|
|
2400
|
+
}
|
|
2401
|
+
function takeText(text, budget) {
|
|
2402
|
+
if (text.length > budget.remaining) {
|
|
2403
|
+
const kept = text.slice(0, Math.max(0, budget.remaining)) + TRUNCATION_MARKER2;
|
|
2404
|
+
budget.remaining = 0;
|
|
2405
|
+
budget.truncated = true;
|
|
2406
|
+
return kept;
|
|
2407
|
+
}
|
|
2408
|
+
budget.remaining -= Math.max(text.length, 1);
|
|
2409
|
+
return text;
|
|
2410
|
+
}
|
|
2411
|
+
function reserve(text, budget) {
|
|
2412
|
+
if (text !== void 0) budget.remaining -= Math.max(text.length, 1);
|
|
2413
|
+
return text;
|
|
2414
|
+
}
|
|
2415
|
+
function takeValue(value, budget, depth) {
|
|
2416
|
+
if (typeof value === "string") return takeText(value, budget);
|
|
2417
|
+
if (value === null || typeof value === "number" || typeof value === "boolean") {
|
|
2418
|
+
budget.remaining -= 8;
|
|
2419
|
+
return value;
|
|
2420
|
+
}
|
|
2421
|
+
if (typeof value !== "object") {
|
|
2422
|
+
budget.remaining -= 1;
|
|
2423
|
+
return value;
|
|
2424
|
+
}
|
|
2425
|
+
if (depth >= MAX_DEPTH2) {
|
|
2426
|
+
budget.remaining -= TRUNCATION_MARKER2.length;
|
|
2427
|
+
budget.truncated = true;
|
|
2428
|
+
return TRUNCATION_MARKER2;
|
|
2429
|
+
}
|
|
2430
|
+
if ("toJSON" in value && typeof value.toJSON === "function") {
|
|
2431
|
+
return takeValue(value.toJSON(), budget, depth + 1);
|
|
2432
|
+
}
|
|
2433
|
+
if (Array.isArray(value)) {
|
|
2434
|
+
budget.remaining -= 2;
|
|
2435
|
+
const out2 = [];
|
|
2436
|
+
for (const item of value) {
|
|
2437
|
+
if (budget.remaining <= 0) {
|
|
2438
|
+
budget.truncated = true;
|
|
2439
|
+
out2.push(TRUNCATION_MARKER2);
|
|
2440
|
+
break;
|
|
2441
|
+
}
|
|
2442
|
+
out2.push(takeValue(item, budget, depth + 1));
|
|
2443
|
+
}
|
|
2444
|
+
return out2;
|
|
2445
|
+
}
|
|
2446
|
+
budget.remaining -= 2;
|
|
2447
|
+
const out = {};
|
|
2448
|
+
if (!isRecord(value)) return out;
|
|
2449
|
+
for (const key in value) {
|
|
2450
|
+
if (!Object.prototype.hasOwnProperty.call(value, key)) continue;
|
|
2451
|
+
if (budget.remaining <= 0) {
|
|
2452
|
+
budget.truncated = true;
|
|
2453
|
+
out["..."] = TRUNCATION_MARKER2;
|
|
2454
|
+
break;
|
|
2455
|
+
}
|
|
2456
|
+
budget.remaining -= Math.max(key.length, 1);
|
|
2457
|
+
out[key] = takeValue(value[key], budget, depth + 1);
|
|
2458
|
+
}
|
|
2459
|
+
return out;
|
|
2460
|
+
}
|
|
2461
|
+
function messageType(message) {
|
|
2462
|
+
return typeof message._getType === "function" ? message._getType() : void 0;
|
|
2463
|
+
}
|
|
2464
|
+
function textPart(text, budget) {
|
|
2465
|
+
return { type: "text", text: takeText(text, budget) };
|
|
2466
|
+
}
|
|
2467
|
+
function joinedText(content, budget) {
|
|
2468
|
+
const texts = [];
|
|
2469
|
+
for (const block of content) {
|
|
2470
|
+
if (budget.remaining <= 0) {
|
|
2471
|
+
budget.truncated = true;
|
|
2472
|
+
texts.push(TRUNCATION_MARKER2);
|
|
2473
|
+
break;
|
|
2474
|
+
}
|
|
2475
|
+
budget.remaining -= 1;
|
|
2476
|
+
if (!isRecord(block)) continue;
|
|
2477
|
+
const text = stringField(block, "text");
|
|
2478
|
+
if (text !== void 0) texts.push(takeText(text, budget));
|
|
2479
|
+
}
|
|
2480
|
+
return texts.join("\n");
|
|
2481
|
+
}
|
|
2482
|
+
function contentPart(block, budget) {
|
|
2483
|
+
budget.remaining -= PART_OVERHEAD;
|
|
2484
|
+
if (!isRecord(block)) return takeValue(block, budget, 0);
|
|
2485
|
+
const type = stringField(block, "type");
|
|
2486
|
+
const text = stringField(block, "text");
|
|
2487
|
+
if (type === "text" && text !== void 0) return textPart(text, budget);
|
|
2488
|
+
if (type === "image_url") {
|
|
2489
|
+
const imageUrl = block["image_url"];
|
|
2490
|
+
const url = typeof imageUrl === "string" ? imageUrl : isRecord(imageUrl) ? stringField(imageUrl, "url") : void 0;
|
|
2491
|
+
if (url !== void 0) return { type: "image", image: takeText(url, budget) };
|
|
2492
|
+
}
|
|
2493
|
+
if (type === "thinking") {
|
|
2494
|
+
const thinking = stringField(block, "thinking");
|
|
2495
|
+
if (thinking !== void 0) return { type: "reasoning", text: takeText(thinking, budget) };
|
|
2496
|
+
}
|
|
2497
|
+
if (type === "image" || type === "file" || type === "audio") {
|
|
2498
|
+
const mediaType = stringField(block, "mime_type");
|
|
2499
|
+
const sourceType = stringField(block, "source_type");
|
|
2500
|
+
const source = block["source"];
|
|
2501
|
+
if (sourceType === "text" && text !== void 0) return textPart(text, budget);
|
|
2502
|
+
const data = sourceType === "url" ? stringField(block, "url") : sourceType === "base64" ? stringField(block, "data") : isRecord(source) ? stringField(source, "url") ?? stringField(source, "data") : void 0;
|
|
2503
|
+
const sourceMediaType = mediaType ?? (isRecord(source) ? stringField(source, "media_type") : void 0);
|
|
2504
|
+
if (data !== void 0) {
|
|
2505
|
+
const filename = stringField(block, "filename");
|
|
2506
|
+
return type === "image" ? { type: "image", image: takeText(data, budget), mediaType: reserve(sourceMediaType, budget) } : {
|
|
2507
|
+
type: "file",
|
|
2508
|
+
data: takeText(data, budget),
|
|
2509
|
+
mediaType: reserve(sourceMediaType, budget),
|
|
2510
|
+
filename: reserve(filename, budget)
|
|
2511
|
+
};
|
|
2512
|
+
}
|
|
2513
|
+
}
|
|
2514
|
+
return takeValue(block, budget, 0);
|
|
2515
|
+
}
|
|
2516
|
+
function contentParts(content, budget, skipToolUseIds) {
|
|
2517
|
+
const parts = [];
|
|
2518
|
+
for (const block of content) {
|
|
2519
|
+
if (budget.remaining <= 0) {
|
|
2520
|
+
budget.truncated = true;
|
|
2521
|
+
parts.push({ type: "text", text: TRUNCATION_MARKER2 });
|
|
2522
|
+
break;
|
|
2523
|
+
}
|
|
2524
|
+
if (isRecord(block) && (block["type"] === "tool_use" || block["type"] === "tool_call")) {
|
|
2525
|
+
const id = stringField(block, "id");
|
|
2526
|
+
if (id !== void 0 && skipToolUseIds.has(id)) continue;
|
|
2527
|
+
}
|
|
2528
|
+
parts.push(contentPart(block, budget));
|
|
2529
|
+
}
|
|
2530
|
+
return parts;
|
|
2531
|
+
}
|
|
2532
|
+
function assistantMessage(message, budget, toolNames) {
|
|
2533
|
+
const toolCalls = (0, import_messages.isAIMessage)(message) ? message.tool_calls ?? [] : [];
|
|
2534
|
+
if (toolCalls.length === 0 && typeof message.content === "string") {
|
|
2535
|
+
return { role: "assistant", content: takeText(message.content, budget) };
|
|
2536
|
+
}
|
|
2537
|
+
const ids = /* @__PURE__ */ new Set();
|
|
2538
|
+
const callParts = [];
|
|
2539
|
+
for (const call of toolCalls) {
|
|
2540
|
+
if (budget.remaining <= 0) {
|
|
2541
|
+
budget.truncated = true;
|
|
2542
|
+
callParts.push({ type: "text", text: TRUNCATION_MARKER2 });
|
|
2543
|
+
break;
|
|
2544
|
+
}
|
|
2545
|
+
budget.remaining -= PART_OVERHEAD;
|
|
2546
|
+
if (call.id !== void 0) {
|
|
2547
|
+
ids.add(call.id);
|
|
2548
|
+
toolNames.set(call.id, call.name);
|
|
2549
|
+
}
|
|
2550
|
+
callParts.push({
|
|
2551
|
+
type: "tool-call",
|
|
2552
|
+
toolCallId: reserve(call.id, budget),
|
|
2553
|
+
toolName: reserve(call.name, budget),
|
|
2554
|
+
input: takeValue(call.args, budget, 0)
|
|
2555
|
+
});
|
|
2556
|
+
}
|
|
2557
|
+
const content = typeof message.content === "string" ? message.content.length > 0 ? [textPart(message.content, budget)] : [] : contentParts(message.content, budget, ids);
|
|
2558
|
+
content.push(...callParts);
|
|
2559
|
+
return { role: "assistant", content };
|
|
2560
|
+
}
|
|
2561
|
+
function toolResultOutput(message, budget) {
|
|
2562
|
+
const failed = (0, import_messages.isToolMessage)(message) && message.status === "error";
|
|
2563
|
+
if (typeof message.content === "string") {
|
|
2564
|
+
return { type: failed ? "error-text" : "text", value: takeText(message.content, budget) };
|
|
2565
|
+
}
|
|
2566
|
+
return { type: "content", value: contentParts(message.content, budget, /* @__PURE__ */ new Set()) };
|
|
2567
|
+
}
|
|
2568
|
+
function toolMessage(message, budget, toolNames) {
|
|
2569
|
+
const toolCallId = (0, import_messages.isToolMessage)(message) ? message.tool_call_id : void 0;
|
|
2570
|
+
const toolName = message.name ?? (toolCallId !== void 0 ? toolNames.get(toolCallId) : void 0);
|
|
2571
|
+
budget.remaining -= PART_OVERHEAD;
|
|
2572
|
+
return {
|
|
2573
|
+
role: "tool",
|
|
2574
|
+
content: [{
|
|
2575
|
+
type: "tool-result",
|
|
2576
|
+
toolCallId: reserve(toolCallId, budget),
|
|
2577
|
+
toolName: reserve(toolName, budget),
|
|
2578
|
+
output: toolResultOutput(message, budget)
|
|
2579
|
+
}]
|
|
2580
|
+
};
|
|
2581
|
+
}
|
|
2582
|
+
function modelMessage(message, budget, toolNames) {
|
|
2583
|
+
budget.remaining -= MESSAGE_OVERHEAD;
|
|
2584
|
+
switch (messageType(message)) {
|
|
2585
|
+
case "system":
|
|
2586
|
+
return {
|
|
2587
|
+
role: "system",
|
|
2588
|
+
content: typeof message.content === "string" ? takeText(message.content, budget) : joinedText(message.content, budget)
|
|
2589
|
+
};
|
|
2590
|
+
case "ai":
|
|
2591
|
+
return assistantMessage(message, budget, toolNames);
|
|
2592
|
+
case "tool":
|
|
2593
|
+
case "function":
|
|
2594
|
+
return toolMessage(message, budget, toolNames);
|
|
2595
|
+
case "generic": {
|
|
2596
|
+
const role = (0, import_messages.isChatMessage)(message) ? message.role : void 0;
|
|
2597
|
+
if (role === "assistant" || role === "system") {
|
|
2598
|
+
return {
|
|
2599
|
+
role,
|
|
2600
|
+
content: typeof message.content === "string" ? takeText(message.content, budget) : joinedText(message.content, budget)
|
|
2601
|
+
};
|
|
2602
|
+
}
|
|
2603
|
+
return userMessage(message, budget);
|
|
2604
|
+
}
|
|
2605
|
+
default:
|
|
2606
|
+
return userMessage(message, budget);
|
|
2607
|
+
}
|
|
2608
|
+
}
|
|
2609
|
+
function userMessage(message, budget) {
|
|
2610
|
+
return {
|
|
2611
|
+
role: "user",
|
|
2612
|
+
content: typeof message.content === "string" ? takeText(message.content, budget) : contentParts(message.content, budget, /* @__PURE__ */ new Set())
|
|
2613
|
+
};
|
|
2614
|
+
}
|
|
2615
|
+
function truncationRecord(omittedMessages) {
|
|
2616
|
+
return { role: CAPTURE_TRUNCATED_ROLE, truncated: true, marker: TRUNCATION_MARKER2, omittedMessages };
|
|
2617
|
+
}
|
|
2618
|
+
function encodeWithinLimit(items, limit, overflow, convert) {
|
|
2619
|
+
let textBudget = limit;
|
|
2620
|
+
for (let attempt = 0; attempt < 8 && textBudget >= 64; attempt++) {
|
|
2621
|
+
const budget = { remaining: textBudget, truncated: false };
|
|
2622
|
+
const out = [];
|
|
2623
|
+
let omitted = 0;
|
|
2624
|
+
for (let i = 0; i < items.length; i++) {
|
|
2625
|
+
if (overflow === "omit" && budget.remaining <= 0) {
|
|
2626
|
+
omitted = items.length - i;
|
|
2627
|
+
break;
|
|
2628
|
+
}
|
|
2629
|
+
out.push(convert(items[i], budget));
|
|
2630
|
+
}
|
|
2631
|
+
const truncated = budget.truncated || omitted > 0;
|
|
2632
|
+
if (truncated && overflow === "omit") out.push(truncationRecord(omitted));
|
|
2633
|
+
const json2 = JSON.stringify(out);
|
|
2634
|
+
if (json2.length <= limit) return { json: json2, truncated };
|
|
2635
|
+
const excess = json2.length - limit + 128;
|
|
2636
|
+
textBudget = Math.max(textBudget - excess, Math.floor(textBudget / 2));
|
|
2637
|
+
}
|
|
2638
|
+
if (overflow === "keep") return void 0;
|
|
2639
|
+
const json = JSON.stringify([truncationRecord(items.length)]);
|
|
2640
|
+
return json.length <= limit ? { json, truncated: true } : void 0;
|
|
2641
|
+
}
|
|
2642
|
+
function captureConversation(messages, limit) {
|
|
2643
|
+
if (messages.length === 0) return void 0;
|
|
2644
|
+
try {
|
|
2645
|
+
const toolNames = /* @__PURE__ */ new Map();
|
|
2646
|
+
return encodeWithinLimit(
|
|
2647
|
+
messages,
|
|
2648
|
+
limit,
|
|
2649
|
+
"omit",
|
|
2650
|
+
(message, budget) => modelMessage(message, budget, toolNames)
|
|
2651
|
+
);
|
|
2652
|
+
} catch {
|
|
2653
|
+
return void 0;
|
|
2654
|
+
}
|
|
2655
|
+
}
|
|
2656
|
+
function capturePrompt(prompt, limit) {
|
|
2657
|
+
try {
|
|
2658
|
+
return encodeWithinLimit([prompt], limit, "omit", (text, budget) => {
|
|
2659
|
+
budget.remaining -= MESSAGE_OVERHEAD;
|
|
2660
|
+
return { role: "user", content: takeText(text, budget) };
|
|
2661
|
+
});
|
|
2662
|
+
} catch {
|
|
2663
|
+
return void 0;
|
|
2664
|
+
}
|
|
2665
|
+
}
|
|
2666
|
+
function captureToolCalls(message, limit) {
|
|
2667
|
+
if (!isRecord(message) || !Array.isArray(message["tool_calls"])) return void 0;
|
|
2668
|
+
const calls = [];
|
|
2669
|
+
let structural = 0;
|
|
2670
|
+
for (const call of message["tool_calls"]) {
|
|
2671
|
+
structural += PART_OVERHEAD;
|
|
2672
|
+
if (isRecord(call)) {
|
|
2673
|
+
structural += (stringField(call, "id")?.length ?? 0) + (stringField(call, "name")?.length ?? 0);
|
|
2674
|
+
calls.push(call);
|
|
2675
|
+
}
|
|
2676
|
+
if (structural > limit) return void 0;
|
|
2677
|
+
}
|
|
2678
|
+
if (calls.length === 0) return void 0;
|
|
2679
|
+
try {
|
|
2680
|
+
return encodeWithinLimit(calls, limit, "keep", (call, budget) => {
|
|
2681
|
+
budget.remaining -= PART_OVERHEAD;
|
|
2682
|
+
return {
|
|
2683
|
+
toolCallId: reserve(stringField(call, "id"), budget),
|
|
2684
|
+
toolName: reserve(stringField(call, "name"), budget),
|
|
2685
|
+
input: takeValue(call["args"], budget, 0)
|
|
2686
|
+
};
|
|
2687
|
+
});
|
|
2688
|
+
} catch {
|
|
2689
|
+
return void 0;
|
|
2690
|
+
}
|
|
2691
|
+
}
|
|
2692
|
+
function parseToolCallInput(input) {
|
|
2693
|
+
try {
|
|
2694
|
+
const parsed = JSON.parse(input);
|
|
2695
|
+
if (isRecord(parsed) && parsed["type"] === "tool_call" && "args" in parsed) {
|
|
2696
|
+
return { id: stringField(parsed, "id"), args: JSON.stringify(parsed["args"]) };
|
|
2697
|
+
}
|
|
2698
|
+
} catch {
|
|
2699
|
+
}
|
|
2700
|
+
return { args: input };
|
|
2701
|
+
}
|
|
2702
|
+
function unwrapToolOutput(output) {
|
|
2703
|
+
if ((0, import_messages.isBaseMessage)(output)) {
|
|
2704
|
+
return {
|
|
2705
|
+
content: output.content,
|
|
2706
|
+
toolCallId: (0, import_messages.isToolMessage)(output) ? output.tool_call_id : void 0
|
|
2707
|
+
};
|
|
2708
|
+
}
|
|
2709
|
+
return { content: output };
|
|
2710
|
+
}
|
|
2711
|
+
|
|
1620
2712
|
// src/callback-handler.ts
|
|
1621
2713
|
function resolveEventId(source) {
|
|
1622
2714
|
if (typeof source !== "function") return randomUUID();
|
|
@@ -1634,32 +2726,38 @@ function isInternalName(name) {
|
|
|
1634
2726
|
if (name.startsWith("__") && name.endsWith("__")) return true;
|
|
1635
2727
|
return false;
|
|
1636
2728
|
}
|
|
1637
|
-
|
|
1638
|
-
function extractTextFromContent(content) {
|
|
2729
|
+
function extractTextFromContent(content, limit) {
|
|
1639
2730
|
if (content == null) return void 0;
|
|
1640
2731
|
if (typeof content === "string") return content;
|
|
1641
2732
|
if (Array.isArray(content)) {
|
|
1642
2733
|
const parts = [];
|
|
2734
|
+
let length = 0;
|
|
1643
2735
|
for (const part of content) {
|
|
2736
|
+
if (length > limit) break;
|
|
2737
|
+
length += 1;
|
|
2738
|
+
let text;
|
|
1644
2739
|
if (typeof part === "string") {
|
|
1645
|
-
|
|
2740
|
+
text = part;
|
|
1646
2741
|
} else if (part && typeof part === "object") {
|
|
1647
2742
|
const p = part;
|
|
1648
2743
|
if (typeof p.text === "string") {
|
|
1649
|
-
|
|
2744
|
+
text = p.text;
|
|
1650
2745
|
} else if (p.type === "text" && typeof p.content === "string") {
|
|
1651
|
-
|
|
2746
|
+
text = p.content;
|
|
1652
2747
|
}
|
|
1653
2748
|
}
|
|
2749
|
+
if (text === void 0) continue;
|
|
2750
|
+
parts.push(text.length > limit ? text.slice(0, limit + 1) : text);
|
|
2751
|
+
length += Math.max(text.length, 1);
|
|
1654
2752
|
}
|
|
1655
2753
|
if (parts.length > 0) return parts.join("\n");
|
|
1656
|
-
return
|
|
2754
|
+
return boundedStringify(content, limit);
|
|
1657
2755
|
}
|
|
1658
2756
|
if (typeof content === "object") {
|
|
1659
2757
|
const c = content;
|
|
1660
2758
|
if (typeof c.text === "string") return c.text;
|
|
1661
2759
|
if (typeof c.content === "string") return c.content;
|
|
1662
|
-
return
|
|
2760
|
+
return boundedStringify(content, limit);
|
|
1663
2761
|
}
|
|
1664
2762
|
return String(content);
|
|
1665
2763
|
}
|
|
@@ -1678,6 +2776,11 @@ var RaindropDeepAgentsHandler = class extends import_base.BaseCallbackHandler {
|
|
|
1678
2776
|
this.eventName = opts.eventName;
|
|
1679
2777
|
this.eventIdSource = opts.eventId;
|
|
1680
2778
|
this.traceChains = opts.traceChains ?? true;
|
|
2779
|
+
this.configuredSpanMaxChars = opts.maxTextFieldChars ?? eventMaxTextFieldChars();
|
|
2780
|
+
this.eventMaxChars = opts.eventMaxTextFieldChars ?? eventMaxTextFieldChars();
|
|
2781
|
+
}
|
|
2782
|
+
get spanMaxChars() {
|
|
2783
|
+
return spanAttributeLimit(this.configuredSpanMaxChars);
|
|
1681
2784
|
}
|
|
1682
2785
|
getEventId(runId, parentRunId) {
|
|
1683
2786
|
const rootId = parentRunId ? this.rootRunIds.get(parentRunId) ?? parentRunId : runId;
|
|
@@ -1743,13 +2846,21 @@ var RaindropDeepAgentsHandler = class extends import_base.BaseCallbackHandler {
|
|
|
1743
2846
|
if (this.spans.has(runId)) return;
|
|
1744
2847
|
const eventId = this.getEventId(runId, parentRunId);
|
|
1745
2848
|
const modelId = getName(llm, runName);
|
|
2849
|
+
const prompt = prompts[0] ?? "";
|
|
1746
2850
|
const span = this.traceShipper.startSpan({
|
|
1747
2851
|
name: "llm",
|
|
1748
2852
|
parent: this.getParent(parentRunId),
|
|
1749
2853
|
eventId,
|
|
2854
|
+
// `ai.generateText` classifies the span as an LLM generation at ingest
|
|
2855
|
+
// (a bare `llm`/`chat` operationId maps to INTERNAL and is skipped by
|
|
2856
|
+
// the rich-interaction extractor). `ai.prompt.messages` carries the
|
|
2857
|
+
// per-step trajectory so replay can see the history each step ran on.
|
|
2858
|
+
// A batch is a list of independent prompts; the span describes the
|
|
2859
|
+
// first one, whose response `handleLLMEnd` reports (`generations[0][0]`).
|
|
1750
2860
|
attributes: [
|
|
1751
2861
|
attrString("ai.model.provider", modelId),
|
|
1752
|
-
attrString("ai.operationId", "
|
|
2862
|
+
attrString("ai.operationId", "ai.generateText"),
|
|
2863
|
+
...promptAttributes(capturePrompt(prompt, this.spanMaxChars))
|
|
1753
2864
|
]
|
|
1754
2865
|
});
|
|
1755
2866
|
this.spans.set(runId, span);
|
|
@@ -1757,7 +2868,7 @@ var RaindropDeepAgentsHandler = class extends import_base.BaseCallbackHandler {
|
|
|
1757
2868
|
userId: this.userId,
|
|
1758
2869
|
convoId: this.convoId,
|
|
1759
2870
|
eventName: this.eventName,
|
|
1760
|
-
input:
|
|
2871
|
+
input: capText2(prompt, this.eventMaxChars),
|
|
1761
2872
|
properties: buildProperties(tags, metadata),
|
|
1762
2873
|
isPending: true
|
|
1763
2874
|
});
|
|
@@ -1769,24 +2880,31 @@ var RaindropDeepAgentsHandler = class extends import_base.BaseCallbackHandler {
|
|
|
1769
2880
|
if (this.spans.has(runId)) return;
|
|
1770
2881
|
const eventId = this.getEventId(runId, parentRunId);
|
|
1771
2882
|
const modelId = getName(llm, runName);
|
|
2883
|
+
const conversation = messages[0] ?? [];
|
|
1772
2884
|
const span = this.traceShipper.startSpan({
|
|
1773
2885
|
name: "llm",
|
|
1774
2886
|
parent: this.getParent(parentRunId),
|
|
1775
2887
|
eventId,
|
|
2888
|
+
// See handleLLMStart: the full history (historical tool calls and
|
|
2889
|
+
// their results included) goes on the span; the event `input` below
|
|
2890
|
+
// stays the latest human message. LangChain batches are a list of
|
|
2891
|
+
// independent conversations; the span describes the first one, the
|
|
2892
|
+
// same member `handleLLMEnd` reports the response of
|
|
2893
|
+
// (`generations[0][0]`), so history and response stay paired.
|
|
1776
2894
|
attributes: [
|
|
1777
2895
|
attrString("ai.model.provider", modelId),
|
|
1778
|
-
attrString("ai.operationId", "
|
|
2896
|
+
attrString("ai.operationId", "ai.generateText"),
|
|
2897
|
+
...promptAttributes(captureConversation(conversation, this.spanMaxChars))
|
|
1779
2898
|
]
|
|
1780
2899
|
});
|
|
1781
2900
|
this.spans.set(runId, span);
|
|
1782
|
-
const
|
|
1783
|
-
const userMessages = allMessages.filter((m) => {
|
|
2901
|
+
const userMessages = conversation.filter((m) => {
|
|
1784
2902
|
const role = m._getType?.() ?? "unknown";
|
|
1785
2903
|
return role === "human";
|
|
1786
2904
|
});
|
|
1787
|
-
const lastMsg = userMessages.length > 0 ? userMessages[userMessages.length - 1] :
|
|
1788
|
-
const extracted = lastMsg ? extractTextFromContent(lastMsg.content) : void 0;
|
|
1789
|
-
const inputText =
|
|
2905
|
+
const lastMsg = userMessages.length > 0 ? userMessages[userMessages.length - 1] : conversation[conversation.length - 1];
|
|
2906
|
+
const extracted = lastMsg ? extractTextFromContent(lastMsg.content, this.eventMaxChars) : void 0;
|
|
2907
|
+
const inputText = capText2(extracted, this.eventMaxChars);
|
|
1790
2908
|
await this.eventShipper.patch(eventId, {
|
|
1791
2909
|
userId: this.userId,
|
|
1792
2910
|
convoId: this.convoId,
|
|
@@ -1809,7 +2927,7 @@ var RaindropDeepAgentsHandler = class extends import_base.BaseCallbackHandler {
|
|
|
1809
2927
|
await this.finalizeEventIfRoot(runId);
|
|
1810
2928
|
return;
|
|
1811
2929
|
}
|
|
1812
|
-
const meta = extractLLMMetadata(output);
|
|
2930
|
+
const meta = extractLLMMetadata(output, this.spanMaxChars);
|
|
1813
2931
|
const {
|
|
1814
2932
|
model,
|
|
1815
2933
|
promptTokens,
|
|
@@ -1817,11 +2935,17 @@ var RaindropDeepAgentsHandler = class extends import_base.BaseCallbackHandler {
|
|
|
1817
2935
|
cachedTokens,
|
|
1818
2936
|
reasoningTokens,
|
|
1819
2937
|
finishReason,
|
|
1820
|
-
outputText
|
|
2938
|
+
outputText,
|
|
2939
|
+
toolCalls
|
|
1821
2940
|
} = meta;
|
|
1822
2941
|
this.traceShipper.endSpan(span, {
|
|
1823
2942
|
attributes: [
|
|
1824
2943
|
attrString("ai.response.model", model),
|
|
2944
|
+
attrString("ai.response.text", capText2(outputText, this.spanMaxChars)),
|
|
2945
|
+
// Tool calls requested by this step, with the ids the matching
|
|
2946
|
+
// `ai.toolCall` spans and the next step's history carry.
|
|
2947
|
+
attrString("ai.response.toolCalls", toolCalls?.json),
|
|
2948
|
+
attrString("ai.response.toolCalls.truncated", toolCalls?.truncated ? "true" : void 0),
|
|
1825
2949
|
attrInt("ai.usage.prompt_tokens", promptTokens),
|
|
1826
2950
|
attrInt("ai.usage.completion_tokens", completionTokens),
|
|
1827
2951
|
attrInt("ai.usage.cached_tokens", cachedTokens),
|
|
@@ -1833,9 +2957,8 @@ var RaindropDeepAgentsHandler = class extends import_base.BaseCallbackHandler {
|
|
|
1833
2957
|
if (cachedTokens != null) properties["ai.usage.cached_tokens"] = cachedTokens;
|
|
1834
2958
|
if (reasoningTokens != null) properties["ai.usage.thoughts_tokens"] = reasoningTokens;
|
|
1835
2959
|
if (finishReason != null) properties["ai.finish_reason"] = finishReason;
|
|
1836
|
-
const cappedOutput = outputText !== void 0 ? truncate(outputText, CHAIN_TEXT_MAX_LEN) : void 0;
|
|
1837
2960
|
await this.finalizeEventIfRoot(runId, {
|
|
1838
|
-
output:
|
|
2961
|
+
output: capText2(outputText, this.eventMaxChars),
|
|
1839
2962
|
model,
|
|
1840
2963
|
usage: { promptTokens, completionTokens },
|
|
1841
2964
|
properties: Object.keys(properties).length > 0 ? properties : void 0
|
|
@@ -1931,14 +3054,16 @@ var RaindropDeepAgentsHandler = class extends import_base.BaseCallbackHandler {
|
|
|
1931
3054
|
try {
|
|
1932
3055
|
const eventId = this.getEventId(runId, parentRunId);
|
|
1933
3056
|
const toolName = getName(tool, runName);
|
|
3057
|
+
const toolCall = parseToolCallInput(input);
|
|
1934
3058
|
const span = this.traceShipper.startSpan({
|
|
1935
3059
|
name: "tool",
|
|
1936
3060
|
parent: this.getParent(parentRunId),
|
|
1937
3061
|
eventId,
|
|
1938
3062
|
operationId: "ai.toolCall",
|
|
1939
3063
|
attributes: [
|
|
3064
|
+
attrString("ai.toolCall.id", toolCall.id),
|
|
1940
3065
|
attrString("ai.toolCall.name", toolName),
|
|
1941
|
-
attrString("
|
|
3066
|
+
attrString("ai.toolCall.args", capText2(toolCall.args, this.spanMaxChars))
|
|
1942
3067
|
]
|
|
1943
3068
|
});
|
|
1944
3069
|
this.spans.set(runId, span);
|
|
@@ -1953,9 +3078,14 @@ var RaindropDeepAgentsHandler = class extends import_base.BaseCallbackHandler {
|
|
|
1953
3078
|
try {
|
|
1954
3079
|
const span = this.spans.get(runId);
|
|
1955
3080
|
if (span) {
|
|
1956
|
-
const
|
|
3081
|
+
const { content, toolCallId } = unwrapToolOutput(output);
|
|
3082
|
+
const result = typeof content === "string" ? capText2(content, this.spanMaxChars) : boundedStringify(content, this.spanMaxChars);
|
|
3083
|
+
const hasId = span.attributes.some((attr) => attr?.key === "ai.toolCall.id");
|
|
1957
3084
|
this.traceShipper.endSpan(span, {
|
|
1958
|
-
attributes: [
|
|
3085
|
+
attributes: [
|
|
3086
|
+
attrString("ai.toolCall.id", hasId ? void 0 : toolCallId),
|
|
3087
|
+
attrString("ai.toolCall.result", result)
|
|
3088
|
+
]
|
|
1959
3089
|
});
|
|
1960
3090
|
}
|
|
1961
3091
|
await this.finalizeEventIfRoot(runId);
|
|
@@ -1991,10 +3121,10 @@ var RaindropDeepAgentsHandler = class extends import_base.BaseCallbackHandler {
|
|
|
1991
3121
|
operationId: "ai.toolCall",
|
|
1992
3122
|
attributes: [
|
|
1993
3123
|
attrString("ai.toolCall.name", action.tool),
|
|
1994
|
-
attrString(
|
|
1995
|
-
|
|
1996
|
-
|
|
1997
|
-
)
|
|
3124
|
+
attrString(
|
|
3125
|
+
"agent.tool_input",
|
|
3126
|
+
typeof action.toolInput === "string" ? capText2(action.toolInput, this.spanMaxChars) : boundedStringify(action.toolInput, this.spanMaxChars)
|
|
3127
|
+
)
|
|
1998
3128
|
]
|
|
1999
3129
|
});
|
|
2000
3130
|
this.spans.set(`${runId}:agent_action`, span);
|
|
@@ -2027,75 +3157,13 @@ function buildProperties(tags, metadata) {
|
|
|
2027
3157
|
if (metadata) Object.assign(props, metadata);
|
|
2028
3158
|
return props;
|
|
2029
3159
|
}
|
|
2030
|
-
|
|
2031
|
-
|
|
2032
|
-
|
|
2033
|
-
|
|
2034
|
-
|
|
2035
|
-
if (typeof value === "string") {
|
|
2036
|
-
if (value.length > budget.remaining) {
|
|
2037
|
-
const taken = value.slice(0, Math.max(0, budget.remaining)) + TRUNCATION_MARKER2;
|
|
2038
|
-
budget.remaining = 0;
|
|
2039
|
-
return taken;
|
|
2040
|
-
}
|
|
2041
|
-
budget.remaining -= Math.max(value.length, 1);
|
|
2042
|
-
return value;
|
|
2043
|
-
}
|
|
2044
|
-
if (value === null || typeof value === "number" || typeof value === "boolean") {
|
|
2045
|
-
budget.remaining -= 8;
|
|
2046
|
-
return value;
|
|
2047
|
-
}
|
|
2048
|
-
if (typeof value !== "object") {
|
|
2049
|
-
budget.remaining -= 8;
|
|
2050
|
-
return value;
|
|
2051
|
-
}
|
|
2052
|
-
if (depth >= MAX_BOUNDED_DEPTH) {
|
|
2053
|
-
budget.remaining -= 16;
|
|
2054
|
-
return `<max depth: ${TRUNCATION_MARKER2}>`;
|
|
2055
|
-
}
|
|
2056
|
-
const withToJson = value;
|
|
2057
|
-
if (typeof withToJson.toJSON === "function") {
|
|
2058
|
-
try {
|
|
2059
|
-
return boundedClone2(withToJson.toJSON(), budget, depth + 1);
|
|
2060
|
-
} catch {
|
|
2061
|
-
}
|
|
2062
|
-
}
|
|
2063
|
-
if (Array.isArray(value)) {
|
|
2064
|
-
const out2 = [];
|
|
2065
|
-
for (const item of value) {
|
|
2066
|
-
if (budget.remaining <= 0) {
|
|
2067
|
-
out2.push(TRUNCATION_MARKER2);
|
|
2068
|
-
break;
|
|
2069
|
-
}
|
|
2070
|
-
out2.push(boundedClone2(item, budget, depth + 1));
|
|
2071
|
-
}
|
|
2072
|
-
return out2;
|
|
2073
|
-
}
|
|
2074
|
-
const out = {};
|
|
2075
|
-
for (const key of Object.keys(value)) {
|
|
2076
|
-
if (budget.remaining <= 0) {
|
|
2077
|
-
out["..."] = TRUNCATION_MARKER2;
|
|
2078
|
-
break;
|
|
2079
|
-
}
|
|
2080
|
-
budget.remaining -= Math.max(key.length, 1);
|
|
2081
|
-
out[key] = boundedClone2(value[key], budget, depth + 1);
|
|
2082
|
-
}
|
|
2083
|
-
return out;
|
|
2084
|
-
}
|
|
2085
|
-
function safeStringify(value, limit = MAX_TEXT_FIELD_CHARS) {
|
|
2086
|
-
try {
|
|
2087
|
-
const pruned = boundedClone2(value, { remaining: limit + TRUNCATION_MARKER2.length + 256 }, 0);
|
|
2088
|
-
return JSON.stringify(pruned) ?? "";
|
|
2089
|
-
} catch {
|
|
2090
|
-
const fallback = String(value);
|
|
2091
|
-
return fallback.length > limit ? fallback.slice(0, limit) : fallback;
|
|
2092
|
-
}
|
|
2093
|
-
}
|
|
2094
|
-
function truncate(str, maxLen) {
|
|
2095
|
-
if (str.length <= maxLen) return str;
|
|
2096
|
-
return str.slice(0, maxLen - 3) + "...";
|
|
3160
|
+
function promptAttributes(capture) {
|
|
3161
|
+
return [
|
|
3162
|
+
attrString("ai.prompt.messages", capture?.json),
|
|
3163
|
+
attrString("ai.prompt.messages.truncated", capture?.truncated ? "true" : void 0)
|
|
3164
|
+
];
|
|
2097
3165
|
}
|
|
2098
|
-
function extractLLMMetadata(output) {
|
|
3166
|
+
function extractLLMMetadata(output, limit) {
|
|
2099
3167
|
const gen = output.generations?.[0]?.[0];
|
|
2100
3168
|
const message = gen?.message;
|
|
2101
3169
|
const responseMeta = message?.response_metadata;
|
|
@@ -2121,7 +3189,7 @@ function extractLLMMetadata(output) {
|
|
|
2121
3189
|
outputDetails?.reasoning ?? usage?.reasoning_tokens ?? usage?.thoughts_tokens
|
|
2122
3190
|
);
|
|
2123
3191
|
const finishReason = generationInfo?.finish_reason ?? responseMeta?.finish_reason ?? responseMeta?.stop_reason;
|
|
2124
|
-
const outputText = gen?.text ?? (typeof message?.content === "string" ? message.content : void 0) ?? (message?.content ? extractTextFromContent(message.content) : void 0);
|
|
3192
|
+
const outputText = gen?.text ?? (typeof message?.content === "string" ? message.content : void 0) ?? (message?.content ? extractTextFromContent(message.content, limit) : void 0);
|
|
2125
3193
|
return {
|
|
2126
3194
|
model,
|
|
2127
3195
|
promptTokens,
|
|
@@ -2129,7 +3197,8 @@ function extractLLMMetadata(output) {
|
|
|
2129
3197
|
cachedTokens,
|
|
2130
3198
|
reasoningTokens,
|
|
2131
3199
|
finishReason,
|
|
2132
|
-
outputText
|
|
3200
|
+
outputText,
|
|
3201
|
+
toolCalls: captureToolCalls(message, limit)
|
|
2133
3202
|
};
|
|
2134
3203
|
}
|
|
2135
3204
|
function asNumber(val) {
|
|
@@ -2138,20 +3207,91 @@ function asNumber(val) {
|
|
|
2138
3207
|
return Number.isFinite(n) ? n : void 0;
|
|
2139
3208
|
}
|
|
2140
3209
|
|
|
3210
|
+
// package.json
|
|
3211
|
+
var package_default = {
|
|
3212
|
+
name: "@raindrop-ai/deep-agents",
|
|
3213
|
+
version: "0.1.3",
|
|
3214
|
+
description: "Raindrop integration for LangChain Deep Agents",
|
|
3215
|
+
main: "dist/index.js",
|
|
3216
|
+
module: "dist/index.mjs",
|
|
3217
|
+
types: "dist/index.d.ts",
|
|
3218
|
+
license: "MIT",
|
|
3219
|
+
homepage: "https://www.raindrop.ai/docs/integrations/deepagents/",
|
|
3220
|
+
bugs: {
|
|
3221
|
+
url: "https://www.raindrop.ai/docs/support/"
|
|
3222
|
+
},
|
|
3223
|
+
exports: {
|
|
3224
|
+
".": {
|
|
3225
|
+
types: "./dist/index.d.ts",
|
|
3226
|
+
import: "./dist/index.mjs",
|
|
3227
|
+
require: "./dist/index.js"
|
|
3228
|
+
}
|
|
3229
|
+
},
|
|
3230
|
+
sideEffects: false,
|
|
3231
|
+
files: [
|
|
3232
|
+
"dist/**"
|
|
3233
|
+
],
|
|
3234
|
+
scripts: {
|
|
3235
|
+
build: "tsup",
|
|
3236
|
+
dev: "tsup --watch",
|
|
3237
|
+
clean: "rm -rf dist",
|
|
3238
|
+
test: "vitest run"
|
|
3239
|
+
},
|
|
3240
|
+
peerDependencies: {
|
|
3241
|
+
"@langchain/core": ">=0.3.0",
|
|
3242
|
+
deepagents: ">=0.5.0"
|
|
3243
|
+
},
|
|
3244
|
+
devDependencies: {
|
|
3245
|
+
"@langchain/anthropic": "~0.3.34",
|
|
3246
|
+
"@langchain/core": ">=0.3.0",
|
|
3247
|
+
"@langchain/openai": "~0.3.17",
|
|
3248
|
+
"@raindrop-ai/core": "workspace:*",
|
|
3249
|
+
"@types/node": "^20.11.17",
|
|
3250
|
+
deepagents: "1.0.0",
|
|
3251
|
+
msw: "^2.12.7",
|
|
3252
|
+
tsup: "^8.4.0",
|
|
3253
|
+
typescript: "^5.3.3",
|
|
3254
|
+
vitest: "^2.1.9",
|
|
3255
|
+
zod: "^3.23.0"
|
|
3256
|
+
},
|
|
3257
|
+
tsup: {
|
|
3258
|
+
entry: [
|
|
3259
|
+
"src/index.ts"
|
|
3260
|
+
],
|
|
3261
|
+
format: [
|
|
3262
|
+
"cjs",
|
|
3263
|
+
"esm"
|
|
3264
|
+
],
|
|
3265
|
+
dts: {
|
|
3266
|
+
resolve: true
|
|
3267
|
+
},
|
|
3268
|
+
clean: true,
|
|
3269
|
+
noExternal: [
|
|
3270
|
+
"@raindrop-ai/core"
|
|
3271
|
+
]
|
|
3272
|
+
},
|
|
3273
|
+
publishConfig: {
|
|
3274
|
+
access: "public"
|
|
3275
|
+
}
|
|
3276
|
+
};
|
|
3277
|
+
|
|
2141
3278
|
// src/version.ts
|
|
2142
|
-
var libraryName =
|
|
2143
|
-
var libraryVersion =
|
|
3279
|
+
var libraryName = package_default.name;
|
|
3280
|
+
var libraryVersion = package_default.version;
|
|
2144
3281
|
|
|
2145
3282
|
// src/index.ts
|
|
2146
3283
|
function createRaindropDeepAgents(opts) {
|
|
2147
3284
|
const writeKey = opts.writeKey;
|
|
2148
3285
|
const enabled = !!writeKey;
|
|
3286
|
+
setMaxTextFieldChars(opts.maxTextFieldChars);
|
|
3287
|
+
const maxChars = eventMaxTextFieldChars();
|
|
2149
3288
|
if (!writeKey) {
|
|
2150
3289
|
console.warn(
|
|
2151
3290
|
"[raindrop-ai/deep-agents] writeKey not provided; telemetry shipping is disabled"
|
|
2152
3291
|
);
|
|
2153
3292
|
}
|
|
2154
|
-
const
|
|
3293
|
+
const appGitContext = createAppGitContext2(writeKey?.trim() ? opts.appGit : false, { allowLocalGit: true });
|
|
3294
|
+
const eventShipper = new EventShipper2({
|
|
2155
3295
|
writeKey,
|
|
2156
3296
|
endpoint: opts.endpoint,
|
|
2157
3297
|
enabled,
|
|
@@ -2159,9 +3299,11 @@ function createRaindropDeepAgents(opts) {
|
|
|
2159
3299
|
projectId: opts.projectId,
|
|
2160
3300
|
sdkName: "deep-agents",
|
|
2161
3301
|
libraryName,
|
|
2162
|
-
libraryVersion
|
|
3302
|
+
libraryVersion,
|
|
3303
|
+
appGitContext,
|
|
3304
|
+
maxTextFieldChars: maxChars
|
|
2163
3305
|
});
|
|
2164
|
-
const traceShipper = new
|
|
3306
|
+
const traceShipper = new TraceShipper2({
|
|
2165
3307
|
writeKey,
|
|
2166
3308
|
endpoint: opts.endpoint,
|
|
2167
3309
|
enabled,
|
|
@@ -2169,7 +3311,9 @@ function createRaindropDeepAgents(opts) {
|
|
|
2169
3311
|
projectId: opts.projectId,
|
|
2170
3312
|
sdkName: "deep-agents",
|
|
2171
3313
|
serviceName: "raindrop.deep-agents",
|
|
2172
|
-
serviceVersion: libraryVersion
|
|
3314
|
+
serviceVersion: libraryVersion,
|
|
3315
|
+
appGitContext,
|
|
3316
|
+
maxTextFieldChars: maxChars
|
|
2173
3317
|
});
|
|
2174
3318
|
const handler = new RaindropDeepAgentsHandler({
|
|
2175
3319
|
eventShipper,
|
|
@@ -2178,7 +3322,9 @@ function createRaindropDeepAgents(opts) {
|
|
|
2178
3322
|
convoId: opts.convoId,
|
|
2179
3323
|
eventName: opts.eventName,
|
|
2180
3324
|
eventId: opts.eventId,
|
|
2181
|
-
traceChains: opts.traceChains
|
|
3325
|
+
traceChains: opts.traceChains,
|
|
3326
|
+
maxTextFieldChars: maxChars,
|
|
3327
|
+
eventMaxTextFieldChars: maxChars
|
|
2182
3328
|
});
|
|
2183
3329
|
return {
|
|
2184
3330
|
handler,
|
|
@@ -2189,7 +3335,14 @@ function createRaindropDeepAgents(opts) {
|
|
|
2189
3335
|
await Promise.all([eventShipper.flush(), traceShipper.flush()]);
|
|
2190
3336
|
},
|
|
2191
3337
|
async shutdown() {
|
|
2192
|
-
|
|
3338
|
+
try {
|
|
3339
|
+
await Promise.all([eventShipper.shutdown(), traceShipper.shutdown()]);
|
|
3340
|
+
} finally {
|
|
3341
|
+
try {
|
|
3342
|
+
appGitContext.dispose();
|
|
3343
|
+
} catch {
|
|
3344
|
+
}
|
|
3345
|
+
}
|
|
2193
3346
|
},
|
|
2194
3347
|
events: {
|
|
2195
3348
|
async patch(eventId, patch) {
|