Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3,020 changes: 3,020 additions & 0 deletions packages/backend/drizzle/migrations/meta/0046_snapshot.json

Large diffs are not rendered by default.

3,179 changes: 3,179 additions & 0 deletions packages/backend/drizzle/migrations_pg/meta/0058_snapshot.json

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions packages/backend/drizzle/schema/postgres/debug-logs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ export const debugLogs = pgTable(
transformedResponse: text('transformed_response'),
rawResponseSnapshot: text('raw_response_snapshot'),
transformedResponseSnapshot: text('transformed_response_snapshot'),
responseHeaders: text('response_headers'),
createdAt: bigint('created_at', { mode: 'number' }).notNull(),
},
(table) => ({
Expand Down
1 change: 1 addition & 0 deletions packages/backend/drizzle/schema/sqlite/debug-logs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ export const debugLogs = sqliteTable(
transformedResponse: text('transformed_response'),
rawResponseSnapshot: text('raw_response_snapshot'),
transformedResponseSnapshot: text('transformed_response_snapshot'),
responseHeaders: text('response_headers'),
createdAt: integer('created_at').notNull(),
},
(table) => ({
Expand Down
7 changes: 7 additions & 0 deletions packages/backend/src/services/debug-manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ export interface DebugLogRecord {
transformedResponse?: any;
rawResponseSnapshot?: any;
transformedResponseSnapshot?: any;
responseHeaders?: Record<string, string> | null;
provider?: string;
createdAt?: number;
}
Expand Down Expand Up @@ -171,6 +172,12 @@ export class DebugManager {
log.transformedResponseSnapshot = payload;
}

addResponseHeaders(requestId: string, headers: Record<string, string>): void {
if (!this.isCaptureEnabled()) return;
const log = this.ensureLog(requestId);
log.responseHeaders = headers;
}

flush(requestId: string) {
// Skip flushing ephemeral requests
if (this.ephemeralRequests.has(requestId)) {
Expand Down
16 changes: 16 additions & 0 deletions packages/backend/src/services/dispatcher.ts
Original file line number Diff line number Diff line change
Expand Up @@ -780,6 +780,14 @@ export class Dispatcher {
adapters
);

// Record upstream response headers for debug tracing
if (currentRequest.requestId) {
DebugManager.getInstance().addResponseHeaders(
currentRequest.requestId,
this.extractResponseHeaders(streamProbe.response)
);
}

// Wrap the stream to release the concurrency slot when the stream
// is fully consumed, cancelled, or errors out. Without this, the
// slot would never be released for streaming responses.
Expand Down Expand Up @@ -834,6 +842,14 @@ export class Dispatcher {
return streamResponse;
}

// Record upstream response headers for debug tracing
if (currentRequest.requestId) {
DebugManager.getInstance().addResponseHeaders(
currentRequest.requestId,
this.extractResponseHeaders(response)
);
}

const nonStreamingResponse = await this.handleNonStreamingResponse(
response,
currentRequest,
Expand Down
2 changes: 2 additions & 0 deletions packages/backend/src/services/usage-storage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -292,6 +292,7 @@ export class UsageStorageService extends EventEmitter {
transformedResponseSnapshot: record.transformedResponseSnapshot
? JSON.stringify(record.transformedResponseSnapshot)
: null,
responseHeaders: record.responseHeaders ? JSON.stringify(record.responseHeaders) : null,
createdAt: record.createdAt || Date.now(),
});

Expand Down Expand Up @@ -471,6 +472,7 @@ export class UsageStorageService extends EventEmitter {
transformedResponse: row.transformedResponse,
rawResponseSnapshot: row.rawResponseSnapshot,
transformedResponseSnapshot: row.transformedResponseSnapshot,
responseHeaders: row.responseHeaders,
};
} catch (error) {
logger.error(`Failed to get debug log for ${requestId}`, error);
Expand Down
9 changes: 9 additions & 0 deletions packages/frontend/src/pages/Debug.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ interface DebugLogDetail extends DebugLogMeta {
transformedResponse: string | object;
rawResponseSnapshot?: string | object;
transformedResponseSnapshot?: string | object;
responseHeaders?: string | object;
}

export const Debug: React.FC = () => {
Expand Down Expand Up @@ -241,6 +242,7 @@ export const Debug: React.FC = () => {
rawResponseSnapshot: normalizeExportContent(detail.rawResponseSnapshot),
transformedResponse: normalizeExportContent(detail.transformedResponse),
transformedResponseSnapshot: normalizeExportContent(detail.transformedResponseSnapshot),
responseHeaders: normalizeExportContent(detail.responseHeaders),
};
return JSON.stringify(payload, null, 2);
}, [detail]);
Expand Down Expand Up @@ -501,6 +503,13 @@ export const Debug: React.FC = () => {
color="text-green-400"
/>
)}
{detail.responseHeaders && (
<AccordionPanel
title="Response Headers"
content={formatContent(detail.responseHeaders)}
color="text-yellow-400"
/>
)}
</div>
) : (
<div className="flex flex-col items-center justify-center h-full text-text-muted gap-4">
Expand Down