@fallom/trace 0.1.12 → 0.2.0
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 +215 -178
- package/dist/chunk-2BP4H4AD.mjs +3012 -0
- package/dist/chunk-7P6ASYW6.mjs +9 -0
- package/dist/chunk-K7HYYE4Y.mjs +2930 -0
- package/dist/chunk-KAZ5NEU2.mjs +2237 -0
- package/dist/chunk-KMA4IPED.mjs +252 -0
- package/dist/chunk-W6M2RQ3W.mjs +251 -0
- package/dist/index.d.mts +210 -256
- package/dist/index.d.ts +210 -256
- package/dist/index.js +792 -789
- package/dist/index.mjs +592 -590
- package/dist/models-2Y6DRQPS.mjs +9 -0
- package/dist/models-BUHMMTWK.mjs +9 -0
- package/dist/models-JIO5LVMB.mjs +8 -0
- package/dist/models-JKMOBZUO.mjs +8 -0
- package/dist/prompts-XSZHTCX7.mjs +15 -0
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -20,249 +20,248 @@ var __copyProps = (to, from, except, desc) => {
|
|
|
20
20
|
};
|
|
21
21
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
22
22
|
|
|
23
|
-
// src/
|
|
24
|
-
var
|
|
25
|
-
__export(
|
|
26
|
-
clearPromptContext: () => clearPromptContext,
|
|
23
|
+
// src/models.ts
|
|
24
|
+
var models_exports = {};
|
|
25
|
+
__export(models_exports, {
|
|
27
26
|
get: () => get,
|
|
28
|
-
|
|
29
|
-
getPromptContext: () => getPromptContext,
|
|
30
|
-
init: () => init
|
|
27
|
+
init: () => init2
|
|
31
28
|
});
|
|
32
|
-
function
|
|
33
|
-
if (
|
|
34
|
-
console.log(`[Fallom
|
|
29
|
+
function log4(msg) {
|
|
30
|
+
if (debugMode2) {
|
|
31
|
+
console.log(`[Fallom] ${msg}`);
|
|
35
32
|
}
|
|
36
33
|
}
|
|
37
|
-
function
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
if (!
|
|
34
|
+
function init2(options = {}) {
|
|
35
|
+
apiKey2 = options.apiKey || process.env.FALLOM_API_KEY || null;
|
|
36
|
+
baseUrl2 = options.baseUrl || process.env.FALLOM_CONFIGS_URL || process.env.FALLOM_BASE_URL || "https://configs.fallom.com";
|
|
37
|
+
initialized2 = true;
|
|
38
|
+
if (!apiKey2) {
|
|
42
39
|
return;
|
|
43
40
|
}
|
|
44
|
-
|
|
41
|
+
fetchConfigs().catch(() => {
|
|
45
42
|
});
|
|
46
43
|
if (!syncInterval) {
|
|
47
44
|
syncInterval = setInterval(() => {
|
|
48
|
-
|
|
45
|
+
fetchConfigs().catch(() => {
|
|
49
46
|
});
|
|
50
47
|
}, 3e4);
|
|
51
48
|
syncInterval.unref();
|
|
52
49
|
}
|
|
53
50
|
}
|
|
54
51
|
function ensureInit() {
|
|
55
|
-
if (!
|
|
52
|
+
if (!initialized2) {
|
|
56
53
|
try {
|
|
57
|
-
|
|
54
|
+
init2();
|
|
58
55
|
} catch {
|
|
59
56
|
}
|
|
60
57
|
}
|
|
61
58
|
}
|
|
62
|
-
async function
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
59
|
+
async function fetchConfigs(timeout = SYNC_TIMEOUT) {
|
|
60
|
+
if (!apiKey2) {
|
|
61
|
+
log4("_fetchConfigs: No API key, skipping");
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
67
64
|
try {
|
|
65
|
+
log4(`Fetching configs from ${baseUrl2}/configs`);
|
|
68
66
|
const controller = new AbortController();
|
|
69
67
|
const timeoutId = setTimeout(() => controller.abort(), timeout);
|
|
70
|
-
const resp = await fetch(`${
|
|
71
|
-
headers: { Authorization: `Bearer ${
|
|
68
|
+
const resp = await fetch(`${baseUrl2}/configs`, {
|
|
69
|
+
headers: { Authorization: `Bearer ${apiKey2}` },
|
|
72
70
|
signal: controller.signal
|
|
73
71
|
});
|
|
74
72
|
clearTimeout(timeoutId);
|
|
73
|
+
log4(`Response status: ${resp.status}`);
|
|
75
74
|
if (resp.ok) {
|
|
76
75
|
const data = await resp.json();
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
76
|
+
const configs = data.configs || [];
|
|
77
|
+
log4(`Got ${configs.length} configs: ${configs.map((c) => c.key)}`);
|
|
78
|
+
for (const c of configs) {
|
|
79
|
+
const key = c.key;
|
|
80
|
+
const version = c.version || 1;
|
|
81
|
+
log4(`Config '${key}' v${version}: ${JSON.stringify(c.variants)}`);
|
|
82
|
+
if (!configCache.has(key)) {
|
|
83
|
+
configCache.set(key, { versions: /* @__PURE__ */ new Map(), latest: null });
|
|
80
84
|
}
|
|
81
|
-
const cached =
|
|
82
|
-
cached.versions.set(
|
|
83
|
-
|
|
84
|
-
userTemplate: p.user_template
|
|
85
|
-
});
|
|
86
|
-
cached.current = p.version;
|
|
85
|
+
const cached = configCache.get(key);
|
|
86
|
+
cached.versions.set(version, c);
|
|
87
|
+
cached.latest = version;
|
|
87
88
|
}
|
|
89
|
+
} else {
|
|
90
|
+
log4(`Fetch failed: ${resp.statusText}`);
|
|
88
91
|
}
|
|
89
|
-
} catch {
|
|
92
|
+
} catch (e) {
|
|
93
|
+
log4(`Fetch exception: ${e}`);
|
|
90
94
|
}
|
|
91
95
|
}
|
|
92
|
-
async function
|
|
93
|
-
if (!
|
|
96
|
+
async function fetchSpecificVersion(configKey, version, timeout = SYNC_TIMEOUT) {
|
|
97
|
+
if (!apiKey2) return null;
|
|
94
98
|
try {
|
|
95
99
|
const controller = new AbortController();
|
|
96
100
|
const timeoutId = setTimeout(() => controller.abort(), timeout);
|
|
97
|
-
const resp = await fetch(
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
+
const resp = await fetch(
|
|
102
|
+
`${baseUrl2}/configs/${configKey}/version/${version}`,
|
|
103
|
+
{
|
|
104
|
+
headers: { Authorization: `Bearer ${apiKey2}` },
|
|
105
|
+
signal: controller.signal
|
|
106
|
+
}
|
|
107
|
+
);
|
|
101
108
|
clearTimeout(timeoutId);
|
|
102
109
|
if (resp.ok) {
|
|
103
|
-
const
|
|
104
|
-
|
|
105
|
-
|
|
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;
|
|
110
|
+
const config = await resp.json();
|
|
111
|
+
if (!configCache.has(configKey)) {
|
|
112
|
+
configCache.set(configKey, { versions: /* @__PURE__ */ new Map(), latest: null });
|
|
111
113
|
}
|
|
114
|
+
configCache.get(configKey).versions.set(version, config);
|
|
115
|
+
return config;
|
|
112
116
|
}
|
|
113
117
|
} catch {
|
|
114
118
|
}
|
|
119
|
+
return null;
|
|
115
120
|
}
|
|
116
|
-
function
|
|
117
|
-
|
|
118
|
-
|
|
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;
|
|
121
|
+
async function get(configKey, sessionId, options = {}) {
|
|
122
|
+
const { version, fallback, debug = false } = options;
|
|
123
|
+
debugMode2 = debug;
|
|
171
124
|
ensureInit();
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
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
|
-
log(`A/B test '${abTestKey}' has ${variants?.length ?? 0} variants`);
|
|
191
|
-
log(`Version data: ${JSON.stringify(versionData, null, 2)}`);
|
|
192
|
-
if (!variants || variants.length === 0) {
|
|
193
|
-
throw new Error(
|
|
194
|
-
`Prompt A/B test '${abTestKey}' has no variants configured.`
|
|
125
|
+
log4(
|
|
126
|
+
`get() called: configKey=${configKey}, sessionId=${sessionId}, fallback=${fallback}`
|
|
127
|
+
);
|
|
128
|
+
try {
|
|
129
|
+
let configData = configCache.get(configKey);
|
|
130
|
+
log4(
|
|
131
|
+
`Cache lookup for '${configKey}': ${configData ? "found" : "not found"}`
|
|
195
132
|
);
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
cumulative += variants[i].weight * 1e4;
|
|
204
|
-
if (hashVal < cumulative) {
|
|
205
|
-
selectedVariant = variants[i];
|
|
206
|
-
selectedIndex = i;
|
|
207
|
-
break;
|
|
133
|
+
if (!configData) {
|
|
134
|
+
log4("Not in cache, fetching...");
|
|
135
|
+
await fetchConfigs(SYNC_TIMEOUT);
|
|
136
|
+
configData = configCache.get(configKey);
|
|
137
|
+
log4(
|
|
138
|
+
`After fetch, cache lookup: ${configData ? "found" : "still not found"}`
|
|
139
|
+
);
|
|
208
140
|
}
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
141
|
+
if (!configData) {
|
|
142
|
+
log4(`Config not found, using fallback: ${fallback}`);
|
|
143
|
+
if (fallback) {
|
|
144
|
+
console.warn(
|
|
145
|
+
`[Fallom WARNING] Config '${configKey}' not found, using fallback model: ${fallback}`
|
|
146
|
+
);
|
|
147
|
+
return returnModel(configKey, sessionId, fallback, 0);
|
|
148
|
+
}
|
|
149
|
+
throw new Error(
|
|
150
|
+
`Config '${configKey}' not found. Check that it exists in your Fallom dashboard.`
|
|
151
|
+
);
|
|
152
|
+
}
|
|
153
|
+
let config;
|
|
154
|
+
let targetVersion;
|
|
155
|
+
if (version !== void 0) {
|
|
156
|
+
config = configData.versions.get(version);
|
|
157
|
+
if (!config) {
|
|
158
|
+
config = await fetchSpecificVersion(configKey, version, SYNC_TIMEOUT) || void 0;
|
|
159
|
+
}
|
|
160
|
+
if (!config) {
|
|
161
|
+
if (fallback) {
|
|
162
|
+
console.warn(
|
|
163
|
+
`[Fallom WARNING] Config '${configKey}' version ${version} not found, using fallback: ${fallback}`
|
|
164
|
+
);
|
|
165
|
+
return returnModel(configKey, sessionId, fallback, 0);
|
|
166
|
+
}
|
|
167
|
+
throw new Error(`Config '${configKey}' version ${version} not found.`);
|
|
168
|
+
}
|
|
169
|
+
targetVersion = version;
|
|
170
|
+
} else {
|
|
171
|
+
targetVersion = configData.latest;
|
|
172
|
+
config = configData.versions.get(targetVersion);
|
|
173
|
+
if (!config) {
|
|
174
|
+
if (fallback) {
|
|
175
|
+
console.warn(
|
|
176
|
+
`[Fallom WARNING] Config '${configKey}' has no cached version, using fallback: ${fallback}`
|
|
177
|
+
);
|
|
178
|
+
return returnModel(configKey, sessionId, fallback, 0);
|
|
179
|
+
}
|
|
180
|
+
throw new Error(`Config '${configKey}' has no cached version.`);
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
const variantsRaw = config.variants;
|
|
184
|
+
const configVersion = config.version || targetVersion;
|
|
185
|
+
const variants = Array.isArray(variantsRaw) ? variantsRaw : Object.values(variantsRaw);
|
|
186
|
+
log4(
|
|
187
|
+
`Config found! Version: ${configVersion}, Variants: ${JSON.stringify(
|
|
188
|
+
variants
|
|
189
|
+
)}`
|
|
220
190
|
);
|
|
191
|
+
const hashBytes = (0, import_crypto.createHash)("md5").update(sessionId).digest();
|
|
192
|
+
const hashVal = hashBytes.readUInt32BE(0) % 1e6;
|
|
193
|
+
log4(`Session hash: ${hashVal} (out of 1,000,000)`);
|
|
194
|
+
let cumulative = 0;
|
|
195
|
+
let assignedModel = variants[variants.length - 1].model;
|
|
196
|
+
for (const v of variants) {
|
|
197
|
+
const oldCumulative = cumulative;
|
|
198
|
+
cumulative += v.weight * 1e4;
|
|
199
|
+
log4(
|
|
200
|
+
`Variant ${v.model}: weight=${v.weight}%, range=${oldCumulative}-${cumulative}, hash=${hashVal}, match=${hashVal < cumulative}`
|
|
201
|
+
);
|
|
202
|
+
if (hashVal < cumulative) {
|
|
203
|
+
assignedModel = v.model;
|
|
204
|
+
break;
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
log4(`\u2705 Assigned model: ${assignedModel}`);
|
|
208
|
+
return returnModel(configKey, sessionId, assignedModel, configVersion);
|
|
209
|
+
} catch (e) {
|
|
210
|
+
if (e instanceof Error && e.message.includes("not found")) {
|
|
211
|
+
throw e;
|
|
212
|
+
}
|
|
213
|
+
if (fallback) {
|
|
214
|
+
console.warn(
|
|
215
|
+
`[Fallom WARNING] Error getting model for '${configKey}': ${e}. Using fallback: ${fallback}`
|
|
216
|
+
);
|
|
217
|
+
return returnModel(configKey, sessionId, fallback, 0);
|
|
218
|
+
}
|
|
219
|
+
throw e;
|
|
221
220
|
}
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
if (
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
);
|
|
221
|
+
}
|
|
222
|
+
function returnModel(configKey, sessionId, model, version) {
|
|
223
|
+
if (version > 0) {
|
|
224
|
+
recordSession(configKey, version, sessionId, model).catch(() => {
|
|
225
|
+
});
|
|
228
226
|
}
|
|
229
|
-
|
|
230
|
-
const user = replaceVariables(content.userTemplate, variables);
|
|
231
|
-
setPromptContext({
|
|
232
|
-
promptKey,
|
|
233
|
-
promptVersion: targetVersion,
|
|
234
|
-
abTestKey,
|
|
235
|
-
variantIndex: selectedIndex
|
|
236
|
-
});
|
|
237
|
-
log(
|
|
238
|
-
`\u2705 Got prompt from A/B: ${promptKey} v${targetVersion} (variant ${selectedIndex})`
|
|
239
|
-
);
|
|
240
|
-
return {
|
|
241
|
-
key: promptKey,
|
|
242
|
-
version: targetVersion,
|
|
243
|
-
system,
|
|
244
|
-
user,
|
|
245
|
-
abTestKey,
|
|
246
|
-
variantIndex: selectedIndex
|
|
247
|
-
};
|
|
227
|
+
return model;
|
|
248
228
|
}
|
|
249
|
-
function
|
|
250
|
-
|
|
229
|
+
async function recordSession(configKey, version, sessionId, model) {
|
|
230
|
+
if (!apiKey2) return;
|
|
231
|
+
try {
|
|
232
|
+
const controller = new AbortController();
|
|
233
|
+
const timeoutId = setTimeout(() => controller.abort(), RECORD_TIMEOUT);
|
|
234
|
+
await fetch(`${baseUrl2}/sessions`, {
|
|
235
|
+
method: "POST",
|
|
236
|
+
headers: {
|
|
237
|
+
Authorization: `Bearer ${apiKey2}`,
|
|
238
|
+
"Content-Type": "application/json"
|
|
239
|
+
},
|
|
240
|
+
body: JSON.stringify({
|
|
241
|
+
config_key: configKey,
|
|
242
|
+
config_version: version,
|
|
243
|
+
session_id: sessionId,
|
|
244
|
+
assigned_model: model
|
|
245
|
+
}),
|
|
246
|
+
signal: controller.signal
|
|
247
|
+
});
|
|
248
|
+
clearTimeout(timeoutId);
|
|
249
|
+
} catch {
|
|
250
|
+
}
|
|
251
251
|
}
|
|
252
|
-
var import_crypto,
|
|
253
|
-
var
|
|
254
|
-
"src/
|
|
252
|
+
var import_crypto, apiKey2, baseUrl2, initialized2, syncInterval, debugMode2, configCache, SYNC_TIMEOUT, RECORD_TIMEOUT;
|
|
253
|
+
var init_models = __esm({
|
|
254
|
+
"src/models.ts"() {
|
|
255
255
|
"use strict";
|
|
256
256
|
import_crypto = require("crypto");
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
257
|
+
apiKey2 = null;
|
|
258
|
+
baseUrl2 = "https://configs.fallom.com";
|
|
259
|
+
initialized2 = false;
|
|
260
260
|
syncInterval = null;
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
promptABCache = /* @__PURE__ */ new Map();
|
|
264
|
-
promptContext = null;
|
|
261
|
+
debugMode2 = false;
|
|
262
|
+
configCache = /* @__PURE__ */ new Map();
|
|
265
263
|
SYNC_TIMEOUT = 2e3;
|
|
264
|
+
RECORD_TIMEOUT = 1e3;
|
|
266
265
|
}
|
|
267
266
|
});
|
|
268
267
|
|
|
@@ -270,11 +269,13 @@ var init_prompts = __esm({
|
|
|
270
269
|
var index_exports = {};
|
|
271
270
|
__export(index_exports, {
|
|
272
271
|
FallomExporter: () => FallomExporter,
|
|
272
|
+
FallomSession: () => FallomSession,
|
|
273
273
|
clearMastraPrompt: () => clearMastraPrompt,
|
|
274
274
|
default: () => index_default,
|
|
275
275
|
init: () => init4,
|
|
276
276
|
models: () => models_exports,
|
|
277
277
|
prompts: () => prompts_exports,
|
|
278
|
+
session: () => session,
|
|
278
279
|
setMastraPrompt: () => setMastraPrompt,
|
|
279
280
|
setMastraPromptAB: () => setMastraPromptAB,
|
|
280
281
|
trace: () => trace_exports
|
|
@@ -284,19 +285,13 @@ module.exports = __toCommonJS(index_exports);
|
|
|
284
285
|
// src/trace.ts
|
|
285
286
|
var trace_exports = {};
|
|
286
287
|
__export(trace_exports, {
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
setSession: () => setSession,
|
|
292
|
-
shutdown: () => shutdown,
|
|
293
|
-
span: () => span,
|
|
294
|
-
wrapAISDK: () => wrapAISDK,
|
|
295
|
-
wrapAnthropic: () => wrapAnthropic,
|
|
296
|
-
wrapGoogleAI: () => wrapGoogleAI,
|
|
297
|
-
wrapMastraAgent: () => wrapMastraAgent,
|
|
298
|
-
wrapOpenAI: () => wrapOpenAI
|
|
288
|
+
FallomSession: () => FallomSession,
|
|
289
|
+
init: () => init,
|
|
290
|
+
session: () => session,
|
|
291
|
+
shutdown: () => shutdown
|
|
299
292
|
});
|
|
293
|
+
|
|
294
|
+
// src/trace/core.ts
|
|
300
295
|
var import_async_hooks = require("async_hooks");
|
|
301
296
|
var import_sdk_node = require("@opentelemetry/sdk-node");
|
|
302
297
|
var import_exporter_trace_otlp_http = require("@opentelemetry/exporter-trace-otlp-http");
|
|
@@ -898,40 +893,39 @@ var Resource = (
|
|
|
898
893
|
})()
|
|
899
894
|
);
|
|
900
895
|
|
|
901
|
-
// src/trace.ts
|
|
902
|
-
var
|
|
903
|
-
var
|
|
904
|
-
var
|
|
905
|
-
var
|
|
906
|
-
var
|
|
896
|
+
// src/trace/core.ts
|
|
897
|
+
var traceContextStorage = new import_async_hooks.AsyncLocalStorage();
|
|
898
|
+
var fallbackTraceContext = null;
|
|
899
|
+
var apiKey = null;
|
|
900
|
+
var baseUrl = "https://traces.fallom.com";
|
|
901
|
+
var initialized = false;
|
|
907
902
|
var captureContent = true;
|
|
908
|
-
var
|
|
903
|
+
var debugMode = false;
|
|
909
904
|
var sdk = null;
|
|
910
|
-
function
|
|
911
|
-
if (
|
|
905
|
+
function log(...args) {
|
|
906
|
+
if (debugMode) console.log("[Fallom]", ...args);
|
|
912
907
|
}
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
}
|
|
908
|
+
function getTraceContextStorage() {
|
|
909
|
+
return traceContextStorage;
|
|
910
|
+
}
|
|
911
|
+
function getFallbackTraceContext() {
|
|
912
|
+
return fallbackTraceContext;
|
|
913
|
+
}
|
|
914
|
+
function isInitialized() {
|
|
915
|
+
return initialized;
|
|
916
|
+
}
|
|
917
|
+
function shouldCaptureContent() {
|
|
918
|
+
return captureContent;
|
|
919
|
+
}
|
|
920
|
+
function isDebugMode() {
|
|
921
|
+
return debugMode;
|
|
922
|
+
}
|
|
923
|
+
var fallomSpanProcessor = {
|
|
924
|
+
onStart(span, _parentContext) {
|
|
925
|
+
log("\u{1F4CD} Span started:", span.name || "unknown");
|
|
932
926
|
},
|
|
933
|
-
onEnd(
|
|
934
|
-
|
|
927
|
+
onEnd(span) {
|
|
928
|
+
log("\u2705 Span ended:", span.name, "duration:", span.duration);
|
|
935
929
|
},
|
|
936
930
|
shutdown() {
|
|
937
931
|
return Promise.resolve();
|
|
@@ -940,47 +934,6 @@ var fallomSpanProcessor = {
|
|
|
940
934
|
return Promise.resolve();
|
|
941
935
|
}
|
|
942
936
|
};
|
|
943
|
-
async function init2(options = {}) {
|
|
944
|
-
if (initialized2) return;
|
|
945
|
-
debugMode2 = options.debug ?? false;
|
|
946
|
-
log2("\u{1F680} Initializing Fallom tracing...");
|
|
947
|
-
apiKey2 = options.apiKey || process.env.FALLOM_API_KEY || null;
|
|
948
|
-
baseUrl2 = options.baseUrl || process.env.FALLOM_TRACES_URL || process.env.FALLOM_BASE_URL || "https://traces.fallom.com";
|
|
949
|
-
const envCapture = process.env.FALLOM_CAPTURE_CONTENT?.toLowerCase();
|
|
950
|
-
if (envCapture === "false" || envCapture === "0" || envCapture === "no") {
|
|
951
|
-
captureContent = false;
|
|
952
|
-
} else {
|
|
953
|
-
captureContent = options.captureContent ?? true;
|
|
954
|
-
}
|
|
955
|
-
if (!apiKey2) {
|
|
956
|
-
throw new Error(
|
|
957
|
-
"No API key provided. Set FALLOM_API_KEY environment variable or pass apiKey parameter."
|
|
958
|
-
);
|
|
959
|
-
}
|
|
960
|
-
initialized2 = true;
|
|
961
|
-
log2("\u{1F4E1} Exporter URL:", `${baseUrl2}/v1/traces`);
|
|
962
|
-
const exporter = new import_exporter_trace_otlp_http.OTLPTraceExporter({
|
|
963
|
-
url: `${baseUrl2}/v1/traces`,
|
|
964
|
-
headers: {
|
|
965
|
-
Authorization: `Bearer ${apiKey2}`
|
|
966
|
-
}
|
|
967
|
-
});
|
|
968
|
-
const instrumentations = await getInstrumentations();
|
|
969
|
-
log2("\u{1F527} Loaded instrumentations:", instrumentations.length);
|
|
970
|
-
sdk = new import_sdk_node.NodeSDK({
|
|
971
|
-
resource: new Resource({
|
|
972
|
-
"service.name": "fallom-traced-app"
|
|
973
|
-
}),
|
|
974
|
-
traceExporter: exporter,
|
|
975
|
-
spanProcessor: fallomSpanProcessor,
|
|
976
|
-
instrumentations
|
|
977
|
-
});
|
|
978
|
-
sdk.start();
|
|
979
|
-
log2("\u2705 SDK started");
|
|
980
|
-
process.on("SIGTERM", () => {
|
|
981
|
-
sdk?.shutdown().catch(console.error);
|
|
982
|
-
});
|
|
983
|
-
}
|
|
984
937
|
async function getInstrumentations() {
|
|
985
938
|
const instrumentations = [];
|
|
986
939
|
await tryAddInstrumentation(
|
|
@@ -1028,82 +981,97 @@ async function tryAddInstrumentation(instrumentations, pkg, className) {
|
|
|
1028
981
|
instrumentations.push(
|
|
1029
982
|
new InstrumentationClass({ traceContent: captureContent })
|
|
1030
983
|
);
|
|
1031
|
-
|
|
984
|
+
log(` \u2705 Loaded ${pkg}`);
|
|
1032
985
|
} else {
|
|
1033
|
-
|
|
986
|
+
log(
|
|
1034
987
|
` \u26A0\uFE0F ${pkg} loaded but ${className} not found. Available:`,
|
|
1035
988
|
Object.keys(mod)
|
|
1036
989
|
);
|
|
1037
990
|
}
|
|
1038
|
-
} catch
|
|
1039
|
-
|
|
1040
|
-
}
|
|
1041
|
-
}
|
|
1042
|
-
function setSession(configKey, sessionId, customerId) {
|
|
1043
|
-
const store = sessionStorage.getStore();
|
|
1044
|
-
if (store) {
|
|
1045
|
-
store.configKey = configKey;
|
|
1046
|
-
store.sessionId = sessionId;
|
|
1047
|
-
store.customerId = customerId;
|
|
1048
|
-
}
|
|
1049
|
-
fallbackSession = { configKey, sessionId, customerId };
|
|
1050
|
-
}
|
|
1051
|
-
function runWithSession(configKey, sessionId, customerIdOrFn, fn) {
|
|
1052
|
-
if (typeof customerIdOrFn === "function") {
|
|
1053
|
-
return sessionStorage.run({ configKey, sessionId }, customerIdOrFn);
|
|
991
|
+
} catch {
|
|
992
|
+
log(` \u274C ${pkg} not installed`);
|
|
1054
993
|
}
|
|
1055
|
-
return sessionStorage.run(
|
|
1056
|
-
{ configKey, sessionId, customerId: customerIdOrFn },
|
|
1057
|
-
fn
|
|
1058
|
-
);
|
|
1059
|
-
}
|
|
1060
|
-
function getSession() {
|
|
1061
|
-
return sessionStorage.getStore() || fallbackSession || void 0;
|
|
1062
|
-
}
|
|
1063
|
-
function clearSession() {
|
|
1064
|
-
fallbackSession = null;
|
|
1065
994
|
}
|
|
1066
|
-
function
|
|
1067
|
-
if (
|
|
1068
|
-
|
|
995
|
+
async function init(options = {}) {
|
|
996
|
+
if (initialized) return;
|
|
997
|
+
debugMode = options.debug ?? false;
|
|
998
|
+
log("\u{1F680} Initializing Fallom tracing...");
|
|
999
|
+
apiKey = options.apiKey || process.env.FALLOM_API_KEY || null;
|
|
1000
|
+
baseUrl = options.baseUrl || process.env.FALLOM_TRACES_URL || process.env.FALLOM_BASE_URL || "https://traces.fallom.com";
|
|
1001
|
+
const envCapture = process.env.FALLOM_CAPTURE_CONTENT?.toLowerCase();
|
|
1002
|
+
if (envCapture === "false" || envCapture === "0" || envCapture === "no") {
|
|
1003
|
+
captureContent = false;
|
|
1004
|
+
} else {
|
|
1005
|
+
captureContent = options.captureContent ?? true;
|
|
1069
1006
|
}
|
|
1070
|
-
|
|
1071
|
-
const configKey = options.configKey || ctx?.configKey;
|
|
1072
|
-
const sessionId = options.sessionId || ctx?.sessionId;
|
|
1073
|
-
if (!configKey || !sessionId) {
|
|
1007
|
+
if (!apiKey) {
|
|
1074
1008
|
throw new Error(
|
|
1075
|
-
"No
|
|
1009
|
+
"No API key provided. Set FALLOM_API_KEY environment variable or pass apiKey parameter."
|
|
1076
1010
|
);
|
|
1077
1011
|
}
|
|
1078
|
-
|
|
1012
|
+
initialized = true;
|
|
1013
|
+
log("\u{1F4E1} Exporter URL:", `${baseUrl}/v1/traces`);
|
|
1014
|
+
const exporter = new import_exporter_trace_otlp_http.OTLPTraceExporter({
|
|
1015
|
+
url: `${baseUrl}/v1/traces`,
|
|
1016
|
+
headers: {
|
|
1017
|
+
Authorization: `Bearer ${apiKey}`
|
|
1018
|
+
}
|
|
1019
|
+
});
|
|
1020
|
+
const instrumentations = await getInstrumentations();
|
|
1021
|
+
log("\u{1F527} Loaded instrumentations:", instrumentations.length);
|
|
1022
|
+
sdk = new import_sdk_node.NodeSDK({
|
|
1023
|
+
resource: new Resource({
|
|
1024
|
+
"service.name": "fallom-traced-app"
|
|
1025
|
+
}),
|
|
1026
|
+
traceExporter: exporter,
|
|
1027
|
+
spanProcessor: fallomSpanProcessor,
|
|
1028
|
+
instrumentations
|
|
1029
|
+
});
|
|
1030
|
+
sdk.start();
|
|
1031
|
+
log("\u2705 SDK started");
|
|
1032
|
+
process.on("SIGTERM", () => {
|
|
1033
|
+
sdk?.shutdown().catch(console.error);
|
|
1079
1034
|
});
|
|
1080
1035
|
}
|
|
1081
|
-
async function
|
|
1036
|
+
async function shutdown() {
|
|
1037
|
+
if (sdk) {
|
|
1038
|
+
await sdk.shutdown();
|
|
1039
|
+
initialized = false;
|
|
1040
|
+
}
|
|
1041
|
+
}
|
|
1042
|
+
async function sendTrace(trace) {
|
|
1043
|
+
const url = `${baseUrl}/v1/traces`;
|
|
1044
|
+
log("\u{1F4E4} Sending trace to:", url);
|
|
1045
|
+
log(" Session:", trace.session_id, "Config:", trace.config_key);
|
|
1082
1046
|
try {
|
|
1083
1047
|
const controller = new AbortController();
|
|
1084
1048
|
const timeoutId = setTimeout(() => controller.abort(), 5e3);
|
|
1085
|
-
await fetch(
|
|
1049
|
+
const response = await fetch(url, {
|
|
1086
1050
|
method: "POST",
|
|
1087
1051
|
headers: {
|
|
1088
|
-
Authorization: `Bearer ${
|
|
1052
|
+
Authorization: `Bearer ${apiKey}`,
|
|
1089
1053
|
"Content-Type": "application/json"
|
|
1090
1054
|
},
|
|
1091
|
-
body: JSON.stringify(
|
|
1092
|
-
config_key: configKey,
|
|
1093
|
-
session_id: sessionId,
|
|
1094
|
-
data
|
|
1095
|
-
}),
|
|
1055
|
+
body: JSON.stringify(trace),
|
|
1096
1056
|
signal: controller.signal
|
|
1097
1057
|
});
|
|
1098
1058
|
clearTimeout(timeoutId);
|
|
1099
|
-
|
|
1059
|
+
if (!response.ok) {
|
|
1060
|
+
const text = await response.text();
|
|
1061
|
+
log("\u274C Trace send failed:", response.status, text);
|
|
1062
|
+
} else {
|
|
1063
|
+
log("\u2705 Trace sent:", trace.name, trace.model);
|
|
1064
|
+
}
|
|
1065
|
+
} catch (err) {
|
|
1066
|
+
log("\u274C Trace send error:", err instanceof Error ? err.message : err);
|
|
1100
1067
|
}
|
|
1101
1068
|
}
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1069
|
+
|
|
1070
|
+
// src/trace/utils.ts
|
|
1071
|
+
function generateHexId(length) {
|
|
1072
|
+
const bytes = new Uint8Array(length / 2);
|
|
1073
|
+
crypto.getRandomValues(bytes);
|
|
1074
|
+
return Array.from(bytes).map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
1107
1075
|
}
|
|
1108
1076
|
function messagesToOtelAttributes(messages, completion, model, responseId) {
|
|
1109
1077
|
const attrs = {};
|
|
@@ -1131,65 +1099,28 @@ function messagesToOtelAttributes(messages, completion, model, responseId) {
|
|
|
1131
1099
|
}
|
|
1132
1100
|
return attrs;
|
|
1133
1101
|
}
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
return Array.from(bytes).map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
1138
|
-
}
|
|
1139
|
-
var traceContextStorage = new import_async_hooks.AsyncLocalStorage();
|
|
1140
|
-
var fallbackTraceContext = null;
|
|
1141
|
-
async function sendTrace(trace) {
|
|
1142
|
-
const url = `${baseUrl2}/v1/traces`;
|
|
1143
|
-
log2("\u{1F4E4} Sending trace to:", url);
|
|
1144
|
-
log2(" Session:", trace.session_id, "Config:", trace.config_key);
|
|
1145
|
-
try {
|
|
1146
|
-
const controller = new AbortController();
|
|
1147
|
-
const timeoutId = setTimeout(() => controller.abort(), 5e3);
|
|
1148
|
-
const response = await fetch(url, {
|
|
1149
|
-
method: "POST",
|
|
1150
|
-
headers: {
|
|
1151
|
-
Authorization: `Bearer ${apiKey2}`,
|
|
1152
|
-
"Content-Type": "application/json"
|
|
1153
|
-
},
|
|
1154
|
-
body: JSON.stringify(trace),
|
|
1155
|
-
signal: controller.signal
|
|
1156
|
-
});
|
|
1157
|
-
clearTimeout(timeoutId);
|
|
1158
|
-
if (!response.ok) {
|
|
1159
|
-
const text = await response.text();
|
|
1160
|
-
log2("\u274C Trace send failed:", response.status, text);
|
|
1161
|
-
} else {
|
|
1162
|
-
log2("\u2705 Trace sent:", trace.name, trace.model);
|
|
1163
|
-
}
|
|
1164
|
-
} catch (err) {
|
|
1165
|
-
log2("\u274C Trace send error:", err instanceof Error ? err.message : err);
|
|
1166
|
-
}
|
|
1167
|
-
}
|
|
1168
|
-
function wrapOpenAI(client) {
|
|
1102
|
+
|
|
1103
|
+
// src/trace/wrappers/openai.ts
|
|
1104
|
+
function wrapOpenAI(client, sessionCtx) {
|
|
1169
1105
|
const originalCreate = client.chat.completions.create.bind(
|
|
1170
1106
|
client.chat.completions
|
|
1171
1107
|
);
|
|
1108
|
+
const ctx = sessionCtx;
|
|
1172
1109
|
client.chat.completions.create = async function(...args) {
|
|
1173
|
-
|
|
1174
|
-
if (!ctx || !initialized2) {
|
|
1110
|
+
if (!isInitialized()) {
|
|
1175
1111
|
return originalCreate(...args);
|
|
1176
1112
|
}
|
|
1177
|
-
|
|
1178
|
-
try {
|
|
1179
|
-
const { getPromptContext: getPromptContext2 } = await Promise.resolve().then(() => (init_prompts(), prompts_exports));
|
|
1180
|
-
promptCtx = getPromptContext2();
|
|
1181
|
-
} catch {
|
|
1182
|
-
}
|
|
1183
|
-
const traceCtx = traceContextStorage.getStore() || fallbackTraceContext;
|
|
1113
|
+
const traceCtx = getTraceContextStorage().getStore() || getFallbackTraceContext();
|
|
1184
1114
|
const traceId = traceCtx?.traceId || generateHexId(32);
|
|
1185
1115
|
const spanId = generateHexId(16);
|
|
1186
1116
|
const parentSpanId = traceCtx?.parentSpanId;
|
|
1187
1117
|
const params = args[0] || {};
|
|
1188
1118
|
const startTime = Date.now();
|
|
1119
|
+
const captureContent2 = shouldCaptureContent();
|
|
1189
1120
|
try {
|
|
1190
1121
|
const response = await originalCreate(...args);
|
|
1191
1122
|
const endTime = Date.now();
|
|
1192
|
-
const attributes =
|
|
1123
|
+
const attributes = captureContent2 ? messagesToOtelAttributes(
|
|
1193
1124
|
params?.messages,
|
|
1194
1125
|
response?.choices?.[0]?.message,
|
|
1195
1126
|
response?.model || params?.model,
|
|
@@ -1218,17 +1149,13 @@ function wrapOpenAI(client) {
|
|
|
1218
1149
|
prompt_tokens: response?.usage?.prompt_tokens,
|
|
1219
1150
|
completion_tokens: response?.usage?.completion_tokens,
|
|
1220
1151
|
total_tokens: response?.usage?.total_tokens,
|
|
1221
|
-
attributes: Object.keys(attributes).length > 0 ? attributes : void 0
|
|
1222
|
-
prompt_key: promptCtx?.promptKey,
|
|
1223
|
-
prompt_version: promptCtx?.promptVersion,
|
|
1224
|
-
prompt_ab_test_key: promptCtx?.abTestKey,
|
|
1225
|
-
prompt_variant_index: promptCtx?.variantIndex
|
|
1152
|
+
attributes: Object.keys(attributes).length > 0 ? attributes : void 0
|
|
1226
1153
|
}).catch(() => {
|
|
1227
1154
|
});
|
|
1228
1155
|
return response;
|
|
1229
1156
|
} catch (error) {
|
|
1230
1157
|
const endTime = Date.now();
|
|
1231
|
-
const attributes =
|
|
1158
|
+
const attributes = captureContent2 ? messagesToOtelAttributes(
|
|
1232
1159
|
params?.messages,
|
|
1233
1160
|
void 0,
|
|
1234
1161
|
params?.model,
|
|
@@ -1252,11 +1179,7 @@ function wrapOpenAI(client) {
|
|
|
1252
1179
|
duration_ms: endTime - startTime,
|
|
1253
1180
|
status: "ERROR",
|
|
1254
1181
|
error_message: error?.message,
|
|
1255
|
-
attributes
|
|
1256
|
-
prompt_key: promptCtx?.promptKey,
|
|
1257
|
-
prompt_version: promptCtx?.promptVersion,
|
|
1258
|
-
prompt_ab_test_key: promptCtx?.abTestKey,
|
|
1259
|
-
prompt_variant_index: promptCtx?.variantIndex
|
|
1182
|
+
attributes
|
|
1260
1183
|
}).catch(() => {
|
|
1261
1184
|
});
|
|
1262
1185
|
throw error;
|
|
@@ -1264,29 +1187,26 @@ function wrapOpenAI(client) {
|
|
|
1264
1187
|
};
|
|
1265
1188
|
return client;
|
|
1266
1189
|
}
|
|
1267
|
-
|
|
1190
|
+
|
|
1191
|
+
// src/trace/wrappers/anthropic.ts
|
|
1192
|
+
function wrapAnthropic(client, sessionCtx) {
|
|
1268
1193
|
const originalCreate = client.messages.create.bind(client.messages);
|
|
1194
|
+
const ctx = sessionCtx;
|
|
1269
1195
|
client.messages.create = async function(...args) {
|
|
1270
|
-
|
|
1271
|
-
if (!ctx || !initialized2) {
|
|
1196
|
+
if (!isInitialized()) {
|
|
1272
1197
|
return originalCreate(...args);
|
|
1273
1198
|
}
|
|
1274
|
-
|
|
1275
|
-
try {
|
|
1276
|
-
const { getPromptContext: getPromptContext2 } = await Promise.resolve().then(() => (init_prompts(), prompts_exports));
|
|
1277
|
-
promptCtx = getPromptContext2();
|
|
1278
|
-
} catch {
|
|
1279
|
-
}
|
|
1280
|
-
const traceCtx = traceContextStorage.getStore() || fallbackTraceContext;
|
|
1199
|
+
const traceCtx = getTraceContextStorage().getStore() || getFallbackTraceContext();
|
|
1281
1200
|
const traceId = traceCtx?.traceId || generateHexId(32);
|
|
1282
1201
|
const spanId = generateHexId(16);
|
|
1283
1202
|
const parentSpanId = traceCtx?.parentSpanId;
|
|
1284
1203
|
const params = args[0] || {};
|
|
1285
1204
|
const startTime = Date.now();
|
|
1205
|
+
const captureContent2 = shouldCaptureContent();
|
|
1286
1206
|
try {
|
|
1287
1207
|
const response = await originalCreate(...args);
|
|
1288
1208
|
const endTime = Date.now();
|
|
1289
|
-
const attributes =
|
|
1209
|
+
const attributes = captureContent2 ? messagesToOtelAttributes(
|
|
1290
1210
|
params?.messages,
|
|
1291
1211
|
{ role: "assistant", content: response?.content?.[0]?.text || "" },
|
|
1292
1212
|
response?.model || params?.model,
|
|
@@ -1318,17 +1238,13 @@ function wrapAnthropic(client) {
|
|
|
1318
1238
|
prompt_tokens: response?.usage?.input_tokens,
|
|
1319
1239
|
completion_tokens: response?.usage?.output_tokens,
|
|
1320
1240
|
total_tokens: (response?.usage?.input_tokens || 0) + (response?.usage?.output_tokens || 0),
|
|
1321
|
-
attributes: Object.keys(attributes).length > 0 ? attributes : void 0
|
|
1322
|
-
prompt_key: promptCtx?.promptKey,
|
|
1323
|
-
prompt_version: promptCtx?.promptVersion,
|
|
1324
|
-
prompt_ab_test_key: promptCtx?.abTestKey,
|
|
1325
|
-
prompt_variant_index: promptCtx?.variantIndex
|
|
1241
|
+
attributes: Object.keys(attributes).length > 0 ? attributes : void 0
|
|
1326
1242
|
}).catch(() => {
|
|
1327
1243
|
});
|
|
1328
1244
|
return response;
|
|
1329
1245
|
} catch (error) {
|
|
1330
1246
|
const endTime = Date.now();
|
|
1331
|
-
const attributes =
|
|
1247
|
+
const attributes = captureContent2 ? messagesToOtelAttributes(
|
|
1332
1248
|
params?.messages,
|
|
1333
1249
|
void 0,
|
|
1334
1250
|
params?.model,
|
|
@@ -1355,11 +1271,7 @@ function wrapAnthropic(client) {
|
|
|
1355
1271
|
duration_ms: endTime - startTime,
|
|
1356
1272
|
status: "ERROR",
|
|
1357
1273
|
error_message: error?.message,
|
|
1358
|
-
attributes
|
|
1359
|
-
prompt_key: promptCtx?.promptKey,
|
|
1360
|
-
prompt_version: promptCtx?.promptVersion,
|
|
1361
|
-
prompt_ab_test_key: promptCtx?.abTestKey,
|
|
1362
|
-
prompt_variant_index: promptCtx?.variantIndex
|
|
1274
|
+
attributes
|
|
1363
1275
|
}).catch(() => {
|
|
1364
1276
|
});
|
|
1365
1277
|
throw error;
|
|
@@ -1367,24 +1279,21 @@ function wrapAnthropic(client) {
|
|
|
1367
1279
|
};
|
|
1368
1280
|
return client;
|
|
1369
1281
|
}
|
|
1370
|
-
|
|
1282
|
+
|
|
1283
|
+
// src/trace/wrappers/google-ai.ts
|
|
1284
|
+
function wrapGoogleAI(model, sessionCtx) {
|
|
1371
1285
|
const originalGenerate = model.generateContent.bind(model);
|
|
1286
|
+
const ctx = sessionCtx;
|
|
1372
1287
|
model.generateContent = async function(...args) {
|
|
1373
|
-
|
|
1374
|
-
if (!ctx || !initialized2) {
|
|
1288
|
+
if (!isInitialized()) {
|
|
1375
1289
|
return originalGenerate(...args);
|
|
1376
1290
|
}
|
|
1377
|
-
|
|
1378
|
-
try {
|
|
1379
|
-
const { getPromptContext: getPromptContext2 } = await Promise.resolve().then(() => (init_prompts(), prompts_exports));
|
|
1380
|
-
promptCtx = getPromptContext2();
|
|
1381
|
-
} catch {
|
|
1382
|
-
}
|
|
1383
|
-
const traceCtx = traceContextStorage.getStore() || fallbackTraceContext;
|
|
1291
|
+
const traceCtx = getTraceContextStorage().getStore() || getFallbackTraceContext();
|
|
1384
1292
|
const traceId = traceCtx?.traceId || generateHexId(32);
|
|
1385
1293
|
const spanId = generateHexId(16);
|
|
1386
1294
|
const parentSpanId = traceCtx?.parentSpanId;
|
|
1387
1295
|
const startTime = Date.now();
|
|
1296
|
+
const captureContent2 = shouldCaptureContent();
|
|
1388
1297
|
try {
|
|
1389
1298
|
const response = await originalGenerate(...args);
|
|
1390
1299
|
const endTime = Date.now();
|
|
@@ -1392,7 +1301,7 @@ function wrapGoogleAI(model) {
|
|
|
1392
1301
|
const usage = result?.usageMetadata;
|
|
1393
1302
|
const modelName = model?.model || "gemini";
|
|
1394
1303
|
const attributes = {};
|
|
1395
|
-
if (
|
|
1304
|
+
if (captureContent2) {
|
|
1396
1305
|
attributes["gen_ai.request.model"] = modelName;
|
|
1397
1306
|
attributes["gen_ai.response.model"] = modelName;
|
|
1398
1307
|
const input = args[0];
|
|
@@ -1435,11 +1344,7 @@ function wrapGoogleAI(model) {
|
|
|
1435
1344
|
prompt_tokens: usage?.promptTokenCount,
|
|
1436
1345
|
completion_tokens: usage?.candidatesTokenCount,
|
|
1437
1346
|
total_tokens: usage?.totalTokenCount,
|
|
1438
|
-
attributes: Object.keys(attributes).length > 0 ? attributes : void 0
|
|
1439
|
-
prompt_key: promptCtx?.promptKey,
|
|
1440
|
-
prompt_version: promptCtx?.promptVersion,
|
|
1441
|
-
prompt_ab_test_key: promptCtx?.abTestKey,
|
|
1442
|
-
prompt_variant_index: promptCtx?.variantIndex
|
|
1347
|
+
attributes: Object.keys(attributes).length > 0 ? attributes : void 0
|
|
1443
1348
|
}).catch(() => {
|
|
1444
1349
|
});
|
|
1445
1350
|
return response;
|
|
@@ -1447,7 +1352,7 @@ function wrapGoogleAI(model) {
|
|
|
1447
1352
|
const endTime = Date.now();
|
|
1448
1353
|
const modelName = model?.model || "gemini";
|
|
1449
1354
|
const attributes = {};
|
|
1450
|
-
if (
|
|
1355
|
+
if (captureContent2) {
|
|
1451
1356
|
attributes["gen_ai.request.model"] = modelName;
|
|
1452
1357
|
attributes["error.message"] = error?.message;
|
|
1453
1358
|
const input = args[0];
|
|
@@ -1471,11 +1376,7 @@ function wrapGoogleAI(model) {
|
|
|
1471
1376
|
duration_ms: endTime - startTime,
|
|
1472
1377
|
status: "ERROR",
|
|
1473
1378
|
error_message: error?.message,
|
|
1474
|
-
attributes:
|
|
1475
|
-
prompt_key: promptCtx?.promptKey,
|
|
1476
|
-
prompt_version: promptCtx?.promptVersion,
|
|
1477
|
-
prompt_ab_test_key: promptCtx?.abTestKey,
|
|
1478
|
-
prompt_variant_index: promptCtx?.variantIndex
|
|
1379
|
+
attributes: captureContent2 ? attributes : void 0
|
|
1479
1380
|
}).catch(() => {
|
|
1480
1381
|
});
|
|
1481
1382
|
throw error;
|
|
@@ -1483,7 +1384,8 @@ function wrapGoogleAI(model) {
|
|
|
1483
1384
|
};
|
|
1484
1385
|
return model;
|
|
1485
1386
|
}
|
|
1486
|
-
|
|
1387
|
+
|
|
1388
|
+
// src/trace/wrappers/vercel-ai/utils.ts
|
|
1487
1389
|
function extractUsageFromResult(result, directUsage) {
|
|
1488
1390
|
let usage = directUsage ?? result?.usage;
|
|
1489
1391
|
const isValidNumber = (v) => v !== null && v !== void 0 && !Number.isNaN(v);
|
|
@@ -1511,38 +1413,25 @@ function extractUsageFromResult(result, directUsage) {
|
|
|
1511
1413
|
}
|
|
1512
1414
|
return { promptTokens, completionTokens, totalTokens, cost };
|
|
1513
1415
|
}
|
|
1514
|
-
|
|
1515
|
-
|
|
1516
|
-
|
|
1517
|
-
|
|
1518
|
-
generateText: createGenerateTextWrapper(aiModule),
|
|
1519
|
-
streamText: createStreamTextWrapper(aiModule),
|
|
1520
|
-
generateObject: aiModule.generateObject ? createGenerateObjectWrapper(aiModule) : void 0,
|
|
1521
|
-
streamObject: aiModule.streamObject ? createStreamObjectWrapper(aiModule) : void 0
|
|
1522
|
-
};
|
|
1523
|
-
}
|
|
1524
|
-
function createGenerateTextWrapper(aiModule) {
|
|
1416
|
+
|
|
1417
|
+
// src/trace/wrappers/vercel-ai/generate-text.ts
|
|
1418
|
+
function createGenerateTextWrapper(aiModule, sessionCtx, debug = false) {
|
|
1419
|
+
const ctx = sessionCtx;
|
|
1525
1420
|
return async (...args) => {
|
|
1526
|
-
|
|
1527
|
-
if (!ctx || !initialized2) {
|
|
1421
|
+
if (!isInitialized()) {
|
|
1528
1422
|
return aiModule.generateText(...args);
|
|
1529
1423
|
}
|
|
1530
|
-
|
|
1531
|
-
try {
|
|
1532
|
-
const { getPromptContext: getPromptContext2 } = await Promise.resolve().then(() => (init_prompts(), prompts_exports));
|
|
1533
|
-
promptCtx = getPromptContext2();
|
|
1534
|
-
} catch {
|
|
1535
|
-
}
|
|
1536
|
-
const traceCtx = traceContextStorage.getStore() || fallbackTraceContext;
|
|
1424
|
+
const traceCtx = getTraceContextStorage().getStore() || getFallbackTraceContext();
|
|
1537
1425
|
const traceId = traceCtx?.traceId || generateHexId(32);
|
|
1538
1426
|
const spanId = generateHexId(16);
|
|
1539
1427
|
const parentSpanId = traceCtx?.parentSpanId;
|
|
1540
1428
|
const params = args[0] || {};
|
|
1541
1429
|
const startTime = Date.now();
|
|
1430
|
+
const captureContent2 = shouldCaptureContent();
|
|
1542
1431
|
try {
|
|
1543
1432
|
const result = await aiModule.generateText(...args);
|
|
1544
1433
|
const endTime = Date.now();
|
|
1545
|
-
if (
|
|
1434
|
+
if (debug || isDebugMode()) {
|
|
1546
1435
|
console.log(
|
|
1547
1436
|
"\n\u{1F50D} [Fallom Debug] generateText result keys:",
|
|
1548
1437
|
Object.keys(result || {})
|
|
@@ -1551,14 +1440,6 @@ function createGenerateTextWrapper(aiModule) {
|
|
|
1551
1440
|
"\u{1F50D} [Fallom Debug] result.usage:",
|
|
1552
1441
|
JSON.stringify(result?.usage, null, 2)
|
|
1553
1442
|
);
|
|
1554
|
-
console.log(
|
|
1555
|
-
"\u{1F50D} [Fallom Debug] result.response keys:",
|
|
1556
|
-
Object.keys(result?.response || {})
|
|
1557
|
-
);
|
|
1558
|
-
console.log(
|
|
1559
|
-
"\u{1F50D} [Fallom Debug] result.response.usage:",
|
|
1560
|
-
JSON.stringify(result?.response?.usage, null, 2)
|
|
1561
|
-
);
|
|
1562
1443
|
console.log(
|
|
1563
1444
|
"\u{1F50D} [Fallom Debug] result.experimental_providerMetadata:",
|
|
1564
1445
|
JSON.stringify(result?.experimental_providerMetadata, null, 2)
|
|
@@ -1566,7 +1447,7 @@ function createGenerateTextWrapper(aiModule) {
|
|
|
1566
1447
|
}
|
|
1567
1448
|
const modelId = result?.response?.modelId || params?.model?.modelId || String(params?.model || "unknown");
|
|
1568
1449
|
const attributes = {};
|
|
1569
|
-
if (
|
|
1450
|
+
if (captureContent2) {
|
|
1570
1451
|
attributes["gen_ai.request.model"] = modelId;
|
|
1571
1452
|
attributes["gen_ai.response.model"] = modelId;
|
|
1572
1453
|
if (params?.prompt) {
|
|
@@ -1616,11 +1497,7 @@ function createGenerateTextWrapper(aiModule) {
|
|
|
1616
1497
|
prompt_tokens: usage.promptTokens,
|
|
1617
1498
|
completion_tokens: usage.completionTokens,
|
|
1618
1499
|
total_tokens: usage.totalTokens,
|
|
1619
|
-
attributes:
|
|
1620
|
-
prompt_key: promptCtx?.promptKey,
|
|
1621
|
-
prompt_version: promptCtx?.promptVersion,
|
|
1622
|
-
prompt_ab_test_key: promptCtx?.abTestKey,
|
|
1623
|
-
prompt_variant_index: promptCtx?.variantIndex
|
|
1500
|
+
attributes: captureContent2 ? attributes : void 0
|
|
1624
1501
|
}).catch(() => {
|
|
1625
1502
|
});
|
|
1626
1503
|
return result;
|
|
@@ -1641,50 +1518,42 @@ function createGenerateTextWrapper(aiModule) {
|
|
|
1641
1518
|
end_time: new Date(endTime).toISOString(),
|
|
1642
1519
|
duration_ms: endTime - startTime,
|
|
1643
1520
|
status: "ERROR",
|
|
1644
|
-
error_message: error?.message
|
|
1645
|
-
prompt_key: promptCtx?.promptKey,
|
|
1646
|
-
prompt_version: promptCtx?.promptVersion,
|
|
1647
|
-
prompt_ab_test_key: promptCtx?.abTestKey,
|
|
1648
|
-
prompt_variant_index: promptCtx?.variantIndex
|
|
1521
|
+
error_message: error?.message
|
|
1649
1522
|
}).catch(() => {
|
|
1650
1523
|
});
|
|
1651
1524
|
throw error;
|
|
1652
1525
|
}
|
|
1653
1526
|
};
|
|
1654
1527
|
}
|
|
1655
|
-
|
|
1528
|
+
|
|
1529
|
+
// src/trace/wrappers/vercel-ai/stream-text.ts
|
|
1530
|
+
function log2(...args) {
|
|
1531
|
+
if (isDebugMode()) console.log("[Fallom]", ...args);
|
|
1532
|
+
}
|
|
1533
|
+
function createStreamTextWrapper(aiModule, sessionCtx, debug = false) {
|
|
1534
|
+
const ctx = sessionCtx;
|
|
1656
1535
|
return async (...args) => {
|
|
1657
|
-
const ctx = sessionStorage.getStore() || fallbackSession;
|
|
1658
1536
|
const params = args[0] || {};
|
|
1659
1537
|
const startTime = Date.now();
|
|
1538
|
+
const captureContent2 = shouldCaptureContent();
|
|
1660
1539
|
const result = await aiModule.streamText(...args);
|
|
1661
|
-
if (!
|
|
1540
|
+
if (!isInitialized()) {
|
|
1662
1541
|
return result;
|
|
1663
1542
|
}
|
|
1664
|
-
const traceCtx =
|
|
1543
|
+
const traceCtx = getTraceContextStorage().getStore() || getFallbackTraceContext();
|
|
1665
1544
|
const traceId = traceCtx?.traceId || generateHexId(32);
|
|
1666
1545
|
const spanId = generateHexId(16);
|
|
1667
1546
|
const parentSpanId = traceCtx?.parentSpanId;
|
|
1668
1547
|
let firstTokenTime = null;
|
|
1669
1548
|
const modelId = params?.model?.modelId || String(params?.model || "unknown");
|
|
1670
|
-
let promptCtx = null;
|
|
1671
|
-
try {
|
|
1672
|
-
const { getPromptContext: getPromptContext2 } = await Promise.resolve().then(() => (init_prompts(), prompts_exports));
|
|
1673
|
-
promptCtx = getPromptContext2();
|
|
1674
|
-
} catch {
|
|
1675
|
-
}
|
|
1676
1549
|
if (result?.usage) {
|
|
1677
1550
|
result.usage.then(async (rawUsage) => {
|
|
1678
1551
|
const endTime = Date.now();
|
|
1679
|
-
if (
|
|
1552
|
+
if (debug || isDebugMode()) {
|
|
1680
1553
|
console.log(
|
|
1681
1554
|
"\n\u{1F50D} [Fallom Debug] streamText usage:",
|
|
1682
1555
|
JSON.stringify(rawUsage, null, 2)
|
|
1683
1556
|
);
|
|
1684
|
-
console.log(
|
|
1685
|
-
"\u{1F50D} [Fallom Debug] streamText result keys:",
|
|
1686
|
-
Object.keys(result || {})
|
|
1687
|
-
);
|
|
1688
1557
|
}
|
|
1689
1558
|
log2("\u{1F4CA} streamText usage:", JSON.stringify(rawUsage, null, 2));
|
|
1690
1559
|
let providerMetadata = result?.experimental_providerMetadata;
|
|
@@ -1700,7 +1569,7 @@ function createStreamTextWrapper(aiModule) {
|
|
|
1700
1569
|
rawUsage
|
|
1701
1570
|
);
|
|
1702
1571
|
const attributes = {};
|
|
1703
|
-
if (
|
|
1572
|
+
if (captureContent2) {
|
|
1704
1573
|
attributes["gen_ai.request.model"] = modelId;
|
|
1705
1574
|
if (params?.prompt) {
|
|
1706
1575
|
attributes["gen_ai.prompt.0.role"] = "user";
|
|
@@ -1734,11 +1603,7 @@ function createStreamTextWrapper(aiModule) {
|
|
|
1734
1603
|
completion_tokens: usage.completionTokens,
|
|
1735
1604
|
total_tokens: usage.totalTokens,
|
|
1736
1605
|
time_to_first_token_ms: firstTokenTime ? firstTokenTime - startTime : void 0,
|
|
1737
|
-
attributes:
|
|
1738
|
-
prompt_key: promptCtx?.promptKey,
|
|
1739
|
-
prompt_version: promptCtx?.promptVersion,
|
|
1740
|
-
prompt_ab_test_key: promptCtx?.abTestKey,
|
|
1741
|
-
prompt_variant_index: promptCtx?.variantIndex
|
|
1606
|
+
attributes: captureContent2 ? attributes : void 0
|
|
1742
1607
|
};
|
|
1743
1608
|
sendTrace(tracePayload).catch(() => {
|
|
1744
1609
|
});
|
|
@@ -1759,11 +1624,7 @@ function createStreamTextWrapper(aiModule) {
|
|
|
1759
1624
|
end_time: new Date(endTime).toISOString(),
|
|
1760
1625
|
duration_ms: endTime - startTime,
|
|
1761
1626
|
status: "ERROR",
|
|
1762
|
-
error_message: error?.message
|
|
1763
|
-
prompt_key: promptCtx?.promptKey,
|
|
1764
|
-
prompt_version: promptCtx?.promptVersion,
|
|
1765
|
-
prompt_ab_test_key: promptCtx?.abTestKey,
|
|
1766
|
-
prompt_variant_index: promptCtx?.variantIndex
|
|
1627
|
+
error_message: error?.message
|
|
1767
1628
|
}).catch(() => {
|
|
1768
1629
|
});
|
|
1769
1630
|
});
|
|
@@ -1791,28 +1652,25 @@ function createStreamTextWrapper(aiModule) {
|
|
|
1791
1652
|
return result;
|
|
1792
1653
|
};
|
|
1793
1654
|
}
|
|
1794
|
-
|
|
1655
|
+
|
|
1656
|
+
// src/trace/wrappers/vercel-ai/generate-object.ts
|
|
1657
|
+
function createGenerateObjectWrapper(aiModule, sessionCtx, debug = false) {
|
|
1658
|
+
const ctx = sessionCtx;
|
|
1795
1659
|
return async (...args) => {
|
|
1796
|
-
|
|
1797
|
-
if (!ctx || !initialized2) {
|
|
1660
|
+
if (!isInitialized()) {
|
|
1798
1661
|
return aiModule.generateObject(...args);
|
|
1799
1662
|
}
|
|
1800
|
-
|
|
1801
|
-
try {
|
|
1802
|
-
const { getPromptContext: getPromptContext2 } = await Promise.resolve().then(() => (init_prompts(), prompts_exports));
|
|
1803
|
-
promptCtx = getPromptContext2();
|
|
1804
|
-
} catch {
|
|
1805
|
-
}
|
|
1806
|
-
const traceCtx = traceContextStorage.getStore() || fallbackTraceContext;
|
|
1663
|
+
const traceCtx = getTraceContextStorage().getStore() || getFallbackTraceContext();
|
|
1807
1664
|
const traceId = traceCtx?.traceId || generateHexId(32);
|
|
1808
1665
|
const spanId = generateHexId(16);
|
|
1809
1666
|
const parentSpanId = traceCtx?.parentSpanId;
|
|
1810
1667
|
const params = args[0] || {};
|
|
1811
1668
|
const startTime = Date.now();
|
|
1669
|
+
const captureContent2 = shouldCaptureContent();
|
|
1812
1670
|
try {
|
|
1813
1671
|
const result = await aiModule.generateObject(...args);
|
|
1814
1672
|
const endTime = Date.now();
|
|
1815
|
-
if (
|
|
1673
|
+
if (debug || isDebugMode()) {
|
|
1816
1674
|
console.log(
|
|
1817
1675
|
"\n\u{1F50D} [Fallom Debug] generateObject result keys:",
|
|
1818
1676
|
Object.keys(result || {})
|
|
@@ -1821,18 +1679,10 @@ function createGenerateObjectWrapper(aiModule) {
|
|
|
1821
1679
|
"\u{1F50D} [Fallom Debug] result.usage:",
|
|
1822
1680
|
JSON.stringify(result?.usage, null, 2)
|
|
1823
1681
|
);
|
|
1824
|
-
console.log(
|
|
1825
|
-
"\u{1F50D} [Fallom Debug] result.response keys:",
|
|
1826
|
-
Object.keys(result?.response || {})
|
|
1827
|
-
);
|
|
1828
|
-
console.log(
|
|
1829
|
-
"\u{1F50D} [Fallom Debug] result.response.usage:",
|
|
1830
|
-
JSON.stringify(result?.response?.usage, null, 2)
|
|
1831
|
-
);
|
|
1832
1682
|
}
|
|
1833
1683
|
const modelId = result?.response?.modelId || params?.model?.modelId || String(params?.model || "unknown");
|
|
1834
1684
|
const attributes = {};
|
|
1835
|
-
if (
|
|
1685
|
+
if (captureContent2) {
|
|
1836
1686
|
attributes["gen_ai.request.model"] = modelId;
|
|
1837
1687
|
attributes["gen_ai.response.model"] = modelId;
|
|
1838
1688
|
if (result?.object) {
|
|
@@ -1871,11 +1721,7 @@ function createGenerateObjectWrapper(aiModule) {
|
|
|
1871
1721
|
prompt_tokens: usage.promptTokens,
|
|
1872
1722
|
completion_tokens: usage.completionTokens,
|
|
1873
1723
|
total_tokens: usage.totalTokens,
|
|
1874
|
-
attributes:
|
|
1875
|
-
prompt_key: promptCtx?.promptKey,
|
|
1876
|
-
prompt_version: promptCtx?.promptVersion,
|
|
1877
|
-
prompt_ab_test_key: promptCtx?.abTestKey,
|
|
1878
|
-
prompt_variant_index: promptCtx?.variantIndex
|
|
1724
|
+
attributes: captureContent2 ? attributes : void 0
|
|
1879
1725
|
}).catch(() => {
|
|
1880
1726
|
});
|
|
1881
1727
|
return result;
|
|
@@ -1896,53 +1742,45 @@ function createGenerateObjectWrapper(aiModule) {
|
|
|
1896
1742
|
end_time: new Date(endTime).toISOString(),
|
|
1897
1743
|
duration_ms: endTime - startTime,
|
|
1898
1744
|
status: "ERROR",
|
|
1899
|
-
error_message: error?.message
|
|
1900
|
-
prompt_key: promptCtx?.promptKey,
|
|
1901
|
-
prompt_version: promptCtx?.promptVersion,
|
|
1902
|
-
prompt_ab_test_key: promptCtx?.abTestKey,
|
|
1903
|
-
prompt_variant_index: promptCtx?.variantIndex
|
|
1745
|
+
error_message: error?.message
|
|
1904
1746
|
}).catch(() => {
|
|
1905
1747
|
});
|
|
1906
1748
|
throw error;
|
|
1907
1749
|
}
|
|
1908
1750
|
};
|
|
1909
1751
|
}
|
|
1910
|
-
|
|
1752
|
+
|
|
1753
|
+
// src/trace/wrappers/vercel-ai/stream-object.ts
|
|
1754
|
+
function log3(...args) {
|
|
1755
|
+
if (isDebugMode()) console.log("[Fallom]", ...args);
|
|
1756
|
+
}
|
|
1757
|
+
function createStreamObjectWrapper(aiModule, sessionCtx, debug = false) {
|
|
1758
|
+
const ctx = sessionCtx;
|
|
1911
1759
|
return async (...args) => {
|
|
1912
|
-
const ctx = sessionStorage.getStore() || fallbackSession;
|
|
1913
1760
|
const params = args[0] || {};
|
|
1914
1761
|
const startTime = Date.now();
|
|
1762
|
+
const captureContent2 = shouldCaptureContent();
|
|
1915
1763
|
const result = await aiModule.streamObject(...args);
|
|
1916
|
-
|
|
1917
|
-
if (!
|
|
1764
|
+
log3("\u{1F50D} streamObject result keys:", Object.keys(result || {}));
|
|
1765
|
+
if (!isInitialized()) {
|
|
1918
1766
|
return result;
|
|
1919
1767
|
}
|
|
1920
|
-
const traceCtx =
|
|
1768
|
+
const traceCtx = getTraceContextStorage().getStore() || getFallbackTraceContext();
|
|
1921
1769
|
const traceId = traceCtx?.traceId || generateHexId(32);
|
|
1922
1770
|
const spanId = generateHexId(16);
|
|
1923
1771
|
const parentSpanId = traceCtx?.parentSpanId;
|
|
1924
1772
|
let firstTokenTime = null;
|
|
1925
1773
|
const modelId = params?.model?.modelId || String(params?.model || "unknown");
|
|
1926
|
-
let promptCtx = null;
|
|
1927
|
-
try {
|
|
1928
|
-
const { getPromptContext: getPromptContext2 } = await Promise.resolve().then(() => (init_prompts(), prompts_exports));
|
|
1929
|
-
promptCtx = getPromptContext2();
|
|
1930
|
-
} catch {
|
|
1931
|
-
}
|
|
1932
1774
|
if (result?.usage) {
|
|
1933
1775
|
result.usage.then(async (rawUsage) => {
|
|
1934
1776
|
const endTime = Date.now();
|
|
1935
|
-
if (
|
|
1777
|
+
if (debug || isDebugMode()) {
|
|
1936
1778
|
console.log(
|
|
1937
1779
|
"\n\u{1F50D} [Fallom Debug] streamObject usage:",
|
|
1938
1780
|
JSON.stringify(rawUsage, null, 2)
|
|
1939
1781
|
);
|
|
1940
|
-
console.log(
|
|
1941
|
-
"\u{1F50D} [Fallom Debug] streamObject result keys:",
|
|
1942
|
-
Object.keys(result || {})
|
|
1943
|
-
);
|
|
1944
1782
|
}
|
|
1945
|
-
|
|
1783
|
+
log3("\u{1F4CA} streamObject usage:", JSON.stringify(rawUsage, null, 2));
|
|
1946
1784
|
let providerMetadata = result?.experimental_providerMetadata;
|
|
1947
1785
|
if (providerMetadata && typeof providerMetadata.then === "function") {
|
|
1948
1786
|
try {
|
|
@@ -1956,7 +1794,7 @@ function createStreamObjectWrapper(aiModule) {
|
|
|
1956
1794
|
rawUsage
|
|
1957
1795
|
);
|
|
1958
1796
|
const attributes = {};
|
|
1959
|
-
if (
|
|
1797
|
+
if (captureContent2) {
|
|
1960
1798
|
attributes["gen_ai.request.model"] = modelId;
|
|
1961
1799
|
}
|
|
1962
1800
|
if (firstTokenTime) {
|
|
@@ -1985,11 +1823,7 @@ function createStreamObjectWrapper(aiModule) {
|
|
|
1985
1823
|
prompt_tokens: usage.promptTokens,
|
|
1986
1824
|
completion_tokens: usage.completionTokens,
|
|
1987
1825
|
total_tokens: usage.totalTokens,
|
|
1988
|
-
attributes:
|
|
1989
|
-
prompt_key: promptCtx?.promptKey,
|
|
1990
|
-
prompt_version: promptCtx?.promptVersion,
|
|
1991
|
-
prompt_ab_test_key: promptCtx?.abTestKey,
|
|
1992
|
-
prompt_variant_index: promptCtx?.variantIndex
|
|
1826
|
+
attributes: captureContent2 ? attributes : void 0
|
|
1993
1827
|
}).catch(() => {
|
|
1994
1828
|
});
|
|
1995
1829
|
}).catch((error) => {
|
|
@@ -2008,11 +1842,7 @@ function createStreamObjectWrapper(aiModule) {
|
|
|
2008
1842
|
end_time: new Date(endTime).toISOString(),
|
|
2009
1843
|
duration_ms: endTime - startTime,
|
|
2010
1844
|
status: "ERROR",
|
|
2011
|
-
error_message: error?.message
|
|
2012
|
-
prompt_key: promptCtx?.promptKey,
|
|
2013
|
-
prompt_version: promptCtx?.promptVersion,
|
|
2014
|
-
prompt_ab_test_key: promptCtx?.abTestKey,
|
|
2015
|
-
prompt_variant_index: promptCtx?.variantIndex
|
|
1845
|
+
error_message: error?.message
|
|
2016
1846
|
}).catch(() => {
|
|
2017
1847
|
});
|
|
2018
1848
|
});
|
|
@@ -2023,7 +1853,7 @@ function createStreamObjectWrapper(aiModule) {
|
|
|
2023
1853
|
for await (const chunk of originalStream) {
|
|
2024
1854
|
if (!firstTokenTime) {
|
|
2025
1855
|
firstTokenTime = Date.now();
|
|
2026
|
-
|
|
1856
|
+
log3("\u23F1\uFE0F Time to first token:", firstTokenTime - startTime, "ms");
|
|
2027
1857
|
}
|
|
2028
1858
|
yield chunk;
|
|
2029
1859
|
}
|
|
@@ -2040,20 +1870,27 @@ function createStreamObjectWrapper(aiModule) {
|
|
|
2040
1870
|
return result;
|
|
2041
1871
|
};
|
|
2042
1872
|
}
|
|
2043
|
-
|
|
1873
|
+
|
|
1874
|
+
// src/trace/wrappers/vercel-ai/index.ts
|
|
1875
|
+
function wrapAISDK(ai, sessionCtx, options) {
|
|
1876
|
+
const debug = options?.debug ?? false;
|
|
1877
|
+
return {
|
|
1878
|
+
generateText: createGenerateTextWrapper(ai, sessionCtx, debug),
|
|
1879
|
+
streamText: createStreamTextWrapper(ai, sessionCtx, debug),
|
|
1880
|
+
generateObject: ai.generateObject ? createGenerateObjectWrapper(ai, sessionCtx, debug) : void 0,
|
|
1881
|
+
streamObject: ai.streamObject ? createStreamObjectWrapper(ai, sessionCtx, debug) : void 0
|
|
1882
|
+
};
|
|
1883
|
+
}
|
|
1884
|
+
|
|
1885
|
+
// src/trace/wrappers/mastra.ts
|
|
1886
|
+
function wrapMastraAgent(agent, sessionCtx) {
|
|
2044
1887
|
const originalGenerate = agent.generate.bind(agent);
|
|
2045
1888
|
const agentName = agent.name || "MastraAgent";
|
|
1889
|
+
const ctx = sessionCtx;
|
|
2046
1890
|
agent.generate = async function(...args) {
|
|
2047
|
-
|
|
2048
|
-
if (!ctx || !initialized2) {
|
|
1891
|
+
if (!isInitialized()) {
|
|
2049
1892
|
return originalGenerate(...args);
|
|
2050
1893
|
}
|
|
2051
|
-
let promptCtx = null;
|
|
2052
|
-
try {
|
|
2053
|
-
const { getPromptContext: getPromptContext2 } = await Promise.resolve().then(() => (init_prompts(), prompts_exports));
|
|
2054
|
-
promptCtx = getPromptContext2();
|
|
2055
|
-
} catch {
|
|
2056
|
-
}
|
|
2057
1894
|
const traceId = generateHexId(32);
|
|
2058
1895
|
const spanId = generateHexId(16);
|
|
2059
1896
|
const startTime = Date.now();
|
|
@@ -2125,11 +1962,7 @@ function wrapMastraAgent(agent) {
|
|
|
2125
1962
|
prompt_tokens: result?.usage?.promptTokens,
|
|
2126
1963
|
completion_tokens: result?.usage?.completionTokens,
|
|
2127
1964
|
total_tokens: result?.usage?.totalTokens,
|
|
2128
|
-
attributes
|
|
2129
|
-
prompt_key: promptCtx?.promptKey,
|
|
2130
|
-
prompt_version: promptCtx?.promptVersion,
|
|
2131
|
-
prompt_ab_test_key: promptCtx?.abTestKey,
|
|
2132
|
-
prompt_variant_index: promptCtx?.variantIndex
|
|
1965
|
+
attributes
|
|
2133
1966
|
};
|
|
2134
1967
|
sendTrace(traceData).catch(() => {
|
|
2135
1968
|
});
|
|
@@ -2148,11 +1981,7 @@ function wrapMastraAgent(agent) {
|
|
|
2148
1981
|
end_time: new Date(endTime).toISOString(),
|
|
2149
1982
|
duration_ms: endTime - startTime,
|
|
2150
1983
|
status: "ERROR",
|
|
2151
|
-
error_message: error instanceof Error ? error.message : String(error)
|
|
2152
|
-
prompt_key: promptCtx?.promptKey,
|
|
2153
|
-
prompt_version: promptCtx?.promptVersion,
|
|
2154
|
-
prompt_ab_test_key: promptCtx?.abTestKey,
|
|
2155
|
-
prompt_variant_index: promptCtx?.variantIndex
|
|
1984
|
+
error_message: error instanceof Error ? error.message : String(error)
|
|
2156
1985
|
};
|
|
2157
1986
|
sendTrace(traceData).catch(() => {
|
|
2158
1987
|
});
|
|
@@ -2162,38 +1991,216 @@ function wrapMastraAgent(agent) {
|
|
|
2162
1991
|
return agent;
|
|
2163
1992
|
}
|
|
2164
1993
|
|
|
2165
|
-
// src/
|
|
2166
|
-
var
|
|
2167
|
-
|
|
1994
|
+
// src/trace/session.ts
|
|
1995
|
+
var FallomSession = class {
|
|
1996
|
+
constructor(options) {
|
|
1997
|
+
this.ctx = {
|
|
1998
|
+
configKey: options.configKey,
|
|
1999
|
+
sessionId: options.sessionId,
|
|
2000
|
+
customerId: options.customerId
|
|
2001
|
+
};
|
|
2002
|
+
}
|
|
2003
|
+
/** Get the session context. */
|
|
2004
|
+
getContext() {
|
|
2005
|
+
return { ...this.ctx };
|
|
2006
|
+
}
|
|
2007
|
+
/**
|
|
2008
|
+
* Get model assignment for this session (A/B testing).
|
|
2009
|
+
*/
|
|
2010
|
+
async getModel(configKeyOrOptions, options) {
|
|
2011
|
+
let configKey;
|
|
2012
|
+
let opts;
|
|
2013
|
+
if (typeof configKeyOrOptions === "string") {
|
|
2014
|
+
configKey = configKeyOrOptions;
|
|
2015
|
+
opts = options || {};
|
|
2016
|
+
} else {
|
|
2017
|
+
configKey = this.ctx.configKey;
|
|
2018
|
+
opts = configKeyOrOptions || {};
|
|
2019
|
+
}
|
|
2020
|
+
const { get: get3 } = await Promise.resolve().then(() => (init_models(), models_exports));
|
|
2021
|
+
return get3(configKey, this.ctx.sessionId, opts);
|
|
2022
|
+
}
|
|
2023
|
+
/**
|
|
2024
|
+
* Wrap a Vercel AI SDK model to trace all calls.
|
|
2025
|
+
*/
|
|
2026
|
+
traceModel(model) {
|
|
2027
|
+
const ctx = this.ctx;
|
|
2028
|
+
const tracedModel = Object.create(model);
|
|
2029
|
+
if (model.doGenerate) {
|
|
2030
|
+
const originalDoGenerate = model.doGenerate.bind(model);
|
|
2031
|
+
tracedModel.doGenerate = async function(...args) {
|
|
2032
|
+
if (!isInitialized()) return originalDoGenerate(...args);
|
|
2033
|
+
const traceCtx = getTraceContextStorage().getStore() || getFallbackTraceContext();
|
|
2034
|
+
const traceId = traceCtx?.traceId || generateHexId(32);
|
|
2035
|
+
const spanId = generateHexId(16);
|
|
2036
|
+
const startTime = Date.now();
|
|
2037
|
+
try {
|
|
2038
|
+
const result = await originalDoGenerate(...args);
|
|
2039
|
+
const endTime = Date.now();
|
|
2040
|
+
const modelId = model.modelId || "unknown";
|
|
2041
|
+
const usage = result?.usage || result?.rawResponse?.usage;
|
|
2042
|
+
sendTrace({
|
|
2043
|
+
config_key: ctx.configKey,
|
|
2044
|
+
session_id: ctx.sessionId,
|
|
2045
|
+
customer_id: ctx.customerId,
|
|
2046
|
+
trace_id: traceId,
|
|
2047
|
+
span_id: spanId,
|
|
2048
|
+
parent_span_id: traceCtx?.parentSpanId,
|
|
2049
|
+
name: "generateText",
|
|
2050
|
+
kind: "llm",
|
|
2051
|
+
model: modelId,
|
|
2052
|
+
start_time: new Date(startTime).toISOString(),
|
|
2053
|
+
end_time: new Date(endTime).toISOString(),
|
|
2054
|
+
duration_ms: endTime - startTime,
|
|
2055
|
+
status: "OK",
|
|
2056
|
+
prompt_tokens: usage?.promptTokens,
|
|
2057
|
+
completion_tokens: usage?.completionTokens,
|
|
2058
|
+
total_tokens: usage?.totalTokens,
|
|
2059
|
+
attributes: shouldCaptureContent() && usage ? { "fallom.raw.usage": JSON.stringify(usage) } : void 0
|
|
2060
|
+
}).catch(() => {
|
|
2061
|
+
});
|
|
2062
|
+
return result;
|
|
2063
|
+
} catch (error) {
|
|
2064
|
+
const endTime = Date.now();
|
|
2065
|
+
sendTrace({
|
|
2066
|
+
config_key: ctx.configKey,
|
|
2067
|
+
session_id: ctx.sessionId,
|
|
2068
|
+
customer_id: ctx.customerId,
|
|
2069
|
+
trace_id: traceId,
|
|
2070
|
+
span_id: spanId,
|
|
2071
|
+
parent_span_id: traceCtx?.parentSpanId,
|
|
2072
|
+
name: "generateText",
|
|
2073
|
+
kind: "llm",
|
|
2074
|
+
model: model.modelId || "unknown",
|
|
2075
|
+
start_time: new Date(startTime).toISOString(),
|
|
2076
|
+
end_time: new Date(endTime).toISOString(),
|
|
2077
|
+
duration_ms: endTime - startTime,
|
|
2078
|
+
status: "ERROR",
|
|
2079
|
+
error_message: error instanceof Error ? error.message : String(error)
|
|
2080
|
+
}).catch(() => {
|
|
2081
|
+
});
|
|
2082
|
+
throw error;
|
|
2083
|
+
}
|
|
2084
|
+
};
|
|
2085
|
+
}
|
|
2086
|
+
if (model.doStream) {
|
|
2087
|
+
const originalDoStream = model.doStream.bind(model);
|
|
2088
|
+
tracedModel.doStream = async function(...args) {
|
|
2089
|
+
if (!isInitialized()) return originalDoStream(...args);
|
|
2090
|
+
const traceCtx = getTraceContextStorage().getStore() || getFallbackTraceContext();
|
|
2091
|
+
const traceId = traceCtx?.traceId || generateHexId(32);
|
|
2092
|
+
const spanId = generateHexId(16);
|
|
2093
|
+
const startTime = Date.now();
|
|
2094
|
+
const modelId = model.modelId || "unknown";
|
|
2095
|
+
try {
|
|
2096
|
+
const result = await originalDoStream(...args);
|
|
2097
|
+
sendTrace({
|
|
2098
|
+
config_key: ctx.configKey,
|
|
2099
|
+
session_id: ctx.sessionId,
|
|
2100
|
+
customer_id: ctx.customerId,
|
|
2101
|
+
trace_id: traceId,
|
|
2102
|
+
span_id: spanId,
|
|
2103
|
+
parent_span_id: traceCtx?.parentSpanId,
|
|
2104
|
+
name: "streamText",
|
|
2105
|
+
kind: "llm",
|
|
2106
|
+
model: modelId,
|
|
2107
|
+
start_time: new Date(startTime).toISOString(),
|
|
2108
|
+
end_time: new Date(Date.now()).toISOString(),
|
|
2109
|
+
duration_ms: Date.now() - startTime,
|
|
2110
|
+
status: "OK",
|
|
2111
|
+
is_streaming: true
|
|
2112
|
+
}).catch(() => {
|
|
2113
|
+
});
|
|
2114
|
+
return result;
|
|
2115
|
+
} catch (error) {
|
|
2116
|
+
sendTrace({
|
|
2117
|
+
config_key: ctx.configKey,
|
|
2118
|
+
session_id: ctx.sessionId,
|
|
2119
|
+
customer_id: ctx.customerId,
|
|
2120
|
+
trace_id: traceId,
|
|
2121
|
+
span_id: spanId,
|
|
2122
|
+
parent_span_id: traceCtx?.parentSpanId,
|
|
2123
|
+
name: "streamText",
|
|
2124
|
+
kind: "llm",
|
|
2125
|
+
model: modelId,
|
|
2126
|
+
start_time: new Date(startTime).toISOString(),
|
|
2127
|
+
end_time: new Date(Date.now()).toISOString(),
|
|
2128
|
+
duration_ms: Date.now() - startTime,
|
|
2129
|
+
status: "ERROR",
|
|
2130
|
+
error_message: error instanceof Error ? error.message : String(error),
|
|
2131
|
+
is_streaming: true
|
|
2132
|
+
}).catch(() => {
|
|
2133
|
+
});
|
|
2134
|
+
throw error;
|
|
2135
|
+
}
|
|
2136
|
+
};
|
|
2137
|
+
}
|
|
2138
|
+
return tracedModel;
|
|
2139
|
+
}
|
|
2140
|
+
/** Wrap OpenAI client. Delegates to shared wrapper. */
|
|
2141
|
+
wrapOpenAI(client) {
|
|
2142
|
+
return wrapOpenAI(client, this.ctx);
|
|
2143
|
+
}
|
|
2144
|
+
/** Wrap Anthropic client. Delegates to shared wrapper. */
|
|
2145
|
+
wrapAnthropic(client) {
|
|
2146
|
+
return wrapAnthropic(client, this.ctx);
|
|
2147
|
+
}
|
|
2148
|
+
/** Wrap Google AI model. Delegates to shared wrapper. */
|
|
2149
|
+
wrapGoogleAI(model) {
|
|
2150
|
+
return wrapGoogleAI(model, this.ctx);
|
|
2151
|
+
}
|
|
2152
|
+
/** Wrap Vercel AI SDK. Delegates to shared wrapper. */
|
|
2153
|
+
wrapAISDK(ai, options) {
|
|
2154
|
+
return wrapAISDK(ai, this.ctx, options);
|
|
2155
|
+
}
|
|
2156
|
+
/** Wrap Mastra agent. Delegates to shared wrapper. */
|
|
2157
|
+
wrapMastraAgent(agent) {
|
|
2158
|
+
return wrapMastraAgent(agent, this.ctx);
|
|
2159
|
+
}
|
|
2160
|
+
};
|
|
2161
|
+
function session(options) {
|
|
2162
|
+
return new FallomSession(options);
|
|
2163
|
+
}
|
|
2164
|
+
|
|
2165
|
+
// src/index.ts
|
|
2166
|
+
init_models();
|
|
2167
|
+
|
|
2168
|
+
// src/prompts.ts
|
|
2169
|
+
var prompts_exports = {};
|
|
2170
|
+
__export(prompts_exports, {
|
|
2171
|
+
clearPromptContext: () => clearPromptContext,
|
|
2168
2172
|
get: () => get2,
|
|
2173
|
+
getAB: () => getAB,
|
|
2174
|
+
getPromptContext: () => getPromptContext,
|
|
2169
2175
|
init: () => init3
|
|
2170
2176
|
});
|
|
2171
2177
|
var import_crypto2 = require("crypto");
|
|
2172
2178
|
var apiKey3 = null;
|
|
2173
|
-
var baseUrl3 = "https://
|
|
2179
|
+
var baseUrl3 = "https://prompts.fallom.com";
|
|
2174
2180
|
var initialized3 = false;
|
|
2175
2181
|
var syncInterval2 = null;
|
|
2176
2182
|
var debugMode3 = false;
|
|
2177
|
-
var
|
|
2183
|
+
var promptCache = /* @__PURE__ */ new Map();
|
|
2184
|
+
var promptABCache = /* @__PURE__ */ new Map();
|
|
2185
|
+
var promptContext = null;
|
|
2178
2186
|
var SYNC_TIMEOUT2 = 2e3;
|
|
2179
|
-
|
|
2180
|
-
function log3(msg) {
|
|
2187
|
+
function log5(msg) {
|
|
2181
2188
|
if (debugMode3) {
|
|
2182
|
-
console.log(`[Fallom] ${msg}`);
|
|
2189
|
+
console.log(`[Fallom Prompts] ${msg}`);
|
|
2183
2190
|
}
|
|
2184
2191
|
}
|
|
2185
2192
|
function init3(options = {}) {
|
|
2186
2193
|
apiKey3 = options.apiKey || process.env.FALLOM_API_KEY || null;
|
|
2187
|
-
baseUrl3 = options.baseUrl || process.env.
|
|
2194
|
+
baseUrl3 = options.baseUrl || process.env.FALLOM_PROMPTS_URL || process.env.FALLOM_BASE_URL || "https://prompts.fallom.com";
|
|
2188
2195
|
initialized3 = true;
|
|
2189
2196
|
if (!apiKey3) {
|
|
2190
2197
|
return;
|
|
2191
2198
|
}
|
|
2192
|
-
|
|
2199
|
+
fetchAll().catch(() => {
|
|
2193
2200
|
});
|
|
2194
2201
|
if (!syncInterval2) {
|
|
2195
2202
|
syncInterval2 = setInterval(() => {
|
|
2196
|
-
|
|
2203
|
+
fetchAll().catch(() => {
|
|
2197
2204
|
});
|
|
2198
2205
|
}, 3e4);
|
|
2199
2206
|
syncInterval2.unref();
|
|
@@ -2207,231 +2214,221 @@ function ensureInit2() {
|
|
|
2207
2214
|
}
|
|
2208
2215
|
}
|
|
2209
2216
|
}
|
|
2210
|
-
async function
|
|
2211
|
-
|
|
2212
|
-
|
|
2213
|
-
|
|
2217
|
+
async function fetchAll() {
|
|
2218
|
+
await Promise.all([fetchPrompts(), fetchPromptABTests()]);
|
|
2219
|
+
}
|
|
2220
|
+
async function fetchPrompts(timeout = SYNC_TIMEOUT2) {
|
|
2221
|
+
if (!apiKey3) return;
|
|
2222
|
+
try {
|
|
2223
|
+
const controller = new AbortController();
|
|
2224
|
+
const timeoutId = setTimeout(() => controller.abort(), timeout);
|
|
2225
|
+
const resp = await fetch(`${baseUrl3}/prompts`, {
|
|
2226
|
+
headers: { Authorization: `Bearer ${apiKey3}` },
|
|
2227
|
+
signal: controller.signal
|
|
2228
|
+
});
|
|
2229
|
+
clearTimeout(timeoutId);
|
|
2230
|
+
if (resp.ok) {
|
|
2231
|
+
const data = await resp.json();
|
|
2232
|
+
for (const p of data.prompts || []) {
|
|
2233
|
+
if (!promptCache.has(p.key)) {
|
|
2234
|
+
promptCache.set(p.key, { versions: /* @__PURE__ */ new Map(), current: null });
|
|
2235
|
+
}
|
|
2236
|
+
const cached = promptCache.get(p.key);
|
|
2237
|
+
cached.versions.set(p.version, {
|
|
2238
|
+
systemPrompt: p.system_prompt,
|
|
2239
|
+
userTemplate: p.user_template
|
|
2240
|
+
});
|
|
2241
|
+
cached.current = p.version;
|
|
2242
|
+
}
|
|
2243
|
+
}
|
|
2244
|
+
} catch {
|
|
2214
2245
|
}
|
|
2246
|
+
}
|
|
2247
|
+
async function fetchPromptABTests(timeout = SYNC_TIMEOUT2) {
|
|
2248
|
+
if (!apiKey3) return;
|
|
2215
2249
|
try {
|
|
2216
|
-
log3(`Fetching configs from ${baseUrl3}/configs`);
|
|
2217
2250
|
const controller = new AbortController();
|
|
2218
2251
|
const timeoutId = setTimeout(() => controller.abort(), timeout);
|
|
2219
|
-
const resp = await fetch(`${baseUrl3}/
|
|
2252
|
+
const resp = await fetch(`${baseUrl3}/prompt-ab-tests`, {
|
|
2220
2253
|
headers: { Authorization: `Bearer ${apiKey3}` },
|
|
2221
2254
|
signal: controller.signal
|
|
2222
2255
|
});
|
|
2223
2256
|
clearTimeout(timeoutId);
|
|
2224
|
-
log3(`Response status: ${resp.status}`);
|
|
2225
2257
|
if (resp.ok) {
|
|
2226
2258
|
const data = await resp.json();
|
|
2227
|
-
const
|
|
2228
|
-
|
|
2229
|
-
|
|
2230
|
-
const key = c.key;
|
|
2231
|
-
const version = c.version || 1;
|
|
2232
|
-
log3(`Config '${key}' v${version}: ${JSON.stringify(c.variants)}`);
|
|
2233
|
-
if (!configCache.has(key)) {
|
|
2234
|
-
configCache.set(key, { versions: /* @__PURE__ */ new Map(), latest: null });
|
|
2259
|
+
for (const t of data.prompt_ab_tests || []) {
|
|
2260
|
+
if (!promptABCache.has(t.key)) {
|
|
2261
|
+
promptABCache.set(t.key, { versions: /* @__PURE__ */ new Map(), current: null });
|
|
2235
2262
|
}
|
|
2236
|
-
const cached =
|
|
2237
|
-
cached.versions.set(version,
|
|
2238
|
-
cached.
|
|
2263
|
+
const cached = promptABCache.get(t.key);
|
|
2264
|
+
cached.versions.set(t.version, { variants: t.variants });
|
|
2265
|
+
cached.current = t.version;
|
|
2239
2266
|
}
|
|
2240
|
-
} else {
|
|
2241
|
-
log3(`Fetch failed: ${resp.statusText}`);
|
|
2242
2267
|
}
|
|
2243
|
-
} catch
|
|
2244
|
-
log3(`Fetch exception: ${e}`);
|
|
2268
|
+
} catch {
|
|
2245
2269
|
}
|
|
2246
2270
|
}
|
|
2247
|
-
|
|
2248
|
-
if (!
|
|
2249
|
-
|
|
2250
|
-
const
|
|
2251
|
-
|
|
2252
|
-
|
|
2253
|
-
|
|
2254
|
-
|
|
2255
|
-
|
|
2256
|
-
|
|
2257
|
-
|
|
2271
|
+
function replaceVariables(template, variables) {
|
|
2272
|
+
if (!variables) return template;
|
|
2273
|
+
return template.replace(/\{\{(\s*\w+\s*)\}\}/g, (match, varName) => {
|
|
2274
|
+
const key = varName.trim();
|
|
2275
|
+
return key in variables ? String(variables[key]) : match;
|
|
2276
|
+
});
|
|
2277
|
+
}
|
|
2278
|
+
function setPromptContext(ctx) {
|
|
2279
|
+
promptContext = ctx;
|
|
2280
|
+
}
|
|
2281
|
+
function getPromptContext() {
|
|
2282
|
+
const ctx = promptContext;
|
|
2283
|
+
promptContext = null;
|
|
2284
|
+
return ctx;
|
|
2285
|
+
}
|
|
2286
|
+
async function get2(promptKey, options = {}) {
|
|
2287
|
+
const { variables, version, debug = false } = options;
|
|
2288
|
+
debugMode3 = debug;
|
|
2289
|
+
ensureInit2();
|
|
2290
|
+
log5(`get() called: promptKey=${promptKey}`);
|
|
2291
|
+
let promptData = promptCache.get(promptKey);
|
|
2292
|
+
if (!promptData) {
|
|
2293
|
+
log5("Not in cache, fetching...");
|
|
2294
|
+
await fetchPrompts(SYNC_TIMEOUT2);
|
|
2295
|
+
promptData = promptCache.get(promptKey);
|
|
2296
|
+
}
|
|
2297
|
+
if (!promptData) {
|
|
2298
|
+
throw new Error(
|
|
2299
|
+
`Prompt '${promptKey}' not found. Check that it exists in your Fallom dashboard.`
|
|
2258
2300
|
);
|
|
2259
|
-
clearTimeout(timeoutId);
|
|
2260
|
-
if (resp.ok) {
|
|
2261
|
-
const config = await resp.json();
|
|
2262
|
-
if (!configCache.has(configKey)) {
|
|
2263
|
-
configCache.set(configKey, { versions: /* @__PURE__ */ new Map(), latest: null });
|
|
2264
|
-
}
|
|
2265
|
-
configCache.get(configKey).versions.set(version, config);
|
|
2266
|
-
return config;
|
|
2267
|
-
}
|
|
2268
|
-
} catch {
|
|
2269
2301
|
}
|
|
2270
|
-
|
|
2302
|
+
const targetVersion = version ?? promptData.current;
|
|
2303
|
+
const content = promptData.versions.get(targetVersion);
|
|
2304
|
+
if (!content) {
|
|
2305
|
+
throw new Error(
|
|
2306
|
+
`Prompt '${promptKey}' version ${targetVersion} not found.`
|
|
2307
|
+
);
|
|
2308
|
+
}
|
|
2309
|
+
const system = replaceVariables(content.systemPrompt, variables);
|
|
2310
|
+
const user = replaceVariables(content.userTemplate, variables);
|
|
2311
|
+
setPromptContext({
|
|
2312
|
+
promptKey,
|
|
2313
|
+
promptVersion: targetVersion
|
|
2314
|
+
});
|
|
2315
|
+
log5(`\u2705 Got prompt: ${promptKey} v${targetVersion}`);
|
|
2316
|
+
return {
|
|
2317
|
+
key: promptKey,
|
|
2318
|
+
version: targetVersion,
|
|
2319
|
+
system,
|
|
2320
|
+
user
|
|
2321
|
+
};
|
|
2271
2322
|
}
|
|
2272
|
-
async function
|
|
2273
|
-
const {
|
|
2323
|
+
async function getAB(abTestKey, sessionId, options = {}) {
|
|
2324
|
+
const { variables, debug = false } = options;
|
|
2274
2325
|
debugMode3 = debug;
|
|
2275
2326
|
ensureInit2();
|
|
2276
|
-
|
|
2277
|
-
|
|
2278
|
-
)
|
|
2279
|
-
|
|
2280
|
-
|
|
2281
|
-
|
|
2282
|
-
|
|
2327
|
+
log5(`getAB() called: abTestKey=${abTestKey}, sessionId=${sessionId}`);
|
|
2328
|
+
let abData = promptABCache.get(abTestKey);
|
|
2329
|
+
if (!abData) {
|
|
2330
|
+
log5("Not in cache, fetching...");
|
|
2331
|
+
await fetchPromptABTests(SYNC_TIMEOUT2);
|
|
2332
|
+
abData = promptABCache.get(abTestKey);
|
|
2333
|
+
}
|
|
2334
|
+
if (!abData) {
|
|
2335
|
+
throw new Error(
|
|
2336
|
+
`Prompt A/B test '${abTestKey}' not found. Check that it exists in your Fallom dashboard.`
|
|
2283
2337
|
);
|
|
2284
|
-
|
|
2285
|
-
|
|
2286
|
-
|
|
2287
|
-
|
|
2288
|
-
|
|
2289
|
-
|
|
2290
|
-
|
|
2291
|
-
|
|
2292
|
-
|
|
2293
|
-
|
|
2294
|
-
|
|
2295
|
-
|
|
2296
|
-
`[Fallom WARNING] Config '${configKey}' not found, using fallback model: ${fallback}`
|
|
2297
|
-
);
|
|
2298
|
-
return returnWithTrace(configKey, sessionId, fallback, 0);
|
|
2299
|
-
}
|
|
2300
|
-
throw new Error(
|
|
2301
|
-
`Config '${configKey}' not found. Check that it exists in your Fallom dashboard.`
|
|
2302
|
-
);
|
|
2303
|
-
}
|
|
2304
|
-
let config;
|
|
2305
|
-
let targetVersion;
|
|
2306
|
-
if (version !== void 0) {
|
|
2307
|
-
config = configData.versions.get(version);
|
|
2308
|
-
if (!config) {
|
|
2309
|
-
config = await fetchSpecificVersion(configKey, version, SYNC_TIMEOUT2) || void 0;
|
|
2310
|
-
}
|
|
2311
|
-
if (!config) {
|
|
2312
|
-
if (fallback) {
|
|
2313
|
-
console.warn(
|
|
2314
|
-
`[Fallom WARNING] Config '${configKey}' version ${version} not found, using fallback: ${fallback}`
|
|
2315
|
-
);
|
|
2316
|
-
return returnWithTrace(configKey, sessionId, fallback, 0);
|
|
2317
|
-
}
|
|
2318
|
-
throw new Error(`Config '${configKey}' version ${version} not found.`);
|
|
2319
|
-
}
|
|
2320
|
-
targetVersion = version;
|
|
2321
|
-
} else {
|
|
2322
|
-
targetVersion = configData.latest;
|
|
2323
|
-
config = configData.versions.get(targetVersion);
|
|
2324
|
-
if (!config) {
|
|
2325
|
-
if (fallback) {
|
|
2326
|
-
console.warn(
|
|
2327
|
-
`[Fallom WARNING] Config '${configKey}' has no cached version, using fallback: ${fallback}`
|
|
2328
|
-
);
|
|
2329
|
-
return returnWithTrace(configKey, sessionId, fallback, 0);
|
|
2330
|
-
}
|
|
2331
|
-
throw new Error(`Config '${configKey}' has no cached version.`);
|
|
2332
|
-
}
|
|
2333
|
-
}
|
|
2334
|
-
const variantsRaw = config.variants;
|
|
2335
|
-
const configVersion = config.version || targetVersion;
|
|
2336
|
-
const variants = Array.isArray(variantsRaw) ? variantsRaw : Object.values(variantsRaw);
|
|
2337
|
-
log3(
|
|
2338
|
-
`Config found! Version: ${configVersion}, Variants: ${JSON.stringify(
|
|
2339
|
-
variants
|
|
2340
|
-
)}`
|
|
2338
|
+
}
|
|
2339
|
+
const currentVersion = abData.current;
|
|
2340
|
+
const versionData = abData.versions.get(currentVersion);
|
|
2341
|
+
if (!versionData) {
|
|
2342
|
+
throw new Error(`Prompt A/B test '${abTestKey}' has no current version.`);
|
|
2343
|
+
}
|
|
2344
|
+
const { variants } = versionData;
|
|
2345
|
+
log5(`A/B test '${abTestKey}' has ${variants?.length ?? 0} variants`);
|
|
2346
|
+
log5(`Version data: ${JSON.stringify(versionData, null, 2)}`);
|
|
2347
|
+
if (!variants || variants.length === 0) {
|
|
2348
|
+
throw new Error(
|
|
2349
|
+
`Prompt A/B test '${abTestKey}' has no variants configured.`
|
|
2341
2350
|
);
|
|
2342
|
-
|
|
2343
|
-
|
|
2344
|
-
|
|
2345
|
-
|
|
2346
|
-
|
|
2347
|
-
|
|
2348
|
-
|
|
2349
|
-
|
|
2350
|
-
|
|
2351
|
-
|
|
2352
|
-
|
|
2353
|
-
|
|
2354
|
-
assignedModel = v.model;
|
|
2355
|
-
break;
|
|
2356
|
-
}
|
|
2357
|
-
}
|
|
2358
|
-
log3(`\u2705 Assigned model: ${assignedModel}`);
|
|
2359
|
-
return returnWithTrace(configKey, sessionId, assignedModel, configVersion);
|
|
2360
|
-
} catch (e) {
|
|
2361
|
-
if (e instanceof Error && e.message.includes("not found")) {
|
|
2362
|
-
throw e;
|
|
2363
|
-
}
|
|
2364
|
-
if (fallback) {
|
|
2365
|
-
console.warn(
|
|
2366
|
-
`[Fallom WARNING] Error getting model for '${configKey}': ${e}. Using fallback: ${fallback}`
|
|
2367
|
-
);
|
|
2368
|
-
return returnWithTrace(configKey, sessionId, fallback, 0);
|
|
2351
|
+
}
|
|
2352
|
+
const hashBytes = (0, import_crypto2.createHash)("md5").update(sessionId).digest();
|
|
2353
|
+
const hashVal = hashBytes.readUInt32BE(0) % 1e6;
|
|
2354
|
+
let cumulative = 0;
|
|
2355
|
+
let selectedVariant = variants[variants.length - 1];
|
|
2356
|
+
let selectedIndex = variants.length - 1;
|
|
2357
|
+
for (let i = 0; i < variants.length; i++) {
|
|
2358
|
+
cumulative += variants[i].weight * 1e4;
|
|
2359
|
+
if (hashVal < cumulative) {
|
|
2360
|
+
selectedVariant = variants[i];
|
|
2361
|
+
selectedIndex = i;
|
|
2362
|
+
break;
|
|
2369
2363
|
}
|
|
2370
|
-
throw e;
|
|
2371
2364
|
}
|
|
2372
|
-
|
|
2373
|
-
|
|
2374
|
-
|
|
2375
|
-
|
|
2376
|
-
|
|
2365
|
+
const promptKey = selectedVariant.prompt_key;
|
|
2366
|
+
const promptVersion = selectedVariant.prompt_version;
|
|
2367
|
+
let promptData = promptCache.get(promptKey);
|
|
2368
|
+
if (!promptData) {
|
|
2369
|
+
await fetchPrompts(SYNC_TIMEOUT2);
|
|
2370
|
+
promptData = promptCache.get(promptKey);
|
|
2377
2371
|
}
|
|
2378
|
-
if (
|
|
2379
|
-
|
|
2380
|
-
|
|
2372
|
+
if (!promptData) {
|
|
2373
|
+
throw new Error(
|
|
2374
|
+
`Prompt '${promptKey}' (from A/B test '${abTestKey}') not found.`
|
|
2375
|
+
);
|
|
2381
2376
|
}
|
|
2382
|
-
|
|
2383
|
-
|
|
2384
|
-
|
|
2385
|
-
|
|
2386
|
-
|
|
2387
|
-
|
|
2388
|
-
const timeoutId = setTimeout(() => controller.abort(), RECORD_TIMEOUT);
|
|
2389
|
-
await fetch(`${baseUrl3}/sessions`, {
|
|
2390
|
-
method: "POST",
|
|
2391
|
-
headers: {
|
|
2392
|
-
Authorization: `Bearer ${apiKey3}`,
|
|
2393
|
-
"Content-Type": "application/json"
|
|
2394
|
-
},
|
|
2395
|
-
body: JSON.stringify({
|
|
2396
|
-
config_key: configKey,
|
|
2397
|
-
config_version: version,
|
|
2398
|
-
session_id: sessionId,
|
|
2399
|
-
assigned_model: model
|
|
2400
|
-
}),
|
|
2401
|
-
signal: controller.signal
|
|
2402
|
-
});
|
|
2403
|
-
clearTimeout(timeoutId);
|
|
2404
|
-
} catch {
|
|
2377
|
+
const targetVersion = promptVersion ?? promptData.current;
|
|
2378
|
+
const content = promptData.versions.get(targetVersion);
|
|
2379
|
+
if (!content) {
|
|
2380
|
+
throw new Error(
|
|
2381
|
+
`Prompt '${promptKey}' version ${targetVersion} not found.`
|
|
2382
|
+
);
|
|
2405
2383
|
}
|
|
2384
|
+
const system = replaceVariables(content.systemPrompt, variables);
|
|
2385
|
+
const user = replaceVariables(content.userTemplate, variables);
|
|
2386
|
+
setPromptContext({
|
|
2387
|
+
promptKey,
|
|
2388
|
+
promptVersion: targetVersion,
|
|
2389
|
+
abTestKey,
|
|
2390
|
+
variantIndex: selectedIndex
|
|
2391
|
+
});
|
|
2392
|
+
log5(
|
|
2393
|
+
`\u2705 Got prompt from A/B: ${promptKey} v${targetVersion} (variant ${selectedIndex})`
|
|
2394
|
+
);
|
|
2395
|
+
return {
|
|
2396
|
+
key: promptKey,
|
|
2397
|
+
version: targetVersion,
|
|
2398
|
+
system,
|
|
2399
|
+
user,
|
|
2400
|
+
abTestKey,
|
|
2401
|
+
variantIndex: selectedIndex
|
|
2402
|
+
};
|
|
2403
|
+
}
|
|
2404
|
+
function clearPromptContext() {
|
|
2405
|
+
promptContext = null;
|
|
2406
2406
|
}
|
|
2407
|
-
|
|
2408
|
-
// src/index.ts
|
|
2409
|
-
init_prompts();
|
|
2410
2407
|
|
|
2411
2408
|
// src/init.ts
|
|
2412
|
-
|
|
2409
|
+
init_models();
|
|
2413
2410
|
async function init4(options = {}) {
|
|
2414
2411
|
const tracesUrl = options.tracesUrl || process.env.FALLOM_TRACES_URL || "https://traces.fallom.com";
|
|
2415
2412
|
const configsUrl = options.configsUrl || process.env.FALLOM_CONFIGS_URL || "https://configs.fallom.com";
|
|
2416
2413
|
const promptsUrl = options.promptsUrl || process.env.FALLOM_PROMPTS_URL || "https://prompts.fallom.com";
|
|
2417
|
-
await
|
|
2414
|
+
await init({
|
|
2418
2415
|
apiKey: options.apiKey,
|
|
2419
2416
|
baseUrl: tracesUrl,
|
|
2420
2417
|
captureContent: options.captureContent,
|
|
2421
2418
|
debug: options.debug
|
|
2422
2419
|
});
|
|
2423
|
-
|
|
2420
|
+
init2({
|
|
2424
2421
|
apiKey: options.apiKey,
|
|
2425
2422
|
baseUrl: configsUrl
|
|
2426
2423
|
});
|
|
2427
|
-
|
|
2424
|
+
init3({
|
|
2428
2425
|
apiKey: options.apiKey,
|
|
2429
2426
|
baseUrl: promptsUrl
|
|
2430
2427
|
});
|
|
2431
2428
|
}
|
|
2432
2429
|
|
|
2433
2430
|
// src/mastra.ts
|
|
2434
|
-
var
|
|
2431
|
+
var import_core12 = require("@opentelemetry/core");
|
|
2435
2432
|
var promptContext2 = {};
|
|
2436
2433
|
function setMastraPrompt(promptKey, version) {
|
|
2437
2434
|
promptContext2 = {
|
|
@@ -2458,9 +2455,13 @@ var FallomExporter = class {
|
|
|
2458
2455
|
this.apiKey = options.apiKey ?? process.env.FALLOM_API_KEY ?? "";
|
|
2459
2456
|
this.baseUrl = options.baseUrl ?? "https://traces.fallom.com";
|
|
2460
2457
|
this.debug = options.debug ?? false;
|
|
2461
|
-
|
|
2462
|
-
|
|
2463
|
-
|
|
2458
|
+
this.session = options.session;
|
|
2459
|
+
if (this.debug) {
|
|
2460
|
+
console.log("[FallomExporter] Constructor called");
|
|
2461
|
+
console.log("[FallomExporter] API key present:", !!this.apiKey);
|
|
2462
|
+
console.log("[FallomExporter] Base URL:", this.baseUrl);
|
|
2463
|
+
console.log("[FallomExporter] Session:", this.session);
|
|
2464
|
+
}
|
|
2464
2465
|
if (!this.apiKey) {
|
|
2465
2466
|
console.warn(
|
|
2466
2467
|
"[FallomExporter] No API key provided. Set FALLOM_API_KEY env var or pass apiKey option."
|
|
@@ -2477,15 +2478,15 @@ var FallomExporter = class {
|
|
|
2477
2478
|
*/
|
|
2478
2479
|
export(spans, resultCallback) {
|
|
2479
2480
|
if (spans.length === 0) {
|
|
2480
|
-
resultCallback({ code:
|
|
2481
|
+
resultCallback({ code: import_core12.ExportResultCode.SUCCESS });
|
|
2481
2482
|
return;
|
|
2482
2483
|
}
|
|
2483
2484
|
this.log(`Exporting ${spans.length} spans...`);
|
|
2484
2485
|
if (this.debug) {
|
|
2485
|
-
for (const
|
|
2486
|
-
this.log(` - ${
|
|
2486
|
+
for (const span of spans) {
|
|
2487
|
+
this.log(` - ${span.name}`, {
|
|
2487
2488
|
attributes: Object.fromEntries(
|
|
2488
|
-
Object.entries(
|
|
2489
|
+
Object.entries(span.attributes).filter(
|
|
2489
2490
|
([k]) => k.startsWith("gen_ai") || k.startsWith("llm")
|
|
2490
2491
|
)
|
|
2491
2492
|
)
|
|
@@ -2494,11 +2495,11 @@ var FallomExporter = class {
|
|
|
2494
2495
|
}
|
|
2495
2496
|
const exportPromise = this.sendSpans(spans).then(() => {
|
|
2496
2497
|
this.log("Export successful");
|
|
2497
|
-
resultCallback({ code:
|
|
2498
|
+
resultCallback({ code: import_core12.ExportResultCode.SUCCESS });
|
|
2498
2499
|
}).catch((error) => {
|
|
2499
2500
|
console.error("[FallomExporter] Export failed:", error);
|
|
2500
2501
|
resultCallback({
|
|
2501
|
-
code:
|
|
2502
|
+
code: import_core12.ExportResultCode.FAILED,
|
|
2502
2503
|
error: error instanceof Error ? error : new Error(String(error))
|
|
2503
2504
|
});
|
|
2504
2505
|
});
|
|
@@ -2521,20 +2522,19 @@ var FallomExporter = class {
|
|
|
2521
2522
|
* Send spans to Fallom's OTLP endpoint.
|
|
2522
2523
|
*/
|
|
2523
2524
|
async sendSpans(spans) {
|
|
2524
|
-
const session = getSession();
|
|
2525
2525
|
const resourceSpans = this.spansToOtlpJson(spans);
|
|
2526
2526
|
const headers = {
|
|
2527
2527
|
"Content-Type": "application/json",
|
|
2528
2528
|
Authorization: `Bearer ${this.apiKey}`
|
|
2529
2529
|
};
|
|
2530
|
-
if (session?.configKey) {
|
|
2531
|
-
headers["X-Fallom-Config-Key"] = session.configKey;
|
|
2530
|
+
if (this.session?.configKey) {
|
|
2531
|
+
headers["X-Fallom-Config-Key"] = this.session.configKey;
|
|
2532
2532
|
}
|
|
2533
|
-
if (session?.sessionId) {
|
|
2534
|
-
headers["X-Fallom-Session-Id"] = session.sessionId;
|
|
2533
|
+
if (this.session?.sessionId) {
|
|
2534
|
+
headers["X-Fallom-Session-Id"] = this.session.sessionId;
|
|
2535
2535
|
}
|
|
2536
|
-
if (session?.customerId) {
|
|
2537
|
-
headers["X-Fallom-Customer-Id"] = session.customerId;
|
|
2536
|
+
if (this.session?.customerId) {
|
|
2537
|
+
headers["X-Fallom-Customer-Id"] = this.session.customerId;
|
|
2538
2538
|
}
|
|
2539
2539
|
if (promptContext2.promptKey) {
|
|
2540
2540
|
headers["X-Fallom-Prompt-Key"] = promptContext2.promptKey;
|
|
@@ -2571,12 +2571,12 @@ var FallomExporter = class {
|
|
|
2571
2571
|
*/
|
|
2572
2572
|
spansToOtlpJson(spans) {
|
|
2573
2573
|
const resourceMap = /* @__PURE__ */ new Map();
|
|
2574
|
-
for (const
|
|
2575
|
-
const resourceKey = JSON.stringify(
|
|
2574
|
+
for (const span of spans) {
|
|
2575
|
+
const resourceKey = JSON.stringify(span.resource.attributes);
|
|
2576
2576
|
if (!resourceMap.has(resourceKey)) {
|
|
2577
2577
|
resourceMap.set(resourceKey, []);
|
|
2578
2578
|
}
|
|
2579
|
-
resourceMap.get(resourceKey).push(
|
|
2579
|
+
resourceMap.get(resourceKey).push(span);
|
|
2580
2580
|
}
|
|
2581
2581
|
const resourceSpans = [];
|
|
2582
2582
|
for (const [_resourceKey, resourceSpanList] of resourceMap) {
|
|
@@ -2591,7 +2591,7 @@ var FallomExporter = class {
|
|
|
2591
2591
|
name: firstSpan.instrumentationLibrary.name,
|
|
2592
2592
|
version: firstSpan.instrumentationLibrary.version
|
|
2593
2593
|
},
|
|
2594
|
-
spans: resourceSpanList.map((
|
|
2594
|
+
spans: resourceSpanList.map((span) => this.spanToOtlp(span))
|
|
2595
2595
|
}
|
|
2596
2596
|
]
|
|
2597
2597
|
});
|
|
@@ -2601,21 +2601,21 @@ var FallomExporter = class {
|
|
|
2601
2601
|
/**
|
|
2602
2602
|
* Convert a single span to OTLP format.
|
|
2603
2603
|
*/
|
|
2604
|
-
spanToOtlp(
|
|
2604
|
+
spanToOtlp(span) {
|
|
2605
2605
|
return {
|
|
2606
|
-
traceId:
|
|
2607
|
-
spanId:
|
|
2608
|
-
parentSpanId:
|
|
2609
|
-
name:
|
|
2610
|
-
kind:
|
|
2611
|
-
startTimeUnixNano: this.hrTimeToNanos(
|
|
2612
|
-
endTimeUnixNano: this.hrTimeToNanos(
|
|
2613
|
-
attributes: this.attributesToOtlp(
|
|
2606
|
+
traceId: span.spanContext().traceId,
|
|
2607
|
+
spanId: span.spanContext().spanId,
|
|
2608
|
+
parentSpanId: span.parentSpanId,
|
|
2609
|
+
name: span.name,
|
|
2610
|
+
kind: span.kind,
|
|
2611
|
+
startTimeUnixNano: this.hrTimeToNanos(span.startTime),
|
|
2612
|
+
endTimeUnixNano: this.hrTimeToNanos(span.endTime),
|
|
2613
|
+
attributes: this.attributesToOtlp(span.attributes),
|
|
2614
2614
|
status: {
|
|
2615
|
-
code:
|
|
2616
|
-
message:
|
|
2615
|
+
code: span.status.code,
|
|
2616
|
+
message: span.status.message
|
|
2617
2617
|
},
|
|
2618
|
-
events:
|
|
2618
|
+
events: span.events.map((event) => ({
|
|
2619
2619
|
timeUnixNano: this.hrTimeToNanos(event.time),
|
|
2620
2620
|
name: event.name,
|
|
2621
2621
|
attributes: this.attributesToOtlp(event.attributes || {})
|
|
@@ -2666,20 +2666,23 @@ var FallomExporter = class {
|
|
|
2666
2666
|
};
|
|
2667
2667
|
|
|
2668
2668
|
// src/index.ts
|
|
2669
|
-
|
|
2669
|
+
init_models();
|
|
2670
2670
|
var index_default = {
|
|
2671
2671
|
init: init4,
|
|
2672
2672
|
trace: trace_exports,
|
|
2673
2673
|
models: models_exports,
|
|
2674
|
-
prompts: prompts_exports
|
|
2674
|
+
prompts: prompts_exports,
|
|
2675
|
+
session
|
|
2675
2676
|
};
|
|
2676
2677
|
// Annotate the CommonJS export names for ESM import in node:
|
|
2677
2678
|
0 && (module.exports = {
|
|
2678
2679
|
FallomExporter,
|
|
2680
|
+
FallomSession,
|
|
2679
2681
|
clearMastraPrompt,
|
|
2680
2682
|
init,
|
|
2681
2683
|
models,
|
|
2682
2684
|
prompts,
|
|
2685
|
+
session,
|
|
2683
2686
|
setMastraPrompt,
|
|
2684
2687
|
setMastraPromptAB,
|
|
2685
2688
|
trace
|