Skip to content

Instantly share code, notes, and snippets.

@aiexz
Created September 24, 2026 21:44
Show Gist options
  • Select an option

  • Save aiexz/601948148d3b6420b73aaac3a5eeb84a to your computer and use it in GitHub Desktop.

Select an option

Save aiexz/601948148d3b6420b73aaac3a5eeb84a to your computer and use it in GitHub Desktop.
Bypass gemini antigravity restrictions in omp
/**
* gemini-antigravity-obfuscator — oh-my-pi extension port of
* minhgv/oh-my-pi@8146af1 ("fix(antigravity): obfuscate sensitive words in
* systemInstruction and drop requestType agent").
*
* Cloud Code Assist inspects `systemInstruction` on agent-mode payloads and
* answers matched ones with a bare `429 RESOURCE_EXHAUSTED` (no
* ErrorInfo/RetryInfo, identical on every retry). Two mitigations, applied
* here at the `before_provider_request` layer — the same layer the core
* patch touches (`buildRequest` in google-gemini-cli.ts passes its wire
* body through this hook, so the extension sees the exact envelope):
*
* 1. Configured literal phrases (default: "RFC 2119") are split with a
* U+200B zero-width space inside `systemInstruction.parts[].text`.
* Visually and semantically intact for the model; clears the
* server-side literal match. Same mitigation CLIProxyAPI ships as
* `antigravity.sensitive-words`.
* 2. `requestType: "agent"` is dropped — it addresses a constrained bucket
* that returns a detail-free 429 (upstream #11689); official
* Antigravity omits it on consumer Cloud Code.
*
* The hook only fires for Gemini traffic: the request model id must contain
* "gemini" (case-insensitive). Everything else passes through untouched.
*
* Install: copy this file to `~/.omp/agent/extensions/` (or
* `<cwd>/.omp/extensions/`), or pass `--extension <path>`.
* Configure: `OMP_ANTIGRAVITY_SENSITIVE_WORDS="RFC 2119,MUST"` (comma
* separated; default `"RFC 2119"`). Empty value disables obfuscation
* (requestType stripping still applies); phrases shorter than 2 chars after
* trimming are ignored, matching the core implementation.
*/
import type { ExtensionAPI } from "@oh-my-pi/pi-coding-agent";
/** Zero-width space: invisible when rendered, breaks literal matching. */
const ZERO_WIDTH_SPACE = "\u200b";
/** Fallback when the env var is unset. Mirrors the core default. */
const DEFAULT_SENSITIVE_WORDS = ["RFC 2119"];
/** Insert a zero-width space after the first character of the phrase. */
function splitPhrase(phrase: string): string {
const chars = [...phrase];
return chars[0] + ZERO_WIDTH_SPACE + chars.slice(1).join("");
}
/**
* Insert a zero-width space after the first character of every literal
* occurrence of each phrase. Matching is literal and case-sensitive;
* empty/whitespace-only phrases and phrases shorter than 2 chars are
* ignored. Returns the input unchanged when nothing matches.
*/
export function obfuscateSensitiveWords(text: string, phrases: readonly string[]): string {
let result = text;
for (const phrase of phrases) {
const trimmed = phrase.trim();
if ([...trimmed].length < 2) continue;
result = result.split(trimmed).join(splitPhrase(trimmed));
}
return result;
}
/** Resolve the active phrase list from the environment. */
export function resolveSensitiveWords(env: Record<string, string | undefined> = process.env): string[] {
const raw = env.OMP_ANTIGRAVITY_SENSITIVE_WORDS;
if (raw === undefined) return [...DEFAULT_SENSITIVE_WORDS];
return raw
.split(",")
.map(part => part.trim())
.filter(part => part.length > 0);
}
interface SystemInstructionPart {
text?: unknown;
[key: string]: unknown;
}
interface AntigravityPayload {
systemInstruction?: {
parts?: unknown;
[key: string]: unknown;
} | null;
requestType?: unknown;
[key: string]: unknown;
}
export interface TransformResult {
payload: AntigravityPayload;
changed: boolean;
}
/**
* Apply both mitigations to a provider wire payload. Pure function over
* plain data so it is unit-testable without the extension runtime.
*/
export function transformAntigravityPayload(
payload: unknown,
sensitiveWords: readonly string[],
): TransformResult {
if (typeof payload !== "object" || payload === null || Array.isArray(payload)) {
return { payload: payload as AntigravityPayload, changed: false };
}
const body = payload as AntigravityPayload;
let changed = false;
let systemInstruction = body.systemInstruction;
let parts: SystemInstructionPart[] | undefined;
if (
typeof systemInstruction === "object" &&
systemInstruction !== null &&
Array.isArray(systemInstruction.parts)
) {
parts = systemInstruction.parts as SystemInstructionPart[];
}
if (parts && sensitiveWords.length > 0) {
const nextParts = parts.map(part => {
if (typeof part !== "object" || part === null || typeof part.text !== "string") return part;
const text = obfuscateSensitiveWords(part.text, sensitiveWords);
if (text === part.text) return part;
changed = true;
return { ...part, text };
});
if (changed) {
systemInstruction = { ...systemInstruction, parts: nextParts };
}
}
let requestType = body.requestType;
if (body.requestType === "agent") {
requestType = undefined;
changed = true;
}
if (!changed) return { payload: body, changed: false };
const next: AntigravityPayload = { ...body };
if (systemInstruction !== body.systemInstruction) next.systemInstruction = systemInstruction;
if (requestType === undefined && "requestType" in body) delete next.requestType;
return { payload: next, changed: true };
}
/** True when the request model is Gemini traffic. */
export function isGeminiModel(modelId: unknown): boolean {
return typeof modelId === "string" && modelId.toLowerCase().includes("gemini");
}
export default function geminiAntigravityObfuscator(pi: ExtensionAPI) {
pi.on("before_provider_request", async (event, ctx) => {
const modelId = ctx.model?.id;
if (!isGeminiModel(modelId)) return undefined;
const { payload, changed } = transformAntigravityPayload(
event.payload,
resolveSensitiveWords(),
);
return changed ? payload : undefined;
});
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment