@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.js
CHANGED
|
@@ -1,4 +1,518 @@
|
|
|
1
|
-
// ../core/dist/chunk-
|
|
1
|
+
// ../core/dist/chunk-BYBMRLZM.js
|
|
2
|
+
var EVAL_CORRELATION_ID_ATTRIBUTE = "raindrop.eval_correlation_id";
|
|
3
|
+
var PROBE_SCOPE = { correlationId: "" };
|
|
4
|
+
var EvalScopeStorage = class {
|
|
5
|
+
constructor() {
|
|
6
|
+
this._als = null;
|
|
7
|
+
this._probed = false;
|
|
8
|
+
}
|
|
9
|
+
maybeAdoptAsyncLocalStorage() {
|
|
10
|
+
if (this._probed) return;
|
|
11
|
+
this._probed = true;
|
|
12
|
+
try {
|
|
13
|
+
const Ctor = globalThis.RAINDROP_ASYNC_LOCAL_STORAGE;
|
|
14
|
+
if (!Ctor) return;
|
|
15
|
+
const als = new Ctor();
|
|
16
|
+
als.run(PROBE_SCOPE, () => {
|
|
17
|
+
});
|
|
18
|
+
this._als = als;
|
|
19
|
+
} catch (e) {
|
|
20
|
+
this._als = null;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
run(scope, callback) {
|
|
24
|
+
this.maybeAdoptAsyncLocalStorage();
|
|
25
|
+
if (this._als) return this._als.run(scope, callback);
|
|
26
|
+
const previous = this._syncScope;
|
|
27
|
+
this._syncScope = scope;
|
|
28
|
+
try {
|
|
29
|
+
return callback();
|
|
30
|
+
} finally {
|
|
31
|
+
this._syncScope = previous;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
current() {
|
|
35
|
+
this.maybeAdoptAsyncLocalStorage();
|
|
36
|
+
if (this._als) return this._als.getStore();
|
|
37
|
+
return this._syncScope;
|
|
38
|
+
}
|
|
39
|
+
};
|
|
40
|
+
var EVAL_SCOPE_STORAGE_KEY = /* @__PURE__ */ Symbol.for("raindrop.tracing.evalScopeStorage");
|
|
41
|
+
function evalScopeStorage() {
|
|
42
|
+
const holder = globalThis;
|
|
43
|
+
let storage = holder[EVAL_SCOPE_STORAGE_KEY];
|
|
44
|
+
if (!storage) {
|
|
45
|
+
storage = new EvalScopeStorage();
|
|
46
|
+
holder[EVAL_SCOPE_STORAGE_KEY] = storage;
|
|
47
|
+
}
|
|
48
|
+
return storage;
|
|
49
|
+
}
|
|
50
|
+
function currentEvalScope() {
|
|
51
|
+
try {
|
|
52
|
+
return evalScopeStorage().current();
|
|
53
|
+
} catch (e) {
|
|
54
|
+
return void 0;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
function evalScopeAttributes() {
|
|
58
|
+
const scope = currentEvalScope();
|
|
59
|
+
if (!scope) return {};
|
|
60
|
+
return { [EVAL_CORRELATION_ID_ATTRIBUTE]: scope.correlationId };
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// ../core/dist/chunk-WJOR6M7H.js
|
|
64
|
+
var STATE_KEY = /* @__PURE__ */ Symbol.for("raindrop.tracing.replayTraceRoutingState");
|
|
65
|
+
function state() {
|
|
66
|
+
const holder = globalThis;
|
|
67
|
+
let current = holder[STATE_KEY];
|
|
68
|
+
if (!current) {
|
|
69
|
+
let storage = null;
|
|
70
|
+
try {
|
|
71
|
+
const Ctor = globalThis.RAINDROP_ASYNC_LOCAL_STORAGE;
|
|
72
|
+
if (Ctor) storage = new Ctor();
|
|
73
|
+
} catch (e) {
|
|
74
|
+
storage = null;
|
|
75
|
+
}
|
|
76
|
+
current = {
|
|
77
|
+
storage,
|
|
78
|
+
syncDestination: void 0,
|
|
79
|
+
spanDestinations: /* @__PURE__ */ new WeakMap()
|
|
80
|
+
};
|
|
81
|
+
holder[STATE_KEY] = current;
|
|
82
|
+
}
|
|
83
|
+
return current;
|
|
84
|
+
}
|
|
85
|
+
function currentReplayTraceDestination() {
|
|
86
|
+
var _a, _b;
|
|
87
|
+
const routing = state();
|
|
88
|
+
return (_b = (_a = routing.storage) == null ? void 0 : _a.getStore()) != null ? _b : routing.syncDestination;
|
|
89
|
+
}
|
|
90
|
+
function rememberReplayTraceDestination(span) {
|
|
91
|
+
const destination = currentReplayTraceDestination();
|
|
92
|
+
if (destination) state().spanDestinations.set(span, destination);
|
|
93
|
+
}
|
|
94
|
+
function copyReplayTraceDestination(source, target) {
|
|
95
|
+
const destination = state().spanDestinations.get(source);
|
|
96
|
+
if (destination) state().spanDestinations.set(target, destination);
|
|
97
|
+
}
|
|
98
|
+
function replayTraceDestinationFor(value) {
|
|
99
|
+
if (typeof value !== "object" && typeof value !== "function" || value === null) {
|
|
100
|
+
return void 0;
|
|
101
|
+
}
|
|
102
|
+
return state().spanDestinations.get(value);
|
|
103
|
+
}
|
|
104
|
+
function recordReplayExportedSpan(destination, spanId, traceId) {
|
|
105
|
+
var _a, _b;
|
|
106
|
+
if (!destination || !spanId || !traceId) return;
|
|
107
|
+
(_a = destination.exportedSpanIds) == null ? void 0 : _a.add(spanId);
|
|
108
|
+
(_b = destination.exportedTraceIds) == null ? void 0 : _b.add(traceId);
|
|
109
|
+
}
|
|
110
|
+
function replayTraceUrl(baseUrl) {
|
|
111
|
+
return `${baseUrl.replace(/\/+$/, "")}/v1/traces`;
|
|
112
|
+
}
|
|
113
|
+
function getAsyncLocalStorageCtor() {
|
|
114
|
+
return globalThis.RAINDROP_ASYNC_LOCAL_STORAGE;
|
|
115
|
+
}
|
|
116
|
+
var MAX_BINDING_STACK = 128;
|
|
117
|
+
var EMPTY_STACK = [];
|
|
118
|
+
var ContextStackStorage = class {
|
|
119
|
+
/** Emitted once when this runtime cannot support an ambient push. */
|
|
120
|
+
constructor(noAmbientBindWarning) {
|
|
121
|
+
this.noAmbientBindWarning = noAmbientBindWarning;
|
|
122
|
+
this._als = null;
|
|
123
|
+
this._enterWithUsable = false;
|
|
124
|
+
this._syncStack = EMPTY_STACK;
|
|
125
|
+
this._adoptionChecked = false;
|
|
126
|
+
this._warnedNoAmbientBind = false;
|
|
127
|
+
}
|
|
128
|
+
maybeAdoptAsyncLocalStorage() {
|
|
129
|
+
if (this._adoptionChecked) return;
|
|
130
|
+
this._adoptionChecked = true;
|
|
131
|
+
const Ctor = getAsyncLocalStorageCtor();
|
|
132
|
+
if (!Ctor) return;
|
|
133
|
+
const als = new Ctor();
|
|
134
|
+
try {
|
|
135
|
+
als.run(EMPTY_STACK, () => {
|
|
136
|
+
});
|
|
137
|
+
} catch (e) {
|
|
138
|
+
return;
|
|
139
|
+
}
|
|
140
|
+
this._als = als;
|
|
141
|
+
if (typeof als.enterWith === "function") {
|
|
142
|
+
try {
|
|
143
|
+
als.enterWith(EMPTY_STACK);
|
|
144
|
+
this._enterWithUsable = true;
|
|
145
|
+
} catch (e) {
|
|
146
|
+
this._enterWithUsable = false;
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
getStack() {
|
|
151
|
+
var _a;
|
|
152
|
+
this.maybeAdoptAsyncLocalStorage();
|
|
153
|
+
if (this._als) return (_a = this._als.getStore()) != null ? _a : this._syncStack;
|
|
154
|
+
return this._syncStack;
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* Persist an ambient stack mutation. Returns false when an ALS is adopted but
|
|
158
|
+
* `enterWith` is unusable (workerd): callers must NOT fall back to the
|
|
159
|
+
* process-shared sync stack, since concurrent isolates would cross-stamp.
|
|
160
|
+
*/
|
|
161
|
+
setAmbientStack(stack) {
|
|
162
|
+
if (this._als) {
|
|
163
|
+
if (!this._enterWithUsable) return false;
|
|
164
|
+
this._als.enterWith(stack);
|
|
165
|
+
return true;
|
|
166
|
+
}
|
|
167
|
+
this._syncStack = stack;
|
|
168
|
+
return true;
|
|
169
|
+
}
|
|
170
|
+
push(binding) {
|
|
171
|
+
this.maybeAdoptAsyncLocalStorage();
|
|
172
|
+
if (this._als && !this._enterWithUsable) {
|
|
173
|
+
this.warnNoAmbientBindOnce();
|
|
174
|
+
return;
|
|
175
|
+
}
|
|
176
|
+
let stack = this.getStack();
|
|
177
|
+
if (stack.length >= MAX_BINDING_STACK) {
|
|
178
|
+
stack = stack.filter((b) => b.isLive());
|
|
179
|
+
if (stack.length >= MAX_BINDING_STACK) {
|
|
180
|
+
stack = stack.slice(stack.length - (MAX_BINDING_STACK - 1));
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
this.setAmbientStack([...stack, binding]);
|
|
184
|
+
}
|
|
185
|
+
remove(binding) {
|
|
186
|
+
binding.markDead();
|
|
187
|
+
const stack = this.getStack();
|
|
188
|
+
const pruned = stack.filter((b) => b !== binding && b.isLive());
|
|
189
|
+
if (pruned.length !== stack.length) {
|
|
190
|
+
this.setAmbientStack(pruned);
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
runWith(binding, callback) {
|
|
194
|
+
this.maybeAdoptAsyncLocalStorage();
|
|
195
|
+
if (this._als) {
|
|
196
|
+
return this._als.run([...this.getStack(), binding], callback);
|
|
197
|
+
}
|
|
198
|
+
const previous = this._syncStack;
|
|
199
|
+
this._syncStack = [...previous, binding];
|
|
200
|
+
try {
|
|
201
|
+
return callback();
|
|
202
|
+
} finally {
|
|
203
|
+
this._syncStack = previous;
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
current() {
|
|
207
|
+
const stack = this.getStack();
|
|
208
|
+
if (stack.length === 0) return void 0;
|
|
209
|
+
const top = stack[stack.length - 1];
|
|
210
|
+
if (top.isLive()) return top;
|
|
211
|
+
const pruned = stack.filter((b) => b.isLive());
|
|
212
|
+
this.setAmbientStack(pruned);
|
|
213
|
+
return pruned.length > 0 ? pruned[pruned.length - 1] : void 0;
|
|
214
|
+
}
|
|
215
|
+
warnNoAmbientBindOnce() {
|
|
216
|
+
if (this._warnedNoAmbientBind) return;
|
|
217
|
+
this._warnedNoAmbientBind = true;
|
|
218
|
+
console.warn(this.noAmbientBindWarning);
|
|
219
|
+
}
|
|
220
|
+
};
|
|
221
|
+
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.";
|
|
222
|
+
var ROUTING_STORAGE_KEY = /* @__PURE__ */ Symbol.for("raindrop.tracing.routingContextStorage");
|
|
223
|
+
function routingStorage() {
|
|
224
|
+
const holder = globalThis;
|
|
225
|
+
let storage = holder[ROUTING_STORAGE_KEY];
|
|
226
|
+
if (!storage) {
|
|
227
|
+
storage = new ContextStackStorage(NO_AMBIENT_ROUTING_BIND_WARNING);
|
|
228
|
+
holder[ROUTING_STORAGE_KEY] = storage;
|
|
229
|
+
}
|
|
230
|
+
return storage;
|
|
231
|
+
}
|
|
232
|
+
function currentRoutingBinding() {
|
|
233
|
+
const bound = routingStorage().current();
|
|
234
|
+
if (!bound) return void 0;
|
|
235
|
+
return {
|
|
236
|
+
projectId: bound.projectId,
|
|
237
|
+
authHint: bound.authHint,
|
|
238
|
+
...bound.appGit ? { appGit: bound.appGit } : {},
|
|
239
|
+
...bound.appGitSource ? { appGitSource: bound.appGitSource } : {}
|
|
240
|
+
};
|
|
241
|
+
}
|
|
242
|
+
var APP_COMMIT_SHA = "raindrop.app.commit_sha";
|
|
243
|
+
var APP_COMMIT_DIRTY = "raindrop.app.commit_dirty";
|
|
244
|
+
var APP_BRANCH = "raindrop.app.branch";
|
|
245
|
+
var APP_GIT_KEYS = [APP_COMMIT_SHA, APP_COMMIT_DIRTY, APP_BRANCH];
|
|
246
|
+
var own = (value, key) => Object.prototype.hasOwnProperty.call(value, key);
|
|
247
|
+
function appGitExplicitKeys(properties) {
|
|
248
|
+
const keys = /* @__PURE__ */ new Set();
|
|
249
|
+
if (!properties) return keys;
|
|
250
|
+
for (const key of APP_GIT_KEYS) {
|
|
251
|
+
if (own(properties, key)) keys.add(key);
|
|
252
|
+
}
|
|
253
|
+
return keys;
|
|
254
|
+
}
|
|
255
|
+
function mergeAppGitSnapshot(base, properties, explicitKeys = /* @__PURE__ */ new Set()) {
|
|
256
|
+
try {
|
|
257
|
+
const result = { ...base };
|
|
258
|
+
if (properties && own(properties, APP_COMMIT_SHA) && properties[APP_COMMIT_SHA] !== result[APP_COMMIT_SHA]) {
|
|
259
|
+
if (!explicitKeys.has(APP_COMMIT_DIRTY) && !own(properties, APP_COMMIT_DIRTY)) {
|
|
260
|
+
delete result[APP_COMMIT_DIRTY];
|
|
261
|
+
}
|
|
262
|
+
if (!explicitKeys.has(APP_BRANCH) && !own(properties, APP_BRANCH)) {
|
|
263
|
+
delete result[APP_BRANCH];
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
for (const key of APP_GIT_KEYS) {
|
|
267
|
+
if (properties && own(properties, key)) result[key] = properties[key];
|
|
268
|
+
}
|
|
269
|
+
return Object.freeze(result);
|
|
270
|
+
} catch (e) {
|
|
271
|
+
return Object.freeze({});
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
function validAppCommitSha(value) {
|
|
275
|
+
if (typeof value !== "string" || value.length > 128) return void 0;
|
|
276
|
+
const cleaned = value.trim();
|
|
277
|
+
return /^(?:[a-fA-F0-9]{40}|[a-fA-F0-9]{64})$/.test(cleaned) ? cleaned.toLowerCase() : void 0;
|
|
278
|
+
}
|
|
279
|
+
function shortString(value) {
|
|
280
|
+
if (typeof value !== "string" || value.length > 1024) return void 0;
|
|
281
|
+
const cleaned = value.trim();
|
|
282
|
+
return cleaned.length > 0 ? cleaned : void 0;
|
|
283
|
+
}
|
|
284
|
+
function flag(value) {
|
|
285
|
+
if (value === true || value === "true" || value === "1") return true;
|
|
286
|
+
if (value === false || value === "false" || value === "0") return false;
|
|
287
|
+
return void 0;
|
|
288
|
+
}
|
|
289
|
+
function environment() {
|
|
290
|
+
try {
|
|
291
|
+
return typeof process === "undefined" ? {} : process.env;
|
|
292
|
+
} catch (e) {
|
|
293
|
+
return {};
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
var DEPLOYMENTS = [
|
|
297
|
+
["VERCEL", "VERCEL_GIT_COMMIT_SHA", "VERCEL_GIT_COMMIT_REF"],
|
|
298
|
+
["NETLIFY", "COMMIT_REF", "BRANCH"],
|
|
299
|
+
["RAILWAY_ENVIRONMENT_NAME", "RAILWAY_GIT_COMMIT_SHA", "RAILWAY_GIT_BRANCH"],
|
|
300
|
+
["RAILWAY_ENVIRONMENT", "RAILWAY_GIT_COMMIT_SHA", "RAILWAY_GIT_BRANCH"],
|
|
301
|
+
["RENDER", "RENDER_GIT_COMMIT", "RENDER_GIT_BRANCH"],
|
|
302
|
+
["DYNO", "HEROKU_BUILD_COMMIT", ""],
|
|
303
|
+
["DYNO", "HEROKU_SLUG_COMMIT", ""],
|
|
304
|
+
["AWS_APP_ID", "AWS_COMMIT_ID", "AWS_BRANCH"],
|
|
305
|
+
["WORKERS_CI", "WORKERS_CI_COMMIT_SHA", "WORKERS_CI_BRANCH"]
|
|
306
|
+
];
|
|
307
|
+
var CI_SOURCES = [
|
|
308
|
+
["GITHUB_ACTIONS", "GITHUB_SHA", "GITHUB_REF_NAME"],
|
|
309
|
+
["GITLAB_CI", "CI_COMMIT_SHA", "CI_COMMIT_REF_NAME"],
|
|
310
|
+
["CIRCLECI", "CIRCLE_SHA1", "CIRCLE_BRANCH"]
|
|
311
|
+
];
|
|
312
|
+
function detectedSource(env, table, detectBranch) {
|
|
313
|
+
for (const row of table) {
|
|
314
|
+
const [marker, shaKey, branchKey] = row;
|
|
315
|
+
if (!marker || !shaKey || !shortString(env[marker]) || flag(env[marker]) === false) continue;
|
|
316
|
+
const commitSha = validAppCommitSha(env[shaKey]);
|
|
317
|
+
if (commitSha)
|
|
318
|
+
return {
|
|
319
|
+
commitSha,
|
|
320
|
+
...detectBranch && branchKey ? { branch: shortString(env[branchKey]) } : {}
|
|
321
|
+
};
|
|
322
|
+
}
|
|
323
|
+
return {};
|
|
324
|
+
}
|
|
325
|
+
var AppGitContextImpl = class {
|
|
326
|
+
constructor(options, runtime = {}) {
|
|
327
|
+
this.defaults = {};
|
|
328
|
+
this.explicit = {};
|
|
329
|
+
this.explicitKeys = /* @__PURE__ */ new Set();
|
|
330
|
+
this.disposed = false;
|
|
331
|
+
this.operations = /* @__PURE__ */ new Map();
|
|
332
|
+
this.operationOverflow = false;
|
|
333
|
+
this.detectBranch = false;
|
|
334
|
+
this.disabled = false;
|
|
335
|
+
var _a, _b, _c, _d, _e, _f;
|
|
336
|
+
try {
|
|
337
|
+
if (options === false) {
|
|
338
|
+
this.disabled = true;
|
|
339
|
+
return;
|
|
340
|
+
}
|
|
341
|
+
const opts = options != null ? options : {};
|
|
342
|
+
const env = (_a = runtime.env) != null ? _a : environment();
|
|
343
|
+
const detectBranch = (_c = (_b = flag(opts.detectBranch)) != null ? _b : flag(env.RAINDROP_GIT_DETECT_BRANCH)) != null ? _c : false;
|
|
344
|
+
this.detectBranch = detectBranch;
|
|
345
|
+
const collectBranch = detectBranch || runtime.captureLegacyReplayBranch === true;
|
|
346
|
+
const autoDetect = runtime.allowDiscovery === false ? false : (_e = (_d = flag(opts.autoDetect)) != null ? _d : flag(env.RAINDROP_GIT_AUTO_DETECT)) != null ? _e : true;
|
|
347
|
+
const configuredSha = opts.commitSha;
|
|
348
|
+
const explicitSha = configuredSha === void 0 ? env.RAINDROP_COMMIT_SHA : configuredSha;
|
|
349
|
+
if (explicitSha === null) this.explicit[APP_COMMIT_SHA] = null;
|
|
350
|
+
else if (typeof explicitSha === "string" && validAppCommitSha(explicitSha))
|
|
351
|
+
this.explicit[APP_COMMIT_SHA] = explicitSha;
|
|
352
|
+
const configuredDirty = opts.commitDirty;
|
|
353
|
+
const explicitDirty = configuredDirty === void 0 ? flag(env.RAINDROP_COMMIT_DIRTY) : configuredDirty;
|
|
354
|
+
if (explicitDirty === null || typeof explicitDirty === "boolean")
|
|
355
|
+
this.explicit[APP_COMMIT_DIRTY] = explicitDirty;
|
|
356
|
+
const configuredBranch = opts.branch;
|
|
357
|
+
const explicitBranch = configuredBranch === void 0 ? env.RAINDROP_BRANCH : configuredBranch;
|
|
358
|
+
if (explicitBranch === null) this.explicit[APP_BRANCH] = null;
|
|
359
|
+
else if (typeof explicitBranch === "string" && explicitBranch.length <= 1024)
|
|
360
|
+
this.explicit[APP_BRANCH] = explicitBranch;
|
|
361
|
+
this.explicitKeys = appGitExplicitKeys(this.explicit);
|
|
362
|
+
this.defaults = { ...this.explicit };
|
|
363
|
+
if (!autoDetect || explicitSha !== void 0) return;
|
|
364
|
+
const sourceDirectory = (_f = shortString(opts.sourceDirectory)) != null ? _f : shortString(env.RAINDROP_GIT_SOURCE_DIRECTORY);
|
|
365
|
+
if (runtime.allowLocalGit === false && !sourceDirectory) return;
|
|
366
|
+
const deploy = sourceDirectory ? {} : detectedSource(env, DEPLOYMENTS, collectBranch);
|
|
367
|
+
if (deploy.commitSha) {
|
|
368
|
+
this.accept(deploy);
|
|
369
|
+
return;
|
|
370
|
+
}
|
|
371
|
+
const fallback = sourceDirectory ? {} : detectedSource(env, CI_SOURCES, collectBranch);
|
|
372
|
+
if (runtime.resolveLocal && (runtime.allowLocalGit !== false || sourceDirectory)) {
|
|
373
|
+
this.cancel = runtime.resolveLocal(sourceDirectory, collectBranch, (result) => {
|
|
374
|
+
try {
|
|
375
|
+
if (!this.disposed) this.accept(result.commitSha ? result : fallback);
|
|
376
|
+
} catch (e) {
|
|
377
|
+
}
|
|
378
|
+
});
|
|
379
|
+
} else this.accept(fallback);
|
|
380
|
+
} catch (e) {
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
accept(result) {
|
|
384
|
+
const sha = validAppCommitSha(result.commitSha);
|
|
385
|
+
if (!sha) return;
|
|
386
|
+
this.replayBranch = shortString(result.branch);
|
|
387
|
+
this.defaults = {
|
|
388
|
+
[APP_COMMIT_SHA]: sha,
|
|
389
|
+
...typeof result.commitDirty === "boolean" ? { [APP_COMMIT_DIRTY]: result.commitDirty } : {},
|
|
390
|
+
...this.detectBranch && this.replayBranch ? { [APP_BRANCH]: this.replayBranch } : {},
|
|
391
|
+
...this.explicit
|
|
392
|
+
};
|
|
393
|
+
}
|
|
394
|
+
snapshot(properties) {
|
|
395
|
+
var _a;
|
|
396
|
+
try {
|
|
397
|
+
const binding = currentRoutingBinding();
|
|
398
|
+
const base = this.disabled && (binding == null ? void 0 : binding.appGitSource) !== "replay-override" ? {} : (_a = binding == null ? void 0 : binding.appGit) != null ? _a : this.defaults;
|
|
399
|
+
return this.mergeSnapshot(base, properties);
|
|
400
|
+
} catch (e) {
|
|
401
|
+
return Object.freeze({});
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
/** Safe defaults when no operation/span start was observed; never infer identity. */
|
|
405
|
+
snapshotExplicit(properties, eventId) {
|
|
406
|
+
try {
|
|
407
|
+
const base = { ...this.explicit };
|
|
408
|
+
const operation = eventId ? this.operations.get(eventId) : void 0;
|
|
409
|
+
if (operation) {
|
|
410
|
+
for (const key of operation.explicitKeys) base[key] = operation.snapshot[key];
|
|
411
|
+
}
|
|
412
|
+
return this.mergeSnapshot(base, properties, new Set(Object.keys(base)));
|
|
413
|
+
} catch (e) {
|
|
414
|
+
return mergeAppGitSnapshot({}, properties);
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
/** Existing replay branch reporting stays separate from opt-in event properties. */
|
|
418
|
+
snapshotForReplay() {
|
|
419
|
+
const snapshot = this.snapshot();
|
|
420
|
+
if (this.replayBranch && !own(snapshot, APP_BRANCH) && snapshot[APP_COMMIT_SHA] === this.defaults[APP_COMMIT_SHA]) {
|
|
421
|
+
return Object.freeze({ ...snapshot, [APP_BRANCH]: this.replayBranch });
|
|
422
|
+
}
|
|
423
|
+
return snapshot;
|
|
424
|
+
}
|
|
425
|
+
/** Merge a frozen span snapshot without losing client-authored provenance. */
|
|
426
|
+
mergeSnapshot(base, properties, explicitKeys = this.explicitKeys) {
|
|
427
|
+
return mergeAppGitSnapshot(base, properties, /* @__PURE__ */ new Set([...this.explicitKeys, ...explicitKeys]));
|
|
428
|
+
}
|
|
429
|
+
/** Shippers belonging to one client share this bounded operation registry. */
|
|
430
|
+
forOperation(eventId, properties, owner) {
|
|
431
|
+
if (!eventId) return this.snapshot(properties);
|
|
432
|
+
let operation = this.operations.get(eventId);
|
|
433
|
+
if (!operation) {
|
|
434
|
+
if (this.operations.size >= 1e4) this.operationOverflow = true;
|
|
435
|
+
if (this.operationOverflow) return this.mergeSnapshot({}, properties);
|
|
436
|
+
operation = {
|
|
437
|
+
snapshot: this.snapshot(properties),
|
|
438
|
+
owners: /* @__PURE__ */ new Set(),
|
|
439
|
+
unowned: owner === void 0,
|
|
440
|
+
explicitKeys: appGitExplicitKeys(properties)
|
|
441
|
+
};
|
|
442
|
+
this.operations.set(eventId, operation);
|
|
443
|
+
} else if (properties && APP_GIT_KEYS.some((key) => own(properties, key))) {
|
|
444
|
+
const explicitKeys = /* @__PURE__ */ new Set([...this.explicitKeys, ...operation.explicitKeys]);
|
|
445
|
+
operation.snapshot = this.mergeSnapshot(operation.snapshot, properties, explicitKeys);
|
|
446
|
+
for (const key of appGitExplicitKeys(properties)) operation.explicitKeys.add(key);
|
|
447
|
+
}
|
|
448
|
+
if (!owner) operation.unowned = true;
|
|
449
|
+
if (owner) operation.owners.add(owner);
|
|
450
|
+
return operation.snapshot;
|
|
451
|
+
}
|
|
452
|
+
releaseOperation(eventId, owner) {
|
|
453
|
+
const operation = this.operations.get(eventId);
|
|
454
|
+
if (!operation) return;
|
|
455
|
+
operation.owners.delete(owner);
|
|
456
|
+
if (operation.owners.size === 0 && !operation.unowned) this.operations.delete(eventId);
|
|
457
|
+
}
|
|
458
|
+
finishOperation(eventId) {
|
|
459
|
+
this.operations.delete(eventId);
|
|
460
|
+
}
|
|
461
|
+
dispose() {
|
|
462
|
+
var _a;
|
|
463
|
+
this.disposed = true;
|
|
464
|
+
try {
|
|
465
|
+
(_a = this.cancel) == null ? void 0 : _a.call(this);
|
|
466
|
+
} catch (e) {
|
|
467
|
+
}
|
|
468
|
+
}
|
|
469
|
+
};
|
|
470
|
+
var AppGitContext = AppGitContextImpl;
|
|
471
|
+
function createAppGitContext(options, runtime = {}) {
|
|
472
|
+
return new AppGitContext(options, runtime);
|
|
473
|
+
}
|
|
474
|
+
function withAppGitProperties(properties, snapshot) {
|
|
475
|
+
try {
|
|
476
|
+
const merged = { ...properties };
|
|
477
|
+
for (const key of APP_GIT_KEYS)
|
|
478
|
+
if (!own(merged, key) && own(snapshot, key)) merged[key] = snapshot[key];
|
|
479
|
+
return merged;
|
|
480
|
+
} catch (e) {
|
|
481
|
+
return properties != null ? properties : {};
|
|
482
|
+
}
|
|
483
|
+
}
|
|
484
|
+
function withAppGitAttributes(attributes, snapshot) {
|
|
485
|
+
try {
|
|
486
|
+
const present = new Set(attributes.flatMap((attr) => attr ? [attr.key] : []));
|
|
487
|
+
const added = [];
|
|
488
|
+
for (const key of APP_GIT_KEYS) {
|
|
489
|
+
if (present.has(key) || present.has(`ai.telemetry.metadata.${key}`) || present.has(`traceloop.association.properties.${key}`))
|
|
490
|
+
continue;
|
|
491
|
+
const value = snapshot[key];
|
|
492
|
+
if (typeof value === "string") added.push({ key, value: { stringValue: value } });
|
|
493
|
+
else if (typeof value === "boolean") added.push({ key, value: { boolValue: value } });
|
|
494
|
+
}
|
|
495
|
+
return added.length ? [...attributes, ...added] : attributes;
|
|
496
|
+
} catch (e) {
|
|
497
|
+
return attributes;
|
|
498
|
+
}
|
|
499
|
+
}
|
|
500
|
+
function appGitPropertiesFromAttributes(attributes) {
|
|
501
|
+
var _a, _b, _c;
|
|
502
|
+
const properties = {};
|
|
503
|
+
try {
|
|
504
|
+
for (const attr of attributes) {
|
|
505
|
+
if (!attr) continue;
|
|
506
|
+
for (const key of APP_GIT_KEYS) {
|
|
507
|
+
if (attr.key === key || attr.key === `ai.telemetry.metadata.${key}` || attr.key === `traceloop.association.properties.${key}`) {
|
|
508
|
+
properties[key] = (_c = (_b = (_a = attr.value.stringValue) != null ? _a : attr.value.boolValue) != null ? _b : attr.value.intValue) != null ? _c : null;
|
|
509
|
+
}
|
|
510
|
+
}
|
|
511
|
+
}
|
|
512
|
+
} catch (e) {
|
|
513
|
+
}
|
|
514
|
+
return properties;
|
|
515
|
+
}
|
|
2
516
|
function getCrypto() {
|
|
3
517
|
const c = globalThis.crypto;
|
|
4
518
|
return c;
|
|
@@ -53,6 +567,25 @@ function base64Encode(bytes) {
|
|
|
53
567
|
}
|
|
54
568
|
return out;
|
|
55
569
|
}
|
|
570
|
+
function base64ToHex(value) {
|
|
571
|
+
if (!value) return "";
|
|
572
|
+
const maybeBuffer = globalThis.Buffer;
|
|
573
|
+
if (maybeBuffer) {
|
|
574
|
+
return maybeBuffer.from(value, "base64").toString("hex");
|
|
575
|
+
}
|
|
576
|
+
const atobFn = globalThis.atob;
|
|
577
|
+
if (typeof atobFn !== "function") return "";
|
|
578
|
+
try {
|
|
579
|
+
const binary = atobFn(value);
|
|
580
|
+
let hex = "";
|
|
581
|
+
for (let i = 0; i < binary.length; i++) {
|
|
582
|
+
hex += (binary.charCodeAt(i) & 255).toString(16).padStart(2, "0");
|
|
583
|
+
}
|
|
584
|
+
return hex;
|
|
585
|
+
} catch (e) {
|
|
586
|
+
return "";
|
|
587
|
+
}
|
|
588
|
+
}
|
|
56
589
|
function generateId() {
|
|
57
590
|
return randomUUID();
|
|
58
591
|
}
|
|
@@ -87,7 +620,7 @@ function runWithTracingSuppressed(fn) {
|
|
|
87
620
|
var DEFAULT_REQUEST_TIMEOUT_MS = 3e4;
|
|
88
621
|
var MAX_RETRY_DELAY_MS = 3e4;
|
|
89
622
|
function wait(ms) {
|
|
90
|
-
return new Promise((
|
|
623
|
+
return new Promise((resolve2) => setTimeout(resolve2, ms));
|
|
91
624
|
}
|
|
92
625
|
function formatEndpoint(endpoint) {
|
|
93
626
|
if (!endpoint) return void 0;
|
|
@@ -124,9 +657,9 @@ async function raceWithTimeout(promise, timeoutMs) {
|
|
|
124
657
|
() => true,
|
|
125
658
|
() => true
|
|
126
659
|
),
|
|
127
|
-
new Promise((
|
|
660
|
+
new Promise((resolve2) => {
|
|
128
661
|
var _a;
|
|
129
|
-
timer = setTimeout(() =>
|
|
662
|
+
timer = setTimeout(() => resolve2(false), Math.max(0, timeoutMs));
|
|
130
663
|
(_a = timer.unref) == null ? void 0 : _a.call(timer);
|
|
131
664
|
})
|
|
132
665
|
]);
|
|
@@ -197,6 +730,7 @@ async function postJson(url, body, headers, opts) {
|
|
|
197
730
|
const resp = await runWithTracingSuppressed(
|
|
198
731
|
() => fetch(url, {
|
|
199
732
|
method: "POST",
|
|
733
|
+
redirect: headers["X-Raindrop-Replay-Id"] !== void 0 ? "error" : "follow",
|
|
200
734
|
headers: {
|
|
201
735
|
"Content-Type": "application/json",
|
|
202
736
|
...headers
|
|
@@ -267,6 +801,11 @@ function attrInt(key, value) {
|
|
|
267
801
|
if (!Number.isFinite(value)) return void 0;
|
|
268
802
|
return { key, value: { intValue: String(Math.trunc(value)) } };
|
|
269
803
|
}
|
|
804
|
+
function attrDouble(key, value) {
|
|
805
|
+
if (value === void 0) return void 0;
|
|
806
|
+
if (!Number.isFinite(value)) return void 0;
|
|
807
|
+
return { key, value: { doubleValue: value } };
|
|
808
|
+
}
|
|
270
809
|
function buildOtlpSpan(args) {
|
|
271
810
|
const attrs = args.attributes.filter((x) => x !== void 0);
|
|
272
811
|
const span = {
|
|
@@ -360,26 +899,29 @@ function resolveLocalDebuggerBaseUrl(baseUrl) {
|
|
|
360
899
|
if (shouldAutoEnableLocalWorkshop()) return DEFAULT_LOCAL_WORKSHOP_URL;
|
|
361
900
|
return null;
|
|
362
901
|
}
|
|
902
|
+
var LOCAL_DEBUGGER_MIRROR_TIMEOUT_MS = 2e3;
|
|
363
903
|
function mirrorTraceExportToLocalDebugger(body, options = {}) {
|
|
364
904
|
var _a;
|
|
365
905
|
const baseUrl = resolveLocalDebuggerBaseUrl(options.baseUrl);
|
|
366
|
-
if (!baseUrl) return;
|
|
367
|
-
|
|
906
|
+
if (!baseUrl) return Promise.resolve();
|
|
907
|
+
return postJson(`${baseUrl}traces`, body, {}, {
|
|
368
908
|
maxAttempts: 1,
|
|
369
909
|
debug: (_a = options.debug) != null ? _a : false,
|
|
370
|
-
sdkName: options.sdkName
|
|
910
|
+
sdkName: options.sdkName,
|
|
911
|
+
timeoutMs: LOCAL_DEBUGGER_MIRROR_TIMEOUT_MS
|
|
371
912
|
}).catch(() => {
|
|
372
913
|
});
|
|
373
914
|
}
|
|
374
915
|
function mirrorPartialEventToLocalDebugger(event, options = {}) {
|
|
375
916
|
var _a;
|
|
376
917
|
const baseUrl = resolveLocalDebuggerBaseUrl(options.baseUrl);
|
|
377
|
-
if (!baseUrl) return;
|
|
918
|
+
if (!baseUrl) return Promise.resolve();
|
|
378
919
|
const headers = options.writeKey ? { Authorization: `Bearer ${options.writeKey}` } : {};
|
|
379
|
-
|
|
920
|
+
return postJson(`${baseUrl}events/track_partial`, event, headers, {
|
|
380
921
|
maxAttempts: 1,
|
|
381
922
|
debug: (_a = options.debug) != null ? _a : false,
|
|
382
|
-
sdkName: options.sdkName
|
|
923
|
+
sdkName: options.sdkName,
|
|
924
|
+
timeoutMs: LOCAL_DEBUGGER_MIRROR_TIMEOUT_MS
|
|
383
925
|
}).catch(() => {
|
|
384
926
|
});
|
|
385
927
|
}
|
|
@@ -404,6 +946,13 @@ function projectIdHeaders(projectId) {
|
|
|
404
946
|
}
|
|
405
947
|
var SHUTDOWN_DEADLINE_MS = 1e4;
|
|
406
948
|
var POST_SHUTDOWN_TIMEOUT_MS = 5e3;
|
|
949
|
+
function appGitOwnerId(prefix) {
|
|
950
|
+
try {
|
|
951
|
+
return `${prefix}:${randomUUID()}`;
|
|
952
|
+
} catch (e) {
|
|
953
|
+
return `${prefix}:${Date.now().toString(36)}:${Math.random().toString(36).slice(2)}`;
|
|
954
|
+
}
|
|
955
|
+
}
|
|
407
956
|
function mergePatches(target, source) {
|
|
408
957
|
var _a, _b, _c, _d, _e, _f, _g, _h, _i;
|
|
409
958
|
const out = { ...target, ...source };
|
|
@@ -453,22 +1002,25 @@ function eventTelemetryProperties(patch) {
|
|
|
453
1002
|
}
|
|
454
1003
|
var EventShipper = class {
|
|
455
1004
|
constructor(opts) {
|
|
1005
|
+
this.appGitOwner = appGitOwnerId("event");
|
|
456
1006
|
this.buffers = /* @__PURE__ */ new Map();
|
|
457
1007
|
this.sticky = /* @__PURE__ */ new Map();
|
|
458
1008
|
this.timers = /* @__PURE__ */ new Map();
|
|
459
1009
|
this.inFlight = /* @__PURE__ */ new Set();
|
|
460
1010
|
this.hasShutdown = false;
|
|
461
|
-
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
462
|
-
this.
|
|
463
|
-
this.
|
|
1011
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _i;
|
|
1012
|
+
this.appGitContext = (_a = opts.appGitContext) != null ? _a : createAppGitContext(opts.appGit);
|
|
1013
|
+
this.ownsAppGitContext = opts.appGitContext === void 0;
|
|
1014
|
+
this.writeKey = (_b = opts.writeKey) == null ? void 0 : _b.trim();
|
|
1015
|
+
this.baseUrl = (_c = formatEndpoint(opts.endpoint)) != null ? _c : "https://api.raindrop.ai/v1/";
|
|
464
1016
|
this.enabled = opts.enabled !== false;
|
|
465
1017
|
this.debug = opts.debug;
|
|
466
|
-
this.partialFlushMs = (
|
|
467
|
-
this.sdkName = (
|
|
1018
|
+
this.partialFlushMs = (_d = opts.partialFlushMs) != null ? _d : 1e3;
|
|
1019
|
+
this.sdkName = (_e = opts.sdkName) != null ? _e : "core";
|
|
468
1020
|
this.prefix = `[raindrop-ai/${this.sdkName}]`;
|
|
469
|
-
this.defaultEventName = (
|
|
1021
|
+
this.defaultEventName = (_f = opts.defaultEventName) != null ? _f : "ai_generation";
|
|
470
1022
|
this.maxTextFieldCharsOpt = opts.maxTextFieldChars;
|
|
471
|
-
this.localDebuggerUrl = (
|
|
1023
|
+
this.localDebuggerUrl = (_g = resolveLocalDebuggerBaseUrl(opts.localDebuggerUrl)) != null ? _g : void 0;
|
|
472
1024
|
if (this.debug && this.localDebuggerUrl) {
|
|
473
1025
|
console.log(`${this.prefix} Local debugger mirroring: ${this.localDebuggerUrl}`);
|
|
474
1026
|
}
|
|
@@ -479,8 +1031,8 @@ var EventShipper = class {
|
|
|
479
1031
|
const isNode = typeof process !== "undefined" && typeof process.version === "string";
|
|
480
1032
|
this.context = {
|
|
481
1033
|
library: {
|
|
482
|
-
name: (
|
|
483
|
-
version: (
|
|
1034
|
+
name: (_h = opts.libraryName) != null ? _h : "@raindrop-ai/core",
|
|
1035
|
+
version: (_i = opts.libraryVersion) != null ? _i : "0.0.0"
|
|
484
1036
|
},
|
|
485
1037
|
metadata: {
|
|
486
1038
|
jsRuntime: isNode ? "node" : "web",
|
|
@@ -488,6 +1040,9 @@ var EventShipper = class {
|
|
|
488
1040
|
}
|
|
489
1041
|
};
|
|
490
1042
|
}
|
|
1043
|
+
ownAppGitContextForShutdown() {
|
|
1044
|
+
this.ownsAppGitContext = true;
|
|
1045
|
+
}
|
|
491
1046
|
isDebugEnabled() {
|
|
492
1047
|
return this.debug;
|
|
493
1048
|
}
|
|
@@ -536,6 +1091,15 @@ var EventShipper = class {
|
|
|
536
1091
|
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k;
|
|
537
1092
|
if (!this.enabled) return;
|
|
538
1093
|
if (!eventId || !eventId.trim()) return;
|
|
1094
|
+
const capturedSticky = this.sticky.get(eventId);
|
|
1095
|
+
const eventAlreadyKnown = capturedSticky !== void 0 || this.buffers.has(eventId);
|
|
1096
|
+
const destination = currentReplayTraceDestination();
|
|
1097
|
+
const cloudReplay = destination !== void 0 && destination.kind !== "workshop";
|
|
1098
|
+
if ((capturedSticky == null ? void 0 : capturedSticky.replayOnly) === true || !eventAlreadyKnown && cloudReplay) {
|
|
1099
|
+
if (patch.isPending === false) this.sticky.delete(eventId);
|
|
1100
|
+
else this.sticky.set(eventId, { ...capturedSticky, replayOnly: true });
|
|
1101
|
+
return;
|
|
1102
|
+
}
|
|
539
1103
|
const maxChars = resolveMaxTextFieldChars(this.maxTextFieldCharsOpt);
|
|
540
1104
|
if (typeof patch.input === "string" && patch.input.length > maxChars) {
|
|
541
1105
|
patch = { ...patch, input: capText(patch.input, maxChars) };
|
|
@@ -557,6 +1121,13 @@ var EventShipper = class {
|
|
|
557
1121
|
}
|
|
558
1122
|
const sticky = (_c = this.sticky.get(eventId)) != null ? _c : {};
|
|
559
1123
|
const existing = (_d = this.buffers.get(eventId)) != null ? _d : {};
|
|
1124
|
+
patch = {
|
|
1125
|
+
...patch,
|
|
1126
|
+
properties: withAppGitProperties(
|
|
1127
|
+
patch.properties,
|
|
1128
|
+
this.appGitContext.forOperation(eventId, patch.properties, this.appGitOwner)
|
|
1129
|
+
)
|
|
1130
|
+
};
|
|
560
1131
|
const merged = mergePatches(existing, patch);
|
|
561
1132
|
merged.isPending = (_g = (_f = (_e = patch.isPending) != null ? _e : existing.isPending) != null ? _f : sticky.isPending) != null ? _g : true;
|
|
562
1133
|
this.buffers.set(eventId, merged);
|
|
@@ -570,6 +1141,8 @@ var EventShipper = class {
|
|
|
570
1141
|
if (t) clearTimeout(t);
|
|
571
1142
|
if (merged.isPending === false) {
|
|
572
1143
|
await this.flushOne(eventId);
|
|
1144
|
+
if (this.appGitContext.releaseOperation) this.appGitContext.releaseOperation(eventId, this.appGitOwner);
|
|
1145
|
+
else this.appGitContext.finishOperation(eventId);
|
|
573
1146
|
return;
|
|
574
1147
|
}
|
|
575
1148
|
const timeout = setTimeout(() => {
|
|
@@ -594,15 +1167,21 @@ var EventShipper = class {
|
|
|
594
1167
|
try {
|
|
595
1168
|
for (const t of this.timers.values()) clearTimeout(t);
|
|
596
1169
|
this.timers.clear();
|
|
1170
|
+
for (const [eventId, sticky] of this.sticky) {
|
|
1171
|
+
if (sticky.replayOnly) this.sticky.delete(eventId);
|
|
1172
|
+
}
|
|
597
1173
|
const settled = await raceWithTimeout(this.flush(), SHUTDOWN_DEADLINE_MS);
|
|
598
1174
|
if (!settled) this.warnShutdownDrop("in-flight request(s) at shutdown");
|
|
599
1175
|
} finally {
|
|
600
1176
|
this.shutdownDeadlineAt = void 0;
|
|
1177
|
+
if (this.ownsAppGitContext) this.appGitContext.dispose();
|
|
601
1178
|
}
|
|
602
1179
|
}
|
|
603
1180
|
async trackSignal(signal) {
|
|
604
1181
|
var _a, _b;
|
|
605
1182
|
if (!this.enabled) return;
|
|
1183
|
+
const destination = currentReplayTraceDestination();
|
|
1184
|
+
if (destination && destination.kind !== "workshop") return;
|
|
606
1185
|
const body = [
|
|
607
1186
|
{
|
|
608
1187
|
event_id: signal.eventId,
|
|
@@ -637,6 +1216,8 @@ var EventShipper = class {
|
|
|
637
1216
|
}
|
|
638
1217
|
async identify(users) {
|
|
639
1218
|
if (!this.enabled) return;
|
|
1219
|
+
const destination = currentReplayTraceDestination();
|
|
1220
|
+
if (destination && destination.kind !== "workshop") return;
|
|
640
1221
|
const list = Array.isArray(users) ? users : [users];
|
|
641
1222
|
const body = list.filter((user) => {
|
|
642
1223
|
if (!(user == null ? void 0 : user.userId) || !user.userId.trim()) {
|
|
@@ -689,8 +1270,9 @@ var EventShipper = class {
|
|
|
689
1270
|
this.buffers.delete(eventId);
|
|
690
1271
|
if (!accumulated) return;
|
|
691
1272
|
const sticky = (_a = this.sticky.get(eventId)) != null ? _a : {};
|
|
692
|
-
const
|
|
693
|
-
const
|
|
1273
|
+
const isPending = (_c = (_b = accumulated.isPending) != null ? _b : sticky.isPending) != null ? _c : true;
|
|
1274
|
+
const eventName = (_e = (_d = accumulated.eventName) != null ? _d : sticky.eventName) != null ? _e : this.defaultEventName;
|
|
1275
|
+
const userId = (_f = accumulated.userId) != null ? _f : sticky.userId;
|
|
694
1276
|
if (!userId) {
|
|
695
1277
|
if (this.debug) {
|
|
696
1278
|
console.warn(`${this.prefix} skipping track_partial for ${eventId}: missing userId`);
|
|
@@ -698,14 +1280,13 @@ var EventShipper = class {
|
|
|
698
1280
|
this.sticky.delete(eventId);
|
|
699
1281
|
return;
|
|
700
1282
|
}
|
|
701
|
-
const { wizardSession, ...restProperties } = (
|
|
1283
|
+
const { wizardSession, ...restProperties } = (_g = accumulated.properties) != null ? _g : {};
|
|
702
1284
|
let telemetryProperties = {};
|
|
703
1285
|
try {
|
|
704
1286
|
telemetryProperties = eventTelemetryProperties(accumulated);
|
|
705
1287
|
} catch (e) {
|
|
706
1288
|
}
|
|
707
|
-
const convoId = (
|
|
708
|
-
const isPending = (_h = (_g = accumulated.isPending) != null ? _g : sticky.isPending) != null ? _h : true;
|
|
1289
|
+
const convoId = (_h = accumulated.convoId) != null ? _h : sticky.convoId;
|
|
709
1290
|
const payload = {
|
|
710
1291
|
event_id: eventId,
|
|
711
1292
|
user_id: userId,
|
|
@@ -747,29 +1328,30 @@ var EventShipper = class {
|
|
|
747
1328
|
endpoint: url
|
|
748
1329
|
});
|
|
749
1330
|
}
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
});
|
|
757
|
-
}
|
|
1331
|
+
const mirror = this.localDebuggerUrl ? mirrorPartialEventToLocalDebugger(payload, {
|
|
1332
|
+
baseUrl: this.localDebuggerUrl,
|
|
1333
|
+
writeKey: this.writeKey,
|
|
1334
|
+
debug: this.debug,
|
|
1335
|
+
sdkName: this.sdkName
|
|
1336
|
+
}) : void 0;
|
|
758
1337
|
if (!this.writeKey) {
|
|
759
1338
|
if (!isPending) this.sticky.delete(eventId);
|
|
1339
|
+
if (mirror) await mirror;
|
|
760
1340
|
return;
|
|
761
1341
|
}
|
|
762
1342
|
const opts = this.requestOpts();
|
|
763
1343
|
if (!opts) {
|
|
764
1344
|
this.warnShutdownDrop(`track_partial ${eventId}`);
|
|
765
1345
|
if (!isPending) this.sticky.delete(eventId);
|
|
1346
|
+
if (mirror) await mirror;
|
|
766
1347
|
return;
|
|
767
1348
|
}
|
|
768
1349
|
const p = postJson(url, payload, this.requestHeaders(), opts);
|
|
769
|
-
|
|
1350
|
+
const combined = mirror ? Promise.all([mirror, p]).then(() => void 0) : p;
|
|
1351
|
+
this.inFlight.add(combined);
|
|
770
1352
|
try {
|
|
771
1353
|
try {
|
|
772
|
-
await
|
|
1354
|
+
await combined;
|
|
773
1355
|
if (this.debug) {
|
|
774
1356
|
console.log(`${this.prefix} sent track_partial ${eventId} (${eventName})`);
|
|
775
1357
|
}
|
|
@@ -781,7 +1363,7 @@ var EventShipper = class {
|
|
|
781
1363
|
);
|
|
782
1364
|
}
|
|
783
1365
|
} finally {
|
|
784
|
-
this.inFlight.delete(
|
|
1366
|
+
this.inFlight.delete(combined);
|
|
785
1367
|
}
|
|
786
1368
|
if (!isPending) {
|
|
787
1369
|
this.sticky.delete(eventId);
|
|
@@ -789,6 +1371,7 @@ var EventShipper = class {
|
|
|
789
1371
|
}
|
|
790
1372
|
};
|
|
791
1373
|
var MODEL_USAGE_ATTRIBUTES = {
|
|
1374
|
+
usageSource: "raindrop.usage.source",
|
|
792
1375
|
providerName: "gen_ai.provider.name",
|
|
793
1376
|
requestModel: "gen_ai.request.model",
|
|
794
1377
|
responseModel: "gen_ai.response.model",
|
|
@@ -797,6 +1380,7 @@ var MODEL_USAGE_ATTRIBUTES = {
|
|
|
797
1380
|
reasoningTokens: "gen_ai.usage.reasoning_tokens",
|
|
798
1381
|
cacheReadInputTokens: "gen_ai.usage.cache_read_input_tokens",
|
|
799
1382
|
cacheWriteInputTokens: "gen_ai.usage.cache_write_input_tokens",
|
|
1383
|
+
providerReportedCost: "gen_ai.usage.provider_reported_cost",
|
|
800
1384
|
nonCachedInputTokens: "raindrop.usage.input_tokens.non_cached",
|
|
801
1385
|
nonReasoningOutputTokens: "raindrop.usage.output_tokens.non_reasoning",
|
|
802
1386
|
totalOutputTokens: "raindrop.usage.output_tokens.total",
|
|
@@ -805,13 +1389,20 @@ var MODEL_USAGE_ATTRIBUTES = {
|
|
|
805
1389
|
cacheWriteTokens: "raindrop.usage.input_tokens.cache_write"
|
|
806
1390
|
};
|
|
807
1391
|
var MODEL_PROVIDER_NAMES = [
|
|
1392
|
+
["google.vertex.anthropic", "google-vertex"],
|
|
1393
|
+
["google.vertex_ai", "google-vertex"],
|
|
808
1394
|
["google.vertex", "google-vertex"],
|
|
1395
|
+
["gcp.vertex_ai", "google-vertex"],
|
|
1396
|
+
["gcp.gemini", "google"],
|
|
1397
|
+
["google_vertexai", "google-vertex"],
|
|
809
1398
|
["vertex.anthropic", "google-vertex"],
|
|
810
1399
|
["amazon-bedrock", "amazon-bedrock"],
|
|
1400
|
+
["aws.bedrock", "amazon-bedrock"],
|
|
811
1401
|
["bedrock", "amazon-bedrock"],
|
|
812
1402
|
["anthropic", "anthropic"],
|
|
813
1403
|
["openai", "openai"],
|
|
814
1404
|
["google", "google"],
|
|
1405
|
+
["az.ai.openai", "azure"],
|
|
815
1406
|
["azure", "azure"],
|
|
816
1407
|
["openrouter", "openrouter"]
|
|
817
1408
|
];
|
|
@@ -822,60 +1413,20 @@ function canonicalModelProvider(provider) {
|
|
|
822
1413
|
const match = MODEL_PROVIDER_NAMES.find(
|
|
823
1414
|
([family]) => normalizedProvider === family || normalizedProvider.startsWith(`${family}.`)
|
|
824
1415
|
);
|
|
825
|
-
return (_a = match == null ? void 0 : match[1]) != null ? _a :
|
|
1416
|
+
return (_a = match == null ? void 0 : match[1]) != null ? _a : normalizedProvider;
|
|
826
1417
|
}
|
|
827
1418
|
function tokenCount(value) {
|
|
828
1419
|
return typeof value === "number" && Number.isSafeInteger(value) && value >= 0 ? value : void 0;
|
|
829
1420
|
}
|
|
830
|
-
function
|
|
831
|
-
|
|
832
|
-
total,
|
|
833
|
-
parts,
|
|
834
|
-
semantics
|
|
835
|
-
}) {
|
|
836
|
-
if (explicit !== void 0) return explicit;
|
|
837
|
-
if (total === void 0) return void 0;
|
|
838
|
-
if (semantics === "exclusive") return total;
|
|
839
|
-
const observedParts = parts.filter((part) => part !== void 0 && part > 0);
|
|
840
|
-
if (semantics === void 0 && observedParts.length > 0) return void 0;
|
|
841
|
-
const exclusive = total - observedParts.reduce((sum, part) => sum + part, 0);
|
|
842
|
-
return exclusive >= 0 ? exclusive : void 0;
|
|
843
|
-
}
|
|
844
|
-
function buildModelUsageAttributes(usage) {
|
|
845
|
-
const inputTokens = tokenCount(usage.inputTokens);
|
|
846
|
-
const outputTokens = tokenCount(usage.outputTokens);
|
|
847
|
-
const explicitNonCachedInputTokens = tokenCount(usage.nonCachedInputTokens);
|
|
848
|
-
const explicitNonReasoningOutputTokens = tokenCount(usage.nonReasoningOutputTokens);
|
|
849
|
-
const reasoningTokens = tokenCount(usage.reasoningTokens);
|
|
850
|
-
const cacheReadInputTokens = tokenCount(usage.cacheReadInputTokens);
|
|
851
|
-
const cacheWriteInputTokens = tokenCount(usage.cacheWriteInputTokens);
|
|
852
|
-
const nonCachedInputTokens = exclusiveTokens({
|
|
853
|
-
explicit: explicitNonCachedInputTokens,
|
|
854
|
-
total: inputTokens,
|
|
855
|
-
parts: [cacheReadInputTokens, cacheWriteInputTokens],
|
|
856
|
-
semantics: usage.inputTokenSemantics
|
|
857
|
-
});
|
|
858
|
-
const nonReasoningOutputTokens = exclusiveTokens({
|
|
859
|
-
explicit: explicitNonReasoningOutputTokens,
|
|
860
|
-
total: outputTokens,
|
|
861
|
-
parts: [reasoningTokens],
|
|
862
|
-
semantics: usage.outputTokenSemantics
|
|
863
|
-
});
|
|
864
|
-
const exclusivePoolAttributes = nonCachedInputTokens !== void 0 && nonReasoningOutputTokens !== void 0 ? [
|
|
865
|
-
// backend consumes this complete raindrop.* set as one atomic billing-pool contract.
|
|
866
|
-
attrInt(MODEL_USAGE_ATTRIBUTES.nonCachedInputTokens, nonCachedInputTokens),
|
|
867
|
-
attrInt(MODEL_USAGE_ATTRIBUTES.nonReasoningOutputTokens, nonReasoningOutputTokens),
|
|
868
|
-
attrInt(MODEL_USAGE_ATTRIBUTES.reasoningOutputTokens, reasoningTokens),
|
|
869
|
-
attrInt(MODEL_USAGE_ATTRIBUTES.cacheReadTokens, cacheReadInputTokens),
|
|
870
|
-
attrInt(MODEL_USAGE_ATTRIBUTES.cacheWriteTokens, cacheWriteInputTokens)
|
|
871
|
-
] : [];
|
|
1421
|
+
function buildRawModelUsageAttributes(usage) {
|
|
1422
|
+
const providerReportedCost = typeof usage.providerReportedCost === "number" && Number.isFinite(usage.providerReportedCost) && usage.providerReportedCost >= 0 ? usage.providerReportedCost : void 0;
|
|
872
1423
|
return [
|
|
873
|
-
attrInt(MODEL_USAGE_ATTRIBUTES.inputTokens, inputTokens),
|
|
874
|
-
attrInt(MODEL_USAGE_ATTRIBUTES.outputTokens, outputTokens),
|
|
875
|
-
attrInt(MODEL_USAGE_ATTRIBUTES.reasoningTokens, reasoningTokens),
|
|
876
|
-
attrInt(MODEL_USAGE_ATTRIBUTES.cacheReadInputTokens, cacheReadInputTokens),
|
|
877
|
-
attrInt(MODEL_USAGE_ATTRIBUTES.cacheWriteInputTokens, cacheWriteInputTokens),
|
|
878
|
-
|
|
1424
|
+
attrInt(MODEL_USAGE_ATTRIBUTES.inputTokens, tokenCount(usage.inputTokens)),
|
|
1425
|
+
attrInt(MODEL_USAGE_ATTRIBUTES.outputTokens, tokenCount(usage.outputTokens)),
|
|
1426
|
+
attrInt(MODEL_USAGE_ATTRIBUTES.reasoningTokens, tokenCount(usage.reasoningTokens)),
|
|
1427
|
+
attrInt(MODEL_USAGE_ATTRIBUTES.cacheReadInputTokens, tokenCount(usage.cacheReadInputTokens)),
|
|
1428
|
+
attrInt(MODEL_USAGE_ATTRIBUTES.cacheWriteInputTokens, tokenCount(usage.cacheWriteInputTokens)),
|
|
1429
|
+
attrDouble(MODEL_USAGE_ATTRIBUTES.providerReportedCost, providerReportedCost)
|
|
879
1430
|
].filter((attribute) => attribute !== void 0);
|
|
880
1431
|
}
|
|
881
1432
|
var STRING_ALIASES = {
|
|
@@ -1065,6 +1616,13 @@ function redactJsonAttributeValue(key, value) {
|
|
|
1065
1616
|
if (scrubbedJson === json) return void 0;
|
|
1066
1617
|
return { stringValue: scrubbedJson };
|
|
1067
1618
|
}
|
|
1619
|
+
function appGitOwnerId2(prefix) {
|
|
1620
|
+
try {
|
|
1621
|
+
return `${prefix}:${randomUUID()}`;
|
|
1622
|
+
} catch (e) {
|
|
1623
|
+
return `${prefix}:${Date.now().toString(36)}:${Math.random().toString(36).slice(2)}`;
|
|
1624
|
+
}
|
|
1625
|
+
}
|
|
1068
1626
|
function identityAttrs(args) {
|
|
1069
1627
|
return [
|
|
1070
1628
|
attrString("ai.telemetry.metadata.raindrop.ai.userId", args.userId),
|
|
@@ -1087,23 +1645,30 @@ function applyOtelSpanAttributeLimit(limit) {
|
|
|
1087
1645
|
}
|
|
1088
1646
|
var TraceShipper = class {
|
|
1089
1647
|
constructor(opts) {
|
|
1648
|
+
this.appGitOwner = appGitOwnerId2("trace");
|
|
1649
|
+
this.appGitEventIds = /* @__PURE__ */ new WeakMap();
|
|
1650
|
+
this.appGitActiveSpans = /* @__PURE__ */ new Map();
|
|
1651
|
+
this.appGitCaptured = /* @__PURE__ */ new WeakSet();
|
|
1652
|
+
this.appGitAdded = /* @__PURE__ */ new WeakMap();
|
|
1090
1653
|
this.queue = [];
|
|
1091
1654
|
this.inFlight = /* @__PURE__ */ new Set();
|
|
1092
1655
|
this.hasShutdown = false;
|
|
1093
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _i;
|
|
1094
|
-
this.
|
|
1095
|
-
this.
|
|
1656
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j;
|
|
1657
|
+
this.appGitContext = (_a = opts.appGitContext) != null ? _a : createAppGitContext(opts.appGit);
|
|
1658
|
+
this.ownsAppGitContext = opts.appGitContext === void 0;
|
|
1659
|
+
this.writeKey = (_b = opts.writeKey) == null ? void 0 : _b.trim();
|
|
1660
|
+
this.baseUrl = (_c = formatEndpoint(opts.endpoint)) != null ? _c : "https://api.raindrop.ai/v1/";
|
|
1096
1661
|
this.enabled = opts.enabled !== false;
|
|
1097
1662
|
this.debug = opts.debug;
|
|
1098
1663
|
this.debugSpans = opts.debugSpans === true;
|
|
1099
|
-
this.flushIntervalMs = (
|
|
1100
|
-
this.maxBatchSize = (
|
|
1101
|
-
this.maxQueueSize = (
|
|
1102
|
-
this.sdkName = (
|
|
1664
|
+
this.flushIntervalMs = (_d = opts.flushIntervalMs) != null ? _d : 1e3;
|
|
1665
|
+
this.maxBatchSize = (_e = opts.maxBatchSize) != null ? _e : 50;
|
|
1666
|
+
this.maxQueueSize = (_f = opts.maxQueueSize) != null ? _f : 5e3;
|
|
1667
|
+
this.sdkName = (_g = opts.sdkName) != null ? _g : "core";
|
|
1103
1668
|
this.prefix = `[raindrop-ai/${this.sdkName}]`;
|
|
1104
|
-
this.serviceName = (
|
|
1105
|
-
this.serviceVersion = (
|
|
1106
|
-
this.localDebuggerUrl = (
|
|
1669
|
+
this.serviceName = (_h = opts.serviceName) != null ? _h : "raindrop.core";
|
|
1670
|
+
this.serviceVersion = (_i = opts.serviceVersion) != null ? _i : "0.0.0";
|
|
1671
|
+
this.localDebuggerUrl = (_j = resolveLocalDebuggerBaseUrl(opts.localDebuggerUrl)) != null ? _j : void 0;
|
|
1107
1672
|
if (this.debug && this.localDebuggerUrl) {
|
|
1108
1673
|
console.log(`${this.prefix} Local debugger mirroring: ${this.localDebuggerUrl}`);
|
|
1109
1674
|
}
|
|
@@ -1167,7 +1732,10 @@ var TraceShipper = class {
|
|
|
1167
1732
|
try {
|
|
1168
1733
|
const result = this.transformSpanHook(current);
|
|
1169
1734
|
if (result === null) return null;
|
|
1170
|
-
if (result !== void 0)
|
|
1735
|
+
if (result !== void 0) {
|
|
1736
|
+
copyReplayTraceDestination(current, result);
|
|
1737
|
+
current = result;
|
|
1738
|
+
}
|
|
1171
1739
|
} catch (err) {
|
|
1172
1740
|
if (this.debug) {
|
|
1173
1741
|
const msg = err instanceof Error ? err.message : String(err);
|
|
@@ -1177,13 +1745,19 @@ var TraceShipper = class {
|
|
|
1177
1745
|
}
|
|
1178
1746
|
}
|
|
1179
1747
|
try {
|
|
1180
|
-
|
|
1748
|
+
const normalized = normalizeModelUsageSpan(current);
|
|
1749
|
+
copyReplayTraceDestination(current, normalized);
|
|
1750
|
+
current = normalized;
|
|
1181
1751
|
} catch (e) {
|
|
1182
1752
|
}
|
|
1183
1753
|
if (!this.disableDefaultRedaction) {
|
|
1184
|
-
|
|
1754
|
+
const redacted = defaultTransformSpan(current);
|
|
1755
|
+
copyReplayTraceDestination(current, redacted);
|
|
1756
|
+
current = redacted;
|
|
1185
1757
|
}
|
|
1186
|
-
|
|
1758
|
+
const capped = this.capSpanAttributes(current);
|
|
1759
|
+
copyReplayTraceDestination(current, capped);
|
|
1760
|
+
return capped;
|
|
1187
1761
|
}
|
|
1188
1762
|
isDebugEnabled() {
|
|
1189
1763
|
return this.debug;
|
|
@@ -1195,46 +1769,84 @@ var TraceShipper = class {
|
|
|
1195
1769
|
return { ...this.authHeaders(), ...projectIdHeaders(this.projectId) };
|
|
1196
1770
|
}
|
|
1197
1771
|
startSpan(args) {
|
|
1198
|
-
var _a, _b;
|
|
1772
|
+
var _a, _b, _c;
|
|
1199
1773
|
const ids = createSpanIds(args.parent);
|
|
1200
1774
|
const started = (_a = args.startTimeUnixNano) != null ? _a : nowUnixNanoString();
|
|
1201
1775
|
const attrs = [
|
|
1202
1776
|
attrString("ai.telemetry.metadata.raindrop.eventId", args.eventId),
|
|
1203
1777
|
...identityAttrs(args),
|
|
1204
|
-
attrString("ai.operationId", args.operationId)
|
|
1778
|
+
attrString("ai.operationId", args.operationId),
|
|
1779
|
+
...Object.entries(evalScopeAttributes()).map(([key, value]) => attrString(key, value))
|
|
1205
1780
|
];
|
|
1206
1781
|
if ((_b = args.attributes) == null ? void 0 : _b.length) attrs.push(...args.attributes);
|
|
1207
|
-
const
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
);
|
|
1782
|
+
const tracksAppGit = this.appGitActiveSpans.has(args.eventId) || this.appGitActiveSpans.size < 1e4;
|
|
1783
|
+
const appGitOverrides = appGitPropertiesFromAttributes(attrs);
|
|
1784
|
+
const span = {
|
|
1785
|
+
ids,
|
|
1786
|
+
name: args.name,
|
|
1787
|
+
startTimeUnixNano: started,
|
|
1788
|
+
attributes: withAppGitAttributes(
|
|
1789
|
+
attrs,
|
|
1790
|
+
this.appGitContext.forOperation(args.eventId, appGitOverrides, this.appGitOwner)
|
|
1791
|
+
)
|
|
1792
|
+
};
|
|
1793
|
+
rememberReplayTraceDestination(span);
|
|
1794
|
+
this.appGitCaptured.add(span);
|
|
1795
|
+
this.appGitEventIds.set(span, args.eventId);
|
|
1796
|
+
if (tracksAppGit) {
|
|
1797
|
+
this.appGitActiveSpans.set(args.eventId, ((_c = this.appGitActiveSpans.get(args.eventId)) != null ? _c : 0) + 1);
|
|
1798
|
+
}
|
|
1799
|
+
this.appGitAdded.set(span, new Set(span.attributes.filter((attr) => !attrs.includes(attr))));
|
|
1800
|
+
const openSpan = buildOtlpSpan({
|
|
1801
|
+
ids: span.ids,
|
|
1802
|
+
name: span.name,
|
|
1803
|
+
startTimeUnixNano: span.startTimeUnixNano,
|
|
1804
|
+
endTimeUnixNano: span.startTimeUnixNano,
|
|
1805
|
+
// placeholder — will be updated on endSpan
|
|
1806
|
+
attributes: span.attributes,
|
|
1807
|
+
status: { code: SpanStatusCode.UNSET }
|
|
1808
|
+
});
|
|
1809
|
+
copyReplayTraceDestination(span, openSpan);
|
|
1810
|
+
this.mirrorToLocalDebugger(openSpan);
|
|
1219
1811
|
return span;
|
|
1220
1812
|
}
|
|
1221
|
-
mirrorToLocalDebugger(span) {
|
|
1222
|
-
|
|
1813
|
+
mirrorToLocalDebugger(span, completed = false) {
|
|
1814
|
+
const destination = replayTraceDestinationFor(span);
|
|
1815
|
+
if (destination && destination.kind !== "workshop") return;
|
|
1816
|
+
const localDebuggerUrl = (destination == null ? void 0 : destination.kind) === "workshop" ? destination.url : this.localDebuggerUrl;
|
|
1817
|
+
if (!localDebuggerUrl) return;
|
|
1223
1818
|
const redacted = this.redactSpan(span);
|
|
1224
1819
|
if (redacted === null) return;
|
|
1820
|
+
if (completed && (destination == null ? void 0 : destination.kind) === "workshop") {
|
|
1821
|
+
recordReplayExportedSpan(
|
|
1822
|
+
destination,
|
|
1823
|
+
base64ToHex(redacted.spanId),
|
|
1824
|
+
base64ToHex(redacted.traceId)
|
|
1825
|
+
);
|
|
1826
|
+
}
|
|
1225
1827
|
const body = buildExportTraceServiceRequest([redacted], this.serviceName, this.serviceVersion);
|
|
1226
|
-
mirrorTraceExportToLocalDebugger(body, {
|
|
1227
|
-
baseUrl:
|
|
1828
|
+
const p = mirrorTraceExportToLocalDebugger(body, {
|
|
1829
|
+
baseUrl: localDebuggerUrl,
|
|
1228
1830
|
debug: false,
|
|
1229
1831
|
sdkName: this.sdkName
|
|
1230
1832
|
});
|
|
1833
|
+
this.inFlight.add(p);
|
|
1834
|
+
void p.finally(() => {
|
|
1835
|
+
this.inFlight.delete(p);
|
|
1836
|
+
});
|
|
1231
1837
|
}
|
|
1232
1838
|
endSpan(span, extra) {
|
|
1233
|
-
var _a, _b;
|
|
1839
|
+
var _a, _b, _c;
|
|
1234
1840
|
if (span.endTimeUnixNano) return;
|
|
1235
1841
|
span.endTimeUnixNano = (_a = extra == null ? void 0 : extra.endTimeUnixNano) != null ? _a : nowUnixNanoString();
|
|
1236
1842
|
if ((_b = extra == null ? void 0 : extra.attributes) == null ? void 0 : _b.length) {
|
|
1843
|
+
const overrides = appGitPropertiesFromAttributes(extra.attributes);
|
|
1844
|
+
const eventId2 = this.appGitEventIds.get(span);
|
|
1845
|
+
const snapshot = eventId2 ? this.appGitContext.forOperation(eventId2, overrides, this.appGitOwner) : overrides;
|
|
1846
|
+
const added = this.appGitAdded.get(span);
|
|
1847
|
+
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));
|
|
1237
1848
|
span.attributes.push(...extra.attributes);
|
|
1849
|
+
span.attributes = withAppGitAttributes(span.attributes, snapshot);
|
|
1238
1850
|
}
|
|
1239
1851
|
let status = extra == null ? void 0 : extra.status;
|
|
1240
1852
|
if (!status && (extra == null ? void 0 : extra.error) !== void 0) {
|
|
@@ -1249,30 +1861,65 @@ var TraceShipper = class {
|
|
|
1249
1861
|
attributes: span.attributes,
|
|
1250
1862
|
status
|
|
1251
1863
|
});
|
|
1864
|
+
copyReplayTraceDestination(span, otlp);
|
|
1865
|
+
this.appGitCaptured.add(otlp);
|
|
1252
1866
|
this.enqueue(otlp);
|
|
1253
|
-
this.mirrorToLocalDebugger(otlp);
|
|
1867
|
+
this.mirrorToLocalDebugger(otlp, true);
|
|
1868
|
+
const eventId = this.appGitEventIds.get(span);
|
|
1869
|
+
if (eventId && this.appGitActiveSpans.has(eventId)) {
|
|
1870
|
+
const remaining = ((_c = this.appGitActiveSpans.get(eventId)) != null ? _c : 1) - 1;
|
|
1871
|
+
if (remaining > 0) this.appGitActiveSpans.set(eventId, remaining);
|
|
1872
|
+
else {
|
|
1873
|
+
this.appGitActiveSpans.delete(eventId);
|
|
1874
|
+
if (this.appGitContext.releaseOperation) this.appGitContext.releaseOperation(eventId, this.appGitOwner);
|
|
1875
|
+
else if (this.ownsAppGitContext) this.appGitContext.finishOperation(eventId);
|
|
1876
|
+
}
|
|
1877
|
+
}
|
|
1254
1878
|
}
|
|
1255
1879
|
createSpan(args) {
|
|
1256
1880
|
var _a;
|
|
1257
1881
|
const ids = createSpanIds(args.parent);
|
|
1258
1882
|
const attrs = [
|
|
1259
1883
|
attrString("ai.telemetry.metadata.raindrop.eventId", args.eventId),
|
|
1260
|
-
...identityAttrs(args)
|
|
1884
|
+
...identityAttrs(args),
|
|
1885
|
+
...Object.entries(evalScopeAttributes()).map(([key, value]) => attrString(key, value))
|
|
1261
1886
|
];
|
|
1262
1887
|
if ((_a = args.attributes) == null ? void 0 : _a.length) attrs.push(...args.attributes);
|
|
1888
|
+
const tracksAppGit = !this.appGitActiveSpans.has(args.eventId);
|
|
1263
1889
|
const otlp = buildOtlpSpan({
|
|
1264
1890
|
ids,
|
|
1265
1891
|
name: args.name,
|
|
1266
1892
|
startTimeUnixNano: args.startTimeUnixNano,
|
|
1267
1893
|
endTimeUnixNano: args.endTimeUnixNano,
|
|
1268
|
-
attributes:
|
|
1894
|
+
attributes: withAppGitAttributes(
|
|
1895
|
+
attrs,
|
|
1896
|
+
this.appGitContext.forOperation(
|
|
1897
|
+
args.eventId,
|
|
1898
|
+
appGitPropertiesFromAttributes(attrs),
|
|
1899
|
+
this.appGitOwner
|
|
1900
|
+
)
|
|
1901
|
+
),
|
|
1269
1902
|
status: args.status
|
|
1270
1903
|
});
|
|
1904
|
+
rememberReplayTraceDestination(otlp);
|
|
1905
|
+
this.appGitCaptured.add(otlp);
|
|
1906
|
+
if (tracksAppGit) {
|
|
1907
|
+
if (this.appGitContext.releaseOperation) this.appGitContext.releaseOperation(args.eventId, this.appGitOwner);
|
|
1908
|
+
else if (this.ownsAppGitContext) this.appGitContext.finishOperation(args.eventId);
|
|
1909
|
+
}
|
|
1271
1910
|
this.enqueue(otlp);
|
|
1272
|
-
this.mirrorToLocalDebugger(otlp);
|
|
1911
|
+
this.mirrorToLocalDebugger(otlp, true);
|
|
1273
1912
|
}
|
|
1274
1913
|
enqueue(span) {
|
|
1914
|
+
var _a;
|
|
1275
1915
|
if (!this.enabled) return;
|
|
1916
|
+
const attributes = (_a = span.attributes) != null ? _a : [];
|
|
1917
|
+
const enriched = this.appGitCaptured.has(span) ? attributes : withAppGitAttributes(attributes, this.appGitContext.snapshot(appGitPropertiesFromAttributes(attributes)));
|
|
1918
|
+
if (enriched !== attributes) {
|
|
1919
|
+
const original = span;
|
|
1920
|
+
span = { ...span, attributes: enriched.filter((attr) => attr !== void 0) };
|
|
1921
|
+
copyReplayTraceDestination(original, span);
|
|
1922
|
+
}
|
|
1276
1923
|
if (this.debugSpans) {
|
|
1277
1924
|
const short = (s) => s ? s.slice(-8) : "none";
|
|
1278
1925
|
console.log(
|
|
@@ -1283,6 +1930,13 @@ var TraceShipper = class {
|
|
|
1283
1930
|
}
|
|
1284
1931
|
const redacted = this.redactSpan(span);
|
|
1285
1932
|
if (redacted === null) return;
|
|
1933
|
+
const destination = replayTraceDestinationFor(redacted);
|
|
1934
|
+
recordReplayExportedSpan(
|
|
1935
|
+
destination,
|
|
1936
|
+
base64ToHex(redacted.spanId),
|
|
1937
|
+
base64ToHex(redacted.traceId)
|
|
1938
|
+
);
|
|
1939
|
+
if ((destination == null ? void 0 : destination.kind) === "workshop") return;
|
|
1286
1940
|
if (this.queue.length >= this.maxQueueSize) {
|
|
1287
1941
|
this.queue.shift();
|
|
1288
1942
|
}
|
|
@@ -1301,47 +1955,67 @@ var TraceShipper = class {
|
|
|
1301
1955
|
}
|
|
1302
1956
|
}
|
|
1303
1957
|
async flush() {
|
|
1304
|
-
|
|
1958
|
+
var _a;
|
|
1959
|
+
if (!this.enabled) {
|
|
1960
|
+
await Promise.all([...this.inFlight].map((p) => p.catch(() => {
|
|
1961
|
+
})));
|
|
1962
|
+
return;
|
|
1963
|
+
}
|
|
1305
1964
|
if (this.timer) {
|
|
1306
1965
|
clearTimeout(this.timer);
|
|
1307
1966
|
this.timer = void 0;
|
|
1308
1967
|
}
|
|
1309
1968
|
while (this.queue.length > 0) {
|
|
1310
1969
|
const batch = this.queue.splice(0, this.maxBatchSize);
|
|
1311
|
-
|
|
1312
|
-
const
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
|
|
1317
|
-
`${this.prefix} shutdown flush deadline exceeded; dropping ${batch.length} spans`
|
|
1318
|
-
)
|
|
1319
|
-
);
|
|
1320
|
-
continue;
|
|
1321
|
-
}
|
|
1322
|
-
const body = buildExportTraceServiceRequest(batch, this.serviceName, this.serviceVersion);
|
|
1323
|
-
const url = `${this.baseUrl}traces`;
|
|
1324
|
-
if (this.debug) {
|
|
1325
|
-
console.log(`${this.prefix} sending traces batch`, {
|
|
1326
|
-
spans: batch.length,
|
|
1327
|
-
endpoint: url
|
|
1328
|
-
});
|
|
1970
|
+
const groups = /* @__PURE__ */ new Map();
|
|
1971
|
+
for (const span of batch) {
|
|
1972
|
+
const destination = replayTraceDestinationFor(span);
|
|
1973
|
+
const spans = groups.get(destination);
|
|
1974
|
+
if (spans) spans.push(span);
|
|
1975
|
+
else groups.set(destination, [span]);
|
|
1329
1976
|
}
|
|
1330
|
-
const
|
|
1331
|
-
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
|
-
if (this.debug) console.log(`${this.prefix} sent ${batch.length} spans`);
|
|
1336
|
-
} catch (err) {
|
|
1337
|
-
const msg = err instanceof Error ? err.message : String(err);
|
|
1977
|
+
for (const [destination, spans] of groups) {
|
|
1978
|
+
if (!destination && !this.writeKey) continue;
|
|
1979
|
+
if ((destination == null ? void 0 : destination.kind) === "workshop") continue;
|
|
1980
|
+
const opts = this.requestOpts();
|
|
1981
|
+
if (!opts) {
|
|
1338
1982
|
rateLimitedLog(
|
|
1339
|
-
`${this.prefix}.
|
|
1340
|
-
() => console.warn(
|
|
1983
|
+
`${this.prefix}.shutdown_deadline`,
|
|
1984
|
+
() => console.warn(
|
|
1985
|
+
`${this.prefix} shutdown flush deadline exceeded; dropping ${spans.length} spans`
|
|
1986
|
+
)
|
|
1341
1987
|
);
|
|
1988
|
+
continue;
|
|
1989
|
+
}
|
|
1990
|
+
const body = buildExportTraceServiceRequest(spans, this.serviceName, this.serviceVersion);
|
|
1991
|
+
const url = destination ? replayTraceUrl(destination.url) : `${this.baseUrl}traces`;
|
|
1992
|
+
const headers = destination ? {
|
|
1993
|
+
Authorization: `Bearer ${destination.apiKey}`,
|
|
1994
|
+
"X-Raindrop-Replay-Id": destination.replayId,
|
|
1995
|
+
"X-Raindrop-Project-Id": (_a = destination.projectId) != null ? _a : "default"
|
|
1996
|
+
} : this.requestHeaders();
|
|
1997
|
+
if (this.debug) {
|
|
1998
|
+
console.log(`${this.prefix} sending traces batch`, {
|
|
1999
|
+
spans: spans.length,
|
|
2000
|
+
endpoint: url
|
|
2001
|
+
});
|
|
2002
|
+
}
|
|
2003
|
+
const p = postJson(url, body, headers, opts);
|
|
2004
|
+
this.inFlight.add(p);
|
|
2005
|
+
try {
|
|
2006
|
+
try {
|
|
2007
|
+
await p;
|
|
2008
|
+
if (this.debug) console.log(`${this.prefix} sent ${spans.length} spans`);
|
|
2009
|
+
} catch (err) {
|
|
2010
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
2011
|
+
rateLimitedLog(
|
|
2012
|
+
`${this.prefix}.send_spans_failed`,
|
|
2013
|
+
() => console.warn(`${this.prefix} failed to send ${spans.length} spans: ${msg}`)
|
|
2014
|
+
);
|
|
2015
|
+
}
|
|
2016
|
+
} finally {
|
|
2017
|
+
this.inFlight.delete(p);
|
|
1342
2018
|
}
|
|
1343
|
-
} finally {
|
|
1344
|
-
this.inFlight.delete(p);
|
|
1345
2019
|
}
|
|
1346
2020
|
}
|
|
1347
2021
|
}
|
|
@@ -1384,17 +2058,165 @@ var TraceShipper = class {
|
|
|
1384
2058
|
if (!settled) {
|
|
1385
2059
|
rateLimitedLog(
|
|
1386
2060
|
`${this.prefix}.shutdown_deadline`,
|
|
1387
|
-
() => console.warn(
|
|
2061
|
+
() => console.warn(
|
|
2062
|
+
`${this.prefix} shutdown flush deadline exceeded; abandoning in-flight spans`
|
|
2063
|
+
)
|
|
1388
2064
|
);
|
|
1389
2065
|
}
|
|
1390
2066
|
} finally {
|
|
1391
2067
|
this.shutdownDeadlineAt = void 0;
|
|
2068
|
+
if (this.ownsAppGitContext) this.appGitContext.dispose();
|
|
1392
2069
|
}
|
|
1393
2070
|
}
|
|
1394
2071
|
};
|
|
1395
2072
|
|
|
1396
2073
|
// ../core/dist/index.node.js
|
|
1397
2074
|
import { AsyncLocalStorage } from "async_hooks";
|
|
2075
|
+
import { execFile } from "child_process";
|
|
2076
|
+
import { resolve } from "path";
|
|
2077
|
+
var resolveLocal = (sourceDirectory, detectBranch, completed) => {
|
|
2078
|
+
const cwd = sourceDirectory ? resolve(sourceDirectory) : process.cwd();
|
|
2079
|
+
let cancelled = false;
|
|
2080
|
+
let active;
|
|
2081
|
+
let deadlineTimer;
|
|
2082
|
+
const deadline = Date.now() + 1e3;
|
|
2083
|
+
const run = (args, done) => {
|
|
2084
|
+
if (cancelled) return;
|
|
2085
|
+
const remaining = deadline - Date.now();
|
|
2086
|
+
if (remaining <= 0) {
|
|
2087
|
+
done(void 0);
|
|
2088
|
+
return;
|
|
2089
|
+
}
|
|
2090
|
+
try {
|
|
2091
|
+
active = execFile(
|
|
2092
|
+
"git",
|
|
2093
|
+
args,
|
|
2094
|
+
{
|
|
2095
|
+
cwd,
|
|
2096
|
+
encoding: "utf8",
|
|
2097
|
+
maxBuffer: 4096,
|
|
2098
|
+
windowsHide: true,
|
|
2099
|
+
env: {
|
|
2100
|
+
...process.env,
|
|
2101
|
+
// The selected application cwd, not the invoking shell's Git plumbing, owns identity.
|
|
2102
|
+
GIT_DIR: void 0,
|
|
2103
|
+
GIT_WORK_TREE: void 0,
|
|
2104
|
+
GIT_COMMON_DIR: void 0,
|
|
2105
|
+
GIT_NAMESPACE: void 0,
|
|
2106
|
+
GIT_INDEX_FILE: void 0,
|
|
2107
|
+
GIT_OBJECT_DIRECTORY: void 0,
|
|
2108
|
+
GIT_ALTERNATE_OBJECT_DIRECTORIES: void 0,
|
|
2109
|
+
GIT_CONFIG_PARAMETERS: void 0,
|
|
2110
|
+
GIT_CONFIG_COUNT: "0",
|
|
2111
|
+
GIT_TERMINAL_PROMPT: "0",
|
|
2112
|
+
GIT_OPTIONAL_LOCKS: "0"
|
|
2113
|
+
}
|
|
2114
|
+
},
|
|
2115
|
+
(error, stdout) => {
|
|
2116
|
+
clearTimeout(deadlineTimer);
|
|
2117
|
+
deadlineTimer = void 0;
|
|
2118
|
+
active = void 0;
|
|
2119
|
+
if (!cancelled) {
|
|
2120
|
+
try {
|
|
2121
|
+
done(error ? void 0 : stdout.trim());
|
|
2122
|
+
} catch (e) {
|
|
2123
|
+
}
|
|
2124
|
+
}
|
|
2125
|
+
}
|
|
2126
|
+
);
|
|
2127
|
+
active.unref();
|
|
2128
|
+
if (active.stdout && "unref" in active.stdout && typeof active.stdout.unref === "function")
|
|
2129
|
+
active.stdout.unref();
|
|
2130
|
+
if (active.stderr && "unref" in active.stderr && typeof active.stderr.unref === "function")
|
|
2131
|
+
active.stderr.unref();
|
|
2132
|
+
deadlineTimer = setTimeout(() => {
|
|
2133
|
+
try {
|
|
2134
|
+
active == null ? void 0 : active.kill("SIGKILL");
|
|
2135
|
+
} catch (e) {
|
|
2136
|
+
}
|
|
2137
|
+
}, remaining);
|
|
2138
|
+
deadlineTimer.unref();
|
|
2139
|
+
} catch (e) {
|
|
2140
|
+
try {
|
|
2141
|
+
done(void 0);
|
|
2142
|
+
} catch (e2) {
|
|
2143
|
+
}
|
|
2144
|
+
}
|
|
2145
|
+
};
|
|
2146
|
+
const scheduled = setTimeout(() => {
|
|
2147
|
+
try {
|
|
2148
|
+
run(["rev-parse", "HEAD"], (rawSha) => {
|
|
2149
|
+
const commitSha = validAppCommitSha(rawSha);
|
|
2150
|
+
if (!commitSha) {
|
|
2151
|
+
completed({});
|
|
2152
|
+
return;
|
|
2153
|
+
}
|
|
2154
|
+
run(["-c", "core.fsmonitor=false", "status", "--porcelain"], (status) => {
|
|
2155
|
+
const finish = (branch) => {
|
|
2156
|
+
run(["rev-parse", "HEAD"], (finalSha) => {
|
|
2157
|
+
const coherent = validAppCommitSha(finalSha) === commitSha;
|
|
2158
|
+
completed({
|
|
2159
|
+
commitSha,
|
|
2160
|
+
...coherent && status !== void 0 ? { commitDirty: status !== "" } : {},
|
|
2161
|
+
...coherent && branch && branch !== "HEAD" ? { branch } : {}
|
|
2162
|
+
});
|
|
2163
|
+
});
|
|
2164
|
+
};
|
|
2165
|
+
if (detectBranch) run(["symbolic-ref", "--quiet", "--short", "HEAD"], finish);
|
|
2166
|
+
else finish();
|
|
2167
|
+
});
|
|
2168
|
+
});
|
|
2169
|
+
} catch (e) {
|
|
2170
|
+
completed({});
|
|
2171
|
+
}
|
|
2172
|
+
}, 0);
|
|
2173
|
+
scheduled.unref();
|
|
2174
|
+
return () => {
|
|
2175
|
+
cancelled = true;
|
|
2176
|
+
clearTimeout(scheduled);
|
|
2177
|
+
clearTimeout(deadlineTimer);
|
|
2178
|
+
try {
|
|
2179
|
+
active == null ? void 0 : active.kill("SIGKILL");
|
|
2180
|
+
} catch (e) {
|
|
2181
|
+
}
|
|
2182
|
+
};
|
|
2183
|
+
};
|
|
2184
|
+
function createAppGitContext2(options, runtime = {}) {
|
|
2185
|
+
return new AppGitContext(options, { ...runtime, resolveLocal });
|
|
2186
|
+
}
|
|
2187
|
+
function hasDestination(options) {
|
|
2188
|
+
var _a;
|
|
2189
|
+
if (options.enabled === false) return false;
|
|
2190
|
+
return Boolean(((_a = options.writeKey) == null ? void 0 : _a.trim()) || resolveLocalDebuggerBaseUrl(options.localDebuggerUrl));
|
|
2191
|
+
}
|
|
2192
|
+
var EventShipper2 = class extends EventShipper {
|
|
2193
|
+
constructor(options) {
|
|
2194
|
+
var _a;
|
|
2195
|
+
const ownsAppGitContext = options.appGitContext === void 0;
|
|
2196
|
+
const appGitContext = (_a = options.appGitContext) != null ? _a : createAppGitContext2(options.appGit, { allowDiscovery: hasDestination(options) });
|
|
2197
|
+
try {
|
|
2198
|
+
super({ ...options, appGitContext });
|
|
2199
|
+
} catch (error) {
|
|
2200
|
+
if (ownsAppGitContext) appGitContext.dispose();
|
|
2201
|
+
throw error;
|
|
2202
|
+
}
|
|
2203
|
+
if (ownsAppGitContext) this.ownAppGitContextForShutdown();
|
|
2204
|
+
}
|
|
2205
|
+
};
|
|
2206
|
+
var TraceShipper2 = class extends TraceShipper {
|
|
2207
|
+
constructor(options) {
|
|
2208
|
+
var _a;
|
|
2209
|
+
const ownsAppGitContext = options.appGitContext === void 0;
|
|
2210
|
+
const appGitContext = (_a = options.appGitContext) != null ? _a : createAppGitContext2(options.appGit, { allowDiscovery: hasDestination(options) });
|
|
2211
|
+
try {
|
|
2212
|
+
super({ ...options, appGitContext });
|
|
2213
|
+
} catch (error) {
|
|
2214
|
+
if (ownsAppGitContext) appGitContext.dispose();
|
|
2215
|
+
throw error;
|
|
2216
|
+
}
|
|
2217
|
+
this.ownsAppGitContext = ownsAppGitContext;
|
|
2218
|
+
}
|
|
2219
|
+
};
|
|
1398
2220
|
globalThis.RAINDROP_ASYNC_LOCAL_STORAGE = AsyncLocalStorage;
|
|
1399
2221
|
var SUPPRESS_TRACING_KEY = /* @__PURE__ */ Symbol.for(
|
|
1400
2222
|
"OpenTelemetry SDK Context Key SUPPRESS_TRACING"
|
|
@@ -1459,7 +2281,20 @@ function loadConfig(projectDirectory) {
|
|
|
1459
2281
|
debug: process.env["RAINDROP_DEBUG"] === "true" ? true : (_g = merged.debug) != null ? _g : false,
|
|
1460
2282
|
captureSystemPrompt: process.env["RAINDROP_CAPTURE_SYSTEM_PROMPT"] !== void 0 ? process.env["RAINDROP_CAPTURE_SYSTEM_PROMPT"] === "true" : (_h = merged.capture_system_prompt) != null ? _h : false,
|
|
1461
2283
|
eventMetadata,
|
|
1462
|
-
localWorkshopUrl: resolveLocalWorkshopUrl(merged.local_workshop_url)
|
|
2284
|
+
localWorkshopUrl: resolveLocalWorkshopUrl(merged.local_workshop_url),
|
|
2285
|
+
appGit: mapAppGit(merged.app_git)
|
|
2286
|
+
};
|
|
2287
|
+
}
|
|
2288
|
+
function mapAppGit(value) {
|
|
2289
|
+
if (value === false) return false;
|
|
2290
|
+
if (value === null || typeof value !== "object" || Array.isArray(value)) return void 0;
|
|
2291
|
+
return {
|
|
2292
|
+
commitSha: "commit_sha" in value && (typeof value.commit_sha === "string" || value.commit_sha === null) ? value.commit_sha : void 0,
|
|
2293
|
+
commitDirty: "commit_dirty" in value && (typeof value.commit_dirty === "boolean" || value.commit_dirty === null) ? value.commit_dirty : void 0,
|
|
2294
|
+
branch: "branch" in value && (typeof value.branch === "string" || value.branch === null) ? value.branch : void 0,
|
|
2295
|
+
detectBranch: "detect_branch" in value && typeof value.detect_branch === "boolean" ? value.detect_branch : void 0,
|
|
2296
|
+
sourceDirectory: "source_directory" in value && typeof value.source_directory === "string" ? value.source_directory : void 0,
|
|
2297
|
+
autoDetect: "auto_detect" in value && typeof value.auto_detect === "boolean" ? value.auto_detect : void 0
|
|
1463
2298
|
};
|
|
1464
2299
|
}
|
|
1465
2300
|
function resolveLocalWorkshopUrl(fileValue) {
|
|
@@ -1476,7 +2311,7 @@ function resolveLocalWorkshopUrl(fileValue) {
|
|
|
1476
2311
|
// package.json
|
|
1477
2312
|
var package_default = {
|
|
1478
2313
|
name: "@raindrop-ai/opencode-plugin",
|
|
1479
|
-
version: "0.1.
|
|
2314
|
+
version: "0.1.4",
|
|
1480
2315
|
description: "Raindrop observability plugin for OpenCode \u2014 automatic session/event/span tracing",
|
|
1481
2316
|
type: "module",
|
|
1482
2317
|
main: "dist/index.js",
|
|
@@ -1547,7 +2382,7 @@ var PLUGIN_NAME = package_default.name;
|
|
|
1547
2382
|
var PLUGIN_VERSION = package_default.version;
|
|
1548
2383
|
|
|
1549
2384
|
// src/shipper.ts
|
|
1550
|
-
var
|
|
2385
|
+
var EventShipper3 = class extends EventShipper2 {
|
|
1551
2386
|
constructor(opts) {
|
|
1552
2387
|
var _a, _b, _c, _d;
|
|
1553
2388
|
super({
|
|
@@ -1559,7 +2394,7 @@ var EventShipper2 = class extends EventShipper {
|
|
|
1559
2394
|
});
|
|
1560
2395
|
}
|
|
1561
2396
|
};
|
|
1562
|
-
var
|
|
2397
|
+
var TraceShipper3 = class extends TraceShipper2 {
|
|
1563
2398
|
constructor(opts) {
|
|
1564
2399
|
var _a, _b, _c;
|
|
1565
2400
|
super({
|
|
@@ -1681,18 +2516,13 @@ function parseOpenCodeAssistantTokens(tokens) {
|
|
|
1681
2516
|
};
|
|
1682
2517
|
}
|
|
1683
2518
|
function modelSpendSpanAttributes(input) {
|
|
1684
|
-
const providerAttr = attrString(
|
|
1685
|
-
|
|
1686
|
-
canonicalModelProvider(input.providerID)
|
|
1687
|
-
);
|
|
1688
|
-
const usageAttrs = buildModelUsageAttributes({
|
|
2519
|
+
const providerAttr = attrString("gen_ai.provider.name", canonicalModelProvider(input.providerID));
|
|
2520
|
+
const usageAttrs = buildRawModelUsageAttributes({
|
|
1689
2521
|
inputTokens: input.tokens.input,
|
|
1690
2522
|
outputTokens: input.tokens.output,
|
|
1691
2523
|
reasoningTokens: input.tokens.reasoning,
|
|
1692
2524
|
cacheReadInputTokens: input.tokens.cacheRead,
|
|
1693
|
-
cacheWriteInputTokens: input.tokens.cacheWrite
|
|
1694
|
-
inputTokenSemantics: "exclusive",
|
|
1695
|
-
outputTokenSemantics: "exclusive"
|
|
2525
|
+
cacheWriteInputTokens: input.tokens.cacheWrite
|
|
1696
2526
|
});
|
|
1697
2527
|
return providerAttr ? [providerAttr, ...usageAttrs] : usageAttrs;
|
|
1698
2528
|
}
|
|
@@ -1700,6 +2530,9 @@ function buildLlmGenAiAttributes(input) {
|
|
|
1700
2530
|
const parsed = parseOpenCodeAssistantTokens(input.tokens);
|
|
1701
2531
|
if (!parsed) return [];
|
|
1702
2532
|
return [
|
|
2533
|
+
// OpenCode has already normalized both token axes. Provenance lets Dawn
|
|
2534
|
+
// select that contract without the SDK or customer declaring semantics.
|
|
2535
|
+
attrString(MODEL_USAGE_ATTRIBUTES.usageSource, "opencode"),
|
|
1703
2536
|
attrString("gen_ai.system", input.providerID),
|
|
1704
2537
|
attrString("gen_ai.request.model", input.modelID),
|
|
1705
2538
|
attrString("gen_ai.response.model", input.modelID),
|
|
@@ -1719,11 +2552,11 @@ function createSessionParentMapHelpers({
|
|
|
1719
2552
|
}) {
|
|
1720
2553
|
function applyChildSessionParentToState(childSessionId) {
|
|
1721
2554
|
const parentInfo = mapChildSessionToParent2.get(childSessionId);
|
|
1722
|
-
const
|
|
1723
|
-
if (!parentInfo || !
|
|
1724
|
-
|
|
1725
|
-
|
|
1726
|
-
|
|
2555
|
+
const state2 = sessions2.get(childSessionId);
|
|
2556
|
+
if (!parentInfo || !state2) return;
|
|
2557
|
+
state2.parentId = parentInfo.parentId;
|
|
2558
|
+
state2.parentTaskSpanIds = parentInfo.parentTaskSpanIds;
|
|
2559
|
+
state2.parentEventContext = parentInfo.eventContext;
|
|
1727
2560
|
}
|
|
1728
2561
|
function queuePendingChildByCallKey(key, childSessionId) {
|
|
1729
2562
|
var _a;
|
|
@@ -1819,10 +2652,10 @@ function markTaskCallFinished(sessionID, callID) {
|
|
|
1819
2652
|
running.delete(callID);
|
|
1820
2653
|
if (running.size === 0) runningTaskCallsBySession.delete(sessionID);
|
|
1821
2654
|
}
|
|
1822
|
-
function endPendingToolSpanWithError(
|
|
1823
|
-
const startInfo =
|
|
2655
|
+
function endPendingToolSpanWithError(state2, callID, tool, toolCallArgs, errorMessage, traceShipper) {
|
|
2656
|
+
const startInfo = state2.toolSpanStarts.get(callID);
|
|
1824
2657
|
if (!startInfo) return false;
|
|
1825
|
-
|
|
2658
|
+
state2.toolSpanStarts.delete(callID);
|
|
1826
2659
|
const error = new Error(errorMessage);
|
|
1827
2660
|
const endAttrs = [
|
|
1828
2661
|
attrString("ai.toolCall.args", toolCallArgs),
|
|
@@ -1922,17 +2755,17 @@ function createHooks(config, worktree, directory, eventShipper, traceShipper) {
|
|
|
1922
2755
|
if (info == null || typeof info !== "object")
|
|
1923
2756
|
throw new Error("session.created: props.info is required");
|
|
1924
2757
|
const parentID = info["parentID"];
|
|
1925
|
-
let
|
|
1926
|
-
if (!
|
|
1927
|
-
|
|
1928
|
-
sessions.set(sessionID,
|
|
2758
|
+
let state2 = sessions.get(sessionID);
|
|
2759
|
+
if (!state2) {
|
|
2760
|
+
state2 = createSessionState(sessionID);
|
|
2761
|
+
sessions.set(sessionID, state2);
|
|
1929
2762
|
}
|
|
1930
|
-
|
|
1931
|
-
if (
|
|
2763
|
+
state2.parentId = parentID;
|
|
2764
|
+
if (state2.parentId) mapChildSessionToParent.set(sessionID, { parentId: state2.parentId });
|
|
1932
2765
|
} else if (event.type === "session.compacted") {
|
|
1933
|
-
const
|
|
1934
|
-
if (!
|
|
1935
|
-
|
|
2766
|
+
const state2 = sessions.get(String(sessionID));
|
|
2767
|
+
if (!state2) return;
|
|
2768
|
+
state2.isCompacting = true;
|
|
1936
2769
|
} else if (event.type === "message.part.updated") {
|
|
1937
2770
|
const part = props["part"];
|
|
1938
2771
|
if (part == null || typeof part !== "object")
|
|
@@ -1944,10 +2777,10 @@ function createHooks(config, worktree, directory, eventShipper, traceShipper) {
|
|
|
1944
2777
|
throw new Error("message.part.updated: part.sessionID is required");
|
|
1945
2778
|
if (messageId == null || messageId === "")
|
|
1946
2779
|
throw new Error("message.part.updated: part.messageID is required");
|
|
1947
|
-
const
|
|
1948
|
-
if (!
|
|
2780
|
+
const state2 = sessions.get(partSessionID);
|
|
2781
|
+
if (!state2) return;
|
|
1949
2782
|
if (partObj["type"] === "text" && typeof partObj["text"] === "string") {
|
|
1950
|
-
|
|
2783
|
+
state2.outputParts.set(messageId, capText2(partObj["text"]));
|
|
1951
2784
|
} else if (partObj["type"] === "tool" && messageId) {
|
|
1952
2785
|
const tool = partObj["tool"];
|
|
1953
2786
|
const callID = partObj["callID"];
|
|
@@ -1979,7 +2812,7 @@ function createHooks(config, worktree, directory, eventShipper, traceShipper) {
|
|
|
1979
2812
|
const input = toolState["input"];
|
|
1980
2813
|
const toolCallArgs = input === void 0 ? void 0 : typeof input === "string" ? capText2(input) : boundedStringify(input);
|
|
1981
2814
|
if (endPendingToolSpanWithError(
|
|
1982
|
-
|
|
2815
|
+
state2,
|
|
1983
2816
|
callID,
|
|
1984
2817
|
tool,
|
|
1985
2818
|
toolCallArgs,
|
|
@@ -1990,7 +2823,7 @@ function createHooks(config, worktree, directory, eventShipper, traceShipper) {
|
|
|
1990
2823
|
}
|
|
1991
2824
|
}
|
|
1992
2825
|
} else if (partObj["type"] === "reasoning" && typeof partObj["text"] === "string") {
|
|
1993
|
-
|
|
2826
|
+
state2.reasoningParts.set(messageId, capText2(partObj["text"]));
|
|
1994
2827
|
}
|
|
1995
2828
|
} else if (event.type === "message.updated") {
|
|
1996
2829
|
const msgInfo = props["info"];
|
|
@@ -2010,10 +2843,10 @@ function createHooks(config, worktree, directory, eventShipper, traceShipper) {
|
|
|
2010
2843
|
throw new Error("message.updated: info.time is required");
|
|
2011
2844
|
const timeObj = time;
|
|
2012
2845
|
if (timeObj["completed"] == null) return;
|
|
2013
|
-
const
|
|
2014
|
-
if (!
|
|
2015
|
-
if (
|
|
2016
|
-
|
|
2846
|
+
const state2 = sessions.get(msgSessionID);
|
|
2847
|
+
if (!state2 || !state2.currentEventId || !state2.currentRootSpan) return;
|
|
2848
|
+
if (state2.processedMessages.has(messageId)) return;
|
|
2849
|
+
state2.processedMessages.add(messageId);
|
|
2017
2850
|
const tokens = info2["tokens"];
|
|
2018
2851
|
if (tokens == null || typeof tokens !== "object")
|
|
2019
2852
|
throw new Error("message.updated: info.tokens is required");
|
|
@@ -2030,13 +2863,13 @@ function createHooks(config, worktree, directory, eventShipper, traceShipper) {
|
|
|
2030
2863
|
);
|
|
2031
2864
|
const modelName = `${providerID}/${modelID}`;
|
|
2032
2865
|
const finishReason = info2["finish"];
|
|
2033
|
-
const outputText =
|
|
2034
|
-
const reasoningText =
|
|
2866
|
+
const outputText = state2.outputParts.get(messageId);
|
|
2867
|
+
const reasoningText = state2.reasoningParts.get(messageId);
|
|
2035
2868
|
const isToolCallsCompletion = finishReason === "tool-calls";
|
|
2036
2869
|
if (outputText !== void 0 && outputText.trim().length > 0) {
|
|
2037
|
-
|
|
2870
|
+
state2.turnOutputParts.push(outputText);
|
|
2038
2871
|
}
|
|
2039
|
-
|
|
2872
|
+
state2.turnOutputTokens += outputTokens;
|
|
2040
2873
|
if (outputText === void 0 && !isToolCallsCompletion) return;
|
|
2041
2874
|
const msgError = info2["error"];
|
|
2042
2875
|
const errorForSpan = msgError ? (() => {
|
|
@@ -2056,17 +2889,17 @@ type: ${name != null ? name : "UnknownError"}`;
|
|
|
2056
2889
|
attrString("ai.response.text", responseText),
|
|
2057
2890
|
...buildLlmGenAiAttributes({ providerID, modelID, tokens: tokensObj })
|
|
2058
2891
|
];
|
|
2059
|
-
if (
|
|
2892
|
+
if (state2.currentSystemPrompt) {
|
|
2060
2893
|
llmAttrs.push(
|
|
2061
2894
|
attrString("gen_ai.prompt.0.role", "system"),
|
|
2062
|
-
attrString("gen_ai.prompt.0.content",
|
|
2895
|
+
attrString("gen_ai.prompt.0.content", state2.currentSystemPrompt)
|
|
2063
2896
|
);
|
|
2064
2897
|
}
|
|
2065
|
-
const llmParent =
|
|
2898
|
+
const llmParent = state2.parentId && state2.parentTaskSpanIds ? state2.parentTaskSpanIds : state2.currentRootSpan.ids;
|
|
2066
2899
|
const llmSpan = traceShipper.startSpan({
|
|
2067
2900
|
name: modelName,
|
|
2068
2901
|
parent: llmParent,
|
|
2069
|
-
eventId:
|
|
2902
|
+
eventId: state2.currentEventId,
|
|
2070
2903
|
attributes: llmAttrs
|
|
2071
2904
|
});
|
|
2072
2905
|
if (typeof timeObj["created"] === "number") {
|
|
@@ -2077,40 +2910,40 @@ type: ${name != null ? name : "UnknownError"}`;
|
|
|
2077
2910
|
return;
|
|
2078
2911
|
}
|
|
2079
2912
|
if (outputText === void 0) return;
|
|
2080
|
-
const turnOutputText = capText2(
|
|
2081
|
-
const rootSpan =
|
|
2082
|
-
const isCompaction =
|
|
2083
|
-
if (
|
|
2084
|
-
const userInput = unwrapQuotes(
|
|
2913
|
+
const turnOutputText = capText2(state2.turnOutputParts.join("\n\n"));
|
|
2914
|
+
const rootSpan = state2.currentRootSpan;
|
|
2915
|
+
const isCompaction = state2.isCompacting === true;
|
|
2916
|
+
if (state2.parentId) {
|
|
2917
|
+
const userInput = unwrapQuotes(state2.currentInput);
|
|
2085
2918
|
const llmAttrs = [
|
|
2086
2919
|
attrString("ai.operationId", "generateText"),
|
|
2087
2920
|
attrString("ai.prompt", userInput),
|
|
2088
2921
|
attrString(
|
|
2089
2922
|
"ai.prompt.messages",
|
|
2090
|
-
buildPromptMessages(
|
|
2923
|
+
buildPromptMessages(state2.currentSystemPrompt, state2.currentInput)
|
|
2091
2924
|
),
|
|
2092
2925
|
attrString("ai.response.text", turnOutputText),
|
|
2093
2926
|
...buildLlmGenAiAttributes({ providerID, modelID, tokens: tokensObj })
|
|
2094
2927
|
];
|
|
2095
|
-
if (
|
|
2928
|
+
if (state2.currentSystemPrompt) {
|
|
2096
2929
|
llmAttrs.push(
|
|
2097
2930
|
attrString("gen_ai.prompt.0.role", "system"),
|
|
2098
|
-
attrString("gen_ai.prompt.0.content",
|
|
2931
|
+
attrString("gen_ai.prompt.0.content", state2.currentSystemPrompt)
|
|
2099
2932
|
);
|
|
2100
2933
|
}
|
|
2101
|
-
if (!
|
|
2934
|
+
if (!state2.parentTaskSpanIds) {
|
|
2102
2935
|
traceShipper.endSpan(rootSpan, {
|
|
2103
2936
|
error: "Missing strict parent task for child session"
|
|
2104
2937
|
});
|
|
2105
|
-
|
|
2106
|
-
|
|
2938
|
+
state2.currentRootSpan = void 0;
|
|
2939
|
+
state2.currentEventId = void 0;
|
|
2107
2940
|
await traceShipper.flush();
|
|
2108
2941
|
return;
|
|
2109
2942
|
}
|
|
2110
2943
|
const finalLlmSpan = traceShipper.startSpan({
|
|
2111
2944
|
name: modelName,
|
|
2112
|
-
parent:
|
|
2113
|
-
eventId:
|
|
2945
|
+
parent: state2.parentTaskSpanIds,
|
|
2946
|
+
eventId: state2.currentEventId,
|
|
2114
2947
|
attributes: llmAttrs
|
|
2115
2948
|
});
|
|
2116
2949
|
if (typeof timeObj["created"] === "number") {
|
|
@@ -2120,19 +2953,19 @@ type: ${name != null ? name : "UnknownError"}`;
|
|
|
2120
2953
|
traceShipper.endSpan(rootSpan, {
|
|
2121
2954
|
attributes: [
|
|
2122
2955
|
attrString("is_subagent", "true"),
|
|
2123
|
-
attrString("parent_session_id",
|
|
2956
|
+
attrString("parent_session_id", state2.parentId)
|
|
2124
2957
|
],
|
|
2125
2958
|
error: errorForSpan
|
|
2126
2959
|
});
|
|
2127
2960
|
} else {
|
|
2128
2961
|
rootSpan.name = isCompaction ? "ai.compaction" : modelName;
|
|
2129
|
-
const userInput = unwrapQuotes(
|
|
2962
|
+
const userInput = unwrapQuotes(state2.currentInput);
|
|
2130
2963
|
const rootAttrs = [
|
|
2131
2964
|
attrString("ai.operationId", "generateText"),
|
|
2132
2965
|
attrString("ai.prompt", userInput),
|
|
2133
2966
|
attrString(
|
|
2134
2967
|
"ai.prompt.messages",
|
|
2135
|
-
buildPromptMessages(
|
|
2968
|
+
buildPromptMessages(state2.currentSystemPrompt, state2.currentInput)
|
|
2136
2969
|
),
|
|
2137
2970
|
attrString("ai.response.text", turnOutputText),
|
|
2138
2971
|
...buildLlmGenAiAttributes({ providerID, modelID, tokens: tokensObj })
|
|
@@ -2141,10 +2974,10 @@ type: ${name != null ? name : "UnknownError"}`;
|
|
|
2141
2974
|
rootAttrs.push(attrString("is_compaction", "true"));
|
|
2142
2975
|
}
|
|
2143
2976
|
rootAttrs.push(attrString("message_id", messageId));
|
|
2144
|
-
if (
|
|
2977
|
+
if (state2.currentSystemPrompt) {
|
|
2145
2978
|
rootAttrs.push(
|
|
2146
2979
|
attrString("gen_ai.prompt.0.role", "system"),
|
|
2147
|
-
attrString("gen_ai.prompt.0.content",
|
|
2980
|
+
attrString("gen_ai.prompt.0.content", state2.currentSystemPrompt)
|
|
2148
2981
|
);
|
|
2149
2982
|
}
|
|
2150
2983
|
traceShipper.endSpan(rootSpan, {
|
|
@@ -2152,24 +2985,24 @@ type: ${name != null ? name : "UnknownError"}`;
|
|
|
2152
2985
|
error: errorForSpan
|
|
2153
2986
|
});
|
|
2154
2987
|
if (isCompaction) {
|
|
2155
|
-
|
|
2988
|
+
state2.isCompacting = false;
|
|
2156
2989
|
}
|
|
2157
2990
|
}
|
|
2158
|
-
|
|
2991
|
+
state2.currentRootSpan = void 0;
|
|
2159
2992
|
const hasAssistantResponse = turnOutputText.trim().length > 0;
|
|
2160
2993
|
if (!hasAssistantResponse && !msgError) {
|
|
2161
2994
|
await traceShipper.flush();
|
|
2162
|
-
|
|
2995
|
+
state2.currentEventId = void 0;
|
|
2163
2996
|
return;
|
|
2164
2997
|
}
|
|
2165
|
-
if (!
|
|
2166
|
-
await eventShipper.finish(
|
|
2167
|
-
userId: (_d = (_c =
|
|
2998
|
+
if (!state2.parentId) {
|
|
2999
|
+
await eventShipper.finish(state2.currentEventId, {
|
|
3000
|
+
userId: (_d = (_c = state2.eventMetadata) == null ? void 0 : _c.userId) != null ? _d : state2.sessionId,
|
|
2168
3001
|
model: modelID,
|
|
2169
3002
|
output: msgError ? void 0 : turnOutputText,
|
|
2170
3003
|
usage: {
|
|
2171
3004
|
promptTokens: inputTokens,
|
|
2172
|
-
completionTokens:
|
|
3005
|
+
completionTokens: state2.turnOutputTokens
|
|
2173
3006
|
},
|
|
2174
3007
|
error: msgError ? {
|
|
2175
3008
|
name: msgError.name,
|
|
@@ -2184,35 +3017,35 @@ type: ${name != null ? name : "UnknownError"}`;
|
|
|
2184
3017
|
});
|
|
2185
3018
|
}
|
|
2186
3019
|
await traceShipper.flush();
|
|
2187
|
-
|
|
3020
|
+
state2.currentEventId = void 0;
|
|
2188
3021
|
} else if (event.type === "session.idle") {
|
|
2189
3022
|
if (!sessionID) return;
|
|
2190
|
-
const
|
|
2191
|
-
if (!
|
|
2192
|
-
if (
|
|
2193
|
-
traceShipper.endSpan(
|
|
2194
|
-
|
|
3023
|
+
const state2 = sessions.get(String(sessionID));
|
|
3024
|
+
if (!state2) return;
|
|
3025
|
+
if (state2.currentRootSpan) {
|
|
3026
|
+
traceShipper.endSpan(state2.currentRootSpan);
|
|
3027
|
+
state2.currentRootSpan = void 0;
|
|
2195
3028
|
}
|
|
2196
|
-
if (
|
|
2197
|
-
|
|
3029
|
+
if (state2.currentEventId) {
|
|
3030
|
+
state2.currentEventId = void 0;
|
|
2198
3031
|
}
|
|
2199
|
-
|
|
3032
|
+
state2.isCompacting = false;
|
|
2200
3033
|
await Promise.all([eventShipper.flush(), traceShipper.flush()]);
|
|
2201
|
-
if (
|
|
3034
|
+
if (state2.parentId) {
|
|
2202
3035
|
cleanupSessionParentMap(String(sessionID));
|
|
2203
3036
|
sessions.delete(String(sessionID));
|
|
2204
3037
|
} else {
|
|
2205
3038
|
}
|
|
2206
3039
|
} else if (event.type === "session.deleted") {
|
|
2207
3040
|
if (!sessionID) return;
|
|
2208
|
-
const
|
|
2209
|
-
if (!
|
|
2210
|
-
if (
|
|
2211
|
-
traceShipper.endSpan(
|
|
2212
|
-
|
|
3041
|
+
const state2 = sessions.get(String(sessionID));
|
|
3042
|
+
if (!state2) return;
|
|
3043
|
+
if (state2.currentRootSpan) {
|
|
3044
|
+
traceShipper.endSpan(state2.currentRootSpan);
|
|
3045
|
+
state2.currentRootSpan = void 0;
|
|
2213
3046
|
}
|
|
2214
|
-
if (
|
|
2215
|
-
|
|
3047
|
+
if (state2.currentEventId) {
|
|
3048
|
+
state2.currentEventId = void 0;
|
|
2216
3049
|
}
|
|
2217
3050
|
cleanupSessionParentMap(String(sessionID));
|
|
2218
3051
|
await Promise.all([eventShipper.flush(), traceShipper.flush()]);
|
|
@@ -2221,8 +3054,8 @@ type: ${name != null ? name : "UnknownError"}`;
|
|
|
2221
3054
|
const errorSessionID = (_h = props["sessionID"]) != null ? _h : sessionID;
|
|
2222
3055
|
if (errorSessionID === void 0 || errorSessionID === "")
|
|
2223
3056
|
throw new Error("session.error: missing sessionID");
|
|
2224
|
-
const
|
|
2225
|
-
if (!
|
|
3057
|
+
const state2 = sessions.get(String(errorSessionID));
|
|
3058
|
+
if (!state2) return;
|
|
2226
3059
|
const errorObj = props["error"];
|
|
2227
3060
|
if (errorObj == null) throw new Error("session.error: missing error object");
|
|
2228
3061
|
const errorName = errorObj.name;
|
|
@@ -2232,12 +3065,12 @@ type: ${name != null ? name : "UnknownError"}`;
|
|
|
2232
3065
|
const errorStr = `${errorMessage != null ? errorMessage : errorName}
|
|
2233
3066
|
|
|
2234
3067
|
type: ${errorName != null ? errorName : "UnknownError"}`;
|
|
2235
|
-
if (
|
|
2236
|
-
traceShipper.endSpan(
|
|
2237
|
-
|
|
3068
|
+
if (state2.currentRootSpan) {
|
|
3069
|
+
traceShipper.endSpan(state2.currentRootSpan, { error: errorStr });
|
|
3070
|
+
state2.currentRootSpan = void 0;
|
|
2238
3071
|
}
|
|
2239
|
-
if (
|
|
2240
|
-
|
|
3072
|
+
if (state2.currentEventId) {
|
|
3073
|
+
state2.currentEventId = void 0;
|
|
2241
3074
|
}
|
|
2242
3075
|
cleanupSessionParentMap(String(errorSessionID));
|
|
2243
3076
|
await Promise.all([eventShipper.flush(), traceShipper.flush()]);
|
|
@@ -2257,15 +3090,15 @@ type: ${errorName != null ? errorName : "UnknownError"}`;
|
|
|
2257
3090
|
var _a, _b, _c, _d, _e, _f, _g;
|
|
2258
3091
|
try {
|
|
2259
3092
|
const { sessionID } = messageInput;
|
|
2260
|
-
let
|
|
2261
|
-
if (!
|
|
2262
|
-
|
|
2263
|
-
sessions.set(sessionID,
|
|
3093
|
+
let state2 = sessions.get(sessionID);
|
|
3094
|
+
if (!state2) {
|
|
3095
|
+
state2 = createSessionState(sessionID);
|
|
3096
|
+
sessions.set(sessionID, state2);
|
|
2264
3097
|
}
|
|
2265
3098
|
applyChildSessionParentToState(sessionID);
|
|
2266
|
-
if (
|
|
2267
|
-
traceShipper.endSpan(
|
|
2268
|
-
|
|
3099
|
+
if (state2.currentRootSpan) {
|
|
3100
|
+
traceShipper.endSpan(state2.currentRootSpan);
|
|
3101
|
+
state2.currentRootSpan = void 0;
|
|
2269
3102
|
}
|
|
2270
3103
|
if (output == null) throw new Error("chat.message: output is required");
|
|
2271
3104
|
const parts = output.parts;
|
|
@@ -2296,39 +3129,39 @@ type: ${errorName != null ? errorName : "UnknownError"}`;
|
|
|
2296
3129
|
}
|
|
2297
3130
|
}
|
|
2298
3131
|
}
|
|
2299
|
-
|
|
3132
|
+
state2.eventMetadata = {
|
|
2300
3133
|
...baseMeta,
|
|
2301
3134
|
...promptMeta,
|
|
2302
3135
|
properties: baseMeta.properties || promptMeta.properties ? { ...(_a = baseMeta.properties) != null ? _a : {}, ...(_b = promptMeta.properties) != null ? _b : {} } : void 0
|
|
2303
3136
|
};
|
|
2304
3137
|
const userText = capText2(textParts.join("\n"));
|
|
2305
|
-
|
|
2306
|
-
|
|
2307
|
-
|
|
2308
|
-
if (
|
|
2309
|
-
if (!
|
|
3138
|
+
state2.currentInput = userText;
|
|
3139
|
+
state2.turnOutputParts = [];
|
|
3140
|
+
state2.turnOutputTokens = 0;
|
|
3141
|
+
if (state2.parentId) {
|
|
3142
|
+
if (!state2.parentTaskSpanIds || !state2.parentEventContext) {
|
|
2310
3143
|
return;
|
|
2311
3144
|
}
|
|
2312
|
-
|
|
2313
|
-
|
|
3145
|
+
state2.currentEventId = state2.parentEventContext.eventId;
|
|
3146
|
+
state2.currentRootSpan = traceShipper.startSpan({
|
|
2314
3147
|
name: "Subagent",
|
|
2315
|
-
parent:
|
|
2316
|
-
eventId:
|
|
3148
|
+
parent: state2.parentTaskSpanIds,
|
|
3149
|
+
eventId: state2.currentEventId,
|
|
2317
3150
|
attributes: [
|
|
2318
3151
|
attrString("workspace", worktree),
|
|
2319
3152
|
attrString("directory", directory),
|
|
2320
3153
|
attrString("hostname", hostname),
|
|
2321
3154
|
attrString("os", os),
|
|
2322
3155
|
attrString("is_subagent", "true"),
|
|
2323
|
-
attrString("parent_session_id",
|
|
3156
|
+
attrString("parent_session_id", state2.parentId)
|
|
2324
3157
|
]
|
|
2325
3158
|
});
|
|
2326
3159
|
return;
|
|
2327
3160
|
}
|
|
2328
|
-
|
|
2329
|
-
|
|
2330
|
-
name:
|
|
2331
|
-
eventId:
|
|
3161
|
+
state2.currentEventId = generateId();
|
|
3162
|
+
state2.currentRootSpan = traceShipper.startSpan({
|
|
3163
|
+
name: state2.isCompacting ? "ai.compaction" : "ai.event",
|
|
3164
|
+
eventId: state2.currentEventId,
|
|
2332
3165
|
attributes: [
|
|
2333
3166
|
attrString("workspace", worktree),
|
|
2334
3167
|
attrString("directory", directory),
|
|
@@ -2336,11 +3169,11 @@ type: ${errorName != null ? errorName : "UnknownError"}`;
|
|
|
2336
3169
|
attrString("os", os)
|
|
2337
3170
|
]
|
|
2338
3171
|
});
|
|
2339
|
-
await eventShipper.patch(
|
|
3172
|
+
await eventShipper.patch(state2.currentEventId, {
|
|
2340
3173
|
isPending: true,
|
|
2341
|
-
userId: (_d = (_c =
|
|
2342
|
-
convoId:
|
|
2343
|
-
eventName: (_f = (_e =
|
|
3174
|
+
userId: (_d = (_c = state2.eventMetadata) == null ? void 0 : _c.userId) != null ? _d : state2.sessionId,
|
|
3175
|
+
convoId: state2.sessionId,
|
|
3176
|
+
eventName: (_f = (_e = state2.eventMetadata) == null ? void 0 : _e.eventName) != null ? _f : config.eventName,
|
|
2344
3177
|
input: userText,
|
|
2345
3178
|
...newAttachments.length > 0 ? { attachments: newAttachments } : {},
|
|
2346
3179
|
properties: {
|
|
@@ -2349,7 +3182,7 @@ type: ${errorName != null ? errorName : "UnknownError"}`;
|
|
|
2349
3182
|
hostname,
|
|
2350
3183
|
os,
|
|
2351
3184
|
plugin_version: PLUGIN_VERSION,
|
|
2352
|
-
...(_g =
|
|
3185
|
+
...(_g = state2.eventMetadata) == null ? void 0 : _g.properties
|
|
2353
3186
|
}
|
|
2354
3187
|
});
|
|
2355
3188
|
} catch (err) {
|
|
@@ -2363,16 +3196,16 @@ type: ${errorName != null ? errorName : "UnknownError"}`;
|
|
|
2363
3196
|
var _a, _b, _c;
|
|
2364
3197
|
try {
|
|
2365
3198
|
const { tool, sessionID, callID } = toolInput;
|
|
2366
|
-
const
|
|
2367
|
-
if (!
|
|
2368
|
-
const spanParent =
|
|
3199
|
+
const state2 = sessions.get(sessionID);
|
|
3200
|
+
if (!state2 || !state2.currentEventId) return;
|
|
3201
|
+
const spanParent = state2.parentId && state2.parentTaskSpanIds ? state2.parentTaskSpanIds : (_a = state2.currentRootSpan) == null ? void 0 : _a.ids;
|
|
2369
3202
|
if (!spanParent) return;
|
|
2370
3203
|
const startTimeUnixNano = nowUnixNanoString();
|
|
2371
3204
|
if (tool === "task") {
|
|
2372
3205
|
const liveTaskSpan = traceShipper.startSpan({
|
|
2373
3206
|
name: "ai.toolCall",
|
|
2374
3207
|
parent: spanParent,
|
|
2375
|
-
eventId:
|
|
3208
|
+
eventId: state2.currentEventId,
|
|
2376
3209
|
attributes: [
|
|
2377
3210
|
attrString("ai.operationId", "ai.toolCall"),
|
|
2378
3211
|
attrString("ai.toolCall.name", tool),
|
|
@@ -2383,9 +3216,9 @@ type: ${errorName != null ? errorName : "UnknownError"}`;
|
|
|
2383
3216
|
const ctx = {
|
|
2384
3217
|
ids: liveTaskSpan.ids,
|
|
2385
3218
|
eventContext: {
|
|
2386
|
-
eventId:
|
|
2387
|
-
userId: (_c = (_b =
|
|
2388
|
-
convoId:
|
|
3219
|
+
eventId: state2.currentEventId,
|
|
3220
|
+
userId: (_c = (_b = state2.eventMetadata) == null ? void 0 : _b.userId) != null ? _c : state2.sessionId,
|
|
3221
|
+
convoId: state2.sessionId
|
|
2389
3222
|
}
|
|
2390
3223
|
};
|
|
2391
3224
|
taskContexts.set(callKey(sessionID, callID), ctx);
|
|
@@ -2396,18 +3229,18 @@ type: ${errorName != null ? errorName : "UnknownError"}`;
|
|
|
2396
3229
|
}
|
|
2397
3230
|
running.add(callID);
|
|
2398
3231
|
resolvePendingChildrenForCall(sessionID, callID, "tool.execute.before");
|
|
2399
|
-
|
|
3232
|
+
state2.toolSpanStarts.set(callID, {
|
|
2400
3233
|
startTimeUnixNano,
|
|
2401
3234
|
parent: spanParent,
|
|
2402
|
-
eventId:
|
|
3235
|
+
eventId: state2.currentEventId,
|
|
2403
3236
|
name: tool,
|
|
2404
3237
|
liveSpan: liveTaskSpan
|
|
2405
3238
|
});
|
|
2406
3239
|
} else {
|
|
2407
|
-
|
|
3240
|
+
state2.toolSpanStarts.set(callID, {
|
|
2408
3241
|
startTimeUnixNano,
|
|
2409
3242
|
parent: spanParent,
|
|
2410
|
-
eventId:
|
|
3243
|
+
eventId: state2.currentEventId,
|
|
2411
3244
|
name: tool
|
|
2412
3245
|
});
|
|
2413
3246
|
}
|
|
@@ -2424,13 +3257,13 @@ type: ${errorName != null ? errorName : "UnknownError"}`;
|
|
|
2424
3257
|
"tool.execute.after": async (toolInput, result) => {
|
|
2425
3258
|
try {
|
|
2426
3259
|
const { tool, sessionID, callID, args } = toolInput;
|
|
2427
|
-
const
|
|
2428
|
-
if (!
|
|
3260
|
+
const state2 = sessions.get(sessionID);
|
|
3261
|
+
if (!state2 || !state2.currentEventId) return;
|
|
2429
3262
|
if (args === void 0 || args === null)
|
|
2430
3263
|
throw new Error("tool.execute.after: args is required");
|
|
2431
3264
|
const toolCallArgs = typeof args === "string" ? capText2(args) : boundedStringify(args);
|
|
2432
|
-
const startInfo =
|
|
2433
|
-
|
|
3265
|
+
const startInfo = state2.toolSpanStarts.get(callID);
|
|
3266
|
+
state2.toolSpanStarts.delete(callID);
|
|
2434
3267
|
const resultMetadata = result.metadata;
|
|
2435
3268
|
const childSessionId = resultMetadata == null ? void 0 : resultMetadata["sessionId"];
|
|
2436
3269
|
if (tool === "task" && childSessionId) {
|
|
@@ -2483,9 +3316,9 @@ type: ${errorName != null ? errorName : "UnknownError"}`;
|
|
|
2483
3316
|
try {
|
|
2484
3317
|
const sessionID = input.sessionID;
|
|
2485
3318
|
if (!sessionID) return;
|
|
2486
|
-
const
|
|
2487
|
-
if (
|
|
2488
|
-
|
|
3319
|
+
const state2 = sessions.get(sessionID);
|
|
3320
|
+
if (state2) {
|
|
3321
|
+
state2.isCompacting = true;
|
|
2489
3322
|
}
|
|
2490
3323
|
} catch (err) {
|
|
2491
3324
|
rateLimitedErrorLog(
|
|
@@ -2502,15 +3335,15 @@ type: ${errorName != null ? errorName : "UnknownError"}`;
|
|
|
2502
3335
|
if (!config.captureSystemPrompt) return;
|
|
2503
3336
|
const sessionID = input.sessionID;
|
|
2504
3337
|
if (!sessionID) return;
|
|
2505
|
-
let
|
|
2506
|
-
if (!
|
|
2507
|
-
|
|
2508
|
-
sessions.set(sessionID,
|
|
3338
|
+
let state2 = sessions.get(sessionID);
|
|
3339
|
+
if (!state2) {
|
|
3340
|
+
state2 = createSessionState(sessionID);
|
|
3341
|
+
sessions.set(sessionID, state2);
|
|
2509
3342
|
}
|
|
2510
3343
|
const MAX_SYSTEM_PROMPT_LENGTH = 32768;
|
|
2511
3344
|
const TRUNCATION_MARKER3 = "\n...[truncated]";
|
|
2512
3345
|
const joined = output.system.join("\n\n");
|
|
2513
|
-
|
|
3346
|
+
state2.currentSystemPrompt = joined.length > MAX_SYSTEM_PROMPT_LENGTH ? joined.slice(0, MAX_SYSTEM_PROMPT_LENGTH - TRUNCATION_MARKER3.length) + TRUNCATION_MARKER3 : joined;
|
|
2514
3347
|
} catch (err) {
|
|
2515
3348
|
rateLimitedErrorLog(
|
|
2516
3349
|
"experimental.chat.system.transform",
|
|
@@ -2522,7 +3355,7 @@ type: ${errorName != null ? errorName : "UnknownError"}`;
|
|
|
2522
3355
|
}
|
|
2523
3356
|
|
|
2524
3357
|
// src/index.ts
|
|
2525
|
-
function createRaindropHandle(eventShipper, traceShipper) {
|
|
3358
|
+
function createRaindropHandle(eventShipper, traceShipper, appGitContext) {
|
|
2526
3359
|
return {
|
|
2527
3360
|
users: {
|
|
2528
3361
|
async identify(users) {
|
|
@@ -2533,12 +3366,19 @@ function createRaindropHandle(eventShipper, traceShipper) {
|
|
|
2533
3366
|
await Promise.all([eventShipper.flush(), traceShipper.flush()]);
|
|
2534
3367
|
},
|
|
2535
3368
|
async shutdown() {
|
|
2536
|
-
|
|
3369
|
+
try {
|
|
3370
|
+
await Promise.all([eventShipper.shutdown(), traceShipper.shutdown()]);
|
|
3371
|
+
} finally {
|
|
3372
|
+
try {
|
|
3373
|
+
appGitContext.dispose();
|
|
3374
|
+
} catch (e) {
|
|
3375
|
+
}
|
|
3376
|
+
}
|
|
2537
3377
|
}
|
|
2538
3378
|
};
|
|
2539
3379
|
}
|
|
2540
|
-
async function plugin(input) {
|
|
2541
|
-
var _a;
|
|
3380
|
+
async function plugin(input, opts = {}) {
|
|
3381
|
+
var _a, _b, _c;
|
|
2542
3382
|
const config = loadConfig(input.directory);
|
|
2543
3383
|
function appLog(level, message) {
|
|
2544
3384
|
console.log(`[raindrop-ai/opencode-plugin] [${level}] ${message}`);
|
|
@@ -2560,21 +3400,28 @@ async function plugin(input) {
|
|
|
2560
3400
|
].filter(Boolean);
|
|
2561
3401
|
appLog("info", `Raindrop tracing enabled \u2014 destinations: ${destinations.join(", ")}`);
|
|
2562
3402
|
}
|
|
2563
|
-
const
|
|
3403
|
+
const configuredAppGit = (_a = opts.appGit) != null ? _a : config.appGit;
|
|
3404
|
+
const appGitContext = createAppGitContext2(
|
|
3405
|
+
((_b = config.writeKey) == null ? void 0 : _b.trim()) || hasLocalDestination ? configuredAppGit : false,
|
|
3406
|
+
{ allowLocalGit: false }
|
|
3407
|
+
);
|
|
3408
|
+
const eventShipper = new EventShipper3({
|
|
2564
3409
|
writeKey: config.writeKey,
|
|
2565
3410
|
endpoint: config.endpoint,
|
|
2566
3411
|
debug: config.debug,
|
|
2567
3412
|
projectId: config.projectId,
|
|
2568
|
-
localDebuggerUrl: config.localWorkshopUrl
|
|
3413
|
+
localDebuggerUrl: config.localWorkshopUrl,
|
|
3414
|
+
appGitContext
|
|
2569
3415
|
});
|
|
2570
|
-
const traceShipper = new
|
|
3416
|
+
const traceShipper = new TraceShipper3({
|
|
2571
3417
|
writeKey: config.writeKey,
|
|
2572
3418
|
endpoint: config.endpoint,
|
|
2573
3419
|
debug: config.debug,
|
|
2574
3420
|
projectId: config.projectId,
|
|
2575
|
-
localDebuggerUrl: config.localWorkshopUrl
|
|
3421
|
+
localDebuggerUrl: config.localWorkshopUrl,
|
|
3422
|
+
appGitContext
|
|
2576
3423
|
});
|
|
2577
|
-
const worktree = (
|
|
3424
|
+
const worktree = (_c = input.worktree) != null ? _c : input.directory;
|
|
2578
3425
|
const hooks = createHooks(
|
|
2579
3426
|
config,
|
|
2580
3427
|
worktree,
|
|
@@ -2582,7 +3429,7 @@ async function plugin(input) {
|
|
|
2582
3429
|
eventShipper,
|
|
2583
3430
|
traceShipper
|
|
2584
3431
|
);
|
|
2585
|
-
return { ...hooks, raindrop: createRaindropHandle(eventShipper, traceShipper) };
|
|
3432
|
+
return { ...hooks, raindrop: createRaindropHandle(eventShipper, traceShipper, appGitContext) };
|
|
2586
3433
|
}
|
|
2587
3434
|
export {
|
|
2588
3435
|
plugin as default
|