mirror of
https://github.com/sipeed/picoclaw.git
synced 2026-06-12 18:08:54 +00:00
feat(models): add extra_body config field in model add/edit UI (#1969)
* Add extraBody field to model configuration forms
This adds a new field allowing users to specify additional JSON fields
to inject into the request body when configuring models.
* Handle ExtraBody clearing when frontend sends empty object
The backend now interprets an empty object sent from the frontend as a
signal to clear the ExtraBody field, while nil/undefined preserves the
existing value. Frontend changed to send {} instead of undefined when
the field is empty.
This commit is contained in:
@@ -12,6 +12,7 @@ import {
|
||||
} from "@/components/shared-form"
|
||||
import { Button } from "@/components/ui/button"
|
||||
import { Input } from "@/components/ui/input"
|
||||
import { Textarea } from "@/components/ui/textarea"
|
||||
import {
|
||||
Sheet,
|
||||
SheetContent,
|
||||
@@ -34,6 +35,7 @@ interface AddForm {
|
||||
maxTokensField: string
|
||||
requestTimeout: string
|
||||
thinkingLevel: string
|
||||
extraBody: string
|
||||
}
|
||||
|
||||
const EMPTY_ADD_FORM: AddForm = {
|
||||
@@ -49,6 +51,7 @@ const EMPTY_ADD_FORM: AddForm = {
|
||||
maxTokensField: "",
|
||||
requestTimeout: "",
|
||||
thinkingLevel: "",
|
||||
extraBody: "",
|
||||
}
|
||||
|
||||
interface AddModelSheetProps {
|
||||
@@ -100,7 +103,7 @@ export function AddModelSheet({
|
||||
}
|
||||
|
||||
const setField =
|
||||
(key: keyof AddForm) => (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
(key: keyof AddForm) => (e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>) => {
|
||||
setForm((f) => ({ ...f, [key]: e.target.value }))
|
||||
if (fieldErrors[key]) {
|
||||
setFieldErrors((prev) => ({ ...prev, [key]: undefined }))
|
||||
@@ -129,6 +132,9 @@ export function AddModelSheet({
|
||||
? Number(form.requestTimeout)
|
||||
: undefined,
|
||||
thinking_level: form.thinkingLevel.trim() || undefined,
|
||||
extra_body: form.extraBody.trim()
|
||||
? JSON.parse(form.extraBody.trim())
|
||||
: undefined,
|
||||
})
|
||||
if (setAsDefault) {
|
||||
await setDefaultModel(modelName)
|
||||
@@ -305,6 +311,18 @@ export function AddModelSheet({
|
||||
placeholder="max_completion_tokens"
|
||||
/>
|
||||
</Field>
|
||||
|
||||
<Field
|
||||
label={t("models.field.extraBody")}
|
||||
hint={t("models.field.extraBodyHint")}
|
||||
>
|
||||
<Textarea
|
||||
value={form.extraBody}
|
||||
onChange={setField("extraBody")}
|
||||
placeholder='{"key": "value"}'
|
||||
rows={3}
|
||||
/>
|
||||
</Field>
|
||||
</AdvancedSection>
|
||||
|
||||
{serverError && (
|
||||
|
||||
@@ -12,6 +12,7 @@ import {
|
||||
} from "@/components/shared-form"
|
||||
import { Button } from "@/components/ui/button"
|
||||
import { Input } from "@/components/ui/input"
|
||||
import { Textarea } from "@/components/ui/textarea"
|
||||
import {
|
||||
Sheet,
|
||||
SheetContent,
|
||||
@@ -32,6 +33,7 @@ interface EditForm {
|
||||
maxTokensField: string
|
||||
requestTimeout: string
|
||||
thinkingLevel: string
|
||||
extraBody: string
|
||||
}
|
||||
|
||||
interface EditModelSheetProps {
|
||||
@@ -59,6 +61,7 @@ export function EditModelSheet({
|
||||
maxTokensField: "",
|
||||
requestTimeout: "",
|
||||
thinkingLevel: "",
|
||||
extraBody: "",
|
||||
})
|
||||
const [saving, setSaving] = useState(false)
|
||||
const [setAsDefault, setSetAsDefault] = useState(false)
|
||||
@@ -79,6 +82,9 @@ export function EditModelSheet({
|
||||
? String(model.request_timeout)
|
||||
: "",
|
||||
thinkingLevel: model.thinking_level ?? "",
|
||||
extraBody: model.extra_body
|
||||
? JSON.stringify(model.extra_body, null, 2)
|
||||
: "",
|
||||
})
|
||||
setSetAsDefault(model.is_default)
|
||||
setError("")
|
||||
@@ -86,7 +92,7 @@ export function EditModelSheet({
|
||||
}, [model])
|
||||
|
||||
const setField =
|
||||
(key: keyof EditForm) => (e: React.ChangeEvent<HTMLInputElement>) =>
|
||||
(key: keyof EditForm) => (e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>) =>
|
||||
setForm((f) => ({ ...f, [key]: e.target.value }))
|
||||
|
||||
const handleSave = async () => {
|
||||
@@ -109,6 +115,9 @@ export function EditModelSheet({
|
||||
? Number(form.requestTimeout)
|
||||
: undefined,
|
||||
thinking_level: form.thinkingLevel || undefined,
|
||||
extra_body: form.extraBody.trim()
|
||||
? JSON.parse(form.extraBody.trim())
|
||||
: {},
|
||||
})
|
||||
if (setAsDefault && !model.is_default) {
|
||||
await setDefaultModel(model.model_name)
|
||||
@@ -273,6 +282,18 @@ export function EditModelSheet({
|
||||
placeholder="max_completion_tokens"
|
||||
/>
|
||||
</Field>
|
||||
|
||||
<Field
|
||||
label={t("models.field.extraBody")}
|
||||
hint={t("models.field.extraBodyHint")}
|
||||
>
|
||||
<Textarea
|
||||
value={form.extraBody}
|
||||
onChange={setField("extraBody")}
|
||||
placeholder='{"key": "value"}'
|
||||
rows={3}
|
||||
/>
|
||||
</Field>
|
||||
</AdvancedSection>
|
||||
|
||||
{error && (
|
||||
|
||||
Reference in New Issue
Block a user