尧图精选

AIRI Character Card Codec 解析:用 @proj-airi/ccc 实现 CCv3 文档校验、兼容分级与多格式导出

🕒 发布时间:2026/9/12 15:43:49 📁 来源:尧图网络
AIRI Character Card Codec 解析用 proj-airi/ccc 实现 CCv3 文档校验、兼容分级与多格式导出【免费下载链接】airi Self hosted, you-owned Grok Companion, a container of souls of waifu, cyber livings to bring them into our worlds, wishing to achieve Neuro-samas altitude. Capable of realtime voice chat, Minecraft, Factorio playing. Web / macOS / Windows supported.项目地址: https://gitcode.com/GitHub_Trending/ai/airipackages/ccc是 AIRI 项目中负责社区角色卡Character Card协议原语的独立包围绕 CCv3Character Card V3标准提供 JSON 信封校验、未知字段的向前兼容保留、TypeScript 契约定义以及 JSON / Markdown / PNG / APNG 导出助手。阅读本文后你将掌握如何用parseCharacterCardV3安全导入任意社区角色卡、通过compatibility分级判断版本新旧、借助defineCard构建领域模型并导出为标准 CCv3 文档以及如何在运行时无关的边界上区分协议错误与存储错误。包的定位与职责边界proj-airi/cccpackages/ccc/README.md是一个**运行时无关runtime-agnostic**的协议编解码包它的职责被刻意收敛为四件事CCv3 JSON 信封校验与兼容性分级parseCharacterCardV3校验过程中未知字段的向前兼容保留保证未来新增的 CCv3 字段不会被静默丢弃共享的 CCv3 TypeScript 契约valibot Schema 与推导类型角色卡的 JSON、Markdown、PNG、APNG 导出助手。包内索引 src/index.ts 通过export *将codec、define、export、utils四个模块统一对外暴露入口只有一个导入体验非常干净。README 同时明确了它不拥有什么不负责 AIRI 模块设置、本地持久化、聊天消息组装或编辑器行为也不负责为角色应用语音、视觉、身体模型或 Agent 配置更不负责从 prompts、greetings、示例或 Lorebook 构造 provider 消息——这些策略属于 AIRI 的角色运行时而非社区协议编解码层。这种边界划分意味着ccc可以独立于任何具体运行环境被复用例如在导入/导出社区角色卡、把 CCv3 信封转换成应用模型之前先做校验、以及构建 PNG/APNG/CHARX 等格式适配器时。解析一份 CCv3 文档核心 API 是parseCharacterCardV3它接受解码后的 JSON 对象或 JSON 文本两种输入返回解析结果与兼容性分级import { parseCharacterCardV3 } from proj-airi/ccc const { card, compatibility } parseCharacterCardV3(jsonText) const characterName card.data.name const versionSupport compatibility // older | current | newer从实现看src/codec/characterCardV3.ts解析过程分两步先用parseJsonSource处理输入——字符串走JSON.parse非字符串直接作为候选对象返回随后用 valibot 的safeParse对characterCardV3Schema做结构化校验成功则返回{ card, compatibility }。compatibility的取值由resolveCompatibility依据spec_version数值比较得出src/codec/characterCardV3.ts当前实现以currentSpecVersion 3为基准compatibility判定条件典型场景olderspec_version 3旧版 V3 文档或更低版本信封currentspec_version 3与当前实现完全一致的文档newerspec_version 3未来版本文档仍可导入但建议提示用户注意比较使用的是Number.parseFloat因此spec_version: 3.0与3都会归为current。旧版和新版的spec_version都不会被拒绝导入compatibility只是把“是否提醒用户”的决策权交给调用方。错误边界InvalidCharacterCardError当输入既不是合法 JSON也不是合法的 CCv3 结构时解析会抛出InvalidCharacterCardErrorsrc/codec/characterCardV3.ts。该错误类携带统一的错误消息Invalid Character Card V3.通过cause保留 valibot 的校验问题明细result.issues或JSON.parse的原始异常通过只读的source字段回放调用方最初传入的原始输入便于排查。在需要区分“协议失败”与“存储/文件系统失败”的边界处配合类型守卫isInvalidCharacterCardError使用try { const { card } parseCharacterCardV3(raw) } catch (error) { if (isInvalidCharacterCardError(error)) { // 协议层失败JSON 畸形或 CCv3 结构不合法 } else { // 存储或文件系统等其他层失败 } }测试用例 test/characterCardV3.test.ts 对三类失败输入做了覆盖不完整的 JSON 文本{、spec错写成chara_card_v2的信封、以及character_book.entries[0].use_regex缺失的结构全部断言抛出InvalidCharacterCardError且isInvalidCharacterCardError判定为真。CCv3 契约valibot Schema 与推导类型整个契约层由 valibot 的 Schema 声明式构建src/codec/characterCardV3.ts从外到内依次是信封characterCardV3Schemaspec必须是字面量chara_card_v3spec_version必须匹配/^\d(?:\.\d)*$/外加data对象数据体characterCardDataSchema覆盖 CCv3 的全部标准字段包括name、description、personality、scenario、first_mes、mes_example、alternate_greetings、character_book、character_version、creator、creator_notes、extensions、post_history_instructions、system_prompt、tags、assets、creation_date、creator_notes_multilingual、group_only_greetings、modification_date、nickname、sourceLorebookcharacterBookSchema与条目characterBookEntrySchema条目支持keys、content、insertion_order、use_regex、positionbefore_char | after_char等标准字段以及case_sensitive、constant、id、priority、selective、secondary_keys等可选字段资源assetSchematype、uri、name、ext扩展extensionsSchema标准depth_promptdepth/prompt/role、fav、talkativeness、world及开放扩展。data的DataV1、DataV2、DataV3类型分别用PickData, ...抽取了继承自 CCv1、CCv2 以及 V3 新增的字段集合src/codec/characterCardV3.ts从类型层面清晰地标出了协议演进脉络V1 贡献了name/description/first_mes等基础字段V2 贡献了system_prompt/post_history_instructions/character_book等V3 则新增了assets、nickname、source、多语言创作者备注和时间戳等。向前兼容的关键objectWithRest 保留未知字段ccc对未知字段的处理方式非常考究所有 Schema 均以objectWithRest({...}, unknown())收尾这意味着任何未声明但出现在文档中的键都会被完整保留在解析结果中而不会在“校验”这一步被丢弃。这解决了社区生态中的经典痛点——当 CCv3 规范未来新增字段、或某个工具在extensions中写入自定义数据时AIRI 尚未理解的字段不会在导入再导出的过程中悄无声息地丢失。这一点在测试中得到了直接验证test/characterCardV3.test.ts 构造了一份带future_envelope_field、future_data_field、future_book_field、future_entry_field、future_asset_field的完整文档断言parseCharacterCardV3的结果toEqual(completeCard)——即所有“未来字段”原样保留。这意味着ccc可以安全地承担“先导入、后升级”的职责即使当前版本不认识新字段也不会破坏数据。领域卡片模型defineCard 与 Card 类型除了直接面向 CCv3 信封的 codecccc还提供了一层“领域友好”的卡片模型。defineCardsrc/define/card.ts接收一个Card对象原样返回借助 TypeScript 类型提供书写提示与约束。Card由五个接口组合而成src/define/card.tsCardCorename、nickname、version、creatorCardMeta任意metadata键值对Recordstring, boolean | number | stringCardAdditionalassets、characterBook、creationDate、modificationDate、source、extensions、greetingsgreetings[0]映射first_mesgreetings.slice(1)映射alternate_greetings、greetingsGroupOnly、notes、notesMultilingualCardExtrapersonality、scenario、systemPrompt、postHistoryInstructions、tags、messageExample类型为Message[][]CardDescription实验性的description字段源码标注为 TODO 待移除。仓库自带的角色卡夹具 test/fixture/seraphina.ts 是defineCard的完整范例——基于 SillyTavern 默认角色卡 SeraphinaAGPL-3.0 授权展示了如何用结构化字段描述角色。领域模型与 CCv3 信封的字段命名不同如characterBookvscharacter_book、creationDatevscreation_date导出层负责两者之间的映射。导出为 CCv3 标准文档JSON 导出exportToJSONsrc/export/json.ts将领域Card对象转换为标准 CCv3 信封spec: chara_card_v3、spec_version: 3.0。字段映射与默认值在createCardData中完成src/export/json.ts要点包括first_mes取greetings[0]alternate_greetings取greetings.slice(1)缺失的description、personality、scenario、creator等以空字符串兜底mes_example将Message[][]数组按\n连接后每个示例块前缀START标签extensions会先注入默认值再与用户扩展合并src/export/json.tsdepth_prompt默认{ depth: 4, prompt: , role: system }、fav: false、talkativeness: 0.5之后展开...data.extensions覆盖。PNG 导出meta-png 元数据嵌入exportToPNG与exportToPNGBase64src/export/png.ts借助meta-png依赖把卡片的 CCv3 JSON 以 base64 编码后写入 PNG 图像的ccv3元数据块分别面向Uint8Array与 base64 data URI 两种输入import { exportToPNG, exportToPNGBase64 } from proj-airi/ccc // 二进制 PNG → 带 ccv3 元数据的 PNG const outPng: Uint8Array exportToPNG(card, rawPngBytes) // base64 PNG → 带 ccv3 元数据的 base64 PNG const outDataUri: string exportToPNGBase64(card, data:image/png;base64,...)这正是社区角色卡生态中“一张 PNG 同时是立绘与角色数据载体”的实现基础。Markdown 与 APNG 导出exportToMDsrc/export/md.ts与exportToAPNGsrc/export/apng.ts当前是预留的空实现占位仓库通过 src/export/index.ts 统一导出exportToMarkdown与exportToMD互为别名同时以export type * as ccv3 from ../codec/characterCardV3把全部协议类型以ccv3命名空间形式对外暴露。从源码结构看这两个格式的完整实现是后续演进方向。消息示例与 Markdown 构建助手utils模块src/utils/index.ts提供两组纯函数助手用于提升卡片内容编写的可读性chat 助手src/utils/chat.tsaction/act生成*...*动作文本message/msg生成...对话文本char生成{{char}}: ...user生成{{user}}: ...且全部支持模板字符串、数组拼接两种调用形态。Message模板字面量类型src/define/types/mes_example.ts限定为{{char|user}}: ${string}从类型层面约束消息示例的格式正确性markdown 助手src/utils/markdown.tscontent以空行连接段落、h生成#级标题、p用分隔符拼接数组、link生成 Markdown 链接。测试验证契约完整性与边界覆盖包的测试配置在 vitest.config.ts通过pnpm --filter proj-airi/ccc testvitest run执行。测试套件 test/characterCardV3.test.ts 覆盖了完整 CCv3 契约解析且未来字段不丢失compatibility currentJSON 文本与对象走同一校验边界spec_version: 4.0→newer、2.0→older的兼容分级exportToJSON对全部标准字段的往返映射畸形 JSON、错误spec、缺失必填结构三种失败输入的InvalidCharacterCardError行为。这与 README 中“Malformed JSON 和非法 CCv3 结构抛出InvalidCharacterCardError”的承诺一一对应可作为接入方参考的行为基线。何时使用与何时不使用按 README 的边界定义ccc适合以下场景导入或导出社区角色卡在把 CCv3 信封转换为应用模型之前先做校验构建 PNG、APNG、CHARX 等格式适配器。而不适合承担持久化 AIRI 专属的当前激活角色状态应用语音、视觉、身体模型或 Agent 配置基于 prompts、greetings、示例或 Lorebook 构造 provider 消息。这些策略归属于 AIRI 的角色运行时。遵循这一边界ccc作为独立、纯净、可替换的协议编解码层可以在不耦合任何运行时细节的前提下为整个项目提供稳定、向前兼容的社区角色卡互操作能力。依赖与许可包的运行时依赖只有两个packages/ccc/package.jsonvalibotSchema 校验与meta-pngPNG 元数据读写均通过 pnpm workspace 的catalog:版本统一管理无任何框架或运行时绑定进一步印证了其运行时无关的设计。包以 MIT 协议开源。【免费下载链接】airi Self hosted, you-owned Grok Companion, a container of souls of waifu, cyber livings to bring them into our worlds, wishing to achieve Neuro-samas altitude. Capable of realtime voice chat, Minecraft, Factorio playing. Web / macOS / Windows supported.项目地址: https://gitcode.com/GitHub_Trending/ai/airi创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
上一篇/下一篇内容由系统自动关联 返回资讯列表 →