
    0j                    v    d 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
dZd	Z G d
 d          ZdS )u  Narrator(说书人):把多 agent 事件流实时写成小说连载(docs/agent-runtime-v2.md §9)。

- 独立观察者,从 EventBus 旁路(tap)收集**公开**事件(private 不读,天然防剧透);
- 每攒一个叙事窗口(≥10 模拟分钟或事件够一批)调一次 LLM:
  前情概要 + 本窗口事件 → 续写 200–400 字第三人称悬疑正文 + 滚动更新概要;
- 输出 paras 供 viz 左栏连载;LLM 失败/超时该窗口顺延,不丢事件。
    )annotations)
get_logger)Event)parse_json_blockzruntime.narratorg     @   u  你是悬疑小说{novel}的执笔者,以第三人称全知视角实时连载一桩孤岛悬案。文风:阴郁克制、像阿加莎·克里斯蒂,多写动作与神态、少下断语。【篇幅·要短】每段**短而紧**:60-120 字,只抓此刻**最要紧的一两笔**(一桩动作、一句机锋、一个神色)。不要面面俱到地铺陈每个房间——镜头聚在最有戏的地方,其余至多一句带过。宁可短,绝不注水。【铁律】登场人物**只有**:{roster}{ghost_clause};绝对不许发明任何新人物、新名字或新道具;只写下面提供的事件中发生的事,不要替人物编造未发生的行为,也不许给人物发明事件里没有的伤口、绷带、随身物件——氛围(风雨、灯火)可点到为止,涉及人与物的**事实**必须来自事件;不要点破谁是凶手。输出 JSON:{{"prose": "本段正文(60-120字,务必简短)", "summary": "截至目前的前情概要(120字内)"}}c                  <    e Zd ZdddddddZddZddZdddZdS ) NarratorNu   《雾鸦》u   阮青)novel_titleghostopeningrosterlist[str] | Noner
   strr   
str | Noner   returnNonec                   || _         |rd| dnd}t                              ||d                    |pg d                    | _        g | _        |pd| _        g | _        d| _        d	| _	        d	| _
        d
S )u   说书人世界设定可配置(叙事层解耦):novel_title=连载书名,ghost=只存在于回忆中的死者(可缺),opening=开篇前情。u1   (以及十年前死去、只存在于回忆中的) u   、)u   顾长风(男)u   邵铭轩(男)u   程亦深(男)u   唐曼(女)u   白聿(男)u   温言(女)u   江离(男))novelghost_clauser   uq   暴风雨之夜,七位《雾鸦》旧人被一纸邀请骗回雾鸦岛,刚看完那场不可能存在的放映。g        FN)llmSYSTEM_TMPLformatjoinsystembuffersummaryparas_last_write_sbusyurgent)selfr   r   r
   r   r   r   s          3/root/genesis-world/src/genesis/runtime/narrator.py__init__zNarrator.__init__"   s     W\dS5SSSSbd!((L::f  [  )[  )[  )[  \  \ ) ] ] "$  V  #V!#
 	    er   c                    |j         dk    r|j        dk    rd S |j        dk     rd S |j        dv rJ|j        rd|j         dnd}| j                            ||j        z              |j        dk    rd	| _        d S d S d S )
Nprivatespeechg333333?)r*   actionambienttransit[z] r   g333333?T)scopeetypesalienceplacer   appendcontentr"   )r#   r'   tags      r$   tapzNarrator.tap3   s     7iAGx$7$7F:F7@@@%&W4/ag////"CKsQY///zT!!"	 A@ "!r&   now_sfloatboolc                    | j         r| j        rdS | j        rdS || j        z
  t          k    pt          | j                   t          k    S )NFT)r   r!   r"   r    WINDOW_Slen	BATCH_MAX)r#   r7   s     r$   duezNarrator.due@   sP    { 	di 	5; 	4**x7X3t{;K;Ky;XXr&   r   
time_labelpanoramac                   d| _         | j        d d         | j        dd          c}| _        d                    d| j         d| g|rd| gng dd |D             d	          }	 | j                            d
| j        dd|dgddd          }nB# t          $ r5}t          	                    d|           || j        z   | _        Y d }~d S d }~ww xY wt          |          }t          |                    dd                                                    p|                                }	|	r$| j                            ||	d           || _        |                    d          r"t          |d                   d d         | _        t                              dt%          |	          t%          | j                             d S )NF   
u   【前情概要】u   【时间】u   【此刻全景】u   【本段事件】c              3      K   | ]	}d | V  
dS )z- N ).0bs     r$   	<genexpr>z!Narrator.write.<locals>.<genexpr>P   s(      &&1h1hh&&&&&&r&   u"   续写正文并更新概要(JSON):r   )roler4   userg?2   narrator)temperaturetimeout_tagu&   说书人卡壳:%s(事件退回缓冲)proser   )ttextr   i,  u$   📖 续写一段(%d字,概要%d字))r"   r   r   r   r   completer   	Exceptionloggerwarningr   r   getstripr   r3   r    infor<   )
r#   r7   r?   r@   batchrJ   outr'   drP   s
             r$   writezNarrator.writeH   s   !["-t{233/?t{yy///':''
 4<C.H..//
 !	

 '&&&&
 1
  	(##h4;%O%O.4%F%F%H03Rj $ R RCC  	 	 	NNCQGGG$+-DKFFFFF	 S!!AEE'2&&''--//>399;; 	'JJ>>???!&D55 	3q|,,TcT2DL:CJJDLHYHYZZZZZs   )+B 
C*CC)N)
r   r   r
   r   r   r   r   r   r   r   )r'   r   r   r   )r7   r8   r   r9   )r   )r7   r8   r?   r   r@   r   r   r   )__name__
__module____qualname__r%   r6   r>   r]   rE   r&   r$   r	   r	   !   s        $2'+     "# # # #Y Y Y Y[ [ [ [ [ [ [r&   r	   N)__doc__
__future__r   genesis.obs.logging_setupr   genesis.runtime.busr   genesis.runtime.cognitionr   rU   r;   r=   r   r	   rE   r&   r$   <module>rf      s     # " " " " " 0 0 0 0 0 0 % % % % % % 6 6 6 6 6 6	&	'	'	C A[ A[ A[ A[ A[ A[ A[ A[ A[ A[r&   