diff --git a/packages/gateway/src/routes/completion.ts b/packages/gateway/src/routes/completion.ts index b3a0b78..58d9c62 100644 --- a/packages/gateway/src/routes/completion.ts +++ b/packages/gateway/src/routes/completion.ts @@ -1191,22 +1191,45 @@ export async function completionRoute(fastify: FastifyInstance): Promise { const text = upstreamJson?.content ?? upstreamJson?.response ?? upstreamJson?.choices?.[0]?.message?.content ?? ''; const respBody = toOpenAIResponsesResponse({ output: text, model: parsed.data.model, status: 'approved' }, parsed.data.model); logger.info({ callId, model: parsed.data.model, len: text.length }, 'codex-bridge passthrough OK'); + const bridgeCaller = (request.headers['x-llm-interceptor-caller'] as string) || 'codex-app'; + const bridgeTokensIn = (upstreamJson?.usage?.prompt_tokens as number | undefined) ?? Math.ceil(inputText.length / 4); + const bridgeTokensOut = (upstreamJson?.usage?.completion_tokens as number | undefined) ?? Math.ceil(text.length / 4); // Track against the merged OpenAI (ChatGPT+Codex) subscription pool. try { const subId = modelToSubscriptionId(parsed.data.model ?? '') ?? 'codex'; - void recordSubscriptionUsage(getPool(), subId, 0); + void recordSubscriptionUsage(getPool(), subId, bridgeTokensIn + bridgeTokensOut); } catch (e) { logger.warn({ e, callId }, 'failed to record subscription usage for passthrough'); } - // Also write an audit row so the dashboard activity tab sees it. + // Write to request_tracking so dashboard token totals include bridge calls. + try { + const bridgeLogger = createRequestLogger(getPool()); + void bridgeLogger.logRequest( + callId, + bridgeCaller, + 'codex_passthrough', + parsed.data.model ?? 'gpt-5.5', + 'approved', + bridgeTokensIn, + bridgeTokensOut, + 0, + Date.now() - startMs, + 0, + false, + undefined, + ); + } catch (e) { + logger.warn({ e, callId }, 'failed to log bridge request to request_tracking'); + } + // Also write an audit row for the activity tab. try { void writeAuditLog({ callId, - caller: (request.headers['x-llm-interceptor-caller'] as string) || 'codex-app', + caller: bridgeCaller, task_type: 'codex_passthrough', status: 'approved', - tokens_in: 0, - tokens_out: text.length, + tokens_in: bridgeTokensIn, + tokens_out: bridgeTokensOut, latency_ms: Date.now() - startMs, confidence: 0, cost_usd: 0,