
    (Gj9L                    j   d Z ddlmZ ddlZddlmZmZmZmZm	Z	 dZ
dZdZdZd	Zd
Zeeef         Z ej        d          Z ej        d          Z ej        d          Z ej        d          Z ej        d          Z ej        d          Z ej        d          Zd<dZd=dZ ej        d          Z ej        d          Z ej        d          Z ej        d          Z ej        d          Z d>d!Z!d?d#Z"d@d$Z#d?d%Z$dAd(Z%dBd+Z&d?d,Z'dCd.Z(dDd0Z)dEd2Z*dFd5Z+dGd6Z,	 dHdId9Z-dJd;Z.dS )Ku  Render agent markdown into Slack Block Kit blocks.

Opt-in (``slack.extra.rich_blocks: true``) alternative to the flat mrkdwn
``text`` payload produced by :meth:`SlackAdapter.format_message`.  Block Kit
gives us real structural primitives — section headers, dividers, and true
*nested* lists via ``rich_text`` — that plain mrkdwn can only approximate.

Design constraints (why this module is deliberately conservative):

* **Markdown pipe-tables render as native ``table`` blocks** — real grid
  cells with per-column alignment and inline-formatted ``rich_text`` content.
  A table that exceeds Slack's limits (100 rows / 20 cols / 10k aggregate
  cell chars) or won't parse falls back to aligned monospace
  ``rich_text_preformatted`` so a large table never breaks the message.
* **Slack caps a message at 50 blocks** and a ``section``/text object at 3000
  characters.  :func:`render_blocks` enforces both and, if the content simply
  cannot be expressed within them, returns ``None`` so the caller falls back
  to the plain-text path.  A rich render is a nice-to-have; it must never lose
  a message.
* **Every blocks payload MUST ship a ``text`` fallback.**  Slack uses it for
  notifications, screen readers, and old clients.  This module only builds the
  ``blocks`` list; the adapter pairs it with the existing mrkdwn string.

The renderer never raises: any unexpected input degrades to ``None`` (caller
uses plain text).  It is a pure function of its input — no Slack client, no
adapter state — so it is trivially unit-testable.
    )annotationsN)AnyDictListOptionalTuple2   i     d      i'  z ^\s{0,3}([-*_])(?:\s*\1){2,}\s*$z!^\s{0,3}(#{1,6})\s+(.+?)\s*#*\s*$z^\s*(`{3,}|~{3,})(.*)$z^(\s*)(\d+)[.)]\s+(.*)$z^(\s*)[-*+]\s+(.*)$z^\s{0,3}>\s?(.*)$z1^\s*\|?\s*:?-{1,}:?\s*(\|\s*:?-{1,}:?\s*)+\|?\s*$linestrreturnboolc                    t          t                              |           pt                              |                     S )z=True if ``line`` is a markdown list item (bullet or ordered).)r   
_BULLET_REmatch_ORDERED_RE)r   s    G/home/rurouni/.hermes/hermes-agent/plugins/platforms/slack/block_kit.py_is_list_liner   :   s1    
  &&A+*;*;D*A*ABBB    spacesintc                P    d}| D ]}||dk    rdndz  }t          |dz  d          S )zHMap leading whitespace to a nesting level (2 spaces or 1 tab per level).r   	            )min)r   widthchs      r   _indent_levelr#   ?   sB    E ( (bDjja'uz1r   z	`([^`]+)`z7(?<!!)\[([^\]]+)\]\(([^()\s]+(?:\([^()]*\)[^()\s]*)*)\)z(?:\*\*|__)(.+?)(?:\*\*|__)z?(?<![\*_])(?:\*|_)(?![\*_\s])(.+?)(?<![\*_\s])(?:\*|_)(?![\*_])z	~~(.+?)~~textList[Dict[str, Any]]c                n    g ddfddfd
}dfddfd || i            pd| dgS )a
  Parse a run of inline markdown into rich_text section child elements.

    Produces ``text`` elements (optionally styled bold/italic/strike/code) and
    ``link`` elements.  Unmatched markup is emitted verbatim as plain text, so
    this never loses characters.
    Nsr   styleOptional[Dict[str, bool]]r   Nonec                R    | sd S d| d}|r||d<                        |           d S )Nr$   typer$   r(   )append)r'   r(   elelementss      r   	emit_textz#_inline_elements.<locals>.emit_text\   sF     	F&,a88 	 BwKr   Dict[str, bool]c                L   d}t                               |           D ]q} | ||                                         |           t          |          }d|d<    |                    d          |pd            |                                }r | |d          |           d S )Nr   Tcoder   )_INLINE_CODE_REfinditerstartdictgroupend)r'   r(   posm
code_style_walk_linksr1   s        r   walkz_inline_elements.<locals>.walkg   s     ))!,, 	 	AK#aggii-(%000eJ!%JvIaggajj*"4555%%''CCAcddGU#####r   c                   d}t                               |           D ]} | ||                                         |           d|                    d          |                    d          d}|rt	          |          |d<                       |           |                                } | |d          |           d S )Nr   linkr   r   )r-   urlr$   r(   )_LINK_REr6   r7   r9   r8   r.   r:   )r'   r(   r;   r<   link_el_walk_emphasisr0   s        r   r>   z%_inline_elements.<locals>._walk_linksr   s    ""1%% 	 	AN1S]+U333/5aggajjRSRYRYZ[R\R\&]&]G /#';; OOG$$$%%''CCqw&&&&&r   c                   | sd S t           dft          dft          dffD ]\  }}|                    |           }|r | d |                                         |           t          |          }d||<    |                    d          |            | |                                d          |            d S  | |rt          |          nd            d S )NboldstrikeitalicTr   )_BOLD_RE
_STRIKE_RE
_ITALIC_REsearchr7   r8   r9   r:   )r'   r(   rxkeyr<   inner_stylerE   r1   s         r   rE   z(_inline_elements.<locals>._walk_emphasis}   s     	F!6*Z,BZQYDZ[ 	 	GB		!A q!''))}e444"5kk#'C qwwqzz;777q{E222 		!E3T%[[[t44444r   r$   r,   N)r'   r   r(   r)   r   r*   )r'   r   r(   r2   r   r*    )r$   r?   rE   r>   r0   r1   s     @@@@r   _inline_elementsrS   S   s     &(H      	$ 	$ 	$ 	$ 	$ 	$ 	$	' 	' 	' 	' 	' 	' 	'5 5 5 5 5 5 5 	DrNNN76677r   Blockc                    t          j        dd|                                           }t          |          t          k    r|d t          dz
           dz   }dd|ddd	S )
Nz[*_~`] r   u   …header
plain_textT)r-   r$   emojir,   )resubstriplenMAX_HEADER_TEXT)r$   cleans     r   _header_blockr`      se    F9b$''--//E
5zzO##+!++,u4|UUY&Z&Z[[[r   c                 
    ddiS )Nr-   dividerrR   rR   r   r   _divider_blockrc      s    Ir   c                B    ddd|                      d          dgdgdS )N	rich_textrich_text_preformattedr$   
r,   r-   r0   )rstripr$   s    r   _preformatted_blockrk      sD      1&,dkk$6G6GHHI 
  r   lines	List[str]c                    g }t          |           D ]A\  }}|r|                    ddd           |                    t          |                     Bdd|dgdS )Nr$   rg   r,   re   rich_text_quoterh   )	enumerater.   extendrS   )rl   section_childrenilns       r   _quote_blockru      s    -/5!! 6 62 	D##VT$B$BCCC 0 4 45555/=MNNO  r   itemsList[Tuple[int, bool, str]]c                    g }d}d}| D ]a\  }}}||f}||k    r"d|rdnd|g d}|                     |           |}|J |d                              dt          |          d           bd	|dS )
a0  Build ONE rich_text block from consecutive list items.

    ``items`` is a list of ``(indent, ordered, text)``.  Each contiguous run
    sharing the same (indent, ordered) becomes a ``rich_text_list`` element;
    indentation changes start a new element, which is how Slack renders true
    nesting.
    Nrich_text_listorderedbullet)r-   r(   indentr0   r0   rich_text_sectionrh   re   )r.   rS   )rv   r0   curcur_keyr|   rz   r$   rO   s           r   _list_blockr      s     &(H$(C*.G!& 
 
w'>>(&-;8 	 C OOC   GJ(6Ft6L6LMM	
 	
 	
 	
  X666r   c                    dd| ddS )Nsectionmrkdwnr,   rR   rj   s    r   _section_blockr      s    $'G'GHHHr   sep_linec                   g }|                                                       d                              d          D ]}|                                 }|                    d          }|                    d          }|r|r|                    d           Z|r|                    d           r|                    d           |S )zParse a markdown separator row (``|:--|:-:|--:|``) into column aligns.

    Returns a list of ``"left"``/``"center"``/``"right"`` per column.
    |:centerrightleft)r\   split
startswithendswithr.   )r   alignscellcr   r   s         r   _parse_alignmentr      s    
 F  &&s++11#66 	" 	"JJLL||C  

3 	"E 	"MM(#### 	"MM'""""MM&!!!!Mr   rowc                    |                                                       d                              dd          }d |                    d          D             S )zSplit a markdown table row into trimmed cell strings.

    Respects backslash-escaped pipes (``\|``) so they aren't treated as
    column separators.
    r   z\| PIPE c                ^    g | ]*}|                                                     d d          +S )r   r   )r\   replace).0r   s     r   
<listcomp>z_split_row.<locals>.<listcomp>   s0    QQQqAGGIInc22QQQr   )r\   r   r   )r   	protecteds     r   
_split_rowr      sO     		!!#&&..unEEIQQIOOC<P<PQQQQr   Dict[str, Any]c                .    ddt          |           dgdS )z=A ``rich_text`` table cell carrying inline-formatted content.re   r}   rh   )rS   rj   s    r   _rich_text_cellr      s/     (6Ft6L6LMM
  r   rowsOptional[Block]c                   d | D             }|sdS t          d |D                       }t          |          t          k    s|t          k    rdS |D ]+}|                    dg|t          |          z
  z             ,t          d |D                       }|t          k    rdS t          |          }g }t          t          |t                              D ]>}|t          |          k     r||         nd}	|
                    |	dk    rd|	ind           ?dd	 |D             d
}
t          d |D                       r||
d<   |
S )u  Build a native Slack ``table`` block from markdown pipe-table rows.

    ``rows`` includes the header row (index 0) and body rows; ``sep_line`` is
    the ``|---|`` alignment row (already consumed by the caller).  Returns
    ``None`` when the table exceeds Slack's limits (100 rows / 20 cols /
    10,000 aggregate cell chars) or parses to nothing — the caller then falls
    back to the monospace preformatted rendering.
    c                T    g | ]%}|                                 t          |          &S rR   )r\   r   r   rs     r   r   z _table_block.<locals>.<listcomp>  s+    777QWWYY7jmm777r   Nc              3  4   K   | ]}t          |          V  d S rQ   r]   r   s     r   	<genexpr>z_table_block.<locals>.<genexpr>  (      ''1A''''''r   rV   c              3  >   K   | ]}|D ]}t          |          V  d S rQ   r   r   r   r   s      r   r   z_table_block.<locals>.<genexpr>  s5      88a88c!ff8888888r   r   aligntablec                &    g | ]}d  |D             S )c                ,    g | ]}t          |          S rR   )r   )r   r   s     r   r   z+_table_block.<locals>.<listcomp>.<listcomp>)  s     888D/$''888r   rR   )r   r   s     r   r   z _table_block.<locals>.<listcomp>)  s'    KKKS88C888KKKr   )r-   r   c              3     K   | ]}|d uV  	d S rQ   rR   )r   css     r   r   z_table_block.<locals>.<genexpr>+  s&      
4
4b2T>
4
4
4
4
4
4r   column_settings)maxr]   MAX_TABLE_ROWSMAX_TABLE_COLSrq   sumMAX_TABLE_CHARSr   ranger    r.   any)r   r   parsedncolsr   total_charsr   r   r   r   blocks              r   _table_blockr     s    87T777F t'''''''E
6{{^##u~'='=t * *	"Q())))88f88888K_$$th''F68O3un--.. N NV__q		& 	5F??//MMMM KKFKKK E 
4
4O
4
4
444 3#2 Lr   c           	        g | D ]&t                    }                    |           'sd                    |           S t          d D                       }D ]+                    dg|t                    z
  z             ,fdt          |          D             g }t                    D ]\  }d                    fdt          |          D                       }|                    |                                           |dk    rA|                    d                    fd	t          |          D                                  d                    |          S )
zERender markdown pipe-table rows as aligned monospace text (fallback).rg   c              3  4   K   | ]}t          |          V  d S rQ   r   r   s     r   r   z _render_table.<locals>.<genexpr>8  r   r   rV   c                H    g | ]t          fd D                       S )c              3  B   K   | ]}t          |                   V  d S rQ   r   r   s     r   r   z+_render_table.<locals>.<listcomp>.<genexpr>;  s-      ,,#ad)),,,,,,r   )r   )r   r   r   s    @r   r   z!_render_table.<locals>.<listcomp>;  s7    CCCc,,,,V,,,,,CCCr   z | c              3  Z   K   | ]%}|                              |                   V  &d S rQ   )ljust)r   r   r   widthss     r   r   z _render_table.<locals>.<genexpr>>  s7      FFA!A$**VAY//FFFFFFr   r   z-+-c              3  .   K   | ]}d |         z  V  dS )-NrR   )r   r   r   s     r   r   z _render_table.<locals>.<genexpr>A  s+      'N'NAfQi'N'N'N'N'N'Nr   )	r   r.   joinr   rq   r]   r   rp   ri   )	r   cellsr   	out_linesrir   r   r   r   s	         @@@r   _render_tabler   0  s    F  1e yy'''''''E * *	"Q())))CCCCeEllCCCFI6"" P PAzzFFFFFuFFFFF'''77UZZ'N'N'N'Nu'N'N'NNNOOO99Yr   markdownOptional[List[Block]]c                .   | r|                                  sdS |pd 	 g |                     dd                              d          }d}t          |          }g dfd}||k     r||         }|                                 s |             |d	z  }3t                              |          }|r |             |                    d	          }g }	|d	z  }||k     r||                                                             |          sS|		                    ||                    |d	z  }||k     r-||                                                             |          S|d	z  }	                    t          d                    |	                               7t                              |          r2 |             	                    t                                 |d	z  }t                              |          }
|
rF |             	                    t          |
                    d
                               |d	z  }d|v r|d	z   |k     rt                               ||d	z                      r |             |}||d	z            }|g}|d
z  }||k     rnd||         v rd||                                          rJ|	                    ||                    |d	z  }||k     r$d||         v r||                                          Jt#          ||          }|	                    |           n/	                    t          t%          |                               t&                              |          r |             g }||k     rVt&                              ||                   }|sn3|	                    |                    d	                     |d	z  }||k     V	                    t)          |                     t+          |          r |             g }||k     rt,                              ||                   }t.                              ||                   }|rR|	                    t1          |                    d	                    d|                    d
          f           |d	z  }nH|rQ|	                    t1          |                    d	                    d|                    d          f           |d	z  }n||                                          rU||                             d          r:|r8|d         \  }}}|||dz   ||                                          z   f|d<   |d	z  }n||                                          sk|ri|d	z   }||k     r?||                                          s%|d	z  }||k     r||                                          %||k     rt+          ||                   r|}nnn||k     	                    t3          |                     Ӊ	                    |           |d	z  }||k      |             sdS t                    t4          k    rdS S # t6          $ r Y dS w xY w)uc  Convert agent markdown to a Slack Block Kit ``blocks`` list.

    Args:
        markdown: The agent's response text (standard markdown).
        mrkdwn_fn: Optional callable converting a markdown paragraph to Slack
            mrkdwn for ``section`` blocks (the adapter passes
            ``format_message``).  When ``None``, the raw paragraph text is used.

    Returns:
        A list of Block Kit block dicts, or ``None`` when the content is empty,
        exceeds Slack's structural limits, or hits an unexpected shape — the
        caller then falls back to the flat ``text`` payload.  Never raises.
    Nc                    | S rQ   rR   )r'   s    r   <lambda>zrender_blocks.<locals>.<lambda>^  s    ! r   z
rg   r   r   r*   c                    sd S d                                                               }                                  | sd S  |           }t          |t                    D ]$}                    t          |                     %d S )Nrg   )r   r\   clear_split_textMAX_SECTION_TEXTr.   r   )r$   renderedchunkblocksfmtparas      r   
flush_paraz!render_blocks.<locals>.flush_parag  s     99T??((**DJJLLL s4yyH$X/?@@ 5 5nU3344445 5r   r   r   r   FT   ) r   r   )r   r*   )r\   r   r   r]   	_FENCE_REr   r9   lstripr   r.   rk   r   _HR_RErc   
_HEADER_REr`   _TABLE_SEP_REr   r   	_QUOTE_REru   r   r   r   r#   r   
MAX_BLOCKS	Exception)r   	mrkdwn_fnrl   rs   nr   r   fencemarkerbodyhm
header_rowr   trowsr   qlinesqmrv   bmomr|   rz   txtjr   r   r   s                           @@@r   render_blocksr   J  s   "  8>>++ t

$CO   ..44T::JJ
	5 
	5 
	5 
	5 
	5 
	5 
	5 
	5 !ee8D ::<< 
Q OOD))E 

Q"$Q!eeE!HOO$5$5$@$@$H$HeKKa)))FA !eeE!HOO$5$5$@$@$H$He Q1$))D//BBCCC ||D!! 
n..///Q !!$''B 
mBHHQKK88999Q d{{q1uqyy]-@-@q1u-N-Ny
!
 Q<#Q!eeuQxE!HNN4D4DLLq***FA !eeuQxE!HNN4D4D
 %UH55$MM%((((MM"5mE6J6J"K"KLLL t$$ 

$&!ee"q22B MM"((1++...FA !ee l622333 T"" $
57!ee#))%(33B$**5844B mBHHQKK&@&@%RS%UVVVQ mBHHQKK&@&@$QR%TUUUQq)) eAh.A.A+.N.N SX /4Ry,%+WcCi%(..BRBR6R$Sb	Q"1X^^-- %  E!eeE!HNN,<,<eFA  !eeE!HNN,<,<eq55]58%<%<5 !AA!? !ee@ k%00111 KKFA_ !eeb 	
 	4v;;## 4   tts   YZ *Z Z 
ZZlimitc                f   t          |           |k    r| gS g }| }t          |          |k    rl|                    dd|          }|dk    r|}|                    |d|                    ||d                             d          }t          |          |k    l|r|                    |           |S )zLSplit ``text`` into <= ``limit``-char chunks on line, then hard, boundaries.rg   r   N)r]   rfindr.   r   )r$   r   out	remainingcuts        r   r   r     s    
4yyEvCI
i..5
 
 oodAu--!88C

9TcT?###cddO**400	 i..5
 
   

9Jr   )r   r   r   r   )r   r   r   r   )r$   r   r   r%   )r$   r   r   rT   )r   rT   )rl   rm   r   rT   )rv   rw   r   rT   )r   r   r   rm   )r   r   r   rm   )r$   r   r   r   )r   rm   r   r   r   r   )r   rm   r   r   rQ   )r   r   r   r   )r$   r   r   r   r   rm   )/__doc__
__future__r   rZ   typingr   r   r   r   r   r   r   r^   r   r   r   r   rT   compiler   r   r   r   r   r   r   r   r#   r5   rC   rJ   rL   rK   rS   r`   rc   rk   ru   r   r   r   r   r   r   r   r   r   rR   r   r   <module>r      s   8 # " " " " " 				 3 3 3 3 3 3 3 3 3 3 3 3 3 3 
 S#X 
7	8	8RZ<==
BJ011	bj344RZ.//
BJ+,,	
OPPC C C C
    "*\**2:PQQ2:455RZZ[[
RZ%%
:8 :8 :8 :8D\ \ \ \   
 
 
 
	 	 	 	7 7 7 7:I I I I   &R R R R   % % % %P       8 e e e e eP     r   