Compare commits

..
2 Commits
15 changed files with 1688 additions and 12 deletions
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "jsc-anima",
"version": "0.0.3",
"version": "0.0.4",
"description": "動漫助理:用喜愛角色的口吻互動,附單行狀態列",
"license": "MIT",
"userConfig": {
+1 -1
View File
@@ -2,7 +2,7 @@
# jsc-anima
目前版本:0.0.3
目前版本:0.0.4
動漫助理:用喜愛角色的口吻和你互動,並在輸入框上方顯示單行狀態列(角色、模型、目錄、分支、5h/7d 剩餘額度、ctx、系統資源)。
+12 -10
View File
@@ -16,10 +16,9 @@ import { CACHE_MS, addEntry, commandName, commitMessage, pageName, parseCatalog,
import type { Entry } from './wiki'
import { DEFAULT_TYPES, RUN_SYSTEM, TODO_COMMAND, TODO_KEY, TYPES_KEY, USAGE, dueNow, nextId, parseArgs as parseTodo, reminderText, renderList } from './todo'
import type { Todo } from './todo'
import { NEED_ACTIVE, TOOL_COMMAND, registerTools, runSkillTool } from './skilltool'
import { NEED_ACTIVE, OFF_COMMAND, TOOL_COMMAND, registerTools, runSkillTool } from './skilltool'
const ACTIVE_KEY = 'active'
const OFF_COMMAND = 'anima-off'
const AFFINITY_COMMAND = 'anima-affinity'
const RAW_LOG_KEY = 'rawlog'
const RAW_LOG_MAX = 200
@@ -312,8 +311,7 @@ export const register: Register = (on, options) => {
await $.command.register({ name: c.slug, description: `啟動《${c.work}》的${c.name}` })
}
await $.command.register({ name: EXTRACT_COMMAND, description: '從輕小說章節萃取作品與角色包,確認後建立 PR' })
await $.command.register({ name: AFFINITY_COMMAND, description: '重置(reset)或手動設定(0-100)目前角色的好感度' })
await $.command.register({ name: OFF_COMMAND, description: '離開角色,回到一般的 Claude Code' })
await $.command.register({ name: AFFINITY_COMMAND, description: '重置(reset)或手動設定(0-100)好感度;未啟動時需指定角色代號' })
const saved = await $.store.get(ACTIVE_KEY)
active = flag('persist', true) && typeof saved === 'string' && findCharacter(saved) ? saved : undefined
if (active && !toolRegistered) {
@@ -331,6 +329,7 @@ export const register: Register = (on, options) => {
if (!isEnabled) return next(e)
if (e.command === EXTRACT_COMMAND) return { text: await runExtract($, e.args) }
if (e.command === OFF_COMMAND) {
if (!findCharacter(active)) return { text: NEED_ACTIVE }
active = undefined
await $.store.delete(ACTIVE_KEY)
return { text: '已離開角色,回到一般模式。' }
@@ -343,18 +342,21 @@ export const register: Register = (on, options) => {
return { text: c ? await todoRun($, c.name, c.persona, String(e.args ?? '')) : NEED_ACTIVE }
}
if (e.command === AFFINITY_COMMAND) {
const c = findCharacter(active)
if (!c) return { text: '請先啟動角色。' }
const arg = String(e.args ?? '').trim()
// 第一個字若是角色代號就指定該角色;否則用目前啟動的角色。
const parts = String(e.args ?? '').trim().split(/\s+/).filter(Boolean)
const named = parts.length ? findCharacter(parts[0]) : undefined
const c = named ?? findCharacter(active)
if (!c) return { text: '未啟動角色時請指定角色代號:anima-affinity <角色代號> [reset|0-100]。' }
const arg = (named ? parts.slice(1) : parts).join(' ')
const cur = await loadAffinity($, c.slug)
if (arg === 'reset') {
await $.store.set(affinityKey(c.slug), initialAffinity())
return { text: '好感度已重置為 0。' }
return { text: `${c.name}的好感度已重置為 0。` }
}
const n = Number(arg)
if (arg === '' || !Number.isFinite(n) || n < 0 || n > 100) return { text: `目前好感度 ${cur.score}(${stageName(cur.score)})。用法:reset 或 0-100 的數字。` }
if (arg === '' || !Number.isFinite(n) || n < 0 || n > 100) return { text: `${c.name}目前好感度 ${cur.score}(${stageName(cur.score)})。用法:[角色代號] reset 或 0-100 的數字。` }
await $.store.set(affinityKey(c.slug), { ...cur, score: Math.round(n) })
return { text: `好感度已設為 ${Math.round(n)}(${stageName(n)})。` }
return { text: `${c.name}的好感度已設為 ${Math.round(n)}(${stageName(n)})。` }
}
const c = findCharacter(e.command)
if (!c) {
+2
View File
@@ -7,10 +7,12 @@ import {
} from './skillgen'
export const TOOL_COMMAND = 'anima-skill'
export const OFF_COMMAND = 'anima-off'
export const NEED_ACTIVE = '請先啟動角色(/jsc-anima:{作品代號}-{角色代號})再使用這個工具。'
export async function registerTools($: Engine): Promise<void> {
await $.command.register({ name: TOOL_COMMAND, description: '依描述產生助理技能並建立 PR:<技能名稱> <描述>' })
await $.command.register({ name: OFF_COMMAND, description: '離開角色,回到一般的 Claude Code' })
await $.command.register({ name: TODO_COMMAND, description: '待辦事項:add/update/list/type/run/done' })
}
+3
View File
@@ -0,0 +1,3 @@
Signature: 8a477f597d28d172789f06886806bc55
# This file is a cache directory tag created by Vitest.
# For information about cache directory tags see https://bford.info/cachedir/
@@ -0,0 +1 @@
{"version":1,"projects":{"":{"files":{"hooks/anima.test.ts":{"failed":true,"duration":0,"lastRun":1792056694665},"hooks/extract.test.ts":{"failed":true,"duration":0,"lastRun":1792056694665},"hooks/persist.test.ts":{"failed":true,"duration":0,"lastRun":1792056694665},"hooks/routing.test.ts":{"failed":true,"duration":0,"lastRun":1792056694665},"hooks/skilltool.test.ts":{"failed":true,"duration":0,"lastRun":1792056694665},"hooks/todo.test.ts":{"failed":true,"duration":0,"lastRun":1792056694665},"hooks/wiki.test.ts":{"failed":true,"duration":0,"lastRun":1792056694665}}}}}
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+3
View File
@@ -0,0 +1,3 @@
Signature: 8a477f597d28d172789f06886806bc55
# This file is a cache directory tag created by Vitest.
# For information about cache directory tags see https://bford.info/cachedir/
+3
View File
@@ -0,0 +1,3 @@
{
"lockfileHash": "e3b0c442"
}
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long