build_pack.py 產生對白索引(放在使用者資料目錄);render_skill.py 把人格卡渲染成 角色 skill 並檢查精選對白逐字來自索引;插件改成執行期從資料目錄讀索引。 Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
48 lines
2.1 KiB
TypeScript
48 lines
2.1 KiB
TypeScript
import type { Register } from 'claude-code'
|
|
|
|
import type { CharacterCode } from './characters'
|
|
import { resolveConfig } from './config'
|
|
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)
|
|
const text = buildRules(config)
|
|
if (text === null) return result
|
|
return { sections: [...result.sections, { id: SECTION_ID, text, scope: 'session' }] }
|
|
})
|
|
|
|
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, loadIndex: load, complete: req => $.model.complete(req), now: Date.now, turn: turn++ },
|
|
e.text,
|
|
)
|
|
if (r === null) return next(e)
|
|
if (showTiming) $.ui.status(`anime-companion 分類 ${r.ms}ms → ${r.fn ?? '失敗'}`)
|
|
// 附加在使用者訊息之前,只增不改,不影響對話的快取。
|
|
if (r.text !== null) await $.session.append({ message: { type: 'user', content: [{ type: 'text', text: r.text }] } })
|
|
return next(e)
|
|
})
|
|
}
|