diff --git a/.gitignore b/.gitignore index 7204a35a5..c74beb7a5 100644 --- a/.gitignore +++ b/.gitignore @@ -9,6 +9,7 @@ target/ node_modules/ apps/codex-plus-manager/src-tauri/gen/ +.kiro .codex_asar_extract/ .codex_asar_extract_latest/ .superpowers/ diff --git a/Cargo.lock b/Cargo.lock index 04bcc8109..305939866 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -415,6 +415,7 @@ dependencies = [ "directories", "fs2", "futures-util", + "proptest", "reqwest 0.12.28", "rusqlite", "serde", @@ -2643,6 +2644,31 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "proptest" +version = "1.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b45fcc2344c680f5025fe57779faef368840d0bd1f42f216291f0dc4ace4744" +dependencies = [ + "bit-set", + "bit-vec", + "bitflags 2.11.1", + "num-traits", + "rand", + "rand_chacha", + "rand_xorshift", + "regex-syntax", + "rusty-fork", + "tempfile", + "unarray", +] + +[[package]] +name = "quick-error" +version = "1.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" + [[package]] name = "quick-xml" version = "0.39.4" @@ -2766,6 +2792,15 @@ dependencies = [ "getrandom 0.3.4", ] +[[package]] +name = "rand_xorshift" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "513962919efc330f829edb2535844d1b912b0fbe2ca165d613e4e8788bb05a5a" +dependencies = [ + "rand_core 0.9.5", +] + [[package]] name = "raw-window-handle" version = "0.6.2" @@ -3037,6 +3072,18 @@ version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" +[[package]] +name = "rusty-fork" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc6bf79ff24e648f6da1f8d1f011e9cac26491b619e6b9280f2b47f1774e6ee2" +dependencies = [ + "fnv", + "quick-error", + "tempfile", + "wait-timeout", +] + [[package]] name = "ryu" version = "1.0.23" @@ -4331,6 +4378,12 @@ version = "1.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "40ce102ab67701b8526c123c1bab5cbe42d7040ccfd0f64af1a385808d2f43de" +[[package]] +name = "unarray" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eaea85b334db583fe3274d12b4cd1880032beab409c0d774be044d4480ab9a94" + [[package]] name = "unic-char-property" version = "0.9.0" @@ -4493,6 +4546,15 @@ dependencies = [ "libc", ] +[[package]] +name = "wait-timeout" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ac3b126d3914f9849036f826e054cbabdc8519970b8998ddaf3b5bd3c65f11" +dependencies = [ + "libc", +] + [[package]] name = "walkdir" version = "2.5.0" diff --git a/apps/codex-plus-manager/package-lock.json b/apps/codex-plus-manager/package-lock.json index 351aa4f57..8c238dc8e 100644 --- a/apps/codex-plus-manager/package-lock.json +++ b/apps/codex-plus-manager/package-lock.json @@ -32,6 +32,7 @@ "@types/react": "^19.0.0", "@types/react-dom": "^19.0.0", "@vitejs/plugin-react": "^4.3.4", + "fast-check": "4.8.0", "tailwindcss": "^4.0.0" } }, @@ -2086,6 +2087,29 @@ "node": ">=6" } }, + "node_modules/fast-check": { + "version": "4.8.0", + "resolved": "https://registry.npmjs.org/fast-check/-/fast-check-4.8.0.tgz", + "integrity": "sha512-GOJ158CUMnN6cSahsv4+ExARvIDuzzinFjkp0E9WtiBa5zcVeLozVkWaE4IzFcc+Y48Wp1EDlUZsXRyAztQcSg==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/dubzzz" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fast-check" + } + ], + "license": "MIT", + "dependencies": { + "pure-rand": "^8.0.0" + }, + "engines": { + "node": ">=12.17.0" + } + }, "node_modules/fdir": { "version": "6.5.0", "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", @@ -2537,6 +2561,23 @@ "node": "^10 || ^12 || >=14" } }, + "node_modules/pure-rand": { + "version": "8.4.1", + "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-8.4.1.tgz", + "integrity": "sha512-c58R2+SPFcSIPXoU834QN/KPDDOSd8sXcSrqf6e83Me6Rrp1EYkxukkjXMVrKvKaADs1SOyNkWdfvLf6zY8qLQ==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/dubzzz" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fast-check" + } + ], + "license": "MIT" + }, "node_modules/react": { "version": "19.2.6", "resolved": "https://registry.npmjs.org/react/-/react-19.2.6.tgz", diff --git a/apps/codex-plus-manager/package.json b/apps/codex-plus-manager/package.json index 9b461d5cc..4e5afbdcf 100644 --- a/apps/codex-plus-manager/package.json +++ b/apps/codex-plus-manager/package.json @@ -35,6 +35,7 @@ "@types/react": "^19.0.0", "@types/react-dom": "^19.0.0", "@vitejs/plugin-react": "^4.3.4", + "fast-check": "4.8.0", "tailwindcss": "^4.0.0" } } diff --git a/apps/codex-plus-manager/src/App.tsx b/apps/codex-plus-manager/src/App.tsx index 11a2c709b..4a073ed73 100644 --- a/apps/codex-plus-manager/src/App.tsx +++ b/apps/codex-plus-manager/src/App.tsx @@ -54,6 +54,7 @@ import { } from "lucide-react"; import { ProviderPresetSelector } from "@/components/ProviderPresetSelector"; import type { PresetPatch } from "@/components/ProviderPresetSelector"; +import { BedrockRelayProfileEditor } from "@/components/BedrockRelayProfileEditor"; import { useEffect, useMemo, useRef, useState, type CSSProperties, type ReactNode } from "react"; import { Badge as UiBadge } from "@/components/ui/badge"; @@ -68,6 +69,8 @@ import { serializeModelWindowRows, type ModelWindowRow, } from "./model-windows"; +import type { BedrockConfig } from "./bedrock-config"; +import { isBedrockRelayProfile, bedrockAllowsProviderTesting, resolveBedrockAfterDerive, bedrockValidationError } from "./bedrock-config"; import { getLanguage, t, tf, toggleLanguage } from "@/i18n"; type Status = "ok" | "failed" | "not_implemented" | "not_checked" | string; @@ -210,6 +213,7 @@ export type RelayProfile = { modelWindows: string; userAgent: string; aggregate?: RelayAggregateConfig | null; + bedrock?: BedrockConfig | null; }; type RelayAggregateStrategy = "failover" | "conversationRoundRobin" | "requestRoundRobin" | "weightedRoundRobin"; @@ -3762,14 +3766,20 @@ function SortableRelayProfileCard({