rynn-k/Gemini-Reverse
GitHub: rynn-k/Gemini-Reverse
非官方 Node.js 客户端,通过逆向实现免 API 密钥调用 Google Gemini 网页版,支持流式对话、多模型与文件上传。
Stars: 2 | Forks: 0

# Gemini-Reverse
一个非官方的 Node.js 客户端,用于访问 [gemini.google.com](https://gemini.google.com),灵感来源于 [@HanaokaYuzu](https://github.com/HanaokaYuzu) 的 Python 逆向工程项目 [Gemini-API](https://github.com/HanaokaYuzu/Gemini-API)。
本包将原始 Python 库的核心概念和功能移植到了 Node.js,并提供完整的 CommonJS 和 TypeScript 支持。
## 功能特性
- 向 Gemini 发送消息并接收响应
- 支持文本增量的流式传输
- 具有对话历史的多轮聊天会话
- 支持文件和图片上传
- Gem(系统提示词)管理 —— 创建、更新、删除、获取
- 自动刷新 Cookie 以保持会话活跃
- 包含 TypeScript 类型声明
- 支持 Proxy(代理)
## 安装
```
npm install gemini-reverse
```
## 身份验证
本包使用浏览器 Cookie 来通过 Gemini 的身份验证。你需要登录 [gemini.google.com](https://gemini.google.com) 后,从浏览器中获取 `__Secure-1PSID` Cookie。
**步骤:**
1. 在浏览器中打开 [gemini.google.com](https://gemini.google.com) 并登录
2. 打开 DevTools → Application → Cookies → `https://gemini.google.com`
3. 复制 `__Secure-1PSID` 的值(以及可选的 `__Secure-1PSIDTS`)
## 快速开始
```
const { GeminiClient } = require('gemini-reverse');
const client = new GeminiClient({
secure_1psid: 'YOUR_SECURE_1PSID',
});
await client.init();
const chat = client.startChat();
const response = await chat.sendMessage({ prompt: 'Hello, Gemini!' });
console.log(response.text);
```
## 用法
### 初始化客户端
```
const client = new GeminiClient({
secure_1psid: 'YOUR_SECURE_1PSID',
secure_1psidts: 'YOUR_SECURE_1PSIDTS', // optional
proxy: 'http://host:port', // optional
});
await client.init({
timeout: 300000, // request timeout in ms, default 300000
autoClose: false, // auto close client after inactivity
closeDelay: 300000, // inactivity delay before closing in ms
autoRefresh: true, // auto refresh cookies in background
refreshInterval: 540000 // cookie refresh interval in ms
});
```
### 生成内容(单轮)
```
const response = await client.generateContent({ prompt: 'What is the capital of France?' });
console.log(response.text);
```
### 流式传输
```
for await (const chunk of client.generateContentStream({ prompt: 'Tell me a long story.' })) {
process.stdout.write(chunk.text_delta);
}
```
### 聊天会话
```
const chat = client.startChat({ model: 'gemini-3.1-pro' });
const res1 = await chat.sendMessage({ prompt: 'My name is Alice.' });
console.log(res1.text);
const res2 = await chat.sendMessage({ prompt: 'What is my name?' });
console.log(res2.text); // remembers context
```
### 聊天中的流式传输
```
const chat = client.startChat({ model: 'gemini-3.0-flash' });
for await (const chunk of chat.sendMessageStream({ prompt: 'Explain quantum computing.' })) {
process.stdout.write(chunk.text_delta);
}
```
### 临时聊天(不保存历史记录)
```
const chat = client.startChat();
const response = await chat.sendMessage({ prompt: 'This will not appear in history.', temporary: true });
```
### 发送文件
```
const chat = client.startChat();
const response = await chat.sendMessage({
prompt: 'Describe this image.',
files: ['./photo.jpg'],
});
console.log(response.text);
```
### 多个候选结果
```
const chat = client.startChat();
const response = await chat.sendMessage({ prompt: 'Give me a poem.' });
// list all candidates
response.candidates.forEach((c, i) => console.log(`[${i}] ${c.text}`));
// choose a specific candidate to continue the conversation
chat.chooseCandidate(1);
```
### 模型
```
// use model name string
const chat = client.startChat({ model: 'gemini-3.1-pro' });
// or use the Model constant
const { Model } = require('gemini-api');
const chat = client.startChat({ model: Model.G_3_0_FLASH });
// or use a custom model dict
const chat = client.startChat({
model: {
model_name: 'my-model',
model_header: { 'x-goog-ext-525001261-jspb': '...' },
},
});
```
**可用模型:**
| String | Constant |
|---|---|
| `gemini-3.1-pro` | `Model.G_3_1_PRO` |
| `gemini-3.0-flash` | `Model.G_3_0_FLASH` |
| `gemini-3.0-flash-thinking` | `Model.G_3_0_FLASH_THINKING` |
| `unspecified` (default) | `Model.UNSPECIFIED` |
### 图片
响应可能包含网络图片或 AI 生成的图片。
```
const response = await chat.sendMessage({ prompt: 'Send me an image of a cat.' });
for (const img of response.images) {
console.log(img.url, img.title, img.alt);
await img.save({ path: './downloads', verbose: true });
}
```
### 读取聊天历史
```
const turns = await client.readChat('c_YOUR_CHAT_ID');
for (const turn of turns) {
console.log('User:', turn.user_prompt);
console.log('Gemini:', turn.assistant_response);
}
```
### 删除聊天
```
await client.deleteChat('c_YOUR_CHAT_ID');
```
### Gems
```
// fetch all gems
const gems = await client.fetchGems();
// get by name
const gem = gems.get({ name: 'Coding partner' });
// filter user-created gems
const myGems = gems.filter({ predefined: false });
// use a gem in chat
const chat = client.startChat({ gem: gem });
// create a gem
const newGem = await client.createGem({
name: 'My Assistant',
prompt: 'You are a helpful assistant that speaks formally.',
description: 'Formal assistant gem',
});
// update a gem
await client.updateGem({
gem: newGem,
name: 'My Assistant v2',
prompt: 'You are a helpful assistant that speaks casually.',
});
// delete a gem
await client.deleteGem(newGem);
```
### 关闭客户端
```
await client.close();
```
## TypeScript
本包开箱即用地包含完整的 TypeScript 声明。
```
import { GeminiClient, ChatSession, ModelOutput, ConversationTurn, Gem, Model } from 'gemini-reverse';
const client = new GeminiClient({ secure_1psid: '...' });
await client.init();
const chat: ChatSession = client.startChat({ model: 'gemini-3.1-pro' });
const response: ModelOutput = await chat.sendMessage({ prompt: 'Hello!' });
console.log(response.text);
```
## 项目结构
```
gemini-api/
├── index.js # entry point
├── index.d.ts # TypeScript declarations
├── client.js # GeminiClient + ChatSession
├── constants.js # Endpoint, GRPC, Headers, Model, ErrorCode
├── exceptions.js # custom error classes
├── types/
│ ├── candidate.js
│ ├── conversation.js
│ ├── gem.js
│ ├── grpc.js
│ ├── image.js
│ └── modeloutput.js
├── utils/
│ ├── accessToken.js
│ ├── parsing.js
│ ├── rotate.js
│ └── upload.js
└── components/
├── chatMixin.js
└── gemMixin.js
```
## 错误处理
```
const {
AuthError,
APIError,
GeminiError,
TimeoutError,
UsageLimitExceeded,
ModelInvalid,
TemporarilyBlocked,
} = require('gemini-reverse');
try {
const response = await chat.sendMessage({ prompt: 'Hello!' });
} catch (e) {
if (e instanceof AuthError) {
console.error('Cookie expired or invalid.');
} else if (e instanceof UsageLimitExceeded) {
console.error('Usage limit reached. Try again later or switch models.');
} else if (e instanceof TemporarilyBlocked) {
console.error('IP temporarily blocked. Try using a proxy.');
} else if (e instanceof TimeoutError) {
console.error('Request timed out.');
} else if (e instanceof ModelInvalid) {
console.error('Invalid or unavailable model.');
} else if (e instanceof APIError) {
console.error('API error:', e.message);
}
}
```
## 致谢
灵感来源于 [@HanaokaYuzu](https://github.com/HanaokaYuzu) 的 [Gemini-API](https://github.com/HanaokaYuzu/Gemini-API) —— 一个通过逆向工程实现的非官方 Python Gemini 客户端。
## 免责声明
这是一个非官方的包,不隶属于 Google,也未获得 Google 的认可。请自行承担使用风险。如果 Google 更改其内部 API,基于 Cookie 的身份验证可能会失效。
## 许可证
MIT
标签:AI 聊天, API 客户端, Chatbot, CommonJS, Cookie 认证, DLL 劫持, Gemini, GNU通用公共许可证, MITM代理, Node.js, NPM 包, TypeScript, Web Scraping, 云资产清单, 代理支持, 会话管理, 告警, 大语言模型, 安全插件, 文件上传, 流式响应, 系统指令, 网络调试, 自动化, 逆向工程, 配置审计, 非官方库