@tachu/extensions 1.0.0-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (152) hide show
  1. package/CHANGELOG.md +77 -0
  2. package/LICENSE +201 -0
  3. package/README.md +825 -0
  4. package/README_ZH.md +815 -0
  5. package/dist/backends/file.d.ts +18 -0
  6. package/dist/backends/file.d.ts.map +1 -0
  7. package/dist/backends/file.js +69 -0
  8. package/dist/backends/file.js.map +1 -0
  9. package/dist/backends/index.d.ts +4 -0
  10. package/dist/backends/index.d.ts.map +1 -0
  11. package/dist/backends/index.js +4 -0
  12. package/dist/backends/index.js.map +1 -0
  13. package/dist/backends/terminal.d.ts +18 -0
  14. package/dist/backends/terminal.d.ts.map +1 -0
  15. package/dist/backends/terminal.js +57 -0
  16. package/dist/backends/terminal.js.map +1 -0
  17. package/dist/backends/web.d.ts +18 -0
  18. package/dist/backends/web.d.ts.map +1 -0
  19. package/dist/backends/web.js +53 -0
  20. package/dist/backends/web.js.map +1 -0
  21. package/dist/common/net.d.ts +31 -0
  22. package/dist/common/net.d.ts.map +1 -0
  23. package/dist/common/net.js +162 -0
  24. package/dist/common/net.js.map +1 -0
  25. package/dist/common/path.d.ts +18 -0
  26. package/dist/common/path.d.ts.map +1 -0
  27. package/dist/common/path.js +34 -0
  28. package/dist/common/path.js.map +1 -0
  29. package/dist/common/process.d.ts +19 -0
  30. package/dist/common/process.d.ts.map +1 -0
  31. package/dist/common/process.js +67 -0
  32. package/dist/common/process.js.map +1 -0
  33. package/dist/index.d.ts +9 -0
  34. package/dist/index.d.ts.map +1 -0
  35. package/dist/index.js +9 -0
  36. package/dist/index.js.map +1 -0
  37. package/dist/mcp/index.d.ts +3 -0
  38. package/dist/mcp/index.d.ts.map +1 -0
  39. package/dist/mcp/index.js +3 -0
  40. package/dist/mcp/index.js.map +1 -0
  41. package/dist/mcp/sse-adapter.d.ts +70 -0
  42. package/dist/mcp/sse-adapter.d.ts.map +1 -0
  43. package/dist/mcp/sse-adapter.js +176 -0
  44. package/dist/mcp/sse-adapter.js.map +1 -0
  45. package/dist/mcp/stdio-adapter.d.ts +73 -0
  46. package/dist/mcp/stdio-adapter.d.ts.map +1 -0
  47. package/dist/mcp/stdio-adapter.js +178 -0
  48. package/dist/mcp/stdio-adapter.js.map +1 -0
  49. package/dist/observability/index.d.ts +3 -0
  50. package/dist/observability/index.d.ts.map +1 -0
  51. package/dist/observability/index.js +3 -0
  52. package/dist/observability/index.js.map +1 -0
  53. package/dist/observability/jsonl-emitter.d.ts +58 -0
  54. package/dist/observability/jsonl-emitter.d.ts.map +1 -0
  55. package/dist/observability/jsonl-emitter.js +96 -0
  56. package/dist/observability/jsonl-emitter.js.map +1 -0
  57. package/dist/observability/otel-emitter.d.ts +52 -0
  58. package/dist/observability/otel-emitter.d.ts.map +1 -0
  59. package/dist/observability/otel-emitter.js +143 -0
  60. package/dist/observability/otel-emitter.js.map +1 -0
  61. package/dist/providers/anthropic.d.ts +54 -0
  62. package/dist/providers/anthropic.d.ts.map +1 -0
  63. package/dist/providers/anthropic.js +298 -0
  64. package/dist/providers/anthropic.js.map +1 -0
  65. package/dist/providers/index.d.ts +4 -0
  66. package/dist/providers/index.d.ts.map +1 -0
  67. package/dist/providers/index.js +4 -0
  68. package/dist/providers/index.js.map +1 -0
  69. package/dist/providers/mock.d.ts +38 -0
  70. package/dist/providers/mock.d.ts.map +1 -0
  71. package/dist/providers/mock.js +79 -0
  72. package/dist/providers/mock.js.map +1 -0
  73. package/dist/providers/openai.d.ts +61 -0
  74. package/dist/providers/openai.d.ts.map +1 -0
  75. package/dist/providers/openai.js +299 -0
  76. package/dist/providers/openai.js.map +1 -0
  77. package/dist/rules/index.d.ts +9 -0
  78. package/dist/rules/index.d.ts.map +1 -0
  79. package/dist/rules/index.js +15 -0
  80. package/dist/rules/index.js.map +1 -0
  81. package/dist/rules/no-hallucination.md +11 -0
  82. package/dist/rules/no-sensitive-output.md +11 -0
  83. package/dist/rules/prefer-concise-response.md +11 -0
  84. package/dist/rules/require-tool-verification.md +11 -0
  85. package/dist/tools/apply-patch/descriptor.md +27 -0
  86. package/dist/tools/apply-patch/executor.d.ts +19 -0
  87. package/dist/tools/apply-patch/executor.d.ts.map +1 -0
  88. package/dist/tools/apply-patch/executor.js +190 -0
  89. package/dist/tools/apply-patch/executor.js.map +1 -0
  90. package/dist/tools/fetch-url/descriptor.md +38 -0
  91. package/dist/tools/fetch-url/executor.d.ts +20 -0
  92. package/dist/tools/fetch-url/executor.d.ts.map +1 -0
  93. package/dist/tools/fetch-url/executor.js +34 -0
  94. package/dist/tools/fetch-url/executor.js.map +1 -0
  95. package/dist/tools/index.d.ts +12 -0
  96. package/dist/tools/index.d.ts.map +1 -0
  97. package/dist/tools/index.js +191 -0
  98. package/dist/tools/index.js.map +1 -0
  99. package/dist/tools/list-dir/descriptor.md +29 -0
  100. package/dist/tools/list-dir/executor.d.ts +22 -0
  101. package/dist/tools/list-dir/executor.d.ts.map +1 -0
  102. package/dist/tools/list-dir/executor.js +46 -0
  103. package/dist/tools/list-dir/executor.js.map +1 -0
  104. package/dist/tools/read-file/descriptor.md +28 -0
  105. package/dist/tools/read-file/executor.d.ts +15 -0
  106. package/dist/tools/read-file/executor.d.ts.map +1 -0
  107. package/dist/tools/read-file/executor.js +22 -0
  108. package/dist/tools/read-file/executor.js.map +1 -0
  109. package/dist/tools/run-shell/descriptor.md +39 -0
  110. package/dist/tools/run-shell/executor.d.ts +20 -0
  111. package/dist/tools/run-shell/executor.d.ts.map +1 -0
  112. package/dist/tools/run-shell/executor.js +76 -0
  113. package/dist/tools/run-shell/executor.js.map +1 -0
  114. package/dist/tools/search-code/descriptor.md +31 -0
  115. package/dist/tools/search-code/executor.d.ts +23 -0
  116. package/dist/tools/search-code/executor.d.ts.map +1 -0
  117. package/dist/tools/search-code/executor.js +113 -0
  118. package/dist/tools/search-code/executor.js.map +1 -0
  119. package/dist/tools/shared.d.ts +21 -0
  120. package/dist/tools/shared.d.ts.map +1 -0
  121. package/dist/tools/shared.js +12 -0
  122. package/dist/tools/shared.js.map +1 -0
  123. package/dist/tools/write-file/descriptor.md +30 -0
  124. package/dist/tools/write-file/executor.d.ts +16 -0
  125. package/dist/tools/write-file/executor.d.ts.map +1 -0
  126. package/dist/tools/write-file/executor.js +18 -0
  127. package/dist/tools/write-file/executor.js.map +1 -0
  128. package/dist/transformers/document-to-text.d.ts +23 -0
  129. package/dist/transformers/document-to-text.d.ts.map +1 -0
  130. package/dist/transformers/document-to-text.js +69 -0
  131. package/dist/transformers/document-to-text.js.map +1 -0
  132. package/dist/transformers/image-to-text.d.ts +38 -0
  133. package/dist/transformers/image-to-text.d.ts.map +1 -0
  134. package/dist/transformers/image-to-text.js +81 -0
  135. package/dist/transformers/image-to-text.js.map +1 -0
  136. package/dist/transformers/index.d.ts +3 -0
  137. package/dist/transformers/index.d.ts.map +1 -0
  138. package/dist/transformers/index.js +3 -0
  139. package/dist/transformers/index.js.map +1 -0
  140. package/dist/vector/index.d.ts +3 -0
  141. package/dist/vector/index.d.ts.map +1 -0
  142. package/dist/vector/index.js +3 -0
  143. package/dist/vector/index.js.map +1 -0
  144. package/dist/vector/local-fs.d.ts +76 -0
  145. package/dist/vector/local-fs.d.ts.map +1 -0
  146. package/dist/vector/local-fs.js +153 -0
  147. package/dist/vector/local-fs.js.map +1 -0
  148. package/dist/vector/qdrant.d.ts +65 -0
  149. package/dist/vector/qdrant.d.ts.map +1 -0
  150. package/dist/vector/qdrant.js +176 -0
  151. package/dist/vector/qdrant.js.map +1 -0
  152. package/package.json +74 -0
package/README_ZH.md ADDED
@@ -0,0 +1,815 @@
1
+ # Tachu
2
+
3
+ **生产级 Agentic 引擎——将任何 LLM 变为可靠、可观测、生产就绪 Agent 的 Harness。**
4
+
5
+ [![npm version](https://img.shields.io/npm/v/@tachu/core?label=%40tachu%2Fcore)](https://www.npmjs.com/package/@tachu/core)
6
+ [![license: Apache-2.0](https://img.shields.io/badge/license-Apache--2.0-blue)](#许可证license)
7
+ [![bun](https://img.shields.io/badge/runtime-bun-orange)](https://bun.sh)
8
+ [![TypeScript](https://img.shields.io/badge/TypeScript-5.x-blue)](https://www.typescriptlang.org)
9
+
10
+ ---
11
+
12
+ ## 什么是 Tachu?
13
+
14
+ **太初有道,万物之始。以声明式描述符创造 Agent 万物。**
15
+
16
+ Tachu 是一个**生产级 Agentic 引擎**——不是 Demo 玩具,不是 API 薄封装。它是等式 **Agent = Model + Harness** 中的 *Harness*:提供结构骨架(协议、生命周期、安全、记忆、编排),让任何 LLM 都能成为可靠、可观测、可生产部署的 Agent。
17
+
18
+ 引擎本身刻意**不感知业务领域**——它不知道你的业务逻辑、用户身份或领域词汇。取而代之的是,它定义了一套极简的核心抽象(Rules、Skills、Tools、Agents),业务通过这些抽象注入所有智能。Tachu 处理那些真正困难的部分:9 阶段执行主干、双平面语义匹配、上下文窗口管理、精确 Token 计数的 Prompt 组装、结构化重试/降级、取消传播,以及端到端可观测性。
19
+
20
+ Tachu 以 Bun 原生 TypeScript Monorepo 形式发布,包含三个包:零依赖引擎核心(`@tachu/core`)、生产级官方扩展库(`@tachu/extensions`),以及完整功能的 CLI 程序(`@tachu/cli`)——后者同时也是参考实现。
21
+
22
+ ---
23
+
24
+ ## 核心亮点(Key Features)
25
+
26
+ - **9 阶段执行主干** — 会话管理 → 安全准入 → 意图分析 → 前置校验 → 任务规划 → DAG 校验 → 子任务执行 → 结果验证 → 输出规范;每个阶段类型安全、可挂钩
27
+ - **双平面匹配(Dual-Plane Matching)** — 语义发现(向量相似度)+ 确定性执行闸门(Scopes、白名单、审批),作用于所有 Rules、Skills、Tools 和 Agents
28
+ - **四大核心抽象** — 以 Markdown + YAML frontmatter 描述符声明 Rules、Skills、Tools、Agents;引擎自动解析、激活并编排
29
+ - **双 Provider 支持** — 生产级 OpenAI 与 Anthropic Adapter;可配置 Provider 降级顺序,实现零停机 Provider 切换
30
+ - **MCP 集成** — 通过 `McpToolAdapter` 接入任意 MCP 服务端(stdio 或 SSE);MCP Tools 成为引擎一等公民
31
+ - **精确 Token 计数** — 基于 tiktoken 的精确 Token 统计;KV Cache 友好的 Prompt 布局;自动上下文压缩(Head-Middle-Tail 策略)
32
+ - **结构化记忆(Memory System)** — 会话上下文窗口(含可配置上限);压缩前强制归档;长期向量记忆召回
33
+ - **OpenTelemetry 可观测性** — 每个阶段进入/退出、LLM 调用、Tool 调用、重试和降级都产出结构化 `EngineEvent`;内置 OTel 与 JSONL Emitter
34
+ - **生产级 CLI** — `tachu chat` / `tachu run` / `tachu init`,完整参数体系、流式渲染、Session 持久化、Ctrl+C 取消传播
35
+ - **Fail-Closed 安全基线** — 循环防护、预算熔断、基础输入校验硬编码于引擎核心,不可关闭
36
+ - **Qdrant 与 LocalFs 向量存储** — 生产环境接入 Qdrant,开发阶段使用内置内存实现
37
+
38
+ ---
39
+
40
+ ## 愿景(Vision)
41
+
42
+ > 太初有道,万物之始。以声明式描述符创造 Agent 万物。
43
+
44
+ Tachu 的长期愿景是成为**通用 Agent 框架**:**引擎提供骨架,业务填充血肉**——任何组织都能基于稳定、可观测、可审计的基础设施构建生产级 Agentic 系统,而无需每次从头解决安全、上下文管理、重试逻辑和多 Provider 编排等困难问题。
45
+
46
+ Tachu 基于三个核心信念:
47
+
48
+ 1. **Harness 才是难点。** 模型智能已经商品化;可靠的编排机制尚未。Tachu 深度投资引擎基础设施,让应用开发者专注领域逻辑。
49
+ 2. **声明优于实现(Declaration over implementation)。** Rules、Skills、Tools、Agents 均以普通 Markdown 文件声明。引擎负责解析。无框架样板代码。
50
+ 3. **默认可观测。** 每个内部事件都是结构化且可发出的。生产系统需要完整 Trace——Tachu 无需额外埋点即可提供。
51
+
52
+ ---
53
+
54
+ ## 核心抽象(Core Abstractions)
55
+
56
+ Tachu 的四大核心抽象**平级独立、相互正交**——各自独立注册、独立激活,可在所有引擎阶段组合使用。
57
+
58
+ | 抽象 | 本质 | 激活闸门 | 作用 |
59
+ |------|------|----------|------|
60
+ | **Rules** | 约束与指导 | 语义发现 → 直接激活 | 注入各阶段 LLM System Prompt |
61
+ | **Skills** | 知识与指令 | 语义发现 → 直接激活 | 激活后注入 LLM 上下文 |
62
+ | **Tools** | 原子可执行操作 | 语义发现 → **必须过闸**(Scopes → 白名单 → 审批) | 带完整副作用追踪的执行 |
63
+ | **Agents** | 自然语言驱动的执行单元 | 语义发现 → 可激活 | 递归使用引擎能力;所有 Tool 调用仍走 Tool 闸门 |
64
+
65
+ 所有四类抽象共享统一的**描述符格式**(Markdown + YAML frontmatter):
66
+
67
+ ```yaml
68
+ name: unique-name # 必填,同类型内唯一
69
+ description: ... # 自然语言描述(用于语义发现)
70
+ tags: [tag1, tag2] # 标签,用于过滤和分类
71
+ trigger: { type: always } # 激活条件
72
+ requires:
73
+ - { kind: tool, name: read-file } # 显式依赖引用
74
+ ```
75
+
76
+ ### 双平面匹配模型(Dual-Plane Matching)
77
+
78
+ 每个核心抽象的激活都经历两个阶段:
79
+
80
+ ```mermaid
81
+ graph LR
82
+ Input[上下文输入] --> Discovery[语义发现面]
83
+ Discovery --> Index[(向量索引)]
84
+ Index --> Candidates[候选集]
85
+ Candidates --> Gate[确定性执行闸门]
86
+ Gate -- Scopes / 白名单 / 审批 --> Execution[执行面]
87
+ ```
88
+
89
+ - **语义发现面**:描述符的 `description` 在注册时向量化写入索引;运行时以当前上下文匹配索引,产出候选集
90
+ - **确定性执行闸门**:最终激活需通过确定性校验(显式引用、白名单/黑名单、权限 Scopes、审批检查)
91
+
92
+ Rules 和 Skills 无闸门直接激活(无副作用)。Tools 必须经过完整闸门。Agents 自由激活,但其内部调用的 Tools 仍需过 Tool 闸门。
93
+
94
+ ---
95
+
96
+ ## 架构总览(Architecture Overview)
97
+
98
+ ### 三层发布结构
99
+
100
+ ```mermaid
101
+ graph TD
102
+ subgraph "业务层(Business Layer)"
103
+ A[业务 Rules / 领域 Tools / 自定义 Adapter / 领域 Skills / Agents / Plan 模板]
104
+ end
105
+ subgraph "引擎扩展库 — @tachu/extensions"
106
+ B[OpenAI & Anthropic Adapter / 7 个常用 Tools / Terminal+File+Web Backend / Qdrant+LocalFs VectorStore / MCP Adapter / OTel+JSONL Emitter / 4 个通用 Rules]
107
+ end
108
+ subgraph "引擎核心 — @tachu/core"
109
+ C[协议定义 / 9 阶段主干 / 生命周期钩子 / Session / 记忆 / 安全 / 模型路由 / 运行状态]
110
+ end
111
+ A --> B
112
+ B --> C
113
+ ```
114
+
115
+ | 层级 | 包 | 职责 |
116
+ |------|----|----|
117
+ | 引擎核心 | `@tachu/core` | 协议接口、9 阶段主干骨架、8 个核心模块、Registry、Prompt 组装器、VectorStore 接口 + 内置轻量实现 |
118
+ | 扩展库 | `@tachu/extensions` | 官方具体实现:Provider Adapter、Tools、Backend、VectorStore Adapter、OTel/JSONL Emitter、通用 Rules |
119
+ | 业务/CLI | `@tachu/cli` 或业务代码 | 组装 core + extensions 为可工作的 Agent;提供领域 Rules/Skills/Tools/Agents |
120
+
121
+ ### 9 阶段执行主干
122
+
123
+ 每个请求都经历完整的 9 个阶段:
124
+
125
+ ```mermaid
126
+ graph TD
127
+ Start([业务请求]) --> S1[阶段 1:会话管理]
128
+ S1 --> S2[阶段 2:最小安全准入]
129
+ S2 --> S3[阶段 3:意图分析 — LLM]
130
+ S3 -- 简单 --> S9[阶段 9:输出规范]
131
+ S3 -- 复杂 --> S4[阶段 4:前置校验]
132
+ S4 --> S5[阶段 5:任务拆分]
133
+ S5 -- Plan 模式 --> PlanLoop{规划审阅循环}
134
+ S5 -- 模板匹配 --> S6
135
+ S5 -- 动态拆分 --> S6[阶段 6:依赖图校验]
136
+ PlanLoop -- 确认 --> S6
137
+ S6 --> S7[阶段 7:子任务执行]
138
+ S7 --> S8[阶段 8:结果验证 — LLM]
139
+ S8 -- 通过 --> S9
140
+ S8 -- 不通过 --> Retry{重试 / 重规划}
141
+ Retry -- 未达上限 --> S5
142
+ Retry -- 耗尽 --> S9
143
+ S9 --> End([输出])
144
+
145
+ style S2 fill:#ffeaa7,stroke:#fdcb6e
146
+ style S7 fill:#dfe6e9,stroke:#b2bec3
147
+ ```
148
+
149
+ | # | 阶段 | LLM 调用 | 关键输出 |
150
+ |---|------|----------|---------|
151
+ | 1 | 会话管理(Session Management) | 否 | 会话上下文加载 |
152
+ | 2 | 最小安全准入(Minimum Safety Check) | 否 | 通过 / 拒绝 |
153
+ | 3 | 意图分析(Intent Analysis) | **是** | `IntentResult`(简单/复杂,上下文相关性) |
154
+ | 4 | 前置校验(Pre-Check) | 否 | 资源可用性、深度安全校验 |
155
+ | 5 | 任务拆分(Task Planning) | **是** | `PlanningResult`(带排名的方案 + DAG) |
156
+ | 6 | 依赖图校验(DAG Validation) | 否 | 环检测、节点完整性(确定性) |
157
+ | 7 | 子任务执行(Sub-task Execution) | 视子任务 | `TaskResult[]`(可并行) |
158
+ | 8 | 结果验证(Result Validation) | **是** | `ValidationResult`(通过 / 执行问题 / 拆分问题) |
159
+ | 9 | 输出规范(Output Normalization) | 否 | `EngineOutput`(含步骤状态、元信息、附件) |
160
+
161
+ **主干关键特性:**
162
+
163
+ - **全路径安全准入** — 阶段 2 对所有请求路径执行,包括简单问题的快速通道
164
+ - **上下文门卫** — 阶段 3 判断会话历史是否与本轮相关;无关历史不向下传递
165
+ - **事不过三** — 任务级重试最多 3 次(可配置);系统级重试最多 2 次
166
+ - **取消传播(Last-message-wins)** — 同一 Session 收到新消息时,通过 `AbortController` 取消当前执行
167
+
168
+ ---
169
+
170
+ ## 安装(Installation)
171
+
172
+ Tachu 需要 [Bun](https://bun.sh) 作为运行时。
173
+
174
+ ```bash
175
+ # 安装引擎核心
176
+ bun add @tachu/core
177
+
178
+ # 安装扩展库(Provider、Tools、Backend、向量存储)
179
+ bun add @tachu/extensions
180
+
181
+ # 全局安装 CLI
182
+ bun add -g @tachu/cli
183
+ ```
184
+
185
+ 安装完成后验证:
186
+
187
+ ```bash
188
+ tachu --version
189
+ ```
190
+
191
+ ---
192
+
193
+ ## 快速开始(Quick Start)
194
+
195
+ ### CLI 方式
196
+
197
+ ```bash
198
+ # 1. 初始化项目工作空间
199
+ tachu init --template minimal --provider openai
200
+
201
+ # 2. 设置 API Key
202
+ export OPENAI_API_KEY=sk-...
203
+
204
+ # 3. 单次执行 Prompt
205
+ tachu run "帮我总结最近 5 条 git commit 的内容"
206
+
207
+ # 4. 进入交互式对话
208
+ tachu chat
209
+
210
+ # 恢复最近一次 Session
211
+ tachu chat --resume
212
+ ```
213
+
214
+ ### 编程式(Programmatic — TypeScript)
215
+
216
+ ```typescript
217
+ import { Engine } from '@tachu/core';
218
+ import { OpenAIProviderAdapter } from '@tachu/extensions/providers';
219
+ import type { EngineConfig, InputEnvelope, ExecutionContext } from '@tachu/core';
220
+
221
+ const config: EngineConfig = {
222
+ retry: { taskMaxRetries: 3, systemMaxRetries: 2 },
223
+ planning: { planCount: 1, enableValidation: true },
224
+ agent: { maxNestingDepth: 1 },
225
+ context: { maxTokens: 8000, compressionThreshold: 0.8 },
226
+ execution: { defaultTimeout: 120_000 },
227
+ models: {
228
+ capabilityMapping: {
229
+ 'high-reasoning': 'gpt-4o',
230
+ 'fast-cheap': 'gpt-4o-mini',
231
+ },
232
+ providerFallbackOrder: ['openai'],
233
+ },
234
+ safety: { maxInputSize: 1_000_000, maxRecursionDepth: 10 },
235
+ hooks: { writeHookTimeout: 5000, failureBehavior: 'continue' },
236
+ storage: {},
237
+ };
238
+
239
+ const engine = new Engine(config);
240
+ engine.useProvider(new OpenAIProviderAdapter({ apiKey: process.env.OPENAI_API_KEY! }));
241
+
242
+ const input: InputEnvelope = {
243
+ content: '写一个 TypeScript 函数,对异步操作做防抖处理',
244
+ metadata: { modality: 'text' },
245
+ };
246
+
247
+ const context: ExecutionContext = {
248
+ requestId: crypto.randomUUID(),
249
+ sessionId: 'session-001',
250
+ traceId: crypto.randomUUID(),
251
+ principal: { userId: 'user-001' },
252
+ budget: { maxTokens: 20_000, maxDurationMs: 60_000 },
253
+ scopes: ['read', 'write'],
254
+ };
255
+
256
+ for await (const chunk of engine.runStream(input, context)) {
257
+ if (chunk.type === 'delta') process.stdout.write(chunk.content);
258
+ if (chunk.type === 'done') console.log('\n\n完成,状态:', chunk.output.status);
259
+ }
260
+ ```
261
+
262
+ ---
263
+
264
+ ## 包结构(Package Layout)
265
+
266
+ ### 三包说明
267
+
268
+ | 包 | 说明 | 主要导出 |
269
+ |----|------|---------|
270
+ | `@tachu/core` | 零依赖引擎核心 | `Engine`、`Registry`、`PromptAssembler`、所有接口与类型 |
271
+ | `@tachu/extensions` | 官方具体实现 | `OpenAIProviderAdapter`、`AnthropicProviderAdapter`、`McpToolAdapter`、`QdrantVectorStore`、`OtelEmitter`、Backend、Tools、Rules |
272
+ | `@tachu/cli` | 生产级 CLI 程序 | `tachu chat`、`tachu run`、`tachu init` |
273
+
274
+ ### 依赖关系(Dependency Relationship)
275
+
276
+ ```mermaid
277
+ graph LR
278
+ cli["@tachu/cli"]
279
+ extensions["@tachu/extensions"]
280
+ core["@tachu/core"]
281
+
282
+ cli --> extensions
283
+ cli --> core
284
+ extensions --> core
285
+
286
+ style core fill:#74b9ff,stroke:#0984e3
287
+ style extensions fill:#a29bfe,stroke:#6c5ce7
288
+ style cli fill:#fd79a8,stroke:#e84393
289
+ ```
290
+
291
+ ### core 包内部结构
292
+
293
+ ```
294
+ @tachu/core / src/
295
+ ├── types/ # 所有 TypeScript 接口:描述符、上下文、I/O、配置
296
+ ├── engine/ # Engine 入口类、各阶段处理器、编排控制面、依赖调度器
297
+ ├── registry/ # Registry:注册/查询/启动校验(四类抽象统一管理)
298
+ ├── modules/ # 8 个核心模块(会话、记忆、运行状态、模型路由、
299
+ │ # Provider、安全、可观测性、Hooks)
300
+ ├── prompt/ # PromptAssembler:Token 预算分配、KV Cache 友好排列
301
+ └── vector/ # VectorStore 接口 + 内置轻量实现
302
+ ```
303
+
304
+ ---
305
+
306
+ ## Provider 与集成(Providers & Integrations)
307
+
308
+ ### LLM Provider
309
+
310
+ | Provider | 包 | 流式输出 | Function Calling | 备注 |
311
+ |----------|----|----|------|------|
312
+ | OpenAI | `@tachu/extensions/providers` | ✅ | ✅ | GPT-4o、GPT-4o-mini 及所有可枚举模型 |
313
+ | Anthropic | `@tachu/extensions/providers` | ✅ | ✅ | Claude 3.5 Sonnet 及所有可枚举模型 |
314
+ | Mock | `@tachu/extensions/providers` | ✅ | ✅ | 测试专用;可配置响应内容 |
315
+
316
+ 通过 `models.providerFallbackOrder` 配置降级顺序。系统级错误(超时、API 报错)时,引擎自动按顺序切换 Provider,无需重新规划。
317
+
318
+ ### MCP(Model Context Protocol)
319
+
320
+ ```typescript
321
+ import { McpToolAdapter } from '@tachu/extensions/mcp';
322
+
323
+ const adapter = new McpToolAdapter();
324
+
325
+ // 通过 stdio 连接本地进程
326
+ await adapter.connect('stdio://path/to/mcp-server');
327
+
328
+ // 通过 SSE 连接远程服务
329
+ await adapter.connect('http://localhost:3000/sse');
330
+
331
+ // MCP Tools 自动注册到引擎 Registry
332
+ const tools = await adapter.listTools(); // 返回 ToolDescriptor[]
333
+ engine.registry.registerAll(tools);
334
+ ```
335
+
336
+ `McpToolAdapter` 负责 MCP Session 生命周期管理、能力协商,并将引擎取消信号传播到 MCP 服务端。
337
+
338
+ ### 向量存储(Vector Stores)
339
+
340
+ | Adapter | 包 | 适用场景 |
341
+ |---------|----|----|
342
+ | `InMemoryVectorStore` | `@tachu/core` | 开发/测试;零依赖内置实现 |
343
+ | `LocalFsVectorStore` | `@tachu/extensions/vector` | 单进程生产;文件持久化 |
344
+ | `QdrantVectorStore` | `@tachu/extensions/vector` | 多进程生产;完整 Qdrant REST API |
345
+
346
+ ```typescript
347
+ import { QdrantVectorStore } from '@tachu/extensions/vector';
348
+
349
+ const vectorStore = new QdrantVectorStore({
350
+ url: 'http://localhost:6333',
351
+ collectionName: 'tachu-descriptors',
352
+ });
353
+ engine.useVectorStore(vectorStore);
354
+ ```
355
+
356
+ ### 可观测性 Emitter
357
+
358
+ | Emitter | 包 | 输出目标 |
359
+ |---------|----|----|
360
+ | `OtelEmitter` | `@tachu/extensions/emitters` | OpenTelemetry Span(via `@opentelemetry/api`) |
361
+ | `JsonlEmitter` | `@tachu/extensions/emitters` | 追加写入 JSONL 文件 |
362
+ | `ConsoleEmitter` | `@tachu/extensions/emitters` | 结构化控制台输出(开发用) |
363
+
364
+ ### 执行 Backend
365
+
366
+ | Backend | 包 | 说明 |
367
+ |---------|----|----|
368
+ | `TerminalBackend` | `@tachu/extensions/backends` | 沙箱终端内的 Shell 命令执行 |
369
+ | `FileBackend` | `@tachu/extensions/backends` | 文件系统读写 |
370
+ | `WebBackend` | `@tachu/extensions/backends` | HTTP 请求至外部 API / Web 资源 |
371
+
372
+ ---
373
+
374
+ ## 设计原则(Design Principles)
375
+
376
+ Tachu 基于七条核心工程原则:
377
+
378
+ 1. **双平面匹配** — 所有四类核心抽象通过语义方式发现(向量相似度),但通过确定性方式激活(Scopes、白名单、审批)。语义发现是参考;执行闸门是权威。
379
+
380
+ 2. **全路径安全准入** — 最小安全检查(阶段 2)对*所有*请求路径执行,包括简单问题的快速通道。安全性绝不为性能让步。
381
+
382
+ 3. **事不过三** — 任务级重试循环和系统级重试循环都有严格上限。不允许无限重试。耗尽上限后,引擎输出步骤级完成状态而非笼统失败。
383
+
384
+ 4. **KV Cache 友好的 Prompt 组装** — System Prompt 按稳定顺序组装(硬约束 Rules → 软偏好 Rules → Skills → Tool 定义),使跨轮次的前缀保持不变,最大化 KV Cache 复用,降低 LLM 成本。
385
+
386
+ 5. **取消传播(Last-message-wins)** — 同一 Session 收到新消息时,通过 `AbortController` 取消当前执行,在已有上下文基础上处理新输入。保证上下文连贯,避免无效工作。
387
+
388
+ 6. **引擎不感知业务权限** — 引擎只在 Tool 执行闸门处校验执行上下文中的粗粒度 `scopes`。细粒度业务授权由 Tool 实现本身或专用的授权 Tool 负责。
389
+
390
+ 7. **Fail-Closed 安全基线** — 循环防护、预算熔断、基础输入校验硬编码于引擎核心,*不可*通过配置禁用。即使业务配置完全为空,引擎也不会失控运行。
391
+
392
+ ---
393
+
394
+ ## 配置(Configuration)
395
+
396
+ 引擎通过项目根目录的 `tachu.config.ts` 文件配置(由 `tachu init` 自动生成):
397
+
398
+ ```typescript
399
+ import type { EngineConfig } from '@tachu/core';
400
+
401
+ const config: EngineConfig = {
402
+ // 描述符注册中心
403
+ registry: {
404
+ descriptorRoot: '.tachu', // Rules/Skills/Tools/Agents 根目录
405
+ },
406
+
407
+ // 运行时行为
408
+ runtime: {
409
+ planMode: false, // 是否默认开启 Plan 模式
410
+ maxConcurrency: 4, // 最大并行子任务数
411
+ },
412
+
413
+ // 上下文窗口与记忆
414
+ memory: {
415
+ maxTokens: 8000, // 上下文窗口 Token 上限
416
+ compressionThreshold: 0.8, // 达到 80% 容量时触发压缩
417
+ archivePath: '.tachu/archive.jsonl',
418
+ vectorIndexLimit: 10000, // 内置向量索引最大条目数
419
+ },
420
+
421
+ // 预算约束
422
+ budget: {
423
+ maxTokens: 50000, // 单次执行总 Token 预算
424
+ maxToolCalls: 50, // 单次执行最大 Tool 调用次数
425
+ maxWallTimeMs: 300000, // 5 分钟墙钟时间上限
426
+ },
427
+
428
+ // 安全基线(硬编码最小集;业务策略通过 Hooks 追加)
429
+ safety: {
430
+ maxInputSize: 1_000_000, // 字节
431
+ maxRecursionDepth: 10,
432
+ enablePromptInjectionCheck: true,
433
+ },
434
+
435
+ // 模型路由
436
+ models: {
437
+ capabilityMapping: {
438
+ 'high-reasoning': { provider: 'openai', model: 'gpt-4o' },
439
+ 'fast-cheap': { provider: 'openai', model: 'gpt-4o-mini' },
440
+ 'vision': { provider: 'openai', model: 'gpt-4o' },
441
+ },
442
+ providerFallbackOrder: ['openai', 'anthropic'],
443
+ },
444
+
445
+ // 可观测性
446
+ observability: {
447
+ emitter: 'jsonl',
448
+ jsonlPath: '.tachu/events.jsonl',
449
+ },
450
+ };
451
+
452
+ export default config;
453
+ ```
454
+
455
+ 所有字段均有合理默认值。`tachu init` 会根据你选择的 Provider 预填生成此文件。
456
+
457
+ ---
458
+
459
+ ## CLI 参考(CLI Reference)
460
+
461
+ ### `tachu init`
462
+
463
+ 初始化 Tachu 项目工作空间。
464
+
465
+ ```
466
+ tachu init [options]
467
+
468
+ 选项:
469
+ --template <name> 脚手架模板:minimal | full (默认:minimal)
470
+ --force 已存在时强制覆盖(不询问)
471
+ --path <dir> 目标目录 (默认:当前目录)
472
+ --provider <name> 写入 config 的默认 Provider:openai | anthropic | mock (默认:mock)
473
+ --no-examples 跳过生成示例 Rule / Tool 描述符
474
+ -h, --help 显示帮助
475
+ ```
476
+
477
+ 生成 `.tachu/` 目录骨架 + `tachu.config.ts` + `.gitignore` 追加条目。
478
+
479
+ ---
480
+
481
+ ### `tachu run <prompt>`
482
+
483
+ 单次执行 Prompt,将结果流式输出到 stdout。
484
+
485
+ ```
486
+ tachu run <prompt> [options]
487
+
488
+ 参数:
489
+ <prompt> Prompt 文本(或通过 stdin 管道传入)
490
+
491
+ 选项:
492
+ --session <id> 指定 Session ID
493
+ --resume 恢复最近一次 Session
494
+ --model <name> 覆盖 high-reasoning 模型
495
+ --provider <name> 覆盖默认 Provider
496
+ --input <file> 从文件读取 Prompt
497
+ --json 将 Prompt 解析为 JSON(结构化输入)
498
+ --output <fmt> 输出格式:text | json | markdown (默认:text)
499
+ --no-validation 跳过阶段 8 结果验证
500
+ --plan-mode 启用 Plan 模式(阶段 5 后暂停等待审批)
501
+ --verbose, -v 详细日志(阶段切换、LLM 调用详情)
502
+ --no-color 禁用 ANSI 彩色输出(同 NO_COLOR 环境变量)
503
+ --timeout <ms> 墙钟时间上限(覆盖 budget.maxWallTimeMs)
504
+ -h, --help 显示帮助
505
+ ```
506
+
507
+ ---
508
+
509
+ ### `tachu chat`
510
+
511
+ 进入多轮交互式对话 Session。
512
+
513
+ ```
514
+ tachu chat [options]
515
+
516
+ 选项:
517
+ --session <id> 指定 Session ID
518
+ --resume 恢复最近一次 Session
519
+ --history 列出所有 Session 后退出(不进入交互)
520
+ --export <file> 将指定 Session 导出为 Markdown 后退出
521
+ --model <name> 覆盖 high-reasoning 模型
522
+ --provider <name> 覆盖默认 Provider
523
+ --plan-mode 启用 Plan 模式
524
+ --verbose, -v 详细日志
525
+ --no-color 禁用彩色输出
526
+ -h, --help 显示帮助
527
+ ```
528
+
529
+ **交互内置命令**(输入时以 `/` 开头):
530
+
531
+ | 命令 | 说明 |
532
+ |------|------|
533
+ | `/exit` | 保存 Session 并退出 |
534
+ | `/reset` | 清空当前 Session 的 Memory |
535
+ | `/new` | 开启新 Session |
536
+ | `/list` | 列出所有已保存的 Session |
537
+ | `/load <id>` | 切换到指定 Session |
538
+ | `/save` | 手动持久化当前 Session |
539
+ | `/export <path>` | 将当前 Session 导出为 Markdown 文件 |
540
+ | `/history` | 显示本 Session 的消息历史 |
541
+ | `/stats` | 显示 Token 用量、Tool 调用次数、剩余预算 |
542
+ | `/help` | 显示所有命令 |
543
+
544
+ **Ctrl+C 行为:**
545
+ - 第一次:取消当前 LLM/Tool 调用(回到提示符,Session 不丢失)
546
+ - 1 秒内第二次:保存 Session 并正常退出
547
+ - 第三次:强制退出
548
+
549
+ ---
550
+
551
+ ## 扩展指南(Extension Guide)
552
+
553
+ Tachu 通过在 `.tachu/` 目录下创建 Markdown 描述符文件来扩展。Rules、Skills 和 Tools 无需任何代码变更——只有 Agent 的执行函数需要在代码中单独注册。
554
+
555
+ ### 自定义 Rule
556
+
557
+ ```markdown
558
+ <!-- .tachu/rules/no-external-calls.md -->
559
+ ---
560
+ name: no-external-calls
561
+ description: 禁止 Agent 在未获明确审批前发起外部网络调用
562
+ type: rule
563
+ scope: [execution]
564
+ tags: [security, network]
565
+ ---
566
+
567
+ 除非被调用 Tool 的 requiresApproval 为 true 且用户已确认,
568
+ 否则不得发起 HTTP 请求、DNS 查询或任何其他外部网络调用。
569
+ ```
570
+
571
+ ### 自定义 Skill
572
+
573
+ ```markdown
574
+ <!-- .tachu/skills/git-workflow/SKILL.md -->
575
+ ---
576
+ name: git-workflow
577
+ description: 本仓库 Git 分支策略、Commit 规范与 PR 工作流知识
578
+ tags: [development, git]
579
+ requires:
580
+ - { kind: tool, name: run-command }
581
+ ---
582
+
583
+ ## Git 工作流
584
+
585
+ 本仓库采用基于主干的开发模式(trunk-based development),配合短生命周期特性分支。
586
+
587
+ ### 分支命名
588
+ - 功能分支:`feat/<ticket>-<short-desc>`
589
+ - 修复分支:`fix/<ticket>-<short-desc>`
590
+
591
+ ### Commit 规范
592
+ 使用 Conventional Commits:`type(scope): subject`
593
+ ...
594
+ ```
595
+
596
+ ### 自定义 Tool
597
+
598
+ ```markdown
599
+ <!-- .tachu/tools/query-db.md -->
600
+ ---
601
+ name: query-db
602
+ description: 对应用数据库执行只读 SQL 查询
603
+ sideEffect: readonly
604
+ idempotent: true
605
+ requiresApproval: false
606
+ timeout: 10000
607
+ inputSchema:
608
+ type: object
609
+ properties:
610
+ sql: { type: string, description: "SQL SELECT 语句" }
611
+ limit: { type: number, description: "最大返回行数", default: 100 }
612
+ required: [sql]
613
+ execute: queryDatabase
614
+ ---
615
+
616
+ 执行参数化只读 SQL 查询,结果以 JSON 数组形式返回。
617
+ ```
618
+
619
+ 在 `engine-factory.ts` 中注册执行函数:
620
+
621
+ ```typescript
622
+ engine.registry.registerExecutor('queryDatabase', async (input, ctx) => {
623
+ const { sql, limit = 100 } = input as { sql: string; limit?: number };
624
+ return db.query(sql).limit(limit).execute();
625
+ });
626
+ ```
627
+
628
+ ### 自定义 Agent
629
+
630
+ ```markdown
631
+ <!-- .tachu/agents/code-reviewer.md -->
632
+ ---
633
+ name: code-reviewer
634
+ description: 审查 Pull Request diff,产出结构化代码审查意见
635
+ sideEffect: readonly
636
+ idempotent: true
637
+ requiresApproval: false
638
+ timeout: 180000
639
+ maxDepth: 1
640
+ availableTools: [read-file, search-code, run-command]
641
+ ---
642
+
643
+ 你是一名严谨的代码审查者。接到 diff 或文件集后:
644
+ 1. 理解变更意图
645
+ 2. 从正确性、清晰度、安全性和性能角度逐项审查
646
+ 3. 输出带有严重程度分级的结构化审查意见:critical / major / minor / nit
647
+ ```
648
+
649
+ ---
650
+
651
+ ## 可观测性与安全(Observability & Safety)
652
+
653
+ ### OpenTelemetry 集成
654
+
655
+ 每个引擎事件映射为一条 OTel Span,实现完整的分布式追踪:
656
+
657
+ ```typescript
658
+ import { OtelEmitter } from '@tachu/extensions/emitters';
659
+ import { NodeTracerProvider } from '@opentelemetry/sdk-trace-node';
660
+ import { SimpleSpanProcessor } from '@opentelemetry/sdk-trace-base';
661
+ import { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-http';
662
+
663
+ const provider = new NodeTracerProvider();
664
+ provider.addSpanProcessor(
665
+ new SimpleSpanProcessor(new OTLPTraceExporter({ url: 'http://localhost:4318/v1/traces' }))
666
+ );
667
+ provider.register();
668
+
669
+ engine.useEmitter(new OtelEmitter());
670
+ ```
671
+
672
+ **每次请求产出的事件类型:**
673
+
674
+ | 事件类型 | 时机 |
675
+ |---------|------|
676
+ | `phase_enter` / `phase_exit` | 每个流程阶段进入/退出 |
677
+ | `llm_call_start` / `llm_call_end` | 每次 LLM 调用 |
678
+ | `tool_call_start` / `tool_call_end` | 每次 Tool 执行 |
679
+ | `retry` | 任务级或系统级重试触发 |
680
+ | `provider_fallback` | Provider 降级启动 |
681
+ | `budget_warning` | 预算已用到上限的 80% |
682
+ | `budget_exhausted` | 预算熔断激活 |
683
+ | `error` | 任何 `EngineError` 子类 |
684
+
685
+ ### 安全模块(Safety Module)
686
+
687
+ 安全模块分两层独立运行:
688
+
689
+ **引擎固有基线(不可禁用):**
690
+ - 输入大小上限(`maxInputSize` 字节)
691
+ - 递归深度限制(`maxRecursionDepth`)
692
+ - 预算熔断(Token/时间预算耗尽时立即终止)
693
+
694
+ **业务可注入策略**(通过 Hooks 或配置):
695
+ - Prompt 注入检测(`enablePromptInjectionCheck: true`)
696
+ - 敏感操作拦截(通过 `engine.registerSafetyPolicy()` 注册)
697
+ - 输出内容合规检查
698
+
699
+ ```typescript
700
+ // 注册自定义安全策略
701
+ engine.registerSafetyPolicy(async (input, ctx) => {
702
+ if (containsPersonalData(input.content)) {
703
+ return { passed: false, violations: [{ type: 'pii', message: '输入中检测到个人隐私数据' }] };
704
+ }
705
+ return { passed: true, violations: [] };
706
+ });
707
+ ```
708
+
709
+ ---
710
+
711
+ ## 发展路线(Roadmap)
712
+
713
+ ### v1.0.0 — 已交付
714
+
715
+ - [x] `@tachu/core`:Engine、9 阶段主干、8 个核心模块、Registry、PromptAssembler、InMemoryVectorStore、完整错误分类体系
716
+ - [x] `@tachu/extensions`:OpenAI + Anthropic Provider、7 个 Tools、Terminal/File/Web Backend、LocalFs + Qdrant VectorStore、MCP stdio+SSE Adapter、OTel+JSONL Emitter、4 个通用 Rules
717
+ - [x] `@tachu/cli`:`tachu init` / `tachu run` / `tachu chat`,完整参数体系、Session 持久化、流式渲染
718
+ - [x] 测试套件(行覆盖率 ≥80%)和性能基准
719
+ - [x] 中英文 README
720
+
721
+ ### v1.x — 规划中
722
+
723
+ - 更多 VectorStore Adapter(Pinecone、pgvector)
724
+ - 更多 Provider Adapter(Google Gemini、Mistral)
725
+ - 更多 MCP Tool 集成
726
+ - 更多内置压缩策略
727
+ - 结构化 Plan 模板库
728
+
729
+ ### v2 — 愿景
730
+
731
+ - 多 Agent 协作(Agent 间通信协议)
732
+ - 跨部署重启的长期记忆持久化
733
+ - 子任务粒度的精细预算分配
734
+
735
+ ---
736
+
737
+ ## 贡献指南(Contributing)
738
+
739
+ ### 环境要求
740
+
741
+ - [Bun](https://bun.sh) >= 1.1.0
742
+ - TypeScript 5.x(通过 devDependencies 提供)
743
+
744
+ ### 开发工作流
745
+
746
+ ```bash
747
+ # 克隆并安装
748
+ git clone https://github.com/dangaogit/tachu
749
+ cd tachu
750
+ bun install
751
+
752
+ # 运行所有测试
753
+ bun test
754
+
755
+ # 类型检查
756
+ bun run typecheck
757
+
758
+ # 构建所有包
759
+ bun run build
760
+
761
+ # 运行指定包的测试
762
+ bun test --filter packages/core
763
+ ```
764
+
765
+ ### 项目规范
766
+
767
+ - 文件名:`kebab-case`
768
+ - 类名/类型名:`PascalCase`
769
+ - 函数/变量名:`camelCase`
770
+ - 常量名:`SCREAMING_SNAKE_CASE`
771
+ - 所有公开 API 必须有 TSDoc 注释(`@param`、`@returns`、`@throws`、`@example`)
772
+ - 测试文件与源码同目录,命名 `*.test.ts`
773
+ - 集成测试放 `__tests__/`
774
+
775
+ Pull Request 要求:
776
+ - 所有测试通过(`bun test`)
777
+ - TypeScript 零错误(`bun run typecheck`)
778
+ - 覆盖率达标(行 ≥80%,分支 ≥70%)
779
+ - 新增公开 API 有完整 TSDoc
780
+
781
+ 详见 `CONTRIBUTING.md`。
782
+
783
+ ---
784
+
785
+ ## 基准测试(Benchmarks)
786
+
787
+ 性能基准位于 `packages/core/benchmarks/`,通过 `bun test` 执行:
788
+
789
+ | 基准 | 度量指标 | 基线数据 |
790
+ |------|---------|---------|
791
+ | `scheduler.bench.ts` — 100 个并行任务 | 调度吞吐量 | *由 verifier 阶段填充* |
792
+ | `vector-store.bench.ts` — 10,000 条索引,topK=10 | 搜索 QPS | *由 verifier 阶段填充* |
793
+ | `prompt-assembler.bench.ts` — 4K Token 窗口组装 | 组装延迟(p99) | *由 verifier 阶段填充* |
794
+
795
+ 基准测试提供回归检测基线;v1 不设定最低性能指标要求。
796
+
797
+ ---
798
+
799
+ ## 文档(Documentation)
800
+
801
+ | 文档 | 说明 |
802
+ |------|------|
803
+ | [架构设计(Architecture Design)](./docs/adr/architecture-design.md) | 愿景、三层结构、四大核心抽象、9 阶段主干设计 |
804
+ | [详细设计(Detailed Design)](./docs/adr/detailed-design.md) | TypeScript 接口、模块规格、配置 Schema |
805
+ | [技术设计(Technical Design)](./docs/adr/technical-design.md) | 技术选型、工程结构、实现指南 |
806
+
807
+ ---
808
+
809
+ ## 许可证(License)
810
+
811
+ [Apache License 2.0](./LICENSE) © 2026 Tachu Contributors
812
+
813
+ 本项目采用 Apache License 2.0 许可证发布。许可证全文见 [LICENSE](./LICENSE) 文件,也可在 <http://www.apache.org/licenses/LICENSE-2.0> 获取。
814
+
815
+ 除非适用法律要求或书面同意,按照本许可证分发的软件是按"原样"分发的,不附带任何明示或暗示的担保或条件。请参阅许可证以了解特定语言的管理权限和限制。