> For the complete documentation index, see [llms.txt](https://tinyhumans.gitbook.io/openhuman/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://tinyhumans.gitbook.io/openhuman/zh/kai-fa/tinycomputer-docker.md).

# Linux 和 Docker 上的 TinyComputer 浏览器

在 Linux 容器中以无头模式运行 TinyComputer 浏览器，使用本地构建的模块和无人值守自动化。

该 `浏览器` 浏览器工具通过 TinyComputer 模块（`libtinycomputer.so`）。编译后的模块注册表只会为其发布的平台固定 TinyComputer 版本。当你的 Linux 主机没有固定版本，或者你需要从确切的 `vendor/tinycomputer` gitlink 构建的版本时，请自行构建，并通过模块覆盖将核心指向它。

本页介绍容器配方、加载器的目录规则、无头研究代理所需的浏览器设置，以及如何让由 cron 驱动的轮次在无需交互式批准的情况下点击和输入。

{% hint style="warning" %}
本地构建是操作者自己的制品。切勿将其 SHA-256 复制到 `crates/openhuman-core/src/modules/registry/` 中作为发布固定值：固定值只能来自已发布的版本。
{% endhint %}

## 1. 在构建阶段构建模块

`vendor/tinycomputer/scripts/build-module` 完成加载器所需的一切。它会运行 `cargo build --locked --release -p tinycomputer --lib` 并安装 `libtinycomputer.so` 到 `TINYCOMPUTER_MODULE_DIR` （模式 `644`，目录 `755`）。它会写入一个 `modules.toml` 到库旁边，以其中命名其 SHA-256，然后遍历每个父目录；如果加载器会拒绝其中任何一个，就会提前失败。

首先初始化嵌套子模块（`git submodule update --init --recursive vendor/tinycomputer`）。TinyComputer 自带其自己的 TinyBus、agent-browser 和 agent-desktop。请使用与核心相同的检出版本进行构建：如果模块的 TinyComputer 契约版本与主机自身不兼容，主机会拒绝该模块。

```dockerfile
# 根据此检出记录的 gitlink 构建 libtinycomputer.so。
FROM rust:1.99.1-bookworm AS tinycomputer
RUN apt-get update && apt-get install -y --no-install-recommends \
        build-essential pkg-config ca-certificates \
        libasound2-dev libxdo-dev libxtst-dev libx11-dev \
    && rm -rf /var/lib/apt/lists/*
WORKDIR /src/tinycomputer
COPY vendor/tinycomputer/ ./
# 整条路径都由 root 拥有且权限为 755：这是加载器接受的形式。
ENV TINYCOMPUTER_MODULE_DIR=/opt/tinycomputer
RUN scripts/build-module
```

然后将其添加到仓库的运行时阶段 `Dockerfile` （其中已包含 `libasound2`, `libxdo3`, `libxtst6` 和 `libx11-6` 模块链接所需的运行时库），以及 Chromium：

```dockerfile
RUN apt-get update && apt-get install -y --no-install-recommends \
        chromium fonts-liberation \
    && rm -rf /var/lib/apt/lists/*
# 将库及其 modules.toml 证明一并复制。
COPY --from=tinycomputer /opt/tinycomputer/ /opt/tinycomputer/
RUN chown -R root:root /opt/tinycomputer \
 && chmod 755 /opt/tinycomputer \
 && chmod 644 /opt/tinycomputer/libtinycomputer.so /opt/tinycomputer/modules.toml
```

### 加载器检查什么

TinyBus 加载器（`vendor/tinybus/crates/tinybus/src/module/host.rs`）只有在以下条件全部满足时才会接受该制品：

* **从 `/` 直到模块自身的** 都由 root 或核心运行所用的用户拥有（uid `10001` 在镜像中）。除非带有 sticky 位，否则任何目录都不能对组或所有人可写。包含符号链接的路径组件会被拒绝，库本身则以 `O_NOFOLLOW`打开。不要将模块放在绑定挂载或命名卷上：这些通常归其他用户所有，或可被组写入。
* **文件** 是一个普通的 `.so` ，大小小于 512 MiB。
* **`modules.toml` 其旁边**，在存在时，会注明库的准确 SHA-256。若不匹配则会被拒绝，因此重建后的库需要 `modules.toml` 该 `build-module` 重新生成。请将两者保持在一起。没有该证明，模块仍然可以加载，但不是已认证接收方，因此诸如 `StartTask` （ `任务` 操作）不会被传递给它。

被拒绝或发生故障的模块会一直保持拒绝状态，直到核心重启。

## 2. 使用模块覆盖加载它

```toml
[modules]
overrides = [{ id = "tinycomputer", path = "/opt/tinycomputer/libtinycomputer.so" }]
```

`id` 是注册表 ID（`tinycomputer`）以及 `path` 库的绝对路径。覆盖会在搜索路径和发布缓存之前进行检查，并绕过已编译的发布摘要，这就是为什么只有操作者自己的配置才能指定它（`config/schema/modules.rs`, `modules::ops::local_override`). `[modules] enabled` 必须保持 `true` （默认值）。

## 3. 无头研究代理的浏览器设置

```toml
[browser]
enabled = true
headless = true
chrome_path = "/usr/bin/chromium"
# 在会话和重启之间保留 cookie 和登录状态。
profile_mode = "persistent"
profile_path = "/home/openhuman/.openhuman/browser-profile"
download_dir = "/home/openhuman/.openhuman/browser-downloads"
# 选择加入：见下方“无人值守操作”。
unattended_actions = ["click", "press"]

[http_request]
# 浏览器共享此列表；对于浏览器会移除“*”。
allowed_domains = ["example.com", "docs.example.org"]
```

* `chrome_path` 会作为浏览器可执行文件传给模块。Debian 的 `chromium` 软件包会安装 `/usr/bin/chromium`.
* `profile_mode = "persistent"` 需要一个 **绝对的** `profile_path`，并且 `download_dir` 也必须是绝对路径。否则会拒绝该会话。请将两者都放在工作区卷下（`/home/openhuman/.openhuman` 在镜像中），入口点会将其 chown 给核心用户，因此它们可以在容器重启后保留。
* 导航遵循 `[http_request].allowed_domains`。空列表会拒绝所有会话。若要让浏览器可以访问任何地方，请在容器环境中设置 `OPENHUMAN_BROWSER_ALLOW_ALL=1` ，而不是添加 `"*"`.
* agent-browser 会自动添加 `--no-sandbox` 和 `--disable-dev-shm-usage` ，当它检测到容器、root 用户或较小的 `/dev/shm`.

## 4. 无人值守操作

默认情况下，每次点击、双击、填充、输入、按键、选择和勾选都要经过强制主机审批门。暂停在 `needs_approval`的浏览器任务也是如此。强制门仅对实时 WebChat 轮次放行，其他一律拒绝，因此若没有下面的设置，cron 任务可以打开并读取页面，但永远不能跟随“下一页”链接。

`[browser] unattended_actions` 指定一种 **受信任的无人值守轮次** 在无需该批准的情况下可以执行的操作类型：

| 名称          | 涵盖                                                             |
| ----------- | -------------------------------------------------------------- |
| `点击`, `双击`  | 点击元素，包括 `查找` 使用 `find_action = "click"`                        |
| `填充`, `输入`  | 向字段中写入文本                                                       |
| `按键`        | 诸如以下的按键操作 `Enter`                                              |
| `选择`, `勾选`  | 选择一个选项、勾选一个复选框                                                 |
| `task_step` | 一个浏览器 `任务` 暂停在 `needs_approval` 在不可逆步骤之前，并通过 `confirm_pending` |

* 该工具从每轮的 `CoreContext` 中读取轮次来源；cron、后台任务和工作流入口点会围绕其轮次进行作用域划分。
* **只有** 来源是 `TrustedAutomation` 且来源为 `Cron`, `Background`，或 `Workflow { require_approval: false }` 才符合条件。
* WebChat、外部渠道（Telegram、Slack，……）、CLI 和直接聊天、未标记的轮次，以及具有 `require_approval = true` require\_approval = true 的工作流，即使是列出的操作，也会保持与之前完全相同的强制门。
* 默认是空列表，这不会改变任何内容。
* 未知名称不允许任何操作。加载时，核心会记录一条警告，包含未知条目的数量（绝不会包含其文本）以及已知名称列表。
* 每个允许的操作都会以 `info` 级别记录，包含操作类型、其摘要的前 12 个十六进制字符以及来源类别。选择器、输入值、页面内容和任务 ID 都不会被记录。搜索 `[browser] unattended action allowed`.
* 支付检查点不是 `needs_approval` 暂停点。无论此列表怎么写，任务仍会在那里停止。

`task_step` 会放行由任务控制器本身标记为不可逆的步骤，例如发送、提交或删除。仅在你控制其提示词和允许网站的作业中列出它。
