Important Fixes, New mechanics, and many more
Some checks failed
CI / validate (push) Failing after 9m21s

This commit is contained in:
2026-08-15 17:37:57 +05:00
parent 1774496cf9
commit 438e5af0ad
56 changed files with 5090 additions and 119 deletions

View File

@@ -0,0 +1,19 @@
import { describe, expect, it } from 'vitest'
import { PlayerIntentSchema } from './index'
describe('shared database contracts', () => {
it('accepts PostgREST timestamptz values with an explicit UTC offset', () => {
const intent = PlayerIntentSchema.parse({
id: '2c321216-ef17-48a2-9aa3-6250bb4354f5',
roundId: '940fc00f-76e1-45dc-b401-55a2084e3e0e',
memberId: '85701d65-0b2c-4c7e-aa30-d67fc77f1f54',
characterId: 'bfc4b38f-bf3c-4ee1-b875-aa98b2b3a756',
action: 'Inspect the access panel.',
ready: true,
createdAt: '2026-08-15T08:42:10.123456+00:00',
updatedAt: '2026-08-15T08:42:11+00:00',
})
expect(intent.ready).toBe(true)
})
})

View File

@@ -1,6 +1,11 @@
import { z } from 'zod'
export * from './moderation'
// PostgreSQL/PostgREST serializes timestamptz values with an explicit offset
// (for example `+00:00`). Browser-created timestamps normally use `Z`.
// Both are valid ISO-8601 timestamps and must be accepted at the API boundary.
const IsoDatetimeSchema = z.string().datetime({ offset: true })
export const abilityKeys = ['str', 'dex', 'con', 'int', 'wis', 'cha'] as const
export const AbilityKeySchema = z.enum(abilityKeys)
export type AbilityKey = z.infer<typeof AbilityKeySchema>
@@ -53,6 +58,7 @@ export const CharacterSchema = z.object({
proficiency: z.number().int().min(1).max(10),
inventory: z.array(z.string().max(120)).max(50).default([]),
statuses: z.array(z.string().max(80)).max(12).default([]),
persona: z.record(z.string(), z.unknown()).optional(),
})
export type Character = z.infer<typeof CharacterSchema>
@@ -63,11 +69,31 @@ export const PlayerIntentSchema = z.object({
characterId: z.string().min(1),
action: z.string().trim().min(1).max(2000),
ready: z.boolean().default(false),
createdAt: z.string().datetime(),
updatedAt: z.string().datetime(),
createdAt: IsoDatetimeSchema,
updatedAt: IsoDatetimeSchema,
})
export type PlayerIntent = z.infer<typeof PlayerIntentSchema>
export const RoundContextSchema = z.object({
scene: z.string().max(6000),
storySummary: z.string().max(6000).nullable(),
recentRounds: z.array(z.object({
number: z.number().int().positive(),
narration: z.string().max(6000),
nextPrompt: z.string().max(500).nullable().optional(),
})).max(2),
humanIntents: z.array(PlayerIntentSchema).max(8),
aiCharacters: z.array(CharacterSchema).max(8),
activeCharacters: z.array(CharacterSchema).max(16),
memories: z.array(z.object({
summary: z.string().min(1).max(1200),
importance: z.number().int().min(1).max(5).optional(),
tags: z.array(z.string().max(40)).max(12).optional(),
entityIds: z.array(z.string()).max(20).optional(),
})).max(8),
})
export type RoundContext = z.infer<typeof RoundContextSchema>
export const CheckRequestSchema = z.object({
actorId: z.string().min(1),
kind: z.enum(['ability', 'attack', 'initiative', 'damage', 'healing']),
@@ -81,7 +107,7 @@ export const CheckRequestSchema = z.object({
export type CheckRequest = z.infer<typeof CheckRequestSchema>
export const DiceRollSchema = z.object({
id: z.string(),
id: z.string().uuid(),
checkKind: CheckRequestSchema.shape.kind,
formula: z.string(),
rolls: z.array(z.number().int()),
@@ -92,7 +118,7 @@ export const DiceRollSchema = z.object({
success: z.boolean().nullable(),
actorId: z.string(),
targetId: z.string().nullable(),
createdAt: z.string().datetime(),
createdAt: IsoDatetimeSchema,
})
export type DiceRoll = z.infer<typeof DiceRollSchema>
@@ -130,6 +156,11 @@ export const RoundResolutionSchema = z.object({
})
export type RoundResolution = z.infer<typeof RoundResolutionSchema>
export const StorySummarySchema = z.object({
summary: z.string().min(20).max(6000),
})
export type StorySummary = z.infer<typeof StorySummarySchema>
export const CoauthorMessageSchema = z.object({
role: z.enum(['user', 'assistant']),
content: z.string().trim().min(1).max(5000),