Compare commits

...

10 Commits

18 changed files with 389 additions and 369 deletions

View File

@ -1,45 +0,0 @@
name: '🐛 反馈缺陷 Bug Report'
description: '反馈一个问题缺陷 | Report an bug'
title: '[Bug] '
labels: '🐛 Bug'
body:
- type: dropdown
attributes:
label: '💻 系统环境 | Operating System'
options:
- Windows
- macOS
- Ubuntu
- Other Linux
- Other
validations:
required: true
- type: dropdown
attributes:
label: '🌐 浏览器 | Browser'
options:
- Chrome
- Edge
- Safari
- Firefox
- Other
validations:
required: true
- type: textarea
attributes:
label: '🐛 问题描述 | Bug Description'
description: A clear and concise description of the bug.
validations:
required: true
- type: textarea
attributes:
label: '🚦 期望结果 | Expected Behavior'
description: A clear and concise description of what you expected to happen.
- type: textarea
attributes:
label: '📷 复现步骤 | Recurrence Steps'
description: A clear and concise description of how to recurrence.
- type: textarea
attributes:
label: '📝 补充信息 | Additional Information'
description: If your problem needs further explanation, or if the issue you're seeing cannot be reproduced in a gist, please add more information here.

View File

@ -1,21 +0,0 @@
name: '🌠 功能需求 Feature Request'
description: '需求或建议 | Suggest an idea'
title: '[Request] '
labels: '🌠 Feature Request'
body:
- type: textarea
attributes:
label: '🥰 需求描述 | Feature Description'
description: Please add a clear and concise description of the problem you are seeking to solve with this feature request.
validations:
required: true
- type: textarea
attributes:
label: '🧐 解决方案 | Proposed Solution'
description: Describe the solution you'd like in a clear and concise manner.
validations:
required: true
- type: textarea
attributes:
label: '📝 补充信息 | Additional Information'
description: Add any other context about the problem here.

View File

@ -1,15 +0,0 @@
name: '😇 疑问或帮助 Help Wanted'
description: '疑问或需要帮助 | Need help'
title: '[Question] '
labels: '😇 Help Wanted'
body:
- type: textarea
attributes:
label: '🧐 问题描述 | Proposed Solution'
description: A clear and concise description of the proplem.
validations:
required: true
- type: textarea
attributes:
label: '📝 补充信息 | Additional Information'
description: Add any other context about the problem here.

View File

@ -1,7 +0,0 @@
---
name: '📝 其他 Other'
about: '其他问题 | Other issues'
title: ''
labels: ''
assignees: ''
---

View File

@ -1,18 +0,0 @@
#### 💻 变更类型 | Change Type
<!-- For change type, change [ ] to [x]. -->
- [ ] ✨ feat
- [ ] 🐛 fix
- [ ] ♻️ refactor
- [ ] 💄 style
- [ ] 🔨 chore
- [ ] 📝 docs
#### 🔀 变更说明 | Description of Change
<!-- Thank you for your Pull Request. Please provide a description above. -->
#### 📝 补充信息 | Additional Information
<!-- Add any other context about the Pull Request here. -->

View File

@ -1,72 +0,0 @@
name: Issue Auto Comment
on:
issues:
types:
- opened
- closed
- assigned
pull_request_target:
types:
- opened
- closed
permissions:
contents: read
jobs:
run:
permissions:
issues: write # for actions-cool/issues-helper to update issues
pull-requests: write # for actions-cool/issues-helper to update PRs
runs-on: ubuntu-latest
steps:
- name: Auto Comment on Issues Opened
uses: wow-actions/auto-comment@v1
with:
GITHUB_TOKEN: ${{ secrets.GH_TOKEN}}
issuesOpened: |
👀 @{{ author }}
Thank you for raising an issue. We will investigate into the matter and get back to you as soon as possible.
Please make sure you have given us as much context as possible.\
非常感谢您提交 issue。我们会尽快调查此事并尽快回复您。 请确保您已经提供了尽可能多的背景信息。
- name: Auto Comment on Issues Closed
uses: wow-actions/auto-comment@v1
with:
GITHUB_TOKEN: ${{ secrets.GH_TOKEN}}
issuesClosed: |
✅ @{{ author }}
<br/>
This issue is closed, If you have any questions, you can comment and reply.\
此问题已经关闭。如果您有任何问题,可以留言并回复。
- name: Auto Comment on Pull Request Opened
uses: wow-actions/auto-comment@v1
with:
GITHUB_TOKEN: ${{ secrets.GH_TOKEN}}
pullRequestOpened: |
👍 @{{ author }}
<br>
Thank you for raising your pull request and contributing to our Community
Please make sure you have followed our contributing guidelines. We will review it as soon as possible.
If you encounter any problems, please feel free to connect with us.\
非常感谢您提出拉取请求并为我们的社区做出贡献,请确保您已经遵循了我们的贡献指南,我们会尽快审查它。
如果您遇到任何问题,请随时与我们联系。
- name: Auto Comment on Pull Request Merged
uses: actions-cool/pr-welcome@main
if: github.event.pull_request.merged == true
with:
token: ${{ secrets.GH_TOKEN }}
comment: |
❤️ Great PR @${{ github.event.pull_request.user.login }} ❤️
<br>
The growth of project is inseparable from user feedback and contribution, thanks for your contribution!\
项目的成长离不开用户反馈和贡献,感谢您的贡献!
emoji: 'hooray'
pr-emoji: '+1, heart'
- name: Remove inactive
if: github.event.issue.state == 'open' && github.actor == github.event.issue.user.login
uses: actions-cool/issues-helper@v3
with:
actions: 'remove-labels'
token: ${{ secrets.GH_TOKEN }}
issue-number: ${{ github.event.issue.number }}
labels: 'Inactive'

View File

@ -1,23 +0,0 @@
name: Issue Check Inactive
on:
schedule:
- cron: '0 0 */15 * *'
permissions:
contents: read
jobs:
issue-check-inactive:
permissions:
issues: write # for actions-cool/issues-helper to update issues
pull-requests: write # for actions-cool/issues-helper to update PRs
runs-on: ubuntu-latest
steps:
- name: check-inactive
uses: actions-cool/issues-helper@v3
with:
actions: 'check-inactive'
token: ${{ secrets.GH_TOKEN }}
inactive-label: 'Inactive'
inactive-day: 30

View File

@ -1,52 +0,0 @@
name: Issue Close Require
on:
schedule:
- cron: '0 0 * * *'
permissions:
contents: read
jobs:
issue-close-require:
permissions:
issues: write # for actions-cool/issues-helper to update issues
pull-requests: write # for actions-cool/issues-helper to update PRs
runs-on: ubuntu-latest
steps:
- name: need reproduce
uses: actions-cool/issues-helper@v3
with:
actions: 'close-issues'
token: ${{ secrets.GH_TOKEN }}
labels: '✅ Fixed'
inactive-day: 3
body: |
👋 @{{ github.event.issue.user.login }}
<br/>
Since the issue was labeled with `✅ Fixed`, but no response in 3 days. This issue will be closed. If you have any questions, you can comment and reply.\
由于该 issue 被标记为已修复,同时 3 天未收到回应。现关闭 issue若有任何问题可评论回复。
- name: need reproduce
uses: actions-cool/issues-helper@v3
with:
actions: 'close-issues'
token: ${{ secrets.GH_TOKEN }}
labels: '🤔 Need Reproduce'
inactive-day: 3
body: |
👋 @{{ github.event.issue.user.login }}
<br/>
Since the issue was labeled with `🤔 Need Reproduce`, but no response in 3 days. This issue will be closed. If you have any questions, you can comment and reply.\
由于该 issue 被标记为需要更多信息,却 3 天未收到回应。现关闭 issue若有任何问题可评论回复。
- name: need reproduce
uses: actions-cool/issues-helper@v3
with:
actions: 'close-issues'
token: ${{ secrets.GH_TOKEN }}
labels: "🙅🏻‍♀️ WON'T DO"
inactive-day: 3
body: |
👋 @{{ github.event.issue.user.login }}
<br/>
Since the issue was labeled with `🙅🏻‍♀️ WON'T DO`, and no response in 3 days. This issue will be closed. If you have any questions, you can comment and reply.\
由于该 issue 被标记为暂不处理,同时 3 天未收到回应。现关闭 issue若有任何问题可评论回复。

View File

@ -1,33 +0,0 @@
name: Release CI
on:
push:
branches:
- main
jobs:
release:
name: Release
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install bun
uses: oven-sh/setup-bun@v1
- name: Install deps
run: bun i
- name: CI
run: bun run ci
- name: Test
run: bun run test
- name: Build
run: bun run build
- name: Release
run: bun run release
env:
GITHUB_TOKEN: ${{ secrets.GH_TOKEN }}
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}

View File

@ -1,27 +0,0 @@
name: Test CI
on:
pull_request:
push:
branches:
- '!main'
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install bun
uses: oven-sh/setup-bun@v1
- name: Install deps
run: bun i
- name: CI
run: bun run ci
- name: Test and coverage
run: bun run test:coverage
- name: Upload coverage to Codecov
uses: codecov/codecov-action@v3

21
LICENSE Normal file
View File

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2024 Barry Wang
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

66
README.md Normal file
View File

@ -0,0 +1,66 @@
# LobeChat Cloudflare Workers AI Image Generation Plugin
This is a LobeChat plugin that generates high-quality images using the `@cf/black-forest-labs/flux-1-schnell` model from [Cloudflare Workers AI](https://developers.cloudflare.com/workers-ai/).
## Features
- Generate high-quality images using Cloudflare's Flux-1-Schnell model
- Request proxying through Cloudflare Worker for simplified authentication
- Generate and view images directly in LobeChat conversations
## Setup Steps
1. Set up Cloudflare Worker
- Deploy the provided Worker code to Cloudflare Workers
- Configure the following environment variables (Secrets) in your Worker settings:
- `WORKER_API_KEY`: Set a secure API key for client authentication
- `CLOUDFLARE_API_TOKEN`: Your Cloudflare API token
- `CLOUDFLARE_ACCOUNT_ID`: Your Cloudflare account ID
2. Configure the plugin in LobeChat
- Add this plugin to LobeChat
- In the configuration page:
- Configure your Worker API key as `WORKER_API_KEY`
- Ensure the Worker URL is correctly configured
## Authentication and Parameters
This plugin uses the following configuration to access your Cloudflare Worker:
- Worker API key: Used as the X-Api-Key request header
- You only need to provide the image description (prompt) when using this plugin
- The Worker automatically calls the Cloudflare AI API using the configured credentials
## Usage Instructions
1. In the chat, request to generate an image, for example:
- "Draw a cat standing on a mountain top"
- "Generate a beach sunset landscape"
2. Supported parameters:
- prompt: Image description (required, maximum 2048 characters)
- steps: Number of diffusion steps (optional, default 4, maximum 8)
Example: "Generate an image of an astronaut riding a horse, using 8 diffusion steps"
## API Format Example
```bash
curl https://schnell-worker.foryoung365.workers.dev \
-X POST \
-H "X-Api-Key: <YOUR_WORKER_API_KEY>" \
-d '{ "prompt": "cyberpunk cat", "steps": 8 }'
```
## Limitations
- There may be usage limitations based on your Cloudflare account type
- The Flux-1-Schnell model has its own capability range; not all prompts will produce ideal results
- Higher diffusion steps take longer to generate but may produce higher quality
## Privacy
- Your prompt text is sent to the Cloudflare AI API through the Worker
- This plugin does not collect or store your personal data
- Generated images are returned directly to your browser through the Worker
`(Not affiliated with any of the above entities)`

66
README_CN.md Normal file
View File

@ -0,0 +1,66 @@
# LobeChat Cloudflare Workers AI 图像生成插件
这是一个LobeChat插件使用[Cloudflare Workers AI](https://developers.cloudflare.com/workers-ai/)的`@cf/black-forest-labs/flux-1-schnell`模型生成高质量图像。
## 功能特点
- 使用Cloudflare的Flux-1-Schnell模型生成高质量图像
- 通过Cloudflare Worker代理请求简化认证过程
- 直接在LobeChat对话中生成和查看图像
## 设置步骤
1. 设置Cloudflare Worker
- 将提供的Worker代码部署到Cloudflare Workers
- 在Worker设置中配置以下环境变量Secrets
- `WORKER_API_KEY`: 设置一个安全的API密钥用于客户端认证
- `CLOUDFLARE_API_TOKEN`: 你的Cloudflare API令牌
- `CLOUDFLARE_ACCOUNT_ID`: 你的Cloudflare账户ID
2. 在LobeChat中配置插件
- 将此插件添加到LobeChat
- 在配置页面中:
- 将你的Worker API密钥配置为`WORKER_API_KEY`
- 确保Worker URL配置正确
## 身份验证和参数
此插件使用以下配置访问你的Cloudflare Worker
- Worker API密钥用作X-Api-Key请求头
- 每次使用此插件时你只需要提供图像描述prompt
- Worker会自动使用配置的凭证调用Cloudflare AI API
## 使用说明
1. 在聊天中,请求生成图像,例如:
- "画一只站在山顶上的猫"
- "生成一幅海滩日落的风景画"
2. 支持的参数:
- prompt图像描述必需最大2048字符
- steps扩散步骤数可选默认4最大8
例如:"生成一幅宇航员骑马的图像使用8个扩散步骤"
## API格式示例
```bash
curl https://[your-worker-name].[your-account-name].workers.dev \
-X POST \
-H "X-Api-Key: <YOUR_WORKER_API_KEY>" \
-d '{ "prompt": "cyberpunk cat", "steps": 8 }'
```
## 限制
- 根据你的Cloudflare账户类型可能有使用限制
- Flux-1-Schnell模型有自己的能力范围不是所有提示都能产生理想结果
- 扩散步骤数越大,生成时间越长,但质量可能更高
## 隐私
- 你的提示文本将通过Worker发送到Cloudflare AI API
- 此插件不会收集或存储你的个人数据
- 生成的图像通过Worker直接返回给你的浏览器
`(与上述任何实体均无关联)`

View File

@ -1,18 +1,20 @@
{ {
"api": { "api": {
"type": "openapi", "type": "openapi",
"url": "https://raw.githubusercontent.com/GithuBarry/chat-plugin-search-engine/main/public/openapi.json", "url": "https://raw.githubusercontent.com/foryoung365/lobechat-plugin-workers-schnell/main/public/openapi.json",
"is_user_authenticated": false "is_user_authenticated": false
}, },
"auth": { "auth": {
"type": "none" "type": "service_http",
"authorization_type": "custom",
"custom_auth_header": "X-Api-Key: ${WORKER_API_KEY}"
}, },
"contact_email": "33831597+GithuBarry@users.noreply.github.com", "contact_email": "1758359+foryoung365@users.noreply.github.com",
"description_for_human": "Google search engine via Serper.dev free API (2500x🆓/month)", "description_for_human": "Generate images with Cloudflare Workers AI's flux-1-schnell model",
"description_for_model": "Plugin for performing web searches using the Serper.dev API to access Google search results.", "description_for_model": "This plugin uses the Cloudflare Workers AI's flux-1-schnell model to generate beautiful images.",
"legal_info_url": "https://serper.dev/terms", "legal_info_url": "https://developers.cloudflare.com/ai/",
"logo_url": "https://serper.dev/favicon.ico", "logo_url": "https://developers.cloudflare.com/favicon.ico",
"name_for_human": "Search Google via Serper", "name_for_human": "AI Image Generator (Flux-1-Schnell)",
"name_for_model": "search-engine-serper", "name_for_model": "ai-image-generator-flux-schnell",
"schema_version": "v1" "schema_version": "v1"
} }

View File

@ -1,46 +1,46 @@
{ {
"components": { "components": {
"securitySchemes": { "securitySchemes": {
"apiAuth": { "apiKeyAuth": {
"type": "apiKey", "type": "apiKey",
"name": "X-API-KEY", "in": "header",
"in": "header" "name": "X-Api-Key",
"description": "API Key for authentication"
} }
} }
}, },
"info": { "info": {
"title": "Web Search", "title": "AI Image Generator",
"version": "1.0.0" "version": "1.0.0",
"description": "Generate images using Cloudflare Workers AI's @cf/black-forest-labs/flux-1-schnell model"
}, },
"openapi": "3.0.0", "openapi": "3.0.0",
"paths": { "paths": {
"/search": { "/": {
"post": { "post": {
"summary": "Search Google and return top 10 results", "summary": "Generate Image",
"operationId": "searchGoogle", "operationId": "generateImage",
"description": "Generate an image based on text prompt using Cloudflare Workers AI's flux-1-schnell model",
"requestBody": { "requestBody": {
"required": true, "required": true,
"content": { "content": {
"application/json": { "application/json": {
"schema": { "schema": {
"type": "object", "type": "object",
"required": [ "required": ["prompt"],
"q"
],
"properties": { "properties": {
"q": { "prompt": {
"type": "string", "type": "string",
"example": "今天吃什么" "description": "Text description of the image you want to generate(English only)",
"minLength": 1,
"maxLength": 2048
}, },
"gl": { "steps": {
"type": "string", "type": "integer",
"description": "Google Geo location parameter", "description": "The number of diffusion steps; higher values can improve quality but take longer",
"example": "cn" "default": 4,
}, "minimum": 1,
"hl": { "maximum": 8
"type": "string",
"description": "Google Geo locale parameter",
"example": "zh-cn"
} }
} }
} }
@ -49,29 +49,30 @@
}, },
"responses": { "responses": {
"200": { "200": {
"description": "Successful search results", "description": "Successfully generated image",
"content": { "content": {
"application/json": { "image/png": {
"schema": { "schema": {
"type": "object", "type": "string",
"required": [ "format": "binary",
"result" "description": "Generated image data"
],
"properties": {
"result": {
"type": "string",
"description": "Top 10 search results",
"example": "\"title\": \"周末游推荐\",\n\"link\": \"https://www.example.com/destinations-for-weekends\",\n\"snippet\": \"周末去哪玩?周末旅游频道,精心推荐数百个周末游经典线路\",\n\"position\": 1"
}
}
} }
} }
} }
},
"400": {
"description": "Invalid request parameters"
},
"401": {
"description": "Unauthorized, invalid API key"
},
"500": {
"description": "Server error"
} }
}, },
"security": [ "security": [
{ {
"apiAuth": [] "apiKeyAuth": []
} }
] ]
} }
@ -79,12 +80,13 @@
}, },
"security": [ "security": [
{ {
"apiAuth": [] "apiKeyAuth": []
} }
], ],
"servers": [ "servers": [
{ {
"url": "https://google.serper.dev" "url": "https://schnell-worker.foryoung365.workers.dev",
"description": "Cloudflare Worker for Image Generation"
} }
] ]
} }

View File

@ -1,13 +1,13 @@
{ {
"author": "Barry", "author": "foryoung365",
"homepage": "https://github.com/GithuBarry/chat-plugin-search-engine", "homepage": "https://github.com/foryoung365/lobechat-plugin-workers-schnell",
"identifier": "search-engine-serper", "identifier": "ai-image-generator-flux-schnell",
"manifest": "https://raw.githubusercontent.com/GithuBarry/chat-plugin-search-engine/main/public/openapi.json", "manifest": "https://raw.githubusercontent.com/foryoung365/lobechat-plugin-workers-schnell/main/public/manifest.json",
"meta": { "meta": {
"avatar": "🔍", "avatar": "🖼️",
"description": "Google search engine via Serper.dev free API (2500x🆓/month)", "description": "Generate images with Cloudflare Workers AI's flux-1-schnell model",
"tags": ["web", "search"], "tags": ["image", "ai", "generation"],
"title": "Search Google via Serper" "title": "AI Image Generator (Flux-1-Schnell)"
}, },
"schemaVersion": 1 "schemaVersion": 1
} }

99
src/DEPLOYMENT.md Normal file
View File

@ -0,0 +1,99 @@
# Cloudflare Worker 部署说明
本文档提供关于如何部署 Cloudflare Worker 代码的说明,该代码用于处理和代理 LobeChat 插件的请求到 Cloudflare AI API。
## 前提条件
1. 一个 Cloudflare 账户
2. 已启用 Cloudflare Workers 服务
3. 安装并配置了 [Wrangler CLI](https://developers.cloudflare.com/workers/cli-wrangler/install-update)Cloudflare 的 Worker CLI 工具)
## 部署步骤
### 1. 准备工作
首先,确保你已经获取了以下信息:
- 你的 Cloudflare 账户 ID可在 Cloudflare 控制台中找到)
- 一个有权限访问 Cloudflare Workers 和 AI API 的 API Token
### 2. 创建 Worker 项目
使用 Wrangler 创建一个新的 Worker 项目:
```bash
# 创建新项目
wrangler init ai-image-proxy-worker
cd ai-image-proxy-worker
```
### 3. 配置 Worker
将本仓库中的 `src/worker.ts` 文件内容复制到你的 Worker 项目的主文件中(通常是 `src/index.ts`)。
然后,创建或修改 `wrangler.toml` 文件如下:
```toml
name = "ai-image-proxy-worker"
compatibility_date = "2023-10-30"
[vars]
# 这里不要填写敏感信息,这些只是占位符
# 实际密钥应使用 Secrets 设置
# 可选:如果你需要绑定自定义域名
# [routes]
# pattern = "your-domain.com/*"
# zone_id = "your-zone-id"
```
### 4. 设置环境变量Secrets
使用 Wrangler 设置必要的 Secrets
```bash
# 设置客户端 API 密钥(你自己定义的值,用于客户端访问你的 Worker
wrangler secret put WORKER_API_KEY
# 设置 Cloudflare API Token从 Cloudflare 控制台获取)
wrangler secret put CLOUDFLARE_API_TOKEN
# 设置 Cloudflare 账户 ID
wrangler secret put CLOUDFLARE_ACCOUNT_ID
```
每条命令运行后,将提示你输入相应的值。
### 5. 部署 Worker
完成配置后,部署 Worker
```bash
wrangler deploy
```
成功部署后Wrangler 将显示你的 Worker 的 URL例如`https://ai-image-proxy-worker.yourusername.workers.dev`。
### 6. 配置 LobeChat 插件
按照 README 中的说明配置 LobeChat 插件,将 `WORKER_API_KEY` 设置为你在步骤 4 中配置的客户端 API 密钥。
## 故障排除
如果遇到问题,请检查:
1. Cloudflare 控制台中的 Worker 日志
2. 确保所有环境变量Secrets都已正确设置
3. 验证你的 API Token 是否有足够的权限
4. 检查你的账户是否启用了 Workers AI 服务
## 安全注意事项
- 定期轮换你的 API 密钥和令牌
- 为 Worker API 密钥使用强密码,因为这是客户端用来访问你的 Worker 的凭证
- 考虑添加速率限制或其他安全措施来防止滥用
## 资源链接
- [Cloudflare Workers 文档](https://developers.cloudflare.com/workers/)
- [Workers AI 文档](https://developers.cloudflare.com/workers-ai/)

77
src/worker.ts Normal file
View File

@ -0,0 +1,77 @@
interface Env {
WORKER_API_KEY: string;
CLOUDFLARE_API_TOKEN: string;
CLOUDFLARE_ACCOUNT_ID: string;
}
export default {
async fetch(request: Request, env: Env, ctx: ExecutionContext) {
if (request.method !== 'POST') {
return new Response('Expected POST', { status: 405 });
}
// 1. 认证客户端 (使用 X-Api-Key 请求头)
const clientApiKey = request.headers.get('X-Api-Key');
// 'WORKER_API_KEY' 是你在 Cloudflare Secrets 中设置的变量名
if (!clientApiKey || clientApiKey !== env.WORKER_API_KEY) {
return new Response('Unauthorized: Missing or invalid API Key', { status: 401 });
}
try {
// 2. 解析客户端请求体 (只需要 prompt)
const clientData = await request.json() as { prompt?: string, steps?: unknown };
const prompt = clientData.prompt;
const steps = clientData.steps;
if (!prompt) {
return new Response('Missing "prompt" in request body', { status: 400 });
}
// 3. 从环境变量(Secrets)获取 Worker 自身的凭证
const apiToken = env.CLOUDFLARE_API_TOKEN;
const accountId = env.CLOUDFLARE_ACCOUNT_ID;
if (!apiToken || !accountId) {
console.error('ERROR: Missing Cloudflare credentials in Worker secrets. Ensure CLOUDFLARE_API_TOKEN and CLOUDFLARE_ACCOUNT_ID secrets are set.');
return new Response('Internal Server Error - Configuration Missing', { status: 500 });
}
// 4. 构造发往 Cloudflare AI 的请求 (使用 Worker 的凭证)
const aiApiUrl = `https://api.cloudflare.com/client/v4/accounts/${accountId}/ai/run/@cf/black-forest-labs/flux-1-schnell`;
const aiRequest = new Request(aiApiUrl, {
method: 'POST',
headers: {
'Authorization': `Bearer ${apiToken}`, // 使用 Worker 的 Token
'Content-Type': 'application/json',
},
body: JSON.stringify({ prompt: prompt, steps: steps || 4 }), // 使用客户端的 Prompt
});
// 5. 发送请求到 AI API 并获取响应
console.log(`Forwarding request to AI API for prompt: "${prompt}"`);
const aiResponse = await fetch(aiRequest);
console.log(`Received response from AI API with status: ${aiResponse.status}`);
// 6. 将 AI 的响应直接返回给客户端
// 创建一个新的 Response 对象以避免潜在的 header 问题或 immutability 问题
const responseHeaders = new Headers(aiResponse.headers);
//responseHeaders.set('X-Proxied-By', 'my-ai-proxy-worker'); // 添加一个自定义头(可选)
return new Response(aiResponse.body, {
status: aiResponse.status,
statusText: aiResponse.statusText,
headers: responseHeaders // 返回 AI 的响应头,可以按需修改
});
} catch (error: unknown) {
console.error('Error processing request:', error);
if (error instanceof SyntaxError) {
return new Response('Invalid JSON in request body', { status: 400 });
}
// 避免将详细错误暴露给客户端
return new Response(`Internal Server Error: ${error instanceof Error ? error.message : 'Unknown error'}`, { status: 500 });
}
},
} satisfies ExportedHandler<Env>;