Skip to main content
Glama
__init__.py6.43 kB
"""统一事件解析器模块。 cli-agent-mcp shared/parsers v0.1.0 同步日期: 2025-12-16 本模块提供统一的事件解析接口,支持自动检测 CLI 来源。 Example: from parsers import parse_event, create_parser # 方式 1: 自动检测(无状态,简单用法) event = parse_event(raw_data) # 方式 2: 使用 Parser 类(有状态,完整功能) parser = create_parser("gemini") for line in stream: event = parser.parse(json.loads(line)) gui.push_event(event) """ from __future__ import annotations from typing import Any from .base import ( VERSION, CLISource, ContentType, EventCategory, OperationType, Status, ) from .claude import ClaudeParser, parse_claude_event from .codex import CodexParser, parse_codex_event from .gemini import GeminiParser, parse_gemini_event from .opencode import OpencodeParser, parse_opencode_event from .unified import ( LifecycleEvent, MessageEvent, OperationEvent, SystemEvent, UnifiedEvent, UnifiedEventBase, make_event_id, make_fallback_event, ) __all__ = [ # 版本 "VERSION", # 基础类型 "CLISource", "EventCategory", "ContentType", "OperationType", "Status", # 统一事件 "UnifiedEventBase", "LifecycleEvent", "MessageEvent", "OperationEvent", "SystemEvent", "UnifiedEvent", # 工厂函数 "make_event_id", "make_fallback_event", # 解析器类 "GeminiParser", "CodexParser", "ClaudeParser", "OpencodeParser", # 便捷函数 "parse_event", "parse_events", "parse_gemini_event", "parse_codex_event", "parse_claude_event", "parse_opencode_event", "detect_source", "create_parser", ] def detect_source(data: dict[str, Any]) -> CLISource: """检测事件来源 CLI。 根据事件中的特征字段判断来自哪个 CLI。 Args: data: 原始事件字典 Returns: CLISource 枚举值 """ event_type = data.get("type", "") subtype = data.get("subtype", "") # OpenCode CLI 特征 # OpenCode 事件包含 sessionID 字段(注意大小写与其他 CLI 不同) if "sessionID" in data: # 特有事件类型 if event_type in ("tool_use", "step_start", "step_finish", "text", "error"): # 检查是否有 part 字段(OpenCode 特有) if "part" in data or event_type == "error": return CLISource.OPENCODE # Claude Code CLI 特征 # system/init 事件包含 claude_code_version if event_type == "system" and subtype == "init": if "claude_code_version" in data or "session_id" in data: return CLISource.CLAUDE # assistant/user/result 事件包含 message 结构 if event_type in ("assistant", "user", "result"): if "message" in data or "session_id" in data: return CLISource.CLAUDE # Gemini CLI 特征 if event_type == "init" and "session_id" in data and "model" in data: return CLISource.GEMINI if event_type in ("message", "tool_use", "tool_result"): if event_type == "message" and "role" in data: return CLISource.GEMINI if event_type in ("tool_use", "tool_result") and "tool_id" in data: return CLISource.GEMINI if event_type == "result" and "stats" in data: return CLISource.GEMINI # Codex CLI 特征 if event_type == "thread.started" and "thread_id" in data: return CLISource.CODEX if event_type in ("item.started", "item.completed", "item.updated"): return CLISource.CODEX if event_type in ("turn.started", "turn.completed", "turn.failed"): return CLISource.CODEX # Live 事件标识(MCP 内部包装) if data.get("geminimcp") == "live": return CLISource.GEMINI if data.get("codexmcp") == "live": return CLISource.CODEX if data.get("claudemcp") == "live": return CLISource.CLAUDE if data.get("opencodemcp") == "live": return CLISource.OPENCODE return CLISource.UNKNOWN def create_parser(source: CLISource | str) -> GeminiParser | CodexParser | ClaudeParser | OpencodeParser: """创建指定 CLI 的解析器实例。 Args: source: CLI 来源标识 Returns: 对应的 Parser 实例 Raises: ValueError: 不支持的 CLI 来源 """ if isinstance(source, str): source = CLISource(source.lower()) if source == CLISource.GEMINI: return GeminiParser() elif source == CLISource.CODEX: return CodexParser() elif source == CLISource.CLAUDE: return ClaudeParser() elif source == CLISource.OPENCODE: return OpencodeParser() else: raise ValueError(f"Unsupported CLI source: {source}") def parse_event(data: dict[str, Any]) -> UnifiedEvent: """自动检测并解析事件,返回单个事件。 这是一个无状态的便捷函数,自动检测 CLI 来源并解析。 对于需要维护状态的场景(如关联 tool_call 和 tool_result), 请使用 create_parser() 创建 Parser 实例。 注意:对于 Claude CLI,一个原始事件可能产生多个统一事件, 此函数只返回第一个。如需获取所有事件,请使用 parse_events()。 Args: data: 原始事件字典 Returns: 统一事件实例 """ events = parse_events(data) return events[0] if events else make_fallback_event(CLISource.UNKNOWN, data) def parse_events(data: dict[str, Any]) -> list[UnifiedEvent]: """自动检测并解析事件,返回事件列表。 对于 Claude CLI,一个原始事件(如 assistant 消息)可能包含 多个内容块(thinking + text + tool_use),每个都会产生一个统一事件。 Args: data: 原始事件字典 Returns: 统一事件列表 """ source = detect_source(data) if source == CLISource.GEMINI: return [parse_gemini_event(data)] elif source == CLISource.CODEX: return [parse_codex_event(data)] elif source == CLISource.CLAUDE: return parse_claude_event(data) elif source == CLISource.OPENCODE: return [parse_opencode_event(data)] else: # 无法识别的来源,返回 Fallback return [make_fallback_event(CLISource.UNKNOWN, data)]

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/shiharuharu/cli-agent-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server