# modelping · 萌芽Ping 在 Cloudflare Workers 上运行的大模型 API **流式首字延迟**与**可用性**监控面板:React + Vite 前端(Static Assets CDN)+ D1 存储(默认保留 30 天探测记录)+ 每分钟 Cron 调度。 ## 目录结构 - [`frontend/`](frontend/):React 前端(入口 [`frontend/index.html`](frontend/index.html)、源码 [`frontend/src/`](frontend/src/));根目录 [`vite.config.ts`](vite.config.ts) 将 `root` 指向此处,[`public/`](public/) 仍为静态资源目录。 - [`worker/`](worker/):Cloudflare Worker — Hono API、D1、加密与定时探测调度;入口见 [`wrangler.json`](wrangler.json) 的 `main` 字段。 ## 功能概要 - 管理端配置:API 根地址、API Key、模型名、协议(**OpenAI Chat Completions 经典** / **OpenAI Responses 新版** / Claude Anthropic)。 - 探测间隔:1、5、10、30、60、360(分钟)。 - 公开仪表盘:24h / 30d 可用率、按日时间条、最近状态码与首字延迟。 - 管理员入口:访问 **`/admin?token=`**(与 `.dev.vars` / Secrets 中 `ADMIN_TOKEN` 一致即可,示例 `shumengya520`)。校验通过后 token 写入当前浏览器 `sessionStorage`,并自动 **`replace` 到 `/admin`**(从地址栏去掉 token,减少泄露)。 - 一键部署:`npm run build && wrangler deploy`(Cloudflare Vite 插件会自动使用 `dist/modelping` 构建产物与资源目录)。 ## 前置条件 - Node.js 20+ - Cloudflare 账号与 [Wrangler](https://developers.cloudflare.com/workers/wrangler/) 登录(`npx wrangler login`) ## 初始化 D1 ```bash npx wrangler d1 create modelping ``` 将输出中的 `database_id` 写入根目录 [`wrangler.json`](wrangler.json) 里 `d1_databases[0].database_id`(替换 `replace-with-your-d1-database-id`)。 应用迁移(本地与远程各执行一次按你开发需要;升级含「OpenAI 新版 Responses」协议时请确保已执行最新 SQL): ```bash npx wrangler d1 migrations apply modelping --local npx wrangler d1 migrations apply modelping --remote ``` ## 密钥与环境变量 | 变量 | 说明 | |------|------| | `ADMIN_TOKEN` | 管理 API Bearer Token;本地可复制 [`.dev.vars.example`](.dev.vars.example) 为 `.dev.vars`。生产务必执行 `npx wrangler secret put ADMIN_TOKEN`。 | | `ENCRYPTION_KEY` | 可选。32 字节 Base64,或任意字符串(将做哈希派生)。不设时,用 `ADMIN_TOKEN` 派生加密密钥(仅建议用于内网/演示)。 | 本地开发: ```bash cp .dev.vars.example .dev.vars # 编辑 .dev.vars ``` ## 开发与部署 ```bash npm install npm run dev ``` 生产构建与部署: ```bash npm run deploy ``` 等价于 `tsc -b && vite build && wrangler deploy`。Wrangler 会使用重定向后的 `dist/modelping/wrangler.json` 上传 Worker 与 `dist/client` 静态资源。 ## 出现「服务端未配置 ADMIN_TOKEN」(503)怎么修 含义:当前运行的 Worker **读不到** `ADMIN_TOKEN`(既不是 Secret,本地也没从 `.dev.vars` 注入)。 **线上(你已 `wrangler deploy` 的网站)** `.dev.vars` **只对本地 dev 有效**,不会跟着部署上去。在项目目录执行: ```bash npx wrangler secret put ADMIN_TOKEN ``` 按提示粘贴与 URL 里一致的口令(例如 `shumengya520`)。成功后无需改代码,再访问 `/admin?token=...` 即可。 也可使用快捷脚本:`npm run secret:admin`(同上,仍是交互式输入 Secret)。 **本地(`npm run dev`)** 1. 项目根目录必须有 **`.dev.vars`**,且**第一行**建议直接写:`ADMIN_TOKEN=你的口令`(不要先写一大段注释,部分环境解析更稳)。 2. 保存后 **关掉 dev 再重新执行** `npm run dev`。 3. 浏览器访问的必须是 dev 打印出的地址(如 `http://localhost:5173/admin?token=你的口令`),不要误用线上域名或 `vite preview` 的静态站(可能没有 Worker)。 ## 管理员登录排障(`/admin?token=...` 进不去) 1. 打开浏览器 **开发者工具 → Network**,访问 `/admin?token=你的口令`,查看 **`/api/admin/ping`**: - **(失败 / 无记录)**:当前页面没有打到本项目的 Worker。本地请使用 **`npm run dev`**(Cloudflare Vite 插件会同时起前端与 Worker);不要只用纯静态预览访问,否则没有 `/api/*`。 - **503 + `admin_token_not_configured`**:Worker 上 **没有可用的 `ADMIN_TOKEN`**。本地检查项目根目录 **`.dev.vars`** 并重启 dev;已部署环境必须执行 **`npx wrangler secret put ADMIN_TOKEN`**(`.dev.vars` **不会**随 `deploy` 传到线上)。 - **401**:请求里的 token 与 `ADMIN_TOKEN` **不一致**(含多余空格时,服务端与 URL 两侧已做 trim,但仍需内容一致)。 - **200**:校验已通过;若仍停在说明页,请看 **Application → Session Storage** 是否写入 `modelping_admin_token`,并尝试硬性刷新或排除扩展拦截。 2. 未登录页面上方如显示 **红色提示条**,即为本次 URL 校验失败原因(此前固定文案下不会显示,容易造成「后台没做」的误解)。 ## 默认内网口令(仅示例) 本地示例默认 Admin Token 为 `shumengya520`。**线上环境请在 Dashboard 或 `wrangler secret put` 修改为强随机字符串。** ## API 摘要 | 方法 | 路径 | 认证 | 说明 | |------|-----|------|------| | GET | `/api/monitors` | 无 | 公开列表与聚合统计 | | GET | `/api/monitors/:id` | 无 | 单条详情 | | GET | `/api/admin/ping` | `Authorization: Bearer ` | 校验 Token | | GET/POST/PUT/DELETE | `/api/admin/monitors`… | Bearer | 增删改监控;`POST .../:id/run` 立即探测一次 | ## 备注 - Cron 表达式为每分钟 `* * * * *`,在 Worker 内根据 `next_run_at` 与 `interval_minutes` 决定是否真正发起外呼。 - 探测使用 `stream: true`,以**首个内容增量**到达时间作为首字延迟。 - Worker 脚本体积请保持精简;前端由 CDN 提供,整体符合常见 Workers 体积限制实践。 ## 许可证 MIT(若需其他许可证请自行替换。)