#!/usr/bin/env python3
"""Create a SillyTavern Character Card V2 JSON document."""
import argparse
import json
import sys
from dataclasses import asdict, dataclass, field
from pathlib import Path
from typing import Any, TextIO
@dataclass
class CharacterCard:
"""The data section of a SillyTavern Character Card V2 document."""
name: str = ""
description: str = ""
personality: str = ""
scenario: str = ""
first_mes: str = ""
mes_example: str = ""
creator_notes: str = ""
system_prompt: str = ""
post_history_instructions: str = ""
alternate_greetings: list[str] = field(default_factory=list)
character_book: None = None
tags: list[str] = field(default_factory=list)
creator: str = ""
character_version: str = ""
extensions: dict[str, Any] = field(default_factory=dict)
def document(self) -> dict[str, Any]:
"""Return this card in the Character Card V2 document structure."""
return {
"spec": "chara_card_v2",
"spec_version": "2.0",
"data": asdict(self),
}
def parseArguments() -> argparse.Namespace:
"""Parse command-line arguments for the character card generator."""
parser = argparse.ArgumentParser(
description="Create a SillyTavern Character Card V2 JSON document.",
)
parser.add_argument(
"description",
help="Character description.",
)
parser.add_argument(
"personality",
help="Character personality summary.",
)
parser.add_argument(
"mes_example",
help="Example messages that demonstrate the character's voice.",
)
parser.add_argument(
"--name",
default="",
help="Optional character name.",
)
parser.add_argument(
"-o",
"--output",
type=Path,
help="Write JSON to this file instead of standard output.",
)
return parser.parse_args()
def writeJson(document: dict[str, Any], output: TextIO) -> None:
"""Write a UTF-8, human-readable JSON document followed by a newline."""
json.dump(document, output, ensure_ascii=False, indent=2)
output.write("\n")
def main() -> int:
"""Create a card from command-line values and write its JSON document."""
arguments = parseArguments()
card = CharacterCard(
name=arguments.name,
description=arguments.description,
personality=arguments.personality,
mes_example=arguments.mes_example,
)
if arguments.output is None:
writeJson(card.document(), sys.stdout)
return 0
try:
with arguments.output.open("w", encoding="utf-8") as output:
writeJson(card.document(), output)
except OSError as error:
print(
f"Could not write {arguments.output}: {error}",
file=sys.stderr,
)
return 1
return 0
if __name__ == "__main__":
raise SystemExit(main())