@rynfar/meridian 1.34.1 → 1.35.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 +15 -9
- package/dist/{cli-bwchvbfb.js → cli-0kfa6j99.js} +1269 -132
- package/dist/cli-p9swy5t3.js +67 -0
- package/dist/cli.js +8 -8
- package/dist/{profileCli-5e3p99k0.js → profileCli-5f15dx7k.js} +1 -1
- package/dist/{profilePage-9nkbct3w.js → profilePage-e90fq8ye.js} +1 -1
- package/dist/{profiles-ntgacztq.js → profiles-edzz1ffd.js} +1 -1
- package/dist/proxy/server.d.ts.map +1 -1
- package/dist/proxy/types.d.ts +2 -0
- package/dist/proxy/types.d.ts.map +1 -1
- package/dist/server.js +2 -2
- package/dist/{setup-5x116vbs.js → setup-v5pnqe04.js} +1 -1
- package/dist/telemetry/index.d.ts +9 -4
- package/dist/telemetry/index.d.ts.map +1 -1
- package/dist/telemetry/logStore.d.ts +4 -25
- package/dist/telemetry/logStore.d.ts.map +1 -1
- package/dist/telemetry/percentiles.d.ts +12 -0
- package/dist/telemetry/percentiles.d.ts.map +1 -0
- package/dist/telemetry/prometheus.d.ts +10 -0
- package/dist/telemetry/prometheus.d.ts.map +1 -0
- package/dist/telemetry/routes.d.ts.map +1 -1
- package/dist/telemetry/sqlite.d.ts +7 -0
- package/dist/telemetry/sqlite.d.ts.map +1 -0
- package/dist/telemetry/store.d.ts +3 -3
- package/dist/telemetry/store.d.ts.map +1 -1
- package/dist/telemetry/types.d.ts +51 -0
- package/dist/telemetry/types.d.ts.map +1 -1
- package/dist/{tokenRefresh-ywwpe8k2.js → tokenRefresh-y7d1qvb3.js} +1 -1
- package/package.json +3 -2
- package/dist/cli-a05ws7rb.js +0 -18
|
@@ -20,9 +20,1133 @@ import {
|
|
|
20
20
|
setActiveProfile
|
|
21
21
|
} from "./cli-vdp9s10c.js";
|
|
22
22
|
import {
|
|
23
|
+
__commonJS,
|
|
24
|
+
__esm,
|
|
23
25
|
__export,
|
|
24
|
-
__require
|
|
25
|
-
|
|
26
|
+
__require,
|
|
27
|
+
__toCommonJS,
|
|
28
|
+
__toESM
|
|
29
|
+
} from "./cli-p9swy5t3.js";
|
|
30
|
+
|
|
31
|
+
// src/telemetry/percentiles.ts
|
|
32
|
+
function computePercentiles(values) {
|
|
33
|
+
if (values.length === 0)
|
|
34
|
+
return { p50: 0, p95: 0, p99: 0, min: 0, max: 0, avg: 0 };
|
|
35
|
+
const sorted = [...values].sort((a, b) => a - b);
|
|
36
|
+
const sum = sorted.reduce((a, b) => a + b, 0);
|
|
37
|
+
return {
|
|
38
|
+
p50: sorted[Math.floor(sorted.length * 0.5)],
|
|
39
|
+
p95: sorted[Math.floor(sorted.length * 0.95)],
|
|
40
|
+
p99: sorted[Math.floor(sorted.length * 0.99)],
|
|
41
|
+
min: sorted[0],
|
|
42
|
+
max: sorted[sorted.length - 1],
|
|
43
|
+
avg: Math.round(sum / sorted.length)
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
function computeSummary(metrics, windowMs) {
|
|
47
|
+
if (metrics.length === 0) {
|
|
48
|
+
const emptyPhase = { p50: 0, p95: 0, p99: 0, min: 0, max: 0, avg: 0 };
|
|
49
|
+
return {
|
|
50
|
+
windowMs,
|
|
51
|
+
totalRequests: 0,
|
|
52
|
+
errorCount: 0,
|
|
53
|
+
requestsPerMinute: 0,
|
|
54
|
+
queueWait: emptyPhase,
|
|
55
|
+
proxyOverhead: emptyPhase,
|
|
56
|
+
ttfb: emptyPhase,
|
|
57
|
+
upstreamDuration: emptyPhase,
|
|
58
|
+
totalDuration: emptyPhase,
|
|
59
|
+
byModel: {},
|
|
60
|
+
byMode: {},
|
|
61
|
+
tokenUsage: {
|
|
62
|
+
totalInputTokens: 0,
|
|
63
|
+
totalOutputTokens: 0,
|
|
64
|
+
totalCacheReadTokens: 0,
|
|
65
|
+
totalCacheCreationTokens: 0,
|
|
66
|
+
avgCacheHitRate: 0,
|
|
67
|
+
cacheMissOnResumeCount: 0
|
|
68
|
+
}
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
const errorCount = metrics.filter((m) => m.error !== null).length;
|
|
72
|
+
const oldest = metrics[metrics.length - 1].timestamp;
|
|
73
|
+
const newest = metrics[0].timestamp;
|
|
74
|
+
const spanMs = Math.max(newest - oldest, 1);
|
|
75
|
+
const requestsPerMinute = metrics.length / spanMs * 60000;
|
|
76
|
+
const queueWaits = metrics.map((m) => m.queueWaitMs);
|
|
77
|
+
const overheads = metrics.map((m) => m.proxyOverheadMs);
|
|
78
|
+
const ttfbs = metrics.filter((m) => m.ttfbMs !== null).map((m) => m.ttfbMs);
|
|
79
|
+
const upstreams = metrics.map((m) => m.upstreamDurationMs);
|
|
80
|
+
const totals = metrics.map((m) => m.totalDurationMs);
|
|
81
|
+
const byModel = {};
|
|
82
|
+
for (const m of metrics) {
|
|
83
|
+
const modelKey = m.requestModel || m.model;
|
|
84
|
+
const entry = byModel[modelKey] ??= { count: 0, totalMs: 0 };
|
|
85
|
+
entry.count++;
|
|
86
|
+
entry.totalMs += m.totalDurationMs;
|
|
87
|
+
}
|
|
88
|
+
const byMode = {};
|
|
89
|
+
for (const m of metrics) {
|
|
90
|
+
const entry = byMode[m.mode] ??= { count: 0, totalMs: 0 };
|
|
91
|
+
entry.count++;
|
|
92
|
+
entry.totalMs += m.totalDurationMs;
|
|
93
|
+
}
|
|
94
|
+
let totalInputTokens = 0;
|
|
95
|
+
let totalOutputTokens = 0;
|
|
96
|
+
let totalCacheReadTokens = 0;
|
|
97
|
+
let totalCacheCreationTokens = 0;
|
|
98
|
+
let cacheHitRateSum = 0;
|
|
99
|
+
let cacheHitRateCount = 0;
|
|
100
|
+
let cacheMissOnResumeCount = 0;
|
|
101
|
+
for (const m of metrics) {
|
|
102
|
+
totalInputTokens += m.inputTokens ?? 0;
|
|
103
|
+
totalOutputTokens += m.outputTokens ?? 0;
|
|
104
|
+
totalCacheReadTokens += m.cacheReadInputTokens ?? 0;
|
|
105
|
+
totalCacheCreationTokens += m.cacheCreationInputTokens ?? 0;
|
|
106
|
+
if (m.cacheHitRate !== undefined) {
|
|
107
|
+
cacheHitRateSum += m.cacheHitRate;
|
|
108
|
+
cacheHitRateCount++;
|
|
109
|
+
}
|
|
110
|
+
if (m.isResume && m.cacheHitRate !== undefined && m.cacheHitRate === 0) {
|
|
111
|
+
cacheMissOnResumeCount++;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
return {
|
|
115
|
+
windowMs,
|
|
116
|
+
totalRequests: metrics.length,
|
|
117
|
+
errorCount,
|
|
118
|
+
requestsPerMinute: Math.round(requestsPerMinute * 100) / 100,
|
|
119
|
+
queueWait: computePercentiles(queueWaits),
|
|
120
|
+
proxyOverhead: computePercentiles(overheads),
|
|
121
|
+
ttfb: ttfbs.length > 0 ? computePercentiles(ttfbs) : { p50: 0, p95: 0, p99: 0, min: 0, max: 0, avg: 0 },
|
|
122
|
+
upstreamDuration: computePercentiles(upstreams),
|
|
123
|
+
totalDuration: computePercentiles(totals),
|
|
124
|
+
byModel: Object.fromEntries(Object.entries(byModel).map(([k, v]) => [k, { count: v.count, avgTotalMs: Math.round(v.totalMs / v.count) }])),
|
|
125
|
+
byMode: Object.fromEntries(Object.entries(byMode).map(([k, v]) => [k, { count: v.count, avgTotalMs: Math.round(v.totalMs / v.count) }])),
|
|
126
|
+
tokenUsage: {
|
|
127
|
+
totalInputTokens,
|
|
128
|
+
totalOutputTokens,
|
|
129
|
+
totalCacheReadTokens,
|
|
130
|
+
totalCacheCreationTokens,
|
|
131
|
+
avgCacheHitRate: cacheHitRateCount > 0 ? Math.round(cacheHitRateSum / cacheHitRateCount * 100) / 100 : 0,
|
|
132
|
+
cacheMissOnResumeCount
|
|
133
|
+
}
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
var init_percentiles = () => {};
|
|
137
|
+
|
|
138
|
+
// node_modules/@neon-rs/load/dist/index.js
|
|
139
|
+
var require_dist = __commonJS((exports) => {
|
|
140
|
+
var __createBinding = exports && exports.__createBinding || (Object.create ? function(o, m, k, k2) {
|
|
141
|
+
if (k2 === undefined)
|
|
142
|
+
k2 = k;
|
|
143
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
144
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
145
|
+
desc = { enumerable: true, get: function() {
|
|
146
|
+
return m[k];
|
|
147
|
+
} };
|
|
148
|
+
}
|
|
149
|
+
Object.defineProperty(o, k2, desc);
|
|
150
|
+
} : function(o, m, k, k2) {
|
|
151
|
+
if (k2 === undefined)
|
|
152
|
+
k2 = k;
|
|
153
|
+
o[k2] = m[k];
|
|
154
|
+
});
|
|
155
|
+
var __setModuleDefault = exports && exports.__setModuleDefault || (Object.create ? function(o, v) {
|
|
156
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
157
|
+
} : function(o, v) {
|
|
158
|
+
o["default"] = v;
|
|
159
|
+
});
|
|
160
|
+
var __importStar = exports && exports.__importStar || function(mod) {
|
|
161
|
+
if (mod && mod.__esModule)
|
|
162
|
+
return mod;
|
|
163
|
+
var result = {};
|
|
164
|
+
if (mod != null) {
|
|
165
|
+
for (var k in mod)
|
|
166
|
+
if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k))
|
|
167
|
+
__createBinding(result, mod, k);
|
|
168
|
+
}
|
|
169
|
+
__setModuleDefault(result, mod);
|
|
170
|
+
return result;
|
|
171
|
+
};
|
|
172
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
173
|
+
exports.load = exports.currentTarget = undefined;
|
|
174
|
+
var path = __importStar(__require("path"));
|
|
175
|
+
var fs = __importStar(__require("fs"));
|
|
176
|
+
function currentTarget() {
|
|
177
|
+
let os = null;
|
|
178
|
+
switch (process.platform) {
|
|
179
|
+
case "android":
|
|
180
|
+
switch (process.arch) {
|
|
181
|
+
case "arm":
|
|
182
|
+
return "android-arm-eabi";
|
|
183
|
+
case "arm64":
|
|
184
|
+
return "android-arm64";
|
|
185
|
+
}
|
|
186
|
+
os = "Android";
|
|
187
|
+
break;
|
|
188
|
+
case "win32":
|
|
189
|
+
switch (process.arch) {
|
|
190
|
+
case "x64":
|
|
191
|
+
return "win32-x64-msvc";
|
|
192
|
+
case "arm64":
|
|
193
|
+
return "win32-arm64-msvc";
|
|
194
|
+
case "ia32":
|
|
195
|
+
return "win32-ia32-msvc";
|
|
196
|
+
}
|
|
197
|
+
os = "Windows";
|
|
198
|
+
break;
|
|
199
|
+
case "darwin":
|
|
200
|
+
switch (process.arch) {
|
|
201
|
+
case "x64":
|
|
202
|
+
return "darwin-x64";
|
|
203
|
+
case "arm64":
|
|
204
|
+
return "darwin-arm64";
|
|
205
|
+
}
|
|
206
|
+
os = "macOS";
|
|
207
|
+
break;
|
|
208
|
+
case "linux":
|
|
209
|
+
switch (process.arch) {
|
|
210
|
+
case "x64":
|
|
211
|
+
case "arm64":
|
|
212
|
+
return isGlibc() ? `linux-${process.arch}-gnu` : `linux-${process.arch}-musl`;
|
|
213
|
+
case "arm":
|
|
214
|
+
return "linux-arm-gnueabihf";
|
|
215
|
+
}
|
|
216
|
+
os = "Linux";
|
|
217
|
+
break;
|
|
218
|
+
case "freebsd":
|
|
219
|
+
if (process.arch === "x64") {
|
|
220
|
+
return "freebsd-x64";
|
|
221
|
+
}
|
|
222
|
+
os = "FreeBSD";
|
|
223
|
+
break;
|
|
224
|
+
}
|
|
225
|
+
if (os) {
|
|
226
|
+
throw new Error(`Neon: unsupported ${os} architecture: ${process.arch}`);
|
|
227
|
+
}
|
|
228
|
+
throw new Error(`Neon: unsupported system: ${process.platform}`);
|
|
229
|
+
}
|
|
230
|
+
exports.currentTarget = currentTarget;
|
|
231
|
+
function isGlibc() {
|
|
232
|
+
const report = process.report?.getReport();
|
|
233
|
+
if (typeof report !== "object" || !report || !("header" in report)) {
|
|
234
|
+
return false;
|
|
235
|
+
}
|
|
236
|
+
const header = report.header;
|
|
237
|
+
return typeof header === "object" && !!header && "glibcVersionRuntime" in header;
|
|
238
|
+
}
|
|
239
|
+
function load(dirname2) {
|
|
240
|
+
const m = path.join(dirname2, "index.node");
|
|
241
|
+
return fs.existsSync(m) ? __require(m) : null;
|
|
242
|
+
}
|
|
243
|
+
exports.load = load;
|
|
244
|
+
});
|
|
245
|
+
|
|
246
|
+
// node_modules/detect-libc/lib/process.js
|
|
247
|
+
var require_process = __commonJS((exports, module) => {
|
|
248
|
+
var isLinux = () => process.platform === "linux";
|
|
249
|
+
var report = null;
|
|
250
|
+
var getReport = () => {
|
|
251
|
+
if (!report) {
|
|
252
|
+
report = isLinux() && process.report ? process.report.getReport() : {};
|
|
253
|
+
}
|
|
254
|
+
return report;
|
|
255
|
+
};
|
|
256
|
+
module.exports = { isLinux, getReport };
|
|
257
|
+
});
|
|
258
|
+
|
|
259
|
+
// node_modules/detect-libc/lib/filesystem.js
|
|
260
|
+
var require_filesystem = __commonJS((exports, module) => {
|
|
261
|
+
var fs = __require("fs");
|
|
262
|
+
var LDD_PATH = "/usr/bin/ldd";
|
|
263
|
+
var readFileSync2 = (path) => fs.readFileSync(path, "utf-8");
|
|
264
|
+
var readFile = (path) => new Promise((resolve2, reject) => {
|
|
265
|
+
fs.readFile(path, "utf-8", (err, data) => {
|
|
266
|
+
if (err) {
|
|
267
|
+
reject(err);
|
|
268
|
+
} else {
|
|
269
|
+
resolve2(data);
|
|
270
|
+
}
|
|
271
|
+
});
|
|
272
|
+
});
|
|
273
|
+
module.exports = {
|
|
274
|
+
LDD_PATH,
|
|
275
|
+
readFileSync: readFileSync2,
|
|
276
|
+
readFile
|
|
277
|
+
};
|
|
278
|
+
});
|
|
279
|
+
|
|
280
|
+
// node_modules/detect-libc/lib/detect-libc.js
|
|
281
|
+
var require_detect_libc = __commonJS((exports, module) => {
|
|
282
|
+
var childProcess = __require("child_process");
|
|
283
|
+
var { isLinux, getReport } = require_process();
|
|
284
|
+
var { LDD_PATH, readFile, readFileSync: readFileSync2 } = require_filesystem();
|
|
285
|
+
var cachedFamilyFilesystem;
|
|
286
|
+
var cachedVersionFilesystem;
|
|
287
|
+
var command = "getconf GNU_LIBC_VERSION 2>&1 || true; ldd --version 2>&1 || true";
|
|
288
|
+
var commandOut = "";
|
|
289
|
+
var safeCommand = () => {
|
|
290
|
+
if (!commandOut) {
|
|
291
|
+
return new Promise((resolve2) => {
|
|
292
|
+
childProcess.exec(command, (err, out) => {
|
|
293
|
+
commandOut = err ? " " : out;
|
|
294
|
+
resolve2(commandOut);
|
|
295
|
+
});
|
|
296
|
+
});
|
|
297
|
+
}
|
|
298
|
+
return commandOut;
|
|
299
|
+
};
|
|
300
|
+
var safeCommandSync = () => {
|
|
301
|
+
if (!commandOut) {
|
|
302
|
+
try {
|
|
303
|
+
commandOut = childProcess.execSync(command, { encoding: "utf8" });
|
|
304
|
+
} catch (_err) {
|
|
305
|
+
commandOut = " ";
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
return commandOut;
|
|
309
|
+
};
|
|
310
|
+
var GLIBC = "glibc";
|
|
311
|
+
var RE_GLIBC_VERSION = /GLIBC\s(\d+\.\d+)/;
|
|
312
|
+
var MUSL = "musl";
|
|
313
|
+
var GLIBC_ON_LDD = GLIBC.toUpperCase();
|
|
314
|
+
var MUSL_ON_LDD = MUSL.toLowerCase();
|
|
315
|
+
var isFileMusl = (f) => f.includes("libc.musl-") || f.includes("ld-musl-");
|
|
316
|
+
var familyFromReport = () => {
|
|
317
|
+
const report = getReport();
|
|
318
|
+
if (report.header && report.header.glibcVersionRuntime) {
|
|
319
|
+
return GLIBC;
|
|
320
|
+
}
|
|
321
|
+
if (Array.isArray(report.sharedObjects)) {
|
|
322
|
+
if (report.sharedObjects.some(isFileMusl)) {
|
|
323
|
+
return MUSL;
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
return null;
|
|
327
|
+
};
|
|
328
|
+
var familyFromCommand = (out) => {
|
|
329
|
+
const [getconf, ldd1] = out.split(/[\r\n]+/);
|
|
330
|
+
if (getconf && getconf.includes(GLIBC)) {
|
|
331
|
+
return GLIBC;
|
|
332
|
+
}
|
|
333
|
+
if (ldd1 && ldd1.includes(MUSL)) {
|
|
334
|
+
return MUSL;
|
|
335
|
+
}
|
|
336
|
+
return null;
|
|
337
|
+
};
|
|
338
|
+
var getFamilyFromLddContent = (content) => {
|
|
339
|
+
if (content.includes(MUSL_ON_LDD)) {
|
|
340
|
+
return MUSL;
|
|
341
|
+
}
|
|
342
|
+
if (content.includes(GLIBC_ON_LDD)) {
|
|
343
|
+
return GLIBC;
|
|
344
|
+
}
|
|
345
|
+
return null;
|
|
346
|
+
};
|
|
347
|
+
var familyFromFilesystem = async () => {
|
|
348
|
+
if (cachedFamilyFilesystem !== undefined) {
|
|
349
|
+
return cachedFamilyFilesystem;
|
|
350
|
+
}
|
|
351
|
+
cachedFamilyFilesystem = null;
|
|
352
|
+
try {
|
|
353
|
+
const lddContent = await readFile(LDD_PATH);
|
|
354
|
+
cachedFamilyFilesystem = getFamilyFromLddContent(lddContent);
|
|
355
|
+
} catch (e) {}
|
|
356
|
+
return cachedFamilyFilesystem;
|
|
357
|
+
};
|
|
358
|
+
var familyFromFilesystemSync = () => {
|
|
359
|
+
if (cachedFamilyFilesystem !== undefined) {
|
|
360
|
+
return cachedFamilyFilesystem;
|
|
361
|
+
}
|
|
362
|
+
cachedFamilyFilesystem = null;
|
|
363
|
+
try {
|
|
364
|
+
const lddContent = readFileSync2(LDD_PATH);
|
|
365
|
+
cachedFamilyFilesystem = getFamilyFromLddContent(lddContent);
|
|
366
|
+
} catch (e) {}
|
|
367
|
+
return cachedFamilyFilesystem;
|
|
368
|
+
};
|
|
369
|
+
var family = async () => {
|
|
370
|
+
let family2 = null;
|
|
371
|
+
if (isLinux()) {
|
|
372
|
+
family2 = await familyFromFilesystem();
|
|
373
|
+
if (!family2) {
|
|
374
|
+
family2 = familyFromReport();
|
|
375
|
+
}
|
|
376
|
+
if (!family2) {
|
|
377
|
+
const out = await safeCommand();
|
|
378
|
+
family2 = familyFromCommand(out);
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
return family2;
|
|
382
|
+
};
|
|
383
|
+
var familySync = () => {
|
|
384
|
+
let family2 = null;
|
|
385
|
+
if (isLinux()) {
|
|
386
|
+
family2 = familyFromFilesystemSync();
|
|
387
|
+
if (!family2) {
|
|
388
|
+
family2 = familyFromReport();
|
|
389
|
+
}
|
|
390
|
+
if (!family2) {
|
|
391
|
+
const out = safeCommandSync();
|
|
392
|
+
family2 = familyFromCommand(out);
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
return family2;
|
|
396
|
+
};
|
|
397
|
+
var isNonGlibcLinux = async () => isLinux() && await family() !== GLIBC;
|
|
398
|
+
var isNonGlibcLinuxSync = () => isLinux() && familySync() !== GLIBC;
|
|
399
|
+
var versionFromFilesystem = async () => {
|
|
400
|
+
if (cachedVersionFilesystem !== undefined) {
|
|
401
|
+
return cachedVersionFilesystem;
|
|
402
|
+
}
|
|
403
|
+
cachedVersionFilesystem = null;
|
|
404
|
+
try {
|
|
405
|
+
const lddContent = await readFile(LDD_PATH);
|
|
406
|
+
const versionMatch = lddContent.match(RE_GLIBC_VERSION);
|
|
407
|
+
if (versionMatch) {
|
|
408
|
+
cachedVersionFilesystem = versionMatch[1];
|
|
409
|
+
}
|
|
410
|
+
} catch (e) {}
|
|
411
|
+
return cachedVersionFilesystem;
|
|
412
|
+
};
|
|
413
|
+
var versionFromFilesystemSync = () => {
|
|
414
|
+
if (cachedVersionFilesystem !== undefined) {
|
|
415
|
+
return cachedVersionFilesystem;
|
|
416
|
+
}
|
|
417
|
+
cachedVersionFilesystem = null;
|
|
418
|
+
try {
|
|
419
|
+
const lddContent = readFileSync2(LDD_PATH);
|
|
420
|
+
const versionMatch = lddContent.match(RE_GLIBC_VERSION);
|
|
421
|
+
if (versionMatch) {
|
|
422
|
+
cachedVersionFilesystem = versionMatch[1];
|
|
423
|
+
}
|
|
424
|
+
} catch (e) {}
|
|
425
|
+
return cachedVersionFilesystem;
|
|
426
|
+
};
|
|
427
|
+
var versionFromReport = () => {
|
|
428
|
+
const report = getReport();
|
|
429
|
+
if (report.header && report.header.glibcVersionRuntime) {
|
|
430
|
+
return report.header.glibcVersionRuntime;
|
|
431
|
+
}
|
|
432
|
+
return null;
|
|
433
|
+
};
|
|
434
|
+
var versionSuffix = (s) => s.trim().split(/\s+/)[1];
|
|
435
|
+
var versionFromCommand = (out) => {
|
|
436
|
+
const [getconf, ldd1, ldd2] = out.split(/[\r\n]+/);
|
|
437
|
+
if (getconf && getconf.includes(GLIBC)) {
|
|
438
|
+
return versionSuffix(getconf);
|
|
439
|
+
}
|
|
440
|
+
if (ldd1 && ldd2 && ldd1.includes(MUSL)) {
|
|
441
|
+
return versionSuffix(ldd2);
|
|
442
|
+
}
|
|
443
|
+
return null;
|
|
444
|
+
};
|
|
445
|
+
var version = async () => {
|
|
446
|
+
let version2 = null;
|
|
447
|
+
if (isLinux()) {
|
|
448
|
+
version2 = await versionFromFilesystem();
|
|
449
|
+
if (!version2) {
|
|
450
|
+
version2 = versionFromReport();
|
|
451
|
+
}
|
|
452
|
+
if (!version2) {
|
|
453
|
+
const out = await safeCommand();
|
|
454
|
+
version2 = versionFromCommand(out);
|
|
455
|
+
}
|
|
456
|
+
}
|
|
457
|
+
return version2;
|
|
458
|
+
};
|
|
459
|
+
var versionSync = () => {
|
|
460
|
+
let version2 = null;
|
|
461
|
+
if (isLinux()) {
|
|
462
|
+
version2 = versionFromFilesystemSync();
|
|
463
|
+
if (!version2) {
|
|
464
|
+
version2 = versionFromReport();
|
|
465
|
+
}
|
|
466
|
+
if (!version2) {
|
|
467
|
+
const out = safeCommandSync();
|
|
468
|
+
version2 = versionFromCommand(out);
|
|
469
|
+
}
|
|
470
|
+
}
|
|
471
|
+
return version2;
|
|
472
|
+
};
|
|
473
|
+
module.exports = {
|
|
474
|
+
GLIBC,
|
|
475
|
+
MUSL,
|
|
476
|
+
family,
|
|
477
|
+
familySync,
|
|
478
|
+
isNonGlibcLinux,
|
|
479
|
+
isNonGlibcLinuxSync,
|
|
480
|
+
version,
|
|
481
|
+
versionSync
|
|
482
|
+
};
|
|
483
|
+
});
|
|
484
|
+
|
|
485
|
+
// node_modules/libsql/auth.js
|
|
486
|
+
var require_auth = __commonJS((exports, module) => {
|
|
487
|
+
var Authorization = {
|
|
488
|
+
ALLOW: 0,
|
|
489
|
+
DENY: 1
|
|
490
|
+
};
|
|
491
|
+
module.exports = Authorization;
|
|
492
|
+
});
|
|
493
|
+
|
|
494
|
+
// node_modules/libsql/sqlite-error.js
|
|
495
|
+
var require_sqlite_error = __commonJS((exports, module) => {
|
|
496
|
+
var descriptor = { value: "SqliteError", writable: true, enumerable: false, configurable: true };
|
|
497
|
+
function SqliteError(message, code, rawCode) {
|
|
498
|
+
if (new.target !== SqliteError) {
|
|
499
|
+
return new SqliteError(message, code);
|
|
500
|
+
}
|
|
501
|
+
if (typeof code !== "string") {
|
|
502
|
+
throw new TypeError("Expected second argument to be a string");
|
|
503
|
+
}
|
|
504
|
+
Error.call(this, message);
|
|
505
|
+
descriptor.value = "" + message;
|
|
506
|
+
Object.defineProperty(this, "message", descriptor);
|
|
507
|
+
Error.captureStackTrace(this, SqliteError);
|
|
508
|
+
this.code = code;
|
|
509
|
+
this.rawCode = rawCode;
|
|
510
|
+
}
|
|
511
|
+
Object.setPrototypeOf(SqliteError, Error);
|
|
512
|
+
Object.setPrototypeOf(SqliteError.prototype, Error.prototype);
|
|
513
|
+
Object.defineProperty(SqliteError.prototype, "name", descriptor);
|
|
514
|
+
module.exports = SqliteError;
|
|
515
|
+
});
|
|
516
|
+
|
|
517
|
+
// node_modules/libsql/index.js
|
|
518
|
+
var require_libsql = __commonJS((exports, module) => {
|
|
519
|
+
var __dirname = "/home/runner/work/meridian/meridian/node_modules/libsql";
|
|
520
|
+
var { load, currentTarget } = require_dist();
|
|
521
|
+
var { familySync, GLIBC, MUSL } = require_detect_libc();
|
|
522
|
+
function requireNative() {
|
|
523
|
+
if (process.env.LIBSQL_JS_DEV) {
|
|
524
|
+
return load(__dirname);
|
|
525
|
+
}
|
|
526
|
+
let target = currentTarget();
|
|
527
|
+
if (familySync() == GLIBC) {
|
|
528
|
+
switch (target) {
|
|
529
|
+
case "linux-x64-musl":
|
|
530
|
+
target = "linux-x64-gnu";
|
|
531
|
+
break;
|
|
532
|
+
case "linux-arm64-musl":
|
|
533
|
+
target = "linux-arm64-gnu";
|
|
534
|
+
break;
|
|
535
|
+
}
|
|
536
|
+
}
|
|
537
|
+
if (target === "linux-arm-gnueabihf" && familySync() == MUSL) {
|
|
538
|
+
target = "linux-arm-musleabihf";
|
|
539
|
+
}
|
|
540
|
+
return __require(`@libsql/${target}`);
|
|
541
|
+
}
|
|
542
|
+
var {
|
|
543
|
+
databaseOpen,
|
|
544
|
+
databaseOpenWithSync,
|
|
545
|
+
databaseInTransaction,
|
|
546
|
+
databaseInterrupt,
|
|
547
|
+
databaseClose,
|
|
548
|
+
databaseSyncSync,
|
|
549
|
+
databaseSyncUntilSync,
|
|
550
|
+
databaseExecSync,
|
|
551
|
+
databasePrepareSync,
|
|
552
|
+
databaseDefaultSafeIntegers,
|
|
553
|
+
databaseAuthorizer,
|
|
554
|
+
databaseLoadExtension,
|
|
555
|
+
databaseMaxWriteReplicationIndex,
|
|
556
|
+
statementRaw,
|
|
557
|
+
statementIsReader,
|
|
558
|
+
statementGet,
|
|
559
|
+
statementRun,
|
|
560
|
+
statementInterrupt,
|
|
561
|
+
statementRowsSync,
|
|
562
|
+
statementColumns,
|
|
563
|
+
statementSafeIntegers,
|
|
564
|
+
rowsNext
|
|
565
|
+
} = requireNative();
|
|
566
|
+
var Authorization = require_auth();
|
|
567
|
+
var SqliteError = require_sqlite_error();
|
|
568
|
+
function convertError(err) {
|
|
569
|
+
if (err.libsqlError) {
|
|
570
|
+
return new SqliteError(err.message, err.code, err.rawCode);
|
|
571
|
+
}
|
|
572
|
+
return err;
|
|
573
|
+
}
|
|
574
|
+
|
|
575
|
+
class Database {
|
|
576
|
+
constructor(path, opts) {
|
|
577
|
+
const encryptionCipher = opts?.encryptionCipher ?? "aes256cbc";
|
|
578
|
+
if (opts && opts.syncUrl) {
|
|
579
|
+
var authToken = "";
|
|
580
|
+
if (opts.syncAuth) {
|
|
581
|
+
console.warn("Warning: The `syncAuth` option is deprecated, please use `authToken` option instead.");
|
|
582
|
+
authToken = opts.syncAuth;
|
|
583
|
+
} else if (opts.authToken) {
|
|
584
|
+
authToken = opts.authToken;
|
|
585
|
+
}
|
|
586
|
+
const encryptionKey = opts?.encryptionKey ?? "";
|
|
587
|
+
const syncPeriod = opts?.syncPeriod ?? 0;
|
|
588
|
+
const readYourWrites = opts?.readYourWrites ?? true;
|
|
589
|
+
const offline = opts?.offline ?? false;
|
|
590
|
+
const remoteEncryptionKey = opts?.remoteEncryptionKey ?? "";
|
|
591
|
+
this.db = databaseOpenWithSync(path, opts.syncUrl, authToken, encryptionCipher, encryptionKey, syncPeriod, readYourWrites, offline, remoteEncryptionKey);
|
|
592
|
+
} else {
|
|
593
|
+
const authToken2 = opts?.authToken ?? "";
|
|
594
|
+
const encryptionKey = opts?.encryptionKey ?? "";
|
|
595
|
+
const timeout = opts?.timeout ?? 0;
|
|
596
|
+
const remoteEncryptionKey = opts?.remoteEncryptionKey ?? "";
|
|
597
|
+
this.db = databaseOpen(path, authToken2, encryptionCipher, encryptionKey, timeout, remoteEncryptionKey);
|
|
598
|
+
}
|
|
599
|
+
this.memory = path === ":memory:";
|
|
600
|
+
this.readonly = false;
|
|
601
|
+
this.name = "";
|
|
602
|
+
this.open = true;
|
|
603
|
+
const db = this.db;
|
|
604
|
+
Object.defineProperties(this, {
|
|
605
|
+
inTransaction: {
|
|
606
|
+
get() {
|
|
607
|
+
return databaseInTransaction(db);
|
|
608
|
+
}
|
|
609
|
+
}
|
|
610
|
+
});
|
|
611
|
+
}
|
|
612
|
+
sync() {
|
|
613
|
+
return databaseSyncSync.call(this.db);
|
|
614
|
+
}
|
|
615
|
+
syncUntil(replicationIndex) {
|
|
616
|
+
return databaseSyncUntilSync.call(this.db, replicationIndex);
|
|
617
|
+
}
|
|
618
|
+
prepare(sql) {
|
|
619
|
+
try {
|
|
620
|
+
const stmt = databasePrepareSync.call(this.db, sql);
|
|
621
|
+
return new Statement(stmt);
|
|
622
|
+
} catch (err) {
|
|
623
|
+
throw convertError(err);
|
|
624
|
+
}
|
|
625
|
+
}
|
|
626
|
+
transaction(fn) {
|
|
627
|
+
if (typeof fn !== "function")
|
|
628
|
+
throw new TypeError("Expected first argument to be a function");
|
|
629
|
+
const db = this;
|
|
630
|
+
const wrapTxn = (mode) => {
|
|
631
|
+
return (...bindParameters) => {
|
|
632
|
+
db.exec("BEGIN " + mode);
|
|
633
|
+
try {
|
|
634
|
+
const result = fn(...bindParameters);
|
|
635
|
+
db.exec("COMMIT");
|
|
636
|
+
return result;
|
|
637
|
+
} catch (err) {
|
|
638
|
+
db.exec("ROLLBACK");
|
|
639
|
+
throw err;
|
|
640
|
+
}
|
|
641
|
+
};
|
|
642
|
+
};
|
|
643
|
+
const properties = {
|
|
644
|
+
default: { value: wrapTxn("") },
|
|
645
|
+
deferred: { value: wrapTxn("DEFERRED") },
|
|
646
|
+
immediate: { value: wrapTxn("IMMEDIATE") },
|
|
647
|
+
exclusive: { value: wrapTxn("EXCLUSIVE") },
|
|
648
|
+
database: { value: this, enumerable: true }
|
|
649
|
+
};
|
|
650
|
+
Object.defineProperties(properties.default.value, properties);
|
|
651
|
+
Object.defineProperties(properties.deferred.value, properties);
|
|
652
|
+
Object.defineProperties(properties.immediate.value, properties);
|
|
653
|
+
Object.defineProperties(properties.exclusive.value, properties);
|
|
654
|
+
return properties.default.value;
|
|
655
|
+
}
|
|
656
|
+
pragma(source, options) {
|
|
657
|
+
if (options == null)
|
|
658
|
+
options = {};
|
|
659
|
+
if (typeof source !== "string")
|
|
660
|
+
throw new TypeError("Expected first argument to be a string");
|
|
661
|
+
if (typeof options !== "object")
|
|
662
|
+
throw new TypeError("Expected second argument to be an options object");
|
|
663
|
+
const simple = options["simple"];
|
|
664
|
+
const stmt = this.prepare(`PRAGMA ${source}`, this, true);
|
|
665
|
+
return simple ? stmt.pluck().get() : stmt.all();
|
|
666
|
+
}
|
|
667
|
+
backup(filename, options) {
|
|
668
|
+
throw new Error("not implemented");
|
|
669
|
+
}
|
|
670
|
+
serialize(options) {
|
|
671
|
+
throw new Error("not implemented");
|
|
672
|
+
}
|
|
673
|
+
function(name, options, fn) {
|
|
674
|
+
if (options == null)
|
|
675
|
+
options = {};
|
|
676
|
+
if (typeof options === "function") {
|
|
677
|
+
fn = options;
|
|
678
|
+
options = {};
|
|
679
|
+
}
|
|
680
|
+
if (typeof name !== "string")
|
|
681
|
+
throw new TypeError("Expected first argument to be a string");
|
|
682
|
+
if (typeof fn !== "function")
|
|
683
|
+
throw new TypeError("Expected last argument to be a function");
|
|
684
|
+
if (typeof options !== "object")
|
|
685
|
+
throw new TypeError("Expected second argument to be an options object");
|
|
686
|
+
if (!name)
|
|
687
|
+
throw new TypeError("User-defined function name cannot be an empty string");
|
|
688
|
+
throw new Error("not implemented");
|
|
689
|
+
}
|
|
690
|
+
aggregate(name, options) {
|
|
691
|
+
if (typeof name !== "string")
|
|
692
|
+
throw new TypeError("Expected first argument to be a string");
|
|
693
|
+
if (typeof options !== "object" || options === null)
|
|
694
|
+
throw new TypeError("Expected second argument to be an options object");
|
|
695
|
+
if (!name)
|
|
696
|
+
throw new TypeError("User-defined function name cannot be an empty string");
|
|
697
|
+
throw new Error("not implemented");
|
|
698
|
+
}
|
|
699
|
+
table(name, factory) {
|
|
700
|
+
if (typeof name !== "string")
|
|
701
|
+
throw new TypeError("Expected first argument to be a string");
|
|
702
|
+
if (!name)
|
|
703
|
+
throw new TypeError("Virtual table module name cannot be an empty string");
|
|
704
|
+
throw new Error("not implemented");
|
|
705
|
+
}
|
|
706
|
+
authorizer(rules) {
|
|
707
|
+
databaseAuthorizer.call(this.db, rules);
|
|
708
|
+
}
|
|
709
|
+
loadExtension(...args) {
|
|
710
|
+
databaseLoadExtension.call(this.db, ...args);
|
|
711
|
+
}
|
|
712
|
+
maxWriteReplicationIndex() {
|
|
713
|
+
return databaseMaxWriteReplicationIndex.call(this.db);
|
|
714
|
+
}
|
|
715
|
+
exec(sql) {
|
|
716
|
+
try {
|
|
717
|
+
databaseExecSync.call(this.db, sql);
|
|
718
|
+
} catch (err) {
|
|
719
|
+
throw convertError(err);
|
|
720
|
+
}
|
|
721
|
+
}
|
|
722
|
+
interrupt() {
|
|
723
|
+
databaseInterrupt.call(this.db);
|
|
724
|
+
}
|
|
725
|
+
close() {
|
|
726
|
+
databaseClose.call(this.db);
|
|
727
|
+
this.open = false;
|
|
728
|
+
}
|
|
729
|
+
defaultSafeIntegers(toggle) {
|
|
730
|
+
databaseDefaultSafeIntegers.call(this.db, toggle ?? true);
|
|
731
|
+
return this;
|
|
732
|
+
}
|
|
733
|
+
unsafeMode(...args) {
|
|
734
|
+
throw new Error("not implemented");
|
|
735
|
+
}
|
|
736
|
+
}
|
|
737
|
+
|
|
738
|
+
class Statement {
|
|
739
|
+
constructor(stmt) {
|
|
740
|
+
this.stmt = stmt;
|
|
741
|
+
this.pluckMode = false;
|
|
742
|
+
}
|
|
743
|
+
raw(raw2) {
|
|
744
|
+
statementRaw.call(this.stmt, raw2 ?? true);
|
|
745
|
+
return this;
|
|
746
|
+
}
|
|
747
|
+
pluck(pluckMode) {
|
|
748
|
+
this.pluckMode = pluckMode ?? true;
|
|
749
|
+
return this;
|
|
750
|
+
}
|
|
751
|
+
get reader() {
|
|
752
|
+
return statementIsReader.call(this.stmt);
|
|
753
|
+
}
|
|
754
|
+
run(...bindParameters) {
|
|
755
|
+
try {
|
|
756
|
+
if (bindParameters.length == 1 && typeof bindParameters[0] === "object") {
|
|
757
|
+
return statementRun.call(this.stmt, bindParameters[0]);
|
|
758
|
+
} else {
|
|
759
|
+
return statementRun.call(this.stmt, bindParameters.flat());
|
|
760
|
+
}
|
|
761
|
+
} catch (err) {
|
|
762
|
+
throw convertError(err);
|
|
763
|
+
}
|
|
764
|
+
}
|
|
765
|
+
get(...bindParameters) {
|
|
766
|
+
try {
|
|
767
|
+
if (bindParameters.length == 1 && typeof bindParameters[0] === "object") {
|
|
768
|
+
return statementGet.call(this.stmt, bindParameters[0]);
|
|
769
|
+
} else {
|
|
770
|
+
return statementGet.call(this.stmt, bindParameters.flat());
|
|
771
|
+
}
|
|
772
|
+
} catch (err) {
|
|
773
|
+
throw convertError(err);
|
|
774
|
+
}
|
|
775
|
+
}
|
|
776
|
+
iterate(...bindParameters) {
|
|
777
|
+
var rows = undefined;
|
|
778
|
+
if (bindParameters.length == 1 && typeof bindParameters[0] === "object") {
|
|
779
|
+
rows = statementRowsSync.call(this.stmt, bindParameters[0]);
|
|
780
|
+
} else {
|
|
781
|
+
rows = statementRowsSync.call(this.stmt, bindParameters.flat());
|
|
782
|
+
}
|
|
783
|
+
const iter = {
|
|
784
|
+
nextRows: Array(100),
|
|
785
|
+
nextRowIndex: 100,
|
|
786
|
+
next() {
|
|
787
|
+
try {
|
|
788
|
+
if (this.nextRowIndex === 100) {
|
|
789
|
+
rowsNext.call(rows, this.nextRows);
|
|
790
|
+
this.nextRowIndex = 0;
|
|
791
|
+
}
|
|
792
|
+
const row = this.nextRows[this.nextRowIndex];
|
|
793
|
+
this.nextRows[this.nextRowIndex] = undefined;
|
|
794
|
+
if (!row) {
|
|
795
|
+
return { done: true };
|
|
796
|
+
}
|
|
797
|
+
this.nextRowIndex++;
|
|
798
|
+
return { value: row, done: false };
|
|
799
|
+
} catch (err) {
|
|
800
|
+
throw convertError(err);
|
|
801
|
+
}
|
|
802
|
+
},
|
|
803
|
+
[Symbol.iterator]() {
|
|
804
|
+
return this;
|
|
805
|
+
}
|
|
806
|
+
};
|
|
807
|
+
return iter;
|
|
808
|
+
}
|
|
809
|
+
all(...bindParameters) {
|
|
810
|
+
try {
|
|
811
|
+
const result = [];
|
|
812
|
+
for (const row of this.iterate(...bindParameters)) {
|
|
813
|
+
if (this.pluckMode) {
|
|
814
|
+
result.push(row[Object.keys(row)[0]]);
|
|
815
|
+
} else {
|
|
816
|
+
result.push(row);
|
|
817
|
+
}
|
|
818
|
+
}
|
|
819
|
+
return result;
|
|
820
|
+
} catch (err) {
|
|
821
|
+
throw convertError(err);
|
|
822
|
+
}
|
|
823
|
+
}
|
|
824
|
+
interrupt() {
|
|
825
|
+
statementInterrupt.call(this.stmt);
|
|
826
|
+
}
|
|
827
|
+
columns() {
|
|
828
|
+
return statementColumns.call(this.stmt);
|
|
829
|
+
}
|
|
830
|
+
safeIntegers(toggle) {
|
|
831
|
+
statementSafeIntegers.call(this.stmt, toggle ?? true);
|
|
832
|
+
return this;
|
|
833
|
+
}
|
|
834
|
+
}
|
|
835
|
+
module.exports = Database;
|
|
836
|
+
module.exports.Authorization = Authorization;
|
|
837
|
+
module.exports.SqliteError = SqliteError;
|
|
838
|
+
});
|
|
839
|
+
|
|
840
|
+
// src/telemetry/sqlite.ts
|
|
841
|
+
var exports_sqlite = {};
|
|
842
|
+
__export(exports_sqlite, {
|
|
843
|
+
createSqliteStores: () => createSqliteStores
|
|
844
|
+
});
|
|
845
|
+
function openDatabase(dbPath) {
|
|
846
|
+
const db = new import_libsql.default(dbPath);
|
|
847
|
+
db.pragma("journal_mode = WAL");
|
|
848
|
+
db.pragma("synchronous = NORMAL");
|
|
849
|
+
db.exec(METRICS_SCHEMA);
|
|
850
|
+
db.exec(LOGS_SCHEMA);
|
|
851
|
+
return db;
|
|
852
|
+
}
|
|
853
|
+
|
|
854
|
+
class SqliteTelemetryStore {
|
|
855
|
+
db;
|
|
856
|
+
retentionMs;
|
|
857
|
+
insertCount = 0;
|
|
858
|
+
insertStmt;
|
|
859
|
+
countStmt;
|
|
860
|
+
constructor(db, retentionDays) {
|
|
861
|
+
this.db = db;
|
|
862
|
+
this.retentionMs = retentionDays * 24 * 60 * 60 * 1000;
|
|
863
|
+
this.insertStmt = db.prepare(`
|
|
864
|
+
INSERT INTO metrics (
|
|
865
|
+
request_id, timestamp, adapter, model, request_model, mode,
|
|
866
|
+
is_resume, is_passthrough, lineage_type,
|
|
867
|
+
has_deferred_tools, deferred_tool_count, tool_count, discovered_tools, session_discovered_count,
|
|
868
|
+
message_count, sdk_session_id,
|
|
869
|
+
status, queue_wait_ms, proxy_overhead_ms, ttfb_ms,
|
|
870
|
+
upstream_duration_ms, total_duration_ms, content_blocks, text_events, error,
|
|
871
|
+
input_tokens, output_tokens, cache_read_input_tokens,
|
|
872
|
+
cache_creation_input_tokens, cache_hit_rate
|
|
873
|
+
) VALUES (
|
|
874
|
+
@requestId, @timestamp, @adapter, @model, @requestModel, @mode,
|
|
875
|
+
@isResume, @isPassthrough, @lineageType,
|
|
876
|
+
@hasDeferredTools, @deferredToolCount, @toolCount, @discoveredTools, @sessionDiscoveredCount,
|
|
877
|
+
@messageCount, @sdkSessionId,
|
|
878
|
+
@status, @queueWaitMs, @proxyOverheadMs, @ttfbMs,
|
|
879
|
+
@upstreamDurationMs, @totalDurationMs, @contentBlocks, @textEvents, @error,
|
|
880
|
+
@inputTokens, @outputTokens, @cacheReadInputTokens,
|
|
881
|
+
@cacheCreationInputTokens, @cacheHitRate
|
|
882
|
+
)
|
|
883
|
+
`);
|
|
884
|
+
this.countStmt = db.prepare("SELECT COUNT(*) as cnt FROM metrics");
|
|
885
|
+
}
|
|
886
|
+
record(metric) {
|
|
887
|
+
try {
|
|
888
|
+
this.insertStmt.run({
|
|
889
|
+
requestId: metric.requestId,
|
|
890
|
+
timestamp: metric.timestamp,
|
|
891
|
+
adapter: metric.adapter ?? null,
|
|
892
|
+
model: metric.model,
|
|
893
|
+
requestModel: metric.requestModel ?? null,
|
|
894
|
+
mode: metric.mode,
|
|
895
|
+
isResume: metric.isResume ? 1 : 0,
|
|
896
|
+
isPassthrough: metric.isPassthrough ? 1 : 0,
|
|
897
|
+
lineageType: metric.lineageType ?? null,
|
|
898
|
+
hasDeferredTools: metric.hasDeferredTools ? 1 : metric.hasDeferredTools === false ? 0 : null,
|
|
899
|
+
deferredToolCount: metric.deferredToolCount ?? null,
|
|
900
|
+
toolCount: metric.toolCount ?? null,
|
|
901
|
+
discoveredTools: metric.discoveredTools ? JSON.stringify(metric.discoveredTools) : null,
|
|
902
|
+
sessionDiscoveredCount: metric.sessionDiscoveredCount ?? null,
|
|
903
|
+
messageCount: metric.messageCount ?? null,
|
|
904
|
+
sdkSessionId: metric.sdkSessionId ?? null,
|
|
905
|
+
status: metric.status,
|
|
906
|
+
queueWaitMs: metric.queueWaitMs,
|
|
907
|
+
proxyOverheadMs: metric.proxyOverheadMs,
|
|
908
|
+
ttfbMs: metric.ttfbMs ?? null,
|
|
909
|
+
upstreamDurationMs: metric.upstreamDurationMs,
|
|
910
|
+
totalDurationMs: metric.totalDurationMs,
|
|
911
|
+
contentBlocks: metric.contentBlocks,
|
|
912
|
+
textEvents: metric.textEvents,
|
|
913
|
+
error: metric.error ?? null,
|
|
914
|
+
inputTokens: metric.inputTokens ?? null,
|
|
915
|
+
outputTokens: metric.outputTokens ?? null,
|
|
916
|
+
cacheReadInputTokens: metric.cacheReadInputTokens ?? null,
|
|
917
|
+
cacheCreationInputTokens: metric.cacheCreationInputTokens ?? null,
|
|
918
|
+
cacheHitRate: metric.cacheHitRate ?? null
|
|
919
|
+
});
|
|
920
|
+
} catch (err) {
|
|
921
|
+
console.error("[telemetry] SQLite write failed, skipping:", err);
|
|
922
|
+
return;
|
|
923
|
+
}
|
|
924
|
+
if (++this.insertCount % CLEANUP_INTERVAL === 0) {
|
|
925
|
+
this.cleanup();
|
|
926
|
+
}
|
|
927
|
+
}
|
|
928
|
+
get size() {
|
|
929
|
+
try {
|
|
930
|
+
return this.countStmt.get().cnt;
|
|
931
|
+
} catch {
|
|
932
|
+
return 0;
|
|
933
|
+
}
|
|
934
|
+
}
|
|
935
|
+
getRecent(options = {}) {
|
|
936
|
+
const { limit = 50, since, model } = options;
|
|
937
|
+
const conditions = [];
|
|
938
|
+
const params = { limit };
|
|
939
|
+
if (since !== undefined) {
|
|
940
|
+
conditions.push("timestamp >= @since");
|
|
941
|
+
params.since = since;
|
|
942
|
+
}
|
|
943
|
+
if (model !== undefined) {
|
|
944
|
+
conditions.push("model = @model");
|
|
945
|
+
params.model = model;
|
|
946
|
+
}
|
|
947
|
+
const where = conditions.length > 0 ? `WHERE ${conditions.join(" AND ")}` : "";
|
|
948
|
+
const sql = `SELECT * FROM metrics ${where} ORDER BY timestamp DESC, id DESC LIMIT @limit`;
|
|
949
|
+
try {
|
|
950
|
+
const rows = this.db.prepare(sql).all(params);
|
|
951
|
+
return rows.map(rowToMetric);
|
|
952
|
+
} catch {
|
|
953
|
+
return [];
|
|
954
|
+
}
|
|
955
|
+
}
|
|
956
|
+
getLastForSession(sdkSessionId) {
|
|
957
|
+
try {
|
|
958
|
+
const row = this.db.prepare(`SELECT * FROM metrics WHERE sdk_session_id = ? AND error IS NULL ORDER BY timestamp DESC, id DESC LIMIT 1`).get(sdkSessionId);
|
|
959
|
+
return row ? rowToMetric(row) : undefined;
|
|
960
|
+
} catch {
|
|
961
|
+
return;
|
|
962
|
+
}
|
|
963
|
+
}
|
|
964
|
+
summarize(windowMs = 60 * 60 * 1000) {
|
|
965
|
+
const since = Date.now() - windowMs;
|
|
966
|
+
const metrics = this.getRecent({ limit: 1e5, since });
|
|
967
|
+
return computeSummary(metrics, windowMs);
|
|
968
|
+
}
|
|
969
|
+
clear() {
|
|
970
|
+
try {
|
|
971
|
+
this.db.exec("DELETE FROM metrics");
|
|
972
|
+
} catch {}
|
|
973
|
+
}
|
|
974
|
+
cleanup() {
|
|
975
|
+
try {
|
|
976
|
+
const cutoff = Date.now() - this.retentionMs;
|
|
977
|
+
this.db.prepare("DELETE FROM metrics WHERE timestamp < ?").run(cutoff);
|
|
978
|
+
this.db.prepare("DELETE FROM diagnostic_logs WHERE timestamp < ?").run(cutoff);
|
|
979
|
+
this.db.pragma("wal_checkpoint(TRUNCATE)");
|
|
980
|
+
} catch (err) {
|
|
981
|
+
console.error("[telemetry] SQLite cleanup failed:", err);
|
|
982
|
+
}
|
|
983
|
+
}
|
|
984
|
+
}
|
|
985
|
+
|
|
986
|
+
class SqliteDiagnosticLogStore {
|
|
987
|
+
db;
|
|
988
|
+
insertStmt;
|
|
989
|
+
constructor(db) {
|
|
990
|
+
this.db = db;
|
|
991
|
+
this.insertStmt = db.prepare(`
|
|
992
|
+
INSERT INTO diagnostic_logs (timestamp, level, category, request_id, message)
|
|
993
|
+
VALUES (@timestamp, @level, @category, @requestId, @message)
|
|
994
|
+
`);
|
|
995
|
+
}
|
|
996
|
+
log(entry) {
|
|
997
|
+
try {
|
|
998
|
+
this.insertStmt.run({
|
|
999
|
+
timestamp: Date.now(),
|
|
1000
|
+
level: entry.level,
|
|
1001
|
+
category: entry.category,
|
|
1002
|
+
requestId: entry.requestId ?? null,
|
|
1003
|
+
message: entry.message
|
|
1004
|
+
});
|
|
1005
|
+
} catch (err) {
|
|
1006
|
+
console.error("[telemetry] SQLite log write failed:", err);
|
|
1007
|
+
}
|
|
1008
|
+
}
|
|
1009
|
+
session(message, requestId) {
|
|
1010
|
+
this.log({ level: "info", category: "session", message, requestId });
|
|
1011
|
+
}
|
|
1012
|
+
lineage(message, requestId) {
|
|
1013
|
+
this.log({ level: "warn", category: "lineage", message, requestId });
|
|
1014
|
+
}
|
|
1015
|
+
error(message, requestId) {
|
|
1016
|
+
this.log({ level: "error", category: "error", message, requestId });
|
|
1017
|
+
}
|
|
1018
|
+
getRecent(options = {}) {
|
|
1019
|
+
const { limit = 100, since, category } = options;
|
|
1020
|
+
const conditions = [];
|
|
1021
|
+
const params = { limit };
|
|
1022
|
+
if (since !== undefined) {
|
|
1023
|
+
conditions.push("timestamp >= @since");
|
|
1024
|
+
params.since = since;
|
|
1025
|
+
}
|
|
1026
|
+
if (category !== undefined) {
|
|
1027
|
+
conditions.push("category = @category");
|
|
1028
|
+
params.category = category;
|
|
1029
|
+
}
|
|
1030
|
+
const where = conditions.length > 0 ? `WHERE ${conditions.join(" AND ")}` : "";
|
|
1031
|
+
const sql = `SELECT * FROM diagnostic_logs ${where} ORDER BY timestamp DESC, id DESC LIMIT @limit`;
|
|
1032
|
+
try {
|
|
1033
|
+
const rows = this.db.prepare(sql).all(params);
|
|
1034
|
+
return rows.map((r) => ({
|
|
1035
|
+
timestamp: r.timestamp,
|
|
1036
|
+
level: r.level,
|
|
1037
|
+
category: r.category,
|
|
1038
|
+
requestId: r.request_id ?? undefined,
|
|
1039
|
+
message: r.message
|
|
1040
|
+
}));
|
|
1041
|
+
} catch {
|
|
1042
|
+
return [];
|
|
1043
|
+
}
|
|
1044
|
+
}
|
|
1045
|
+
clear() {
|
|
1046
|
+
try {
|
|
1047
|
+
this.db.exec("DELETE FROM diagnostic_logs");
|
|
1048
|
+
} catch {}
|
|
1049
|
+
}
|
|
1050
|
+
}
|
|
1051
|
+
function rowToMetric(r) {
|
|
1052
|
+
return {
|
|
1053
|
+
requestId: r.request_id,
|
|
1054
|
+
timestamp: r.timestamp,
|
|
1055
|
+
adapter: r.adapter ?? undefined,
|
|
1056
|
+
model: r.model,
|
|
1057
|
+
requestModel: r.request_model ?? undefined,
|
|
1058
|
+
mode: r.mode,
|
|
1059
|
+
isResume: r.is_resume === 1,
|
|
1060
|
+
isPassthrough: r.is_passthrough === 1,
|
|
1061
|
+
lineageType: r.lineage_type ?? undefined,
|
|
1062
|
+
hasDeferredTools: r.has_deferred_tools === 1 ? true : r.has_deferred_tools === 0 ? false : undefined,
|
|
1063
|
+
deferredToolCount: r.deferred_tool_count ?? undefined,
|
|
1064
|
+
toolCount: r.tool_count ?? undefined,
|
|
1065
|
+
discoveredTools: r.discovered_tools ? JSON.parse(r.discovered_tools) : undefined,
|
|
1066
|
+
sessionDiscoveredCount: r.session_discovered_count ?? undefined,
|
|
1067
|
+
messageCount: r.message_count ?? undefined,
|
|
1068
|
+
sdkSessionId: r.sdk_session_id ?? undefined,
|
|
1069
|
+
status: r.status,
|
|
1070
|
+
queueWaitMs: r.queue_wait_ms,
|
|
1071
|
+
proxyOverheadMs: r.proxy_overhead_ms,
|
|
1072
|
+
ttfbMs: r.ttfb_ms ?? null,
|
|
1073
|
+
upstreamDurationMs: r.upstream_duration_ms,
|
|
1074
|
+
totalDurationMs: r.total_duration_ms,
|
|
1075
|
+
contentBlocks: r.content_blocks,
|
|
1076
|
+
textEvents: r.text_events,
|
|
1077
|
+
error: r.error ?? null,
|
|
1078
|
+
inputTokens: r.input_tokens ?? undefined,
|
|
1079
|
+
outputTokens: r.output_tokens ?? undefined,
|
|
1080
|
+
cacheReadInputTokens: r.cache_read_input_tokens ?? undefined,
|
|
1081
|
+
cacheCreationInputTokens: r.cache_creation_input_tokens ?? undefined,
|
|
1082
|
+
cacheHitRate: r.cache_hit_rate ?? undefined
|
|
1083
|
+
};
|
|
1084
|
+
}
|
|
1085
|
+
function createSqliteStores(dbPath, retentionDays) {
|
|
1086
|
+
const db = openDatabase(dbPath);
|
|
1087
|
+
return {
|
|
1088
|
+
telemetry: new SqliteTelemetryStore(db, retentionDays),
|
|
1089
|
+
diagnostics: new SqliteDiagnosticLogStore(db),
|
|
1090
|
+
close: () => {
|
|
1091
|
+
try {
|
|
1092
|
+
db.close();
|
|
1093
|
+
} catch {}
|
|
1094
|
+
}
|
|
1095
|
+
};
|
|
1096
|
+
}
|
|
1097
|
+
var import_libsql, METRICS_SCHEMA = `
|
|
1098
|
+
CREATE TABLE IF NOT EXISTS metrics (
|
|
1099
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
1100
|
+
request_id TEXT NOT NULL,
|
|
1101
|
+
timestamp INTEGER NOT NULL,
|
|
1102
|
+
adapter TEXT,
|
|
1103
|
+
model TEXT NOT NULL,
|
|
1104
|
+
request_model TEXT,
|
|
1105
|
+
mode TEXT NOT NULL,
|
|
1106
|
+
is_resume INTEGER NOT NULL,
|
|
1107
|
+
is_passthrough INTEGER NOT NULL,
|
|
1108
|
+
lineage_type TEXT,
|
|
1109
|
+
has_deferred_tools INTEGER,
|
|
1110
|
+
deferred_tool_count INTEGER,
|
|
1111
|
+
tool_count INTEGER,
|
|
1112
|
+
discovered_tools TEXT,
|
|
1113
|
+
session_discovered_count INTEGER,
|
|
1114
|
+
message_count INTEGER,
|
|
1115
|
+
sdk_session_id TEXT,
|
|
1116
|
+
status INTEGER NOT NULL,
|
|
1117
|
+
queue_wait_ms REAL NOT NULL,
|
|
1118
|
+
proxy_overhead_ms REAL NOT NULL,
|
|
1119
|
+
ttfb_ms REAL,
|
|
1120
|
+
upstream_duration_ms REAL NOT NULL,
|
|
1121
|
+
total_duration_ms REAL NOT NULL,
|
|
1122
|
+
content_blocks INTEGER NOT NULL,
|
|
1123
|
+
text_events INTEGER NOT NULL,
|
|
1124
|
+
error TEXT,
|
|
1125
|
+
input_tokens INTEGER,
|
|
1126
|
+
output_tokens INTEGER,
|
|
1127
|
+
cache_read_input_tokens INTEGER,
|
|
1128
|
+
cache_creation_input_tokens INTEGER,
|
|
1129
|
+
cache_hit_rate REAL
|
|
1130
|
+
);
|
|
1131
|
+
CREATE INDEX IF NOT EXISTS idx_metrics_ts ON metrics(timestamp);
|
|
1132
|
+
CREATE INDEX IF NOT EXISTS idx_metrics_model ON metrics(model);
|
|
1133
|
+
CREATE INDEX IF NOT EXISTS idx_metrics_session_success ON metrics(sdk_session_id, timestamp DESC, id DESC);
|
|
1134
|
+
`, LOGS_SCHEMA = `
|
|
1135
|
+
CREATE TABLE IF NOT EXISTS diagnostic_logs (
|
|
1136
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
1137
|
+
timestamp INTEGER NOT NULL,
|
|
1138
|
+
level TEXT NOT NULL,
|
|
1139
|
+
category TEXT NOT NULL,
|
|
1140
|
+
request_id TEXT,
|
|
1141
|
+
message TEXT NOT NULL
|
|
1142
|
+
);
|
|
1143
|
+
CREATE INDEX IF NOT EXISTS idx_logs_ts ON diagnostic_logs(timestamp);
|
|
1144
|
+
CREATE INDEX IF NOT EXISTS idx_logs_cat ON diagnostic_logs(category);
|
|
1145
|
+
`, CLEANUP_INTERVAL = 1000;
|
|
1146
|
+
var init_sqlite = __esm(() => {
|
|
1147
|
+
init_percentiles();
|
|
1148
|
+
import_libsql = __toESM(require_libsql(), 1);
|
|
1149
|
+
});
|
|
26
1150
|
|
|
27
1151
|
// node_modules/hono/dist/compose.js
|
|
28
1152
|
var compose = (middleware, onError, onNotFound) => {
|
|
@@ -2187,7 +3311,8 @@ var DEFAULT_PROXY_CONFIG = {
|
|
|
2187
3311
|
idleTimeoutSeconds: 120,
|
|
2188
3312
|
silent: false,
|
|
2189
3313
|
profiles: undefined,
|
|
2190
|
-
defaultProfile: undefined
|
|
3314
|
+
defaultProfile: undefined,
|
|
3315
|
+
version: undefined
|
|
2191
3316
|
};
|
|
2192
3317
|
|
|
2193
3318
|
// src/env.ts
|
|
@@ -2198,6 +3323,13 @@ function envBool(suffix) {
|
|
|
2198
3323
|
const val = env(suffix);
|
|
2199
3324
|
return val === "1" || val === "true" || val === "yes";
|
|
2200
3325
|
}
|
|
3326
|
+
function envInt(suffix, defaultValue) {
|
|
3327
|
+
const val = env(suffix);
|
|
3328
|
+
if (!val)
|
|
3329
|
+
return defaultValue;
|
|
3330
|
+
const parsed = parseInt(val, 10);
|
|
3331
|
+
return Number.isFinite(parsed) ? parsed : defaultValue;
|
|
3332
|
+
}
|
|
2201
3333
|
|
|
2202
3334
|
// src/proxy/server.ts
|
|
2203
3335
|
import { exec as execCallback2 } from "child_process";
|
|
@@ -6270,7 +7402,12 @@ function stripMcpPrefix(toolName) {
|
|
|
6270
7402
|
return toolName;
|
|
6271
7403
|
}
|
|
6272
7404
|
|
|
7405
|
+
// src/telemetry/index.ts
|
|
7406
|
+
import { join } from "node:path";
|
|
7407
|
+
import { homedir } from "node:os";
|
|
7408
|
+
|
|
6273
7409
|
// src/telemetry/store.ts
|
|
7410
|
+
init_percentiles();
|
|
6274
7411
|
var DEFAULT_CAPACITY = 1000;
|
|
6275
7412
|
function getCapacity() {
|
|
6276
7413
|
const raw2 = process.env.MERIDIAN_TELEMETRY_SIZE ?? process.env.CLAUDE_PROXY_TELEMETRY_SIZE;
|
|
@@ -6282,7 +7419,7 @@ function getCapacity() {
|
|
|
6282
7419
|
return parsed;
|
|
6283
7420
|
}
|
|
6284
7421
|
|
|
6285
|
-
class
|
|
7422
|
+
class MemoryTelemetryStore {
|
|
6286
7423
|
buffer;
|
|
6287
7424
|
head = 0;
|
|
6288
7425
|
count = 0;
|
|
@@ -6329,94 +7466,7 @@ class TelemetryStore {
|
|
|
6329
7466
|
summarize(windowMs = 60 * 60 * 1000) {
|
|
6330
7467
|
const since = Date.now() - windowMs;
|
|
6331
7468
|
const metrics = this.getRecent({ limit: this.capacity, since });
|
|
6332
|
-
|
|
6333
|
-
const emptyPhase = { p50: 0, p95: 0, p99: 0, min: 0, max: 0, avg: 0 };
|
|
6334
|
-
return {
|
|
6335
|
-
windowMs,
|
|
6336
|
-
totalRequests: 0,
|
|
6337
|
-
errorCount: 0,
|
|
6338
|
-
requestsPerMinute: 0,
|
|
6339
|
-
queueWait: emptyPhase,
|
|
6340
|
-
proxyOverhead: emptyPhase,
|
|
6341
|
-
ttfb: emptyPhase,
|
|
6342
|
-
upstreamDuration: emptyPhase,
|
|
6343
|
-
totalDuration: emptyPhase,
|
|
6344
|
-
byModel: {},
|
|
6345
|
-
byMode: {},
|
|
6346
|
-
tokenUsage: {
|
|
6347
|
-
totalInputTokens: 0,
|
|
6348
|
-
totalOutputTokens: 0,
|
|
6349
|
-
totalCacheReadTokens: 0,
|
|
6350
|
-
totalCacheCreationTokens: 0,
|
|
6351
|
-
avgCacheHitRate: 0,
|
|
6352
|
-
cacheMissOnResumeCount: 0
|
|
6353
|
-
}
|
|
6354
|
-
};
|
|
6355
|
-
}
|
|
6356
|
-
const errorCount = metrics.filter((m) => m.error !== null).length;
|
|
6357
|
-
const oldest = metrics[metrics.length - 1].timestamp;
|
|
6358
|
-
const newest = metrics[0].timestamp;
|
|
6359
|
-
const spanMs = Math.max(newest - oldest, 1);
|
|
6360
|
-
const requestsPerMinute = metrics.length / spanMs * 60000;
|
|
6361
|
-
const queueWaits = metrics.map((m) => m.queueWaitMs);
|
|
6362
|
-
const overheads = metrics.map((m) => m.proxyOverheadMs);
|
|
6363
|
-
const ttfbs = metrics.filter((m) => m.ttfbMs !== null).map((m) => m.ttfbMs);
|
|
6364
|
-
const upstreams = metrics.map((m) => m.upstreamDurationMs);
|
|
6365
|
-
const totals = metrics.map((m) => m.totalDurationMs);
|
|
6366
|
-
const byModel = {};
|
|
6367
|
-
for (const m of metrics) {
|
|
6368
|
-
const modelKey = m.requestModel || m.model;
|
|
6369
|
-
const entry = byModel[modelKey] ??= { count: 0, totalMs: 0 };
|
|
6370
|
-
entry.count++;
|
|
6371
|
-
entry.totalMs += m.totalDurationMs;
|
|
6372
|
-
}
|
|
6373
|
-
const byMode = {};
|
|
6374
|
-
for (const m of metrics) {
|
|
6375
|
-
const entry = byMode[m.mode] ??= { count: 0, totalMs: 0 };
|
|
6376
|
-
entry.count++;
|
|
6377
|
-
entry.totalMs += m.totalDurationMs;
|
|
6378
|
-
}
|
|
6379
|
-
let totalInputTokens = 0;
|
|
6380
|
-
let totalOutputTokens = 0;
|
|
6381
|
-
let totalCacheReadTokens = 0;
|
|
6382
|
-
let totalCacheCreationTokens = 0;
|
|
6383
|
-
let cacheHitRateSum = 0;
|
|
6384
|
-
let cacheHitRateCount = 0;
|
|
6385
|
-
let cacheMissOnResumeCount = 0;
|
|
6386
|
-
for (const m of metrics) {
|
|
6387
|
-
totalInputTokens += m.inputTokens ?? 0;
|
|
6388
|
-
totalOutputTokens += m.outputTokens ?? 0;
|
|
6389
|
-
totalCacheReadTokens += m.cacheReadInputTokens ?? 0;
|
|
6390
|
-
totalCacheCreationTokens += m.cacheCreationInputTokens ?? 0;
|
|
6391
|
-
if (m.cacheHitRate !== undefined) {
|
|
6392
|
-
cacheHitRateSum += m.cacheHitRate;
|
|
6393
|
-
cacheHitRateCount++;
|
|
6394
|
-
}
|
|
6395
|
-
if (m.isResume && m.cacheHitRate !== undefined && m.cacheHitRate === 0) {
|
|
6396
|
-
cacheMissOnResumeCount++;
|
|
6397
|
-
}
|
|
6398
|
-
}
|
|
6399
|
-
return {
|
|
6400
|
-
windowMs,
|
|
6401
|
-
totalRequests: metrics.length,
|
|
6402
|
-
errorCount,
|
|
6403
|
-
requestsPerMinute: Math.round(requestsPerMinute * 100) / 100,
|
|
6404
|
-
queueWait: computePercentiles(queueWaits),
|
|
6405
|
-
proxyOverhead: computePercentiles(overheads),
|
|
6406
|
-
ttfb: ttfbs.length > 0 ? computePercentiles(ttfbs) : { p50: 0, p95: 0, p99: 0, min: 0, max: 0, avg: 0 },
|
|
6407
|
-
upstreamDuration: computePercentiles(upstreams),
|
|
6408
|
-
totalDuration: computePercentiles(totals),
|
|
6409
|
-
byModel: Object.fromEntries(Object.entries(byModel).map(([k, v]) => [k, { count: v.count, avgTotalMs: Math.round(v.totalMs / v.count) }])),
|
|
6410
|
-
byMode: Object.fromEntries(Object.entries(byMode).map(([k, v]) => [k, { count: v.count, avgTotalMs: Math.round(v.totalMs / v.count) }])),
|
|
6411
|
-
tokenUsage: {
|
|
6412
|
-
totalInputTokens,
|
|
6413
|
-
totalOutputTokens,
|
|
6414
|
-
totalCacheReadTokens,
|
|
6415
|
-
totalCacheCreationTokens,
|
|
6416
|
-
avgCacheHitRate: cacheHitRateCount > 0 ? Math.round(cacheHitRateSum / cacheHitRateCount * 100) / 100 : 0,
|
|
6417
|
-
cacheMissOnResumeCount
|
|
6418
|
-
}
|
|
6419
|
-
};
|
|
7469
|
+
return computeSummary(metrics, windowMs);
|
|
6420
7470
|
}
|
|
6421
7471
|
clear() {
|
|
6422
7472
|
this.buffer = new Array(this.capacity).fill(null);
|
|
@@ -6424,25 +7474,12 @@ class TelemetryStore {
|
|
|
6424
7474
|
this.count = 0;
|
|
6425
7475
|
}
|
|
6426
7476
|
}
|
|
6427
|
-
|
|
6428
|
-
|
|
6429
|
-
return { p50: 0, p95: 0, p99: 0, min: 0, max: 0, avg: 0 };
|
|
6430
|
-
const sorted = [...values].sort((a, b) => a - b);
|
|
6431
|
-
const sum = sorted.reduce((a, b) => a + b, 0);
|
|
6432
|
-
return {
|
|
6433
|
-
p50: sorted[Math.floor(sorted.length * 0.5)],
|
|
6434
|
-
p95: sorted[Math.floor(sorted.length * 0.95)],
|
|
6435
|
-
p99: sorted[Math.floor(sorted.length * 0.99)],
|
|
6436
|
-
min: sorted[0],
|
|
6437
|
-
max: sorted[sorted.length - 1],
|
|
6438
|
-
avg: Math.round(sum / sorted.length)
|
|
6439
|
-
};
|
|
6440
|
-
}
|
|
6441
|
-
var telemetryStore = new TelemetryStore;
|
|
7477
|
+
var telemetryStore = new MemoryTelemetryStore;
|
|
7478
|
+
|
|
6442
7479
|
// src/telemetry/logStore.ts
|
|
6443
7480
|
var DEFAULT_CAPACITY2 = 500;
|
|
6444
7481
|
|
|
6445
|
-
class
|
|
7482
|
+
class MemoryDiagnosticLogStore {
|
|
6446
7483
|
buffer;
|
|
6447
7484
|
head = 0;
|
|
6448
7485
|
count = 0;
|
|
@@ -6488,7 +7525,7 @@ class DiagnosticLogStore {
|
|
|
6488
7525
|
this.count = 0;
|
|
6489
7526
|
}
|
|
6490
7527
|
}
|
|
6491
|
-
var diagnosticLog = new
|
|
7528
|
+
var diagnosticLog = new MemoryDiagnosticLogStore;
|
|
6492
7529
|
// src/telemetry/routes.ts
|
|
6493
7530
|
import { existsSync, readFileSync } from "node:fs";
|
|
6494
7531
|
import { resolve, dirname } from "node:path";
|
|
@@ -6866,7 +7903,7 @@ function createTelemetryRoutes() {
|
|
|
6866
7903
|
const limit = Number.parseInt(c.req.query("limit") || "50", 10);
|
|
6867
7904
|
const since = c.req.query("since") ? Number.parseInt(c.req.query("since"), 10) : undefined;
|
|
6868
7905
|
const model = c.req.query("model") || undefined;
|
|
6869
|
-
const requests =
|
|
7906
|
+
const requests = telemetryStore2.getRecent({
|
|
6870
7907
|
limit: Math.min(limit, 500),
|
|
6871
7908
|
since,
|
|
6872
7909
|
model
|
|
@@ -6875,14 +7912,14 @@ function createTelemetryRoutes() {
|
|
|
6875
7912
|
});
|
|
6876
7913
|
routes.get("/summary", (c) => {
|
|
6877
7914
|
const windowMs = Number.parseInt(c.req.query("window") || "3600000", 10);
|
|
6878
|
-
const summary =
|
|
7915
|
+
const summary = telemetryStore2.summarize(windowMs);
|
|
6879
7916
|
return c.json(summary);
|
|
6880
7917
|
});
|
|
6881
7918
|
routes.get("/logs", (c) => {
|
|
6882
7919
|
const limit = Number.parseInt(c.req.query("limit") || "100", 10);
|
|
6883
7920
|
const since = c.req.query("since") ? Number.parseInt(c.req.query("since"), 10) : undefined;
|
|
6884
7921
|
const category = c.req.query("category") || undefined;
|
|
6885
|
-
const logs =
|
|
7922
|
+
const logs = diagnosticLog2.getRecent({
|
|
6886
7923
|
limit: Math.min(limit, 500),
|
|
6887
7924
|
since,
|
|
6888
7925
|
category
|
|
@@ -7014,6 +8051,95 @@ refresh();setInterval(refresh,10000);
|
|
|
7014
8051
|
</script>
|
|
7015
8052
|
</body>
|
|
7016
8053
|
</html>`;
|
|
8054
|
+
|
|
8055
|
+
// src/telemetry/index.ts
|
|
8056
|
+
init_percentiles();
|
|
8057
|
+
|
|
8058
|
+
// src/telemetry/prometheus.ts
|
|
8059
|
+
var DURATION_BUCKETS = [10, 25, 50, 100, 250, 500, 1000, 2500, 5000, 1e4, 30000];
|
|
8060
|
+
var PHASES = [
|
|
8061
|
+
{ key: "queue_wait", extract: (m) => m.queueWaitMs },
|
|
8062
|
+
{ key: "proxy_overhead", extract: (m) => m.proxyOverheadMs },
|
|
8063
|
+
{ key: "ttfb", extract: (m) => m.ttfbMs },
|
|
8064
|
+
{ key: "upstream", extract: (m) => m.upstreamDurationMs },
|
|
8065
|
+
{ key: "total", extract: (m) => m.totalDurationMs }
|
|
8066
|
+
];
|
|
8067
|
+
function escapeLabelValue(v) {
|
|
8068
|
+
return v.replace(/\\/g, "\\\\").replace(/"/g, "\\\"").replace(/\n/g, "\\n");
|
|
8069
|
+
}
|
|
8070
|
+
function formatLabels(labels) {
|
|
8071
|
+
return Object.entries(labels).map(([k, v]) => `${k}="${escapeLabelValue(v)}"`).join(",");
|
|
8072
|
+
}
|
|
8073
|
+
function renderPrometheusMetrics(store) {
|
|
8074
|
+
const metrics = store.getRecent({ limit: 1e4 });
|
|
8075
|
+
const lines = [];
|
|
8076
|
+
lines.push("# HELP meridian_requests_total Total proxy requests");
|
|
8077
|
+
lines.push("# TYPE meridian_requests_total counter");
|
|
8078
|
+
const counters = new Map;
|
|
8079
|
+
for (const m of metrics) {
|
|
8080
|
+
const key = `${m.model}\x00${m.mode}\x00${m.status}`;
|
|
8081
|
+
counters.set(key, (counters.get(key) ?? 0) + 1);
|
|
8082
|
+
}
|
|
8083
|
+
for (const [key, count] of counters) {
|
|
8084
|
+
const [model, mode, status] = key.split("\x00");
|
|
8085
|
+
lines.push(`meridian_requests_total{${formatLabels({ model, mode, status })}} ${count}`);
|
|
8086
|
+
}
|
|
8087
|
+
lines.push("");
|
|
8088
|
+
lines.push("# HELP meridian_request_duration_ms Request duration by phase in milliseconds");
|
|
8089
|
+
lines.push("# TYPE meridian_request_duration_ms histogram");
|
|
8090
|
+
for (const phase of PHASES) {
|
|
8091
|
+
const values = [];
|
|
8092
|
+
for (const m of metrics) {
|
|
8093
|
+
const v = phase.extract(m);
|
|
8094
|
+
if (v !== null)
|
|
8095
|
+
values.push(v);
|
|
8096
|
+
}
|
|
8097
|
+
const phaseLabel = `phase="${escapeLabelValue(phase.key)}"`;
|
|
8098
|
+
for (const le of DURATION_BUCKETS) {
|
|
8099
|
+
const count = values.filter((v) => v <= le).length;
|
|
8100
|
+
lines.push(`meridian_request_duration_ms_bucket{${phaseLabel},le="${le}"} ${count}`);
|
|
8101
|
+
}
|
|
8102
|
+
lines.push(`meridian_request_duration_ms_bucket{${phaseLabel},le="+Inf"} ${values.length}`);
|
|
8103
|
+
const sum = values.reduce((a, b) => a + b, 0);
|
|
8104
|
+
lines.push(`meridian_request_duration_ms_sum{${phaseLabel}} ${sum}`);
|
|
8105
|
+
lines.push(`meridian_request_duration_ms_count{${phaseLabel}} ${values.length}`);
|
|
8106
|
+
}
|
|
8107
|
+
lines.push("");
|
|
8108
|
+
return lines.join(`
|
|
8109
|
+
`);
|
|
8110
|
+
}
|
|
8111
|
+
|
|
8112
|
+
// src/telemetry/index.ts
|
|
8113
|
+
init_sqlite();
|
|
8114
|
+
function getDefaultDbPath() {
|
|
8115
|
+
return join(homedir(), ".config", "meridian", "telemetry.db");
|
|
8116
|
+
}
|
|
8117
|
+
function createStores() {
|
|
8118
|
+
if (!envBool("TELEMETRY_PERSIST")) {
|
|
8119
|
+
return {
|
|
8120
|
+
telemetry: new MemoryTelemetryStore,
|
|
8121
|
+
diagnostics: new MemoryDiagnosticLogStore
|
|
8122
|
+
};
|
|
8123
|
+
}
|
|
8124
|
+
try {
|
|
8125
|
+
const { createSqliteStores: createSqliteStores2 } = (init_sqlite(), __toCommonJS(exports_sqlite));
|
|
8126
|
+
const dbPath = env("TELEMETRY_DB") ?? getDefaultDbPath();
|
|
8127
|
+
const retention = envInt("TELEMETRY_RETENTION_DAYS", 7);
|
|
8128
|
+
const stores = createSqliteStores2(dbPath, retention);
|
|
8129
|
+
console.error(`[telemetry] SQLite persistence enabled: ${dbPath} (${retention}d retention)`);
|
|
8130
|
+
return { telemetry: stores.telemetry, diagnostics: stores.diagnostics };
|
|
8131
|
+
} catch {
|
|
8132
|
+
console.warn("[telemetry] MERIDIAN_TELEMETRY_PERSIST is set but libsql is not installed. Run: npm install libsql");
|
|
8133
|
+
return {
|
|
8134
|
+
telemetry: new MemoryTelemetryStore,
|
|
8135
|
+
diagnostics: new MemoryDiagnosticLogStore
|
|
8136
|
+
};
|
|
8137
|
+
}
|
|
8138
|
+
}
|
|
8139
|
+
var stores = createStores();
|
|
8140
|
+
var telemetryStore2 = stores.telemetry;
|
|
8141
|
+
var diagnosticLog2 = stores.diagnostics;
|
|
8142
|
+
|
|
7017
8143
|
// src/proxy/errors.ts
|
|
7018
8144
|
function classifyError(errMsg) {
|
|
7019
8145
|
const lower = errMsg.toLowerCase();
|
|
@@ -7121,7 +8247,7 @@ function isExtraUsageRequiredError(errMsg) {
|
|
|
7121
8247
|
import { exec as execCallback } from "child_process";
|
|
7122
8248
|
import { existsSync as existsSync2 } from "fs";
|
|
7123
8249
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
7124
|
-
import { join, dirname as dirname2 } from "path";
|
|
8250
|
+
import { join as join2, dirname as dirname2 } from "path";
|
|
7125
8251
|
import { promisify } from "util";
|
|
7126
8252
|
var exec = promisify(execCallback);
|
|
7127
8253
|
var AUTH_STATUS_CACHE_TTL_MS = 60000;
|
|
@@ -7263,7 +8389,7 @@ async function resolveClaudeExecutableAsync() {
|
|
|
7263
8389
|
if (runningUnderBun) {
|
|
7264
8390
|
try {
|
|
7265
8391
|
const sdkPath = fileURLToPath2(import.meta.resolve("@anthropic-ai/claude-agent-sdk"));
|
|
7266
|
-
const sdkCliJs =
|
|
8392
|
+
const sdkCliJs = join2(dirname2(sdkPath), "cli.js");
|
|
7267
8393
|
if (existsSync2(sdkCliJs)) {
|
|
7268
8394
|
cachedClaudePath = sdkCliJs;
|
|
7269
8395
|
return sdkCliJs;
|
|
@@ -7281,7 +8407,7 @@ async function resolveClaudeExecutableAsync() {
|
|
|
7281
8407
|
if (!runningUnderBun) {
|
|
7282
8408
|
try {
|
|
7283
8409
|
const sdkPath = fileURLToPath2(import.meta.resolve("@anthropic-ai/claude-agent-sdk"));
|
|
7284
|
-
const sdkCliJs =
|
|
8410
|
+
const sdkCliJs = join2(dirname2(sdkPath), "cli.js");
|
|
7285
8411
|
if (existsSync2(sdkCliJs)) {
|
|
7286
8412
|
cachedClaudePath = sdkCliJs;
|
|
7287
8413
|
return sdkCliJs;
|
|
@@ -14268,7 +15394,7 @@ function verifyLineage(cached, messages, cacheKey2, cache) {
|
|
|
14268
15394
|
if (suffixOverlap >= MIN_SUFFIX_FOR_COMPACTION && cached.messageHashes.length >= MIN_STORED_FOR_COMPACTION && suffixStartInIncoming > 0) {
|
|
14269
15395
|
const compactionMsg = `Compaction detected (key=${cacheKey2.slice(0, 8)}…): suffix overlap ${suffixOverlap}/${cached.messageHashes.length}. Allowing resume.`;
|
|
14270
15396
|
console.error(`[PROXY] ${compactionMsg}`);
|
|
14271
|
-
|
|
15397
|
+
diagnosticLog2.lineage(compactionMsg);
|
|
14272
15398
|
cached.lineageHash = computeLineageHash(messages);
|
|
14273
15399
|
cached.messageHashes = incomingHashes;
|
|
14274
15400
|
cached.messageCount = messages.length;
|
|
@@ -14286,13 +15412,13 @@ function verifyLineage(cached, messages, cacheKey2, cache) {
|
|
|
14286
15412
|
}
|
|
14287
15413
|
const undoMsg = `Undo detected (key=${cacheKey2.slice(0, 8)}…): prefix overlap ${prefixOverlap}/${cached.messageHashes.length}, rollback UUID: ${rollbackUuid || "none (legacy session)"}.`;
|
|
14288
15414
|
console.error(`[PROXY] ${undoMsg}`);
|
|
14289
|
-
|
|
15415
|
+
diagnosticLog2.lineage(undoMsg);
|
|
14290
15416
|
return { type: "undo", session: cached, prefixOverlap, rollbackUuid };
|
|
14291
15417
|
}
|
|
14292
15418
|
if (prefixOverlap > 0 && messages.length > cached.messageCount) {
|
|
14293
15419
|
const modifiedMsg = `Modified continuation (key=${cacheKey2.slice(0, 8)}…): prefix overlap ${prefixOverlap}/${cached.messageHashes.length}, incoming ${messages.length} msgs. Allowing resume.`;
|
|
14294
15420
|
console.error(`[PROXY] ${modifiedMsg}`);
|
|
14295
|
-
|
|
15421
|
+
diagnosticLog2.lineage(modifiedMsg);
|
|
14296
15422
|
cached.lineageHash = computeLineageHash(messages.slice(0, messages.length));
|
|
14297
15423
|
cached.messageHashes = incomingHashes;
|
|
14298
15424
|
cached.messageCount = messages.length;
|
|
@@ -14379,8 +15505,8 @@ import {
|
|
|
14379
15505
|
unlinkSync,
|
|
14380
15506
|
writeFileSync
|
|
14381
15507
|
} from "node:fs";
|
|
14382
|
-
import { homedir } from "node:os";
|
|
14383
|
-
import { join as
|
|
15508
|
+
import { homedir as homedir2 } from "node:os";
|
|
15509
|
+
import { join as join3 } from "node:path";
|
|
14384
15510
|
var DEFAULT_MAX_STORED_SESSIONS = 1e4;
|
|
14385
15511
|
var STALE_LOCK_THRESHOLD_MS = 30000;
|
|
14386
15512
|
function getMaxStoredSessions() {
|
|
@@ -14431,11 +15557,11 @@ function getStorePath() {
|
|
|
14431
15557
|
if (!existsSync3(dir)) {
|
|
14432
15558
|
mkdirSync(dir, { recursive: true });
|
|
14433
15559
|
}
|
|
14434
|
-
return
|
|
15560
|
+
return join3(dir, "sessions.json");
|
|
14435
15561
|
}
|
|
14436
15562
|
function getDefaultCacheDir() {
|
|
14437
|
-
const newDir =
|
|
14438
|
-
const oldDir =
|
|
15563
|
+
const newDir = join3(homedir2(), ".cache", "meridian");
|
|
15564
|
+
const oldDir = join3(homedir2(), ".cache", "opencode-claude-max-proxy");
|
|
14439
15565
|
if (existsSync3(newDir))
|
|
14440
15566
|
return newDir;
|
|
14441
15567
|
if (existsSync3(oldDir)) {
|
|
@@ -14867,7 +15993,7 @@ function checkTokenHealth(requestId, sdkSessionId, usage, turnNumber, isResume,
|
|
|
14867
15993
|
isResume,
|
|
14868
15994
|
isPassthrough
|
|
14869
15995
|
};
|
|
14870
|
-
const prevMetric =
|
|
15996
|
+
const prevMetric = telemetryStore2.getLastForSession(sdkSessionId);
|
|
14871
15997
|
const previous = prevMetric ? {
|
|
14872
15998
|
requestId: prevMetric.requestId,
|
|
14873
15999
|
turnNumber: turnNumber - 1,
|
|
@@ -14886,7 +16012,7 @@ function checkTokenHealth(requestId, sdkSessionId, usage, turnNumber, isResume,
|
|
|
14886
16012
|
console.error(line);
|
|
14887
16013
|
}
|
|
14888
16014
|
for (const a of anomalies) {
|
|
14889
|
-
|
|
16015
|
+
diagnosticLog2.log({
|
|
14890
16016
|
level: a.severity === "critical" ? "error" : "warn",
|
|
14891
16017
|
category: "token",
|
|
14892
16018
|
message: `${requestId} ${a.type}: ${a.detail}`,
|
|
@@ -14897,6 +16023,7 @@ function checkTokenHealth(requestId, sdkSessionId, usage, turnNumber, isResume,
|
|
|
14897
16023
|
}
|
|
14898
16024
|
function createProxyServer(config = {}) {
|
|
14899
16025
|
const finalConfig = { ...DEFAULT_PROXY_CONFIG, ...config };
|
|
16026
|
+
const serverVersion = finalConfig.version ?? "unknown";
|
|
14900
16027
|
restoreActiveProfile(finalConfig.profiles);
|
|
14901
16028
|
const sessionDiscoveredTools = new Map;
|
|
14902
16029
|
const app = new Hono2;
|
|
@@ -14908,7 +16035,7 @@ function createProxyServer(config = {}) {
|
|
|
14908
16035
|
status: "ok",
|
|
14909
16036
|
service: "meridian",
|
|
14910
16037
|
format: "anthropic",
|
|
14911
|
-
endpoints: ["/v1/messages", "/messages", "/v1/chat/completions", "/v1/models", "/telemetry", "/health"]
|
|
16038
|
+
endpoints: ["/v1/messages", "/messages", "/v1/chat/completions", "/v1/models", "/telemetry", "/metrics", "/health"]
|
|
14912
16039
|
});
|
|
14913
16040
|
}
|
|
14914
16041
|
return c.html(landingHtml);
|
|
@@ -15031,14 +16158,14 @@ function createProxyServer(config = {}) {
|
|
|
15031
16158
|
const toolCount = body.tools?.length ?? 0;
|
|
15032
16159
|
const requestLogLine = `${requestMeta.requestId} adapter=${adapter.name} model=${model} stream=${stream2} tools=${toolCount} lineage=${lineageType} session=${resumeSessionId?.slice(0, 8) || "new"}${isUndo && undoRollbackUuid ? ` rollback=${undoRollbackUuid.slice(0, 8)}` : ""}${agentMode ? ` agent=${agentMode}` : ""} active=${activeSessions}/${MAX_CONCURRENT_SESSIONS} msgCount=${msgCount}`;
|
|
15033
16160
|
console.error(`[PROXY] ${requestLogLine} msgs=${msgSummary}`);
|
|
15034
|
-
|
|
16161
|
+
diagnosticLog2.session(`${requestLogLine}`, requestMeta.requestId);
|
|
15035
16162
|
if (lineageResult.type === "diverged" && profileSessionId) {
|
|
15036
16163
|
const recovery = lookupSessionRecovery(profileSessionId);
|
|
15037
16164
|
if (recovery) {
|
|
15038
16165
|
const prevId = recovery.previousClaudeSessionId || recovery.claudeSessionId;
|
|
15039
16166
|
const recoveryMsg = `${requestMeta.requestId} SESSION RECOVERY: previous conversation available. Run: claude --resume ${prevId}`;
|
|
15040
16167
|
console.error(`[PROXY] ${recoveryMsg}`);
|
|
15041
|
-
|
|
16168
|
+
diagnosticLog2.session(recoveryMsg, requestMeta.requestId);
|
|
15042
16169
|
}
|
|
15043
16170
|
}
|
|
15044
16171
|
claudeLog("request.received", {
|
|
@@ -15471,7 +16598,7 @@ Subprocess stderr: ${stderrOutput}`;
|
|
|
15471
16598
|
});
|
|
15472
16599
|
const nonStreamQueueWaitMs = requestMeta.queueStartedAt - requestMeta.queueEnteredAt;
|
|
15473
16600
|
checkTokenHealth(requestMeta.requestId, currentSessionId || resumeSessionId, lastUsage, allMessages.length, isResume, passthrough);
|
|
15474
|
-
|
|
16601
|
+
telemetryStore2.record({
|
|
15475
16602
|
requestId: requestMeta.requestId,
|
|
15476
16603
|
timestamp: Date.now(),
|
|
15477
16604
|
adapter: adapter.name,
|
|
@@ -15969,7 +17096,7 @@ data: {"type":"message_stop"}
|
|
|
15969
17096
|
});
|
|
15970
17097
|
const streamQueueWaitMs = requestMeta.queueStartedAt - requestMeta.queueEnteredAt;
|
|
15971
17098
|
checkTokenHealth(requestMeta.requestId, currentSessionId || resumeSessionId, lastUsage, allMessages.length, isResume, passthrough);
|
|
15972
|
-
|
|
17099
|
+
telemetryStore2.record({
|
|
15973
17100
|
requestId: requestMeta.requestId,
|
|
15974
17101
|
timestamp: Date.now(),
|
|
15975
17102
|
adapter: adapter.name,
|
|
@@ -16088,7 +17215,7 @@ data: ${JSON.stringify({
|
|
|
16088
17215
|
const classified = classifyError(errMsg);
|
|
16089
17216
|
claudeLog("proxy.error", { error: errMsg, classified: classified.type });
|
|
16090
17217
|
const errorQueueWaitMs = requestMeta.queueStartedAt - requestMeta.queueEnteredAt;
|
|
16091
|
-
|
|
17218
|
+
telemetryStore2.record({
|
|
16092
17219
|
requestId: requestMeta.requestId,
|
|
16093
17220
|
timestamp: Date.now(),
|
|
16094
17221
|
adapter: adapter.name,
|
|
@@ -16132,6 +17259,12 @@ data: ${JSON.stringify({
|
|
|
16132
17259
|
app.post("/v1/messages", (c) => handleWithQueue(c, "/v1/messages"));
|
|
16133
17260
|
app.post("/messages", (c) => handleWithQueue(c, "/messages"));
|
|
16134
17261
|
app.route("/telemetry", createTelemetryRoutes());
|
|
17262
|
+
app.get("/metrics", (c) => {
|
|
17263
|
+
const body = renderPrometheusMetrics(telemetryStore2);
|
|
17264
|
+
return c.body(body, 200, {
|
|
17265
|
+
"Content-Type": "text/plain; version=0.0.4; charset=utf-8"
|
|
17266
|
+
});
|
|
17267
|
+
});
|
|
16135
17268
|
app.get("/health", async (c) => {
|
|
16136
17269
|
try {
|
|
16137
17270
|
const healthProfile = resolveProfile(finalConfig.profiles, finalConfig.defaultProfile);
|
|
@@ -16140,6 +17273,7 @@ data: ${JSON.stringify({
|
|
|
16140
17273
|
if (!auth) {
|
|
16141
17274
|
return c.json({
|
|
16142
17275
|
status: "degraded",
|
|
17276
|
+
version: serverVersion,
|
|
16143
17277
|
error: "Could not verify auth status",
|
|
16144
17278
|
mode: envBool("PASSTHROUGH") ? "passthrough" : "internal"
|
|
16145
17279
|
});
|
|
@@ -16147,12 +17281,14 @@ data: ${JSON.stringify({
|
|
|
16147
17281
|
if (!auth.loggedIn) {
|
|
16148
17282
|
return c.json({
|
|
16149
17283
|
status: "unhealthy",
|
|
17284
|
+
version: serverVersion,
|
|
16150
17285
|
error: "Not logged in. Run: claude login",
|
|
16151
17286
|
auth: { loggedIn: false }
|
|
16152
17287
|
}, 503);
|
|
16153
17288
|
}
|
|
16154
17289
|
return c.json({
|
|
16155
17290
|
status: "healthy",
|
|
17291
|
+
version: serverVersion,
|
|
16156
17292
|
auth: {
|
|
16157
17293
|
loggedIn: true,
|
|
16158
17294
|
email: auth.email,
|
|
@@ -16164,6 +17300,7 @@ data: ${JSON.stringify({
|
|
|
16164
17300
|
} catch {
|
|
16165
17301
|
return c.json({
|
|
16166
17302
|
status: "degraded",
|
|
17303
|
+
version: serverVersion,
|
|
16167
17304
|
error: "Could not verify auth status",
|
|
16168
17305
|
mode: envBool("PASSTHROUGH") ? "passthrough" : "internal"
|
|
16169
17306
|
});
|
|
@@ -16191,7 +17328,7 @@ data: ${JSON.stringify({
|
|
|
16191
17328
|
});
|
|
16192
17329
|
});
|
|
16193
17330
|
app.get("/profiles", async (c) => {
|
|
16194
|
-
const { profilePageHtml } = await import("./profilePage-
|
|
17331
|
+
const { profilePageHtml } = await import("./profilePage-e90fq8ye.js");
|
|
16195
17332
|
return c.html(profilePageHtml);
|
|
16196
17333
|
});
|
|
16197
17334
|
app.post("/profiles/active", async (c) => {
|