mirror of
https://github.com/bytedance/deer-flow.git
synced 2026-10-26 05:06:59 +00:00
fix(models): preserve keys after reverted connection edits (#6813)
This commit is contained in:
parent
b74e3842f7
commit
294de7cefd
@ -212,7 +212,6 @@ function ModelEditor({
|
||||
const [draft, setDraft] = useState(() => modelDraft(model));
|
||||
const [key, setKey] = useState("");
|
||||
const [clearKey, setClearKey] = useState(false);
|
||||
const [connectionChanged, setConnectionChanged] = useState(false);
|
||||
const [pending, setPending] = useState(false);
|
||||
const [result, setResult] = useState("");
|
||||
const active = useRef(true);
|
||||
@ -229,7 +228,7 @@ function ModelEditor({
|
||||
model?.provider === draft.provider &&
|
||||
(draft.provider !== "openai-compatible" ||
|
||||
model?.base_url === draft.base_url);
|
||||
const canKeepKey = sameConnection && !connectionChanged && model?.has_api_key;
|
||||
const canKeepKey = sameConnection && model?.has_api_key;
|
||||
const requiresKey =
|
||||
provider?.requires_api_key ?? draft.provider !== "openai-compatible";
|
||||
const missingKey = requiresKey && ((!key.trim() && !canKeepKey) || clearKey);
|
||||
@ -246,7 +245,6 @@ function ModelEditor({
|
||||
...(value === "openai-compatible" ? { base_url: "" } : {}),
|
||||
});
|
||||
setKey("");
|
||||
setConnectionChanged(true);
|
||||
setClearKey(false);
|
||||
setResult("");
|
||||
abort.current?.abort();
|
||||
@ -255,11 +253,7 @@ function ModelEditor({
|
||||
return {
|
||||
config: {
|
||||
...draft,
|
||||
...(clearKey || (connectionChanged && !key)
|
||||
? { api_key: "" }
|
||||
: key
|
||||
? { api_key: key }
|
||||
: {}),
|
||||
...(clearKey ? { api_key: "" } : key ? { api_key: key } : {}),
|
||||
},
|
||||
expected_revision: model?.revision ?? null,
|
||||
};
|
||||
@ -345,14 +339,13 @@ function ModelEditor({
|
||||
onChange={(e) => {
|
||||
setDraft({ ...draft, base_url: e.target.value });
|
||||
setKey("");
|
||||
setConnectionChanged(true);
|
||||
setClearKey(false);
|
||||
setResult("");
|
||||
}}
|
||||
/>
|
||||
</label>
|
||||
)}
|
||||
{model && (connectionChanged || !sameConnection) && (
|
||||
{model && !sameConnection && (
|
||||
<p role="status">{text.providerChanged}</p>
|
||||
)}
|
||||
<label className="block space-y-1">
|
||||
|
||||
@ -264,6 +264,27 @@ test("switching providers clears test status and cannot reuse a saved key", asyn
|
||||
).not.toHaveProperty("base_url");
|
||||
});
|
||||
|
||||
test("reverting a provider switch preserves the saved key", async () => {
|
||||
rs.mocked(loadManagedModels).mockResolvedValue({
|
||||
models: [{ ...existing, provider: "openai", base_url: null }],
|
||||
});
|
||||
mount();
|
||||
fireEvent.click(await screen.findByRole("button", { name: "Edit model" }));
|
||||
await selectProvider("Anthropic");
|
||||
await selectProvider("OpenAI");
|
||||
|
||||
expect(screen.queryByText(enUS.settings.models.providerChanged)).toBeNull();
|
||||
expect(
|
||||
screen.getByPlaceholderText(enUS.settings.models.keepKey),
|
||||
).toBeTruthy();
|
||||
|
||||
fireEvent.click(screen.getByRole("button", { name: "Save" }));
|
||||
await waitFor(() => expect(saveManagedModel).toHaveBeenCalledTimes(1));
|
||||
expect(
|
||||
rs.mocked(saveManagedModel).mock.calls[0]![0].config,
|
||||
).not.toHaveProperty("api_key");
|
||||
});
|
||||
|
||||
test("custom endpoint is separate and allows no authentication", async () => {
|
||||
mount();
|
||||
await waitFor(() =>
|
||||
@ -289,6 +310,29 @@ test("custom endpoint is separate and allows no authentication", async () => {
|
||||
});
|
||||
});
|
||||
|
||||
test("reverting a custom endpoint edit preserves the saved key", async () => {
|
||||
mount();
|
||||
fireEvent.click(await screen.findByRole("button", { name: "Edit model" }));
|
||||
const endpoint = screen.getByLabelText("Base URL");
|
||||
fireEvent.change(endpoint, {
|
||||
target: { value: "https://other.example.com/v1" },
|
||||
});
|
||||
fireEvent.change(endpoint, {
|
||||
target: { value: existing.base_url },
|
||||
});
|
||||
|
||||
expect(screen.queryByText(enUS.settings.models.providerChanged)).toBeNull();
|
||||
expect(
|
||||
screen.getByPlaceholderText(enUS.settings.models.keepKey),
|
||||
).toBeTruthy();
|
||||
|
||||
fireEvent.click(screen.getByRole("button", { name: "Save" }));
|
||||
await waitFor(() => expect(saveManagedModel).toHaveBeenCalledTimes(1));
|
||||
expect(
|
||||
rs.mocked(saveManagedModel).mock.calls[0]![0].config,
|
||||
).not.toHaveProperty("api_key");
|
||||
});
|
||||
|
||||
test("preset edits retain stable ID, leave key blank and preserve advanced overrides", async () => {
|
||||
rs.mocked(loadManagedModels).mockResolvedValue({
|
||||
models: [
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user