mirror of
https://github.com/Nezumi-2711/9router.git
synced 2026-09-22 13:38:31 +00:00
# v0.4.30 (2026-05-11)
## Features - MCP stdio→SSE bridge: expose local stdio MCP plugins over SSE (api/mcp/[plugin]/sse, /message) - Dynamic Linux cert resolution + NSS DB injection (Debian/Arch/Fedora/openSUSE, Chrome/Chromium/Firefox incl. snap) (#1010) - Cowork tool: expanded settings UI & API - GitBook docs (DocsContent, DocsLayout) ## Fixes - OAuth callback postMessage scoped to expected origins (CWE-1385) (#998) - Re-enable TLS verification on DNS-bypass fetch (CWE-295) (#998) - Normalize `developer` role → `system` for OpenAI-format providers (Deepseek, Groq, …) (#1011, closes #773) - Respect `PORT` env in internal model-test fetch (#1014) - Dropdown text readability in dark theme on usage page (#997) ## Improvements - Refactor Claude CLI spoof headers into shared constant - Tool deduper utility in open-sse handlers
This commit is contained in:
@@ -16,6 +16,7 @@ import { handleForcedSSEToJson } from "./chatCore/sseToJsonHandler.js";
|
||||
import { handleNonStreamingResponse } from "./chatCore/nonStreamingHandler.js";
|
||||
import { handleStreamingResponse, buildOnStreamComplete } from "./chatCore/streamingHandler.js";
|
||||
import { detectClientTool, isNativePassthrough } from "../utils/clientDetector.js";
|
||||
import { dedupeTools } from "../utils/toolDeduper.js";
|
||||
import { injectCaveman } from "../rtk/caveman.js";
|
||||
import { compressMessages, formatRtkLog } from "../rtk/index.js";
|
||||
|
||||
@@ -94,6 +95,15 @@ export async function handleChatCore({ body, modelInfo, credentials, log, onCred
|
||||
translatedBody.model = model;
|
||||
}
|
||||
|
||||
// Dedupe duplicate built-in tools when equivalent MCP tools are present (Claude clients only).
|
||||
if (clientTool === "claude" && Array.isArray(translatedBody.tools)) {
|
||||
const { tools: deduped, stripped } = dedupeTools(translatedBody.tools);
|
||||
if (stripped.length > 0) {
|
||||
translatedBody.tools = deduped;
|
||||
log?.debug?.("TOOLDEDUP", `stripped ${stripped.length}: ${stripped.slice(0, 3).join(", ")}${stripped.length > 3 ? "..." : ""}`);
|
||||
}
|
||||
}
|
||||
|
||||
// Token savers: applied at the final body just before dispatch
|
||||
// Covers both passthrough (source shape) and translated (target shape) flows
|
||||
const finalFormat = passthrough ? sourceFormat : targetFormat;
|
||||
|
||||
Reference in New Issue
Block a user