From 904f5f8a6c7fe4605f8fc4308a7c44993643b334 Mon Sep 17 00:00:00 2001 From: Miayui <774713819@qq.com> Date: Fri, 18 Sep 2026 14:48:07 +0800 Subject: [PATCH] docs: streamline project README --- README.md | 447 ++++++++++++++++++++++++++---------------------------- 1 file changed, 219 insertions(+), 228 deletions(-) diff --git a/README.md b/README.md index 503be41..e6a7959 100755 --- a/README.md +++ b/README.md @@ -1,296 +1,287 @@ # Cognitive Agent -面向车载执行器的认知编排 Agent 单仓工程。系统把自然语言请求转换为可校验的语义配置,再由确定性的领域插件编译为 CAN 命令计划,最后经安全策略和执行器下发。 +面向车载执行器的认知编排单仓工程。系统把自然语言或结构化请求转换为可校验的语义配置,由领域插件确定性编译为 `CommandPlan`,经过平台安全门禁后以 dry-run、模拟台架或真实 CAN 方式执行,并保存可审计结果。 -Web 控制台与同源 API 由同一个 Python 服务提供。本地启动: +当前仓库以腾势 N7 / T2G 座舱演示和硬件台架为主。默认环境不会打开真实硬件;气候、天幕和氛围灯领域的矩阵目前也只允许虚拟执行。 -```bash -.\.venv\Scripts\python.exe .\tools\start_n7web.py -``` +## 能做什么 -启动脚本会先安装缺失的前端依赖并执行 Vue 3 + Vite 生产构建,然后启动 `8000` 主服务和独立的 `8090` 只读模式卡服务。已经有可复用的 `apps/web-console/dist` 时,可使用 `--skip-web-build` 跳过本次构建。 +- 同源 Python HTTP 服务与 Vue 3 + Vite Web 控制台。 +- 能力目录驱动的自然语言编排、模式卡片、跨域场景和 NDJSON 助手流。 +- `IntentIR`、`FunctionConfig`、`SceneConfig`、`CommandPlan`、`TraceEvent` 和 `ExecutionReport` 公共契约。 +- 座椅、空调、天幕、氛围灯四个领域插件,以及平台侧门窗、插座、阅读灯等原生 CAN 能力。 +- 虚拟 CAN、模拟硬件、T2G ZLG CAN 台架和双通道车身 CAN 接入。 +- 语音输入、MediaPipe 手势、NFC/红外外设、模式目录同步和只读固件 OTA 服务。 -### Vue 3 + Vite 前端 +AI 模型只能提出受契约约束的语义计划,不能生成或发送原始 CAN 帧。真实执行仍由服务端的能力白名单、参数 Schema、硬件授权、安全策略、互斥和反馈检查共同决定。 -前端根应用位于 `apps/web-console/src/App.vue`,入口为 `src/main.js`。Vue 和 Vite 均由 npm 锁定版本管理,浏览器不再依赖 CDN 或全局 `window.Vue`。现有 MQTT、NFC、语音、模式卡和车辆控制脚本作为兼容运行层继续使用原 DOM 契约,由 Vue 根应用承载页面结构。 - -单独进行前端开发时,先保持 Python 主服务运行,再启动 Vite: - -```powershell -cd .\apps\web-console -npm ci -npm run dev -``` - -开发页面为 `http://127.0.0.1:5173/`,`/api` 与 `/artifacts` 会代理到 `http://127.0.0.1:8000`。生成生产静态资源: - -```powershell -cd .\apps\web-console -npm run build -``` - -构建输出位于 `apps/web-console/dist`;Python 主服务检测到该目录后会优先提供生产构建。上述流程不会改变主页的 `8000` 端口,也不会改变模式卡服务的 `8090` 端口。 - -Windows PowerShell 未安装 `make` 时可直接运行: - -```powershell -$env:PYTHONPATH = "src;domains/seat/src" -python -m cognitive_agent.server -``` - -## 建设阶段 - -- 阶段一:每个领域独立完成能力定义、功能配置生成、配置校验、CAN 编译和单执行器测试。 -- 阶段二:由中央编排器生成 `SceneConfig`,引用多份 `FunctionConfig`,按依赖关系、时间偏移和失败策略组合执行。 -- 最终形态:Web 控制台接收一句话请求,展示结构化决策摘要、配置文件、校验结果和执行状态。 - -## 核心约束 - -1. LLM 只能生成 `IntentIR`、`FunctionConfig` 或 `SceneConfig`,不能直接生成或发送原始 CAN 帧。 -2. `FunctionConfig` 只允许包含一个 `domain`;跨域需求必须使用 `SceneConfig` 引用多份领域配置。 -3. CAN 编译必须是确定性的:相同配置、相同平台标定和相同插件版本必须生成相同 `CommandPlan`。 -4. DBC、通道定义和安全标定由集成人员在 `platforms/` 统一维护;领域成员只维护语义信号映射。 -5. 所有真实执行必须经过公共 Schema 校验、领域校验、安全策略、dry-run 和审计记录。 -6. UI 展示可审计的决策摘要和阶段事件,不展示模型私有思维链。 - -## 目录 +## 处理链路 ```text -. -├── apps/ # API 服务、Web 控制台和内置手势模型资源 -├── artifacts/ # 每次请求的生成物和执行记录(不入库) -├── config/ # 全局环境和策略配置 -├── contracts/ # 冻结的公共 Schema、示例和版本规则 -├── deploy/ # 容器及部署资源 -├── docs/ # 架构、流程、治理和 ADR -├── firmware/t2g/ # 仓库内统一座椅 IAR 工程与可烧录产物 -├── domains/ # 可独立开发、测试、交付的领域插件 -│ ├── _template/ # 新领域模板 -│ ├── seat/ # 座椅 -│ ├── climate/ # 空调 -│ ├── ambient_light/ # 氛围灯 -│ └── roof/ # 天幕/遮阳帘/调光玻璃 -├── platforms/ # 车型、DBC、总线和安全标定 -├── src/cognitive_agent/ # 中央 Agent、编排器、运行时和基础设施 -├── tests/ # 跨域契约、集成和端到端测试 -└── tools/ # 脚手架、校验和开发工具 -``` - -完整依赖关系和处理链路见 [总体架构](docs/architecture/overview.md),成员交付步骤见 [领域交付流程](docs/workflows/domain-delivery.md),修改边界见 [所有权规则](docs/governance/ownership.md)。 -整体排期和阶段准入条件见 [集成路线](docs/workflows/integration-roadmap.md)。 - - -## 配置处理链路 - -```text -用户文本 - -> GPT + Capability Registry + 当前会话状态 - -> 通用能力请求(领域、能力、作用域、操作和参数) - -> IntentIR(意图抽取、领域识别、歧义与置信度) - -> 单领域:FunctionConfig - -> 多领域:SceneConfig + N 个 FunctionConfig - -> 公共 Schema 校验 + 领域语义校验 +用户请求 + -> 能力目录 / 会话状态 / Codex 或本地解析 + -> IntentIR + -> FunctionConfig(单领域)或 SceneConfig(跨领域) + -> 公共 Schema + 领域语义校验 -> 领域 Compiler -> CommandPlan - -> 平台安全校验 -> 调度 -> CAN Gateway - -> 回读/超时/结果 -> TraceEvent + ExecutionReport + -> 平台安全校验 -> dry-run / simulated_hardware / physical CAN + -> 回读、超时和审计 -> TraceEvent + ExecutionReport ``` -运行时产物统一保存在: +运行时产物位于 `artifacts/runs//`,典型结构如下: ```text -artifacts/runs// -├── intent.yaml -├── scene.yaml # 仅跨域请求存在 -├── functions/.yaml -├── command-plans/.yaml -├── trace.jsonl -└── execution-report.yaml +intent.yaml +scene.yaml # 跨域请求才有 +functions/.yaml +command-plans/.yaml +trace.jsonl +execution-report.yaml ``` -`artifacts/` 中禁止写入 API Key、完整隐私文本或未脱敏的车辆标识。 +不要在 `artifacts/` 写入 API Key、完整隐私文本或未脱敏车辆标识。 -## 可执行领域 +## 当前能力边界 -座椅与空调等车身设备使用同一 ZLG CAN 盒双通道联动时,参见 [T2G 座椅与车身双通道 CAN 联动](docs/workflows/t2g-cabin-dual-channel-can.md)。 +| 能力面 | 当前状态 | 事实来源 | +| --- | --- | --- | +| `seat` | 虚拟矩阵闭环;T2G 台架使用独立硬件映射和校准 | [`domains/seat/`](domains/seat/)、[台架流程](docs/workflows/t2g-seat-hardware-bench.md) | +| `climate` | dry-run;支持分区温度、电源、风量、A/C、循环、风向和前除霜 | [`domains/climate/`](domains/climate/) | +| `roof` | dry-run;支持透光率、后遮阳帘位置和自动调光 | [`domains/roof/`](domains/roof/) | +| `ambient_light` | dry-run;支持开关、RGB、亮度和矩阵场景模式 | [`domains/ambient_light/`](domains/ambient_light/) | +| 原生车身 CAN | 按平台和运行时能力目录启用,不等同于领域插件 | [`config/native_can_capabilities/`](config/native_can_capabilities/)、[`platforms/`](platforms/) | +| 模式卡片 | `config/scene_templates/` 提供内置模板;用户模式持久化到 `artifacts/mode-profiles/` | [模式时间轴](docs/mode-schedules.md) | -当前已接入四个相互隔离的可执行领域: +`platforms/reference_vehicle` 的 `execution_enabled` 为 `false`。`platforms/t2g_seat_bench` 和 `platforms/t2g_cabin_bench` 才是仓库内允许配置真实执行的台架平台,但仍需硬件开关、授权令牌、总线配置和反馈校验全部满足。 -- 座椅:所有热管理、位置移动和姿态预设能力仅面向副驾;未指定座位时默认副驾,显式主驾请求拒绝执行。 -- 空调:基于 `空调-天幕-氛围灯CAN信号矩阵表.xlsx` 的电源、18–32℃ 分区温度、0–7 档风量、A/C、内外循环、风向和前除霜。 -- 天幕:基于同一矩阵的 0–100% 透光率、后遮阳帘绝对位置和自动调光。 -- 氛围灯:基于同一矩阵的总开关、24-bit RGB、0–100% 亮度和 ECU 场景模式。 +## 快速开始 -一句话只涉及一个领域时直接生成一份 `FunctionConfig`;涉及多个领域时生成一份 `SceneConfig` 引用各领域独立的 `FunctionConfig`,并由各自编译器产生 `CommandPlan`。三份新增矩阵仍缺少车型适用性、完整计数器、校验和和发送周期,因此与座椅演示一样只允许虚拟执行。 +### 环境要求 -```bash -make validate -make test -make dev -``` +- Python 3.11 或更高版本。 +- Node.js 与 npm(构建 Web 控制台)。 +- Codex CLI `0.150.0-alpha.8`,用于内置 AI 助手。 +- 真实台架另需 ZLG 驱动/桥接程序、对应 DBC、IAR 工具链和硬件授权。 -浏览器访问 `http://127.0.0.1:8000`。设置 `OPENAI_API_KEY` 后,GPT Structured Outputs 会基于各领域的 `config/capabilities.yaml` 和当前会话状态直接生成通用能力请求;后端只做结构校验、领域路由和确定性执行适配,不用本地语义规则改写 GPT 动作。本地解析器用于未配置 GPT,或 GPT/`auto` 模式因 API Key、模型权限、网络或结构化响应异常而失败时的安全降级;结果会明确标记 `local_rules_fallback`。模型由 `OPENAI_MODEL=gpt-5.6-sol` 指定;兼容 OpenAI Responses API 的服务可通过 `OPENAI_BASE_URL` 指定。无论使用哪种解析器,配置校验、CAN 编译和虚拟执行均为同一确定性路径。 +### 安装(PowerShell) -### Codex AI 助手 +```powershell +py -3.11 -m venv .venv +.\.venv\Scripts\python.exe -m pip install --upgrade pip +.\.venv\Scripts\python.exe -m pip install -e ".[test,dev,api,can,llm,ir]" -首页 AI 助手以长驻 `codex app-server --stdio` 为会话与推理核心。浏览器仍只连接同源 `/api/assistant/stream`,不会接触 Codex 协议或凭据;后端把 App Server 的 thread、turn 和 item 事件转换为 NDJSON 流。普通问题由 Codex 直接回答。涉及本工程能力时,`/api/assistant/capabilities`、回合上下文和只读 MCP 工具 `n7_vehicle.get_n7web_capabilities` 都从同一个运行时能力注册表生成,座舱模式、NFC 绑定红外外设及 CAN0/CAN1 执行绑定会随实际状态更新,不允许模型凭常识猜测。常见能力询问直接由本地权威目录回答,无需等待模型生成。 +cd apps\web-console +npm ci +npm run build +cd ..\.. -显式及复杂车辆需求通过唯一放行的 `n7_vehicle.execute_cockpit_request` MCP 工具进入工程。服务端把一次性工具令牌绑定到本回合原始指令;Codex 可以为原子设备控制提交结构化语义计划,但不能提交新的自然语言指令或原始 CAN。计划必须通过原文证据、能力白名单、目标和参数契约校验,本地确定性解析结果优先,之后仍进入既有 Schema、硬件授权、安全预检、互斥和 CAN 执行链。模型不能扩展用户未请求的控制,也不能覆盖执行模式和硬件授权。 - -“车上有点热”“车里有点冷”等与受限模式完整匹配、且不包含否定或知识问法的高置信度舒适请求,使用 N7Web 内部快速路由:分别归一化为空调开启、全车 23℃/26℃、2 档风量等确定性指令,绕过模型和 MCP 往返以尽快给出进度与结果。该快速路由只缩短意图理解路径,不绕过能力注册、Schema、执行模式、硬件授权、安全预检、互斥、CAN 编译或反馈确认;其他隐式、复合或含糊请求仍交给 Codex 判断,并受上述 MCP 边界约束。 - -能力目录中的 `service_surfaces` 仅用于显示语音输入、手势输入、NFC 绑定、座椅自标定和自修复等服务的运行状态,条目固定标记为 `assistant_access=informational`。这里的 `available=true` 只表示对应服务面可用,不表示 AI 助手可以调用它;可执行边界以 `capabilities`、`modes`、`learned_peripherals` 中的 `assistant_callable` 以及服务端再次校验结果为准。 - -本地运行前需要安装并登录固定兼容版本的 Codex CLI: - -```bash npm install --global @openai/codex@0.150.0-alpha.8 codex login status -make dev ``` -也可以让 Codex 使用进程环境中的 `OPENAI_API_KEY`。未配置自定义地址时,N7Web 会在 App Server 没有缓存账户的情况下通过 API-key 登录;配置非官方 `OPENAI_BASE_URL` 时,会自动为线程注入完整的 OpenAI-compatible provider,使 Codex 确实请求该地址,而不是回落到 `api.openai.com`。助手默认选择低推理强度的 `gpt-5.6-luna`,可用 `CODEX_ASSISTANT_MODEL` 覆盖;`CODEX_ASSISTANT_REASONING_EFFORT` 默认为 `low`,`CODEX_ASSISTANT_TURN_TIMEOUT_SECONDS` 默认为 300 秒,`CODEX_ASSISTANT_WORKSPACE` 用来指定隔离的只读工作目录。当前工程的常用场景登记在 `config/scene_templates`:明确名称会直接做严格别名匹配;“适合/用于/用来……的功能模式”等用途描述会先通过受限语法提炼为简洁模式名,再做同样的严格匹配,不使用子串或相似度猜测。命中且没有同名已保存模式时,模板会在本地复制为新的待保存草稿,不调用 Codex,也不会修改内置模板;草稿仍会经过实时能力契约、完整性、CAN 编译和 dry-run 校验。未命中的长尾名称继续进入独立的单轮结构化 Scene Composer;该路径默认超时 45 秒,已验证的候选计划在当前进程内按车型和能力契约版本缓存 3600 秒,同场景跨用户并发请求会合并,但每个请求仍会独立经过实时安全校验。可分别通过 `CODEX_ASSISTANT_SCENE_TIMEOUT_SECONDS`、`CODEX_ASSISTANT_SCENE_CACHE_TTL_SECONDS`、`CODEX_ASSISTANT_SCENE_CACHE_MAX_ENTRIES` 和 `CODEX_ASSISTANT_SCENE_MAX_CONCURRENT_PLANS` 调整超时、缓存和并行规划上限(默认 8)。为避免兼容服务的 WebSocket 断流造成长时间重试,自定义 provider 默认关闭 WebSocket,并把模型流重试限制为一次;可通过 `CODEX_ASSISTANT_DISABLE_WEBSOCKETS` 和 `CODEX_ASSISTANT_STREAM_MAX_RETRIES` 调整。 +语音识别是可选安装项: -启动采用失败关闭语义:CLI 缺失、App Server 握手失败、模型认证配置缺失/登录失败,或有效 MCP 配置未能收敛并验证为仅启用 `n7_vehicle` 时,`cognitive_agent.server` 会直接启动失败,不会继续提供一个看似可用的降级网页。进程启动后若 App Server 退出,`/api/health` 返回 `503`,`/api/assistant/status` 显示不可用;凭据被服务端撤销、模型权限、网络或生成失败等只有真实模型请求才能发现的问题,则由当前问答流返回 `assistant_model_failed`。这些情况都不会静默回退到旧的正则问答路由;本地能力快答和冷热快速控制仍只按各自严格的确定性条件工作。 - -App Server 的协议与审批字段以 [Codex App Server 官方文档](https://learn.chatgpt.com/docs/app-server) 和 [Codex 配置参考](https://learn.chatgpt.com/zh-Hans/docs/config-file/config-reference) 为准。线程级 `approvalPolicy=never` 与 MCP 工具级 `default_tools_approval_mode=approve` 作用于不同边界:前者禁止命令/文件修改请求进入交互审批,后者仅避免受限的 N7Web MCP 工具产生前端无法处理的第二次审批;真实执行授权仍完全由 N7Web 的一次性令牌、原文绑定和车辆安全链决定。 - -### AI 助手语音输入、快捷模式与手势控制 - -首页左侧的 Codex AI 助手接受普通问题、工程工作和车辆控制需求;Enter 发送,Shift+Enter 换行。观影、午休和零重力是可直接调用的快捷模式,“保存当前”可把当前副驾驶姿态保存为命名模式。能力快答和高置信度舒适请求走确定性快速链,其他请求由 Codex App Server 理解后再通过工程能力与安全边界执行。 - -语音入口分为两种明确模式:用户点击输入框右侧的麦克风按钮时,以 `manual` 模式立即开始本地中文录音,不要求也不剥离唤醒词;浏览器已获得麦克风权限、AI 助手处于展开状态且页面可见时,则自动进入低干扰的 `wake` 待机,只在识别到“你好,小迪”后展示并继续接收问题。首次使用仍需通过一次手动点击完成浏览器麦克风授权。前端优先选择 `TAKSTAR V2`,使用 `AudioWorklet` 在音频线程采集(旧浏览器才降级到 `ScriptProcessor`),并通过 `X-Speech-Input-Mode: manual|wake` 将两条链路显式隔离。 - -累积音频按节流窗口发送到同源 `/api/speech/preview`:手动模式直接把未语义清洗的实时转录显示在输入框,唤醒模式在命中前不改动输入框、命中后只显示唤醒词之后的内容,partial 阶段均不会提交或执行。浏览器检测到静音端点后立即停止音轨,再把 16 kHz PCM WAV 发送到 `/api/speech/transcribe` 生成权威 final。服务端使用 Silero VAD 保留句首/句尾保护区,SenseVoiceSmall 负责声学识别,统一 `TranscriptAssembler` 负责 final commit、顺序、重复回调和保守的相邻重叠消除。 - -最终响应把不同信任层明确拆开:`captured_text` 保留完整声学识别结果;`raw_text` 在 `manual` 模式保留完整原文,在 `wake` 模式仅剥离已确认的唤醒词;`assistant_text` 在保留普通问答的前提下处理重复、结巴、false start、修正、撤销、否定、多设备、多数字和小数,供 AI 助手输入框使用;`clean_text/control_text`、结构化 `commands`、`cancelled_fragments` 和 `execution_eligible` 继续作为严格车控旁路。未知能力或非车控内容不会被清空,也不会绕过 Codex 助手直接执行。听写本身不自动发送消息、不自动执行控制,也不保存录音。首次部署: - -```bash -python -m pip install -e ".[speech]" -python tools/install_sensevoice_model.py +```powershell +.\.venv\Scripts\python.exe -m pip install -e ".[speech]" +.\.venv\Scripts\python.exe tools\install_sensevoice_model.py ``` -安装脚本同时校验并部署 `artifacts/models/silero-vad/silero_vad.onnx`。默认使用完整精度 SenseVoice、`language=zh`、ITN 和最多 8 个 CPU 线程;VAD 针对短会话使用阈值 `0.45`、最短语音 `0.16s`、结束静音 `0.65s`、最长分段 `12s`、前置 `0.25s`、后置 `0.35s`。可通过 `SPEECH_MODEL_*`、`SPEECH_LANGUAGE`、`SPEECH_USE_ITN`、`SPEECH_NUM_THREADS`、`SPEECH_PROVIDER` 与 `SPEECH_VAD_*` 覆盖;`SPEECH_WAKE_WORD_ENABLED` 控制唤醒门,`SPEECH_WAKE_WORDS` 使用 `|` 分隔主唤醒词和别名。 +配置模型认证时使用 `OPENAI_API_KEY`,或让 Codex CLI 使用已登录账户。`.env` 和 `.env.auth` 已被 Git 忽略;可参照 [`config/environments/`](config/environments/) 中的示例配置。不要把密钥提交到仓库。 -当前 sherpa-onnx 版本支持 SenseVoice 的 `hr_lexicon`/`hr_rule_fsts`,只有同时提供经过验证的文件时才会启用:`SPEECH_HR_LEXICON` 和 `SPEECH_HR_RULE_FSTS`。未对非 transducer 的 SenseVoice 使用 hotword decoding。可插拔 `RecoveryRecognizer` 默认关闭,只为将来让 uncertain case 使用二次识别,不会下载大型模型。 +### 启动完整本地演示 -诊断时设置 `SPEECH_DEBUG=1` 输出按 `utteranceId`、segment 边界、raw final、拼接前后、理解结果、Intent 与阶段耗时组织的 JSON 日志;只有额外设置 `SPEECH_DEBUG_RESPONSE=1` 才把 trace 返回浏览器。前端访问参数 `?speechDebug=1`(或 localStorage 同名值)启用控制台日志,生产默认不打印。回归与指标基准: +推荐使用启动器。它会管理主服务、只读模式卡片服务和只读 OTA 服务: -```bash -pytest tests/unit/test_speech_transcription.py tests/unit/test_transcript_assembler.py -python tools/benchmark_speech_pipeline.py --audio-dir artifacts/tmp/speech-regression-audio +```powershell +.\.venv\Scripts\python.exe tools\start_n7web.py --skip-web-build ``` -麦克风仅可用于安全来源:本机使用 `http://127.0.0.1:8000`,远程使用 HTTPS。 +默认端口: -顶部“手势控制”打开同页抽屉。浏览器在本机完成 MediaPipe 推理,识别结果仍通过同一自然语言编排、安全校验与执行链路处理。运行必需资源已经纳入本工程: +| 服务 | 地址 | 说明 | +| --- | --- | --- | +| 主服务和 Web 控制台 | `http://127.0.0.1:8000` | API、控制台、助手和车控入口 | +| 模式卡片目录 | `http://127.0.0.1:8090/n7/scenes` | HTTP/UDP 只读目录服务 | +| 固件 OTA | `http://127.0.0.1:8012` | 只读发布清单和下载 | -```text -apps/web-console/assets/gesture/gesture_recognizer.task -config/gesture/default.yaml -``` - -因此源码打包和容器构建不依赖相邻的 `seat_gesture_control` 目录。模型文件只保留一份,不包含原工程的测试视频、日志或验证输出。浏览器摄像头要求安全来源,本地使用 `http://127.0.0.1:8000`,远程部署使用 HTTPS;首次使用仍需浏览器授予摄像头权限。MediaPipe Web 运行时从 jsDelivr 按需加载,视频帧不上传到后端。 - -手势安全状态机采用张掌保持 1 秒激活、动作保持 600 ms 且至少 8 帧确认、单次运动 1.5 秒上限、连续 3 秒无有效动作自动锁止。换动作不需要重新张掌;握拳立即停止当前动作但保持激活;多手画面不执行动作。手势映射可在抽屉内自定义并保存在当前浏览器。 - -同一局域网的其他电脑需要体验时,使用 `make dev-lan` 监听全部网络接口。服务启动日志会打印实际 LAN 地址,例如 `http://172.20.10.5:8000`。前端和 API 使用同源访问,不需要 CORS,也不会把 `OPENAI_API_KEY` 发送到浏览器。若没有启用 `.env.auth`,任何可达设备都能触发服务端 GPT 请求,因此未认证的 LAN 模式只应在可信网络内临时演示。 - -### N7 模式卡片局域网目录 - -服务正常启动时,会把当前车型可见的工程预设模式和用户自定义模式原子同步到相邻目录 `../scenses/demo-scenes.json`,并提供无需登录、只读的 `GET /n7/scenes`。YAML 模式库仍是唯一真源;创建、更新、删除、恢复模式都会刷新 JSON,原有模式执行和安全校验链路不变。JSON 保留 `n7-scenes` v1 的 `id/label/background_time/description/actions` 字段,同时在动作中保留完整的 `domain/capability/target_scope/operation/parameters`,因此座椅、空调、天幕和氛围灯配置不会在导出时丢失。可用 `N7_SCENE_CATALOG_PATH` 或启动参数 `--scene-catalog` 覆盖输出路径。 - -分阶段动态模式额外保留完整 `schedule` 和用于展示单轮阶段起点的 `preview_actions`,并标记 `execution.kind=server_schedule`。此类模式的旧版 `actions` 列表为空,避免不认识时间轴的 v1 客户端把多个阶段同时下发;必须通过主工程已认证、受控的模式执行链运行。静态模式和已有 `timeline` 格式不变。 - -主项目和客户端只读目录服务可以用一个监督脚本同时启动: +启动前端构建: ```powershell .\.venv\Scripts\python.exe tools\start_n7web.py ``` -脚本自动设置 `PYTHONPATH`:管理页面默认仅监听 `127.0.0.1:8000`,只读固件 OTA 服务监听 `127.0.0.1:8012`,模式卡片 HTTP/UDP 服务监听 `0.0.0.0:8090`。OTA 服务只提供健康检查、全部历史发布列表、最新版本清单和固件下载,设计为通过固定公网 HTTPS 隧道供车机访问,不暴露工作台和车辆控制接口。车机通过 `GET /api/firmware-workbench/releases` 枚举所有可下载固件,通过 `GET /api/firmware-workbench/releases/latest` 查询最新固件。如果 `8012` 端口已经运行健康的 N7 OTA 服务,启动器会直接复用它。可通过 `--host`、`--port`、`--ota-host`、`--ota-port`、`--scene-port`、`--catalog` 和 `--server-id` 覆盖参数。任一由启动器管理的子服务异常退出或按一次 `Ctrl+C` 时,脚本会停止其余受管服务。 +启动器支持 `--host`、`--port`、`--scene-port`、`--ota-port`、`--catalog`、`--server-id`、`--python` 和 `--dry-run`。使用 `--host 0.0.0.0` 前请确认网络可信,并为公网部署启用认证和 HTTPS。 -同步由模式注册表的创建、更新、删除、恢复和显式重载事件触发,不会持续扫描目录。每次变更只重新生成并原子替换一份小型 JSON;独立目录服务在收到 HTTP 请求时才读取它。因此空闲时的额外开销主要是一个等待请求的 Python 进程和一个 UDP 发现线程,而不是持续的 CPU 或磁盘轮询。 +健康检查: -前端通过 `POST /api/mode-profiles` 新增模式卡片,或通过 `POST /api/mode-profiles/{id}` 修改模式卡控制流后,主服务会先完成 YAML 持久化和 `/n7/scenes` 原子同步,再从同一份目录投影中按模式 ID 提取一个 `scenes[]` 元素,并在 1 秒内以约 333 ms 间隔向 MQTT `from_pc/scenes` 发布 3 次。每帧都是完全相同的更新后单卡 JSON,不包含目录外层或其他已有卡片,QoS 沿用车辆 MQTT 配置且 `retain=false`。删除和页面刷新只更新原有持久化/目录链路,不会触发该 Topic。 - -检测到已绑定外设的 NFC 卡时,主服务会按英文稳定 `device_id` 对已学习且启用的红外能力分组,并向 MQTT `extension/toy` 发布 3 帧相同的设备能力消息(约在 0、333、666 ms 发布,QoS 1、`retain=false`)。`extension_name` 使用中文显示名,`actions[].target_scope` 使用英文 `device_id`;卡片持续停留不会重复发送,移开后再次检测才会重新发送。该消息仅广播能力目录,不会触发红外发射。 - -车端需要控制这些 TCP 红外外设时,向同一个车辆 MQTT Broker 的 `extension/ctl` 发布 QoS 1、`retain=false` 的 JSON。PC 主服务固定订阅该 Topic;消息外层必须且只能包含 `domain`、`operation_count`、`actions`,其中 `domain` 为 `self_extension`,`operation_count` 必须与动作数量一致(1–64),`actions` 使用 `/n7/scenes` 中的红外动作格式: - -```json -{ - "domain": "self_extension", - "operation_count": 2, - "actions": [ - { - "type": "infrared_emit", - "at_ms": 0, - "domain": "self_extension", - "capability": "infrared.emit", - "target_scope": "toy-light-001", - "operation": "emit", - "parameters": {"action": "打开", "slot": 2} - }, - { - "type": "infrared_emit", - "at_ms": 1000, - "domain": "self_extension", - "capability": "infrared.emit", - "target_scope": "toy-light-001", - "operation": "emit", - "parameters": {"action": "切换为蓝色", "slot": 5} - } - ] -} +```powershell +Invoke-RestMethod http://127.0.0.1:8000/api/health +Invoke-RestMethod http://127.0.0.1:8000/api/assistant/status ``` -服务在执行首条动作前会对完整控制流做原子鉴权:每一项都必须与本机目录中“已学习、已启用、具有持久 NFC 绑定”的 `device_id + action + slot` 完全一致;NFC 卡此时无需仍在感应区。执行前还会逐项重新鉴权,以阻止排队期间已被禁用或删除的能力。动作按 `at_ms` 排序后通过本机 TCP 红外网关串行下发,相邻发射至少间隔 800 ms;任一动作失败即停止剩余控制流。为避免重连误执行,retained 消息和 MQTT `dup` 重投消息都会被拒绝,消息体上限为 256 KiB。接收、鉴权、排队、执行结果和拒绝原因可在 `GET /api/extension/health` 的 `extension_control` 字段查看。 +`/api/health` 依赖 Codex App Server 就绪;助手进程不可用时返回 HTTP `503`,不会伪装成可用服务。 -如果只需单独启动 UDP 发现和只读目录服务,也可以在另一个 PowerShell 终端运行: +### 只启动主服务 + +需要自行运行前端开发服务器或不需要模式目录/OTA 服务时,可直接运行: ```powershell $env:PYTHONPATH = "src;domains/seat/src" -.\.venv\Scripts\python.exe -m cognitive_agent.lan_scene_server --bind 0.0.0.0 --port 8090 +.\.venv\Scripts\python.exe -m cognitive_agent.server ``` -客户端向 UDP `8090` 发送 `N7_SCENES_DISCOVER_V1`,收到 `N7_SCENES_V1` 后访问 `http://<服务端IP>:8090/n7/scenes`。独立服务每次请求都读取最新的 JSON,并为只读接口开放 CORS;它不提供模式创建、修改、删除或执行能力。 +前端热更新: -Linux 上使用 USBCANFD-200U 被动同步 CH1 车辆状态时,使用 -`zlgcan-linux` 后端。USB 权限、60 MHz/500k/2M 位时序、只读配置和状态接口 -验证见 [Linux ZLG 车辆状态接入](docs/workflows/linux-zlg-vehicle-state.md)。 -有线 ZLG 与本机 NanoMQ 无线链路使用相同的通道角色:CAN0 只对应副驾座椅, -CAN1 对应空调、车窗、灯光、遮阳帘、主驾座椅等其余车辆状态和控制。车辆控制 -后端不允许回退到 CAN0;MQTT 主题、原始 CAN 帧 JSON 合约和有线/无线共用安全 -门禁见同一文档。 +```powershell +cd apps\web-console +npm run dev +``` -需要在终端独立核对双通道状态或下发一条明确的白名单语义命令时,可构建 -`can_read_trans`。该程序由同一个 C++ 进程持有 ZLG 设备:CAN0 监听并控制副驾 -座椅固件原生协议,CAN1 监听并控制其余车辆矩阵协议;默认只监听、默认不启用 -适配器内部终端电阻,也不提供任意原始帧注入入口。`console --execute` 可在同一 -设备会话中持续接收状态并交互下发 CAN0/CAN1 白名单命令。构建、命令示例、反馈 -判定和安全限制见 [can_read_trans 双通道检测与控制](docs/workflows/can-read-trans.md)。 +Vite 使用 `http://127.0.0.1:5173`,并把 `/api` 与 `/artifacts` 代理到 `http://127.0.0.1:8000`。生产构建输出为 `apps/web-console/dist`,主服务检测到该目录后优先提供构建产物。 -## 认证与公网体验 +在已安装 GNU Make 的环境中,`make dev` 等价于启动主服务;Windows PowerShell 推荐使用上面的显式 Python 命令,以确保使用仓库的 `.venv`。 -公网演示必须启用 `.env.auth` 中的服务端认证。密码使用 PBKDF2-SHA256 哈希保存;认证成功后签发有有效期的 HMAC 会话 Cookie,Cookie 使用 `HttpOnly` 和 `SameSite=Strict`,经 HTTPS 代理时自动增加 `Secure`。登录失败按来源 IP 限流,GPT 请求按体验账号限制每分钟调用次数。未登录访问页面会跳转 `/login`,未登录 API 请求返回 `401`。 +## 开发与验证 -生成认证材料: +先激活 `.venv`,或把下面的 `python` 替换为 `.\.venv\Scripts\python.exe`。仓库的 `Makefile` 使用 POSIX 风格环境变量,在 Windows 上也可以直接调用 Python 脚本。 ```bash -PYTHONPATH=src python -m cognitive_agent.auth hash-password -PYTHONPATH=src python -m cognitive_agent.auth generate-secret +# 公共 Schema、领域清单、平台资源和生成 CAN 协议 +make validate + +# 全量 Python、前端契约和 CAN 协议回归 +make test + +# 仅前端运行时契约 +make test-frontend + +# 生成或检查共享 CAN 语义协议 +make can-protocol-generate +make can-protocol-check ``` -固定公网演示部署在 `https://511.kendeji.fun`。服务器使用 Docker Compose -运行应用,容器端口只绑定 `127.0.0.1:8511`,由 Caddy 终止 HTTPS 并反向 -代理。部署结构、更新和运维命令见 -[`deploy/server/README.md`](deploy/server/README.md)。本地 `make dev` 与 -`make dev-lan` 仍分别用于回环地址和可信局域网开发。 +不使用 `make` 时: -当前 dry-run 规划策略允许 GPT 在没有同名 preset 时,将可理解的模式目标分解为已注册原子能力并生成保守候选参数。候选值只用于模型理解演示,不能替代实车模式标定。 +```powershell +.\.venv\Scripts\python.exe tools\validate_repository.py +.\.venv\Scripts\python.exe -m pytest +``` -靠背/坐垫与坐垫/腿托支持演示级精确夹角,并可将当前五轴姿态保存为会话持久化的命名 `FunctionPreset`。保存操作不发 CAN;再次调用时先展开为五个原子电机动作,再进入同一编译、校验和虚拟执行链路。 +仓库配置了 `pytest` 的 `contract`、`integration` 和 `hardware` markers。默认测试使用虚拟或模拟执行;真实台架测试必须按 [T2G 前端测试集](docs/testing/t2g-seat-frontend-test-suite.md) 的顺序执行,并显式确认硬件。 -完整能力边界、矩阵解释和验收用例见 [座椅阶段一交付](docs/workflows/seat-stage1-delivery.md)。 +构建双通道 CAN 读取工具需要 CMake 和外部 CANFD SDK: -已验证的 T2G 加热、通风、四电机和原生动态模式能力已完整纳入 `firmware/t2g`,包括 IAR 工程及仓库内 `common/tviibh8m` 构建依赖。M0/M1/M2/M3 分别对应水平、坐盆、靠背和腿托;revision 13通过`0x306`反馈带斜向耦合补偿的木马模式与四轴全程联动动态摇篮的阶段/循环状态。木马模式围绕中间姿态在`[270,250,460,400]`和`[370,130,540,460]`之间连续俯仰往复:坐盆峰峰行程120 Hall、约18 mm垂直分量,水平峰峰行程100 Hall、90%巡航Duty,用额外水平行程抵消坐盆斜向运动约16.4 mm的反向水平分量;参数集中在`seat_dynamic_mode_config.h`并由N7长期库镜像。动态模式收到一次启动命令后由ECU连续循环,收到停止/全停命令或累计运行10分钟时停止;目标到位式阶段在底层堵转/无运动保护继续生效的前提下使用独立保护窗口。真实硬件请求先被动核对新版周期反馈与 480/374/917/647 Hall 量程,未检测到匹配固件时默认通过 IAR C-SPY 自动烧写并复验,再发送 CAN 并等待真实回读。当前前端、能力注册、编译、安全门禁和状态反馈只允许副驾 `passenger/front_right`;固件中的 `Driver_Seat_*` 仅是板端既有协议字段名。构建、ZLG bridge、接线、安全门禁、前端测试集和已知量程归零见 [T2G 座椅真实硬件台架接入](docs/workflows/t2g-seat-hardware-bench.md) 与 [前端能力测试集](docs/testing/t2g-seat-frontend-test-suite.md)。 +```bash +make can-read-trans +make can-read-trans-test +``` + +## API 入口 + +浏览器只访问同源服务。下面是主要集成面,完整路由以 [`src/cognitive_agent/server.py`](src/cognitive_agent/server.py) 为准: + +| 方法 | 路径 | 用途 | +| --- | --- | --- | +| `GET` | `/api/health` | 服务与助手健康状态 | +| `GET` | `/api/runtime` | 当前运行时、平台和执行模式摘要 | +| `GET` | `/api/assistant/status` | Codex App Server 状态 | +| `GET` | `/api/assistant/capabilities` | 权威能力目录快照 | +| `POST` | `/api/requests` | 提交自然语言或结构化车控请求 | +| `POST` | `/api/requests/preview` | 只规划/校验,不执行 | +| `POST` | `/api/assistant/stream` | AI 助手 NDJSON 流 | +| `GET` | `/api/hardware/seat-state` | 座椅状态快照 | +| `GET` | `/api/hardware/vehicle-state` | 车身状态快照 | +| `GET` | `/api/vehicle-display-sync` | 网页与车机任务同步 | +| `GET` | `/n7/scenes` | 只读模式目录 | + +`/api/internal/codex/vehicle-control` 仅供本机 Codex MCP 回调使用,需要一次性令牌和原始请求绑定,不是浏览器或第三方 API。语音、手势、NFC、固件工作台和自修复接口也由服务端权限门禁保护。 + +## 配置与安全 + +默认 [`config/default.yaml`](config/default.yaml) 使用 `dry_run`、结构化输出和 `artifacts/runs`。真实硬件必须同时满足: + +1. 平台 manifest 的 `execution_enabled: true`。 +2. 对应 CAN 后端、通道、DBC 和校准可用。 +3. 服务端硬件开关、授权令牌和安全策略通过校验。 +4. 领域映射明确允许硬件执行,并收到真实反馈。 + +模拟台架显式使用: + +```powershell +$env:COGNITIVE_AGENT_SIMULATED_HARDWARE_ENABLED = "true" +``` + +模拟结果会标记为 `simulated_hardware`,不会打开真实 CAN、ZLG 或 IAR。真实 T2G 座椅需要参考 [`config/environments/t2g_seat_bench.example.yaml`](config/environments/t2g_seat_bench.example.yaml) 和 [硬件台架流程](docs/workflows/t2g-seat-hardware-bench.md);不要仅通过前端按钮声称已经获得硬件权限。 + +语音和摄像头只在安全来源工作:本机使用 `http://127.0.0.1:8000`,远程部署必须使用 HTTPS。局域网开发命令如下: + +```bash +make dev-lan +``` + +该模式会监听全部网络接口,任何可达设备都可能触发服务端请求,只适合可信网络临时演示。 + +## 代码结构 + +```text +apps/web-console/ Vue 入口、兼容运行层、静态资源和 PWA +src/cognitive_agent/ HTTP 服务、应用编排、运行时、基础设施和助手适配 +domains/*/ 领域插件:能力、Schema、映射、编译器和测试 +platforms/*/ 车型、DBC、总线和校准;定义执行边界 +contracts/schemas/ 冻结的公共 JSON Schema +config/ 环境、策略、车辆、模式和原生能力配置 +tests/ 跨域契约、集成、端到端和前端测试 +tools/ 启动器、仓库校验、协议生成、HIL 和诊断工具 +firmware/t2g/ T2G 固件工程和可烧录依赖 +deploy/ Docker Compose、服务器和 Kubernetes 占位配置 +docs/ 架构、决策、治理、工作流和测试说明 +artifacts/ 本地运行产物、模型、HIL 报告和持久化数据 +``` + +依赖边界:领域插件只依赖 SDK 和公共契约,不直接调用 LLM、HTTP 或 CAN;编排层只组合语义配置,不按 CAN signal 编排;DBC 和安全标定由 `platforms/` 统一维护。详见 [总体架构](docs/architecture/overview.md)、[领域交付流程](docs/workflows/domain-delivery.md) 和 [所有权规则](docs/governance/ownership.md)。 + +## 可选能力 + +### 语音 + +安装 `.[speech]` 并运行 `tools/install_sensevoice_model.py` 后,控制台支持手动录音和唤醒词待机。预览和最终识别接口为 `/api/speech/preview` 与 `/api/speech/transcribe`;录音不持久化。调试使用 `SPEECH_DEBUG=1`,默认不向浏览器返回 trace。 + +### 手势 + +手势模型随仓库提供:`apps/web-console/assets/gesture/gesture_recognizer.task`。推理在浏览器完成,视频帧不上传;需要摄像头权限和安全来源。 + +### NFC / 红外外设 + +安装 `.[ir]` 后运行主服务。NFC、GSCU1B TCP 网关、红外槽位目录和 MQTT 回退由 `/api/extension/*` 管理;学习、绑定和发射均受服务端能力目录与持久 NFC 绑定约束。 + +### Android PAD + +```powershell +powershell -ExecutionPolicy Bypass -File .\tools\android_pad_dev.ps1 +powershell -ExecutionPolicy Bypass -File .\tools\android_pad_dev.ps1 -Stop +``` + +脚本使用模拟台架,不打开真实硬件执行。 + +## 部署 + +服务器 Docker Compose 和 Caddy 反向代理说明见 [`deploy/server/README.md`](deploy/server/README.md)。镜像默认以非 root 用户、只读根文件系统运行,应用只绑定服务器回环地址,再由 Caddy 提供 HTTPS。部署时通过私密环境文件注入认证材料和模型凭据,不把 `.env`、`.env.auth`、Codex `auth.json` 或 API Key 放入镜像和版本库。 + +`deploy/docker/` 记录后续拆分 API/worker/Web 的边界;`deploy/k8s/` 目前是 Kubernetes 资源占位文档。真实 CAN 设备只能挂载到明确授权的执行器环境。 + +## 相关文档 + +- [总体架构](docs/architecture/overview.md) +- [T2G 座椅与车身双通道 CAN](docs/workflows/t2g-cabin-dual-channel-can.md) +- [T2G 座椅真实硬件台架](docs/workflows/t2g-seat-hardware-bench.md) +- [T2G 座椅前端测试集](docs/testing/t2g-seat-frontend-test-suite.md) +- [中文语音控制链路](docs/speech-recognition.md) +- [模式卡片与时间轴](docs/mode-schedules.md) +- [领域交付流程](docs/workflows/domain-delivery.md) +- [所有权与变更边界](docs/governance/ownership.md) +- [服务器部署](deploy/server/README.md) +- [Web 控制台细节](apps/web-console/README.md) + +## 项目状态 + +这是面向演示、集成和受控台架验证的工程,不是未经适配即可部署到任意车型的通用车控产品。提交修改前至少运行 `validate` 和相关领域测试;涉及 DBC、平台标定、硬件执行或公共 Schema 的变更,需要同时更新对应专题文档与回归用例。