@raindrop-ai/openai-managed-agents 0.0.3 → 0.0.5
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 +26 -0
- package/dist/index.d.mts +278 -28
- package/dist/index.d.ts +278 -28
- package/dist/index.js +1539 -299
- package/dist/index.mjs +1539 -299
- package/package.json +5 -5
package/dist/index.js
CHANGED
|
@@ -25,7 +25,36 @@ __export(index_exports, {
|
|
|
25
25
|
});
|
|
26
26
|
module.exports = __toCommonJS(index_exports);
|
|
27
27
|
|
|
28
|
-
// ../core/dist/chunk-
|
|
28
|
+
// ../core/dist/chunk-ZCB62SIO.js
|
|
29
|
+
var __create = Object.create;
|
|
30
|
+
var __defProp2 = Object.defineProperty;
|
|
31
|
+
var __getOwnPropDesc2 = Object.getOwnPropertyDescriptor;
|
|
32
|
+
var __getOwnPropNames2 = Object.getOwnPropertyNames;
|
|
33
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
34
|
+
var __hasOwnProp2 = Object.prototype.hasOwnProperty;
|
|
35
|
+
var __commonJS = (cb, mod) => function __require() {
|
|
36
|
+
try {
|
|
37
|
+
return mod || (0, cb[__getOwnPropNames2(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
|
|
38
|
+
} catch (e) {
|
|
39
|
+
throw mod = 0, e;
|
|
40
|
+
}
|
|
41
|
+
};
|
|
42
|
+
var __copyProps2 = (to, from, except, desc) => {
|
|
43
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
44
|
+
for (let key of __getOwnPropNames2(from))
|
|
45
|
+
if (!__hasOwnProp2.call(to, key) && key !== except)
|
|
46
|
+
__defProp2(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc2(from, key)) || desc.enumerable });
|
|
47
|
+
}
|
|
48
|
+
return to;
|
|
49
|
+
};
|
|
50
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps2(
|
|
51
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
52
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
53
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
54
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
55
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp2(target, "default", { value: mod, enumerable: true }) : target,
|
|
56
|
+
mod
|
|
57
|
+
));
|
|
29
58
|
var EVAL_CORRELATION_ID_ATTRIBUTE = "raindrop.eval_correlation_id";
|
|
30
59
|
var PROBE_SCOPE = { correlationId: "" };
|
|
31
60
|
var EvalScopeStorage = class {
|
|
@@ -87,21 +116,246 @@ function evalScopeAttributes() {
|
|
|
87
116
|
return { [EVAL_CORRELATION_ID_ATTRIBUTE]: scope.correlationId };
|
|
88
117
|
}
|
|
89
118
|
|
|
90
|
-
// ../core/dist/chunk-
|
|
119
|
+
// ../core/dist/chunk-AX36JKJL.js
|
|
120
|
+
var require_NameRedactor = __commonJS({
|
|
121
|
+
"../redact-pii/dist/built-ins/NameRedactor.js"(exports2) {
|
|
122
|
+
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
123
|
+
exports2.NameRedactor = void 0;
|
|
124
|
+
var greetingRegex = /(^|\.\s+)(dear|hi|hello|greetings|hey|hey there)/gi;
|
|
125
|
+
var closingRegex = /(thx|thanks|thank you|regards|best|[a-z]{1,30}ly|[a-z]{1,30} regards|all the best|happy [a-z]{1,30}ing|take care|have a [a-z]{1,30} (weekend|night|day))/gi;
|
|
126
|
+
var greetingOrClosing = new RegExp("(((" + greetingRegex.source + ")|(" + closingRegex.source + "\\s*[,.!]*))[\\s-]*)", "gi");
|
|
127
|
+
var genericName = new RegExp("( ?(([A-Z][a-z]{1,30})|([A-Z]\\.))){1,10}([,.]|[,.]?$)", "my");
|
|
128
|
+
var NameRedactor = class {
|
|
129
|
+
constructor(replaceWith = "PERSON_NAME") {
|
|
130
|
+
this.replaceWith = replaceWith;
|
|
131
|
+
}
|
|
132
|
+
redact(textToRedact) {
|
|
133
|
+
var _a;
|
|
134
|
+
greetingOrClosing.lastIndex = 0;
|
|
135
|
+
genericName.lastIndex = 0;
|
|
136
|
+
const pieces = [];
|
|
137
|
+
let copiedThrough = 0;
|
|
138
|
+
let changed = false;
|
|
139
|
+
let greetingOrClosingMatch = greetingOrClosing.exec(textToRedact);
|
|
140
|
+
while (greetingOrClosingMatch !== null) {
|
|
141
|
+
genericName.lastIndex = greetingOrClosing.lastIndex;
|
|
142
|
+
const genericNameMatch = genericName.exec(textToRedact);
|
|
143
|
+
if (genericNameMatch !== null && genericNameMatch.index === greetingOrClosing.lastIndex) {
|
|
144
|
+
const suffix = (_a = genericNameMatch[5]) !== null && _a !== void 0 ? _a : "";
|
|
145
|
+
const end = genericNameMatch.index + genericNameMatch[0].length;
|
|
146
|
+
pieces.push(textToRedact.slice(copiedThrough, genericNameMatch.index), this.replaceWith, suffix);
|
|
147
|
+
copiedThrough = end;
|
|
148
|
+
changed = true;
|
|
149
|
+
greetingOrClosing.lastIndex = end - suffix.length;
|
|
150
|
+
}
|
|
151
|
+
greetingOrClosingMatch = greetingOrClosing.exec(textToRedact);
|
|
152
|
+
}
|
|
153
|
+
if (!changed)
|
|
154
|
+
return textToRedact;
|
|
155
|
+
pieces.push(textToRedact.slice(copiedThrough));
|
|
156
|
+
return pieces.join("");
|
|
157
|
+
}
|
|
158
|
+
};
|
|
159
|
+
exports2.NameRedactor = NameRedactor;
|
|
160
|
+
}
|
|
161
|
+
});
|
|
162
|
+
var require_simple_regexp_patterns = __commonJS({
|
|
163
|
+
"../redact-pii/dist/built-ins/simple-regexp-patterns.js"(exports2) {
|
|
164
|
+
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
165
|
+
exports2.url = exports2.digits = exports2.credentials = exports2.password = exports2.username = exports2.emailAddress = exports2.usSocialSecurityNumber = exports2.ipAddress = exports2.phoneNumber = exports2.zipcode = exports2.streetAddress = exports2.creditCardNumber = void 0;
|
|
166
|
+
var aptRegex = /(apt|bldg|dept|fl|hngr|lot|pier|rm|ste|slip|trlr|unit|#)\.? *[a-z0-9-]+\b/gi;
|
|
167
|
+
var poBoxRegex = /P\.? ?O\.? *Box +\d+/gi;
|
|
168
|
+
var roadRegex = /(street|st|road|rd|avenue|ave|drive|dr|loop|court|ct|circle|cir|lane|ln|boulevard|blvd|way)\.?\b/gi;
|
|
169
|
+
exports2.creditCardNumber = /\d{4}[ -]?\d{4}[ -]?\d{4}[ -]?\d{4}|\d{4}[ -]?\d{6}[ -]?\d{4}\d?/g;
|
|
170
|
+
exports2.streetAddress = new RegExp("(\\d{1,10}\\s*(\\w{1,30} ){1,2}" + roadRegex.source + "(\\s+" + aptRegex.source + ")?)|(" + poBoxRegex.source + ")", "gi");
|
|
171
|
+
exports2.zipcode = /\b\d{5}\b(-\d{4})?\b/g;
|
|
172
|
+
exports2.phoneNumber = /(\(?\+?[0-9]{1,2}\)?[-. ]?)?(\(?[0-9]{3}\)?|[0-9]{3})[-. ]?([0-9]{3}[-. ]?[0-9]{4}|\b[A-Z0-9]{7}\b)/g;
|
|
173
|
+
exports2.ipAddress = /(\d{1,3}(\.\d{1,3}){3}|[0-9A-F]{4}(:[0-9A-F]{4}){5}(::|(:0000)+))/gi;
|
|
174
|
+
exports2.usSocialSecurityNumber = /\b\d{3}[ -.]\d{2}[ -.]\d{4}\b/g;
|
|
175
|
+
exports2.emailAddress = /([a-z0-9_\-.+]{1,64})@\w+(\.\w+)*/gi;
|
|
176
|
+
exports2.username = /(user( ?name)?|login): \S+/gi;
|
|
177
|
+
exports2.password = /(pass(word|phrase)?|secret): \S+/gi;
|
|
178
|
+
exports2.credentials = /(login( cred(ential)?s| info(rmation)?)?|cred(ential)?s) ?:\s*\S+\s+\/?\s*\S+/gi;
|
|
179
|
+
exports2.digits = /\b\d{4,}\b/g;
|
|
180
|
+
exports2.url = /([^\s:/?#]{1,64}):\/\/([^/?#\s]*)([^?#\s]*)(\?([^#\s]*))?(#([^\s]*))?/g;
|
|
181
|
+
}
|
|
182
|
+
});
|
|
183
|
+
var require_utils = __commonJS({
|
|
184
|
+
"../redact-pii/dist/utils.js"(exports2) {
|
|
185
|
+
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
186
|
+
exports2.snakeCase = exports2.isSyncRedactor = exports2.isSimpleRegexpCustomRedactorConfig = void 0;
|
|
187
|
+
function isSimpleRegexpCustomRedactorConfig(redactor2) {
|
|
188
|
+
return typeof redactor2.regexpPattern !== "undefined";
|
|
189
|
+
}
|
|
190
|
+
exports2.isSimpleRegexpCustomRedactorConfig = isSimpleRegexpCustomRedactorConfig;
|
|
191
|
+
function isSyncRedactor(redactor2) {
|
|
192
|
+
return typeof redactor2.redact === "function";
|
|
193
|
+
}
|
|
194
|
+
exports2.isSyncRedactor = isSyncRedactor;
|
|
195
|
+
function snakeCase(input = "") {
|
|
196
|
+
var _a;
|
|
197
|
+
const words = (_a = input.match(/[A-Z]{2,}(?=[A-Z][a-z]|[0-9]|\b)|[A-Z]?[a-z]+|[A-Z]+|[0-9]+/g)) !== null && _a !== void 0 ? _a : [];
|
|
198
|
+
return words.map((word) => word.toLowerCase()).join("_");
|
|
199
|
+
}
|
|
200
|
+
exports2.snakeCase = snakeCase;
|
|
201
|
+
}
|
|
202
|
+
});
|
|
203
|
+
var require_SimpleRegexpRedactor = __commonJS({
|
|
204
|
+
"../redact-pii/dist/built-ins/SimpleRegexpRedactor.js"(exports2) {
|
|
205
|
+
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
206
|
+
exports2.SimpleRegexpRedactor = void 0;
|
|
207
|
+
var utils_1 = require_utils();
|
|
208
|
+
var SimpleRegexpRedactor = class {
|
|
209
|
+
constructor({ replaceWith = (0, utils_1.snakeCase)().toUpperCase(), regexpPattern: regexpMatcher }) {
|
|
210
|
+
this.replaceWith = replaceWith;
|
|
211
|
+
this.regexpMatcher = regexpMatcher;
|
|
212
|
+
}
|
|
213
|
+
redact(textToRedact) {
|
|
214
|
+
return textToRedact.replace(this.regexpMatcher, this.replaceWith);
|
|
215
|
+
}
|
|
216
|
+
};
|
|
217
|
+
exports2.SimpleRegexpRedactor = SimpleRegexpRedactor;
|
|
218
|
+
}
|
|
219
|
+
});
|
|
220
|
+
var require_composition = __commonJS({
|
|
221
|
+
"../redact-pii/dist/composition.js"(exports2) {
|
|
222
|
+
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
223
|
+
exports2.composeChildRedactors = void 0;
|
|
224
|
+
var NameRedactor_1 = require_NameRedactor();
|
|
225
|
+
var simpleRegexpBuiltIns = require_simple_regexp_patterns();
|
|
226
|
+
var SimpleRegexpRedactor_1 = require_SimpleRegexpRedactor();
|
|
227
|
+
var utils_1 = require_utils();
|
|
228
|
+
function normalizeCustomRedactorConfig(redactorConfig) {
|
|
229
|
+
return (0, utils_1.isSimpleRegexpCustomRedactorConfig)(redactorConfig) ? new SimpleRegexpRedactor_1.SimpleRegexpRedactor({
|
|
230
|
+
regexpPattern: redactorConfig.regexpPattern,
|
|
231
|
+
replaceWith: redactorConfig.replaceWith
|
|
232
|
+
}) : redactorConfig;
|
|
233
|
+
}
|
|
234
|
+
function composeChildRedactors(opts = {}) {
|
|
235
|
+
var _a, _b, _c, _d;
|
|
236
|
+
const childRedactors = [];
|
|
237
|
+
if (opts.customRedactors && opts.customRedactors.before) {
|
|
238
|
+
opts.customRedactors.before.map(normalizeCustomRedactorConfig).forEach((redactor2) => childRedactors.push(redactor2));
|
|
239
|
+
}
|
|
240
|
+
for (const regexpName of Object.keys(simpleRegexpBuiltIns)) {
|
|
241
|
+
if (!opts.builtInRedactors || !opts.builtInRedactors[regexpName] || opts.builtInRedactors[regexpName].enabled !== false) {
|
|
242
|
+
childRedactors.push(new SimpleRegexpRedactor_1.SimpleRegexpRedactor({
|
|
243
|
+
regexpPattern: simpleRegexpBuiltIns[regexpName],
|
|
244
|
+
replaceWith: ((_b = (_a = opts.builtInRedactors) === null || _a === void 0 ? void 0 : _a[regexpName]) === null || _b === void 0 ? void 0 : _b.replaceWith) || opts.globalReplaceWith || (0, utils_1.snakeCase)(regexpName).toUpperCase()
|
|
245
|
+
}));
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
if (!opts.builtInRedactors || !opts.builtInRedactors.names || opts.builtInRedactors.names.enabled !== false) {
|
|
249
|
+
childRedactors.push(new NameRedactor_1.NameRedactor(((_d = (_c = opts.builtInRedactors) === null || _c === void 0 ? void 0 : _c.names) === null || _d === void 0 ? void 0 : _d.replaceWith) || opts.globalReplaceWith));
|
|
250
|
+
}
|
|
251
|
+
if (opts.customRedactors && opts.customRedactors.after) {
|
|
252
|
+
opts.customRedactors.after.map(normalizeCustomRedactorConfig).forEach((redactor2) => childRedactors.push(redactor2));
|
|
253
|
+
}
|
|
254
|
+
return childRedactors;
|
|
255
|
+
}
|
|
256
|
+
exports2.composeChildRedactors = composeChildRedactors;
|
|
257
|
+
}
|
|
258
|
+
});
|
|
259
|
+
var require_AsyncCompositeRedactor = __commonJS({
|
|
260
|
+
"../redact-pii/dist/AsyncCompositeRedactor.js"(exports2) {
|
|
261
|
+
var __awaiter = exports2 && exports2.__awaiter || function(thisArg, _arguments, P, generator) {
|
|
262
|
+
function adopt(value) {
|
|
263
|
+
return value instanceof P ? value : new P(function(resolve2) {
|
|
264
|
+
resolve2(value);
|
|
265
|
+
});
|
|
266
|
+
}
|
|
267
|
+
return new (P || (P = Promise))(function(resolve2, reject) {
|
|
268
|
+
function fulfilled(value) {
|
|
269
|
+
try {
|
|
270
|
+
step(generator.next(value));
|
|
271
|
+
} catch (e) {
|
|
272
|
+
reject(e);
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
function rejected(value) {
|
|
276
|
+
try {
|
|
277
|
+
step(generator["throw"](value));
|
|
278
|
+
} catch (e) {
|
|
279
|
+
reject(e);
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
function step(result) {
|
|
283
|
+
result.done ? resolve2(result.value) : adopt(result.value).then(fulfilled, rejected);
|
|
284
|
+
}
|
|
285
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
286
|
+
});
|
|
287
|
+
};
|
|
288
|
+
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
289
|
+
exports2.AsyncCompositeRedactor = void 0;
|
|
290
|
+
var composition_1 = require_composition();
|
|
291
|
+
var utils_1 = require_utils();
|
|
292
|
+
var AsyncCompositeRedactor = class {
|
|
293
|
+
constructor(opts) {
|
|
294
|
+
this.childRedactors = [];
|
|
295
|
+
this.redactAsync = (textToRedact) => __awaiter(this, void 0, void 0, function* () {
|
|
296
|
+
for (const redactor2 of this.childRedactors) {
|
|
297
|
+
if ((0, utils_1.isSyncRedactor)(redactor2)) {
|
|
298
|
+
textToRedact = redactor2.redact(textToRedact);
|
|
299
|
+
} else {
|
|
300
|
+
textToRedact = yield redactor2.redactAsync(textToRedact);
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
return textToRedact;
|
|
304
|
+
});
|
|
305
|
+
this.childRedactors = (0, composition_1.composeChildRedactors)(opts);
|
|
306
|
+
}
|
|
307
|
+
};
|
|
308
|
+
exports2.AsyncCompositeRedactor = AsyncCompositeRedactor;
|
|
309
|
+
}
|
|
310
|
+
});
|
|
311
|
+
var require_SyncCompositeRedactor = __commonJS({
|
|
312
|
+
"../redact-pii/dist/SyncCompositeRedactor.js"(exports2) {
|
|
313
|
+
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
314
|
+
exports2.SyncCompositeRedactor = void 0;
|
|
315
|
+
var composition_1 = require_composition();
|
|
316
|
+
var SyncCompositeRedactor = class {
|
|
317
|
+
constructor(opts) {
|
|
318
|
+
this.childRedactors = [];
|
|
319
|
+
this.redact = (textToRedact) => {
|
|
320
|
+
for (const redactor2 of this.childRedactors) {
|
|
321
|
+
textToRedact = redactor2.redact(textToRedact);
|
|
322
|
+
}
|
|
323
|
+
return textToRedact;
|
|
324
|
+
};
|
|
325
|
+
this.childRedactors = (0, composition_1.composeChildRedactors)(opts);
|
|
326
|
+
}
|
|
327
|
+
};
|
|
328
|
+
exports2.SyncCompositeRedactor = SyncCompositeRedactor;
|
|
329
|
+
}
|
|
330
|
+
});
|
|
331
|
+
var require_dist = __commonJS({
|
|
332
|
+
"../redact-pii/dist/index.js"(exports2) {
|
|
333
|
+
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
334
|
+
exports2.SyncRedactor = exports2.AsyncRedactor = void 0;
|
|
335
|
+
var AsyncCompositeRedactor_1 = require_AsyncCompositeRedactor();
|
|
336
|
+
Object.defineProperty(exports2, "AsyncRedactor", { enumerable: true, get: function() {
|
|
337
|
+
return AsyncCompositeRedactor_1.AsyncCompositeRedactor;
|
|
338
|
+
} });
|
|
339
|
+
var SyncCompositeRedactor_1 = require_SyncCompositeRedactor();
|
|
340
|
+
Object.defineProperty(exports2, "SyncRedactor", { enumerable: true, get: function() {
|
|
341
|
+
return SyncCompositeRedactor_1.SyncCompositeRedactor;
|
|
342
|
+
} });
|
|
343
|
+
}
|
|
344
|
+
});
|
|
91
345
|
var STATE_KEY = /* @__PURE__ */ Symbol.for("raindrop.tracing.replayTraceRoutingState");
|
|
92
346
|
function state() {
|
|
93
347
|
const holder = globalThis;
|
|
94
348
|
let current = holder[STATE_KEY];
|
|
95
349
|
if (!current) {
|
|
96
|
-
let
|
|
350
|
+
let storage2 = null;
|
|
97
351
|
try {
|
|
98
352
|
const Ctor = globalThis.RAINDROP_ASYNC_LOCAL_STORAGE;
|
|
99
|
-
if (Ctor)
|
|
353
|
+
if (Ctor) storage2 = new Ctor();
|
|
100
354
|
} catch (e) {
|
|
101
|
-
|
|
355
|
+
storage2 = null;
|
|
102
356
|
}
|
|
103
357
|
current = {
|
|
104
|
-
storage,
|
|
358
|
+
storage: storage2,
|
|
105
359
|
syncDestination: void 0,
|
|
106
360
|
spanDestinations: /* @__PURE__ */ new WeakMap()
|
|
107
361
|
};
|
|
@@ -249,12 +503,12 @@ var NO_AMBIENT_ROUTING_BIND_WARNING = "[raindrop] This runtime's AsyncLocalStora
|
|
|
249
503
|
var ROUTING_STORAGE_KEY = /* @__PURE__ */ Symbol.for("raindrop.tracing.routingContextStorage");
|
|
250
504
|
function routingStorage() {
|
|
251
505
|
const holder = globalThis;
|
|
252
|
-
let
|
|
253
|
-
if (!
|
|
254
|
-
|
|
255
|
-
holder[ROUTING_STORAGE_KEY] =
|
|
506
|
+
let storage2 = holder[ROUTING_STORAGE_KEY];
|
|
507
|
+
if (!storage2) {
|
|
508
|
+
storage2 = new ContextStackStorage(NO_AMBIENT_ROUTING_BIND_WARNING);
|
|
509
|
+
holder[ROUTING_STORAGE_KEY] = storage2;
|
|
256
510
|
}
|
|
257
|
-
return
|
|
511
|
+
return storage2;
|
|
258
512
|
}
|
|
259
513
|
function currentRoutingBinding() {
|
|
260
514
|
const bound = routingStorage().current();
|
|
@@ -540,6 +794,14 @@ function appGitPropertiesFromAttributes(attributes) {
|
|
|
540
794
|
}
|
|
541
795
|
return properties;
|
|
542
796
|
}
|
|
797
|
+
function normalizeFeatureFlags(input) {
|
|
798
|
+
if (Array.isArray(input)) {
|
|
799
|
+
return Object.fromEntries(input.map((name) => [name, "true"]));
|
|
800
|
+
}
|
|
801
|
+
return Object.fromEntries(
|
|
802
|
+
Object.entries(input).map(([k, v]) => [k, String(v)])
|
|
803
|
+
);
|
|
804
|
+
}
|
|
543
805
|
function getCrypto() {
|
|
544
806
|
const c = globalThis.crypto;
|
|
545
807
|
return c;
|
|
@@ -641,11 +903,91 @@ function runWithTracingSuppressed(fn) {
|
|
|
641
903
|
return fn();
|
|
642
904
|
}
|
|
643
905
|
}
|
|
906
|
+
var MAX_QUOTED_ITEMS = 3;
|
|
907
|
+
function isRecord(value) {
|
|
908
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
909
|
+
}
|
|
910
|
+
function itemLabel(item) {
|
|
911
|
+
if (typeof item.event_id === "string" && item.event_id) return `event ${item.event_id}`;
|
|
912
|
+
if (typeof item.index === "number") return `item ${item.index}`;
|
|
913
|
+
return "item";
|
|
914
|
+
}
|
|
915
|
+
function describeRejected(item) {
|
|
916
|
+
const issues = Array.isArray(item.issues) ? item.issues : [];
|
|
917
|
+
const text = issues.filter(isRecord).map((issue) => {
|
|
918
|
+
const path = typeof issue.path === "string" && issue.path ? `${issue.path}: ` : "";
|
|
919
|
+
return `${path}${typeof issue.message === "string" ? issue.message : "invalid"}`;
|
|
920
|
+
}).join("; ");
|
|
921
|
+
return `${itemLabel(item)} (${text || "invalid"})`;
|
|
922
|
+
}
|
|
923
|
+
function describeWarning(item) {
|
|
924
|
+
if (typeof item.message === "string" && item.message) return `${itemLabel(item)}: ${item.message}`;
|
|
925
|
+
const fields = Array.isArray(item.fields) ? item.fields.filter((f) => typeof f === "string") : [];
|
|
926
|
+
return `${itemLabel(item)}: ignored ${fields.join(", ") || "input"}`;
|
|
927
|
+
}
|
|
928
|
+
function summarize(items, describe) {
|
|
929
|
+
const quoted = items.slice(0, MAX_QUOTED_ITEMS).map(describe).join(" | ");
|
|
930
|
+
const more = items.length > MAX_QUOTED_ITEMS ? ` (+${items.length - MAX_QUOTED_ITEMS} more)` : "";
|
|
931
|
+
return `${quoted}${more}`;
|
|
932
|
+
}
|
|
933
|
+
function reportIngestResponse(bodyText, prefix, opName) {
|
|
934
|
+
if (!bodyText) return;
|
|
935
|
+
let body;
|
|
936
|
+
try {
|
|
937
|
+
body = JSON.parse(bodyText);
|
|
938
|
+
} catch (e) {
|
|
939
|
+
return;
|
|
940
|
+
}
|
|
941
|
+
if (!isRecord(body)) return;
|
|
942
|
+
const rejected = Array.isArray(body.rejected) ? body.rejected.filter(isRecord) : [];
|
|
943
|
+
if (rejected.length > 0) {
|
|
944
|
+
rateLimitedLog(
|
|
945
|
+
`${prefix}.ingest_rejected`,
|
|
946
|
+
() => console.warn(
|
|
947
|
+
`${prefix} ${opName}: ingest rejected ${rejected.length} item(s), which were not stored: ${summarize(rejected, describeRejected)}`
|
|
948
|
+
)
|
|
949
|
+
);
|
|
950
|
+
}
|
|
951
|
+
const warnings = Array.isArray(body.warnings) ? body.warnings.filter(isRecord) : [];
|
|
952
|
+
if (warnings.length > 0) {
|
|
953
|
+
rateLimitedLog(
|
|
954
|
+
`${prefix}.ingest_warnings`,
|
|
955
|
+
() => console.warn(
|
|
956
|
+
`${prefix} ${opName}: ingest accepted ${warnings.length} item(s) with changes: ${summarize(warnings, describeWarning)}`
|
|
957
|
+
)
|
|
958
|
+
);
|
|
959
|
+
}
|
|
960
|
+
}
|
|
961
|
+
var DEFAULT_FLUSH_TIMEOUT_MS = 1e4;
|
|
644
962
|
var DEFAULT_REQUEST_TIMEOUT_MS = 3e4;
|
|
645
963
|
var MAX_RETRY_DELAY_MS = 3e4;
|
|
646
964
|
function wait(ms) {
|
|
647
965
|
return new Promise((resolve2) => setTimeout(resolve2, ms));
|
|
648
966
|
}
|
|
967
|
+
function waitUnlessAborted(ms, signal) {
|
|
968
|
+
if (!signal) return wait(ms);
|
|
969
|
+
if (signal.aborted) return Promise.resolve();
|
|
970
|
+
return new Promise((resolve2) => {
|
|
971
|
+
const done = () => {
|
|
972
|
+
clearTimeout(timer);
|
|
973
|
+
signal.removeEventListener("abort", done);
|
|
974
|
+
resolve2();
|
|
975
|
+
};
|
|
976
|
+
const timer = setTimeout(done, ms);
|
|
977
|
+
signal.addEventListener("abort", done, { once: true });
|
|
978
|
+
});
|
|
979
|
+
}
|
|
980
|
+
function eitherSignal(a, b) {
|
|
981
|
+
if (!b) return a;
|
|
982
|
+
const any = AbortSignal.any;
|
|
983
|
+
if (typeof any === "function") return any([a, b]);
|
|
984
|
+
const controller = new AbortController();
|
|
985
|
+
const abort = () => controller.abort();
|
|
986
|
+
if (a.aborted || b.aborted) abort();
|
|
987
|
+
a.addEventListener("abort", abort, { once: true });
|
|
988
|
+
b.addEventListener("abort", abort, { once: true });
|
|
989
|
+
return controller.signal;
|
|
990
|
+
}
|
|
649
991
|
function formatEndpoint(endpoint) {
|
|
650
992
|
if (!endpoint) return void 0;
|
|
651
993
|
return endpoint.endsWith("/") ? endpoint : `${endpoint}/`;
|
|
@@ -690,6 +1032,26 @@ async function raceWithTimeout(promise, timeoutMs) {
|
|
|
690
1032
|
if (timer) clearTimeout(timer);
|
|
691
1033
|
return settledInTime;
|
|
692
1034
|
}
|
|
1035
|
+
var InFlightCutOff = class {
|
|
1036
|
+
constructor() {
|
|
1037
|
+
this.controller = new AbortController();
|
|
1038
|
+
}
|
|
1039
|
+
get signal() {
|
|
1040
|
+
return this.controller.signal;
|
|
1041
|
+
}
|
|
1042
|
+
cut() {
|
|
1043
|
+
this.controller.abort();
|
|
1044
|
+
this.controller = new AbortController();
|
|
1045
|
+
}
|
|
1046
|
+
};
|
|
1047
|
+
async function awaitEarlierSends(earlier, deadlineAt, cutOff, isRunning) {
|
|
1048
|
+
if (earlier.length === 0) return { settled: true, stillRunning: 0 };
|
|
1049
|
+
const settled = await raceWithTimeout(Promise.allSettled(earlier), deadlineAt - Date.now());
|
|
1050
|
+
if (settled) return { settled, stillRunning: 0 };
|
|
1051
|
+
const stillRunning = earlier.filter(isRunning).length;
|
|
1052
|
+
if (stillRunning > 0) cutOff.cut();
|
|
1053
|
+
return { settled: stillRunning === 0, stillRunning };
|
|
1054
|
+
}
|
|
693
1055
|
function parseRetryAfter(headers) {
|
|
694
1056
|
var _a;
|
|
695
1057
|
const value = (_a = headers.get("Retry-After")) != null ? _a : headers.get("retry-after");
|
|
@@ -713,45 +1075,80 @@ function getRetryDelayMs(attemptNumber, previousError) {
|
|
|
713
1075
|
const factor = Math.pow(2, attemptNumber - 2);
|
|
714
1076
|
return Math.min(base * factor, MAX_RETRY_DELAY_MS);
|
|
715
1077
|
}
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
if (opts.debug) {
|
|
723
|
-
console.warn(
|
|
724
|
-
`${prefix} ${opName} retry ${attemptNumber}/${opts.maxAttempts} in ${delay}ms`
|
|
725
|
-
);
|
|
726
|
-
}
|
|
727
|
-
if (delay > 0) await wait(delay);
|
|
728
|
-
} else if (opts.debug) {
|
|
729
|
-
console.log(`${prefix} ${opName} attempt ${attemptNumber}/${opts.maxAttempts}`);
|
|
730
|
-
}
|
|
731
|
-
try {
|
|
732
|
-
return await operation();
|
|
733
|
-
} catch (err) {
|
|
734
|
-
lastError = err;
|
|
735
|
-
if (opts.debug) {
|
|
736
|
-
const msg = err instanceof Error ? err.message : String(err);
|
|
737
|
-
console.warn(
|
|
738
|
-
`${prefix} ${opName} attempt ${attemptNumber} failed: ${msg}${attemptNumber === opts.maxAttempts ? " (no more retries)" : ""}`
|
|
739
|
-
);
|
|
740
|
-
}
|
|
741
|
-
if (lastError && typeof lastError === "object" && "retryable" in lastError && !lastError.retryable)
|
|
742
|
-
break;
|
|
743
|
-
if (attemptNumber === opts.maxAttempts) break;
|
|
744
|
-
}
|
|
1078
|
+
var sendPausedUntil = /* @__PURE__ */ new Map();
|
|
1079
|
+
function originOf(url) {
|
|
1080
|
+
try {
|
|
1081
|
+
return new URL(url).origin;
|
|
1082
|
+
} catch (e) {
|
|
1083
|
+
return url;
|
|
745
1084
|
}
|
|
746
|
-
|
|
1085
|
+
}
|
|
1086
|
+
function noteSendPause(url, status, retryAfterMs) {
|
|
1087
|
+
var _a;
|
|
1088
|
+
if (status !== 429 && status !== 503 || typeof retryAfterMs !== "number") return;
|
|
1089
|
+
const until = Date.now() + Math.min(Math.max(0, retryAfterMs), MAX_RETRY_DELAY_MS);
|
|
1090
|
+
const origin = originOf(url);
|
|
1091
|
+
sendPausedUntil.set(origin, Math.max((_a = sendPausedUntil.get(origin)) != null ? _a : 0, until));
|
|
1092
|
+
}
|
|
1093
|
+
function pausedUntil(url) {
|
|
1094
|
+
const until = sendPausedUntil.get(originOf(url));
|
|
1095
|
+
if (until === void 0) return void 0;
|
|
1096
|
+
if (until <= Date.now()) {
|
|
1097
|
+
sendPausedUntil.delete(originOf(url));
|
|
1098
|
+
return void 0;
|
|
1099
|
+
}
|
|
1100
|
+
return Math.min(until, Date.now() + MAX_RETRY_DELAY_MS);
|
|
1101
|
+
}
|
|
1102
|
+
function prefixFor(opts) {
|
|
1103
|
+
return opts.sdkName ? `[raindrop-ai/${opts.sdkName}]` : "[raindrop-ai/core]";
|
|
747
1104
|
}
|
|
748
1105
|
async function postJson(url, body, headers, opts) {
|
|
1106
|
+
var _a;
|
|
1107
|
+
const outcome = await sendJson(url, body, headers, { ...opts, deadlineAt: void 0 });
|
|
1108
|
+
if (outcome.status === "delivered") return;
|
|
1109
|
+
throw (_a = outcome.error) != null ? _a : new Error(`${redactUrlForLog(url)}: not sent (${outcome.status})`);
|
|
1110
|
+
}
|
|
1111
|
+
async function sendJson(url, body, headers, opts) {
|
|
749
1112
|
var _a;
|
|
750
1113
|
const opName = `POST ${redactUrlForLog(url)}`;
|
|
1114
|
+
const prefix = prefixFor(opts);
|
|
751
1115
|
const timeoutMs = (_a = opts.timeoutMs) != null ? _a : DEFAULT_REQUEST_TIMEOUT_MS;
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
1116
|
+
const deadlineAt = opts.deadlineAt;
|
|
1117
|
+
const remaining = () => deadlineAt === void 0 ? Infinity : deadlineAt - Date.now();
|
|
1118
|
+
let lastError;
|
|
1119
|
+
const cutOff = opts.cutOff;
|
|
1120
|
+
for (let attempt = 1; attempt <= opts.maxAttempts; attempt++) {
|
|
1121
|
+
if (cutOff == null ? void 0 : cutOff.aborted) return { status: "deferred", error: lastError };
|
|
1122
|
+
if (attempt > 1) {
|
|
1123
|
+
const delay = getRetryDelayMs(attempt, lastError);
|
|
1124
|
+
if (delay >= remaining()) {
|
|
1125
|
+
return { status: "deferred", retryAtMs: Date.now() + delay, error: lastError };
|
|
1126
|
+
}
|
|
1127
|
+
if (opts.debug) {
|
|
1128
|
+
console.warn(`${prefix} ${opName} retry ${attempt}/${opts.maxAttempts} in ${delay}ms`);
|
|
1129
|
+
}
|
|
1130
|
+
if (delay > 0) await waitUnlessAborted(delay, cutOff);
|
|
1131
|
+
if (cutOff == null ? void 0 : cutOff.aborted) return { status: "deferred", error: lastError };
|
|
1132
|
+
} else if (opts.debug) {
|
|
1133
|
+
console.log(`${prefix} ${opName} attempt ${attempt}/${opts.maxAttempts}`);
|
|
1134
|
+
}
|
|
1135
|
+
const pauseEnd = pausedUntil(url);
|
|
1136
|
+
if (pauseEnd !== void 0) {
|
|
1137
|
+
if (deadlineAt !== void 0 && pauseEnd >= deadlineAt) {
|
|
1138
|
+
return { status: "deferred", retryAtMs: pauseEnd, error: lastError };
|
|
1139
|
+
}
|
|
1140
|
+
await waitUnlessAborted(Math.max(0, pauseEnd - Date.now()), cutOff);
|
|
1141
|
+
if (cutOff == null ? void 0 : cutOff.aborted) return { status: "deferred", retryAtMs: pauseEnd, error: lastError };
|
|
1142
|
+
}
|
|
1143
|
+
const left = remaining();
|
|
1144
|
+
if (left <= 0) return { status: "deferred", error: lastError };
|
|
1145
|
+
const attemptTimeoutMs = Math.min(timeoutMs, left);
|
|
1146
|
+
const clampedByDeadline = attemptTimeoutMs < timeoutMs;
|
|
1147
|
+
const timeoutSignal = AbortSignal.timeout(attemptTimeoutMs);
|
|
1148
|
+
const signal = eitherSignal(timeoutSignal, cutOff);
|
|
1149
|
+
let resp;
|
|
1150
|
+
try {
|
|
1151
|
+
resp = await runWithTracingSuppressed(
|
|
755
1152
|
() => fetch(url, {
|
|
756
1153
|
method: "POST",
|
|
757
1154
|
redirect: headers["X-Raindrop-Replay-Id"] !== void 0 ? "error" : "follow",
|
|
@@ -760,24 +1157,98 @@ async function postJson(url, body, headers, opts) {
|
|
|
760
1157
|
...headers
|
|
761
1158
|
},
|
|
762
1159
|
body: JSON.stringify(body),
|
|
763
|
-
signal
|
|
1160
|
+
signal
|
|
764
1161
|
})
|
|
765
1162
|
);
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
);
|
|
771
|
-
const retryAfterMs = parseRetryAfter(resp.headers);
|
|
772
|
-
if (typeof retryAfterMs === "number") err.retryAfterMs = retryAfterMs;
|
|
773
|
-
err.retryable = resp.status === 429 || resp.status >= 500;
|
|
774
|
-
throw err;
|
|
1163
|
+
} catch (err) {
|
|
1164
|
+
const error = err instanceof Error ? err : new Error(String(err));
|
|
1165
|
+
if ((cutOff == null ? void 0 : cutOff.aborted) || timeoutSignal.aborted && clampedByDeadline) {
|
|
1166
|
+
return { status: "cut_off", error };
|
|
775
1167
|
}
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
1168
|
+
lastError = error;
|
|
1169
|
+
logAttemptFailure(opts, prefix, opName, attempt, error);
|
|
1170
|
+
continue;
|
|
1171
|
+
}
|
|
1172
|
+
if (!resp.ok) {
|
|
1173
|
+
const text = await resp.text().catch(() => "");
|
|
1174
|
+
const error = new Error(
|
|
1175
|
+
`HTTP ${resp.status} ${resp.statusText}${text ? `: ${text}` : ""}`
|
|
1176
|
+
);
|
|
1177
|
+
const retryAfterMs = parseRetryAfter(resp.headers);
|
|
1178
|
+
if (typeof retryAfterMs === "number") error.retryAfterMs = retryAfterMs;
|
|
1179
|
+
noteSendPause(url, resp.status, retryAfterMs);
|
|
1180
|
+
error.retryable = resp.status === 408 || resp.status === 429 || resp.status >= 500;
|
|
1181
|
+
if (!error.retryable) return { status: "rejected", error };
|
|
1182
|
+
lastError = error;
|
|
1183
|
+
logAttemptFailure(opts, prefix, opName, attempt, error);
|
|
1184
|
+
continue;
|
|
1185
|
+
}
|
|
1186
|
+
try {
|
|
1187
|
+
reportIngestResponse(await resp.text(), prefix, opName);
|
|
1188
|
+
} catch (e) {
|
|
1189
|
+
}
|
|
1190
|
+
return { status: "delivered" };
|
|
1191
|
+
}
|
|
1192
|
+
return { status: "failed", error: lastError != null ? lastError : new Error(`${opName}: no attempts`) };
|
|
1193
|
+
}
|
|
1194
|
+
function logAttemptFailure(opts, prefix, opName, attempt, error) {
|
|
1195
|
+
if (!opts.debug) return;
|
|
1196
|
+
console.warn(
|
|
1197
|
+
`${prefix} ${opName} attempt ${attempt} failed: ${error.message}${attempt === opts.maxAttempts ? " (no more retries)" : ""}`
|
|
1198
|
+
);
|
|
1199
|
+
}
|
|
1200
|
+
function asCompat(result) {
|
|
1201
|
+
return result;
|
|
1202
|
+
}
|
|
1203
|
+
var DELIVERED = Object.freeze({
|
|
1204
|
+
delivered: true,
|
|
1205
|
+
timedOut: false,
|
|
1206
|
+
dropped: 0,
|
|
1207
|
+
queued: 0,
|
|
1208
|
+
inFlight: 0
|
|
1209
|
+
});
|
|
1210
|
+
function fateOf(outcome, shuttingDown) {
|
|
1211
|
+
switch (outcome.status) {
|
|
1212
|
+
case "delivered":
|
|
1213
|
+
case "rejected":
|
|
1214
|
+
return "delivered";
|
|
1215
|
+
case "deferred":
|
|
1216
|
+
return shuttingDown ? "dropped" : "queued";
|
|
1217
|
+
default:
|
|
1218
|
+
return "dropped";
|
|
1219
|
+
}
|
|
1220
|
+
}
|
|
1221
|
+
function summarize2(fates, inFlight, timedOut) {
|
|
1222
|
+
const dropped = fates.filter((fate) => fate === "dropped").length;
|
|
1223
|
+
const queued = fates.filter((fate) => fate === "queued").length;
|
|
1224
|
+
return {
|
|
1225
|
+
delivered: dropped === 0 && queued === 0 && inFlight === 0,
|
|
1226
|
+
timedOut: timedOut || queued > 0 || inFlight > 0,
|
|
1227
|
+
dropped,
|
|
1228
|
+
queued,
|
|
1229
|
+
inFlight
|
|
1230
|
+
};
|
|
1231
|
+
}
|
|
1232
|
+
function combineResults(...results) {
|
|
1233
|
+
return results.reduce(
|
|
1234
|
+
(acc, r) => ({
|
|
1235
|
+
delivered: acc.delivered && r.delivered,
|
|
1236
|
+
timedOut: acc.timedOut || r.timedOut,
|
|
1237
|
+
dropped: acc.dropped + r.dropped,
|
|
1238
|
+
queued: acc.queued + r.queued,
|
|
1239
|
+
inFlight: acc.inFlight + r.inFlight
|
|
1240
|
+
}),
|
|
1241
|
+
{ ...DELIVERED }
|
|
779
1242
|
);
|
|
780
1243
|
}
|
|
1244
|
+
function describeUndelivered(what, result) {
|
|
1245
|
+
const parts = [
|
|
1246
|
+
result.dropped > 0 ? `${result.dropped} dropped` : "",
|
|
1247
|
+
result.queued > 0 ? `${result.queued} still queued` : "",
|
|
1248
|
+
result.inFlight > 0 ? `${result.inFlight} still sending` : ""
|
|
1249
|
+
].filter(Boolean);
|
|
1250
|
+
return `${what} returned before everything was delivered: ${parts.join(", ")}`;
|
|
1251
|
+
}
|
|
781
1252
|
var DEFAULT_MAX_TEXT_FIELD_CHARS = 1e6;
|
|
782
1253
|
var TRUNCATION_MARKER = "...[truncated by raindrop]";
|
|
783
1254
|
var BOUNDED_CLONE_MAX_DEPTH = 12;
|
|
@@ -1044,7 +1515,245 @@ function normalizeProjectId(raw, opts) {
|
|
|
1044
1515
|
function projectIdHeaders(projectId) {
|
|
1045
1516
|
return projectId ? { [PROJECT_ID_HEADER]: projectId } : {};
|
|
1046
1517
|
}
|
|
1047
|
-
var
|
|
1518
|
+
var import_redact_pii = __toESM(require_dist(), 1);
|
|
1519
|
+
var DEFAULT_PII_REDACTION_OPTIONS = {
|
|
1520
|
+
builtInRedactors: {
|
|
1521
|
+
credentials: { replaceWith: "<REDACTED CREDENTIALS>" },
|
|
1522
|
+
creditCardNumber: { replaceWith: "<REDACTED CREDIT CARD NUMBER>" },
|
|
1523
|
+
// Any run of 4+ digits: too broad.
|
|
1524
|
+
digits: { enabled: false },
|
|
1525
|
+
emailAddress: { replaceWith: "<REDACTED EMAIL>" },
|
|
1526
|
+
ipAddress: { enabled: false },
|
|
1527
|
+
names: { enabled: false },
|
|
1528
|
+
// Matches (pass(word|phrase)|secret): \S+
|
|
1529
|
+
password: { replaceWith: "<REDACTED SECRET>" },
|
|
1530
|
+
phoneNumber: { replaceWith: "<REDACTED PHONE NUMBER>" },
|
|
1531
|
+
streetAddress: { replaceWith: "<REDACTED ADDRESS>" },
|
|
1532
|
+
url: { enabled: false },
|
|
1533
|
+
username: { enabled: false },
|
|
1534
|
+
usSocialSecurityNumber: { replaceWith: "<REDACTED SOCIAL SECURITY NUMBER>" },
|
|
1535
|
+
zipcode: { enabled: false }
|
|
1536
|
+
}
|
|
1537
|
+
};
|
|
1538
|
+
var redactor;
|
|
1539
|
+
function redactPiiText(text) {
|
|
1540
|
+
redactor != null ? redactor : redactor = new import_redact_pii.SyncRedactor(DEFAULT_PII_REDACTION_OPTIONS);
|
|
1541
|
+
return redactor.redact(text);
|
|
1542
|
+
}
|
|
1543
|
+
var KINDS = ["event", "signal", "identify"];
|
|
1544
|
+
var DEFAULT_PII_FIELDS = {
|
|
1545
|
+
event: ["ai_data.input", "ai_data.output"],
|
|
1546
|
+
signal: [],
|
|
1547
|
+
identify: []
|
|
1548
|
+
};
|
|
1549
|
+
var PROTECTED_LOCATIONS = new Set(
|
|
1550
|
+
[
|
|
1551
|
+
["event_id"],
|
|
1552
|
+
["user_id"],
|
|
1553
|
+
["ai_data", "convo_id"],
|
|
1554
|
+
["event"],
|
|
1555
|
+
["timestamp"],
|
|
1556
|
+
["is_pending"],
|
|
1557
|
+
["signal_name"],
|
|
1558
|
+
["signal_type"]
|
|
1559
|
+
].map((keys) => JSON.stringify(keys))
|
|
1560
|
+
);
|
|
1561
|
+
var SIGNAL_PATH_ALIASES = {
|
|
1562
|
+
comment: "properties.comment",
|
|
1563
|
+
after: "properties.after"
|
|
1564
|
+
};
|
|
1565
|
+
function parsePiiFieldPath(path) {
|
|
1566
|
+
if (typeof path !== "string") return null;
|
|
1567
|
+
const segments = [];
|
|
1568
|
+
let i = 0;
|
|
1569
|
+
const n = path.length;
|
|
1570
|
+
let expectSeparator = false;
|
|
1571
|
+
while (i < n) {
|
|
1572
|
+
const ch = path[i];
|
|
1573
|
+
if (ch === "[") {
|
|
1574
|
+
const close = path.indexOf("]", i);
|
|
1575
|
+
if (path[i + 1] === '"') {
|
|
1576
|
+
let j2 = i + 2;
|
|
1577
|
+
let key = "";
|
|
1578
|
+
while (j2 < n && path[j2] !== '"') {
|
|
1579
|
+
if (path[j2] === "\\" && j2 + 1 < n) {
|
|
1580
|
+
key += path[j2 + 1];
|
|
1581
|
+
j2 += 2;
|
|
1582
|
+
} else {
|
|
1583
|
+
key += path[j2];
|
|
1584
|
+
j2 += 1;
|
|
1585
|
+
}
|
|
1586
|
+
}
|
|
1587
|
+
if (j2 >= n || path[j2 + 1] !== "]" || key === "") return null;
|
|
1588
|
+
segments.push({ kind: "key", key });
|
|
1589
|
+
i = j2 + 2;
|
|
1590
|
+
} else {
|
|
1591
|
+
if (close === -1) return null;
|
|
1592
|
+
const inner = path.slice(i + 1, close);
|
|
1593
|
+
if (inner === "") segments.push({ kind: "every" });
|
|
1594
|
+
else if (/^(0|[1-9]\d*)$/.test(inner))
|
|
1595
|
+
segments.push({ kind: "index", index: Number(inner) });
|
|
1596
|
+
else return null;
|
|
1597
|
+
i = close + 1;
|
|
1598
|
+
}
|
|
1599
|
+
expectSeparator = true;
|
|
1600
|
+
continue;
|
|
1601
|
+
}
|
|
1602
|
+
if (ch === ".") {
|
|
1603
|
+
if (!expectSeparator) return null;
|
|
1604
|
+
i += 1;
|
|
1605
|
+
expectSeparator = false;
|
|
1606
|
+
if (i >= n || path[i] === ".") return null;
|
|
1607
|
+
continue;
|
|
1608
|
+
}
|
|
1609
|
+
if (expectSeparator) return null;
|
|
1610
|
+
let j = i;
|
|
1611
|
+
while (j < n && path[j] !== "." && path[j] !== "[") j += 1;
|
|
1612
|
+
const token = path.slice(i, j);
|
|
1613
|
+
if (token === "*") segments.push({ kind: "any_key" });
|
|
1614
|
+
else if (token === "" || /[\]*"\s]/.test(token)) return null;
|
|
1615
|
+
else segments.push({ kind: "key", key: token });
|
|
1616
|
+
i = j;
|
|
1617
|
+
expectSeparator = true;
|
|
1618
|
+
}
|
|
1619
|
+
return segments.length > 0 && expectSeparator ? segments : null;
|
|
1620
|
+
}
|
|
1621
|
+
function mergePiiFieldMaps(...maps) {
|
|
1622
|
+
const out = { event: [], signal: [], identify: [] };
|
|
1623
|
+
for (const kind of KINDS) {
|
|
1624
|
+
const seen = /* @__PURE__ */ new Set();
|
|
1625
|
+
for (const map of maps) {
|
|
1626
|
+
const paths = map == null ? void 0 : map[kind];
|
|
1627
|
+
if (!Array.isArray(paths)) continue;
|
|
1628
|
+
for (const path of paths) {
|
|
1629
|
+
if (typeof path !== "string" || seen.has(path)) continue;
|
|
1630
|
+
seen.add(path);
|
|
1631
|
+
out[kind].push(path);
|
|
1632
|
+
}
|
|
1633
|
+
}
|
|
1634
|
+
}
|
|
1635
|
+
return out;
|
|
1636
|
+
}
|
|
1637
|
+
function isPlainObject(value) {
|
|
1638
|
+
if (value === null || typeof value !== "object" || Array.isArray(value)) return false;
|
|
1639
|
+
const proto = Object.getPrototypeOf(value);
|
|
1640
|
+
return proto === Object.prototype || proto === null;
|
|
1641
|
+
}
|
|
1642
|
+
function isProtected(location) {
|
|
1643
|
+
return PROTECTED_LOCATIONS.has(JSON.stringify(location));
|
|
1644
|
+
}
|
|
1645
|
+
function redactAll(value, location) {
|
|
1646
|
+
if (location !== null && isProtected(location)) return value;
|
|
1647
|
+
if (typeof value === "string") return redactPiiText(value);
|
|
1648
|
+
if (Array.isArray(value)) return value.map((item) => redactAll(item, null));
|
|
1649
|
+
if (isPlainObject(value)) {
|
|
1650
|
+
const out = {};
|
|
1651
|
+
for (const [key, child] of Object.entries(value)) {
|
|
1652
|
+
out[key] = redactAll(child, location === null ? null : [...location, key]);
|
|
1653
|
+
}
|
|
1654
|
+
return out;
|
|
1655
|
+
}
|
|
1656
|
+
return value;
|
|
1657
|
+
}
|
|
1658
|
+
function applyPath(value, segments, location) {
|
|
1659
|
+
if (segments.length === 0) return redactAll(value, location);
|
|
1660
|
+
const [head, ...rest] = segments;
|
|
1661
|
+
if (head.kind === "key" || head.kind === "any_key") {
|
|
1662
|
+
if (!isPlainObject(value)) return value;
|
|
1663
|
+
const keys = head.kind === "key" ? [head.key] : Object.keys(value);
|
|
1664
|
+
let out2;
|
|
1665
|
+
for (const key of keys) {
|
|
1666
|
+
if (!Object.prototype.hasOwnProperty.call(value, key)) continue;
|
|
1667
|
+
const child = value[key];
|
|
1668
|
+
const next = applyPath(child, rest, location === null ? null : [...location, key]);
|
|
1669
|
+
if (next !== child) {
|
|
1670
|
+
out2 != null ? out2 : out2 = { ...value };
|
|
1671
|
+
out2[key] = next;
|
|
1672
|
+
}
|
|
1673
|
+
}
|
|
1674
|
+
return out2 != null ? out2 : value;
|
|
1675
|
+
}
|
|
1676
|
+
if (!Array.isArray(value)) return value;
|
|
1677
|
+
const indices = head.kind === "index" ? head.index < value.length ? [head.index] : [] : value.keys();
|
|
1678
|
+
let out;
|
|
1679
|
+
for (const index of indices) {
|
|
1680
|
+
const child = value[index];
|
|
1681
|
+
const next = applyPath(child, rest, null);
|
|
1682
|
+
if (next !== child) {
|
|
1683
|
+
out != null ? out : out = [...value];
|
|
1684
|
+
out[index] = next;
|
|
1685
|
+
}
|
|
1686
|
+
}
|
|
1687
|
+
return out != null ? out : value;
|
|
1688
|
+
}
|
|
1689
|
+
var PiiFieldRedactor = class {
|
|
1690
|
+
constructor(options = {}) {
|
|
1691
|
+
var _a;
|
|
1692
|
+
this.startupMap = options.startupFieldMap;
|
|
1693
|
+
this.prefix = (_a = options.logPrefix) != null ? _a : "[raindrop-ai/core]";
|
|
1694
|
+
}
|
|
1695
|
+
/** Replace the server-provided layer (CONTRACT 11.2). Additive: it can only add fields. */
|
|
1696
|
+
setServerFieldMap(map) {
|
|
1697
|
+
this.serverMap = map;
|
|
1698
|
+
this.compiled = void 0;
|
|
1699
|
+
}
|
|
1700
|
+
/** The paths in effect for a kind, defaults first. */
|
|
1701
|
+
effectivePaths(kind) {
|
|
1702
|
+
return mergePiiFieldMaps(DEFAULT_PII_FIELDS, this.startupMap, this.serverMap)[kind];
|
|
1703
|
+
}
|
|
1704
|
+
compile() {
|
|
1705
|
+
if (this.compiled) return this.compiled;
|
|
1706
|
+
const out = { event: [], signal: [], identify: [] };
|
|
1707
|
+
for (const kind of KINDS) {
|
|
1708
|
+
for (const path of this.effectivePaths(kind)) {
|
|
1709
|
+
const variants = [path];
|
|
1710
|
+
if (kind === "signal" && SIGNAL_PATH_ALIASES[path])
|
|
1711
|
+
variants.push(SIGNAL_PATH_ALIASES[path]);
|
|
1712
|
+
for (const variant of variants) {
|
|
1713
|
+
const segments = parsePiiFieldPath(variant);
|
|
1714
|
+
if (segments) {
|
|
1715
|
+
out[kind].push(segments);
|
|
1716
|
+
} else {
|
|
1717
|
+
rateLimitedLog(
|
|
1718
|
+
`${this.prefix}.pii_field_path_invalid`,
|
|
1719
|
+
() => console.warn(
|
|
1720
|
+
`${this.prefix} redactPiiFields: ignoring invalid ${kind} path ${JSON.stringify(variant)}`
|
|
1721
|
+
)
|
|
1722
|
+
);
|
|
1723
|
+
}
|
|
1724
|
+
}
|
|
1725
|
+
}
|
|
1726
|
+
}
|
|
1727
|
+
this.compiled = out;
|
|
1728
|
+
return out;
|
|
1729
|
+
}
|
|
1730
|
+
/** The payload with every selected field redacted (a copy where changed). */
|
|
1731
|
+
redact(kind, payload) {
|
|
1732
|
+
let out = payload;
|
|
1733
|
+
for (const segments of this.compile()[kind]) out = applyPath(out, segments, []);
|
|
1734
|
+
return out;
|
|
1735
|
+
}
|
|
1736
|
+
};
|
|
1737
|
+
function detectRuntime() {
|
|
1738
|
+
if (typeof process === "object" && process && typeof process.env === "object" && process.env && typeof process.version === "string") {
|
|
1739
|
+
return "node";
|
|
1740
|
+
}
|
|
1741
|
+
if (typeof window === "object") return "browser";
|
|
1742
|
+
if (typeof WebSocketPair !== "undefined") return "cloudflare-worker";
|
|
1743
|
+
if (typeof EdgeRuntime === "string") return "vercel-edge";
|
|
1744
|
+
if (typeof WorkerGlobalScope !== "undefined" && typeof importScripts === "function") {
|
|
1745
|
+
return "web-worker";
|
|
1746
|
+
}
|
|
1747
|
+
return "unknown";
|
|
1748
|
+
}
|
|
1749
|
+
var PLACEHOLDER_USER_IDS = /* @__PURE__ */ new Set(["null", "undefined"]);
|
|
1750
|
+
function isMissingUserId(value) {
|
|
1751
|
+
if (value === void 0 || value === null) return true;
|
|
1752
|
+
if (typeof value !== "string") return false;
|
|
1753
|
+
const trimmed = value.trim();
|
|
1754
|
+
return trimmed === "" || PLACEHOLDER_USER_IDS.has(trimmed);
|
|
1755
|
+
}
|
|
1756
|
+
var MAX_DEFERRED_SENDS = 1e3;
|
|
1048
1757
|
var POST_SHUTDOWN_TIMEOUT_MS = 5e3;
|
|
1049
1758
|
function appGitOwnerId(prefix) {
|
|
1050
1759
|
try {
|
|
@@ -1053,18 +1762,52 @@ function appGitOwnerId(prefix) {
|
|
|
1053
1762
|
return `${prefix}:${Date.now().toString(36)}:${Math.random().toString(36).slice(2)}`;
|
|
1054
1763
|
}
|
|
1055
1764
|
}
|
|
1765
|
+
function earliestIsoTimestamp(...values) {
|
|
1766
|
+
let earliest;
|
|
1767
|
+
for (const value of values) {
|
|
1768
|
+
if (value === void 0) continue;
|
|
1769
|
+
const date = new Date(value);
|
|
1770
|
+
if (Number.isNaN(date.getTime())) continue;
|
|
1771
|
+
if (earliest === void 0 || date < earliest) earliest = date;
|
|
1772
|
+
}
|
|
1773
|
+
return earliest == null ? void 0 : earliest.toISOString();
|
|
1774
|
+
}
|
|
1775
|
+
function isPlainObject2(value) {
|
|
1776
|
+
if (value === null || typeof value !== "object" || Array.isArray(value)) return false;
|
|
1777
|
+
const proto = Object.getPrototypeOf(value);
|
|
1778
|
+
return proto === Object.prototype || proto === null;
|
|
1779
|
+
}
|
|
1780
|
+
var UNSAFE_MERGE_KEYS = /* @__PURE__ */ new Set(["__proto__", "constructor", "prototype"]);
|
|
1781
|
+
function deepMergeProperties(target, source) {
|
|
1782
|
+
const out = { ...target };
|
|
1783
|
+
for (const [key, value] of Object.entries(source)) {
|
|
1784
|
+
if (value === void 0 || UNSAFE_MERGE_KEYS.has(key)) continue;
|
|
1785
|
+
const existing = out[key];
|
|
1786
|
+
out[key] = isPlainObject2(existing) && isPlainObject2(value) ? deepMergeProperties(existing, value) : value;
|
|
1787
|
+
}
|
|
1788
|
+
return out;
|
|
1789
|
+
}
|
|
1056
1790
|
function mergePatches(target, source) {
|
|
1057
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _i;
|
|
1058
|
-
const
|
|
1791
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k;
|
|
1792
|
+
const defined2 = Object.fromEntries(
|
|
1793
|
+
Object.entries(source).filter(([, value]) => value !== void 0)
|
|
1794
|
+
);
|
|
1795
|
+
const out = { ...target, ...defined2 };
|
|
1059
1796
|
if (target.properties || source.properties) {
|
|
1060
|
-
out.properties =
|
|
1797
|
+
out.properties = deepMergeProperties((_a = target.properties) != null ? _a : {}, (_b = source.properties) != null ? _b : {});
|
|
1798
|
+
}
|
|
1799
|
+
if (target.callerProperties || source.callerProperties) {
|
|
1800
|
+
out.callerProperties = deepMergeProperties(
|
|
1801
|
+
(_c = target.callerProperties) != null ? _c : {},
|
|
1802
|
+
(_d = source.callerProperties) != null ? _d : {}
|
|
1803
|
+
);
|
|
1061
1804
|
}
|
|
1062
1805
|
if (target.usage || source.usage) {
|
|
1063
|
-
out.usage = { ...(
|
|
1064
|
-
if (((
|
|
1806
|
+
out.usage = { ...(_e = target.usage) != null ? _e : {} };
|
|
1807
|
+
if (((_f = source.usage) == null ? void 0 : _f.promptTokens) !== void 0) {
|
|
1065
1808
|
out.usage.promptTokens = source.usage.promptTokens;
|
|
1066
1809
|
}
|
|
1067
|
-
if (((
|
|
1810
|
+
if (((_g = source.usage) == null ? void 0 : _g.completionTokens) !== void 0) {
|
|
1068
1811
|
out.usage.completionTokens = source.usage.completionTokens;
|
|
1069
1812
|
}
|
|
1070
1813
|
}
|
|
@@ -1072,10 +1815,10 @@ function mergePatches(target, source) {
|
|
|
1072
1815
|
out.error = target.error;
|
|
1073
1816
|
}
|
|
1074
1817
|
if (target.featureFlags || source.featureFlags) {
|
|
1075
|
-
out.featureFlags = { ...(
|
|
1818
|
+
out.featureFlags = { ...(_h = target.featureFlags) != null ? _h : {}, ...(_i = source.featureFlags) != null ? _i : {} };
|
|
1076
1819
|
}
|
|
1077
1820
|
if (target.attachments || source.attachments) {
|
|
1078
|
-
out.attachments = [...(
|
|
1821
|
+
out.attachments = [...(_j = target.attachments) != null ? _j : [], ...(_k = source.attachments) != null ? _k : []];
|
|
1079
1822
|
}
|
|
1080
1823
|
return out;
|
|
1081
1824
|
}
|
|
@@ -1100,6 +1843,15 @@ function eventTelemetryProperties(patch) {
|
|
|
1100
1843
|
}
|
|
1101
1844
|
return properties;
|
|
1102
1845
|
}
|
|
1846
|
+
var FINISHED_EVENT_MEMORY = 1e4;
|
|
1847
|
+
var MANUAL_UPDATES = /* @__PURE__ */ new WeakSet();
|
|
1848
|
+
function markManualUpdate(patch) {
|
|
1849
|
+
try {
|
|
1850
|
+
MANUAL_UPDATES.add(patch);
|
|
1851
|
+
} catch (e) {
|
|
1852
|
+
}
|
|
1853
|
+
return patch;
|
|
1854
|
+
}
|
|
1103
1855
|
var EventShipper = class {
|
|
1104
1856
|
constructor(opts) {
|
|
1105
1857
|
this.appGitOwner = appGitOwnerId("event");
|
|
@@ -1107,6 +1859,12 @@ var EventShipper = class {
|
|
|
1107
1859
|
this.sticky = /* @__PURE__ */ new Map();
|
|
1108
1860
|
this.timers = /* @__PURE__ */ new Map();
|
|
1109
1861
|
this.inFlight = /* @__PURE__ */ new Set();
|
|
1862
|
+
this.background = /* @__PURE__ */ new Set();
|
|
1863
|
+
this.backgroundDrops = 0;
|
|
1864
|
+
this.cutOff = new InFlightCutOff();
|
|
1865
|
+
this.finishedEventIds = /* @__PURE__ */ new Set();
|
|
1866
|
+
this.sendChains = /* @__PURE__ */ new Map();
|
|
1867
|
+
this.deferredSends = /* @__PURE__ */ new Set();
|
|
1110
1868
|
this.hasShutdown = false;
|
|
1111
1869
|
var _a, _b, _c, _d, _e, _f, _g, _h, _i;
|
|
1112
1870
|
this.appGitContext = (_a = opts.appGitContext) != null ? _a : createAppGitContext(opts.appGit);
|
|
@@ -1120,6 +1878,7 @@ var EventShipper = class {
|
|
|
1120
1878
|
this.prefix = `[raindrop-ai/${this.sdkName}]`;
|
|
1121
1879
|
this.defaultEventName = (_f = opts.defaultEventName) != null ? _f : "ai_generation";
|
|
1122
1880
|
this.maxTextFieldCharsOpt = opts.maxTextFieldChars;
|
|
1881
|
+
this.flushTimeoutMs = resolveFlushTimeoutMs(opts.flushTimeoutMs);
|
|
1123
1882
|
this.localDebuggerUrl = (_g = resolveLocalDebuggerBaseUrl(opts.localDebuggerUrl)) != null ? _g : void 0;
|
|
1124
1883
|
if (this.debug && this.localDebuggerUrl) {
|
|
1125
1884
|
console.log(`${this.prefix} Local debugger mirroring: ${this.localDebuggerUrl}`);
|
|
@@ -1128,15 +1887,29 @@ var EventShipper = class {
|
|
|
1128
1887
|
debug: this.debug,
|
|
1129
1888
|
prefix: this.prefix
|
|
1130
1889
|
});
|
|
1131
|
-
|
|
1890
|
+
this.redactPii = opts.redactPii === true;
|
|
1891
|
+
this.piiFields = new PiiFieldRedactor({
|
|
1892
|
+
startupFieldMap: opts.redactPiiFields,
|
|
1893
|
+
logPrefix: this.prefix
|
|
1894
|
+
});
|
|
1895
|
+
if (opts.redactPiiFields && !this.redactPii) {
|
|
1896
|
+
rateLimitedLog(
|
|
1897
|
+
`${this.prefix}.pii_fields_without_redaction`,
|
|
1898
|
+
() => console.warn(
|
|
1899
|
+
`${this.prefix} redactPiiFields is set but redactPii is off; nothing is redacted. Set redactPii: true to use it.`
|
|
1900
|
+
)
|
|
1901
|
+
);
|
|
1902
|
+
}
|
|
1903
|
+
this.wizardSession = opts.wizardSession || void 0;
|
|
1904
|
+
const runtime = detectRuntime();
|
|
1132
1905
|
this.context = {
|
|
1133
1906
|
library: {
|
|
1134
1907
|
name: (_h = opts.libraryName) != null ? _h : "@raindrop-ai/core",
|
|
1135
1908
|
version: (_i = opts.libraryVersion) != null ? _i : "0.0.0"
|
|
1136
1909
|
},
|
|
1137
1910
|
metadata: {
|
|
1138
|
-
jsRuntime:
|
|
1139
|
-
...
|
|
1911
|
+
jsRuntime: runtime,
|
|
1912
|
+
...runtime === "node" ? { nodeVersion: process.version } : {}
|
|
1140
1913
|
}
|
|
1141
1914
|
};
|
|
1142
1915
|
}
|
|
@@ -1153,28 +1926,21 @@ var EventShipper = class {
|
|
|
1153
1926
|
return { ...this.authHeaders(), ...projectIdHeaders(this.projectId) };
|
|
1154
1927
|
}
|
|
1155
1928
|
/**
|
|
1156
|
-
*
|
|
1157
|
-
*
|
|
1158
|
-
*
|
|
1159
|
-
*
|
|
1160
|
-
*
|
|
1161
|
-
* Checked fresh on EVERY send, so a shutdown that begins while the flush
|
|
1162
|
-
* path is mid-drain takes effect immediately: no further retries, and the
|
|
1163
|
-
* per-attempt timeout is clamped to the remaining window. After
|
|
1164
|
-
* `shutdown()` returns (deadline cleared, `hasShutdown` still set),
|
|
1165
|
-
* sends — late callers, or flush work the deadline abandoned mid-drain —
|
|
1166
|
-
* run as a single short attempt rather than regaining the full retry
|
|
1167
|
-
* schedule.
|
|
1929
|
+
* Retry/timeout options for one POST. While `shutdown()` drains, sends retry
|
|
1930
|
+
* within its window (deadline = the shutdown deadline); a flush passes its
|
|
1931
|
+
* own deadline. `null` when the shutdown window is spent: the caller drops
|
|
1932
|
+
* the payload with a warning. After `shutdown()` returns, late sends get a
|
|
1933
|
+
* single short attempt rather than the full retry schedule.
|
|
1168
1934
|
*/
|
|
1169
|
-
requestOpts() {
|
|
1935
|
+
requestOpts(deadlineAt) {
|
|
1170
1936
|
if (this.shutdownDeadlineAt !== void 0) {
|
|
1171
|
-
|
|
1172
|
-
if (remainingMs <= 0) return null;
|
|
1937
|
+
if (this.shutdownDeadlineAt - Date.now() <= 0) return null;
|
|
1173
1938
|
return {
|
|
1174
|
-
maxAttempts:
|
|
1939
|
+
maxAttempts: 3,
|
|
1175
1940
|
debug: this.debug,
|
|
1176
1941
|
sdkName: this.sdkName,
|
|
1177
|
-
|
|
1942
|
+
deadlineAt: Math.min(this.shutdownDeadlineAt, deadlineAt != null ? deadlineAt : Infinity),
|
|
1943
|
+
cutOff: this.cutOff.signal
|
|
1178
1944
|
};
|
|
1179
1945
|
}
|
|
1180
1946
|
if (this.hasShutdown) {
|
|
@@ -1182,15 +1948,94 @@ var EventShipper = class {
|
|
|
1182
1948
|
maxAttempts: 1,
|
|
1183
1949
|
debug: this.debug,
|
|
1184
1950
|
sdkName: this.sdkName,
|
|
1185
|
-
timeoutMs: POST_SHUTDOWN_TIMEOUT_MS
|
|
1951
|
+
timeoutMs: POST_SHUTDOWN_TIMEOUT_MS,
|
|
1952
|
+
cutOff: this.cutOff.signal
|
|
1186
1953
|
};
|
|
1187
1954
|
}
|
|
1188
|
-
return {
|
|
1955
|
+
return {
|
|
1956
|
+
maxAttempts: 3,
|
|
1957
|
+
debug: this.debug,
|
|
1958
|
+
sdkName: this.sdkName,
|
|
1959
|
+
deadlineAt,
|
|
1960
|
+
cutOff: this.cutOff.signal
|
|
1961
|
+
};
|
|
1962
|
+
}
|
|
1963
|
+
shuttingDown() {
|
|
1964
|
+
return this.shutdownDeadlineAt !== void 0 || this.hasShutdown;
|
|
1189
1965
|
}
|
|
1190
1966
|
async patch(eventId, patch) {
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
|
|
1967
|
+
await this.patchWithFate(eventId, patch);
|
|
1968
|
+
}
|
|
1969
|
+
/**
|
|
1970
|
+
* Queue an update without waiting for any network send: for integrations,
|
|
1971
|
+
* whose captured call must return as soon as the update is queued (rule C9,
|
|
1972
|
+
* hot path). A finishing update starts its send in the background; `flush()`
|
|
1973
|
+
* and `shutdown()` wait for it within their deadline and count it in their
|
|
1974
|
+
* result. Never throws or rejects.
|
|
1975
|
+
*/
|
|
1976
|
+
enqueue(eventId, patch) {
|
|
1977
|
+
let op;
|
|
1978
|
+
try {
|
|
1979
|
+
op = this.patchWithFate(eventId, patch).catch((err) => {
|
|
1980
|
+
this.warnBackgroundFailure(eventId, err);
|
|
1981
|
+
return "dropped";
|
|
1982
|
+
}).then((fate) => {
|
|
1983
|
+
if (fate === "dropped") this.backgroundDrops += 1;
|
|
1984
|
+
return fate;
|
|
1985
|
+
});
|
|
1986
|
+
} catch (err) {
|
|
1987
|
+
this.warnBackgroundFailure(eventId, err);
|
|
1988
|
+
return;
|
|
1989
|
+
}
|
|
1990
|
+
this.background.add(op);
|
|
1991
|
+
void op.finally(() => this.background.delete(op));
|
|
1992
|
+
}
|
|
1993
|
+
/** `finish()` without waiting for the send; see `enqueue`. */
|
|
1994
|
+
enqueueFinish(eventId, patch = {}) {
|
|
1995
|
+
this.enqueue(eventId, { ...patch, isPending: false });
|
|
1996
|
+
}
|
|
1997
|
+
/**
|
|
1998
|
+
* Caller properties win over everything the integration derived (W6). A
|
|
1999
|
+
* clash is intended by the caller, so it is only logged in debug mode.
|
|
2000
|
+
*/
|
|
2001
|
+
withCallerProperties(eventId, derived, caller) {
|
|
2002
|
+
if (!caller || Object.keys(caller).length === 0) return derived;
|
|
2003
|
+
if (this.debug) {
|
|
2004
|
+
try {
|
|
2005
|
+
const keys = overriddenKeys(derived, caller);
|
|
2006
|
+
if (keys.length > 0) {
|
|
2007
|
+
console.log(
|
|
2008
|
+
`${this.prefix} event ${eventId}: caller properties override the integration's value for ${keys.map((k) => `"${k}"`).join(", ")}`
|
|
2009
|
+
);
|
|
2010
|
+
}
|
|
2011
|
+
} catch (e) {
|
|
2012
|
+
}
|
|
2013
|
+
}
|
|
2014
|
+
return deepMergeProperties(derived, caller);
|
|
2015
|
+
}
|
|
2016
|
+
warnBackgroundFailure(eventId, err) {
|
|
2017
|
+
rateLimitedLog(
|
|
2018
|
+
`${this.prefix}.background_update`,
|
|
2019
|
+
() => console.warn(`${this.prefix} update for event ${eventId} failed:`, err)
|
|
2020
|
+
);
|
|
2021
|
+
}
|
|
2022
|
+
/**
|
|
2023
|
+
* Id of the last event an integration finished in this process (manual
|
|
2024
|
+
* events API finishes excluded): what integrations expose as `lastEventId`
|
|
2025
|
+
* (wrapper profile W10).
|
|
2026
|
+
*/
|
|
2027
|
+
get lastFinishedEventId() {
|
|
2028
|
+
return this.lastFinished;
|
|
2029
|
+
}
|
|
2030
|
+
async patchWithFate(eventId, patch) {
|
|
2031
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m;
|
|
2032
|
+
const manual = MANUAL_UPDATES.has(patch);
|
|
2033
|
+
if (!this.enabled) return void 0;
|
|
2034
|
+
if (!eventId || !eventId.trim()) return void 0;
|
|
2035
|
+
if (patch.userId !== void 0 && isMissingUserId(patch.userId)) {
|
|
2036
|
+
const { userId: _placeholder, ...rest } = patch;
|
|
2037
|
+
patch = rest;
|
|
2038
|
+
}
|
|
1194
2039
|
const capturedSticky = this.sticky.get(eventId);
|
|
1195
2040
|
const eventAlreadyKnown = capturedSticky !== void 0 || this.buffers.has(eventId);
|
|
1196
2041
|
const destination = currentReplayTraceDestination();
|
|
@@ -1198,7 +2043,7 @@ var EventShipper = class {
|
|
|
1198
2043
|
if ((capturedSticky == null ? void 0 : capturedSticky.replayOnly) === true || !eventAlreadyKnown && cloudReplay) {
|
|
1199
2044
|
if (patch.isPending === false) this.sticky.delete(eventId);
|
|
1200
2045
|
else this.sticky.set(eventId, { ...capturedSticky, replayOnly: true });
|
|
1201
|
-
return;
|
|
2046
|
+
return void 0;
|
|
1202
2047
|
}
|
|
1203
2048
|
const maxChars = resolveMaxTextFieldChars(this.maxTextFieldCharsOpt);
|
|
1204
2049
|
if (typeof patch.input === "string" && patch.input.length > maxChars) {
|
|
@@ -1221,11 +2066,12 @@ var EventShipper = class {
|
|
|
1221
2066
|
}
|
|
1222
2067
|
const sticky = (_c = this.sticky.get(eventId)) != null ? _c : {};
|
|
1223
2068
|
const existing = (_d = this.buffers.get(eventId)) != null ? _d : {};
|
|
2069
|
+
const explicitProperties = patch.callerProperties !== void 0 ? { ...patch.properties, ...patch.callerProperties } : patch.properties;
|
|
1224
2070
|
patch = {
|
|
1225
2071
|
...patch,
|
|
1226
2072
|
properties: withAppGitProperties(
|
|
1227
2073
|
patch.properties,
|
|
1228
|
-
this.appGitContext.forOperation(eventId,
|
|
2074
|
+
this.appGitContext.forOperation(eventId, explicitProperties, this.appGitOwner)
|
|
1229
2075
|
)
|
|
1230
2076
|
};
|
|
1231
2077
|
const merged = mergePatches(existing, patch);
|
|
@@ -1235,47 +2081,165 @@ var EventShipper = class {
|
|
|
1235
2081
|
userId: (_h = merged.userId) != null ? _h : sticky.userId,
|
|
1236
2082
|
convoId: (_i = merged.convoId) != null ? _i : sticky.convoId,
|
|
1237
2083
|
eventName: (_j = merged.eventName) != null ? _j : sticky.eventName,
|
|
1238
|
-
isPending: (_k = merged.isPending) != null ? _k : sticky.isPending
|
|
2084
|
+
isPending: (_k = merged.isPending) != null ? _k : sticky.isPending,
|
|
2085
|
+
startedAt: (_l = earliestIsoTimestamp(sticky.startedAt, patch.timestamp)) != null ? _l : (/* @__PURE__ */ new Date()).toISOString(),
|
|
2086
|
+
resumed: sticky.resumed,
|
|
2087
|
+
hasContent: sticky.hasContent === true || patchHasContent(patch),
|
|
2088
|
+
callerProperties: patch.callerProperties !== void 0 ? deepMergeProperties((_m = sticky.callerProperties) != null ? _m : {}, patch.callerProperties) : sticky.callerProperties
|
|
1239
2089
|
});
|
|
1240
2090
|
const t = this.timers.get(eventId);
|
|
1241
2091
|
if (t) clearTimeout(t);
|
|
1242
2092
|
if (merged.isPending === false) {
|
|
1243
|
-
|
|
2093
|
+
if (!manual) this.lastFinished = eventId;
|
|
2094
|
+
this.noteFinish(eventId);
|
|
2095
|
+
this.noteEmptyFinish(eventId);
|
|
2096
|
+
const fate = await this.flushOne(eventId);
|
|
1244
2097
|
if (this.appGitContext.releaseOperation) this.appGitContext.releaseOperation(eventId, this.appGitOwner);
|
|
1245
2098
|
else this.appGitContext.finishOperation(eventId);
|
|
1246
|
-
return;
|
|
2099
|
+
return fate;
|
|
1247
2100
|
}
|
|
1248
2101
|
const timeout = setTimeout(() => {
|
|
1249
2102
|
void this.flushOne(eventId).catch(() => {
|
|
1250
2103
|
});
|
|
1251
2104
|
}, this.partialFlushMs);
|
|
1252
2105
|
this.timers.set(eventId, timeout);
|
|
2106
|
+
return void 0;
|
|
2107
|
+
}
|
|
2108
|
+
/**
|
|
2109
|
+
* A second finish for an event is still sent (ingest finalizes once and
|
|
2110
|
+
* treats it as an update, CONTRACT §10.2), but it usually means several
|
|
2111
|
+
* calls share one event id by mistake, so it is warned about.
|
|
2112
|
+
*/
|
|
2113
|
+
noteFinish(eventId) {
|
|
2114
|
+
if (this.finishedEventIds.has(eventId)) {
|
|
2115
|
+
rateLimitedLog(
|
|
2116
|
+
`${this.prefix}.repeated_finish`,
|
|
2117
|
+
() => console.warn(
|
|
2118
|
+
`${this.prefix} event ${eventId} was already finished in this process; sending the update anyway (ingest finalizes an event once). Use a separate event id per interaction, or keep the event pending until its last call.`
|
|
2119
|
+
)
|
|
2120
|
+
);
|
|
2121
|
+
return;
|
|
2122
|
+
}
|
|
2123
|
+
this.finishedEventIds.add(eventId);
|
|
2124
|
+
if (this.finishedEventIds.size > FINISHED_EVENT_MEMORY) {
|
|
2125
|
+
const oldest = this.finishedEventIds.values().next().value;
|
|
2126
|
+
if (oldest !== void 0) this.finishedEventIds.delete(oldest);
|
|
2127
|
+
}
|
|
2128
|
+
}
|
|
2129
|
+
/**
|
|
2130
|
+
* An event finished with no input, output or attachments is almost always a
|
|
2131
|
+
* caller bug (CONTRACT §14.2, rule C5); it is sent anyway and warned about.
|
|
2132
|
+
* Not for a resumed event: its content may have been sent by another process.
|
|
2133
|
+
*/
|
|
2134
|
+
noteEmptyFinish(eventId) {
|
|
2135
|
+
const sticky = this.sticky.get(eventId);
|
|
2136
|
+
if ((sticky == null ? void 0 : sticky.resumed) === true || (sticky == null ? void 0 : sticky.hasContent) === true) return;
|
|
2137
|
+
rateLimitedLog(
|
|
2138
|
+
`${this.prefix}.empty_finish`,
|
|
2139
|
+
() => console.warn(
|
|
2140
|
+
`${this.prefix} event ${eventId} finished with no input, output or attachments; sending it anyway. Pass the interaction's input at begin or its output at finish.`
|
|
2141
|
+
)
|
|
2142
|
+
);
|
|
2143
|
+
}
|
|
2144
|
+
/**
|
|
2145
|
+
* Continue an event that was begun elsewhere (another process, a queue
|
|
2146
|
+
* worker, a later request) using only its id. No request is sent; later
|
|
2147
|
+
* `patch` / `finish` calls for this id are sent even without a `userId`,
|
|
2148
|
+
* and ingest keeps the user, conversation and start time it already has.
|
|
2149
|
+
* Pass `userId` / `convoId` / `eventName` if you have them.
|
|
2150
|
+
*/
|
|
2151
|
+
resume(eventId, options = {}) {
|
|
2152
|
+
var _a, _b, _c;
|
|
2153
|
+
if (!this.enabled) return;
|
|
2154
|
+
if (!eventId || !eventId.trim()) return;
|
|
2155
|
+
const sticky = (_a = this.sticky.get(eventId)) != null ? _a : {};
|
|
2156
|
+
this.sticky.set(eventId, {
|
|
2157
|
+
...sticky,
|
|
2158
|
+
userId: isMissingUserId(options.userId) ? sticky.userId : options.userId,
|
|
2159
|
+
convoId: (_b = options.convoId) != null ? _b : sticky.convoId,
|
|
2160
|
+
eventName: (_c = options.eventName) != null ? _c : sticky.eventName,
|
|
2161
|
+
resumed: true
|
|
2162
|
+
});
|
|
1253
2163
|
}
|
|
1254
2164
|
async finish(eventId, patch) {
|
|
1255
|
-
|
|
2165
|
+
const update = { ...patch, isPending: false };
|
|
2166
|
+
if (MANUAL_UPDATES.has(patch)) MANUAL_UPDATES.add(update);
|
|
2167
|
+
await this.patch(eventId, update);
|
|
1256
2168
|
}
|
|
2169
|
+
/**
|
|
2170
|
+
* Send everything buffered, open (pending) events included, within
|
|
2171
|
+
* `flushTimeoutMs` (CONTRACT 1.2.1). Resolves, never rejects, to whether it
|
|
2172
|
+
* all reached ingest; when it didn't, it also warns. At the deadline,
|
|
2173
|
+
* payloads not yet sent stay queued for a later send and a request cut off
|
|
2174
|
+
* mid-flight is dropped. Sends already running when it was called are
|
|
2175
|
+
* waited for up to the deadline and then cut off.
|
|
2176
|
+
*/
|
|
1257
2177
|
async flush() {
|
|
1258
|
-
|
|
2178
|
+
const result = await this.drainAll(Date.now() + this.flushTimeoutMs);
|
|
2179
|
+
if (!result.delivered && this.shutdownDeadlineAt === void 0) {
|
|
2180
|
+
rateLimitedLog(
|
|
2181
|
+
`${this.prefix}.flush_undelivered`,
|
|
2182
|
+
() => console.warn(`${this.prefix} ${describeUndelivered("flush()", result)}`)
|
|
2183
|
+
);
|
|
2184
|
+
}
|
|
2185
|
+
return asCompat(result);
|
|
2186
|
+
}
|
|
2187
|
+
async drainAll(deadlineAt) {
|
|
2188
|
+
if (!this.enabled) return { ...DELIVERED };
|
|
2189
|
+
const deferred = [...this.deferredSends];
|
|
2190
|
+
this.deferredSends.clear();
|
|
2191
|
+
for (const entry of deferred) if (entry.timer) clearTimeout(entry.timer);
|
|
1259
2192
|
const ids = [...this.buffers.keys()];
|
|
1260
|
-
await Promise.all(
|
|
1261
|
-
|
|
1262
|
-
|
|
2193
|
+
const fates = await Promise.all([
|
|
2194
|
+
...ids.map((id) => this.flushOne(id, deadlineAt)),
|
|
2195
|
+
...deferred.map((entry) => entry.send(deadlineAt))
|
|
2196
|
+
]);
|
|
2197
|
+
const background = [...this.background];
|
|
2198
|
+
if (background.length > 0) {
|
|
2199
|
+
await raceWithTimeout(Promise.all(background), deadlineAt - Date.now());
|
|
2200
|
+
}
|
|
2201
|
+
for (; this.backgroundDrops > 0; this.backgroundDrops -= 1) fates.push("dropped");
|
|
2202
|
+
const running = [...this.inFlight];
|
|
2203
|
+
const { settled, stillRunning } = await awaitEarlierSends(
|
|
2204
|
+
running,
|
|
2205
|
+
deadlineAt,
|
|
2206
|
+
this.cutOff,
|
|
2207
|
+
(p) => this.inFlight.has(p)
|
|
2208
|
+
);
|
|
2209
|
+
const unresolved = background.filter((op) => this.background.has(op)).length;
|
|
2210
|
+
return summarize2(
|
|
2211
|
+
fates.filter((fate) => fate !== void 0),
|
|
2212
|
+
Math.max(stillRunning, unresolved),
|
|
2213
|
+
!settled || unresolved > 0
|
|
2214
|
+
);
|
|
1263
2215
|
}
|
|
2216
|
+
/**
|
|
2217
|
+
* Flush within `flushTimeoutMs` and stop. Sends retry while the window
|
|
2218
|
+
* allows; whatever is left at the deadline is dropped with a warning, so a
|
|
2219
|
+
* dead network can never wedge process exit. Resolves, never rejects.
|
|
2220
|
+
*/
|
|
1264
2221
|
async shutdown() {
|
|
1265
2222
|
this.hasShutdown = true;
|
|
1266
|
-
|
|
2223
|
+
const deadlineAt = Date.now() + this.flushTimeoutMs;
|
|
2224
|
+
this.shutdownDeadlineAt = deadlineAt;
|
|
2225
|
+
let result = { ...DELIVERED };
|
|
1267
2226
|
try {
|
|
1268
2227
|
for (const t of this.timers.values()) clearTimeout(t);
|
|
1269
2228
|
this.timers.clear();
|
|
1270
2229
|
for (const [eventId, sticky] of this.sticky) {
|
|
1271
2230
|
if (sticky.replayOnly) this.sticky.delete(eventId);
|
|
1272
2231
|
}
|
|
1273
|
-
|
|
1274
|
-
if (!
|
|
2232
|
+
result = await this.drainAll(deadlineAt);
|
|
2233
|
+
if (!result.delivered) {
|
|
2234
|
+
this.warnShutdownDrop(
|
|
2235
|
+
`${result.dropped + result.queued + result.inFlight} payload(s) not delivered`
|
|
2236
|
+
);
|
|
2237
|
+
}
|
|
1275
2238
|
} finally {
|
|
1276
2239
|
this.shutdownDeadlineAt = void 0;
|
|
1277
2240
|
if (this.ownsAppGitContext) this.appGitContext.dispose();
|
|
1278
2241
|
}
|
|
2242
|
+
return asCompat(result);
|
|
1279
2243
|
}
|
|
1280
2244
|
async trackSignal(signal) {
|
|
1281
2245
|
var _a, _b;
|
|
@@ -1296,23 +2260,9 @@ var EventShipper = class {
|
|
|
1296
2260
|
...signal.after ? { after: signal.after } : {}
|
|
1297
2261
|
}
|
|
1298
2262
|
}
|
|
1299
|
-
];
|
|
2263
|
+
].map((item) => this.redactFields("signal", item));
|
|
1300
2264
|
if (!this.writeKey) return;
|
|
1301
|
-
|
|
1302
|
-
const opts = this.requestOpts();
|
|
1303
|
-
if (!opts) {
|
|
1304
|
-
this.warnShutdownDrop("signal");
|
|
1305
|
-
return;
|
|
1306
|
-
}
|
|
1307
|
-
try {
|
|
1308
|
-
await postJson(url, body, this.requestHeaders(), opts);
|
|
1309
|
-
} catch (err) {
|
|
1310
|
-
const msg = err instanceof Error ? err.message : String(err);
|
|
1311
|
-
rateLimitedLog(
|
|
1312
|
-
`${this.prefix}.send_signal_failed`,
|
|
1313
|
-
() => console.warn(`${this.prefix} failed to send signal (dropping): ${msg}`)
|
|
1314
|
-
);
|
|
1315
|
-
}
|
|
2265
|
+
await this.sendDirect("signal", `${this.baseUrl}signals/track`, body);
|
|
1316
2266
|
}
|
|
1317
2267
|
async identify(users) {
|
|
1318
2268
|
if (!this.enabled) return;
|
|
@@ -1327,30 +2277,80 @@ var EventShipper = class {
|
|
|
1327
2277
|
return false;
|
|
1328
2278
|
}
|
|
1329
2279
|
return true;
|
|
1330
|
-
}).map(
|
|
1331
|
-
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
|
-
|
|
1336
|
-
|
|
2280
|
+
}).map(
|
|
2281
|
+
(user) => {
|
|
2282
|
+
var _a;
|
|
2283
|
+
return this.redactFields("identify", {
|
|
2284
|
+
user_id: user.userId,
|
|
2285
|
+
traits: (_a = user.traits) != null ? _a : {}
|
|
2286
|
+
});
|
|
2287
|
+
}
|
|
2288
|
+
);
|
|
1337
2289
|
if (!this.writeKey) return;
|
|
1338
2290
|
if (body.length === 0) return;
|
|
1339
|
-
|
|
1340
|
-
|
|
2291
|
+
await this.sendDirect("identify", `${this.baseUrl}users/identify`, body);
|
|
2292
|
+
}
|
|
2293
|
+
/**
|
|
2294
|
+
* Send a signal or identify body. Tracked so `flush()` waits for it. A send
|
|
2295
|
+
* a flush deadline deferred is kept and retried later (outside shutdown).
|
|
2296
|
+
*/
|
|
2297
|
+
async sendDirect(kind, url, body, deadlineAt) {
|
|
2298
|
+
const opts = this.requestOpts(deadlineAt);
|
|
1341
2299
|
if (!opts) {
|
|
1342
|
-
this.warnShutdownDrop(
|
|
1343
|
-
return;
|
|
2300
|
+
this.warnShutdownDrop(kind);
|
|
2301
|
+
return "dropped";
|
|
1344
2302
|
}
|
|
2303
|
+
const sending = sendJson(url, body, this.requestHeaders(), opts);
|
|
2304
|
+
const tracked = sending.then(() => void 0);
|
|
2305
|
+
this.inFlight.add(tracked);
|
|
2306
|
+
let outcome;
|
|
1345
2307
|
try {
|
|
1346
|
-
|
|
1347
|
-
}
|
|
1348
|
-
|
|
2308
|
+
outcome = await sending;
|
|
2309
|
+
} finally {
|
|
2310
|
+
this.inFlight.delete(tracked);
|
|
2311
|
+
}
|
|
2312
|
+
const fate = fateOf(outcome, this.shuttingDown());
|
|
2313
|
+
if (fate === "queued") {
|
|
2314
|
+
this.deferSend(
|
|
2315
|
+
(later) => this.sendDirect(kind, url, body, later),
|
|
2316
|
+
outcome.status === "deferred" ? outcome.retryAtMs : void 0
|
|
2317
|
+
);
|
|
2318
|
+
} else if (fate === "dropped") {
|
|
2319
|
+
this.warnSendDropped(kind, outcome);
|
|
2320
|
+
}
|
|
2321
|
+
return fate;
|
|
2322
|
+
}
|
|
2323
|
+
deferSend(send, retryAtMs) {
|
|
2324
|
+
var _a, _b;
|
|
2325
|
+
if (this.deferredSends.size >= MAX_DEFERRED_SENDS) {
|
|
1349
2326
|
rateLimitedLog(
|
|
1350
|
-
`${this.prefix}.
|
|
1351
|
-
() => console.warn(`${this.prefix}
|
|
2327
|
+
`${this.prefix}.deferred_full`,
|
|
2328
|
+
() => console.warn(`${this.prefix} too many sends waiting for a retry; dropping one`)
|
|
1352
2329
|
);
|
|
2330
|
+
return;
|
|
1353
2331
|
}
|
|
2332
|
+
const entry = { send };
|
|
2333
|
+
const delay = Math.max(this.partialFlushMs, (retryAtMs != null ? retryAtMs : 0) - Date.now());
|
|
2334
|
+
entry.timer = setTimeout(() => {
|
|
2335
|
+
if (!this.deferredSends.delete(entry)) return;
|
|
2336
|
+
void send().catch(() => {
|
|
2337
|
+
});
|
|
2338
|
+
}, delay);
|
|
2339
|
+
(_b = (_a = entry.timer).unref) == null ? void 0 : _b.call(_a);
|
|
2340
|
+
this.deferredSends.add(entry);
|
|
2341
|
+
}
|
|
2342
|
+
warnSendDropped(what, outcome) {
|
|
2343
|
+
var _a, _b;
|
|
2344
|
+
if (outcome.status === "delivered" || outcome.status === "rejected") return;
|
|
2345
|
+
const reason = outcome.status === "cut_off" ? "cut off at the flush deadline (not resent: it may have reached ingest)" : outcome.status === "deferred" ? "not sent before the shutdown deadline" : (_b = (_a = outcome.error) == null ? void 0 : _a.message) != null ? _b : outcome.status;
|
|
2346
|
+
rateLimitedLog(
|
|
2347
|
+
`${this.prefix}.send_${what}_dropped`,
|
|
2348
|
+
() => console.warn(`${this.prefix} failed to send ${what} (dropping): ${reason}`)
|
|
2349
|
+
);
|
|
2350
|
+
}
|
|
2351
|
+
/** The payload with its PII fields redacted when `redactPii` is on (CONTRACT 11.2). */
|
|
2352
|
+
redactFields(kind, payload) {
|
|
2353
|
+
return this.redactPii ? this.piiFields.redact(kind, payload) : payload;
|
|
1354
2354
|
}
|
|
1355
2355
|
warnShutdownDrop(what) {
|
|
1356
2356
|
rateLimitedLog(
|
|
@@ -1358,9 +2358,8 @@ var EventShipper = class {
|
|
|
1358
2358
|
() => console.warn(`${this.prefix} shutdown flush deadline exceeded; dropping ${what}`)
|
|
1359
2359
|
);
|
|
1360
2360
|
}
|
|
1361
|
-
async flushOne(eventId) {
|
|
1362
|
-
|
|
1363
|
-
if (!this.enabled) return;
|
|
2361
|
+
async flushOne(eventId, deadlineAt) {
|
|
2362
|
+
if (!this.enabled) return void 0;
|
|
1364
2363
|
const timer = this.timers.get(eventId);
|
|
1365
2364
|
if (timer) {
|
|
1366
2365
|
clearTimeout(timer);
|
|
@@ -1368,30 +2367,91 @@ var EventShipper = class {
|
|
|
1368
2367
|
}
|
|
1369
2368
|
const accumulated = this.buffers.get(eventId);
|
|
1370
2369
|
this.buffers.delete(eventId);
|
|
1371
|
-
if (!accumulated) return;
|
|
2370
|
+
if (!accumulated) return void 0;
|
|
2371
|
+
const previous = this.sendChains.get(eventId);
|
|
2372
|
+
let release = () => {
|
|
2373
|
+
};
|
|
2374
|
+
const current = new Promise((resolve2) => {
|
|
2375
|
+
release = resolve2;
|
|
2376
|
+
});
|
|
2377
|
+
this.sendChains.set(eventId, current);
|
|
2378
|
+
try {
|
|
2379
|
+
if (previous) {
|
|
2380
|
+
const ready = deadlineAt === void 0 ? (await previous, true) : await raceWithTimeout(previous, deadlineAt - Date.now());
|
|
2381
|
+
if (!ready) {
|
|
2382
|
+
return this.requeue(eventId, accumulated, void 0);
|
|
2383
|
+
}
|
|
2384
|
+
}
|
|
2385
|
+
return await this.sendAccumulated(eventId, accumulated, deadlineAt);
|
|
2386
|
+
} finally {
|
|
2387
|
+
release();
|
|
2388
|
+
if (this.sendChains.get(eventId) === current) this.sendChains.delete(eventId);
|
|
2389
|
+
}
|
|
2390
|
+
}
|
|
2391
|
+
/**
|
|
2392
|
+
* Put an unsent update back under any newer one and send it later
|
|
2393
|
+
* (CONTRACT 1.2.1). During shutdown it is dropped instead.
|
|
2394
|
+
*/
|
|
2395
|
+
requeue(eventId, accumulated, retryAtMs) {
|
|
2396
|
+
var _a, _b;
|
|
2397
|
+
if (this.shuttingDown()) {
|
|
2398
|
+
this.warnShutdownDrop(`track_partial ${eventId}`);
|
|
2399
|
+
if (accumulated.isPending === false) this.sticky.delete(eventId);
|
|
2400
|
+
return "dropped";
|
|
2401
|
+
}
|
|
2402
|
+
const newer = this.buffers.get(eventId);
|
|
2403
|
+
const merged = newer ? mergePatches(accumulated, newer) : accumulated;
|
|
2404
|
+
merged.isPending = (_a = newer == null ? void 0 : newer.isPending) != null ? _a : accumulated.isPending;
|
|
2405
|
+
this.buffers.set(eventId, merged);
|
|
2406
|
+
const existing = this.timers.get(eventId);
|
|
2407
|
+
if (existing) clearTimeout(existing);
|
|
2408
|
+
const delay = Math.max(this.partialFlushMs, (retryAtMs != null ? retryAtMs : 0) - Date.now());
|
|
2409
|
+
const timeout = setTimeout(() => {
|
|
2410
|
+
void this.flushOne(eventId).catch(() => {
|
|
2411
|
+
});
|
|
2412
|
+
}, delay);
|
|
2413
|
+
(_b = timeout.unref) == null ? void 0 : _b.call(timeout);
|
|
2414
|
+
this.timers.set(eventId, timeout);
|
|
2415
|
+
return "queued";
|
|
2416
|
+
}
|
|
2417
|
+
async sendAccumulated(eventId, accumulated, deadlineAt) {
|
|
2418
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p;
|
|
1372
2419
|
const sticky = (_a = this.sticky.get(eventId)) != null ? _a : {};
|
|
1373
2420
|
const isPending = (_c = (_b = accumulated.isPending) != null ? _b : sticky.isPending) != null ? _c : true;
|
|
1374
|
-
const
|
|
1375
|
-
const
|
|
1376
|
-
|
|
1377
|
-
|
|
1378
|
-
|
|
1379
|
-
|
|
2421
|
+
const knownEventName = (_d = accumulated.eventName) != null ? _d : sticky.eventName;
|
|
2422
|
+
const eventName = knownEventName != null ? knownEventName : sticky.resumed ? void 0 : this.defaultEventName;
|
|
2423
|
+
const userId = (_e = accumulated.userId) != null ? _e : sticky.userId;
|
|
2424
|
+
if (!userId && !sticky.resumed) {
|
|
2425
|
+
rateLimitedLog(
|
|
2426
|
+
`${this.prefix}.track_partial_missing_user`,
|
|
2427
|
+
() => console.warn(
|
|
2428
|
+
`${this.prefix} skipping track_partial for ${eventId}: missing userId (pass userId, or call resume(eventId) to continue an event begun elsewhere)`
|
|
2429
|
+
)
|
|
2430
|
+
);
|
|
1380
2431
|
this.sticky.delete(eventId);
|
|
1381
|
-
return;
|
|
2432
|
+
return void 0;
|
|
1382
2433
|
}
|
|
1383
|
-
|
|
2434
|
+
if (!userId) {
|
|
2435
|
+
rateLimitedLog(
|
|
2436
|
+
`${this.prefix}.track_partial_resumed_without_user`,
|
|
2437
|
+
() => console.warn(
|
|
2438
|
+
`${this.prefix} sending track_partial for ${eventId} without a userId; ingest will use the user stored for this event (pass userId to resume() to set it explicitly)`
|
|
2439
|
+
)
|
|
2440
|
+
);
|
|
2441
|
+
}
|
|
2442
|
+
const { wizardSession, ...restProperties } = (_f = accumulated.properties) != null ? _f : {};
|
|
1384
2443
|
let telemetryProperties = {};
|
|
1385
2444
|
try {
|
|
1386
2445
|
telemetryProperties = eventTelemetryProperties(accumulated);
|
|
1387
2446
|
} catch (e) {
|
|
1388
2447
|
}
|
|
1389
|
-
const convoId = (
|
|
1390
|
-
const
|
|
2448
|
+
const convoId = (_g = accumulated.convoId) != null ? _g : sticky.convoId;
|
|
2449
|
+
const sessionTag = wizardSession != null ? wizardSession : this.wizardSession;
|
|
2450
|
+
const unredacted = {
|
|
1391
2451
|
event_id: eventId,
|
|
1392
|
-
user_id: userId,
|
|
1393
|
-
event: eventName,
|
|
1394
|
-
timestamp: (_i = accumulated.timestamp) != null ? _i : (/* @__PURE__ */ new Date()).toISOString(),
|
|
2452
|
+
...userId ? { user_id: userId } : {},
|
|
2453
|
+
...eventName ? { event: eventName } : {},
|
|
2454
|
+
timestamp: (_i = (_h = sticky.startedAt) != null ? _h : accumulated.timestamp) != null ? _i : (/* @__PURE__ */ new Date()).toISOString(),
|
|
1395
2455
|
ai_data: {
|
|
1396
2456
|
input: accumulated.input,
|
|
1397
2457
|
output: accumulated.error !== void 0 && accumulated.error !== null ? void 0 : accumulated.output,
|
|
@@ -1399,32 +2459,38 @@ var EventShipper = class {
|
|
|
1399
2459
|
convo_id: convoId
|
|
1400
2460
|
},
|
|
1401
2461
|
properties: {
|
|
1402
|
-
...
|
|
1403
|
-
|
|
1404
|
-
|
|
2462
|
+
...this.withCallerProperties(
|
|
2463
|
+
eventId,
|
|
2464
|
+
{ ...restProperties, ...telemetryProperties },
|
|
2465
|
+
(_j = sticky.callerProperties) != null ? _j : accumulated.callerProperties
|
|
2466
|
+
),
|
|
2467
|
+
...sessionTag ? { "raindrop.wizardSession": sessionTag } : {},
|
|
1405
2468
|
$context: this.context
|
|
1406
2469
|
},
|
|
1407
2470
|
...accumulated.featureFlags && Object.keys(accumulated.featureFlags).length > 0 ? { feature_flags: accumulated.featureFlags } : {},
|
|
1408
2471
|
attachments: accumulated.attachments,
|
|
1409
2472
|
is_pending: isPending
|
|
1410
2473
|
};
|
|
2474
|
+
const payload = this.redactFields("event", unredacted);
|
|
1411
2475
|
const url = `${this.baseUrl}events/track_partial`;
|
|
1412
2476
|
if (this.debug) {
|
|
2477
|
+
const sent = payload;
|
|
2478
|
+
const preview = (v, n) => typeof v === "string" ? v.slice(0, n) : void 0;
|
|
1413
2479
|
console.log(`${this.prefix} sending track_partial`, {
|
|
1414
2480
|
eventId,
|
|
1415
2481
|
eventName,
|
|
1416
2482
|
userId,
|
|
1417
2483
|
convoId,
|
|
1418
2484
|
isPending,
|
|
1419
|
-
inputPreview:
|
|
1420
|
-
outputPreview:
|
|
1421
|
-
attachments: (
|
|
1422
|
-
attachmentKinds: (
|
|
2485
|
+
inputPreview: preview((_k = sent.ai_data) == null ? void 0 : _k.input, 120),
|
|
2486
|
+
outputPreview: preview((_l = sent.ai_data) == null ? void 0 : _l.output, 120),
|
|
2487
|
+
attachments: (_n = (_m = sent.attachments) == null ? void 0 : _m.length) != null ? _n : 0,
|
|
2488
|
+
attachmentKinds: (_p = (_o = sent.attachments) == null ? void 0 : _o.map((a) => ({
|
|
1423
2489
|
type: a.type,
|
|
1424
2490
|
role: a.role,
|
|
1425
2491
|
name: a.name,
|
|
1426
|
-
valuePreview: a.value
|
|
1427
|
-
}))) != null ?
|
|
2492
|
+
valuePreview: preview(a.value, 60)
|
|
2493
|
+
}))) != null ? _p : [],
|
|
1428
2494
|
endpoint: url
|
|
1429
2495
|
});
|
|
1430
2496
|
}
|
|
@@ -1437,39 +2503,94 @@ var EventShipper = class {
|
|
|
1437
2503
|
if (!this.writeKey) {
|
|
1438
2504
|
if (!isPending) this.sticky.delete(eventId);
|
|
1439
2505
|
if (mirror) await mirror;
|
|
1440
|
-
return;
|
|
2506
|
+
return void 0;
|
|
1441
2507
|
}
|
|
1442
|
-
const opts = this.requestOpts();
|
|
2508
|
+
const opts = this.requestOpts(deadlineAt);
|
|
1443
2509
|
if (!opts) {
|
|
1444
2510
|
this.warnShutdownDrop(`track_partial ${eventId}`);
|
|
1445
2511
|
if (!isPending) this.sticky.delete(eventId);
|
|
1446
2512
|
if (mirror) await mirror;
|
|
1447
|
-
return;
|
|
2513
|
+
return "dropped";
|
|
1448
2514
|
}
|
|
1449
|
-
const
|
|
1450
|
-
const combined =
|
|
2515
|
+
const sending = sendJson(url, payload, this.requestHeaders(), opts);
|
|
2516
|
+
const combined = Promise.all([mirror, sending.then(() => void 0)]).then(() => void 0);
|
|
1451
2517
|
this.inFlight.add(combined);
|
|
2518
|
+
let outcome;
|
|
1452
2519
|
try {
|
|
1453
|
-
|
|
1454
|
-
|
|
1455
|
-
|
|
1456
|
-
console.log(`${this.prefix} sent track_partial ${eventId} (${eventName})`);
|
|
1457
|
-
}
|
|
1458
|
-
} catch (err) {
|
|
1459
|
-
const msg = err instanceof Error ? err.message : String(err);
|
|
1460
|
-
rateLimitedLog(
|
|
1461
|
-
`${this.prefix}.send_track_partial_failed`,
|
|
1462
|
-
() => console.warn(`${this.prefix} failed to send track_partial (dropping): ${msg}`)
|
|
1463
|
-
);
|
|
1464
|
-
}
|
|
2520
|
+
outcome = await sending;
|
|
2521
|
+
if (mirror) await mirror.catch(() => {
|
|
2522
|
+
});
|
|
1465
2523
|
} finally {
|
|
1466
2524
|
this.inFlight.delete(combined);
|
|
1467
2525
|
}
|
|
2526
|
+
const fate = fateOf(outcome, this.shuttingDown());
|
|
2527
|
+
if (fate === "queued") {
|
|
2528
|
+
return this.requeue(
|
|
2529
|
+
eventId,
|
|
2530
|
+
accumulated,
|
|
2531
|
+
outcome.status === "deferred" ? outcome.retryAtMs : void 0
|
|
2532
|
+
);
|
|
2533
|
+
}
|
|
2534
|
+
if (fate === "dropped") this.warnSendDropped("track_partial", outcome);
|
|
2535
|
+
else if (this.debug && outcome.status === "delivered") {
|
|
2536
|
+
console.log(`${this.prefix} sent track_partial ${eventId} (${eventName})`);
|
|
2537
|
+
}
|
|
1468
2538
|
if (!isPending) {
|
|
1469
2539
|
this.sticky.delete(eventId);
|
|
1470
2540
|
}
|
|
2541
|
+
return fate;
|
|
1471
2542
|
}
|
|
1472
2543
|
};
|
|
2544
|
+
function overriddenKeys(derived, caller) {
|
|
2545
|
+
const keys = [];
|
|
2546
|
+
for (const [key, value] of Object.entries(caller)) {
|
|
2547
|
+
if (value === void 0 || !(key in derived)) continue;
|
|
2548
|
+
const existing = derived[key];
|
|
2549
|
+
if (isPlainObject2(existing) && isPlainObject2(value)) {
|
|
2550
|
+
if (overriddenKeys(existing, value).length > 0) keys.push(key);
|
|
2551
|
+
} else if (JSON.stringify(existing) !== JSON.stringify(value)) {
|
|
2552
|
+
keys.push(key);
|
|
2553
|
+
}
|
|
2554
|
+
}
|
|
2555
|
+
return keys;
|
|
2556
|
+
}
|
|
2557
|
+
function patchHasContent(patch) {
|
|
2558
|
+
var _a, _b;
|
|
2559
|
+
return typeof patch.input === "string" && patch.input.length > 0 || typeof patch.output === "string" && patch.output.length > 0 || ((_b = (_a = patch.attachments) == null ? void 0 : _a.length) != null ? _b : 0) > 0;
|
|
2560
|
+
}
|
|
2561
|
+
function resolveFlushTimeoutMs(value) {
|
|
2562
|
+
return typeof value === "number" && Number.isFinite(value) && value > 0 ? value : DEFAULT_FLUSH_TIMEOUT_MS;
|
|
2563
|
+
}
|
|
2564
|
+
function createEventsApi(shipper) {
|
|
2565
|
+
return {
|
|
2566
|
+
async patch(eventId, patch) {
|
|
2567
|
+
await (shipper == null ? void 0 : shipper.patch(eventId, markManualUpdate(asCallerPatch(patch))));
|
|
2568
|
+
},
|
|
2569
|
+
async finish(eventId, patch = {}) {
|
|
2570
|
+
await (shipper == null ? void 0 : shipper.finish(eventId, markManualUpdate(asCallerPatch(patch))));
|
|
2571
|
+
},
|
|
2572
|
+
async addAttachments(eventId, attachments) {
|
|
2573
|
+
await (shipper == null ? void 0 : shipper.patch(eventId, markManualUpdate({ attachments })));
|
|
2574
|
+
},
|
|
2575
|
+
async setProperties(eventId, properties) {
|
|
2576
|
+
await (shipper == null ? void 0 : shipper.patch(eventId, markManualUpdate({ properties, callerProperties: properties })));
|
|
2577
|
+
},
|
|
2578
|
+
async setFeatureFlags(eventId, featureFlags) {
|
|
2579
|
+
await (shipper == null ? void 0 : shipper.patch(eventId, markManualUpdate({ featureFlags: normalizeFeatureFlags(featureFlags) })));
|
|
2580
|
+
},
|
|
2581
|
+
resume(eventId, options) {
|
|
2582
|
+
shipper == null ? void 0 : shipper.resume(eventId, options);
|
|
2583
|
+
}
|
|
2584
|
+
};
|
|
2585
|
+
}
|
|
2586
|
+
function asCallerPatch(patch) {
|
|
2587
|
+
var _a;
|
|
2588
|
+
if (!patch.properties) return patch;
|
|
2589
|
+
return {
|
|
2590
|
+
...patch,
|
|
2591
|
+
callerProperties: { ...patch.properties, ...(_a = patch.callerProperties) != null ? _a : {} }
|
|
2592
|
+
};
|
|
2593
|
+
}
|
|
1473
2594
|
var MODEL_USAGE_ATTRIBUTES = {
|
|
1474
2595
|
usageSource: "raindrop.usage.source",
|
|
1475
2596
|
providerName: "gen_ai.provider.name",
|
|
@@ -1529,6 +2650,21 @@ function buildRawModelUsageAttributes(usage) {
|
|
|
1529
2650
|
attrDouble(MODEL_USAGE_ATTRIBUTES.providerReportedCost, providerReportedCost)
|
|
1530
2651
|
].filter((attribute) => attribute !== void 0);
|
|
1531
2652
|
}
|
|
2653
|
+
var KNOWN_MODEL_PROVIDERS = /* @__PURE__ */ new Set([
|
|
2654
|
+
...MODEL_PROVIDER_NAMES.map(([, family]) => family),
|
|
2655
|
+
"vercel",
|
|
2656
|
+
// Further vendors Dawn's pricing resolves (apps/dawn/lib/spend).
|
|
2657
|
+
"deepseek",
|
|
2658
|
+
"fireworks-ai",
|
|
2659
|
+
"groq",
|
|
2660
|
+
"inception",
|
|
2661
|
+
"mistral",
|
|
2662
|
+
"moonshotai",
|
|
2663
|
+
"perplexity",
|
|
2664
|
+
"togetherai",
|
|
2665
|
+
"xai",
|
|
2666
|
+
"zai"
|
|
2667
|
+
]);
|
|
1532
2668
|
var STRING_ALIASES = {
|
|
1533
2669
|
[MODEL_USAGE_ATTRIBUTES.requestModel]: ["ai.model.id", "ai.model"]
|
|
1534
2670
|
};
|
|
@@ -1648,12 +2784,41 @@ var REDACTED_PLACEHOLDER = "[REDACTED]";
|
|
|
1648
2784
|
function normalizeKeyName(name) {
|
|
1649
2785
|
return name.toLowerCase().replace(/[-_.]/g, "");
|
|
1650
2786
|
}
|
|
2787
|
+
var URL_USERINFO = new RegExp(
|
|
2788
|
+
String.raw`\b([a-z][a-z0-9+.-]{0,${DEFAULT_MAX_TEXT_FIELD_CHARS - 1}})(?::\/\/([^\s/?#]{1,${DEFAULT_MAX_TEXT_FIELD_CHARS}})@)?`,
|
|
2789
|
+
"gi"
|
|
2790
|
+
);
|
|
2791
|
+
var URL_QUERY_PARAM = /([?&#]([A-Za-z0-9_.\-]+)=)[^&#?\s"']*/g;
|
|
2792
|
+
var URL_SECRET_QUERY_KEYS = /* @__PURE__ */ new Set([
|
|
2793
|
+
"token",
|
|
2794
|
+
"secret",
|
|
2795
|
+
"sig",
|
|
2796
|
+
"signature",
|
|
2797
|
+
"awsaccesskeyid",
|
|
2798
|
+
"xamzsignature",
|
|
2799
|
+
"xamzcredential",
|
|
2800
|
+
"xamzsecuritytoken",
|
|
2801
|
+
"xgoogsignature"
|
|
2802
|
+
]);
|
|
2803
|
+
var DEFAULT_SECRET_SET = buildSecretSet(DEFAULT_SECRET_KEY_NAMES);
|
|
2804
|
+
function redactUrlSecrets(text, secretSet = DEFAULT_SECRET_SET, placeholder = REDACTED_PLACEHOLDER) {
|
|
2805
|
+
if (text.length > DEFAULT_MAX_TEXT_FIELD_CHARS) return placeholder;
|
|
2806
|
+
if (!text.includes("://") && !text.includes("=")) return text;
|
|
2807
|
+
return text.replace(
|
|
2808
|
+
URL_USERINFO,
|
|
2809
|
+
(whole, scheme, userinfo) => userinfo === void 0 ? whole : `${scheme}://${placeholder}@`
|
|
2810
|
+
).replace(URL_QUERY_PARAM, (whole, prefix, key) => {
|
|
2811
|
+
const normalized = normalizeKeyName(key);
|
|
2812
|
+
return secretSet.has(normalized) || URL_SECRET_QUERY_KEYS.has(normalized) ? `${prefix}${placeholder}` : whole;
|
|
2813
|
+
});
|
|
2814
|
+
}
|
|
1651
2815
|
function redactSecretsInObject(value, options) {
|
|
1652
2816
|
var _a, _b;
|
|
1653
2817
|
const normalizedSecretSet = buildSecretSet((_a = options == null ? void 0 : options.secretKeyNames) != null ? _a : DEFAULT_SECRET_KEY_NAMES);
|
|
1654
2818
|
const placeholder = (_b = options == null ? void 0 : options.placeholder) != null ? _b : REDACTED_PLACEHOLDER;
|
|
1655
2819
|
const seen = /* @__PURE__ */ new WeakSet();
|
|
1656
2820
|
const walk = (node) => {
|
|
2821
|
+
if (typeof node === "string") return redactUrlSecrets(node, normalizedSecretSet, placeholder);
|
|
1657
2822
|
if (node === null || typeof node !== "object") return node;
|
|
1658
2823
|
if (seen.has(node)) return "[CIRCULAR]";
|
|
1659
2824
|
seen.add(node);
|
|
@@ -1752,6 +2917,7 @@ var TraceShipper = class {
|
|
|
1752
2917
|
this.appGitAdded = /* @__PURE__ */ new WeakMap();
|
|
1753
2918
|
this.queue = [];
|
|
1754
2919
|
this.inFlight = /* @__PURE__ */ new Set();
|
|
2920
|
+
this.cutOff = new InFlightCutOff();
|
|
1755
2921
|
this.hasShutdown = false;
|
|
1756
2922
|
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j;
|
|
1757
2923
|
this.appGitContext = (_a = opts.appGitContext) != null ? _a : createAppGitContext(opts.appGit);
|
|
@@ -1764,6 +2930,7 @@ var TraceShipper = class {
|
|
|
1764
2930
|
this.flushIntervalMs = (_d = opts.flushIntervalMs) != null ? _d : 1e3;
|
|
1765
2931
|
this.maxBatchSize = (_e = opts.maxBatchSize) != null ? _e : 50;
|
|
1766
2932
|
this.maxQueueSize = (_f = opts.maxQueueSize) != null ? _f : 5e3;
|
|
2933
|
+
this.flushTimeoutMs = resolveFlushTimeoutMs(opts.flushTimeoutMs);
|
|
1767
2934
|
this.sdkName = (_g = opts.sdkName) != null ? _g : "core";
|
|
1768
2935
|
this.prefix = `[raindrop-ai/${this.sdkName}]`;
|
|
1769
2936
|
this.serviceName = (_h = opts.serviceName) != null ? _h : "raindrop.core";
|
|
@@ -2042,25 +3209,51 @@ var TraceShipper = class {
|
|
|
2042
3209
|
}
|
|
2043
3210
|
this.queue.push(redacted);
|
|
2044
3211
|
if (this.queue.length >= this.maxBatchSize) {
|
|
2045
|
-
void this.
|
|
3212
|
+
void this.drain().catch(() => {
|
|
2046
3213
|
});
|
|
2047
3214
|
return;
|
|
2048
3215
|
}
|
|
2049
|
-
|
|
2050
|
-
|
|
2051
|
-
|
|
2052
|
-
|
|
2053
|
-
|
|
2054
|
-
|
|
2055
|
-
|
|
3216
|
+
this.scheduleDrain(this.flushIntervalMs);
|
|
3217
|
+
}
|
|
3218
|
+
scheduleDrain(delayMs) {
|
|
3219
|
+
if (this.timer) return;
|
|
3220
|
+
this.timer = setTimeout(() => {
|
|
3221
|
+
this.timer = void 0;
|
|
3222
|
+
void this.drain().catch(() => {
|
|
3223
|
+
});
|
|
3224
|
+
}, delayMs);
|
|
2056
3225
|
}
|
|
3226
|
+
/**
|
|
3227
|
+
* Send every queued span within `flushTimeoutMs` (CONTRACT 1.2.1). Resolves,
|
|
3228
|
+
* never rejects, to whether they all reached ingest, and warns when they
|
|
3229
|
+
* didn't. Spans not yet sent at the deadline stay queued.
|
|
3230
|
+
*/
|
|
2057
3231
|
async flush() {
|
|
2058
|
-
|
|
2059
|
-
if (!this.
|
|
2060
|
-
|
|
2061
|
-
|
|
2062
|
-
|
|
3232
|
+
const result = await this.drainWithin(Date.now() + this.flushTimeoutMs);
|
|
3233
|
+
if (!result.delivered && this.shutdownDeadlineAt === void 0) {
|
|
3234
|
+
rateLimitedLog(
|
|
3235
|
+
`${this.prefix}.flush_undelivered`,
|
|
3236
|
+
() => console.warn(`${this.prefix} ${describeUndelivered("flush()", result)}`)
|
|
3237
|
+
);
|
|
2063
3238
|
}
|
|
3239
|
+
return asCompat(result);
|
|
3240
|
+
}
|
|
3241
|
+
async drainWithin(deadlineAt) {
|
|
3242
|
+
const fates = this.enabled ? await this.drain(deadlineAt) : [];
|
|
3243
|
+
const running = [...this.inFlight];
|
|
3244
|
+
const { settled, stillRunning } = await awaitEarlierSends(
|
|
3245
|
+
running,
|
|
3246
|
+
deadlineAt,
|
|
3247
|
+
this.cutOff,
|
|
3248
|
+
(p) => this.inFlight.has(p)
|
|
3249
|
+
);
|
|
3250
|
+
return summarize2(fates, stillRunning, !settled);
|
|
3251
|
+
}
|
|
3252
|
+
/** Send queued batches; with a deadline, a deferred batch goes back on the queue. */
|
|
3253
|
+
async drain(deadlineAt) {
|
|
3254
|
+
var _a;
|
|
3255
|
+
const fates = [];
|
|
3256
|
+
if (!this.enabled) return fates;
|
|
2064
3257
|
if (this.timer) {
|
|
2065
3258
|
clearTimeout(this.timer);
|
|
2066
3259
|
this.timer = void 0;
|
|
@@ -2074,10 +3267,12 @@ var TraceShipper = class {
|
|
|
2074
3267
|
if (spans) spans.push(span);
|
|
2075
3268
|
else groups.set(destination, [span]);
|
|
2076
3269
|
}
|
|
3270
|
+
const requeue = [];
|
|
3271
|
+
let retryAtMs;
|
|
2077
3272
|
for (const [destination, spans] of groups) {
|
|
2078
3273
|
if (!destination && !this.writeKey) continue;
|
|
2079
3274
|
if ((destination == null ? void 0 : destination.kind) === "workshop") continue;
|
|
2080
|
-
const opts = this.requestOpts();
|
|
3275
|
+
const opts = this.requestOpts(deadlineAt);
|
|
2081
3276
|
if (!opts) {
|
|
2082
3277
|
rateLimitedLog(
|
|
2083
3278
|
`${this.prefix}.shutdown_deadline`,
|
|
@@ -2085,6 +3280,7 @@ var TraceShipper = class {
|
|
|
2085
3280
|
`${this.prefix} shutdown flush deadline exceeded; dropping ${spans.length} spans`
|
|
2086
3281
|
)
|
|
2087
3282
|
);
|
|
3283
|
+
fates.push("dropped");
|
|
2088
3284
|
continue;
|
|
2089
3285
|
}
|
|
2090
3286
|
const body = buildExportTraceServiceRequest(spans, this.serviceName, this.serviceVersion);
|
|
@@ -2100,35 +3296,56 @@ var TraceShipper = class {
|
|
|
2100
3296
|
endpoint: url
|
|
2101
3297
|
});
|
|
2102
3298
|
}
|
|
2103
|
-
const
|
|
2104
|
-
|
|
3299
|
+
const sending = sendJson(url, body, headers, opts);
|
|
3300
|
+
const tracked = sending.then(() => void 0);
|
|
3301
|
+
this.inFlight.add(tracked);
|
|
3302
|
+
let outcome;
|
|
2105
3303
|
try {
|
|
2106
|
-
|
|
2107
|
-
await p;
|
|
2108
|
-
if (this.debug) console.log(`${this.prefix} sent ${spans.length} spans`);
|
|
2109
|
-
} catch (err) {
|
|
2110
|
-
const msg = err instanceof Error ? err.message : String(err);
|
|
2111
|
-
rateLimitedLog(
|
|
2112
|
-
`${this.prefix}.send_spans_failed`,
|
|
2113
|
-
() => console.warn(`${this.prefix} failed to send ${spans.length} spans: ${msg}`)
|
|
2114
|
-
);
|
|
2115
|
-
}
|
|
3304
|
+
outcome = await sending;
|
|
2116
3305
|
} finally {
|
|
2117
|
-
this.inFlight.delete(
|
|
3306
|
+
this.inFlight.delete(tracked);
|
|
3307
|
+
}
|
|
3308
|
+
const fate = fateOf(outcome, this.shutdownDeadlineAt !== void 0 || this.hasShutdown);
|
|
3309
|
+
fates.push(fate);
|
|
3310
|
+
if (fate === "queued") {
|
|
3311
|
+
requeue.push(...spans);
|
|
3312
|
+
if (outcome.status === "deferred" && outcome.retryAtMs !== void 0) {
|
|
3313
|
+
retryAtMs = Math.max(retryAtMs != null ? retryAtMs : 0, outcome.retryAtMs);
|
|
3314
|
+
}
|
|
3315
|
+
} else if (fate === "dropped") {
|
|
3316
|
+
const reason = outcome.status === "cut_off" ? "cut off at the flush deadline (not resent: it may have reached ingest)" : outcome.status === "deferred" ? "not sent before the shutdown deadline" : "error" in outcome && outcome.error ? outcome.error.message : outcome.status;
|
|
3317
|
+
rateLimitedLog(
|
|
3318
|
+
`${this.prefix}.send_spans_failed`,
|
|
3319
|
+
() => console.warn(`${this.prefix} failed to send ${spans.length} spans: ${reason}`)
|
|
3320
|
+
);
|
|
3321
|
+
} else if (this.debug) {
|
|
3322
|
+
console.log(`${this.prefix} sent ${spans.length} spans`);
|
|
2118
3323
|
}
|
|
2119
3324
|
}
|
|
3325
|
+
if (requeue.length > 0) {
|
|
3326
|
+
this.queue.unshift(...requeue);
|
|
3327
|
+
if (this.queue.length > this.maxQueueSize) {
|
|
3328
|
+
this.queue.splice(this.maxQueueSize);
|
|
3329
|
+
}
|
|
3330
|
+
this.scheduleDrain(Math.max(this.flushIntervalMs, (retryAtMs != null ? retryAtMs : 0) - Date.now()));
|
|
3331
|
+
break;
|
|
3332
|
+
}
|
|
2120
3333
|
}
|
|
3334
|
+
return fates;
|
|
2121
3335
|
}
|
|
2122
|
-
/** See EventShipper.requestOpts — same
|
|
2123
|
-
requestOpts() {
|
|
3336
|
+
/** See EventShipper.requestOpts — same deadline semantics. */
|
|
3337
|
+
requestOpts(deadlineAt) {
|
|
3338
|
+
const opts = this.scheduleFor(deadlineAt);
|
|
3339
|
+
return opts && { ...opts, cutOff: this.cutOff.signal };
|
|
3340
|
+
}
|
|
3341
|
+
scheduleFor(deadlineAt) {
|
|
2124
3342
|
if (this.shutdownDeadlineAt !== void 0) {
|
|
2125
|
-
|
|
2126
|
-
if (remainingMs <= 0) return null;
|
|
3343
|
+
if (this.shutdownDeadlineAt - Date.now() <= 0) return null;
|
|
2127
3344
|
return {
|
|
2128
|
-
maxAttempts:
|
|
3345
|
+
maxAttempts: 3,
|
|
2129
3346
|
debug: this.debug,
|
|
2130
3347
|
sdkName: this.sdkName,
|
|
2131
|
-
|
|
3348
|
+
deadlineAt: Math.min(this.shutdownDeadlineAt, deadlineAt != null ? deadlineAt : Infinity)
|
|
2132
3349
|
};
|
|
2133
3350
|
}
|
|
2134
3351
|
if (this.hasShutdown) {
|
|
@@ -2139,27 +3356,28 @@ var TraceShipper = class {
|
|
|
2139
3356
|
timeoutMs: POST_SHUTDOWN_TIMEOUT_MS
|
|
2140
3357
|
};
|
|
2141
3358
|
}
|
|
2142
|
-
return { maxAttempts: 3, debug: this.debug, sdkName: this.sdkName };
|
|
3359
|
+
return { maxAttempts: 3, debug: this.debug, sdkName: this.sdkName, deadlineAt };
|
|
2143
3360
|
}
|
|
3361
|
+
/**
|
|
3362
|
+
* Flush within `flushTimeoutMs` and stop; spans left at the deadline are
|
|
3363
|
+
* dropped with a warning. Resolves, never rejects.
|
|
3364
|
+
*/
|
|
2144
3365
|
async shutdown() {
|
|
2145
3366
|
this.hasShutdown = true;
|
|
2146
|
-
|
|
3367
|
+
const deadlineAt = Date.now() + this.flushTimeoutMs;
|
|
3368
|
+
this.shutdownDeadlineAt = deadlineAt;
|
|
3369
|
+
let result = { ...DELIVERED };
|
|
2147
3370
|
try {
|
|
2148
3371
|
if (this.timer) {
|
|
2149
3372
|
clearTimeout(this.timer);
|
|
2150
3373
|
this.timer = void 0;
|
|
2151
3374
|
}
|
|
2152
|
-
|
|
2153
|
-
|
|
2154
|
-
await Promise.all([...this.inFlight].map((p) => p.catch(() => {
|
|
2155
|
-
})));
|
|
2156
|
-
};
|
|
2157
|
-
const settled = await raceWithTimeout(drain(), SHUTDOWN_DEADLINE_MS);
|
|
2158
|
-
if (!settled) {
|
|
3375
|
+
result = await this.drainWithin(deadlineAt);
|
|
3376
|
+
if (!result.delivered) {
|
|
2159
3377
|
rateLimitedLog(
|
|
2160
3378
|
`${this.prefix}.shutdown_deadline`,
|
|
2161
3379
|
() => console.warn(
|
|
2162
|
-
`${this.prefix} shutdown flush deadline exceeded;
|
|
3380
|
+
`${this.prefix} shutdown flush deadline exceeded; ${describeUndelivered("shutdown()", result)}`
|
|
2163
3381
|
)
|
|
2164
3382
|
);
|
|
2165
3383
|
}
|
|
@@ -2167,10 +3385,74 @@ var TraceShipper = class {
|
|
|
2167
3385
|
this.shutdownDeadlineAt = void 0;
|
|
2168
3386
|
if (this.ownsAppGitContext) this.appGitContext.dispose();
|
|
2169
3387
|
}
|
|
3388
|
+
return asCompat(result);
|
|
2170
3389
|
}
|
|
2171
3390
|
};
|
|
3391
|
+
function eventShipperOptions(client, extras = {}) {
|
|
3392
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _i;
|
|
3393
|
+
return {
|
|
3394
|
+
...extras,
|
|
3395
|
+
writeKey: (_a = extras.writeKey) != null ? _a : client.writeKey,
|
|
3396
|
+
endpoint: (_b = extras.endpoint) != null ? _b : client.endpoint,
|
|
3397
|
+
projectId: (_c = extras.projectId) != null ? _c : client.projectId,
|
|
3398
|
+
debug: (_e = (_d = extras.debug) != null ? _d : client.debug) != null ? _e : false,
|
|
3399
|
+
maxTextFieldChars: (_f = extras.maxTextFieldChars) != null ? _f : client.maxTextFieldChars,
|
|
3400
|
+
flushTimeoutMs: (_g = extras.flushTimeoutMs) != null ? _g : client.flushTimeoutMs,
|
|
3401
|
+
redactPii: (_h = extras.redactPii) != null ? _h : client.redactPii,
|
|
3402
|
+
redactPiiFields: (_i = extras.redactPiiFields) != null ? _i : client.redactPiiFields
|
|
3403
|
+
};
|
|
3404
|
+
}
|
|
3405
|
+
function traceShipperOptions(client, extras = {}) {
|
|
3406
|
+
var _a, _b, _c, _d, _e, _f, _g;
|
|
3407
|
+
return {
|
|
3408
|
+
...extras,
|
|
3409
|
+
writeKey: (_a = extras.writeKey) != null ? _a : client.writeKey,
|
|
3410
|
+
endpoint: (_b = extras.endpoint) != null ? _b : client.endpoint,
|
|
3411
|
+
projectId: (_c = extras.projectId) != null ? _c : client.projectId,
|
|
3412
|
+
debug: (_e = (_d = extras.debug) != null ? _d : client.debug) != null ? _e : false,
|
|
3413
|
+
maxTextFieldChars: (_f = extras.maxTextFieldChars) != null ? _f : client.maxTextFieldChars,
|
|
3414
|
+
flushTimeoutMs: (_g = extras.flushTimeoutMs) != null ? _g : client.flushTimeoutMs
|
|
3415
|
+
};
|
|
3416
|
+
}
|
|
3417
|
+
function createShippers(client, setup = {}) {
|
|
3418
|
+
return {
|
|
3419
|
+
eventShipper: new EventShipper(eventShipperOptions(client, { ...setup.common, ...setup.event })),
|
|
3420
|
+
traceShipper: new TraceShipper(traceShipperOptions(client, { ...setup.common, ...setup.trace }))
|
|
3421
|
+
};
|
|
3422
|
+
}
|
|
3423
|
+
function isFlushResult(value) {
|
|
3424
|
+
return typeof value === "object" && value !== null && "delivered" in value && typeof value.delivered === "boolean" && "dropped" in value && typeof value.dropped === "number" && "queued" in value && typeof value.queued === "number" && "inFlight" in value && typeof value.inFlight === "number" && "timedOut" in value && typeof value.timedOut === "boolean";
|
|
3425
|
+
}
|
|
3426
|
+
var UNDELIVERED = Object.freeze({
|
|
3427
|
+
delivered: false,
|
|
3428
|
+
timedOut: false,
|
|
3429
|
+
dropped: 0,
|
|
3430
|
+
queued: 0,
|
|
3431
|
+
inFlight: 0
|
|
3432
|
+
});
|
|
3433
|
+
async function settle(call, what) {
|
|
3434
|
+
try {
|
|
3435
|
+
const result = await call();
|
|
3436
|
+
return isFlushResult(result) ? result : DELIVERED;
|
|
3437
|
+
} catch (error) {
|
|
3438
|
+
console.warn(`[raindrop-ai] ${what} failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
3439
|
+
return UNDELIVERED;
|
|
3440
|
+
}
|
|
3441
|
+
}
|
|
3442
|
+
async function flushShippers(...shippers) {
|
|
3443
|
+
const results = await Promise.all(
|
|
3444
|
+
shippers.flatMap((s) => s ? [settle(() => s.flush(), "flush()")] : [])
|
|
3445
|
+
);
|
|
3446
|
+
return asCompat(combineResults(...results));
|
|
3447
|
+
}
|
|
3448
|
+
async function shutdownShippers(...shippers) {
|
|
3449
|
+
const results = await Promise.all(
|
|
3450
|
+
shippers.flatMap((s) => s ? [settle(() => s.shutdown(), "shutdown()")] : [])
|
|
3451
|
+
);
|
|
3452
|
+
return asCompat(combineResults(...results));
|
|
3453
|
+
}
|
|
2172
3454
|
var PROMPT_TOOLS_ATTRIBUTE = "ai.prompt.tools";
|
|
2173
|
-
function
|
|
3455
|
+
function isRecord3(value) {
|
|
2174
3456
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
2175
3457
|
}
|
|
2176
3458
|
var JSON_SCHEMA_KEYS = [
|
|
@@ -2188,17 +3470,17 @@ var JSON_SCHEMA_KEYS = [
|
|
|
2188
3470
|
"required"
|
|
2189
3471
|
];
|
|
2190
3472
|
function isJsonSchema(value) {
|
|
2191
|
-
if (!
|
|
3473
|
+
if (!isRecord3(value)) return false;
|
|
2192
3474
|
if (typeof value["~standard"] === "object") return false;
|
|
2193
|
-
if (
|
|
3475
|
+
if (isRecord3(value._def) || isRecord3(value._zod)) return false;
|
|
2194
3476
|
if (Object.keys(value).length === 0) return true;
|
|
2195
3477
|
return JSON_SCHEMA_KEYS.some((key) => key in value);
|
|
2196
3478
|
}
|
|
2197
3479
|
function toJsonSchema(value, options) {
|
|
2198
3480
|
if (value === void 0 || value === null) return void 0;
|
|
2199
3481
|
if (isJsonSchema(value)) return value;
|
|
2200
|
-
if (
|
|
2201
|
-
if (
|
|
3482
|
+
if (isRecord3(value) && isJsonSchema(value.jsonSchema)) return value.jsonSchema;
|
|
3483
|
+
if (isRecord3(value) && isJsonSchema(value.json)) return value.json;
|
|
2202
3484
|
if (options == null ? void 0 : options.schema) {
|
|
2203
3485
|
try {
|
|
2204
3486
|
return options.schema(value);
|
|
@@ -2221,23 +3503,23 @@ function functionTool(name, description, schema, options) {
|
|
|
2221
3503
|
}
|
|
2222
3504
|
function normalizeToolDeclaration(tool, options, fallbackName) {
|
|
2223
3505
|
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j;
|
|
2224
|
-
if (!
|
|
3506
|
+
if (!isRecord3(tool)) return void 0;
|
|
2225
3507
|
if (tool.type === "provider-defined" || tool.type === "provider") {
|
|
2226
3508
|
const name2 = (_b = (_a = pickString(tool.name)) != null ? _a : pickString(tool.id)) != null ? _b : fallbackName;
|
|
2227
3509
|
if (name2 === void 0) return void 0;
|
|
2228
3510
|
const declaration = { type: "provider-defined", name: name2 };
|
|
2229
3511
|
const id = pickString(tool.id);
|
|
2230
3512
|
if (id !== void 0) declaration.id = id;
|
|
2231
|
-
if (
|
|
3513
|
+
if (isRecord3(tool.args)) declaration.args = tool.args;
|
|
2232
3514
|
return declaration;
|
|
2233
3515
|
}
|
|
2234
|
-
if (
|
|
3516
|
+
if (isRecord3(tool.toolSpec)) {
|
|
2235
3517
|
const spec = tool.toolSpec;
|
|
2236
3518
|
const name2 = (_c = pickString(spec.name)) != null ? _c : fallbackName;
|
|
2237
3519
|
if (name2 === void 0) return void 0;
|
|
2238
3520
|
return functionTool(name2, spec.description, spec.inputSchema, options);
|
|
2239
3521
|
}
|
|
2240
|
-
if (
|
|
3522
|
+
if (isRecord3(tool.function)) {
|
|
2241
3523
|
const fn = tool.function;
|
|
2242
3524
|
const name2 = (_d = pickString(fn.name)) != null ? _d : fallbackName;
|
|
2243
3525
|
if (name2 === void 0) return void 0;
|
|
@@ -2263,7 +3545,7 @@ function isGeminiToolGroup(tool) {
|
|
|
2263
3545
|
if (Array.isArray(tool.functionDeclarations)) return true;
|
|
2264
3546
|
const keys = Object.keys(tool);
|
|
2265
3547
|
if (keys.length === 0 || NOT_A_GEMINI_GROUP_KEYS.some((key) => key in tool)) return false;
|
|
2266
|
-
return keys.every((key) =>
|
|
3548
|
+
return keys.every((key) => isRecord3(tool[key]));
|
|
2267
3549
|
}
|
|
2268
3550
|
function expandGeminiTool(tool, options) {
|
|
2269
3551
|
const declarations = [];
|
|
@@ -2273,7 +3555,7 @@ function expandGeminiTool(tool, options) {
|
|
|
2273
3555
|
const normalized = normalizeToolDeclaration(declaration, options);
|
|
2274
3556
|
if (normalized) declarations.push(normalized);
|
|
2275
3557
|
}
|
|
2276
|
-
} else if (
|
|
3558
|
+
} else if (isRecord3(value)) {
|
|
2277
3559
|
declarations.push({ type: "provider-defined", id: key, name: key, args: value });
|
|
2278
3560
|
}
|
|
2279
3561
|
}
|
|
@@ -2283,14 +3565,14 @@ function normalizeToolDeclarations(tools, options) {
|
|
|
2283
3565
|
if (tools === void 0 || tools === null) return void 0;
|
|
2284
3566
|
if (Array.isArray(tools)) {
|
|
2285
3567
|
return tools.flatMap((tool) => {
|
|
2286
|
-
if (
|
|
3568
|
+
if (isRecord3(tool) && isGeminiToolGroup(tool)) {
|
|
2287
3569
|
return expandGeminiTool(tool, options);
|
|
2288
3570
|
}
|
|
2289
3571
|
const declaration = normalizeToolDeclaration(tool, options);
|
|
2290
3572
|
return declaration ? [declaration] : [];
|
|
2291
3573
|
});
|
|
2292
3574
|
}
|
|
2293
|
-
if (!
|
|
3575
|
+
if (!isRecord3(tools)) return void 0;
|
|
2294
3576
|
return Object.entries(tools).flatMap(([key, tool]) => {
|
|
2295
3577
|
const declaration = normalizeToolDeclaration(tool, options, key);
|
|
2296
3578
|
return declaration ? [declaration] : [];
|
|
@@ -2436,39 +3718,6 @@ var resolveLocal = (sourceDirectory, detectBranch, completed) => {
|
|
|
2436
3718
|
function createAppGitContext2(options, runtime = {}) {
|
|
2437
3719
|
return new AppGitContext(options, { ...runtime, resolveLocal });
|
|
2438
3720
|
}
|
|
2439
|
-
function hasDestination(options) {
|
|
2440
|
-
var _a;
|
|
2441
|
-
if (options.enabled === false) return false;
|
|
2442
|
-
return Boolean(((_a = options.writeKey) == null ? void 0 : _a.trim()) || resolveLocalDebuggerBaseUrl(options.localDebuggerUrl));
|
|
2443
|
-
}
|
|
2444
|
-
var EventShipper2 = class extends EventShipper {
|
|
2445
|
-
constructor(options) {
|
|
2446
|
-
var _a;
|
|
2447
|
-
const ownsAppGitContext = options.appGitContext === void 0;
|
|
2448
|
-
const appGitContext = (_a = options.appGitContext) != null ? _a : createAppGitContext2(options.appGit, { allowDiscovery: hasDestination(options) });
|
|
2449
|
-
try {
|
|
2450
|
-
super({ ...options, appGitContext });
|
|
2451
|
-
} catch (error) {
|
|
2452
|
-
if (ownsAppGitContext) appGitContext.dispose();
|
|
2453
|
-
throw error;
|
|
2454
|
-
}
|
|
2455
|
-
if (ownsAppGitContext) this.ownAppGitContextForShutdown();
|
|
2456
|
-
}
|
|
2457
|
-
};
|
|
2458
|
-
var TraceShipper2 = class extends TraceShipper {
|
|
2459
|
-
constructor(options) {
|
|
2460
|
-
var _a;
|
|
2461
|
-
const ownsAppGitContext = options.appGitContext === void 0;
|
|
2462
|
-
const appGitContext = (_a = options.appGitContext) != null ? _a : createAppGitContext2(options.appGit, { allowDiscovery: hasDestination(options) });
|
|
2463
|
-
try {
|
|
2464
|
-
super({ ...options, appGitContext });
|
|
2465
|
-
} catch (error) {
|
|
2466
|
-
if (ownsAppGitContext) appGitContext.dispose();
|
|
2467
|
-
throw error;
|
|
2468
|
-
}
|
|
2469
|
-
this.ownsAppGitContext = ownsAppGitContext;
|
|
2470
|
-
}
|
|
2471
|
-
};
|
|
2472
3721
|
globalThis.RAINDROP_ASYNC_LOCAL_STORAGE = import_async_hooks.AsyncLocalStorage;
|
|
2473
3722
|
var SUPPRESS_TRACING_KEY = /* @__PURE__ */ Symbol.for(
|
|
2474
3723
|
"OpenTelemetry SDK Context Key SUPPRESS_TRACING"
|
|
@@ -2606,6 +3855,8 @@ var RaindropManagedAgentsHandler = class {
|
|
|
2606
3855
|
eventName: (_e = context.eventName) != null ? _e : "ai_generation",
|
|
2607
3856
|
input: void 0,
|
|
2608
3857
|
model: void 0,
|
|
3858
|
+
// Caller-supplied properties win over the derived keys below (W6).
|
|
3859
|
+
callerProperties: context.properties,
|
|
2609
3860
|
properties: {
|
|
2610
3861
|
...context.properties,
|
|
2611
3862
|
"ai.provider": "openai",
|
|
@@ -2926,7 +4177,7 @@ function isRecord2(value) {
|
|
|
2926
4177
|
// package.json
|
|
2927
4178
|
var package_default = {
|
|
2928
4179
|
name: "@raindrop-ai/openai-managed-agents",
|
|
2929
|
-
version: "0.0.
|
|
4180
|
+
version: "0.0.5",
|
|
2930
4181
|
description: "Raindrop tracing for the OpenAI Agents API",
|
|
2931
4182
|
main: "dist/index.js",
|
|
2932
4183
|
module: "dist/index.mjs",
|
|
@@ -2968,11 +4219,11 @@ var package_default = {
|
|
|
2968
4219
|
"@raindrop-ai/core": "workspace:*",
|
|
2969
4220
|
"@types/node": "^20.11.17",
|
|
2970
4221
|
msw: "^2.12.7",
|
|
2971
|
-
tsup: "^
|
|
4222
|
+
tsup: "^9.0.0",
|
|
2972
4223
|
typescript: "^5.3.3",
|
|
2973
|
-
vitest: "^
|
|
4224
|
+
vitest: "^4.1.12",
|
|
2974
4225
|
openai: "7.15.0",
|
|
2975
|
-
zod: "^
|
|
4226
|
+
zod: "^4.6.6"
|
|
2976
4227
|
},
|
|
2977
4228
|
tsup: {
|
|
2978
4229
|
entry: [
|
|
@@ -3094,7 +4345,7 @@ function wrapManagedAgents(client, handler, context) {
|
|
|
3094
4345
|
|
|
3095
4346
|
// src/index.ts
|
|
3096
4347
|
function createRaindropOpenAIManagedAgents(opts = {}) {
|
|
3097
|
-
var _a
|
|
4348
|
+
var _a;
|
|
3098
4349
|
const enabled = Boolean((_a = opts.writeKey) == null ? void 0 : _a.trim());
|
|
3099
4350
|
if (!enabled)
|
|
3100
4351
|
console.warn(
|
|
@@ -3103,44 +4354,33 @@ function createRaindropOpenAIManagedAgents(opts = {}) {
|
|
|
3103
4354
|
const appGitContext = createAppGitContext2(enabled ? opts.appGit : false, {
|
|
3104
4355
|
allowLocalGit: false
|
|
3105
4356
|
});
|
|
3106
|
-
const
|
|
3107
|
-
|
|
3108
|
-
|
|
3109
|
-
|
|
3110
|
-
|
|
3111
|
-
|
|
3112
|
-
|
|
3113
|
-
libraryName,
|
|
3114
|
-
libraryVersion
|
|
3115
|
-
appGitContext,
|
|
3116
|
-
maxTextFieldChars: opts.maxTextFieldChars,
|
|
3117
|
-
localDebuggerUrl: opts.localWorkshopUrl === false ? null : opts.localWorkshopUrl
|
|
3118
|
-
};
|
|
3119
|
-
const events = new EventShipper2(shipperOptions);
|
|
3120
|
-
const traces = new TraceShipper2({
|
|
3121
|
-
...shipperOptions,
|
|
3122
|
-
serviceName: "raindrop.openai-managed-agents",
|
|
3123
|
-
serviceVersion: libraryVersion
|
|
4357
|
+
const { eventShipper: events, traceShipper: traces } = createShippers(opts, {
|
|
4358
|
+
common: {
|
|
4359
|
+
enabled,
|
|
4360
|
+
sdkName: "openai-managed-agents",
|
|
4361
|
+
appGitContext,
|
|
4362
|
+
localDebuggerUrl: opts.localWorkshopUrl === false ? null : opts.localWorkshopUrl
|
|
4363
|
+
},
|
|
4364
|
+
event: { libraryName, libraryVersion },
|
|
4365
|
+
trace: { serviceName: "raindrop.openai-managed-agents", serviceVersion: libraryVersion }
|
|
3124
4366
|
});
|
|
3125
4367
|
const handler = new RaindropManagedAgentsHandler(events, traces, opts);
|
|
3126
4368
|
return {
|
|
3127
4369
|
handler,
|
|
3128
4370
|
wrap: (client, context) => wrapManagedAgents(client, handler, context),
|
|
3129
|
-
|
|
3130
|
-
|
|
3131
|
-
finish: (id, patch) => events.finish(id, patch),
|
|
3132
|
-
addAttachments: (id, attachments) => events.patch(id, { attachments }),
|
|
3133
|
-
setProperties: (id, properties) => events.patch(id, { properties })
|
|
4371
|
+
get lastEventId() {
|
|
4372
|
+
return events == null ? void 0 : events.lastFinishedEventId;
|
|
3134
4373
|
},
|
|
4374
|
+
events: createEventsApi(events),
|
|
3135
4375
|
users: { identify: (users) => events.identify(users) },
|
|
3136
4376
|
signals: { track: (signal) => events.trackSignal(signal) },
|
|
3137
|
-
|
|
3138
|
-
|
|
4377
|
+
flush() {
|
|
4378
|
+
return flushShippers(events, traces);
|
|
3139
4379
|
},
|
|
3140
4380
|
async shutdown() {
|
|
3141
4381
|
try {
|
|
3142
4382
|
handler.shutdown();
|
|
3143
|
-
await
|
|
4383
|
+
return await shutdownShippers(events, traces);
|
|
3144
4384
|
} finally {
|
|
3145
4385
|
appGitContext.dispose();
|
|
3146
4386
|
}
|