import type { Action, CoupRules, Event, LiarsDiceRules, PlayerInfo, TexasHoldemRules } from "../protocol/types"; export type GameType = "texas_holdem" | "liars_dice" | "coup"; export type GameRules = { readonly game: "texas_holdem"; readonly rules: TexasHoldemRules; } | { readonly game: "liars_dice"; readonly rules: LiarsDiceRules; } | { readonly game: "coup"; readonly rules: CoupRules; }; export type LegalAction = Action; export interface GameSpecificProfile { readonly extraPrompt?: string; /** * [0..1] risk-aversion hyperparameter. Information-only for M1-12; * consumed by M1-14 (rev3 锁:M1-13 fallback 也不读). */ readonly riskAversion?: number; } export interface StrategyProfile { readonly name: string; readonly version: number; readonly provider: "anthropic" | "openai"; readonly model: string; readonly systemPrompt: string; readonly temperature?: number; readonly maxTokens: number; readonly costCapUSDPerMatch?: number; readonly gameSpecific?: Partial>; } export interface DecisionRequest { readonly game: GameType; readonly matchId: string; readonly playerId: string; /** * Game-specific rules from server_game_start.data.rules. Caller * must ensure shape matches the `game` discriminator * (TexasHoldemRules / LiarsDiceRules / CoupRules per * protocol/types.ts MsgGameStartDataTexasHoldem / LiarsDice / Coup). */ readonly rules: GameRules["rules"]; readonly legalActions: readonly LegalAction[]; /** * Game-specific state from action_request.data.state. Protocol- * level shape is opaque (`state: {}` per messages/server_action_ * request.schema.json); narrowing is per-game. M1-12 prompt- * builder dispatches on `game` and treats this as the per-game * state shape (TexasHoldemState / LiarsDiceState / CoupState). */ readonly publicState: unknown; /** * Reserved for future private-narrowed fields. Server currently * embeds your_hand / your_dice / your_cards / coins inside * publicState; this slot stays optional unknown for forward * compatibility (M1-12 Risks #4). */ readonly privateState?: unknown; readonly players: readonly PlayerInfo[]; /** * Incremental events since the player's last action_request * (action_request.data.new_events). Caller MUST normalize null → * [] before constructing DecisionRequest (M1-12 Risks #11; protocol * spec allows `new_events: null` on first action_request). */ readonly recentEvents: readonly Event[]; readonly strategyProfile: StrategyProfile; readonly turnTimeoutMs: number; readonly decisionBudgetMs: number; } export interface DecisionResponseProviderMetadata { readonly provider: string; readonly model: string; readonly inputTokens?: number; readonly outputTokens?: number; readonly costUSD?: number; readonly latencyMs: number; readonly retries?: number; readonly fallback?: boolean; } export interface DecisionResponse { readonly action: string; readonly params?: Record; readonly summary?: string; readonly providerMetadata: DecisionResponseProviderMetadata; }