From a10a4bf4913dfc15f2b22e7af4f16da406cf09ad Mon Sep 17 00:00:00 2001 From: Raxxoor Date: Sat, 2 May 2026 00:24:16 +0100 Subject: [PATCH] fix(settings): restore CLI fingerprint toggles (#1863) Integrated into release/v3.7.8 --- package-lock.json | 64 +++++++------- package.json | 2 +- src/app/(dashboard)/dashboard/agents/page.tsx | 4 +- .../settings/components/RoutingTab.tsx | 83 ++++++++++++++++++- src/i18n/messages/en.json | 1 + src/shared/constants/cliCompatProviders.ts | 43 ++++++---- 6 files changed, 150 insertions(+), 47 deletions(-) diff --git a/package-lock.json b/package-lock.json index fc1e1aac60..ffb703666f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -33,7 +33,7 @@ "lowdb": "^7.0.1", "monaco-editor": "^0.55.1", "next": "^16.2.3", - "next-intl": "^4.8.3", + "next-intl": "^4.11.0", "node-machine-id": "^1.1.12", "open": "^11.0.0", "ora": "^9.1.0", @@ -1409,18 +1409,18 @@ "license": "MIT" }, "node_modules/@formatjs/icu-messageformat-parser": { - "version": "3.5.5", - "resolved": "https://registry.npmjs.org/@formatjs/icu-messageformat-parser/-/icu-messageformat-parser-3.5.5.tgz", - "integrity": "sha512-ASMon8BNlKHgQQpZx84xI80EXRS90GlsEU4wEulCKCzrMtUdrfEvFc9UEYmRbvEvtFQLZ4qHXnisUy6PuFjwyA==", + "version": "3.5.6", + "resolved": "https://registry.npmjs.org/@formatjs/icu-messageformat-parser/-/icu-messageformat-parser-3.5.6.tgz", + "integrity": "sha512-04ZjRIeQCnR/h32wBP9/S7rkyy1hLAs2fXJcNwc7hseJd//K9TMBqK0ukb4dXqnALKQ9m5ruZeOD2qqEkK9ixg==", "license": "MIT", "dependencies": { - "@formatjs/icu-skeleton-parser": "2.1.5" + "@formatjs/icu-skeleton-parser": "2.1.6" } }, "node_modules/@formatjs/icu-skeleton-parser": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@formatjs/icu-skeleton-parser/-/icu-skeleton-parser-2.1.5.tgz", - "integrity": "sha512-9Kc6tMaAPZKTGevdfcvx5zT3v4BTfamo+djJE29wF6ds1QLhoA09MZNDpWMZaebWzuoOTIXhDvgmqmjSlUOGlw==", + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/@formatjs/icu-skeleton-parser/-/icu-skeleton-parser-2.1.6.tgz", + "integrity": "sha512-9f1VQ2kaaLHK0WPU1OrAmiNKCKJwyoDmwNzQXbUa6XtFBOgHZ4YZURE8sSedHmMr0kvpB75OtplB0hMYkfdwfg==", "license": "MIT" }, "node_modules/@formatjs/intl-localematcher": { @@ -8634,9 +8634,9 @@ } }, "node_modules/icu-minify": { - "version": "4.9.2", - "resolved": "https://registry.npmjs.org/icu-minify/-/icu-minify-4.9.2.tgz", - "integrity": "sha512-MYt1aKn6Hrag6KO1gns+2XUjguLnL4lUxnHZXCStB2hdml+ooYzMW1VnOkrwKg5aTh5fGjvfZsgJ9DYC21lTmg==", + "version": "4.11.0", + "resolved": "https://registry.npmjs.org/icu-minify/-/icu-minify-4.11.0.tgz", + "integrity": "sha512-XRvblCwLqWXio5ZLcmDqXvJv7alSACK6UjXuuMOdQWB//d25AQX6xlVlI1FEbc3Q6iPLXXo6HaVLn8LcAFhn1Q==", "funding": [ { "type": "individual", @@ -8767,15 +8767,21 @@ } }, "node_modules/intl-messageformat": { - "version": "11.2.2", - "resolved": "https://registry.npmjs.org/intl-messageformat/-/intl-messageformat-11.2.2.tgz", - "integrity": "sha512-yUfyIkPGqMvvk2onw2xBJeLsjXdiYUYebR8mmZVQYBuZUJsFGVht48Ftm1khgu8EZ0n+izX4rAEj3fLAilkh9g==", + "version": "11.2.3", + "resolved": "https://registry.npmjs.org/intl-messageformat/-/intl-messageformat-11.2.3.tgz", + "integrity": "sha512-kZthTU+3WLcoWoRg5j6LOkN1TeUBtmkX0OIwSAbcHVIfQAEbGVdmANM8u6GL3eUDOqLwheYoXMUshAh1UdeXlQ==", "license": "BSD-3-Clause", "dependencies": { - "@formatjs/fast-memoize": "3.1.2", - "@formatjs/icu-messageformat-parser": "3.5.5" + "@formatjs/fast-memoize": "3.1.3", + "@formatjs/icu-messageformat-parser": "3.5.6" } }, + "node_modules/intl-messageformat/node_modules/@formatjs/fast-memoize": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/@formatjs/fast-memoize/-/fast-memoize-3.1.3.tgz", + "integrity": "sha512-Ocd1vPuD68rW6BJDuAOtnnc1GPeVepY5kZXML1psGVFQ+1Q8CfkftT3Tnam+Mxx97Pz08jIEDCotl/GV+Naccg==", + "license": "MIT" + }, "node_modules/ip-address": { "version": "10.1.0", "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-10.1.0.tgz", @@ -11160,9 +11166,9 @@ } }, "node_modules/next-intl": { - "version": "4.9.2", - "resolved": "https://registry.npmjs.org/next-intl/-/next-intl-4.9.2.tgz", - "integrity": "sha512-AZoMRsVGLZczB2hisq1OTWmNAYAKwk/jaWH4+9pfl5TCG8kbILZZptZHux9zw7DyN1yzh6X7jmaQvoykHs9Y7Q==", + "version": "4.11.0", + "resolved": "https://registry.npmjs.org/next-intl/-/next-intl-4.11.0.tgz", + "integrity": "sha512-Chp8rgEVUYOX/bCtYy+PXH6lDX3X+GPT9sR9HScHroL283em/4urP9btfdHEMEHJJXdq2W/5wDaDDtWONPdNSA==", "funding": [ { "type": "individual", @@ -11174,11 +11180,11 @@ "@formatjs/intl-localematcher": "^0.8.1", "@parcel/watcher": "^2.4.1", "@swc/core": "^1.15.2", - "icu-minify": "^4.9.2", + "icu-minify": "^4.11.0", "negotiator": "^1.0.0", - "next-intl-swc-plugin-extractor": "^4.9.2", + "next-intl-swc-plugin-extractor": "^4.11.0", "po-parser": "^2.1.1", - "use-intl": "^4.9.2" + "use-intl": "^4.11.0" }, "peerDependencies": { "next": "^12.0.0 || ^13.0.0 || ^14.0.0 || ^15.0.0 || ^16.0.0", @@ -11191,9 +11197,9 @@ } }, "node_modules/next-intl-swc-plugin-extractor": { - "version": "4.9.2", - "resolved": "https://registry.npmjs.org/next-intl-swc-plugin-extractor/-/next-intl-swc-plugin-extractor-4.9.2.tgz", - "integrity": "sha512-VMlEe18tvYgl+2Fl+/hOKckm0Z0EZooBLt3nFjDMva+gopFwZYhNeLBDrc/R8rulWvwBxz8LN+uKPFSQ0fFJ4A==", + "version": "4.11.0", + "resolved": "https://registry.npmjs.org/next-intl-swc-plugin-extractor/-/next-intl-swc-plugin-extractor-4.11.0.tgz", + "integrity": "sha512-WUGBSxGNd8eQ0rAsJHFmRw2H7+SZAXQIY/HAnYM57JaUsj5D2vx4KOz4zFtXlyKDtsw9awHfgWVvBae2/RDF9A==", "license": "MIT" }, "node_modules/next/node_modules/@swc/helpers": { @@ -14346,9 +14352,9 @@ } }, "node_modules/use-intl": { - "version": "4.9.2", - "resolved": "https://registry.npmjs.org/use-intl/-/use-intl-4.9.2.tgz", - "integrity": "sha512-/FCW/P/wJCv6oGTUOWLNvv+i2uowOg7r/1HAZSBfwbcNoBe5tzXgh9uZaoEKaRl9t7MnZqrDNgEJoYd+1ko1oQ==", + "version": "4.11.0", + "resolved": "https://registry.npmjs.org/use-intl/-/use-intl-4.11.0.tgz", + "integrity": "sha512-7ILhTLuo3fnSKhoTGDk5X9591pjtWr6qB4inrlvGkN9OEyKhoiG73GZFoLSs68wz3BsSGtoWa62iWvrYEYU+iA==", "funding": [ { "type": "individual", @@ -14359,7 +14365,7 @@ "dependencies": { "@formatjs/fast-memoize": "^3.1.0", "@schummar/icu-type-parser": "1.21.5", - "icu-minify": "^4.9.2", + "icu-minify": "^4.11.0", "intl-messageformat": "^11.1.0" }, "peerDependencies": { diff --git a/package.json b/package.json index 41cec7a351..0b0259596f 100644 --- a/package.json +++ b/package.json @@ -127,7 +127,7 @@ "lowdb": "^7.0.1", "monaco-editor": "^0.55.1", "next": "^16.2.3", - "next-intl": "^4.8.3", + "next-intl": "^4.11.0", "node-machine-id": "^1.1.12", "open": "^11.0.0", "ora": "^9.1.0", diff --git a/src/app/(dashboard)/dashboard/agents/page.tsx b/src/app/(dashboard)/dashboard/agents/page.tsx index b030b297c7..0df7fd0e8b 100644 --- a/src/app/(dashboard)/dashboard/agents/page.tsx +++ b/src/app/(dashboard)/dashboard/agents/page.tsx @@ -403,8 +403,8 @@ export default function AgentsPage() { fingerprint

{t("fingerprintSettingsHint")}{" "} - - {t("openSettings")} + + {t("settingsRoutingLink")}

diff --git a/src/app/(dashboard)/dashboard/settings/components/RoutingTab.tsx b/src/app/(dashboard)/dashboard/settings/components/RoutingTab.tsx index 2430de8ad5..ca886cddf0 100644 --- a/src/app/(dashboard)/dashboard/settings/components/RoutingTab.tsx +++ b/src/app/(dashboard)/dashboard/settings/components/RoutingTab.tsx @@ -1,9 +1,14 @@ "use client"; -import { useEffect, useState } from "react"; +import { useEffect, useMemo, useState } from "react"; import { Button, Card } from "@/shared/components"; import { useTranslations } from "next-intl"; import FallbackChainsEditor from "./FallbackChainsEditor"; +import { + CLI_COMPAT_PROVIDER_DISPLAY, + CLI_COMPAT_TOGGLE_IDS, + normalizeCliCompatProviderId, +} from "@/shared/constants/cliCompatProviders"; export default function RoutingTab() { const [settings, setSettings] = useState({ @@ -40,6 +45,26 @@ export default function RoutingTab() { } }; + const cliCompatProviders = useMemo( + () => + Array.isArray(settings.cliCompatProviders) + ? settings.cliCompatProviders.map((providerId: string) => normalizeCliCompatProviderId(providerId)) + : [], + [settings.cliCompatProviders] + ); + const cliCompatProviderSet = useMemo(() => new Set(cliCompatProviders), [cliCompatProviders]); + + const toggleCliCompatProvider = (providerId: string, enabled: boolean) => { + const normalizedProviderId = normalizeCliCompatProviderId(providerId); + const nextProviders = new Set(cliCompatProviders); + if (enabled) { + nextProviders.add(normalizedProviderId); + } else { + nextProviders.delete(normalizedProviderId); + } + updateSetting({ cliCompatProviders: Array.from(nextProviders) }); + }; + return (
@@ -224,6 +249,62 @@ export default function RoutingTab() {
+ +
+
+ +
+
+

{t("cliFingerprint")}

+

{t("cliFingerprintDesc")}

+

+ {t("cliFingerprintEnabled", { count: cliCompatProviderSet.size })} +

+
+
+ +
+ {CLI_COMPAT_TOGGLE_IDS.map((providerId) => { + const normalizedProviderId = normalizeCliCompatProviderId(providerId); + const providerDisplay = CLI_COMPAT_PROVIDER_DISPLAY[providerId]; + const checked = cliCompatProviderSet.has(normalizedProviderId); + const label = providerDisplay?.name || providerId; + const description = providerDisplay?.description || providerId; + + return ( + + ); + })} +
+
+
diff --git a/src/i18n/messages/en.json b/src/i18n/messages/en.json index f1a6e3dc9e..d61db2dfc3 100644 --- a/src/i18n/messages/en.json +++ b/src/i18n/messages/en.json @@ -4669,6 +4669,7 @@ "flowDiagramCli": "CLI Agent", "flowDiagramCliDesc": "Processes with own auth/model", "fingerprintSettingsHint": "CLI Fingerprint matching (disguise requests as specific CLI tools) can be configured in", + "settingsRoutingLink": "Settings/Routing", "openSettings": "Settings" }, "templateNames": { diff --git a/src/shared/constants/cliCompatProviders.ts b/src/shared/constants/cliCompatProviders.ts index 1cbd51c9d3..8dc7c25195 100644 --- a/src/shared/constants/cliCompatProviders.ts +++ b/src/shared/constants/cliCompatProviders.ts @@ -1,4 +1,3 @@ -import { CLI_TOOLS } from "./cliTools"; import { normalizeCliCompatProviderId } from "../utils/cliCompat"; export { normalizeCliCompatProviderId }; @@ -53,21 +52,37 @@ export const CLI_COMPAT_OMITTED_PROVIDER_IDS = [ * Provider IDs toggled in Settings -> CLI Fingerprint. * * Source of truth: - * - derive from visible CLI tools when a provider mapping exists - * - keep legacy-compatible IDs that are still used by existing setups + * - expose only providers with an implemented `CLI_FINGERPRINTS` entry + * - keep legacy-compatible display IDs such as `copilot` while persisting normalized provider IDs */ -const TOOL_ID_TO_PROVIDER_ID: Record = { - kilo: "kilocode", - copilot: "github", -}; - -const DERIVED_PROVIDER_IDS = Object.values(CLI_TOOLS) - .map((tool: any) => normalizeCliCompatProviderId(TOOL_ID_TO_PROVIDER_ID[tool.id] ?? tool.id)) - // "continue" currently has no provider id in AI_PROVIDERS - .filter((providerId) => IMPLEMENTED_CLI_FINGERPRINT_PROVIDER_IDS.includes(providerId as any)); - export const CLI_COMPAT_PROVIDER_IDS = Array.from( - new Set([...DERIVED_PROVIDER_IDS, ...IMPLEMENTED_CLI_FINGERPRINT_PROVIDER_IDS]) + new Set([...IMPLEMENTED_CLI_FINGERPRINT_PROVIDER_IDS]) ); export const CLI_COMPAT_TOGGLE_IDS = Array.from(new Set(CLI_COMPAT_DISPLAY_PROVIDER_IDS)); + +export const CLI_COMPAT_PROVIDER_DISPLAY: Record< + (typeof CLI_COMPAT_DISPLAY_PROVIDER_IDS)[number], + { name: string; description: string } +> = { + claude: { + name: "Claude Code", + description: "Anthropic Claude Code CLI", + }, + codex: { + name: "OpenAI Codex CLI", + description: "OpenAI Codex CLI", + }, + copilot: { + name: "GitHub Copilot", + description: "GitHub Copilot CLI compatibility", + }, + antigravity: { + name: "Antigravity", + description: "Google Antigravity IDE compatibility", + }, + qwen: { + name: "Qwen Code / Qoder", + description: "Qwen Code and Qoder CLI compatibility", + }, +};