feat: 補齊規格缺漏(狀態列顯示思考程度、動漫層與主題色、萃取角色包可啟動)

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
root
2026-10-15 08:28:15 +00:00
co-authored by Claude Sonnet 5.5
parent 59fcf2b3eb
commit e99e7b1536
4 changed files with 117 additions and 6 deletions
+22 -3
View File
@@ -1,6 +1,7 @@
import type { Engine, Register } from 'claude-code'
import { CHARACTERS, applyOverrides, findCharacter, personaSection } from './characters'
import { CHARACTERS, applyOverrides, findCharacter, packToCharacter, personaSection, registerCharacters, themeColor } from './characters'
import type { PackLike } from './characters'
import type { Axes } from './characters'
import { EXTRACT_COMMAND, runExtract } from './extractCommand'
import { applyEvent, hearts, initialAffinity, stageName, stageVoice, dayKey } from './affinity'
@@ -242,6 +243,21 @@ async function quotaRemain($: Engine): Promise<number | undefined> {
}
// 讀 characters/index.json(外掛目錄內),把萃取產生的角色包註冊成可啟動的角色。
async function loadPacks($: Engine): Promise<void> {
const dir = new URL('../characters/', import.meta.url).pathname
try {
if (!(await $.fs.exists(`${dir}index.json`))) return
const index = JSON.parse(await $.fs.read(`${dir}index.json`)) as { packs: { work: string; workName: string; slug: string }[] }
for (const i of index.packs) {
const pack = JSON.parse(await $.fs.read(`${dir}${i.work}/${i.slug}.json`)) as PackLike
registerCharacters([packToCharacter(pack, i.workName)])
}
} catch {
// 角色包損壞不影響內建角色。
}
}
export const register: Register = (on, options) => {
const opt = options as Record<string, unknown>
const flag = (k: string, d: boolean) => (typeof opt[k] === 'boolean' ? (opt[k] as boolean) : d)
@@ -252,6 +268,7 @@ export const register: Register = (on, options) => {
let active: string | undefined
let toolRegistered = false
let route: Route | undefined
let lastPick: { model: ModelName; effort: Effort } | undefined
let prefixed = false
const holder: { sys?: Sys } = {}
const wikiCommands = new Set<string>()
@@ -276,6 +293,7 @@ export const register: Register = (on, options) => {
on('session.start', async ($, e, next) => {
if (isEnabled) {
await loadPacks($)
for (const c of CHARACTERS) {
await $.command.register({ name: c.slug, description: `啟動《${c.work}》的${c.name}` })
}
@@ -397,6 +415,7 @@ export const register: Register = (on, options) => {
quotaRemain: await quotaRemain($),
downgradeAt: num('downgradeAt', 15),
})
lastPick = { model: pick.model, effort: pick.effort }
return yield* next({ ...e, model: pick.model, effort: pick.effort })
})
@@ -458,13 +477,13 @@ export const register: Register = (on, options) => {
}
const builders: Record<string, () => Promise<Segment['parts'] | undefined> | Segment['parts'] | undefined> = {
character: () => [{ text: c.name, color: 'cyan' }],
character: () => [{ text: c.name, color: themeColor(c) }],
love: async () => {
if (!flag('affinity', true) || !flag('showHearts', true)) return undefined
const a = await loadAffinity($, c.slug)
return [{ text: hearts(a.score), color: 'red' as const }]
},
model: () => (model ? [{ text: model }] : undefined),
model: () => (model ? [{ text: lastPick && routingOn() ? `${model} · ${lastPick.effort}` : model }] : undefined),
dir: () => (cwd ? [{ text: cwd.split('/').filter(Boolean).pop() ?? '/' }] : undefined),
branch: () => (branch ? [{ text: `⎇ ${branch}` }] : undefined),
'5h': () => quota('five_hour', '5h', false),