Files
chenlin 0d986f60bd
web-platform-ci / Standalone decision service (no cloud credentials) (push) Has been cancelled
web-platform-ci / TypeScript, lint, unit, build (push) Has been cancelled
web-platform-ci / Playwright E2E (push) Has been cancelled
lekiwi-compatibility / cpu-compatibility (push) Has been cancelled
feat: release v1.0.2 LeKiwi 语言控制与网站嵌入
集成服务器托管模型、自然语言移动与有界抓放、内置 LeKiwi URL 导入和双摄像头;同步部署契约与指定域名 iframe 白名单,保留原有物理安全、会话及调用预算防护。

更新 npm 包及锁文件版本、CHANGELOG 与发布文档。提交前 typecheck、120 项定向前端测试和 44 项后端测试通过(3 项可选跳过);真实 v2 云模型抓放仍待单独验收,不包含运行密钥或构建产物。
2026-09-24 15:29:49 +08:00

110 lines
11 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# LeKiwi 本机模型服务
独立于训练、控制桥和 MuJoCo;只接收结构化状态并返回经校验的计划/判定,不执行物理步进或模型给出的代码。默认 `127.0.0.1:8768/api/decision/v1`。
## 网站模式
`python -m decision_server --website-origin https://cadworld-sim.robotquan.com` 启动独立同源网站模式,不打印服务令牌、不自动发现 `.env`。当前生产另显式指定 `--website-key-file /run/secrets/model-keys.env --website-budget-file /var/lib/cadworld/budget.sqlite`,按两项固定变量读取站长授权的 DeepSeek flash/Jev 1.13 密钥;启动不推理。密钥为服务器受保护只读文件,不打包到镜像/静态站点,不发送到浏览器。
每访客任务、取消和限额仍独立,只有固定模型凭据由服务器提供;全站 60 次/小时、600 次/24h 的上游调用预留记录持久化,进程重启/换 Cookie 不重置。共享模式禁用公开配置修改、模型目录、连接测试及订阅接口;本地模式与非共享模式的原连接/官方订阅能力保留,无自动回退。
新增 `/command`:DeepSeek 结构化理解单个动作、Jev 检查意图;距离/角度/字段/方向与单位再由代码检查。只返回受限语义,不返回代码/执行器写入。实际驱动与物理成功在浏览器判断,取消身份覆盖整条双模型请求。见 [网站 API](../docs/website-api.md)、[部署手册](../docs/website-deployment.md) 和 [当前实测](../docs/website-hosted-control-2026-09-24.md)。
## 语言控制面板:本地推荐启动方式
本地与网站统一为“机器人语言控制”,界面不再填写 token/密钥或配置模型。使用现有同源会话模式,密钥文件由操作者准备,包含 `DEEPSEEK_API_KEY` 与 `OPENROUTER_API_KEY`,不进入前端:
```bash
source .venv/bin/activate
python -m decision_server --website-origin http://127.0.0.1:5173 --website-dev \
--website-key-file /absolute/path/model-keys.env \
--website-budget-file "$HOME/.local/state/mujoco-decision/language-budget.sqlite"
# 另一终端;浏览器必须使用与 website-origin 完全一致的地址
npm run dev -- --host 127.0.0.1
```
Vite 本地/网站模式均代理 `/api/decision/v1`。换端口时同步修改 `--website-origin`;代理目标默认 `127.0.0.1:8768`,可用服务器环境变量 `CADWORLD_DEV_API` 修改。没有可用模型服务会报错,不自动转 mock。旧 Bearer 服务仍供程序化客户端使用,不能直接替代此面板的同源服务。
## 旧 Bearer 客户端启动(非新版面板)
```bash
source .venv/bin/activate
# 当前环境已有 aiohttp 3.14.3,无需升级 MuJoCo/训练依赖。
# 新环境可单独安装:python -m pip install -r decision_server/requirements.txt
npm run decision-server
```
控制台打印本进程专用服务令牌。旧程序化客户端需要 Bearer 令牌;它不是模型 API Key。默认仅允许工作台 `localhost/127.0.0.1:5173/4173`,其他本机测试端口通过 `--origin http://127.0.0.1:4176` 显式允许。
用户已批准本项目使用 `.env` 中的两项凭据。按需显式启用:
```bash
npm run decision-server -- --openrouter-env .env --deepseek-env .env
```
- OpenRouter:只读取 `OPENROUTER_API_KEY`,仅配置 Jev `typesafe/jev-1.13` / `https://openrouter.ai/api/alpha/decisions`。
- DeepSeek:只读取 `Deepseek_API_KEY` / `DEEPSEEK_API_KEY`,配置用户再次确认的 `deepseek-flash` / `https://api.deepseek.com`,使用 Responses 协议。
- 加载器不 source/eval、不展开环境变量、不读取其他变量值作为配置、不接受文件中的 URL/model,不自动发请求。重复目标变量、坏格式或缺密钥明确报错。没有指定参数时不自动扫描 `.env`。
- 密钥仅服务内存;无 dotenv/云 SDK/系统钥匙串隐式回退。文件本身由用户管理,服务不会改写;`.gitignore` 已排除 `.env`。普通连接也可通过受保护 HTTP 接口配置,不在浏览器持久化。
默认非秘密连接元数据在仓库外 `~/.local/state/mujoco-decision/connections.json`(0600)。重启后普通连接需要重新提供密钥;换地址必须重新提供密钥,不携旧密钥跨域。远端只允许 HTTPS,HTTP 仅字面回环地址/localhost;不跟随重定向、不继承代理环境配置。
## 协议与限制
| 路由 | 方法 | 内容 |
| ------------------------------------------------- | ---- | ----------------------------------------------------------- |
| `/status` | GET | 版本、非秘密配置、调用摘要;没有 prompt、响应原文或账号地址 |
| `/connections` | PUT | `role,protocol,baseUrl,model,apiKey`;role 为 llm/jev |
| `/test` | POST | `{role}`,显式连接测试;API 会计费,Codex 只做离线能力门禁 |
| `/plan` | POST | `{observation,instruction,remaining}` |
| `/decide` | POST | `{observation,candidates,failure?}` |
| `/cancel` | POST | `{runId,requestId}` |
| `/codex/status`, `/codex/models`, `/codex/limits` | GET | 官方账号状态、模型目录、原始数值额度窗口 |
| `/codex/login`, `/codex/cancel`, `/codex/logout` | POST | 空对象;官方登录 URL 仅此响应交给浏览器,不能保存/日志导出 |
所有路由均有精确 Host、Origin、Bearer 校验;没有任意 URL/RPC 转发、文件读取或 shell 接口。请求体上限 64 KiB,响应上限 256 KiB;上游 HTTP 45 秒,服务推理 60 秒,必要的进程中断/回收有独立短期限。每服务同一时刻仅一个推理/连接测试;取消、配置变更和断连令旧请求无效。
每回合最多 3 次 LLM(初始 + 2 次重规划)、60 次 Jev,最多 20 分钟墙钟;同一服务最多 120 次/小时,最多保留 32 个回合预算记录。失败/取消也计数,重复/过期 requestId 不可重新执行。没有网络自动重试、静默模型替换或规则降级。连接测试使用独立预算桶,也计全局预算。
LLM 显式选择 `responses` 或 `chat-completions`。两者都要求结构化 JSON;不兼容时明确报错,不悄悄降级。Jev 显式选择 `typesafe` 或 `openrouter-decisions`,两者均是 `state/questions/answers`,不是聊天接口。保留服务选择,不根据概率私自重排。只返回经过验证的计划/判定及数值 usage;OpenRouter 返回的 cost 是服务报告值,不是硬编码估价。DeepSeek 未返回费用时仅显示 token,不能伪造金额。
## 官方 Codex:实验性、逐模型门禁
仅支持已验证的 **codex-cli 0.147.0**;不自动安装/升级,不使用私有 ChatGPT 接口,不把订阅凭据传给 API Base URL。
- 每进程在仓库外创建独立临时 HOME/CODEX_HOME/cwd,关闭项目指令、shell、code mode、插件、apps、hooks 等;拒绝继承的 MCP/hooks/notify 执行配置。仅会话 OAuth,退出进程即丢失,不读取用户全局登录。
- 随代码附带匹配版本的模型目录,仅缩减工具能力和替换提示词,保留模型标识/可见性/账号范围。来源和许可见 `THIRD_PARTY_NOTICES.md`。隐藏/退役的 gpt-5.4 不是当前默认或通关替身。
- 每个选定模型首次使用前运行原生 CLI 离线门禁:仅连接私有回环假 Responses 服务,验证不暴露工具;强行注入 apply_patch、shell_command、exec_command、view_image 必须分别返回 unsupported,并验证未写文件。失败、超时或版本不符立即拒绝规划。
- 通过 `account/login/start(type=chatgpt)` 登录、`account/read` 确认、`model/list` 选择;模型目录不是实际账号权限/额度的承诺,上游仍可拒绝。真实调用必须已登录且逐模型门禁通过。
- `thread/start(ephemeral)` + `turn/start(outputSchema)`;只接受当前 thread/turn 的最终合法计划,工具输出/未知项拒绝。取消走精确 `turn/interrupt`;失败则终止进程,结束后 unsubscribe,释放线程资源。
- `account/rateLimits/read` 只展示官方数值窗口;不推算订阅美元费用。额度不足、登录失效、型号/请求被拒绝均明确错误,不切换付费 API。
本机 5 个可见模型的离线门禁、真实 stdio 假推理的结构化计划与 unsubscribe 已通过。**未完成真实 ChatGPT 登录/订阅推理验收**;需要用户浏览器交互。
## 测试与已知验证范围
```bash
source .venv/bin/activate
npm run test:decision-server
# 额外:本机固定版本 CLI,无账号登录/远端推理
DECISION_CODEX_SMOKE=1 npm run test:decision-server
```
常规 CI 仅本地假服务和 mock,不需要凭据/CLI/GPU/机器人资产;原生 Codex 用例显式启用。共享 `contracts/lekiwi-agent-v1.schema.json` 的 Python/TS 有限子集校验均拒绝额外字段、非有限数、非法对象/技能和跳前置条件计划。
真实单请求证据(输入为**合成契约夹具**,不是实时物理采样,也不是完整抓放闭环):
- `build/lekiwi-agent/openrouter-jev-smoke.json`:Jev 初始状态判定通过,服务报告 $0.00004263。
- `build/lekiwi-agent/deepseek-plan-smoke.json`:最初指定的 `deepseek-v4.1-flash` 未出现在官方模型列表,没有发起该型号推理。
- 经用户确认改为 `deepseek-flash` 后,`build/lekiwi-agent/deepseek-flash-plan-smoke.json`:11 阶段规划及所有前置条件通过;836 输入 / 1608 输出 token,没有费用字段。
- Codex 最初门禁把省略的 tools 当作失败,保留 `current-model-first-gate.json`;修正为允许“省略或空数组”(不接受非空工具)后,5 个可见模型及 4 类注入全部通过,见 `build/lekiwi-agent/codex-capability/`。省略 tools 的 API 语义是不提供工具,不是忽略已有工具。
后续主工作台已完成两次真实 DeepSeek `deepseek-flash` + OpenRouter Jev 物理回合;最新为 1 次规划、11 次判定、实际持物搬运 0.593727 m,详见 [任务验收](../docs/lekiwi-agent.md)。证据保存在 `build/e2e/lekiwi-agent-final-gates/`。未保存的配置草稿会禁用任务/测试,避免仍调用旧付费配置。真实 ChatGPT 隔离登录已确认,订阅推理未运行;用户已接受以 DeepSeek + Jev 回合完成本次验收。临时登录会话已关闭,不能把登录/离线门禁当成订阅推理资格证明。
Sources:
- [OpenRouter Decisions 官方协议](https://openrouter.ai/docs/api/api-reference/alphadecisions/submit-a-decisions-questions-and-answers-request)
- [DeepSeek Responses 兼容说明](https://api-docs.deepseek.com/guides/responses_api)
- [Codex App Server](https://developers.openai.com/codex/app-server)
- [Codex 0.147.0 配置 schema](https://raw.githubusercontent.com/openai/codex/rust-v0.147.0/codex-rs/core/config.schema.json)