@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.mjs
CHANGED
|
@@ -1,4 +1,33 @@
|
|
|
1
|
-
// ../core/dist/chunk-
|
|
1
|
+
// ../core/dist/chunk-ZCB62SIO.js
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __commonJS = (cb, mod) => function __require() {
|
|
9
|
+
try {
|
|
10
|
+
return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
|
|
11
|
+
} catch (e) {
|
|
12
|
+
throw mod = 0, e;
|
|
13
|
+
}
|
|
14
|
+
};
|
|
15
|
+
var __copyProps = (to, from, except, desc) => {
|
|
16
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
17
|
+
for (let key of __getOwnPropNames(from))
|
|
18
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
19
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
20
|
+
}
|
|
21
|
+
return to;
|
|
22
|
+
};
|
|
23
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
24
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
25
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
26
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
27
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
28
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
29
|
+
mod
|
|
30
|
+
));
|
|
2
31
|
var EVAL_CORRELATION_ID_ATTRIBUTE = "raindrop.eval_correlation_id";
|
|
3
32
|
var PROBE_SCOPE = { correlationId: "" };
|
|
4
33
|
var EvalScopeStorage = class {
|
|
@@ -60,21 +89,246 @@ function evalScopeAttributes() {
|
|
|
60
89
|
return { [EVAL_CORRELATION_ID_ATTRIBUTE]: scope.correlationId };
|
|
61
90
|
}
|
|
62
91
|
|
|
63
|
-
// ../core/dist/chunk-
|
|
92
|
+
// ../core/dist/chunk-AX36JKJL.js
|
|
93
|
+
var require_NameRedactor = __commonJS({
|
|
94
|
+
"../redact-pii/dist/built-ins/NameRedactor.js"(exports) {
|
|
95
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
96
|
+
exports.NameRedactor = void 0;
|
|
97
|
+
var greetingRegex = /(^|\.\s+)(dear|hi|hello|greetings|hey|hey there)/gi;
|
|
98
|
+
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;
|
|
99
|
+
var greetingOrClosing = new RegExp("(((" + greetingRegex.source + ")|(" + closingRegex.source + "\\s*[,.!]*))[\\s-]*)", "gi");
|
|
100
|
+
var genericName = new RegExp("( ?(([A-Z][a-z]{1,30})|([A-Z]\\.))){1,10}([,.]|[,.]?$)", "my");
|
|
101
|
+
var NameRedactor = class {
|
|
102
|
+
constructor(replaceWith = "PERSON_NAME") {
|
|
103
|
+
this.replaceWith = replaceWith;
|
|
104
|
+
}
|
|
105
|
+
redact(textToRedact) {
|
|
106
|
+
var _a;
|
|
107
|
+
greetingOrClosing.lastIndex = 0;
|
|
108
|
+
genericName.lastIndex = 0;
|
|
109
|
+
const pieces = [];
|
|
110
|
+
let copiedThrough = 0;
|
|
111
|
+
let changed = false;
|
|
112
|
+
let greetingOrClosingMatch = greetingOrClosing.exec(textToRedact);
|
|
113
|
+
while (greetingOrClosingMatch !== null) {
|
|
114
|
+
genericName.lastIndex = greetingOrClosing.lastIndex;
|
|
115
|
+
const genericNameMatch = genericName.exec(textToRedact);
|
|
116
|
+
if (genericNameMatch !== null && genericNameMatch.index === greetingOrClosing.lastIndex) {
|
|
117
|
+
const suffix = (_a = genericNameMatch[5]) !== null && _a !== void 0 ? _a : "";
|
|
118
|
+
const end = genericNameMatch.index + genericNameMatch[0].length;
|
|
119
|
+
pieces.push(textToRedact.slice(copiedThrough, genericNameMatch.index), this.replaceWith, suffix);
|
|
120
|
+
copiedThrough = end;
|
|
121
|
+
changed = true;
|
|
122
|
+
greetingOrClosing.lastIndex = end - suffix.length;
|
|
123
|
+
}
|
|
124
|
+
greetingOrClosingMatch = greetingOrClosing.exec(textToRedact);
|
|
125
|
+
}
|
|
126
|
+
if (!changed)
|
|
127
|
+
return textToRedact;
|
|
128
|
+
pieces.push(textToRedact.slice(copiedThrough));
|
|
129
|
+
return pieces.join("");
|
|
130
|
+
}
|
|
131
|
+
};
|
|
132
|
+
exports.NameRedactor = NameRedactor;
|
|
133
|
+
}
|
|
134
|
+
});
|
|
135
|
+
var require_simple_regexp_patterns = __commonJS({
|
|
136
|
+
"../redact-pii/dist/built-ins/simple-regexp-patterns.js"(exports) {
|
|
137
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
138
|
+
exports.url = exports.digits = exports.credentials = exports.password = exports.username = exports.emailAddress = exports.usSocialSecurityNumber = exports.ipAddress = exports.phoneNumber = exports.zipcode = exports.streetAddress = exports.creditCardNumber = void 0;
|
|
139
|
+
var aptRegex = /(apt|bldg|dept|fl|hngr|lot|pier|rm|ste|slip|trlr|unit|#)\.? *[a-z0-9-]+\b/gi;
|
|
140
|
+
var poBoxRegex = /P\.? ?O\.? *Box +\d+/gi;
|
|
141
|
+
var roadRegex = /(street|st|road|rd|avenue|ave|drive|dr|loop|court|ct|circle|cir|lane|ln|boulevard|blvd|way)\.?\b/gi;
|
|
142
|
+
exports.creditCardNumber = /\d{4}[ -]?\d{4}[ -]?\d{4}[ -]?\d{4}|\d{4}[ -]?\d{6}[ -]?\d{4}\d?/g;
|
|
143
|
+
exports.streetAddress = new RegExp("(\\d{1,10}\\s*(\\w{1,30} ){1,2}" + roadRegex.source + "(\\s+" + aptRegex.source + ")?)|(" + poBoxRegex.source + ")", "gi");
|
|
144
|
+
exports.zipcode = /\b\d{5}\b(-\d{4})?\b/g;
|
|
145
|
+
exports.phoneNumber = /(\(?\+?[0-9]{1,2}\)?[-. ]?)?(\(?[0-9]{3}\)?|[0-9]{3})[-. ]?([0-9]{3}[-. ]?[0-9]{4}|\b[A-Z0-9]{7}\b)/g;
|
|
146
|
+
exports.ipAddress = /(\d{1,3}(\.\d{1,3}){3}|[0-9A-F]{4}(:[0-9A-F]{4}){5}(::|(:0000)+))/gi;
|
|
147
|
+
exports.usSocialSecurityNumber = /\b\d{3}[ -.]\d{2}[ -.]\d{4}\b/g;
|
|
148
|
+
exports.emailAddress = /([a-z0-9_\-.+]{1,64})@\w+(\.\w+)*/gi;
|
|
149
|
+
exports.username = /(user( ?name)?|login): \S+/gi;
|
|
150
|
+
exports.password = /(pass(word|phrase)?|secret): \S+/gi;
|
|
151
|
+
exports.credentials = /(login( cred(ential)?s| info(rmation)?)?|cred(ential)?s) ?:\s*\S+\s+\/?\s*\S+/gi;
|
|
152
|
+
exports.digits = /\b\d{4,}\b/g;
|
|
153
|
+
exports.url = /([^\s:/?#]{1,64}):\/\/([^/?#\s]*)([^?#\s]*)(\?([^#\s]*))?(#([^\s]*))?/g;
|
|
154
|
+
}
|
|
155
|
+
});
|
|
156
|
+
var require_utils = __commonJS({
|
|
157
|
+
"../redact-pii/dist/utils.js"(exports) {
|
|
158
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
159
|
+
exports.snakeCase = exports.isSyncRedactor = exports.isSimpleRegexpCustomRedactorConfig = void 0;
|
|
160
|
+
function isSimpleRegexpCustomRedactorConfig(redactor2) {
|
|
161
|
+
return typeof redactor2.regexpPattern !== "undefined";
|
|
162
|
+
}
|
|
163
|
+
exports.isSimpleRegexpCustomRedactorConfig = isSimpleRegexpCustomRedactorConfig;
|
|
164
|
+
function isSyncRedactor(redactor2) {
|
|
165
|
+
return typeof redactor2.redact === "function";
|
|
166
|
+
}
|
|
167
|
+
exports.isSyncRedactor = isSyncRedactor;
|
|
168
|
+
function snakeCase(input = "") {
|
|
169
|
+
var _a;
|
|
170
|
+
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 : [];
|
|
171
|
+
return words.map((word) => word.toLowerCase()).join("_");
|
|
172
|
+
}
|
|
173
|
+
exports.snakeCase = snakeCase;
|
|
174
|
+
}
|
|
175
|
+
});
|
|
176
|
+
var require_SimpleRegexpRedactor = __commonJS({
|
|
177
|
+
"../redact-pii/dist/built-ins/SimpleRegexpRedactor.js"(exports) {
|
|
178
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
179
|
+
exports.SimpleRegexpRedactor = void 0;
|
|
180
|
+
var utils_1 = require_utils();
|
|
181
|
+
var SimpleRegexpRedactor = class {
|
|
182
|
+
constructor({ replaceWith = (0, utils_1.snakeCase)().toUpperCase(), regexpPattern: regexpMatcher }) {
|
|
183
|
+
this.replaceWith = replaceWith;
|
|
184
|
+
this.regexpMatcher = regexpMatcher;
|
|
185
|
+
}
|
|
186
|
+
redact(textToRedact) {
|
|
187
|
+
return textToRedact.replace(this.regexpMatcher, this.replaceWith);
|
|
188
|
+
}
|
|
189
|
+
};
|
|
190
|
+
exports.SimpleRegexpRedactor = SimpleRegexpRedactor;
|
|
191
|
+
}
|
|
192
|
+
});
|
|
193
|
+
var require_composition = __commonJS({
|
|
194
|
+
"../redact-pii/dist/composition.js"(exports) {
|
|
195
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
196
|
+
exports.composeChildRedactors = void 0;
|
|
197
|
+
var NameRedactor_1 = require_NameRedactor();
|
|
198
|
+
var simpleRegexpBuiltIns = require_simple_regexp_patterns();
|
|
199
|
+
var SimpleRegexpRedactor_1 = require_SimpleRegexpRedactor();
|
|
200
|
+
var utils_1 = require_utils();
|
|
201
|
+
function normalizeCustomRedactorConfig(redactorConfig) {
|
|
202
|
+
return (0, utils_1.isSimpleRegexpCustomRedactorConfig)(redactorConfig) ? new SimpleRegexpRedactor_1.SimpleRegexpRedactor({
|
|
203
|
+
regexpPattern: redactorConfig.regexpPattern,
|
|
204
|
+
replaceWith: redactorConfig.replaceWith
|
|
205
|
+
}) : redactorConfig;
|
|
206
|
+
}
|
|
207
|
+
function composeChildRedactors(opts = {}) {
|
|
208
|
+
var _a, _b, _c, _d;
|
|
209
|
+
const childRedactors = [];
|
|
210
|
+
if (opts.customRedactors && opts.customRedactors.before) {
|
|
211
|
+
opts.customRedactors.before.map(normalizeCustomRedactorConfig).forEach((redactor2) => childRedactors.push(redactor2));
|
|
212
|
+
}
|
|
213
|
+
for (const regexpName of Object.keys(simpleRegexpBuiltIns)) {
|
|
214
|
+
if (!opts.builtInRedactors || !opts.builtInRedactors[regexpName] || opts.builtInRedactors[regexpName].enabled !== false) {
|
|
215
|
+
childRedactors.push(new SimpleRegexpRedactor_1.SimpleRegexpRedactor({
|
|
216
|
+
regexpPattern: simpleRegexpBuiltIns[regexpName],
|
|
217
|
+
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()
|
|
218
|
+
}));
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
if (!opts.builtInRedactors || !opts.builtInRedactors.names || opts.builtInRedactors.names.enabled !== false) {
|
|
222
|
+
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));
|
|
223
|
+
}
|
|
224
|
+
if (opts.customRedactors && opts.customRedactors.after) {
|
|
225
|
+
opts.customRedactors.after.map(normalizeCustomRedactorConfig).forEach((redactor2) => childRedactors.push(redactor2));
|
|
226
|
+
}
|
|
227
|
+
return childRedactors;
|
|
228
|
+
}
|
|
229
|
+
exports.composeChildRedactors = composeChildRedactors;
|
|
230
|
+
}
|
|
231
|
+
});
|
|
232
|
+
var require_AsyncCompositeRedactor = __commonJS({
|
|
233
|
+
"../redact-pii/dist/AsyncCompositeRedactor.js"(exports) {
|
|
234
|
+
var __awaiter = exports && exports.__awaiter || function(thisArg, _arguments, P, generator) {
|
|
235
|
+
function adopt(value) {
|
|
236
|
+
return value instanceof P ? value : new P(function(resolve2) {
|
|
237
|
+
resolve2(value);
|
|
238
|
+
});
|
|
239
|
+
}
|
|
240
|
+
return new (P || (P = Promise))(function(resolve2, reject) {
|
|
241
|
+
function fulfilled(value) {
|
|
242
|
+
try {
|
|
243
|
+
step(generator.next(value));
|
|
244
|
+
} catch (e) {
|
|
245
|
+
reject(e);
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
function rejected(value) {
|
|
249
|
+
try {
|
|
250
|
+
step(generator["throw"](value));
|
|
251
|
+
} catch (e) {
|
|
252
|
+
reject(e);
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
function step(result) {
|
|
256
|
+
result.done ? resolve2(result.value) : adopt(result.value).then(fulfilled, rejected);
|
|
257
|
+
}
|
|
258
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
259
|
+
});
|
|
260
|
+
};
|
|
261
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
262
|
+
exports.AsyncCompositeRedactor = void 0;
|
|
263
|
+
var composition_1 = require_composition();
|
|
264
|
+
var utils_1 = require_utils();
|
|
265
|
+
var AsyncCompositeRedactor = class {
|
|
266
|
+
constructor(opts) {
|
|
267
|
+
this.childRedactors = [];
|
|
268
|
+
this.redactAsync = (textToRedact) => __awaiter(this, void 0, void 0, function* () {
|
|
269
|
+
for (const redactor2 of this.childRedactors) {
|
|
270
|
+
if ((0, utils_1.isSyncRedactor)(redactor2)) {
|
|
271
|
+
textToRedact = redactor2.redact(textToRedact);
|
|
272
|
+
} else {
|
|
273
|
+
textToRedact = yield redactor2.redactAsync(textToRedact);
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
return textToRedact;
|
|
277
|
+
});
|
|
278
|
+
this.childRedactors = (0, composition_1.composeChildRedactors)(opts);
|
|
279
|
+
}
|
|
280
|
+
};
|
|
281
|
+
exports.AsyncCompositeRedactor = AsyncCompositeRedactor;
|
|
282
|
+
}
|
|
283
|
+
});
|
|
284
|
+
var require_SyncCompositeRedactor = __commonJS({
|
|
285
|
+
"../redact-pii/dist/SyncCompositeRedactor.js"(exports) {
|
|
286
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
287
|
+
exports.SyncCompositeRedactor = void 0;
|
|
288
|
+
var composition_1 = require_composition();
|
|
289
|
+
var SyncCompositeRedactor = class {
|
|
290
|
+
constructor(opts) {
|
|
291
|
+
this.childRedactors = [];
|
|
292
|
+
this.redact = (textToRedact) => {
|
|
293
|
+
for (const redactor2 of this.childRedactors) {
|
|
294
|
+
textToRedact = redactor2.redact(textToRedact);
|
|
295
|
+
}
|
|
296
|
+
return textToRedact;
|
|
297
|
+
};
|
|
298
|
+
this.childRedactors = (0, composition_1.composeChildRedactors)(opts);
|
|
299
|
+
}
|
|
300
|
+
};
|
|
301
|
+
exports.SyncCompositeRedactor = SyncCompositeRedactor;
|
|
302
|
+
}
|
|
303
|
+
});
|
|
304
|
+
var require_dist = __commonJS({
|
|
305
|
+
"../redact-pii/dist/index.js"(exports) {
|
|
306
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
307
|
+
exports.SyncRedactor = exports.AsyncRedactor = void 0;
|
|
308
|
+
var AsyncCompositeRedactor_1 = require_AsyncCompositeRedactor();
|
|
309
|
+
Object.defineProperty(exports, "AsyncRedactor", { enumerable: true, get: function() {
|
|
310
|
+
return AsyncCompositeRedactor_1.AsyncCompositeRedactor;
|
|
311
|
+
} });
|
|
312
|
+
var SyncCompositeRedactor_1 = require_SyncCompositeRedactor();
|
|
313
|
+
Object.defineProperty(exports, "SyncRedactor", { enumerable: true, get: function() {
|
|
314
|
+
return SyncCompositeRedactor_1.SyncCompositeRedactor;
|
|
315
|
+
} });
|
|
316
|
+
}
|
|
317
|
+
});
|
|
64
318
|
var STATE_KEY = /* @__PURE__ */ Symbol.for("raindrop.tracing.replayTraceRoutingState");
|
|
65
319
|
function state() {
|
|
66
320
|
const holder = globalThis;
|
|
67
321
|
let current = holder[STATE_KEY];
|
|
68
322
|
if (!current) {
|
|
69
|
-
let
|
|
323
|
+
let storage2 = null;
|
|
70
324
|
try {
|
|
71
325
|
const Ctor = globalThis.RAINDROP_ASYNC_LOCAL_STORAGE;
|
|
72
|
-
if (Ctor)
|
|
326
|
+
if (Ctor) storage2 = new Ctor();
|
|
73
327
|
} catch (e) {
|
|
74
|
-
|
|
328
|
+
storage2 = null;
|
|
75
329
|
}
|
|
76
330
|
current = {
|
|
77
|
-
storage,
|
|
331
|
+
storage: storage2,
|
|
78
332
|
syncDestination: void 0,
|
|
79
333
|
spanDestinations: /* @__PURE__ */ new WeakMap()
|
|
80
334
|
};
|
|
@@ -222,12 +476,12 @@ var NO_AMBIENT_ROUTING_BIND_WARNING = "[raindrop] This runtime's AsyncLocalStora
|
|
|
222
476
|
var ROUTING_STORAGE_KEY = /* @__PURE__ */ Symbol.for("raindrop.tracing.routingContextStorage");
|
|
223
477
|
function routingStorage() {
|
|
224
478
|
const holder = globalThis;
|
|
225
|
-
let
|
|
226
|
-
if (!
|
|
227
|
-
|
|
228
|
-
holder[ROUTING_STORAGE_KEY] =
|
|
479
|
+
let storage2 = holder[ROUTING_STORAGE_KEY];
|
|
480
|
+
if (!storage2) {
|
|
481
|
+
storage2 = new ContextStackStorage(NO_AMBIENT_ROUTING_BIND_WARNING);
|
|
482
|
+
holder[ROUTING_STORAGE_KEY] = storage2;
|
|
229
483
|
}
|
|
230
|
-
return
|
|
484
|
+
return storage2;
|
|
231
485
|
}
|
|
232
486
|
function currentRoutingBinding() {
|
|
233
487
|
const bound = routingStorage().current();
|
|
@@ -513,6 +767,14 @@ function appGitPropertiesFromAttributes(attributes) {
|
|
|
513
767
|
}
|
|
514
768
|
return properties;
|
|
515
769
|
}
|
|
770
|
+
function normalizeFeatureFlags(input) {
|
|
771
|
+
if (Array.isArray(input)) {
|
|
772
|
+
return Object.fromEntries(input.map((name) => [name, "true"]));
|
|
773
|
+
}
|
|
774
|
+
return Object.fromEntries(
|
|
775
|
+
Object.entries(input).map(([k, v]) => [k, String(v)])
|
|
776
|
+
);
|
|
777
|
+
}
|
|
516
778
|
function getCrypto() {
|
|
517
779
|
const c = globalThis.crypto;
|
|
518
780
|
return c;
|
|
@@ -614,11 +876,91 @@ function runWithTracingSuppressed(fn) {
|
|
|
614
876
|
return fn();
|
|
615
877
|
}
|
|
616
878
|
}
|
|
879
|
+
var MAX_QUOTED_ITEMS = 3;
|
|
880
|
+
function isRecord(value) {
|
|
881
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
882
|
+
}
|
|
883
|
+
function itemLabel(item) {
|
|
884
|
+
if (typeof item.event_id === "string" && item.event_id) return `event ${item.event_id}`;
|
|
885
|
+
if (typeof item.index === "number") return `item ${item.index}`;
|
|
886
|
+
return "item";
|
|
887
|
+
}
|
|
888
|
+
function describeRejected(item) {
|
|
889
|
+
const issues = Array.isArray(item.issues) ? item.issues : [];
|
|
890
|
+
const text = issues.filter(isRecord).map((issue) => {
|
|
891
|
+
const path = typeof issue.path === "string" && issue.path ? `${issue.path}: ` : "";
|
|
892
|
+
return `${path}${typeof issue.message === "string" ? issue.message : "invalid"}`;
|
|
893
|
+
}).join("; ");
|
|
894
|
+
return `${itemLabel(item)} (${text || "invalid"})`;
|
|
895
|
+
}
|
|
896
|
+
function describeWarning(item) {
|
|
897
|
+
if (typeof item.message === "string" && item.message) return `${itemLabel(item)}: ${item.message}`;
|
|
898
|
+
const fields = Array.isArray(item.fields) ? item.fields.filter((f) => typeof f === "string") : [];
|
|
899
|
+
return `${itemLabel(item)}: ignored ${fields.join(", ") || "input"}`;
|
|
900
|
+
}
|
|
901
|
+
function summarize(items, describe) {
|
|
902
|
+
const quoted = items.slice(0, MAX_QUOTED_ITEMS).map(describe).join(" | ");
|
|
903
|
+
const more = items.length > MAX_QUOTED_ITEMS ? ` (+${items.length - MAX_QUOTED_ITEMS} more)` : "";
|
|
904
|
+
return `${quoted}${more}`;
|
|
905
|
+
}
|
|
906
|
+
function reportIngestResponse(bodyText, prefix, opName) {
|
|
907
|
+
if (!bodyText) return;
|
|
908
|
+
let body;
|
|
909
|
+
try {
|
|
910
|
+
body = JSON.parse(bodyText);
|
|
911
|
+
} catch (e) {
|
|
912
|
+
return;
|
|
913
|
+
}
|
|
914
|
+
if (!isRecord(body)) return;
|
|
915
|
+
const rejected = Array.isArray(body.rejected) ? body.rejected.filter(isRecord) : [];
|
|
916
|
+
if (rejected.length > 0) {
|
|
917
|
+
rateLimitedLog(
|
|
918
|
+
`${prefix}.ingest_rejected`,
|
|
919
|
+
() => console.warn(
|
|
920
|
+
`${prefix} ${opName}: ingest rejected ${rejected.length} item(s), which were not stored: ${summarize(rejected, describeRejected)}`
|
|
921
|
+
)
|
|
922
|
+
);
|
|
923
|
+
}
|
|
924
|
+
const warnings = Array.isArray(body.warnings) ? body.warnings.filter(isRecord) : [];
|
|
925
|
+
if (warnings.length > 0) {
|
|
926
|
+
rateLimitedLog(
|
|
927
|
+
`${prefix}.ingest_warnings`,
|
|
928
|
+
() => console.warn(
|
|
929
|
+
`${prefix} ${opName}: ingest accepted ${warnings.length} item(s) with changes: ${summarize(warnings, describeWarning)}`
|
|
930
|
+
)
|
|
931
|
+
);
|
|
932
|
+
}
|
|
933
|
+
}
|
|
934
|
+
var DEFAULT_FLUSH_TIMEOUT_MS = 1e4;
|
|
617
935
|
var DEFAULT_REQUEST_TIMEOUT_MS = 3e4;
|
|
618
936
|
var MAX_RETRY_DELAY_MS = 3e4;
|
|
619
937
|
function wait(ms) {
|
|
620
938
|
return new Promise((resolve2) => setTimeout(resolve2, ms));
|
|
621
939
|
}
|
|
940
|
+
function waitUnlessAborted(ms, signal) {
|
|
941
|
+
if (!signal) return wait(ms);
|
|
942
|
+
if (signal.aborted) return Promise.resolve();
|
|
943
|
+
return new Promise((resolve2) => {
|
|
944
|
+
const done = () => {
|
|
945
|
+
clearTimeout(timer);
|
|
946
|
+
signal.removeEventListener("abort", done);
|
|
947
|
+
resolve2();
|
|
948
|
+
};
|
|
949
|
+
const timer = setTimeout(done, ms);
|
|
950
|
+
signal.addEventListener("abort", done, { once: true });
|
|
951
|
+
});
|
|
952
|
+
}
|
|
953
|
+
function eitherSignal(a, b) {
|
|
954
|
+
if (!b) return a;
|
|
955
|
+
const any = AbortSignal.any;
|
|
956
|
+
if (typeof any === "function") return any([a, b]);
|
|
957
|
+
const controller = new AbortController();
|
|
958
|
+
const abort = () => controller.abort();
|
|
959
|
+
if (a.aborted || b.aborted) abort();
|
|
960
|
+
a.addEventListener("abort", abort, { once: true });
|
|
961
|
+
b.addEventListener("abort", abort, { once: true });
|
|
962
|
+
return controller.signal;
|
|
963
|
+
}
|
|
622
964
|
function formatEndpoint(endpoint) {
|
|
623
965
|
if (!endpoint) return void 0;
|
|
624
966
|
return endpoint.endsWith("/") ? endpoint : `${endpoint}/`;
|
|
@@ -663,6 +1005,26 @@ async function raceWithTimeout(promise, timeoutMs) {
|
|
|
663
1005
|
if (timer) clearTimeout(timer);
|
|
664
1006
|
return settledInTime;
|
|
665
1007
|
}
|
|
1008
|
+
var InFlightCutOff = class {
|
|
1009
|
+
constructor() {
|
|
1010
|
+
this.controller = new AbortController();
|
|
1011
|
+
}
|
|
1012
|
+
get signal() {
|
|
1013
|
+
return this.controller.signal;
|
|
1014
|
+
}
|
|
1015
|
+
cut() {
|
|
1016
|
+
this.controller.abort();
|
|
1017
|
+
this.controller = new AbortController();
|
|
1018
|
+
}
|
|
1019
|
+
};
|
|
1020
|
+
async function awaitEarlierSends(earlier, deadlineAt, cutOff, isRunning) {
|
|
1021
|
+
if (earlier.length === 0) return { settled: true, stillRunning: 0 };
|
|
1022
|
+
const settled = await raceWithTimeout(Promise.allSettled(earlier), deadlineAt - Date.now());
|
|
1023
|
+
if (settled) return { settled, stillRunning: 0 };
|
|
1024
|
+
const stillRunning = earlier.filter(isRunning).length;
|
|
1025
|
+
if (stillRunning > 0) cutOff.cut();
|
|
1026
|
+
return { settled: stillRunning === 0, stillRunning };
|
|
1027
|
+
}
|
|
666
1028
|
function parseRetryAfter(headers) {
|
|
667
1029
|
var _a;
|
|
668
1030
|
const value = (_a = headers.get("Retry-After")) != null ? _a : headers.get("retry-after");
|
|
@@ -686,45 +1048,80 @@ function getRetryDelayMs(attemptNumber, previousError) {
|
|
|
686
1048
|
const factor = Math.pow(2, attemptNumber - 2);
|
|
687
1049
|
return Math.min(base * factor, MAX_RETRY_DELAY_MS);
|
|
688
1050
|
}
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
console.warn(
|
|
711
|
-
`${prefix} ${opName} attempt ${attemptNumber} failed: ${msg}${attemptNumber === opts.maxAttempts ? " (no more retries)" : ""}`
|
|
712
|
-
);
|
|
713
|
-
}
|
|
714
|
-
if (lastError && typeof lastError === "object" && "retryable" in lastError && !lastError.retryable)
|
|
715
|
-
break;
|
|
716
|
-
if (attemptNumber === opts.maxAttempts) break;
|
|
717
|
-
}
|
|
1051
|
+
var sendPausedUntil = /* @__PURE__ */ new Map();
|
|
1052
|
+
function originOf(url) {
|
|
1053
|
+
try {
|
|
1054
|
+
return new URL(url).origin;
|
|
1055
|
+
} catch (e) {
|
|
1056
|
+
return url;
|
|
1057
|
+
}
|
|
1058
|
+
}
|
|
1059
|
+
function noteSendPause(url, status, retryAfterMs) {
|
|
1060
|
+
var _a;
|
|
1061
|
+
if (status !== 429 && status !== 503 || typeof retryAfterMs !== "number") return;
|
|
1062
|
+
const until = Date.now() + Math.min(Math.max(0, retryAfterMs), MAX_RETRY_DELAY_MS);
|
|
1063
|
+
const origin = originOf(url);
|
|
1064
|
+
sendPausedUntil.set(origin, Math.max((_a = sendPausedUntil.get(origin)) != null ? _a : 0, until));
|
|
1065
|
+
}
|
|
1066
|
+
function pausedUntil(url) {
|
|
1067
|
+
const until = sendPausedUntil.get(originOf(url));
|
|
1068
|
+
if (until === void 0) return void 0;
|
|
1069
|
+
if (until <= Date.now()) {
|
|
1070
|
+
sendPausedUntil.delete(originOf(url));
|
|
1071
|
+
return void 0;
|
|
718
1072
|
}
|
|
719
|
-
|
|
1073
|
+
return Math.min(until, Date.now() + MAX_RETRY_DELAY_MS);
|
|
1074
|
+
}
|
|
1075
|
+
function prefixFor(opts) {
|
|
1076
|
+
return opts.sdkName ? `[raindrop-ai/${opts.sdkName}]` : "[raindrop-ai/core]";
|
|
720
1077
|
}
|
|
721
1078
|
async function postJson(url, body, headers, opts) {
|
|
1079
|
+
var _a;
|
|
1080
|
+
const outcome = await sendJson(url, body, headers, { ...opts, deadlineAt: void 0 });
|
|
1081
|
+
if (outcome.status === "delivered") return;
|
|
1082
|
+
throw (_a = outcome.error) != null ? _a : new Error(`${redactUrlForLog(url)}: not sent (${outcome.status})`);
|
|
1083
|
+
}
|
|
1084
|
+
async function sendJson(url, body, headers, opts) {
|
|
722
1085
|
var _a;
|
|
723
1086
|
const opName = `POST ${redactUrlForLog(url)}`;
|
|
1087
|
+
const prefix = prefixFor(opts);
|
|
724
1088
|
const timeoutMs = (_a = opts.timeoutMs) != null ? _a : DEFAULT_REQUEST_TIMEOUT_MS;
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
1089
|
+
const deadlineAt = opts.deadlineAt;
|
|
1090
|
+
const remaining = () => deadlineAt === void 0 ? Infinity : deadlineAt - Date.now();
|
|
1091
|
+
let lastError;
|
|
1092
|
+
const cutOff = opts.cutOff;
|
|
1093
|
+
for (let attempt = 1; attempt <= opts.maxAttempts; attempt++) {
|
|
1094
|
+
if (cutOff == null ? void 0 : cutOff.aborted) return { status: "deferred", error: lastError };
|
|
1095
|
+
if (attempt > 1) {
|
|
1096
|
+
const delay = getRetryDelayMs(attempt, lastError);
|
|
1097
|
+
if (delay >= remaining()) {
|
|
1098
|
+
return { status: "deferred", retryAtMs: Date.now() + delay, error: lastError };
|
|
1099
|
+
}
|
|
1100
|
+
if (opts.debug) {
|
|
1101
|
+
console.warn(`${prefix} ${opName} retry ${attempt}/${opts.maxAttempts} in ${delay}ms`);
|
|
1102
|
+
}
|
|
1103
|
+
if (delay > 0) await waitUnlessAborted(delay, cutOff);
|
|
1104
|
+
if (cutOff == null ? void 0 : cutOff.aborted) return { status: "deferred", error: lastError };
|
|
1105
|
+
} else if (opts.debug) {
|
|
1106
|
+
console.log(`${prefix} ${opName} attempt ${attempt}/${opts.maxAttempts}`);
|
|
1107
|
+
}
|
|
1108
|
+
const pauseEnd = pausedUntil(url);
|
|
1109
|
+
if (pauseEnd !== void 0) {
|
|
1110
|
+
if (deadlineAt !== void 0 && pauseEnd >= deadlineAt) {
|
|
1111
|
+
return { status: "deferred", retryAtMs: pauseEnd, error: lastError };
|
|
1112
|
+
}
|
|
1113
|
+
await waitUnlessAborted(Math.max(0, pauseEnd - Date.now()), cutOff);
|
|
1114
|
+
if (cutOff == null ? void 0 : cutOff.aborted) return { status: "deferred", retryAtMs: pauseEnd, error: lastError };
|
|
1115
|
+
}
|
|
1116
|
+
const left = remaining();
|
|
1117
|
+
if (left <= 0) return { status: "deferred", error: lastError };
|
|
1118
|
+
const attemptTimeoutMs = Math.min(timeoutMs, left);
|
|
1119
|
+
const clampedByDeadline = attemptTimeoutMs < timeoutMs;
|
|
1120
|
+
const timeoutSignal = AbortSignal.timeout(attemptTimeoutMs);
|
|
1121
|
+
const signal = eitherSignal(timeoutSignal, cutOff);
|
|
1122
|
+
let resp;
|
|
1123
|
+
try {
|
|
1124
|
+
resp = await runWithTracingSuppressed(
|
|
728
1125
|
() => fetch(url, {
|
|
729
1126
|
method: "POST",
|
|
730
1127
|
redirect: headers["X-Raindrop-Replay-Id"] !== void 0 ? "error" : "follow",
|
|
@@ -733,24 +1130,98 @@ async function postJson(url, body, headers, opts) {
|
|
|
733
1130
|
...headers
|
|
734
1131
|
},
|
|
735
1132
|
body: JSON.stringify(body),
|
|
736
|
-
signal
|
|
1133
|
+
signal
|
|
737
1134
|
})
|
|
738
1135
|
);
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
);
|
|
744
|
-
const retryAfterMs = parseRetryAfter(resp.headers);
|
|
745
|
-
if (typeof retryAfterMs === "number") err.retryAfterMs = retryAfterMs;
|
|
746
|
-
err.retryable = resp.status === 429 || resp.status >= 500;
|
|
747
|
-
throw err;
|
|
1136
|
+
} catch (err) {
|
|
1137
|
+
const error = err instanceof Error ? err : new Error(String(err));
|
|
1138
|
+
if ((cutOff == null ? void 0 : cutOff.aborted) || timeoutSignal.aborted && clampedByDeadline) {
|
|
1139
|
+
return { status: "cut_off", error };
|
|
748
1140
|
}
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
1141
|
+
lastError = error;
|
|
1142
|
+
logAttemptFailure(opts, prefix, opName, attempt, error);
|
|
1143
|
+
continue;
|
|
1144
|
+
}
|
|
1145
|
+
if (!resp.ok) {
|
|
1146
|
+
const text = await resp.text().catch(() => "");
|
|
1147
|
+
const error = new Error(
|
|
1148
|
+
`HTTP ${resp.status} ${resp.statusText}${text ? `: ${text}` : ""}`
|
|
1149
|
+
);
|
|
1150
|
+
const retryAfterMs = parseRetryAfter(resp.headers);
|
|
1151
|
+
if (typeof retryAfterMs === "number") error.retryAfterMs = retryAfterMs;
|
|
1152
|
+
noteSendPause(url, resp.status, retryAfterMs);
|
|
1153
|
+
error.retryable = resp.status === 408 || resp.status === 429 || resp.status >= 500;
|
|
1154
|
+
if (!error.retryable) return { status: "rejected", error };
|
|
1155
|
+
lastError = error;
|
|
1156
|
+
logAttemptFailure(opts, prefix, opName, attempt, error);
|
|
1157
|
+
continue;
|
|
1158
|
+
}
|
|
1159
|
+
try {
|
|
1160
|
+
reportIngestResponse(await resp.text(), prefix, opName);
|
|
1161
|
+
} catch (e) {
|
|
1162
|
+
}
|
|
1163
|
+
return { status: "delivered" };
|
|
1164
|
+
}
|
|
1165
|
+
return { status: "failed", error: lastError != null ? lastError : new Error(`${opName}: no attempts`) };
|
|
1166
|
+
}
|
|
1167
|
+
function logAttemptFailure(opts, prefix, opName, attempt, error) {
|
|
1168
|
+
if (!opts.debug) return;
|
|
1169
|
+
console.warn(
|
|
1170
|
+
`${prefix} ${opName} attempt ${attempt} failed: ${error.message}${attempt === opts.maxAttempts ? " (no more retries)" : ""}`
|
|
1171
|
+
);
|
|
1172
|
+
}
|
|
1173
|
+
function asCompat(result) {
|
|
1174
|
+
return result;
|
|
1175
|
+
}
|
|
1176
|
+
var DELIVERED = Object.freeze({
|
|
1177
|
+
delivered: true,
|
|
1178
|
+
timedOut: false,
|
|
1179
|
+
dropped: 0,
|
|
1180
|
+
queued: 0,
|
|
1181
|
+
inFlight: 0
|
|
1182
|
+
});
|
|
1183
|
+
function fateOf(outcome, shuttingDown) {
|
|
1184
|
+
switch (outcome.status) {
|
|
1185
|
+
case "delivered":
|
|
1186
|
+
case "rejected":
|
|
1187
|
+
return "delivered";
|
|
1188
|
+
case "deferred":
|
|
1189
|
+
return shuttingDown ? "dropped" : "queued";
|
|
1190
|
+
default:
|
|
1191
|
+
return "dropped";
|
|
1192
|
+
}
|
|
1193
|
+
}
|
|
1194
|
+
function summarize2(fates, inFlight, timedOut) {
|
|
1195
|
+
const dropped = fates.filter((fate) => fate === "dropped").length;
|
|
1196
|
+
const queued = fates.filter((fate) => fate === "queued").length;
|
|
1197
|
+
return {
|
|
1198
|
+
delivered: dropped === 0 && queued === 0 && inFlight === 0,
|
|
1199
|
+
timedOut: timedOut || queued > 0 || inFlight > 0,
|
|
1200
|
+
dropped,
|
|
1201
|
+
queued,
|
|
1202
|
+
inFlight
|
|
1203
|
+
};
|
|
1204
|
+
}
|
|
1205
|
+
function combineResults(...results) {
|
|
1206
|
+
return results.reduce(
|
|
1207
|
+
(acc, r) => ({
|
|
1208
|
+
delivered: acc.delivered && r.delivered,
|
|
1209
|
+
timedOut: acc.timedOut || r.timedOut,
|
|
1210
|
+
dropped: acc.dropped + r.dropped,
|
|
1211
|
+
queued: acc.queued + r.queued,
|
|
1212
|
+
inFlight: acc.inFlight + r.inFlight
|
|
1213
|
+
}),
|
|
1214
|
+
{ ...DELIVERED }
|
|
752
1215
|
);
|
|
753
1216
|
}
|
|
1217
|
+
function describeUndelivered(what, result) {
|
|
1218
|
+
const parts = [
|
|
1219
|
+
result.dropped > 0 ? `${result.dropped} dropped` : "",
|
|
1220
|
+
result.queued > 0 ? `${result.queued} still queued` : "",
|
|
1221
|
+
result.inFlight > 0 ? `${result.inFlight} still sending` : ""
|
|
1222
|
+
].filter(Boolean);
|
|
1223
|
+
return `${what} returned before everything was delivered: ${parts.join(", ")}`;
|
|
1224
|
+
}
|
|
754
1225
|
var DEFAULT_MAX_TEXT_FIELD_CHARS = 1e6;
|
|
755
1226
|
var TRUNCATION_MARKER = "...[truncated by raindrop]";
|
|
756
1227
|
var BOUNDED_CLONE_MAX_DEPTH = 12;
|
|
@@ -1017,7 +1488,245 @@ function normalizeProjectId(raw, opts) {
|
|
|
1017
1488
|
function projectIdHeaders(projectId) {
|
|
1018
1489
|
return projectId ? { [PROJECT_ID_HEADER]: projectId } : {};
|
|
1019
1490
|
}
|
|
1020
|
-
var
|
|
1491
|
+
var import_redact_pii = __toESM(require_dist(), 1);
|
|
1492
|
+
var DEFAULT_PII_REDACTION_OPTIONS = {
|
|
1493
|
+
builtInRedactors: {
|
|
1494
|
+
credentials: { replaceWith: "<REDACTED CREDENTIALS>" },
|
|
1495
|
+
creditCardNumber: { replaceWith: "<REDACTED CREDIT CARD NUMBER>" },
|
|
1496
|
+
// Any run of 4+ digits: too broad.
|
|
1497
|
+
digits: { enabled: false },
|
|
1498
|
+
emailAddress: { replaceWith: "<REDACTED EMAIL>" },
|
|
1499
|
+
ipAddress: { enabled: false },
|
|
1500
|
+
names: { enabled: false },
|
|
1501
|
+
// Matches (pass(word|phrase)|secret): \S+
|
|
1502
|
+
password: { replaceWith: "<REDACTED SECRET>" },
|
|
1503
|
+
phoneNumber: { replaceWith: "<REDACTED PHONE NUMBER>" },
|
|
1504
|
+
streetAddress: { replaceWith: "<REDACTED ADDRESS>" },
|
|
1505
|
+
url: { enabled: false },
|
|
1506
|
+
username: { enabled: false },
|
|
1507
|
+
usSocialSecurityNumber: { replaceWith: "<REDACTED SOCIAL SECURITY NUMBER>" },
|
|
1508
|
+
zipcode: { enabled: false }
|
|
1509
|
+
}
|
|
1510
|
+
};
|
|
1511
|
+
var redactor;
|
|
1512
|
+
function redactPiiText(text) {
|
|
1513
|
+
redactor != null ? redactor : redactor = new import_redact_pii.SyncRedactor(DEFAULT_PII_REDACTION_OPTIONS);
|
|
1514
|
+
return redactor.redact(text);
|
|
1515
|
+
}
|
|
1516
|
+
var KINDS = ["event", "signal", "identify"];
|
|
1517
|
+
var DEFAULT_PII_FIELDS = {
|
|
1518
|
+
event: ["ai_data.input", "ai_data.output"],
|
|
1519
|
+
signal: [],
|
|
1520
|
+
identify: []
|
|
1521
|
+
};
|
|
1522
|
+
var PROTECTED_LOCATIONS = new Set(
|
|
1523
|
+
[
|
|
1524
|
+
["event_id"],
|
|
1525
|
+
["user_id"],
|
|
1526
|
+
["ai_data", "convo_id"],
|
|
1527
|
+
["event"],
|
|
1528
|
+
["timestamp"],
|
|
1529
|
+
["is_pending"],
|
|
1530
|
+
["signal_name"],
|
|
1531
|
+
["signal_type"]
|
|
1532
|
+
].map((keys) => JSON.stringify(keys))
|
|
1533
|
+
);
|
|
1534
|
+
var SIGNAL_PATH_ALIASES = {
|
|
1535
|
+
comment: "properties.comment",
|
|
1536
|
+
after: "properties.after"
|
|
1537
|
+
};
|
|
1538
|
+
function parsePiiFieldPath(path) {
|
|
1539
|
+
if (typeof path !== "string") return null;
|
|
1540
|
+
const segments = [];
|
|
1541
|
+
let i = 0;
|
|
1542
|
+
const n = path.length;
|
|
1543
|
+
let expectSeparator = false;
|
|
1544
|
+
while (i < n) {
|
|
1545
|
+
const ch = path[i];
|
|
1546
|
+
if (ch === "[") {
|
|
1547
|
+
const close = path.indexOf("]", i);
|
|
1548
|
+
if (path[i + 1] === '"') {
|
|
1549
|
+
let j2 = i + 2;
|
|
1550
|
+
let key = "";
|
|
1551
|
+
while (j2 < n && path[j2] !== '"') {
|
|
1552
|
+
if (path[j2] === "\\" && j2 + 1 < n) {
|
|
1553
|
+
key += path[j2 + 1];
|
|
1554
|
+
j2 += 2;
|
|
1555
|
+
} else {
|
|
1556
|
+
key += path[j2];
|
|
1557
|
+
j2 += 1;
|
|
1558
|
+
}
|
|
1559
|
+
}
|
|
1560
|
+
if (j2 >= n || path[j2 + 1] !== "]" || key === "") return null;
|
|
1561
|
+
segments.push({ kind: "key", key });
|
|
1562
|
+
i = j2 + 2;
|
|
1563
|
+
} else {
|
|
1564
|
+
if (close === -1) return null;
|
|
1565
|
+
const inner = path.slice(i + 1, close);
|
|
1566
|
+
if (inner === "") segments.push({ kind: "every" });
|
|
1567
|
+
else if (/^(0|[1-9]\d*)$/.test(inner))
|
|
1568
|
+
segments.push({ kind: "index", index: Number(inner) });
|
|
1569
|
+
else return null;
|
|
1570
|
+
i = close + 1;
|
|
1571
|
+
}
|
|
1572
|
+
expectSeparator = true;
|
|
1573
|
+
continue;
|
|
1574
|
+
}
|
|
1575
|
+
if (ch === ".") {
|
|
1576
|
+
if (!expectSeparator) return null;
|
|
1577
|
+
i += 1;
|
|
1578
|
+
expectSeparator = false;
|
|
1579
|
+
if (i >= n || path[i] === ".") return null;
|
|
1580
|
+
continue;
|
|
1581
|
+
}
|
|
1582
|
+
if (expectSeparator) return null;
|
|
1583
|
+
let j = i;
|
|
1584
|
+
while (j < n && path[j] !== "." && path[j] !== "[") j += 1;
|
|
1585
|
+
const token = path.slice(i, j);
|
|
1586
|
+
if (token === "*") segments.push({ kind: "any_key" });
|
|
1587
|
+
else if (token === "" || /[\]*"\s]/.test(token)) return null;
|
|
1588
|
+
else segments.push({ kind: "key", key: token });
|
|
1589
|
+
i = j;
|
|
1590
|
+
expectSeparator = true;
|
|
1591
|
+
}
|
|
1592
|
+
return segments.length > 0 && expectSeparator ? segments : null;
|
|
1593
|
+
}
|
|
1594
|
+
function mergePiiFieldMaps(...maps) {
|
|
1595
|
+
const out = { event: [], signal: [], identify: [] };
|
|
1596
|
+
for (const kind of KINDS) {
|
|
1597
|
+
const seen = /* @__PURE__ */ new Set();
|
|
1598
|
+
for (const map of maps) {
|
|
1599
|
+
const paths = map == null ? void 0 : map[kind];
|
|
1600
|
+
if (!Array.isArray(paths)) continue;
|
|
1601
|
+
for (const path of paths) {
|
|
1602
|
+
if (typeof path !== "string" || seen.has(path)) continue;
|
|
1603
|
+
seen.add(path);
|
|
1604
|
+
out[kind].push(path);
|
|
1605
|
+
}
|
|
1606
|
+
}
|
|
1607
|
+
}
|
|
1608
|
+
return out;
|
|
1609
|
+
}
|
|
1610
|
+
function isPlainObject(value) {
|
|
1611
|
+
if (value === null || typeof value !== "object" || Array.isArray(value)) return false;
|
|
1612
|
+
const proto = Object.getPrototypeOf(value);
|
|
1613
|
+
return proto === Object.prototype || proto === null;
|
|
1614
|
+
}
|
|
1615
|
+
function isProtected(location) {
|
|
1616
|
+
return PROTECTED_LOCATIONS.has(JSON.stringify(location));
|
|
1617
|
+
}
|
|
1618
|
+
function redactAll(value, location) {
|
|
1619
|
+
if (location !== null && isProtected(location)) return value;
|
|
1620
|
+
if (typeof value === "string") return redactPiiText(value);
|
|
1621
|
+
if (Array.isArray(value)) return value.map((item) => redactAll(item, null));
|
|
1622
|
+
if (isPlainObject(value)) {
|
|
1623
|
+
const out = {};
|
|
1624
|
+
for (const [key, child] of Object.entries(value)) {
|
|
1625
|
+
out[key] = redactAll(child, location === null ? null : [...location, key]);
|
|
1626
|
+
}
|
|
1627
|
+
return out;
|
|
1628
|
+
}
|
|
1629
|
+
return value;
|
|
1630
|
+
}
|
|
1631
|
+
function applyPath(value, segments, location) {
|
|
1632
|
+
if (segments.length === 0) return redactAll(value, location);
|
|
1633
|
+
const [head, ...rest] = segments;
|
|
1634
|
+
if (head.kind === "key" || head.kind === "any_key") {
|
|
1635
|
+
if (!isPlainObject(value)) return value;
|
|
1636
|
+
const keys = head.kind === "key" ? [head.key] : Object.keys(value);
|
|
1637
|
+
let out2;
|
|
1638
|
+
for (const key of keys) {
|
|
1639
|
+
if (!Object.prototype.hasOwnProperty.call(value, key)) continue;
|
|
1640
|
+
const child = value[key];
|
|
1641
|
+
const next = applyPath(child, rest, location === null ? null : [...location, key]);
|
|
1642
|
+
if (next !== child) {
|
|
1643
|
+
out2 != null ? out2 : out2 = { ...value };
|
|
1644
|
+
out2[key] = next;
|
|
1645
|
+
}
|
|
1646
|
+
}
|
|
1647
|
+
return out2 != null ? out2 : value;
|
|
1648
|
+
}
|
|
1649
|
+
if (!Array.isArray(value)) return value;
|
|
1650
|
+
const indices = head.kind === "index" ? head.index < value.length ? [head.index] : [] : value.keys();
|
|
1651
|
+
let out;
|
|
1652
|
+
for (const index of indices) {
|
|
1653
|
+
const child = value[index];
|
|
1654
|
+
const next = applyPath(child, rest, null);
|
|
1655
|
+
if (next !== child) {
|
|
1656
|
+
out != null ? out : out = [...value];
|
|
1657
|
+
out[index] = next;
|
|
1658
|
+
}
|
|
1659
|
+
}
|
|
1660
|
+
return out != null ? out : value;
|
|
1661
|
+
}
|
|
1662
|
+
var PiiFieldRedactor = class {
|
|
1663
|
+
constructor(options = {}) {
|
|
1664
|
+
var _a;
|
|
1665
|
+
this.startupMap = options.startupFieldMap;
|
|
1666
|
+
this.prefix = (_a = options.logPrefix) != null ? _a : "[raindrop-ai/core]";
|
|
1667
|
+
}
|
|
1668
|
+
/** Replace the server-provided layer (CONTRACT 11.2). Additive: it can only add fields. */
|
|
1669
|
+
setServerFieldMap(map) {
|
|
1670
|
+
this.serverMap = map;
|
|
1671
|
+
this.compiled = void 0;
|
|
1672
|
+
}
|
|
1673
|
+
/** The paths in effect for a kind, defaults first. */
|
|
1674
|
+
effectivePaths(kind) {
|
|
1675
|
+
return mergePiiFieldMaps(DEFAULT_PII_FIELDS, this.startupMap, this.serverMap)[kind];
|
|
1676
|
+
}
|
|
1677
|
+
compile() {
|
|
1678
|
+
if (this.compiled) return this.compiled;
|
|
1679
|
+
const out = { event: [], signal: [], identify: [] };
|
|
1680
|
+
for (const kind of KINDS) {
|
|
1681
|
+
for (const path of this.effectivePaths(kind)) {
|
|
1682
|
+
const variants = [path];
|
|
1683
|
+
if (kind === "signal" && SIGNAL_PATH_ALIASES[path])
|
|
1684
|
+
variants.push(SIGNAL_PATH_ALIASES[path]);
|
|
1685
|
+
for (const variant of variants) {
|
|
1686
|
+
const segments = parsePiiFieldPath(variant);
|
|
1687
|
+
if (segments) {
|
|
1688
|
+
out[kind].push(segments);
|
|
1689
|
+
} else {
|
|
1690
|
+
rateLimitedLog(
|
|
1691
|
+
`${this.prefix}.pii_field_path_invalid`,
|
|
1692
|
+
() => console.warn(
|
|
1693
|
+
`${this.prefix} redactPiiFields: ignoring invalid ${kind} path ${JSON.stringify(variant)}`
|
|
1694
|
+
)
|
|
1695
|
+
);
|
|
1696
|
+
}
|
|
1697
|
+
}
|
|
1698
|
+
}
|
|
1699
|
+
}
|
|
1700
|
+
this.compiled = out;
|
|
1701
|
+
return out;
|
|
1702
|
+
}
|
|
1703
|
+
/** The payload with every selected field redacted (a copy where changed). */
|
|
1704
|
+
redact(kind, payload) {
|
|
1705
|
+
let out = payload;
|
|
1706
|
+
for (const segments of this.compile()[kind]) out = applyPath(out, segments, []);
|
|
1707
|
+
return out;
|
|
1708
|
+
}
|
|
1709
|
+
};
|
|
1710
|
+
function detectRuntime() {
|
|
1711
|
+
if (typeof process === "object" && process && typeof process.env === "object" && process.env && typeof process.version === "string") {
|
|
1712
|
+
return "node";
|
|
1713
|
+
}
|
|
1714
|
+
if (typeof window === "object") return "browser";
|
|
1715
|
+
if (typeof WebSocketPair !== "undefined") return "cloudflare-worker";
|
|
1716
|
+
if (typeof EdgeRuntime === "string") return "vercel-edge";
|
|
1717
|
+
if (typeof WorkerGlobalScope !== "undefined" && typeof importScripts === "function") {
|
|
1718
|
+
return "web-worker";
|
|
1719
|
+
}
|
|
1720
|
+
return "unknown";
|
|
1721
|
+
}
|
|
1722
|
+
var PLACEHOLDER_USER_IDS = /* @__PURE__ */ new Set(["null", "undefined"]);
|
|
1723
|
+
function isMissingUserId(value) {
|
|
1724
|
+
if (value === void 0 || value === null) return true;
|
|
1725
|
+
if (typeof value !== "string") return false;
|
|
1726
|
+
const trimmed = value.trim();
|
|
1727
|
+
return trimmed === "" || PLACEHOLDER_USER_IDS.has(trimmed);
|
|
1728
|
+
}
|
|
1729
|
+
var MAX_DEFERRED_SENDS = 1e3;
|
|
1021
1730
|
var POST_SHUTDOWN_TIMEOUT_MS = 5e3;
|
|
1022
1731
|
function appGitOwnerId(prefix) {
|
|
1023
1732
|
try {
|
|
@@ -1026,18 +1735,52 @@ function appGitOwnerId(prefix) {
|
|
|
1026
1735
|
return `${prefix}:${Date.now().toString(36)}:${Math.random().toString(36).slice(2)}`;
|
|
1027
1736
|
}
|
|
1028
1737
|
}
|
|
1738
|
+
function earliestIsoTimestamp(...values) {
|
|
1739
|
+
let earliest;
|
|
1740
|
+
for (const value of values) {
|
|
1741
|
+
if (value === void 0) continue;
|
|
1742
|
+
const date = new Date(value);
|
|
1743
|
+
if (Number.isNaN(date.getTime())) continue;
|
|
1744
|
+
if (earliest === void 0 || date < earliest) earliest = date;
|
|
1745
|
+
}
|
|
1746
|
+
return earliest == null ? void 0 : earliest.toISOString();
|
|
1747
|
+
}
|
|
1748
|
+
function isPlainObject2(value) {
|
|
1749
|
+
if (value === null || typeof value !== "object" || Array.isArray(value)) return false;
|
|
1750
|
+
const proto = Object.getPrototypeOf(value);
|
|
1751
|
+
return proto === Object.prototype || proto === null;
|
|
1752
|
+
}
|
|
1753
|
+
var UNSAFE_MERGE_KEYS = /* @__PURE__ */ new Set(["__proto__", "constructor", "prototype"]);
|
|
1754
|
+
function deepMergeProperties(target, source) {
|
|
1755
|
+
const out = { ...target };
|
|
1756
|
+
for (const [key, value] of Object.entries(source)) {
|
|
1757
|
+
if (value === void 0 || UNSAFE_MERGE_KEYS.has(key)) continue;
|
|
1758
|
+
const existing = out[key];
|
|
1759
|
+
out[key] = isPlainObject2(existing) && isPlainObject2(value) ? deepMergeProperties(existing, value) : value;
|
|
1760
|
+
}
|
|
1761
|
+
return out;
|
|
1762
|
+
}
|
|
1029
1763
|
function mergePatches(target, source) {
|
|
1030
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _i;
|
|
1031
|
-
const
|
|
1764
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k;
|
|
1765
|
+
const defined2 = Object.fromEntries(
|
|
1766
|
+
Object.entries(source).filter(([, value]) => value !== void 0)
|
|
1767
|
+
);
|
|
1768
|
+
const out = { ...target, ...defined2 };
|
|
1032
1769
|
if (target.properties || source.properties) {
|
|
1033
|
-
out.properties =
|
|
1770
|
+
out.properties = deepMergeProperties((_a = target.properties) != null ? _a : {}, (_b = source.properties) != null ? _b : {});
|
|
1771
|
+
}
|
|
1772
|
+
if (target.callerProperties || source.callerProperties) {
|
|
1773
|
+
out.callerProperties = deepMergeProperties(
|
|
1774
|
+
(_c = target.callerProperties) != null ? _c : {},
|
|
1775
|
+
(_d = source.callerProperties) != null ? _d : {}
|
|
1776
|
+
);
|
|
1034
1777
|
}
|
|
1035
1778
|
if (target.usage || source.usage) {
|
|
1036
|
-
out.usage = { ...(
|
|
1037
|
-
if (((
|
|
1779
|
+
out.usage = { ...(_e = target.usage) != null ? _e : {} };
|
|
1780
|
+
if (((_f = source.usage) == null ? void 0 : _f.promptTokens) !== void 0) {
|
|
1038
1781
|
out.usage.promptTokens = source.usage.promptTokens;
|
|
1039
1782
|
}
|
|
1040
|
-
if (((
|
|
1783
|
+
if (((_g = source.usage) == null ? void 0 : _g.completionTokens) !== void 0) {
|
|
1041
1784
|
out.usage.completionTokens = source.usage.completionTokens;
|
|
1042
1785
|
}
|
|
1043
1786
|
}
|
|
@@ -1045,10 +1788,10 @@ function mergePatches(target, source) {
|
|
|
1045
1788
|
out.error = target.error;
|
|
1046
1789
|
}
|
|
1047
1790
|
if (target.featureFlags || source.featureFlags) {
|
|
1048
|
-
out.featureFlags = { ...(
|
|
1791
|
+
out.featureFlags = { ...(_h = target.featureFlags) != null ? _h : {}, ...(_i = source.featureFlags) != null ? _i : {} };
|
|
1049
1792
|
}
|
|
1050
1793
|
if (target.attachments || source.attachments) {
|
|
1051
|
-
out.attachments = [...(
|
|
1794
|
+
out.attachments = [...(_j = target.attachments) != null ? _j : [], ...(_k = source.attachments) != null ? _k : []];
|
|
1052
1795
|
}
|
|
1053
1796
|
return out;
|
|
1054
1797
|
}
|
|
@@ -1073,6 +1816,15 @@ function eventTelemetryProperties(patch) {
|
|
|
1073
1816
|
}
|
|
1074
1817
|
return properties;
|
|
1075
1818
|
}
|
|
1819
|
+
var FINISHED_EVENT_MEMORY = 1e4;
|
|
1820
|
+
var MANUAL_UPDATES = /* @__PURE__ */ new WeakSet();
|
|
1821
|
+
function markManualUpdate(patch) {
|
|
1822
|
+
try {
|
|
1823
|
+
MANUAL_UPDATES.add(patch);
|
|
1824
|
+
} catch (e) {
|
|
1825
|
+
}
|
|
1826
|
+
return patch;
|
|
1827
|
+
}
|
|
1076
1828
|
var EventShipper = class {
|
|
1077
1829
|
constructor(opts) {
|
|
1078
1830
|
this.appGitOwner = appGitOwnerId("event");
|
|
@@ -1080,6 +1832,12 @@ var EventShipper = class {
|
|
|
1080
1832
|
this.sticky = /* @__PURE__ */ new Map();
|
|
1081
1833
|
this.timers = /* @__PURE__ */ new Map();
|
|
1082
1834
|
this.inFlight = /* @__PURE__ */ new Set();
|
|
1835
|
+
this.background = /* @__PURE__ */ new Set();
|
|
1836
|
+
this.backgroundDrops = 0;
|
|
1837
|
+
this.cutOff = new InFlightCutOff();
|
|
1838
|
+
this.finishedEventIds = /* @__PURE__ */ new Set();
|
|
1839
|
+
this.sendChains = /* @__PURE__ */ new Map();
|
|
1840
|
+
this.deferredSends = /* @__PURE__ */ new Set();
|
|
1083
1841
|
this.hasShutdown = false;
|
|
1084
1842
|
var _a, _b, _c, _d, _e, _f, _g, _h, _i;
|
|
1085
1843
|
this.appGitContext = (_a = opts.appGitContext) != null ? _a : createAppGitContext(opts.appGit);
|
|
@@ -1093,6 +1851,7 @@ var EventShipper = class {
|
|
|
1093
1851
|
this.prefix = `[raindrop-ai/${this.sdkName}]`;
|
|
1094
1852
|
this.defaultEventName = (_f = opts.defaultEventName) != null ? _f : "ai_generation";
|
|
1095
1853
|
this.maxTextFieldCharsOpt = opts.maxTextFieldChars;
|
|
1854
|
+
this.flushTimeoutMs = resolveFlushTimeoutMs(opts.flushTimeoutMs);
|
|
1096
1855
|
this.localDebuggerUrl = (_g = resolveLocalDebuggerBaseUrl(opts.localDebuggerUrl)) != null ? _g : void 0;
|
|
1097
1856
|
if (this.debug && this.localDebuggerUrl) {
|
|
1098
1857
|
console.log(`${this.prefix} Local debugger mirroring: ${this.localDebuggerUrl}`);
|
|
@@ -1101,15 +1860,29 @@ var EventShipper = class {
|
|
|
1101
1860
|
debug: this.debug,
|
|
1102
1861
|
prefix: this.prefix
|
|
1103
1862
|
});
|
|
1104
|
-
|
|
1863
|
+
this.redactPii = opts.redactPii === true;
|
|
1864
|
+
this.piiFields = new PiiFieldRedactor({
|
|
1865
|
+
startupFieldMap: opts.redactPiiFields,
|
|
1866
|
+
logPrefix: this.prefix
|
|
1867
|
+
});
|
|
1868
|
+
if (opts.redactPiiFields && !this.redactPii) {
|
|
1869
|
+
rateLimitedLog(
|
|
1870
|
+
`${this.prefix}.pii_fields_without_redaction`,
|
|
1871
|
+
() => console.warn(
|
|
1872
|
+
`${this.prefix} redactPiiFields is set but redactPii is off; nothing is redacted. Set redactPii: true to use it.`
|
|
1873
|
+
)
|
|
1874
|
+
);
|
|
1875
|
+
}
|
|
1876
|
+
this.wizardSession = opts.wizardSession || void 0;
|
|
1877
|
+
const runtime = detectRuntime();
|
|
1105
1878
|
this.context = {
|
|
1106
1879
|
library: {
|
|
1107
1880
|
name: (_h = opts.libraryName) != null ? _h : "@raindrop-ai/core",
|
|
1108
1881
|
version: (_i = opts.libraryVersion) != null ? _i : "0.0.0"
|
|
1109
1882
|
},
|
|
1110
1883
|
metadata: {
|
|
1111
|
-
jsRuntime:
|
|
1112
|
-
...
|
|
1884
|
+
jsRuntime: runtime,
|
|
1885
|
+
...runtime === "node" ? { nodeVersion: process.version } : {}
|
|
1113
1886
|
}
|
|
1114
1887
|
};
|
|
1115
1888
|
}
|
|
@@ -1126,28 +1899,21 @@ var EventShipper = class {
|
|
|
1126
1899
|
return { ...this.authHeaders(), ...projectIdHeaders(this.projectId) };
|
|
1127
1900
|
}
|
|
1128
1901
|
/**
|
|
1129
|
-
*
|
|
1130
|
-
*
|
|
1131
|
-
*
|
|
1132
|
-
*
|
|
1133
|
-
*
|
|
1134
|
-
* Checked fresh on EVERY send, so a shutdown that begins while the flush
|
|
1135
|
-
* path is mid-drain takes effect immediately: no further retries, and the
|
|
1136
|
-
* per-attempt timeout is clamped to the remaining window. After
|
|
1137
|
-
* `shutdown()` returns (deadline cleared, `hasShutdown` still set),
|
|
1138
|
-
* sends — late callers, or flush work the deadline abandoned mid-drain —
|
|
1139
|
-
* run as a single short attempt rather than regaining the full retry
|
|
1140
|
-
* schedule.
|
|
1902
|
+
* Retry/timeout options for one POST. While `shutdown()` drains, sends retry
|
|
1903
|
+
* within its window (deadline = the shutdown deadline); a flush passes its
|
|
1904
|
+
* own deadline. `null` when the shutdown window is spent: the caller drops
|
|
1905
|
+
* the payload with a warning. After `shutdown()` returns, late sends get a
|
|
1906
|
+
* single short attempt rather than the full retry schedule.
|
|
1141
1907
|
*/
|
|
1142
|
-
requestOpts() {
|
|
1908
|
+
requestOpts(deadlineAt) {
|
|
1143
1909
|
if (this.shutdownDeadlineAt !== void 0) {
|
|
1144
|
-
|
|
1145
|
-
if (remainingMs <= 0) return null;
|
|
1910
|
+
if (this.shutdownDeadlineAt - Date.now() <= 0) return null;
|
|
1146
1911
|
return {
|
|
1147
|
-
maxAttempts:
|
|
1912
|
+
maxAttempts: 3,
|
|
1148
1913
|
debug: this.debug,
|
|
1149
1914
|
sdkName: this.sdkName,
|
|
1150
|
-
|
|
1915
|
+
deadlineAt: Math.min(this.shutdownDeadlineAt, deadlineAt != null ? deadlineAt : Infinity),
|
|
1916
|
+
cutOff: this.cutOff.signal
|
|
1151
1917
|
};
|
|
1152
1918
|
}
|
|
1153
1919
|
if (this.hasShutdown) {
|
|
@@ -1155,15 +1921,94 @@ var EventShipper = class {
|
|
|
1155
1921
|
maxAttempts: 1,
|
|
1156
1922
|
debug: this.debug,
|
|
1157
1923
|
sdkName: this.sdkName,
|
|
1158
|
-
timeoutMs: POST_SHUTDOWN_TIMEOUT_MS
|
|
1924
|
+
timeoutMs: POST_SHUTDOWN_TIMEOUT_MS,
|
|
1925
|
+
cutOff: this.cutOff.signal
|
|
1159
1926
|
};
|
|
1160
1927
|
}
|
|
1161
|
-
return {
|
|
1928
|
+
return {
|
|
1929
|
+
maxAttempts: 3,
|
|
1930
|
+
debug: this.debug,
|
|
1931
|
+
sdkName: this.sdkName,
|
|
1932
|
+
deadlineAt,
|
|
1933
|
+
cutOff: this.cutOff.signal
|
|
1934
|
+
};
|
|
1935
|
+
}
|
|
1936
|
+
shuttingDown() {
|
|
1937
|
+
return this.shutdownDeadlineAt !== void 0 || this.hasShutdown;
|
|
1162
1938
|
}
|
|
1163
1939
|
async patch(eventId, patch) {
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1940
|
+
await this.patchWithFate(eventId, patch);
|
|
1941
|
+
}
|
|
1942
|
+
/**
|
|
1943
|
+
* Queue an update without waiting for any network send: for integrations,
|
|
1944
|
+
* whose captured call must return as soon as the update is queued (rule C9,
|
|
1945
|
+
* hot path). A finishing update starts its send in the background; `flush()`
|
|
1946
|
+
* and `shutdown()` wait for it within their deadline and count it in their
|
|
1947
|
+
* result. Never throws or rejects.
|
|
1948
|
+
*/
|
|
1949
|
+
enqueue(eventId, patch) {
|
|
1950
|
+
let op;
|
|
1951
|
+
try {
|
|
1952
|
+
op = this.patchWithFate(eventId, patch).catch((err) => {
|
|
1953
|
+
this.warnBackgroundFailure(eventId, err);
|
|
1954
|
+
return "dropped";
|
|
1955
|
+
}).then((fate) => {
|
|
1956
|
+
if (fate === "dropped") this.backgroundDrops += 1;
|
|
1957
|
+
return fate;
|
|
1958
|
+
});
|
|
1959
|
+
} catch (err) {
|
|
1960
|
+
this.warnBackgroundFailure(eventId, err);
|
|
1961
|
+
return;
|
|
1962
|
+
}
|
|
1963
|
+
this.background.add(op);
|
|
1964
|
+
void op.finally(() => this.background.delete(op));
|
|
1965
|
+
}
|
|
1966
|
+
/** `finish()` without waiting for the send; see `enqueue`. */
|
|
1967
|
+
enqueueFinish(eventId, patch = {}) {
|
|
1968
|
+
this.enqueue(eventId, { ...patch, isPending: false });
|
|
1969
|
+
}
|
|
1970
|
+
/**
|
|
1971
|
+
* Caller properties win over everything the integration derived (W6). A
|
|
1972
|
+
* clash is intended by the caller, so it is only logged in debug mode.
|
|
1973
|
+
*/
|
|
1974
|
+
withCallerProperties(eventId, derived, caller) {
|
|
1975
|
+
if (!caller || Object.keys(caller).length === 0) return derived;
|
|
1976
|
+
if (this.debug) {
|
|
1977
|
+
try {
|
|
1978
|
+
const keys = overriddenKeys(derived, caller);
|
|
1979
|
+
if (keys.length > 0) {
|
|
1980
|
+
console.log(
|
|
1981
|
+
`${this.prefix} event ${eventId}: caller properties override the integration's value for ${keys.map((k) => `"${k}"`).join(", ")}`
|
|
1982
|
+
);
|
|
1983
|
+
}
|
|
1984
|
+
} catch (e) {
|
|
1985
|
+
}
|
|
1986
|
+
}
|
|
1987
|
+
return deepMergeProperties(derived, caller);
|
|
1988
|
+
}
|
|
1989
|
+
warnBackgroundFailure(eventId, err) {
|
|
1990
|
+
rateLimitedLog(
|
|
1991
|
+
`${this.prefix}.background_update`,
|
|
1992
|
+
() => console.warn(`${this.prefix} update for event ${eventId} failed:`, err)
|
|
1993
|
+
);
|
|
1994
|
+
}
|
|
1995
|
+
/**
|
|
1996
|
+
* Id of the last event an integration finished in this process (manual
|
|
1997
|
+
* events API finishes excluded): what integrations expose as `lastEventId`
|
|
1998
|
+
* (wrapper profile W10).
|
|
1999
|
+
*/
|
|
2000
|
+
get lastFinishedEventId() {
|
|
2001
|
+
return this.lastFinished;
|
|
2002
|
+
}
|
|
2003
|
+
async patchWithFate(eventId, patch) {
|
|
2004
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m;
|
|
2005
|
+
const manual = MANUAL_UPDATES.has(patch);
|
|
2006
|
+
if (!this.enabled) return void 0;
|
|
2007
|
+
if (!eventId || !eventId.trim()) return void 0;
|
|
2008
|
+
if (patch.userId !== void 0 && isMissingUserId(patch.userId)) {
|
|
2009
|
+
const { userId: _placeholder, ...rest } = patch;
|
|
2010
|
+
patch = rest;
|
|
2011
|
+
}
|
|
1167
2012
|
const capturedSticky = this.sticky.get(eventId);
|
|
1168
2013
|
const eventAlreadyKnown = capturedSticky !== void 0 || this.buffers.has(eventId);
|
|
1169
2014
|
const destination = currentReplayTraceDestination();
|
|
@@ -1171,7 +2016,7 @@ var EventShipper = class {
|
|
|
1171
2016
|
if ((capturedSticky == null ? void 0 : capturedSticky.replayOnly) === true || !eventAlreadyKnown && cloudReplay) {
|
|
1172
2017
|
if (patch.isPending === false) this.sticky.delete(eventId);
|
|
1173
2018
|
else this.sticky.set(eventId, { ...capturedSticky, replayOnly: true });
|
|
1174
|
-
return;
|
|
2019
|
+
return void 0;
|
|
1175
2020
|
}
|
|
1176
2021
|
const maxChars = resolveMaxTextFieldChars(this.maxTextFieldCharsOpt);
|
|
1177
2022
|
if (typeof patch.input === "string" && patch.input.length > maxChars) {
|
|
@@ -1194,11 +2039,12 @@ var EventShipper = class {
|
|
|
1194
2039
|
}
|
|
1195
2040
|
const sticky = (_c = this.sticky.get(eventId)) != null ? _c : {};
|
|
1196
2041
|
const existing = (_d = this.buffers.get(eventId)) != null ? _d : {};
|
|
2042
|
+
const explicitProperties = patch.callerProperties !== void 0 ? { ...patch.properties, ...patch.callerProperties } : patch.properties;
|
|
1197
2043
|
patch = {
|
|
1198
2044
|
...patch,
|
|
1199
2045
|
properties: withAppGitProperties(
|
|
1200
2046
|
patch.properties,
|
|
1201
|
-
this.appGitContext.forOperation(eventId,
|
|
2047
|
+
this.appGitContext.forOperation(eventId, explicitProperties, this.appGitOwner)
|
|
1202
2048
|
)
|
|
1203
2049
|
};
|
|
1204
2050
|
const merged = mergePatches(existing, patch);
|
|
@@ -1208,47 +2054,165 @@ var EventShipper = class {
|
|
|
1208
2054
|
userId: (_h = merged.userId) != null ? _h : sticky.userId,
|
|
1209
2055
|
convoId: (_i = merged.convoId) != null ? _i : sticky.convoId,
|
|
1210
2056
|
eventName: (_j = merged.eventName) != null ? _j : sticky.eventName,
|
|
1211
|
-
isPending: (_k = merged.isPending) != null ? _k : sticky.isPending
|
|
2057
|
+
isPending: (_k = merged.isPending) != null ? _k : sticky.isPending,
|
|
2058
|
+
startedAt: (_l = earliestIsoTimestamp(sticky.startedAt, patch.timestamp)) != null ? _l : (/* @__PURE__ */ new Date()).toISOString(),
|
|
2059
|
+
resumed: sticky.resumed,
|
|
2060
|
+
hasContent: sticky.hasContent === true || patchHasContent(patch),
|
|
2061
|
+
callerProperties: patch.callerProperties !== void 0 ? deepMergeProperties((_m = sticky.callerProperties) != null ? _m : {}, patch.callerProperties) : sticky.callerProperties
|
|
1212
2062
|
});
|
|
1213
2063
|
const t = this.timers.get(eventId);
|
|
1214
2064
|
if (t) clearTimeout(t);
|
|
1215
2065
|
if (merged.isPending === false) {
|
|
1216
|
-
|
|
2066
|
+
if (!manual) this.lastFinished = eventId;
|
|
2067
|
+
this.noteFinish(eventId);
|
|
2068
|
+
this.noteEmptyFinish(eventId);
|
|
2069
|
+
const fate = await this.flushOne(eventId);
|
|
1217
2070
|
if (this.appGitContext.releaseOperation) this.appGitContext.releaseOperation(eventId, this.appGitOwner);
|
|
1218
2071
|
else this.appGitContext.finishOperation(eventId);
|
|
1219
|
-
return;
|
|
2072
|
+
return fate;
|
|
1220
2073
|
}
|
|
1221
2074
|
const timeout = setTimeout(() => {
|
|
1222
2075
|
void this.flushOne(eventId).catch(() => {
|
|
1223
2076
|
});
|
|
1224
2077
|
}, this.partialFlushMs);
|
|
1225
2078
|
this.timers.set(eventId, timeout);
|
|
2079
|
+
return void 0;
|
|
2080
|
+
}
|
|
2081
|
+
/**
|
|
2082
|
+
* A second finish for an event is still sent (ingest finalizes once and
|
|
2083
|
+
* treats it as an update, CONTRACT §10.2), but it usually means several
|
|
2084
|
+
* calls share one event id by mistake, so it is warned about.
|
|
2085
|
+
*/
|
|
2086
|
+
noteFinish(eventId) {
|
|
2087
|
+
if (this.finishedEventIds.has(eventId)) {
|
|
2088
|
+
rateLimitedLog(
|
|
2089
|
+
`${this.prefix}.repeated_finish`,
|
|
2090
|
+
() => console.warn(
|
|
2091
|
+
`${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.`
|
|
2092
|
+
)
|
|
2093
|
+
);
|
|
2094
|
+
return;
|
|
2095
|
+
}
|
|
2096
|
+
this.finishedEventIds.add(eventId);
|
|
2097
|
+
if (this.finishedEventIds.size > FINISHED_EVENT_MEMORY) {
|
|
2098
|
+
const oldest = this.finishedEventIds.values().next().value;
|
|
2099
|
+
if (oldest !== void 0) this.finishedEventIds.delete(oldest);
|
|
2100
|
+
}
|
|
2101
|
+
}
|
|
2102
|
+
/**
|
|
2103
|
+
* An event finished with no input, output or attachments is almost always a
|
|
2104
|
+
* caller bug (CONTRACT §14.2, rule C5); it is sent anyway and warned about.
|
|
2105
|
+
* Not for a resumed event: its content may have been sent by another process.
|
|
2106
|
+
*/
|
|
2107
|
+
noteEmptyFinish(eventId) {
|
|
2108
|
+
const sticky = this.sticky.get(eventId);
|
|
2109
|
+
if ((sticky == null ? void 0 : sticky.resumed) === true || (sticky == null ? void 0 : sticky.hasContent) === true) return;
|
|
2110
|
+
rateLimitedLog(
|
|
2111
|
+
`${this.prefix}.empty_finish`,
|
|
2112
|
+
() => console.warn(
|
|
2113
|
+
`${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.`
|
|
2114
|
+
)
|
|
2115
|
+
);
|
|
2116
|
+
}
|
|
2117
|
+
/**
|
|
2118
|
+
* Continue an event that was begun elsewhere (another process, a queue
|
|
2119
|
+
* worker, a later request) using only its id. No request is sent; later
|
|
2120
|
+
* `patch` / `finish` calls for this id are sent even without a `userId`,
|
|
2121
|
+
* and ingest keeps the user, conversation and start time it already has.
|
|
2122
|
+
* Pass `userId` / `convoId` / `eventName` if you have them.
|
|
2123
|
+
*/
|
|
2124
|
+
resume(eventId, options = {}) {
|
|
2125
|
+
var _a, _b, _c;
|
|
2126
|
+
if (!this.enabled) return;
|
|
2127
|
+
if (!eventId || !eventId.trim()) return;
|
|
2128
|
+
const sticky = (_a = this.sticky.get(eventId)) != null ? _a : {};
|
|
2129
|
+
this.sticky.set(eventId, {
|
|
2130
|
+
...sticky,
|
|
2131
|
+
userId: isMissingUserId(options.userId) ? sticky.userId : options.userId,
|
|
2132
|
+
convoId: (_b = options.convoId) != null ? _b : sticky.convoId,
|
|
2133
|
+
eventName: (_c = options.eventName) != null ? _c : sticky.eventName,
|
|
2134
|
+
resumed: true
|
|
2135
|
+
});
|
|
1226
2136
|
}
|
|
1227
2137
|
async finish(eventId, patch) {
|
|
1228
|
-
|
|
2138
|
+
const update = { ...patch, isPending: false };
|
|
2139
|
+
if (MANUAL_UPDATES.has(patch)) MANUAL_UPDATES.add(update);
|
|
2140
|
+
await this.patch(eventId, update);
|
|
1229
2141
|
}
|
|
2142
|
+
/**
|
|
2143
|
+
* Send everything buffered, open (pending) events included, within
|
|
2144
|
+
* `flushTimeoutMs` (CONTRACT 1.2.1). Resolves, never rejects, to whether it
|
|
2145
|
+
* all reached ingest; when it didn't, it also warns. At the deadline,
|
|
2146
|
+
* payloads not yet sent stay queued for a later send and a request cut off
|
|
2147
|
+
* mid-flight is dropped. Sends already running when it was called are
|
|
2148
|
+
* waited for up to the deadline and then cut off.
|
|
2149
|
+
*/
|
|
1230
2150
|
async flush() {
|
|
1231
|
-
|
|
2151
|
+
const result = await this.drainAll(Date.now() + this.flushTimeoutMs);
|
|
2152
|
+
if (!result.delivered && this.shutdownDeadlineAt === void 0) {
|
|
2153
|
+
rateLimitedLog(
|
|
2154
|
+
`${this.prefix}.flush_undelivered`,
|
|
2155
|
+
() => console.warn(`${this.prefix} ${describeUndelivered("flush()", result)}`)
|
|
2156
|
+
);
|
|
2157
|
+
}
|
|
2158
|
+
return asCompat(result);
|
|
2159
|
+
}
|
|
2160
|
+
async drainAll(deadlineAt) {
|
|
2161
|
+
if (!this.enabled) return { ...DELIVERED };
|
|
2162
|
+
const deferred = [...this.deferredSends];
|
|
2163
|
+
this.deferredSends.clear();
|
|
2164
|
+
for (const entry of deferred) if (entry.timer) clearTimeout(entry.timer);
|
|
1232
2165
|
const ids = [...this.buffers.keys()];
|
|
1233
|
-
await Promise.all(
|
|
1234
|
-
|
|
1235
|
-
|
|
2166
|
+
const fates = await Promise.all([
|
|
2167
|
+
...ids.map((id) => this.flushOne(id, deadlineAt)),
|
|
2168
|
+
...deferred.map((entry) => entry.send(deadlineAt))
|
|
2169
|
+
]);
|
|
2170
|
+
const background = [...this.background];
|
|
2171
|
+
if (background.length > 0) {
|
|
2172
|
+
await raceWithTimeout(Promise.all(background), deadlineAt - Date.now());
|
|
2173
|
+
}
|
|
2174
|
+
for (; this.backgroundDrops > 0; this.backgroundDrops -= 1) fates.push("dropped");
|
|
2175
|
+
const running = [...this.inFlight];
|
|
2176
|
+
const { settled, stillRunning } = await awaitEarlierSends(
|
|
2177
|
+
running,
|
|
2178
|
+
deadlineAt,
|
|
2179
|
+
this.cutOff,
|
|
2180
|
+
(p) => this.inFlight.has(p)
|
|
2181
|
+
);
|
|
2182
|
+
const unresolved = background.filter((op) => this.background.has(op)).length;
|
|
2183
|
+
return summarize2(
|
|
2184
|
+
fates.filter((fate) => fate !== void 0),
|
|
2185
|
+
Math.max(stillRunning, unresolved),
|
|
2186
|
+
!settled || unresolved > 0
|
|
2187
|
+
);
|
|
1236
2188
|
}
|
|
2189
|
+
/**
|
|
2190
|
+
* Flush within `flushTimeoutMs` and stop. Sends retry while the window
|
|
2191
|
+
* allows; whatever is left at the deadline is dropped with a warning, so a
|
|
2192
|
+
* dead network can never wedge process exit. Resolves, never rejects.
|
|
2193
|
+
*/
|
|
1237
2194
|
async shutdown() {
|
|
1238
2195
|
this.hasShutdown = true;
|
|
1239
|
-
|
|
2196
|
+
const deadlineAt = Date.now() + this.flushTimeoutMs;
|
|
2197
|
+
this.shutdownDeadlineAt = deadlineAt;
|
|
2198
|
+
let result = { ...DELIVERED };
|
|
1240
2199
|
try {
|
|
1241
2200
|
for (const t of this.timers.values()) clearTimeout(t);
|
|
1242
2201
|
this.timers.clear();
|
|
1243
2202
|
for (const [eventId, sticky] of this.sticky) {
|
|
1244
2203
|
if (sticky.replayOnly) this.sticky.delete(eventId);
|
|
1245
2204
|
}
|
|
1246
|
-
|
|
1247
|
-
if (!
|
|
2205
|
+
result = await this.drainAll(deadlineAt);
|
|
2206
|
+
if (!result.delivered) {
|
|
2207
|
+
this.warnShutdownDrop(
|
|
2208
|
+
`${result.dropped + result.queued + result.inFlight} payload(s) not delivered`
|
|
2209
|
+
);
|
|
2210
|
+
}
|
|
1248
2211
|
} finally {
|
|
1249
2212
|
this.shutdownDeadlineAt = void 0;
|
|
1250
2213
|
if (this.ownsAppGitContext) this.appGitContext.dispose();
|
|
1251
2214
|
}
|
|
2215
|
+
return asCompat(result);
|
|
1252
2216
|
}
|
|
1253
2217
|
async trackSignal(signal) {
|
|
1254
2218
|
var _a, _b;
|
|
@@ -1269,23 +2233,9 @@ var EventShipper = class {
|
|
|
1269
2233
|
...signal.after ? { after: signal.after } : {}
|
|
1270
2234
|
}
|
|
1271
2235
|
}
|
|
1272
|
-
];
|
|
2236
|
+
].map((item) => this.redactFields("signal", item));
|
|
1273
2237
|
if (!this.writeKey) return;
|
|
1274
|
-
|
|
1275
|
-
const opts = this.requestOpts();
|
|
1276
|
-
if (!opts) {
|
|
1277
|
-
this.warnShutdownDrop("signal");
|
|
1278
|
-
return;
|
|
1279
|
-
}
|
|
1280
|
-
try {
|
|
1281
|
-
await postJson(url, body, this.requestHeaders(), opts);
|
|
1282
|
-
} catch (err) {
|
|
1283
|
-
const msg = err instanceof Error ? err.message : String(err);
|
|
1284
|
-
rateLimitedLog(
|
|
1285
|
-
`${this.prefix}.send_signal_failed`,
|
|
1286
|
-
() => console.warn(`${this.prefix} failed to send signal (dropping): ${msg}`)
|
|
1287
|
-
);
|
|
1288
|
-
}
|
|
2238
|
+
await this.sendDirect("signal", `${this.baseUrl}signals/track`, body);
|
|
1289
2239
|
}
|
|
1290
2240
|
async identify(users) {
|
|
1291
2241
|
if (!this.enabled) return;
|
|
@@ -1300,30 +2250,80 @@ var EventShipper = class {
|
|
|
1300
2250
|
return false;
|
|
1301
2251
|
}
|
|
1302
2252
|
return true;
|
|
1303
|
-
}).map(
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
|
|
2253
|
+
}).map(
|
|
2254
|
+
(user) => {
|
|
2255
|
+
var _a;
|
|
2256
|
+
return this.redactFields("identify", {
|
|
2257
|
+
user_id: user.userId,
|
|
2258
|
+
traits: (_a = user.traits) != null ? _a : {}
|
|
2259
|
+
});
|
|
2260
|
+
}
|
|
2261
|
+
);
|
|
1310
2262
|
if (!this.writeKey) return;
|
|
1311
2263
|
if (body.length === 0) return;
|
|
1312
|
-
|
|
1313
|
-
|
|
2264
|
+
await this.sendDirect("identify", `${this.baseUrl}users/identify`, body);
|
|
2265
|
+
}
|
|
2266
|
+
/**
|
|
2267
|
+
* Send a signal or identify body. Tracked so `flush()` waits for it. A send
|
|
2268
|
+
* a flush deadline deferred is kept and retried later (outside shutdown).
|
|
2269
|
+
*/
|
|
2270
|
+
async sendDirect(kind, url, body, deadlineAt) {
|
|
2271
|
+
const opts = this.requestOpts(deadlineAt);
|
|
1314
2272
|
if (!opts) {
|
|
1315
|
-
this.warnShutdownDrop(
|
|
1316
|
-
return;
|
|
2273
|
+
this.warnShutdownDrop(kind);
|
|
2274
|
+
return "dropped";
|
|
1317
2275
|
}
|
|
2276
|
+
const sending = sendJson(url, body, this.requestHeaders(), opts);
|
|
2277
|
+
const tracked = sending.then(() => void 0);
|
|
2278
|
+
this.inFlight.add(tracked);
|
|
2279
|
+
let outcome;
|
|
1318
2280
|
try {
|
|
1319
|
-
|
|
1320
|
-
}
|
|
1321
|
-
|
|
2281
|
+
outcome = await sending;
|
|
2282
|
+
} finally {
|
|
2283
|
+
this.inFlight.delete(tracked);
|
|
2284
|
+
}
|
|
2285
|
+
const fate = fateOf(outcome, this.shuttingDown());
|
|
2286
|
+
if (fate === "queued") {
|
|
2287
|
+
this.deferSend(
|
|
2288
|
+
(later) => this.sendDirect(kind, url, body, later),
|
|
2289
|
+
outcome.status === "deferred" ? outcome.retryAtMs : void 0
|
|
2290
|
+
);
|
|
2291
|
+
} else if (fate === "dropped") {
|
|
2292
|
+
this.warnSendDropped(kind, outcome);
|
|
2293
|
+
}
|
|
2294
|
+
return fate;
|
|
2295
|
+
}
|
|
2296
|
+
deferSend(send, retryAtMs) {
|
|
2297
|
+
var _a, _b;
|
|
2298
|
+
if (this.deferredSends.size >= MAX_DEFERRED_SENDS) {
|
|
1322
2299
|
rateLimitedLog(
|
|
1323
|
-
`${this.prefix}.
|
|
1324
|
-
() => console.warn(`${this.prefix}
|
|
2300
|
+
`${this.prefix}.deferred_full`,
|
|
2301
|
+
() => console.warn(`${this.prefix} too many sends waiting for a retry; dropping one`)
|
|
1325
2302
|
);
|
|
2303
|
+
return;
|
|
1326
2304
|
}
|
|
2305
|
+
const entry = { send };
|
|
2306
|
+
const delay = Math.max(this.partialFlushMs, (retryAtMs != null ? retryAtMs : 0) - Date.now());
|
|
2307
|
+
entry.timer = setTimeout(() => {
|
|
2308
|
+
if (!this.deferredSends.delete(entry)) return;
|
|
2309
|
+
void send().catch(() => {
|
|
2310
|
+
});
|
|
2311
|
+
}, delay);
|
|
2312
|
+
(_b = (_a = entry.timer).unref) == null ? void 0 : _b.call(_a);
|
|
2313
|
+
this.deferredSends.add(entry);
|
|
2314
|
+
}
|
|
2315
|
+
warnSendDropped(what, outcome) {
|
|
2316
|
+
var _a, _b;
|
|
2317
|
+
if (outcome.status === "delivered" || outcome.status === "rejected") return;
|
|
2318
|
+
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;
|
|
2319
|
+
rateLimitedLog(
|
|
2320
|
+
`${this.prefix}.send_${what}_dropped`,
|
|
2321
|
+
() => console.warn(`${this.prefix} failed to send ${what} (dropping): ${reason}`)
|
|
2322
|
+
);
|
|
2323
|
+
}
|
|
2324
|
+
/** The payload with its PII fields redacted when `redactPii` is on (CONTRACT 11.2). */
|
|
2325
|
+
redactFields(kind, payload) {
|
|
2326
|
+
return this.redactPii ? this.piiFields.redact(kind, payload) : payload;
|
|
1327
2327
|
}
|
|
1328
2328
|
warnShutdownDrop(what) {
|
|
1329
2329
|
rateLimitedLog(
|
|
@@ -1331,9 +2331,8 @@ var EventShipper = class {
|
|
|
1331
2331
|
() => console.warn(`${this.prefix} shutdown flush deadline exceeded; dropping ${what}`)
|
|
1332
2332
|
);
|
|
1333
2333
|
}
|
|
1334
|
-
async flushOne(eventId) {
|
|
1335
|
-
|
|
1336
|
-
if (!this.enabled) return;
|
|
2334
|
+
async flushOne(eventId, deadlineAt) {
|
|
2335
|
+
if (!this.enabled) return void 0;
|
|
1337
2336
|
const timer = this.timers.get(eventId);
|
|
1338
2337
|
if (timer) {
|
|
1339
2338
|
clearTimeout(timer);
|
|
@@ -1341,30 +2340,91 @@ var EventShipper = class {
|
|
|
1341
2340
|
}
|
|
1342
2341
|
const accumulated = this.buffers.get(eventId);
|
|
1343
2342
|
this.buffers.delete(eventId);
|
|
1344
|
-
if (!accumulated) return;
|
|
2343
|
+
if (!accumulated) return void 0;
|
|
2344
|
+
const previous = this.sendChains.get(eventId);
|
|
2345
|
+
let release = () => {
|
|
2346
|
+
};
|
|
2347
|
+
const current = new Promise((resolve2) => {
|
|
2348
|
+
release = resolve2;
|
|
2349
|
+
});
|
|
2350
|
+
this.sendChains.set(eventId, current);
|
|
2351
|
+
try {
|
|
2352
|
+
if (previous) {
|
|
2353
|
+
const ready = deadlineAt === void 0 ? (await previous, true) : await raceWithTimeout(previous, deadlineAt - Date.now());
|
|
2354
|
+
if (!ready) {
|
|
2355
|
+
return this.requeue(eventId, accumulated, void 0);
|
|
2356
|
+
}
|
|
2357
|
+
}
|
|
2358
|
+
return await this.sendAccumulated(eventId, accumulated, deadlineAt);
|
|
2359
|
+
} finally {
|
|
2360
|
+
release();
|
|
2361
|
+
if (this.sendChains.get(eventId) === current) this.sendChains.delete(eventId);
|
|
2362
|
+
}
|
|
2363
|
+
}
|
|
2364
|
+
/**
|
|
2365
|
+
* Put an unsent update back under any newer one and send it later
|
|
2366
|
+
* (CONTRACT 1.2.1). During shutdown it is dropped instead.
|
|
2367
|
+
*/
|
|
2368
|
+
requeue(eventId, accumulated, retryAtMs) {
|
|
2369
|
+
var _a, _b;
|
|
2370
|
+
if (this.shuttingDown()) {
|
|
2371
|
+
this.warnShutdownDrop(`track_partial ${eventId}`);
|
|
2372
|
+
if (accumulated.isPending === false) this.sticky.delete(eventId);
|
|
2373
|
+
return "dropped";
|
|
2374
|
+
}
|
|
2375
|
+
const newer = this.buffers.get(eventId);
|
|
2376
|
+
const merged = newer ? mergePatches(accumulated, newer) : accumulated;
|
|
2377
|
+
merged.isPending = (_a = newer == null ? void 0 : newer.isPending) != null ? _a : accumulated.isPending;
|
|
2378
|
+
this.buffers.set(eventId, merged);
|
|
2379
|
+
const existing = this.timers.get(eventId);
|
|
2380
|
+
if (existing) clearTimeout(existing);
|
|
2381
|
+
const delay = Math.max(this.partialFlushMs, (retryAtMs != null ? retryAtMs : 0) - Date.now());
|
|
2382
|
+
const timeout = setTimeout(() => {
|
|
2383
|
+
void this.flushOne(eventId).catch(() => {
|
|
2384
|
+
});
|
|
2385
|
+
}, delay);
|
|
2386
|
+
(_b = timeout.unref) == null ? void 0 : _b.call(timeout);
|
|
2387
|
+
this.timers.set(eventId, timeout);
|
|
2388
|
+
return "queued";
|
|
2389
|
+
}
|
|
2390
|
+
async sendAccumulated(eventId, accumulated, deadlineAt) {
|
|
2391
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p;
|
|
1345
2392
|
const sticky = (_a = this.sticky.get(eventId)) != null ? _a : {};
|
|
1346
2393
|
const isPending = (_c = (_b = accumulated.isPending) != null ? _b : sticky.isPending) != null ? _c : true;
|
|
1347
|
-
const
|
|
1348
|
-
const
|
|
1349
|
-
|
|
1350
|
-
|
|
1351
|
-
|
|
1352
|
-
|
|
2394
|
+
const knownEventName = (_d = accumulated.eventName) != null ? _d : sticky.eventName;
|
|
2395
|
+
const eventName = knownEventName != null ? knownEventName : sticky.resumed ? void 0 : this.defaultEventName;
|
|
2396
|
+
const userId = (_e = accumulated.userId) != null ? _e : sticky.userId;
|
|
2397
|
+
if (!userId && !sticky.resumed) {
|
|
2398
|
+
rateLimitedLog(
|
|
2399
|
+
`${this.prefix}.track_partial_missing_user`,
|
|
2400
|
+
() => console.warn(
|
|
2401
|
+
`${this.prefix} skipping track_partial for ${eventId}: missing userId (pass userId, or call resume(eventId) to continue an event begun elsewhere)`
|
|
2402
|
+
)
|
|
2403
|
+
);
|
|
1353
2404
|
this.sticky.delete(eventId);
|
|
1354
|
-
return;
|
|
2405
|
+
return void 0;
|
|
2406
|
+
}
|
|
2407
|
+
if (!userId) {
|
|
2408
|
+
rateLimitedLog(
|
|
2409
|
+
`${this.prefix}.track_partial_resumed_without_user`,
|
|
2410
|
+
() => console.warn(
|
|
2411
|
+
`${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)`
|
|
2412
|
+
)
|
|
2413
|
+
);
|
|
1355
2414
|
}
|
|
1356
|
-
const { wizardSession, ...restProperties } = (
|
|
2415
|
+
const { wizardSession, ...restProperties } = (_f = accumulated.properties) != null ? _f : {};
|
|
1357
2416
|
let telemetryProperties = {};
|
|
1358
2417
|
try {
|
|
1359
2418
|
telemetryProperties = eventTelemetryProperties(accumulated);
|
|
1360
2419
|
} catch (e) {
|
|
1361
2420
|
}
|
|
1362
|
-
const convoId = (
|
|
1363
|
-
const
|
|
2421
|
+
const convoId = (_g = accumulated.convoId) != null ? _g : sticky.convoId;
|
|
2422
|
+
const sessionTag = wizardSession != null ? wizardSession : this.wizardSession;
|
|
2423
|
+
const unredacted = {
|
|
1364
2424
|
event_id: eventId,
|
|
1365
|
-
user_id: userId,
|
|
1366
|
-
event: eventName,
|
|
1367
|
-
timestamp: (_i = accumulated.timestamp) != null ? _i : (/* @__PURE__ */ new Date()).toISOString(),
|
|
2425
|
+
...userId ? { user_id: userId } : {},
|
|
2426
|
+
...eventName ? { event: eventName } : {},
|
|
2427
|
+
timestamp: (_i = (_h = sticky.startedAt) != null ? _h : accumulated.timestamp) != null ? _i : (/* @__PURE__ */ new Date()).toISOString(),
|
|
1368
2428
|
ai_data: {
|
|
1369
2429
|
input: accumulated.input,
|
|
1370
2430
|
output: accumulated.error !== void 0 && accumulated.error !== null ? void 0 : accumulated.output,
|
|
@@ -1372,32 +2432,38 @@ var EventShipper = class {
|
|
|
1372
2432
|
convo_id: convoId
|
|
1373
2433
|
},
|
|
1374
2434
|
properties: {
|
|
1375
|
-
...
|
|
1376
|
-
|
|
1377
|
-
|
|
2435
|
+
...this.withCallerProperties(
|
|
2436
|
+
eventId,
|
|
2437
|
+
{ ...restProperties, ...telemetryProperties },
|
|
2438
|
+
(_j = sticky.callerProperties) != null ? _j : accumulated.callerProperties
|
|
2439
|
+
),
|
|
2440
|
+
...sessionTag ? { "raindrop.wizardSession": sessionTag } : {},
|
|
1378
2441
|
$context: this.context
|
|
1379
2442
|
},
|
|
1380
2443
|
...accumulated.featureFlags && Object.keys(accumulated.featureFlags).length > 0 ? { feature_flags: accumulated.featureFlags } : {},
|
|
1381
2444
|
attachments: accumulated.attachments,
|
|
1382
2445
|
is_pending: isPending
|
|
1383
2446
|
};
|
|
2447
|
+
const payload = this.redactFields("event", unredacted);
|
|
1384
2448
|
const url = `${this.baseUrl}events/track_partial`;
|
|
1385
2449
|
if (this.debug) {
|
|
2450
|
+
const sent = payload;
|
|
2451
|
+
const preview = (v, n) => typeof v === "string" ? v.slice(0, n) : void 0;
|
|
1386
2452
|
console.log(`${this.prefix} sending track_partial`, {
|
|
1387
2453
|
eventId,
|
|
1388
2454
|
eventName,
|
|
1389
2455
|
userId,
|
|
1390
2456
|
convoId,
|
|
1391
2457
|
isPending,
|
|
1392
|
-
inputPreview:
|
|
1393
|
-
outputPreview:
|
|
1394
|
-
attachments: (
|
|
1395
|
-
attachmentKinds: (
|
|
2458
|
+
inputPreview: preview((_k = sent.ai_data) == null ? void 0 : _k.input, 120),
|
|
2459
|
+
outputPreview: preview((_l = sent.ai_data) == null ? void 0 : _l.output, 120),
|
|
2460
|
+
attachments: (_n = (_m = sent.attachments) == null ? void 0 : _m.length) != null ? _n : 0,
|
|
2461
|
+
attachmentKinds: (_p = (_o = sent.attachments) == null ? void 0 : _o.map((a) => ({
|
|
1396
2462
|
type: a.type,
|
|
1397
2463
|
role: a.role,
|
|
1398
2464
|
name: a.name,
|
|
1399
|
-
valuePreview: a.value
|
|
1400
|
-
}))) != null ?
|
|
2465
|
+
valuePreview: preview(a.value, 60)
|
|
2466
|
+
}))) != null ? _p : [],
|
|
1401
2467
|
endpoint: url
|
|
1402
2468
|
});
|
|
1403
2469
|
}
|
|
@@ -1410,39 +2476,94 @@ var EventShipper = class {
|
|
|
1410
2476
|
if (!this.writeKey) {
|
|
1411
2477
|
if (!isPending) this.sticky.delete(eventId);
|
|
1412
2478
|
if (mirror) await mirror;
|
|
1413
|
-
return;
|
|
2479
|
+
return void 0;
|
|
1414
2480
|
}
|
|
1415
|
-
const opts = this.requestOpts();
|
|
2481
|
+
const opts = this.requestOpts(deadlineAt);
|
|
1416
2482
|
if (!opts) {
|
|
1417
2483
|
this.warnShutdownDrop(`track_partial ${eventId}`);
|
|
1418
2484
|
if (!isPending) this.sticky.delete(eventId);
|
|
1419
2485
|
if (mirror) await mirror;
|
|
1420
|
-
return;
|
|
2486
|
+
return "dropped";
|
|
1421
2487
|
}
|
|
1422
|
-
const
|
|
1423
|
-
const combined =
|
|
2488
|
+
const sending = sendJson(url, payload, this.requestHeaders(), opts);
|
|
2489
|
+
const combined = Promise.all([mirror, sending.then(() => void 0)]).then(() => void 0);
|
|
1424
2490
|
this.inFlight.add(combined);
|
|
2491
|
+
let outcome;
|
|
1425
2492
|
try {
|
|
1426
|
-
|
|
1427
|
-
|
|
1428
|
-
|
|
1429
|
-
console.log(`${this.prefix} sent track_partial ${eventId} (${eventName})`);
|
|
1430
|
-
}
|
|
1431
|
-
} catch (err) {
|
|
1432
|
-
const msg = err instanceof Error ? err.message : String(err);
|
|
1433
|
-
rateLimitedLog(
|
|
1434
|
-
`${this.prefix}.send_track_partial_failed`,
|
|
1435
|
-
() => console.warn(`${this.prefix} failed to send track_partial (dropping): ${msg}`)
|
|
1436
|
-
);
|
|
1437
|
-
}
|
|
2493
|
+
outcome = await sending;
|
|
2494
|
+
if (mirror) await mirror.catch(() => {
|
|
2495
|
+
});
|
|
1438
2496
|
} finally {
|
|
1439
2497
|
this.inFlight.delete(combined);
|
|
1440
2498
|
}
|
|
2499
|
+
const fate = fateOf(outcome, this.shuttingDown());
|
|
2500
|
+
if (fate === "queued") {
|
|
2501
|
+
return this.requeue(
|
|
2502
|
+
eventId,
|
|
2503
|
+
accumulated,
|
|
2504
|
+
outcome.status === "deferred" ? outcome.retryAtMs : void 0
|
|
2505
|
+
);
|
|
2506
|
+
}
|
|
2507
|
+
if (fate === "dropped") this.warnSendDropped("track_partial", outcome);
|
|
2508
|
+
else if (this.debug && outcome.status === "delivered") {
|
|
2509
|
+
console.log(`${this.prefix} sent track_partial ${eventId} (${eventName})`);
|
|
2510
|
+
}
|
|
1441
2511
|
if (!isPending) {
|
|
1442
2512
|
this.sticky.delete(eventId);
|
|
1443
2513
|
}
|
|
2514
|
+
return fate;
|
|
1444
2515
|
}
|
|
1445
2516
|
};
|
|
2517
|
+
function overriddenKeys(derived, caller) {
|
|
2518
|
+
const keys = [];
|
|
2519
|
+
for (const [key, value] of Object.entries(caller)) {
|
|
2520
|
+
if (value === void 0 || !(key in derived)) continue;
|
|
2521
|
+
const existing = derived[key];
|
|
2522
|
+
if (isPlainObject2(existing) && isPlainObject2(value)) {
|
|
2523
|
+
if (overriddenKeys(existing, value).length > 0) keys.push(key);
|
|
2524
|
+
} else if (JSON.stringify(existing) !== JSON.stringify(value)) {
|
|
2525
|
+
keys.push(key);
|
|
2526
|
+
}
|
|
2527
|
+
}
|
|
2528
|
+
return keys;
|
|
2529
|
+
}
|
|
2530
|
+
function patchHasContent(patch) {
|
|
2531
|
+
var _a, _b;
|
|
2532
|
+
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;
|
|
2533
|
+
}
|
|
2534
|
+
function resolveFlushTimeoutMs(value) {
|
|
2535
|
+
return typeof value === "number" && Number.isFinite(value) && value > 0 ? value : DEFAULT_FLUSH_TIMEOUT_MS;
|
|
2536
|
+
}
|
|
2537
|
+
function createEventsApi(shipper) {
|
|
2538
|
+
return {
|
|
2539
|
+
async patch(eventId, patch) {
|
|
2540
|
+
await (shipper == null ? void 0 : shipper.patch(eventId, markManualUpdate(asCallerPatch(patch))));
|
|
2541
|
+
},
|
|
2542
|
+
async finish(eventId, patch = {}) {
|
|
2543
|
+
await (shipper == null ? void 0 : shipper.finish(eventId, markManualUpdate(asCallerPatch(patch))));
|
|
2544
|
+
},
|
|
2545
|
+
async addAttachments(eventId, attachments) {
|
|
2546
|
+
await (shipper == null ? void 0 : shipper.patch(eventId, markManualUpdate({ attachments })));
|
|
2547
|
+
},
|
|
2548
|
+
async setProperties(eventId, properties) {
|
|
2549
|
+
await (shipper == null ? void 0 : shipper.patch(eventId, markManualUpdate({ properties, callerProperties: properties })));
|
|
2550
|
+
},
|
|
2551
|
+
async setFeatureFlags(eventId, featureFlags) {
|
|
2552
|
+
await (shipper == null ? void 0 : shipper.patch(eventId, markManualUpdate({ featureFlags: normalizeFeatureFlags(featureFlags) })));
|
|
2553
|
+
},
|
|
2554
|
+
resume(eventId, options) {
|
|
2555
|
+
shipper == null ? void 0 : shipper.resume(eventId, options);
|
|
2556
|
+
}
|
|
2557
|
+
};
|
|
2558
|
+
}
|
|
2559
|
+
function asCallerPatch(patch) {
|
|
2560
|
+
var _a;
|
|
2561
|
+
if (!patch.properties) return patch;
|
|
2562
|
+
return {
|
|
2563
|
+
...patch,
|
|
2564
|
+
callerProperties: { ...patch.properties, ...(_a = patch.callerProperties) != null ? _a : {} }
|
|
2565
|
+
};
|
|
2566
|
+
}
|
|
1446
2567
|
var MODEL_USAGE_ATTRIBUTES = {
|
|
1447
2568
|
usageSource: "raindrop.usage.source",
|
|
1448
2569
|
providerName: "gen_ai.provider.name",
|
|
@@ -1502,6 +2623,21 @@ function buildRawModelUsageAttributes(usage) {
|
|
|
1502
2623
|
attrDouble(MODEL_USAGE_ATTRIBUTES.providerReportedCost, providerReportedCost)
|
|
1503
2624
|
].filter((attribute) => attribute !== void 0);
|
|
1504
2625
|
}
|
|
2626
|
+
var KNOWN_MODEL_PROVIDERS = /* @__PURE__ */ new Set([
|
|
2627
|
+
...MODEL_PROVIDER_NAMES.map(([, family]) => family),
|
|
2628
|
+
"vercel",
|
|
2629
|
+
// Further vendors Dawn's pricing resolves (apps/dawn/lib/spend).
|
|
2630
|
+
"deepseek",
|
|
2631
|
+
"fireworks-ai",
|
|
2632
|
+
"groq",
|
|
2633
|
+
"inception",
|
|
2634
|
+
"mistral",
|
|
2635
|
+
"moonshotai",
|
|
2636
|
+
"perplexity",
|
|
2637
|
+
"togetherai",
|
|
2638
|
+
"xai",
|
|
2639
|
+
"zai"
|
|
2640
|
+
]);
|
|
1505
2641
|
var STRING_ALIASES = {
|
|
1506
2642
|
[MODEL_USAGE_ATTRIBUTES.requestModel]: ["ai.model.id", "ai.model"]
|
|
1507
2643
|
};
|
|
@@ -1621,12 +2757,41 @@ var REDACTED_PLACEHOLDER = "[REDACTED]";
|
|
|
1621
2757
|
function normalizeKeyName(name) {
|
|
1622
2758
|
return name.toLowerCase().replace(/[-_.]/g, "");
|
|
1623
2759
|
}
|
|
2760
|
+
var URL_USERINFO = new RegExp(
|
|
2761
|
+
String.raw`\b([a-z][a-z0-9+.-]{0,${DEFAULT_MAX_TEXT_FIELD_CHARS - 1}})(?::\/\/([^\s/?#]{1,${DEFAULT_MAX_TEXT_FIELD_CHARS}})@)?`,
|
|
2762
|
+
"gi"
|
|
2763
|
+
);
|
|
2764
|
+
var URL_QUERY_PARAM = /([?&#]([A-Za-z0-9_.\-]+)=)[^&#?\s"']*/g;
|
|
2765
|
+
var URL_SECRET_QUERY_KEYS = /* @__PURE__ */ new Set([
|
|
2766
|
+
"token",
|
|
2767
|
+
"secret",
|
|
2768
|
+
"sig",
|
|
2769
|
+
"signature",
|
|
2770
|
+
"awsaccesskeyid",
|
|
2771
|
+
"xamzsignature",
|
|
2772
|
+
"xamzcredential",
|
|
2773
|
+
"xamzsecuritytoken",
|
|
2774
|
+
"xgoogsignature"
|
|
2775
|
+
]);
|
|
2776
|
+
var DEFAULT_SECRET_SET = buildSecretSet(DEFAULT_SECRET_KEY_NAMES);
|
|
2777
|
+
function redactUrlSecrets(text, secretSet = DEFAULT_SECRET_SET, placeholder = REDACTED_PLACEHOLDER) {
|
|
2778
|
+
if (text.length > DEFAULT_MAX_TEXT_FIELD_CHARS) return placeholder;
|
|
2779
|
+
if (!text.includes("://") && !text.includes("=")) return text;
|
|
2780
|
+
return text.replace(
|
|
2781
|
+
URL_USERINFO,
|
|
2782
|
+
(whole, scheme, userinfo) => userinfo === void 0 ? whole : `${scheme}://${placeholder}@`
|
|
2783
|
+
).replace(URL_QUERY_PARAM, (whole, prefix, key) => {
|
|
2784
|
+
const normalized = normalizeKeyName(key);
|
|
2785
|
+
return secretSet.has(normalized) || URL_SECRET_QUERY_KEYS.has(normalized) ? `${prefix}${placeholder}` : whole;
|
|
2786
|
+
});
|
|
2787
|
+
}
|
|
1624
2788
|
function redactSecretsInObject(value, options) {
|
|
1625
2789
|
var _a, _b;
|
|
1626
2790
|
const normalizedSecretSet = buildSecretSet((_a = options == null ? void 0 : options.secretKeyNames) != null ? _a : DEFAULT_SECRET_KEY_NAMES);
|
|
1627
2791
|
const placeholder = (_b = options == null ? void 0 : options.placeholder) != null ? _b : REDACTED_PLACEHOLDER;
|
|
1628
2792
|
const seen = /* @__PURE__ */ new WeakSet();
|
|
1629
2793
|
const walk = (node) => {
|
|
2794
|
+
if (typeof node === "string") return redactUrlSecrets(node, normalizedSecretSet, placeholder);
|
|
1630
2795
|
if (node === null || typeof node !== "object") return node;
|
|
1631
2796
|
if (seen.has(node)) return "[CIRCULAR]";
|
|
1632
2797
|
seen.add(node);
|
|
@@ -1725,6 +2890,7 @@ var TraceShipper = class {
|
|
|
1725
2890
|
this.appGitAdded = /* @__PURE__ */ new WeakMap();
|
|
1726
2891
|
this.queue = [];
|
|
1727
2892
|
this.inFlight = /* @__PURE__ */ new Set();
|
|
2893
|
+
this.cutOff = new InFlightCutOff();
|
|
1728
2894
|
this.hasShutdown = false;
|
|
1729
2895
|
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j;
|
|
1730
2896
|
this.appGitContext = (_a = opts.appGitContext) != null ? _a : createAppGitContext(opts.appGit);
|
|
@@ -1737,6 +2903,7 @@ var TraceShipper = class {
|
|
|
1737
2903
|
this.flushIntervalMs = (_d = opts.flushIntervalMs) != null ? _d : 1e3;
|
|
1738
2904
|
this.maxBatchSize = (_e = opts.maxBatchSize) != null ? _e : 50;
|
|
1739
2905
|
this.maxQueueSize = (_f = opts.maxQueueSize) != null ? _f : 5e3;
|
|
2906
|
+
this.flushTimeoutMs = resolveFlushTimeoutMs(opts.flushTimeoutMs);
|
|
1740
2907
|
this.sdkName = (_g = opts.sdkName) != null ? _g : "core";
|
|
1741
2908
|
this.prefix = `[raindrop-ai/${this.sdkName}]`;
|
|
1742
2909
|
this.serviceName = (_h = opts.serviceName) != null ? _h : "raindrop.core";
|
|
@@ -2015,25 +3182,51 @@ var TraceShipper = class {
|
|
|
2015
3182
|
}
|
|
2016
3183
|
this.queue.push(redacted);
|
|
2017
3184
|
if (this.queue.length >= this.maxBatchSize) {
|
|
2018
|
-
void this.
|
|
3185
|
+
void this.drain().catch(() => {
|
|
2019
3186
|
});
|
|
2020
3187
|
return;
|
|
2021
3188
|
}
|
|
2022
|
-
|
|
2023
|
-
|
|
2024
|
-
|
|
2025
|
-
|
|
2026
|
-
|
|
2027
|
-
|
|
2028
|
-
|
|
3189
|
+
this.scheduleDrain(this.flushIntervalMs);
|
|
3190
|
+
}
|
|
3191
|
+
scheduleDrain(delayMs) {
|
|
3192
|
+
if (this.timer) return;
|
|
3193
|
+
this.timer = setTimeout(() => {
|
|
3194
|
+
this.timer = void 0;
|
|
3195
|
+
void this.drain().catch(() => {
|
|
3196
|
+
});
|
|
3197
|
+
}, delayMs);
|
|
2029
3198
|
}
|
|
3199
|
+
/**
|
|
3200
|
+
* Send every queued span within `flushTimeoutMs` (CONTRACT 1.2.1). Resolves,
|
|
3201
|
+
* never rejects, to whether they all reached ingest, and warns when they
|
|
3202
|
+
* didn't. Spans not yet sent at the deadline stay queued.
|
|
3203
|
+
*/
|
|
2030
3204
|
async flush() {
|
|
2031
|
-
|
|
2032
|
-
if (!this.
|
|
2033
|
-
|
|
2034
|
-
|
|
2035
|
-
|
|
3205
|
+
const result = await this.drainWithin(Date.now() + this.flushTimeoutMs);
|
|
3206
|
+
if (!result.delivered && this.shutdownDeadlineAt === void 0) {
|
|
3207
|
+
rateLimitedLog(
|
|
3208
|
+
`${this.prefix}.flush_undelivered`,
|
|
3209
|
+
() => console.warn(`${this.prefix} ${describeUndelivered("flush()", result)}`)
|
|
3210
|
+
);
|
|
2036
3211
|
}
|
|
3212
|
+
return asCompat(result);
|
|
3213
|
+
}
|
|
3214
|
+
async drainWithin(deadlineAt) {
|
|
3215
|
+
const fates = this.enabled ? await this.drain(deadlineAt) : [];
|
|
3216
|
+
const running = [...this.inFlight];
|
|
3217
|
+
const { settled, stillRunning } = await awaitEarlierSends(
|
|
3218
|
+
running,
|
|
3219
|
+
deadlineAt,
|
|
3220
|
+
this.cutOff,
|
|
3221
|
+
(p) => this.inFlight.has(p)
|
|
3222
|
+
);
|
|
3223
|
+
return summarize2(fates, stillRunning, !settled);
|
|
3224
|
+
}
|
|
3225
|
+
/** Send queued batches; with a deadline, a deferred batch goes back on the queue. */
|
|
3226
|
+
async drain(deadlineAt) {
|
|
3227
|
+
var _a;
|
|
3228
|
+
const fates = [];
|
|
3229
|
+
if (!this.enabled) return fates;
|
|
2037
3230
|
if (this.timer) {
|
|
2038
3231
|
clearTimeout(this.timer);
|
|
2039
3232
|
this.timer = void 0;
|
|
@@ -2047,10 +3240,12 @@ var TraceShipper = class {
|
|
|
2047
3240
|
if (spans) spans.push(span);
|
|
2048
3241
|
else groups.set(destination, [span]);
|
|
2049
3242
|
}
|
|
3243
|
+
const requeue = [];
|
|
3244
|
+
let retryAtMs;
|
|
2050
3245
|
for (const [destination, spans] of groups) {
|
|
2051
3246
|
if (!destination && !this.writeKey) continue;
|
|
2052
3247
|
if ((destination == null ? void 0 : destination.kind) === "workshop") continue;
|
|
2053
|
-
const opts = this.requestOpts();
|
|
3248
|
+
const opts = this.requestOpts(deadlineAt);
|
|
2054
3249
|
if (!opts) {
|
|
2055
3250
|
rateLimitedLog(
|
|
2056
3251
|
`${this.prefix}.shutdown_deadline`,
|
|
@@ -2058,6 +3253,7 @@ var TraceShipper = class {
|
|
|
2058
3253
|
`${this.prefix} shutdown flush deadline exceeded; dropping ${spans.length} spans`
|
|
2059
3254
|
)
|
|
2060
3255
|
);
|
|
3256
|
+
fates.push("dropped");
|
|
2061
3257
|
continue;
|
|
2062
3258
|
}
|
|
2063
3259
|
const body = buildExportTraceServiceRequest(spans, this.serviceName, this.serviceVersion);
|
|
@@ -2073,35 +3269,56 @@ var TraceShipper = class {
|
|
|
2073
3269
|
endpoint: url
|
|
2074
3270
|
});
|
|
2075
3271
|
}
|
|
2076
|
-
const
|
|
2077
|
-
|
|
3272
|
+
const sending = sendJson(url, body, headers, opts);
|
|
3273
|
+
const tracked = sending.then(() => void 0);
|
|
3274
|
+
this.inFlight.add(tracked);
|
|
3275
|
+
let outcome;
|
|
2078
3276
|
try {
|
|
2079
|
-
|
|
2080
|
-
await p;
|
|
2081
|
-
if (this.debug) console.log(`${this.prefix} sent ${spans.length} spans`);
|
|
2082
|
-
} catch (err) {
|
|
2083
|
-
const msg = err instanceof Error ? err.message : String(err);
|
|
2084
|
-
rateLimitedLog(
|
|
2085
|
-
`${this.prefix}.send_spans_failed`,
|
|
2086
|
-
() => console.warn(`${this.prefix} failed to send ${spans.length} spans: ${msg}`)
|
|
2087
|
-
);
|
|
2088
|
-
}
|
|
3277
|
+
outcome = await sending;
|
|
2089
3278
|
} finally {
|
|
2090
|
-
this.inFlight.delete(
|
|
3279
|
+
this.inFlight.delete(tracked);
|
|
3280
|
+
}
|
|
3281
|
+
const fate = fateOf(outcome, this.shutdownDeadlineAt !== void 0 || this.hasShutdown);
|
|
3282
|
+
fates.push(fate);
|
|
3283
|
+
if (fate === "queued") {
|
|
3284
|
+
requeue.push(...spans);
|
|
3285
|
+
if (outcome.status === "deferred" && outcome.retryAtMs !== void 0) {
|
|
3286
|
+
retryAtMs = Math.max(retryAtMs != null ? retryAtMs : 0, outcome.retryAtMs);
|
|
3287
|
+
}
|
|
3288
|
+
} else if (fate === "dropped") {
|
|
3289
|
+
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;
|
|
3290
|
+
rateLimitedLog(
|
|
3291
|
+
`${this.prefix}.send_spans_failed`,
|
|
3292
|
+
() => console.warn(`${this.prefix} failed to send ${spans.length} spans: ${reason}`)
|
|
3293
|
+
);
|
|
3294
|
+
} else if (this.debug) {
|
|
3295
|
+
console.log(`${this.prefix} sent ${spans.length} spans`);
|
|
3296
|
+
}
|
|
3297
|
+
}
|
|
3298
|
+
if (requeue.length > 0) {
|
|
3299
|
+
this.queue.unshift(...requeue);
|
|
3300
|
+
if (this.queue.length > this.maxQueueSize) {
|
|
3301
|
+
this.queue.splice(this.maxQueueSize);
|
|
2091
3302
|
}
|
|
3303
|
+
this.scheduleDrain(Math.max(this.flushIntervalMs, (retryAtMs != null ? retryAtMs : 0) - Date.now()));
|
|
3304
|
+
break;
|
|
2092
3305
|
}
|
|
2093
3306
|
}
|
|
3307
|
+
return fates;
|
|
3308
|
+
}
|
|
3309
|
+
/** See EventShipper.requestOpts — same deadline semantics. */
|
|
3310
|
+
requestOpts(deadlineAt) {
|
|
3311
|
+
const opts = this.scheduleFor(deadlineAt);
|
|
3312
|
+
return opts && { ...opts, cutOff: this.cutOff.signal };
|
|
2094
3313
|
}
|
|
2095
|
-
|
|
2096
|
-
requestOpts() {
|
|
3314
|
+
scheduleFor(deadlineAt) {
|
|
2097
3315
|
if (this.shutdownDeadlineAt !== void 0) {
|
|
2098
|
-
|
|
2099
|
-
if (remainingMs <= 0) return null;
|
|
3316
|
+
if (this.shutdownDeadlineAt - Date.now() <= 0) return null;
|
|
2100
3317
|
return {
|
|
2101
|
-
maxAttempts:
|
|
3318
|
+
maxAttempts: 3,
|
|
2102
3319
|
debug: this.debug,
|
|
2103
3320
|
sdkName: this.sdkName,
|
|
2104
|
-
|
|
3321
|
+
deadlineAt: Math.min(this.shutdownDeadlineAt, deadlineAt != null ? deadlineAt : Infinity)
|
|
2105
3322
|
};
|
|
2106
3323
|
}
|
|
2107
3324
|
if (this.hasShutdown) {
|
|
@@ -2112,27 +3329,28 @@ var TraceShipper = class {
|
|
|
2112
3329
|
timeoutMs: POST_SHUTDOWN_TIMEOUT_MS
|
|
2113
3330
|
};
|
|
2114
3331
|
}
|
|
2115
|
-
return { maxAttempts: 3, debug: this.debug, sdkName: this.sdkName };
|
|
3332
|
+
return { maxAttempts: 3, debug: this.debug, sdkName: this.sdkName, deadlineAt };
|
|
2116
3333
|
}
|
|
3334
|
+
/**
|
|
3335
|
+
* Flush within `flushTimeoutMs` and stop; spans left at the deadline are
|
|
3336
|
+
* dropped with a warning. Resolves, never rejects.
|
|
3337
|
+
*/
|
|
2117
3338
|
async shutdown() {
|
|
2118
3339
|
this.hasShutdown = true;
|
|
2119
|
-
|
|
3340
|
+
const deadlineAt = Date.now() + this.flushTimeoutMs;
|
|
3341
|
+
this.shutdownDeadlineAt = deadlineAt;
|
|
3342
|
+
let result = { ...DELIVERED };
|
|
2120
3343
|
try {
|
|
2121
3344
|
if (this.timer) {
|
|
2122
3345
|
clearTimeout(this.timer);
|
|
2123
3346
|
this.timer = void 0;
|
|
2124
3347
|
}
|
|
2125
|
-
|
|
2126
|
-
|
|
2127
|
-
await Promise.all([...this.inFlight].map((p) => p.catch(() => {
|
|
2128
|
-
})));
|
|
2129
|
-
};
|
|
2130
|
-
const settled = await raceWithTimeout(drain(), SHUTDOWN_DEADLINE_MS);
|
|
2131
|
-
if (!settled) {
|
|
3348
|
+
result = await this.drainWithin(deadlineAt);
|
|
3349
|
+
if (!result.delivered) {
|
|
2132
3350
|
rateLimitedLog(
|
|
2133
3351
|
`${this.prefix}.shutdown_deadline`,
|
|
2134
3352
|
() => console.warn(
|
|
2135
|
-
`${this.prefix} shutdown flush deadline exceeded;
|
|
3353
|
+
`${this.prefix} shutdown flush deadline exceeded; ${describeUndelivered("shutdown()", result)}`
|
|
2136
3354
|
)
|
|
2137
3355
|
);
|
|
2138
3356
|
}
|
|
@@ -2140,10 +3358,74 @@ var TraceShipper = class {
|
|
|
2140
3358
|
this.shutdownDeadlineAt = void 0;
|
|
2141
3359
|
if (this.ownsAppGitContext) this.appGitContext.dispose();
|
|
2142
3360
|
}
|
|
3361
|
+
return asCompat(result);
|
|
2143
3362
|
}
|
|
2144
3363
|
};
|
|
3364
|
+
function eventShipperOptions(client, extras = {}) {
|
|
3365
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _i;
|
|
3366
|
+
return {
|
|
3367
|
+
...extras,
|
|
3368
|
+
writeKey: (_a = extras.writeKey) != null ? _a : client.writeKey,
|
|
3369
|
+
endpoint: (_b = extras.endpoint) != null ? _b : client.endpoint,
|
|
3370
|
+
projectId: (_c = extras.projectId) != null ? _c : client.projectId,
|
|
3371
|
+
debug: (_e = (_d = extras.debug) != null ? _d : client.debug) != null ? _e : false,
|
|
3372
|
+
maxTextFieldChars: (_f = extras.maxTextFieldChars) != null ? _f : client.maxTextFieldChars,
|
|
3373
|
+
flushTimeoutMs: (_g = extras.flushTimeoutMs) != null ? _g : client.flushTimeoutMs,
|
|
3374
|
+
redactPii: (_h = extras.redactPii) != null ? _h : client.redactPii,
|
|
3375
|
+
redactPiiFields: (_i = extras.redactPiiFields) != null ? _i : client.redactPiiFields
|
|
3376
|
+
};
|
|
3377
|
+
}
|
|
3378
|
+
function traceShipperOptions(client, extras = {}) {
|
|
3379
|
+
var _a, _b, _c, _d, _e, _f, _g;
|
|
3380
|
+
return {
|
|
3381
|
+
...extras,
|
|
3382
|
+
writeKey: (_a = extras.writeKey) != null ? _a : client.writeKey,
|
|
3383
|
+
endpoint: (_b = extras.endpoint) != null ? _b : client.endpoint,
|
|
3384
|
+
projectId: (_c = extras.projectId) != null ? _c : client.projectId,
|
|
3385
|
+
debug: (_e = (_d = extras.debug) != null ? _d : client.debug) != null ? _e : false,
|
|
3386
|
+
maxTextFieldChars: (_f = extras.maxTextFieldChars) != null ? _f : client.maxTextFieldChars,
|
|
3387
|
+
flushTimeoutMs: (_g = extras.flushTimeoutMs) != null ? _g : client.flushTimeoutMs
|
|
3388
|
+
};
|
|
3389
|
+
}
|
|
3390
|
+
function createShippers(client, setup = {}) {
|
|
3391
|
+
return {
|
|
3392
|
+
eventShipper: new EventShipper(eventShipperOptions(client, { ...setup.common, ...setup.event })),
|
|
3393
|
+
traceShipper: new TraceShipper(traceShipperOptions(client, { ...setup.common, ...setup.trace }))
|
|
3394
|
+
};
|
|
3395
|
+
}
|
|
3396
|
+
function isFlushResult(value) {
|
|
3397
|
+
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";
|
|
3398
|
+
}
|
|
3399
|
+
var UNDELIVERED = Object.freeze({
|
|
3400
|
+
delivered: false,
|
|
3401
|
+
timedOut: false,
|
|
3402
|
+
dropped: 0,
|
|
3403
|
+
queued: 0,
|
|
3404
|
+
inFlight: 0
|
|
3405
|
+
});
|
|
3406
|
+
async function settle(call, what) {
|
|
3407
|
+
try {
|
|
3408
|
+
const result = await call();
|
|
3409
|
+
return isFlushResult(result) ? result : DELIVERED;
|
|
3410
|
+
} catch (error) {
|
|
3411
|
+
console.warn(`[raindrop-ai] ${what} failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
3412
|
+
return UNDELIVERED;
|
|
3413
|
+
}
|
|
3414
|
+
}
|
|
3415
|
+
async function flushShippers(...shippers) {
|
|
3416
|
+
const results = await Promise.all(
|
|
3417
|
+
shippers.flatMap((s) => s ? [settle(() => s.flush(), "flush()")] : [])
|
|
3418
|
+
);
|
|
3419
|
+
return asCompat(combineResults(...results));
|
|
3420
|
+
}
|
|
3421
|
+
async function shutdownShippers(...shippers) {
|
|
3422
|
+
const results = await Promise.all(
|
|
3423
|
+
shippers.flatMap((s) => s ? [settle(() => s.shutdown(), "shutdown()")] : [])
|
|
3424
|
+
);
|
|
3425
|
+
return asCompat(combineResults(...results));
|
|
3426
|
+
}
|
|
2145
3427
|
var PROMPT_TOOLS_ATTRIBUTE = "ai.prompt.tools";
|
|
2146
|
-
function
|
|
3428
|
+
function isRecord3(value) {
|
|
2147
3429
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
2148
3430
|
}
|
|
2149
3431
|
var JSON_SCHEMA_KEYS = [
|
|
@@ -2161,17 +3443,17 @@ var JSON_SCHEMA_KEYS = [
|
|
|
2161
3443
|
"required"
|
|
2162
3444
|
];
|
|
2163
3445
|
function isJsonSchema(value) {
|
|
2164
|
-
if (!
|
|
3446
|
+
if (!isRecord3(value)) return false;
|
|
2165
3447
|
if (typeof value["~standard"] === "object") return false;
|
|
2166
|
-
if (
|
|
3448
|
+
if (isRecord3(value._def) || isRecord3(value._zod)) return false;
|
|
2167
3449
|
if (Object.keys(value).length === 0) return true;
|
|
2168
3450
|
return JSON_SCHEMA_KEYS.some((key) => key in value);
|
|
2169
3451
|
}
|
|
2170
3452
|
function toJsonSchema(value, options) {
|
|
2171
3453
|
if (value === void 0 || value === null) return void 0;
|
|
2172
3454
|
if (isJsonSchema(value)) return value;
|
|
2173
|
-
if (
|
|
2174
|
-
if (
|
|
3455
|
+
if (isRecord3(value) && isJsonSchema(value.jsonSchema)) return value.jsonSchema;
|
|
3456
|
+
if (isRecord3(value) && isJsonSchema(value.json)) return value.json;
|
|
2175
3457
|
if (options == null ? void 0 : options.schema) {
|
|
2176
3458
|
try {
|
|
2177
3459
|
return options.schema(value);
|
|
@@ -2194,23 +3476,23 @@ function functionTool(name, description, schema, options) {
|
|
|
2194
3476
|
}
|
|
2195
3477
|
function normalizeToolDeclaration(tool, options, fallbackName) {
|
|
2196
3478
|
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j;
|
|
2197
|
-
if (!
|
|
3479
|
+
if (!isRecord3(tool)) return void 0;
|
|
2198
3480
|
if (tool.type === "provider-defined" || tool.type === "provider") {
|
|
2199
3481
|
const name2 = (_b = (_a = pickString(tool.name)) != null ? _a : pickString(tool.id)) != null ? _b : fallbackName;
|
|
2200
3482
|
if (name2 === void 0) return void 0;
|
|
2201
3483
|
const declaration = { type: "provider-defined", name: name2 };
|
|
2202
3484
|
const id = pickString(tool.id);
|
|
2203
3485
|
if (id !== void 0) declaration.id = id;
|
|
2204
|
-
if (
|
|
3486
|
+
if (isRecord3(tool.args)) declaration.args = tool.args;
|
|
2205
3487
|
return declaration;
|
|
2206
3488
|
}
|
|
2207
|
-
if (
|
|
3489
|
+
if (isRecord3(tool.toolSpec)) {
|
|
2208
3490
|
const spec = tool.toolSpec;
|
|
2209
3491
|
const name2 = (_c = pickString(spec.name)) != null ? _c : fallbackName;
|
|
2210
3492
|
if (name2 === void 0) return void 0;
|
|
2211
3493
|
return functionTool(name2, spec.description, spec.inputSchema, options);
|
|
2212
3494
|
}
|
|
2213
|
-
if (
|
|
3495
|
+
if (isRecord3(tool.function)) {
|
|
2214
3496
|
const fn = tool.function;
|
|
2215
3497
|
const name2 = (_d = pickString(fn.name)) != null ? _d : fallbackName;
|
|
2216
3498
|
if (name2 === void 0) return void 0;
|
|
@@ -2236,7 +3518,7 @@ function isGeminiToolGroup(tool) {
|
|
|
2236
3518
|
if (Array.isArray(tool.functionDeclarations)) return true;
|
|
2237
3519
|
const keys = Object.keys(tool);
|
|
2238
3520
|
if (keys.length === 0 || NOT_A_GEMINI_GROUP_KEYS.some((key) => key in tool)) return false;
|
|
2239
|
-
return keys.every((key) =>
|
|
3521
|
+
return keys.every((key) => isRecord3(tool[key]));
|
|
2240
3522
|
}
|
|
2241
3523
|
function expandGeminiTool(tool, options) {
|
|
2242
3524
|
const declarations = [];
|
|
@@ -2246,7 +3528,7 @@ function expandGeminiTool(tool, options) {
|
|
|
2246
3528
|
const normalized = normalizeToolDeclaration(declaration, options);
|
|
2247
3529
|
if (normalized) declarations.push(normalized);
|
|
2248
3530
|
}
|
|
2249
|
-
} else if (
|
|
3531
|
+
} else if (isRecord3(value)) {
|
|
2250
3532
|
declarations.push({ type: "provider-defined", id: key, name: key, args: value });
|
|
2251
3533
|
}
|
|
2252
3534
|
}
|
|
@@ -2256,14 +3538,14 @@ function normalizeToolDeclarations(tools, options) {
|
|
|
2256
3538
|
if (tools === void 0 || tools === null) return void 0;
|
|
2257
3539
|
if (Array.isArray(tools)) {
|
|
2258
3540
|
return tools.flatMap((tool) => {
|
|
2259
|
-
if (
|
|
3541
|
+
if (isRecord3(tool) && isGeminiToolGroup(tool)) {
|
|
2260
3542
|
return expandGeminiTool(tool, options);
|
|
2261
3543
|
}
|
|
2262
3544
|
const declaration = normalizeToolDeclaration(tool, options);
|
|
2263
3545
|
return declaration ? [declaration] : [];
|
|
2264
3546
|
});
|
|
2265
3547
|
}
|
|
2266
|
-
if (!
|
|
3548
|
+
if (!isRecord3(tools)) return void 0;
|
|
2267
3549
|
return Object.entries(tools).flatMap(([key, tool]) => {
|
|
2268
3550
|
const declaration = normalizeToolDeclaration(tool, options, key);
|
|
2269
3551
|
return declaration ? [declaration] : [];
|
|
@@ -2409,39 +3691,6 @@ var resolveLocal = (sourceDirectory, detectBranch, completed) => {
|
|
|
2409
3691
|
function createAppGitContext2(options, runtime = {}) {
|
|
2410
3692
|
return new AppGitContext(options, { ...runtime, resolveLocal });
|
|
2411
3693
|
}
|
|
2412
|
-
function hasDestination(options) {
|
|
2413
|
-
var _a;
|
|
2414
|
-
if (options.enabled === false) return false;
|
|
2415
|
-
return Boolean(((_a = options.writeKey) == null ? void 0 : _a.trim()) || resolveLocalDebuggerBaseUrl(options.localDebuggerUrl));
|
|
2416
|
-
}
|
|
2417
|
-
var EventShipper2 = class extends EventShipper {
|
|
2418
|
-
constructor(options) {
|
|
2419
|
-
var _a;
|
|
2420
|
-
const ownsAppGitContext = options.appGitContext === void 0;
|
|
2421
|
-
const appGitContext = (_a = options.appGitContext) != null ? _a : createAppGitContext2(options.appGit, { allowDiscovery: hasDestination(options) });
|
|
2422
|
-
try {
|
|
2423
|
-
super({ ...options, appGitContext });
|
|
2424
|
-
} catch (error) {
|
|
2425
|
-
if (ownsAppGitContext) appGitContext.dispose();
|
|
2426
|
-
throw error;
|
|
2427
|
-
}
|
|
2428
|
-
if (ownsAppGitContext) this.ownAppGitContextForShutdown();
|
|
2429
|
-
}
|
|
2430
|
-
};
|
|
2431
|
-
var TraceShipper2 = class extends TraceShipper {
|
|
2432
|
-
constructor(options) {
|
|
2433
|
-
var _a;
|
|
2434
|
-
const ownsAppGitContext = options.appGitContext === void 0;
|
|
2435
|
-
const appGitContext = (_a = options.appGitContext) != null ? _a : createAppGitContext2(options.appGit, { allowDiscovery: hasDestination(options) });
|
|
2436
|
-
try {
|
|
2437
|
-
super({ ...options, appGitContext });
|
|
2438
|
-
} catch (error) {
|
|
2439
|
-
if (ownsAppGitContext) appGitContext.dispose();
|
|
2440
|
-
throw error;
|
|
2441
|
-
}
|
|
2442
|
-
this.ownsAppGitContext = ownsAppGitContext;
|
|
2443
|
-
}
|
|
2444
|
-
};
|
|
2445
3694
|
globalThis.RAINDROP_ASYNC_LOCAL_STORAGE = AsyncLocalStorage;
|
|
2446
3695
|
var SUPPRESS_TRACING_KEY = /* @__PURE__ */ Symbol.for(
|
|
2447
3696
|
"OpenTelemetry SDK Context Key SUPPRESS_TRACING"
|
|
@@ -2579,6 +3828,8 @@ var RaindropManagedAgentsHandler = class {
|
|
|
2579
3828
|
eventName: (_e = context.eventName) != null ? _e : "ai_generation",
|
|
2580
3829
|
input: void 0,
|
|
2581
3830
|
model: void 0,
|
|
3831
|
+
// Caller-supplied properties win over the derived keys below (W6).
|
|
3832
|
+
callerProperties: context.properties,
|
|
2582
3833
|
properties: {
|
|
2583
3834
|
...context.properties,
|
|
2584
3835
|
"ai.provider": "openai",
|
|
@@ -2899,7 +4150,7 @@ function isRecord2(value) {
|
|
|
2899
4150
|
// package.json
|
|
2900
4151
|
var package_default = {
|
|
2901
4152
|
name: "@raindrop-ai/openai-managed-agents",
|
|
2902
|
-
version: "0.0.
|
|
4153
|
+
version: "0.0.5",
|
|
2903
4154
|
description: "Raindrop tracing for the OpenAI Agents API",
|
|
2904
4155
|
main: "dist/index.js",
|
|
2905
4156
|
module: "dist/index.mjs",
|
|
@@ -2941,11 +4192,11 @@ var package_default = {
|
|
|
2941
4192
|
"@raindrop-ai/core": "workspace:*",
|
|
2942
4193
|
"@types/node": "^20.11.17",
|
|
2943
4194
|
msw: "^2.12.7",
|
|
2944
|
-
tsup: "^
|
|
4195
|
+
tsup: "^9.0.0",
|
|
2945
4196
|
typescript: "^5.3.3",
|
|
2946
|
-
vitest: "^
|
|
4197
|
+
vitest: "^4.1.12",
|
|
2947
4198
|
openai: "7.15.0",
|
|
2948
|
-
zod: "^
|
|
4199
|
+
zod: "^4.6.6"
|
|
2949
4200
|
},
|
|
2950
4201
|
tsup: {
|
|
2951
4202
|
entry: [
|
|
@@ -3067,7 +4318,7 @@ function wrapManagedAgents(client, handler, context) {
|
|
|
3067
4318
|
|
|
3068
4319
|
// src/index.ts
|
|
3069
4320
|
function createRaindropOpenAIManagedAgents(opts = {}) {
|
|
3070
|
-
var _a
|
|
4321
|
+
var _a;
|
|
3071
4322
|
const enabled = Boolean((_a = opts.writeKey) == null ? void 0 : _a.trim());
|
|
3072
4323
|
if (!enabled)
|
|
3073
4324
|
console.warn(
|
|
@@ -3076,44 +4327,33 @@ function createRaindropOpenAIManagedAgents(opts = {}) {
|
|
|
3076
4327
|
const appGitContext = createAppGitContext2(enabled ? opts.appGit : false, {
|
|
3077
4328
|
allowLocalGit: false
|
|
3078
4329
|
});
|
|
3079
|
-
const
|
|
3080
|
-
|
|
3081
|
-
|
|
3082
|
-
|
|
3083
|
-
|
|
3084
|
-
|
|
3085
|
-
|
|
3086
|
-
libraryName,
|
|
3087
|
-
libraryVersion
|
|
3088
|
-
appGitContext,
|
|
3089
|
-
maxTextFieldChars: opts.maxTextFieldChars,
|
|
3090
|
-
localDebuggerUrl: opts.localWorkshopUrl === false ? null : opts.localWorkshopUrl
|
|
3091
|
-
};
|
|
3092
|
-
const events = new EventShipper2(shipperOptions);
|
|
3093
|
-
const traces = new TraceShipper2({
|
|
3094
|
-
...shipperOptions,
|
|
3095
|
-
serviceName: "raindrop.openai-managed-agents",
|
|
3096
|
-
serviceVersion: libraryVersion
|
|
4330
|
+
const { eventShipper: events, traceShipper: traces } = createShippers(opts, {
|
|
4331
|
+
common: {
|
|
4332
|
+
enabled,
|
|
4333
|
+
sdkName: "openai-managed-agents",
|
|
4334
|
+
appGitContext,
|
|
4335
|
+
localDebuggerUrl: opts.localWorkshopUrl === false ? null : opts.localWorkshopUrl
|
|
4336
|
+
},
|
|
4337
|
+
event: { libraryName, libraryVersion },
|
|
4338
|
+
trace: { serviceName: "raindrop.openai-managed-agents", serviceVersion: libraryVersion }
|
|
3097
4339
|
});
|
|
3098
4340
|
const handler = new RaindropManagedAgentsHandler(events, traces, opts);
|
|
3099
4341
|
return {
|
|
3100
4342
|
handler,
|
|
3101
4343
|
wrap: (client, context) => wrapManagedAgents(client, handler, context),
|
|
3102
|
-
|
|
3103
|
-
|
|
3104
|
-
finish: (id, patch) => events.finish(id, patch),
|
|
3105
|
-
addAttachments: (id, attachments) => events.patch(id, { attachments }),
|
|
3106
|
-
setProperties: (id, properties) => events.patch(id, { properties })
|
|
4344
|
+
get lastEventId() {
|
|
4345
|
+
return events == null ? void 0 : events.lastFinishedEventId;
|
|
3107
4346
|
},
|
|
4347
|
+
events: createEventsApi(events),
|
|
3108
4348
|
users: { identify: (users) => events.identify(users) },
|
|
3109
4349
|
signals: { track: (signal) => events.trackSignal(signal) },
|
|
3110
|
-
|
|
3111
|
-
|
|
4350
|
+
flush() {
|
|
4351
|
+
return flushShippers(events, traces);
|
|
3112
4352
|
},
|
|
3113
4353
|
async shutdown() {
|
|
3114
4354
|
try {
|
|
3115
4355
|
handler.shutdown();
|
|
3116
|
-
await
|
|
4356
|
+
return await shutdownShippers(events, traces);
|
|
3117
4357
|
} finally {
|
|
3118
4358
|
appGitContext.dispose();
|
|
3119
4359
|
}
|