Fix proxy debug trace truncation previews (#313)
This commit is contained in:
@@ -150,4 +150,37 @@ describe('proxyDebugTraceStore', () => {
|
||||
downgradeDecision: true,
|
||||
});
|
||||
});
|
||||
|
||||
it('stores truncated debug payload previews as valid JSON text for json-capable databases', async () => {
|
||||
const trace = await store.createProxyDebugTrace({
|
||||
downstreamPath: '/v1/responses',
|
||||
clientKind: 'codex',
|
||||
requestedModel: 'gpt-5.4',
|
||||
requestHeaders: {
|
||||
authorization: `Bearer ${'x'.repeat(5000)}`,
|
||||
'x-client': 'Codex Desktop',
|
||||
},
|
||||
requestBody: {
|
||||
model: 'gpt-5.4',
|
||||
input: [{ role: 'user', content: 'hello '.repeat(2000) }],
|
||||
},
|
||||
maxBodyBytes: 1024,
|
||||
});
|
||||
|
||||
const detail = await store.getProxyDebugTraceDetail(trace.id);
|
||||
const headersPayload = JSON.parse(detail?.trace.requestHeadersJson || 'null');
|
||||
const bodyPayload = JSON.parse(detail?.trace.requestBodyJson || 'null');
|
||||
|
||||
expect(headersPayload).toMatchObject({
|
||||
__metapiTruncated: true,
|
||||
});
|
||||
expect(typeof headersPayload.preview).toBe('string');
|
||||
expect(headersPayload.preview).toContain('authorization');
|
||||
|
||||
expect(bodyPayload).toMatchObject({
|
||||
__metapiTruncated: true,
|
||||
});
|
||||
expect(typeof bodyPayload.preview).toBe('string');
|
||||
expect(bodyPayload.preview).toContain('"model": "gpt-5.4"');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -25,6 +25,24 @@ export type ProxyDebugTraceSession = {
|
||||
let lastPruneAtMs = 0;
|
||||
const PRUNE_INTERVAL_MS = 5 * 60 * 1000;
|
||||
|
||||
type TruncatedDebugPreview = {
|
||||
__metapiTruncated: true;
|
||||
preview: string;
|
||||
originalBytes: number;
|
||||
storedBytes: number;
|
||||
};
|
||||
|
||||
function buildTruncatedDebugPreview(text: string, maxBytes: number, originalBytes: number): string {
|
||||
const truncated = Buffer.from(text, 'utf8').subarray(0, Math.max(0, maxBytes)).toString('utf8');
|
||||
const payload: TruncatedDebugPreview = {
|
||||
__metapiTruncated: true,
|
||||
preview: truncated,
|
||||
originalBytes,
|
||||
storedBytes: maxBytes,
|
||||
};
|
||||
return JSON.stringify(payload, null, 2);
|
||||
}
|
||||
|
||||
function stringifyDebugValue(value: unknown, maxBytes: number): string | null {
|
||||
if (value == null) return null;
|
||||
|
||||
@@ -45,8 +63,7 @@ function stringifyDebugValue(value: unknown, maxBytes: number): string | null {
|
||||
return text;
|
||||
}
|
||||
|
||||
const truncated = buffer.subarray(0, Math.max(0, maxBytes)).toString('utf8');
|
||||
return `${truncated}\n...[truncated ${buffer.length - maxBytes} bytes]`;
|
||||
return buildTruncatedDebugPreview(text, maxBytes, buffer.length);
|
||||
}
|
||||
|
||||
function normalizeHeadersValue(value: HeadersLike): Record<string, unknown> | null {
|
||||
|
||||
Reference in New Issue
Block a user