Merge branch 'feat/chat-toolcall-hardening' into feat/chat-codex-ui
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -24,10 +24,16 @@
|
||||
```
|
||||
|
||||
- `id`:Codex item 的 id;同一 item 的 `started` 与 `completed` 必须落成**同一条**(按 id 幂等 upsert,不允许写两行)。
|
||||
- **状态单调**:同一 `id` 的每条快照按 `updatedAt` 合并落盘——`updatedAt` 更旧的快照不得覆盖更新的 `status` 与 `updatedAt`。逐条快照落盘与回合末整批落盘两条路径会并发竞争,后到的旧快照不能把已经 `completed` / `failed` 的卡片打回 `running`;`updatedAt` 相同时终态优先;`startedAt` 取最早的非零值(`item/completed` 不一定带 `startedAtMs`)。
|
||||
- `title` 是折叠态的一行标题,按 kind 固定:`command` → `执行命令`、`file_change` → `编辑 N 个文件`(N = changes 去重后数量)、其余见 kind 枚举。
|
||||
- `summary` 是折叠态标题后面的短摘要:命令取命令首行(截断 120 字符),`file_change` 取首个变更路径。
|
||||
- `detail.command` / `detail.output` 各截断到 4000 字符;`detail.changes[].path` 用项目相对路径。
|
||||
- **必须脱敏**:沿用既有 `codex_app_server.rs` 里对 command/tool 参数的安全处理,不得把 API Key、Token、Cookie、绝对用户目录写进 `detail`。
|
||||
- `summary` 是折叠态标题后面的短摘要:命令取命令首行(截断 120 字符),`file_change` 取首个变更路径。`summary` 的每个来源(命令、变更路径、`tool`)都必须先脱敏再落盘。
|
||||
- `detail.command` / `detail.output` 各截断到 4000 字符。
|
||||
- **路径形状**:`detail.changes[].path` 用**项目相对路径**(如 `game/src/x.ts`,分隔符统一成 `/`);项目外的绝对路径落成 `<absolute-path>` 占位。任何情况下都不得写出项目根目录本身、用户家目录或绝对路径的原始值。
|
||||
- **必须脱敏**(落盘前统一走 `agent/direct_tool_calls.rs` 的 `sanitize_detail_text`,顺序:项目路径归一化 → `redact_absolute_path_tokens` → `redact_secret_tokens` → `sanitize_error_context`):
|
||||
- 前缀型密钥沿用 `redact_secret_tokens`(`sk-…`、`tnr_sk_…`、`ghp_…`、`AKIA…`、`eyJ…` 等);
|
||||
- 键值型凭据沿用 `sanitize_error_context`(= `redact_secret_tokens` + `redact_error_sensitive_assignments` + `redact_error_bearer_values` + `redact_error_config_names` 的既有组合),覆盖 `Authorization: Bearer …`、`Cookie: session=…`、`api_key=…`、`client_secret=…`、`token=…` 等形状;
|
||||
- 含 `--password` / `--token` / `--secret` / `--api-key` 这类敏感 CLI 标志的行按既有 fail-closed 约定**整行**替换成 `[redacted sensitive context]`(与 `sanitize_agent_runtime_text` 一致;即使标志后面只是 `$VAR` 占位符也整行替换,占位符本身不会保留);
|
||||
- 脱敏必须幂等(同一段文本连跑两次结果一致),且不得把未脱敏文本写进 `detail` / `summary`。
|
||||
|
||||
### 2. 实时事件(新增字段,不改既有字段语义)
|
||||
|
||||
@@ -43,10 +49,11 @@ toolCalls?: DirectTurnToolCall[] | null;
|
||||
|
||||
### 3. 回读命令
|
||||
|
||||
新增 Tauri 命令 `read_direct_tool_calls(projectPath)`,返回按时间正序的 `DirectTurnToolCall[]`,最多最近 200 条(超出截断,保留最新)。
|
||||
新增 Tauri 命令 `read_direct_tool_calls(projectPath)`,返回按时间正序的 `DirectTurnToolCall[]`。
|
||||
|
||||
- **上限语义**:200 条是「按时间保留最新 200 条」。超出时更早回合的卡片会被**静默丢弃**(老回合卡片会消失),不做分页、不做历史回填;同一 `id` 的多条记录先按 `updatedAt` 合并,再按时间正序裁剪。
|
||||
- 历史文件缺失 → 返回空数组,不报错。
|
||||
- 单行损坏 → 跳过该行继续,不整体失败(与 Codex item 流一样是"尽力而为"的展示数据,不是业务真相)。
|
||||
- 单行损坏 → 逐行读字节并逐行解码,跳过该行继续,不整体失败;只有损坏字节与下一行黏成一行(例如写入被截断、缺失换行)时,被丢掉的也只是那**一行**,其后的合法记录必须继续读回(与 Codex item 流一样是"尽力而为"的展示数据,不是业务真相)。
|
||||
|
||||
### 4. 前端合并与渲染(2026-09 修订:一回合一个折叠块)
|
||||
|
||||
@@ -116,7 +123,7 @@ toolCalls?: DirectTurnToolCall[] | null;
|
||||
|
||||
- Rust(`apps/ai-game-creator-shell/src-tauri/src/`):`agent/codex_app_server.rs`(item → 结构化采集)、`agent/direct_runtime.rs`(随事件下发 + 回合结束持久化)、`agent/direct_project_history.rs` 或新增 `agent/direct_tool_calls.rs`(upsert 与回读)、`commands.rs`(新增命令注册)。
|
||||
- 前端(`apps/ai-game-creator-shell/src/`):`app/types.ts`(新增字段与类型)、`App.tsx`(订阅、累加、加载时合并)、`features/agent-runtime/` 或新增 `features/project-workspace/ToolCallCard.tsx`(卡片组件)、`styles.css`(卡片样式,新样式集中在文件末尾中文注释区块)。
|
||||
- 测试:Rust 侧单元测试(upsert 幂等、截断、脱敏、损坏行跳过)、前端 `tests/`(卡片渲染、折叠交互、重开项目后合并、老事件兼容)。
|
||||
- 测试:Rust 侧单元测试(upsert 幂等、状态按 `updatedAt` 单调合并、截断、脱敏覆盖与幂等性、项目相对路径形状、非法 UTF-8 损坏行跳过、200 条上限保留最新)、前端 `tests/`(卡片渲染、折叠交互、重开项目后合并、老事件兼容)。
|
||||
|
||||
## 实施顺序(每步都要能独立验证)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user