
    6jS                    D   d Z ddlmZ ddlZddlZddlZddlZddlZddlm	Z	 ddl
mZmZ ddlmZmZ ddlmZ ddlmZ dd	lmZ dd
lmZ ddlmZ ddlmZ ddlmZ ddlmZ  ed          Z dZ! ej"        d          Z#dZ$ddZ% G d d          Z& G d d          Z'dS )u  WerewolfMind:LLM 角色脑,实现引擎那套 DecisionProvider 接口(无缝替下 RandomProvider)。

设计延续平台理念:人设 + 如实状态(对局板)+ 软引导,少规则、让博弈智能涌现;
但比命案局更吃逻辑与欺骗。每个决策点 = 一次结构化输出调用;失败/越界 → 随机兜底,世界不停摆。
模型工厂 make_model 注入(真实=lc_adapter.build_chat_model;测试=FakeModel),便于零真实调用单测。
    )annotationsN)Path)CallableOptional)HumanMessageSystemMessage)
get_logger)
perception)schema)BoardMemory)RandomProvider)lookup_transcript)Role)	GameStatezwerewolf.brainu`   9 人预女猎·屠边:狼方杀光所有神 或 所有民 即胜;好人放逐所有狼即胜。      	world_dir
str | Pathreturndict[int, str]c                   t          |           dz  }|                                si S 	 t          j        |                    d                    }nU# t          j        t          f$ r<}t                              dt          |          dd                    i cY d}~S d}~ww xY wi }|
                                D ]M\  }}t          |                                          r't          |t                    r||t          |          <   N|S )ur   从世界目录读 personas.json → {seat: 人设文本};无文件或解析失败则返回空(退回无人设)。zpersonas.jsonzutf-8)encodingu   读取座位人设失败:%sNx   )r   existsjsonloads	read_textJSONDecodeErrorOSErrorloggerwarningstritemsisdigit
isinstanceint)r   praweoutkvs          1/root/genesis-world/src/genesis/werewolf/brain.pyload_personasr.   *   s   Y/)A88:: 	jg6677 '*   4c!ffTcTlCCC						 C		  1q66>> 	
1c 2 2 	CAKJs   (A B%)1B B% B%c                      e Zd ZdZdddddd5dZd6d7dZd8d9d"Zd# Zd$ Zd% Z	d& Z
d' Zd( Zd) Zd* Zd+ Zd, Zd:d-Zd. Zd;d0Zed<d2            Zd3 Zd4 ZdS )=WerewolfMinduz   某座位的 AI 大脑。维护自己的主观对局板;每次决策喂入【人设 + 如实对局板 + 本次任务】。N    )make_think_modelpersonarngretriesseatr&   roler   rolesdict[str, Role]
make_modelr   r3   Optional[Callable]r4   r"   r5   Optional[random.Random]r6   r   Nonec                   || _         || _        || _        || _        || _        || _        || _        t          |          | _        t          |pt          j        |                    | _        d | _        d S N)r7   r8   r9   r;   r3   r4   r6   r   boardr   randomRandomfallbackstream_sink)	selfr7   r8   r9   r;   r3   r4   r5   r6   s	            r-   __init__zWerewolfMind.__init__>   sq     		
$ 0 &&
&s'AfmD.A.ABB    T
structuredboolc           	        | j         j        dk    rdnd}d| j         d| j         j         d| d| j         d	g}| j        r|                    d	| j        z              | j         j        r|                    | j         j                   |                    d
t          z              |r|                    d           n|                    d           |                    d           d                    |          S )Nwolfu   狼人阵营u   好人阵营u   你是 u    号玩家,你的身份是【u   】(u   )。全程牢记你就是 u    号本人——绝不会查验/投票/怀疑/带走你自己;提到别人时一律用对方的座位号,别把自己的号说成别人。u'   你的性子(用它决定说话风格):u   你在玩 9 人狼人杀。uj   凭你的身份、性子与立场,基于下面如实的对局信息做决策。只输出结构化结果。u+  发言时像真人一样自然口语:可以有停顿、迟疑、『嗯…』『我想想』、改口、带口头禅和情绪,别像念稿。高手不耿直——会铺垫、试探、藏信息、找时机、配合队友,而不是一上来就摊牌或说『我不跳预言家』这种没信息量的废话。该悍跳、对跳、隐藏实力、结盟、带节奏、撒谎就来(尤其你若是狼:和狼队口径一致、互相抬轿、别公开拆队友的台)。每次只说有信息量或有目的的一段话,只说这段话本身,不要前缀/解释。u  注意:你只能基于『你确实掌握到的信息』推理。可以伪装身份、可以撒谎带节奏,但别把『纯靠猜的』说成『我知道的事实』——尤其首夜你对别人的身份一无所知,不要凭空断言谁是预言家/女巫/神。
)	r8   teamr7   namer4   appendpersona_hintWIN_RULEjoin)rF   rI   rN   partss       r-   _systemzWerewolfMind._systemL   sR   !%6!9!9~~~@49 @ @49> @ @W[ @ @*.)@ @ @ A< 	SLLBT\QRRR9! 	1LL/0002X=>>> 	qLL  F  G  G  G  G LLpq q q 	 t 	u 	u 	uyyrH   Ftaskstater   extrathinkc                   | j                             t          j        || j        | j                  t                    dz   |z   |z   }t          |                                           t          |          g}|r| j
        r| j
        n| j        }t          |dd          }	t          | j        dz             D ]}
	 t          5   |                                |d                              |          }d	d	d	           n# 1 swxY w Y   ||c S t$                              d
| j        |	|
dz              nR# t(          $ rE}t$                              d| j        |	|
dz   t+          |          d	d                    Y d	}~nd	}~ww xY w|
| j        k     rt-          j        d|
dz   z             t$                              d| j        |	| j        dz              d	S )u  渲染对局板 + 本次任务 → 结构化输出;失败重试 self.retries 次,仍失败才返回 None(随机兜底)。
        think=True 用思考模式模型(发言/复盘,质量优先)。重试是稳定性关键:治"LLM偶发失败→3号发言这种傻瓜兜底"。transcript_tailz

content__name__?   function_calling)methodNu   [%d号 %s] 第%d次返回空u   [%d号 %s] 第%d次失败:%sr   g?u.   [%d号 %s] 重试 %d 次仍失败,随机兜底)rA   renderr
   viewr7   r9   TRANSCRIPT_TAILr   rU   r   r3   r;   getattrranger6   _LLM_SEMwith_structured_outputinvoker    r!   	Exceptionr"   timesleep)rF   r   rV   rW   rX   rY   usermsgsmakerO   attemptr*   r)   s                r-   _askzWerewolfMind._askd   sM    
!!*/%DJ"O"Oap!qq "'(dllnn555|D7Q7Q7QR).^43H^t$$tvz3//T\A-.. 	0 	0Gk h h$&&77GY7ZZaabfggCh h h h h h h h h h h h h h h?JJJ=ty$PWZ[P[\\\\ k k k=ty$PWZ[P[]`ab]c]cdhehdh]ijjjjjjjjk%%
3'A+.///GTXZ^ZfijZjkkktsB   =D:3D7D:D	D:
D	D:%D::
F	;FF	c                    |j         dk    rdnd}|                     t          j        d| d| d|          }|	|j        |vr| j                            |||          S |j        |j        dS )Nra   u   今天是首夜,你们对所有人的身份一无所知——按直觉/座位/谁威胁大盲刀即可,别在理由里编造『他是预言家』这种你根本没法知道的话。r1   u   天黑,你在狼队私聊频道里和队友商量今晚刀谁(你说的只有狼队友看得到;前面队友的提议见上方)。u   可刀:u=   。给出你提议的 target 和一句给队友的 message。)targetmessage)dayrs   SCWolfDiscussOutru   rD   wolf_discussrv   )rF   rW   r7   
candidates
firstnightr*   s         r-   rz   zWerewolfMind.wolf_discuss|   s    jojswxjxjxg g A 	ii)x%x x.8x x xy~@ @ ;#*J66=--eT:FFF*===rH   c                    |                      t          j        d| d|          }|r|j        |v r|j        n| j                            |||          S )Nu5   天黑了,和狼队商定今晚刀谁。可刀对象:   。)rs   rx   NightKillOutru   rD   decide_killrF   rW   r7   r{   r*   s        r-   r   zWerewolfMind.decide_kill   s[    ii)pak)p)p)prwxx!wcjJ&>&>szzT]E^E^_dfjlvEwEwwrH   c                    |                      t          j        d| d|          }|r|j        |v r|j        n| j                            |||          S )Nu(   你要查验一人验明好坏。可查:r~   )rs   rx   NightCheckOutru   rD   decide_checkr   s        r-   r   zWerewolfMind.decide_check   s\    ii(*dU_*d*d*dfkll!xcjJ&>&>szzT]E_E_`egkmwExExxrH   c                   |d| dnd}|                      t          j        | d| d| d| d|          }|| j                            ||||||          S |j        |v r|j        nd }	t          |j                  |	dS )	Nu   今夜 u    号倒在刀下。u   今夜你未获知刀型。u   解药可用=u   ,毒药可用=u&   。决定救不救、毒不毒(可毒:u   )。)savepoison)rs   rx   WitchOutrD   decide_witchpoison_targetrJ   r   )
rF   rW   r7   knifecan_save
can_poisonpoison_candidatesknr*   r   s
             r-   r   zWerewolfMind.decide_witch   s    5:5F1u1111Liii  N  NH  N  NJ  N  N  wH  N  N  N  PUV V;=--eT5(JXijjj&)&7;L&L&L""RVSX&999rH   c                    |                      t          j        d|          }|rt          |j                  n| j                            ||          S )NuD   警长竞选:是否上警竞选警徽(1.5 票、可定发言顺序)?)rs   rx   RunSheriffOutrJ   runrD   decide_run_sheriffrF   rW   r7   r*   s       r-   r   zWerewolfMind.decide_run_sheriff   sF    ii(*prwxx #VtCG}}})I)I%QU)V)VVrH   c                t    |                      t          j        d|          }|r|j        dv r|j        nd}d|iS )Nu   你当选警长,握有发言定序权:决定本轮从你左手边(cw,座位顺位)还是右手边(ccw,逆位)起依次发言,你自己将压轴最后发言。把你最想压制/想后置观察的可疑位置安排到对你最有利的发言序。)cwccwr   	direction)rs   rx   SpeechDirOutr   )rF   rW   r7   r*   ds        r-   decide_speech_dirzWerewolfMind.decide_speech_dir   sQ    iiT V[\ \ "Ocm}&D&DCMM4QrH   c                t    |                      t          j        d|          }|rt          |j                  ndS )Nu   竞选发言结束,进入退水环节:综合场上局势与你的目的,是否退水(退出警长竞选)?(若你是悍跳/警上无优势/想把警徽让给队友等,可考虑退;否则不退)F)rs   rx   WithdrawOutrJ   withdrawr   s       r-   decide_withdrawzWerewolfMind.decide_withdraw   s@    iirsxz z &)3tCL!!!e3rH   c                t    |                      t          j        d| d|          }|r|j        |v r|j        S d S )Nu[   你(警长)即将出局,临终可把警徽移交给一名存活玩家或撕毁。可移交:uP   。移交给你最信任、对好人/你阵营最有利的人(撕毁填 null)。)rs   rx   BadgePassOutru   r   s        r-   decide_badge_passzWerewolfMind.decide_badge_pass   s`    iih  wA h h hinp p  	3:++:trH   c                t    |                      t          j        d|          }|rt          |j                  ndS )Nu"  轮到你发言。你是狼,可选择自爆(掀桌亮身份,中止今天发言投票直接入夜)。自爆是极强但极少用的手段——只在能打断好人关键归票/查杀传递、或保住更重要队友时才用;通常不自爆,正常发言带节奏即可。现在要自爆吗?F)rs   rx   
ExplodeOutrJ   exploder   s       r-   decide_explodezWerewolfMind.decide_explode   s@    ii\]bd d %(2tCK   U2rH   c                ~   t          j        || j        | j                  }d}|j        dk    rrt          |j                  dk    rZ|                     t          j	        d|          }|r7|j
        pd                                rt          ||j
                  }|rd|z   }t          | j        dz             D ]C}|                     ||          }|r|c S || j        k     rt!          j        d|dz   z             Dt$                              d| j        | j        dz              | j                            ||          S )	Nr1   r2      u   发言前,你想调阅哪段原始记录来佐证判断?给一个 query(某座位号 / 'day:N' / 关键词);不需要就留空。u$   

【你刚调阅的原始记录】
ra         ?u.   [%d号] 发言重试 %d 次仍空,随机兜底)r
   re   r7   r9   rw   len
transcriptrs   rx   	RecallOutquerystripr   rh   r6   _speak_textrm   rn   r    r!   rD   speak)	rF   rW   r7   r,   rX   rechitrr   texts	            r-   r   zWerewolfMind.speak   sR   OE49dj995A::#al++b00))BL `  bgh hC L	R..00 L'3955 LEKE T\A-.. 	0 	0G##E511D %%
3'A+.///GTXT`cdTdeee}""5$///rH   c                   |j         dk    rdnd}| j                            t          j        || j        | j                  t                    d| j         dz   |z   dz   |z   }	 t          5  | 	                                
                    t          |                     d	          
          t          |
          g          }ddd           n# 1 swxY w Y   t          |dd          pd                                pdS # t           $ rA}t"                              d| j        t'          |          dd                    Y d}~dS d}~ww xY w)uI   纯文本生成一段发言(非结构化,鲁棒);失败/空返回 None。ra   u/   现在是首日,信息少,可以略作铺垫。uu   已是第二天之后,务必言简意赅、抓重点,一两句到一小段就好,别长篇复述别人说过的话。r[   u   

轮到你(u   号)发言。以你的身份和立场,像真人一样自然口语地说(可带停顿/迟疑/口头禅/情绪,别念稿;有套路、有目的,别耿直摊牌或说废话)。ux   过身份/报查验/站边/归票/试探/隐藏都行。只输出这段话本身,不要任何前缀、格式或解释。FrI   r]   Nr^   r1   u   [%d号] 发言生成失败:%sr   )rw   rA   rd   r
   re   r7   r9   rf   ri   r;   rk   r   rU   r   rg   r   rl   r    r!   r"   )rF   rW   rX   brevityro   r*   r)   s          r-   r   zWerewolfMind._speak_text   s    IN	UVDD P 	
!!*/%DJ"O"Oap!qqz49 z z zz  YY \aa	 M Moo''..dll^clFdFd0e0e0e0<T0J0J0J0L M MM M M M M M M M M M M M M M M CB//52<<>>F$F 	 	 	NN:DIs1vvdsd|TTT44444	s=   %D ,ACD CD C)D 
E6E

Ec                >   t          | j        dz             D ][}|                     |          }|r| j                            |            dS || j        k     rt          j        d|dz   z             \t                              d| j	        | j        dz              dS )u  每天收尾的记忆压缩(每个存活 agent 各跑一次;引擎 _digest_day 钩子触发)。
        多回合、信息量大 → 双层压缩防遗忘+控长:
        ① key_facts = 铁的客观事实清单(死亡+死法/公开身份声明/对跳/查验/警长/票型异常),累积保留别丢旧的;
        ② notes = 滚动主观分析+计划,在旧 notes 上重写。
        触发规则:每天收尾压一次(此处);常驻事实/票型/查验等硬信息另由 PlayerView 每回合如实下发,二者互补。
        ★实现:走纯文本+宽松解析(非结构化)——实测 MiniMax 对 DayDigestOut 这种多字段 function_calling
          首日约 40% 吐空/回显字段名,导致 agent 次日记忆全空;纯文本 invoke 无函数调用脆弱性,稳。失败重试。ra   Nr   u:   [%d号] 记忆压缩重试 %d 次仍失败,保留旧局记)
rh   r6   _digest_textrA   apply_digestrm   rn   r    r!   r7   )rF   rW   r7   rr   r   s        r-   
digest_dayzWerewolfMind.digest_day   s     T\A-.. 	0 	0G!!%((A 
''***%%
3'A+.///SUYU^`d`lop`pqqqqqrH   Optional[dict]c                   d}| j         j        s| j         j        rd| j         j         d| j         j         }| j                             t	          j        || j        | j                  t                    |z   dz   }	 t          5  | 
                                                    t          |                     d                    t          |          g          }d	d	d	           n# 1 swxY w Y   t          |d
d          pd                                }nN# t"          $ rA}t$                              d| j        t)          |          d	d                    Y d	}~d	S d	}~ww xY w|                     |          S )uu   纯文本生成记忆压缩 → 宽松解析成 {key_facts,notes,prime_suspect,most_trusted};失败/空返回 None。r1   u   

你已有的【事实】:u   
你已有的【局记】:r[   u=  

今天结束,做记忆压缩。严格按下面 4 行纯文本输出(每行一项、冒号后写内容、没有就留空,不要任何别的话):
事实:<铁的客观事实清单,累积旧的+今天新增——谁死了+死法(刀/毒/枪/放逐)、谁公开跳了什么身份/谁对跳、公开查验结果、警长是谁、票型异常;只记客观事实不下判断>
分析:<基于事实,你这个身份/立场的好狼判断与下一步计划,在旧局记上重写,几句话>
最疑:<你最怀疑是狼的座位号,或留空>
最信:<你最信任的座位号,或留空>Fr   r]   Nr^   u#   [%d号] 记忆压缩生成失败:%sr   )rA   	key_factsnotesrd   r
   re   r7   r9   rf   ri   r;   rk   r   rU   r   rg   r   rl   r    r!   r"   _parse_digest)rF   rW   oldro   r*   r   r)   s          r-   r   zWerewolfMind._digest_text   s   : 	v4:#3 	vu$*2FuucgcmcsuuC
!!*/%DJ"O"Oap!qq>>	 M Moo''..dll^clFdFd0e0e0e0<T0J0J0J0L M MM M M M M M M M M M M M M M M CB//52<<>>DD 	 	 	NN@$)SQRVVTXUXTX\ZZZ44444	 !!$'''s=   =D AC*D *C..D 1C.2(D 
E&%6E!!E&r   c                   ddddd}i }|                                  D ]}|                                                    d                              dd          }|                                D ]f\  }}|                    |d	z             s|                    |d
z             r1|t          |          dz   d                                         ||<    ng|                    d          s|                    d          sdS dD ]T}t          j	        d|                    |          pd          }|r!t          |                                          nd||<   U|S )uy   把『事实/分析/最疑/最信』四行纯文本宽松解析成 digest dict;至少要有事实或分析才算有效。r   r   prime_suspectmost_trusted)u   事实u   分析u   最疑u   最信u   -*【 u   】r1   :u   ：ra   N)r   r   z\d+)
splitlinesr   lstripreplacer#   
startswithr   getresearchr&   group)	r   labelsgotlineslabelkeyr+   ms	            r-   r   zWerewolfMind._parse_digest  s`    (7oaoppOO%% 	 	D

##H--55eR@@A$llnn  
s<<,, UU]0K0K  Ua17799CHE ww{## 	CGGG,<,< 	42 	3 	3A	&#''!**"233A'(2S^^^dCFF
rH   c                    |                      t          j        d| d|          }|| j                            |||          S |j        |v r|j        nd S )Nu!   放逐投票:投谁出局?可投:u   (弃票填 null)。)rs   rx   VoteOutrD   decide_voteru   r   s        r-   r   zWerewolfMind.decide_vote  s]    ii
$g
$g$g$ginoo;=,,UD*EEE Z:55szz4?rH   c                    |                      t          j        d| d|          }|| j                            |||          S |j        |v r|j        nd S )Nu1   你(猎人)出局,可开枪带走一人。可带:u   (放弃填 null)。)rs   rx   HunterShootOutrD   decide_hunter_shootru   r   s        r-   r   z WerewolfMind.decide_hunter_shoot  si    ii)+~_i+~+~+~  AF  G  G;=44UD*MMM Z:55szz4?rH   )r7   r&   r8   r   r9   r:   r;   r   r3   r<   r4   r"   r5   r=   r6   r&   r   r>   )T)rI   rJ   r   r"   )r1   F)rV   r"   rW   r   rX   r"   rY   rJ   )rX   r"   )r   r   )r   r"   r   r   )r_   
__module____qualname____doc__rG   rU   rs   rz   r   r   r   r   r   r   r   r   r   r   r   r   staticmethodr   r   r    rH   r-   r0   r0   ;   s        E  E RV "4XY                    0    0> > >x x xy y y: : :W W W     4 4 4  3 3 30 0 0*   $r r r"( ( ( (.    \"@ @ @@ @ @ @ @rH   r0   c                      e Zd ZdZddZddZd Zd	 Zd
 Zd Z	d Z
d Zd Zd Zd Zd Zd Zd Zd Ze	 	 d d!d            ZdS )"MindProvideru]   把每座位的 WerewolfMind 组装成引擎用的单一 DecisionProvider(按 seat 路由)。mindsdict[int, WerewolfMind]r   r>   c                    || _         d S r@   )r   )rF   r   s     r-   rG   zMindProvider.__init__(  s    


rH   c                L    | j                                         D ]	}||_        
dS )ua   给所有 AI 脑装上流式发言回调(网页 live 用);不设则发言走非流式结构化。N)r   valuesrE   )rF   sinkr   s      r-   set_stream_sinkzMindProvider.set_stream_sink+  s2    ""$$ 	! 	!A AMM	! 	!rH   c                F    | j         |                             |||          S r@   )r   rz   rF   r   r7   cs       r-   rz   zMindProvider.wolf_discuss0  "    tz$/?/L/LQPTVW/X/X(XrH   c                F    | j         |                             |||          S r@   )r   r   r   s       r-   r   zMindProvider.decide_kill1  !    dj.>.J.J1dTU.V.V'VrH   c                F    | j         |                             |||          S r@   )r   r   r   s       r-   r   zMindProvider.decide_check2  r   rH   c                L    | j         |                             ||||||          S r@   )r   r   )rF   r   r7   r+   cscppcs          r-   r   zMindProvider.decide_witch3  s,    4:d;K;X;XYZ\`bcegikmo;p;p4prH   c                D    | j         |                             ||          S r@   )r   r   rF   r   r7   s      r-   r   zMindProvider.decide_run_sheriff4  s     $*T2B2U2UVWY]2^2^+^rH   c                D    | j         |                             ||          S r@   )r   r   r   s      r-   r   zMindProvider.decide_speech_dir5  s     D1A1S1STUW[1\1\*\rH   c                D    | j         |                             ||          S r@   )r   r   r   s      r-   r   zMindProvider.decide_withdraw6  s     tz$/?/O/OPQSW/X/X(XrH   c                F    | j         |                             |||          S r@   )r   r   r   s       r-   r   zMindProvider.decide_badge_pass7  s#    DJt4D4V4VWXZ^`a4b4b-brH   c                D    | j         |                             ||          S r@   )r   r   r   s      r-   r   zMindProvider.decide_explode8  s    dj.>.M.MaQU.V.V'VrH   c                D    | j         |                             ||          S r@   )r   r   r   s      r-   r   zMindProvider.speak9  s    TZ%5%;%;At%D%DDrH   c                F    | j         |                             |||          S r@   )r   r   r   s       r-   r   zMindProvider.decide_vote:  r   rH   c                F    | j         |                             |||          S r@   )r   r   r   s       r-   r   z MindProvider.decide_hunter_shoot;  s#    dj6F6Z6Z[\^bde6f6f/frH   c                D    | j         |                             ||          S r@   )r   r   r   s      r-   r   zMindProvider.digest_day<  s    $*T*:*E*Ea*N*N#NrH   Nr;   r   personasr   r3   r<   'MindProvider'c                ^    pi fdj         j        D             } | |          S )u   按已发牌的引擎给每个座位建一个对应身份的脑。make_think_model:发言/复盘用的思考模式模型(可选)。c                    i | ]g}|t          |j        j                            |                   j                            |d           t          j        |                    hS )r1   )r3   r4   r5   )r0   r9   rW   role_ofr   rB   rC   ).0r7   enginer;   r3   r   s     r-   
<dictcomp>z)MindProvider.for_game.<locals>.<dictcomp>C  s     
 
 
  ,tV\&,2F2Ft2L2L%Mv|]g0@'/||D"'='=6=QUCVCVX X X
 
 
rH   )rW   r9   )clsr  r;   r   r3   r   s    ```` r-   for_gamezMindProvider.for_game>  s_     >r
 
 
 
 
 
 
 *	
 
 
 s5zzrH   )r   r   r   r>   )r   r>   )NN)r;   r   r   r   r3   r<   r   r   )r_   r   r   r   rG   r   rz   r   r   r   r   r   r   r   r   r   r   r   r   classmethodr  r   rH   r-   r   r   %  s        gg   ! ! ! !
 YXXVVVXXXppp^^^\\\XXXbbbVVVDDDVVVfffNNNOS8<
 
 
 
 [
 
 
rH   r   )r   r   r   r   )(r   
__future__r   r   rB   r   	threadingrm   pathlibr   typingr   r   langchain_core.messagesr   r   genesis.obs.logging_setupr	   genesis.werewolfr
   r   rx   genesis.werewolf.boardmemoryr   genesis.werewolf.enginer   genesis.werewolf.recallr   genesis.werewolf.rolesr   genesis.werewolf.stater   r    rR   	Semaphoreri   rf   r.   r0   r   r   rH   r-   <module>r     s    # " " " " "   				            % % % % % % % % ? ? ? ? ? ? ? ? 0 0 0 0 0 0 ' ' ' ' ' ' ) ) ) ) ) ) 4 4 4 4 4 4 2 2 2 2 2 2 5 5 5 5 5 5 ' ' ' ' ' ' , , , , , ,	$	%	%n 9q!!    "g@ g@ g@ g@ g@ g@ g@ g@T$ $ $ $ $ $ $ $ $ $rH   