@raindrop-ai/opencode-plugin 0.1.2 → 0.1.4
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 +4 -0
- package/dist/index.cjs +1155 -308
- package/dist/index.d.cts +15 -2
- package/dist/index.d.ts +15 -2
- package/dist/index.js +1155 -308
- package/package.json +2 -2
package/dist/index.cjs
CHANGED
|
@@ -24,7 +24,521 @@ __export(index_exports, {
|
|
|
24
24
|
});
|
|
25
25
|
module.exports = __toCommonJS(index_exports);
|
|
26
26
|
|
|
27
|
-
// ../core/dist/chunk-
|
|
27
|
+
// ../core/dist/chunk-BYBMRLZM.js
|
|
28
|
+
var EVAL_CORRELATION_ID_ATTRIBUTE = "raindrop.eval_correlation_id";
|
|
29
|
+
var PROBE_SCOPE = { correlationId: "" };
|
|
30
|
+
var EvalScopeStorage = class {
|
|
31
|
+
constructor() {
|
|
32
|
+
this._als = null;
|
|
33
|
+
this._probed = false;
|
|
34
|
+
}
|
|
35
|
+
maybeAdoptAsyncLocalStorage() {
|
|
36
|
+
if (this._probed) return;
|
|
37
|
+
this._probed = true;
|
|
38
|
+
try {
|
|
39
|
+
const Ctor = globalThis.RAINDROP_ASYNC_LOCAL_STORAGE;
|
|
40
|
+
if (!Ctor) return;
|
|
41
|
+
const als = new Ctor();
|
|
42
|
+
als.run(PROBE_SCOPE, () => {
|
|
43
|
+
});
|
|
44
|
+
this._als = als;
|
|
45
|
+
} catch (e) {
|
|
46
|
+
this._als = null;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
run(scope, callback) {
|
|
50
|
+
this.maybeAdoptAsyncLocalStorage();
|
|
51
|
+
if (this._als) return this._als.run(scope, callback);
|
|
52
|
+
const previous = this._syncScope;
|
|
53
|
+
this._syncScope = scope;
|
|
54
|
+
try {
|
|
55
|
+
return callback();
|
|
56
|
+
} finally {
|
|
57
|
+
this._syncScope = previous;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
current() {
|
|
61
|
+
this.maybeAdoptAsyncLocalStorage();
|
|
62
|
+
if (this._als) return this._als.getStore();
|
|
63
|
+
return this._syncScope;
|
|
64
|
+
}
|
|
65
|
+
};
|
|
66
|
+
var EVAL_SCOPE_STORAGE_KEY = /* @__PURE__ */ Symbol.for("raindrop.tracing.evalScopeStorage");
|
|
67
|
+
function evalScopeStorage() {
|
|
68
|
+
const holder = globalThis;
|
|
69
|
+
let storage = holder[EVAL_SCOPE_STORAGE_KEY];
|
|
70
|
+
if (!storage) {
|
|
71
|
+
storage = new EvalScopeStorage();
|
|
72
|
+
holder[EVAL_SCOPE_STORAGE_KEY] = storage;
|
|
73
|
+
}
|
|
74
|
+
return storage;
|
|
75
|
+
}
|
|
76
|
+
function currentEvalScope() {
|
|
77
|
+
try {
|
|
78
|
+
return evalScopeStorage().current();
|
|
79
|
+
} catch (e) {
|
|
80
|
+
return void 0;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
function evalScopeAttributes() {
|
|
84
|
+
const scope = currentEvalScope();
|
|
85
|
+
if (!scope) return {};
|
|
86
|
+
return { [EVAL_CORRELATION_ID_ATTRIBUTE]: scope.correlationId };
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// ../core/dist/chunk-WJOR6M7H.js
|
|
90
|
+
var STATE_KEY = /* @__PURE__ */ Symbol.for("raindrop.tracing.replayTraceRoutingState");
|
|
91
|
+
function state() {
|
|
92
|
+
const holder = globalThis;
|
|
93
|
+
let current = holder[STATE_KEY];
|
|
94
|
+
if (!current) {
|
|
95
|
+
let storage = null;
|
|
96
|
+
try {
|
|
97
|
+
const Ctor = globalThis.RAINDROP_ASYNC_LOCAL_STORAGE;
|
|
98
|
+
if (Ctor) storage = new Ctor();
|
|
99
|
+
} catch (e) {
|
|
100
|
+
storage = null;
|
|
101
|
+
}
|
|
102
|
+
current = {
|
|
103
|
+
storage,
|
|
104
|
+
syncDestination: void 0,
|
|
105
|
+
spanDestinations: /* @__PURE__ */ new WeakMap()
|
|
106
|
+
};
|
|
107
|
+
holder[STATE_KEY] = current;
|
|
108
|
+
}
|
|
109
|
+
return current;
|
|
110
|
+
}
|
|
111
|
+
function currentReplayTraceDestination() {
|
|
112
|
+
var _a, _b;
|
|
113
|
+
const routing = state();
|
|
114
|
+
return (_b = (_a = routing.storage) == null ? void 0 : _a.getStore()) != null ? _b : routing.syncDestination;
|
|
115
|
+
}
|
|
116
|
+
function rememberReplayTraceDestination(span) {
|
|
117
|
+
const destination = currentReplayTraceDestination();
|
|
118
|
+
if (destination) state().spanDestinations.set(span, destination);
|
|
119
|
+
}
|
|
120
|
+
function copyReplayTraceDestination(source, target) {
|
|
121
|
+
const destination = state().spanDestinations.get(source);
|
|
122
|
+
if (destination) state().spanDestinations.set(target, destination);
|
|
123
|
+
}
|
|
124
|
+
function replayTraceDestinationFor(value) {
|
|
125
|
+
if (typeof value !== "object" && typeof value !== "function" || value === null) {
|
|
126
|
+
return void 0;
|
|
127
|
+
}
|
|
128
|
+
return state().spanDestinations.get(value);
|
|
129
|
+
}
|
|
130
|
+
function recordReplayExportedSpan(destination, spanId, traceId) {
|
|
131
|
+
var _a, _b;
|
|
132
|
+
if (!destination || !spanId || !traceId) return;
|
|
133
|
+
(_a = destination.exportedSpanIds) == null ? void 0 : _a.add(spanId);
|
|
134
|
+
(_b = destination.exportedTraceIds) == null ? void 0 : _b.add(traceId);
|
|
135
|
+
}
|
|
136
|
+
function replayTraceUrl(baseUrl) {
|
|
137
|
+
return `${baseUrl.replace(/\/+$/, "")}/v1/traces`;
|
|
138
|
+
}
|
|
139
|
+
function getAsyncLocalStorageCtor() {
|
|
140
|
+
return globalThis.RAINDROP_ASYNC_LOCAL_STORAGE;
|
|
141
|
+
}
|
|
142
|
+
var MAX_BINDING_STACK = 128;
|
|
143
|
+
var EMPTY_STACK = [];
|
|
144
|
+
var ContextStackStorage = class {
|
|
145
|
+
/** Emitted once when this runtime cannot support an ambient push. */
|
|
146
|
+
constructor(noAmbientBindWarning) {
|
|
147
|
+
this.noAmbientBindWarning = noAmbientBindWarning;
|
|
148
|
+
this._als = null;
|
|
149
|
+
this._enterWithUsable = false;
|
|
150
|
+
this._syncStack = EMPTY_STACK;
|
|
151
|
+
this._adoptionChecked = false;
|
|
152
|
+
this._warnedNoAmbientBind = false;
|
|
153
|
+
}
|
|
154
|
+
maybeAdoptAsyncLocalStorage() {
|
|
155
|
+
if (this._adoptionChecked) return;
|
|
156
|
+
this._adoptionChecked = true;
|
|
157
|
+
const Ctor = getAsyncLocalStorageCtor();
|
|
158
|
+
if (!Ctor) return;
|
|
159
|
+
const als = new Ctor();
|
|
160
|
+
try {
|
|
161
|
+
als.run(EMPTY_STACK, () => {
|
|
162
|
+
});
|
|
163
|
+
} catch (e) {
|
|
164
|
+
return;
|
|
165
|
+
}
|
|
166
|
+
this._als = als;
|
|
167
|
+
if (typeof als.enterWith === "function") {
|
|
168
|
+
try {
|
|
169
|
+
als.enterWith(EMPTY_STACK);
|
|
170
|
+
this._enterWithUsable = true;
|
|
171
|
+
} catch (e) {
|
|
172
|
+
this._enterWithUsable = false;
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
getStack() {
|
|
177
|
+
var _a;
|
|
178
|
+
this.maybeAdoptAsyncLocalStorage();
|
|
179
|
+
if (this._als) return (_a = this._als.getStore()) != null ? _a : this._syncStack;
|
|
180
|
+
return this._syncStack;
|
|
181
|
+
}
|
|
182
|
+
/**
|
|
183
|
+
* Persist an ambient stack mutation. Returns false when an ALS is adopted but
|
|
184
|
+
* `enterWith` is unusable (workerd): callers must NOT fall back to the
|
|
185
|
+
* process-shared sync stack, since concurrent isolates would cross-stamp.
|
|
186
|
+
*/
|
|
187
|
+
setAmbientStack(stack) {
|
|
188
|
+
if (this._als) {
|
|
189
|
+
if (!this._enterWithUsable) return false;
|
|
190
|
+
this._als.enterWith(stack);
|
|
191
|
+
return true;
|
|
192
|
+
}
|
|
193
|
+
this._syncStack = stack;
|
|
194
|
+
return true;
|
|
195
|
+
}
|
|
196
|
+
push(binding) {
|
|
197
|
+
this.maybeAdoptAsyncLocalStorage();
|
|
198
|
+
if (this._als && !this._enterWithUsable) {
|
|
199
|
+
this.warnNoAmbientBindOnce();
|
|
200
|
+
return;
|
|
201
|
+
}
|
|
202
|
+
let stack = this.getStack();
|
|
203
|
+
if (stack.length >= MAX_BINDING_STACK) {
|
|
204
|
+
stack = stack.filter((b) => b.isLive());
|
|
205
|
+
if (stack.length >= MAX_BINDING_STACK) {
|
|
206
|
+
stack = stack.slice(stack.length - (MAX_BINDING_STACK - 1));
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
this.setAmbientStack([...stack, binding]);
|
|
210
|
+
}
|
|
211
|
+
remove(binding) {
|
|
212
|
+
binding.markDead();
|
|
213
|
+
const stack = this.getStack();
|
|
214
|
+
const pruned = stack.filter((b) => b !== binding && b.isLive());
|
|
215
|
+
if (pruned.length !== stack.length) {
|
|
216
|
+
this.setAmbientStack(pruned);
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
runWith(binding, callback) {
|
|
220
|
+
this.maybeAdoptAsyncLocalStorage();
|
|
221
|
+
if (this._als) {
|
|
222
|
+
return this._als.run([...this.getStack(), binding], callback);
|
|
223
|
+
}
|
|
224
|
+
const previous = this._syncStack;
|
|
225
|
+
this._syncStack = [...previous, binding];
|
|
226
|
+
try {
|
|
227
|
+
return callback();
|
|
228
|
+
} finally {
|
|
229
|
+
this._syncStack = previous;
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
current() {
|
|
233
|
+
const stack = this.getStack();
|
|
234
|
+
if (stack.length === 0) return void 0;
|
|
235
|
+
const top = stack[stack.length - 1];
|
|
236
|
+
if (top.isLive()) return top;
|
|
237
|
+
const pruned = stack.filter((b) => b.isLive());
|
|
238
|
+
this.setAmbientStack(pruned);
|
|
239
|
+
return pruned.length > 0 ? pruned[pruned.length - 1] : void 0;
|
|
240
|
+
}
|
|
241
|
+
warnNoAmbientBindOnce() {
|
|
242
|
+
if (this._warnedNoAmbientBind) return;
|
|
243
|
+
this._warnedNoAmbientBind = true;
|
|
244
|
+
console.warn(this.noAmbientBindWarning);
|
|
245
|
+
}
|
|
246
|
+
};
|
|
247
|
+
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.";
|
|
248
|
+
var ROUTING_STORAGE_KEY = /* @__PURE__ */ Symbol.for("raindrop.tracing.routingContextStorage");
|
|
249
|
+
function routingStorage() {
|
|
250
|
+
const holder = globalThis;
|
|
251
|
+
let storage = holder[ROUTING_STORAGE_KEY];
|
|
252
|
+
if (!storage) {
|
|
253
|
+
storage = new ContextStackStorage(NO_AMBIENT_ROUTING_BIND_WARNING);
|
|
254
|
+
holder[ROUTING_STORAGE_KEY] = storage;
|
|
255
|
+
}
|
|
256
|
+
return storage;
|
|
257
|
+
}
|
|
258
|
+
function currentRoutingBinding() {
|
|
259
|
+
const bound = routingStorage().current();
|
|
260
|
+
if (!bound) return void 0;
|
|
261
|
+
return {
|
|
262
|
+
projectId: bound.projectId,
|
|
263
|
+
authHint: bound.authHint,
|
|
264
|
+
...bound.appGit ? { appGit: bound.appGit } : {},
|
|
265
|
+
...bound.appGitSource ? { appGitSource: bound.appGitSource } : {}
|
|
266
|
+
};
|
|
267
|
+
}
|
|
268
|
+
var APP_COMMIT_SHA = "raindrop.app.commit_sha";
|
|
269
|
+
var APP_COMMIT_DIRTY = "raindrop.app.commit_dirty";
|
|
270
|
+
var APP_BRANCH = "raindrop.app.branch";
|
|
271
|
+
var APP_GIT_KEYS = [APP_COMMIT_SHA, APP_COMMIT_DIRTY, APP_BRANCH];
|
|
272
|
+
var own = (value, key) => Object.prototype.hasOwnProperty.call(value, key);
|
|
273
|
+
function appGitExplicitKeys(properties) {
|
|
274
|
+
const keys = /* @__PURE__ */ new Set();
|
|
275
|
+
if (!properties) return keys;
|
|
276
|
+
for (const key of APP_GIT_KEYS) {
|
|
277
|
+
if (own(properties, key)) keys.add(key);
|
|
278
|
+
}
|
|
279
|
+
return keys;
|
|
280
|
+
}
|
|
281
|
+
function mergeAppGitSnapshot(base, properties, explicitKeys = /* @__PURE__ */ new Set()) {
|
|
282
|
+
try {
|
|
283
|
+
const result = { ...base };
|
|
284
|
+
if (properties && own(properties, APP_COMMIT_SHA) && properties[APP_COMMIT_SHA] !== result[APP_COMMIT_SHA]) {
|
|
285
|
+
if (!explicitKeys.has(APP_COMMIT_DIRTY) && !own(properties, APP_COMMIT_DIRTY)) {
|
|
286
|
+
delete result[APP_COMMIT_DIRTY];
|
|
287
|
+
}
|
|
288
|
+
if (!explicitKeys.has(APP_BRANCH) && !own(properties, APP_BRANCH)) {
|
|
289
|
+
delete result[APP_BRANCH];
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
for (const key of APP_GIT_KEYS) {
|
|
293
|
+
if (properties && own(properties, key)) result[key] = properties[key];
|
|
294
|
+
}
|
|
295
|
+
return Object.freeze(result);
|
|
296
|
+
} catch (e) {
|
|
297
|
+
return Object.freeze({});
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
function validAppCommitSha(value) {
|
|
301
|
+
if (typeof value !== "string" || value.length > 128) return void 0;
|
|
302
|
+
const cleaned = value.trim();
|
|
303
|
+
return /^(?:[a-fA-F0-9]{40}|[a-fA-F0-9]{64})$/.test(cleaned) ? cleaned.toLowerCase() : void 0;
|
|
304
|
+
}
|
|
305
|
+
function shortString(value) {
|
|
306
|
+
if (typeof value !== "string" || value.length > 1024) return void 0;
|
|
307
|
+
const cleaned = value.trim();
|
|
308
|
+
return cleaned.length > 0 ? cleaned : void 0;
|
|
309
|
+
}
|
|
310
|
+
function flag(value) {
|
|
311
|
+
if (value === true || value === "true" || value === "1") return true;
|
|
312
|
+
if (value === false || value === "false" || value === "0") return false;
|
|
313
|
+
return void 0;
|
|
314
|
+
}
|
|
315
|
+
function environment() {
|
|
316
|
+
try {
|
|
317
|
+
return typeof process === "undefined" ? {} : process.env;
|
|
318
|
+
} catch (e) {
|
|
319
|
+
return {};
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
var DEPLOYMENTS = [
|
|
323
|
+
["VERCEL", "VERCEL_GIT_COMMIT_SHA", "VERCEL_GIT_COMMIT_REF"],
|
|
324
|
+
["NETLIFY", "COMMIT_REF", "BRANCH"],
|
|
325
|
+
["RAILWAY_ENVIRONMENT_NAME", "RAILWAY_GIT_COMMIT_SHA", "RAILWAY_GIT_BRANCH"],
|
|
326
|
+
["RAILWAY_ENVIRONMENT", "RAILWAY_GIT_COMMIT_SHA", "RAILWAY_GIT_BRANCH"],
|
|
327
|
+
["RENDER", "RENDER_GIT_COMMIT", "RENDER_GIT_BRANCH"],
|
|
328
|
+
["DYNO", "HEROKU_BUILD_COMMIT", ""],
|
|
329
|
+
["DYNO", "HEROKU_SLUG_COMMIT", ""],
|
|
330
|
+
["AWS_APP_ID", "AWS_COMMIT_ID", "AWS_BRANCH"],
|
|
331
|
+
["WORKERS_CI", "WORKERS_CI_COMMIT_SHA", "WORKERS_CI_BRANCH"]
|
|
332
|
+
];
|
|
333
|
+
var CI_SOURCES = [
|
|
334
|
+
["GITHUB_ACTIONS", "GITHUB_SHA", "GITHUB_REF_NAME"],
|
|
335
|
+
["GITLAB_CI", "CI_COMMIT_SHA", "CI_COMMIT_REF_NAME"],
|
|
336
|
+
["CIRCLECI", "CIRCLE_SHA1", "CIRCLE_BRANCH"]
|
|
337
|
+
];
|
|
338
|
+
function detectedSource(env, table, detectBranch) {
|
|
339
|
+
for (const row of table) {
|
|
340
|
+
const [marker, shaKey, branchKey] = row;
|
|
341
|
+
if (!marker || !shaKey || !shortString(env[marker]) || flag(env[marker]) === false) continue;
|
|
342
|
+
const commitSha = validAppCommitSha(env[shaKey]);
|
|
343
|
+
if (commitSha)
|
|
344
|
+
return {
|
|
345
|
+
commitSha,
|
|
346
|
+
...detectBranch && branchKey ? { branch: shortString(env[branchKey]) } : {}
|
|
347
|
+
};
|
|
348
|
+
}
|
|
349
|
+
return {};
|
|
350
|
+
}
|
|
351
|
+
var AppGitContextImpl = class {
|
|
352
|
+
constructor(options, runtime = {}) {
|
|
353
|
+
this.defaults = {};
|
|
354
|
+
this.explicit = {};
|
|
355
|
+
this.explicitKeys = /* @__PURE__ */ new Set();
|
|
356
|
+
this.disposed = false;
|
|
357
|
+
this.operations = /* @__PURE__ */ new Map();
|
|
358
|
+
this.operationOverflow = false;
|
|
359
|
+
this.detectBranch = false;
|
|
360
|
+
this.disabled = false;
|
|
361
|
+
var _a, _b, _c, _d, _e, _f;
|
|
362
|
+
try {
|
|
363
|
+
if (options === false) {
|
|
364
|
+
this.disabled = true;
|
|
365
|
+
return;
|
|
366
|
+
}
|
|
367
|
+
const opts = options != null ? options : {};
|
|
368
|
+
const env = (_a = runtime.env) != null ? _a : environment();
|
|
369
|
+
const detectBranch = (_c = (_b = flag(opts.detectBranch)) != null ? _b : flag(env.RAINDROP_GIT_DETECT_BRANCH)) != null ? _c : false;
|
|
370
|
+
this.detectBranch = detectBranch;
|
|
371
|
+
const collectBranch = detectBranch || runtime.captureLegacyReplayBranch === true;
|
|
372
|
+
const autoDetect = runtime.allowDiscovery === false ? false : (_e = (_d = flag(opts.autoDetect)) != null ? _d : flag(env.RAINDROP_GIT_AUTO_DETECT)) != null ? _e : true;
|
|
373
|
+
const configuredSha = opts.commitSha;
|
|
374
|
+
const explicitSha = configuredSha === void 0 ? env.RAINDROP_COMMIT_SHA : configuredSha;
|
|
375
|
+
if (explicitSha === null) this.explicit[APP_COMMIT_SHA] = null;
|
|
376
|
+
else if (typeof explicitSha === "string" && validAppCommitSha(explicitSha))
|
|
377
|
+
this.explicit[APP_COMMIT_SHA] = explicitSha;
|
|
378
|
+
const configuredDirty = opts.commitDirty;
|
|
379
|
+
const explicitDirty = configuredDirty === void 0 ? flag(env.RAINDROP_COMMIT_DIRTY) : configuredDirty;
|
|
380
|
+
if (explicitDirty === null || typeof explicitDirty === "boolean")
|
|
381
|
+
this.explicit[APP_COMMIT_DIRTY] = explicitDirty;
|
|
382
|
+
const configuredBranch = opts.branch;
|
|
383
|
+
const explicitBranch = configuredBranch === void 0 ? env.RAINDROP_BRANCH : configuredBranch;
|
|
384
|
+
if (explicitBranch === null) this.explicit[APP_BRANCH] = null;
|
|
385
|
+
else if (typeof explicitBranch === "string" && explicitBranch.length <= 1024)
|
|
386
|
+
this.explicit[APP_BRANCH] = explicitBranch;
|
|
387
|
+
this.explicitKeys = appGitExplicitKeys(this.explicit);
|
|
388
|
+
this.defaults = { ...this.explicit };
|
|
389
|
+
if (!autoDetect || explicitSha !== void 0) return;
|
|
390
|
+
const sourceDirectory = (_f = shortString(opts.sourceDirectory)) != null ? _f : shortString(env.RAINDROP_GIT_SOURCE_DIRECTORY);
|
|
391
|
+
if (runtime.allowLocalGit === false && !sourceDirectory) return;
|
|
392
|
+
const deploy = sourceDirectory ? {} : detectedSource(env, DEPLOYMENTS, collectBranch);
|
|
393
|
+
if (deploy.commitSha) {
|
|
394
|
+
this.accept(deploy);
|
|
395
|
+
return;
|
|
396
|
+
}
|
|
397
|
+
const fallback = sourceDirectory ? {} : detectedSource(env, CI_SOURCES, collectBranch);
|
|
398
|
+
if (runtime.resolveLocal && (runtime.allowLocalGit !== false || sourceDirectory)) {
|
|
399
|
+
this.cancel = runtime.resolveLocal(sourceDirectory, collectBranch, (result) => {
|
|
400
|
+
try {
|
|
401
|
+
if (!this.disposed) this.accept(result.commitSha ? result : fallback);
|
|
402
|
+
} catch (e) {
|
|
403
|
+
}
|
|
404
|
+
});
|
|
405
|
+
} else this.accept(fallback);
|
|
406
|
+
} catch (e) {
|
|
407
|
+
}
|
|
408
|
+
}
|
|
409
|
+
accept(result) {
|
|
410
|
+
const sha = validAppCommitSha(result.commitSha);
|
|
411
|
+
if (!sha) return;
|
|
412
|
+
this.replayBranch = shortString(result.branch);
|
|
413
|
+
this.defaults = {
|
|
414
|
+
[APP_COMMIT_SHA]: sha,
|
|
415
|
+
...typeof result.commitDirty === "boolean" ? { [APP_COMMIT_DIRTY]: result.commitDirty } : {},
|
|
416
|
+
...this.detectBranch && this.replayBranch ? { [APP_BRANCH]: this.replayBranch } : {},
|
|
417
|
+
...this.explicit
|
|
418
|
+
};
|
|
419
|
+
}
|
|
420
|
+
snapshot(properties) {
|
|
421
|
+
var _a;
|
|
422
|
+
try {
|
|
423
|
+
const binding = currentRoutingBinding();
|
|
424
|
+
const base = this.disabled && (binding == null ? void 0 : binding.appGitSource) !== "replay-override" ? {} : (_a = binding == null ? void 0 : binding.appGit) != null ? _a : this.defaults;
|
|
425
|
+
return this.mergeSnapshot(base, properties);
|
|
426
|
+
} catch (e) {
|
|
427
|
+
return Object.freeze({});
|
|
428
|
+
}
|
|
429
|
+
}
|
|
430
|
+
/** Safe defaults when no operation/span start was observed; never infer identity. */
|
|
431
|
+
snapshotExplicit(properties, eventId) {
|
|
432
|
+
try {
|
|
433
|
+
const base = { ...this.explicit };
|
|
434
|
+
const operation = eventId ? this.operations.get(eventId) : void 0;
|
|
435
|
+
if (operation) {
|
|
436
|
+
for (const key of operation.explicitKeys) base[key] = operation.snapshot[key];
|
|
437
|
+
}
|
|
438
|
+
return this.mergeSnapshot(base, properties, new Set(Object.keys(base)));
|
|
439
|
+
} catch (e) {
|
|
440
|
+
return mergeAppGitSnapshot({}, properties);
|
|
441
|
+
}
|
|
442
|
+
}
|
|
443
|
+
/** Existing replay branch reporting stays separate from opt-in event properties. */
|
|
444
|
+
snapshotForReplay() {
|
|
445
|
+
const snapshot = this.snapshot();
|
|
446
|
+
if (this.replayBranch && !own(snapshot, APP_BRANCH) && snapshot[APP_COMMIT_SHA] === this.defaults[APP_COMMIT_SHA]) {
|
|
447
|
+
return Object.freeze({ ...snapshot, [APP_BRANCH]: this.replayBranch });
|
|
448
|
+
}
|
|
449
|
+
return snapshot;
|
|
450
|
+
}
|
|
451
|
+
/** Merge a frozen span snapshot without losing client-authored provenance. */
|
|
452
|
+
mergeSnapshot(base, properties, explicitKeys = this.explicitKeys) {
|
|
453
|
+
return mergeAppGitSnapshot(base, properties, /* @__PURE__ */ new Set([...this.explicitKeys, ...explicitKeys]));
|
|
454
|
+
}
|
|
455
|
+
/** Shippers belonging to one client share this bounded operation registry. */
|
|
456
|
+
forOperation(eventId, properties, owner) {
|
|
457
|
+
if (!eventId) return this.snapshot(properties);
|
|
458
|
+
let operation = this.operations.get(eventId);
|
|
459
|
+
if (!operation) {
|
|
460
|
+
if (this.operations.size >= 1e4) this.operationOverflow = true;
|
|
461
|
+
if (this.operationOverflow) return this.mergeSnapshot({}, properties);
|
|
462
|
+
operation = {
|
|
463
|
+
snapshot: this.snapshot(properties),
|
|
464
|
+
owners: /* @__PURE__ */ new Set(),
|
|
465
|
+
unowned: owner === void 0,
|
|
466
|
+
explicitKeys: appGitExplicitKeys(properties)
|
|
467
|
+
};
|
|
468
|
+
this.operations.set(eventId, operation);
|
|
469
|
+
} else if (properties && APP_GIT_KEYS.some((key) => own(properties, key))) {
|
|
470
|
+
const explicitKeys = /* @__PURE__ */ new Set([...this.explicitKeys, ...operation.explicitKeys]);
|
|
471
|
+
operation.snapshot = this.mergeSnapshot(operation.snapshot, properties, explicitKeys);
|
|
472
|
+
for (const key of appGitExplicitKeys(properties)) operation.explicitKeys.add(key);
|
|
473
|
+
}
|
|
474
|
+
if (!owner) operation.unowned = true;
|
|
475
|
+
if (owner) operation.owners.add(owner);
|
|
476
|
+
return operation.snapshot;
|
|
477
|
+
}
|
|
478
|
+
releaseOperation(eventId, owner) {
|
|
479
|
+
const operation = this.operations.get(eventId);
|
|
480
|
+
if (!operation) return;
|
|
481
|
+
operation.owners.delete(owner);
|
|
482
|
+
if (operation.owners.size === 0 && !operation.unowned) this.operations.delete(eventId);
|
|
483
|
+
}
|
|
484
|
+
finishOperation(eventId) {
|
|
485
|
+
this.operations.delete(eventId);
|
|
486
|
+
}
|
|
487
|
+
dispose() {
|
|
488
|
+
var _a;
|
|
489
|
+
this.disposed = true;
|
|
490
|
+
try {
|
|
491
|
+
(_a = this.cancel) == null ? void 0 : _a.call(this);
|
|
492
|
+
} catch (e) {
|
|
493
|
+
}
|
|
494
|
+
}
|
|
495
|
+
};
|
|
496
|
+
var AppGitContext = AppGitContextImpl;
|
|
497
|
+
function createAppGitContext(options, runtime = {}) {
|
|
498
|
+
return new AppGitContext(options, runtime);
|
|
499
|
+
}
|
|
500
|
+
function withAppGitProperties(properties, snapshot) {
|
|
501
|
+
try {
|
|
502
|
+
const merged = { ...properties };
|
|
503
|
+
for (const key of APP_GIT_KEYS)
|
|
504
|
+
if (!own(merged, key) && own(snapshot, key)) merged[key] = snapshot[key];
|
|
505
|
+
return merged;
|
|
506
|
+
} catch (e) {
|
|
507
|
+
return properties != null ? properties : {};
|
|
508
|
+
}
|
|
509
|
+
}
|
|
510
|
+
function withAppGitAttributes(attributes, snapshot) {
|
|
511
|
+
try {
|
|
512
|
+
const present = new Set(attributes.flatMap((attr) => attr ? [attr.key] : []));
|
|
513
|
+
const added = [];
|
|
514
|
+
for (const key of APP_GIT_KEYS) {
|
|
515
|
+
if (present.has(key) || present.has(`ai.telemetry.metadata.${key}`) || present.has(`traceloop.association.properties.${key}`))
|
|
516
|
+
continue;
|
|
517
|
+
const value = snapshot[key];
|
|
518
|
+
if (typeof value === "string") added.push({ key, value: { stringValue: value } });
|
|
519
|
+
else if (typeof value === "boolean") added.push({ key, value: { boolValue: value } });
|
|
520
|
+
}
|
|
521
|
+
return added.length ? [...attributes, ...added] : attributes;
|
|
522
|
+
} catch (e) {
|
|
523
|
+
return attributes;
|
|
524
|
+
}
|
|
525
|
+
}
|
|
526
|
+
function appGitPropertiesFromAttributes(attributes) {
|
|
527
|
+
var _a, _b, _c;
|
|
528
|
+
const properties = {};
|
|
529
|
+
try {
|
|
530
|
+
for (const attr of attributes) {
|
|
531
|
+
if (!attr) continue;
|
|
532
|
+
for (const key of APP_GIT_KEYS) {
|
|
533
|
+
if (attr.key === key || attr.key === `ai.telemetry.metadata.${key}` || attr.key === `traceloop.association.properties.${key}`) {
|
|
534
|
+
properties[key] = (_c = (_b = (_a = attr.value.stringValue) != null ? _a : attr.value.boolValue) != null ? _b : attr.value.intValue) != null ? _c : null;
|
|
535
|
+
}
|
|
536
|
+
}
|
|
537
|
+
}
|
|
538
|
+
} catch (e) {
|
|
539
|
+
}
|
|
540
|
+
return properties;
|
|
541
|
+
}
|
|
28
542
|
function getCrypto() {
|
|
29
543
|
const c = globalThis.crypto;
|
|
30
544
|
return c;
|
|
@@ -79,6 +593,25 @@ function base64Encode(bytes) {
|
|
|
79
593
|
}
|
|
80
594
|
return out;
|
|
81
595
|
}
|
|
596
|
+
function base64ToHex(value) {
|
|
597
|
+
if (!value) return "";
|
|
598
|
+
const maybeBuffer = globalThis.Buffer;
|
|
599
|
+
if (maybeBuffer) {
|
|
600
|
+
return maybeBuffer.from(value, "base64").toString("hex");
|
|
601
|
+
}
|
|
602
|
+
const atobFn = globalThis.atob;
|
|
603
|
+
if (typeof atobFn !== "function") return "";
|
|
604
|
+
try {
|
|
605
|
+
const binary = atobFn(value);
|
|
606
|
+
let hex = "";
|
|
607
|
+
for (let i = 0; i < binary.length; i++) {
|
|
608
|
+
hex += (binary.charCodeAt(i) & 255).toString(16).padStart(2, "0");
|
|
609
|
+
}
|
|
610
|
+
return hex;
|
|
611
|
+
} catch (e) {
|
|
612
|
+
return "";
|
|
613
|
+
}
|
|
614
|
+
}
|
|
82
615
|
function generateId() {
|
|
83
616
|
return randomUUID();
|
|
84
617
|
}
|
|
@@ -113,7 +646,7 @@ function runWithTracingSuppressed(fn) {
|
|
|
113
646
|
var DEFAULT_REQUEST_TIMEOUT_MS = 3e4;
|
|
114
647
|
var MAX_RETRY_DELAY_MS = 3e4;
|
|
115
648
|
function wait(ms) {
|
|
116
|
-
return new Promise((
|
|
649
|
+
return new Promise((resolve2) => setTimeout(resolve2, ms));
|
|
117
650
|
}
|
|
118
651
|
function formatEndpoint(endpoint) {
|
|
119
652
|
if (!endpoint) return void 0;
|
|
@@ -150,9 +683,9 @@ async function raceWithTimeout(promise, timeoutMs) {
|
|
|
150
683
|
() => true,
|
|
151
684
|
() => true
|
|
152
685
|
),
|
|
153
|
-
new Promise((
|
|
686
|
+
new Promise((resolve2) => {
|
|
154
687
|
var _a;
|
|
155
|
-
timer = setTimeout(() =>
|
|
688
|
+
timer = setTimeout(() => resolve2(false), Math.max(0, timeoutMs));
|
|
156
689
|
(_a = timer.unref) == null ? void 0 : _a.call(timer);
|
|
157
690
|
})
|
|
158
691
|
]);
|
|
@@ -223,6 +756,7 @@ async function postJson(url, body, headers, opts) {
|
|
|
223
756
|
const resp = await runWithTracingSuppressed(
|
|
224
757
|
() => fetch(url, {
|
|
225
758
|
method: "POST",
|
|
759
|
+
redirect: headers["X-Raindrop-Replay-Id"] !== void 0 ? "error" : "follow",
|
|
226
760
|
headers: {
|
|
227
761
|
"Content-Type": "application/json",
|
|
228
762
|
...headers
|
|
@@ -293,6 +827,11 @@ function attrInt(key, value) {
|
|
|
293
827
|
if (!Number.isFinite(value)) return void 0;
|
|
294
828
|
return { key, value: { intValue: String(Math.trunc(value)) } };
|
|
295
829
|
}
|
|
830
|
+
function attrDouble(key, value) {
|
|
831
|
+
if (value === void 0) return void 0;
|
|
832
|
+
if (!Number.isFinite(value)) return void 0;
|
|
833
|
+
return { key, value: { doubleValue: value } };
|
|
834
|
+
}
|
|
296
835
|
function buildOtlpSpan(args) {
|
|
297
836
|
const attrs = args.attributes.filter((x) => x !== void 0);
|
|
298
837
|
const span = {
|
|
@@ -386,26 +925,29 @@ function resolveLocalDebuggerBaseUrl(baseUrl) {
|
|
|
386
925
|
if (shouldAutoEnableLocalWorkshop()) return DEFAULT_LOCAL_WORKSHOP_URL;
|
|
387
926
|
return null;
|
|
388
927
|
}
|
|
928
|
+
var LOCAL_DEBUGGER_MIRROR_TIMEOUT_MS = 2e3;
|
|
389
929
|
function mirrorTraceExportToLocalDebugger(body, options = {}) {
|
|
390
930
|
var _a;
|
|
391
931
|
const baseUrl = resolveLocalDebuggerBaseUrl(options.baseUrl);
|
|
392
|
-
if (!baseUrl) return;
|
|
393
|
-
|
|
932
|
+
if (!baseUrl) return Promise.resolve();
|
|
933
|
+
return postJson(`${baseUrl}traces`, body, {}, {
|
|
394
934
|
maxAttempts: 1,
|
|
395
935
|
debug: (_a = options.debug) != null ? _a : false,
|
|
396
|
-
sdkName: options.sdkName
|
|
936
|
+
sdkName: options.sdkName,
|
|
937
|
+
timeoutMs: LOCAL_DEBUGGER_MIRROR_TIMEOUT_MS
|
|
397
938
|
}).catch(() => {
|
|
398
939
|
});
|
|
399
940
|
}
|
|
400
941
|
function mirrorPartialEventToLocalDebugger(event, options = {}) {
|
|
401
942
|
var _a;
|
|
402
943
|
const baseUrl = resolveLocalDebuggerBaseUrl(options.baseUrl);
|
|
403
|
-
if (!baseUrl) return;
|
|
944
|
+
if (!baseUrl) return Promise.resolve();
|
|
404
945
|
const headers = options.writeKey ? { Authorization: `Bearer ${options.writeKey}` } : {};
|
|
405
|
-
|
|
946
|
+
return postJson(`${baseUrl}events/track_partial`, event, headers, {
|
|
406
947
|
maxAttempts: 1,
|
|
407
948
|
debug: (_a = options.debug) != null ? _a : false,
|
|
408
|
-
sdkName: options.sdkName
|
|
949
|
+
sdkName: options.sdkName,
|
|
950
|
+
timeoutMs: LOCAL_DEBUGGER_MIRROR_TIMEOUT_MS
|
|
409
951
|
}).catch(() => {
|
|
410
952
|
});
|
|
411
953
|
}
|
|
@@ -430,6 +972,13 @@ function projectIdHeaders(projectId) {
|
|
|
430
972
|
}
|
|
431
973
|
var SHUTDOWN_DEADLINE_MS = 1e4;
|
|
432
974
|
var POST_SHUTDOWN_TIMEOUT_MS = 5e3;
|
|
975
|
+
function appGitOwnerId(prefix) {
|
|
976
|
+
try {
|
|
977
|
+
return `${prefix}:${randomUUID()}`;
|
|
978
|
+
} catch (e) {
|
|
979
|
+
return `${prefix}:${Date.now().toString(36)}:${Math.random().toString(36).slice(2)}`;
|
|
980
|
+
}
|
|
981
|
+
}
|
|
433
982
|
function mergePatches(target, source) {
|
|
434
983
|
var _a, _b, _c, _d, _e, _f, _g, _h, _i;
|
|
435
984
|
const out = { ...target, ...source };
|
|
@@ -479,22 +1028,25 @@ function eventTelemetryProperties(patch) {
|
|
|
479
1028
|
}
|
|
480
1029
|
var EventShipper = class {
|
|
481
1030
|
constructor(opts) {
|
|
1031
|
+
this.appGitOwner = appGitOwnerId("event");
|
|
482
1032
|
this.buffers = /* @__PURE__ */ new Map();
|
|
483
1033
|
this.sticky = /* @__PURE__ */ new Map();
|
|
484
1034
|
this.timers = /* @__PURE__ */ new Map();
|
|
485
1035
|
this.inFlight = /* @__PURE__ */ new Set();
|
|
486
1036
|
this.hasShutdown = false;
|
|
487
|
-
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
488
|
-
this.
|
|
489
|
-
this.
|
|
1037
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _i;
|
|
1038
|
+
this.appGitContext = (_a = opts.appGitContext) != null ? _a : createAppGitContext(opts.appGit);
|
|
1039
|
+
this.ownsAppGitContext = opts.appGitContext === void 0;
|
|
1040
|
+
this.writeKey = (_b = opts.writeKey) == null ? void 0 : _b.trim();
|
|
1041
|
+
this.baseUrl = (_c = formatEndpoint(opts.endpoint)) != null ? _c : "https://api.raindrop.ai/v1/";
|
|
490
1042
|
this.enabled = opts.enabled !== false;
|
|
491
1043
|
this.debug = opts.debug;
|
|
492
|
-
this.partialFlushMs = (
|
|
493
|
-
this.sdkName = (
|
|
1044
|
+
this.partialFlushMs = (_d = opts.partialFlushMs) != null ? _d : 1e3;
|
|
1045
|
+
this.sdkName = (_e = opts.sdkName) != null ? _e : "core";
|
|
494
1046
|
this.prefix = `[raindrop-ai/${this.sdkName}]`;
|
|
495
|
-
this.defaultEventName = (
|
|
1047
|
+
this.defaultEventName = (_f = opts.defaultEventName) != null ? _f : "ai_generation";
|
|
496
1048
|
this.maxTextFieldCharsOpt = opts.maxTextFieldChars;
|
|
497
|
-
this.localDebuggerUrl = (
|
|
1049
|
+
this.localDebuggerUrl = (_g = resolveLocalDebuggerBaseUrl(opts.localDebuggerUrl)) != null ? _g : void 0;
|
|
498
1050
|
if (this.debug && this.localDebuggerUrl) {
|
|
499
1051
|
console.log(`${this.prefix} Local debugger mirroring: ${this.localDebuggerUrl}`);
|
|
500
1052
|
}
|
|
@@ -505,8 +1057,8 @@ var EventShipper = class {
|
|
|
505
1057
|
const isNode = typeof process !== "undefined" && typeof process.version === "string";
|
|
506
1058
|
this.context = {
|
|
507
1059
|
library: {
|
|
508
|
-
name: (
|
|
509
|
-
version: (
|
|
1060
|
+
name: (_h = opts.libraryName) != null ? _h : "@raindrop-ai/core",
|
|
1061
|
+
version: (_i = opts.libraryVersion) != null ? _i : "0.0.0"
|
|
510
1062
|
},
|
|
511
1063
|
metadata: {
|
|
512
1064
|
jsRuntime: isNode ? "node" : "web",
|
|
@@ -514,6 +1066,9 @@ var EventShipper = class {
|
|
|
514
1066
|
}
|
|
515
1067
|
};
|
|
516
1068
|
}
|
|
1069
|
+
ownAppGitContextForShutdown() {
|
|
1070
|
+
this.ownsAppGitContext = true;
|
|
1071
|
+
}
|
|
517
1072
|
isDebugEnabled() {
|
|
518
1073
|
return this.debug;
|
|
519
1074
|
}
|
|
@@ -562,6 +1117,15 @@ var EventShipper = class {
|
|
|
562
1117
|
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k;
|
|
563
1118
|
if (!this.enabled) return;
|
|
564
1119
|
if (!eventId || !eventId.trim()) return;
|
|
1120
|
+
const capturedSticky = this.sticky.get(eventId);
|
|
1121
|
+
const eventAlreadyKnown = capturedSticky !== void 0 || this.buffers.has(eventId);
|
|
1122
|
+
const destination = currentReplayTraceDestination();
|
|
1123
|
+
const cloudReplay = destination !== void 0 && destination.kind !== "workshop";
|
|
1124
|
+
if ((capturedSticky == null ? void 0 : capturedSticky.replayOnly) === true || !eventAlreadyKnown && cloudReplay) {
|
|
1125
|
+
if (patch.isPending === false) this.sticky.delete(eventId);
|
|
1126
|
+
else this.sticky.set(eventId, { ...capturedSticky, replayOnly: true });
|
|
1127
|
+
return;
|
|
1128
|
+
}
|
|
565
1129
|
const maxChars = resolveMaxTextFieldChars(this.maxTextFieldCharsOpt);
|
|
566
1130
|
if (typeof patch.input === "string" && patch.input.length > maxChars) {
|
|
567
1131
|
patch = { ...patch, input: capText(patch.input, maxChars) };
|
|
@@ -583,6 +1147,13 @@ var EventShipper = class {
|
|
|
583
1147
|
}
|
|
584
1148
|
const sticky = (_c = this.sticky.get(eventId)) != null ? _c : {};
|
|
585
1149
|
const existing = (_d = this.buffers.get(eventId)) != null ? _d : {};
|
|
1150
|
+
patch = {
|
|
1151
|
+
...patch,
|
|
1152
|
+
properties: withAppGitProperties(
|
|
1153
|
+
patch.properties,
|
|
1154
|
+
this.appGitContext.forOperation(eventId, patch.properties, this.appGitOwner)
|
|
1155
|
+
)
|
|
1156
|
+
};
|
|
586
1157
|
const merged = mergePatches(existing, patch);
|
|
587
1158
|
merged.isPending = (_g = (_f = (_e = patch.isPending) != null ? _e : existing.isPending) != null ? _f : sticky.isPending) != null ? _g : true;
|
|
588
1159
|
this.buffers.set(eventId, merged);
|
|
@@ -596,6 +1167,8 @@ var EventShipper = class {
|
|
|
596
1167
|
if (t) clearTimeout(t);
|
|
597
1168
|
if (merged.isPending === false) {
|
|
598
1169
|
await this.flushOne(eventId);
|
|
1170
|
+
if (this.appGitContext.releaseOperation) this.appGitContext.releaseOperation(eventId, this.appGitOwner);
|
|
1171
|
+
else this.appGitContext.finishOperation(eventId);
|
|
599
1172
|
return;
|
|
600
1173
|
}
|
|
601
1174
|
const timeout = setTimeout(() => {
|
|
@@ -620,15 +1193,21 @@ var EventShipper = class {
|
|
|
620
1193
|
try {
|
|
621
1194
|
for (const t of this.timers.values()) clearTimeout(t);
|
|
622
1195
|
this.timers.clear();
|
|
1196
|
+
for (const [eventId, sticky] of this.sticky) {
|
|
1197
|
+
if (sticky.replayOnly) this.sticky.delete(eventId);
|
|
1198
|
+
}
|
|
623
1199
|
const settled = await raceWithTimeout(this.flush(), SHUTDOWN_DEADLINE_MS);
|
|
624
1200
|
if (!settled) this.warnShutdownDrop("in-flight request(s) at shutdown");
|
|
625
1201
|
} finally {
|
|
626
1202
|
this.shutdownDeadlineAt = void 0;
|
|
1203
|
+
if (this.ownsAppGitContext) this.appGitContext.dispose();
|
|
627
1204
|
}
|
|
628
1205
|
}
|
|
629
1206
|
async trackSignal(signal) {
|
|
630
1207
|
var _a, _b;
|
|
631
1208
|
if (!this.enabled) return;
|
|
1209
|
+
const destination = currentReplayTraceDestination();
|
|
1210
|
+
if (destination && destination.kind !== "workshop") return;
|
|
632
1211
|
const body = [
|
|
633
1212
|
{
|
|
634
1213
|
event_id: signal.eventId,
|
|
@@ -663,6 +1242,8 @@ var EventShipper = class {
|
|
|
663
1242
|
}
|
|
664
1243
|
async identify(users) {
|
|
665
1244
|
if (!this.enabled) return;
|
|
1245
|
+
const destination = currentReplayTraceDestination();
|
|
1246
|
+
if (destination && destination.kind !== "workshop") return;
|
|
666
1247
|
const list = Array.isArray(users) ? users : [users];
|
|
667
1248
|
const body = list.filter((user) => {
|
|
668
1249
|
if (!(user == null ? void 0 : user.userId) || !user.userId.trim()) {
|
|
@@ -715,8 +1296,9 @@ var EventShipper = class {
|
|
|
715
1296
|
this.buffers.delete(eventId);
|
|
716
1297
|
if (!accumulated) return;
|
|
717
1298
|
const sticky = (_a = this.sticky.get(eventId)) != null ? _a : {};
|
|
718
|
-
const
|
|
719
|
-
const
|
|
1299
|
+
const isPending = (_c = (_b = accumulated.isPending) != null ? _b : sticky.isPending) != null ? _c : true;
|
|
1300
|
+
const eventName = (_e = (_d = accumulated.eventName) != null ? _d : sticky.eventName) != null ? _e : this.defaultEventName;
|
|
1301
|
+
const userId = (_f = accumulated.userId) != null ? _f : sticky.userId;
|
|
720
1302
|
if (!userId) {
|
|
721
1303
|
if (this.debug) {
|
|
722
1304
|
console.warn(`${this.prefix} skipping track_partial for ${eventId}: missing userId`);
|
|
@@ -724,14 +1306,13 @@ var EventShipper = class {
|
|
|
724
1306
|
this.sticky.delete(eventId);
|
|
725
1307
|
return;
|
|
726
1308
|
}
|
|
727
|
-
const { wizardSession, ...restProperties } = (
|
|
1309
|
+
const { wizardSession, ...restProperties } = (_g = accumulated.properties) != null ? _g : {};
|
|
728
1310
|
let telemetryProperties = {};
|
|
729
1311
|
try {
|
|
730
1312
|
telemetryProperties = eventTelemetryProperties(accumulated);
|
|
731
1313
|
} catch (e) {
|
|
732
1314
|
}
|
|
733
|
-
const convoId = (
|
|
734
|
-
const isPending = (_h = (_g = accumulated.isPending) != null ? _g : sticky.isPending) != null ? _h : true;
|
|
1315
|
+
const convoId = (_h = accumulated.convoId) != null ? _h : sticky.convoId;
|
|
735
1316
|
const payload = {
|
|
736
1317
|
event_id: eventId,
|
|
737
1318
|
user_id: userId,
|
|
@@ -773,29 +1354,30 @@ var EventShipper = class {
|
|
|
773
1354
|
endpoint: url
|
|
774
1355
|
});
|
|
775
1356
|
}
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
});
|
|
783
|
-
}
|
|
1357
|
+
const mirror = this.localDebuggerUrl ? mirrorPartialEventToLocalDebugger(payload, {
|
|
1358
|
+
baseUrl: this.localDebuggerUrl,
|
|
1359
|
+
writeKey: this.writeKey,
|
|
1360
|
+
debug: this.debug,
|
|
1361
|
+
sdkName: this.sdkName
|
|
1362
|
+
}) : void 0;
|
|
784
1363
|
if (!this.writeKey) {
|
|
785
1364
|
if (!isPending) this.sticky.delete(eventId);
|
|
1365
|
+
if (mirror) await mirror;
|
|
786
1366
|
return;
|
|
787
1367
|
}
|
|
788
1368
|
const opts = this.requestOpts();
|
|
789
1369
|
if (!opts) {
|
|
790
1370
|
this.warnShutdownDrop(`track_partial ${eventId}`);
|
|
791
1371
|
if (!isPending) this.sticky.delete(eventId);
|
|
1372
|
+
if (mirror) await mirror;
|
|
792
1373
|
return;
|
|
793
1374
|
}
|
|
794
1375
|
const p = postJson(url, payload, this.requestHeaders(), opts);
|
|
795
|
-
|
|
1376
|
+
const combined = mirror ? Promise.all([mirror, p]).then(() => void 0) : p;
|
|
1377
|
+
this.inFlight.add(combined);
|
|
796
1378
|
try {
|
|
797
1379
|
try {
|
|
798
|
-
await
|
|
1380
|
+
await combined;
|
|
799
1381
|
if (this.debug) {
|
|
800
1382
|
console.log(`${this.prefix} sent track_partial ${eventId} (${eventName})`);
|
|
801
1383
|
}
|
|
@@ -807,7 +1389,7 @@ var EventShipper = class {
|
|
|
807
1389
|
);
|
|
808
1390
|
}
|
|
809
1391
|
} finally {
|
|
810
|
-
this.inFlight.delete(
|
|
1392
|
+
this.inFlight.delete(combined);
|
|
811
1393
|
}
|
|
812
1394
|
if (!isPending) {
|
|
813
1395
|
this.sticky.delete(eventId);
|
|
@@ -815,6 +1397,7 @@ var EventShipper = class {
|
|
|
815
1397
|
}
|
|
816
1398
|
};
|
|
817
1399
|
var MODEL_USAGE_ATTRIBUTES = {
|
|
1400
|
+
usageSource: "raindrop.usage.source",
|
|
818
1401
|
providerName: "gen_ai.provider.name",
|
|
819
1402
|
requestModel: "gen_ai.request.model",
|
|
820
1403
|
responseModel: "gen_ai.response.model",
|
|
@@ -823,6 +1406,7 @@ var MODEL_USAGE_ATTRIBUTES = {
|
|
|
823
1406
|
reasoningTokens: "gen_ai.usage.reasoning_tokens",
|
|
824
1407
|
cacheReadInputTokens: "gen_ai.usage.cache_read_input_tokens",
|
|
825
1408
|
cacheWriteInputTokens: "gen_ai.usage.cache_write_input_tokens",
|
|
1409
|
+
providerReportedCost: "gen_ai.usage.provider_reported_cost",
|
|
826
1410
|
nonCachedInputTokens: "raindrop.usage.input_tokens.non_cached",
|
|
827
1411
|
nonReasoningOutputTokens: "raindrop.usage.output_tokens.non_reasoning",
|
|
828
1412
|
totalOutputTokens: "raindrop.usage.output_tokens.total",
|
|
@@ -831,13 +1415,20 @@ var MODEL_USAGE_ATTRIBUTES = {
|
|
|
831
1415
|
cacheWriteTokens: "raindrop.usage.input_tokens.cache_write"
|
|
832
1416
|
};
|
|
833
1417
|
var MODEL_PROVIDER_NAMES = [
|
|
1418
|
+
["google.vertex.anthropic", "google-vertex"],
|
|
1419
|
+
["google.vertex_ai", "google-vertex"],
|
|
834
1420
|
["google.vertex", "google-vertex"],
|
|
1421
|
+
["gcp.vertex_ai", "google-vertex"],
|
|
1422
|
+
["gcp.gemini", "google"],
|
|
1423
|
+
["google_vertexai", "google-vertex"],
|
|
835
1424
|
["vertex.anthropic", "google-vertex"],
|
|
836
1425
|
["amazon-bedrock", "amazon-bedrock"],
|
|
1426
|
+
["aws.bedrock", "amazon-bedrock"],
|
|
837
1427
|
["bedrock", "amazon-bedrock"],
|
|
838
1428
|
["anthropic", "anthropic"],
|
|
839
1429
|
["openai", "openai"],
|
|
840
1430
|
["google", "google"],
|
|
1431
|
+
["az.ai.openai", "azure"],
|
|
841
1432
|
["azure", "azure"],
|
|
842
1433
|
["openrouter", "openrouter"]
|
|
843
1434
|
];
|
|
@@ -848,60 +1439,20 @@ function canonicalModelProvider(provider) {
|
|
|
848
1439
|
const match = MODEL_PROVIDER_NAMES.find(
|
|
849
1440
|
([family]) => normalizedProvider === family || normalizedProvider.startsWith(`${family}.`)
|
|
850
1441
|
);
|
|
851
|
-
return (_a = match == null ? void 0 : match[1]) != null ? _a :
|
|
1442
|
+
return (_a = match == null ? void 0 : match[1]) != null ? _a : normalizedProvider;
|
|
852
1443
|
}
|
|
853
1444
|
function tokenCount(value) {
|
|
854
1445
|
return typeof value === "number" && Number.isSafeInteger(value) && value >= 0 ? value : void 0;
|
|
855
1446
|
}
|
|
856
|
-
function
|
|
857
|
-
|
|
858
|
-
total,
|
|
859
|
-
parts,
|
|
860
|
-
semantics
|
|
861
|
-
}) {
|
|
862
|
-
if (explicit !== void 0) return explicit;
|
|
863
|
-
if (total === void 0) return void 0;
|
|
864
|
-
if (semantics === "exclusive") return total;
|
|
865
|
-
const observedParts = parts.filter((part) => part !== void 0 && part > 0);
|
|
866
|
-
if (semantics === void 0 && observedParts.length > 0) return void 0;
|
|
867
|
-
const exclusive = total - observedParts.reduce((sum, part) => sum + part, 0);
|
|
868
|
-
return exclusive >= 0 ? exclusive : void 0;
|
|
869
|
-
}
|
|
870
|
-
function buildModelUsageAttributes(usage) {
|
|
871
|
-
const inputTokens = tokenCount(usage.inputTokens);
|
|
872
|
-
const outputTokens = tokenCount(usage.outputTokens);
|
|
873
|
-
const explicitNonCachedInputTokens = tokenCount(usage.nonCachedInputTokens);
|
|
874
|
-
const explicitNonReasoningOutputTokens = tokenCount(usage.nonReasoningOutputTokens);
|
|
875
|
-
const reasoningTokens = tokenCount(usage.reasoningTokens);
|
|
876
|
-
const cacheReadInputTokens = tokenCount(usage.cacheReadInputTokens);
|
|
877
|
-
const cacheWriteInputTokens = tokenCount(usage.cacheWriteInputTokens);
|
|
878
|
-
const nonCachedInputTokens = exclusiveTokens({
|
|
879
|
-
explicit: explicitNonCachedInputTokens,
|
|
880
|
-
total: inputTokens,
|
|
881
|
-
parts: [cacheReadInputTokens, cacheWriteInputTokens],
|
|
882
|
-
semantics: usage.inputTokenSemantics
|
|
883
|
-
});
|
|
884
|
-
const nonReasoningOutputTokens = exclusiveTokens({
|
|
885
|
-
explicit: explicitNonReasoningOutputTokens,
|
|
886
|
-
total: outputTokens,
|
|
887
|
-
parts: [reasoningTokens],
|
|
888
|
-
semantics: usage.outputTokenSemantics
|
|
889
|
-
});
|
|
890
|
-
const exclusivePoolAttributes = nonCachedInputTokens !== void 0 && nonReasoningOutputTokens !== void 0 ? [
|
|
891
|
-
// backend consumes this complete raindrop.* set as one atomic billing-pool contract.
|
|
892
|
-
attrInt(MODEL_USAGE_ATTRIBUTES.nonCachedInputTokens, nonCachedInputTokens),
|
|
893
|
-
attrInt(MODEL_USAGE_ATTRIBUTES.nonReasoningOutputTokens, nonReasoningOutputTokens),
|
|
894
|
-
attrInt(MODEL_USAGE_ATTRIBUTES.reasoningOutputTokens, reasoningTokens),
|
|
895
|
-
attrInt(MODEL_USAGE_ATTRIBUTES.cacheReadTokens, cacheReadInputTokens),
|
|
896
|
-
attrInt(MODEL_USAGE_ATTRIBUTES.cacheWriteTokens, cacheWriteInputTokens)
|
|
897
|
-
] : [];
|
|
1447
|
+
function buildRawModelUsageAttributes(usage) {
|
|
1448
|
+
const providerReportedCost = typeof usage.providerReportedCost === "number" && Number.isFinite(usage.providerReportedCost) && usage.providerReportedCost >= 0 ? usage.providerReportedCost : void 0;
|
|
898
1449
|
return [
|
|
899
|
-
attrInt(MODEL_USAGE_ATTRIBUTES.inputTokens, inputTokens),
|
|
900
|
-
attrInt(MODEL_USAGE_ATTRIBUTES.outputTokens, outputTokens),
|
|
901
|
-
attrInt(MODEL_USAGE_ATTRIBUTES.reasoningTokens, reasoningTokens),
|
|
902
|
-
attrInt(MODEL_USAGE_ATTRIBUTES.cacheReadInputTokens, cacheReadInputTokens),
|
|
903
|
-
attrInt(MODEL_USAGE_ATTRIBUTES.cacheWriteInputTokens, cacheWriteInputTokens),
|
|
904
|
-
|
|
1450
|
+
attrInt(MODEL_USAGE_ATTRIBUTES.inputTokens, tokenCount(usage.inputTokens)),
|
|
1451
|
+
attrInt(MODEL_USAGE_ATTRIBUTES.outputTokens, tokenCount(usage.outputTokens)),
|
|
1452
|
+
attrInt(MODEL_USAGE_ATTRIBUTES.reasoningTokens, tokenCount(usage.reasoningTokens)),
|
|
1453
|
+
attrInt(MODEL_USAGE_ATTRIBUTES.cacheReadInputTokens, tokenCount(usage.cacheReadInputTokens)),
|
|
1454
|
+
attrInt(MODEL_USAGE_ATTRIBUTES.cacheWriteInputTokens, tokenCount(usage.cacheWriteInputTokens)),
|
|
1455
|
+
attrDouble(MODEL_USAGE_ATTRIBUTES.providerReportedCost, providerReportedCost)
|
|
905
1456
|
].filter((attribute) => attribute !== void 0);
|
|
906
1457
|
}
|
|
907
1458
|
var STRING_ALIASES = {
|
|
@@ -1091,6 +1642,13 @@ function redactJsonAttributeValue(key, value) {
|
|
|
1091
1642
|
if (scrubbedJson === json) return void 0;
|
|
1092
1643
|
return { stringValue: scrubbedJson };
|
|
1093
1644
|
}
|
|
1645
|
+
function appGitOwnerId2(prefix) {
|
|
1646
|
+
try {
|
|
1647
|
+
return `${prefix}:${randomUUID()}`;
|
|
1648
|
+
} catch (e) {
|
|
1649
|
+
return `${prefix}:${Date.now().toString(36)}:${Math.random().toString(36).slice(2)}`;
|
|
1650
|
+
}
|
|
1651
|
+
}
|
|
1094
1652
|
function identityAttrs(args) {
|
|
1095
1653
|
return [
|
|
1096
1654
|
attrString("ai.telemetry.metadata.raindrop.ai.userId", args.userId),
|
|
@@ -1113,23 +1671,30 @@ function applyOtelSpanAttributeLimit(limit) {
|
|
|
1113
1671
|
}
|
|
1114
1672
|
var TraceShipper = class {
|
|
1115
1673
|
constructor(opts) {
|
|
1674
|
+
this.appGitOwner = appGitOwnerId2("trace");
|
|
1675
|
+
this.appGitEventIds = /* @__PURE__ */ new WeakMap();
|
|
1676
|
+
this.appGitActiveSpans = /* @__PURE__ */ new Map();
|
|
1677
|
+
this.appGitCaptured = /* @__PURE__ */ new WeakSet();
|
|
1678
|
+
this.appGitAdded = /* @__PURE__ */ new WeakMap();
|
|
1116
1679
|
this.queue = [];
|
|
1117
1680
|
this.inFlight = /* @__PURE__ */ new Set();
|
|
1118
1681
|
this.hasShutdown = false;
|
|
1119
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _i;
|
|
1120
|
-
this.
|
|
1121
|
-
this.
|
|
1682
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j;
|
|
1683
|
+
this.appGitContext = (_a = opts.appGitContext) != null ? _a : createAppGitContext(opts.appGit);
|
|
1684
|
+
this.ownsAppGitContext = opts.appGitContext === void 0;
|
|
1685
|
+
this.writeKey = (_b = opts.writeKey) == null ? void 0 : _b.trim();
|
|
1686
|
+
this.baseUrl = (_c = formatEndpoint(opts.endpoint)) != null ? _c : "https://api.raindrop.ai/v1/";
|
|
1122
1687
|
this.enabled = opts.enabled !== false;
|
|
1123
1688
|
this.debug = opts.debug;
|
|
1124
1689
|
this.debugSpans = opts.debugSpans === true;
|
|
1125
|
-
this.flushIntervalMs = (
|
|
1126
|
-
this.maxBatchSize = (
|
|
1127
|
-
this.maxQueueSize = (
|
|
1128
|
-
this.sdkName = (
|
|
1690
|
+
this.flushIntervalMs = (_d = opts.flushIntervalMs) != null ? _d : 1e3;
|
|
1691
|
+
this.maxBatchSize = (_e = opts.maxBatchSize) != null ? _e : 50;
|
|
1692
|
+
this.maxQueueSize = (_f = opts.maxQueueSize) != null ? _f : 5e3;
|
|
1693
|
+
this.sdkName = (_g = opts.sdkName) != null ? _g : "core";
|
|
1129
1694
|
this.prefix = `[raindrop-ai/${this.sdkName}]`;
|
|
1130
|
-
this.serviceName = (
|
|
1131
|
-
this.serviceVersion = (
|
|
1132
|
-
this.localDebuggerUrl = (
|
|
1695
|
+
this.serviceName = (_h = opts.serviceName) != null ? _h : "raindrop.core";
|
|
1696
|
+
this.serviceVersion = (_i = opts.serviceVersion) != null ? _i : "0.0.0";
|
|
1697
|
+
this.localDebuggerUrl = (_j = resolveLocalDebuggerBaseUrl(opts.localDebuggerUrl)) != null ? _j : void 0;
|
|
1133
1698
|
if (this.debug && this.localDebuggerUrl) {
|
|
1134
1699
|
console.log(`${this.prefix} Local debugger mirroring: ${this.localDebuggerUrl}`);
|
|
1135
1700
|
}
|
|
@@ -1193,7 +1758,10 @@ var TraceShipper = class {
|
|
|
1193
1758
|
try {
|
|
1194
1759
|
const result = this.transformSpanHook(current);
|
|
1195
1760
|
if (result === null) return null;
|
|
1196
|
-
if (result !== void 0)
|
|
1761
|
+
if (result !== void 0) {
|
|
1762
|
+
copyReplayTraceDestination(current, result);
|
|
1763
|
+
current = result;
|
|
1764
|
+
}
|
|
1197
1765
|
} catch (err) {
|
|
1198
1766
|
if (this.debug) {
|
|
1199
1767
|
const msg = err instanceof Error ? err.message : String(err);
|
|
@@ -1203,13 +1771,19 @@ var TraceShipper = class {
|
|
|
1203
1771
|
}
|
|
1204
1772
|
}
|
|
1205
1773
|
try {
|
|
1206
|
-
|
|
1774
|
+
const normalized = normalizeModelUsageSpan(current);
|
|
1775
|
+
copyReplayTraceDestination(current, normalized);
|
|
1776
|
+
current = normalized;
|
|
1207
1777
|
} catch (e) {
|
|
1208
1778
|
}
|
|
1209
1779
|
if (!this.disableDefaultRedaction) {
|
|
1210
|
-
|
|
1780
|
+
const redacted = defaultTransformSpan(current);
|
|
1781
|
+
copyReplayTraceDestination(current, redacted);
|
|
1782
|
+
current = redacted;
|
|
1211
1783
|
}
|
|
1212
|
-
|
|
1784
|
+
const capped = this.capSpanAttributes(current);
|
|
1785
|
+
copyReplayTraceDestination(current, capped);
|
|
1786
|
+
return capped;
|
|
1213
1787
|
}
|
|
1214
1788
|
isDebugEnabled() {
|
|
1215
1789
|
return this.debug;
|
|
@@ -1221,46 +1795,84 @@ var TraceShipper = class {
|
|
|
1221
1795
|
return { ...this.authHeaders(), ...projectIdHeaders(this.projectId) };
|
|
1222
1796
|
}
|
|
1223
1797
|
startSpan(args) {
|
|
1224
|
-
var _a, _b;
|
|
1798
|
+
var _a, _b, _c;
|
|
1225
1799
|
const ids = createSpanIds(args.parent);
|
|
1226
1800
|
const started = (_a = args.startTimeUnixNano) != null ? _a : nowUnixNanoString();
|
|
1227
1801
|
const attrs = [
|
|
1228
1802
|
attrString("ai.telemetry.metadata.raindrop.eventId", args.eventId),
|
|
1229
1803
|
...identityAttrs(args),
|
|
1230
|
-
attrString("ai.operationId", args.operationId)
|
|
1804
|
+
attrString("ai.operationId", args.operationId),
|
|
1805
|
+
...Object.entries(evalScopeAttributes()).map(([key, value]) => attrString(key, value))
|
|
1231
1806
|
];
|
|
1232
1807
|
if ((_b = args.attributes) == null ? void 0 : _b.length) attrs.push(...args.attributes);
|
|
1233
|
-
const
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
);
|
|
1808
|
+
const tracksAppGit = this.appGitActiveSpans.has(args.eventId) || this.appGitActiveSpans.size < 1e4;
|
|
1809
|
+
const appGitOverrides = appGitPropertiesFromAttributes(attrs);
|
|
1810
|
+
const span = {
|
|
1811
|
+
ids,
|
|
1812
|
+
name: args.name,
|
|
1813
|
+
startTimeUnixNano: started,
|
|
1814
|
+
attributes: withAppGitAttributes(
|
|
1815
|
+
attrs,
|
|
1816
|
+
this.appGitContext.forOperation(args.eventId, appGitOverrides, this.appGitOwner)
|
|
1817
|
+
)
|
|
1818
|
+
};
|
|
1819
|
+
rememberReplayTraceDestination(span);
|
|
1820
|
+
this.appGitCaptured.add(span);
|
|
1821
|
+
this.appGitEventIds.set(span, args.eventId);
|
|
1822
|
+
if (tracksAppGit) {
|
|
1823
|
+
this.appGitActiveSpans.set(args.eventId, ((_c = this.appGitActiveSpans.get(args.eventId)) != null ? _c : 0) + 1);
|
|
1824
|
+
}
|
|
1825
|
+
this.appGitAdded.set(span, new Set(span.attributes.filter((attr) => !attrs.includes(attr))));
|
|
1826
|
+
const openSpan = buildOtlpSpan({
|
|
1827
|
+
ids: span.ids,
|
|
1828
|
+
name: span.name,
|
|
1829
|
+
startTimeUnixNano: span.startTimeUnixNano,
|
|
1830
|
+
endTimeUnixNano: span.startTimeUnixNano,
|
|
1831
|
+
// placeholder — will be updated on endSpan
|
|
1832
|
+
attributes: span.attributes,
|
|
1833
|
+
status: { code: SpanStatusCode.UNSET }
|
|
1834
|
+
});
|
|
1835
|
+
copyReplayTraceDestination(span, openSpan);
|
|
1836
|
+
this.mirrorToLocalDebugger(openSpan);
|
|
1245
1837
|
return span;
|
|
1246
1838
|
}
|
|
1247
|
-
mirrorToLocalDebugger(span) {
|
|
1248
|
-
|
|
1839
|
+
mirrorToLocalDebugger(span, completed = false) {
|
|
1840
|
+
const destination = replayTraceDestinationFor(span);
|
|
1841
|
+
if (destination && destination.kind !== "workshop") return;
|
|
1842
|
+
const localDebuggerUrl = (destination == null ? void 0 : destination.kind) === "workshop" ? destination.url : this.localDebuggerUrl;
|
|
1843
|
+
if (!localDebuggerUrl) return;
|
|
1249
1844
|
const redacted = this.redactSpan(span);
|
|
1250
1845
|
if (redacted === null) return;
|
|
1846
|
+
if (completed && (destination == null ? void 0 : destination.kind) === "workshop") {
|
|
1847
|
+
recordReplayExportedSpan(
|
|
1848
|
+
destination,
|
|
1849
|
+
base64ToHex(redacted.spanId),
|
|
1850
|
+
base64ToHex(redacted.traceId)
|
|
1851
|
+
);
|
|
1852
|
+
}
|
|
1251
1853
|
const body = buildExportTraceServiceRequest([redacted], this.serviceName, this.serviceVersion);
|
|
1252
|
-
mirrorTraceExportToLocalDebugger(body, {
|
|
1253
|
-
baseUrl:
|
|
1854
|
+
const p = mirrorTraceExportToLocalDebugger(body, {
|
|
1855
|
+
baseUrl: localDebuggerUrl,
|
|
1254
1856
|
debug: false,
|
|
1255
1857
|
sdkName: this.sdkName
|
|
1256
1858
|
});
|
|
1859
|
+
this.inFlight.add(p);
|
|
1860
|
+
void p.finally(() => {
|
|
1861
|
+
this.inFlight.delete(p);
|
|
1862
|
+
});
|
|
1257
1863
|
}
|
|
1258
1864
|
endSpan(span, extra) {
|
|
1259
|
-
var _a, _b;
|
|
1865
|
+
var _a, _b, _c;
|
|
1260
1866
|
if (span.endTimeUnixNano) return;
|
|
1261
1867
|
span.endTimeUnixNano = (_a = extra == null ? void 0 : extra.endTimeUnixNano) != null ? _a : nowUnixNanoString();
|
|
1262
1868
|
if ((_b = extra == null ? void 0 : extra.attributes) == null ? void 0 : _b.length) {
|
|
1869
|
+
const overrides = appGitPropertiesFromAttributes(extra.attributes);
|
|
1870
|
+
const eventId2 = this.appGitEventIds.get(span);
|
|
1871
|
+
const snapshot = eventId2 ? this.appGitContext.forOperation(eventId2, overrides, this.appGitOwner) : overrides;
|
|
1872
|
+
const added = this.appGitAdded.get(span);
|
|
1873
|
+
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));
|
|
1263
1874
|
span.attributes.push(...extra.attributes);
|
|
1875
|
+
span.attributes = withAppGitAttributes(span.attributes, snapshot);
|
|
1264
1876
|
}
|
|
1265
1877
|
let status = extra == null ? void 0 : extra.status;
|
|
1266
1878
|
if (!status && (extra == null ? void 0 : extra.error) !== void 0) {
|
|
@@ -1275,30 +1887,65 @@ var TraceShipper = class {
|
|
|
1275
1887
|
attributes: span.attributes,
|
|
1276
1888
|
status
|
|
1277
1889
|
});
|
|
1890
|
+
copyReplayTraceDestination(span, otlp);
|
|
1891
|
+
this.appGitCaptured.add(otlp);
|
|
1278
1892
|
this.enqueue(otlp);
|
|
1279
|
-
this.mirrorToLocalDebugger(otlp);
|
|
1893
|
+
this.mirrorToLocalDebugger(otlp, true);
|
|
1894
|
+
const eventId = this.appGitEventIds.get(span);
|
|
1895
|
+
if (eventId && this.appGitActiveSpans.has(eventId)) {
|
|
1896
|
+
const remaining = ((_c = this.appGitActiveSpans.get(eventId)) != null ? _c : 1) - 1;
|
|
1897
|
+
if (remaining > 0) this.appGitActiveSpans.set(eventId, remaining);
|
|
1898
|
+
else {
|
|
1899
|
+
this.appGitActiveSpans.delete(eventId);
|
|
1900
|
+
if (this.appGitContext.releaseOperation) this.appGitContext.releaseOperation(eventId, this.appGitOwner);
|
|
1901
|
+
else if (this.ownsAppGitContext) this.appGitContext.finishOperation(eventId);
|
|
1902
|
+
}
|
|
1903
|
+
}
|
|
1280
1904
|
}
|
|
1281
1905
|
createSpan(args) {
|
|
1282
1906
|
var _a;
|
|
1283
1907
|
const ids = createSpanIds(args.parent);
|
|
1284
1908
|
const attrs = [
|
|
1285
1909
|
attrString("ai.telemetry.metadata.raindrop.eventId", args.eventId),
|
|
1286
|
-
...identityAttrs(args)
|
|
1910
|
+
...identityAttrs(args),
|
|
1911
|
+
...Object.entries(evalScopeAttributes()).map(([key, value]) => attrString(key, value))
|
|
1287
1912
|
];
|
|
1288
1913
|
if ((_a = args.attributes) == null ? void 0 : _a.length) attrs.push(...args.attributes);
|
|
1914
|
+
const tracksAppGit = !this.appGitActiveSpans.has(args.eventId);
|
|
1289
1915
|
const otlp = buildOtlpSpan({
|
|
1290
1916
|
ids,
|
|
1291
1917
|
name: args.name,
|
|
1292
1918
|
startTimeUnixNano: args.startTimeUnixNano,
|
|
1293
1919
|
endTimeUnixNano: args.endTimeUnixNano,
|
|
1294
|
-
attributes:
|
|
1920
|
+
attributes: withAppGitAttributes(
|
|
1921
|
+
attrs,
|
|
1922
|
+
this.appGitContext.forOperation(
|
|
1923
|
+
args.eventId,
|
|
1924
|
+
appGitPropertiesFromAttributes(attrs),
|
|
1925
|
+
this.appGitOwner
|
|
1926
|
+
)
|
|
1927
|
+
),
|
|
1295
1928
|
status: args.status
|
|
1296
1929
|
});
|
|
1930
|
+
rememberReplayTraceDestination(otlp);
|
|
1931
|
+
this.appGitCaptured.add(otlp);
|
|
1932
|
+
if (tracksAppGit) {
|
|
1933
|
+
if (this.appGitContext.releaseOperation) this.appGitContext.releaseOperation(args.eventId, this.appGitOwner);
|
|
1934
|
+
else if (this.ownsAppGitContext) this.appGitContext.finishOperation(args.eventId);
|
|
1935
|
+
}
|
|
1297
1936
|
this.enqueue(otlp);
|
|
1298
|
-
this.mirrorToLocalDebugger(otlp);
|
|
1937
|
+
this.mirrorToLocalDebugger(otlp, true);
|
|
1299
1938
|
}
|
|
1300
1939
|
enqueue(span) {
|
|
1940
|
+
var _a;
|
|
1301
1941
|
if (!this.enabled) return;
|
|
1942
|
+
const attributes = (_a = span.attributes) != null ? _a : [];
|
|
1943
|
+
const enriched = this.appGitCaptured.has(span) ? attributes : withAppGitAttributes(attributes, this.appGitContext.snapshot(appGitPropertiesFromAttributes(attributes)));
|
|
1944
|
+
if (enriched !== attributes) {
|
|
1945
|
+
const original = span;
|
|
1946
|
+
span = { ...span, attributes: enriched.filter((attr) => attr !== void 0) };
|
|
1947
|
+
copyReplayTraceDestination(original, span);
|
|
1948
|
+
}
|
|
1302
1949
|
if (this.debugSpans) {
|
|
1303
1950
|
const short = (s) => s ? s.slice(-8) : "none";
|
|
1304
1951
|
console.log(
|
|
@@ -1309,6 +1956,13 @@ var TraceShipper = class {
|
|
|
1309
1956
|
}
|
|
1310
1957
|
const redacted = this.redactSpan(span);
|
|
1311
1958
|
if (redacted === null) return;
|
|
1959
|
+
const destination = replayTraceDestinationFor(redacted);
|
|
1960
|
+
recordReplayExportedSpan(
|
|
1961
|
+
destination,
|
|
1962
|
+
base64ToHex(redacted.spanId),
|
|
1963
|
+
base64ToHex(redacted.traceId)
|
|
1964
|
+
);
|
|
1965
|
+
if ((destination == null ? void 0 : destination.kind) === "workshop") return;
|
|
1312
1966
|
if (this.queue.length >= this.maxQueueSize) {
|
|
1313
1967
|
this.queue.shift();
|
|
1314
1968
|
}
|
|
@@ -1327,47 +1981,67 @@ var TraceShipper = class {
|
|
|
1327
1981
|
}
|
|
1328
1982
|
}
|
|
1329
1983
|
async flush() {
|
|
1330
|
-
|
|
1984
|
+
var _a;
|
|
1985
|
+
if (!this.enabled) {
|
|
1986
|
+
await Promise.all([...this.inFlight].map((p) => p.catch(() => {
|
|
1987
|
+
})));
|
|
1988
|
+
return;
|
|
1989
|
+
}
|
|
1331
1990
|
if (this.timer) {
|
|
1332
1991
|
clearTimeout(this.timer);
|
|
1333
1992
|
this.timer = void 0;
|
|
1334
1993
|
}
|
|
1335
1994
|
while (this.queue.length > 0) {
|
|
1336
1995
|
const batch = this.queue.splice(0, this.maxBatchSize);
|
|
1337
|
-
|
|
1338
|
-
const
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
|
|
1342
|
-
|
|
1343
|
-
`${this.prefix} shutdown flush deadline exceeded; dropping ${batch.length} spans`
|
|
1344
|
-
)
|
|
1345
|
-
);
|
|
1346
|
-
continue;
|
|
1347
|
-
}
|
|
1348
|
-
const body = buildExportTraceServiceRequest(batch, this.serviceName, this.serviceVersion);
|
|
1349
|
-
const url = `${this.baseUrl}traces`;
|
|
1350
|
-
if (this.debug) {
|
|
1351
|
-
console.log(`${this.prefix} sending traces batch`, {
|
|
1352
|
-
spans: batch.length,
|
|
1353
|
-
endpoint: url
|
|
1354
|
-
});
|
|
1996
|
+
const groups = /* @__PURE__ */ new Map();
|
|
1997
|
+
for (const span of batch) {
|
|
1998
|
+
const destination = replayTraceDestinationFor(span);
|
|
1999
|
+
const spans = groups.get(destination);
|
|
2000
|
+
if (spans) spans.push(span);
|
|
2001
|
+
else groups.set(destination, [span]);
|
|
1355
2002
|
}
|
|
1356
|
-
const
|
|
1357
|
-
|
|
1358
|
-
|
|
1359
|
-
|
|
1360
|
-
|
|
1361
|
-
if (this.debug) console.log(`${this.prefix} sent ${batch.length} spans`);
|
|
1362
|
-
} catch (err) {
|
|
1363
|
-
const msg = err instanceof Error ? err.message : String(err);
|
|
2003
|
+
for (const [destination, spans] of groups) {
|
|
2004
|
+
if (!destination && !this.writeKey) continue;
|
|
2005
|
+
if ((destination == null ? void 0 : destination.kind) === "workshop") continue;
|
|
2006
|
+
const opts = this.requestOpts();
|
|
2007
|
+
if (!opts) {
|
|
1364
2008
|
rateLimitedLog(
|
|
1365
|
-
`${this.prefix}.
|
|
1366
|
-
() => console.warn(
|
|
2009
|
+
`${this.prefix}.shutdown_deadline`,
|
|
2010
|
+
() => console.warn(
|
|
2011
|
+
`${this.prefix} shutdown flush deadline exceeded; dropping ${spans.length} spans`
|
|
2012
|
+
)
|
|
1367
2013
|
);
|
|
2014
|
+
continue;
|
|
2015
|
+
}
|
|
2016
|
+
const body = buildExportTraceServiceRequest(spans, this.serviceName, this.serviceVersion);
|
|
2017
|
+
const url = destination ? replayTraceUrl(destination.url) : `${this.baseUrl}traces`;
|
|
2018
|
+
const headers = destination ? {
|
|
2019
|
+
Authorization: `Bearer ${destination.apiKey}`,
|
|
2020
|
+
"X-Raindrop-Replay-Id": destination.replayId,
|
|
2021
|
+
"X-Raindrop-Project-Id": (_a = destination.projectId) != null ? _a : "default"
|
|
2022
|
+
} : this.requestHeaders();
|
|
2023
|
+
if (this.debug) {
|
|
2024
|
+
console.log(`${this.prefix} sending traces batch`, {
|
|
2025
|
+
spans: spans.length,
|
|
2026
|
+
endpoint: url
|
|
2027
|
+
});
|
|
2028
|
+
}
|
|
2029
|
+
const p = postJson(url, body, headers, opts);
|
|
2030
|
+
this.inFlight.add(p);
|
|
2031
|
+
try {
|
|
2032
|
+
try {
|
|
2033
|
+
await p;
|
|
2034
|
+
if (this.debug) console.log(`${this.prefix} sent ${spans.length} spans`);
|
|
2035
|
+
} catch (err) {
|
|
2036
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
2037
|
+
rateLimitedLog(
|
|
2038
|
+
`${this.prefix}.send_spans_failed`,
|
|
2039
|
+
() => console.warn(`${this.prefix} failed to send ${spans.length} spans: ${msg}`)
|
|
2040
|
+
);
|
|
2041
|
+
}
|
|
2042
|
+
} finally {
|
|
2043
|
+
this.inFlight.delete(p);
|
|
1368
2044
|
}
|
|
1369
|
-
} finally {
|
|
1370
|
-
this.inFlight.delete(p);
|
|
1371
2045
|
}
|
|
1372
2046
|
}
|
|
1373
2047
|
}
|
|
@@ -1410,17 +2084,165 @@ var TraceShipper = class {
|
|
|
1410
2084
|
if (!settled) {
|
|
1411
2085
|
rateLimitedLog(
|
|
1412
2086
|
`${this.prefix}.shutdown_deadline`,
|
|
1413
|
-
() => console.warn(
|
|
2087
|
+
() => console.warn(
|
|
2088
|
+
`${this.prefix} shutdown flush deadline exceeded; abandoning in-flight spans`
|
|
2089
|
+
)
|
|
1414
2090
|
);
|
|
1415
2091
|
}
|
|
1416
2092
|
} finally {
|
|
1417
2093
|
this.shutdownDeadlineAt = void 0;
|
|
2094
|
+
if (this.ownsAppGitContext) this.appGitContext.dispose();
|
|
1418
2095
|
}
|
|
1419
2096
|
}
|
|
1420
2097
|
};
|
|
1421
2098
|
|
|
1422
2099
|
// ../core/dist/index.node.js
|
|
1423
2100
|
var import_async_hooks = require("async_hooks");
|
|
2101
|
+
var import_child_process = require("child_process");
|
|
2102
|
+
var import_path = require("path");
|
|
2103
|
+
var resolveLocal = (sourceDirectory, detectBranch, completed) => {
|
|
2104
|
+
const cwd = sourceDirectory ? (0, import_path.resolve)(sourceDirectory) : process.cwd();
|
|
2105
|
+
let cancelled = false;
|
|
2106
|
+
let active;
|
|
2107
|
+
let deadlineTimer;
|
|
2108
|
+
const deadline = Date.now() + 1e3;
|
|
2109
|
+
const run = (args, done) => {
|
|
2110
|
+
if (cancelled) return;
|
|
2111
|
+
const remaining = deadline - Date.now();
|
|
2112
|
+
if (remaining <= 0) {
|
|
2113
|
+
done(void 0);
|
|
2114
|
+
return;
|
|
2115
|
+
}
|
|
2116
|
+
try {
|
|
2117
|
+
active = (0, import_child_process.execFile)(
|
|
2118
|
+
"git",
|
|
2119
|
+
args,
|
|
2120
|
+
{
|
|
2121
|
+
cwd,
|
|
2122
|
+
encoding: "utf8",
|
|
2123
|
+
maxBuffer: 4096,
|
|
2124
|
+
windowsHide: true,
|
|
2125
|
+
env: {
|
|
2126
|
+
...process.env,
|
|
2127
|
+
// The selected application cwd, not the invoking shell's Git plumbing, owns identity.
|
|
2128
|
+
GIT_DIR: void 0,
|
|
2129
|
+
GIT_WORK_TREE: void 0,
|
|
2130
|
+
GIT_COMMON_DIR: void 0,
|
|
2131
|
+
GIT_NAMESPACE: void 0,
|
|
2132
|
+
GIT_INDEX_FILE: void 0,
|
|
2133
|
+
GIT_OBJECT_DIRECTORY: void 0,
|
|
2134
|
+
GIT_ALTERNATE_OBJECT_DIRECTORIES: void 0,
|
|
2135
|
+
GIT_CONFIG_PARAMETERS: void 0,
|
|
2136
|
+
GIT_CONFIG_COUNT: "0",
|
|
2137
|
+
GIT_TERMINAL_PROMPT: "0",
|
|
2138
|
+
GIT_OPTIONAL_LOCKS: "0"
|
|
2139
|
+
}
|
|
2140
|
+
},
|
|
2141
|
+
(error, stdout) => {
|
|
2142
|
+
clearTimeout(deadlineTimer);
|
|
2143
|
+
deadlineTimer = void 0;
|
|
2144
|
+
active = void 0;
|
|
2145
|
+
if (!cancelled) {
|
|
2146
|
+
try {
|
|
2147
|
+
done(error ? void 0 : stdout.trim());
|
|
2148
|
+
} catch (e) {
|
|
2149
|
+
}
|
|
2150
|
+
}
|
|
2151
|
+
}
|
|
2152
|
+
);
|
|
2153
|
+
active.unref();
|
|
2154
|
+
if (active.stdout && "unref" in active.stdout && typeof active.stdout.unref === "function")
|
|
2155
|
+
active.stdout.unref();
|
|
2156
|
+
if (active.stderr && "unref" in active.stderr && typeof active.stderr.unref === "function")
|
|
2157
|
+
active.stderr.unref();
|
|
2158
|
+
deadlineTimer = setTimeout(() => {
|
|
2159
|
+
try {
|
|
2160
|
+
active == null ? void 0 : active.kill("SIGKILL");
|
|
2161
|
+
} catch (e) {
|
|
2162
|
+
}
|
|
2163
|
+
}, remaining);
|
|
2164
|
+
deadlineTimer.unref();
|
|
2165
|
+
} catch (e) {
|
|
2166
|
+
try {
|
|
2167
|
+
done(void 0);
|
|
2168
|
+
} catch (e2) {
|
|
2169
|
+
}
|
|
2170
|
+
}
|
|
2171
|
+
};
|
|
2172
|
+
const scheduled = setTimeout(() => {
|
|
2173
|
+
try {
|
|
2174
|
+
run(["rev-parse", "HEAD"], (rawSha) => {
|
|
2175
|
+
const commitSha = validAppCommitSha(rawSha);
|
|
2176
|
+
if (!commitSha) {
|
|
2177
|
+
completed({});
|
|
2178
|
+
return;
|
|
2179
|
+
}
|
|
2180
|
+
run(["-c", "core.fsmonitor=false", "status", "--porcelain"], (status) => {
|
|
2181
|
+
const finish = (branch) => {
|
|
2182
|
+
run(["rev-parse", "HEAD"], (finalSha) => {
|
|
2183
|
+
const coherent = validAppCommitSha(finalSha) === commitSha;
|
|
2184
|
+
completed({
|
|
2185
|
+
commitSha,
|
|
2186
|
+
...coherent && status !== void 0 ? { commitDirty: status !== "" } : {},
|
|
2187
|
+
...coherent && branch && branch !== "HEAD" ? { branch } : {}
|
|
2188
|
+
});
|
|
2189
|
+
});
|
|
2190
|
+
};
|
|
2191
|
+
if (detectBranch) run(["symbolic-ref", "--quiet", "--short", "HEAD"], finish);
|
|
2192
|
+
else finish();
|
|
2193
|
+
});
|
|
2194
|
+
});
|
|
2195
|
+
} catch (e) {
|
|
2196
|
+
completed({});
|
|
2197
|
+
}
|
|
2198
|
+
}, 0);
|
|
2199
|
+
scheduled.unref();
|
|
2200
|
+
return () => {
|
|
2201
|
+
cancelled = true;
|
|
2202
|
+
clearTimeout(scheduled);
|
|
2203
|
+
clearTimeout(deadlineTimer);
|
|
2204
|
+
try {
|
|
2205
|
+
active == null ? void 0 : active.kill("SIGKILL");
|
|
2206
|
+
} catch (e) {
|
|
2207
|
+
}
|
|
2208
|
+
};
|
|
2209
|
+
};
|
|
2210
|
+
function createAppGitContext2(options, runtime = {}) {
|
|
2211
|
+
return new AppGitContext(options, { ...runtime, resolveLocal });
|
|
2212
|
+
}
|
|
2213
|
+
function hasDestination(options) {
|
|
2214
|
+
var _a;
|
|
2215
|
+
if (options.enabled === false) return false;
|
|
2216
|
+
return Boolean(((_a = options.writeKey) == null ? void 0 : _a.trim()) || resolveLocalDebuggerBaseUrl(options.localDebuggerUrl));
|
|
2217
|
+
}
|
|
2218
|
+
var EventShipper2 = class extends EventShipper {
|
|
2219
|
+
constructor(options) {
|
|
2220
|
+
var _a;
|
|
2221
|
+
const ownsAppGitContext = options.appGitContext === void 0;
|
|
2222
|
+
const appGitContext = (_a = options.appGitContext) != null ? _a : createAppGitContext2(options.appGit, { allowDiscovery: hasDestination(options) });
|
|
2223
|
+
try {
|
|
2224
|
+
super({ ...options, appGitContext });
|
|
2225
|
+
} catch (error) {
|
|
2226
|
+
if (ownsAppGitContext) appGitContext.dispose();
|
|
2227
|
+
throw error;
|
|
2228
|
+
}
|
|
2229
|
+
if (ownsAppGitContext) this.ownAppGitContextForShutdown();
|
|
2230
|
+
}
|
|
2231
|
+
};
|
|
2232
|
+
var TraceShipper2 = class extends TraceShipper {
|
|
2233
|
+
constructor(options) {
|
|
2234
|
+
var _a;
|
|
2235
|
+
const ownsAppGitContext = options.appGitContext === void 0;
|
|
2236
|
+
const appGitContext = (_a = options.appGitContext) != null ? _a : createAppGitContext2(options.appGit, { allowDiscovery: hasDestination(options) });
|
|
2237
|
+
try {
|
|
2238
|
+
super({ ...options, appGitContext });
|
|
2239
|
+
} catch (error) {
|
|
2240
|
+
if (ownsAppGitContext) appGitContext.dispose();
|
|
2241
|
+
throw error;
|
|
2242
|
+
}
|
|
2243
|
+
this.ownsAppGitContext = ownsAppGitContext;
|
|
2244
|
+
}
|
|
2245
|
+
};
|
|
1424
2246
|
globalThis.RAINDROP_ASYNC_LOCAL_STORAGE = import_async_hooks.AsyncLocalStorage;
|
|
1425
2247
|
var SUPPRESS_TRACING_KEY = /* @__PURE__ */ Symbol.for(
|
|
1426
2248
|
"OpenTelemetry SDK Context Key SUPPRESS_TRACING"
|
|
@@ -1485,7 +2307,20 @@ function loadConfig(projectDirectory) {
|
|
|
1485
2307
|
debug: process.env["RAINDROP_DEBUG"] === "true" ? true : (_g = merged.debug) != null ? _g : false,
|
|
1486
2308
|
captureSystemPrompt: process.env["RAINDROP_CAPTURE_SYSTEM_PROMPT"] !== void 0 ? process.env["RAINDROP_CAPTURE_SYSTEM_PROMPT"] === "true" : (_h = merged.capture_system_prompt) != null ? _h : false,
|
|
1487
2309
|
eventMetadata,
|
|
1488
|
-
localWorkshopUrl: resolveLocalWorkshopUrl(merged.local_workshop_url)
|
|
2310
|
+
localWorkshopUrl: resolveLocalWorkshopUrl(merged.local_workshop_url),
|
|
2311
|
+
appGit: mapAppGit(merged.app_git)
|
|
2312
|
+
};
|
|
2313
|
+
}
|
|
2314
|
+
function mapAppGit(value) {
|
|
2315
|
+
if (value === false) return false;
|
|
2316
|
+
if (value === null || typeof value !== "object" || Array.isArray(value)) return void 0;
|
|
2317
|
+
return {
|
|
2318
|
+
commitSha: "commit_sha" in value && (typeof value.commit_sha === "string" || value.commit_sha === null) ? value.commit_sha : void 0,
|
|
2319
|
+
commitDirty: "commit_dirty" in value && (typeof value.commit_dirty === "boolean" || value.commit_dirty === null) ? value.commit_dirty : void 0,
|
|
2320
|
+
branch: "branch" in value && (typeof value.branch === "string" || value.branch === null) ? value.branch : void 0,
|
|
2321
|
+
detectBranch: "detect_branch" in value && typeof value.detect_branch === "boolean" ? value.detect_branch : void 0,
|
|
2322
|
+
sourceDirectory: "source_directory" in value && typeof value.source_directory === "string" ? value.source_directory : void 0,
|
|
2323
|
+
autoDetect: "auto_detect" in value && typeof value.auto_detect === "boolean" ? value.auto_detect : void 0
|
|
1489
2324
|
};
|
|
1490
2325
|
}
|
|
1491
2326
|
function resolveLocalWorkshopUrl(fileValue) {
|
|
@@ -1502,7 +2337,7 @@ function resolveLocalWorkshopUrl(fileValue) {
|
|
|
1502
2337
|
// package.json
|
|
1503
2338
|
var package_default = {
|
|
1504
2339
|
name: "@raindrop-ai/opencode-plugin",
|
|
1505
|
-
version: "0.1.
|
|
2340
|
+
version: "0.1.4",
|
|
1506
2341
|
description: "Raindrop observability plugin for OpenCode \u2014 automatic session/event/span tracing",
|
|
1507
2342
|
type: "module",
|
|
1508
2343
|
main: "dist/index.js",
|
|
@@ -1573,7 +2408,7 @@ var PLUGIN_NAME = package_default.name;
|
|
|
1573
2408
|
var PLUGIN_VERSION = package_default.version;
|
|
1574
2409
|
|
|
1575
2410
|
// src/shipper.ts
|
|
1576
|
-
var
|
|
2411
|
+
var EventShipper3 = class extends EventShipper2 {
|
|
1577
2412
|
constructor(opts) {
|
|
1578
2413
|
var _a, _b, _c, _d;
|
|
1579
2414
|
super({
|
|
@@ -1585,7 +2420,7 @@ var EventShipper2 = class extends EventShipper {
|
|
|
1585
2420
|
});
|
|
1586
2421
|
}
|
|
1587
2422
|
};
|
|
1588
|
-
var
|
|
2423
|
+
var TraceShipper3 = class extends TraceShipper2 {
|
|
1589
2424
|
constructor(opts) {
|
|
1590
2425
|
var _a, _b, _c;
|
|
1591
2426
|
super({
|
|
@@ -1707,18 +2542,13 @@ function parseOpenCodeAssistantTokens(tokens) {
|
|
|
1707
2542
|
};
|
|
1708
2543
|
}
|
|
1709
2544
|
function modelSpendSpanAttributes(input) {
|
|
1710
|
-
const providerAttr = attrString(
|
|
1711
|
-
|
|
1712
|
-
canonicalModelProvider(input.providerID)
|
|
1713
|
-
);
|
|
1714
|
-
const usageAttrs = buildModelUsageAttributes({
|
|
2545
|
+
const providerAttr = attrString("gen_ai.provider.name", canonicalModelProvider(input.providerID));
|
|
2546
|
+
const usageAttrs = buildRawModelUsageAttributes({
|
|
1715
2547
|
inputTokens: input.tokens.input,
|
|
1716
2548
|
outputTokens: input.tokens.output,
|
|
1717
2549
|
reasoningTokens: input.tokens.reasoning,
|
|
1718
2550
|
cacheReadInputTokens: input.tokens.cacheRead,
|
|
1719
|
-
cacheWriteInputTokens: input.tokens.cacheWrite
|
|
1720
|
-
inputTokenSemantics: "exclusive",
|
|
1721
|
-
outputTokenSemantics: "exclusive"
|
|
2551
|
+
cacheWriteInputTokens: input.tokens.cacheWrite
|
|
1722
2552
|
});
|
|
1723
2553
|
return providerAttr ? [providerAttr, ...usageAttrs] : usageAttrs;
|
|
1724
2554
|
}
|
|
@@ -1726,6 +2556,9 @@ function buildLlmGenAiAttributes(input) {
|
|
|
1726
2556
|
const parsed = parseOpenCodeAssistantTokens(input.tokens);
|
|
1727
2557
|
if (!parsed) return [];
|
|
1728
2558
|
return [
|
|
2559
|
+
// OpenCode has already normalized both token axes. Provenance lets Dawn
|
|
2560
|
+
// select that contract without the SDK or customer declaring semantics.
|
|
2561
|
+
attrString(MODEL_USAGE_ATTRIBUTES.usageSource, "opencode"),
|
|
1729
2562
|
attrString("gen_ai.system", input.providerID),
|
|
1730
2563
|
attrString("gen_ai.request.model", input.modelID),
|
|
1731
2564
|
attrString("gen_ai.response.model", input.modelID),
|
|
@@ -1745,11 +2578,11 @@ function createSessionParentMapHelpers({
|
|
|
1745
2578
|
}) {
|
|
1746
2579
|
function applyChildSessionParentToState(childSessionId) {
|
|
1747
2580
|
const parentInfo = mapChildSessionToParent2.get(childSessionId);
|
|
1748
|
-
const
|
|
1749
|
-
if (!parentInfo || !
|
|
1750
|
-
|
|
1751
|
-
|
|
1752
|
-
|
|
2581
|
+
const state2 = sessions2.get(childSessionId);
|
|
2582
|
+
if (!parentInfo || !state2) return;
|
|
2583
|
+
state2.parentId = parentInfo.parentId;
|
|
2584
|
+
state2.parentTaskSpanIds = parentInfo.parentTaskSpanIds;
|
|
2585
|
+
state2.parentEventContext = parentInfo.eventContext;
|
|
1753
2586
|
}
|
|
1754
2587
|
function queuePendingChildByCallKey(key, childSessionId) {
|
|
1755
2588
|
var _a;
|
|
@@ -1845,10 +2678,10 @@ function markTaskCallFinished(sessionID, callID) {
|
|
|
1845
2678
|
running.delete(callID);
|
|
1846
2679
|
if (running.size === 0) runningTaskCallsBySession.delete(sessionID);
|
|
1847
2680
|
}
|
|
1848
|
-
function endPendingToolSpanWithError(
|
|
1849
|
-
const startInfo =
|
|
2681
|
+
function endPendingToolSpanWithError(state2, callID, tool, toolCallArgs, errorMessage, traceShipper) {
|
|
2682
|
+
const startInfo = state2.toolSpanStarts.get(callID);
|
|
1850
2683
|
if (!startInfo) return false;
|
|
1851
|
-
|
|
2684
|
+
state2.toolSpanStarts.delete(callID);
|
|
1852
2685
|
const error = new Error(errorMessage);
|
|
1853
2686
|
const endAttrs = [
|
|
1854
2687
|
attrString("ai.toolCall.args", toolCallArgs),
|
|
@@ -1948,17 +2781,17 @@ function createHooks(config, worktree, directory, eventShipper, traceShipper) {
|
|
|
1948
2781
|
if (info == null || typeof info !== "object")
|
|
1949
2782
|
throw new Error("session.created: props.info is required");
|
|
1950
2783
|
const parentID = info["parentID"];
|
|
1951
|
-
let
|
|
1952
|
-
if (!
|
|
1953
|
-
|
|
1954
|
-
sessions.set(sessionID,
|
|
2784
|
+
let state2 = sessions.get(sessionID);
|
|
2785
|
+
if (!state2) {
|
|
2786
|
+
state2 = createSessionState(sessionID);
|
|
2787
|
+
sessions.set(sessionID, state2);
|
|
1955
2788
|
}
|
|
1956
|
-
|
|
1957
|
-
if (
|
|
2789
|
+
state2.parentId = parentID;
|
|
2790
|
+
if (state2.parentId) mapChildSessionToParent.set(sessionID, { parentId: state2.parentId });
|
|
1958
2791
|
} else if (event.type === "session.compacted") {
|
|
1959
|
-
const
|
|
1960
|
-
if (!
|
|
1961
|
-
|
|
2792
|
+
const state2 = sessions.get(String(sessionID));
|
|
2793
|
+
if (!state2) return;
|
|
2794
|
+
state2.isCompacting = true;
|
|
1962
2795
|
} else if (event.type === "message.part.updated") {
|
|
1963
2796
|
const part = props["part"];
|
|
1964
2797
|
if (part == null || typeof part !== "object")
|
|
@@ -1970,10 +2803,10 @@ function createHooks(config, worktree, directory, eventShipper, traceShipper) {
|
|
|
1970
2803
|
throw new Error("message.part.updated: part.sessionID is required");
|
|
1971
2804
|
if (messageId == null || messageId === "")
|
|
1972
2805
|
throw new Error("message.part.updated: part.messageID is required");
|
|
1973
|
-
const
|
|
1974
|
-
if (!
|
|
2806
|
+
const state2 = sessions.get(partSessionID);
|
|
2807
|
+
if (!state2) return;
|
|
1975
2808
|
if (partObj["type"] === "text" && typeof partObj["text"] === "string") {
|
|
1976
|
-
|
|
2809
|
+
state2.outputParts.set(messageId, capText2(partObj["text"]));
|
|
1977
2810
|
} else if (partObj["type"] === "tool" && messageId) {
|
|
1978
2811
|
const tool = partObj["tool"];
|
|
1979
2812
|
const callID = partObj["callID"];
|
|
@@ -2005,7 +2838,7 @@ function createHooks(config, worktree, directory, eventShipper, traceShipper) {
|
|
|
2005
2838
|
const input = toolState["input"];
|
|
2006
2839
|
const toolCallArgs = input === void 0 ? void 0 : typeof input === "string" ? capText2(input) : boundedStringify(input);
|
|
2007
2840
|
if (endPendingToolSpanWithError(
|
|
2008
|
-
|
|
2841
|
+
state2,
|
|
2009
2842
|
callID,
|
|
2010
2843
|
tool,
|
|
2011
2844
|
toolCallArgs,
|
|
@@ -2016,7 +2849,7 @@ function createHooks(config, worktree, directory, eventShipper, traceShipper) {
|
|
|
2016
2849
|
}
|
|
2017
2850
|
}
|
|
2018
2851
|
} else if (partObj["type"] === "reasoning" && typeof partObj["text"] === "string") {
|
|
2019
|
-
|
|
2852
|
+
state2.reasoningParts.set(messageId, capText2(partObj["text"]));
|
|
2020
2853
|
}
|
|
2021
2854
|
} else if (event.type === "message.updated") {
|
|
2022
2855
|
const msgInfo = props["info"];
|
|
@@ -2036,10 +2869,10 @@ function createHooks(config, worktree, directory, eventShipper, traceShipper) {
|
|
|
2036
2869
|
throw new Error("message.updated: info.time is required");
|
|
2037
2870
|
const timeObj = time;
|
|
2038
2871
|
if (timeObj["completed"] == null) return;
|
|
2039
|
-
const
|
|
2040
|
-
if (!
|
|
2041
|
-
if (
|
|
2042
|
-
|
|
2872
|
+
const state2 = sessions.get(msgSessionID);
|
|
2873
|
+
if (!state2 || !state2.currentEventId || !state2.currentRootSpan) return;
|
|
2874
|
+
if (state2.processedMessages.has(messageId)) return;
|
|
2875
|
+
state2.processedMessages.add(messageId);
|
|
2043
2876
|
const tokens = info2["tokens"];
|
|
2044
2877
|
if (tokens == null || typeof tokens !== "object")
|
|
2045
2878
|
throw new Error("message.updated: info.tokens is required");
|
|
@@ -2056,13 +2889,13 @@ function createHooks(config, worktree, directory, eventShipper, traceShipper) {
|
|
|
2056
2889
|
);
|
|
2057
2890
|
const modelName = `${providerID}/${modelID}`;
|
|
2058
2891
|
const finishReason = info2["finish"];
|
|
2059
|
-
const outputText =
|
|
2060
|
-
const reasoningText =
|
|
2892
|
+
const outputText = state2.outputParts.get(messageId);
|
|
2893
|
+
const reasoningText = state2.reasoningParts.get(messageId);
|
|
2061
2894
|
const isToolCallsCompletion = finishReason === "tool-calls";
|
|
2062
2895
|
if (outputText !== void 0 && outputText.trim().length > 0) {
|
|
2063
|
-
|
|
2896
|
+
state2.turnOutputParts.push(outputText);
|
|
2064
2897
|
}
|
|
2065
|
-
|
|
2898
|
+
state2.turnOutputTokens += outputTokens;
|
|
2066
2899
|
if (outputText === void 0 && !isToolCallsCompletion) return;
|
|
2067
2900
|
const msgError = info2["error"];
|
|
2068
2901
|
const errorForSpan = msgError ? (() => {
|
|
@@ -2082,17 +2915,17 @@ type: ${name != null ? name : "UnknownError"}`;
|
|
|
2082
2915
|
attrString("ai.response.text", responseText),
|
|
2083
2916
|
...buildLlmGenAiAttributes({ providerID, modelID, tokens: tokensObj })
|
|
2084
2917
|
];
|
|
2085
|
-
if (
|
|
2918
|
+
if (state2.currentSystemPrompt) {
|
|
2086
2919
|
llmAttrs.push(
|
|
2087
2920
|
attrString("gen_ai.prompt.0.role", "system"),
|
|
2088
|
-
attrString("gen_ai.prompt.0.content",
|
|
2921
|
+
attrString("gen_ai.prompt.0.content", state2.currentSystemPrompt)
|
|
2089
2922
|
);
|
|
2090
2923
|
}
|
|
2091
|
-
const llmParent =
|
|
2924
|
+
const llmParent = state2.parentId && state2.parentTaskSpanIds ? state2.parentTaskSpanIds : state2.currentRootSpan.ids;
|
|
2092
2925
|
const llmSpan = traceShipper.startSpan({
|
|
2093
2926
|
name: modelName,
|
|
2094
2927
|
parent: llmParent,
|
|
2095
|
-
eventId:
|
|
2928
|
+
eventId: state2.currentEventId,
|
|
2096
2929
|
attributes: llmAttrs
|
|
2097
2930
|
});
|
|
2098
2931
|
if (typeof timeObj["created"] === "number") {
|
|
@@ -2103,40 +2936,40 @@ type: ${name != null ? name : "UnknownError"}`;
|
|
|
2103
2936
|
return;
|
|
2104
2937
|
}
|
|
2105
2938
|
if (outputText === void 0) return;
|
|
2106
|
-
const turnOutputText = capText2(
|
|
2107
|
-
const rootSpan =
|
|
2108
|
-
const isCompaction =
|
|
2109
|
-
if (
|
|
2110
|
-
const userInput = unwrapQuotes(
|
|
2939
|
+
const turnOutputText = capText2(state2.turnOutputParts.join("\n\n"));
|
|
2940
|
+
const rootSpan = state2.currentRootSpan;
|
|
2941
|
+
const isCompaction = state2.isCompacting === true;
|
|
2942
|
+
if (state2.parentId) {
|
|
2943
|
+
const userInput = unwrapQuotes(state2.currentInput);
|
|
2111
2944
|
const llmAttrs = [
|
|
2112
2945
|
attrString("ai.operationId", "generateText"),
|
|
2113
2946
|
attrString("ai.prompt", userInput),
|
|
2114
2947
|
attrString(
|
|
2115
2948
|
"ai.prompt.messages",
|
|
2116
|
-
buildPromptMessages(
|
|
2949
|
+
buildPromptMessages(state2.currentSystemPrompt, state2.currentInput)
|
|
2117
2950
|
),
|
|
2118
2951
|
attrString("ai.response.text", turnOutputText),
|
|
2119
2952
|
...buildLlmGenAiAttributes({ providerID, modelID, tokens: tokensObj })
|
|
2120
2953
|
];
|
|
2121
|
-
if (
|
|
2954
|
+
if (state2.currentSystemPrompt) {
|
|
2122
2955
|
llmAttrs.push(
|
|
2123
2956
|
attrString("gen_ai.prompt.0.role", "system"),
|
|
2124
|
-
attrString("gen_ai.prompt.0.content",
|
|
2957
|
+
attrString("gen_ai.prompt.0.content", state2.currentSystemPrompt)
|
|
2125
2958
|
);
|
|
2126
2959
|
}
|
|
2127
|
-
if (!
|
|
2960
|
+
if (!state2.parentTaskSpanIds) {
|
|
2128
2961
|
traceShipper.endSpan(rootSpan, {
|
|
2129
2962
|
error: "Missing strict parent task for child session"
|
|
2130
2963
|
});
|
|
2131
|
-
|
|
2132
|
-
|
|
2964
|
+
state2.currentRootSpan = void 0;
|
|
2965
|
+
state2.currentEventId = void 0;
|
|
2133
2966
|
await traceShipper.flush();
|
|
2134
2967
|
return;
|
|
2135
2968
|
}
|
|
2136
2969
|
const finalLlmSpan = traceShipper.startSpan({
|
|
2137
2970
|
name: modelName,
|
|
2138
|
-
parent:
|
|
2139
|
-
eventId:
|
|
2971
|
+
parent: state2.parentTaskSpanIds,
|
|
2972
|
+
eventId: state2.currentEventId,
|
|
2140
2973
|
attributes: llmAttrs
|
|
2141
2974
|
});
|
|
2142
2975
|
if (typeof timeObj["created"] === "number") {
|
|
@@ -2146,19 +2979,19 @@ type: ${name != null ? name : "UnknownError"}`;
|
|
|
2146
2979
|
traceShipper.endSpan(rootSpan, {
|
|
2147
2980
|
attributes: [
|
|
2148
2981
|
attrString("is_subagent", "true"),
|
|
2149
|
-
attrString("parent_session_id",
|
|
2982
|
+
attrString("parent_session_id", state2.parentId)
|
|
2150
2983
|
],
|
|
2151
2984
|
error: errorForSpan
|
|
2152
2985
|
});
|
|
2153
2986
|
} else {
|
|
2154
2987
|
rootSpan.name = isCompaction ? "ai.compaction" : modelName;
|
|
2155
|
-
const userInput = unwrapQuotes(
|
|
2988
|
+
const userInput = unwrapQuotes(state2.currentInput);
|
|
2156
2989
|
const rootAttrs = [
|
|
2157
2990
|
attrString("ai.operationId", "generateText"),
|
|
2158
2991
|
attrString("ai.prompt", userInput),
|
|
2159
2992
|
attrString(
|
|
2160
2993
|
"ai.prompt.messages",
|
|
2161
|
-
buildPromptMessages(
|
|
2994
|
+
buildPromptMessages(state2.currentSystemPrompt, state2.currentInput)
|
|
2162
2995
|
),
|
|
2163
2996
|
attrString("ai.response.text", turnOutputText),
|
|
2164
2997
|
...buildLlmGenAiAttributes({ providerID, modelID, tokens: tokensObj })
|
|
@@ -2167,10 +3000,10 @@ type: ${name != null ? name : "UnknownError"}`;
|
|
|
2167
3000
|
rootAttrs.push(attrString("is_compaction", "true"));
|
|
2168
3001
|
}
|
|
2169
3002
|
rootAttrs.push(attrString("message_id", messageId));
|
|
2170
|
-
if (
|
|
3003
|
+
if (state2.currentSystemPrompt) {
|
|
2171
3004
|
rootAttrs.push(
|
|
2172
3005
|
attrString("gen_ai.prompt.0.role", "system"),
|
|
2173
|
-
attrString("gen_ai.prompt.0.content",
|
|
3006
|
+
attrString("gen_ai.prompt.0.content", state2.currentSystemPrompt)
|
|
2174
3007
|
);
|
|
2175
3008
|
}
|
|
2176
3009
|
traceShipper.endSpan(rootSpan, {
|
|
@@ -2178,24 +3011,24 @@ type: ${name != null ? name : "UnknownError"}`;
|
|
|
2178
3011
|
error: errorForSpan
|
|
2179
3012
|
});
|
|
2180
3013
|
if (isCompaction) {
|
|
2181
|
-
|
|
3014
|
+
state2.isCompacting = false;
|
|
2182
3015
|
}
|
|
2183
3016
|
}
|
|
2184
|
-
|
|
3017
|
+
state2.currentRootSpan = void 0;
|
|
2185
3018
|
const hasAssistantResponse = turnOutputText.trim().length > 0;
|
|
2186
3019
|
if (!hasAssistantResponse && !msgError) {
|
|
2187
3020
|
await traceShipper.flush();
|
|
2188
|
-
|
|
3021
|
+
state2.currentEventId = void 0;
|
|
2189
3022
|
return;
|
|
2190
3023
|
}
|
|
2191
|
-
if (!
|
|
2192
|
-
await eventShipper.finish(
|
|
2193
|
-
userId: (_d = (_c =
|
|
3024
|
+
if (!state2.parentId) {
|
|
3025
|
+
await eventShipper.finish(state2.currentEventId, {
|
|
3026
|
+
userId: (_d = (_c = state2.eventMetadata) == null ? void 0 : _c.userId) != null ? _d : state2.sessionId,
|
|
2194
3027
|
model: modelID,
|
|
2195
3028
|
output: msgError ? void 0 : turnOutputText,
|
|
2196
3029
|
usage: {
|
|
2197
3030
|
promptTokens: inputTokens,
|
|
2198
|
-
completionTokens:
|
|
3031
|
+
completionTokens: state2.turnOutputTokens
|
|
2199
3032
|
},
|
|
2200
3033
|
error: msgError ? {
|
|
2201
3034
|
name: msgError.name,
|
|
@@ -2210,35 +3043,35 @@ type: ${name != null ? name : "UnknownError"}`;
|
|
|
2210
3043
|
});
|
|
2211
3044
|
}
|
|
2212
3045
|
await traceShipper.flush();
|
|
2213
|
-
|
|
3046
|
+
state2.currentEventId = void 0;
|
|
2214
3047
|
} else if (event.type === "session.idle") {
|
|
2215
3048
|
if (!sessionID) return;
|
|
2216
|
-
const
|
|
2217
|
-
if (!
|
|
2218
|
-
if (
|
|
2219
|
-
traceShipper.endSpan(
|
|
2220
|
-
|
|
3049
|
+
const state2 = sessions.get(String(sessionID));
|
|
3050
|
+
if (!state2) return;
|
|
3051
|
+
if (state2.currentRootSpan) {
|
|
3052
|
+
traceShipper.endSpan(state2.currentRootSpan);
|
|
3053
|
+
state2.currentRootSpan = void 0;
|
|
2221
3054
|
}
|
|
2222
|
-
if (
|
|
2223
|
-
|
|
3055
|
+
if (state2.currentEventId) {
|
|
3056
|
+
state2.currentEventId = void 0;
|
|
2224
3057
|
}
|
|
2225
|
-
|
|
3058
|
+
state2.isCompacting = false;
|
|
2226
3059
|
await Promise.all([eventShipper.flush(), traceShipper.flush()]);
|
|
2227
|
-
if (
|
|
3060
|
+
if (state2.parentId) {
|
|
2228
3061
|
cleanupSessionParentMap(String(sessionID));
|
|
2229
3062
|
sessions.delete(String(sessionID));
|
|
2230
3063
|
} else {
|
|
2231
3064
|
}
|
|
2232
3065
|
} else if (event.type === "session.deleted") {
|
|
2233
3066
|
if (!sessionID) return;
|
|
2234
|
-
const
|
|
2235
|
-
if (!
|
|
2236
|
-
if (
|
|
2237
|
-
traceShipper.endSpan(
|
|
2238
|
-
|
|
3067
|
+
const state2 = sessions.get(String(sessionID));
|
|
3068
|
+
if (!state2) return;
|
|
3069
|
+
if (state2.currentRootSpan) {
|
|
3070
|
+
traceShipper.endSpan(state2.currentRootSpan);
|
|
3071
|
+
state2.currentRootSpan = void 0;
|
|
2239
3072
|
}
|
|
2240
|
-
if (
|
|
2241
|
-
|
|
3073
|
+
if (state2.currentEventId) {
|
|
3074
|
+
state2.currentEventId = void 0;
|
|
2242
3075
|
}
|
|
2243
3076
|
cleanupSessionParentMap(String(sessionID));
|
|
2244
3077
|
await Promise.all([eventShipper.flush(), traceShipper.flush()]);
|
|
@@ -2247,8 +3080,8 @@ type: ${name != null ? name : "UnknownError"}`;
|
|
|
2247
3080
|
const errorSessionID = (_h = props["sessionID"]) != null ? _h : sessionID;
|
|
2248
3081
|
if (errorSessionID === void 0 || errorSessionID === "")
|
|
2249
3082
|
throw new Error("session.error: missing sessionID");
|
|
2250
|
-
const
|
|
2251
|
-
if (!
|
|
3083
|
+
const state2 = sessions.get(String(errorSessionID));
|
|
3084
|
+
if (!state2) return;
|
|
2252
3085
|
const errorObj = props["error"];
|
|
2253
3086
|
if (errorObj == null) throw new Error("session.error: missing error object");
|
|
2254
3087
|
const errorName = errorObj.name;
|
|
@@ -2258,12 +3091,12 @@ type: ${name != null ? name : "UnknownError"}`;
|
|
|
2258
3091
|
const errorStr = `${errorMessage != null ? errorMessage : errorName}
|
|
2259
3092
|
|
|
2260
3093
|
type: ${errorName != null ? errorName : "UnknownError"}`;
|
|
2261
|
-
if (
|
|
2262
|
-
traceShipper.endSpan(
|
|
2263
|
-
|
|
3094
|
+
if (state2.currentRootSpan) {
|
|
3095
|
+
traceShipper.endSpan(state2.currentRootSpan, { error: errorStr });
|
|
3096
|
+
state2.currentRootSpan = void 0;
|
|
2264
3097
|
}
|
|
2265
|
-
if (
|
|
2266
|
-
|
|
3098
|
+
if (state2.currentEventId) {
|
|
3099
|
+
state2.currentEventId = void 0;
|
|
2267
3100
|
}
|
|
2268
3101
|
cleanupSessionParentMap(String(errorSessionID));
|
|
2269
3102
|
await Promise.all([eventShipper.flush(), traceShipper.flush()]);
|
|
@@ -2283,15 +3116,15 @@ type: ${errorName != null ? errorName : "UnknownError"}`;
|
|
|
2283
3116
|
var _a, _b, _c, _d, _e, _f, _g;
|
|
2284
3117
|
try {
|
|
2285
3118
|
const { sessionID } = messageInput;
|
|
2286
|
-
let
|
|
2287
|
-
if (!
|
|
2288
|
-
|
|
2289
|
-
sessions.set(sessionID,
|
|
3119
|
+
let state2 = sessions.get(sessionID);
|
|
3120
|
+
if (!state2) {
|
|
3121
|
+
state2 = createSessionState(sessionID);
|
|
3122
|
+
sessions.set(sessionID, state2);
|
|
2290
3123
|
}
|
|
2291
3124
|
applyChildSessionParentToState(sessionID);
|
|
2292
|
-
if (
|
|
2293
|
-
traceShipper.endSpan(
|
|
2294
|
-
|
|
3125
|
+
if (state2.currentRootSpan) {
|
|
3126
|
+
traceShipper.endSpan(state2.currentRootSpan);
|
|
3127
|
+
state2.currentRootSpan = void 0;
|
|
2295
3128
|
}
|
|
2296
3129
|
if (output == null) throw new Error("chat.message: output is required");
|
|
2297
3130
|
const parts = output.parts;
|
|
@@ -2322,39 +3155,39 @@ type: ${errorName != null ? errorName : "UnknownError"}`;
|
|
|
2322
3155
|
}
|
|
2323
3156
|
}
|
|
2324
3157
|
}
|
|
2325
|
-
|
|
3158
|
+
state2.eventMetadata = {
|
|
2326
3159
|
...baseMeta,
|
|
2327
3160
|
...promptMeta,
|
|
2328
3161
|
properties: baseMeta.properties || promptMeta.properties ? { ...(_a = baseMeta.properties) != null ? _a : {}, ...(_b = promptMeta.properties) != null ? _b : {} } : void 0
|
|
2329
3162
|
};
|
|
2330
3163
|
const userText = capText2(textParts.join("\n"));
|
|
2331
|
-
|
|
2332
|
-
|
|
2333
|
-
|
|
2334
|
-
if (
|
|
2335
|
-
if (!
|
|
3164
|
+
state2.currentInput = userText;
|
|
3165
|
+
state2.turnOutputParts = [];
|
|
3166
|
+
state2.turnOutputTokens = 0;
|
|
3167
|
+
if (state2.parentId) {
|
|
3168
|
+
if (!state2.parentTaskSpanIds || !state2.parentEventContext) {
|
|
2336
3169
|
return;
|
|
2337
3170
|
}
|
|
2338
|
-
|
|
2339
|
-
|
|
3171
|
+
state2.currentEventId = state2.parentEventContext.eventId;
|
|
3172
|
+
state2.currentRootSpan = traceShipper.startSpan({
|
|
2340
3173
|
name: "Subagent",
|
|
2341
|
-
parent:
|
|
2342
|
-
eventId:
|
|
3174
|
+
parent: state2.parentTaskSpanIds,
|
|
3175
|
+
eventId: state2.currentEventId,
|
|
2343
3176
|
attributes: [
|
|
2344
3177
|
attrString("workspace", worktree),
|
|
2345
3178
|
attrString("directory", directory),
|
|
2346
3179
|
attrString("hostname", hostname),
|
|
2347
3180
|
attrString("os", os),
|
|
2348
3181
|
attrString("is_subagent", "true"),
|
|
2349
|
-
attrString("parent_session_id",
|
|
3182
|
+
attrString("parent_session_id", state2.parentId)
|
|
2350
3183
|
]
|
|
2351
3184
|
});
|
|
2352
3185
|
return;
|
|
2353
3186
|
}
|
|
2354
|
-
|
|
2355
|
-
|
|
2356
|
-
name:
|
|
2357
|
-
eventId:
|
|
3187
|
+
state2.currentEventId = generateId();
|
|
3188
|
+
state2.currentRootSpan = traceShipper.startSpan({
|
|
3189
|
+
name: state2.isCompacting ? "ai.compaction" : "ai.event",
|
|
3190
|
+
eventId: state2.currentEventId,
|
|
2358
3191
|
attributes: [
|
|
2359
3192
|
attrString("workspace", worktree),
|
|
2360
3193
|
attrString("directory", directory),
|
|
@@ -2362,11 +3195,11 @@ type: ${errorName != null ? errorName : "UnknownError"}`;
|
|
|
2362
3195
|
attrString("os", os)
|
|
2363
3196
|
]
|
|
2364
3197
|
});
|
|
2365
|
-
await eventShipper.patch(
|
|
3198
|
+
await eventShipper.patch(state2.currentEventId, {
|
|
2366
3199
|
isPending: true,
|
|
2367
|
-
userId: (_d = (_c =
|
|
2368
|
-
convoId:
|
|
2369
|
-
eventName: (_f = (_e =
|
|
3200
|
+
userId: (_d = (_c = state2.eventMetadata) == null ? void 0 : _c.userId) != null ? _d : state2.sessionId,
|
|
3201
|
+
convoId: state2.sessionId,
|
|
3202
|
+
eventName: (_f = (_e = state2.eventMetadata) == null ? void 0 : _e.eventName) != null ? _f : config.eventName,
|
|
2370
3203
|
input: userText,
|
|
2371
3204
|
...newAttachments.length > 0 ? { attachments: newAttachments } : {},
|
|
2372
3205
|
properties: {
|
|
@@ -2375,7 +3208,7 @@ type: ${errorName != null ? errorName : "UnknownError"}`;
|
|
|
2375
3208
|
hostname,
|
|
2376
3209
|
os,
|
|
2377
3210
|
plugin_version: PLUGIN_VERSION,
|
|
2378
|
-
...(_g =
|
|
3211
|
+
...(_g = state2.eventMetadata) == null ? void 0 : _g.properties
|
|
2379
3212
|
}
|
|
2380
3213
|
});
|
|
2381
3214
|
} catch (err) {
|
|
@@ -2389,16 +3222,16 @@ type: ${errorName != null ? errorName : "UnknownError"}`;
|
|
|
2389
3222
|
var _a, _b, _c;
|
|
2390
3223
|
try {
|
|
2391
3224
|
const { tool, sessionID, callID } = toolInput;
|
|
2392
|
-
const
|
|
2393
|
-
if (!
|
|
2394
|
-
const spanParent =
|
|
3225
|
+
const state2 = sessions.get(sessionID);
|
|
3226
|
+
if (!state2 || !state2.currentEventId) return;
|
|
3227
|
+
const spanParent = state2.parentId && state2.parentTaskSpanIds ? state2.parentTaskSpanIds : (_a = state2.currentRootSpan) == null ? void 0 : _a.ids;
|
|
2395
3228
|
if (!spanParent) return;
|
|
2396
3229
|
const startTimeUnixNano = nowUnixNanoString();
|
|
2397
3230
|
if (tool === "task") {
|
|
2398
3231
|
const liveTaskSpan = traceShipper.startSpan({
|
|
2399
3232
|
name: "ai.toolCall",
|
|
2400
3233
|
parent: spanParent,
|
|
2401
|
-
eventId:
|
|
3234
|
+
eventId: state2.currentEventId,
|
|
2402
3235
|
attributes: [
|
|
2403
3236
|
attrString("ai.operationId", "ai.toolCall"),
|
|
2404
3237
|
attrString("ai.toolCall.name", tool),
|
|
@@ -2409,9 +3242,9 @@ type: ${errorName != null ? errorName : "UnknownError"}`;
|
|
|
2409
3242
|
const ctx = {
|
|
2410
3243
|
ids: liveTaskSpan.ids,
|
|
2411
3244
|
eventContext: {
|
|
2412
|
-
eventId:
|
|
2413
|
-
userId: (_c = (_b =
|
|
2414
|
-
convoId:
|
|
3245
|
+
eventId: state2.currentEventId,
|
|
3246
|
+
userId: (_c = (_b = state2.eventMetadata) == null ? void 0 : _b.userId) != null ? _c : state2.sessionId,
|
|
3247
|
+
convoId: state2.sessionId
|
|
2415
3248
|
}
|
|
2416
3249
|
};
|
|
2417
3250
|
taskContexts.set(callKey(sessionID, callID), ctx);
|
|
@@ -2422,18 +3255,18 @@ type: ${errorName != null ? errorName : "UnknownError"}`;
|
|
|
2422
3255
|
}
|
|
2423
3256
|
running.add(callID);
|
|
2424
3257
|
resolvePendingChildrenForCall(sessionID, callID, "tool.execute.before");
|
|
2425
|
-
|
|
3258
|
+
state2.toolSpanStarts.set(callID, {
|
|
2426
3259
|
startTimeUnixNano,
|
|
2427
3260
|
parent: spanParent,
|
|
2428
|
-
eventId:
|
|
3261
|
+
eventId: state2.currentEventId,
|
|
2429
3262
|
name: tool,
|
|
2430
3263
|
liveSpan: liveTaskSpan
|
|
2431
3264
|
});
|
|
2432
3265
|
} else {
|
|
2433
|
-
|
|
3266
|
+
state2.toolSpanStarts.set(callID, {
|
|
2434
3267
|
startTimeUnixNano,
|
|
2435
3268
|
parent: spanParent,
|
|
2436
|
-
eventId:
|
|
3269
|
+
eventId: state2.currentEventId,
|
|
2437
3270
|
name: tool
|
|
2438
3271
|
});
|
|
2439
3272
|
}
|
|
@@ -2450,13 +3283,13 @@ type: ${errorName != null ? errorName : "UnknownError"}`;
|
|
|
2450
3283
|
"tool.execute.after": async (toolInput, result) => {
|
|
2451
3284
|
try {
|
|
2452
3285
|
const { tool, sessionID, callID, args } = toolInput;
|
|
2453
|
-
const
|
|
2454
|
-
if (!
|
|
3286
|
+
const state2 = sessions.get(sessionID);
|
|
3287
|
+
if (!state2 || !state2.currentEventId) return;
|
|
2455
3288
|
if (args === void 0 || args === null)
|
|
2456
3289
|
throw new Error("tool.execute.after: args is required");
|
|
2457
3290
|
const toolCallArgs = typeof args === "string" ? capText2(args) : boundedStringify(args);
|
|
2458
|
-
const startInfo =
|
|
2459
|
-
|
|
3291
|
+
const startInfo = state2.toolSpanStarts.get(callID);
|
|
3292
|
+
state2.toolSpanStarts.delete(callID);
|
|
2460
3293
|
const resultMetadata = result.metadata;
|
|
2461
3294
|
const childSessionId = resultMetadata == null ? void 0 : resultMetadata["sessionId"];
|
|
2462
3295
|
if (tool === "task" && childSessionId) {
|
|
@@ -2509,9 +3342,9 @@ type: ${errorName != null ? errorName : "UnknownError"}`;
|
|
|
2509
3342
|
try {
|
|
2510
3343
|
const sessionID = input.sessionID;
|
|
2511
3344
|
if (!sessionID) return;
|
|
2512
|
-
const
|
|
2513
|
-
if (
|
|
2514
|
-
|
|
3345
|
+
const state2 = sessions.get(sessionID);
|
|
3346
|
+
if (state2) {
|
|
3347
|
+
state2.isCompacting = true;
|
|
2515
3348
|
}
|
|
2516
3349
|
} catch (err) {
|
|
2517
3350
|
rateLimitedErrorLog(
|
|
@@ -2528,15 +3361,15 @@ type: ${errorName != null ? errorName : "UnknownError"}`;
|
|
|
2528
3361
|
if (!config.captureSystemPrompt) return;
|
|
2529
3362
|
const sessionID = input.sessionID;
|
|
2530
3363
|
if (!sessionID) return;
|
|
2531
|
-
let
|
|
2532
|
-
if (!
|
|
2533
|
-
|
|
2534
|
-
sessions.set(sessionID,
|
|
3364
|
+
let state2 = sessions.get(sessionID);
|
|
3365
|
+
if (!state2) {
|
|
3366
|
+
state2 = createSessionState(sessionID);
|
|
3367
|
+
sessions.set(sessionID, state2);
|
|
2535
3368
|
}
|
|
2536
3369
|
const MAX_SYSTEM_PROMPT_LENGTH = 32768;
|
|
2537
3370
|
const TRUNCATION_MARKER3 = "\n...[truncated]";
|
|
2538
3371
|
const joined = output.system.join("\n\n");
|
|
2539
|
-
|
|
3372
|
+
state2.currentSystemPrompt = joined.length > MAX_SYSTEM_PROMPT_LENGTH ? joined.slice(0, MAX_SYSTEM_PROMPT_LENGTH - TRUNCATION_MARKER3.length) + TRUNCATION_MARKER3 : joined;
|
|
2540
3373
|
} catch (err) {
|
|
2541
3374
|
rateLimitedErrorLog(
|
|
2542
3375
|
"experimental.chat.system.transform",
|
|
@@ -2548,7 +3381,7 @@ type: ${errorName != null ? errorName : "UnknownError"}`;
|
|
|
2548
3381
|
}
|
|
2549
3382
|
|
|
2550
3383
|
// src/index.ts
|
|
2551
|
-
function createRaindropHandle(eventShipper, traceShipper) {
|
|
3384
|
+
function createRaindropHandle(eventShipper, traceShipper, appGitContext) {
|
|
2552
3385
|
return {
|
|
2553
3386
|
users: {
|
|
2554
3387
|
async identify(users) {
|
|
@@ -2559,12 +3392,19 @@ function createRaindropHandle(eventShipper, traceShipper) {
|
|
|
2559
3392
|
await Promise.all([eventShipper.flush(), traceShipper.flush()]);
|
|
2560
3393
|
},
|
|
2561
3394
|
async shutdown() {
|
|
2562
|
-
|
|
3395
|
+
try {
|
|
3396
|
+
await Promise.all([eventShipper.shutdown(), traceShipper.shutdown()]);
|
|
3397
|
+
} finally {
|
|
3398
|
+
try {
|
|
3399
|
+
appGitContext.dispose();
|
|
3400
|
+
} catch (e) {
|
|
3401
|
+
}
|
|
3402
|
+
}
|
|
2563
3403
|
}
|
|
2564
3404
|
};
|
|
2565
3405
|
}
|
|
2566
|
-
async function plugin(input) {
|
|
2567
|
-
var _a;
|
|
3406
|
+
async function plugin(input, opts = {}) {
|
|
3407
|
+
var _a, _b, _c;
|
|
2568
3408
|
const config = loadConfig(input.directory);
|
|
2569
3409
|
function appLog(level, message) {
|
|
2570
3410
|
console.log(`[raindrop-ai/opencode-plugin] [${level}] ${message}`);
|
|
@@ -2586,21 +3426,28 @@ async function plugin(input) {
|
|
|
2586
3426
|
].filter(Boolean);
|
|
2587
3427
|
appLog("info", `Raindrop tracing enabled \u2014 destinations: ${destinations.join(", ")}`);
|
|
2588
3428
|
}
|
|
2589
|
-
const
|
|
3429
|
+
const configuredAppGit = (_a = opts.appGit) != null ? _a : config.appGit;
|
|
3430
|
+
const appGitContext = createAppGitContext2(
|
|
3431
|
+
((_b = config.writeKey) == null ? void 0 : _b.trim()) || hasLocalDestination ? configuredAppGit : false,
|
|
3432
|
+
{ allowLocalGit: false }
|
|
3433
|
+
);
|
|
3434
|
+
const eventShipper = new EventShipper3({
|
|
2590
3435
|
writeKey: config.writeKey,
|
|
2591
3436
|
endpoint: config.endpoint,
|
|
2592
3437
|
debug: config.debug,
|
|
2593
3438
|
projectId: config.projectId,
|
|
2594
|
-
localDebuggerUrl: config.localWorkshopUrl
|
|
3439
|
+
localDebuggerUrl: config.localWorkshopUrl,
|
|
3440
|
+
appGitContext
|
|
2595
3441
|
});
|
|
2596
|
-
const traceShipper = new
|
|
3442
|
+
const traceShipper = new TraceShipper3({
|
|
2597
3443
|
writeKey: config.writeKey,
|
|
2598
3444
|
endpoint: config.endpoint,
|
|
2599
3445
|
debug: config.debug,
|
|
2600
3446
|
projectId: config.projectId,
|
|
2601
|
-
localDebuggerUrl: config.localWorkshopUrl
|
|
3447
|
+
localDebuggerUrl: config.localWorkshopUrl,
|
|
3448
|
+
appGitContext
|
|
2602
3449
|
});
|
|
2603
|
-
const worktree = (
|
|
3450
|
+
const worktree = (_c = input.worktree) != null ? _c : input.directory;
|
|
2604
3451
|
const hooks = createHooks(
|
|
2605
3452
|
config,
|
|
2606
3453
|
worktree,
|
|
@@ -2608,5 +3455,5 @@ async function plugin(input) {
|
|
|
2608
3455
|
eventShipper,
|
|
2609
3456
|
traceShipper
|
|
2610
3457
|
);
|
|
2611
|
-
return { ...hooks, raindrop: createRaindropHandle(eventShipper, traceShipper) };
|
|
3458
|
+
return { ...hooks, raindrop: createRaindropHandle(eventShipper, traceShipper, appGitContext) };
|
|
2612
3459
|
}
|