agent-core-v2:唯一的引擎
v1 退场、v2 接管的时间线,三层作用域与工作区实例,Service/Fiber 单元层与 Feature 接缝,以及 human 内核的边界。
packages/agent-core-v2(约 13.6 万行)的包描述没变:
The unified agent engine for Kimi (v2 — DI Scope architecture)
变的是地位。v0.29.1 时本文讲的是「正在进行的 v2 重构」:v1 agent-core 仍是 CLI 主路径,v2 只在服务端落地。到 v0.43.0,packages/agent-core 目录已经不存在,代码里也搜不到回退开关 KIMI_CODE_LEGACY_FLAG——v2 是唯一的引擎,kap-server、acp-server、klient、node-sdk、migration-legacy、remote-control 都建在它上面。
v1 退场的时间线
CHANGELOG 里能找到的节点:
| 版本 | 变化 |
|---|---|
| 0.24.0 | kimi server run / kimi web 默认跑 v2,v1 服务端包删除(#1617) |
| 0.25.0 | 服务端 v1 wire schema 挪进引擎各域与服务端包,共享 schema 包退出 v2 服务端栈(#1755) |
| 0.33.0 | TUI、kimi -p、kimi acp、kimi export、kimi provider 默认跑 v2,KIMI_CODE_LEGACY_FLAG=1 可回退(#2627) |
| 0.40.0 | kimi acp 不再理会 KIMI_CODE_LEGACY_FLAG(#3434) |
packages/agent-core 本身在哪个版本删除,CHANGELOG 没有记。按 monorepo 全景的口径,v0.29.1 时 v1 约 6.6 万行、v2 已约 9.8 万行。
路线很典型:新架构先在服务端落地,再切 CLI 默认值并保留回退开关,最后撤掉开关、删掉旧代码。每一步都可观察、可回退。
三层作用域,外加工作区实例
作用域枚举从 _base/di/scope.ts 挪到了 app/scopes.ts,改成字符串值,并向 DI 内核声明拓扑:
export enum LifecycleScope {
App = 'app',
Session = 'session',
Agent = 'agent',
}
export const SCOPE_TOPOLOGY: readonly LifecycleScope[] = [
LifecycleScope.App,
LifecycleScope.Session,
LifecycleScope.Agent,
];
setScopeTopology(SCOPE_TOPOLOGY);_base/di 只把作用域当字符串(ScopeKind = string),Scope.createChild() 按声明的拓扑拒绝「子级不高于父级」的建法。服务用 registerScopedService(scope, id, ctor, activation, domain) 注册,直接调用的有 App 级 75 处、Session 级 18 处、Agent 级 45 处;ScopeActivation 决定作用域一建就实例化还是首次解析时再建,重复注册直接报错,有意替换要用 overrideScopedService。
DI 作用域就这三层。工作区那一层在代码里不是作用域,而是 WorkspaceInstance(workspace/workspaceInstance/):App 级的 IWorkspaceInstanceManager 为每个工作区创建一个实例,它有 materializing / active / closing / disposed 四态,持有运行时注册表、单元宿主与 Program,后者按工作区装配 WorkspaceFsService、WorkspaceGitService、WorkspaceTrustService 等服务。
以恢复会话为例:App 级 ISessionManager 的 controllerForSession() 先查 ISessionIndex 拿到会话所属工作区,经 IWorkspaceInstanceManager.getOrCreate() 物化工作区实例,交给它的 SessionLifecycleService,后者用 createScopedChildHandle(…, LifecycleScope.Session, …) 建出 Session 作用域;Agent 作用域同理由 agentLifecycleService.ts 建出。
需要提醒一句:根 AGENTS.md 的项目地图写的是四层 LifecycleScope(App / Workspace / Session / Agent),还说调用方组合 ISessionIndex → IWorkspaceLifecycleService.handlerFor → handler、没有 App 级会话门面。这与 v0.43.0 的代码不符:全仓没有 LifecycleScope.Workspace,IWorkspaceLifecycleService 只出现在 node-sdk 与 kimi-inspect 的注释里,ISessionManager 仍注册在 App 级——文档走在了代码前面,读源码时以代码为准。
单元层:Service、Fiber 与贡献点
根 AGENTS.md 称之为 L3 单元层。_base/di/service.ts 的 Service 是抽象基类,同时实现 Fiber 接口:一个服务单元可以在运行时 provide() 子单元(类、函数或对象形式的 recipe,可声明 inject 与 Config),单元有 Pending / Activating / Active / Unloading / Failed 五态。
collection<T>(name) 定义集合贡献点:多方贡献、统一消费。ScopeUnits(kind) 就是其中之一,贡献进来的单元会在对应作用域创建时由 watchScopeUnits() 物化。单元的增删改由 cascadeEngine.ts 沿依赖图级联(provide / unprovide / update),并记下每次级联拆了谁、重建了谁;循环依赖仍抛 CyclicDependencyError。App 级 IFeatureManager 暴露 provideUnit / unprovideUnit / updateUnit,单元因此能在运行时热插拔。src/debug/ 的 ledger、graph、cascade 调试服务,就是 kimi-inspect 里 DI 视图的数据源。
Feature 接缝
features/ 是功能挂进引擎的统一入口。Feature 继承 Service,提供一组声明式的 contribute*():contributeService、contributeAgentService、contributeTool、contributeCommand、contributeConfig、contributeSessionModel、contributeAgentModel 等。最短的例子是 features/btw/btwFeature.ts:
export class BtwFeature extends Feature {
static override readonly name = 'btw';
constructor() {
super();
this.contributeService(LifecycleScope.Session, ISessionBtwService, SessionBtwService);
}
}
registerFeature(BtwFeature);contributeService 内部就是往 ScopeUnits(scope) 贡献一个单元。registerFeature() 只做登记,App 级的 FeatureAssemblyService 启动时把登记过的 recipe 逐个交给 IFeatureManager.provideUnit()。目前登记了 17 个:btw、cron、dateChange、debugEvents、externalHooks、fileHistory、goal、notify、plan、reminder、sessionInit、skill、swarm、todo、tokenCounting、tower、usage。
human 内核与导入边界
src/human/ 是另一块值得注意的区域。packages/agent-core-v2/scripts/check-import-boundaries.mjs(lint:imports)这样定位它:
human is the pure LLM/agent kernel: it never imports llm-adapter or v2 domains
反过来,只有 llm-adapter、agent/loop/machine、session/agentLifecycle 三处能 import human 的实现,其余代码只能用少数「词汇」模块(llm/message、llm/usage 等)。同一个脚本还宣告「the kosong kernel is deleted」。所以 v2 的 package.json 既不声明 @moonshot-ai/kosong,也不声明 @moonshot-ai/kaos:模型请求层是 src/human/llm 与 src/llm-adapter,执行与文件 / 进程访问走自己的 src/os/(IHostProcessService 等,见 kaos)。
另外,agent-core-v2、kap-server、transcript 是零注释区(scripts/check-no-comments.mjs 随 pnpm lint 检查),v0.29.1 时本文引用的文件头注释都已删除。
这次接管解决了什么
| v1 的问题 | v2 的解法 |
|---|---|
| 服务全是单例,会话 / agent 级状态靠手工传递 | 作用域树,容器管生命周期 |
| 功能散落在引擎各处 | Feature 接缝,contribute*() 声明式挂载 |
PermissionManager 一个类多职责 | permissionGate / permissionMode / permissionPolicy / permissionRules 四个域 |
| 会话活动状态在多处折算 | ISessionActivityView 单一真相 |
| 两代引擎长期并存 | 服务端先行、CLI 跟进、回退开关兜底、最后删除 |
代价也真实:规模是 v0.29.1 时 v1 的两倍多,概念层次(作用域、工作区实例、单元、贡献点、Feature、human 边界)也更多。好在关键边界都有脚本检查,而不是靠口头约定。
下一篇:kaos 执行环境抽象。