added rp api

This commit is contained in:
2026-06-10 11:49:01 +03:00
parent 73baf4dbe1
commit f407e41b6d
13 changed files with 397 additions and 22 deletions
+25
View File
@@ -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;
}
+62 -9
View File
@@ -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
+40 -2
View File
@@ -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),
},
};
}