diff --git a/src/api/providers/openrouter.ts b/src/api/providers/openrouter.ts index 1202d535f11..e8e95ad58df 100644 --- a/src/api/providers/openrouter.ts +++ b/src/api/providers/openrouter.ts @@ -29,7 +29,6 @@ import { BaseProvider } from "./base-provider" import type { ApiHandlerCreateMessageMetadata, SingleCompletionHandler } from "../index" import { handleOpenAIError } from "./utils/openai-error-handler" import { generateImageWithProvider, ImageGenerationResult } from "./utils/image-generation" -import { sanitizeReasoningDetailId } from "./utils/sanitize-reasoning-id" // Add custom interface for OpenRouter params. type OpenRouterChatCompletionParams = OpenAI.Chat.ChatCompletionCreateParams & { @@ -287,18 +286,18 @@ export class OpenRouterHandler extends BaseProvider implements SingleCompletionH if (detail.data !== undefined) { existing.data = (existing.data || "") + detail.data } - // Update other fields if provided - sanitize ID to remove invalid characters - if (detail.id !== undefined) existing.id = sanitizeReasoningDetailId(detail.id) + // Update other fields if provided + if (detail.id !== undefined) existing.id = detail.id if (detail.format !== undefined) existing.format = detail.format if (detail.signature !== undefined) existing.signature = detail.signature } else { - // Start new reasoning detail accumulation - sanitize ID to remove invalid characters + // Start new reasoning detail accumulation reasoningDetailsAccumulator.set(key, { type: detail.type, text: detail.text, summary: detail.summary, data: detail.data, - id: sanitizeReasoningDetailId(detail.id), + id: detail.id, format: detail.format, signature: detail.signature, index, diff --git a/src/api/providers/roo.ts b/src/api/providers/roo.ts index ac8957f010d..f7f9a9db183 100644 --- a/src/api/providers/roo.ts +++ b/src/api/providers/roo.ts @@ -19,7 +19,6 @@ import { MODEL_DEFAULTS } from "../providers/fetchers/roo" import { handleOpenAIError } from "./utils/openai-error-handler" import { generateImageWithProvider, generateImageWithImagesApi, ImageGenerationResult } from "./utils/image-generation" import { t } from "../../i18n" -import { sanitizeReasoningDetailId } from "./utils/sanitize-reasoning-id" // Extend OpenAI's CompletionUsage to include Roo specific fields interface RooUsage extends OpenAI.CompletionUsage { @@ -194,18 +193,18 @@ export class RooHandler extends BaseOpenAiCompatibleProvider { if (detail.data !== undefined) { existing.data = (existing.data || "") + detail.data } - // Update other fields if provided - sanitize ID to remove invalid characters - if (detail.id !== undefined) existing.id = sanitizeReasoningDetailId(detail.id) + // Update other fields if provided + if (detail.id !== undefined) existing.id = detail.id if (detail.format !== undefined) existing.format = detail.format if (detail.signature !== undefined) existing.signature = detail.signature } else { - // Start new reasoning detail accumulation - sanitize ID to remove invalid characters + // Start new reasoning detail accumulation reasoningDetailsAccumulator.set(key, { type: detail.type, text: detail.text, summary: detail.summary, data: detail.data, - id: sanitizeReasoningDetailId(detail.id), + id: detail.id, format: detail.format, signature: detail.signature, index, diff --git a/src/api/providers/utils/__tests__/sanitize-reasoning-id.spec.ts b/src/api/providers/utils/__tests__/sanitize-reasoning-id.spec.ts deleted file mode 100644 index 2418e33c5f6..00000000000 --- a/src/api/providers/utils/__tests__/sanitize-reasoning-id.spec.ts +++ /dev/null @@ -1,59 +0,0 @@ -import { sanitizeReasoningDetailId } from "../sanitize-reasoning-id" - -describe("sanitizeReasoningDetailId", () => { - it("should return null for null input", () => { - expect(sanitizeReasoningDetailId(null)).toBeNull() - }) - - it("should return undefined for undefined input", () => { - expect(sanitizeReasoningDetailId(undefined)).toBeUndefined() - }) - - it("should return empty string for empty string input", () => { - expect(sanitizeReasoningDetailId("")).toBe("") - }) - - it("should not modify IDs with only valid characters", () => { - expect(sanitizeReasoningDetailId("abc123")).toBe("abc123") - expect(sanitizeReasoningDetailId("test_id")).toBe("test_id") - expect(sanitizeReasoningDetailId("test-id")).toBe("test-id") - expect(sanitizeReasoningDetailId("ABC_123-test")).toBe("ABC_123-test") - }) - - it("should replace colons with underscores", () => { - expect(sanitizeReasoningDetailId("rs_033ca40017d1ad93016931b1d2bf7481a2969fd5c1835cb1d3:4")).toBe( - "rs_033ca40017d1ad93016931b1d2bf7481a2969fd5c1835cb1d3_4", - ) - }) - - it("should replace multiple invalid characters", () => { - expect(sanitizeReasoningDetailId("test:1:2:3")).toBe("test_1_2_3") - }) - - it("should replace other special characters with underscores", () => { - expect(sanitizeReasoningDetailId("test@id")).toBe("test_id") - expect(sanitizeReasoningDetailId("test.id")).toBe("test_id") - expect(sanitizeReasoningDetailId("test#id")).toBe("test_id") - expect(sanitizeReasoningDetailId("test$id")).toBe("test_id") - expect(sanitizeReasoningDetailId("test%id")).toBe("test_id") - expect(sanitizeReasoningDetailId("test^id")).toBe("test_id") - expect(sanitizeReasoningDetailId("test&id")).toBe("test_id") - expect(sanitizeReasoningDetailId("test*id")).toBe("test_id") - expect(sanitizeReasoningDetailId("test+id")).toBe("test_id") - expect(sanitizeReasoningDetailId("test=id")).toBe("test_id") - expect(sanitizeReasoningDetailId("test id")).toBe("test_id") - }) - - it("should handle mixed valid and invalid characters", () => { - expect(sanitizeReasoningDetailId("rs_abc:1@2#3")).toBe("rs_abc_1_2_3") - }) - - it("should handle IDs starting with valid characters followed by invalid ones", () => { - expect(sanitizeReasoningDetailId("valid_start:invalid")).toBe("valid_start_invalid") - }) - - it("should handle consecutive invalid characters", () => { - expect(sanitizeReasoningDetailId("test::id")).toBe("test__id") - expect(sanitizeReasoningDetailId("test:::id")).toBe("test___id") - }) -}) diff --git a/src/api/providers/utils/sanitize-reasoning-id.ts b/src/api/providers/utils/sanitize-reasoning-id.ts deleted file mode 100644 index 03c58b4a313..00000000000 --- a/src/api/providers/utils/sanitize-reasoning-id.ts +++ /dev/null @@ -1,16 +0,0 @@ -/** - * Sanitizes reasoning detail IDs to only contain allowed characters. - * The OpenAI Responses API only allows IDs containing letters, numbers, underscores, or dashes. - * This function replaces any invalid characters (like colons from IDs like "rs_xxx:4") with underscores. - * - * @param id - The original ID that may contain invalid characters - * @returns The sanitized ID with only allowed characters, or undefined if input is undefined/null - */ -export function sanitizeReasoningDetailId(id: string | null | undefined): string | null | undefined { - if (id === null || id === undefined) { - return id - } - - // Replace any character that is not a letter, number, underscore, or dash with an underscore - return id.replace(/[^a-zA-Z0-9_-]/g, "_") -}