
Baoyu Danger Gemini Web
Wire unofficial Gemini web session auth, chat, and image generation into Node/TypeScript agent workflows when you cannot use the official API alone.
Overview
baoyu-danger-gemini-web is an agent skill for the Build phase that integrates unofficial Gemini web session APIs into TypeScript agent workflows.
Install
npx skills add https://github.com/ideacco/baoyu-skills-openclaw --skill baoyu-danger-gemini-webWhat is this skill?
- TypeScript client with Gemini web cookie path resolution and access-token helpers
- Structured error types for auth, usage limits, timeouts, and image-generation failures
- Gem mixin and candidate/model output types for agent-oriented consumption
- File upload and JSON extraction utilities for multimodal web flows
- Optional auto-refresh and timeout controls for long-running sessions
Adoption & trust: 1 installs on skills.sh; 12 GitHub stars; 0/3 security scanners passed (skills.sh audits); trending (+100% hot-view momentum).
What problem does it solve?
You need Gemini web chat or image output from an agent but only have cookie-based web access patterns, not a clean official API integration.
Who is it for?
Indie builders prototyping multimodal agents or image pipelines that already accept unofficial web-session maintenance overhead.
Skip if: Production SaaS that must comply with Google API terms, enterprise auth, or teams that refuse to manage rotating browser cookies.
When should I use this skill?
When you need Gemini web chat, candidates, or generated images from a TypeScript agent and are implementing cookie/token based access.
What do I get? / Deliverables
Your agent can call a typed Gemini web client with explicit errors, uploads, and model output parsing instead of brittle one-off scripts.
- Reusable Gemini web client module
- Typed error handling for agent retries
- Hooks for file upload and image candidate parsing
Recommended Skills
Journey fit
Canonical shelf is Build → integrations because the skill ships a client library for external Gemini web endpoints rather than product UX or launch work. It connects your codebase to a third-party AI surface (cookies, tokens, RPC), which is integration work during implementation.
How it compares
Use instead of raw fetch scripts against Gemini web RPC when you want typed errors and reusable agent-side utilities—not instead of the official @google/generative-ai SDK.
Common Questions / FAQ
Who is baoyu-danger-gemini-web for?
Solo and indie developers building AI agents or automation in TypeScript who need Gemini web capabilities and are comfortable maintaining session cookies and unofficial endpoints.
When should I use baoyu-danger-gemini-web?
Use it during Build while hooking LLM or image backends into your repo—especially when prototyping integrations before you commit to official Google Cloud API keys.
Is baoyu-danger-gemini-web safe to install?
Review the Security Audits panel on this Prism page and treat web-session skills as high trust: they may touch secrets, network, and non-documented endpoints—audit the repo before enabling in CI or shared environments.
SKILL.md
READMESKILL.md - Baoyu Danger Gemini Web
import { Endpoint, ErrorCode, Headers, Model } from './constants.js'; import { GemMixin } from './components/gem-mixin.js'; import { APIError, AuthError, GeminiError, ImageGenerationError, ModelInvalid, TemporarilyBlocked, TimeoutError, UsageLimitExceeded, } from './exceptions.js'; import { Candidate, Gem, GeneratedImage, ModelOutput, RPCData, WebImage } from './types/index.js'; import { extract_json_from_response, get_access_token, get_nested_value, logger, parse_file_name, rotate_1psidts, rotate_tasks, fetch_with_timeout, sleep, upload_file, write_cookie_file, resolveGeminiWebCookiePath, } from './utils/index.js'; type InitOptions = { timeout?: number; auto_close?: boolean; close_delay?: number; auto_refresh?: boolean; refresh_interval?: number; verbose?: boolean; }; type RequestKwargs = RequestInit & { timeout_ms?: number }; function normalize_headers(h?: HeadersInit): Record<string, string> { if (!h) return {}; if (Array.isArray(h)) return Object.fromEntries(h.map(([k, v]) => [k, v])); if (h instanceof Headers) { const out: Record<string, string> = {}; h.forEach((v, k) => { out[k] = v; }); return out; } return { ...(h as Record<string, string>) }; } function collect_strings(root: unknown, accept: (s: string) => boolean, limit: number = 20): string[] { const out: string[] = []; const seen = new Set<string>(); const stack: unknown[] = [root]; while (stack.length > 0 && out.length < limit) { const v = stack.pop(); if (typeof v === 'string') { if (accept(v) && !seen.has(v)) { seen.add(v); out.push(v); } continue; } if (Array.isArray(v)) { for (let i = 0; i < v.length; i++) stack.push(v[i]); continue; } if (v && typeof v === 'object') { for (const val of Object.values(v as Record<string, unknown>)) stack.push(val); } } return out; } export class GeminiClient extends GemMixin { public cookies: Record<string, string> = {}; public proxy: string | null = null; public _running: boolean = false; public access_token: string | null = null; public timeout: number = 300; public auto_close: boolean = false; public close_delay: number = 300; public auto_refresh: boolean = true; public refresh_interval: number = 540; public kwargs: RequestInit; private close_timer: ReturnType<typeof setTimeout> | null = null; private refresh_abort: AbortController | null = null; constructor( secure_1psid: string | null = null, secure_1psidts: string | null = null, proxy: string | null = null, kwargs: RequestInit = {}, ) { super(); this.proxy = proxy; this.kwargs = kwargs; if (secure_1psid) { this.cookies['__Secure-1PSID'] = secure_1psid; if (secure_1psidts) this.cookies['__Secure-1PSIDTS'] = secure_1psidts; } } async init( timeoutOrOpts: number | InitOptions = 300, auto_close: boolean = false, close_delay: number = 300, auto_refresh: boolean = true, refresh_interval: number = 540, verbose: boolean = true, ): Promise<void> { const opts: InitOptions = typeof timeoutOrOpts === 'object' ? timeoutOrOpts : { timeout: timeoutOrOpts, auto_close, close_delay, auto_refresh, refresh_interval, verbose }; const timeout = opts.timeout ?? 300; const ac = opts.auto_close ?? false; const cd = opts.close_delay ?? 300; const ar = opts.auto_refresh ?? true; const ri = opts.refresh_interval ?? 540; const vb = opts.verbose ?? true; try { const [token, valid] = await get_access_token(this.cookies, this.proxy, vb); this.access_token = token; this.cookies = valid; this._running = true; this.timeout = timeout; this.auto_close = ac; this.close_delay = cd; if (this.auto_close) await this.reset_close_task(); this.auto_refresh = ar; this.refresh_interval = ri; const sid = th