added rp api
This commit is contained in:
@@ -71,3 +71,28 @@
|
||||
color: #8b95a5;
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
|
||||
.character-fieldset {
|
||||
border: 1px solid #2f3748;
|
||||
border-radius: 10px;
|
||||
padding: 1rem;
|
||||
margin: 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 1rem;
|
||||
}
|
||||
|
||||
.character-fieldset legend {
|
||||
padding: 0 0.35rem;
|
||||
color: #c5cdd8;
|
||||
}
|
||||
|
||||
.character-checkbox {
|
||||
flex-direction: row !important;
|
||||
align-items: center;
|
||||
gap: 0.5rem !important;
|
||||
}
|
||||
|
||||
.character-checkbox input {
|
||||
width: auto;
|
||||
}
|
||||
|
||||
@@ -130,15 +130,6 @@ export default function Character() {
|
||||
/>
|
||||
</label>
|
||||
|
||||
<label>
|
||||
Первое сообщение (first_mes)
|
||||
<textarea
|
||||
rows={2}
|
||||
value={card.data.first_mes}
|
||||
onChange={(e) => updateField("first_mes", e.target.value)}
|
||||
/>
|
||||
</label>
|
||||
|
||||
<label>
|
||||
Примеры диалога (mes_example)
|
||||
<textarea
|
||||
@@ -158,6 +149,68 @@ export default function Character() {
|
||||
/>
|
||||
</label>
|
||||
|
||||
<fieldset className="character-fieldset">
|
||||
<legend>Изображения (Anima / RP-чат)</legend>
|
||||
|
||||
<label className="character-checkbox">
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={card.data.sd_enabled}
|
||||
onChange={(e) => updateField("sd_enabled", e.target.checked)}
|
||||
/>
|
||||
Разрешить генерацию картинок в чате
|
||||
</label>
|
||||
|
||||
<label>
|
||||
Appearance tags (booru, для «нарисуй себя»)
|
||||
<textarea
|
||||
rows={2}
|
||||
value={card.data.appearance_tags}
|
||||
onChange={(e) => updateField("appearance_tags", e.target.value)}
|
||||
placeholder="silver_hair, wolf_ears, blue_eyes, ..."
|
||||
/>
|
||||
</label>
|
||||
|
||||
<label>
|
||||
Appearance prose (контекст, не в промпт SD)
|
||||
<textarea
|
||||
rows={2}
|
||||
value={card.data.appearance_prose}
|
||||
onChange={(e) => updateField("appearance_prose", e.target.value)}
|
||||
/>
|
||||
</label>
|
||||
|
||||
<label>
|
||||
LoRA (имя файла в ComfyUI)
|
||||
<input
|
||||
value={card.data.lora_name}
|
||||
onChange={(e) => updateField("lora_name", e.target.value)}
|
||||
placeholder="anima-preview-3-masterpieces-v5.safetensors"
|
||||
/>
|
||||
</label>
|
||||
|
||||
<label>
|
||||
LoRA weight
|
||||
<input
|
||||
type="number"
|
||||
min={0}
|
||||
max={2}
|
||||
step={0.05}
|
||||
value={card.data.lora_weight}
|
||||
onChange={(e) => updateField("lora_weight", Number(e.target.value))}
|
||||
/>
|
||||
</label>
|
||||
|
||||
<label>
|
||||
RP persona_id (опционально)
|
||||
<input
|
||||
value={card.data.rp_persona_id}
|
||||
onChange={(e) => updateField("rp_persona_id", e.target.value)}
|
||||
placeholder="default или card_имя_карточки"
|
||||
/>
|
||||
</label>
|
||||
</fieldset>
|
||||
|
||||
<label>
|
||||
Теги (через запятую)
|
||||
<input
|
||||
|
||||
@@ -12,6 +12,12 @@ export interface CharacterCardData {
|
||||
creator_notes: string;
|
||||
alternate_greetings: string[];
|
||||
character_version: string;
|
||||
appearance_tags: string;
|
||||
appearance_prose: string;
|
||||
lora_name: string;
|
||||
lora_weight: number;
|
||||
rp_persona_id: string;
|
||||
sd_enabled: boolean;
|
||||
}
|
||||
|
||||
export interface CharacterCardV2 {
|
||||
@@ -38,21 +44,53 @@ export const DEFAULT_CARD: CharacterCardV2 = {
|
||||
creator_notes: "",
|
||||
alternate_greetings: [],
|
||||
character_version: "1.0",
|
||||
appearance_tags: "",
|
||||
appearance_prose: "",
|
||||
lora_name: "",
|
||||
lora_weight: 0.8,
|
||||
rp_persona_id: "",
|
||||
sd_enabled: true,
|
||||
},
|
||||
};
|
||||
|
||||
function pickImageFields(data: Record<string, unknown>): Partial<CharacterCardData> {
|
||||
const ext = data.extensions as Record<string, unknown> | undefined;
|
||||
const out: Partial<CharacterCardData> = {};
|
||||
const tags =
|
||||
(data.appearance_tags as string) ||
|
||||
(ext?.appearance_tags as string) ||
|
||||
"";
|
||||
if (tags) out.appearance_tags = tags;
|
||||
const prose = (data.appearance_prose as string) || (ext?.appearance_prose as string) || "";
|
||||
if (prose) out.appearance_prose = prose;
|
||||
if (data.lora_name) out.lora_name = String(data.lora_name);
|
||||
if (data.lora_weight != null) out.lora_weight = Number(data.lora_weight);
|
||||
if (data.rp_persona_id) out.rp_persona_id = String(data.rp_persona_id);
|
||||
return out;
|
||||
}
|
||||
|
||||
export function normalizeCard(raw: CharacterCardV2 | Record<string, unknown>): CharacterCardV2 {
|
||||
if (raw.data && typeof raw.data === "object") {
|
||||
const data = raw.data as Record<string, unknown>;
|
||||
return {
|
||||
spec: (raw.spec as string) ?? "chara_card_v2",
|
||||
spec_version: (raw.spec_version as string) ?? "2.0",
|
||||
data: { ...DEFAULT_CARD.data, ...(raw.data as Partial<CharacterCardData>) },
|
||||
data: {
|
||||
...DEFAULT_CARD.data,
|
||||
...(data as Partial<CharacterCardData>),
|
||||
...pickImageFields(data),
|
||||
},
|
||||
};
|
||||
}
|
||||
const flat = raw as Record<string, unknown>;
|
||||
return {
|
||||
spec: "chara_card_v2",
|
||||
spec_version: "2.0",
|
||||
data: { ...DEFAULT_CARD.data, ...(raw as Partial<CharacterCardData>) },
|
||||
data: {
|
||||
...DEFAULT_CARD.data,
|
||||
...(flat as Partial<CharacterCardData>),
|
||||
...pickImageFields(flat),
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user