pipecat-ai/gradient-bang
GitHub: pipecat-ai/gradient-bang
一个在线多人与 LLM 协作的虚拟宇宙,通过实时代理工作流演示探索、交易与战斗的全栈应用。
Stars: 314 | Forks: 47
# 梯度爆炸
Gradient Bang 是一个在线多人宇宙,您可以在其中探索、交易、战斗并与其它玩家和 LLM 协作。游戏中的所有内容都是一个 AI 代理,包括您指挥的飞船。
该项目展示了实时代理工作流的全部能力,例如多任务处理、高级工具调用和低延迟语音。
➡️ [加入测试](https://www.gradient-bang.com)
## 快速开始(Claude Code)
如果您已安装 [Claude Code](https://docs.anthropic.com/en/docs/claude-code),从全新克隆快速启动的最快方式是:
```
/init
```
这条单一命令会安装依赖、启动 Supabase、生成环境文件、创建世界数据,并引导您提供 API 密钥。请参阅下方的 [初始设置](#initial-setup) 了解等效的手动步骤。
本 README 中描述的许多步骤也都有对应的 Claude Code 技能——请查找 `/skill-name` 调用提示。参见底部的完整 [Claude Code 技能参考](#claude-code-skills-reference)。
## 目录
- [初始设置](#initial-setup)
- [本地运行](#running-locally)
- [部署](#deployment)
- [环境变量](#environment-variables)
- [认证与密钥快速指南](#auth--secrets-quick-guide)
- [Claude Code 技能参考](#claude-code-skills-reference)
## 初始设置
如果您希望参与 Gradient Bang 的开发,第一步是让整个应用在本地运行。需要运行四个组件:
- **Supabase** 是“游戏服务器”。我们使用其 PostgreSQL 数据库(包含一些重要的 PL/pgSQL 函数)进行存储,并通过 [Subabase Edge Functions](https://supabase.com/docs/guides/functions) 提供 API。Supabase 提供 [CLI 工具](https://supabase.com/docs/guides/local-development) 可在本地运行其堆栈用于开发。
- **边缘函数** 开发服务器用于运行 `deployment/supabase/functions` 文件夹中的函数。
- **客户端** 是游戏 UI,使用 React 构建并通过 `turbo` 部署到 Vercel。
- **机器人** 是一个 Pipecat 机器人,部署到 [Pipecat 云](https://docs.pipecat.ai/deployment/pipecat-cloud/introduction)。
### 前置条件
- **uv**:Python 包管理器
- **[Supabase 账户](https://supabase.com/)**:游戏服务器函数、认证与数据库
- **Docker**:运行本地 Supabase 堆栈和代理部署所必需
- **Node.js 18+**:用于边缘函数部署和客户端
- (可选) **[Pipecat 云账户](https://docs.pipecat.ai/deployment/pipecat-cloud/introduction)**:生产级代理托管
- (可选) **[Supabase CLI](https://supabase.com/docs/guides/local-development/cli/getting-started)**:如果无法使用 `npx`,可直接全局安装 CLI 替代
### 步骤 1:设置 Supabase
首先运行 `supabase start`。Supabase 包含多个服务,就像穿着一件风衣。此命令会下载并运行所有相关的 Docker 镜像。运行后,您会看到多个服务在不同端口监听,这些端口随后会被使用。
```
npx supabase start --workdir deployment/
```
接下来,获取创建本地 Supabase 堆栈配置所需的 API 密钥并生成 `.env.supabase` 文件:
```
tok=$(openssl rand -hex 32)
npx supabase status -o env --workdir deployment | awk -F= -v tok="$tok" '
$1=="API_URL" {v=$2; gsub(/"/,"",v); print "SUPABASE_URL=" v}
$1=="ANON_KEY" {v=$2; gsub(/"/,"",v); print "SUPABASE_ANON_KEY=" v}
$1=="SERVICE_ROLE_KEY" {v=$2; gsub(/"/,"",v); print "SUPABASE_SERVICE_ROLE_KEY=" v}
END {
print "POSTGRES_POOLER_URL=postgresql://postgres:postgres@db:5432/postgres"
print "EDGE_API_TOKEN=" tok
}
' > .env.supabase
```
接着,在 `supabase start` 之后(以及任何手动数据库重置后)运行此辅助命令。它会设置一些重要的 PL/pgSQL 函数,以保持战斗回合自动结算:
```
scripts/supabase-reset-with-cron.sh
```
接下来,使用要绘制的扇区数量和随机种子运行宇宙脉冲脚本。这会创建世界数据。然后,将这些数据加载到本地数据库中。
```
uv run universe-bang 5000 1234
# 加载 .env.supabase 到环境(如果尚未完成)
set -a && source .env.supabase && set +a
uv run -m gradientbang.scripts.load_universe_to_supabase --from-json world-data/
```
### 步骤 2:边缘函数
从现在开始,您需要运行 Supabase 边缘函数进程:
```
npx supabase functions serve --workdir deployment --no-verify-jwt --env-file .env.supabase
```
您需要在数据库中创建一个用户账户以便登录。目前没有用户界面,因此您可以通过以下两种方式之一完成:
选项 1:本地 Supabase 提供了 Studio 仪表板:http://127.0.0.1:54323/project/default/auth/users
点击右侧的“添加用户”绿色按钮,然后点击“创建新用户”。输入用户名和密码,并保持“自动确认用户?”已勾选。
选项 2:通过终端:
```
curl -X POST http://127.0.0.1:54321/functions/v1/register \
-H "Content-Type: application/json" \
-d '{
"email": "test@example.com",
"password": "secret123"
}'
```
### 步骤 3:运行 Pipecat 机器人和游戏客户端
安装 Python 依赖:
```
uv sync --all-groups
```
复制 `env.bot.example` 文件并添加您的密钥(完整的密钥列表请参考 [机器人环境变量](#bot-env-bot)):
> 注意:在本地开发中请保持 `BOT_USE_KRISP` 设置为 `0`([参考此处](https://docs.pipecat.ai/deployment/pipecat-cloud/guides/krisp-viva#local-development))
```
cp env.bot.example .env.bot
```
最后,运行机器人进程:
```
# 用于本地开发和 SmallWebRTCTransport 的简单方法
uv run bot
# 添加 "-t daily --host 0.0.0.0" 以使用 Daily 传输并监听所有接口(例如与 Tailscale 配合使用)
uv run bot -t daily --host 0.0.0.0
```
#### 本地池化模式
默认情况下,机器人通过 HTTP 调用 Supabase 边缘函数来执行所有游戏服务器操作。这会增加延迟(平均 500 毫秒,冷启动最长可达 10 秒)。如果在 `.env.bot` 中设置 `LOCAL_API_POSTGRES_URL` 为 Supabase 会话池连接字符串,机器人将直接在本地 Postgres 上运行等效函数逻辑,完全绕过边缘函数网络跳转。这在生产环境中特别有用,此时机器人容器与数据库位于同一位置。
### 步骤 4:运行 Web 客户端
如果其他组件都在运行,客户端应该可以无需额外环境变量直接启动。
```
cd client/
pnpm i
pnpm run dev
```
您可以在 `client/app` 目录中创建 `.env` 文件来配置客户端:
```
cd client/app/
cp env.example .env.local
```
至此应该已包含所有必需内容。您现在可以打开 http://localhost:5173,使用设置的用户名和密码登录,创建角色并开始对话!
在我的 Linux 电脑上运行 `ufw` 防火墙时,我需要添加一条防火墙规则,允许 Supabase 的 Docker 容器之间互相通信:
```
# 运行以下之一以修复:
# 允许来自所有 Docker 网络
sudo ufw allow from 172.16.0.0/12 to any port 7860 proto tcp
# 或更严格的限制——仅 Supabase 桥接网络
sudo ufw allow from 172.18.0.0/16 to any port 7860 proto tcp
```
## 本地运行
总结一下,要在本地运行完整堆栈,您需要同时运行 **Supabase**、**边缘函数**、**客户端** 和 **机器人**。
```
# 启动 Supabase(这在后台运行,因此您无需保持终端打开)
npx supabase start --workdir deployment # and don't forget to "npx supabase stop --workdir deployment" when you're done!)
# 在不同终端窗口中保持以下窗口打开:
npx supabase functions serve --workdir deployment --no-verify-jwt --env-file .env.supabase
uv run bot
cd client && pnpm run dev
```
### 查找角色 ID
要通过名称查找现有角色的 ID:
```
set -a && source .env.supabase && set +a
uv run character-lookup "SpaceTrader"
```
### 运行 NPC 任务代理
使用基于文本的任务代理以自主方式运行任务:
```
set -a && source .env.supabase && set +a
uv run npc-run "Explore and find 5 new sectors"
```
带查找角色的示例:
```
set -a && source .env.supabase && set +a
uv run npc-run $(uv run character-lookup "SpaceTrader") "Check my status and move to an adjacent sector"
```
### 保留用户账户的数据库重置
```
# local
scripts/reset-world.sh --env .env.supabase 1000 42
# live
scripts/reset-world.sh --env .env.cloud 1000 42
```
### 生成宇宙地图可视化
```
uv run -m gradientbang.scripts.universe_svg
```
这将生成 `artifacts/universe-map.svg`,展示扇区、跃迁点、联邦空间(高亮显示)和大型港口。
### 本地相邻开发(Tailscale)
如果您希望在某一台计算机上运行 Gradient Bang 堆栈并在另一台设备上访问,可以使用 [Tailscale](https://tailscale.com/) 最简便。配合 `tailscale serve` 和一些配置更改,即可通过 Tailnet 访问。`systemd` 文件夹中包含另一个服务 `gradient-bang-tailscale.service`,它运行一些 `tailscale serve` 命令并适配一些环境变量。下面的代码片段中,`apollo` 是您的机器名,`seahorse-peacock` 是您的 Tailscale DNS 名称。[按照这些说明](https://tailscale.com/docs/how-to/set-up-https-certificates) 为您的 Tailnet 设置 HTTPS,然后在此机器上运行 `tailscale cert`。(在 Tailscale 仪表板中,您也可以进入 DNS 部分设置一个有趣的名称,例如 seahorse-peacock,而不是随机的十六进制值。)
对这些环境文件做出以下更改:
```
# .env.supabase
DAILY_API_KEY=7df... # Your Daily API key, because you'll want to run the Daily transport
SUPABASE_URL=https://apollo.seahorse-peacock.ts.net:8443/edge
# .env.bot
SUPABASE_URL=https://apollo.seahorse-peacock.ts.net:8443/edge
DAILY_API_KEY=7df...
# client/app/.env.local
VITE_SERVER_URL=https://apollo.seahorse-peacock.ts.net:8443/edge/functions/v1
VITE_PIPECAT_TRANSPORT=daily
VITE_BOT_URL=https://apollo.seahorse-peacock.ts.net:8443/bot
```
打开 `client/app/vite.config.js`,并添加 `host` 和 `allowedHosts` 行,使底部的 `server` 对象如下所示:
```
server: {
host: '0.0.0.0',
allowedHosts: true,
watch: {
// Watch the starfield dist for changes
ignored: ["!**/node_modules/@gradient-bang/**"],
},
},
```
然后运行一些 `tailscale serve` 命令以及其它服务。
```
# 如果您未使用 gradient-bang-tailscale.service(它会自动运行这些命令),请运行以下命令
tailscale serve --bg --https 443 http://localhost:5173
tailscale serve --bg --https 8443 --set-path=edge http://localhost:54321
tailscale serve --bg --https 8443 --set-path=bot http://localhost:7860
# 全部关闭:
tailscale serve reset
# 启动 Supabase(这在后台运行,因此您无需保持终端打开)
npx supabase start --workdir deployment # and don't forget to "npx supabase stop --workdir deployment" when you're done!)
# 在不同终端窗口中保持以下窗口打开:
npx supabase functions serve --workdir deployment --no-verify-jwt --env-file .env.supabase
# 为机器人添加传输和主机选项
uv run bot -t daily --host 0.0.0.0
cd client && pnpm run dev
```
在 Linux 上,我使用 `systemd` 来管理所有这些服务。`systemd` 文件夹包含这四个组件的服务文件,以及一个 `gradient-bang.target` 文件,允许我执行以下操作:
```
# 开始工作
systemctl --user start gradient-bang.target
# 重新启动所有服务,因为有时您需要格外小心
systemctl --user restart gradient-bang.target
# 把我的电脑还给我
systemctl --user stop gradient-bang.target
```
但实际上,我创建了一个别名,让操作更简单:
```
gb() {
systemctl --user "$@" gradient-bang.target
}
# 现在我可以只执行以下命令来启动:
gb start
```
## 运行测试
### 边缘函数测试(Deno)
游戏服务器(边缘函数)的集成测试位于 `deployment/supabase/functions/tests/`。
**依赖项**:Docker、Node.js / npx(Supabase CLI 会自动安装 Deno)。
无需 `.` 文件——测试运行器会在临时端口上创建独立的 Supabase 堆栈并自动提取凭据。
```
bash deployment/supabase/functions/tests/run_tests.sh
```
运行器会启动一个隔离的 Supabase 实例,运行带覆盖率的测试,打印覆盖率报告,然后自动清理所有内容。
### Python 测试(pytest)
Python 测试位于 `tests/` 目录中,并使用 pytest 标记进行分类。
```
# 运行所有单元测试(无需服务器)
uv run pytest -m unit -v
# 仅运行 LLM 行为测试(上下文摘要等)
uv run pytest -m llm -v
```
可用标记:`unit`、`llm`、`integration`、`stress`、`live_api`。
### 单元测试
`tests/unit/` 目录包含针对机器人代理层的单元测试——包括 EventRelay 路由、VoiceAgent 工具注册、TaskAgent 构造,以及连接真实对象与模拟外部边界的 EventRelay↔VoiceAgent 集成测试。
```
# 运行所有单元测试
uv run pytest -m unit -v
# 仅运行中继↔语音集成测试
uv run pytest tests/unit/test_voice_relay_integration.py -v
```
### Python 集成测试(需要数据库)
Python 集成测试需要一个已播种的 Supabase 数据库。一个全流程脚本会处理生命周期:它在不同端口(54421+)上启动隔离的 Supabase 实例,通过 `test_reset` 进行播种,运行 `pytest -m integration`,然后清理所有内容。开发数据库不会被修改。
集成测试在直接运行 `uv run pytest`(不带脚本)时会被自动跳过。
## 部署
如果您希望在云端运行自己的游戏世界,您需要一个 Supabase 项目。
### 创建新的 Supabase 项目
```
npx supabase login
npx supabase projects create gb-game-server \
--db-password \
--region us-west-1 \
--org-id \
--size small
```
从 [/deployment/supabase](/deployment/supabase/) 模板推送配置:
```
npx supabase link --workdir deployment
npx supabase config push --workdir deployment
```
### 创建 `.env.cloud` 环境
一键生成(提示输入项目引用和数据库密码)。
注意:这将创建一个需要从您的机器启用 IPv6 路由的 `POSTGRES_POOLER_URL`。如果无法使用 IPv6,您需要点击 Supabase 项目仪表板顶部的“”按钮,查找“方法:会话池器”连接字符串,并将 `POSTGRES_POOLER_URL` 改为会话池器格式。
加载环境变量,以便后续步骤可以执行:
```
set -a && source .env.cloud && set +a
```
### 推送数据库结构
#### 可选:重置远程数据库
```
npx supabase link --workdir deployment
npx supabase db reset --linked --workdir deployment
npx supabase db push --workdir deployment
```
将 SQL 迁移应用到关联的项目:
```
npx supabase migration up --workdir deployment/ --db-url "$POSTGRES_POOLER_URL"
```
### 战斗回合解析定时任务配置(云端)
在迁移完成后设置 `app_runtime_config` 中的 Supabase URL 和边缘令牌:
```
scripts/setup-production-combat-tick.sh
```
验证配置:
```
psql "$POSTGRES_POOLER_URL" -c "SELECT key, updated_at FROM app_runtime_config WHERE key IN ('supabase_url','edge_api_token');"
```
### 部署边缘函数
将边缘函数部署到您的 Supabase 项目。部署过程中可能会出现关于装饰器标志的警告,您可以忽略。
```
npx supabase functions deploy --workdir deployment/ --no-verify-jwt
```
添加所需的密钥。请忽略关于 SUPABASE\_ 变量的警告,它们会在项目中自动设置。
> 注意:稍后我们需要添加 `BOT_START_URL` 和 `BOT_START_API_KEY`。
#### 添加世界数据
如果您还没有宇宙,可以按如下方式创建:
```
uv run universe-bang 5000 1234
```
现在将其加载到您的 Supabase 项目中:
```
uv run -m gradientbang.scripts.load_universe_to_supabase --from-json world-data/
```
加载任务定义(或使用 `/load-quests`):
```
uv run -m gradientbang.scripts.load_quests_to_supabase --from-json quest-data/
```
### 将机器人部署到 Pipecat 云
#### 为机器人创建 `.env.bot`
请参考 [机器人环境变量](#bot-env-bot) 获取完整列表:
```
cp env.bot.example .env.bot
# 填写您的 API 密钥和 Supabase 凭据
```
在 Pipecat 云中创建新的密钥集:
```
pipecat cloud secrets set gb-bot-secrets --file .env.bot
```
构建并部署机器人:
```
docker build -f deployment/Dockerfile.bot -t gb-bot:latest .
docker push gb-bot:latest
cd deployment/
pipecat cloud deploy
# ... 或者是公开的
# pipecat cloud deploy --no-credentials
```
#### 更新边缘函数中的机器人启动 URL
创建并记下公共 API 密钥:
```
pipecat cloud organizations keys create
```
将机器人集成变量添加到 `.env.cloud`:
```
BOT_START_URL=https://api.pipecat.daily.co/v1/public/{AGENT_NAME}/start
BOT_START_API_KEY=...
```
应用到边缘函数:
```
npx supabase secrets set --env-file .env.cloud
```
#### 将客户端指向生产环境
```
# client/app/.env
VITE_SERVER_URL=https://{SUPABASE_PROJECT_ID}.supabase.co/functions/v1
VITE_PIPECAT_TRANSPORT=daily
```
```
cd client/
pnpm run dev
```
## 环境变量
### 边缘函数(`.env.supabase` / `.env.cloud`)
| 变量 | 是否必需 | 默认值 | 描述 |
|------|----------|--------|------|
| `SUPABASE_URL` | 是 | — | Supabase 项目 URL |
| `SUPABASE_ANON_KEY` | 是 | — | 公开的 Supabase 匿名 JWT 密钥 |
| `SUPABASE_SERVICE_ROLE_KEY` | 是 | — | 服务角色密钥(绕过 RLS) |
| `POSTGRES_POOLER_URL` | 是 | — | PgBouncer 池化的 PostgreSQL 连接字符串 |
| `EDGE_API_TOKEN` | 是 | — | 用于通过 `X-API-Token` 标头进行内部请求的令牌;未设置时本地开发跳过验证 |
| `BOT_START_URL` | 否 | `http://host.docker.internal:7860/start` | 机器人 `/start` 端点的 URL,用于创建语音聊天会话 |
| `BOT_START_API_KEY` | 否 | — | 向机器人启动端点进行身份验证的 Bearer 令牌 |
| `MOVE_DELAY_SCALE` | 否 | `1.0` | 移动延迟的乘数(本地开发可设为 `0.25` 以加快速度) |
| `MOVE_DELAY_SECONDS_PER_TURN` | 否 | `0.667` | 每轮转向的基础移动延迟(秒) |
| `COMBAT_TICK_BATCH_SIZE` | 否 | `20` | 每轮处理的最大战斗遭遇数 |
| `COMBAT_ROUND_TIMEOUT` | 否 | `30` | 战斗轮次自动解析前的秒数 |
| `SHIELD_REGEN_PER_ROUND` | 否 | `10` | 每轮恢复的护盾值 |
| `SALVAGE_TTL_SECONDS` | 否 | `900` | 残骸的 TTL(秒) |
| `CHARACTER_SPAWN_MP_DISTANCE` | 否 | `8` | 新角色生成位置与最近大型港口的图距离(最小为 `2`) |
| `EDGE_ADMIN_PASSWORD` | 否 | — | 仅管理端点使用的明文密码 |
| `EDGE_ADMIN_PASSWORD_HASH` | 否 | — | 明文密码的 SHA-256 哈希(可替代明文) |
### 机器人(`.env.bot`)
#### API 密钥
| 变量 | 是否必需 | 描述 |
|------|----------|------|
| `DEEPGRAM_API_KEY` | 是 | [Deepgram](https://console.deepgram.com) 的语音转文本 API 密钥 |
| `CARTESIA_API_KEY` | 是 | [Cartesia](https://play.cartesia.ai) 的文本转语音 API 密钥 |
| `GOOGLE_API_KEY` | 是 | [Google AI Studio](https://aistudio.google.com/apikey) 的 Gemini LLM API 密钥 |
| `ANTHROPIC_API_KEY` | 否 | [Anthropic](https://console.anthropic.com) 的 Claude LLM API 密钥 |
| `OPENAI_API_KEY` | 否 | [OpenAI](https://platform.openai.com) 的 API 密钥(在使用 OpenAI 作为 LLM 提供方时使用) |
#### Supabase 与连接性
| 变量 | 是否必需 | 默认值 | 描述 |
|------|----------|--------|------|
| `SUPABASE_URL` | 是 | — | Supabase 项目 URL |
| `SUPABASE_SERVICE_ROLE_KEY` | 是 | — | 用于数据库访问的服务角色密钥 |
| `EDGE_API_TOKEN` | 是 | — | 用于身份验证的边缘函数调用令牌 |
| `DAILY_API_KEY` | 否 | — | [Daily](https://www.daily.co/) API 密钥(用于 Daily 传输) |
| `LOCAL_API_POSTGRES_URL` | 否 | — | 用于在机器人容器内直接运行边缘函数逻辑的 Postgres 会话池连接字符串,绕过 Supabase 网络开销 |
#### LLM 配置
| 变量 | 是否必需 | 默认值 | 描述 |
|------|----------|--------|------|
| `VOICE_LLM_PROVIDER` | 是 | — | 语音 LLM 提供方(`google`、`anthropic`、`openai`) |
| `VOICE_LLM_MODEL` | 是 | — | 语音 LLM 模型名称 |
| `VOICE_LLM_THINKING_BUDGET` | 否 | `0` | 语音代理的扩展思考 Token 预算 |
| `VO_LLM_FUNCTION_CALL_TIMEOUT_SECS` | 否 | `20` | 语音代理工具调用超时(秒) |
| `TASK_LLM_PROVIDER` | 是 | — | 任务代理 LLM 提供方 |
| `TASK_LLM_MODEL` | 是 | — | 任务代理 LLM 模型名称 |
| `TASK_LLM_THINKING_BUDGET` | 否 | `4096` | 任务代理的扩展思考 Token 预算 |
| `TASK_LLM_FUNCTION_CALL_TIMEOUT_SECS` | 否 | `20` | 任务代理工具调用超时(秒) |
| `TASK_AGENT_TIMEOUT` | 否 | — | 任务代理最大生命周期(秒),超时被取消(例如 `1800` 表示 30 分钟) |
| `UI_AGENT_LLM_PROVIDER` | 是 | — | UI 代理 LLM 提供方 |
| `UI_AGENT_LLM_MODEL` | 是 | — | UI 代理 LLM 模型名称 |
| `UI_AGENT_LLM_THINKING_BUDGET` | 否 | `0` | UI 代理的扩展思考 Token 预算 |
| `CONTEXT_SUMMARIZATION_MESSAGE_LIMIT` | 否 | `200` | 上下文摘要化前的最大未汇总消息数 |
#### UI 代理调优
| 变量 | 默认值 | 描述 |
|------|--------|------|
| `UI_AGENT_STATUS_TIMEOUT_SECS` | `10` | 状态查询超时(秒) |
| `UI_AGENT_PORTS_LIST_TIMEOUT_SECS` | `15` | 端口列表超时(秒) |
| `UI_AGENT_SHIPS_LIST_TIMEOUT_SECS` | `15` | 船只列表超时(秒) |
| `UI_AGENT_COURSE_PLOT_TIMEOUT_SECS` | `25` | 航线规划超时(秒) |
| `UI_AGENT_PORTS_LIST_STALE_SECS` | `60` | 端口列表陈旧阈值(秒) |
| `UI_AGENT_INTENT_REQUEST_DELAY_SECS` | `2.0` | 意图请求延迟(秒) |
| `UI_AGENT_SHIPS_CACHE_TTL_SECS` | `60` | 船只列表缓存 TTL(秒) |
#### 测试与调试
| 变量 | 默认值 | 描述 |
|------|--------|------|
| `BOT_IDLE_REPORT_ENABLED` | `1` | 启用空闲任务状态报告(`0` 禁用,处理器保持为直通模式) |
| `BOT_IDLE_REPORT_TIME` | `7.5` | 沉默多少秒后机器人给出单句任务状态更新 |
| `BOT_IDLE_REPORT_COOLDOWN` | `30` | 连续报告之间的最小间隔(秒) |
| `BOT_USE_KRISP` | `0` | 启用 Krisp 降噪(`1` 生产,`0` 本地开发) |
| `BOT_TEST_CHARACTER_ID` | — | 硬编码角色 ID 用于测试 |
| `BOT_TEST_CHARACTER_NAME` | — | 硬编码角色名称用于测试 |
| `BOT_TEST_NPC_CHARACTER_NAME` | — | 硬编码 NPC 名称用于测试 |
| `LOG_LEVEL` | `INFO` | 日志级别(`DEBUG`、`INFO`、`WARNING` 等) |
| `TOKEN_USAGE_LOG` | — | Token 用量指标 CSV 文件路径 |
#### 可选集成
| 变量 | 默认值 | 描述 |
|------|--------|------|
| `WANDB_API_KEY` | — | [Weights & Biases](https://wandb.ai) API 密钥,用于 Weave 追踪 |
| `WEAVE_PROJECT` | `gradientbang` | Weave 项目名称 |
| `SMART_TURN_S3_BUCKET` | — | S3 存储桶用于智能回合音频 |
| `AWS_ACCESS_KEY_ID` | — | AWS 访问密钥(用于 S3 智能回合) |
| `AWS_SECRET_ACCESS_KEY` | — | AWS 密钥(用于 S3 智能回合) |
| `AWS_REGION` | `us-east-1` | AWS 区域 |
### 认证与密钥快速指南
- **网关检查(Supabase)**:默认 `verify_jwt=true` 需要 `Authorization: Bearer $SUPABASE_ANON_KEY`(或用户访问令牌)。生产环境中保持开启;仅用于本地开发的 `--no-verify-jwt` 可选。
- **应用网关(游戏玩法)**:每个游戏玩法边缘函数都需要 `X-API-Token: $EDGE_API_TOKEN`,并在内部使用 `SUPABASE_SERVICE_ROLE_KEY` 进行数据库访问。
- **机器人/客户端调用**:发送两者标头。匿名密钥可以公开,但游戏玩法令牌必须保密。
- **生产环境必需密钥**:`SUPABASE_URL`、`SUPABASE_ANON_KEY`、`SUPABASE_SERVICE_ROLE_KEY`、`POSTGRES_POOLER_URL`、`EDGE_API_TOKEN`(以及机器人相关环境变量)。
- **战斗定时任务**:确保 `app_runtime_config` 中设置了 `supabase_url` 和 `edge_api_token` 的生产环境值(可使用 `scripts/setup-production-combat-tick.sh`)。
## Claude Code 技能参考
该项目包含一组 [Claude Code](https://docs.anthropic.com/en/docs/claude-code) 技能(斜杠命令),可自动化常见的开发与测试流程。请在 Claude Code 中使用 `/skill-name` 调用。
| 技能 | 描述 | 参数 |
|------|------|------|
| `/init` | 从全新克隆完成完整项目设置。安装依赖、启动 Supabase、生成环境文件、创建世界数据,并提示输入 API 密钥。 | 无(交互式提示输入 API 密钥) |
| `/migrate` | 应用待处理的 Supabase 数据库迁移。应用前会审核 SQL,不会重置或删除数据。 | `local`、`dev` 或 `prod` |
| `/reset-world` | 重置游戏数据库,生成全新宇宙、加载任务、播种战斗定时任务配置。 | 环境(`local`/`cloud`)、扇区数(默认 `5000`)、种子(可选) |
| `/load-quests` | 从 `quest-data/` JSON 文件加载任务定义到 Supabase。 | 模式(`upsert`/`force`)、是否为干运行(是/否) |
| `/character-create` | 通过 `user_character_create` 边缘函数创建新游戏角色。 | 邮箱、密码、角色名(全部交互式提示) |
| `/npc ` | 以后台方式运行一个自主 AI 任务代理作为游戏角色。 | 角色名(参数或提示)、任务描述(提示) |
| `/combat ` | 为测试启动一次战斗遭遇。显示扇区上下文后开始。 | 角色名或飞船 UUID |
| `/destroy-ship` | 为测试销毁飞船——软删除、发布事件、伪角色清理。 | 飞船 UUID(提示) |
| `/restore-ship` | 为测试恢复已销毁飞船——清除销毁标志、恢复状态、重建伪角色。 | 飞船 UUID(提示) |
| `/deploy ` | 完整部署:先部署边缘函数,再部署机器人到 Pipecat 云。 | `dev` 或 `prod` |
| `/deploy-functions` | 部署所有 Supabase 边缘函数。 | `dev` 或 `prod` |
| `/deploy-bot` | 通过云端构建将机器人部署到 Pipecat 云。 | `dev` 或 `prod` |
Gradient Bang 是一个在线多人宇宙,您可以在其中探索、交易、战斗并与其它玩家和 LLM 协作。游戏中的所有内容都是一个 AI 代理,包括您指挥的飞船。
该项目展示了实时代理工作流的全部能力,例如多任务处理、高级工具调用和低延迟语音。
➡️ [加入测试](https://www.gradient-bang.com)
## 快速开始(Claude Code)
如果您已安装 [Claude Code](https://docs.anthropic.com/en/docs/claude-code),从全新克隆快速启动的最快方式是:
```
/init
```
这条单一命令会安装依赖、启动 Supabase、生成环境文件、创建世界数据,并引导您提供 API 密钥。请参阅下方的 [初始设置](#initial-setup) 了解等效的手动步骤。
本 README 中描述的许多步骤也都有对应的 Claude Code 技能——请查找 `/skill-name` 调用提示。参见底部的完整 [Claude Code 技能参考](#claude-code-skills-reference)。
## 目录
- [初始设置](#initial-setup)
- [本地运行](#running-locally)
- [部署](#deployment)
- [环境变量](#environment-variables)
- [认证与密钥快速指南](#auth--secrets-quick-guide)
- [Claude Code 技能参考](#claude-code-skills-reference)
## 初始设置
如果您希望参与 Gradient Bang 的开发,第一步是让整个应用在本地运行。需要运行四个组件:
- **Supabase** 是“游戏服务器”。我们使用其 PostgreSQL 数据库(包含一些重要的 PL/pgSQL 函数)进行存储,并通过 [Subabase Edge Functions](https://supabase.com/docs/guides/functions) 提供 API。Supabase 提供 [CLI 工具](https://supabase.com/docs/guides/local-development) 可在本地运行其堆栈用于开发。
- **边缘函数** 开发服务器用于运行 `deployment/supabase/functions` 文件夹中的函数。
- **客户端** 是游戏 UI,使用 React 构建并通过 `turbo` 部署到 Vercel。
- **机器人** 是一个 Pipecat 机器人,部署到 [Pipecat 云](https://docs.pipecat.ai/deployment/pipecat-cloud/introduction)。
### 前置条件
- **uv**:Python 包管理器
- **[Supabase 账户](https://supabase.com/)**:游戏服务器函数、认证与数据库
- **Docker**:运行本地 Supabase 堆栈和代理部署所必需
- **Node.js 18+**:用于边缘函数部署和客户端
- (可选) **[Pipecat 云账户](https://docs.pipecat.ai/deployment/pipecat-cloud/introduction)**:生产级代理托管
- (可选) **[Supabase CLI](https://supabase.com/docs/guides/local-development/cli/getting-started)**:如果无法使用 `npx`,可直接全局安装 CLI 替代
### 步骤 1:设置 Supabase
首先运行 `supabase start`。Supabase 包含多个服务,就像穿着一件风衣。此命令会下载并运行所有相关的 Docker 镜像。运行后,您会看到多个服务在不同端口监听,这些端口随后会被使用。
```
npx supabase start --workdir deployment/
```
接下来,获取创建本地 Supabase 堆栈配置所需的 API 密钥并生成 `.env.supabase` 文件:
```
tok=$(openssl rand -hex 32)
npx supabase status -o env --workdir deployment | awk -F= -v tok="$tok" '
$1=="API_URL" {v=$2; gsub(/"/,"",v); print "SUPABASE_URL=" v}
$1=="ANON_KEY" {v=$2; gsub(/"/,"",v); print "SUPABASE_ANON_KEY=" v}
$1=="SERVICE_ROLE_KEY" {v=$2; gsub(/"/,"",v); print "SUPABASE_SERVICE_ROLE_KEY=" v}
END {
print "POSTGRES_POOLER_URL=postgresql://postgres:postgres@db:5432/postgres"
print "EDGE_API_TOKEN=" tok
}
' > .env.supabase
```
接着,在 `supabase start` 之后(以及任何手动数据库重置后)运行此辅助命令。它会设置一些重要的 PL/pgSQL 函数,以保持战斗回合自动结算:
```
scripts/supabase-reset-with-cron.sh
```
接下来,使用要绘制的扇区数量和随机种子运行宇宙脉冲脚本。这会创建世界数据。然后,将这些数据加载到本地数据库中。
```
uv run universe-bang 5000 1234
# 加载 .env.supabase 到环境(如果尚未完成)
set -a && source .env.supabase && set +a
uv run -m gradientbang.scripts.load_universe_to_supabase --from-json world-data/
```
### 步骤 2:边缘函数
从现在开始,您需要运行 Supabase 边缘函数进程:
```
npx supabase functions serve --workdir deployment --no-verify-jwt --env-file .env.supabase
```
您需要在数据库中创建一个用户账户以便登录。目前没有用户界面,因此您可以通过以下两种方式之一完成:
选项 1:本地 Supabase 提供了 Studio 仪表板:http://127.0.0.1:54323/project/default/auth/users
点击右侧的“添加用户”绿色按钮,然后点击“创建新用户”。输入用户名和密码,并保持“自动确认用户?”已勾选。
选项 2:通过终端:
```
curl -X POST http://127.0.0.1:54321/functions/v1/register \
-H "Content-Type: application/json" \
-d '{
"email": "test@example.com",
"password": "secret123"
}'
```
### 步骤 3:运行 Pipecat 机器人和游戏客户端
安装 Python 依赖:
```
uv sync --all-groups
```
复制 `env.bot.example` 文件并添加您的密钥(完整的密钥列表请参考 [机器人环境变量](#bot-env-bot)):
> 注意:在本地开发中请保持 `BOT_USE_KRISP` 设置为 `0`([参考此处](https://docs.pipecat.ai/deployment/pipecat-cloud/guides/krisp-viva#local-development))
```
cp env.bot.example .env.bot
```
最后,运行机器人进程:
```
# 用于本地开发和 SmallWebRTCTransport 的简单方法
uv run bot
# 添加 "-t daily --host 0.0.0.0" 以使用 Daily 传输并监听所有接口(例如与 Tailscale 配合使用)
uv run bot -t daily --host 0.0.0.0
```
#### 本地池化模式
默认情况下,机器人通过 HTTP 调用 Supabase 边缘函数来执行所有游戏服务器操作。这会增加延迟(平均 500 毫秒,冷启动最长可达 10 秒)。如果在 `.env.bot` 中设置 `LOCAL_API_POSTGRES_URL` 为 Supabase 会话池连接字符串,机器人将直接在本地 Postgres 上运行等效函数逻辑,完全绕过边缘函数网络跳转。这在生产环境中特别有用,此时机器人容器与数据库位于同一位置。
### 步骤 4:运行 Web 客户端
如果其他组件都在运行,客户端应该可以无需额外环境变量直接启动。
```
cd client/
pnpm i
pnpm run dev
```
您可以在 `client/app` 目录中创建 `.env` 文件来配置客户端:
```
cd client/app/
cp env.example .env.local
```
至此应该已包含所有必需内容。您现在可以打开 http://localhost:5173,使用设置的用户名和密码登录,创建角色并开始对话!
在我的 Linux 电脑上运行 `ufw` 防火墙时,我需要添加一条防火墙规则,允许 Supabase 的 Docker 容器之间互相通信:
```
# 运行以下之一以修复:
# 允许来自所有 Docker 网络
sudo ufw allow from 172.16.0.0/12 to any port 7860 proto tcp
# 或更严格的限制——仅 Supabase 桥接网络
sudo ufw allow from 172.18.0.0/16 to any port 7860 proto tcp
```
## 本地运行
总结一下,要在本地运行完整堆栈,您需要同时运行 **Supabase**、**边缘函数**、**客户端** 和 **机器人**。
```
# 启动 Supabase(这在后台运行,因此您无需保持终端打开)
npx supabase start --workdir deployment # and don't forget to "npx supabase stop --workdir deployment" when you're done!)
# 在不同终端窗口中保持以下窗口打开:
npx supabase functions serve --workdir deployment --no-verify-jwt --env-file .env.supabase
uv run bot
cd client && pnpm run dev
```
### 查找角色 ID
要通过名称查找现有角色的 ID:
```
set -a && source .env.supabase && set +a
uv run character-lookup "SpaceTrader"
```
### 运行 NPC 任务代理
使用基于文本的任务代理以自主方式运行任务:
```
set -a && source .env.supabase && set +a
uv run npc-run 标签:AI代理, AI驱动游戏, Claude Code, DLL 劫持, LLM集成, PostgreSQL, SEO, Supabase, 交易系统, 低延迟语音, 关键词, 协作游戏, 在线多人游戏, 多人宇宙, 多任务处理, 大语言模型, 宇宙探索, 实时交互, 实时工作流, 战斗系统, 测试用例, 游戏服务器, 玩家协作, 网络游戏, 自动化攻击, 语音交互, 请求拦截, 边缘函数, 逆向工具, 高级工具调用