Add AI-assisted world and character drafting flows
All checks were successful
CI / validate (push) Successful in 14m3s
All checks were successful
CI / validate (push) Successful in 14m3s
This commit is contained in:
31
packages/shared/src/character.test.ts
Normal file
31
packages/shared/src/character.test.ts
Normal file
@@ -0,0 +1,31 @@
|
||||
import { describe, expect, it } from 'vitest'
|
||||
import { CharacterDraftSchema } from './index'
|
||||
|
||||
const draft = {
|
||||
name: 'Iris Vale',
|
||||
concept: 'A patient relay mechanic who hears impossible harmonics.',
|
||||
abilities: { str: 9, dex: 13, con: 12, int: 16, wis: 14, cha: 10 },
|
||||
hp: 12,
|
||||
maxHp: 12,
|
||||
defense: 13,
|
||||
proficiency: 2,
|
||||
inventory: ['Signal lens', 'Field toolkit'],
|
||||
persona: {
|
||||
voice: 'Precise, with dry humor.',
|
||||
motivation: 'Prove the relay is speaking from the future.',
|
||||
flaw: 'Treats every warning as a puzzle.',
|
||||
bond: 'Will not abandon another crew member.',
|
||||
},
|
||||
}
|
||||
|
||||
describe('CharacterDraftSchema', () => {
|
||||
it('accepts a complete editable 13+ character draft', () => {
|
||||
expect(CharacterDraftSchema.parse(draft)).toEqual(draft)
|
||||
expect(CharacterDraftSchema.toJSONSchema()).toMatchObject({ type: 'object' })
|
||||
})
|
||||
|
||||
it('rejects invalid server-facing mechanics', () => {
|
||||
expect(() => CharacterDraftSchema.parse({ ...draft, hp: 20, maxHp: 10 })).toThrow()
|
||||
expect(() => CharacterDraftSchema.parse({ ...draft, defense: 99 })).toThrow()
|
||||
})
|
||||
})
|
||||
@@ -45,6 +45,30 @@ export const WorldStarterSchema = z.object({
|
||||
})
|
||||
export type WorldStarter = z.infer<typeof WorldStarterSchema>
|
||||
|
||||
export const CharacterPersonaSchema = z.object({
|
||||
voice: z.string().trim().min(1).max(240),
|
||||
motivation: z.string().trim().min(1).max(300),
|
||||
flaw: z.string().trim().min(1).max(300),
|
||||
bond: z.string().trim().min(1).max(300),
|
||||
})
|
||||
export type CharacterPersona = z.infer<typeof CharacterPersonaSchema>
|
||||
|
||||
export const CharacterDraftSchema = z.object({
|
||||
name: z.string().trim().min(1).max(80),
|
||||
concept: z.string().trim().min(3).max(600),
|
||||
abilities: AbilityScoresSchema,
|
||||
hp: z.number().int().min(1).max(100),
|
||||
maxHp: z.number().int().min(1).max(100),
|
||||
defense: z.number().int().min(1).max(40),
|
||||
proficiency: z.number().int().min(1).max(10),
|
||||
inventory: z.array(z.string().trim().min(1).max(120)).max(12),
|
||||
persona: CharacterPersonaSchema,
|
||||
}).strict().refine(value => value.hp <= value.maxHp, {
|
||||
message: 'hp must not exceed maxHp',
|
||||
path: ['hp'],
|
||||
})
|
||||
export type CharacterDraft = z.infer<typeof CharacterDraftSchema>
|
||||
|
||||
export const CharacterSchema = z.object({
|
||||
id: z.string().min(1),
|
||||
name: z.string().min(1).max(80),
|
||||
|
||||
Reference in New Issue
Block a user