docs: add AI agent command bar + privacy gateway three-mode design

This commit is contained in:
2026-03-03 23:31:12 +00:00
parent 88ce820fe9
commit 7d84e36f5e
@@ -0,0 +1,218 @@
# AI Agent Command Bar + Privacy Gateway Three-Mode Design
**Date:** 2026-03-03
**Branch:** feature/enhance-testing-security-states
**Status:** Approved
## Overview
Add two missing frontend entry points:
1. **AI Agent Command Bar** — bottom of ConsolePage, submit tasks to KVM Agent
2. **Privacy Gateway Mode Selector** — extend /privacy page CertificateTab with OFF/AUDIT/REDACT modes
## Architecture
```
Browser (port 8080)
├── /api/v1/agent/* → Go reverse proxy → KVM Agent (port 8890)
└── /api/v1/privacy/* → Go reverse proxy → Privacy Gateway (port 8889)
```
Go adds `proxy_handler.go` using `httputil.ReverseProxy`, one instance per target.
## Backend Changes
### Go: proxy_handler.go (new)
- `AgentProxy`: `/api/v1/agent/*``http://localhost:8890`
- `PrivacyProxy`: `/api/v1/privacy/*``http://localhost:8889`
- Register in `router.go`
- Strip prefix before forwarding
- Log proxy errors
### privacy_api.py (redesign)
**Remove:** `privacy_enabled: bool`, old boolean format
**New state.json format:**
```json
{"mode": "off"}
```
**Endpoints:**
```
GET /api/v1/privacy/mode → {mode: "off"|"audit"|"redact"}
POST /api/v1/privacy/mode body: {mode: "off"|"audit"|"redact"} → {mode: "..."}
GET /api/v1/privacy/stats → {requests, files, pii_by_type, actions:{allow,audit,redact}, top_domains}
GET /api/v1/privacy/audit ?limit=50 → [{...log entries}]
GET /api/v1/privacy/cert → (unchanged)
POST /api/v1/privacy/masking → (unchanged)
```
### addon.py (update)
Read `mode` from state.json, three-branch logic:
```python
if mode == "off": pass_through() # no logging
elif mode == "audit": log_request(); allow() # log only
elif mode == "redact": log_request(); redact() # log + redact
```
### audit_logger.py (extend)
Log schema per intercepted request:
```json
{
"timestamp": "ISO8601",
"mode": "audit|redact",
"domain": "api.openai.com",
"method": "POST",
"path": "/v1/chat/completions",
"action": "allow|redact",
"files_detected": 1,
"pii_types": ["id_card", "phone"],
"source_ip": "192.168.1.x",
"request_size_bytes": 12345
}
```
Storage: SQLite table `audit_log`, supports `GET /api/v1/privacy/audit?limit=50`.
### runner.py (task cancellation)
- Add `asyncio.Event cancel_event` per running task
- `DELETE /api/v1/agent/tasks/{id}` sets the event
- runner checks event between action steps → sets status `CANCELLED`
- KVM HID cleanup via `safe_cleanup()` on cancel
### kvm_agent/api_server.py
No changes needed — `DELETE /api/v1/agent/tasks/{id}` already exists.
## Frontend Changes
### New: `AgentCommandBar.tsx`
```
┌─────────────────────────────────────────────────────────┐
│ [任务描述输入框.............................] [执行] [终止] │
│ 状态: 空闲 | 运行中 (task_id: abc123) │
│ 最近: ✅ 打开记事本 ❌ 找不到文件 │
└─────────────────────────────────────────────────────────┘
```
- Placed below `.video-container` in ConsolePage
- [终止] button visible only when task is running
- Task history: last 5 entries, success/fail icons
### New: `agentStore.ts`
```typescript
interface AgentStore {
status: "idle" | "running" | "error"
currentTask: Task | null
taskHistory: Task[]
submitTask(description: string): Promise<void>
cancelTask(id: string): Promise<void>
pollStatus(id: string): void // 2s interval, stops on terminal state
}
```
### Modified: `PrivacyPage.tsx` — CertificateTab
Replace binary ToggleCard with three-segment mode selector:
```
隐私网关模式:
┌──────────┬──────────┬──────────┐
│ 关闭 │ 审计 │ 脱敏 │
└──────────┴──────────┴──────────┘
描述: 不拦截任何请求 / 记录但不拦截 / 记录并脱敏文件
```
- Calls `POST /api/v1/privacy/mode {mode: "..."}`
- Loads current mode on mount via `GET /api/v1/privacy/mode`
### i18n keys to add
```json
"agent.command_placeholder": "描述任务,例如:打开记事本",
"agent.submit": "执行",
"agent.cancel": "终止",
"agent.status_idle": "空闲",
"agent.status_running": "运行中",
"agent.task_success": "成功",
"agent.task_failed": "失败",
"agent.task_cancelled": "已终止",
"privacy.mode_off": "关闭",
"privacy.mode_audit": "审计",
"privacy.mode_redact": "脱敏",
"privacy.mode_off_desc": "不拦截任何请求",
"privacy.mode_audit_desc": "记录 PII 但不拦截",
"privacy.mode_redact_desc": "记录并自动脱敏文件"
```
## Data Flow
### Agent Task Submission
```
User input → agentStore.submitTask()
→ POST /api/v1/agent/tasks {task_type: "general", description: "..."}
→ Go proxy → api_server.py
→ TaskQueue (SQLite) → runner.py executes
→ Poll GET /api/v1/agent/tasks/{id} every 2s
→ On COMPLETED/FAILED/CANCELLED → stop polling, update history
```
### Agent Task Cancellation
```
User clicks [终止] → agentStore.cancelTask(id)
→ DELETE /api/v1/agent/tasks/{id}
→ Go proxy → api_server.py
→ Sets cancel_event on runner
→ runner finishes current action step → stops
→ safe_cleanup() → status = CANCELLED
→ Frontend poll detects CANCELLED → shows "已终止"
```
### Privacy Mode Switch
```
User clicks mode → POST /api/v1/privacy/mode {mode: "audit"}
→ Go proxy → privacy_api.py
→ Writes state.json {mode: "audit"}
→ addon.py reads mode on next intercept
```
### Audit Log Query (PrivacyPage AuditTab)
```
AuditTab mount → GET /api/v1/privacy/audit?limit=50
→ Go proxy → privacy_api.py
→ SQLite query audit_log → return entries
→ Render table with timestamp/domain/action/pii columns
```
## Testing
| Layer | What to test |
|-------|-------------|
| Go proxy | `httptest` mock downstream, verify routing + error forwarding |
| privacy_api | pytest: mode switch, stats format, audit log insert/query |
| addon.py | mock three-mode branches (off/audit/redact) |
| runner.py | cancel_event propagation, CANCELLED status |
| AgentCommandBar | vitest: submit → poll → complete flow, cancel button visibility |
| PrivacyPage | vitest: mode selector loads current mode, calls correct endpoint |
## Implementation Order
1. **Go proxy** (unblocks all frontend API calls)
2. **privacy_api.py redesign** (mode enum + audit log)
3. **addon.py update** (three-mode branch)
4. **runner.py cancellation**
5. **agentStore.ts + AgentCommandBar.tsx**
6. **PrivacyPage CertificateTab mode selector**
7. **i18n + wiring**
8. **Tests**