@relayplane/proxy 1.8.37 → 1.8.39
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/dist/budget.d.ts +39 -0
- package/dist/budget.d.ts.map +1 -1
- package/dist/budget.js +173 -0
- package/dist/budget.js.map +1 -1
- package/dist/cli.js +0 -0
- package/dist/config.d.ts +21 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js.map +1 -1
- package/dist/episode-writer.d.ts +28 -0
- package/dist/episode-writer.d.ts.map +1 -0
- package/dist/episode-writer.js +263 -0
- package/dist/episode-writer.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +9 -1
- package/dist/index.js.map +1 -1
- package/dist/osmosis-store.d.ts +5 -0
- package/dist/osmosis-store.d.ts.map +1 -1
- package/dist/osmosis-store.js +83 -8
- package/dist/osmosis-store.js.map +1 -1
- package/dist/session-tracker.d.ts.map +1 -1
- package/dist/session-tracker.js +7 -1
- package/dist/session-tracker.js.map +1 -1
- package/dist/standalone-proxy.d.ts.map +1 -1
- package/dist/standalone-proxy.js +619 -24
- package/dist/standalone-proxy.js.map +1 -1
- package/dist/tool-router.d.ts +163 -0
- package/dist/tool-router.d.ts.map +1 -0
- package/dist/tool-router.js +528 -0
- package/dist/tool-router.js.map +1 -0
- package/dist/trace-writer.d.ts +155 -0
- package/dist/trace-writer.d.ts.map +1 -0
- package/dist/trace-writer.js +589 -0
- package/dist/trace-writer.js.map +1 -0
- package/package.json +14 -13
- package/LICENSE +0 -21
|
@@ -0,0 +1,589 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* TraceWriter — deterministic per-request trace files for RelayPlane.
|
|
4
|
+
*
|
|
5
|
+
* Writes structured JSONL trace files to ~/.relayplane/traces/{sessionId}/{YYYY-MM-DD}/{traceId}.jsonl
|
|
6
|
+
* and maintains a SQLite index at ~/.relayplane/traces/index.db.
|
|
7
|
+
*
|
|
8
|
+
* CAP 3: Deterministic Traces (Phase 2, Session 2)
|
|
9
|
+
*/
|
|
10
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
11
|
+
if (k2 === undefined) k2 = k;
|
|
12
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
13
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
14
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
15
|
+
}
|
|
16
|
+
Object.defineProperty(o, k2, desc);
|
|
17
|
+
}) : (function(o, m, k, k2) {
|
|
18
|
+
if (k2 === undefined) k2 = k;
|
|
19
|
+
o[k2] = m[k];
|
|
20
|
+
}));
|
|
21
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
22
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
23
|
+
}) : function(o, v) {
|
|
24
|
+
o["default"] = v;
|
|
25
|
+
});
|
|
26
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
27
|
+
var ownKeys = function(o) {
|
|
28
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
29
|
+
var ar = [];
|
|
30
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
31
|
+
return ar;
|
|
32
|
+
};
|
|
33
|
+
return ownKeys(o);
|
|
34
|
+
};
|
|
35
|
+
return function (mod) {
|
|
36
|
+
if (mod && mod.__esModule) return mod;
|
|
37
|
+
var result = {};
|
|
38
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
39
|
+
__setModuleDefault(result, mod);
|
|
40
|
+
return result;
|
|
41
|
+
};
|
|
42
|
+
})();
|
|
43
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
44
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
45
|
+
};
|
|
46
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
47
|
+
exports.TraceWriter = void 0;
|
|
48
|
+
exports.defaultTracesConfig = defaultTracesConfig;
|
|
49
|
+
exports.sha256Hex = sha256Hex;
|
|
50
|
+
const crypto = __importStar(require("node:crypto"));
|
|
51
|
+
const fs = __importStar(require("node:fs"));
|
|
52
|
+
const path = __importStar(require("node:path"));
|
|
53
|
+
const os = __importStar(require("node:os"));
|
|
54
|
+
const better_sqlite3_1 = __importDefault(require("better-sqlite3"));
|
|
55
|
+
// ── Defaults ─────────────────────────────────────────────────────────────────
|
|
56
|
+
function defaultTracesConfig() {
|
|
57
|
+
return {
|
|
58
|
+
enabled: true,
|
|
59
|
+
storeFullRequests: false,
|
|
60
|
+
retentionDays: 30,
|
|
61
|
+
directory: path.join(os.homedir(), '.relayplane', 'traces'),
|
|
62
|
+
maxDiskMb: 500,
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
// ── TraceWriter ───────────────────────────────────────────────────────────────
|
|
66
|
+
class TraceWriter {
|
|
67
|
+
static _instance = null;
|
|
68
|
+
db = null;
|
|
69
|
+
config;
|
|
70
|
+
baseDir;
|
|
71
|
+
// Per-session monotonic sequence (across all traces in a session)
|
|
72
|
+
sessionSequences = new Map();
|
|
73
|
+
// Per-trace event count (for trace_index.event_count)
|
|
74
|
+
traceEventCounts = new Map();
|
|
75
|
+
// Per-trace start timestamp
|
|
76
|
+
traceStartTimes = new Map();
|
|
77
|
+
// In-memory session graphs (flushed on session.end or shutdown)
|
|
78
|
+
sessionGraphs = new Map();
|
|
79
|
+
// Per-session idle timers (emit session.end after 60s of inactivity)
|
|
80
|
+
sessionIdleTimers = new Map();
|
|
81
|
+
// Sessions already announced with session.start
|
|
82
|
+
knownSessions = new Set();
|
|
83
|
+
constructor(config) {
|
|
84
|
+
this.config = config;
|
|
85
|
+
// Normalise ~ to home dir
|
|
86
|
+
this.baseDir = config.directory.startsWith('~')
|
|
87
|
+
? config.directory.replace(/^~/, os.homedir())
|
|
88
|
+
: config.directory;
|
|
89
|
+
if (config.enabled) {
|
|
90
|
+
try {
|
|
91
|
+
fs.mkdirSync(this.baseDir, { recursive: true });
|
|
92
|
+
this.initDb();
|
|
93
|
+
this.pruneOldFiles();
|
|
94
|
+
}
|
|
95
|
+
catch (err) {
|
|
96
|
+
console.error('[trace-writer] init failed:', err);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
static getInstance(config) {
|
|
101
|
+
if (!TraceWriter._instance) {
|
|
102
|
+
TraceWriter._instance = new TraceWriter(config ?? defaultTracesConfig());
|
|
103
|
+
}
|
|
104
|
+
return TraceWriter._instance;
|
|
105
|
+
}
|
|
106
|
+
/** Replace the singleton (for testing / config reload) */
|
|
107
|
+
static reset() {
|
|
108
|
+
if (TraceWriter._instance) {
|
|
109
|
+
TraceWriter._instance.shutdown();
|
|
110
|
+
TraceWriter._instance = null;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
isEnabled() {
|
|
114
|
+
return this.config.enabled;
|
|
115
|
+
}
|
|
116
|
+
// ── DB ───────────────────────────────────────────────────────────────────
|
|
117
|
+
initDb() {
|
|
118
|
+
const dbPath = path.join(this.baseDir, 'index.db');
|
|
119
|
+
try {
|
|
120
|
+
this.db = new better_sqlite3_1.default(dbPath);
|
|
121
|
+
this.db.exec(`
|
|
122
|
+
CREATE TABLE IF NOT EXISTS trace_index (
|
|
123
|
+
trace_id TEXT PRIMARY KEY,
|
|
124
|
+
session_id TEXT NOT NULL,
|
|
125
|
+
parent_trace_id TEXT,
|
|
126
|
+
event_count INTEGER DEFAULT 0,
|
|
127
|
+
started_at INTEGER NOT NULL,
|
|
128
|
+
ended_at INTEGER,
|
|
129
|
+
duration_ms INTEGER,
|
|
130
|
+
cost_usd REAL,
|
|
131
|
+
model_used TEXT,
|
|
132
|
+
tool_names TEXT,
|
|
133
|
+
trace_file TEXT NOT NULL
|
|
134
|
+
);
|
|
135
|
+
CREATE INDEX IF NOT EXISTS idx_trace_session ON trace_index(session_id);
|
|
136
|
+
CREATE INDEX IF NOT EXISTS idx_trace_started ON trace_index(started_at);
|
|
137
|
+
|
|
138
|
+
CREATE TABLE IF NOT EXISTS session_graphs (
|
|
139
|
+
session_id TEXT PRIMARY KEY,
|
|
140
|
+
root_trace_id TEXT,
|
|
141
|
+
started_at INTEGER NOT NULL,
|
|
142
|
+
ended_at INTEGER,
|
|
143
|
+
trace_count INTEGER DEFAULT 0,
|
|
144
|
+
tool_call_count INTEGER DEFAULT 0,
|
|
145
|
+
total_cost_usd REAL DEFAULT 0,
|
|
146
|
+
graph_json TEXT
|
|
147
|
+
);
|
|
148
|
+
`);
|
|
149
|
+
}
|
|
150
|
+
catch (err) {
|
|
151
|
+
console.error('[trace-writer] DB init failed:', err);
|
|
152
|
+
this.db = null;
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
// ── Helpers ──────────────────────────────────────────────────────────────
|
|
156
|
+
traceFilePath(sessionId, traceId, ts) {
|
|
157
|
+
const d = new Date(ts);
|
|
158
|
+
const dateStr = `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, '0')}-${String(d.getDate()).padStart(2, '0')}`;
|
|
159
|
+
const resolved = path.resolve(this.baseDir, sessionId, dateStr, `${traceId}.jsonl`);
|
|
160
|
+
// Guard against path traversal via malformed sessionId or traceId
|
|
161
|
+
if (!resolved.startsWith(this.baseDir + path.sep) && resolved !== this.baseDir) {
|
|
162
|
+
throw new Error(`[trace-writer] path traversal detected: ${resolved}`);
|
|
163
|
+
}
|
|
164
|
+
return resolved;
|
|
165
|
+
}
|
|
166
|
+
traceRelPath(sessionId, traceId, ts) {
|
|
167
|
+
const d = new Date(ts);
|
|
168
|
+
const dateStr = `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, '0')}-${String(d.getDate()).padStart(2, '0')}`;
|
|
169
|
+
return `${sessionId}/${dateStr}/${traceId}.jsonl`;
|
|
170
|
+
}
|
|
171
|
+
/** Estimate total size of baseDir in bytes (best-effort, non-recursive to keep it fast). */
|
|
172
|
+
estimateDirSizeBytes() {
|
|
173
|
+
try {
|
|
174
|
+
let total = 0;
|
|
175
|
+
const walk = (dir, depth) => {
|
|
176
|
+
if (depth > 5)
|
|
177
|
+
return; // cap recursion
|
|
178
|
+
for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
|
|
179
|
+
const full = path.join(dir, entry.name);
|
|
180
|
+
if (entry.isFile()) {
|
|
181
|
+
try {
|
|
182
|
+
total += fs.statSync(full).size;
|
|
183
|
+
}
|
|
184
|
+
catch { }
|
|
185
|
+
}
|
|
186
|
+
else if (entry.isDirectory()) {
|
|
187
|
+
walk(full, depth + 1);
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
};
|
|
191
|
+
walk(this.baseDir, 0);
|
|
192
|
+
return total;
|
|
193
|
+
}
|
|
194
|
+
catch {
|
|
195
|
+
return 0;
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
/** Returns true if writing is allowed under the maxDiskMb cap. */
|
|
199
|
+
isDiskBudgetOk() {
|
|
200
|
+
const limitBytes = this.config.maxDiskMb * 1024 * 1024;
|
|
201
|
+
return this.estimateDirSizeBytes() < limitBytes;
|
|
202
|
+
}
|
|
203
|
+
nextSequence(sessionId) {
|
|
204
|
+
const n = (this.sessionSequences.get(sessionId) ?? 0) + 1;
|
|
205
|
+
this.sessionSequences.set(sessionId, n);
|
|
206
|
+
return n;
|
|
207
|
+
}
|
|
208
|
+
resetIdleTimer(sessionId) {
|
|
209
|
+
const existing = this.sessionIdleTimers.get(sessionId);
|
|
210
|
+
if (existing)
|
|
211
|
+
clearTimeout(existing);
|
|
212
|
+
const timer = setTimeout(() => {
|
|
213
|
+
void this.endSession(sessionId);
|
|
214
|
+
}, 60_000);
|
|
215
|
+
// Allow process to exit without waiting for idle timers
|
|
216
|
+
if (typeof timer === 'object' && 'unref' in timer)
|
|
217
|
+
timer.unref();
|
|
218
|
+
this.sessionIdleTimers.set(sessionId, timer);
|
|
219
|
+
}
|
|
220
|
+
// ── Session Graph ────────────────────────────────────────────────────────
|
|
221
|
+
updateGraph(sessionId, traceId, event) {
|
|
222
|
+
let graph = this.sessionGraphs.get(sessionId);
|
|
223
|
+
if (!graph) {
|
|
224
|
+
graph = {
|
|
225
|
+
sessionId,
|
|
226
|
+
rootTraceId: traceId,
|
|
227
|
+
startedAt: event.timestamp,
|
|
228
|
+
nodes: [],
|
|
229
|
+
edges: [],
|
|
230
|
+
};
|
|
231
|
+
this.sessionGraphs.set(sessionId, graph);
|
|
232
|
+
}
|
|
233
|
+
if (event.eventType === 'request.start') {
|
|
234
|
+
graph.nodes.push({
|
|
235
|
+
id: traceId,
|
|
236
|
+
type: 'request',
|
|
237
|
+
label: event.payload.model ?? 'unknown',
|
|
238
|
+
startedAt: event.timestamp,
|
|
239
|
+
});
|
|
240
|
+
}
|
|
241
|
+
else if (event.eventType === 'request.end') {
|
|
242
|
+
const node = graph.nodes.find(n => n.id === traceId);
|
|
243
|
+
if (node) {
|
|
244
|
+
node.durationMs = event.durationMs;
|
|
245
|
+
node.costUsd = event.payload.costUsd;
|
|
246
|
+
node.outcome = event.error ? 'failure' : 'success';
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
else if (event.eventType === 'tool.call' || event.eventType === 'tool.denied') {
|
|
250
|
+
const nodeId = `${traceId}:tool:${event.sequence}`;
|
|
251
|
+
graph.nodes.push({
|
|
252
|
+
id: nodeId,
|
|
253
|
+
type: 'tool-call',
|
|
254
|
+
label: event.payload.toolName ?? 'unknown',
|
|
255
|
+
startedAt: event.timestamp,
|
|
256
|
+
outcome: event.eventType === 'tool.denied' ? 'denied' : undefined,
|
|
257
|
+
});
|
|
258
|
+
graph.edges.push({
|
|
259
|
+
from: traceId,
|
|
260
|
+
to: nodeId,
|
|
261
|
+
type: 'called',
|
|
262
|
+
timestamp: event.timestamp,
|
|
263
|
+
});
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
// ── Core write ───────────────────────────────────────────────────────────
|
|
267
|
+
async write(sessionId, traceId, input) {
|
|
268
|
+
if (!this.config.enabled)
|
|
269
|
+
return;
|
|
270
|
+
const now = Date.now();
|
|
271
|
+
// Track trace start time on first event for this trace
|
|
272
|
+
if (!this.traceStartTimes.has(traceId)) {
|
|
273
|
+
this.traceStartTimes.set(traceId, now);
|
|
274
|
+
}
|
|
275
|
+
// Emit session.start the first time we see this session
|
|
276
|
+
if (input.eventType === 'request.start' && !this.knownSessions.has(sessionId)) {
|
|
277
|
+
this.knownSessions.add(sessionId);
|
|
278
|
+
this.upsertSessionGraphRecord(sessionId, traceId, now);
|
|
279
|
+
// Write session.start synchronously (avoids recursive async)
|
|
280
|
+
this.writeEventSync(sessionId, traceId, now, {
|
|
281
|
+
eventType: 'session.start',
|
|
282
|
+
payload: {},
|
|
283
|
+
});
|
|
284
|
+
}
|
|
285
|
+
this.writeEventSync(sessionId, traceId, now, input);
|
|
286
|
+
this.resetIdleTimer(sessionId);
|
|
287
|
+
}
|
|
288
|
+
writeEventSync(sessionId, traceId, now, input) {
|
|
289
|
+
const sequence = this.nextSequence(sessionId);
|
|
290
|
+
const event = {
|
|
291
|
+
traceId,
|
|
292
|
+
sessionId,
|
|
293
|
+
parentTraceId: input.parentTraceId,
|
|
294
|
+
agentId: input.agentId,
|
|
295
|
+
sequence,
|
|
296
|
+
timestamp: now,
|
|
297
|
+
eventType: input.eventType,
|
|
298
|
+
durationMs: input.durationMs,
|
|
299
|
+
error: input.error,
|
|
300
|
+
payload: input.payload ?? {},
|
|
301
|
+
};
|
|
302
|
+
this.updateGraph(sessionId, traceId, event);
|
|
303
|
+
const startTs = this.traceStartTimes.get(traceId) ?? now;
|
|
304
|
+
let filePath;
|
|
305
|
+
try {
|
|
306
|
+
filePath = this.traceFilePath(sessionId, traceId, startTs);
|
|
307
|
+
}
|
|
308
|
+
catch (err) {
|
|
309
|
+
console.error('[trace-writer] write rejected:', err);
|
|
310
|
+
return;
|
|
311
|
+
}
|
|
312
|
+
if (!this.isDiskBudgetOk()) {
|
|
313
|
+
console.error(`[trace-writer] disk budget exceeded (maxDiskMb=${this.config.maxDiskMb}); dropping event`);
|
|
314
|
+
return;
|
|
315
|
+
}
|
|
316
|
+
try {
|
|
317
|
+
fs.mkdirSync(path.dirname(filePath), { recursive: true });
|
|
318
|
+
fs.appendFileSync(filePath, JSON.stringify(event) + '\n');
|
|
319
|
+
}
|
|
320
|
+
catch (err) {
|
|
321
|
+
console.error('[trace-writer] write failed:', err);
|
|
322
|
+
}
|
|
323
|
+
const count = (this.traceEventCounts.get(traceId) ?? 0) + 1;
|
|
324
|
+
this.traceEventCounts.set(traceId, count);
|
|
325
|
+
}
|
|
326
|
+
// ── Finalize (update index.db after response sent) ───────────────────────
|
|
327
|
+
async finalizeTrace(traceId, sessionId, meta) {
|
|
328
|
+
if (!this.config.enabled || !this.db)
|
|
329
|
+
return;
|
|
330
|
+
const startedAt = this.traceStartTimes.get(traceId) ?? Date.now();
|
|
331
|
+
const endedAt = Date.now();
|
|
332
|
+
const eventCount = this.traceEventCounts.get(traceId) ?? 0;
|
|
333
|
+
const graph = this.sessionGraphs.get(sessionId);
|
|
334
|
+
const toolCalls = graph?.nodes.filter(n => n.type === 'tool-call') ?? [];
|
|
335
|
+
const toolNames = [...new Set(toolCalls.map(n => n.label))];
|
|
336
|
+
try {
|
|
337
|
+
this.db
|
|
338
|
+
.prepare(`INSERT OR REPLACE INTO trace_index
|
|
339
|
+
(trace_id, session_id, event_count, started_at, ended_at, duration_ms, cost_usd, model_used, tool_names, trace_file)
|
|
340
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`)
|
|
341
|
+
.run(traceId, sessionId, eventCount, startedAt, endedAt, meta.durationMs ?? null, meta.costUsd ?? null, meta.modelUsed ?? null, JSON.stringify(toolNames), this.traceRelPath(sessionId, traceId, startedAt));
|
|
342
|
+
this.db
|
|
343
|
+
.prepare(`UPDATE session_graphs
|
|
344
|
+
SET trace_count = trace_count + 1,
|
|
345
|
+
tool_call_count = tool_call_count + ?,
|
|
346
|
+
total_cost_usd = total_cost_usd + ?
|
|
347
|
+
WHERE session_id = ?`)
|
|
348
|
+
.run(toolCalls.length, meta.costUsd ?? 0, sessionId);
|
|
349
|
+
}
|
|
350
|
+
catch (err) {
|
|
351
|
+
console.error('[trace-writer] finalizeTrace failed:', err);
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
// ── Session end ──────────────────────────────────────────────────────────
|
|
355
|
+
async endSession(sessionId) {
|
|
356
|
+
if (!this.config.enabled || !this.db)
|
|
357
|
+
return;
|
|
358
|
+
const graph = this.sessionGraphs.get(sessionId);
|
|
359
|
+
if (!graph)
|
|
360
|
+
return;
|
|
361
|
+
graph.endedAt = Date.now();
|
|
362
|
+
try {
|
|
363
|
+
this.db
|
|
364
|
+
.prepare(`UPDATE session_graphs SET ended_at = ?, graph_json = ? WHERE session_id = ?`)
|
|
365
|
+
.run(graph.endedAt, JSON.stringify(graph), sessionId);
|
|
366
|
+
}
|
|
367
|
+
catch (err) {
|
|
368
|
+
console.error('[trace-writer] endSession failed:', err);
|
|
369
|
+
}
|
|
370
|
+
this.sessionGraphs.delete(sessionId);
|
|
371
|
+
this.sessionSequences.delete(sessionId);
|
|
372
|
+
const timer = this.sessionIdleTimers.get(sessionId);
|
|
373
|
+
if (timer)
|
|
374
|
+
clearTimeout(timer);
|
|
375
|
+
this.sessionIdleTimers.delete(sessionId);
|
|
376
|
+
}
|
|
377
|
+
upsertSessionGraphRecord(sessionId, rootTraceId, startedAt) {
|
|
378
|
+
if (!this.db)
|
|
379
|
+
return;
|
|
380
|
+
try {
|
|
381
|
+
this.db
|
|
382
|
+
.prepare(`INSERT OR IGNORE INTO session_graphs (session_id, root_trace_id, started_at)
|
|
383
|
+
VALUES (?, ?, ?)`)
|
|
384
|
+
.run(sessionId, rootTraceId, startedAt);
|
|
385
|
+
}
|
|
386
|
+
catch (err) {
|
|
387
|
+
console.error('[trace-writer] upsertSessionGraphRecord failed:', err);
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
// ── REST / MCP queries ───────────────────────────────────────────────────
|
|
391
|
+
getRecentTraces(limit = 20) {
|
|
392
|
+
if (!this.db)
|
|
393
|
+
return [];
|
|
394
|
+
try {
|
|
395
|
+
return this.db
|
|
396
|
+
.prepare(`SELECT trace_id, session_id, started_at, ended_at, duration_ms, cost_usd, model_used, tool_names, event_count
|
|
397
|
+
FROM trace_index
|
|
398
|
+
ORDER BY started_at DESC
|
|
399
|
+
LIMIT ?`)
|
|
400
|
+
.all(Math.min(limit, 100));
|
|
401
|
+
}
|
|
402
|
+
catch {
|
|
403
|
+
return [];
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
getSessionGraph(sessionId) {
|
|
407
|
+
// In-memory first (session still active)
|
|
408
|
+
const live = this.sessionGraphs.get(sessionId);
|
|
409
|
+
if (live)
|
|
410
|
+
return live;
|
|
411
|
+
if (!this.db)
|
|
412
|
+
return null;
|
|
413
|
+
try {
|
|
414
|
+
const row = this.db
|
|
415
|
+
.prepare(`SELECT graph_json FROM session_graphs WHERE session_id = ?`)
|
|
416
|
+
.get(sessionId);
|
|
417
|
+
if (row?.graph_json)
|
|
418
|
+
return JSON.parse(row.graph_json);
|
|
419
|
+
}
|
|
420
|
+
catch { }
|
|
421
|
+
return null;
|
|
422
|
+
}
|
|
423
|
+
// ── Events reader ────────────────────────────────────────────────────────
|
|
424
|
+
/** Read raw JSONL events for a trace by traceId. Returns parsed events array. */
|
|
425
|
+
getTraceEvents(traceId) {
|
|
426
|
+
if (!this.db)
|
|
427
|
+
return [];
|
|
428
|
+
try {
|
|
429
|
+
const row = this.db
|
|
430
|
+
.prepare(`SELECT trace_file FROM trace_index WHERE trace_id = ?`)
|
|
431
|
+
.get(traceId);
|
|
432
|
+
if (!row)
|
|
433
|
+
return [];
|
|
434
|
+
const fullPath = path.join(this.baseDir, row.trace_file);
|
|
435
|
+
if (!fs.existsSync(fullPath))
|
|
436
|
+
return [];
|
|
437
|
+
const content = fs.readFileSync(fullPath, 'utf-8');
|
|
438
|
+
return content
|
|
439
|
+
.split('\n')
|
|
440
|
+
.filter(l => l.trim())
|
|
441
|
+
.map(l => {
|
|
442
|
+
try {
|
|
443
|
+
return JSON.parse(l);
|
|
444
|
+
}
|
|
445
|
+
catch {
|
|
446
|
+
return null;
|
|
447
|
+
}
|
|
448
|
+
})
|
|
449
|
+
.filter((e) => e !== null);
|
|
450
|
+
}
|
|
451
|
+
catch {
|
|
452
|
+
return [];
|
|
453
|
+
}
|
|
454
|
+
}
|
|
455
|
+
// ── Export ───────────────────────────────────────────────────────────────
|
|
456
|
+
async export(options) {
|
|
457
|
+
if (!this.db) {
|
|
458
|
+
if (options.format === 'markdown') {
|
|
459
|
+
return '# RelayPlane Trace Export\n\nTrace index DB not available.\n';
|
|
460
|
+
}
|
|
461
|
+
return '';
|
|
462
|
+
}
|
|
463
|
+
const conditions = [];
|
|
464
|
+
const params = [];
|
|
465
|
+
if (options.sessionIds?.length) {
|
|
466
|
+
conditions.push(`session_id IN (${options.sessionIds.map(() => '?').join(',')})`);
|
|
467
|
+
params.push(...options.sessionIds);
|
|
468
|
+
}
|
|
469
|
+
if (options.fromTimestamp != null) {
|
|
470
|
+
conditions.push('started_at >= ?');
|
|
471
|
+
params.push(options.fromTimestamp);
|
|
472
|
+
}
|
|
473
|
+
if (options.toTimestamp != null) {
|
|
474
|
+
conditions.push('started_at <= ?');
|
|
475
|
+
params.push(options.toTimestamp);
|
|
476
|
+
}
|
|
477
|
+
const where = conditions.length ? `WHERE ${conditions.join(' AND ')}` : '';
|
|
478
|
+
const rows = this.db
|
|
479
|
+
.prepare(`SELECT * FROM trace_index ${where} ORDER BY started_at DESC`)
|
|
480
|
+
.all(...params);
|
|
481
|
+
switch (options.format) {
|
|
482
|
+
case 'jsonl':
|
|
483
|
+
return rows.map(r => JSON.stringify(r)).join('\n');
|
|
484
|
+
case 'markdown': {
|
|
485
|
+
const lines = [
|
|
486
|
+
'# RelayPlane Trace Export',
|
|
487
|
+
'',
|
|
488
|
+
`Exported: ${new Date().toISOString()}`,
|
|
489
|
+
`Total traces: ${rows.length}`,
|
|
490
|
+
'',
|
|
491
|
+
'| Trace ID | Session | Started | Duration | Cost | Model | Tools |',
|
|
492
|
+
'|----------|---------|---------|----------|------|-------|-------|',
|
|
493
|
+
];
|
|
494
|
+
for (const row of rows) {
|
|
495
|
+
const started = new Date(row['started_at']).toISOString();
|
|
496
|
+
const dur = row['duration_ms'] != null ? `${row['duration_ms']}ms` : '-';
|
|
497
|
+
const cost = row['cost_usd'] != null ? `$${row['cost_usd'].toFixed(4)}` : '-';
|
|
498
|
+
const tools = row['tool_names']
|
|
499
|
+
? JSON.parse(row['tool_names']).join(', ') || '-'
|
|
500
|
+
: '-';
|
|
501
|
+
lines.push(`| ${row['trace_id'].slice(0, 8)}… | ${row['session_id'].slice(0, 8)}… | ${started} | ${dur} | ${cost} | ${row['model_used'] ?? '-'} | ${tools} |`);
|
|
502
|
+
}
|
|
503
|
+
return lines.join('\n');
|
|
504
|
+
}
|
|
505
|
+
case 'traceops': {
|
|
506
|
+
// OTLP-like spans
|
|
507
|
+
const spans = rows.map(row => ({
|
|
508
|
+
traceId: row['trace_id'],
|
|
509
|
+
spanId: row['trace_id'].replace(/-/g, '').slice(0, 16),
|
|
510
|
+
parentSpanId: null,
|
|
511
|
+
startTimeUnixNano: row['started_at'] * 1_000_000,
|
|
512
|
+
durationNano: (row['duration_ms'] ?? 0) * 1_000_000,
|
|
513
|
+
attributes: [
|
|
514
|
+
{ key: 'session.id', value: { stringValue: row['session_id'] } },
|
|
515
|
+
{ key: 'model.used', value: { stringValue: row['model_used'] ?? '' } },
|
|
516
|
+
{ key: 'cost.usd', value: { doubleValue: row['cost_usd'] ?? 0 } },
|
|
517
|
+
],
|
|
518
|
+
}));
|
|
519
|
+
return JSON.stringify({ resourceSpans: [{ scopeSpans: [{ spans }] }] }, null, 2);
|
|
520
|
+
}
|
|
521
|
+
default:
|
|
522
|
+
throw new Error(`Unsupported export format: ${options.format}`);
|
|
523
|
+
}
|
|
524
|
+
}
|
|
525
|
+
// ── Replay ───────────────────────────────────────────────────────────────
|
|
526
|
+
replay(_traceId) {
|
|
527
|
+
if (!this.config.storeFullRequests) {
|
|
528
|
+
return Promise.reject(new Error('Replay requires storeFullRequests=true. ' +
|
|
529
|
+
'Set config.traces.storeFullRequests = true to enable replay.'));
|
|
530
|
+
}
|
|
531
|
+
return Promise.reject(new Error('Replay not yet implemented for storeFullRequests=true'));
|
|
532
|
+
}
|
|
533
|
+
// ── Retention ────────────────────────────────────────────────────────────
|
|
534
|
+
pruneOldFiles() {
|
|
535
|
+
if (!this.db)
|
|
536
|
+
return;
|
|
537
|
+
const cutoff = Date.now() - this.config.retentionDays * 24 * 60 * 60 * 1000;
|
|
538
|
+
try {
|
|
539
|
+
const old = this.db
|
|
540
|
+
.prepare(`SELECT trace_file, trace_id FROM trace_index WHERE started_at < ?`)
|
|
541
|
+
.all(cutoff);
|
|
542
|
+
for (const row of old) {
|
|
543
|
+
try {
|
|
544
|
+
fs.unlinkSync(path.join(this.baseDir, row.trace_file));
|
|
545
|
+
}
|
|
546
|
+
catch { }
|
|
547
|
+
}
|
|
548
|
+
if (old.length > 0) {
|
|
549
|
+
this.db.prepare(`DELETE FROM trace_index WHERE started_at < ?`).run(cutoff);
|
|
550
|
+
}
|
|
551
|
+
this.db
|
|
552
|
+
.prepare(`DELETE FROM session_graphs WHERE ended_at IS NOT NULL AND ended_at < ?`)
|
|
553
|
+
.run(cutoff);
|
|
554
|
+
}
|
|
555
|
+
catch (err) {
|
|
556
|
+
console.error('[trace-writer] pruneOldFiles failed:', err);
|
|
557
|
+
}
|
|
558
|
+
}
|
|
559
|
+
// ── Shutdown ─────────────────────────────────────────────────────────────
|
|
560
|
+
shutdown() {
|
|
561
|
+
for (const timer of this.sessionIdleTimers.values()) {
|
|
562
|
+
clearTimeout(timer);
|
|
563
|
+
}
|
|
564
|
+
this.sessionIdleTimers.clear();
|
|
565
|
+
for (const [sessionId, graph] of this.sessionGraphs) {
|
|
566
|
+
if (this.db) {
|
|
567
|
+
graph.endedAt = Date.now();
|
|
568
|
+
try {
|
|
569
|
+
this.db
|
|
570
|
+
.prepare(`UPDATE session_graphs SET ended_at = ?, graph_json = ? WHERE session_id = ?`)
|
|
571
|
+
.run(graph.endedAt, JSON.stringify(graph), sessionId);
|
|
572
|
+
}
|
|
573
|
+
catch { }
|
|
574
|
+
}
|
|
575
|
+
}
|
|
576
|
+
this.sessionGraphs.clear();
|
|
577
|
+
try {
|
|
578
|
+
this.db?.close();
|
|
579
|
+
}
|
|
580
|
+
catch { }
|
|
581
|
+
this.db = null;
|
|
582
|
+
}
|
|
583
|
+
}
|
|
584
|
+
exports.TraceWriter = TraceWriter;
|
|
585
|
+
// ── Convenience hash helpers (exported for standalone-proxy.ts) ──────────────
|
|
586
|
+
function sha256Hex(input) {
|
|
587
|
+
return crypto.createHash('sha256').update(input).digest('hex');
|
|
588
|
+
}
|
|
589
|
+
//# sourceMappingURL=trace-writer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"trace-writer.js","sourceRoot":"","sources":["../src/trace-writer.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@relayplane/proxy",
|
|
3
|
-
"version": "1.8.
|
|
3
|
+
"version": "1.8.39",
|
|
4
4
|
"description": "Open source cost intelligence proxy for AI agents. Cut LLM costs ~80% with smart model routing. Dashboard, policy engine, 11 providers. MIT licensed.",
|
|
5
5
|
"homepage": "https://relayplane.com",
|
|
6
6
|
"repository": {
|
|
@@ -13,6 +13,17 @@
|
|
|
13
13
|
"relayplane": "dist/cli.js",
|
|
14
14
|
"relayplane-proxy": "dist/cli.js"
|
|
15
15
|
},
|
|
16
|
+
"scripts": {
|
|
17
|
+
"build": "tsc",
|
|
18
|
+
"dev": "tsc --watch",
|
|
19
|
+
"start": "node dist/cli.js",
|
|
20
|
+
"test": "vitest run",
|
|
21
|
+
"test:watch": "vitest",
|
|
22
|
+
"harness:v1.7": "bash ./scripts/v1.7-harness.sh",
|
|
23
|
+
"prepublishOnly": "npm run build",
|
|
24
|
+
"test:integration": "vitest run __tests__/integration/",
|
|
25
|
+
"test:e2e": "vitest run test/e2e/"
|
|
26
|
+
},
|
|
16
27
|
"keywords": [
|
|
17
28
|
"relayplane",
|
|
18
29
|
"ai",
|
|
@@ -56,15 +67,5 @@
|
|
|
56
67
|
"dist",
|
|
57
68
|
"assets",
|
|
58
69
|
"README.md"
|
|
59
|
-
]
|
|
60
|
-
|
|
61
|
-
"build": "tsc",
|
|
62
|
-
"dev": "tsc --watch",
|
|
63
|
-
"start": "node dist/cli.js",
|
|
64
|
-
"test": "vitest run",
|
|
65
|
-
"test:watch": "vitest",
|
|
66
|
-
"harness:v1.7": "bash ./scripts/v1.7-harness.sh",
|
|
67
|
-
"test:integration": "vitest run __tests__/integration/",
|
|
68
|
-
"test:e2e": "vitest run test/e2e/"
|
|
69
|
-
}
|
|
70
|
-
}
|
|
70
|
+
]
|
|
71
|
+
}
|