内容
# Trailin — 本地电子邮件代理
一个为 **任何电子邮件提供商** 运行的本地AI电子邮件代理 — Gmail, Outlook / Microsoft 365 / Exchange Online, 以及 Pipedream 可以连接的任何其他提供商 — 基于:
- **[pi](https://github.com/badlogic/pi-mono)** (`@earendil-works/pi-agent-core` + `@earendil-works/pi-ai`) — 代理循环和LLM层
- **Pipedream Connect + MCP** — 每个 Pipedream 目录中的应用都使用托管的OAuth;来自 Pipedream 的 MCP 服务器的电子邮件工具,每个连接的帐户一个会话,因此 **多个帐户 — 相同提供商或混合 — 同时工作**
- **Fastify** API 服务器使用 **SQLite** (Drizzle) 持久性和 **node-cron** 自动化调度器
- **Vite + React + shadcn-style UI** (Tailwind v4)
```
apps/
server/ Fastify API: 聊天(SSE),Pipedream Connect,实时邮件工具,自动化 + 调度器
web/ Vite/React UI: 首页简介,自动化,设置 + 持久聊天栏
packages/
shared/ 服务器和 Web 之间共享的类型
```
## 设置
1. **安装** (Node 20+, pnpm):
```sh
pnpm install
```
2. **运行** (在 :3001 上启动服务器,在 :5173 上启动 Web):
```sh
pnpm dev
```
3. **在应用中配置** — 打开 http://localhost:5173 → **设置**:
1. 登录到 AI 提供商(Claude/Copilot/ChatGPT 订阅或 API 密钥)并选择模型。
2. 在 **连接电子邮件** 下,按照一次性 Pipedream 设置:创建免费帐户,在 [设置 → API](https://pipedream.com/settings/api) 下创建 OAuth 客户端(复制 Client ID + Secret),创建 [项目](https://pipedream.com/projects) 并粘贴其 URL。表单在保存前会使用 Pipedream 检查值。
3. 点击 **连接帐户**,选择提供商(建议 Gmail 和 Outlook;搜索涵盖 Pipedream 的完整目录)并完成登录。重复添加更多帐户 — 允许来自同一提供商的多个帐户。Outlook 连接器涵盖 outlook.com 和 Microsoft 365 / Exchange Online 工作帐户。
## 主机/单进程模式
`pnpm build` 构建 Web 应用;当 `apps/web/dist` 存在时,服务器会自行提供服务:
```sh
pnpm build
pnpm start # 所有内容都在 http://localhost:3001 上
```
## 工作原理
- 每个聊天对话都有自己的 **pi 代理**。创建时,服务器连接到 Pipedream 的 MCP 服务器 (`https://remote.mcp.pipedream.net/v3`) **每个连接的帐户一次**,使用 `x-pd-account-id` 固定,在 `tools-only` 模式(结构化参数,无子代理)下,列出工具,并将它们桥接到 pi `AgentTool`s。对于同一应用的多个帐户,工具名称带有帐户后缀 (`gmail-find-email__work`),每个描述都指明其操作的帐户。
- **自动化** 是 cron 调度的常驻指令(“每周 8 点总结未读邮件”)。每次运行都会启动一个新的代理,执行指令,并将结果存储在 SQLite 中(在 *最近运行* 下可见)。
- **实时读取邮件** — 代理的读取工具是每个帐户的 Pipedream MCP 工具;本地不镜像任何内容。确定性读取(草稿与发送的学习循环,语音学习)通过每个提供商的小型实时读取驱动程序进行(目前:Gmail,Outlook)。
- **网页搜索开箱即用** — 代理(及其委托研究人员)带有 `web_search` 工具,无需密钥:默认情况下,搜索通过 Exa 的无密钥公共 MCP 端点进行,或者当设置 `BRAVE_SEARCH_API_KEY` 时,使用 Brave Search API(`src/websearch/`)。
- 提供商特定代码(草稿,读取,附件)位于 `src/email/` 中的注册表后面 — 新提供商在 `register*.ts` 文件中注册,除此之外没有任何提供商硬编码。
- 对话记录,自动化,草稿和记忆存储在 `data/trailin.db` 中。代理上下文(工具调用历史)每个对话内存中存储,在服务器重启时重置。
## 开发
- **测试:** `pnpm --filter @trailin/server test` (vitest)。测试位于 `apps/server/test/`,镜像 `src/` — 绝不混存。
## 当前限制(v1)
- 单用户(一个 `PIPEDREAM_EXTERNAL_USER_ID`)— 适用于桌面,需要多租户托管前的每个用户 ID。
- 自动化仅 *运行和报告*;触发器(例如“新邮件时”)将使用 Pipedream 触发器/ Webhooks — 一个自然的下一步骤。
- MCP 会话为每个对话创建;一个长期存在的对话可能需要一个新的对话,一旦 Pipedream 访问令牌过期(〜1 小时)。