@epoch-agent/protocol 0.1.0

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.
package/LICENSE ADDED
@@ -0,0 +1,219 @@
1
+
2
+ Apache License
3
+ Version 2.0, January 2004
4
+ http://www.apache.org/licenses/
5
+
6
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
7
+
8
+ 1. Definitions.
9
+
10
+ "License" shall mean the terms and conditions for use, reproduction,
11
+ and distribution as defined by Sections 1 through 9 of this document.
12
+
13
+ "Licensor" shall mean the copyright owner or entity authorized by
14
+ the copyright owner that is granting the License.
15
+
16
+ "Legal Entity" shall mean the union of the acting entity and all
17
+ other entities that control, are controlled by, or are under common
18
+ control with that entity. For the purposes of this definition,
19
+ "control" means (i) the power, direct or indirect, to cause the
20
+ direction or management of such entity, whether by contract or
21
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
22
+ outstanding shares, or (iii) beneficial ownership of such entity.
23
+
24
+ "You" (or "Your") shall mean an individual or Legal Entity
25
+ exercising permissions granted by this License.
26
+
27
+ "Source" form shall mean the preferred form for making modifications,
28
+ including but not limited to software source code, documentation
29
+ source, and configuration files.
30
+
31
+ "Object" form shall mean any form resulting from mechanical
32
+ transformation or translation of a Source form, including but
33
+ not limited to compiled object code, generated documentation,
34
+ and conversions to other media types.
35
+
36
+ "Work" shall mean the work of authorship, whether in Source or
37
+ Object form, made available under the License, as indicated by a
38
+ copyright notice that is included in or attached to the work
39
+ (an example is provided in the Appendix below).
40
+
41
+ "Derivative Works" shall mean any work, whether in Source or Object
42
+ form, that is based on (or derived from) the Work and for which the
43
+ editorial revisions, annotations, elaborations, or other modifications
44
+ represent, as a whole, an original work of authorship. For the purposes
45
+ of this License, Derivative Works shall not include works that remain
46
+ separable from, or merely link (or bind by name) to the interfaces of,
47
+ the Work and Derivative Works thereof.
48
+
49
+ "Contribution" shall mean any work of authorship, including
50
+ the original version of the Work and any modifications or additions
51
+ to that Work or Derivative Works thereof, that is intentionally
52
+ submitted to Licensor for inclusion in the Work by the copyright owner
53
+ or by an individual or Legal Entity authorized to submit on behalf of
54
+ the copyright owner. For the purposes of this definition, "submitted"
55
+ means any form of electronic, verbal, or written communication sent
56
+ to the Licensor or its representatives, including but not limited to
57
+ communication on electronic mailing lists, source code control systems,
58
+ and issue tracking systems that are managed by, or on behalf of, the
59
+ Licensor for the purpose of discussing and improving the Work, but
60
+ excluding communication that is conspicuously marked or otherwise
61
+ designated in writing by the copyright owner as "Not a Contribution."
62
+
63
+ "Contributor" shall mean Licensor and any individual or Legal Entity
64
+ on behalf of whom a Contribution has been received by Licensor and
65
+ subsequently incorporated within the Work.
66
+
67
+ 2. Grant of Copyright License. Subject to the terms and conditions of
68
+ this License, each Contributor hereby grants to You a perpetual,
69
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
70
+ copyright license to reproduce, prepare Derivative Works of,
71
+ publicly display, publicly perform, sublicense, and distribute the
72
+ Work and such Derivative Works in Source or Object form.
73
+
74
+ 3. Grant of Patent License. Subject to the terms and conditions of
75
+ this License, each Contributor hereby grants to You a perpetual,
76
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
77
+ (except as stated in this section) patent license to make, have made,
78
+ use, offer to sell, sell, import, and otherwise transfer the Work,
79
+ where such license applies only to those patent claims licensable
80
+ by such Contributor that are necessarily infringed by their
81
+ Contribution(s) alone or by combination of their Contribution(s)
82
+ with the Work to which such Contribution(s) was submitted. If You
83
+ institute patent litigation against any entity (including a
84
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
85
+ or a Contribution incorporated within the Work constitutes direct
86
+ or contributory patent infringement, then any patent licenses
87
+ granted to You under this License for that Work shall terminate
88
+ as of the date such litigation is filed.
89
+
90
+ 4. Redistribution. You may reproduce and distribute copies of the
91
+ Work or Derivative Works thereof in any medium, with or without
92
+ modifications, and in Source or Object form, provided that You
93
+ meet the following conditions:
94
+
95
+ (a) You must give any other recipients of the Work or
96
+ Derivative Works a copy of this License; and
97
+
98
+ (b) You must cause any modified files to carry prominent notices
99
+ stating that You changed the files; and
100
+
101
+ (c) You must retain, in the Source form of any Derivative Works
102
+ that You distribute, all copyright, patent, trademark, and
103
+ attribution notices from the Source form of the Work,
104
+ excluding those notices that do not pertain to any part of
105
+ the Derivative Works; and
106
+
107
+ (d) If the Work includes a "NOTICE" text file as part of its
108
+ distribution, then any Derivative Works that You distribute must
109
+ include a readable copy of the attribution notices contained
110
+ within such NOTICE file, excluding those notices that do not
111
+ pertain to any part of the Derivative Works, in at least one
112
+ of the following places: within a NOTICE text file distributed
113
+ as part of the Derivative Works; within the Source form or
114
+ documentation, if provided along with the Derivative Works; or,
115
+ within a display generated by the Derivative Works, if and
116
+ wherever such third-party notices normally appear. The contents
117
+ of the NOTICE file are for informational purposes only and
118
+ do not modify the License. You may add Your own attribution
119
+ notices within Derivative Works that You distribute, alongside
120
+ or as an addendum to the NOTICE text from the Work, provided
121
+ that such additional attribution notices cannot be construed
122
+ as modifying the License.
123
+
124
+ You may add Your own copyright statement to Your modifications and
125
+ may provide additional or different license terms and conditions
126
+ for use, reproduction, or distribution of Your modifications, or
127
+ for any such Derivative Works as a whole, provided Your use,
128
+ reproduction, and distribution of the Work otherwise complies with
129
+ the conditions stated in this License.
130
+
131
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
132
+ any Contribution intentionally submitted for inclusion in the Work
133
+ by You to the Licensor shall be under the terms and conditions of
134
+ this License, without any additional terms or conditions.
135
+ Notwithstanding the above, nothing herein shall supersede or modify
136
+ the terms of any separate license agreement you may have executed
137
+ with Licensor regarding such Contributions.
138
+
139
+ 6. Trademarks. This License does not grant permission to use the trade
140
+ names, trademarks, service marks, or product names of the Licensor,
141
+ except as required for reasonable and customary use in describing the
142
+ origin of the Work and reproducing the content of the NOTICE file.
143
+
144
+ 7. Disclaimer of Warranty. Unless required by applicable law or
145
+ agreed to in writing, Licensor provides the Work (and each
146
+ Contributor provides its Contributions) on an "AS IS" BASIS,
147
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
148
+ implied, including, without limitation, any warranties or conditions
149
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
150
+ PARTICULAR PURPOSE. You are solely responsible for determining the
151
+ appropriateness of using or redistributing the Work and assume any
152
+ risks associated with Your exercise of permissions under this License.
153
+
154
+ 8. Limitation of Liability. In no event and under no legal theory,
155
+ whether in tort (including negligence), contract, or otherwise,
156
+ unless required by applicable law (such as deliberate and grossly
157
+ negligent acts) or agreed to in writing, shall any Contributor be
158
+ liable to You for damages, including any direct, indirect, special,
159
+ incidental, or consequential damages of any character arising as a
160
+ result of this License or out of the use or inability to use the
161
+ Work (including but not limited to damages for loss of goodwill,
162
+ work stoppage, computer failure or malfunction, or any and all
163
+ other commercial damages or losses), even if such Contributor
164
+ has been advised of the possibility of such damages.
165
+
166
+ 9. Accepting Warranty or Additional Liability. While redistributing
167
+ the Work or Derivative Works thereof, You may choose to offer,
168
+ and charge a fee for, acceptance of support, warranty, indemnity,
169
+ or other liability obligations and/or rights consistent with this
170
+ License. However, in accepting such obligations, You may act only
171
+ on Your own behalf and on Your sole responsibility, not on behalf
172
+ of any other Contributor, and only if You agree to indemnify,
173
+ defend, and hold each Contributor harmless for any liability
174
+ incurred by, or claims asserted against, such Contributor by reason
175
+ of your accepting any such warranty or additional liability.
176
+
177
+ END OF TERMS AND CONDITIONS
178
+
179
+ APPENDIX: How to apply the Apache License to your work.
180
+
181
+ To apply the Apache License to your work, attach the following
182
+ boilerplate notice, with the fields enclosed by brackets "[]"
183
+ replaced with your own identifying information. (Don't include
184
+ the brackets!) The text should be enclosed in the appropriate
185
+ comment syntax for the file format. We also recommend that a
186
+ file or class name and description of purpose be included on the
187
+ same "printed page" as the copyright notice for easier
188
+ identification within third-party archives.
189
+
190
+ Copyright [yyyy] [name of copyright owner]
191
+
192
+ Licensed under the Apache License, Version 2.0 (the "License");
193
+ you may not use this file except in compliance with the License.
194
+ You may obtain a copy of the License at
195
+
196
+ http://www.apache.org/licenses/LICENSE-2.0
197
+
198
+ Unless required by applicable law or agreed to in writing, software
199
+ distributed under the License is distributed on an "AS IS" BASIS,
200
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
201
+ See the License for the specific language governing permissions and
202
+ limitations under the License.
203
+
204
+ --------------------------------------------------------------------------------
205
+
206
+ epoch-agent
207
+ Copyright 2024-2026 bowen
208
+
209
+ Portions of this software are derived from the Gemini CLI
210
+ (https://github.com/google-gemini/gemini-cli), Copyright 2025 Google LLC,
211
+ licensed under the Apache License, Version 2.0. Those files have been modified;
212
+ each one retains its original copyright notice and SPDX-License-Identifier
213
+ header. See the NOTICE file in the project source repository for the complete
214
+ list of derived files.
215
+
216
+ This software also quotes, with attribution, two lines of prose from OpenAI
217
+ Codex (https://github.com/openai/codex), Copyright 2025 OpenAI, licensed under
218
+ the Apache License, Version 2.0. No source file is a derived work of Codex.
219
+ See the NOTICE file for details.
package/README.md ADDED
@@ -0,0 +1,135 @@
1
+ # @epoch-agent/protocol
2
+
3
+ 契约层。跨包边界上的类型与常量,没有任何实现。
4
+
5
+ - ✅ **做**:定义跨包共用的类型 / 常量(工具、事件、权限、插件、Hook、配置、线协议),
6
+ 以及**纯粹作用在这些类型上的口径函数**(`contentToText` / `promptTokens` 这种)——
7
+ 它们跟着类型走,不跟着某个包走,而且 [tui](../tui) 只依赖 protocol,
8
+ 放别处它就够不着,只能自己抄一份
9
+ - ❌ **不做**:领域逻辑、任何 I/O、任何状态
10
+ - **依赖**:无。零 runtime 依赖,谁都可以依赖它
11
+
12
+ 判断一个类型该不该放这里:**是否被两个以上的包共用**。只有 core 和它的直接下游用到的
13
+ (比如 `SessionManager` 的输入输出类型)不放这里,留在实现包。
14
+
15
+ ## 文件
16
+
17
+ | 文件 | 内容 |
18
+ | -------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------- |
19
+ | `tool.ts` | `EpochTool` / `ToolContext` / `ToolResult` / `ToolExposure` |
20
+ | `plugin.ts` | `EpochPlugin` —— 第三方加工具的唯一入口 |
21
+ | `events.ts` | `AgentEvent` 判别联合 —— 引擎与所有宿主之间的事件契约、`TokenUsage` |
22
+ | `usage.ts` | `TokenUsage` 的口径算术 + **压缩那条线**(`compressionThresholdTokens`) |
23
+ | `message.ts` | `EpochMessage` 及其内容块 |
24
+ | `permission.ts` | 5 级权限、操作类型、审批请求 / 应答、`PermissionManager` 接口 |
25
+ | `plan.ts` | plan **模式**(临时只读区间,出口要人批一次)—— 与 `plan` 那个权限级别的口径 |
26
+ | `question.ts` | 结构化提问的请求 / 答复(**不过权限层** —— 提问不是审批) |
27
+ | `hook.ts` | Hook 类型与 trigger |
28
+ | `config.ts` | 配置形状 |
29
+ | `context.ts` | 上下文预算的构成(`/context` 那张账目:每一段花了多少) |
30
+ | `task.ts` | 后台任务的形状(宿主要展示它们:状态栏计数、`/tasks`、Web 那一栏) |
31
+ | `keybindings.ts` | 键位的**值域**(动作全集 + `KeyChord` + 与 `"ctrl+l"` 写法互转)。默认表在 tui |
32
+ | `i18n.ts` | 界面语言的值域(`Lang` / `LANGS` / `DEFAULT_LANG`)—— **封闭的两个值**;外加 API URL 上那个 `WIRE_LANG_PARAM`(方案 58) |
33
+ | `model-ref.ts` | `<provider>/<model>` 的解析 |
34
+ | `agent-role.ts` | 子 agent 角色(`delegate_task` 的 role 取值) |
35
+ | `commands.ts` | 自定义斜杠命令的定义 / 展开结果 / 内置命令保留名单 |
36
+ | `mentions.ts` | `@路径` 的抽取规则(TUI 和引擎共用一份,两边写岔了会静默错位) |
37
+ | `system-note.ts` | 「这条 `user` 消息其实是系统在说话」那个前缀 + 拼 / 剥两个函数。**四处共用,且必须逐字节相同**,理由在它的文件头 |
38
+ | `secret.ts` | 凭据存储后端的接口 |
39
+ | `trust.ts` | 工作区信任的判定结果 |
40
+ | `schedule.ts` | 定时任务:三档触发器(判别联合)、一条任务 / 一次运行的形状、欠条、宿主注入点 |
41
+ | `diagnostics.ts` | 启动诊断(`DiagnosticSink`,`epoch doctor` 打的就是这些)。`detail` 收 `string \| LocalizedDetail` —— 后者能按语言重放,`toList(lang)` 是那条路 |
42
+ | `telemetry.ts` | `Telemetry` / `SpanLike` / GenAI 语义约定常量 / `NOOP_TELEMETRY` |
43
+ | `artifact.ts` | 大块工具输出的落盘引用 |
44
+ | `wire.ts` | 线上的信封(`WireEnvelope` / `WireHubEvent` / `WireAuthGuard`) |
45
+ | `wire-rest.ts` | Web UI 的 REST 载荷(`Wire*Response`)与鉴权常量 |
46
+ | `wire-capability.ts` | 能力页那一个端点的载荷。**单开一个文件**是因为 `wire-rest.ts` 已经 788 行 |
47
+ | `wire-security.ts` | 安全中心那五块。**全是读** —— 一个写字段都没有,判据在它的文件头 |
48
+ | `wire-permission.ts` | 改**这个会话此刻**的权限档那一对(决定 20 ③)。和上一行不是一回事,见下 |
49
+ | `wire-settings.ts` | 设置页:每一项赢在哪一层 + 能写进哪几层。见下面「设置那一份」 |
50
+ | `headless-wire.ts` | 程序驱动 `epoch` 时 stdin / stdout 的形状(`init` / `result` + 五个入站事件) |
51
+
52
+ > **第三方要接这套 wire 自己做前端**:这几个文件就是契约,直接 `import type`,
53
+ > 别照着文档抄(文档会过期,类型不会)。接法见
54
+ > [docs/EMBEDDING.md §10](../../docs/EMBEDDING.md)。
55
+
56
+ > ⚠️ **`wire-security.ts` 和 `wire-permission.ts` 别按「都带 permission」并起来。**
57
+ > 前者是**安全中心那一屏**的载荷,全是读,答的是「规矩是什么」(规则表、遮蔽
58
+ > 发现、托管锁、信任、策略、审计流水);后者是**输入框框外那一行**上那一格,
59
+ > 有写,答的是「这个会话现在是哪一档、改不改得动」。
60
+ > 两者的耦合是真的(`WirePermissionState.level` 就是 `WirePermissionStatus.level`
61
+ > 那一格,`WireBlockedLevel` 是 `WireManagedLock.bypassDisabled` 的投影),
62
+ > 所以后者 `import type` 了前者那两个 —— 判据写在它的文件头,
63
+ > 拆文件不等于解耦。
64
+
65
+ ### 设置那一份(`wire-settings.ts`)
66
+
67
+ 它发的不是值,是**值加上它赢在哪一层**(epoch 的设置有六层来源,见
68
+ [docs/SETTINGS.md](../../docs/SETTINGS.md))—— 只显示「当前值」的设置界面会在
69
+ 「用户改了一个开关、被上面某一层压回去」时撒谎。
70
+
71
+ ⚠️ 这份契约里最要紧的一个字段是 `WireSettingWrite.futile`,而它在**读**响应上:
72
+ 写进的层压不过当前赢的那一层时,那个改动写了等于没写,**而这一句必须在用户按下
73
+ 保存之前说出来**。做成写响应的一个字段就迟了 —— 那时它只是一句事后通知。
74
+
75
+ `WireSettingApply` 是另一条容易接错的:写完这个进程**不会重读配置**,所以落盘
76
+ 之后 `GET` 回来的值一个字都不会变。别乐观更新那一行 —— 那会显示一个这台机器上
77
+ 哪儿都不存在的状态。
78
+
79
+ ## 改这里要注意
80
+
81
+ `wire.ts` 的信封有**两个出口**:`epoch web` 的 SSE 和
82
+ `epoch --output-format stream-json` 的 stdout NDJSON。共用是刻意的 ——
83
+ `fixtures/wire/*.json` 那几份录像因此能同时当两边的夹具,`seq` 的语义也只有一份。
84
+ `headless-wire.ts` 只加了两个生命周期事件,信封本身一个字段没动。
85
+
86
+ `wire.ts` / `wire-rest.ts` 是 [server](../server) 和 [web](../web) 共用的**同一份**形状:
87
+ 假服务端(`web/dev/fake-server.ts`)的每个响应体都挂 `satisfies Wire*Response`,
88
+ 所以字段名漂了两边一起编译不过。这是故意的——之前假服务端自己编了一套形状,
89
+ 于是「先对假服务端验前端」这条验收顺序失去了意义。
90
+
91
+ `events.ts` 的 `AgentEvent` 加成员时,[view](../view) 的 reducer 要跟着处理,
92
+ 否则 TUI 和 Web 会静默丢事件。**先想清楚谁发** —— `diff` 那一条在这个联合里
93
+ 声明了、消费了、渲染了整整一轮,中间一个发射方都没有(判据写在它的 JSDoc 上)。
94
+
95
+ `run-start`(2026-08-15)是这个联合最新的一条,由 core 在**第一次模型请求之前、
96
+ 预算闸门之后**发,一次 `run()` 最多一条。它带的 `estimatedTokens` 是
97
+ **运行前估算**,界面上必须挂「估算」字样 —— 2026-08-15 换了真分词器
98
+ (`o200k_base`)之后偏差小了,但它仍然是发之前算的,真值只有 provider 回的
99
+ `usage` 说了算。判据全文在 `provider/tokenizer.ts` 的文件头末尾。
100
+
101
+ `agent-role.ts` 的 `AgentRoleScope` 分「子 agent」和「会话」两档,引擎拿它**只**
102
+ 挑 system prompt 的身份行;工具收窄、轮次预算、prompt 追加段两档完全一样。
103
+ **逐条挑专家(方案 57,2026-08-17)没有第三档**:`session` 那句身份行是
104
+ 「这一次以「x」的身份工作」,「这一次」在逐条语境下正好是对的 —— 两者在模型读到的
105
+ 字节上没有区别。网线上那一格是 `WireSendMessageRequest.role`(缺席 = 用这段会话的
106
+ 角色,认不出来是 400 `unknown-role`),完整判据在 `AgentRoleScope` 的文件注释里。
107
+
108
+ `WireSessionSummary.workspace` 是**三档判别联合**(`bound` / `none` / `unknown`,
109
+ 2026-08-19),不是一个可空引用 —— 这是一次**破坏性 wire 变更**(同 `{binding}`
110
+ 那次:同一个 monorepo 里 `packages/web` 是唯一消费方,同批改)。换掉它的理由和
111
+ `{workspace: … | null}` → `{binding}` 那次逐字同源:那个 `null` 一个值扛了
112
+ 「明确不使用工作区」和「这个进程说不出它在哪儿干过活」两件事,而**侧栏把这一行
113
+ 归到哪一组,正好取决于这两者的差别**。三档的取值优先级(内存绑定 → `live` →
114
+ 库里落着的那次决定 → `unknown`)在 server 的 `sessions/summary.ts`,
115
+ **这边不抄第二份**。⚠️ 同一个类型上另外三格(`pendingSince` / `turnStartedAt` /
116
+ `lastFinish`)**照旧是可空的、也照旧只有 Hub 手里那些会话才有** ——
117
+ 它们是运行时活性,进程一退就真的不存在;`workspace` 能落盘是因为它是
118
+ **用户的一次决定**。
119
+
120
+ `TokenUsage` 的五个 token 字段**有两种不同的包含关系**(缓存两项与 `inputTokens`
121
+ 不重叠、`reasoningTokens` 含在 `outputTokens` 里),口径表就写在 `events.ts` 上。
122
+ 要「一共多少 token」或「提示词多大」,用 `usage.ts` 的两个函数,
123
+ **别自己把字段加一遍** —— 漏掉缓存那两项的症状是上下文占用显示成个位数百分比,
124
+ 而且只在开了 prompt caching 的 provider 上才出现。
125
+
126
+ 同一个文件里还有**「快满了」那条线**(2026-08-16):
127
+ `compressionThresholdTokens(contextLength, threshold)` 和
128
+ `isContextNearlyFull(prompt, contextLength, threshold)`。它们住在这儿的理由和上面
129
+ 那两个逐字相同 —— **两个必然的消费方,必须给出同一个数**:引擎那边是
130
+ `ContextCompressor.shouldCompress()`(真的触发压缩的那一处),界面那边是设置页
131
+ 「记忆与上下文」里那句「压缩在 64,000 token 时开始」。各写一遍的症状极难查:
132
+ 界面说「还早」,下一轮却压了。
133
+
134
+ ⚠️ 它只是**那条线**,不是「会不会压」的完整答案 —— 压缩器上还有冷却期和熔断,
135
+ 两者都只会让压缩更晚发生。所以界面拿它画的是「到线了」,不是「下一轮一定压」。