@fallom/trace 0.1.3 → 0.1.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 +120 -1
- package/dist/chunk-IGJD7GBO.mjs +248 -0
- package/dist/chunk-VNUUS74T.mjs +242 -0
- package/dist/index.d.mts +141 -16
- package/dist/index.d.ts +141 -16
- package/dist/index.js +472 -120
- package/dist/index.mjs +141 -37
- package/dist/prompts-67DJ33I4.mjs +14 -0
- package/dist/prompts-ODF4KO2E.mjs +14 -0
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -3,6 +3,9 @@ var __defProp = Object.defineProperty;
|
|
|
3
3
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
4
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
5
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __esm = (fn, res) => function __init() {
|
|
7
|
+
return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
|
|
8
|
+
};
|
|
6
9
|
var __export = (target, all) => {
|
|
7
10
|
for (var name in all)
|
|
8
11
|
__defProp(target, name, { get: all[name], enumerable: true });
|
|
@@ -17,12 +20,252 @@ var __copyProps = (to, from, except, desc) => {
|
|
|
17
20
|
};
|
|
18
21
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
22
|
|
|
23
|
+
// src/prompts.ts
|
|
24
|
+
var prompts_exports = {};
|
|
25
|
+
__export(prompts_exports, {
|
|
26
|
+
clearPromptContext: () => clearPromptContext,
|
|
27
|
+
get: () => get,
|
|
28
|
+
getAB: () => getAB,
|
|
29
|
+
getPromptContext: () => getPromptContext,
|
|
30
|
+
init: () => init
|
|
31
|
+
});
|
|
32
|
+
function log(msg) {
|
|
33
|
+
if (debugMode) {
|
|
34
|
+
console.log(`[Fallom Prompts] ${msg}`);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
function init(options = {}) {
|
|
38
|
+
apiKey = options.apiKey || process.env.FALLOM_API_KEY || null;
|
|
39
|
+
baseUrl = options.baseUrl || process.env.FALLOM_BASE_URL || "https://spans.fallom.com";
|
|
40
|
+
initialized = true;
|
|
41
|
+
if (!apiKey) {
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
fetchAll().catch(() => {
|
|
45
|
+
});
|
|
46
|
+
if (!syncInterval) {
|
|
47
|
+
syncInterval = setInterval(() => {
|
|
48
|
+
fetchAll().catch(() => {
|
|
49
|
+
});
|
|
50
|
+
}, 3e4);
|
|
51
|
+
syncInterval.unref();
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
function ensureInit() {
|
|
55
|
+
if (!initialized) {
|
|
56
|
+
try {
|
|
57
|
+
init();
|
|
58
|
+
} catch {
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
async function fetchAll() {
|
|
63
|
+
await Promise.all([fetchPrompts(), fetchPromptABTests()]);
|
|
64
|
+
}
|
|
65
|
+
async function fetchPrompts(timeout = SYNC_TIMEOUT) {
|
|
66
|
+
if (!apiKey) return;
|
|
67
|
+
try {
|
|
68
|
+
const controller = new AbortController();
|
|
69
|
+
const timeoutId = setTimeout(() => controller.abort(), timeout);
|
|
70
|
+
const resp = await fetch(`${baseUrl}/prompts`, {
|
|
71
|
+
headers: { Authorization: `Bearer ${apiKey}` },
|
|
72
|
+
signal: controller.signal
|
|
73
|
+
});
|
|
74
|
+
clearTimeout(timeoutId);
|
|
75
|
+
if (resp.ok) {
|
|
76
|
+
const data = await resp.json();
|
|
77
|
+
for (const p of data.prompts || []) {
|
|
78
|
+
if (!promptCache.has(p.key)) {
|
|
79
|
+
promptCache.set(p.key, { versions: /* @__PURE__ */ new Map(), current: null });
|
|
80
|
+
}
|
|
81
|
+
const cached = promptCache.get(p.key);
|
|
82
|
+
cached.versions.set(p.version, {
|
|
83
|
+
systemPrompt: p.system_prompt,
|
|
84
|
+
userTemplate: p.user_template
|
|
85
|
+
});
|
|
86
|
+
cached.current = p.version;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
} catch {
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
async function fetchPromptABTests(timeout = SYNC_TIMEOUT) {
|
|
93
|
+
if (!apiKey) return;
|
|
94
|
+
try {
|
|
95
|
+
const controller = new AbortController();
|
|
96
|
+
const timeoutId = setTimeout(() => controller.abort(), timeout);
|
|
97
|
+
const resp = await fetch(`${baseUrl}/prompt-ab-tests`, {
|
|
98
|
+
headers: { Authorization: `Bearer ${apiKey}` },
|
|
99
|
+
signal: controller.signal
|
|
100
|
+
});
|
|
101
|
+
clearTimeout(timeoutId);
|
|
102
|
+
if (resp.ok) {
|
|
103
|
+
const data = await resp.json();
|
|
104
|
+
for (const t of data.prompt_ab_tests || []) {
|
|
105
|
+
if (!promptABCache.has(t.key)) {
|
|
106
|
+
promptABCache.set(t.key, { versions: /* @__PURE__ */ new Map(), current: null });
|
|
107
|
+
}
|
|
108
|
+
const cached = promptABCache.get(t.key);
|
|
109
|
+
cached.versions.set(t.version, { variants: t.variants });
|
|
110
|
+
cached.current = t.version;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
} catch {
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
function replaceVariables(template, variables) {
|
|
117
|
+
if (!variables) return template;
|
|
118
|
+
return template.replace(/\{\{(\s*\w+\s*)\}\}/g, (match, varName) => {
|
|
119
|
+
const key = varName.trim();
|
|
120
|
+
return key in variables ? String(variables[key]) : match;
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
function setPromptContext(ctx) {
|
|
124
|
+
promptContext = ctx;
|
|
125
|
+
}
|
|
126
|
+
function getPromptContext() {
|
|
127
|
+
const ctx = promptContext;
|
|
128
|
+
promptContext = null;
|
|
129
|
+
return ctx;
|
|
130
|
+
}
|
|
131
|
+
async function get(promptKey, options = {}) {
|
|
132
|
+
const { variables, version, debug = false } = options;
|
|
133
|
+
debugMode = debug;
|
|
134
|
+
ensureInit();
|
|
135
|
+
log(`get() called: promptKey=${promptKey}`);
|
|
136
|
+
let promptData = promptCache.get(promptKey);
|
|
137
|
+
if (!promptData) {
|
|
138
|
+
log("Not in cache, fetching...");
|
|
139
|
+
await fetchPrompts(SYNC_TIMEOUT);
|
|
140
|
+
promptData = promptCache.get(promptKey);
|
|
141
|
+
}
|
|
142
|
+
if (!promptData) {
|
|
143
|
+
throw new Error(
|
|
144
|
+
`Prompt '${promptKey}' not found. Check that it exists in your Fallom dashboard.`
|
|
145
|
+
);
|
|
146
|
+
}
|
|
147
|
+
const targetVersion = version ?? promptData.current;
|
|
148
|
+
const content = promptData.versions.get(targetVersion);
|
|
149
|
+
if (!content) {
|
|
150
|
+
throw new Error(
|
|
151
|
+
`Prompt '${promptKey}' version ${targetVersion} not found.`
|
|
152
|
+
);
|
|
153
|
+
}
|
|
154
|
+
const system = replaceVariables(content.systemPrompt, variables);
|
|
155
|
+
const user = replaceVariables(content.userTemplate, variables);
|
|
156
|
+
setPromptContext({
|
|
157
|
+
promptKey,
|
|
158
|
+
promptVersion: targetVersion
|
|
159
|
+
});
|
|
160
|
+
log(`\u2705 Got prompt: ${promptKey} v${targetVersion}`);
|
|
161
|
+
return {
|
|
162
|
+
key: promptKey,
|
|
163
|
+
version: targetVersion,
|
|
164
|
+
system,
|
|
165
|
+
user
|
|
166
|
+
};
|
|
167
|
+
}
|
|
168
|
+
async function getAB(abTestKey, sessionId, options = {}) {
|
|
169
|
+
const { variables, debug = false } = options;
|
|
170
|
+
debugMode = debug;
|
|
171
|
+
ensureInit();
|
|
172
|
+
log(`getAB() called: abTestKey=${abTestKey}, sessionId=${sessionId}`);
|
|
173
|
+
let abData = promptABCache.get(abTestKey);
|
|
174
|
+
if (!abData) {
|
|
175
|
+
log("Not in cache, fetching...");
|
|
176
|
+
await fetchPromptABTests(SYNC_TIMEOUT);
|
|
177
|
+
abData = promptABCache.get(abTestKey);
|
|
178
|
+
}
|
|
179
|
+
if (!abData) {
|
|
180
|
+
throw new Error(
|
|
181
|
+
`Prompt A/B test '${abTestKey}' not found. Check that it exists in your Fallom dashboard.`
|
|
182
|
+
);
|
|
183
|
+
}
|
|
184
|
+
const currentVersion = abData.current;
|
|
185
|
+
const versionData = abData.versions.get(currentVersion);
|
|
186
|
+
if (!versionData) {
|
|
187
|
+
throw new Error(`Prompt A/B test '${abTestKey}' has no current version.`);
|
|
188
|
+
}
|
|
189
|
+
const { variants } = versionData;
|
|
190
|
+
const hashBytes = (0, import_crypto.createHash)("md5").update(sessionId).digest();
|
|
191
|
+
const hashVal = hashBytes.readUInt32BE(0) % 1e6;
|
|
192
|
+
let cumulative = 0;
|
|
193
|
+
let selectedVariant = variants[variants.length - 1];
|
|
194
|
+
let selectedIndex = variants.length - 1;
|
|
195
|
+
for (let i = 0; i < variants.length; i++) {
|
|
196
|
+
cumulative += variants[i].weight * 1e4;
|
|
197
|
+
if (hashVal < cumulative) {
|
|
198
|
+
selectedVariant = variants[i];
|
|
199
|
+
selectedIndex = i;
|
|
200
|
+
break;
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
const promptKey = selectedVariant.prompt_key;
|
|
204
|
+
const promptVersion = selectedVariant.prompt_version;
|
|
205
|
+
let promptData = promptCache.get(promptKey);
|
|
206
|
+
if (!promptData) {
|
|
207
|
+
await fetchPrompts(SYNC_TIMEOUT);
|
|
208
|
+
promptData = promptCache.get(promptKey);
|
|
209
|
+
}
|
|
210
|
+
if (!promptData) {
|
|
211
|
+
throw new Error(
|
|
212
|
+
`Prompt '${promptKey}' (from A/B test '${abTestKey}') not found.`
|
|
213
|
+
);
|
|
214
|
+
}
|
|
215
|
+
const targetVersion = promptVersion ?? promptData.current;
|
|
216
|
+
const content = promptData.versions.get(targetVersion);
|
|
217
|
+
if (!content) {
|
|
218
|
+
throw new Error(
|
|
219
|
+
`Prompt '${promptKey}' version ${targetVersion} not found.`
|
|
220
|
+
);
|
|
221
|
+
}
|
|
222
|
+
const system = replaceVariables(content.systemPrompt, variables);
|
|
223
|
+
const user = replaceVariables(content.userTemplate, variables);
|
|
224
|
+
setPromptContext({
|
|
225
|
+
promptKey,
|
|
226
|
+
promptVersion: targetVersion,
|
|
227
|
+
abTestKey,
|
|
228
|
+
variantIndex: selectedIndex
|
|
229
|
+
});
|
|
230
|
+
log(
|
|
231
|
+
`\u2705 Got prompt from A/B: ${promptKey} v${targetVersion} (variant ${selectedIndex})`
|
|
232
|
+
);
|
|
233
|
+
return {
|
|
234
|
+
key: promptKey,
|
|
235
|
+
version: targetVersion,
|
|
236
|
+
system,
|
|
237
|
+
user,
|
|
238
|
+
abTestKey,
|
|
239
|
+
variantIndex: selectedIndex
|
|
240
|
+
};
|
|
241
|
+
}
|
|
242
|
+
function clearPromptContext() {
|
|
243
|
+
promptContext = null;
|
|
244
|
+
}
|
|
245
|
+
var import_crypto, apiKey, baseUrl, initialized, syncInterval, debugMode, promptCache, promptABCache, promptContext, SYNC_TIMEOUT;
|
|
246
|
+
var init_prompts = __esm({
|
|
247
|
+
"src/prompts.ts"() {
|
|
248
|
+
"use strict";
|
|
249
|
+
import_crypto = require("crypto");
|
|
250
|
+
apiKey = null;
|
|
251
|
+
baseUrl = "https://spans.fallom.com";
|
|
252
|
+
initialized = false;
|
|
253
|
+
syncInterval = null;
|
|
254
|
+
debugMode = false;
|
|
255
|
+
promptCache = /* @__PURE__ */ new Map();
|
|
256
|
+
promptABCache = /* @__PURE__ */ new Map();
|
|
257
|
+
promptContext = null;
|
|
258
|
+
SYNC_TIMEOUT = 2e3;
|
|
259
|
+
}
|
|
260
|
+
});
|
|
261
|
+
|
|
20
262
|
// src/index.ts
|
|
21
263
|
var index_exports = {};
|
|
22
264
|
__export(index_exports, {
|
|
23
265
|
default: () => index_default,
|
|
24
|
-
init: () =>
|
|
266
|
+
init: () => init4,
|
|
25
267
|
models: () => models_exports,
|
|
268
|
+
prompts: () => prompts_exports,
|
|
26
269
|
trace: () => trace_exports
|
|
27
270
|
});
|
|
28
271
|
module.exports = __toCommonJS(index_exports);
|
|
@@ -32,7 +275,7 @@ var trace_exports = {};
|
|
|
32
275
|
__export(trace_exports, {
|
|
33
276
|
clearSession: () => clearSession,
|
|
34
277
|
getSession: () => getSession,
|
|
35
|
-
init: () =>
|
|
278
|
+
init: () => init2,
|
|
36
279
|
runWithSession: () => runWithSession,
|
|
37
280
|
setSession: () => setSession,
|
|
38
281
|
shutdown: () => shutdown,
|
|
@@ -671,29 +914,37 @@ var Resource = (
|
|
|
671
914
|
// src/trace.ts
|
|
672
915
|
var sessionStorage = new import_async_hooks.AsyncLocalStorage();
|
|
673
916
|
var fallbackSession = null;
|
|
674
|
-
var
|
|
675
|
-
var
|
|
676
|
-
var
|
|
917
|
+
var apiKey2 = null;
|
|
918
|
+
var baseUrl2 = "https://spans.fallom.com";
|
|
919
|
+
var initialized2 = false;
|
|
677
920
|
var captureContent = true;
|
|
678
|
-
var
|
|
921
|
+
var debugMode2 = false;
|
|
679
922
|
var sdk = null;
|
|
680
|
-
function
|
|
681
|
-
if (
|
|
923
|
+
function log2(...args) {
|
|
924
|
+
if (debugMode2) console.log("[Fallom]", ...args);
|
|
682
925
|
}
|
|
683
926
|
var fallomSpanProcessor = {
|
|
684
927
|
onStart(span2, _parentContext) {
|
|
685
|
-
|
|
928
|
+
log2("\u{1F4CD} Span started:", span2.name || "unknown");
|
|
686
929
|
const ctx = sessionStorage.getStore() || fallbackSession;
|
|
687
930
|
if (ctx) {
|
|
688
931
|
span2.setAttribute("fallom.config_key", ctx.configKey);
|
|
689
932
|
span2.setAttribute("fallom.session_id", ctx.sessionId);
|
|
690
|
-
|
|
933
|
+
if (ctx.customerId) {
|
|
934
|
+
span2.setAttribute("fallom.customer_id", ctx.customerId);
|
|
935
|
+
}
|
|
936
|
+
log2(
|
|
937
|
+
" Added session context:",
|
|
938
|
+
ctx.configKey,
|
|
939
|
+
ctx.sessionId,
|
|
940
|
+
ctx.customerId
|
|
941
|
+
);
|
|
691
942
|
} else {
|
|
692
|
-
|
|
943
|
+
log2(" No session context available");
|
|
693
944
|
}
|
|
694
945
|
},
|
|
695
946
|
onEnd(span2) {
|
|
696
|
-
|
|
947
|
+
log2("\u2705 Span ended:", span2.name, "duration:", span2.duration);
|
|
697
948
|
},
|
|
698
949
|
shutdown() {
|
|
699
950
|
return Promise.resolve();
|
|
@@ -702,33 +953,33 @@ var fallomSpanProcessor = {
|
|
|
702
953
|
return Promise.resolve();
|
|
703
954
|
}
|
|
704
955
|
};
|
|
705
|
-
async function
|
|
706
|
-
if (
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
956
|
+
async function init2(options = {}) {
|
|
957
|
+
if (initialized2) return;
|
|
958
|
+
debugMode2 = options.debug ?? false;
|
|
959
|
+
log2("\u{1F680} Initializing Fallom tracing...");
|
|
960
|
+
apiKey2 = options.apiKey || process.env.FALLOM_API_KEY || null;
|
|
961
|
+
baseUrl2 = options.baseUrl || process.env.FALLOM_BASE_URL || "https://spans.fallom.com";
|
|
711
962
|
const envCapture = process.env.FALLOM_CAPTURE_CONTENT?.toLowerCase();
|
|
712
963
|
if (envCapture === "false" || envCapture === "0" || envCapture === "no") {
|
|
713
964
|
captureContent = false;
|
|
714
965
|
} else {
|
|
715
966
|
captureContent = options.captureContent ?? true;
|
|
716
967
|
}
|
|
717
|
-
if (!
|
|
968
|
+
if (!apiKey2) {
|
|
718
969
|
throw new Error(
|
|
719
970
|
"No API key provided. Set FALLOM_API_KEY environment variable or pass apiKey parameter."
|
|
720
971
|
);
|
|
721
972
|
}
|
|
722
|
-
|
|
723
|
-
|
|
973
|
+
initialized2 = true;
|
|
974
|
+
log2("\u{1F4E1} Exporter URL:", `${baseUrl2}/v1/traces`);
|
|
724
975
|
const exporter = new import_exporter_trace_otlp_http.OTLPTraceExporter({
|
|
725
|
-
url: `${
|
|
976
|
+
url: `${baseUrl2}/v1/traces`,
|
|
726
977
|
headers: {
|
|
727
|
-
Authorization: `Bearer ${
|
|
978
|
+
Authorization: `Bearer ${apiKey2}`
|
|
728
979
|
}
|
|
729
980
|
});
|
|
730
981
|
const instrumentations = await getInstrumentations();
|
|
731
|
-
|
|
982
|
+
log2("\u{1F527} Loaded instrumentations:", instrumentations.length);
|
|
732
983
|
sdk = new import_sdk_node.NodeSDK({
|
|
733
984
|
resource: new Resource({
|
|
734
985
|
"service.name": "fallom-traced-app"
|
|
@@ -738,20 +989,48 @@ async function init(options = {}) {
|
|
|
738
989
|
instrumentations
|
|
739
990
|
});
|
|
740
991
|
sdk.start();
|
|
741
|
-
|
|
992
|
+
log2("\u2705 SDK started");
|
|
742
993
|
process.on("SIGTERM", () => {
|
|
743
994
|
sdk?.shutdown().catch(console.error);
|
|
744
995
|
});
|
|
745
996
|
}
|
|
746
997
|
async function getInstrumentations() {
|
|
747
998
|
const instrumentations = [];
|
|
748
|
-
await tryAddInstrumentation(
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
await tryAddInstrumentation(
|
|
754
|
-
|
|
999
|
+
await tryAddInstrumentation(
|
|
1000
|
+
instrumentations,
|
|
1001
|
+
"@traceloop/instrumentation-openai",
|
|
1002
|
+
"OpenAIInstrumentation"
|
|
1003
|
+
);
|
|
1004
|
+
await tryAddInstrumentation(
|
|
1005
|
+
instrumentations,
|
|
1006
|
+
"@traceloop/instrumentation-anthropic",
|
|
1007
|
+
"AnthropicInstrumentation"
|
|
1008
|
+
);
|
|
1009
|
+
await tryAddInstrumentation(
|
|
1010
|
+
instrumentations,
|
|
1011
|
+
"@traceloop/instrumentation-cohere",
|
|
1012
|
+
"CohereInstrumentation"
|
|
1013
|
+
);
|
|
1014
|
+
await tryAddInstrumentation(
|
|
1015
|
+
instrumentations,
|
|
1016
|
+
"@traceloop/instrumentation-bedrock",
|
|
1017
|
+
"BedrockInstrumentation"
|
|
1018
|
+
);
|
|
1019
|
+
await tryAddInstrumentation(
|
|
1020
|
+
instrumentations,
|
|
1021
|
+
"@traceloop/instrumentation-google-generativeai",
|
|
1022
|
+
"GoogleGenerativeAIInstrumentation"
|
|
1023
|
+
);
|
|
1024
|
+
await tryAddInstrumentation(
|
|
1025
|
+
instrumentations,
|
|
1026
|
+
"@traceloop/instrumentation-azure",
|
|
1027
|
+
"AzureOpenAIInstrumentation"
|
|
1028
|
+
);
|
|
1029
|
+
await tryAddInstrumentation(
|
|
1030
|
+
instrumentations,
|
|
1031
|
+
"@traceloop/instrumentation-vertexai",
|
|
1032
|
+
"VertexAIInstrumentation"
|
|
1033
|
+
);
|
|
755
1034
|
return instrumentations;
|
|
756
1035
|
}
|
|
757
1036
|
async function tryAddInstrumentation(instrumentations, pkg, className) {
|
|
@@ -759,25 +1038,37 @@ async function tryAddInstrumentation(instrumentations, pkg, className) {
|
|
|
759
1038
|
const mod = await import(pkg);
|
|
760
1039
|
const InstrumentationClass = mod[className] || mod.default?.[className];
|
|
761
1040
|
if (InstrumentationClass) {
|
|
762
|
-
instrumentations.push(
|
|
763
|
-
|
|
1041
|
+
instrumentations.push(
|
|
1042
|
+
new InstrumentationClass({ traceContent: captureContent })
|
|
1043
|
+
);
|
|
1044
|
+
log2(` \u2705 Loaded ${pkg}`);
|
|
764
1045
|
} else {
|
|
765
|
-
|
|
1046
|
+
log2(
|
|
1047
|
+
` \u26A0\uFE0F ${pkg} loaded but ${className} not found. Available:`,
|
|
1048
|
+
Object.keys(mod)
|
|
1049
|
+
);
|
|
766
1050
|
}
|
|
767
1051
|
} catch (e) {
|
|
768
|
-
|
|
1052
|
+
log2(` \u274C ${pkg} not installed`);
|
|
769
1053
|
}
|
|
770
1054
|
}
|
|
771
|
-
function setSession(configKey, sessionId) {
|
|
1055
|
+
function setSession(configKey, sessionId, customerId) {
|
|
772
1056
|
const store = sessionStorage.getStore();
|
|
773
1057
|
if (store) {
|
|
774
1058
|
store.configKey = configKey;
|
|
775
1059
|
store.sessionId = sessionId;
|
|
1060
|
+
store.customerId = customerId;
|
|
776
1061
|
}
|
|
777
|
-
fallbackSession = { configKey, sessionId };
|
|
1062
|
+
fallbackSession = { configKey, sessionId, customerId };
|
|
778
1063
|
}
|
|
779
|
-
function runWithSession(configKey, sessionId, fn) {
|
|
780
|
-
|
|
1064
|
+
function runWithSession(configKey, sessionId, customerIdOrFn, fn) {
|
|
1065
|
+
if (typeof customerIdOrFn === "function") {
|
|
1066
|
+
return sessionStorage.run({ configKey, sessionId }, customerIdOrFn);
|
|
1067
|
+
}
|
|
1068
|
+
return sessionStorage.run(
|
|
1069
|
+
{ configKey, sessionId, customerId: customerIdOrFn },
|
|
1070
|
+
fn
|
|
1071
|
+
);
|
|
781
1072
|
}
|
|
782
1073
|
function getSession() {
|
|
783
1074
|
return sessionStorage.getStore() || fallbackSession || void 0;
|
|
@@ -786,7 +1077,7 @@ function clearSession() {
|
|
|
786
1077
|
fallbackSession = null;
|
|
787
1078
|
}
|
|
788
1079
|
function span(data, options = {}) {
|
|
789
|
-
if (!
|
|
1080
|
+
if (!initialized2) {
|
|
790
1081
|
throw new Error("Fallom not initialized. Call trace.init() first.");
|
|
791
1082
|
}
|
|
792
1083
|
const ctx = sessionStorage.getStore() || fallbackSession;
|
|
@@ -804,10 +1095,10 @@ async function sendSpan(configKey, sessionId, data) {
|
|
|
804
1095
|
try {
|
|
805
1096
|
const controller = new AbortController();
|
|
806
1097
|
const timeoutId = setTimeout(() => controller.abort(), 5e3);
|
|
807
|
-
await fetch(`${
|
|
1098
|
+
await fetch(`${baseUrl2}/spans`, {
|
|
808
1099
|
method: "POST",
|
|
809
1100
|
headers: {
|
|
810
|
-
Authorization: `Bearer ${
|
|
1101
|
+
Authorization: `Bearer ${apiKey2}`,
|
|
811
1102
|
"Content-Type": "application/json"
|
|
812
1103
|
},
|
|
813
1104
|
body: JSON.stringify({
|
|
@@ -824,34 +1115,42 @@ async function sendSpan(configKey, sessionId, data) {
|
|
|
824
1115
|
async function shutdown() {
|
|
825
1116
|
if (sdk) {
|
|
826
1117
|
await sdk.shutdown();
|
|
827
|
-
|
|
1118
|
+
initialized2 = false;
|
|
828
1119
|
}
|
|
829
1120
|
}
|
|
830
1121
|
async function sendTrace(trace) {
|
|
831
1122
|
try {
|
|
832
1123
|
const controller = new AbortController();
|
|
833
1124
|
const timeoutId = setTimeout(() => controller.abort(), 5e3);
|
|
834
|
-
await fetch(`${
|
|
1125
|
+
await fetch(`${baseUrl2}/v1/traces`, {
|
|
835
1126
|
method: "POST",
|
|
836
1127
|
headers: {
|
|
837
|
-
Authorization: `Bearer ${
|
|
1128
|
+
Authorization: `Bearer ${apiKey2}`,
|
|
838
1129
|
"Content-Type": "application/json"
|
|
839
1130
|
},
|
|
840
1131
|
body: JSON.stringify(trace),
|
|
841
1132
|
signal: controller.signal
|
|
842
1133
|
});
|
|
843
1134
|
clearTimeout(timeoutId);
|
|
844
|
-
|
|
1135
|
+
log2("\u{1F4E4} Trace sent:", trace.name, trace.model);
|
|
845
1136
|
} catch {
|
|
846
1137
|
}
|
|
847
1138
|
}
|
|
848
1139
|
function wrapOpenAI(client) {
|
|
849
|
-
const originalCreate = client.chat.completions.create.bind(
|
|
1140
|
+
const originalCreate = client.chat.completions.create.bind(
|
|
1141
|
+
client.chat.completions
|
|
1142
|
+
);
|
|
850
1143
|
client.chat.completions.create = async function(...args) {
|
|
851
1144
|
const ctx = sessionStorage.getStore() || fallbackSession;
|
|
852
|
-
if (!ctx || !
|
|
1145
|
+
if (!ctx || !initialized2) {
|
|
853
1146
|
return originalCreate(...args);
|
|
854
1147
|
}
|
|
1148
|
+
let promptCtx = null;
|
|
1149
|
+
try {
|
|
1150
|
+
const { getPromptContext: getPromptContext2 } = await Promise.resolve().then(() => (init_prompts(), prompts_exports));
|
|
1151
|
+
promptCtx = getPromptContext2();
|
|
1152
|
+
} catch {
|
|
1153
|
+
}
|
|
855
1154
|
const params = args[0] || {};
|
|
856
1155
|
const startTime = Date.now();
|
|
857
1156
|
try {
|
|
@@ -860,6 +1159,7 @@ function wrapOpenAI(client) {
|
|
|
860
1159
|
sendTrace({
|
|
861
1160
|
config_key: ctx.configKey,
|
|
862
1161
|
session_id: ctx.sessionId,
|
|
1162
|
+
customer_id: ctx.customerId,
|
|
863
1163
|
name: "chat.completions.create",
|
|
864
1164
|
model: response?.model || params?.model,
|
|
865
1165
|
start_time: new Date(startTime).toISOString(),
|
|
@@ -870,7 +1170,11 @@ function wrapOpenAI(client) {
|
|
|
870
1170
|
completion_tokens: response?.usage?.completion_tokens,
|
|
871
1171
|
total_tokens: response?.usage?.total_tokens,
|
|
872
1172
|
input: captureContent ? JSON.stringify(params?.messages) : void 0,
|
|
873
|
-
output: captureContent ? response?.choices?.[0]?.message?.content : void 0
|
|
1173
|
+
output: captureContent ? response?.choices?.[0]?.message?.content : void 0,
|
|
1174
|
+
prompt_key: promptCtx?.promptKey,
|
|
1175
|
+
prompt_version: promptCtx?.promptVersion,
|
|
1176
|
+
prompt_ab_test_key: promptCtx?.abTestKey,
|
|
1177
|
+
prompt_variant_index: promptCtx?.variantIndex
|
|
874
1178
|
}).catch(() => {
|
|
875
1179
|
});
|
|
876
1180
|
return response;
|
|
@@ -879,13 +1183,18 @@ function wrapOpenAI(client) {
|
|
|
879
1183
|
sendTrace({
|
|
880
1184
|
config_key: ctx.configKey,
|
|
881
1185
|
session_id: ctx.sessionId,
|
|
1186
|
+
customer_id: ctx.customerId,
|
|
882
1187
|
name: "chat.completions.create",
|
|
883
1188
|
model: params?.model,
|
|
884
1189
|
start_time: new Date(startTime).toISOString(),
|
|
885
1190
|
end_time: new Date(endTime).toISOString(),
|
|
886
1191
|
duration_ms: endTime - startTime,
|
|
887
1192
|
status: "ERROR",
|
|
888
|
-
error_message: error?.message
|
|
1193
|
+
error_message: error?.message,
|
|
1194
|
+
prompt_key: promptCtx?.promptKey,
|
|
1195
|
+
prompt_version: promptCtx?.promptVersion,
|
|
1196
|
+
prompt_ab_test_key: promptCtx?.abTestKey,
|
|
1197
|
+
prompt_variant_index: promptCtx?.variantIndex
|
|
889
1198
|
}).catch(() => {
|
|
890
1199
|
});
|
|
891
1200
|
throw error;
|
|
@@ -897,9 +1206,15 @@ function wrapAnthropic(client) {
|
|
|
897
1206
|
const originalCreate = client.messages.create.bind(client.messages);
|
|
898
1207
|
client.messages.create = async function(...args) {
|
|
899
1208
|
const ctx = sessionStorage.getStore() || fallbackSession;
|
|
900
|
-
if (!ctx || !
|
|
1209
|
+
if (!ctx || !initialized2) {
|
|
901
1210
|
return originalCreate(...args);
|
|
902
1211
|
}
|
|
1212
|
+
let promptCtx = null;
|
|
1213
|
+
try {
|
|
1214
|
+
const { getPromptContext: getPromptContext2 } = await Promise.resolve().then(() => (init_prompts(), prompts_exports));
|
|
1215
|
+
promptCtx = getPromptContext2();
|
|
1216
|
+
} catch {
|
|
1217
|
+
}
|
|
903
1218
|
const params = args[0] || {};
|
|
904
1219
|
const startTime = Date.now();
|
|
905
1220
|
try {
|
|
@@ -908,6 +1223,7 @@ function wrapAnthropic(client) {
|
|
|
908
1223
|
sendTrace({
|
|
909
1224
|
config_key: ctx.configKey,
|
|
910
1225
|
session_id: ctx.sessionId,
|
|
1226
|
+
customer_id: ctx.customerId,
|
|
911
1227
|
name: "messages.create",
|
|
912
1228
|
model: response?.model || params?.model,
|
|
913
1229
|
start_time: new Date(startTime).toISOString(),
|
|
@@ -918,7 +1234,11 @@ function wrapAnthropic(client) {
|
|
|
918
1234
|
completion_tokens: response?.usage?.output_tokens,
|
|
919
1235
|
total_tokens: (response?.usage?.input_tokens || 0) + (response?.usage?.output_tokens || 0),
|
|
920
1236
|
input: captureContent ? JSON.stringify(params?.messages) : void 0,
|
|
921
|
-
output: captureContent ? response?.content?.[0]?.text : void 0
|
|
1237
|
+
output: captureContent ? response?.content?.[0]?.text : void 0,
|
|
1238
|
+
prompt_key: promptCtx?.promptKey,
|
|
1239
|
+
prompt_version: promptCtx?.promptVersion,
|
|
1240
|
+
prompt_ab_test_key: promptCtx?.abTestKey,
|
|
1241
|
+
prompt_variant_index: promptCtx?.variantIndex
|
|
922
1242
|
}).catch(() => {
|
|
923
1243
|
});
|
|
924
1244
|
return response;
|
|
@@ -927,13 +1247,18 @@ function wrapAnthropic(client) {
|
|
|
927
1247
|
sendTrace({
|
|
928
1248
|
config_key: ctx.configKey,
|
|
929
1249
|
session_id: ctx.sessionId,
|
|
1250
|
+
customer_id: ctx.customerId,
|
|
930
1251
|
name: "messages.create",
|
|
931
1252
|
model: params?.model,
|
|
932
1253
|
start_time: new Date(startTime).toISOString(),
|
|
933
1254
|
end_time: new Date(endTime).toISOString(),
|
|
934
1255
|
duration_ms: endTime - startTime,
|
|
935
1256
|
status: "ERROR",
|
|
936
|
-
error_message: error?.message
|
|
1257
|
+
error_message: error?.message,
|
|
1258
|
+
prompt_key: promptCtx?.promptKey,
|
|
1259
|
+
prompt_version: promptCtx?.promptVersion,
|
|
1260
|
+
prompt_ab_test_key: promptCtx?.abTestKey,
|
|
1261
|
+
prompt_variant_index: promptCtx?.variantIndex
|
|
937
1262
|
}).catch(() => {
|
|
938
1263
|
});
|
|
939
1264
|
throw error;
|
|
@@ -945,9 +1270,15 @@ function wrapGoogleAI(model) {
|
|
|
945
1270
|
const originalGenerate = model.generateContent.bind(model);
|
|
946
1271
|
model.generateContent = async function(...args) {
|
|
947
1272
|
const ctx = sessionStorage.getStore() || fallbackSession;
|
|
948
|
-
if (!ctx || !
|
|
1273
|
+
if (!ctx || !initialized2) {
|
|
949
1274
|
return originalGenerate(...args);
|
|
950
1275
|
}
|
|
1276
|
+
let promptCtx = null;
|
|
1277
|
+
try {
|
|
1278
|
+
const { getPromptContext: getPromptContext2 } = await Promise.resolve().then(() => (init_prompts(), prompts_exports));
|
|
1279
|
+
promptCtx = getPromptContext2();
|
|
1280
|
+
} catch {
|
|
1281
|
+
}
|
|
951
1282
|
const startTime = Date.now();
|
|
952
1283
|
try {
|
|
953
1284
|
const response = await originalGenerate(...args);
|
|
@@ -957,6 +1288,7 @@ function wrapGoogleAI(model) {
|
|
|
957
1288
|
sendTrace({
|
|
958
1289
|
config_key: ctx.configKey,
|
|
959
1290
|
session_id: ctx.sessionId,
|
|
1291
|
+
customer_id: ctx.customerId,
|
|
960
1292
|
name: "generateContent",
|
|
961
1293
|
model: model?.model || "gemini",
|
|
962
1294
|
start_time: new Date(startTime).toISOString(),
|
|
@@ -967,7 +1299,11 @@ function wrapGoogleAI(model) {
|
|
|
967
1299
|
completion_tokens: usage?.candidatesTokenCount,
|
|
968
1300
|
total_tokens: usage?.totalTokenCount,
|
|
969
1301
|
input: captureContent ? JSON.stringify(args[0]) : void 0,
|
|
970
|
-
output: captureContent ? result?.text?.() : void 0
|
|
1302
|
+
output: captureContent ? result?.text?.() : void 0,
|
|
1303
|
+
prompt_key: promptCtx?.promptKey,
|
|
1304
|
+
prompt_version: promptCtx?.promptVersion,
|
|
1305
|
+
prompt_ab_test_key: promptCtx?.abTestKey,
|
|
1306
|
+
prompt_variant_index: promptCtx?.variantIndex
|
|
971
1307
|
}).catch(() => {
|
|
972
1308
|
});
|
|
973
1309
|
return response;
|
|
@@ -976,13 +1312,18 @@ function wrapGoogleAI(model) {
|
|
|
976
1312
|
sendTrace({
|
|
977
1313
|
config_key: ctx.configKey,
|
|
978
1314
|
session_id: ctx.sessionId,
|
|
1315
|
+
customer_id: ctx.customerId,
|
|
979
1316
|
name: "generateContent",
|
|
980
1317
|
model: model?.model || "gemini",
|
|
981
1318
|
start_time: new Date(startTime).toISOString(),
|
|
982
1319
|
end_time: new Date(endTime).toISOString(),
|
|
983
1320
|
duration_ms: endTime - startTime,
|
|
984
1321
|
status: "ERROR",
|
|
985
|
-
error_message: error?.message
|
|
1322
|
+
error_message: error?.message,
|
|
1323
|
+
prompt_key: promptCtx?.promptKey,
|
|
1324
|
+
prompt_version: promptCtx?.promptVersion,
|
|
1325
|
+
prompt_ab_test_key: promptCtx?.abTestKey,
|
|
1326
|
+
prompt_variant_index: promptCtx?.variantIndex
|
|
986
1327
|
}).catch(() => {
|
|
987
1328
|
});
|
|
988
1329
|
throw error;
|
|
@@ -994,71 +1335,71 @@ function wrapGoogleAI(model) {
|
|
|
994
1335
|
// src/models.ts
|
|
995
1336
|
var models_exports = {};
|
|
996
1337
|
__export(models_exports, {
|
|
997
|
-
get: () =>
|
|
998
|
-
init: () =>
|
|
1338
|
+
get: () => get2,
|
|
1339
|
+
init: () => init3
|
|
999
1340
|
});
|
|
1000
|
-
var
|
|
1001
|
-
var
|
|
1002
|
-
var
|
|
1003
|
-
var
|
|
1004
|
-
var
|
|
1005
|
-
var
|
|
1341
|
+
var import_crypto2 = require("crypto");
|
|
1342
|
+
var apiKey3 = null;
|
|
1343
|
+
var baseUrl3 = "https://spans.fallom.com";
|
|
1344
|
+
var initialized3 = false;
|
|
1345
|
+
var syncInterval2 = null;
|
|
1346
|
+
var debugMode3 = false;
|
|
1006
1347
|
var configCache = /* @__PURE__ */ new Map();
|
|
1007
|
-
var
|
|
1348
|
+
var SYNC_TIMEOUT2 = 2e3;
|
|
1008
1349
|
var RECORD_TIMEOUT = 1e3;
|
|
1009
|
-
function
|
|
1010
|
-
if (
|
|
1350
|
+
function log3(msg) {
|
|
1351
|
+
if (debugMode3) {
|
|
1011
1352
|
console.log(`[Fallom] ${msg}`);
|
|
1012
1353
|
}
|
|
1013
1354
|
}
|
|
1014
|
-
function
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
if (!
|
|
1355
|
+
function init3(options = {}) {
|
|
1356
|
+
apiKey3 = options.apiKey || process.env.FALLOM_API_KEY || null;
|
|
1357
|
+
baseUrl3 = options.baseUrl || process.env.FALLOM_BASE_URL || "https://spans.fallom.com";
|
|
1358
|
+
initialized3 = true;
|
|
1359
|
+
if (!apiKey3) {
|
|
1019
1360
|
return;
|
|
1020
1361
|
}
|
|
1021
1362
|
fetchConfigs().catch(() => {
|
|
1022
1363
|
});
|
|
1023
|
-
if (!
|
|
1024
|
-
|
|
1364
|
+
if (!syncInterval2) {
|
|
1365
|
+
syncInterval2 = setInterval(() => {
|
|
1025
1366
|
fetchConfigs().catch(() => {
|
|
1026
1367
|
});
|
|
1027
1368
|
}, 3e4);
|
|
1028
|
-
|
|
1369
|
+
syncInterval2.unref();
|
|
1029
1370
|
}
|
|
1030
1371
|
}
|
|
1031
|
-
function
|
|
1032
|
-
if (!
|
|
1372
|
+
function ensureInit2() {
|
|
1373
|
+
if (!initialized3) {
|
|
1033
1374
|
try {
|
|
1034
|
-
|
|
1375
|
+
init3();
|
|
1035
1376
|
} catch {
|
|
1036
1377
|
}
|
|
1037
1378
|
}
|
|
1038
1379
|
}
|
|
1039
|
-
async function fetchConfigs(timeout =
|
|
1040
|
-
if (!
|
|
1041
|
-
|
|
1380
|
+
async function fetchConfigs(timeout = SYNC_TIMEOUT2) {
|
|
1381
|
+
if (!apiKey3) {
|
|
1382
|
+
log3("_fetchConfigs: No API key, skipping");
|
|
1042
1383
|
return;
|
|
1043
1384
|
}
|
|
1044
1385
|
try {
|
|
1045
|
-
|
|
1386
|
+
log3(`Fetching configs from ${baseUrl3}/configs`);
|
|
1046
1387
|
const controller = new AbortController();
|
|
1047
1388
|
const timeoutId = setTimeout(() => controller.abort(), timeout);
|
|
1048
|
-
const resp = await fetch(`${
|
|
1049
|
-
headers: { Authorization: `Bearer ${
|
|
1389
|
+
const resp = await fetch(`${baseUrl3}/configs`, {
|
|
1390
|
+
headers: { Authorization: `Bearer ${apiKey3}` },
|
|
1050
1391
|
signal: controller.signal
|
|
1051
1392
|
});
|
|
1052
1393
|
clearTimeout(timeoutId);
|
|
1053
|
-
|
|
1394
|
+
log3(`Response status: ${resp.status}`);
|
|
1054
1395
|
if (resp.ok) {
|
|
1055
1396
|
const data = await resp.json();
|
|
1056
1397
|
const configs = data.configs || [];
|
|
1057
|
-
|
|
1398
|
+
log3(`Got ${configs.length} configs: ${configs.map((c) => c.key)}`);
|
|
1058
1399
|
for (const c of configs) {
|
|
1059
1400
|
const key = c.key;
|
|
1060
1401
|
const version = c.version || 1;
|
|
1061
|
-
|
|
1402
|
+
log3(`Config '${key}' v${version}: ${JSON.stringify(c.variants)}`);
|
|
1062
1403
|
if (!configCache.has(key)) {
|
|
1063
1404
|
configCache.set(key, { versions: /* @__PURE__ */ new Map(), latest: null });
|
|
1064
1405
|
}
|
|
@@ -1067,21 +1408,21 @@ async function fetchConfigs(timeout = SYNC_TIMEOUT) {
|
|
|
1067
1408
|
cached.latest = version;
|
|
1068
1409
|
}
|
|
1069
1410
|
} else {
|
|
1070
|
-
|
|
1411
|
+
log3(`Fetch failed: ${resp.statusText}`);
|
|
1071
1412
|
}
|
|
1072
1413
|
} catch (e) {
|
|
1073
|
-
|
|
1414
|
+
log3(`Fetch exception: ${e}`);
|
|
1074
1415
|
}
|
|
1075
1416
|
}
|
|
1076
|
-
async function fetchSpecificVersion(configKey, version, timeout =
|
|
1077
|
-
if (!
|
|
1417
|
+
async function fetchSpecificVersion(configKey, version, timeout = SYNC_TIMEOUT2) {
|
|
1418
|
+
if (!apiKey3) return null;
|
|
1078
1419
|
try {
|
|
1079
1420
|
const controller = new AbortController();
|
|
1080
1421
|
const timeoutId = setTimeout(() => controller.abort(), timeout);
|
|
1081
1422
|
const resp = await fetch(
|
|
1082
|
-
`${
|
|
1423
|
+
`${baseUrl3}/configs/${configKey}/version/${version}`,
|
|
1083
1424
|
{
|
|
1084
|
-
headers: { Authorization: `Bearer ${
|
|
1425
|
+
headers: { Authorization: `Bearer ${apiKey3}` },
|
|
1085
1426
|
signal: controller.signal
|
|
1086
1427
|
}
|
|
1087
1428
|
);
|
|
@@ -1098,22 +1439,22 @@ async function fetchSpecificVersion(configKey, version, timeout = SYNC_TIMEOUT)
|
|
|
1098
1439
|
}
|
|
1099
1440
|
return null;
|
|
1100
1441
|
}
|
|
1101
|
-
async function
|
|
1442
|
+
async function get2(configKey, sessionId, options = {}) {
|
|
1102
1443
|
const { version, fallback, debug = false } = options;
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1444
|
+
debugMode3 = debug;
|
|
1445
|
+
ensureInit2();
|
|
1446
|
+
log3(`get() called: configKey=${configKey}, sessionId=${sessionId}, fallback=${fallback}`);
|
|
1106
1447
|
try {
|
|
1107
1448
|
let configData = configCache.get(configKey);
|
|
1108
|
-
|
|
1449
|
+
log3(`Cache lookup for '${configKey}': ${configData ? "found" : "not found"}`);
|
|
1109
1450
|
if (!configData) {
|
|
1110
|
-
|
|
1111
|
-
await fetchConfigs(
|
|
1451
|
+
log3("Not in cache, fetching...");
|
|
1452
|
+
await fetchConfigs(SYNC_TIMEOUT2);
|
|
1112
1453
|
configData = configCache.get(configKey);
|
|
1113
|
-
|
|
1454
|
+
log3(`After fetch, cache lookup: ${configData ? "found" : "still not found"}`);
|
|
1114
1455
|
}
|
|
1115
1456
|
if (!configData) {
|
|
1116
|
-
|
|
1457
|
+
log3(`Config not found, using fallback: ${fallback}`);
|
|
1117
1458
|
if (fallback) {
|
|
1118
1459
|
console.warn(`[Fallom WARNING] Config '${configKey}' not found, using fallback model: ${fallback}`);
|
|
1119
1460
|
return returnWithTrace(configKey, sessionId, fallback, 0);
|
|
@@ -1127,7 +1468,7 @@ async function get(configKey, sessionId, options = {}) {
|
|
|
1127
1468
|
if (version !== void 0) {
|
|
1128
1469
|
config = configData.versions.get(version);
|
|
1129
1470
|
if (!config) {
|
|
1130
|
-
config = await fetchSpecificVersion(configKey, version,
|
|
1471
|
+
config = await fetchSpecificVersion(configKey, version, SYNC_TIMEOUT2) || void 0;
|
|
1131
1472
|
}
|
|
1132
1473
|
if (!config) {
|
|
1133
1474
|
if (fallback) {
|
|
@@ -1151,22 +1492,22 @@ async function get(configKey, sessionId, options = {}) {
|
|
|
1151
1492
|
const variantsRaw = config.variants;
|
|
1152
1493
|
const configVersion = config.version || targetVersion;
|
|
1153
1494
|
const variants = Array.isArray(variantsRaw) ? variantsRaw : Object.values(variantsRaw);
|
|
1154
|
-
|
|
1155
|
-
const hashBytes = (0,
|
|
1495
|
+
log3(`Config found! Version: ${configVersion}, Variants: ${JSON.stringify(variants)}`);
|
|
1496
|
+
const hashBytes = (0, import_crypto2.createHash)("md5").update(sessionId).digest();
|
|
1156
1497
|
const hashVal = hashBytes.readUInt32BE(0) % 1e6;
|
|
1157
|
-
|
|
1498
|
+
log3(`Session hash: ${hashVal} (out of 1,000,000)`);
|
|
1158
1499
|
let cumulative = 0;
|
|
1159
1500
|
let assignedModel = variants[variants.length - 1].model;
|
|
1160
1501
|
for (const v of variants) {
|
|
1161
1502
|
const oldCumulative = cumulative;
|
|
1162
1503
|
cumulative += v.weight * 1e4;
|
|
1163
|
-
|
|
1504
|
+
log3(`Variant ${v.model}: weight=${v.weight}%, range=${oldCumulative}-${cumulative}, hash=${hashVal}, match=${hashVal < cumulative}`);
|
|
1164
1505
|
if (hashVal < cumulative) {
|
|
1165
1506
|
assignedModel = v.model;
|
|
1166
1507
|
break;
|
|
1167
1508
|
}
|
|
1168
1509
|
}
|
|
1169
|
-
|
|
1510
|
+
log3(`\u2705 Assigned model: ${assignedModel}`);
|
|
1170
1511
|
return returnWithTrace(configKey, sessionId, assignedModel, configVersion);
|
|
1171
1512
|
} catch (e) {
|
|
1172
1513
|
if (e instanceof Error && e.message.includes("not found")) {
|
|
@@ -1191,14 +1532,14 @@ function returnWithTrace(configKey, sessionId, model, version) {
|
|
|
1191
1532
|
return model;
|
|
1192
1533
|
}
|
|
1193
1534
|
async function recordSession(configKey, version, sessionId, model) {
|
|
1194
|
-
if (!
|
|
1535
|
+
if (!apiKey3) return;
|
|
1195
1536
|
try {
|
|
1196
1537
|
const controller = new AbortController();
|
|
1197
1538
|
const timeoutId = setTimeout(() => controller.abort(), RECORD_TIMEOUT);
|
|
1198
|
-
await fetch(`${
|
|
1539
|
+
await fetch(`${baseUrl3}/sessions`, {
|
|
1199
1540
|
method: "POST",
|
|
1200
1541
|
headers: {
|
|
1201
|
-
Authorization: `Bearer ${
|
|
1542
|
+
Authorization: `Bearer ${apiKey3}`,
|
|
1202
1543
|
"Content-Type": "application/json"
|
|
1203
1544
|
},
|
|
1204
1545
|
body: JSON.stringify({
|
|
@@ -1214,30 +1555,41 @@ async function recordSession(configKey, version, sessionId, model) {
|
|
|
1214
1555
|
}
|
|
1215
1556
|
}
|
|
1216
1557
|
|
|
1558
|
+
// src/index.ts
|
|
1559
|
+
init_prompts();
|
|
1560
|
+
|
|
1217
1561
|
// src/init.ts
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1562
|
+
init_prompts();
|
|
1563
|
+
async function init4(options = {}) {
|
|
1564
|
+
const baseUrl4 = options.baseUrl || process.env.FALLOM_BASE_URL || "https://spans.fallom.com";
|
|
1565
|
+
await init2({
|
|
1221
1566
|
apiKey: options.apiKey,
|
|
1222
|
-
baseUrl:
|
|
1567
|
+
baseUrl: baseUrl4,
|
|
1223
1568
|
captureContent: options.captureContent,
|
|
1224
1569
|
debug: options.debug
|
|
1225
1570
|
});
|
|
1226
|
-
|
|
1571
|
+
init3({
|
|
1572
|
+
apiKey: options.apiKey,
|
|
1573
|
+
baseUrl: baseUrl4
|
|
1574
|
+
});
|
|
1575
|
+
init({
|
|
1227
1576
|
apiKey: options.apiKey,
|
|
1228
|
-
baseUrl:
|
|
1577
|
+
baseUrl: baseUrl4
|
|
1229
1578
|
});
|
|
1230
1579
|
}
|
|
1231
1580
|
|
|
1232
1581
|
// src/index.ts
|
|
1582
|
+
init_prompts();
|
|
1233
1583
|
var index_default = {
|
|
1234
|
-
init:
|
|
1584
|
+
init: init4,
|
|
1235
1585
|
trace: trace_exports,
|
|
1236
|
-
models: models_exports
|
|
1586
|
+
models: models_exports,
|
|
1587
|
+
prompts: prompts_exports
|
|
1237
1588
|
};
|
|
1238
1589
|
// Annotate the CommonJS export names for ESM import in node:
|
|
1239
1590
|
0 && (module.exports = {
|
|
1240
1591
|
init,
|
|
1241
1592
|
models,
|
|
1593
|
+
prompts,
|
|
1242
1594
|
trace
|
|
1243
1595
|
});
|