lingagent 0.1.0__tar.gz

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 (33) hide show
  1. lingagent-0.1.0/PKG-INFO +374 -0
  2. lingagent-0.1.0/README.md +351 -0
  3. lingagent-0.1.0/pyproject.toml +51 -0
  4. lingagent-0.1.0/pyproject.toml.orig +53 -0
  5. lingagent-0.1.0/src/agent_harness/__init__.py +300 -0
  6. lingagent-0.1.0/src/agent_harness/__main__.py +4 -0
  7. lingagent-0.1.0/src/agent_harness/assembly.py +159 -0
  8. lingagent-0.1.0/src/agent_harness/compact.py +114 -0
  9. lingagent-0.1.0/src/agent_harness/config.py +14 -0
  10. lingagent-0.1.0/src/agent_harness/config_wizard.py +100 -0
  11. lingagent-0.1.0/src/agent_harness/guardrail.py +391 -0
  12. lingagent-0.1.0/src/agent_harness/hooks.py +70 -0
  13. lingagent-0.1.0/src/agent_harness/llm.py +344 -0
  14. lingagent-0.1.0/src/agent_harness/loop.py +169 -0
  15. lingagent-0.1.0/src/agent_harness/messages.py +20 -0
  16. lingagent-0.1.0/src/agent_harness/paths.py +9 -0
  17. lingagent-0.1.0/src/agent_harness/schema.py +151 -0
  18. lingagent-0.1.0/src/agent_harness/sensors.py +132 -0
  19. lingagent-0.1.0/src/agent_harness/server.py +451 -0
  20. lingagent-0.1.0/src/agent_harness/session.py +317 -0
  21. lingagent-0.1.0/src/agent_harness/settings.py +141 -0
  22. lingagent-0.1.0/src/agent_harness/shell.py +100 -0
  23. lingagent-0.1.0/src/agent_harness/subagent.py +100 -0
  24. lingagent-0.1.0/src/agent_harness/tasks.py +96 -0
  25. lingagent-0.1.0/src/agent_harness/tools.py +388 -0
  26. lingagent-0.1.0/src/agent_harness/trace.py +138 -0
  27. lingagent-0.1.0/src/agent_harness/tui.py +594 -0
  28. lingagent-0.1.0/src/agent_harness/web_dist/assets/index-3srHxkHj.css +1 -0
  29. lingagent-0.1.0/src/agent_harness/web_dist/assets/index-Dn4Kq7qr.js +38 -0
  30. lingagent-0.1.0/src/agent_harness/web_dist/favicon.svg +1 -0
  31. lingagent-0.1.0/src/agent_harness/web_dist/icons.svg +24 -0
  32. lingagent-0.1.0/src/agent_harness/web_dist/index.html +14 -0
  33. lingagent-0.1.0/src/agent_harness/weblaunch.py +377 -0
@@ -0,0 +1,374 @@
1
+ Metadata-Version: 2.4
2
+ Name: lingagent
3
+ Version: 0.1.0
4
+ Summary: A coding-agent harness: LLM decides, the harness dispatches tools, guards and logs
5
+ Author: ypchen
6
+ Author-email: ypchen <3311614415@qq.com>
7
+ License-Expression: MIT
8
+ Classifier: Development Status :: 3 - Alpha
9
+ Classifier: Intended Audience :: Developers
10
+ Classifier: License :: OSI Approved :: MIT License
11
+ Classifier: Programming Language :: Python :: 3
12
+ Classifier: Operating System :: OS Independent
13
+ Classifier: Topic :: Software Development :: Libraries
14
+ Requires-Dist: fastapi>=0.141.1
15
+ Requires-Dist: openai>=3.8.0
16
+ Requires-Dist: prompt-toolkit>=3.0.53
17
+ Requires-Dist: rich>=15.0.0
18
+ Requires-Dist: uvicorn>=0.53.0
19
+ Requires-Dist: wcwidth>=0.2.13
20
+ Requires-Dist: websockets>=17.2
21
+ Requires-Python: >=3.14
22
+ Description-Content-Type: text/markdown
23
+
24
+ # Agent Harness
25
+
26
+ 一个自己转圈干活的 coding agent 引擎:LLM 只做「下一步做什么」的决策,其余(工具分发、治理拦截、反馈回灌、记忆读写、停机)全是自己写的工程。
27
+
28
+ 核心等式:**Agent = LLM + Harness**。
29
+
30
+ - 终端界面(TUI)+ 网页界面(React,实时流 + 网页审批)
31
+ - 危险动作走风险分级:只读放行 / 改动静默问人 / 极危险直拒
32
+ - 每步动作留轨迹(trace),会话可恢复(session)
33
+ - 硬标准:**移除真 LLM 后核心机制仍能用确定性单测验证**(202 条测试)
34
+
35
+ ## 环境要求
36
+
37
+ | 依赖 | 版本 | 说明 |
38
+ |---|---|---|
39
+ | Python | 3.14+ | `.python-version` 已锁 3.14;用 `uv` 托管,不碰系统环境 |
40
+ | uv | 0.12+ | 包管理与运行入口 |
41
+ | Node.js | 20+ | 只有网页前端需要(`web/`) |
42
+
43
+ ## 安装
44
+
45
+ ```bash
46
+ git clone <repo> && cd AgentHarness
47
+ uv sync
48
+ ```
49
+
50
+ ## 安装(当产品用:装完在任意目录 `linga` 就能启动)
51
+
52
+ 不打成「仓库里跑」的形态,而是装成一条命令——像 `claude`、`gh` 那样。
53
+
54
+ **最省事:发布到 PyPI 之后一行**(见下「为什么是三行」):
55
+
56
+ ```bash
57
+ uv tool install lingagent # 或 pipx install lingagent
58
+ ```
59
+
60
+ **还没发布时的本地做法(三条命令,只跑一次):**
61
+
62
+ ```bash
63
+ uv run python scripts/build_web.py # 把前端构建产物打进包里(需要 Node)
64
+ uv build # 产出 dist/lingagent-0.1.0-py3-none-any.whl
65
+ uv tool install dist/lingagent-0.1.0-py3-none-any.whl
66
+ ```
67
+
68
+ 装完先做一次配置(交互式,问三句就写好 `~/.agent-harness/config.toml`):
69
+
70
+ ```bash
71
+ linga --init
72
+ ```
73
+
74
+ 之后随便 `cd` 到哪个目录:
75
+
76
+ ```bash
77
+ linga # 启动 TUI(会话 / 轨迹按当前目录的项目身份归档)
78
+ lingagent-web # 只起后端 + 网页界面
79
+ linga --stop-web # 关掉后台的后端
80
+ ```
81
+
82
+ 装好的包**不需要 Node、不需要仓库、不需要 web/**:前端构建产物跟着 wheel 走,后端一个端口
83
+ (`http://localhost:8000`)就把界面和 WebSocket 一起发出去。开发时(在仓库里)仍走 vite 5173 热更新。
84
+
85
+ 卸载:`uv tool uninstall lingagent`。
86
+
87
+ **为什么上面是三行而不是一行**:`web_dist/` 不提交进 git(构建产物不该进版本库),所以本地要先
88
+ `build_web` 把前端塞进 wheel;也没发布到 PyPI,所以要 `uv build` 现打一个。只要把 wheel 推到 PyPI,
89
+ `uv tool install lingagent` 就是唯一一行——这是下一步该做的事,跟安装方式无关。
90
+
91
+ ## 配置
92
+
93
+ 复制示例配置到用户目录(**不在仓库里**,也不该提交):
94
+
95
+ ```bash
96
+ mkdir -p ~/.agent-harness && cp harness.example.toml ~/.agent-harness/config.toml
97
+ # Windows: mkdir %USERPROFILE%\.agent-harness && copy harness.example.toml %USERPROFILE%\.agent-harness\config.toml
98
+ ```
99
+
100
+ 最小可用配置:
101
+
102
+ ```toml
103
+ [model]
104
+ default = "deepseek-flash"
105
+
106
+ [models.deepseek-flash]
107
+ name = "deepseek-flash"
108
+ base_url = "https://api.deepseek.com"
109
+ api_key_env = "DEEPSEEK_API_KEY" # 从环境变量读(推荐)
110
+ # api_key = "sk-..." # 或直写明文(优先于上面的 env;别提交进仓库)
111
+ ```
112
+
113
+ 密钥两种写法二选一,**都没有就在启动时直接报错退出**(TUI 和后端都会前置校验)。
114
+
115
+ 其余可调项(`[loop] max_steps`、`[context] compact_threshold`、`[server] port`、`[web] autostart` / `stop_on_exit` / `stop_wait`)见 `harness.example.toml` 里的注释。
116
+
117
+ ## 运行
118
+
119
+ **终端界面:**
120
+
121
+ ```bash
122
+ uv run linga # 用配置里的 default profile
123
+ uv run linga --model deepseek-v4-pro # 临时指定 profile
124
+ ```
125
+
126
+ 首次启动会:列出历史会话让你选(`0` 开新会话、`n`/`p` 翻页)→ 自动拉起网页端(`[web] autostart = false` 可关)。
127
+
128
+ 界面内命令:输入 `/` 会弹出命令菜单——`/model` 切模型、`/trace` 看本轮轨迹(`/trace N` 钻取单条)。
129
+ 退出:`Ctrl+C` 连按两次,或 `Ctrl+D`。
130
+
131
+ **网页界面:**
132
+
133
+ ```bash
134
+ # 终端 1:后端(默认 127.0.0.1:8000)
135
+ uv run lingagent-web
136
+
137
+ # 终端 2:前端(默认 5173)
138
+ cd web && npm install && npm run dev
139
+ ```
140
+
141
+ 打开 <http://localhost:5173>。由 TUI 自启时这两步都不用手动做。
142
+
143
+ > 改了 `[server] port` 的话前端也要跟上:在 `web/.env` 里写 `VITE_WS_PORT=新端口`(不写默认 8000)。
144
+
145
+ ## 测试
146
+
147
+ ```bash
148
+ uv run pytest # 全量(170 条)
149
+ cd web && npx tsc --noEmit # 前端类型检查
150
+ ```
151
+
152
+ agent 自己的 `run_tests` 工具按项目根的标记文件认测试入口,所以换个项目也能用:
153
+
154
+ | 标记文件 | 跑什么 |
155
+ |---|---|
156
+ | `pyproject.toml` / `pytest.ini` / `tox.ini` / `setup.cfg` | `python -m pytest -q`(红了按段提取失败清单 + 详情) |
157
+ | `package.json` 且 `scripts.test` 存在 | `npm test` |
158
+ | `go.mod` | `go test ./...` |
159
+ | `Cargo.toml` | `cargo test` |
160
+ | `Makefile` 且有 `test:` 目标 | `make test` |
161
+
162
+ 一个都认不出就直说"没找到测试入口",让模型改用 `run_shell`——不会伪造成一条红的测试报告。它认的是**工作目录**(项目根),子目录里的子包(比如 `web/`)不管。
163
+
164
+ ## 数据都在哪
165
+
166
+ | 内容 | 位置 | 说明 |
167
+ |---|---|---|
168
+ | 配置 | `~/.agent-harness/config.toml` | 含密钥,**不要提交** |
169
+ | 会话存档 | `~/.agent-harness/sessions/<项目名-身份前8位>/<会话id>.jsonl` | 一行一条消息,append-only |
170
+ | 轨迹 | 同目录 `<会话id>.trace.jsonl` | 一步一条事件,含工具结果**全文**,只增不减 |
171
+ | 项目身份 | 工作目录下的 `.agent-harness-id` | 一行 uuid,决定历史归谁 |
172
+ | 超长输出的全文 | 工作目录下的 `.agent-harness-out/` | 已 gitignore,留 7 天;给模型分段读用 |
173
+ | 后台任务日志 | `~/.agent-harness/tasks/<时间戳>-tN.log` | 留 7 天 |
174
+
175
+ 旧版本把这两样放在 `~/.agent_harness.toml` 和 `~/.agent_harness_sessions/`,首次运行会自动搬到新位置。
176
+
177
+ 注意两件事:
178
+
179
+ 1. **历史归属靠工作目录里的 `.agent-harness-id`**(一个 uuid 文件,已 gitignore)。所以项目**改名、移动目录都不会丢历史**——文件跟着文件夹走,身份不变。反过来说:**删掉这个文件等于换身份**,旧历史不会消失,但不会在这个目录下再列出来(把旧的 id 内容写回去就接上了)。旧布局(按绝对路径命名的目录)会在首次访问时自动迁移过来。
180
+ 2. **trace 会一直长**(工具结果全文,审计账不截断)。攒久了清一下:
181
+
182
+ ```bash
183
+ uv run linga --clean-trace 30 # 删 30 天前的轨迹(0 = 全删)
184
+ ```
185
+
186
+ 删轨迹不影响会话本身。要彻底不写,配置里 `[trace] enabled = false`——session 照常,只是没有"给人看的账"。TUI 启动时如果发现轨迹一个月没人看过,会提醒一句。
187
+
188
+ 真发生压缩时会往对话里插一行提示(`⟳ 上下文偏长…`),不会静默改小上下文。
189
+
190
+ 关于结果长度:进模型上下文(history / session)的那份截断到 32k 字符(头 24k + 尾 8k,中间注明省略);**被省略的中间那段不丢**——落在项目根的 `.agent-harness-out/`(已 gitignore,留 7 天)并把路径写进提示,模型可以直接 `read_file` 或 `sed -n` 读那一段,不用把原命令重跑一遍。trace 里保留全文。读取侧也有护栏——单条超过 2MB 的事件不解析(只显示摘要),网页端单字段最多 2k 字符。
191
+
192
+ ## 网页端
193
+
194
+ 打开 `http://localhost:5173`,界面分三块:
195
+
196
+ - **左栏**:历史会话,按「今天 / 昨天 / 日期」分组,上面有个搜索框(只搜标题);可折叠成 56px
197
+ - **中间**:对话。assistant 不套气泡,工具调用折成一行(`▸ edit_file src/x.py +2 −1`)——点开看 diff,右侧看输出与耗时;输入框上方的 `+ 新会话` 直接换会话,不刷新页面
198
+ - **右栏**:选中那条工具的详情(参数 / 改动 / 输出 / 耗时),窄屏自动收起
199
+ - **顶栏**:会话开始时间、模型(点开可切)、在线状态、上下文用量、自动批准开关
200
+ - **底部**:`轨迹 / 后台任务` 抽屉,收起时只剩一条 tab;后台任务上有运行中的数量
201
+
202
+ 窄屏(≤1180px 收右栏、≤900px 收左栏宽度)都能用,不做手机版——它不是给手机用的。
203
+
204
+ 后端和前端 dev server 都是后台进程(不弹窗、日志吞掉)。它们跟 TUI **同生共死**:退出 TUI(`exit` /
205
+ Ctrl+C 两次 / Ctrl+D / 关窗口)时,这次启动拉起来的会一起收掉,端口当场释放:
206
+
207
+ ```
208
+ 网页端已关闭:后端已结束(PID 2652)
209
+ ```
210
+
211
+ 只收**自己拉的**:如果进 TUI 时端口已经有人(另一个 TUI 起的、或你手动起的),复用它,退出时不动它。
212
+
213
+ **网页上还有一轮在跑时会先等它**(不是干等到底:`[web] stop_wait` 秒,默认 120,Ctrl+C 当场不等):
214
+
215
+ ```
216
+ 网页上还有 1 轮在跑——等它写完再关(最多 120 秒,Ctrl+C 直接关)
217
+ 网页端已关闭:后端已结束(PID 2652)
218
+ ```
219
+
220
+ 不等的话那一轮会被拦腰砍断:工具可能正改文件、trace 停在半截、浏览器里的人在等一个永远不来的回复。
221
+
222
+ 想把网页端留着自己用(关掉终端后在浏览器里继续聊),在配置里关掉这一条:
223
+
224
+ ```toml
225
+ [web]
226
+ stop_on_exit = false # 默认 true
227
+ stop_wait = 120 # 收之前等网页那轮跑完的秒数(0 = 不等)
228
+ ```
229
+
230
+ **TUI 被强杀**(`kill -9` / 任务管理器结束 / 关掉整个终端窗口)时 `finally` 跑不到,进程会变成孤儿。
231
+ 下次启动会自己认领:`~/.agent-harness/web.json` 记着"哪个 TUI 拉起了哪些 pid",那个 TUI 已经没了、
232
+ 端口还占着、`/health` 还答 agent-harness——三条都成立才收,然后印一行
233
+
234
+ ```
235
+ 收掉上次遗留的进程:后端已结束(上次遗留 PID 2652)
236
+ ```
237
+
238
+ 也可以手动收(不需要 API key):
239
+
240
+ ```bash
241
+ uv run linga --stop-web # 结束占用 8000 / 5173 的进程
242
+ ```
243
+
244
+ 后端复用前 TUI 会先问一句 `/health`:如果 8000 上的进程不是当前版本(协议号对不上),启动时就印一行黄字提醒,而不是假装一切正常。
245
+
246
+ ## 已知边界(有意不做的)
247
+
248
+ - **没有 OS 级沙箱**:`run_shell` 靠风险分级 + 人工审批,不是容器隔离。别拿它跑不可信的任务。
249
+ - **审批会超时**:默认 5 分钟没人答复就按驳回处理(`[loop] approval_timeout`,设 0 = 一直等)。
250
+ - **网页端的「停止」只在本步结束后生效**:正在跑的命令 / 子 agent 会跑完,之后不再发起新动作(不硬杀进程)。TUI 用 Ctrl+C。
251
+ - **子 agent 的「只读」靠提示词**,工具是全量的;它不能再派生孙 agent(深度上限 1)。
252
+ - **子 agent 的中间过程不进实时流**,只进 trace。
253
+ - 只接 OpenAI 兼容协议面;DeepSeek 私有参数(`thinking` / `reasoning_effort`)默认不传。
254
+
255
+ ## 审批怎么答
256
+
257
+ 危险动作会停下来问你一句,只认三个键:
258
+
259
+ | 键 | 含义 |
260
+ |---|---|
261
+ | `Enter` | 执行这一次 |
262
+ | `Esc` | 驳回(也可以打 `n` 回车) |
263
+ | `a` + `Enter` | 执行,并且**本次会话不再问这个程序** |
264
+
265
+ 网页端是三个按钮:批准 / 驳回 / 本会话不再问。
266
+
267
+ 记住的范围是"程序名"(`git`、`uv`、`del`),不是整条命令;只存在内存里,**重启就忘**。想让某些命令永远不问,写进配置:
268
+
269
+ ```toml
270
+ [guardrail]
271
+ allow = ["git *", "uv *", "rg *"] # 前缀语义:以这些词开头的命令不再问
272
+ ```
273
+
274
+ `catastrophic` 档(`format` / `mkfs` / `dd` / `rm -rf /`)**不受 allow 影响**——写 `allow = ["*"]` 也放不出来,这是刻意留的地板。
275
+
276
+ ### 自动批准(Shift+Tab)
277
+
278
+ 在提示行按 `Shift+Tab`:底部那条横线整条变黄,写着 `⚡ 自动批准 · Shift+Tab 关闭`。这时所有审批自动通过,屏幕上留一行 `⚡ 自动批准 · 改动文件:rm`,`/trace` 里也有一条 `⚡ 自动批准`。
279
+
280
+ 三条边界:
281
+
282
+ - **`catastrophic` 不受影响**:`format` / `mkfs` / `dd` / `rm -rf /` 仍然直接拒——它由主循环在执行前拦掉,连审批都不会进,自动批准碰不到那条路。
283
+ - **只活在内存里**:重启回到手动,不写配置、不跨会话。
284
+ - **要在提示行按**:运行中屏幕归流式渲染,`Shift+Tab` 到不了输入行;正在等你审批时也不行(那三个键只管这一条命令)。
285
+
286
+ 网页端顶栏有同一个开关(`自动批准` → 开启后变成 `⚡ 自动批准`,整颗变黄),语义与 TUI 的 `Shift+Tab` 完全一致:不弹审批卡、命令照跑、对话里留一行 `自动批准 · 改动文件:rm`、trace 里记一条 `kind: auto`。它也是内存态,关掉页面或重连就回到手动。
287
+
288
+ 底部那条横线还会显示上下文用量:
289
+
290
+ ```
291
+ ────── 上下文 8.4k/70k (12%) · Shift+Tab 自动批准
292
+ ```
293
+
294
+ - 左边是**当前**(系统提示 + 历史的字符当量,和压缩判断用同一个估算函数)
295
+ - 右边是**会触发压缩的阈值**(`[context] compact_threshold`,不是模型的物理窗口)
296
+ - 括号里是占比;超过 70% 转黄、95% 转红——不必等它变成"这一轮怎么这么慢"才发现
297
+
298
+ 网页端把同一个数字放在顶栏(`8.4k/70k (12%)`),算法与 TUI 共用:两边各算一套的话,迟早出现"显示 60% 但已经开始压缩"。
299
+
300
+ ## 命令在哪个 shell 里跑
301
+
302
+ `run_shell` 按这个顺序挑一个,用第一个能用的:
303
+
304
+ | 顺序 | shell | 说明 |
305
+ |---|---|---|
306
+ | 1 | **Git Bash**(`bash -c`) | 首选。引号/管道/`for` 都是标准 bash,模型最熟 |
307
+ | 2 | **PowerShell 7**(`pwsh -Command`) | 没装 Git Bash 时 |
308
+ | 3 | **Windows PowerShell 5** | 再退一步 |
309
+ | 4 | cmd.exe | 前面都没有才用(兜底) |
310
+
311
+ `C:\Windows\System32\bash.exe` 是 **WSL 启动器**,不是 Git Bash,会被跳过(它会把命令扔进 Linux,路径全对不上)。
312
+
313
+ 指定别的 shell:
314
+
315
+ ```bash
316
+ set AGENT_HARNESS_SHELL=D:\Git\bin\bash.exe # Windows cmd
317
+ export AGENT_HARNESS_SHELL=/usr/bin/bash # bash
318
+ ```
319
+
320
+ 横幅里会显示当前用的是哪个(`会话 … · 模型 … · Git Bash`)。
321
+
322
+ ## 后台任务(dev server 这类)
323
+
324
+ 有些命令**没有「跑完」这个状态**——`npm run dev`、`vite --watch`、`uvicorn --reload`。前台跑它们只有两个结局:等 120 秒被杀,或者把会话堵住。
325
+
326
+ 所以 `run_shell` 多了一个 `background` 参数,配套两个工具:
327
+
328
+ ```
329
+ run_shell("npm run dev", background=true) → 已在后台启动 t1(立刻返回,不等)
330
+ task_output("t1") → 状态 + 输出末尾
331
+ task_stop("t1") → 连子进程一起停
332
+ ```
333
+
334
+ 四件事要知道:
335
+
336
+ - **输出写文件**:`~/.agent-harness/tasks/<时间戳>-tN.log`,留 7 天自动清。`task_output` 只读末尾 64KB——日志可以无限长,整读会先把内存吃光。
337
+ - **Ctrl+C 不连坐**:后台任务在独立进程组里,中断当前这一轮不会顺手把 dev server 杀掉;只有 `task_stop` 或退出程序才收(退出时统一杀)。
338
+ - **重启即忘**:任务只活在内存里,和「本会话记住的批准」同一个尺度。
339
+ - **有的程序把输出攒在缓冲区**:迟迟看不到日志时,加 `PYTHONUNBUFFERED=1` 或 `stdbuf -oL` 再起一次。
340
+
341
+ ## 常见坑
342
+
343
+ - **同一台机器上 `find` 有两个**:在 Git Bash 里 `find` 是 GNU 的(找文件),`cmd` 里是 Windows 的(逐行搜文本)。跑命令的是 bash,所以 `find . -name "*.py"` 才对;`find /c /v ""` 那套是 cmd 语法,在这里会把 `*.py` 当路径(2026-10-19 就这么灌出过 91MB 输出)。不确定就 `command -v find` 看一眼。
344
+ - **`write_file` 覆盖整个文件**,改已有文件用 `edit_file`。
345
+ - 项目约定写在 `AGENTS.md`,启动时自动注入 system prompt。
346
+
347
+ ## 目录结构
348
+
349
+ ```
350
+ src/agent_harness/
351
+ __init__.py CLI 主入口(选会话 / REPL / 落盘)
352
+ loop.py 主循环:护栏 → 预钩子 → 执行 → 回灌 → 停机
353
+ guardrail.py 命令风险分级 + 路径围栏
354
+ llm.py OpenAI 兼容流式适配器(含 413 反应式压缩、思考流拆分)
355
+ tools.py 工具实现(读 / 写 / 编辑 / shell / 后台任务 / pytest)+ 结果截断
356
+ shell.py 挑一个 shell(bash → pwsh7 → pwsh5 → cmd)
357
+ tasks.py 后台任务登记簿(id / 进程 / 输出文件)
358
+ schema.py 工具 schema(= 模型看到的菜单)
359
+ compact.py 投影式微压缩
360
+ session.py 会话存档(JSONL)
361
+ trace.py 轨迹记录(给人看的账)
362
+ hooks.py 策略挂载点
363
+ subagent.py 子 agent(上下文隔离)
364
+ settings.py 多 profile 配置
365
+ paths.py 应用目录(~/.agent-harness)
366
+ assembly.py 公共装配 + SwitchableLLM
367
+ tui.py 终端界面
368
+ server.py FastAPI + WebSocket 后端
369
+ weblaunch.py TUI 启动时拉起网页端
370
+ tests/ test_s1 ~ test_s11 + test_tools(155 条)
371
+ web/ React + TS + Vite 前端
372
+ docs/PLAN.md 工程真源(决策记录)
373
+ docs/HANDOFF.md 会话交接单
374
+ ```