persona.spec.ts 3.0 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970
  1. import { describe, expect, it } from 'vitest'
  2. import { personaText, registerPersona, attachPersonaToAgent, PERSONA_BLACKLIST } from '../src/persona'
  3. describe('persona 轻适配内容(只做 dsh 原生身份的小说场景适配)', () => {
  4. it('覆盖身份/主技能指向/状态校准/创作分工/真源纪律', () => {
  5. expect(personaText).toContain('Webnovel Writer 写作工作台')
  6. expect(personaText).toContain('工作台总控') // 指向主技能 novel-director
  7. expect(personaText).toContain('novel_get_story_status') // 状态校准第一律
  8. expect(personaText).toContain('子代理') // 创作分工
  9. expect(personaText).toContain('建议稿') // 规划提案
  10. expect(personaText).toContain('草稿区')
  11. expect(personaText).toContain('定稿区只读')
  12. })
  13. it('轻量:不内置完整工具指引与节点 SOP(已移入主技能与节点技能)', () => {
  14. expect(personaText).not.toContain('六大铁律')
  15. expect(personaText).not.toContain('材料包')
  16. expect(personaText.length).toBeLessThan(1200)
  17. })
  18. it('不含 §9.3 黑名单词', () => {
  19. for (const w of PERSONA_BLACKLIST) {
  20. expect(personaText).not.toContain(w)
  21. }
  22. })
  23. })
  24. describe('persona 注册(轻适配:不 complete,保留 dsh 原生指引段)', () => {
  25. it('用官方槽位 deployment:persona-prefix,order:0,无 complete', () => {
  26. let registered: unknown = null
  27. const sys = {
  28. section: (s: unknown) => { registered = s },
  29. }
  30. const ok = registerPersona(sys)
  31. expect(ok).toBe(true)
  32. expect(registered).toMatchObject({
  33. name: 'deployment:persona-prefix',
  34. order: 0,
  35. })
  36. expect((registered as { complete?: boolean }).complete).toBeUndefined()
  37. })
  38. it('attachPersonaToAgent:经 agent.ctx.inject 的 scoped 注册(非全局)', () => {
  39. let registered: unknown = null
  40. const fakeCtx = {
  41. systemPrompt: { section: (s: unknown) => { registered = s } },
  42. inject: (_deps: readonly string[], cb: (scope: unknown) => void) => { cb(fakeCtx); return undefined },
  43. }
  44. const undo = attachPersonaToAgent(fakeCtx as never)
  45. expect(typeof undo, '交回注销函数(审计 B2)').toBe('function')
  46. expect(registered as { name?: string; complete?: boolean } | null).toMatchObject({ name: 'deployment:persona-prefix' })
  47. expect((registered as { complete?: boolean } | null)?.complete).toBeUndefined()
  48. })
  49. it('attachPersonaToAgent 缺 inject 面 fail-open', () => {
  50. expect(attachPersonaToAgent({ systemPrompt: {} as never } as never)).toBeUndefined()
  51. expect(attachPersonaToAgent(undefined)).toBeUndefined()
  52. })
  53. it('可注入自定义文本', () => {
  54. let got: string | null = null
  55. const sys = { section: (s: { text?: string }) => { got = (s.text as string | undefined) ?? null } }
  56. registerPersona(sys, '自定义身份文本')
  57. expect(got).toBe('自定义身份文本')
  58. })
  59. it('无 systemPrompt 表面 fail-open 不抛', () => {
  60. expect(registerPersona(undefined)).toBe(false)
  61. })
  62. })