diff --git a/.env.example b/.env.example index 70bbf194..6ffdf6f1 100644 --- a/.env.example +++ b/.env.example @@ -89,6 +89,11 @@ TZ= # Browser Configuration # =================================== +# AI Studio app URL to open (optional) +# Set this to your own app URL in the format https://ai.studio/apps/ +# Leave empty to use the built-in default app +AI_STUDIO_APP_URL= + # Path to the Camoufox browser executable # Leave empty to use the default path based on your OS CAMOUFOX_EXECUTABLE_PATH= diff --git a/README.md b/README.md index 07a83d5b..6eae66f9 100644 --- a/README.md +++ b/README.md @@ -273,6 +273,7 @@ services: | `FAILURE_THRESHOLD` | 切换帐户前允许的连续失败次数(设为 `0` 禁用)。 | `3` | | `IMMEDIATE_SWITCH_STATUS_CODES` | 触发立即切换帐户的 HTTP 状态码(逗号分隔,设为空值以禁用)。 | `429,503` | | `MAX_CONTEXTS` | 最大同时登录的账号数量。同时登录的账号切换更快,无需重新登录。数值越大内存消耗越高(约:1 个账号 ~700MB,2 个账号 ~950MB,3 个账号 ~1100MB)。设为 `0` 表示无限制。 | `1` | +| `AI_STUDIO_APP_URL` | 要打开的 AI Studio 应用地址(可选),格式为 `https://ai.studio/apps/<应用 ID>`;留空时使用内置应用。[教程](docs/zh/create-ai-studio-app.md) | 内置应用 | | `HTTP_PROXY` | 用于访问 Google 服务的 HTTP 代理地址。 | 无 | | `HTTPS_PROXY` | 用于访问 Google 服务的 HTTPS 代理地址。 | 无 | | `NO_PROXY` | 不经过代理的地址列表(逗号分隔)。项目已内置自动绕过本地地址(localhost, 127.0.0.1, ::, ::1, 0.0.0.0),通常无需手动配置本地绕过。 | 无 | diff --git a/README_EN.md b/README_EN.md index 5bb3b82c..80152b93 100644 --- a/README_EN.md +++ b/README_EN.md @@ -259,21 +259,22 @@ Usage: #### 🌐 Proxy Configuration -| Variable | Description | Default | -| :------------------------------ | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :-------- | -| `INITIAL_AUTH_INDEX` | Initial authentication index to use on startup. | `0` | -| `ENABLE_AUTH_UPDATE` | Whether to enable automatic auth credential updates. Defaults to enabled. The auth file will be automatically updated upon successful login/account switch and every 24 hours. Set to `false` to disable. | `true` | -| `MAX_RETRIES` | Maximum number of retries for failed requests (only effective for fake streaming and non-streaming). | `3` | -| `RETRY_DELAY` | Delay between retries in milliseconds. | `2000` | -| `STREAM_TIMEOUT_MS` | Timeout between real streaming chunks, in milliseconds. Maximum: `300000`. | `60000` | -| `FAKE_STREAM_TIMEOUT_MS` | Timeout for fake streaming / non-streaming buffered responses, in milliseconds. Maximum: `300000`. | `300000` | -| `SWITCH_ON_USES` | Number of requests before automatically switching accounts (`0` to disable). | `40` | -| `FAILURE_THRESHOLD` | Number of consecutive failures before switching accounts (`0` to disable). | `3` | -| `IMMEDIATE_SWITCH_STATUS_CODES` | HTTP status codes that trigger immediate account switching (comma-separated, set to empty to disable). | `429,503` | -| `MAX_CONTEXTS` | Maximum number of accounts that can be logged in simultaneously. Accounts logged in simultaneously can switch faster without re-login. Higher values consume more memory (approx: 1 account ~700MB, 2 accounts ~950MB, 3 accounts ~1100MB). Set to `0` for unlimited. | `1` | -| `HTTP_PROXY` | HTTP proxy address for accessing Google services. | None | -| `HTTPS_PROXY` | HTTPS proxy address for accessing Google services. | None | -| `NO_PROXY` | Comma-separated list of addresses to bypass the proxy. The project automatically bypasses local addresses (localhost, 127.0.0.1, ::, ::1 and 0.0.0.0), so manual local bypass configuration is usually not required. | None | +| Variable | Description | Default | +| :------------------------------ | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :----------- | +| `INITIAL_AUTH_INDEX` | Initial authentication index to use on startup. | `0` | +| `ENABLE_AUTH_UPDATE` | Whether to enable automatic auth credential updates. Defaults to enabled. The auth file will be automatically updated upon successful login/account switch and every 24 hours. Set to `false` to disable. | `true` | +| `MAX_RETRIES` | Maximum number of retries for failed requests (only effective for fake streaming and non-streaming). | `3` | +| `RETRY_DELAY` | Delay between retries in milliseconds. | `2000` | +| `STREAM_TIMEOUT_MS` | Timeout between real streaming chunks, in milliseconds. Maximum: `300000`. | `60000` | +| `FAKE_STREAM_TIMEOUT_MS` | Timeout for fake streaming / non-streaming buffered responses, in milliseconds. Maximum: `300000`. | `300000` | +| `SWITCH_ON_USES` | Number of requests before automatically switching accounts (`0` to disable). | `40` | +| `FAILURE_THRESHOLD` | Number of consecutive failures before switching accounts (`0` to disable). | `3` | +| `IMMEDIATE_SWITCH_STATUS_CODES` | HTTP status codes that trigger immediate account switching (comma-separated, set to empty to disable). | `429,503` | +| `MAX_CONTEXTS` | Maximum number of accounts that can be logged in simultaneously. Accounts logged in simultaneously can switch faster without re-login. Higher values consume more memory (approx: 1 account ~700MB, 2 accounts ~950MB, 3 accounts ~1100MB). Set to `0` for unlimited. | `1` | +| `AI_STUDIO_APP_URL` | AI Studio app URL to open (optional), in the format `https://ai.studio/apps/`. Leave empty to use the built-in app. [Guide](docs/en/create-ai-studio-app.md) | Built-in app | +| `HTTP_PROXY` | HTTP proxy address for accessing Google services. | None | +| `HTTPS_PROXY` | HTTPS proxy address for accessing Google services. | None | +| `NO_PROXY` | Comma-separated list of addresses to bypass the proxy. The project automatically bypasses local addresses (localhost, 127.0.0.1, ::, ::1 and 0.0.0.0), so manual local bypass configuration is usually not required. | None | #### 🗒️ Other Configuration diff --git a/docs/assets/ai-studio-app/01-remix.png b/docs/assets/ai-studio-app/01-remix.png new file mode 100644 index 00000000..51c93290 Binary files /dev/null and b/docs/assets/ai-studio-app/01-remix.png differ diff --git a/docs/assets/ai-studio-app/02-remix-dialog.png b/docs/assets/ai-studio-app/02-remix-dialog.png new file mode 100644 index 00000000..dd1794a1 Binary files /dev/null and b/docs/assets/ai-studio-app/02-remix-dialog.png differ diff --git a/docs/assets/ai-studio-app/03-code.png b/docs/assets/ai-studio-app/03-code.png new file mode 100644 index 00000000..9ae42e07 Binary files /dev/null and b/docs/assets/ai-studio-app/03-code.png differ diff --git a/docs/assets/ai-studio-app/04-preview-error.png b/docs/assets/ai-studio-app/04-preview-error.png new file mode 100644 index 00000000..9a8cf2f9 Binary files /dev/null and b/docs/assets/ai-studio-app/04-preview-error.png differ diff --git a/docs/assets/ai-studio-app/05-share.png b/docs/assets/ai-studio-app/05-share.png new file mode 100644 index 00000000..3c7d1e53 Binary files /dev/null and b/docs/assets/ai-studio-app/05-share.png differ diff --git a/docs/en/create-ai-studio-app.md b/docs/en/create-ai-studio-app.md new file mode 100644 index 00000000..e4de941b --- /dev/null +++ b/docs/en/create-ai-studio-app.md @@ -0,0 +1,70 @@ +# Create an AI Studio App + +This guide creates a dedicated AI Studio App for the project and obtains the app link required by the `AI_STUDIO_APP_URL` environment variable. + +## 1. Open the blank app + +Sign in to your Google account, then open the [AI Studio blank app](https://aistudio.google.com/apps/bundled/blank). + +Click **Remix** in the upper-right corner. Do not use the Remix button beside the prompt box in the lower-left corner. + +![Click Remix in the upper-right corner](../assets/ai-studio-app/01-remix.png) + +## 2. Create your copy + +Change the **App name** in the dialog. You may also update the **Description**. Then click **Remix app** in the lower-right corner. + +![Enter an app name and click Remix app](../assets/ai-studio-app/02-remix-dialog.png) + +Wait for the copy to be created. After your app name appears at the top, click **Code** above the preview area to open the code editor. + +![Click Code to open the editor](../assets/ai-studio-app/03-code.png) + +## 3. Replace the app files + +Replace the complete contents of these files in the code editor: + +1. Open `index.ts` in the AI Studio App, delete its existing contents, then copy and paste the complete contents of this project's [`scripts/client/build.js`](../../scripts/client/build.js). +2. Open `index.html` in the AI Studio App, delete its existing contents, then copy and paste the complete contents of this project's [`scripts/client/index.html`](../../scripts/client/index.html). + +Click **Save** at the bottom of the editor when finished. You can also press `Ctrl+S` (`Command+S` on macOS). + +> Copy the files from the version of the repository you are currently using. If a future project update changes either file, replace the corresponding App file again and save it. + +## 4. Check the preview + +Click **Preview** above the preview area and wait about 10 seconds. The following error means the client code is running and waiting for this project to establish a connection; it is expected here: + +```text +Error: ❌ Failed to get authIndex: authIndex postMessage timeout (10s) +``` + +![Expected timeout message in Preview](../assets/ai-studio-app/04-preview-error.png) + +AI Studio may also show a code error count on the left or at the bottom. Do not click **Fix** and let AI rewrite the code. You can continue as long as Preview displays the `authIndex postMessage timeout (10s)` message above. + +## 5. Share publicly and copy the link + +1. Click **Share** in the upper-right corner. You do not need to click **Publish**. +2. Under **General access**, select **Public: Anyone with the link can view**. +3. Click **Copy link** at the bottom of the sharing panel. + +![Set access to Public and copy the link](../assets/ai-studio-app/05-share.png) + +The copied link should look like this: + +```text +https://ai.studio/apps/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx +``` + +## 6. Configure the environment variable + +Add the complete link to the `.env` file in the project root: + +```env +AI_STUDIO_APP_URL=https://ai.studio/apps/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx +``` + +Save `.env` and restart AIStudioToAPI. The `AI Studio App URL` entry in the startup log should show the URL you configured. + +> The App must remain Public, or the Google account running AIStudioToAPI may be unable to open it. A public link also allows anyone who has it to view the App, so never add API keys, cookies, or other secrets to `index.ts` or `index.html`. diff --git a/docs/zh/create-ai-studio-app.md b/docs/zh/create-ai-studio-app.md new file mode 100644 index 00000000..a1c2f3e7 --- /dev/null +++ b/docs/zh/create-ai-studio-app.md @@ -0,0 +1,70 @@ +# 新建 AI Studio App 教程 + +本教程用于创建项目专用的 AI Studio App,并获取 `AI_STUDIO_APP_URL` 环境变量所需的应用链接。 + +## 1. 打开空白 App + +登录 Google 账号后,访问 [AI Studio 空白 App](https://aistudio.google.com/apps/bundled/blank)。 + +页面打开后,点击右上角的 **Remix**。不要点击左下角输入框旁的 Remix 按钮。 + +![点击页面右上角的 Remix](../assets/ai-studio-app/01-remix.png) + +## 2. 创建自己的副本 + +在弹窗中修改 **App name**,也可以按需修改 **Description**,然后点击右下角的 **Remix app**。 + +![填写名称并点击 Remix app](../assets/ai-studio-app/02-remix-dialog.png) + +等待应用副本创建完成。顶部出现你设置的应用名称后,点击预览区上方的 **Code**,进入代码编辑器。 + +![点击 Code 进入代码编辑器](../assets/ai-studio-app/03-code.png) + +## 3. 替换代码文件 + +在代码编辑器中依次替换以下文件的全部内容: + +1. 打开 AI Studio App 中的 `index.ts`,删除原有内容,然后复制本项目 [`scripts/client/build.js`](../../scripts/client/build.js) 的全部内容并粘贴进去。 +2. 打开 AI Studio App 中的 `index.html`,删除原有内容,然后复制本项目 [`scripts/client/index.html`](../../scripts/client/index.html) 的全部内容并粘贴进去。 + +完成后,点击编辑器下方的 **Save**;也可以按 `Ctrl+S`(macOS 使用 `Command+S`)保存。 + +> 请直接复制当前版本仓库中的文件。项目升级且这两个文件发生变化后,需要回到 App 中重新替换并保存。 + +## 4. 检查预览 + +点击预览区上方的 **Preview**,等待大约 10 秒。如果出现以下错误,说明客户端代码已经正常运行并正在等待本项目建立连接,这是预期现象: + +```text +Error: ❌ Failed to get authIndex: authIndex postMessage timeout (10s) +``` + +![Preview 中出现预期的超时提示](../assets/ai-studio-app/04-preview-error.png) + +AI Studio 左侧或底部可能同时显示代码错误数量。不要点击 **Fix** 让 AI 自动改写代码;只要预览出现上面的 `authIndex postMessage timeout (10s)` 即可继续。 + +## 5. 公开分享并复制链接 + +1. 点击页面右上角的 **Share**,无需点击 **Publish**。 +2. 在 **General access** 中选择 **Public: Anyone with the link can view**。 +3. 点击分享面板底部的 **Copy link**。 + +![将访问范围设为 Public 并复制链接](../assets/ai-studio-app/05-share.png) + +复制到的链接应类似: + +```text +https://ai.studio/apps/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx +``` + +## 6. 配置环境变量 + +将完整链接写入项目根目录的 `.env`: + +```env +AI_STUDIO_APP_URL=https://ai.studio/apps/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx +``` + +保存 `.env` 后重启 AIStudioToAPI。启动日志中的 `AI Studio App URL` 应显示你刚配置的地址。 + +> 该 App 必须保持 Public;否则运行 AIStudioToAPI 的 Google 账号可能无法打开它。公开链接也意味着任何获得链接的人都可以查看 App,请不要在 `index.ts` 或 `index.html` 中加入密钥、Cookie 或其他敏感信息。 diff --git a/src/core/BrowserManager.js b/src/core/BrowserManager.js index 0ea00ba0..6f64b341 100644 --- a/src/core/BrowserManager.js +++ b/src/core/BrowserManager.js @@ -79,7 +79,7 @@ class BrowserManager { this._wsInitState = new Map(); // Target URL for AI Studio app - this.targetUrl = "https://ai.studio/apps/cab9ab6c-44f9-4e7a-8972-037f8ae177ab"; + this.targetUrl = config.aiStudioAppUrl; // Firefox/Camoufox does not use Chromium-style command line args. // We keep this empty; Camoufox has its own anti-fingerprinting optimizations built-in. diff --git a/src/utils/ConfigLoader.js b/src/utils/ConfigLoader.js index 1400fd82..56d50cb9 100644 --- a/src/utils/ConfigLoader.js +++ b/src/utils/ConfigLoader.js @@ -9,6 +9,33 @@ const fs = require("fs"); const path = require("path"); const { getProxySummaryFromEnv } = require("./ProxyUtils"); +const DEFAULT_AI_STUDIO_APP_URL = "https://ai.studio/apps/cab9ab6c-44f9-4e7a-8972-037f8ae177ab"; + +function parseAiStudioAppUrl(value) { + const rawValue = String(value || "").trim(); + if (!rawValue) return null; + + try { + const url = new URL(rawValue); + const pathSegments = url.pathname.split("/").filter(Boolean); + if ( + url.protocol !== "https:" || + url.hostname !== "ai.studio" || + url.username || + url.password || + url.search || + url.hash || + pathSegments.length !== 2 || + pathSegments[0] !== "apps" + ) { + return null; + } + return `https://ai.studio/apps/${pathSegments[1]}`; + } catch { + return null; + } +} + /** * Configuration Loader Module * Responsible for loading system configuration from environment variables @@ -20,6 +47,7 @@ class ConfigLoader { loadConfiguration() { const config = { + aiStudioAppUrl: DEFAULT_AI_STUDIO_APP_URL, apiKeys: [], apiKeySource: "Not set", browserExecutablePath: null, @@ -46,6 +74,17 @@ class ConfigLoader { }; // Environment variable overrides + if (process.env.AI_STUDIO_APP_URL) { + const aiStudioAppUrl = parseAiStudioAppUrl(process.env.AI_STUDIO_APP_URL); + if (aiStudioAppUrl) { + config.aiStudioAppUrl = aiStudioAppUrl; + } else { + this.logger.warn( + `[Config] Invalid AI_STUDIO_APP_URL "${process.env.AI_STUDIO_APP_URL}". ` + + `Expected https://ai.studio/apps/; using the default app.` + ); + } + } if (process.env.PORT) { const parsed = parseInt(process.env.PORT, 10); config.httpPort = Number.isFinite(parsed) ? parsed : config.httpPort; @@ -197,6 +236,7 @@ class ConfigLoader { this.logger.info("================ [ Active Configuration ] ================"); this.logger.info(` HTTP Server Port: ${config.httpPort}`); this.logger.info(` Listening Address: ${config.host}`); + this.logger.info(` AI Studio App URL: ${config.aiStudioAppUrl}`); this.logger.info(` Streaming Mode: ${config.streamingMode}`); this.logger.info(` Stream Timeout: ${config.streamTimeoutMs}ms`); this.logger.info(` Fake/Non-Stream Timeout: ${config.fakeStreamTimeoutMs}ms`);