feat: 优化运行时判定

This commit is contained in:
richarjiang
2026-09-24 14:27:07 +08:00
parent dfd3998399
commit f0ac603f27
25 changed files with 2368 additions and 58 deletions

View File

@@ -85,8 +85,14 @@ laya-router start
| `port` | 默认 `8765`。 |
| `device` | `auto`、`mps`、`cuda` 或 `cpu`。`auto` 预热失败会回退。 |
| `log_prompts` | 是否把原文写入 `data/routes.jsonl`。 |
| `request_timeout` | Hook 等待服务的秒数,默认 `2.5`。 |
| `request_timeout` | 用户 prompt 的 hook 等待秒数,默认 `2.5`。 |
| `event_timeout` | 工具 hook 的等待秒数,默认 `1.0`。 |
| `max_prompt_chars` | 送进模型的最大字符数。超长时保留头尾。 |
| `trajectory` | 工具调用之后,以及改未读过的文件之前,注入一句短提示。 |
| `gate` | 收紧有风险的 Bash 和编辑。不会返回 allow。 |
| `stop_check` | 改完代码却没验证时,不让这一轮停下来。 |
| `skills` | 每条用户 prompt 最多推荐一个已安装的 skill。 |
| `skill_inject` | `suggest` 只给名字和路径。`content` 在同一会话里附上一次 `SKILL.md` 正文。 |
改完配置或服务端代码后执行 `laya-router restart`。
@@ -103,6 +109,20 @@ laya-router start
服务挂了时,hook 输出 `{}` 并退出 0,Codex 和 Claude Code 照常工作。原因写在 `~/.laya-router/logs/hook.log`。
## 运行过程中
同一条 hook 命令也监听 `PreToolUse`、`PostToolUse` 和 `Stop`。会话轨迹放在常驻服务的内存里。
- `PreToolUse` 遇到 Bash 或编辑:风险高就拒绝;风险中等时,Claude Code 会询问,Codex 只注入警告,因为 Codex 不接受 `permissionDecision: ask`。要改一个还没读过的文件时,会提示先读。
- `PostToolUse`:每次 Bash 或编辑都会注入一句短提示。连续两条完全相同的提示会去掉。连续失败两次,或者 `is_stuck` 很高,就要求先停下来重新规划。`Read`、`Grep`、`Glob` 只记账,不插话。
- `Stop`:代码改过、之后没有跑测试或构建时,hook 最多拦一次,让 agent 继续做验证。`stop_hook_active` 一律放行,避免死循环。
`UserPromptSubmit` 上还会再做一轮 skill 推荐,最多一个。名单来自 `~/.claude/skills`、`~/.codex/skills`、`~/.agents/skills`、项目里的 skill 目录,以及 Claude 插件的安装路径。frontmatter 里 `disable-model-invocation: true` 的 skill 会跳过。第一问给全部候选排序,并用三个是否题决定这条 prompt 是否需要 skill。第二问只重读前三名。任一阈值低于 0.30 就不推荐。
`laya-mcp` 用 stdio 提供 `laya_judge`。想让模型自己调用,在 Claude Code 里允许 `mcp__laya`。安装时如果 `PATH` 上有对应命令,会执行 `claude mcp add` 和 `codex mcp add`。
升级之后,Codex 要再跑一次 `/hooks`,信任新加的 hook。
## 开发
```bash
@@ -115,7 +135,7 @@ PYTHONPATH=src uv run --no-project --with pytest python -m pytest
| --- | --- | --- |
| `src/laya_router/questions.py` | 问题措辞。改措辞时把 `QUESTIONS_VERSION` 加一。 | `laya-router restart` |
| `src/laya_router/render.py` | 注入给 Agent 的文本 | `laya-router restart`,然后下一条 prompt |
| `src/laya_router/hook.py` | 超时、跳过斜杠命令、失败放行 | `laya-router restart`,然后下一条 prompt |
| `src/laya_router/hook.py` | 用户 prompt 和工具事件、超时、失败放行 | `laya-router restart`,然后下一条 prompt |
| `src/laya_router/server.py` | 加载模型、`/route`、看板 | `laya-router restart` |
| `src/laya_router/dashboard.html` | 浏览器页面 | `laya-router restart` |
@@ -129,7 +149,7 @@ PYTHONPATH=src uv run --no-project --with pytest python -m pytest
`routes.jsonl` 默认保存完整 prompt,包括你贴进 Codex 或 Claude Code 的内容。`log_prompts = false` 时只保存 SHA-256。运行目录是仓库外面的 `~/.laya-router/`,不要把它提交进 git。
安装程序会改写 `~/.codex/hooks.json`,并往 `~/.claude/settings.json` 合并一条 `UserPromptSubmit`。Claude 的这个文件里常常有 API 凭证。程序会保留原有字段,改文件前写一份带时间戳的 `*.bak-*`,卸载时只删自己的 hook。公开任何本机配置之前先看 diff。
安装程序会改写 `~/.codex/hooks.json`,并往 `~/.claude/settings.json` 合并 `UserPromptSubmit`、`PreToolUse`、`PostToolUse` 和 `Stop`。Claude 的这个文件里常常有 API 凭证。程序会保留原有字段,改文件前写一份带时间戳的 `*.bak-*`,卸载时只删自己的 hook。公开任何本机配置之前先看 diff。
其他网站的页面读不到这些接口:服务没有发送 `Access-Control-Allow-Origin`。监听地址仍然应该保持默认。