Skip to content

Commit cbd0b1c

Browse files
committed
refactor: harden open-sse services, eliminate any casts, add dashboard pages
- Replace all `as any` casts in MCP advancedTools with typed helpers (toRecord, toString, toNumber) - Harden open-sse services: rateLimitManager, sessionManager, usage, roleNormalizer, signatureCache, comboMetrics - Improve responseSanitizer and responseTranslator type safety - Remove deprecated openai-responses request translator - Add dashboard pages: /a2a, /mcp, /auto-combo with live data - Improve error/loading/not-found pages with consistent design - Add root loading.tsx and typecheck tsconfig variants - Add check-t11-any-budget.mjs audit script
1 parent 889e2ba commit cbd0b1c

39 files changed

+1529
-826
lines changed

open-sse/handlers/responseSanitizer.ts

Lines changed: 116 additions & 97 deletions
Original file line numberDiff line numberDiff line change
@@ -9,17 +9,6 @@
99
* 4. Converts developer role → system for non-OpenAI providers
1010
*/
1111

12-
// ── Standard OpenAI ChatCompletion fields ──────────────────────────────────
13-
const ALLOWED_TOP_LEVEL_FIELDS = new Set([
14-
"id",
15-
"object",
16-
"created",
17-
"model",
18-
"choices",
19-
"usage",
20-
"system_fingerprint",
21-
]);
22-
2312
const ALLOWED_USAGE_FIELDS = new Set([
2413
"prompt_tokens",
2514
"completion_tokens",
@@ -28,16 +17,20 @@ const ALLOWED_USAGE_FIELDS = new Set([
2817
"completion_tokens_details",
2918
]);
3019

31-
const ALLOWED_MESSAGE_FIELDS = new Set([
32-
"role",
33-
"content",
34-
"tool_calls",
35-
"function_call",
36-
"refusal",
37-
"reasoning_content",
38-
]);
20+
type JsonRecord = Record<string, unknown>;
21+
22+
function toRecord(value: unknown): JsonRecord | null {
23+
if (!value || typeof value !== "object" || Array.isArray(value)) return null;
24+
return value as JsonRecord;
25+
}
26+
27+
function toString(value: unknown): string | undefined {
28+
return typeof value === "string" ? value : undefined;
29+
}
3930

40-
const ALLOWED_CHOICE_FIELDS = new Set(["index", "message", "delta", "finish_reason", "logprobs"]);
31+
function toNumber(value: unknown): number | undefined {
32+
return typeof value === "number" && Number.isFinite(value) ? value : undefined;
33+
}
4134

4235
// ── Think tag regex ────────────────────────────────────────────────────────
4336
// Matches <think>...</think> blocks (greedy, dotAll)
@@ -81,33 +74,34 @@ export function extractThinkingFromContent(text: string): {
8174
* Sanitize a non-streaming OpenAI ChatCompletion response.
8275
* Strips non-standard fields and normalizes required fields.
8376
*/
84-
export function sanitizeOpenAIResponse(body: any): any {
85-
if (!body || typeof body !== "object") return body;
77+
export function sanitizeOpenAIResponse(body: unknown): unknown {
78+
const bodyRecord = toRecord(body);
79+
if (!bodyRecord) return body;
8680

8781
// Build sanitized response with only allowed top-level fields
88-
const sanitized: Record<string, any> = {};
82+
const sanitized: JsonRecord = {};
8983

9084
// Ensure required fields exist
91-
sanitized.id = normalizeResponseId(body.id);
92-
sanitized.object = body.object || "chat.completion";
93-
sanitized.created = body.created || Math.floor(Date.now() / 1000);
94-
sanitized.model = body.model || "unknown";
85+
sanitized.id = normalizeResponseId(bodyRecord.id);
86+
sanitized.object = toString(bodyRecord.object) || "chat.completion";
87+
sanitized.created = toNumber(bodyRecord.created) ?? Math.floor(Date.now() / 1000);
88+
sanitized.model = toString(bodyRecord.model) || "unknown";
9589

9690
// Sanitize choices
97-
if (Array.isArray(body.choices)) {
98-
sanitized.choices = body.choices.map((choice: any, idx: number) => sanitizeChoice(choice, idx));
91+
if (Array.isArray(bodyRecord.choices)) {
92+
sanitized.choices = bodyRecord.choices.map((choice, idx) => sanitizeChoice(choice, idx));
9993
} else {
10094
sanitized.choices = [];
10195
}
10296

10397
// Sanitize usage
104-
if (body.usage && typeof body.usage === "object") {
105-
sanitized.usage = sanitizeUsage(body.usage);
98+
if (bodyRecord.usage !== undefined) {
99+
sanitized.usage = sanitizeUsage(bodyRecord.usage);
106100
}
107101

108102
// Keep system_fingerprint if present (it's a valid OpenAI field)
109-
if (body.system_fingerprint) {
110-
sanitized.system_fingerprint = body.system_fingerprint;
103+
if (bodyRecord.system_fingerprint) {
104+
sanitized.system_fingerprint = bodyRecord.system_fingerprint;
111105
}
112106

113107
return sanitized;
@@ -116,23 +110,32 @@ export function sanitizeOpenAIResponse(body: any): any {
116110
/**
117111
* Sanitize a single choice object.
118112
*/
119-
function sanitizeChoice(choice: any, defaultIndex: number): any {
120-
const sanitized: Record<string, any> = {
121-
index: choice.index ?? defaultIndex,
122-
finish_reason: choice.finish_reason || null,
113+
function sanitizeChoice(choice: unknown, defaultIndex: number): JsonRecord {
114+
const choiceRecord = toRecord(choice);
115+
const sanitized: JsonRecord = {
116+
index: defaultIndex,
117+
finish_reason: null,
123118
};
124119

120+
if (choiceRecord?.index !== undefined) {
121+
sanitized.index = choiceRecord.index;
122+
}
123+
124+
if (choiceRecord?.finish_reason !== undefined) {
125+
sanitized.finish_reason = choiceRecord.finish_reason;
126+
}
127+
125128
// Sanitize message (non-streaming) or delta (streaming)
126-
if (choice.message) {
127-
sanitized.message = sanitizeMessage(choice.message);
129+
if (choiceRecord?.message !== undefined) {
130+
sanitized.message = sanitizeMessage(choiceRecord.message);
128131
}
129-
if (choice.delta) {
130-
sanitized.delta = sanitizeMessage(choice.delta);
132+
if (choiceRecord?.delta !== undefined) {
133+
sanitized.delta = sanitizeMessage(choiceRecord.delta);
131134
}
132135

133136
// Keep logprobs if present
134-
if (choice.logprobs !== undefined) {
135-
sanitized.logprobs = choice.logprobs;
137+
if (choiceRecord?.logprobs !== undefined) {
138+
sanitized.logprobs = choiceRecord.logprobs;
136139
}
137140

138141
return sanitized;
@@ -141,41 +144,42 @@ function sanitizeChoice(choice: any, defaultIndex: number): any {
141144
/**
142145
* Sanitize a message object, extracting <think> tags if present.
143146
*/
144-
function sanitizeMessage(msg: any): any {
145-
if (!msg || typeof msg !== "object") return msg;
147+
function sanitizeMessage(msg: unknown): unknown {
148+
const msgRecord = toRecord(msg);
149+
if (!msgRecord) return msg;
146150

147-
const sanitized: Record<string, any> = {};
151+
const sanitized: JsonRecord = {};
148152

149153
// Copy only allowed fields
150-
if (msg.role) sanitized.role = msg.role;
151-
if (msg.refusal !== undefined) sanitized.refusal = msg.refusal;
154+
if (msgRecord.role) sanitized.role = msgRecord.role;
155+
if (msgRecord.refusal !== undefined) sanitized.refusal = msgRecord.refusal;
152156

153157
// Handle content — extract <think> tags
154-
if (typeof msg.content === "string") {
155-
const { content, thinking } = extractThinkingFromContent(msg.content);
158+
if (typeof msgRecord.content === "string") {
159+
const { content, thinking } = extractThinkingFromContent(msgRecord.content);
156160
sanitized.content = content;
157161

158162
// Set reasoning_content from <think> tags (if not already set)
159-
if (thinking && !msg.reasoning_content) {
163+
if (thinking && !msgRecord.reasoning_content) {
160164
sanitized.reasoning_content = thinking;
161165
}
162-
} else if (msg.content !== undefined) {
163-
sanitized.content = msg.content;
166+
} else if (msgRecord.content !== undefined) {
167+
sanitized.content = msgRecord.content;
164168
}
165169

166170
// Preserve existing reasoning_content (from providers that natively support it)
167-
if (msg.reasoning_content && !sanitized.reasoning_content) {
168-
sanitized.reasoning_content = msg.reasoning_content;
171+
if (msgRecord.reasoning_content && !sanitized.reasoning_content) {
172+
sanitized.reasoning_content = msgRecord.reasoning_content;
169173
}
170174

171175
// Preserve tool_calls
172-
if (msg.tool_calls) {
173-
sanitized.tool_calls = msg.tool_calls;
176+
if (msgRecord.tool_calls) {
177+
sanitized.tool_calls = msgRecord.tool_calls;
174178
}
175179

176180
// Preserve function_call (legacy)
177-
if (msg.function_call) {
178-
sanitized.function_call = msg.function_call;
181+
if (msgRecord.function_call) {
182+
sanitized.function_call = msgRecord.function_call;
179183
}
180184

181185
return sanitized;
@@ -184,30 +188,33 @@ function sanitizeMessage(msg: any): any {
184188
/**
185189
* Sanitize usage object — keep only standard fields.
186190
*/
187-
function sanitizeUsage(usage: any): any {
188-
if (!usage || typeof usage !== "object") return usage;
191+
function sanitizeUsage(usage: unknown): unknown {
192+
const usageRecord = toRecord(usage);
193+
if (!usageRecord) return usage;
189194

190-
const sanitized: Record<string, any> = {};
195+
const sanitized: JsonRecord = {};
191196
for (const key of ALLOWED_USAGE_FIELDS) {
192-
if (usage[key] !== undefined) {
193-
sanitized[key] = usage[key];
197+
if (usageRecord[key] !== undefined) {
198+
sanitized[key] = usageRecord[key];
194199
}
195200
}
196201

197202
// Ensure required fields
198-
if (sanitized.prompt_tokens === undefined) sanitized.prompt_tokens = 0;
199-
if (sanitized.completion_tokens === undefined) sanitized.completion_tokens = 0;
200-
if (sanitized.total_tokens === undefined) {
201-
sanitized.total_tokens = sanitized.prompt_tokens + sanitized.completion_tokens;
202-
}
203+
const promptTokens = toNumber(sanitized.prompt_tokens) ?? 0;
204+
const completionTokens = toNumber(sanitized.completion_tokens) ?? 0;
205+
const totalTokens = toNumber(sanitized.total_tokens) ?? promptTokens + completionTokens;
206+
207+
sanitized.prompt_tokens = promptTokens;
208+
sanitized.completion_tokens = completionTokens;
209+
sanitized.total_tokens = totalTokens;
203210

204211
return sanitized;
205212
}
206213

207214
/**
208215
* Normalize response ID to use chatcmpl- prefix.
209216
*/
210-
function normalizeResponseId(id: any): string {
217+
function normalizeResponseId(id: unknown): string {
211218
if (!id || typeof id !== "string") {
212219
return `chatcmpl-${crypto.randomUUID().replace(/-/g, "").slice(0, 29)}`;
213220
}
@@ -221,48 +228,60 @@ function normalizeResponseId(id: any): string {
221228
* Sanitize a streaming SSE chunk for passthrough mode.
222229
* Lighter than full sanitization — only strips problematic extra fields.
223230
*/
224-
export function sanitizeStreamingChunk(parsed: any): any {
225-
if (!parsed || typeof parsed !== "object") return parsed;
231+
export function sanitizeStreamingChunk(parsed: unknown): unknown {
232+
const parsedRecord = toRecord(parsed);
233+
if (!parsedRecord) return parsed;
226234

227235
// Build sanitized chunk
228-
const sanitized: Record<string, any> = {};
236+
const sanitized: JsonRecord = {};
229237

230238
// Keep only standard fields
231-
if (parsed.id !== undefined) sanitized.id = parsed.id;
232-
sanitized.object = parsed.object || "chat.completion.chunk";
233-
if (parsed.created !== undefined) sanitized.created = parsed.created;
234-
if (parsed.model !== undefined) sanitized.model = parsed.model;
239+
if (parsedRecord.id !== undefined) sanitized.id = parsedRecord.id;
240+
sanitized.object = toString(parsedRecord.object) || "chat.completion.chunk";
241+
if (parsedRecord.created !== undefined) sanitized.created = parsedRecord.created;
242+
if (parsedRecord.model !== undefined) sanitized.model = parsedRecord.model;
235243

236244
// Sanitize choices with delta
237-
if (Array.isArray(parsed.choices)) {
238-
sanitized.choices = parsed.choices.map((choice: any) => {
239-
const c: Record<string, any> = {
240-
index: choice.index ?? 0,
241-
};
242-
if (choice.delta !== undefined) {
243-
c.delta = {};
244-
const delta = choice.delta;
245-
if (delta.role !== undefined) c.delta.role = delta.role;
246-
if (delta.content !== undefined) c.delta.content = delta.content;
247-
if (delta.reasoning_content !== undefined)
248-
c.delta.reasoning_content = delta.reasoning_content;
249-
if (delta.tool_calls !== undefined) c.delta.tool_calls = delta.tool_calls;
250-
if (delta.function_call !== undefined) c.delta.function_call = delta.function_call;
245+
if (Array.isArray(parsedRecord.choices)) {
246+
sanitized.choices = parsedRecord.choices.map((choice) => {
247+
const c: JsonRecord = { index: 0 };
248+
const choiceRecord = toRecord(choice);
249+
if (!choiceRecord) return c;
250+
251+
c.index = toNumber(choiceRecord.index) ?? 0;
252+
253+
if (choiceRecord.delta !== undefined) {
254+
const deltaRecord = toRecord(choiceRecord.delta);
255+
if (deltaRecord) {
256+
const delta: JsonRecord = {};
257+
if (deltaRecord.role !== undefined) delta.role = deltaRecord.role;
258+
if (deltaRecord.content !== undefined) delta.content = deltaRecord.content;
259+
if (deltaRecord.reasoning_content !== undefined) {
260+
delta.reasoning_content = deltaRecord.reasoning_content;
261+
}
262+
if (deltaRecord.tool_calls !== undefined) delta.tool_calls = deltaRecord.tool_calls;
263+
if (deltaRecord.function_call !== undefined)
264+
delta.function_call = deltaRecord.function_call;
265+
c.delta = delta;
266+
} else {
267+
c.delta = choiceRecord.delta;
268+
}
251269
}
252-
if (choice.finish_reason !== undefined) c.finish_reason = choice.finish_reason;
253-
if (choice.logprobs !== undefined) c.logprobs = choice.logprobs;
270+
271+
if (choiceRecord.finish_reason !== undefined) c.finish_reason = choiceRecord.finish_reason;
272+
if (choiceRecord.logprobs !== undefined) c.logprobs = choiceRecord.logprobs;
254273
return c;
255274
});
256275
}
257276

258277
// Sanitize usage if present
259-
if (parsed.usage && typeof parsed.usage === "object") {
260-
sanitized.usage = sanitizeUsage(parsed.usage);
278+
if (parsedRecord.usage !== undefined) {
279+
sanitized.usage = sanitizeUsage(parsedRecord.usage);
261280
}
262281

263282
// Keep system_fingerprint if present
264-
if (parsed.system_fingerprint) {
265-
sanitized.system_fingerprint = parsed.system_fingerprint;
283+
if (parsedRecord.system_fingerprint) {
284+
sanitized.system_fingerprint = parsedRecord.system_fingerprint;
266285
}
267286

268287
return sanitized;

0 commit comments

Comments
 (0)