11from __future__ import annotations
22
33import re
4- from pathlib import Path
5- from typing import Any , cast
64
75from agent .lifecycle .composition import (
86 AFTER_REASONING_PREPROCESS_EVENT ,
97 PROMPT_RENDER_EVENT ,
108)
119from agent .lifecycle .types import AfterReasoningCtx , PromptRenderCtx
1210from agent .plugin_composition import Context , ServiceKey
13- from agent .plugins import Plugin , on_after_reasoning
1411from agent .prompting import PromptSectionRender
1512from .runtime import MemeCatalog , MemeDecorator
1613
17- _CTX_SLOT = "prompt:ctx"
1814_MEME_RE = re .compile (
1915 r"(?<!`)<meme:([a-zA-Z0-9_-]+)>(?!`)" ,
2016 re .IGNORECASE ,
@@ -44,22 +40,6 @@ def decorate_meme_ctx(ctx: AfterReasoningCtx, decorator: MemeDecorator) -> None:
4440 ctx .meme_tag = decorated .tag
4541
4642
47- class MemePromptModule :
48- slot = "meme.prompt"
49- requires = ("prompt_render.emit" , "citation.prompt" , _CTX_SLOT )
50- produces = (_CTX_SLOT ,)
51-
52- def __init__ (self , plugin : "MemePlugin" ) -> None :
53- self ._plugin = plugin
54-
55- async def run (self , frame : Any ) -> Any :
56- ctx = frame .slots .get (_CTX_SLOT )
57- if not isinstance (ctx , PromptRenderCtx ):
58- return frame
59- append_meme_prompt (ctx , self ._plugin .catalog )
60- return frame
61-
62-
6343api_version = 3
6444name = "meme"
6545version = "1.0.0"
@@ -88,51 +68,6 @@ def answer_listener(answer: AfterReasoningCtx) -> None:
8868 _ = await ctx .on (AFTER_REASONING_PREPROCESS_EVENT , answer_listener )
8969
9070
91- class MemePlugin (Plugin ):
92- api_version = 2
93-
94- @classmethod
95- def dashboard_module (cls ) -> str | None :
96- return "dashboard.py"
97-
98- name = "meme"
99- version = "1.0.0"
100-
101- @classmethod
102- def skill_roots (cls ) -> tuple [str , ...]:
103- return ("skills" ,)
104-
105- _catalog : Any = None
106- _decorator : Any = None
107-
108- async def prepare (self ) -> None :
109- memes_dir = (
110- _workspace (self .context .plugin_dir , self .context .workspace ) / "memes"
111- )
112- self ._catalog = MemeCatalog (memes_dir )
113- self ._decorator = MemeDecorator (self ._catalog )
114-
115- def prompt_render_modules (self ) -> list [object ]:
116- return [MemePromptModule (self )]
117-
118- @on_after_reasoning ()
119- async def decorate_meme (self , ctx : AfterReasoningCtx ) -> AfterReasoningCtx :
120- decorate_meme_ctx (ctx , self .decorator )
121- return ctx
122-
123- @property
124- def catalog (self ) -> Any :
125- if self ._catalog is None :
126- raise RuntimeError ("meme 插件尚未初始化" )
127- return self ._catalog
128-
129- @property
130- def decorator (self ) -> Any :
131- if self ._decorator is None :
132- raise RuntimeError ("meme 插件尚未初始化" )
133- return self ._decorator
134-
135-
13671def _extract_meme_tag (response : str ) -> tuple [str , str | None ]:
13772 match = _MEME_RE .search (response )
13873 if match is None :
@@ -141,9 +76,3 @@ def _extract_meme_tag(response: str) -> tuple[str, str | None]:
14176 cleaned = re .sub (r"[ \t]+\n" , "\n " , cleaned )
14277 cleaned = re .sub (r" {2,}" , " " , cleaned )
14378 return cleaned .strip (), match .group (1 ).lower ()
144-
145-
146- def _workspace (plugin_dir : Path , configured : Path | None ) -> Path :
147- if configured is not None :
148- return configured
149- return cast (Path , plugin_dir .parent .parent )
0 commit comments