1仕組みと動作原理
実装の基盤は手書きのGemini Webクライアント(オープンソースのgemini_webapiから移植されたTypeScript)であり、Web版のプライベートAPIをSDKとして利用しています。これにより、公式APIキーなしでテキストや画像を生成できます。
| `scripts/gemini-webapi/*` | TypeScript port of `gemini_webapi` (GeminiClient, types, utils) |
エンドポイントはconstants.tsに集約されています:INITでページトークンを取得、GENERATEでStreamGenerateプライベートエンドポイントを使用、ROTATE_COOKIESでセッションCookieをローテーション、UPLOADで参照画像をアップロード、BATCH_EXECでbatchexecuteを経由します。
'https://gemini.google.com/_/BardChatUi/data/assistant.lamda.BardFrontendService/StreamGenerate',
認証の最初のステップはWebページからのSNlM0eアクセストークンの取得です:gemini.google.com/appに対してGETを実行し、正規表現でHTMLから抽出し、以降のすべての生成リクエストに付与します。
const m = text.match(/\"SNlM0e\":\"(.*?)\"/);
クレデンシャルのソースはブラウザのセッションCookie(__Secure-1PSID / __Secure-1PSIDTS)です:まずローカルのCookieファイルを読み込み、失敗した場合はCDP経由でブラウザに接続してCookieを取得します。デフォルトでは実行中のローカルChromeデバッグセッションを再利用します。
const existingCookies = hasExplicitProfile ? null : await fetch_cookies_from_existing_chrome(30_000, verbose);
Cookieとトークンは永続化されます:cookies.jsonに__Secure-1PSID/1PSIDTSなどが保存され、バックグラウンドの定期タスクがRotateCookiesを使用して1PSIDTSを更新し、ディスクに再保存します。
this.cookies['__Secure-1PSIDTS'] = newTs;
生成リクエストはフォームPOSTです:bodyにat(アクセストークン)とf.req(ネストされたJSON配列)を含め、レスポンスはWeb版のストリーミングチャンクテキストとなるため、本文チャンクを抽出するために独自にアンパックする必要があります。
const body = new URLSearchParams({ at: this.access_token, 'f.req': f_req }).toString();
マルチターン会話はGeminiのチャットメタデータをローカルセッションファイルに保存することで実現されます:--sessionIdで同一のメタデータを再利用して対話を継続し、メッセージ履歴もJSONに記録されます。
Session files stored in data directory under `sessions/<id>.json`.
リバースエンジニアリングの利用には明示的な「事前同意」が必要です:初回利用時にはconsent.json(accepted + disclaimerVersion 1.0)を書き込む必要があり、拒否した場合は即座に終了します。
1. Check if consent file exists with `accepted: true` and `disclaimerVersion: "1.0"`
画像バックエンドとしても機能します:--imageで画像を出力(デフォルトはgenerated.png)、--reference/--refでビジョン入力、--promptfilesでファイルからプロンプトを読み込むため、リポジトリ内では「単体でバックエンドとなる」例外的なスキルとして位置付けられています。
Skills that **are themselves** image-generation backends — currently `baoyu-image-gen`, `baoyu-image-gen` (deprecated), and `baoyu-danger-gemini-web` — do NOT include a `## Image Generation Tools` section.
2コア機能
3外部依存関係
| Kind | Dependency / Endpoint |
|---|---|
| network | gemini.google.com(INIT 页面 + StreamGenerate 私有接口 + batchexecute) |
| network | accounts.google.com(RotateCookies 轮换 1PSIDTS) |
| network | www.google.com(基础页/常量) |
| network | content-push.googleapis.com(参考图上传) |
| package | baoyu-chrome-cdp ^0.1.1(npm,用于发现/启动/接管 Chrome 调试会话并读 cookie) |
| cli | bun / npx(${BUN_X} 运行时) |
| cli | 本机 Chrome/Chromium/Edge 可执行文件(CDP 取 cookie;路径可由 GEMINI_WEB_CHROME_PATH 覆盖) |
4推奨統制措置と判定根拠
- SKILL.md / 脚本: 非公開またはリバースエンジニアリングされたプライベートAPIの呼び出し / クライアント識別の偽装
- SKILL.md / 脚本参数: 自動検出のバイパス、ホストサンドボックスの無効化、またはSSL証明書検証のスキップを含む
- SKILL.md / 会话存储: ブラウザのユーザーログイン状態およびセッションCookieの読み取りまたは再利用
- 本地凭据 / 浏览器配置: ユーザーのログインCookie/セッション/キーチェーンの読み取り: ブラウザセッションCookie: __Secure-1PSID / __Secure-1PSIDTS(ローカルのcookies.jsonまたはCDP Network経由)
- scripts/: ローカルスクリプトまたはコマンドの実行: scripts/main.ts(bunで実行。必要に応じてChromeデバッグセッションを起動/制御)
- 网络端点: 外部ネットワークアクセスの宣言: https://gemini.google.com/app(SNlM0eトークン取得のためのINIT)
- 本地工作目录: ファイルの読み書きおよび成果物の出力: cookies.json(クレデンシャルの永続化: __Secure-1PSID/1PSIDTSの書き込み)
5二重目の独立検証
- [ok] 逆向 API 而非官方 API(red 主因之一) — constants.ts 直指 gemini.google.com 的 StreamGenerate 私有路径;get-access-token.ts 用正则从页面抓 SNlM0e;SKILL.md/description 自述 reverse-engineered,README 有 Disclaimer 段落。
- [ok] 读取浏览器 cookie(red 主因之二) — load-browser-cookies.ts 走 CDP(引用 'Network.getCookies')读 cookie;get-access-token.ts 优先本地 cookie 文件,失败回落 CDP;client.ts 在 init/refresh 两处写 cookie 文件。
- [ok] CDP 复用已运行 Chrome 调试会话 — SKILL.md 原文与 load-browser-cookies.ts 的 fetch_cookies_from_existing_chrome(30_000, ...) 一致;另有 hasExplicitProfile 判断(设了 --profile-dir 或 GEMINI_WEB_CHROME_PROFILE_DIR 才跳过复用)。
- [ok] token 落盘 — cookie-file.ts write_cookie_file → writeFile(p, JSON.stringify(payload, null, 2));rotate-1psidts.ts 另写 .cached_1psidts_<sid>.txt。paths.ts 默认数据目录可用 GEMINI_WEB_DATA_DIR/GEMINI_WEB_COOKIE_PATH 覆盖。
- [ok] 无 TLS 降级 / 无 stealth 反检测 / 无任意代码执行 — grep rejectUnauthorized / NODE_TLS / --ignore-certificate 与 webdriver / patchright / blink-features 均零命中;无 eval/new Function/远程脚本加载;Chrome 以本机真实 profile 启动(--remote-debugging-port),未做指纹伪装。
- [ok] consent 门禁存在但为“软门禁” — SKILL.md 要求先建 consent.json 再使用;但门禁由 agent 按文档执行,脚本自身不校验该文件——属文档级约束,已在 risks 写明。
- [ok] meta 元数据 — GitHub API:MIT、25926 stars、pushed_at 2026-09-10T15:13:43Z;本地 HEAD 与 pin 1567581c26ec… 一致。
6結論
076923f8aed80181…