wanghehe123/dsh-Friend--packages-dsh-friend-persona1

@wishp3/dsh-friend-persona

角色卡存取、预设注册、人格提示词分区

AI 분석

核心用途是管理虚拟伴侣的角色设定,支持导入 SillyTavern 酒馆卡。适合需要自定义伴侣性格、导入已有角色卡预设的用户。

패키지
@wishp3/dsh-friend-persona
버전
0.1.0
라이선스
MIT
최근 업데이트
2026. 8. 14.

설치

검증된 bundle이 없거나 호환성 검사에 실패했습니다. 먼저 저장소 설명을 읽어 주세요. 전체 README 읽기 ↗

@wishp3/dsh-friend-persona

角色卡存取、酒馆卡导入、预设注册、人格提示词分区。

Host 入口仍是 src/index.ts(由接线任务挂载)。本包已导出的模块:

  • src/store.ts — 角色卡 CRUD、默认角色种子、数据根解析
  • src/tavern-import.ts — SillyTavern PNG / JSON 导入

数据根目录解析优先级

resolveFriendDataDir({ dshHome?, override?, env?, homedir? }) 是纯函数,不会写死 ~/.dsh。第一个非空值生效:

  1. options.override — 直接指定 friend 数据根(已含 friend/,测试注入用)
  2. 环境变量 FRIEND_DATA_DIR — 同样是 friend 数据根
  3. options.dshHome — 拼成 /friend
  4. 环境变量 DSH_HOME — 拼成 /friend(冒烟脚本的隔离临时 home 走这条)
  5. /.dsh/friend

角色卡路径:/characters//persona.json

单元测试一律把 override 指到 os.tmpdir();读取默认回退时传入 env: {},避免本机真实 DSH_HOME 泄漏进断言。

角色卡 schema

写入前校验这些字段(手写类型守卫,不引入 zod,也不运行时依赖 @deepseek-ai/schemastery):

字段类型约束
namestring必填,trim 后非空
personalitystring必填
backgroundstring必填
speakingStylestring必填
languagestring必填
nicknamestring必填(对用户的称呼)
greetingsstring[]必填(可空数组)
live2dModelstring?若出现必须是字符串
voicestring?若出现必须是字符串
tagsstring[]必填(可空数组)

校验失败抛出 PersonaValidationError(可读中文),不会改写磁盘上的原文件。存储层不缓存卡片内容,外部编辑器改完下次 get/list 即可见。

中文名会生成可用 slug(保留 CJK);重名自动加 -2-3 后缀。首次启动调用 seedDefault():仅当 characters/default/persona.json 不存在时写入内置「小友」,已存在则不覆盖。

酒馆卡导入回退

importTavernCardJson / importTavernCardPng 兼容 V1 顶层字段、V2 data 包装、V3 chara_card_v3。PNG 读 tEXt/iTXtchara(其次 ccv3)chunk。缺省字段:

persona 字段酒馆来源回退
namedata.name / char_nameUnnamed Character
personalitydata.personality""
backgrounddescription/char_persona + scenario/world_scenario""
speakingStylesystem_prompt,否则 post_history_instructions;若有 mes_example 则追加""
languageextensions.language / speak_languagezh-CN
nicknameextensions.nickname{{user}} 视为未设
greetingsfirst_mes/char_greeting + alternate_greetings[]
live2dModelextensions.live2dModel / live2d省略
voiceextensions.voice省略
tagsdata.tags[]

导入结果会再走一遍 persona schema,因此可以直接 store.create(...)