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 +90 -22
- package/README.md +90 -22
- package/docs/backend-release.md +31 -0
- package/index.mjs +6 -1
- package/lib/backend-release.json +36 -0
- package/lib/backend.mjs +53 -7
- package/lib/native.mjs +50 -18
- package/lib/setup.mjs +27 -4
- package/lib/studio-native.mjs +1137 -0
- package/lib/studio-release.json +27 -0
- package/lib/studio.mjs +641 -0
- package/native-task/README.md +3 -1
- package/package.json +16 -3
- package/scripts/backend-release.mjs +111 -0
- package/scripts/backend.mjs +4 -1
- package/scripts/studio-smoke.mjs +195 -0
- package/scripts/studio.mjs +377 -0
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
|
|
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
|
-
|
|
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
|
|
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
|
|
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),
|
|
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
|
-
##
|
|
148
|
+
## Default optimized backend and rollback
|
|
85
149
|
|
|
86
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
-
-
|
|
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
|
|
146
|
+
当前为 Alpha:仅支持已验证的 Gemini.app 版本,选这个选项之前需要先在本机完成 setup(需要 Gemini.app 已登录,以及会话模板),只完成过一次真实 Argon 的工具往返验证,读不到额度;Agent 中途打断时,未回传结果的工具调用会占住唯一的 Task 名额最长约 4 分钟。配置步骤、会话要求和限制见 [native-task/README.md](native-task/README.md)。
|
|
83
147
|
|
|
84
|
-
##
|
|
148
|
+
## 默认优化后端与回退
|
|
85
149
|
|
|
86
|
-
|
|
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
|
-
|
|
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
|
-
|
|
160
|
+
这会安装经过 SHA-256 校验的官方 v4.22.0,并记住回退选择,之后自动启动也使用官方版。恢复默认优化版:
|
|
98
161
|
|
|
99
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
490
|
-
|
|
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 (
|
|
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
|
|
572
|
+
else if (type.includes('json')) respBody = citeJSON(await new Response(respBody).text());
|
|
527
573
|
}
|
|
528
574
|
|
|
529
575
|
return new Response(respBody, {
|