aily-lex
v1.0.6
Published
Headless AI Agent Runtime — multi-host, MCP-compatible
Downloads
107
Readme
aily-lex
Headless AI Agent Runtime — 无渲染、多宿主、MCP 兼容的 Agent 核心。
从 aily-blockly 的 aily-chat 模块解耦而来,作为独立的 Agent 运行时,服务于 blockly 图形化 → code 代码版 → simulator 仿真版 产品路线。
特性
- AsyncGenerator 核心循环 —
query()驱动:调模型→收集工具调用→执行→追加结果→循环,每步 yieldAgentEvent - 完全无状态 — 客户端持有全部对话历史,每次调用发送完整 messages 数组
- 15 个内置工具 — 文件读写编辑、grep/glob 搜索、bash 执行、子 Agent、网络请求等
- 工具 prompt.ts 模式 — 每个工具自包含 name + description + prompt (Claude Code 模式)
- 读写并发分区 — readOnly 工具并发执行,write 工具顺序执行
- 三级上下文压缩 — microcompact (截断长输出) → autocompact (摘要旧消息) → manual
- AbortController 层级 — 会话→查询→工具,逐层取消
- Skill 系统 — 声明式提示增强器,按优先级注入系统提示
- 可插拔端点 — IEndpoint 接口适配 Anthropic/OpenAI/DeepSeek/aily-services 等
- Node.js 直接执行 — 工具通过 fs/promises + child_process.spawn 直接操作,无 IPC 开销
- worker_threads 隔离 — IDE 通过 WorkerThreadBridge 与 Agent 通信
快速开始
npm install
npm run build
npm test使用
import { AilyLexAgent, getAllBaseTools } from 'aily-lex';
import type { IEndpoint } from 'aily-lex';
// 1. 实现 IEndpoint 对接你的 LLM
const endpoint: IEndpoint = { /* ... */ };
// 2. 创建 Agent
const agent = new AilyLexAgent({
host: nodeHostAccess, // NodeHostAccess 实例
endpoint,
model: { modelId: 'claude-sonnet-4-20250514' },
systemPrompt: '你是一个编程助手。',
});
// 3. 注册工具
agent.registerTools(getAllBaseTools());
// 4. 对话
for await (const event of agent.chat('帮我读取 package.json')) {
switch (event.type) {
case 'text_delta':
process.stdout.write(event.text);
break;
case 'tool_call_start':
console.log(`\n[调用工具: ${event.toolName}]`);
break;
}
}项目结构
src/
├── index.ts 根 barrel export
├── base/common/ 零依赖基础设施
│ ├── lifecycle.ts IDisposable, DisposableStore
│ ├── event.ts Event<T>, Emitter<T>
│ ├── observable.ts observable<T>(), derived<T>()
│ ├── async.ts createLinkedAbortController, raceAbort
│ └── errors.ts AilyLexError 层级
├── types/ 集中类型定义
│ ├── events.ts AgentEvent 联合类型 (12 种)
│ ├── tool.ts IAilyTool, ToolAnnotations, ToolContext
│ ├── message.ts APIMessage, Turn, SessionSnapshot
│ ├── skill.ts IAilySkill
│ ├── hooks.ts QueryHooks, HookDecision
│ └── host.ts IAilyHostAPI, HostCapabilities
├── platform/ 服务接口
│ ├── endpoint/ IEndpoint, IEndpointService, ModelStreamChunk
│ ├── instantiation/ ServiceIdentifier, ServiceCollection (DI)
│ ├── configuration/ IConfigurationService
│ ├── log/ ILogService, ConsoleLogService
│ ├── mcp/ IMcpClientService
│ └── telemetry/ ITelemetryService
├── agent/common/ 核心 Agent 逻辑
│ ├── agent.ts AilyLexAgent 主编排器
│ ├── query.ts query() AsyncGenerator 核心循环
│ ├── deps.ts QueryDeps (可注入 I/O 依赖)
│ ├── config.ts QueryConfig
│ ├── turnManager.ts TurnManager 会话管理
│ ├── contextManager.ts ContextManager 三级压缩
│ ├── transitions.ts 工具执行读写分区
│ ├── stopHooks.ts 停止点钩子
│ └── tokenBudget.ts Token 预算计算
├── tools/ 内置工具
│ ├── tools.ts getAllBaseTools() 中央注册
│ ├── common/ ToolRegistry, toolUtils
│ ├── fileRead/ 读文件
│ ├── fileWrite/ 写文件
│ ├── fileEdit/ 精确字符串替换
│ ├── fileMultiEdit/ 批量替换
│ ├── fileDelete/ 删除文件
│ ├── listDir/ 列目录
│ ├── createDirectory/ 创建目录
│ ├── grep/ 文本搜索
│ ├── glob/ 文件名模式搜索
│ ├── bash/ Shell 命令执行
│ ├── runSubagent/ 子 Agent
│ ├── askUser/ 用户交互
│ ├── getErrors/ 诊断错误
│ ├── getChangedFiles/ Git 变更文件
│ └── webFetch/ 网络请求
├── skills/common/ SkillRegistry
└── host/ 宿主层
├── common/protocol.ts IPC 协议 (UIToAgentMessage / AgentToUIMessage)
├── worker/workerBridge.ts WorkerThreadBridge (node:worker_threads)
└── node/ Node.js 直接执行
├── nodeFileSystem.ts fs/promises 实现
├── nodeTerminal.ts child_process.spawn 实现
└── nodeHostAccess.ts 组合入口系统提示构建
AilyLexAgent._buildSystemPrompt() 三阶段构建:
- systemPromptPrefix — 宿主传入的基础系统提示
- Skills —
SkillRegistry.getAll()按优先级排序,包裹在<skill>标签中 - Tool instructions — 每个工具的
prompt字段,包裹在<toolInstructions>标签中
架构参考
融合了两大 Agent 代码库的模式:
| 模式 | 来源 | |----------------------|----------------| | AsyncGenerator 核心循环 | Claude Code | | 显式依赖注入 (QueryDeps) | Claude Code | | 工具自包含目录 + prompt.ts | Claude Code | | 读写并发分区 | Claude Code | | AbortController 树 | Claude Code | | 三层目录结构 | VS Code Copilot | | Observable 状态 | VS Code Copilot | | ToolAnnotations 分区 | VS Code Copilot | | ServiceIdentifier DI | VS Code Copilot | | 多模型端点抽象 | VS Code Copilot | | StopHook | VS Code Copilot |
宿主端集成(aily-blockly)
aily-blockly 通过本地路径引用 aily-lex(package.json 中配置为 "aily-lex": "file:../aily-lex")。
首次安装
# 1. 构建 aily-lex
cd aily-lex
npm run build
# 2. 在 aily-blockly 中安装
cd ../aily-blockly
npm install更新(修改 aily-lex 代码后)
# 在 aily-lex 目录执行
npm run build
# 在 aily-blockly 目录重新安装(更新 node_modules/aily-lex 中的 dist)
npm install d:\codes\aily-lex # Windows 绝对路径
# 或
npm install ../aily-lex # 相对路径(在 aily-blockly 目录执行)为什么要重新
npm install?file:协议依赖在首次安装时会复制文件到node_modules,之后修改源码不会自动同步。
每次npm run build后需重新npm install才能让 aily-blockly 用到最新dist/。
快速验证
# 确认 QueryHooks 等最新类型已同步到宿主
Select-String "askHandler" node_modules/aily-lex/dist/types/hooks.d.ts开发
npm run build # TypeScript 编译
npm run build:watch # 监听模式
npm test # vitest 运行测试
npm run test:watch # 测试监听模式License
MIT
