# ai_browser_demo — AI Browser 启动入口

> **示例位置：** `samples/ai_browser_demo/`
> **核心演示：** 命令行参数解析 + WebView2 集成 + WS Hub pub/sub 消息枢纽 + 日志面板
> **最后更新：** 2026-06-26

---

## 一、概述

`ai_browser_demo` 是 **eduwin AI Browser** 的启动入口骨架，将框架多个模块集成到一个可执行程序中：

| 模块 | 用途 |
|------|------|
| `eduwin_app` | 窗口创建、消息循环、窗口关闭/缩放回调 |
| `eduwin_cmd` | 命令行参数解析（`--headless`、`--port`、`--url`、`--help`） |
| `eduwin_webview` | WebView2 浏览器容器 |
| `eduwin_net（ws_hub）` | 通用 pub/sub WebSocket 消息枢纽 |
| `eduwin_logview` | 右侧日志面板（三列：时间 / 级别 / 消息） |
| `eduwin_thread` | 后台线程运行 WS 服务器 |

### 架构

```
┌──────────────────────────────────────────────────────┐
│                   ai_browser_demo                     │
│                                                      │
│  ┌─ WebView2 ─────────────────────────────┐          │
│  │  （左侧内容区）                         │          │
│  └────────────────────────────────────────┘          │
│                                                      │
│  ┌─ LogView ──────────────────────────────┐          │
│  │  时间  │  级别  │  消息                 │          │
│  │  14:30 │  ⓘ    │  日志面板已初始化     │          │
│  │  14:30 │  ⓘ    │  WS Hub 已启动        │          │
│  │  14:31 │  ⓘ    │  conn_id=0 订阅 'js'  │          │
│  │  14:31 │  ⚠    │  客户端断开           │          │
│  │  14:32 │  ✕    │  无效 JSON            │          │
│  └────────────────────────────────────────┘          │
│                                                      │
│  ┌─ ws_hub（后台线程）───────────────────┐           │
│  │  通用 pub/sub，多个 WS 客户端自由路由   │          │
│  └────────────────────────────────────────┘          │
└──────────────────────────────────────────────────────┘
```

---

## 二、通信协议 — 通用 pub/sub

`ai_browser_demo` 使用 **ws_hub（话题驱动的 pub/sub 模式）**，类似 MQTT。

### 2.1 设计思路

- **不再区分 Agent 连接和 JS 连接** — 两者都是**对等 WS 客户端**
- 客户端通过 JSON 指令自由订阅/发布话题
- 消息路由不经过 C 层逻辑，服务端只做透传

### 2.2 协议格式

所有消息为 JSON 格式，UTF-8 编码：

**订阅话题：**
```json
{"type":"subscribe","topic":"agent"}
```

**取消订阅：**
```json
{"type":"unsubscribe","topic":"agent"}
```

**发布消息：**
```json
{"type":"publish","topic":"agent","data":{"action":"describe"}}
```

**收到推送（服务端 → 非发送者的所有订阅者）：**
```json
{"topic":"agent","data":{"action":"describe"}}
```

### 2.3 典型对话流程

```
Python Agent                     ai_browser_demo              WebView JS
    │                                  │                          │
    │── WS connect ──────────────────►  │                          │
    │                                  │◄── WS connect ──────────│
    │                                  │                          │
    │── subscribe "agent" ───────────►  │                          │
    │                                  │◄── subscribe "js" ──────│
    │                                  │                          │
    │── publish topic="agent" ───────►  │                          │
    │   {"action":"describe"}          │── 转发给 "js" 订阅者 ──► │
    │                                  │     （排除发送者）        │
    │                                  │◄── publish topic="js" ──│
    │◄── 转发给 "agent" 订阅者 ───────│    DOM tree              │
    │                                  │                          │
```

### 2.4 服务端限制

| 项 | 上限 |
|----|------|
| 最大连接数 | 64 |
| 话题名长度 | 64 字符 |
| 每连接可订阅话题数 | 16 |
| 单条消息最大长度 | 16 KB |

---

## 三、命令行参数

| 参数 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| `--headless` | 开关 | 有窗口 | 隐身模式（无界面，WebView 挂傀儡窗口） |
| `--port` | 值 | `9099` | WS 服务器端口 |
| `--url` | 值 | `about:blank` | 起始导航 URL |
| `--title` | 值 | `AI Browser` | 窗口标题 |
| `--help` | 开关 | — | 显示帮助信息 |

```bash
# 默认有头模式
ai_browser_demo.exe

# 隐身模式，自定义端口
ai_browser_demo.exe --headless --port 9090

# 指定起始 URL
ai_browser_demo.exe --url https://www.bing.com

# 查看帮助
ai_browser_demo.exe --help
```

---

## 四、核心 API 使用

### 4.1 日志面板

通过框架 `eduwin_logview` 组件创建和使用：

```c
#include "eduwin.h"

static HWND g_logview;

g_logview = create_logview(g_win, x, y, w, h);

logview_info(g_logview, L"应用已启动，端口 %d", 9099);
logview_warn(g_logview, L"连接超时 (conn_id=%d)", 5);
logview_error(g_logview, L"网络错误");
```

面板自动：
- 附加时间戳
- 限制行数（默认 500，超限删最旧）
- 自动滚底
- 双击行复制消息内容到剪贴板

### 4.2 WS Hub

```c
ws_hub_t *hub = ws_hub_create(port);

// 主循环
while (g_running) {
    int cid = ws_hub_accept(hub, 200);          // 接受新连接
    int ready = ws_hub_poll(hub, 200);           // 轮询消息
    ws_hub_subscribe(hub, cid, "agent");         // 订阅话题
    int n = ws_hub_publish(hub, sender, "agent", payload, len);  // 发布
    ws_hub_disconnect(hub, cid);                 // 断开连接
}

ws_hub_close(hub);
```

### 4.3 傀儡窗口

```c
// headless 模式下 WebView2 需要有效父窗口
HWND hwnd = create_hidden_window(1200, 800);
```

---

## 五、测试

Python 测试脚本位于 demo 目录下：

| 脚本 | 用途 |
|------|------|
| `pub.py` | DIP 指令测试客户端（单条模式） |
| `test_ws_pubsub.py` | 基础双向通信测试 |
| `test_ws_pubsub2.py` | 多发进阶测试 |

```bash
# 单条指令
python samples\ai_browser_demo\pub.py '{"action":"describe"}'
```

---

## 六、构建

```bash
cd D:\XTU\c-train\eduwin
build_lib.bat                 # 先编译框架库

cd D:\XTU\c-train\samples\ai_browser_demo
build.bat                     # 编译 demo
```

依赖链接库：`eduwin.lib user32.lib gdi32.lib gdiplus.lib comctl32.lib comdlg32.lib shell32.lib winmm.lib ole32.lib oleaut32.lib version.lib advapi32.lib ws2_32.lib`

---

## 七、已集成的框架模块

| 模块 | 文件 | @public_api 函数 |
|------|------|-----------------|
| `eduwin_cmd` | `eduwin_cmd.h/c` | `cmd_init`, `cmd_has`, `cmd_get`, `cmd_get_def`, `cmd_is`, `cmd_print_help`, `cmd_cleanup` |
| `eduwin_net` | `eduwin_net.h/c` | `ws_server_*`, `ws_hub_*`（含 ws_hub pub/sub 全套） |
| `eduwin_thread` | `eduwin_thread.h/c` | `thread_run`, `thread_join`, `thread_cleanup` |
| `eduwin_app` | `eduwin_app.h/c` | `init_app`, `create_window`, `create_hidden_window`, `show_window`, `run_app`, `on_window_close`, `on_window_resize` |
| `eduwin_logview` | `eduwin_logview.h/c` | `create_logview`, `logview_info/warn/error`, `logview_clear`, `logview_set_max_rows` |
| `eduwin_webview` | `eduwin_webview.h/c` | `webview_init`, `create_webview`, `webview_navigate`, `on_webview_ready`, `on_navigation_completed`, `on_webview_message` |
