feat(w4): ship v1.5.0 timeline, character arc, and compliance
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -0,0 +1,47 @@
|
||||
import type { CharacterArcNode } from '../../shared/arc'
|
||||
import { KnowledgeRepository } from '../db/repositories/knowledge.repo'
|
||||
import { SettingRepository } from '../db/repositories/setting.repo'
|
||||
import { ChapterRepository } from '../db/repositories/chapter.repo'
|
||||
import type { SqliteDb } from '../db/types'
|
||||
|
||||
export class ArcService {
|
||||
constructor(private db: SqliteDb) {}
|
||||
|
||||
getForCharacter(settingId: string): CharacterArcNode[] {
|
||||
const setting = new SettingRepository(this.db).get(settingId)
|
||||
if (!setting || setting.type !== 'character') return []
|
||||
|
||||
const knowledge = new KnowledgeRepository(this.db)
|
||||
.list()
|
||||
.filter((k) => k.type === 'character' && k.title.includes(setting.name))
|
||||
const chapterRepo = new ChapterRepository(this.db)
|
||||
const chapters = new Map(chapterRepo.list().map((c) => [c.id, c]))
|
||||
|
||||
const nodes: CharacterArcNode[] = knowledge
|
||||
.map((k) => {
|
||||
const chapterId = k.lastMentionChapterId ?? k.sourceChapterId
|
||||
const chapter = chapterId ? chapters.get(chapterId) : undefined
|
||||
return {
|
||||
id: k.id,
|
||||
title: k.title,
|
||||
content: k.content,
|
||||
chapterId: chapterId ?? null,
|
||||
chapterTitle: chapter?.title ?? null,
|
||||
updatedAt: k.updatedAt
|
||||
}
|
||||
})
|
||||
.sort((a, b) => a.updatedAt.localeCompare(b.updatedAt))
|
||||
|
||||
if (nodes.length === 0 && setting.description.trim()) {
|
||||
nodes.push({
|
||||
id: `setting:${setting.id}`,
|
||||
title: '角色设定',
|
||||
content: setting.description.replace(/<[^>]+>/g, '').slice(0, 200),
|
||||
chapterId: null,
|
||||
chapterTitle: null,
|
||||
updatedAt: setting.updatedAt
|
||||
})
|
||||
}
|
||||
return nodes
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user