@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.mjs
CHANGED
|
@@ -63,7 +63,459 @@ function evalScopeAttributes() {
|
|
|
63
63
|
return { [EVAL_CORRELATION_ID_ATTRIBUTE]: scope.correlationId };
|
|
64
64
|
}
|
|
65
65
|
|
|
66
|
-
// ../core/dist/chunk-
|
|
66
|
+
// ../core/dist/chunk-WJOR6M7H.js
|
|
67
|
+
var STATE_KEY = /* @__PURE__ */ Symbol.for("raindrop.tracing.replayTraceRoutingState");
|
|
68
|
+
function state() {
|
|
69
|
+
const holder = globalThis;
|
|
70
|
+
let current = holder[STATE_KEY];
|
|
71
|
+
if (!current) {
|
|
72
|
+
let storage = null;
|
|
73
|
+
try {
|
|
74
|
+
const Ctor = globalThis.RAINDROP_ASYNC_LOCAL_STORAGE;
|
|
75
|
+
if (Ctor) storage = new Ctor();
|
|
76
|
+
} catch (e) {
|
|
77
|
+
storage = null;
|
|
78
|
+
}
|
|
79
|
+
current = {
|
|
80
|
+
storage,
|
|
81
|
+
syncDestination: void 0,
|
|
82
|
+
spanDestinations: /* @__PURE__ */ new WeakMap()
|
|
83
|
+
};
|
|
84
|
+
holder[STATE_KEY] = current;
|
|
85
|
+
}
|
|
86
|
+
return current;
|
|
87
|
+
}
|
|
88
|
+
function currentReplayTraceDestination() {
|
|
89
|
+
var _a, _b;
|
|
90
|
+
const routing = state();
|
|
91
|
+
return (_b = (_a = routing.storage) == null ? void 0 : _a.getStore()) != null ? _b : routing.syncDestination;
|
|
92
|
+
}
|
|
93
|
+
function rememberReplayTraceDestination(span) {
|
|
94
|
+
const destination = currentReplayTraceDestination();
|
|
95
|
+
if (destination) state().spanDestinations.set(span, destination);
|
|
96
|
+
}
|
|
97
|
+
function copyReplayTraceDestination(source, target) {
|
|
98
|
+
const destination = state().spanDestinations.get(source);
|
|
99
|
+
if (destination) state().spanDestinations.set(target, destination);
|
|
100
|
+
}
|
|
101
|
+
function replayTraceDestinationFor(value) {
|
|
102
|
+
if (typeof value !== "object" && typeof value !== "function" || value === null) {
|
|
103
|
+
return void 0;
|
|
104
|
+
}
|
|
105
|
+
return state().spanDestinations.get(value);
|
|
106
|
+
}
|
|
107
|
+
function recordReplayExportedSpan(destination, spanId, traceId) {
|
|
108
|
+
var _a, _b;
|
|
109
|
+
if (!destination || !spanId || !traceId) return;
|
|
110
|
+
(_a = destination.exportedSpanIds) == null ? void 0 : _a.add(spanId);
|
|
111
|
+
(_b = destination.exportedTraceIds) == null ? void 0 : _b.add(traceId);
|
|
112
|
+
}
|
|
113
|
+
function replayTraceUrl(baseUrl) {
|
|
114
|
+
return `${baseUrl.replace(/\/+$/, "")}/v1/traces`;
|
|
115
|
+
}
|
|
116
|
+
function getAsyncLocalStorageCtor() {
|
|
117
|
+
return globalThis.RAINDROP_ASYNC_LOCAL_STORAGE;
|
|
118
|
+
}
|
|
119
|
+
var MAX_BINDING_STACK = 128;
|
|
120
|
+
var EMPTY_STACK = [];
|
|
121
|
+
var ContextStackStorage = class {
|
|
122
|
+
/** Emitted once when this runtime cannot support an ambient push. */
|
|
123
|
+
constructor(noAmbientBindWarning) {
|
|
124
|
+
this.noAmbientBindWarning = noAmbientBindWarning;
|
|
125
|
+
this._als = null;
|
|
126
|
+
this._enterWithUsable = false;
|
|
127
|
+
this._syncStack = EMPTY_STACK;
|
|
128
|
+
this._adoptionChecked = false;
|
|
129
|
+
this._warnedNoAmbientBind = false;
|
|
130
|
+
}
|
|
131
|
+
maybeAdoptAsyncLocalStorage() {
|
|
132
|
+
if (this._adoptionChecked) return;
|
|
133
|
+
this._adoptionChecked = true;
|
|
134
|
+
const Ctor = getAsyncLocalStorageCtor();
|
|
135
|
+
if (!Ctor) return;
|
|
136
|
+
const als = new Ctor();
|
|
137
|
+
try {
|
|
138
|
+
als.run(EMPTY_STACK, () => {
|
|
139
|
+
});
|
|
140
|
+
} catch (e) {
|
|
141
|
+
return;
|
|
142
|
+
}
|
|
143
|
+
this._als = als;
|
|
144
|
+
if (typeof als.enterWith === "function") {
|
|
145
|
+
try {
|
|
146
|
+
als.enterWith(EMPTY_STACK);
|
|
147
|
+
this._enterWithUsable = true;
|
|
148
|
+
} catch (e) {
|
|
149
|
+
this._enterWithUsable = false;
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
getStack() {
|
|
154
|
+
var _a;
|
|
155
|
+
this.maybeAdoptAsyncLocalStorage();
|
|
156
|
+
if (this._als) return (_a = this._als.getStore()) != null ? _a : this._syncStack;
|
|
157
|
+
return this._syncStack;
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* Persist an ambient stack mutation. Returns false when an ALS is adopted but
|
|
161
|
+
* `enterWith` is unusable (workerd): callers must NOT fall back to the
|
|
162
|
+
* process-shared sync stack, since concurrent isolates would cross-stamp.
|
|
163
|
+
*/
|
|
164
|
+
setAmbientStack(stack) {
|
|
165
|
+
if (this._als) {
|
|
166
|
+
if (!this._enterWithUsable) return false;
|
|
167
|
+
this._als.enterWith(stack);
|
|
168
|
+
return true;
|
|
169
|
+
}
|
|
170
|
+
this._syncStack = stack;
|
|
171
|
+
return true;
|
|
172
|
+
}
|
|
173
|
+
push(binding) {
|
|
174
|
+
this.maybeAdoptAsyncLocalStorage();
|
|
175
|
+
if (this._als && !this._enterWithUsable) {
|
|
176
|
+
this.warnNoAmbientBindOnce();
|
|
177
|
+
return;
|
|
178
|
+
}
|
|
179
|
+
let stack = this.getStack();
|
|
180
|
+
if (stack.length >= MAX_BINDING_STACK) {
|
|
181
|
+
stack = stack.filter((b) => b.isLive());
|
|
182
|
+
if (stack.length >= MAX_BINDING_STACK) {
|
|
183
|
+
stack = stack.slice(stack.length - (MAX_BINDING_STACK - 1));
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
this.setAmbientStack([...stack, binding]);
|
|
187
|
+
}
|
|
188
|
+
remove(binding) {
|
|
189
|
+
binding.markDead();
|
|
190
|
+
const stack = this.getStack();
|
|
191
|
+
const pruned = stack.filter((b) => b !== binding && b.isLive());
|
|
192
|
+
if (pruned.length !== stack.length) {
|
|
193
|
+
this.setAmbientStack(pruned);
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
runWith(binding, callback) {
|
|
197
|
+
this.maybeAdoptAsyncLocalStorage();
|
|
198
|
+
if (this._als) {
|
|
199
|
+
return this._als.run([...this.getStack(), binding], callback);
|
|
200
|
+
}
|
|
201
|
+
const previous = this._syncStack;
|
|
202
|
+
this._syncStack = [...previous, binding];
|
|
203
|
+
try {
|
|
204
|
+
return callback();
|
|
205
|
+
} finally {
|
|
206
|
+
this._syncStack = previous;
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
current() {
|
|
210
|
+
const stack = this.getStack();
|
|
211
|
+
if (stack.length === 0) return void 0;
|
|
212
|
+
const top = stack[stack.length - 1];
|
|
213
|
+
if (top.isLive()) return top;
|
|
214
|
+
const pruned = stack.filter((b) => b.isLive());
|
|
215
|
+
this.setAmbientStack(pruned);
|
|
216
|
+
return pruned.length > 0 ? pruned[pruned.length - 1] : void 0;
|
|
217
|
+
}
|
|
218
|
+
warnNoAmbientBindOnce() {
|
|
219
|
+
if (this._warnedNoAmbientBind) return;
|
|
220
|
+
this._warnedNoAmbientBind = true;
|
|
221
|
+
console.warn(this.noAmbientBindWarning);
|
|
222
|
+
}
|
|
223
|
+
};
|
|
224
|
+
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.";
|
|
225
|
+
var ROUTING_STORAGE_KEY = /* @__PURE__ */ Symbol.for("raindrop.tracing.routingContextStorage");
|
|
226
|
+
function routingStorage() {
|
|
227
|
+
const holder = globalThis;
|
|
228
|
+
let storage = holder[ROUTING_STORAGE_KEY];
|
|
229
|
+
if (!storage) {
|
|
230
|
+
storage = new ContextStackStorage(NO_AMBIENT_ROUTING_BIND_WARNING);
|
|
231
|
+
holder[ROUTING_STORAGE_KEY] = storage;
|
|
232
|
+
}
|
|
233
|
+
return storage;
|
|
234
|
+
}
|
|
235
|
+
function currentRoutingBinding() {
|
|
236
|
+
const bound = routingStorage().current();
|
|
237
|
+
if (!bound) return void 0;
|
|
238
|
+
return {
|
|
239
|
+
projectId: bound.projectId,
|
|
240
|
+
authHint: bound.authHint,
|
|
241
|
+
...bound.appGit ? { appGit: bound.appGit } : {},
|
|
242
|
+
...bound.appGitSource ? { appGitSource: bound.appGitSource } : {}
|
|
243
|
+
};
|
|
244
|
+
}
|
|
245
|
+
var APP_COMMIT_SHA = "raindrop.app.commit_sha";
|
|
246
|
+
var APP_COMMIT_DIRTY = "raindrop.app.commit_dirty";
|
|
247
|
+
var APP_BRANCH = "raindrop.app.branch";
|
|
248
|
+
var APP_GIT_KEYS = [APP_COMMIT_SHA, APP_COMMIT_DIRTY, APP_BRANCH];
|
|
249
|
+
var own = (value, key) => Object.prototype.hasOwnProperty.call(value, key);
|
|
250
|
+
function appGitExplicitKeys(properties) {
|
|
251
|
+
const keys = /* @__PURE__ */ new Set();
|
|
252
|
+
if (!properties) return keys;
|
|
253
|
+
for (const key of APP_GIT_KEYS) {
|
|
254
|
+
if (own(properties, key)) keys.add(key);
|
|
255
|
+
}
|
|
256
|
+
return keys;
|
|
257
|
+
}
|
|
258
|
+
function mergeAppGitSnapshot(base, properties, explicitKeys = /* @__PURE__ */ new Set()) {
|
|
259
|
+
try {
|
|
260
|
+
const result = { ...base };
|
|
261
|
+
if (properties && own(properties, APP_COMMIT_SHA) && properties[APP_COMMIT_SHA] !== result[APP_COMMIT_SHA]) {
|
|
262
|
+
if (!explicitKeys.has(APP_COMMIT_DIRTY) && !own(properties, APP_COMMIT_DIRTY)) {
|
|
263
|
+
delete result[APP_COMMIT_DIRTY];
|
|
264
|
+
}
|
|
265
|
+
if (!explicitKeys.has(APP_BRANCH) && !own(properties, APP_BRANCH)) {
|
|
266
|
+
delete result[APP_BRANCH];
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
for (const key of APP_GIT_KEYS) {
|
|
270
|
+
if (properties && own(properties, key)) result[key] = properties[key];
|
|
271
|
+
}
|
|
272
|
+
return Object.freeze(result);
|
|
273
|
+
} catch (e) {
|
|
274
|
+
return Object.freeze({});
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
function validAppCommitSha(value) {
|
|
278
|
+
if (typeof value !== "string" || value.length > 128) return void 0;
|
|
279
|
+
const cleaned = value.trim();
|
|
280
|
+
return /^(?:[a-fA-F0-9]{40}|[a-fA-F0-9]{64})$/.test(cleaned) ? cleaned.toLowerCase() : void 0;
|
|
281
|
+
}
|
|
282
|
+
function shortString(value) {
|
|
283
|
+
if (typeof value !== "string" || value.length > 1024) return void 0;
|
|
284
|
+
const cleaned = value.trim();
|
|
285
|
+
return cleaned.length > 0 ? cleaned : void 0;
|
|
286
|
+
}
|
|
287
|
+
function flag(value) {
|
|
288
|
+
if (value === true || value === "true" || value === "1") return true;
|
|
289
|
+
if (value === false || value === "false" || value === "0") return false;
|
|
290
|
+
return void 0;
|
|
291
|
+
}
|
|
292
|
+
function environment() {
|
|
293
|
+
try {
|
|
294
|
+
return typeof process === "undefined" ? {} : process.env;
|
|
295
|
+
} catch (e) {
|
|
296
|
+
return {};
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
var DEPLOYMENTS = [
|
|
300
|
+
["VERCEL", "VERCEL_GIT_COMMIT_SHA", "VERCEL_GIT_COMMIT_REF"],
|
|
301
|
+
["NETLIFY", "COMMIT_REF", "BRANCH"],
|
|
302
|
+
["RAILWAY_ENVIRONMENT_NAME", "RAILWAY_GIT_COMMIT_SHA", "RAILWAY_GIT_BRANCH"],
|
|
303
|
+
["RAILWAY_ENVIRONMENT", "RAILWAY_GIT_COMMIT_SHA", "RAILWAY_GIT_BRANCH"],
|
|
304
|
+
["RENDER", "RENDER_GIT_COMMIT", "RENDER_GIT_BRANCH"],
|
|
305
|
+
["DYNO", "HEROKU_BUILD_COMMIT", ""],
|
|
306
|
+
["DYNO", "HEROKU_SLUG_COMMIT", ""],
|
|
307
|
+
["AWS_APP_ID", "AWS_COMMIT_ID", "AWS_BRANCH"],
|
|
308
|
+
["WORKERS_CI", "WORKERS_CI_COMMIT_SHA", "WORKERS_CI_BRANCH"]
|
|
309
|
+
];
|
|
310
|
+
var CI_SOURCES = [
|
|
311
|
+
["GITHUB_ACTIONS", "GITHUB_SHA", "GITHUB_REF_NAME"],
|
|
312
|
+
["GITLAB_CI", "CI_COMMIT_SHA", "CI_COMMIT_REF_NAME"],
|
|
313
|
+
["CIRCLECI", "CIRCLE_SHA1", "CIRCLE_BRANCH"]
|
|
314
|
+
];
|
|
315
|
+
function detectedSource(env, table, detectBranch) {
|
|
316
|
+
for (const row of table) {
|
|
317
|
+
const [marker, shaKey, branchKey] = row;
|
|
318
|
+
if (!marker || !shaKey || !shortString(env[marker]) || flag(env[marker]) === false) continue;
|
|
319
|
+
const commitSha = validAppCommitSha(env[shaKey]);
|
|
320
|
+
if (commitSha)
|
|
321
|
+
return {
|
|
322
|
+
commitSha,
|
|
323
|
+
...detectBranch && branchKey ? { branch: shortString(env[branchKey]) } : {}
|
|
324
|
+
};
|
|
325
|
+
}
|
|
326
|
+
return {};
|
|
327
|
+
}
|
|
328
|
+
var AppGitContextImpl = class {
|
|
329
|
+
constructor(options, runtime = {}) {
|
|
330
|
+
this.defaults = {};
|
|
331
|
+
this.explicit = {};
|
|
332
|
+
this.explicitKeys = /* @__PURE__ */ new Set();
|
|
333
|
+
this.disposed = false;
|
|
334
|
+
this.operations = /* @__PURE__ */ new Map();
|
|
335
|
+
this.operationOverflow = false;
|
|
336
|
+
this.detectBranch = false;
|
|
337
|
+
this.disabled = false;
|
|
338
|
+
var _a, _b, _c, _d, _e, _f;
|
|
339
|
+
try {
|
|
340
|
+
if (options === false) {
|
|
341
|
+
this.disabled = true;
|
|
342
|
+
return;
|
|
343
|
+
}
|
|
344
|
+
const opts = options != null ? options : {};
|
|
345
|
+
const env = (_a = runtime.env) != null ? _a : environment();
|
|
346
|
+
const detectBranch = (_c = (_b = flag(opts.detectBranch)) != null ? _b : flag(env.RAINDROP_GIT_DETECT_BRANCH)) != null ? _c : false;
|
|
347
|
+
this.detectBranch = detectBranch;
|
|
348
|
+
const collectBranch = detectBranch || runtime.captureLegacyReplayBranch === true;
|
|
349
|
+
const autoDetect = runtime.allowDiscovery === false ? false : (_e = (_d = flag(opts.autoDetect)) != null ? _d : flag(env.RAINDROP_GIT_AUTO_DETECT)) != null ? _e : true;
|
|
350
|
+
const configuredSha = opts.commitSha;
|
|
351
|
+
const explicitSha = configuredSha === void 0 ? env.RAINDROP_COMMIT_SHA : configuredSha;
|
|
352
|
+
if (explicitSha === null) this.explicit[APP_COMMIT_SHA] = null;
|
|
353
|
+
else if (typeof explicitSha === "string" && validAppCommitSha(explicitSha))
|
|
354
|
+
this.explicit[APP_COMMIT_SHA] = explicitSha;
|
|
355
|
+
const configuredDirty = opts.commitDirty;
|
|
356
|
+
const explicitDirty = configuredDirty === void 0 ? flag(env.RAINDROP_COMMIT_DIRTY) : configuredDirty;
|
|
357
|
+
if (explicitDirty === null || typeof explicitDirty === "boolean")
|
|
358
|
+
this.explicit[APP_COMMIT_DIRTY] = explicitDirty;
|
|
359
|
+
const configuredBranch = opts.branch;
|
|
360
|
+
const explicitBranch = configuredBranch === void 0 ? env.RAINDROP_BRANCH : configuredBranch;
|
|
361
|
+
if (explicitBranch === null) this.explicit[APP_BRANCH] = null;
|
|
362
|
+
else if (typeof explicitBranch === "string" && explicitBranch.length <= 1024)
|
|
363
|
+
this.explicit[APP_BRANCH] = explicitBranch;
|
|
364
|
+
this.explicitKeys = appGitExplicitKeys(this.explicit);
|
|
365
|
+
this.defaults = { ...this.explicit };
|
|
366
|
+
if (!autoDetect || explicitSha !== void 0) return;
|
|
367
|
+
const sourceDirectory = (_f = shortString(opts.sourceDirectory)) != null ? _f : shortString(env.RAINDROP_GIT_SOURCE_DIRECTORY);
|
|
368
|
+
if (runtime.allowLocalGit === false && !sourceDirectory) return;
|
|
369
|
+
const deploy = sourceDirectory ? {} : detectedSource(env, DEPLOYMENTS, collectBranch);
|
|
370
|
+
if (deploy.commitSha) {
|
|
371
|
+
this.accept(deploy);
|
|
372
|
+
return;
|
|
373
|
+
}
|
|
374
|
+
const fallback = sourceDirectory ? {} : detectedSource(env, CI_SOURCES, collectBranch);
|
|
375
|
+
if (runtime.resolveLocal && (runtime.allowLocalGit !== false || sourceDirectory)) {
|
|
376
|
+
this.cancel = runtime.resolveLocal(sourceDirectory, collectBranch, (result) => {
|
|
377
|
+
try {
|
|
378
|
+
if (!this.disposed) this.accept(result.commitSha ? result : fallback);
|
|
379
|
+
} catch (e) {
|
|
380
|
+
}
|
|
381
|
+
});
|
|
382
|
+
} else this.accept(fallback);
|
|
383
|
+
} catch (e) {
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
accept(result) {
|
|
387
|
+
const sha = validAppCommitSha(result.commitSha);
|
|
388
|
+
if (!sha) return;
|
|
389
|
+
this.replayBranch = shortString(result.branch);
|
|
390
|
+
this.defaults = {
|
|
391
|
+
[APP_COMMIT_SHA]: sha,
|
|
392
|
+
...typeof result.commitDirty === "boolean" ? { [APP_COMMIT_DIRTY]: result.commitDirty } : {},
|
|
393
|
+
...this.detectBranch && this.replayBranch ? { [APP_BRANCH]: this.replayBranch } : {},
|
|
394
|
+
...this.explicit
|
|
395
|
+
};
|
|
396
|
+
}
|
|
397
|
+
snapshot(properties) {
|
|
398
|
+
var _a;
|
|
399
|
+
try {
|
|
400
|
+
const binding = currentRoutingBinding();
|
|
401
|
+
const base = this.disabled && (binding == null ? void 0 : binding.appGitSource) !== "replay-override" ? {} : (_a = binding == null ? void 0 : binding.appGit) != null ? _a : this.defaults;
|
|
402
|
+
return this.mergeSnapshot(base, properties);
|
|
403
|
+
} catch (e) {
|
|
404
|
+
return Object.freeze({});
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
/** Safe defaults when no operation/span start was observed; never infer identity. */
|
|
408
|
+
snapshotExplicit(properties, eventId) {
|
|
409
|
+
try {
|
|
410
|
+
const base = { ...this.explicit };
|
|
411
|
+
const operation = eventId ? this.operations.get(eventId) : void 0;
|
|
412
|
+
if (operation) {
|
|
413
|
+
for (const key of operation.explicitKeys) base[key] = operation.snapshot[key];
|
|
414
|
+
}
|
|
415
|
+
return this.mergeSnapshot(base, properties, new Set(Object.keys(base)));
|
|
416
|
+
} catch (e) {
|
|
417
|
+
return mergeAppGitSnapshot({}, properties);
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
/** Existing replay branch reporting stays separate from opt-in event properties. */
|
|
421
|
+
snapshotForReplay() {
|
|
422
|
+
const snapshot = this.snapshot();
|
|
423
|
+
if (this.replayBranch && !own(snapshot, APP_BRANCH) && snapshot[APP_COMMIT_SHA] === this.defaults[APP_COMMIT_SHA]) {
|
|
424
|
+
return Object.freeze({ ...snapshot, [APP_BRANCH]: this.replayBranch });
|
|
425
|
+
}
|
|
426
|
+
return snapshot;
|
|
427
|
+
}
|
|
428
|
+
/** Merge a frozen span snapshot without losing client-authored provenance. */
|
|
429
|
+
mergeSnapshot(base, properties, explicitKeys = this.explicitKeys) {
|
|
430
|
+
return mergeAppGitSnapshot(base, properties, /* @__PURE__ */ new Set([...this.explicitKeys, ...explicitKeys]));
|
|
431
|
+
}
|
|
432
|
+
/** Shippers belonging to one client share this bounded operation registry. */
|
|
433
|
+
forOperation(eventId, properties, owner) {
|
|
434
|
+
if (!eventId) return this.snapshot(properties);
|
|
435
|
+
let operation = this.operations.get(eventId);
|
|
436
|
+
if (!operation) {
|
|
437
|
+
if (this.operations.size >= 1e4) this.operationOverflow = true;
|
|
438
|
+
if (this.operationOverflow) return this.mergeSnapshot({}, properties);
|
|
439
|
+
operation = {
|
|
440
|
+
snapshot: this.snapshot(properties),
|
|
441
|
+
owners: /* @__PURE__ */ new Set(),
|
|
442
|
+
unowned: owner === void 0,
|
|
443
|
+
explicitKeys: appGitExplicitKeys(properties)
|
|
444
|
+
};
|
|
445
|
+
this.operations.set(eventId, operation);
|
|
446
|
+
} else if (properties && APP_GIT_KEYS.some((key) => own(properties, key))) {
|
|
447
|
+
const explicitKeys = /* @__PURE__ */ new Set([...this.explicitKeys, ...operation.explicitKeys]);
|
|
448
|
+
operation.snapshot = this.mergeSnapshot(operation.snapshot, properties, explicitKeys);
|
|
449
|
+
for (const key of appGitExplicitKeys(properties)) operation.explicitKeys.add(key);
|
|
450
|
+
}
|
|
451
|
+
if (!owner) operation.unowned = true;
|
|
452
|
+
if (owner) operation.owners.add(owner);
|
|
453
|
+
return operation.snapshot;
|
|
454
|
+
}
|
|
455
|
+
releaseOperation(eventId, owner) {
|
|
456
|
+
const operation = this.operations.get(eventId);
|
|
457
|
+
if (!operation) return;
|
|
458
|
+
operation.owners.delete(owner);
|
|
459
|
+
if (operation.owners.size === 0 && !operation.unowned) this.operations.delete(eventId);
|
|
460
|
+
}
|
|
461
|
+
finishOperation(eventId) {
|
|
462
|
+
this.operations.delete(eventId);
|
|
463
|
+
}
|
|
464
|
+
dispose() {
|
|
465
|
+
var _a;
|
|
466
|
+
this.disposed = true;
|
|
467
|
+
try {
|
|
468
|
+
(_a = this.cancel) == null ? void 0 : _a.call(this);
|
|
469
|
+
} catch (e) {
|
|
470
|
+
}
|
|
471
|
+
}
|
|
472
|
+
};
|
|
473
|
+
var AppGitContext = AppGitContextImpl;
|
|
474
|
+
function createAppGitContext(options, runtime = {}) {
|
|
475
|
+
return new AppGitContext(options, runtime);
|
|
476
|
+
}
|
|
477
|
+
function withAppGitProperties(properties, snapshot) {
|
|
478
|
+
try {
|
|
479
|
+
const merged = { ...properties };
|
|
480
|
+
for (const key of APP_GIT_KEYS)
|
|
481
|
+
if (!own(merged, key) && own(snapshot, key)) merged[key] = snapshot[key];
|
|
482
|
+
return merged;
|
|
483
|
+
} catch (e) {
|
|
484
|
+
return properties != null ? properties : {};
|
|
485
|
+
}
|
|
486
|
+
}
|
|
487
|
+
function withAppGitAttributes(attributes, snapshot) {
|
|
488
|
+
try {
|
|
489
|
+
const present = new Set(attributes.flatMap((attr) => attr ? [attr.key] : []));
|
|
490
|
+
const added = [];
|
|
491
|
+
for (const key of APP_GIT_KEYS) {
|
|
492
|
+
if (present.has(key) || present.has(`ai.telemetry.metadata.${key}`) || present.has(`traceloop.association.properties.${key}`))
|
|
493
|
+
continue;
|
|
494
|
+
const value = snapshot[key];
|
|
495
|
+
if (typeof value === "string") added.push({ key, value: { stringValue: value } });
|
|
496
|
+
else if (typeof value === "boolean") added.push({ key, value: { boolValue: value } });
|
|
497
|
+
}
|
|
498
|
+
return added.length ? [...attributes, ...added] : attributes;
|
|
499
|
+
} catch (e) {
|
|
500
|
+
return attributes;
|
|
501
|
+
}
|
|
502
|
+
}
|
|
503
|
+
function appGitPropertiesFromAttributes(attributes) {
|
|
504
|
+
var _a, _b, _c;
|
|
505
|
+
const properties = {};
|
|
506
|
+
try {
|
|
507
|
+
for (const attr of attributes) {
|
|
508
|
+
if (!attr) continue;
|
|
509
|
+
for (const key of APP_GIT_KEYS) {
|
|
510
|
+
if (attr.key === key || attr.key === `ai.telemetry.metadata.${key}` || attr.key === `traceloop.association.properties.${key}`) {
|
|
511
|
+
properties[key] = (_c = (_b = (_a = attr.value.stringValue) != null ? _a : attr.value.boolValue) != null ? _b : attr.value.intValue) != null ? _c : null;
|
|
512
|
+
}
|
|
513
|
+
}
|
|
514
|
+
}
|
|
515
|
+
} catch (e) {
|
|
516
|
+
}
|
|
517
|
+
return properties;
|
|
518
|
+
}
|
|
67
519
|
function getCrypto() {
|
|
68
520
|
const c = globalThis.crypto;
|
|
69
521
|
return c;
|
|
@@ -168,7 +620,7 @@ function runWithTracingSuppressed(fn) {
|
|
|
168
620
|
var DEFAULT_REQUEST_TIMEOUT_MS = 3e4;
|
|
169
621
|
var MAX_RETRY_DELAY_MS = 3e4;
|
|
170
622
|
function wait(ms) {
|
|
171
|
-
return new Promise((
|
|
623
|
+
return new Promise((resolve2) => setTimeout(resolve2, ms));
|
|
172
624
|
}
|
|
173
625
|
function formatEndpoint(endpoint) {
|
|
174
626
|
if (!endpoint) return void 0;
|
|
@@ -205,9 +657,9 @@ async function raceWithTimeout(promise, timeoutMs) {
|
|
|
205
657
|
() => true,
|
|
206
658
|
() => true
|
|
207
659
|
),
|
|
208
|
-
new Promise((
|
|
660
|
+
new Promise((resolve2) => {
|
|
209
661
|
var _a;
|
|
210
|
-
timer = setTimeout(() =>
|
|
662
|
+
timer = setTimeout(() => resolve2(false), Math.max(0, timeoutMs));
|
|
211
663
|
(_a = timer.unref) == null ? void 0 : _a.call(timer);
|
|
212
664
|
})
|
|
213
665
|
]);
|
|
@@ -380,55 +832,6 @@ function buildExportTraceServiceRequest(spans, serviceName = "raindrop.core", se
|
|
|
380
832
|
]
|
|
381
833
|
};
|
|
382
834
|
}
|
|
383
|
-
var STATE_KEY = /* @__PURE__ */ Symbol.for("raindrop.tracing.replayTraceRoutingState");
|
|
384
|
-
function state() {
|
|
385
|
-
const holder = globalThis;
|
|
386
|
-
let current = holder[STATE_KEY];
|
|
387
|
-
if (!current) {
|
|
388
|
-
let storage = null;
|
|
389
|
-
try {
|
|
390
|
-
const Ctor = globalThis.RAINDROP_ASYNC_LOCAL_STORAGE;
|
|
391
|
-
if (Ctor) storage = new Ctor();
|
|
392
|
-
} catch (e) {
|
|
393
|
-
storage = null;
|
|
394
|
-
}
|
|
395
|
-
current = {
|
|
396
|
-
storage,
|
|
397
|
-
syncDestination: void 0,
|
|
398
|
-
spanDestinations: /* @__PURE__ */ new WeakMap()
|
|
399
|
-
};
|
|
400
|
-
holder[STATE_KEY] = current;
|
|
401
|
-
}
|
|
402
|
-
return current;
|
|
403
|
-
}
|
|
404
|
-
function currentReplayTraceDestination() {
|
|
405
|
-
var _a, _b;
|
|
406
|
-
const routing = state();
|
|
407
|
-
return (_b = (_a = routing.storage) == null ? void 0 : _a.getStore()) != null ? _b : routing.syncDestination;
|
|
408
|
-
}
|
|
409
|
-
function rememberReplayTraceDestination(span) {
|
|
410
|
-
const destination = currentReplayTraceDestination();
|
|
411
|
-
if (destination) state().spanDestinations.set(span, destination);
|
|
412
|
-
}
|
|
413
|
-
function copyReplayTraceDestination(source, target) {
|
|
414
|
-
const destination = state().spanDestinations.get(source);
|
|
415
|
-
if (destination) state().spanDestinations.set(target, destination);
|
|
416
|
-
}
|
|
417
|
-
function replayTraceDestinationFor(value) {
|
|
418
|
-
if (typeof value !== "object" && typeof value !== "function" || value === null) {
|
|
419
|
-
return void 0;
|
|
420
|
-
}
|
|
421
|
-
return state().spanDestinations.get(value);
|
|
422
|
-
}
|
|
423
|
-
function recordReplayExportedSpan(destination, spanId, traceId) {
|
|
424
|
-
var _a, _b;
|
|
425
|
-
if (!destination || !spanId || !traceId) return;
|
|
426
|
-
(_a = destination.exportedSpanIds) == null ? void 0 : _a.add(spanId);
|
|
427
|
-
(_b = destination.exportedTraceIds) == null ? void 0 : _b.add(traceId);
|
|
428
|
-
}
|
|
429
|
-
function replayTraceUrl(baseUrl) {
|
|
430
|
-
return `${baseUrl.replace(/\/+$/, "")}/v1/traces`;
|
|
431
|
-
}
|
|
432
835
|
var LOCAL_DEBUGGER_ENV_VAR = "RAINDROP_LOCAL_DEBUGGER";
|
|
433
836
|
var WORKSHOP_ENV_VAR = "RAINDROP_WORKSHOP";
|
|
434
837
|
var DEFAULT_LOCAL_WORKSHOP_URL = "http://localhost:5899/v1/";
|
|
@@ -538,6 +941,13 @@ function projectIdHeaders(projectId) {
|
|
|
538
941
|
}
|
|
539
942
|
var SHUTDOWN_DEADLINE_MS = 1e4;
|
|
540
943
|
var POST_SHUTDOWN_TIMEOUT_MS = 5e3;
|
|
944
|
+
function appGitOwnerId(prefix) {
|
|
945
|
+
try {
|
|
946
|
+
return `${prefix}:${randomUUID()}`;
|
|
947
|
+
} catch (e) {
|
|
948
|
+
return `${prefix}:${Date.now().toString(36)}:${Math.random().toString(36).slice(2)}`;
|
|
949
|
+
}
|
|
950
|
+
}
|
|
541
951
|
function mergePatches(target, source) {
|
|
542
952
|
var _a, _b, _c, _d, _e, _f, _g, _h, _i;
|
|
543
953
|
const out = { ...target, ...source };
|
|
@@ -587,22 +997,25 @@ function eventTelemetryProperties(patch) {
|
|
|
587
997
|
}
|
|
588
998
|
var EventShipper = class {
|
|
589
999
|
constructor(opts) {
|
|
1000
|
+
this.appGitOwner = appGitOwnerId("event");
|
|
590
1001
|
this.buffers = /* @__PURE__ */ new Map();
|
|
591
1002
|
this.sticky = /* @__PURE__ */ new Map();
|
|
592
1003
|
this.timers = /* @__PURE__ */ new Map();
|
|
593
1004
|
this.inFlight = /* @__PURE__ */ new Set();
|
|
594
1005
|
this.hasShutdown = false;
|
|
595
|
-
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
596
|
-
this.
|
|
597
|
-
this.
|
|
1006
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _i;
|
|
1007
|
+
this.appGitContext = (_a = opts.appGitContext) != null ? _a : createAppGitContext(opts.appGit);
|
|
1008
|
+
this.ownsAppGitContext = opts.appGitContext === void 0;
|
|
1009
|
+
this.writeKey = (_b = opts.writeKey) == null ? void 0 : _b.trim();
|
|
1010
|
+
this.baseUrl = (_c = formatEndpoint(opts.endpoint)) != null ? _c : "https://api.raindrop.ai/v1/";
|
|
598
1011
|
this.enabled = opts.enabled !== false;
|
|
599
1012
|
this.debug = opts.debug;
|
|
600
|
-
this.partialFlushMs = (
|
|
601
|
-
this.sdkName = (
|
|
1013
|
+
this.partialFlushMs = (_d = opts.partialFlushMs) != null ? _d : 1e3;
|
|
1014
|
+
this.sdkName = (_e = opts.sdkName) != null ? _e : "core";
|
|
602
1015
|
this.prefix = `[raindrop-ai/${this.sdkName}]`;
|
|
603
|
-
this.defaultEventName = (
|
|
1016
|
+
this.defaultEventName = (_f = opts.defaultEventName) != null ? _f : "ai_generation";
|
|
604
1017
|
this.maxTextFieldCharsOpt = opts.maxTextFieldChars;
|
|
605
|
-
this.localDebuggerUrl = (
|
|
1018
|
+
this.localDebuggerUrl = (_g = resolveLocalDebuggerBaseUrl(opts.localDebuggerUrl)) != null ? _g : void 0;
|
|
606
1019
|
if (this.debug && this.localDebuggerUrl) {
|
|
607
1020
|
console.log(`${this.prefix} Local debugger mirroring: ${this.localDebuggerUrl}`);
|
|
608
1021
|
}
|
|
@@ -613,8 +1026,8 @@ var EventShipper = class {
|
|
|
613
1026
|
const isNode = typeof process !== "undefined" && typeof process.version === "string";
|
|
614
1027
|
this.context = {
|
|
615
1028
|
library: {
|
|
616
|
-
name: (
|
|
617
|
-
version: (
|
|
1029
|
+
name: (_h = opts.libraryName) != null ? _h : "@raindrop-ai/core",
|
|
1030
|
+
version: (_i = opts.libraryVersion) != null ? _i : "0.0.0"
|
|
618
1031
|
},
|
|
619
1032
|
metadata: {
|
|
620
1033
|
jsRuntime: isNode ? "node" : "web",
|
|
@@ -622,6 +1035,9 @@ var EventShipper = class {
|
|
|
622
1035
|
}
|
|
623
1036
|
};
|
|
624
1037
|
}
|
|
1038
|
+
ownAppGitContextForShutdown() {
|
|
1039
|
+
this.ownsAppGitContext = true;
|
|
1040
|
+
}
|
|
625
1041
|
isDebugEnabled() {
|
|
626
1042
|
return this.debug;
|
|
627
1043
|
}
|
|
@@ -700,6 +1116,13 @@ var EventShipper = class {
|
|
|
700
1116
|
}
|
|
701
1117
|
const sticky = (_c = this.sticky.get(eventId)) != null ? _c : {};
|
|
702
1118
|
const existing = (_d = this.buffers.get(eventId)) != null ? _d : {};
|
|
1119
|
+
patch = {
|
|
1120
|
+
...patch,
|
|
1121
|
+
properties: withAppGitProperties(
|
|
1122
|
+
patch.properties,
|
|
1123
|
+
this.appGitContext.forOperation(eventId, patch.properties, this.appGitOwner)
|
|
1124
|
+
)
|
|
1125
|
+
};
|
|
703
1126
|
const merged = mergePatches(existing, patch);
|
|
704
1127
|
merged.isPending = (_g = (_f = (_e = patch.isPending) != null ? _e : existing.isPending) != null ? _f : sticky.isPending) != null ? _g : true;
|
|
705
1128
|
this.buffers.set(eventId, merged);
|
|
@@ -713,6 +1136,8 @@ var EventShipper = class {
|
|
|
713
1136
|
if (t) clearTimeout(t);
|
|
714
1137
|
if (merged.isPending === false) {
|
|
715
1138
|
await this.flushOne(eventId);
|
|
1139
|
+
if (this.appGitContext.releaseOperation) this.appGitContext.releaseOperation(eventId, this.appGitOwner);
|
|
1140
|
+
else this.appGitContext.finishOperation(eventId);
|
|
716
1141
|
return;
|
|
717
1142
|
}
|
|
718
1143
|
const timeout = setTimeout(() => {
|
|
@@ -744,6 +1169,7 @@ var EventShipper = class {
|
|
|
744
1169
|
if (!settled) this.warnShutdownDrop("in-flight request(s) at shutdown");
|
|
745
1170
|
} finally {
|
|
746
1171
|
this.shutdownDeadlineAt = void 0;
|
|
1172
|
+
if (this.ownsAppGitContext) this.appGitContext.dispose();
|
|
747
1173
|
}
|
|
748
1174
|
}
|
|
749
1175
|
async trackSignal(signal) {
|
|
@@ -1171,6 +1597,13 @@ function redactJsonAttributeValue(key, value) {
|
|
|
1171
1597
|
if (scrubbedJson === json) return void 0;
|
|
1172
1598
|
return { stringValue: scrubbedJson };
|
|
1173
1599
|
}
|
|
1600
|
+
function appGitOwnerId2(prefix) {
|
|
1601
|
+
try {
|
|
1602
|
+
return `${prefix}:${randomUUID()}`;
|
|
1603
|
+
} catch (e) {
|
|
1604
|
+
return `${prefix}:${Date.now().toString(36)}:${Math.random().toString(36).slice(2)}`;
|
|
1605
|
+
}
|
|
1606
|
+
}
|
|
1174
1607
|
function identityAttrs(args) {
|
|
1175
1608
|
return [
|
|
1176
1609
|
attrString("ai.telemetry.metadata.raindrop.ai.userId", args.userId),
|
|
@@ -1193,23 +1626,30 @@ function applyOtelSpanAttributeLimit(limit) {
|
|
|
1193
1626
|
}
|
|
1194
1627
|
var TraceShipper = class {
|
|
1195
1628
|
constructor(opts) {
|
|
1629
|
+
this.appGitOwner = appGitOwnerId2("trace");
|
|
1630
|
+
this.appGitEventIds = /* @__PURE__ */ new WeakMap();
|
|
1631
|
+
this.appGitActiveSpans = /* @__PURE__ */ new Map();
|
|
1632
|
+
this.appGitCaptured = /* @__PURE__ */ new WeakSet();
|
|
1633
|
+
this.appGitAdded = /* @__PURE__ */ new WeakMap();
|
|
1196
1634
|
this.queue = [];
|
|
1197
1635
|
this.inFlight = /* @__PURE__ */ new Set();
|
|
1198
1636
|
this.hasShutdown = false;
|
|
1199
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _i;
|
|
1200
|
-
this.
|
|
1201
|
-
this.
|
|
1637
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j;
|
|
1638
|
+
this.appGitContext = (_a = opts.appGitContext) != null ? _a : createAppGitContext(opts.appGit);
|
|
1639
|
+
this.ownsAppGitContext = opts.appGitContext === void 0;
|
|
1640
|
+
this.writeKey = (_b = opts.writeKey) == null ? void 0 : _b.trim();
|
|
1641
|
+
this.baseUrl = (_c = formatEndpoint(opts.endpoint)) != null ? _c : "https://api.raindrop.ai/v1/";
|
|
1202
1642
|
this.enabled = opts.enabled !== false;
|
|
1203
1643
|
this.debug = opts.debug;
|
|
1204
1644
|
this.debugSpans = opts.debugSpans === true;
|
|
1205
|
-
this.flushIntervalMs = (
|
|
1206
|
-
this.maxBatchSize = (
|
|
1207
|
-
this.maxQueueSize = (
|
|
1208
|
-
this.sdkName = (
|
|
1645
|
+
this.flushIntervalMs = (_d = opts.flushIntervalMs) != null ? _d : 1e3;
|
|
1646
|
+
this.maxBatchSize = (_e = opts.maxBatchSize) != null ? _e : 50;
|
|
1647
|
+
this.maxQueueSize = (_f = opts.maxQueueSize) != null ? _f : 5e3;
|
|
1648
|
+
this.sdkName = (_g = opts.sdkName) != null ? _g : "core";
|
|
1209
1649
|
this.prefix = `[raindrop-ai/${this.sdkName}]`;
|
|
1210
|
-
this.serviceName = (
|
|
1211
|
-
this.serviceVersion = (
|
|
1212
|
-
this.localDebuggerUrl = (
|
|
1650
|
+
this.serviceName = (_h = opts.serviceName) != null ? _h : "raindrop.core";
|
|
1651
|
+
this.serviceVersion = (_i = opts.serviceVersion) != null ? _i : "0.0.0";
|
|
1652
|
+
this.localDebuggerUrl = (_j = resolveLocalDebuggerBaseUrl(opts.localDebuggerUrl)) != null ? _j : void 0;
|
|
1213
1653
|
if (this.debug && this.localDebuggerUrl) {
|
|
1214
1654
|
console.log(`${this.prefix} Local debugger mirroring: ${this.localDebuggerUrl}`);
|
|
1215
1655
|
}
|
|
@@ -1310,7 +1750,7 @@ var TraceShipper = class {
|
|
|
1310
1750
|
return { ...this.authHeaders(), ...projectIdHeaders(this.projectId) };
|
|
1311
1751
|
}
|
|
1312
1752
|
startSpan(args) {
|
|
1313
|
-
var _a, _b;
|
|
1753
|
+
var _a, _b, _c;
|
|
1314
1754
|
const ids = createSpanIds(args.parent);
|
|
1315
1755
|
const started = (_a = args.startTimeUnixNano) != null ? _a : nowUnixNanoString();
|
|
1316
1756
|
const attrs = [
|
|
@@ -1320,13 +1760,24 @@ var TraceShipper = class {
|
|
|
1320
1760
|
...Object.entries(evalScopeAttributes()).map(([key, value]) => attrString(key, value))
|
|
1321
1761
|
];
|
|
1322
1762
|
if ((_b = args.attributes) == null ? void 0 : _b.length) attrs.push(...args.attributes);
|
|
1763
|
+
const tracksAppGit = this.appGitActiveSpans.has(args.eventId) || this.appGitActiveSpans.size < 1e4;
|
|
1764
|
+
const appGitOverrides = appGitPropertiesFromAttributes(attrs);
|
|
1323
1765
|
const span = {
|
|
1324
1766
|
ids,
|
|
1325
1767
|
name: args.name,
|
|
1326
1768
|
startTimeUnixNano: started,
|
|
1327
|
-
attributes:
|
|
1769
|
+
attributes: withAppGitAttributes(
|
|
1770
|
+
attrs,
|
|
1771
|
+
this.appGitContext.forOperation(args.eventId, appGitOverrides, this.appGitOwner)
|
|
1772
|
+
)
|
|
1328
1773
|
};
|
|
1329
1774
|
rememberReplayTraceDestination(span);
|
|
1775
|
+
this.appGitCaptured.add(span);
|
|
1776
|
+
this.appGitEventIds.set(span, args.eventId);
|
|
1777
|
+
if (tracksAppGit) {
|
|
1778
|
+
this.appGitActiveSpans.set(args.eventId, ((_c = this.appGitActiveSpans.get(args.eventId)) != null ? _c : 0) + 1);
|
|
1779
|
+
}
|
|
1780
|
+
this.appGitAdded.set(span, new Set(span.attributes.filter((attr) => !attrs.includes(attr))));
|
|
1330
1781
|
const openSpan = buildOtlpSpan({
|
|
1331
1782
|
ids: span.ids,
|
|
1332
1783
|
name: span.name,
|
|
@@ -1366,11 +1817,17 @@ var TraceShipper = class {
|
|
|
1366
1817
|
});
|
|
1367
1818
|
}
|
|
1368
1819
|
endSpan(span, extra) {
|
|
1369
|
-
var _a, _b;
|
|
1820
|
+
var _a, _b, _c;
|
|
1370
1821
|
if (span.endTimeUnixNano) return;
|
|
1371
1822
|
span.endTimeUnixNano = (_a = extra == null ? void 0 : extra.endTimeUnixNano) != null ? _a : nowUnixNanoString();
|
|
1372
1823
|
if ((_b = extra == null ? void 0 : extra.attributes) == null ? void 0 : _b.length) {
|
|
1824
|
+
const overrides = appGitPropertiesFromAttributes(extra.attributes);
|
|
1825
|
+
const eventId2 = this.appGitEventIds.get(span);
|
|
1826
|
+
const snapshot = eventId2 ? this.appGitContext.forOperation(eventId2, overrides, this.appGitOwner) : overrides;
|
|
1827
|
+
const added = this.appGitAdded.get(span);
|
|
1828
|
+
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));
|
|
1373
1829
|
span.attributes.push(...extra.attributes);
|
|
1830
|
+
span.attributes = withAppGitAttributes(span.attributes, snapshot);
|
|
1374
1831
|
}
|
|
1375
1832
|
let status = extra == null ? void 0 : extra.status;
|
|
1376
1833
|
if (!status && (extra == null ? void 0 : extra.error) !== void 0) {
|
|
@@ -1386,8 +1843,19 @@ var TraceShipper = class {
|
|
|
1386
1843
|
status
|
|
1387
1844
|
});
|
|
1388
1845
|
copyReplayTraceDestination(span, otlp);
|
|
1846
|
+
this.appGitCaptured.add(otlp);
|
|
1389
1847
|
this.enqueue(otlp);
|
|
1390
1848
|
this.mirrorToLocalDebugger(otlp, true);
|
|
1849
|
+
const eventId = this.appGitEventIds.get(span);
|
|
1850
|
+
if (eventId && this.appGitActiveSpans.has(eventId)) {
|
|
1851
|
+
const remaining = ((_c = this.appGitActiveSpans.get(eventId)) != null ? _c : 1) - 1;
|
|
1852
|
+
if (remaining > 0) this.appGitActiveSpans.set(eventId, remaining);
|
|
1853
|
+
else {
|
|
1854
|
+
this.appGitActiveSpans.delete(eventId);
|
|
1855
|
+
if (this.appGitContext.releaseOperation) this.appGitContext.releaseOperation(eventId, this.appGitOwner);
|
|
1856
|
+
else if (this.ownsAppGitContext) this.appGitContext.finishOperation(eventId);
|
|
1857
|
+
}
|
|
1858
|
+
}
|
|
1391
1859
|
}
|
|
1392
1860
|
createSpan(args) {
|
|
1393
1861
|
var _a;
|
|
@@ -1398,20 +1866,41 @@ var TraceShipper = class {
|
|
|
1398
1866
|
...Object.entries(evalScopeAttributes()).map(([key, value]) => attrString(key, value))
|
|
1399
1867
|
];
|
|
1400
1868
|
if ((_a = args.attributes) == null ? void 0 : _a.length) attrs.push(...args.attributes);
|
|
1869
|
+
const tracksAppGit = !this.appGitActiveSpans.has(args.eventId);
|
|
1401
1870
|
const otlp = buildOtlpSpan({
|
|
1402
1871
|
ids,
|
|
1403
1872
|
name: args.name,
|
|
1404
1873
|
startTimeUnixNano: args.startTimeUnixNano,
|
|
1405
1874
|
endTimeUnixNano: args.endTimeUnixNano,
|
|
1406
|
-
attributes:
|
|
1875
|
+
attributes: withAppGitAttributes(
|
|
1876
|
+
attrs,
|
|
1877
|
+
this.appGitContext.forOperation(
|
|
1878
|
+
args.eventId,
|
|
1879
|
+
appGitPropertiesFromAttributes(attrs),
|
|
1880
|
+
this.appGitOwner
|
|
1881
|
+
)
|
|
1882
|
+
),
|
|
1407
1883
|
status: args.status
|
|
1408
1884
|
});
|
|
1409
1885
|
rememberReplayTraceDestination(otlp);
|
|
1886
|
+
this.appGitCaptured.add(otlp);
|
|
1887
|
+
if (tracksAppGit) {
|
|
1888
|
+
if (this.appGitContext.releaseOperation) this.appGitContext.releaseOperation(args.eventId, this.appGitOwner);
|
|
1889
|
+
else if (this.ownsAppGitContext) this.appGitContext.finishOperation(args.eventId);
|
|
1890
|
+
}
|
|
1410
1891
|
this.enqueue(otlp);
|
|
1411
1892
|
this.mirrorToLocalDebugger(otlp, true);
|
|
1412
1893
|
}
|
|
1413
1894
|
enqueue(span) {
|
|
1895
|
+
var _a;
|
|
1414
1896
|
if (!this.enabled) return;
|
|
1897
|
+
const attributes = (_a = span.attributes) != null ? _a : [];
|
|
1898
|
+
const enriched = this.appGitCaptured.has(span) ? attributes : withAppGitAttributes(attributes, this.appGitContext.snapshot(appGitPropertiesFromAttributes(attributes)));
|
|
1899
|
+
if (enriched !== attributes) {
|
|
1900
|
+
const original = span;
|
|
1901
|
+
span = { ...span, attributes: enriched.filter((attr) => attr !== void 0) };
|
|
1902
|
+
copyReplayTraceDestination(original, span);
|
|
1903
|
+
}
|
|
1415
1904
|
if (this.debugSpans) {
|
|
1416
1905
|
const short = (s) => s ? s.slice(-8) : "none";
|
|
1417
1906
|
console.log(
|
|
@@ -1557,12 +2046,158 @@ var TraceShipper = class {
|
|
|
1557
2046
|
}
|
|
1558
2047
|
} finally {
|
|
1559
2048
|
this.shutdownDeadlineAt = void 0;
|
|
2049
|
+
if (this.ownsAppGitContext) this.appGitContext.dispose();
|
|
1560
2050
|
}
|
|
1561
2051
|
}
|
|
1562
2052
|
};
|
|
1563
2053
|
|
|
1564
2054
|
// ../core/dist/index.node.js
|
|
1565
2055
|
import { AsyncLocalStorage } from "async_hooks";
|
|
2056
|
+
import { execFile } from "child_process";
|
|
2057
|
+
import { resolve } from "path";
|
|
2058
|
+
var resolveLocal = (sourceDirectory, detectBranch, completed) => {
|
|
2059
|
+
const cwd = sourceDirectory ? resolve(sourceDirectory) : process.cwd();
|
|
2060
|
+
let cancelled = false;
|
|
2061
|
+
let active;
|
|
2062
|
+
let deadlineTimer;
|
|
2063
|
+
const deadline = Date.now() + 1e3;
|
|
2064
|
+
const run = (args, done) => {
|
|
2065
|
+
if (cancelled) return;
|
|
2066
|
+
const remaining = deadline - Date.now();
|
|
2067
|
+
if (remaining <= 0) {
|
|
2068
|
+
done(void 0);
|
|
2069
|
+
return;
|
|
2070
|
+
}
|
|
2071
|
+
try {
|
|
2072
|
+
active = execFile(
|
|
2073
|
+
"git",
|
|
2074
|
+
args,
|
|
2075
|
+
{
|
|
2076
|
+
cwd,
|
|
2077
|
+
encoding: "utf8",
|
|
2078
|
+
maxBuffer: 4096,
|
|
2079
|
+
windowsHide: true,
|
|
2080
|
+
env: {
|
|
2081
|
+
...process.env,
|
|
2082
|
+
// The selected application cwd, not the invoking shell's Git plumbing, owns identity.
|
|
2083
|
+
GIT_DIR: void 0,
|
|
2084
|
+
GIT_WORK_TREE: void 0,
|
|
2085
|
+
GIT_COMMON_DIR: void 0,
|
|
2086
|
+
GIT_NAMESPACE: void 0,
|
|
2087
|
+
GIT_INDEX_FILE: void 0,
|
|
2088
|
+
GIT_OBJECT_DIRECTORY: void 0,
|
|
2089
|
+
GIT_ALTERNATE_OBJECT_DIRECTORIES: void 0,
|
|
2090
|
+
GIT_CONFIG_PARAMETERS: void 0,
|
|
2091
|
+
GIT_CONFIG_COUNT: "0",
|
|
2092
|
+
GIT_TERMINAL_PROMPT: "0",
|
|
2093
|
+
GIT_OPTIONAL_LOCKS: "0"
|
|
2094
|
+
}
|
|
2095
|
+
},
|
|
2096
|
+
(error, stdout) => {
|
|
2097
|
+
clearTimeout(deadlineTimer);
|
|
2098
|
+
deadlineTimer = void 0;
|
|
2099
|
+
active = void 0;
|
|
2100
|
+
if (!cancelled) {
|
|
2101
|
+
try {
|
|
2102
|
+
done(error ? void 0 : stdout.trim());
|
|
2103
|
+
} catch (e) {
|
|
2104
|
+
}
|
|
2105
|
+
}
|
|
2106
|
+
}
|
|
2107
|
+
);
|
|
2108
|
+
active.unref();
|
|
2109
|
+
if (active.stdout && "unref" in active.stdout && typeof active.stdout.unref === "function")
|
|
2110
|
+
active.stdout.unref();
|
|
2111
|
+
if (active.stderr && "unref" in active.stderr && typeof active.stderr.unref === "function")
|
|
2112
|
+
active.stderr.unref();
|
|
2113
|
+
deadlineTimer = setTimeout(() => {
|
|
2114
|
+
try {
|
|
2115
|
+
active == null ? void 0 : active.kill("SIGKILL");
|
|
2116
|
+
} catch (e) {
|
|
2117
|
+
}
|
|
2118
|
+
}, remaining);
|
|
2119
|
+
deadlineTimer.unref();
|
|
2120
|
+
} catch (e) {
|
|
2121
|
+
try {
|
|
2122
|
+
done(void 0);
|
|
2123
|
+
} catch (e2) {
|
|
2124
|
+
}
|
|
2125
|
+
}
|
|
2126
|
+
};
|
|
2127
|
+
const scheduled = setTimeout(() => {
|
|
2128
|
+
try {
|
|
2129
|
+
run(["rev-parse", "HEAD"], (rawSha) => {
|
|
2130
|
+
const commitSha = validAppCommitSha(rawSha);
|
|
2131
|
+
if (!commitSha) {
|
|
2132
|
+
completed({});
|
|
2133
|
+
return;
|
|
2134
|
+
}
|
|
2135
|
+
run(["-c", "core.fsmonitor=false", "status", "--porcelain"], (status) => {
|
|
2136
|
+
const finish = (branch) => {
|
|
2137
|
+
run(["rev-parse", "HEAD"], (finalSha) => {
|
|
2138
|
+
const coherent = validAppCommitSha(finalSha) === commitSha;
|
|
2139
|
+
completed({
|
|
2140
|
+
commitSha,
|
|
2141
|
+
...coherent && status !== void 0 ? { commitDirty: status !== "" } : {},
|
|
2142
|
+
...coherent && branch && branch !== "HEAD" ? { branch } : {}
|
|
2143
|
+
});
|
|
2144
|
+
});
|
|
2145
|
+
};
|
|
2146
|
+
if (detectBranch) run(["symbolic-ref", "--quiet", "--short", "HEAD"], finish);
|
|
2147
|
+
else finish();
|
|
2148
|
+
});
|
|
2149
|
+
});
|
|
2150
|
+
} catch (e) {
|
|
2151
|
+
completed({});
|
|
2152
|
+
}
|
|
2153
|
+
}, 0);
|
|
2154
|
+
scheduled.unref();
|
|
2155
|
+
return () => {
|
|
2156
|
+
cancelled = true;
|
|
2157
|
+
clearTimeout(scheduled);
|
|
2158
|
+
clearTimeout(deadlineTimer);
|
|
2159
|
+
try {
|
|
2160
|
+
active == null ? void 0 : active.kill("SIGKILL");
|
|
2161
|
+
} catch (e) {
|
|
2162
|
+
}
|
|
2163
|
+
};
|
|
2164
|
+
};
|
|
2165
|
+
function createAppGitContext2(options, runtime = {}) {
|
|
2166
|
+
return new AppGitContext(options, { ...runtime, resolveLocal });
|
|
2167
|
+
}
|
|
2168
|
+
function hasDestination(options) {
|
|
2169
|
+
var _a;
|
|
2170
|
+
if (options.enabled === false) return false;
|
|
2171
|
+
return Boolean(((_a = options.writeKey) == null ? void 0 : _a.trim()) || resolveLocalDebuggerBaseUrl(options.localDebuggerUrl));
|
|
2172
|
+
}
|
|
2173
|
+
var EventShipper2 = class extends EventShipper {
|
|
2174
|
+
constructor(options) {
|
|
2175
|
+
var _a;
|
|
2176
|
+
const ownsAppGitContext = options.appGitContext === void 0;
|
|
2177
|
+
const appGitContext = (_a = options.appGitContext) != null ? _a : createAppGitContext2(options.appGit, { allowDiscovery: hasDestination(options) });
|
|
2178
|
+
try {
|
|
2179
|
+
super({ ...options, appGitContext });
|
|
2180
|
+
} catch (error) {
|
|
2181
|
+
if (ownsAppGitContext) appGitContext.dispose();
|
|
2182
|
+
throw error;
|
|
2183
|
+
}
|
|
2184
|
+
if (ownsAppGitContext) this.ownAppGitContextForShutdown();
|
|
2185
|
+
}
|
|
2186
|
+
};
|
|
2187
|
+
var TraceShipper2 = class extends TraceShipper {
|
|
2188
|
+
constructor(options) {
|
|
2189
|
+
var _a;
|
|
2190
|
+
const ownsAppGitContext = options.appGitContext === void 0;
|
|
2191
|
+
const appGitContext = (_a = options.appGitContext) != null ? _a : createAppGitContext2(options.appGit, { allowDiscovery: hasDestination(options) });
|
|
2192
|
+
try {
|
|
2193
|
+
super({ ...options, appGitContext });
|
|
2194
|
+
} catch (error) {
|
|
2195
|
+
if (ownsAppGitContext) appGitContext.dispose();
|
|
2196
|
+
throw error;
|
|
2197
|
+
}
|
|
2198
|
+
this.ownsAppGitContext = ownsAppGitContext;
|
|
2199
|
+
}
|
|
2200
|
+
};
|
|
1566
2201
|
globalThis.RAINDROP_ASYNC_LOCAL_STORAGE = AsyncLocalStorage;
|
|
1567
2202
|
var SUPPRESS_TRACING_KEY = /* @__PURE__ */ Symbol.for(
|
|
1568
2203
|
"OpenTelemetry SDK Context Key SUPPRESS_TRACING"
|
|
@@ -1590,6 +2225,468 @@ function installTracingSuppressionHook() {
|
|
|
1590
2225
|
}
|
|
1591
2226
|
installTracingSuppressionHook();
|
|
1592
2227
|
|
|
2228
|
+
// src/conversation.ts
|
|
2229
|
+
import {
|
|
2230
|
+
isAIMessage,
|
|
2231
|
+
isBaseMessage,
|
|
2232
|
+
isChatMessage,
|
|
2233
|
+
isToolMessage
|
|
2234
|
+
} from "@langchain/core/messages";
|
|
2235
|
+
|
|
2236
|
+
// src/truncation.ts
|
|
2237
|
+
var TRUNCATION_MARKER2 = "...[truncated by raindrop]";
|
|
2238
|
+
var DEFAULT_MAX_TEXT_FIELD_CHARS2 = 1e6;
|
|
2239
|
+
var MAX_DEPTH = 12;
|
|
2240
|
+
var configuredMaxTextFieldChars;
|
|
2241
|
+
function setMaxTextFieldChars(limit) {
|
|
2242
|
+
if (limit === void 0) return;
|
|
2243
|
+
if (typeof limit === "number" && Number.isFinite(limit) && limit > 0) {
|
|
2244
|
+
configuredMaxTextFieldChars = Math.floor(limit);
|
|
2245
|
+
} else {
|
|
2246
|
+
console.warn(`[raindrop-ai] maxTextFieldChars=${String(limit)} ignored; must be > 0`);
|
|
2247
|
+
}
|
|
2248
|
+
}
|
|
2249
|
+
function otelEnvLimit() {
|
|
2250
|
+
if (typeof process === "undefined") return void 0;
|
|
2251
|
+
const raw = process.env?.OTEL_SPAN_ATTRIBUTE_VALUE_LENGTH_LIMIT;
|
|
2252
|
+
if (!raw) return void 0;
|
|
2253
|
+
const parsed = Number.parseInt(raw, 10);
|
|
2254
|
+
return Number.isFinite(parsed) && parsed > 0 ? parsed : void 0;
|
|
2255
|
+
}
|
|
2256
|
+
function eventMaxTextFieldChars() {
|
|
2257
|
+
return configuredMaxTextFieldChars ?? DEFAULT_MAX_TEXT_FIELD_CHARS2;
|
|
2258
|
+
}
|
|
2259
|
+
function spanAttributeLimit(limit) {
|
|
2260
|
+
const env = otelEnvLimit();
|
|
2261
|
+
return env !== void 0 && env < limit ? env : limit;
|
|
2262
|
+
}
|
|
2263
|
+
function effectiveMaxTextFieldChars() {
|
|
2264
|
+
return spanAttributeLimit(eventMaxTextFieldChars());
|
|
2265
|
+
}
|
|
2266
|
+
function truncateToLimit2(text, limit) {
|
|
2267
|
+
if (limit > TRUNCATION_MARKER2.length) {
|
|
2268
|
+
return text.slice(0, limit - TRUNCATION_MARKER2.length) + TRUNCATION_MARKER2;
|
|
2269
|
+
}
|
|
2270
|
+
return text.slice(0, limit);
|
|
2271
|
+
}
|
|
2272
|
+
function capText2(value, limit) {
|
|
2273
|
+
if (typeof value !== "string") return value;
|
|
2274
|
+
const max = limit ?? effectiveMaxTextFieldChars();
|
|
2275
|
+
if (value.length <= max) return value;
|
|
2276
|
+
return truncateToLimit2(value, max);
|
|
2277
|
+
}
|
|
2278
|
+
function boundedClone2(value, budget, depth) {
|
|
2279
|
+
if (budget.remaining <= 0) return TRUNCATION_MARKER2;
|
|
2280
|
+
if (typeof value === "string") {
|
|
2281
|
+
if (value.length > budget.remaining) {
|
|
2282
|
+
const taken = value.slice(0, Math.max(0, budget.remaining)) + TRUNCATION_MARKER2;
|
|
2283
|
+
budget.remaining = 0;
|
|
2284
|
+
return taken;
|
|
2285
|
+
}
|
|
2286
|
+
budget.remaining -= Math.max(value.length, 1);
|
|
2287
|
+
return value;
|
|
2288
|
+
}
|
|
2289
|
+
if (value === null || typeof value === "number" || typeof value === "boolean") {
|
|
2290
|
+
budget.remaining -= 8;
|
|
2291
|
+
return value;
|
|
2292
|
+
}
|
|
2293
|
+
if (typeof value === "bigint") return boundedClone2(value.toString(), budget, depth);
|
|
2294
|
+
if (typeof value !== "object") {
|
|
2295
|
+
budget.remaining -= 1;
|
|
2296
|
+
return value;
|
|
2297
|
+
}
|
|
2298
|
+
if (value instanceof Uint8Array) {
|
|
2299
|
+
const maxBytes = Math.max(0, Math.ceil(budget.remaining * 3 / 4));
|
|
2300
|
+
if (value.byteLength > maxBytes) {
|
|
2301
|
+
const taken = base64Encode(value.subarray(0, maxBytes)) + TRUNCATION_MARKER2;
|
|
2302
|
+
budget.remaining = 0;
|
|
2303
|
+
return taken;
|
|
2304
|
+
}
|
|
2305
|
+
const encoded = base64Encode(value);
|
|
2306
|
+
budget.remaining -= Math.max(encoded.length, 1);
|
|
2307
|
+
return encoded;
|
|
2308
|
+
}
|
|
2309
|
+
if (depth >= MAX_DEPTH) {
|
|
2310
|
+
budget.remaining -= 16;
|
|
2311
|
+
const name = value.constructor?.name ?? "object";
|
|
2312
|
+
return `<max depth: ${name}>`;
|
|
2313
|
+
}
|
|
2314
|
+
const toJSON = value.toJSON;
|
|
2315
|
+
if (typeof toJSON === "function") {
|
|
2316
|
+
budget.remaining -= 2;
|
|
2317
|
+
return boundedClone2(toJSON.call(value), budget, depth + 1);
|
|
2318
|
+
}
|
|
2319
|
+
if (Array.isArray(value)) {
|
|
2320
|
+
budget.remaining -= 2;
|
|
2321
|
+
const out2 = [];
|
|
2322
|
+
for (const item of value) {
|
|
2323
|
+
if (budget.remaining <= 0) {
|
|
2324
|
+
out2.push(TRUNCATION_MARKER2);
|
|
2325
|
+
break;
|
|
2326
|
+
}
|
|
2327
|
+
out2.push(boundedClone2(item, budget, depth + 1));
|
|
2328
|
+
}
|
|
2329
|
+
return out2;
|
|
2330
|
+
}
|
|
2331
|
+
budget.remaining -= 2;
|
|
2332
|
+
const out = {};
|
|
2333
|
+
for (const key in value) {
|
|
2334
|
+
if (!Object.prototype.hasOwnProperty.call(value, key)) continue;
|
|
2335
|
+
if (budget.remaining <= 0) {
|
|
2336
|
+
out["..."] = TRUNCATION_MARKER2;
|
|
2337
|
+
break;
|
|
2338
|
+
}
|
|
2339
|
+
let cappedKey = key;
|
|
2340
|
+
if (key.length > budget.remaining) {
|
|
2341
|
+
cappedKey = key.slice(0, Math.max(0, budget.remaining)) + TRUNCATION_MARKER2;
|
|
2342
|
+
budget.remaining = 0;
|
|
2343
|
+
out[cappedKey] = TRUNCATION_MARKER2;
|
|
2344
|
+
break;
|
|
2345
|
+
}
|
|
2346
|
+
budget.remaining -= Math.max(key.length, 1);
|
|
2347
|
+
out[cappedKey] = boundedClone2(value[key], budget, depth + 1);
|
|
2348
|
+
}
|
|
2349
|
+
return out;
|
|
2350
|
+
}
|
|
2351
|
+
function boundedStringify(value, limit) {
|
|
2352
|
+
const max = limit ?? effectiveMaxTextFieldChars();
|
|
2353
|
+
try {
|
|
2354
|
+
if (typeof value === "string") {
|
|
2355
|
+
const text2 = JSON.stringify(capText2(value, max));
|
|
2356
|
+
return text2.length <= max ? text2 : truncateToLimit2(text2, max);
|
|
2357
|
+
}
|
|
2358
|
+
const pruned = boundedClone2(value, { remaining: max + TRUNCATION_MARKER2.length + 256 }, 0);
|
|
2359
|
+
const text = JSON.stringify(pruned);
|
|
2360
|
+
if (text === void 0) return void 0;
|
|
2361
|
+
return text.length <= max ? text : truncateToLimit2(text, max);
|
|
2362
|
+
} catch {
|
|
2363
|
+
return void 0;
|
|
2364
|
+
}
|
|
2365
|
+
}
|
|
2366
|
+
|
|
2367
|
+
// src/conversation.ts
|
|
2368
|
+
var CAPTURE_TRUNCATED_ROLE = "raindrop";
|
|
2369
|
+
var MESSAGE_OVERHEAD = 32;
|
|
2370
|
+
var PART_OVERHEAD = 24;
|
|
2371
|
+
var MAX_DEPTH2 = 12;
|
|
2372
|
+
function isRecord(value) {
|
|
2373
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
2374
|
+
}
|
|
2375
|
+
function stringField(record, key) {
|
|
2376
|
+
const value = record[key];
|
|
2377
|
+
return typeof value === "string" ? value : void 0;
|
|
2378
|
+
}
|
|
2379
|
+
function takeText(text, budget) {
|
|
2380
|
+
if (text.length > budget.remaining) {
|
|
2381
|
+
const kept = text.slice(0, Math.max(0, budget.remaining)) + TRUNCATION_MARKER2;
|
|
2382
|
+
budget.remaining = 0;
|
|
2383
|
+
budget.truncated = true;
|
|
2384
|
+
return kept;
|
|
2385
|
+
}
|
|
2386
|
+
budget.remaining -= Math.max(text.length, 1);
|
|
2387
|
+
return text;
|
|
2388
|
+
}
|
|
2389
|
+
function reserve(text, budget) {
|
|
2390
|
+
if (text !== void 0) budget.remaining -= Math.max(text.length, 1);
|
|
2391
|
+
return text;
|
|
2392
|
+
}
|
|
2393
|
+
function takeValue(value, budget, depth) {
|
|
2394
|
+
if (typeof value === "string") return takeText(value, budget);
|
|
2395
|
+
if (value === null || typeof value === "number" || typeof value === "boolean") {
|
|
2396
|
+
budget.remaining -= 8;
|
|
2397
|
+
return value;
|
|
2398
|
+
}
|
|
2399
|
+
if (typeof value !== "object") {
|
|
2400
|
+
budget.remaining -= 1;
|
|
2401
|
+
return value;
|
|
2402
|
+
}
|
|
2403
|
+
if (depth >= MAX_DEPTH2) {
|
|
2404
|
+
budget.remaining -= TRUNCATION_MARKER2.length;
|
|
2405
|
+
budget.truncated = true;
|
|
2406
|
+
return TRUNCATION_MARKER2;
|
|
2407
|
+
}
|
|
2408
|
+
if ("toJSON" in value && typeof value.toJSON === "function") {
|
|
2409
|
+
return takeValue(value.toJSON(), budget, depth + 1);
|
|
2410
|
+
}
|
|
2411
|
+
if (Array.isArray(value)) {
|
|
2412
|
+
budget.remaining -= 2;
|
|
2413
|
+
const out2 = [];
|
|
2414
|
+
for (const item of value) {
|
|
2415
|
+
if (budget.remaining <= 0) {
|
|
2416
|
+
budget.truncated = true;
|
|
2417
|
+
out2.push(TRUNCATION_MARKER2);
|
|
2418
|
+
break;
|
|
2419
|
+
}
|
|
2420
|
+
out2.push(takeValue(item, budget, depth + 1));
|
|
2421
|
+
}
|
|
2422
|
+
return out2;
|
|
2423
|
+
}
|
|
2424
|
+
budget.remaining -= 2;
|
|
2425
|
+
const out = {};
|
|
2426
|
+
if (!isRecord(value)) return out;
|
|
2427
|
+
for (const key in value) {
|
|
2428
|
+
if (!Object.prototype.hasOwnProperty.call(value, key)) continue;
|
|
2429
|
+
if (budget.remaining <= 0) {
|
|
2430
|
+
budget.truncated = true;
|
|
2431
|
+
out["..."] = TRUNCATION_MARKER2;
|
|
2432
|
+
break;
|
|
2433
|
+
}
|
|
2434
|
+
budget.remaining -= Math.max(key.length, 1);
|
|
2435
|
+
out[key] = takeValue(value[key], budget, depth + 1);
|
|
2436
|
+
}
|
|
2437
|
+
return out;
|
|
2438
|
+
}
|
|
2439
|
+
function messageType(message) {
|
|
2440
|
+
return typeof message._getType === "function" ? message._getType() : void 0;
|
|
2441
|
+
}
|
|
2442
|
+
function textPart(text, budget) {
|
|
2443
|
+
return { type: "text", text: takeText(text, budget) };
|
|
2444
|
+
}
|
|
2445
|
+
function joinedText(content, budget) {
|
|
2446
|
+
const texts = [];
|
|
2447
|
+
for (const block of content) {
|
|
2448
|
+
if (budget.remaining <= 0) {
|
|
2449
|
+
budget.truncated = true;
|
|
2450
|
+
texts.push(TRUNCATION_MARKER2);
|
|
2451
|
+
break;
|
|
2452
|
+
}
|
|
2453
|
+
budget.remaining -= 1;
|
|
2454
|
+
if (!isRecord(block)) continue;
|
|
2455
|
+
const text = stringField(block, "text");
|
|
2456
|
+
if (text !== void 0) texts.push(takeText(text, budget));
|
|
2457
|
+
}
|
|
2458
|
+
return texts.join("\n");
|
|
2459
|
+
}
|
|
2460
|
+
function contentPart(block, budget) {
|
|
2461
|
+
budget.remaining -= PART_OVERHEAD;
|
|
2462
|
+
if (!isRecord(block)) return takeValue(block, budget, 0);
|
|
2463
|
+
const type = stringField(block, "type");
|
|
2464
|
+
const text = stringField(block, "text");
|
|
2465
|
+
if (type === "text" && text !== void 0) return textPart(text, budget);
|
|
2466
|
+
if (type === "image_url") {
|
|
2467
|
+
const imageUrl = block["image_url"];
|
|
2468
|
+
const url = typeof imageUrl === "string" ? imageUrl : isRecord(imageUrl) ? stringField(imageUrl, "url") : void 0;
|
|
2469
|
+
if (url !== void 0) return { type: "image", image: takeText(url, budget) };
|
|
2470
|
+
}
|
|
2471
|
+
if (type === "thinking") {
|
|
2472
|
+
const thinking = stringField(block, "thinking");
|
|
2473
|
+
if (thinking !== void 0) return { type: "reasoning", text: takeText(thinking, budget) };
|
|
2474
|
+
}
|
|
2475
|
+
if (type === "image" || type === "file" || type === "audio") {
|
|
2476
|
+
const mediaType = stringField(block, "mime_type");
|
|
2477
|
+
const sourceType = stringField(block, "source_type");
|
|
2478
|
+
const source = block["source"];
|
|
2479
|
+
if (sourceType === "text" && text !== void 0) return textPart(text, budget);
|
|
2480
|
+
const data = sourceType === "url" ? stringField(block, "url") : sourceType === "base64" ? stringField(block, "data") : isRecord(source) ? stringField(source, "url") ?? stringField(source, "data") : void 0;
|
|
2481
|
+
const sourceMediaType = mediaType ?? (isRecord(source) ? stringField(source, "media_type") : void 0);
|
|
2482
|
+
if (data !== void 0) {
|
|
2483
|
+
const filename = stringField(block, "filename");
|
|
2484
|
+
return type === "image" ? { type: "image", image: takeText(data, budget), mediaType: reserve(sourceMediaType, budget) } : {
|
|
2485
|
+
type: "file",
|
|
2486
|
+
data: takeText(data, budget),
|
|
2487
|
+
mediaType: reserve(sourceMediaType, budget),
|
|
2488
|
+
filename: reserve(filename, budget)
|
|
2489
|
+
};
|
|
2490
|
+
}
|
|
2491
|
+
}
|
|
2492
|
+
return takeValue(block, budget, 0);
|
|
2493
|
+
}
|
|
2494
|
+
function contentParts(content, budget, skipToolUseIds) {
|
|
2495
|
+
const parts = [];
|
|
2496
|
+
for (const block of content) {
|
|
2497
|
+
if (budget.remaining <= 0) {
|
|
2498
|
+
budget.truncated = true;
|
|
2499
|
+
parts.push({ type: "text", text: TRUNCATION_MARKER2 });
|
|
2500
|
+
break;
|
|
2501
|
+
}
|
|
2502
|
+
if (isRecord(block) && (block["type"] === "tool_use" || block["type"] === "tool_call")) {
|
|
2503
|
+
const id = stringField(block, "id");
|
|
2504
|
+
if (id !== void 0 && skipToolUseIds.has(id)) continue;
|
|
2505
|
+
}
|
|
2506
|
+
parts.push(contentPart(block, budget));
|
|
2507
|
+
}
|
|
2508
|
+
return parts;
|
|
2509
|
+
}
|
|
2510
|
+
function assistantMessage(message, budget, toolNames) {
|
|
2511
|
+
const toolCalls = isAIMessage(message) ? message.tool_calls ?? [] : [];
|
|
2512
|
+
if (toolCalls.length === 0 && typeof message.content === "string") {
|
|
2513
|
+
return { role: "assistant", content: takeText(message.content, budget) };
|
|
2514
|
+
}
|
|
2515
|
+
const ids = /* @__PURE__ */ new Set();
|
|
2516
|
+
const callParts = [];
|
|
2517
|
+
for (const call of toolCalls) {
|
|
2518
|
+
if (budget.remaining <= 0) {
|
|
2519
|
+
budget.truncated = true;
|
|
2520
|
+
callParts.push({ type: "text", text: TRUNCATION_MARKER2 });
|
|
2521
|
+
break;
|
|
2522
|
+
}
|
|
2523
|
+
budget.remaining -= PART_OVERHEAD;
|
|
2524
|
+
if (call.id !== void 0) {
|
|
2525
|
+
ids.add(call.id);
|
|
2526
|
+
toolNames.set(call.id, call.name);
|
|
2527
|
+
}
|
|
2528
|
+
callParts.push({
|
|
2529
|
+
type: "tool-call",
|
|
2530
|
+
toolCallId: reserve(call.id, budget),
|
|
2531
|
+
toolName: reserve(call.name, budget),
|
|
2532
|
+
input: takeValue(call.args, budget, 0)
|
|
2533
|
+
});
|
|
2534
|
+
}
|
|
2535
|
+
const content = typeof message.content === "string" ? message.content.length > 0 ? [textPart(message.content, budget)] : [] : contentParts(message.content, budget, ids);
|
|
2536
|
+
content.push(...callParts);
|
|
2537
|
+
return { role: "assistant", content };
|
|
2538
|
+
}
|
|
2539
|
+
function toolResultOutput(message, budget) {
|
|
2540
|
+
const failed = isToolMessage(message) && message.status === "error";
|
|
2541
|
+
if (typeof message.content === "string") {
|
|
2542
|
+
return { type: failed ? "error-text" : "text", value: takeText(message.content, budget) };
|
|
2543
|
+
}
|
|
2544
|
+
return { type: "content", value: contentParts(message.content, budget, /* @__PURE__ */ new Set()) };
|
|
2545
|
+
}
|
|
2546
|
+
function toolMessage(message, budget, toolNames) {
|
|
2547
|
+
const toolCallId = isToolMessage(message) ? message.tool_call_id : void 0;
|
|
2548
|
+
const toolName = message.name ?? (toolCallId !== void 0 ? toolNames.get(toolCallId) : void 0);
|
|
2549
|
+
budget.remaining -= PART_OVERHEAD;
|
|
2550
|
+
return {
|
|
2551
|
+
role: "tool",
|
|
2552
|
+
content: [{
|
|
2553
|
+
type: "tool-result",
|
|
2554
|
+
toolCallId: reserve(toolCallId, budget),
|
|
2555
|
+
toolName: reserve(toolName, budget),
|
|
2556
|
+
output: toolResultOutput(message, budget)
|
|
2557
|
+
}]
|
|
2558
|
+
};
|
|
2559
|
+
}
|
|
2560
|
+
function modelMessage(message, budget, toolNames) {
|
|
2561
|
+
budget.remaining -= MESSAGE_OVERHEAD;
|
|
2562
|
+
switch (messageType(message)) {
|
|
2563
|
+
case "system":
|
|
2564
|
+
return {
|
|
2565
|
+
role: "system",
|
|
2566
|
+
content: typeof message.content === "string" ? takeText(message.content, budget) : joinedText(message.content, budget)
|
|
2567
|
+
};
|
|
2568
|
+
case "ai":
|
|
2569
|
+
return assistantMessage(message, budget, toolNames);
|
|
2570
|
+
case "tool":
|
|
2571
|
+
case "function":
|
|
2572
|
+
return toolMessage(message, budget, toolNames);
|
|
2573
|
+
case "generic": {
|
|
2574
|
+
const role = isChatMessage(message) ? message.role : void 0;
|
|
2575
|
+
if (role === "assistant" || role === "system") {
|
|
2576
|
+
return {
|
|
2577
|
+
role,
|
|
2578
|
+
content: typeof message.content === "string" ? takeText(message.content, budget) : joinedText(message.content, budget)
|
|
2579
|
+
};
|
|
2580
|
+
}
|
|
2581
|
+
return userMessage(message, budget);
|
|
2582
|
+
}
|
|
2583
|
+
default:
|
|
2584
|
+
return userMessage(message, budget);
|
|
2585
|
+
}
|
|
2586
|
+
}
|
|
2587
|
+
function userMessage(message, budget) {
|
|
2588
|
+
return {
|
|
2589
|
+
role: "user",
|
|
2590
|
+
content: typeof message.content === "string" ? takeText(message.content, budget) : contentParts(message.content, budget, /* @__PURE__ */ new Set())
|
|
2591
|
+
};
|
|
2592
|
+
}
|
|
2593
|
+
function truncationRecord(omittedMessages) {
|
|
2594
|
+
return { role: CAPTURE_TRUNCATED_ROLE, truncated: true, marker: TRUNCATION_MARKER2, omittedMessages };
|
|
2595
|
+
}
|
|
2596
|
+
function encodeWithinLimit(items, limit, overflow, convert) {
|
|
2597
|
+
let textBudget = limit;
|
|
2598
|
+
for (let attempt = 0; attempt < 8 && textBudget >= 64; attempt++) {
|
|
2599
|
+
const budget = { remaining: textBudget, truncated: false };
|
|
2600
|
+
const out = [];
|
|
2601
|
+
let omitted = 0;
|
|
2602
|
+
for (let i = 0; i < items.length; i++) {
|
|
2603
|
+
if (overflow === "omit" && budget.remaining <= 0) {
|
|
2604
|
+
omitted = items.length - i;
|
|
2605
|
+
break;
|
|
2606
|
+
}
|
|
2607
|
+
out.push(convert(items[i], budget));
|
|
2608
|
+
}
|
|
2609
|
+
const truncated = budget.truncated || omitted > 0;
|
|
2610
|
+
if (truncated && overflow === "omit") out.push(truncationRecord(omitted));
|
|
2611
|
+
const json2 = JSON.stringify(out);
|
|
2612
|
+
if (json2.length <= limit) return { json: json2, truncated };
|
|
2613
|
+
const excess = json2.length - limit + 128;
|
|
2614
|
+
textBudget = Math.max(textBudget - excess, Math.floor(textBudget / 2));
|
|
2615
|
+
}
|
|
2616
|
+
if (overflow === "keep") return void 0;
|
|
2617
|
+
const json = JSON.stringify([truncationRecord(items.length)]);
|
|
2618
|
+
return json.length <= limit ? { json, truncated: true } : void 0;
|
|
2619
|
+
}
|
|
2620
|
+
function captureConversation(messages, limit) {
|
|
2621
|
+
if (messages.length === 0) return void 0;
|
|
2622
|
+
try {
|
|
2623
|
+
const toolNames = /* @__PURE__ */ new Map();
|
|
2624
|
+
return encodeWithinLimit(
|
|
2625
|
+
messages,
|
|
2626
|
+
limit,
|
|
2627
|
+
"omit",
|
|
2628
|
+
(message, budget) => modelMessage(message, budget, toolNames)
|
|
2629
|
+
);
|
|
2630
|
+
} catch {
|
|
2631
|
+
return void 0;
|
|
2632
|
+
}
|
|
2633
|
+
}
|
|
2634
|
+
function capturePrompt(prompt, limit) {
|
|
2635
|
+
try {
|
|
2636
|
+
return encodeWithinLimit([prompt], limit, "omit", (text, budget) => {
|
|
2637
|
+
budget.remaining -= MESSAGE_OVERHEAD;
|
|
2638
|
+
return { role: "user", content: takeText(text, budget) };
|
|
2639
|
+
});
|
|
2640
|
+
} catch {
|
|
2641
|
+
return void 0;
|
|
2642
|
+
}
|
|
2643
|
+
}
|
|
2644
|
+
function captureToolCalls(message, limit) {
|
|
2645
|
+
if (!isRecord(message) || !Array.isArray(message["tool_calls"])) return void 0;
|
|
2646
|
+
const calls = [];
|
|
2647
|
+
let structural = 0;
|
|
2648
|
+
for (const call of message["tool_calls"]) {
|
|
2649
|
+
structural += PART_OVERHEAD;
|
|
2650
|
+
if (isRecord(call)) {
|
|
2651
|
+
structural += (stringField(call, "id")?.length ?? 0) + (stringField(call, "name")?.length ?? 0);
|
|
2652
|
+
calls.push(call);
|
|
2653
|
+
}
|
|
2654
|
+
if (structural > limit) return void 0;
|
|
2655
|
+
}
|
|
2656
|
+
if (calls.length === 0) return void 0;
|
|
2657
|
+
try {
|
|
2658
|
+
return encodeWithinLimit(calls, limit, "keep", (call, budget) => {
|
|
2659
|
+
budget.remaining -= PART_OVERHEAD;
|
|
2660
|
+
return {
|
|
2661
|
+
toolCallId: reserve(stringField(call, "id"), budget),
|
|
2662
|
+
toolName: reserve(stringField(call, "name"), budget),
|
|
2663
|
+
input: takeValue(call["args"], budget, 0)
|
|
2664
|
+
};
|
|
2665
|
+
});
|
|
2666
|
+
} catch {
|
|
2667
|
+
return void 0;
|
|
2668
|
+
}
|
|
2669
|
+
}
|
|
2670
|
+
function parseToolCallInput(input) {
|
|
2671
|
+
try {
|
|
2672
|
+
const parsed = JSON.parse(input);
|
|
2673
|
+
if (isRecord(parsed) && parsed["type"] === "tool_call" && "args" in parsed) {
|
|
2674
|
+
return { id: stringField(parsed, "id"), args: JSON.stringify(parsed["args"]) };
|
|
2675
|
+
}
|
|
2676
|
+
} catch {
|
|
2677
|
+
}
|
|
2678
|
+
return { args: input };
|
|
2679
|
+
}
|
|
2680
|
+
function unwrapToolOutput(output) {
|
|
2681
|
+
if (isBaseMessage(output)) {
|
|
2682
|
+
return {
|
|
2683
|
+
content: output.content,
|
|
2684
|
+
toolCallId: isToolMessage(output) ? output.tool_call_id : void 0
|
|
2685
|
+
};
|
|
2686
|
+
}
|
|
2687
|
+
return { content: output };
|
|
2688
|
+
}
|
|
2689
|
+
|
|
1593
2690
|
// src/callback-handler.ts
|
|
1594
2691
|
function resolveEventId(source) {
|
|
1595
2692
|
if (typeof source !== "function") return randomUUID();
|
|
@@ -1607,32 +2704,38 @@ function isInternalName(name) {
|
|
|
1607
2704
|
if (name.startsWith("__") && name.endsWith("__")) return true;
|
|
1608
2705
|
return false;
|
|
1609
2706
|
}
|
|
1610
|
-
|
|
1611
|
-
function extractTextFromContent(content) {
|
|
2707
|
+
function extractTextFromContent(content, limit) {
|
|
1612
2708
|
if (content == null) return void 0;
|
|
1613
2709
|
if (typeof content === "string") return content;
|
|
1614
2710
|
if (Array.isArray(content)) {
|
|
1615
2711
|
const parts = [];
|
|
2712
|
+
let length = 0;
|
|
1616
2713
|
for (const part of content) {
|
|
2714
|
+
if (length > limit) break;
|
|
2715
|
+
length += 1;
|
|
2716
|
+
let text;
|
|
1617
2717
|
if (typeof part === "string") {
|
|
1618
|
-
|
|
2718
|
+
text = part;
|
|
1619
2719
|
} else if (part && typeof part === "object") {
|
|
1620
2720
|
const p = part;
|
|
1621
2721
|
if (typeof p.text === "string") {
|
|
1622
|
-
|
|
2722
|
+
text = p.text;
|
|
1623
2723
|
} else if (p.type === "text" && typeof p.content === "string") {
|
|
1624
|
-
|
|
2724
|
+
text = p.content;
|
|
1625
2725
|
}
|
|
1626
2726
|
}
|
|
2727
|
+
if (text === void 0) continue;
|
|
2728
|
+
parts.push(text.length > limit ? text.slice(0, limit + 1) : text);
|
|
2729
|
+
length += Math.max(text.length, 1);
|
|
1627
2730
|
}
|
|
1628
2731
|
if (parts.length > 0) return parts.join("\n");
|
|
1629
|
-
return
|
|
2732
|
+
return boundedStringify(content, limit);
|
|
1630
2733
|
}
|
|
1631
2734
|
if (typeof content === "object") {
|
|
1632
2735
|
const c = content;
|
|
1633
2736
|
if (typeof c.text === "string") return c.text;
|
|
1634
2737
|
if (typeof c.content === "string") return c.content;
|
|
1635
|
-
return
|
|
2738
|
+
return boundedStringify(content, limit);
|
|
1636
2739
|
}
|
|
1637
2740
|
return String(content);
|
|
1638
2741
|
}
|
|
@@ -1651,6 +2754,11 @@ var RaindropDeepAgentsHandler = class extends BaseCallbackHandler {
|
|
|
1651
2754
|
this.eventName = opts.eventName;
|
|
1652
2755
|
this.eventIdSource = opts.eventId;
|
|
1653
2756
|
this.traceChains = opts.traceChains ?? true;
|
|
2757
|
+
this.configuredSpanMaxChars = opts.maxTextFieldChars ?? eventMaxTextFieldChars();
|
|
2758
|
+
this.eventMaxChars = opts.eventMaxTextFieldChars ?? eventMaxTextFieldChars();
|
|
2759
|
+
}
|
|
2760
|
+
get spanMaxChars() {
|
|
2761
|
+
return spanAttributeLimit(this.configuredSpanMaxChars);
|
|
1654
2762
|
}
|
|
1655
2763
|
getEventId(runId, parentRunId) {
|
|
1656
2764
|
const rootId = parentRunId ? this.rootRunIds.get(parentRunId) ?? parentRunId : runId;
|
|
@@ -1716,13 +2824,21 @@ var RaindropDeepAgentsHandler = class extends BaseCallbackHandler {
|
|
|
1716
2824
|
if (this.spans.has(runId)) return;
|
|
1717
2825
|
const eventId = this.getEventId(runId, parentRunId);
|
|
1718
2826
|
const modelId = getName(llm, runName);
|
|
2827
|
+
const prompt = prompts[0] ?? "";
|
|
1719
2828
|
const span = this.traceShipper.startSpan({
|
|
1720
2829
|
name: "llm",
|
|
1721
2830
|
parent: this.getParent(parentRunId),
|
|
1722
2831
|
eventId,
|
|
2832
|
+
// `ai.generateText` classifies the span as an LLM generation at ingest
|
|
2833
|
+
// (a bare `llm`/`chat` operationId maps to INTERNAL and is skipped by
|
|
2834
|
+
// the rich-interaction extractor). `ai.prompt.messages` carries the
|
|
2835
|
+
// per-step trajectory so replay can see the history each step ran on.
|
|
2836
|
+
// A batch is a list of independent prompts; the span describes the
|
|
2837
|
+
// first one, whose response `handleLLMEnd` reports (`generations[0][0]`).
|
|
1723
2838
|
attributes: [
|
|
1724
2839
|
attrString("ai.model.provider", modelId),
|
|
1725
|
-
attrString("ai.operationId", "
|
|
2840
|
+
attrString("ai.operationId", "ai.generateText"),
|
|
2841
|
+
...promptAttributes(capturePrompt(prompt, this.spanMaxChars))
|
|
1726
2842
|
]
|
|
1727
2843
|
});
|
|
1728
2844
|
this.spans.set(runId, span);
|
|
@@ -1730,7 +2846,7 @@ var RaindropDeepAgentsHandler = class extends BaseCallbackHandler {
|
|
|
1730
2846
|
userId: this.userId,
|
|
1731
2847
|
convoId: this.convoId,
|
|
1732
2848
|
eventName: this.eventName,
|
|
1733
|
-
input:
|
|
2849
|
+
input: capText2(prompt, this.eventMaxChars),
|
|
1734
2850
|
properties: buildProperties(tags, metadata),
|
|
1735
2851
|
isPending: true
|
|
1736
2852
|
});
|
|
@@ -1742,24 +2858,31 @@ var RaindropDeepAgentsHandler = class extends BaseCallbackHandler {
|
|
|
1742
2858
|
if (this.spans.has(runId)) return;
|
|
1743
2859
|
const eventId = this.getEventId(runId, parentRunId);
|
|
1744
2860
|
const modelId = getName(llm, runName);
|
|
2861
|
+
const conversation = messages[0] ?? [];
|
|
1745
2862
|
const span = this.traceShipper.startSpan({
|
|
1746
2863
|
name: "llm",
|
|
1747
2864
|
parent: this.getParent(parentRunId),
|
|
1748
2865
|
eventId,
|
|
2866
|
+
// See handleLLMStart: the full history (historical tool calls and
|
|
2867
|
+
// their results included) goes on the span; the event `input` below
|
|
2868
|
+
// stays the latest human message. LangChain batches are a list of
|
|
2869
|
+
// independent conversations; the span describes the first one, the
|
|
2870
|
+
// same member `handleLLMEnd` reports the response of
|
|
2871
|
+
// (`generations[0][0]`), so history and response stay paired.
|
|
1749
2872
|
attributes: [
|
|
1750
2873
|
attrString("ai.model.provider", modelId),
|
|
1751
|
-
attrString("ai.operationId", "
|
|
2874
|
+
attrString("ai.operationId", "ai.generateText"),
|
|
2875
|
+
...promptAttributes(captureConversation(conversation, this.spanMaxChars))
|
|
1752
2876
|
]
|
|
1753
2877
|
});
|
|
1754
2878
|
this.spans.set(runId, span);
|
|
1755
|
-
const
|
|
1756
|
-
const userMessages = allMessages.filter((m) => {
|
|
2879
|
+
const userMessages = conversation.filter((m) => {
|
|
1757
2880
|
const role = m._getType?.() ?? "unknown";
|
|
1758
2881
|
return role === "human";
|
|
1759
2882
|
});
|
|
1760
|
-
const lastMsg = userMessages.length > 0 ? userMessages[userMessages.length - 1] :
|
|
1761
|
-
const extracted = lastMsg ? extractTextFromContent(lastMsg.content) : void 0;
|
|
1762
|
-
const inputText =
|
|
2883
|
+
const lastMsg = userMessages.length > 0 ? userMessages[userMessages.length - 1] : conversation[conversation.length - 1];
|
|
2884
|
+
const extracted = lastMsg ? extractTextFromContent(lastMsg.content, this.eventMaxChars) : void 0;
|
|
2885
|
+
const inputText = capText2(extracted, this.eventMaxChars);
|
|
1763
2886
|
await this.eventShipper.patch(eventId, {
|
|
1764
2887
|
userId: this.userId,
|
|
1765
2888
|
convoId: this.convoId,
|
|
@@ -1782,7 +2905,7 @@ var RaindropDeepAgentsHandler = class extends BaseCallbackHandler {
|
|
|
1782
2905
|
await this.finalizeEventIfRoot(runId);
|
|
1783
2906
|
return;
|
|
1784
2907
|
}
|
|
1785
|
-
const meta = extractLLMMetadata(output);
|
|
2908
|
+
const meta = extractLLMMetadata(output, this.spanMaxChars);
|
|
1786
2909
|
const {
|
|
1787
2910
|
model,
|
|
1788
2911
|
promptTokens,
|
|
@@ -1790,11 +2913,17 @@ var RaindropDeepAgentsHandler = class extends BaseCallbackHandler {
|
|
|
1790
2913
|
cachedTokens,
|
|
1791
2914
|
reasoningTokens,
|
|
1792
2915
|
finishReason,
|
|
1793
|
-
outputText
|
|
2916
|
+
outputText,
|
|
2917
|
+
toolCalls
|
|
1794
2918
|
} = meta;
|
|
1795
2919
|
this.traceShipper.endSpan(span, {
|
|
1796
2920
|
attributes: [
|
|
1797
2921
|
attrString("ai.response.model", model),
|
|
2922
|
+
attrString("ai.response.text", capText2(outputText, this.spanMaxChars)),
|
|
2923
|
+
// Tool calls requested by this step, with the ids the matching
|
|
2924
|
+
// `ai.toolCall` spans and the next step's history carry.
|
|
2925
|
+
attrString("ai.response.toolCalls", toolCalls?.json),
|
|
2926
|
+
attrString("ai.response.toolCalls.truncated", toolCalls?.truncated ? "true" : void 0),
|
|
1798
2927
|
attrInt("ai.usage.prompt_tokens", promptTokens),
|
|
1799
2928
|
attrInt("ai.usage.completion_tokens", completionTokens),
|
|
1800
2929
|
attrInt("ai.usage.cached_tokens", cachedTokens),
|
|
@@ -1806,9 +2935,8 @@ var RaindropDeepAgentsHandler = class extends BaseCallbackHandler {
|
|
|
1806
2935
|
if (cachedTokens != null) properties["ai.usage.cached_tokens"] = cachedTokens;
|
|
1807
2936
|
if (reasoningTokens != null) properties["ai.usage.thoughts_tokens"] = reasoningTokens;
|
|
1808
2937
|
if (finishReason != null) properties["ai.finish_reason"] = finishReason;
|
|
1809
|
-
const cappedOutput = outputText !== void 0 ? truncate(outputText, CHAIN_TEXT_MAX_LEN) : void 0;
|
|
1810
2938
|
await this.finalizeEventIfRoot(runId, {
|
|
1811
|
-
output:
|
|
2939
|
+
output: capText2(outputText, this.eventMaxChars),
|
|
1812
2940
|
model,
|
|
1813
2941
|
usage: { promptTokens, completionTokens },
|
|
1814
2942
|
properties: Object.keys(properties).length > 0 ? properties : void 0
|
|
@@ -1904,14 +3032,16 @@ var RaindropDeepAgentsHandler = class extends BaseCallbackHandler {
|
|
|
1904
3032
|
try {
|
|
1905
3033
|
const eventId = this.getEventId(runId, parentRunId);
|
|
1906
3034
|
const toolName = getName(tool, runName);
|
|
3035
|
+
const toolCall = parseToolCallInput(input);
|
|
1907
3036
|
const span = this.traceShipper.startSpan({
|
|
1908
3037
|
name: "tool",
|
|
1909
3038
|
parent: this.getParent(parentRunId),
|
|
1910
3039
|
eventId,
|
|
1911
3040
|
operationId: "ai.toolCall",
|
|
1912
3041
|
attributes: [
|
|
3042
|
+
attrString("ai.toolCall.id", toolCall.id),
|
|
1913
3043
|
attrString("ai.toolCall.name", toolName),
|
|
1914
|
-
attrString("
|
|
3044
|
+
attrString("ai.toolCall.args", capText2(toolCall.args, this.spanMaxChars))
|
|
1915
3045
|
]
|
|
1916
3046
|
});
|
|
1917
3047
|
this.spans.set(runId, span);
|
|
@@ -1926,9 +3056,14 @@ var RaindropDeepAgentsHandler = class extends BaseCallbackHandler {
|
|
|
1926
3056
|
try {
|
|
1927
3057
|
const span = this.spans.get(runId);
|
|
1928
3058
|
if (span) {
|
|
1929
|
-
const
|
|
3059
|
+
const { content, toolCallId } = unwrapToolOutput(output);
|
|
3060
|
+
const result = typeof content === "string" ? capText2(content, this.spanMaxChars) : boundedStringify(content, this.spanMaxChars);
|
|
3061
|
+
const hasId = span.attributes.some((attr) => attr?.key === "ai.toolCall.id");
|
|
1930
3062
|
this.traceShipper.endSpan(span, {
|
|
1931
|
-
attributes: [
|
|
3063
|
+
attributes: [
|
|
3064
|
+
attrString("ai.toolCall.id", hasId ? void 0 : toolCallId),
|
|
3065
|
+
attrString("ai.toolCall.result", result)
|
|
3066
|
+
]
|
|
1932
3067
|
});
|
|
1933
3068
|
}
|
|
1934
3069
|
await this.finalizeEventIfRoot(runId);
|
|
@@ -1964,10 +3099,10 @@ var RaindropDeepAgentsHandler = class extends BaseCallbackHandler {
|
|
|
1964
3099
|
operationId: "ai.toolCall",
|
|
1965
3100
|
attributes: [
|
|
1966
3101
|
attrString("ai.toolCall.name", action.tool),
|
|
1967
|
-
attrString(
|
|
1968
|
-
|
|
1969
|
-
|
|
1970
|
-
)
|
|
3102
|
+
attrString(
|
|
3103
|
+
"agent.tool_input",
|
|
3104
|
+
typeof action.toolInput === "string" ? capText2(action.toolInput, this.spanMaxChars) : boundedStringify(action.toolInput, this.spanMaxChars)
|
|
3105
|
+
)
|
|
1971
3106
|
]
|
|
1972
3107
|
});
|
|
1973
3108
|
this.spans.set(`${runId}:agent_action`, span);
|
|
@@ -2000,75 +3135,13 @@ function buildProperties(tags, metadata) {
|
|
|
2000
3135
|
if (metadata) Object.assign(props, metadata);
|
|
2001
3136
|
return props;
|
|
2002
3137
|
}
|
|
2003
|
-
|
|
2004
|
-
|
|
2005
|
-
|
|
2006
|
-
|
|
2007
|
-
|
|
2008
|
-
if (typeof value === "string") {
|
|
2009
|
-
if (value.length > budget.remaining) {
|
|
2010
|
-
const taken = value.slice(0, Math.max(0, budget.remaining)) + TRUNCATION_MARKER2;
|
|
2011
|
-
budget.remaining = 0;
|
|
2012
|
-
return taken;
|
|
2013
|
-
}
|
|
2014
|
-
budget.remaining -= Math.max(value.length, 1);
|
|
2015
|
-
return value;
|
|
2016
|
-
}
|
|
2017
|
-
if (value === null || typeof value === "number" || typeof value === "boolean") {
|
|
2018
|
-
budget.remaining -= 8;
|
|
2019
|
-
return value;
|
|
2020
|
-
}
|
|
2021
|
-
if (typeof value !== "object") {
|
|
2022
|
-
budget.remaining -= 8;
|
|
2023
|
-
return value;
|
|
2024
|
-
}
|
|
2025
|
-
if (depth >= MAX_BOUNDED_DEPTH) {
|
|
2026
|
-
budget.remaining -= 16;
|
|
2027
|
-
return `<max depth: ${TRUNCATION_MARKER2}>`;
|
|
2028
|
-
}
|
|
2029
|
-
const withToJson = value;
|
|
2030
|
-
if (typeof withToJson.toJSON === "function") {
|
|
2031
|
-
try {
|
|
2032
|
-
return boundedClone2(withToJson.toJSON(), budget, depth + 1);
|
|
2033
|
-
} catch {
|
|
2034
|
-
}
|
|
2035
|
-
}
|
|
2036
|
-
if (Array.isArray(value)) {
|
|
2037
|
-
const out2 = [];
|
|
2038
|
-
for (const item of value) {
|
|
2039
|
-
if (budget.remaining <= 0) {
|
|
2040
|
-
out2.push(TRUNCATION_MARKER2);
|
|
2041
|
-
break;
|
|
2042
|
-
}
|
|
2043
|
-
out2.push(boundedClone2(item, budget, depth + 1));
|
|
2044
|
-
}
|
|
2045
|
-
return out2;
|
|
2046
|
-
}
|
|
2047
|
-
const out = {};
|
|
2048
|
-
for (const key of Object.keys(value)) {
|
|
2049
|
-
if (budget.remaining <= 0) {
|
|
2050
|
-
out["..."] = TRUNCATION_MARKER2;
|
|
2051
|
-
break;
|
|
2052
|
-
}
|
|
2053
|
-
budget.remaining -= Math.max(key.length, 1);
|
|
2054
|
-
out[key] = boundedClone2(value[key], budget, depth + 1);
|
|
2055
|
-
}
|
|
2056
|
-
return out;
|
|
2057
|
-
}
|
|
2058
|
-
function safeStringify(value, limit = MAX_TEXT_FIELD_CHARS) {
|
|
2059
|
-
try {
|
|
2060
|
-
const pruned = boundedClone2(value, { remaining: limit + TRUNCATION_MARKER2.length + 256 }, 0);
|
|
2061
|
-
return JSON.stringify(pruned) ?? "";
|
|
2062
|
-
} catch {
|
|
2063
|
-
const fallback = String(value);
|
|
2064
|
-
return fallback.length > limit ? fallback.slice(0, limit) : fallback;
|
|
2065
|
-
}
|
|
2066
|
-
}
|
|
2067
|
-
function truncate(str, maxLen) {
|
|
2068
|
-
if (str.length <= maxLen) return str;
|
|
2069
|
-
return str.slice(0, maxLen - 3) + "...";
|
|
3138
|
+
function promptAttributes(capture) {
|
|
3139
|
+
return [
|
|
3140
|
+
attrString("ai.prompt.messages", capture?.json),
|
|
3141
|
+
attrString("ai.prompt.messages.truncated", capture?.truncated ? "true" : void 0)
|
|
3142
|
+
];
|
|
2070
3143
|
}
|
|
2071
|
-
function extractLLMMetadata(output) {
|
|
3144
|
+
function extractLLMMetadata(output, limit) {
|
|
2072
3145
|
const gen = output.generations?.[0]?.[0];
|
|
2073
3146
|
const message = gen?.message;
|
|
2074
3147
|
const responseMeta = message?.response_metadata;
|
|
@@ -2094,7 +3167,7 @@ function extractLLMMetadata(output) {
|
|
|
2094
3167
|
outputDetails?.reasoning ?? usage?.reasoning_tokens ?? usage?.thoughts_tokens
|
|
2095
3168
|
);
|
|
2096
3169
|
const finishReason = generationInfo?.finish_reason ?? responseMeta?.finish_reason ?? responseMeta?.stop_reason;
|
|
2097
|
-
const outputText = gen?.text ?? (typeof message?.content === "string" ? message.content : void 0) ?? (message?.content ? extractTextFromContent(message.content) : void 0);
|
|
3170
|
+
const outputText = gen?.text ?? (typeof message?.content === "string" ? message.content : void 0) ?? (message?.content ? extractTextFromContent(message.content, limit) : void 0);
|
|
2098
3171
|
return {
|
|
2099
3172
|
model,
|
|
2100
3173
|
promptTokens,
|
|
@@ -2102,7 +3175,8 @@ function extractLLMMetadata(output) {
|
|
|
2102
3175
|
cachedTokens,
|
|
2103
3176
|
reasoningTokens,
|
|
2104
3177
|
finishReason,
|
|
2105
|
-
outputText
|
|
3178
|
+
outputText,
|
|
3179
|
+
toolCalls: captureToolCalls(message, limit)
|
|
2106
3180
|
};
|
|
2107
3181
|
}
|
|
2108
3182
|
function asNumber(val) {
|
|
@@ -2111,20 +3185,91 @@ function asNumber(val) {
|
|
|
2111
3185
|
return Number.isFinite(n) ? n : void 0;
|
|
2112
3186
|
}
|
|
2113
3187
|
|
|
3188
|
+
// package.json
|
|
3189
|
+
var package_default = {
|
|
3190
|
+
name: "@raindrop-ai/deep-agents",
|
|
3191
|
+
version: "0.1.3",
|
|
3192
|
+
description: "Raindrop integration for LangChain Deep Agents",
|
|
3193
|
+
main: "dist/index.js",
|
|
3194
|
+
module: "dist/index.mjs",
|
|
3195
|
+
types: "dist/index.d.ts",
|
|
3196
|
+
license: "MIT",
|
|
3197
|
+
homepage: "https://www.raindrop.ai/docs/integrations/deepagents/",
|
|
3198
|
+
bugs: {
|
|
3199
|
+
url: "https://www.raindrop.ai/docs/support/"
|
|
3200
|
+
},
|
|
3201
|
+
exports: {
|
|
3202
|
+
".": {
|
|
3203
|
+
types: "./dist/index.d.ts",
|
|
3204
|
+
import: "./dist/index.mjs",
|
|
3205
|
+
require: "./dist/index.js"
|
|
3206
|
+
}
|
|
3207
|
+
},
|
|
3208
|
+
sideEffects: false,
|
|
3209
|
+
files: [
|
|
3210
|
+
"dist/**"
|
|
3211
|
+
],
|
|
3212
|
+
scripts: {
|
|
3213
|
+
build: "tsup",
|
|
3214
|
+
dev: "tsup --watch",
|
|
3215
|
+
clean: "rm -rf dist",
|
|
3216
|
+
test: "vitest run"
|
|
3217
|
+
},
|
|
3218
|
+
peerDependencies: {
|
|
3219
|
+
"@langchain/core": ">=0.3.0",
|
|
3220
|
+
deepagents: ">=0.5.0"
|
|
3221
|
+
},
|
|
3222
|
+
devDependencies: {
|
|
3223
|
+
"@langchain/anthropic": "~0.3.34",
|
|
3224
|
+
"@langchain/core": ">=0.3.0",
|
|
3225
|
+
"@langchain/openai": "~0.3.17",
|
|
3226
|
+
"@raindrop-ai/core": "workspace:*",
|
|
3227
|
+
"@types/node": "^20.11.17",
|
|
3228
|
+
deepagents: "1.0.0",
|
|
3229
|
+
msw: "^2.12.7",
|
|
3230
|
+
tsup: "^8.4.0",
|
|
3231
|
+
typescript: "^5.3.3",
|
|
3232
|
+
vitest: "^2.1.9",
|
|
3233
|
+
zod: "^3.23.0"
|
|
3234
|
+
},
|
|
3235
|
+
tsup: {
|
|
3236
|
+
entry: [
|
|
3237
|
+
"src/index.ts"
|
|
3238
|
+
],
|
|
3239
|
+
format: [
|
|
3240
|
+
"cjs",
|
|
3241
|
+
"esm"
|
|
3242
|
+
],
|
|
3243
|
+
dts: {
|
|
3244
|
+
resolve: true
|
|
3245
|
+
},
|
|
3246
|
+
clean: true,
|
|
3247
|
+
noExternal: [
|
|
3248
|
+
"@raindrop-ai/core"
|
|
3249
|
+
]
|
|
3250
|
+
},
|
|
3251
|
+
publishConfig: {
|
|
3252
|
+
access: "public"
|
|
3253
|
+
}
|
|
3254
|
+
};
|
|
3255
|
+
|
|
2114
3256
|
// src/version.ts
|
|
2115
|
-
var libraryName =
|
|
2116
|
-
var libraryVersion =
|
|
3257
|
+
var libraryName = package_default.name;
|
|
3258
|
+
var libraryVersion = package_default.version;
|
|
2117
3259
|
|
|
2118
3260
|
// src/index.ts
|
|
2119
3261
|
function createRaindropDeepAgents(opts) {
|
|
2120
3262
|
const writeKey = opts.writeKey;
|
|
2121
3263
|
const enabled = !!writeKey;
|
|
3264
|
+
setMaxTextFieldChars(opts.maxTextFieldChars);
|
|
3265
|
+
const maxChars = eventMaxTextFieldChars();
|
|
2122
3266
|
if (!writeKey) {
|
|
2123
3267
|
console.warn(
|
|
2124
3268
|
"[raindrop-ai/deep-agents] writeKey not provided; telemetry shipping is disabled"
|
|
2125
3269
|
);
|
|
2126
3270
|
}
|
|
2127
|
-
const
|
|
3271
|
+
const appGitContext = createAppGitContext2(writeKey?.trim() ? opts.appGit : false, { allowLocalGit: true });
|
|
3272
|
+
const eventShipper = new EventShipper2({
|
|
2128
3273
|
writeKey,
|
|
2129
3274
|
endpoint: opts.endpoint,
|
|
2130
3275
|
enabled,
|
|
@@ -2132,9 +3277,11 @@ function createRaindropDeepAgents(opts) {
|
|
|
2132
3277
|
projectId: opts.projectId,
|
|
2133
3278
|
sdkName: "deep-agents",
|
|
2134
3279
|
libraryName,
|
|
2135
|
-
libraryVersion
|
|
3280
|
+
libraryVersion,
|
|
3281
|
+
appGitContext,
|
|
3282
|
+
maxTextFieldChars: maxChars
|
|
2136
3283
|
});
|
|
2137
|
-
const traceShipper = new
|
|
3284
|
+
const traceShipper = new TraceShipper2({
|
|
2138
3285
|
writeKey,
|
|
2139
3286
|
endpoint: opts.endpoint,
|
|
2140
3287
|
enabled,
|
|
@@ -2142,7 +3289,9 @@ function createRaindropDeepAgents(opts) {
|
|
|
2142
3289
|
projectId: opts.projectId,
|
|
2143
3290
|
sdkName: "deep-agents",
|
|
2144
3291
|
serviceName: "raindrop.deep-agents",
|
|
2145
|
-
serviceVersion: libraryVersion
|
|
3292
|
+
serviceVersion: libraryVersion,
|
|
3293
|
+
appGitContext,
|
|
3294
|
+
maxTextFieldChars: maxChars
|
|
2146
3295
|
});
|
|
2147
3296
|
const handler = new RaindropDeepAgentsHandler({
|
|
2148
3297
|
eventShipper,
|
|
@@ -2151,7 +3300,9 @@ function createRaindropDeepAgents(opts) {
|
|
|
2151
3300
|
convoId: opts.convoId,
|
|
2152
3301
|
eventName: opts.eventName,
|
|
2153
3302
|
eventId: opts.eventId,
|
|
2154
|
-
traceChains: opts.traceChains
|
|
3303
|
+
traceChains: opts.traceChains,
|
|
3304
|
+
maxTextFieldChars: maxChars,
|
|
3305
|
+
eventMaxTextFieldChars: maxChars
|
|
2155
3306
|
});
|
|
2156
3307
|
return {
|
|
2157
3308
|
handler,
|
|
@@ -2162,7 +3313,14 @@ function createRaindropDeepAgents(opts) {
|
|
|
2162
3313
|
await Promise.all([eventShipper.flush(), traceShipper.flush()]);
|
|
2163
3314
|
},
|
|
2164
3315
|
async shutdown() {
|
|
2165
|
-
|
|
3316
|
+
try {
|
|
3317
|
+
await Promise.all([eventShipper.shutdown(), traceShipper.shutdown()]);
|
|
3318
|
+
} finally {
|
|
3319
|
+
try {
|
|
3320
|
+
appGitContext.dispose();
|
|
3321
|
+
} catch {
|
|
3322
|
+
}
|
|
3323
|
+
}
|
|
2166
3324
|
},
|
|
2167
3325
|
events: {
|
|
2168
3326
|
async patch(eventId, patch) {
|