feat: 亞絲娜與直葉的角色包 (#6, #7)

build_pack.py 產生對白索引(放在使用者資料目錄);render_skill.py 把人格卡渲染成
角色 skill 並檢查精選對白逐字來自索引;插件改成執行期從資料目錄讀索引。

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
Jeffery (jiantw83)
2026-10-14 20:52:40 +00:00
co-authored by Claude Sonnet 5.5
parent 352ce7dcad
commit 697ed6a0b9
15 changed files with 587 additions and 24 deletions
+16 -2
View File
@@ -1,15 +1,21 @@
import type { Register } from 'claude-code'
import type { CharacterCode } from './characters'
import { resolveConfig } from './config'
import { INDEXES } from './data/index'
import { indexPath, loadIndex } from './index-loader'
import { buildInjection } from './inject'
import type { IndexEntry } from './retrieval'
import { buildRules, SECTION_ID } from './rules'
// 規則段落(W8)加到系統提示最後;每則使用者訊息再依功能標籤檢索角色的對白當語氣參考(W7)。
// 對白索引在使用者資料目錄(dataDir,預設 ~/.claude/anime-companion/<角色>/index.jsonl)。
export const register: Register = (on, options) => {
const config = resolveConfig(options)
const showTiming = options.showTiming === true
const dataDir = typeof options.dataDir === 'string' ? options.dataDir : ''
let turn = 0
// 只快取讀到內容的索引;沒讀到(還沒建置)下一輪會再試,建置完不必重開 session。
const cache = new Map<CharacterCode, readonly IndexEntry[]>()
on('prompt.compose', async ($, e, next) => {
const result = await next(e)
@@ -20,8 +26,16 @@ export const register: Register = (on, options) => {
on('prompt.submit', async ($, e, next) => {
if (e.command || e.isMeta) return next(e)
const load = async (code: CharacterCode) => {
const hit = cache.get(code)
if (hit) return hit
const path = indexPath(dataDir, await $.env.get('HOME'), code)
const index = await loadIndex(p => $.fs.read(p), path)
if (index.length > 0) cache.set(code, index)
return index
}
const r = await buildInjection(
{ config, indexes: INDEXES, complete: req => $.model.complete(req), now: Date.now, turn: turn++ },
{ config, loadIndex: load, complete: req => $.model.complete(req), now: Date.now, turn: turn++ },
e.text,
)
if (r === null) return next(e)