magpie-gemini-web 0.4.0 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.en.md CHANGED
@@ -2,12 +2,18 @@
2
2
 
3
3
  [中文](README.md) | English
4
4
 
5
- Use Gemini on the web through your Google account in [Magpie](https://usemagpie.ai/). The plugin runs the [gemini-web2api-go](https://github.com/zexadev/gemini-web2api-go) backend on your machine. The backend turns the Gemini web app into an OpenAI-compatible API.
5
+ Use Gemini on the web and Google AI Studio through your Google account in [Magpie](https://usemagpie.ai/). The plugin runs [gemini-web2api-go](https://github.com/zexadev/gemini-web2api-go) and [AIStudio2API](https://github.com/Mag1cFall/AIStudio2API) backends on your machine, turning Google web interfaces into OpenAI-compatible APIs.
6
6
 
7
- ## Getting started
7
+ The plugin provides two independent providers:
8
+ - `gemini-web`: the Gemini web app; see [Getting started](#getting-started-gemini-web).
9
+ - `ai-studio`: Google AI Studio, with native tool calling; see [Google AI Studio](#google-ai-studio-ai-studio).
10
+
11
+ > **2026-10-16 update:** Full-price Google AI Pro accounts can now use `gemini-4-argon` directly in Antigravity, and can likewise be proxied directly with Magpie.
12
+
13
+ ## Getting started (Gemini Web)
8
14
 
9
15
  1. Install **magpie-gemini-web** from the Magpie plugin market.
10
- 2. Sign in to Gemini Web and choose **一键配置本地 Gemini Web (one-click local setup, recommended)**. The plugin downloads the backend, verifies it and starts it in the background.
16
+ 2. Sign in to Gemini Web and choose **一键配置本地 Gemini Web (one-click local setup, recommended)**. The plugin downloads this project's optimized backend, verifies its SHA-256 and starts it in the background. No Go installation or manual patching is needed.
11
17
  3. Copy your cookie when prompted. **Use a private / incognito window** (Firefox recommended):
12
18
  1. In the private window, open <https://gemini.google.com/app> and sign in to the Google account you want to use.
13
19
  2. Press F12 (⌥⌘I on macOS), switch to **Network** and reload the page.
@@ -24,7 +30,7 @@ From then on, Magpie starts the backend automatically every time it launches. To
24
30
 
25
31
  **Connecting an existing backend:** if you already run gemini-web2api-go yourself, choose 连接已有后端 (connect an existing backend with a custom URL and API key). Enter its URL (ending in `/v1`) and its `API_KEY`.
26
32
 
27
- ## Plugin options
33
+ ## Plugin options (Gemini Web)
28
34
 
29
35
  Tool calls are on by default (coding agents send tools with every request); image input is off. To allow images:
30
36
 
@@ -38,7 +44,7 @@ magpie plugin options magpie-gemini-web '{"allowImages":true}'
38
44
  | `allowImages` | `false` | Allows image input |
39
45
  | `baseURL` | `http://127.0.0.1:8083/v1` | Default backend URL |
40
46
  | `contextLimit` / `outputLimit` | `1000000` / `8192` | Context and output limits reported to clients |
41
- | `requestTimeoutMs` / `modelTimeoutMs` | `240000` / `10000` | Timeouts in ms for requests and for fetching the model list |
47
+ | `requestTimeoutMs` / `modelTimeoutMs` | `240000` / `10000` | Timeouts in ms for requests and for fetching the model list. The request timeout counts each wait on the backend, so a reply that keeps coming is never cut off |
42
48
  | `stripCitations` | `true` | Removes the citation markers Gemini adds to replies, `[cite: 1]` and `[cite_start]`, tool call arguments included. Set it to `false` while Gemini edits code that contains such text itself |
43
49
 
44
50
  ## Thinking effort
@@ -48,7 +54,7 @@ You can switch a model between `low` and `high` effort in Magpie if it has a `-t
48
54
  ## Security and data
49
55
 
50
56
  - The backend listens on `127.0.0.1` only. Your cookie goes only to that local backend, and Magpie stores a locally generated API key instead.
51
- - The plugin pins the official v4.22.0 backend binary and checks its SHA-256 on download and on every start. Builds are available for macOS, Linux and Windows on x64 and arm64.
57
+ - The default backend is this project's **4.22.0-magpie.1**, built from pinned upstream v4.22.0 sources with this repository's patch. SHA-256 is checked on download and before launching a new process. Builds cover macOS, Linux and Windows on x64 and arm64; the release includes sources, build metadata and checksums.
52
58
  - The data directory is `~/.local/share/magpie-gemini-web` (set `GEMINI_WEB_DATA_DIR` to change it). The backend writes its log to `backend.log` there.
53
59
  - The plugin sends one request at a time, but this can't guarantee that Google won't flag your account. Use it at your own risk.
54
60
 
@@ -70,41 +76,103 @@ Usage and emails are read the way the backend reaches Google for that account. W
70
76
 
71
77
  So with a proxy pool, an account just added by one-click setup has no email yet. Send one request with it, sign in to it again with **「添加本地后端里已有的 Google 账号」**, then remove the sign-in without an email.
72
78
 
73
- ## Limitations
79
+ ## Limitations (Gemini Web)
74
80
 
75
81
  - Upstream emulates tool calls with prompts, so they aren't always reliable. Flash models often don't call tools.
76
82
  - Only text models whose names start with `gemini-` are exposed. A `cost` of 0 doesn't reflect your actual Google quota.
77
83
 
84
+ ## Google AI Studio (`ai-studio`)
85
+
86
+ Uses Google AI Studio through [AIStudio2API](https://github.com/Mag1cFall/AIStudio2API) (pinned to v0.2.12). Unlike Gemini Web, tool calls use native Function Calling, thinking models offer four levels in Magpie, `minimal` / `low` / `medium` / `high` (`minimal` is the fastest and uses the least quota), and generation needs no browser.
87
+
88
+ ### Getting started
89
+
90
+ 1. Sign in to Google AI Studio and choose **一键配置本地 Google AI Studio(推荐)** (one-click local setup). The plugin downloads AIStudio2API, verifies its SHA-256 and starts it in the background.
91
+ 2. Sign in to your Google account in the separate login window that opens (your usual browser is not affected), then close it. The first time, the login browser Camoufox is downloaded first, so the window can take a few minutes to appear; the login must finish within 15 minutes.
92
+
93
+ To add another account, run the one-click setup again. All accounts share one sign-in card: the local service picks the account for each request, using one until it cools down, then the next.
94
+
95
+ Other sign-in options:
96
+
97
+ - **使用本机已有的 AI Studio 服务** (use the local service already set up): signs in when the machine already has accounts (added from the command line, say), without a login window.
98
+ - **重新登录失效的 AI Studio 账号** (sign an expired account in again): when an account's Google login expires, choose it here to sign in again.
99
+ - **连接已有 AIStudio2API** (connect an existing AIStudio2API): if you run AIStudio2API yourself, enter its address (default `http://127.0.0.1:2048/v1`) and `PROXY_API_KEY`.
100
+
101
+ Usage card: AI Studio reports no remaining quota, so the card shows the pool's accounts and the models they are cooling down on. Each model gets a meter; a full one means no account can use it for now, with the time it comes back.
102
+
103
+ ### Plugin options
104
+
105
+ `allowTools`, `allowImages`, `requestTimeoutMs` and `modelTimeoutMs` apply to both providers; the other AI Studio options go under `studio`. The root `baseURL`, `contextLimit`, `outputLimit` and `stripCitations` apply to Gemini Web only.
106
+
107
+ ```bash
108
+ magpie plugin options magpie-gemini-web '{"studio":{"proxy":"http://127.0.0.1:7890"}}'
109
+ ```
110
+
111
+ | Option | Default | Description |
112
+ | :--- | :--- | :--- |
113
+ | `studio.proxy` | none | Proxy for reaching Google (http / https / socks5). The `AI_STUDIO_PROXY` environment variable works too |
114
+ | `studio.baseURL` | `http://127.0.0.1:2048/v1` | Default address for connecting an existing AIStudio2API |
115
+ | `studio.contextLimit` / `studio.outputLimit` | the model catalog's | Limits declared to clients; they can only lower the catalog's |
116
+ | `studio.allowTools` etc. | as at the root | Override the root option of the same name for AI Studio only |
117
+
118
+ AI Studio replies keep their citation marks such as `[cite: 1]`; they can't be stripped.
119
+
120
+ ### Command line
121
+
122
+ When an error from the plugin asks you to run a command, it gives the command with its full path, ready to copy. In the plugin's directory you can also use:
123
+
124
+ | Command | What it does |
125
+ | :--- | :--- |
126
+ | `npm run studio:status` | Show the service and account status |
127
+ | `npm run studio:start` / `studio:stop` | Start / stop the local service |
128
+ | `npm run studio:login` | Add a Google account |
129
+ | `npm run studio:relogin -- [<account>]` | Sign an expired account in again (optional when only one is) |
130
+ | `npm run studio:install -- --archive <file>` | Install offline from a downloaded archive |
131
+ | `node scripts/studio.mjs import <dir>` | Import existing accounts while the service is stopped |
132
+ | `npm run studio:smoke` | Live acceptance run (uses account quota) |
133
+
134
+ ### Security and data
135
+
136
+ - The service listens on `127.0.0.1` only; Magpie keeps a locally generated API key.
137
+ - Data directory: `~/.local/share/magpie-ai-studio` (override with `AI_STUDIO_DATA_DIR`). The log is `backend.log`, started afresh on the next start once it passes 10 MB.
138
+ - A first setup uses port 2048, or another free port when 2048 is taken (by an AIStudio2API of your own, say), saved in the data directory's `config.json`.
139
+ - The downloaded archive stays in the data directory; installing again uses it when its checksum matches.
140
+ - Supported on macOS, Linux (x64 / arm64) and Windows x64.
141
+
78
142
  ## Native Task on macOS (experimental)
79
143
 
80
144
  On macOS, sign-in offers one more option, "macOS 原生 Task(实验性)": requests skip the Gemini Web backend and go to a local daemon that runs them in Gemini.app's own Task mode, with tool calls on its native Function Calling channel, as the model `gemini-task-argon`. Windows and Linux don't offer it; keep using one-click setup there.
81
145
 
82
- This is an alpha: it supports only the verified Gemini.app build, needs a local setup first (Gemini.app signed in, plus session templates), hasn't passed an end-to-end check against real Argon yet, and shows no usage. See [native-task/README.md](native-task/README.md) for setup, session requirements and limitations.
146
+ This is an alpha: it supports only the verified Gemini.app build, needs a local setup first (Gemini.app signed in, plus session templates), has passed only one live tool round trip against real Argon, and shows no usage; if an agent is interrupted before it returns a tool result, that call holds the only Task slot for up to about 4 minutes. See [native-task/README.md](native-task/README.md) for setup, session requirements and limitations.
83
147
 
84
- ## Argon patched build (optional)
148
+ ## Default optimized backend and rollback
85
149
 
86
- The official backend already supports `gemini-4-argon`, which needs a paid or Ultra account. This repo's patched build also verifies that responses really come from Argon, so a silent downgrade is caught, and it lowers latency. It also makes the backend's requests look more like a browser's: on a direct connection every request carries the full set of Chrome headers (the official build's direct chat requests say `Go-http-client/2.0`), and refreshing the cookies to keep a session alive no longer fetches the `/app` page right away. Building it requires Go 1.26+:
150
+ Starting with plugin **0.4.1**, one-click setup uses [4.22.0-magpie.1](https://github.com/BUKOWSKIREAL/magpie-gemini-web/releases/tag/backend-v4.22.0-magpie.1). It includes the changes that previously required a manual build: stable XSRF caching, cancellation propagation for the main generation and upload requests, early completion after complete tool calls, browser headers, and verification of the returned Argon model. Your Google account still needs access to the requested model.
151
+
152
+ **Upgrading an existing installation:** the plugin leaves a running backend alone. Stop the existing backend process (its process ID is in `backend.pid` in the data directory), then start Magpie or send a request. A stopped old official backend is upgraded automatically, preserving configuration, the cookie database and API keys. Explicitly installed local Argon builds are kept; to replace one with the published build, stop it and run `backend:install` below.
153
+
154
+ To roll back, stop the backend and run this from the plugin directory:
87
155
 
88
156
  ```bash
89
- git clone https://github.com/BUKOWSKIREAL/magpie-gemini-web.git && cd magpie-gemini-web
90
- git clone https://github.com/zexadev/gemini-web2api-go.git backend-source
91
- git -C backend-source checkout a65b1d1a5ac614c1b455857334b4f1c73ab8fcfb
92
- git -C backend-source apply ../patches/argon.patch
93
- npm run backend:build:argon
94
- npm run backend:install:argon
157
+ npm run backend:install:upstream
95
158
  ```
96
159
 
97
- Restart Magpie when the install finishes, and the plugin starts the Argon build in the background. If an older backend is still running, stop it first with `kill $(cat ~/.local/share/magpie-gemini-web/backend.pid)`. Run `npm run backend:install` to switch back to the official build.
160
+ This installs the checksum-verified official v4.22.0 and saves the selection, so automatic starts keep using upstream. To restore the default optimized build:
98
161
 
99
- When `patches/argon.patch` changes (after you pull a new version of this repo, say), apply it again to clean sources and rebuild. Once the old backend is stopped, the plugin starts the new one on the next request:
162
+ ```bash
163
+ npm run backend:install
164
+ ```
165
+
166
+ A failed download or checksum verification keeps the previous binary. On Windows, stop the old process before replacing its executable.
167
+
168
+ The backend release includes source and build metadata. Developers with Git, Node 22+ and Go 1.27.1 can reproduce all six builds and compare the pinned hashes from this repository:
100
169
 
101
170
  ```bash
102
- git -C backend-source checkout -- . && git -C backend-source clean -fdq
103
- git -C backend-source apply ../patches/argon.patch
104
- npm run backend:build:argon && npm run backend:install:argon
105
- kill $(cat ~/.local/share/magpie-gemini-web/backend.pid)
171
+ npm run backend:release:build
106
172
  ```
107
173
 
174
+ The script extracts clean sources from the pinned upstream commit and applies `patches/argon.patch`; it never changes the developer's `backend-source` working tree. See [docs/backend-release.md](docs/backend-release.md) for the release procedure.
175
+
108
176
  ## License
109
177
 
110
178
  MIT. The upstream gemini-web2api-go project is also MIT (see `LICENSE-UPSTREAM`).
package/README.md CHANGED
@@ -2,12 +2,18 @@
2
2
 
3
3
  中文 | [English](README.en.md)
4
4
 
5
- 让 [Magpie](https://usemagpie.ai/) 通过你的 Google 账号使用 Gemini 网页版。插件在本机运行 [gemini-web2api-go](https://github.com/zexadev/gemini-web2api-go) 后端,把 Gemini 网页转成 OpenAI 兼容接口。
5
+ 让 [Magpie](https://usemagpie.ai/) 通过你的 Google 账号使用 Gemini 网页版与 Google AI Studio。插件在本机运行 [gemini-web2api-go](https://github.com/zexadev/gemini-web2api-go) 与 [AIStudio2API](https://github.com/Mag1cFall/AIStudio2API) 后端,把 Google 网页转成 OpenAI 兼容接口。
6
6
 
7
- ## 开始使用
7
+ 插件提供两个互相独立的 Provider:
8
+ - `gemini-web`:Gemini 网页版,见下面的[开始使用](#开始使用-gemini-web);
9
+ - `ai-studio`:Google AI Studio,原生工具调用,见 [Google AI Studio](#google-ai-studio-ai-studio)。
10
+
11
+ > **2026-10-16 更新**:现在正价支付的 Google AI Pro 可以直接在 Antigravity 中使用 `gemini-4-argon`,同理也可以直接用 Magpie 反代。
12
+
13
+ ## 开始使用 (Gemini Web)
8
14
 
9
15
  1. 在 Magpie 插件市场安装 **magpie-gemini-web**。
10
- 2. 登录 Gemini Web,选 **「一键配置本地 Gemini Web(推荐)」**。插件会自动下载并校验后端,在后台启动它。
16
+ 2. 登录 Gemini Web,选 **「一键配置本地 Gemini Web(推荐)」**。插件会自动下载本项目发布的优化后端、校验 SHA-256,并在后台启动;不需要安装 Go 或手动打补丁。
11
17
  3. 按提示复制 Cookie,**一定要用无痕 / 隐私窗口**(推荐 Firefox):
12
18
  1. 在无痕窗口打开 <https://gemini.google.com/app>,登录要使用的 Google 账号;
13
19
  2. 按 F12(macOS 按 ⌥⌘I),切到 **Network(网络)**,刷新页面;
@@ -24,7 +30,7 @@
24
30
 
25
31
  **连接已有后端**:如果你自己运行了 gemini-web2api-go,登录时选「连接已有后端(自定义地址 + API key)」,填后端地址(以 `/v1` 结尾)和它的 `API_KEY`。
26
32
 
27
- ## 插件选项
33
+ ## 插件选项 (Gemini Web)
28
34
 
29
35
  工具调用默认开启(Coding Agent 每个请求都带工具),图片输入默认关闭。需要图片输入时:
30
36
 
@@ -38,7 +44,7 @@ magpie plugin options magpie-gemini-web '{"allowImages":true}'
38
44
  | `allowImages` | `false` | 允许图片输入 |
39
45
  | `baseURL` | `http://127.0.0.1:8083/v1` | 默认后端地址 |
40
46
  | `contextLimit` / `outputLimit` | `1000000` / `8192` | 向客户端声明的上下文 / 输出上限 |
41
- | `requestTimeoutMs` / `modelTimeoutMs` | `240000` / `10000` | 请求 / 拉取模型列表的超时(毫秒) |
47
+ | `requestTimeoutMs` / `modelTimeoutMs` | `240000` / `10000` | 请求 / 拉取模型列表的超时(毫秒)。请求超时按每次等待后端计算,回复持续输出时不会被打断 |
42
48
  | `stripCitations` | `true` | 去掉 Gemini 在回复里加的引用标记 `[cite: 1]`、`[cite_start]`(包括工具调用参数)。让 Gemini 编辑本身含有这类文本的代码时,可以设为 `false` |
43
49
 
44
50
  ## 思考档位
@@ -48,7 +54,7 @@ magpie plugin options magpie-gemini-web '{"allowImages":true}'
48
54
  ## 安全与数据
49
55
 
50
56
  - 后端只监听 `127.0.0.1`;Cookie 只交给本机后端,Magpie 保存的是本地生成的 API key。
51
- - 后端二进制锁定官方 v4.22.0,下载和每次启动都校验 SHA-256。支持 macOS、Linux、Windows(x64 / arm64)。
57
+ - 默认后端为本项目发布的 **4.22.0-magpie.1**,基于固定的上游 v4.22.0 源码应用本仓库补丁。下载和启动新进程前校验 SHA-256。支持 macOS、Linux、Windows(x64 / arm64),发布页提供源码、构建记录和校验和。
52
58
  - 数据目录:`~/.local/share/magpie-gemini-web`(可用 `GEMINI_WEB_DATA_DIR` 修改),日志在 `backend.log`。
53
59
  - 插件限制并发为 1,但无法保证账号不被 Google 风控,请自行承担风险。
54
60
 
@@ -70,41 +76,103 @@ Magpie 的额度卡片会显示 Google 账号的 **5 小时** 和 **每周** 用
70
76
 
71
77
  所以配了代理池时,一键配置刚添加的账号暂时没有邮箱。先用它发一次请求,再用「添加本地后端里已有的 Google 账号」重新登录它,然后删掉没有邮箱的那个登录。
72
78
 
73
- ## 局限
79
+ ## 局限 (Gemini Web)
74
80
 
75
81
  - 工具调用由上游用提示词模拟,不一定可靠,Flash 系列经常不调用工具。
76
82
  - 只开放 `gemini-` 开头的文本模型;`cost` 显示为 0 不代表 Google 的实际配额。
77
83
 
84
+ ## Google AI Studio (`ai-studio`)
85
+
86
+ 通过 [AIStudio2API](https://github.com/Mag1cFall/AIStudio2API)(固定 v0.2.12)使用 Google AI Studio。和 Gemini Web 相比,工具调用走原生 Function Calling,思考模型可以在 Magpie 里切换 `minimal` / `low` / `medium` / `high` 四档(`minimal` 最快、最省额度),日常生成不需要浏览器。
87
+
88
+ ### 开始使用
89
+
90
+ 1. 登录 Google AI Studio,选 **「一键配置本地 Google AI Studio(推荐)」**。插件会自动下载 AIStudio2API、校验 SHA-256 并在后台启动。
91
+ 2. 在弹出的独立登录窗口里登录 Google 账号(不影响你平时用的浏览器),完成后关掉窗口即可。第一次要先下载登录用的浏览器 Camoufox,窗口可能要等几分钟才出现;需要在 15 分钟内完成登录。
92
+
93
+ 想加更多账号,再走一遍一键配置。所有账号共用一张登录卡片:每个请求用哪个账号由本地服务决定,先用一个,冷却了再换下一个。
94
+
95
+ 其他登录选项:
96
+
97
+ - **使用本机已有的 AI Studio 服务**:本机已经有账号(比如用命令行添加的)时直接登录,不打开登录窗口。
98
+ - **重新登录失效的 AI Studio 账号**:账号的 Google 登录过期后,在这里选中它重新登录。
99
+ - **连接已有 AIStudio2API**:你自己运行了 AIStudio2API 时,填它的地址(默认 `http://127.0.0.1:2048/v1`)和 `PROXY_API_KEY`。
100
+
101
+ 额度卡片:AI Studio 不提供剩余额度,卡片显示账号池里的账号和正在冷却的模型。每个模型一条进度条,满格表示暂时没有账号能用它,旁边是恢复时间。
102
+
103
+ ### 插件选项
104
+
105
+ `allowTools`、`allowImages`、`requestTimeoutMs`、`modelTimeoutMs` 两个 Provider 共用;其余 AI Studio 选项放在 `studio` 里,根级别的 `baseURL`、`contextLimit`、`outputLimit`、`stripCitations` 只对 Gemini Web 生效。
106
+
107
+ ```bash
108
+ magpie plugin options magpie-gemini-web '{"studio":{"proxy":"http://127.0.0.1:7890"}}'
109
+ ```
110
+
111
+ | 选项 | 默认值 | 说明 |
112
+ | :--- | :--- | :--- |
113
+ | `studio.proxy` | 无 | 访问 Google 用的代理(http / https / socks5)。也可以用环境变量 `AI_STUDIO_PROXY` |
114
+ | `studio.baseURL` | `http://127.0.0.1:2048/v1` | 「连接已有 AIStudio2API」的默认地址 |
115
+ | `studio.contextLimit` / `studio.outputLimit` | 模型目录的值 | 向客户端声明的上限,只会调低 |
116
+ | `studio.allowTools` 等 | 同根级别 | 只对 AI Studio 覆盖根级别的同名选项 |
117
+
118
+ AI Studio 的回复保留引用标记 `[cite: 1]`,不能去掉。
119
+
120
+ ### 命令行
121
+
122
+ 插件报错里需要你运行命令时,会给出带完整路径的命令,复制即可运行。在插件目录里也可以用:
123
+
124
+ | 命令 | 作用 |
125
+ | :--- | :--- |
126
+ | `npm run studio:status` | 查看服务和账号状态 |
127
+ | `npm run studio:start` / `studio:stop` | 启动 / 停止本地服务 |
128
+ | `npm run studio:login` | 添加 Google 账号 |
129
+ | `npm run studio:relogin -- [<账号>]` | 重新登录过期的账号(只有一个时可省略) |
130
+ | `npm run studio:install -- --archive <文件>` | 用下载好的安装包离线安装 |
131
+ | `node scripts/studio.mjs import <目录>` | 服务停止时导入已有账号 |
132
+ | `npm run studio:smoke` | 真实请求验收(会用掉账号额度) |
133
+
134
+ ### 数据与安全
135
+
136
+ - 服务只监听 `127.0.0.1`,Magpie 保存的是本地生成的 API key。
137
+ - 数据目录:`~/.local/share/magpie-ai-studio`(可用 `AI_STUDIO_DATA_DIR` 修改)。日志在 `backend.log`,超过 10 MB 时下次启动换新。
138
+ - 第一次配置使用 2048 端口;被占用时(比如你自己也在跑 AIStudio2API)自动换一个,记在数据目录的 `config.json`。
139
+ - 下载的安装包留在数据目录,重装时校验通过就不再下载。
140
+ - 支持 macOS、Linux(x64 / arm64)和 Windows x64。
141
+
78
142
  ## macOS 原生 Task(实验性)
79
143
 
80
144
  在 macOS 上登录时会多出一个「macOS 原生 Task(实验性)」选项:请求不走 Gemini Web 后端,而是交给本机常驻服务,由 Gemini.app 自己的 Task 模式执行,工具调用走原生的 Function Calling 通道,模型为 `gemini-task-argon`。Windows 和 Linux 上不会出现这个选项,请继续使用上面的一键配置。
81
145
 
82
- 当前为 Alpha:仅支持已验证的 Gemini.app 版本,选这个选项之前需要先在本机完成 setup(需要 Gemini.app 已登录,以及会话模板),尚未完成真实 Argon 的端到端验收,读不到额度。配置步骤、会话要求和限制见 [native-task/README.md](native-task/README.md)。
146
+ 当前为 Alpha:仅支持已验证的 Gemini.app 版本,选这个选项之前需要先在本机完成 setup(需要 Gemini.app 已登录,以及会话模板),只完成过一次真实 Argon 的工具往返验证,读不到额度;Agent 中途打断时,未回传结果的工具调用会占住唯一的 Task 名额最长约 4 分钟。配置步骤、会话要求和限制见 [native-task/README.md](native-task/README.md)。
83
147
 
84
- ## Argon 增强版(可选)
148
+ ## 默认优化后端与回退
85
149
 
86
- 官方后端已支持 `gemini-4-argon`(需付费 / Ultra 账号)。本仓库的补丁版额外校验返回的确实是 Argon(防止被静默降级),并降低延迟。它也让后端的请求更像浏览器:直连时每个请求都带齐 Chrome 请求头(官方版直连时,对话请求的 UA 是 `Go-http-client/2.0`),保活刷新 Cookie 后也不再立即重新抓取 `/app` 页面。需要 Go 1.26+:
150
+ 从插件 **0.4.1** 起,一键配置默认使用 [4.22.0-magpie.1](https://github.com/BUKOWSKIREAL/magpie-gemini-web/releases/tag/backend-v4.22.0-magpie.1)。它包含原先需要手动编译的优化:稳定的 XSRF 缓存、主要生成与上传请求的取消传播、完整工具调用后的提前收尾、浏览器请求头,以及 Argon 返回模型校验。Google 账号仍需具备对应模型权限。
151
+
152
+ **已有用户升级**:插件不会中断正在运行的后端。先停止现有后端进程(进程 ID 在数据目录的 `backend.pid`),再启动 Magpie 或发送请求;停止状态的旧官方后端会自动更新,配置、Cookie 数据库和 API key 保留。已经手动安装的本地 Argon 构建会继续复用;要切到发布版,可在停止后端后运行下面的 `backend:install`。
153
+
154
+ 需要回退时,在插件目录停止后端后运行:
87
155
 
88
156
  ```bash
89
- git clone https://github.com/BUKOWSKIREAL/magpie-gemini-web.git && cd magpie-gemini-web
90
- git clone https://github.com/zexadev/gemini-web2api-go.git backend-source
91
- git -C backend-source checkout a65b1d1a5ac614c1b455857334b4f1c73ab8fcfb
92
- git -C backend-source apply ../patches/argon.patch
93
- npm run backend:build:argon
94
- npm run backend:install:argon
157
+ npm run backend:install:upstream
95
158
  ```
96
159
 
97
- 安装后重启 Magpie 即可,插件会在后台启动 Argon 版(如有旧后端在运行,先 `kill $(cat ~/.local/share/magpie-gemini-web/backend.pid)`)。运行 `npm run backend:install` 可切回官方版。
160
+ 这会安装经过 SHA-256 校验的官方 v4.22.0,并记住回退选择,之后自动启动也使用官方版。恢复默认优化版:
98
161
 
99
- `patches/argon.patch` 更新后(比如拉取了本仓库的新版本),需要在干净的源码上重新应用补丁并重新构建。停掉旧后端后,插件会在下一个请求时启动新版:
162
+ ```bash
163
+ npm run backend:install
164
+ ```
165
+
166
+ 下载失败或校验不通过时保留旧二进制。Windows 上必须先停止旧进程,才能替换正在使用的可执行文件。
167
+
168
+ 源码与构建记录随后端 Release 提供。开发者使用 Git、Node 22+、Go 1.27.1,可从本仓库复现全部六个平台的构建并核对哈希:
100
169
 
101
170
  ```bash
102
- git -C backend-source checkout -- . && git -C backend-source clean -fdq
103
- git -C backend-source apply ../patches/argon.patch
104
- npm run backend:build:argon && npm run backend:install:argon
105
- kill $(cat ~/.local/share/magpie-gemini-web/backend.pid)
171
+ npm run backend:release:build
106
172
  ```
107
173
 
174
+ 构建脚本从固定的上游提交提取干净源码、应用 `patches/argon.patch`,不会修改本地 `backend-source` 的工作内容。发布流程见 [docs/backend-release.md](docs/backend-release.md)。
175
+
108
176
  ## 友链
109
177
 
110
178
  [LINUX DO](https://linux.do/) — 真诚、友善、团结、专业的技术社区。
@@ -0,0 +1,31 @@
1
+ # Backend releases
2
+
3
+ The plugin's default backend is built from the upstream commit and toolchain recorded in `lib/backend-release.json`, with `patches/argon.patch` applied. The builder overrides the backend's displayed version with the release version. Six binaries are pinned by SHA-256 in the same JSON file. The build does not include the developer's uncommitted backend sources, local data or credentials.
4
+
5
+ For a new backend release:
6
+
7
+ 1. Choose a new backend version and tag in `lib/backend-release.json`. Never replace files under an already published backend tag: older plugins pin those hashes. Update the upstream commit or patch when needed.
8
+ 2. Run `node scripts/backend-release.mjs --write-pins`. It extracts a clean upstream tree, applies the patch, runs Go tests, cross-compiles all six targets and writes the resulting pins. It uses a local `backend-source` Git object database if available; otherwise it fetches the pinned public commit in a temporary directory.
9
+ 3. Run `npm test` and `node scripts/backend-smoke.mjs`. The smoke test uses a temporary data directory, checks the actual executable's version and hash, starts it on a spare loopback port, checks authentication and model discovery, and verifies reuse. It uses no Google account and takes the tokenizer's offline fallback.
10
+ 4. Commit the release metadata, installer changes, tests and documentation. Run the **Verify backend release** GitHub Actions workflow at that commit. It rebuilds on native macOS, Linux and Windows runners for both architectures, compares the pinned hashes, and runs the installation/startup smoke test. Wait for all jobs to pass.
11
+ 5. Create a private draft under the pinned backend tag. Attach all six binaries, `SHA256SUMS.txt`, `build.json`, the patched source archive and `LICENSE-UPSTREAM` from `backend-build/release`. If local binary uploads are unreliable, run **Upload verified backend release** with the successful verification run ID: it downloads the six CI artifacts, checks every committed hash, and uploads missing executables to the draft. Existing assets must match exactly; published releases cannot be modified by this workflow. Include the upstream commit and patch SHA-256 in the release notes, then publish the complete draft. Keep backend-only releases from replacing the plugin release as GitHub's latest release.
12
+ 6. Verify public asset downloads against the committed pins. Run `node scripts/backend-smoke.mjs --download` to test the actual default download URL on the host platform.
13
+ 7. Bump and publish the plugin package only after the backend assets are publicly available. Inspect `npm pack --dry-run`; the npm package contains release metadata and patch/build scripts, but no executables, local databases or credentials. Attach the exact published npm tarball to the plugin's GitHub release as well.
14
+
15
+ Reproduce a release without changing its pins:
16
+
17
+ ```bash
18
+ npm run backend:release:build
19
+ ```
20
+
21
+ Build just the host target and compare its hash:
22
+
23
+ ```bash
24
+ node scripts/backend-release.mjs --target=host --verify
25
+ ```
26
+
27
+ The metadata records `CGO_ENABLED=0`, the exact Go toolchain, upstream commit, patch hash and build flags. The binary hashes are reproducible; the source archive is supplied for inspection and is not promised to have a reproducible gzip timestamp. The source archive includes upstream's license, and `LICENSE-UPSTREAM` is also supplied as a separate asset.
28
+
29
+ Existing running processes are left alone to avoid interrupting requests. Once an old official backend is stopped, automatic startup installs the optimized build while preserving configuration, secrets and the database. A download or checksum failure keeps the old file and never starts an unverified replacement.
30
+
31
+ An explicit `npm run backend:install:upstream` installs the pinned upstream v4.22.0 and persists `upstream` in `backend-channel.json`. Automatic startup respects that choice. `npm run backend:install` returns to the optimized channel. Stop a running backend before replacing it, particularly on Windows. Explicit local Argon builds remain trusted through their existing build manifest.
package/index.mjs CHANGED
@@ -63,7 +63,11 @@ async function forwardManaged(input, init, getAuth, opts) {
63
63
  }
64
64
 
65
65
  export const GeminiWebPlugin = async (_input, options = {}) => {
66
- const opts = settings(options);
66
+ if (!options || typeof options !== 'object' || Array.isArray(options)) {
67
+ settings(options);
68
+ }
69
+ const { studio: _studio, ...webOptions } = options;
70
+ const opts = settings(webOptions);
67
71
 
68
72
  // Bring a backend set up earlier back after Magpie or the computer restarts. Not awaited:
69
73
  // requests that arrive first start it themselves through forwardManaged.
@@ -220,4 +224,5 @@ export const GeminiWebPlugin = async (_input, options = {}) => {
220
224
  };
221
225
  };
222
226
 
227
+ export { AIStudioPlugin } from './lib/studio.mjs';
223
228
  export default GeminiWebPlugin;
@@ -0,0 +1,36 @@
1
+ {
2
+ "version": "4.22.0-magpie.1",
3
+ "repository": "BUKOWSKIREAL/magpie-gemini-web",
4
+ "tag": "backend-v4.22.0-magpie.1",
5
+ "upstream": {
6
+ "repository": "https://github.com/zexadev/gemini-web2api-go.git",
7
+ "commit": "a65b1d1a5ac614c1b455857334b4f1c73ab8fcfb"
8
+ },
9
+ "goVersion": "1.27.1",
10
+ "binaries": {
11
+ "darwin-arm64": {
12
+ "asset": "gemini-web2api-go_v4.22.0-magpie.1_darwin_arm64",
13
+ "sha256": "833dd54e7c0df927afc1d4e0f6443bcc03b7f0a4d04d24cdfde47d5dd27349c5"
14
+ },
15
+ "darwin-x64": {
16
+ "asset": "gemini-web2api-go_v4.22.0-magpie.1_darwin_amd64",
17
+ "sha256": "d65b053a0e5f8e1065ea35835b3a7d12f783d97964c02bef49679df7ead92fd4"
18
+ },
19
+ "linux-x64": {
20
+ "asset": "gemini-web2api-go_v4.22.0-magpie.1_linux_amd64",
21
+ "sha256": "94f082e666b34051f191959de3f2cd601078d117b1d3ededcdcd6b2201c48ef9"
22
+ },
23
+ "linux-arm64": {
24
+ "asset": "gemini-web2api-go_v4.22.0-magpie.1_linux_arm64",
25
+ "sha256": "4a7cbca2771acc9e836a5a986e11b3b247baf77e9900262cb588b515a1161aaa"
26
+ },
27
+ "win32-x64": {
28
+ "asset": "gemini-web2api-go_v4.22.0-magpie.1_windows_amd64.exe",
29
+ "sha256": "61d279d50c6c09ffe81ed059a557077900948d0ae598e4c4b3a5d5c213ad5e5c"
30
+ },
31
+ "win32-arm64": {
32
+ "asset": "gemini-web2api-go_v4.22.0-magpie.1_windows_arm64.exe",
33
+ "sha256": "20bad088b114d3dc989830ff35f7e56c1e0026caf9721b739fe982f5fd3d1880"
34
+ }
35
+ }
36
+ }
package/lib/backend.mjs CHANGED
@@ -30,7 +30,7 @@ const KNOWN_OPTIONS = new Set([
30
30
  'stripCitations'
31
31
  ]);
32
32
 
33
- function makeOpenAIError(status, message, extraHeaders = {}) {
33
+ export function makeOpenAIError(status, message, extraHeaders = {}) {
34
34
  const codeMap = {
35
35
  400: 'invalid_request_error',
36
36
  401: 'unauthorized',
@@ -360,6 +360,47 @@ async function thinkingTwin(body, c, opts) {
360
360
  return cached?.ids.has(twin) ? twin : null;
361
361
  }
362
362
 
363
+ // waitTimer aborts its signal when one wait on the backend, from start() to stop(), outlasts ms.
364
+ function waitTimer(ms) {
365
+ const controller = new AbortController();
366
+ let timeout;
367
+ return {
368
+ signal: controller.signal,
369
+ start() {
370
+ clearTimeout(timeout);
371
+ timeout = setTimeout(() => {
372
+ controller.abort(new DOMException(`The backend sent nothing for ${ms} ms`, 'TimeoutError'));
373
+ }, ms);
374
+ },
375
+ stop() {
376
+ clearTimeout(timeout);
377
+ }
378
+ };
379
+ }
380
+
381
+ // timedBody passes a response body on, timing each read from the backend with timer. Time the
382
+ // reader of the returned stream takes between reads doesn't count.
383
+ function timedBody(body, timer) {
384
+ const reader = body.getReader();
385
+ return new ReadableStream({
386
+ async pull(controller) {
387
+ timer.start();
388
+ let piece;
389
+ try {
390
+ piece = await reader.read();
391
+ } finally {
392
+ timer.stop();
393
+ }
394
+ if (piece.done) controller.close();
395
+ else controller.enqueue(piece.value);
396
+ },
397
+ cancel(reason) {
398
+ timer.stop();
399
+ return reader.cancel(reason);
400
+ }
401
+ });
402
+ }
403
+
363
404
  export async function forward(input, init, getAuth, opts) {
364
405
  const req = new Request(input, init);
365
406
 
@@ -479,17 +520,20 @@ export async function forward(input, init, getAuth, opts) {
479
520
  }
480
521
  }
481
522
 
482
- const twin = await thinkingTwin(body, c, opts);
523
+ const twin = opts.nativeThinking ? null : await thinkingTwin(body, c, opts);
483
524
  if (twin) {
484
525
  body.model = twin;
485
526
  rawBody = JSON.stringify(body);
486
527
  }
487
528
  }
488
529
 
489
- const timeoutSignal = AbortSignal.timeout(opts.requestTimeoutMs);
490
- const signal = AbortSignal.any([req.signal, timeoutSignal]);
530
+ // requestTimeoutMs bounds each wait on the backend, for the response headers and then for each
531
+ // piece of the body, so a long streamed reply that keeps coming is never cut off.
532
+ const timer = waitTimer(opts.requestTimeoutMs);
533
+ const signal = AbortSignal.any([req.signal, timer.signal]);
491
534
 
492
535
  let upstreamRes;
536
+ timer.start();
493
537
  try {
494
538
  upstreamRes = await fetch(incomingUrl, {
495
539
  method: req.method,
@@ -502,13 +546,15 @@ export async function forward(input, init, getAuth, opts) {
502
546
  if (req.signal.aborted) {
503
547
  throw req.signal.reason || new DOMException('The operation was aborted.', 'AbortError');
504
548
  }
505
- if (timeoutSignal.aborted || err?.name === 'TimeoutError') {
549
+ if (timer.signal.aborted || err?.name === 'TimeoutError') {
506
550
  return makeOpenAIError(504, 'Gateway timeout: backend request timed out');
507
551
  }
508
552
  if (err?.name === 'AbortError') {
509
553
  throw err;
510
554
  }
511
555
  return makeOpenAIError(502, 'Bad gateway: failed to reach backend service', { [UNREACHABLE_HEADER]: 'unreachable' });
556
+ } finally {
557
+ timer.stop();
512
558
  }
513
559
 
514
560
  const respHeaders = new Headers(upstreamRes.headers);
@@ -519,11 +565,11 @@ export async function forward(input, init, getAuth, opts) {
519
565
  }
520
566
 
521
567
  // Gemini's citation markers come out of a chat reply, streamed or whole (see cite.mjs).
522
- let respBody = upstreamRes.body;
568
+ let respBody = upstreamRes.body && timedBody(upstreamRes.body, timer);
523
569
  if (opts.stripCitations && incomingUrl === chatUrl && upstreamRes.ok && respBody) {
524
570
  const type = upstreamRes.headers.get('content-type') || '';
525
571
  if (type.includes('text/event-stream')) respBody = citeStream(respBody);
526
- else if (type.includes('json')) respBody = citeJSON(await upstreamRes.text());
572
+ else if (type.includes('json')) respBody = citeJSON(await new Response(respBody).text());
527
573
  }
528
574
 
529
575
  return new Response(respBody, {