Skip to content

Commit 3970868

Browse files
refactor: remove meme plugin v2 shell
1 parent 6de810e commit 3970868

4 files changed

Lines changed: 90 additions & 360 deletions

File tree

.github/workflows/plugin-api-v3.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ jobs:
4949
cache-dependency-path: .akashic-core/requirements.txt
5050
- name: Install pinned Core dependencies
5151
run: python -m pip install -r .akashic-core/requirements.txt pytest pytest-asyncio
52-
- name: Compare v2 and v3 Meme receipts
52+
- name: Verify Meme v3 behavior
5353
env:
5454
AKASHIC_AGENT_ROOT: .akashic-core
5555
AKASHIC_CITATION_ROOT: .citation

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
| `dashboard_module = "dashboard.py"` | 声明 v3 Dashboard |
1515
| `workspace_roots = ("memes",)` | 取得 Core 分配的表情包资产根 |
1616

17-
插件通过模块命名导出声明静态贡献,通过 `apply(ctx, config)` 自行构建 `MemeCatalog`/`MemeDecorator` 并注册接入点。`citation.protocol` 是硬依赖:Citation 先剥离 cited metadata 并保留 meme tag,Meme 再完成媒体装饰,Citation cleanup 最后清除残留协议标签。Core 只分配生命周期、依赖顺序与 workspace root;Meme 的目录结构、随机选图和 Dashboard 仍由插件拥有。`MemePlugin` 暂时保留,只用于迁移期差分验证。
17+
插件通过模块命名导出声明静态贡献,通过 `apply(ctx, config)` 自行构建 `MemeCatalog`/`MemeDecorator` 并注册接入点。`citation.protocol` 是硬依赖:Citation 先剥离 cited metadata 并保留 meme tag,Meme 再完成媒体装饰,Citation cleanup 最后清除残留协议标签。Core 只分配生命周期、依赖顺序与 workspace root;Meme 的目录结构、随机选图和 Dashboard 仍由插件拥有。
1818

1919
---
2020

@@ -24,7 +24,7 @@
2424

2525
从工作区路径(`workspace/memes/`)加载 `manifest.json`,构建 `MemeCatalog``MemeDecorator` 实例。`MemeCatalog` 按需检测 manifest 的 mtime,变动时自动热重载,不需要重启。
2626

27-
### 2. 注入 catalog(MemePromptModule)
27+
### 2. 注入 catalog
2828

2929
每轮推理前,调用 `catalog.build_prompt_block()` 把启用的表情包类别(名称、描述、别名)拼成文本块,追加到系统 prompt 底部,告知 LLM 可以在回复中嵌入 `<meme:tag>` 标签。如果 catalog 为空则跳过注入。
3030

plugin.py

Lines changed: 0 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,16 @@
11
from __future__ import annotations
22

33
import re
4-
from pathlib import Path
5-
from typing import Any, cast
64

75
from agent.lifecycle.composition import (
86
AFTER_REASONING_PREPROCESS_EVENT,
97
PROMPT_RENDER_EVENT,
108
)
119
from agent.lifecycle.types import AfterReasoningCtx, PromptRenderCtx
1210
from agent.plugin_composition import Context, ServiceKey
13-
from agent.plugins import Plugin, on_after_reasoning
1411
from agent.prompting import PromptSectionRender
1512
from .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-
6343
api_version = 3
6444
name = "meme"
6545
version = "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-
13671
def _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

Comments
 (0)