从 OpenClaw、Codex 到 Hermes,看懂 AI Agent 架构为什么正在收敛

作 者:吴佳浩Alben
撰稿时间:2026.8.21
更新时间:2026.8.22
本文只讨论公开 GitHub 仓库、公开提交记录和公开源代码,目的是还原多个独立团队各自的设计演化路径,不构成对"代码抄袭"的指控——筒子们这一点全文只声明这一次,后面我们就不再重复。(现在很多无良的自媒体大肆的宣扬Codex终于开源了之类的话,实属没必要,接下来我们一起来看看真相)
引言:Agent 的核心竞争力到底是什么?
很多人认为:
Agent 的核心竞争力是 Prompt。
也有人认为:
Agent 的核心竞争力是 Tool 数量。
还有人认为:
Agent 越智能,只需要换更强的大模型就够了。
但过去一年 Agent Framework 的发展,正在证明一个完全不同的事实:
真正决定下一代 Agent 能力的,不是 Prompt,不是 Tool 数量,也不是模型参数——而是 Runtime。
为什么?因为你会发现一个奇怪的现象:
OpenClaw、OpenAI Codex、NousResearch Hermes——三个路线完全不同的项目,最终都开始出现同一组东西:
Skill 系统 Plugin 系统 Runtime 生命周期管理 Subagent Invocation Analytics Permission / Trust Workflow
这不是谁抄谁。而是:
当 Agent 复杂度超过某个临界点,它一定会开始向操作系统演化。
三个项目的 GitHub 仓库公开时间:
openai/codex | |||
NousResearch/hermes-agent |
Codex 比 Hermes 早了三个多月,三个项目各自独立发展,语言不同、架构哲学不同、目标用户不同——但它们最终却长出了几乎相同的架构骨架。这篇文章,就是试图回答一个问题:
为什么所有 Agent Framework,最后都会变成 Agent OS?
Codex、Hermes、OpenClaw 只是案例,真正的主角是 Agent Framework 本身。
第一章:Agent 演化的五个时代
回顾过去三年,AI Agent 的架构演化可以清晰地分成五个阶段:
2023 Prompt Era一个超长 Prompt 解决所有问题"写好 system prompt 就够了"↓2024 Tool Era模型开始调用外部能力Function Calling / Tool Use 出现↓2025 Skill Era能力开始模块化封装SKILL.md 成为约定↓2026 Runtime Era能力开始生命周期管理Skill 变成可观测、可统计的运行时对象↓未来 Agent OS Era多个 Agent 协作运行Memory / Workflow / Scheduler / Permission

你可能觉得这个划分太粗了。那我们换一个角度——把它和软件工程的历史放在一起看:
两边的演化逻辑完全一致:复杂度增长 → 必须抽象 → 必须封装 → 必须管理生命周期 → 必须变成操作系统。
Agent 的 Skill,本质上就是 AI 时代的 Library。
理解了这条主线,后面的每一章都只是在回答一个问题:这一步为什么一定会发生?
第二章:Skill 为什么是 Agent 世界的"函数库"
从 SKILL.md 说起
2025 年,几乎所有主流 Agent Framework 都不约而同地采用了同一种文件格式:
---name: github-code-reviewdescription: Review PRs: diffs, inline comments via gh or REST.---## 适用场景当用户需要 review Pull Request 时使用本 Skill。## 工作流程1. 读取 PR diff2. 检查代码质量3. 提交 inline comments
OpenClaw 用它。Codex 用它。Hermes 用它。这不是谁学谁——而是当能力需要被复用、被分享、被组合时,一份带 frontmatter 的 Markdown 文件是最自然的选择:
人可读(不像 JSON 那样对非技术用户不友好) 机器可解析(frontmatter 是结构化数据) 可包含多级文件(references/、scripts/、assets/) 可版本控制(纯文本,Git 友好)
三者的目录结构几乎一致:
SKILL.md | SKILL.md | SKILL.md | |
references/ | references/ | references/ | |
scripts/ | scripts/ | scripts/ | |
assets/ | assets/ | assets/ | |
templates/ |
这不是"三家公司开了同样的会",而是 Skill 这个东西的本质决定了它的组织方式——就像 npm 包一定有 package.json,Python 包一定有 __init__.py,不是因为谁抄谁,而是因为这个问题的解空间就这么大。
当能力需要被复用,它就一定会被封装成 Library。SKILL.md 只是这个时代的 package.json。
但 Skill 一多,问题就来了
三个项目发展到 2026 年,都遇到了同一个瓶颈:
Skill 数量 < 10 → 目录扫描够用Skill 数量 ~ 50 → 需要缓存Skill 数量 ~ 200 → 需要聚合入口Skill 数量 ~ 1000+ → 需要 Runtime
这就是为什么三个项目不约而同地在 2026 年开始做同一件事:把 Skill 从静态文件,变成有生命周期的运行时对象。
第三章:OpenClaw——第一个成功的 Agent Application,但不是最终形态
OpenClaw 做对了什么
OpenClaw 是 2024 年最早跑通的 Application Agent,它的架构非常清晰:
用户│Channel(Telegram / Discord / Web)│Agent│Tool(Function Calling)│Skill(SKILL.md)│Plugin(第三方扩展)
OpenClaw 的成功在于:它最先证明了"一个 Agent 可以成为日常使用的个人助手"。 用户入口强、生态扩展快、个人助手场景成熟。
但 OpenClaw 遇到了什么问题
当 Skill 从几十增长到几百、几千时,OpenClaw 的扁平架构开始出现压力:
谁调用了这个 Skill?为什么调用?权限是什么?成本多少?版本是什么?依赖什么?
这些问题的答案,不是"换更强的模型"就能解决的——它们是工程问题,需要一套运行时管理系统来回答。
OpenClaw 的 SKILL.md 是静态文件,缺少:
显式/隐式调用追踪 运行时统计 插件隔离 Subagent 生命周期 项目级信任边界
不是说 OpenClaw 做错了什么,而是它正处于:
Application Agent → Runtime Agent的过渡期。

一句话总结:
OpenClaw 解决了"如何拥有一个 Agent",而 Codex 和 Hermes 正在解决"如何管理一万个 Agent 能力"。
这不是谁比谁强——OpenClaw 在 Application 层最先跑通,Codex 和 Hermes 在 Runtime 层最先碰到墙。它们面对的是同一条演化路径的不同阶段。
第四章:Skill 为什么一定会变成 Runtime
这一章是全文的核心。我们用三个项目的真实代码来回答一个问题:
Skill 从静态文件变成运行时对象,到底发生了什么?
4.1 Skill 从"一个"变成"一组":聚合入口
当 Skill 超过几十个之后,用户不可能记住每一个名字。三个项目各自发明了"聚合入口":
Hermes 的解法:Skill Bundle
Hermes 提交:2026-05-19:feat(skills): add skill bundles
Hermes 的 Bundle 是一个用户可编辑的 YAML 文件:
name: backend-devdescription: Backend feature work — code review, testing, PR workflow.skills:- github-code-review- test-driven-development- github-pr-workflowinstruction: |Focus on small, reviewable changes.
调用方式是 /backend-dev,系统完成的流程:

Hermes 代码中有一组清晰的公开函数:
get_skill_bundles()resolve_bundle_command_key()build_bundle_invocation_message()reload_bundles()list_bundles()save_bundle()delete_bundle()
还维护 Bundle 缓存和 Slash 名称冲突规则:
_bundles_cache: Dict[str, Dict[str, Any]] = {}_bundles_cache_mtime: Optional[float] = None# If a bundle and a skill share the same slash name, the bundle wins.
这不是简单的"有一个 SKILL.md",而是把 Skill 做成了:配置文件 + Slash 入口 + 多 Skill 聚合 + 缓存 + CRUD + 冲突优先级 + 统一上下文注入。
Codex 的解法:Skill Root / Package / Alias
Codex 相关提交集中在 2026 年 8 月:
2026-08-04:Move executor skill bundle loading into the skills extension 2026-08-06:Support plugin roots in the host skill loader 2026-08-07:Add shared skill root loading interfaces 2026-08-07:Unify plugin skill loading with the host skill service 2026-08-12:Resolve skill package aliases in skills.read
Codex 的 Rust 代码结构中出现了:
pub struct LoadedSkillRoot {pub skills: Vec<SkillMetadata>,}pub struct SkillRootSnapshots<Root> {// snapshot cache for loaded roots}pub fn collect_explicit_skill_mentions(// collect skills selected by explicit mentions) -> Vec<SkillMetadata>pub enum ImplicitSkillAccess {// implicit access from script or document reads}
Codex 的组织方式是"一个插件/Executor 根目录 → 多个 Skill 资源",与 Hermes 的"一个命令名 → 多个 Skill"思路不同,但要解决的问题是同一个:
skill-bundles/*.yaml | ||
/backend-dev | ||
get_skill_bundles() | ||
_bundles_cache_mtime | SkillRootSnapshotCache | |
build_bundle_invocation_message() |
为什么都会走到"聚合入口"这一步?
因为当 Skill 数量超过几十个之后,靠用户手动一个个挑选或者靠目录扫描已经无法满足调用效率——你需要一个"打包"的中间层,把相关 Skill 捆在一起,用一个入口触发。这不是某个团队独创的巧思,而是 Skill 系统规模变大之后的必然结果。
任何 Agent,只要 Skill 足够多,就一定会发明 Bundle,只是名字不同。
4.2 Skill 开始有"被谁调用"的记录:Invocation Analytics
当 Skill 变成运行时对象后,下一个问题立刻出现:
哪些 Skill 真正被调用了?是用户主动选的,还是模型自己触发的?调用频率是多少?哪个插件提供的 Skill 最受欢迎?
不回答这些问题,就没法优化 Prompt、淘汰无用 Skill、给插件方做归因分账。
Hermes 的解法:Skill Metrics
Hermes 的 Skill 生命周期:
Skill discovery → Skill preprocessing → Skill injection → Skill invocation → Skill metrics相关提交:
2026-04-24:Skill preprocessing / inline shell 2026-05-19:Skill bundles 2026-07-29:Relay Skill Metrics
Hermes 的 Skill 预处理代码包含真实的模板变量和 inline shell 语法:
_SKILL_TEMPLATE_RE = re.compile(r"\$\{(HERMES_SKILL_DIR|HERMES_SESSION_ID)\}")_INLINE_SHELL_RE = re.compile(r"!`([^`\n]+)`")_INLINE_SHELL_MAX_OUTPUT = 4000def expand_inline_shell(content: str,skill_dir: Path | None,timeout: int,) -> str:"""Replace every !`cmd` snippet in content with its stdout."""if "!`" not in content:return contentdef _replace(match: re.Match) -> str:cmd = match.group(1).strip()if not cmd:return ""return run_inline_shell(cmd, skill_dir, timeout)return _INLINE_SHELL_RE.sub(_replace, content)
Hermes 的 Skill 因此具备了:运行时变量替换、Skill 目录感知、当前 Session 感知、动态 Shell 片段、超时保护、输出长度限制。
Codex 的解法:Invocation Analytics
Codex 相关提交:
2026-07-10:Add a skill invocation extension contributor 2026-07-24:Propagate remote plugin IDs to skill metadata 2026-08-11:Track resource-backed skill invocations 2026-08-11:Track implicit executor skill invocations 2026-08-18:Attribute executor skill invocations to plugins
Codex 的 Rust 源码中区分了显式与隐式调用:
pub(crate) fnemit_explicit_skill_invocations(sess: &Session,turn_context: &TurnContext,mentioned_skills: &[SkillMetadata],injected_skills: &[SkillMetadata],tracking: TrackEventsContext,) {// explicit invocation telemetry and analytics}pub(crate) async fn maybe_emit_implicit_skill_invocation(sess: &Session,turn_context: &TurnContext,command: &str,workdir: &PathUri,native_workdir: Option<&AbsolutePathBuf>,environment_id: &str,) {let Some(invocation) = detect_implicit_skill_invocation(turn_context.extension_data.as_ref(),environment_id,command,workdir,native_workdir,) else {return;};}
并用集合去重,避免同一 Skill 被重复统计:
struct ImplicitSkillInvocations(Mutex<HashSet<String>>);let inserted = {let skill_invocations = turn_context.extension_data.get_or_init(ImplicitSkillInvocations::default);let mut seen_skills = skill_invocations.0.lock().await;seen_skills.insert(seen_key)};if !inserted {return; // 已经统计过,不重复}
三者的对照
SKILL.md | SKILL.md | SKILL.md | |
HashSet | |||
把 Skill 生命周期画成状态机,三个项目都走到了"Tracked"这一步:

OpenClaw 停在 Injected。Hermes 和 Codex 都走到了 Tracked 和 Attributed。
为什么都会做 Invocation Analytics?
因为只有统计"哪些 Skill 真正被调用了、被谁调用的、是用户主动选的还是模型自己触发的",才能反过来优化 Prompt、淘汰长期没人用的 Skill、给插件方做归因分账。Skill 库一旦变成"运行时资产",不统计使用情况就等于闭着眼睛做产品——这也是为什么 Hermes 和 Codex 都不约而同地把"显式/隐式"分开追踪:混在一起统计,Analytics 会失真。
当 Skill 开始被统计,它就已经不是 Prompt,而是产品。
第五章:Plugin 为什么一定异步化
同步插件的问题
最简单的插件架构是这样的:
Agent 执行→ 调用 Plugin→ Plugin 同步返回→ Agent 继续
问题出在:如果 Plugin 崩溃了、超时了、死锁了,Agent 主流程也会被阻塞。一个坏插件拖垮整个 Agent 会话——这在 Skill 数量少时可以忍受,在 Skill/Plugin 数量上百时就不可接受了。
这和操作系统的进程隔离是同一个道理:
操作系统:一个进程崩溃不能拖垮整个系统Agent: 一个插件崩溃不能拖垮整个 Agent
Hermes 的解法:Stream Observer Hooks
Hermes 提交:2026-07-16:Add streaming output observer hooks
Hermes 定义了 on_stream_start / on_stream_delta / on_stream_end,每个插件消费者有独立队列,异步执行,插件异常不会阻断主 Agent:
@dataclassclass _ConsumerDispatcher:hook_name: strcallback: Callable[..., Any]events: "queue.Queue[dict[str, Any] | object]"thread: threading.Thread | None = Nonetry:dispatcher.callback(**payload)except Exception as exc:logger.warning("Hook '%s' callback %s raised: %s",dispatcher.hook_name,_callback_name(dispatcher.callback),exc,)
关键设计:
每个插件一个独立队列 独立线程消费 队列满时丢弃旧事件 插件异常被 try/except捕获,不上抛
Codex 的解法:Async Command Hooks
Codex:
2026-07-20:Hook context spill limits 2026-08-08:Support asynchronous command hooks 2026-08-15:Add MCP tool handler support to hooks engine 2026-08-18:Enable MCP tool hooks in Codex sessions
两边都走到了同一条链路:

值得说明的是,Codex 的基础 Hooks 实现更早(2026-02-05 Add hooks implementation),是在原有基础上逐步接入了异步和 MCP 能力。这说明演化不是一夜之间完成的,而是在已有基础上逐步加固。
为什么插件系统都会走向"异步旁路"?
因为插件是第三方代码,一旦插件逻辑同步阻塞了主 Agent 的执行流,一个插件崩溃就能拖垮整个 Agent 会话。把插件挂载成异步 Observer、用独立线程或任务处理、捕获异常不上抛,是任何允许第三方扩展的运行时都会走的安全设计——这不是 Agent Framework 独有的模式,而是插件架构的通用工程常识。
就像你在算力文章里讲的"稀疏让数字翻倍"一样:稀疏不是 NVIDIA 独有的技术,而是 Tensor Core 硬件设计到一定阶段后必然出现的能力。插件隔离也一样,不是某个 Agent 的创新,而是插件生态发展到一定规模后必然出现的工程需求。
插件不是能力,而是生态;生态一定要求隔离。
第六章:为什么 Multi-Agent 是必然
单 Agent 的天花板
一个 Agent 能力再强,也无法独立承担复杂任务编排。原因很朴素:
1. 上下文窗口有限 → 复杂任务需要拆分到子上下文2. 单线程执行 → 长任务阻塞主会话3. 无法并行 → 互不依赖的子任务不能同时跑4. 无隔离 → 一个子任务出错影响整体5. 无恢复 → 子任务中断后无法重连
这和操作系统的进程演化完全一致:
Hermes 的解法:Subagent Lifecycle API
Hermes 提交:
2026-07-12:Public Subagent Lifecycle API 2026-07-16:Fix subagent lifecycle ownership invariants
Hermes 定义了完整的公开类型和状态机:
class SubagentState(str, enum.Enum):PENDING = "PENDING"STARTING = "STARTING"RUNNING = "RUNNING"SUCCEEDED = "SUCCEEDED"FAILED = "FAILED"INTERRUPTED = "INTERRUPTED"CANCEL_REQUESTED = "CANCEL_REQUESTED"CANCELLED = "CANCELLED"UNKNOWN = "UNKNOWN"@dataclasses.dataclass(frozen=True)class SubagentLaunchRequest:goal: strcontext: Optional[str] = Nonerole: str = "leaf"model: Optional[str] = Noneallowed_toolsets: Optional[tuple[str, ...]] = Noneblocked_tools: tuple[str, ...] = ()working_directory: Optional[str] = Noneparent_session_id: Optional[str] = Nonecorrelation_id: Optional[str] = Nonemetadata: Mapping[str, Any] = dataclasses.field(default_factory=dict)timeout_seconds: Optional[float] = None@dataclasses.dataclass(frozen=True)class SubagentHandle:contract_version: intsubagent_id: strparent_session_id: Optional[str]correlation_id: Optional[str]created_at: floatprovider: Optional[str]model: Optional[str]role: strdepth: intcapability: str
服务接口是 launch() / status() / wait() / cancel() / result() / reconnect(),并维护了线程安全 Registry:
class _Registry:def __init__(self) -> None:self.lock = threading.RLock()self.records: dict[str, _Record] = {}self.correlations: dict[tuple[Optional[str], str], str] = {}
Codex 的解法:MultiAgent 工具集
Codex 对应代码在 codex-rs/core/src/session/multi_agents.rs 和 codex-rs/core/src/tools/handlers/multi_agents/,公开工具包括:
spawn_agentsend_messagefollowup_taskwait_agentinterrupt_agentresume_agentclose_agent
Codex 的说明文本中直接写着:
You can spawn sub-agents to handle subtasks,and those sub-agents can spawn their own sub-agents.You can use spawn_agent to create a new agent,followup_task to give an existing agent a new task,and send_message to pass a message to a running agent.
对应的 Rust 代码模块:
pub(crate) use close_agent::Handler as CloseAgentHandler;pub(crate) use resume_agent::Handler as ResumeAgentHandler;pub(crate) use send_input::Handler as SendInputHandler;pub(crate) use spawn::Handler as SpawnAgentHandler;pub(crate) use wait::Handler as WaitAgentHandler;
两边的对照

SubagentLaunchRequest | spawn_agent | |
SubagentHandle | ||
parent_session_id | SubAgentSource | |
PENDING/RUNNING/SUCCEEDED | ||
cancel() | interrupt_agent | |
reconnect() | resume_agent | |
depth | ||
capability |
值得特别说明的是,Codex 的 MultiAgent 基础其实早于 Hermes:
2026-04-28 Codex: MultiAgentV2 root and subagent context hints2026-07-12 Hermes: Public Subagent Lifecycle API2026-07-15 Codex: preserve paginated history for spawned subagents2026-08-06 Codex: lazy MCP startup for subagents2026-08-12 Codex: subagent analytics connections2026-08-17 Codex: subagent navigation
更准确的顺序是:Codex 先有 MultiAgent 雏形 → Hermes 公开了更完整的生命周期 API → Codex 随后继续强化 history、MCP、Analytics 等能力。
这正是"共同演化"而非单向复制的最好例证——两边互有先后,最终都收敛到了同一套状态机模型上。
为什么都会拆分生命周期?
因为真实的多 Agent 任务不是"跑完/没跑完"这么简单——存在等待父任务反馈、被用户中途取消、执行失败后需要恢复现场等场景。单一的 Running/Finished 两态模型根本装不下这些情况,所以两边都拆出了 PENDING、CANCEL_REQUESTED、INTERRUPTED 这类中间态,本质上是在为"任务编排会出错、会被打断"这个现实做工程上的兜底。
一个 Agent 能力再强,也比不上多个 Agent 会协作。
第七章:三条路线最终在哪里汇合
现在把前面六章的演化路径全部串起来:

三个项目在这个路径上的位置:

三条路线从不同入口出发,最终都汇合到了同一个节点:Skill Runtime。这不是巧合——因为这三条路线各自遇到的瓶颈,最终都指向同一个解:
OpenClaw:Skill 太多,静态管理不够用 → 需要 RuntimeCodex: 插件 Skill 需要统一加载 → 需要 RuntimeHermes: Skill 需要统计和追踪 → 需要 Runtime
三条路走到同一个路口,不是因为互相看了对方的地图,而是因为路只有这一条。
第八章:未来 Agent Runtime 还需要补齐什么
如果:
Prompt → Skill → Runtime → Agent OS这条演化路径成立,那么下一阶段 Agent Framework 的竞争重点,将不再只是增加更多工具,而是围绕 能力管理、执行控制、安全治理和任务编排 建立完整 Runtime。
目前来看,未来 Agent Runtime 可能还需要补齐以下几个核心组件:
1. Skill Registry:能力分发与生命周期管理
当前三个项目中的 Skill,大多仍然依赖:
本地目录Git 仓库插件包项目内置资源
随着 Skill 数量增长,未来需要类似软件包生态的能力管理层:
版本管理依赖解析能力发现安全扫描来源认证升级回滚
它不一定会完全复制 npm,但会承担类似的职责:
让 Skill 从项目文件,逐渐变成可以独立管理和分发的 Agent 能力资产。
未来可能出现类似:
agent install github-code-reviewagent update code-analysisagent remove security-check
这样的能力管理方式。
2. Agent Execution Orchestrator:智能任务执行编排
当前 Multi-Agent 更多解决:
创建 Subagent发送任务等待结果获取返回
但当 Agent 数量增加后,还需要更高层的执行管理:
任务拆分优先级控制资源限制失败恢复并行执行状态追踪
未来的 Agent Runtime 可能会出现类似调度系统:
用户任务|Planner Agent|Execution Orchestrator|-----------------| | |Agent A Agent B Agent C
它更像 Kubernetes 的思想:
不是管理容器,而是管理智能任务。
3. Permission & Trust System:Agent 安全边界
当 Agent 可以:
读取文件执行 Shell访问网络调用企业系统创建子 Agent
权限控制会成为基础能力。
目前很多 Agent Framework 已经开始探索:
Skill TrustPlugin PermissionTool AllowlistSandbox Execution
但未来更可能发展成细粒度权限模型:
Skill A:可以读取代码禁止修改文件Skill B:可以执行测试禁止访问网络Plugin C:可以创建 Subagent最大深度 <= 2
Agent 的安全边界,会逐渐类似操作系统中的权限模型。
4. Memory Runtime:从存储到记忆管理
Memory 并不是简单的"保存聊天记录"。
当前 Agent 已经出现:
Conversation MemoryVector MemoryKnowledge MemorySession State
但真正缺少的是统一 Memory Runtime:
什么时候保存保存什么内容什么时候检索如何更新如何遗忘谁可以访问
未来 Memory 更像数据库系统:
不仅存储信息,还负责:
生命周期管理权限控制冲突解决重要性排序
Agent 的长期能力,很大程度取决于 Memory Runtime。
5. Agent Workflow Engine:动态任务编排
当前 Multi-Agent 更多还是:
spawn↓执行↓wait↓返回
但复杂业务需要更强的流程能力:
任务定义条件判断并行执行人工审批失败重试状态恢复
未来 Workflow Engine 会区别于传统 DAG:
传统 Workflow:
A → B → CAgent Workflow:
任务目标|Agent 自主规划|动态生成执行路径|根据结果调整下一步
它更接近:
Workflow Engine+Planner+Feedback Loop

下一代 Agent 竞争,不是谁拥有更多 Prompt 或更多 Tool,而是谁能够更高效、更安全地管理智能能力。
当下的情况完整对照表
SKILL.md | SKILL.md | SKILL.md | ||
一句话总结
过去的软件世界,从代码发展出了操作系统;今天的 AI 世界,也正在经历同样的过程。Prompt 只是 Agent 的汇编语言,Skill 是它的库,Runtime 是它的操作系统雏形。当 Agent 数量、能力和复杂度不断增长,最终竞争的不会是谁拥有更多 Prompt,而是谁能管理更多智能能力。
Agent Framework 不是被设计成 OS,而是被复杂度一步步逼成 OS。
个人声明
本文数据来自 GitHub 仓库公开元数据、公开提交记录和公开源码。提交日期以 GitHub API 返回的 commit author date 为准;部分提交链接使用短 SHA,GitHub 会自动解析。三个项目的架构演化分析基于公开可见的代码结构,不构成对任何项目"代码抄袭"的指控。有疑议不要喷俺,可以留言!!! 今天就先讲到这里,筒子们 See ya!
夜雨聆风