Use getModelInfo instead of parseModel in /api/translator/translate
so custom OpenAI/Anthropic-compatible provider prefixes resolve
correctly, aligning the debug path with the runtime chat path.
Fixes#1083
Co-authored-by: Cursor <cursoragent@cursor.com>
- mask API keys in usage stats/history responses (apiKeyMasked)
- validate proxy URL scheme + reject shell metachars before env write
- escape HTML in OAuth callback page to prevent XSS
- atomic O_EXCL lock file to prevent TOCTOU race in MITM startServer
- set mitmIsRestarting guard synchronously before any await
Co-authored-by: Cursor <cursoragent@cursor.com>
Some OpenAI-compatible providers emit optional string tool parameters
as empty strings (e.g. pages: "") instead of omitting them. Claude
Code rejects pages: "" as invalid, breaking the Read tool for
non-PDF files routed through 9router.
Add sanitizeToolArguments() that parses tool-call arguments and
removes known optional empty-string fields before emitting
input_json_delta back to Claude format. Currently handles the
Read tool pages field specifically.
Includes regression test.
Fixes#1278
Co-authored-by: JoJo <noreply@github.com>