@hilbras/omnihilbras 1.84.0 → 1.85.1

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/dist/index.d.ts CHANGED
@@ -22,6 +22,7 @@ export * from './providers/chatgpt-web/index.js';
22
22
  export * from './providers/deepseek-web/deepseek-pow.js';
23
23
  export * from './providers/deepseek-web/index.js';
24
24
  export * from './providers/qwen-web/index.js';
25
+ export * from './providers/gemini-web/index.js';
25
26
  export * from './providers/tokenharbor-web/index.js';
26
27
  export * from './core/url.js';
27
28
  export * from './core/bounded-map.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,gCAAgC,CAAC;AAC/C,cAAc,4BAA4B,CAAC;AAC3C,cAAc,gCAAgC,CAAC;AAC/C,cAAc,6BAA6B,CAAC;AAC5C,cAAc,wCAAwC,CAAC;AACvD,cAAc,6BAA6B,CAAC;AAC5C,cAAc,iCAAiC,CAAC;AAChD,cAAc,kBAAkB,CAAC;AACjC,cAAc,oBAAoB,CAAC;AACnC,cAAc,wBAAwB,CAAC;AACvC,cAAc,qBAAqB,CAAC;AACpC,cAAc,qBAAqB,CAAC;AACpC,cAAc,iBAAiB,CAAC;AAChC,cAAc,mBAAmB,CAAC;AAClC,cAAc,wBAAwB,CAAC;AACvC,cAAc,0BAA0B,CAAC;AACzC,cAAc,uCAAuC,CAAC;AACtD,cAAc,kCAAkC,CAAC;AACjD,cAAc,gCAAgC,CAAC;AAC/C,cAAc,2BAA2B,CAAC;AAC1C,cAAc,kCAAkC,CAAC;AACjD,cAAc,0CAA0C,CAAC;AACzD,cAAc,mCAAmC,CAAC;AAClD,cAAc,+BAA+B,CAAC;AAC9C,cAAc,sCAAsC,CAAC;AACrD,cAAc,eAAe,CAAC;AAC9B,cAAc,uBAAuB,CAAC;AACtC,cAAc,0BAA0B,CAAC;AACzC,cAAc,yBAAyB,CAAC;AACxC,cAAc,yBAAyB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,gCAAgC,CAAC;AAC/C,cAAc,4BAA4B,CAAC;AAC3C,cAAc,gCAAgC,CAAC;AAC/C,cAAc,6BAA6B,CAAC;AAC5C,cAAc,wCAAwC,CAAC;AACvD,cAAc,6BAA6B,CAAC;AAC5C,cAAc,iCAAiC,CAAC;AAChD,cAAc,kBAAkB,CAAC;AACjC,cAAc,oBAAoB,CAAC;AACnC,cAAc,wBAAwB,CAAC;AACvC,cAAc,qBAAqB,CAAC;AACpC,cAAc,qBAAqB,CAAC;AACpC,cAAc,iBAAiB,CAAC;AAChC,cAAc,mBAAmB,CAAC;AAClC,cAAc,wBAAwB,CAAC;AACvC,cAAc,0BAA0B,CAAC;AACzC,cAAc,uCAAuC,CAAC;AACtD,cAAc,kCAAkC,CAAC;AACjD,cAAc,gCAAgC,CAAC;AAC/C,cAAc,2BAA2B,CAAC;AAC1C,cAAc,kCAAkC,CAAC;AACjD,cAAc,0CAA0C,CAAC;AACzD,cAAc,mCAAmC,CAAC;AAClD,cAAc,+BAA+B,CAAC;AAC9C,cAAc,iCAAiC,CAAC;AAChD,cAAc,sCAAsC,CAAC;AACrD,cAAc,eAAe,CAAC;AAC9B,cAAc,uBAAuB,CAAC;AACtC,cAAc,0BAA0B,CAAC;AACzC,cAAc,yBAAyB,CAAC;AACxC,cAAc,yBAAyB,CAAC"}
package/dist/index.js CHANGED
@@ -22,6 +22,7 @@ export * from './providers/chatgpt-web/index.js';
22
22
  export * from './providers/deepseek-web/deepseek-pow.js';
23
23
  export * from './providers/deepseek-web/index.js';
24
24
  export * from './providers/qwen-web/index.js';
25
+ export * from './providers/gemini-web/index.js';
25
26
  export * from './providers/tokenharbor-web/index.js';
26
27
  export * from './core/url.js';
27
28
  export * from './core/bounded-map.js';
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,gCAAgC,CAAC;AAC/C,cAAc,4BAA4B,CAAC;AAC3C,cAAc,gCAAgC,CAAC;AAC/C,cAAc,6BAA6B,CAAC;AAC5C,cAAc,wCAAwC,CAAC;AACvD,cAAc,6BAA6B,CAAC;AAC5C,cAAc,iCAAiC,CAAC;AAChD,cAAc,kBAAkB,CAAC;AACjC,cAAc,oBAAoB,CAAC;AACnC,cAAc,wBAAwB,CAAC;AACvC,cAAc,qBAAqB,CAAC;AACpC,cAAc,qBAAqB,CAAC;AACpC,cAAc,iBAAiB,CAAC;AAChC,cAAc,mBAAmB,CAAC;AAClC,cAAc,wBAAwB,CAAC;AACvC,cAAc,0BAA0B,CAAC;AACzC,cAAc,uCAAuC,CAAC;AACtD,cAAc,kCAAkC,CAAC;AACjD,cAAc,gCAAgC,CAAC;AAC/C,cAAc,2BAA2B,CAAC;AAC1C,cAAc,kCAAkC,CAAC;AACjD,cAAc,0CAA0C,CAAC;AACzD,cAAc,mCAAmC,CAAC;AAClD,cAAc,+BAA+B,CAAC;AAC9C,cAAc,sCAAsC,CAAC;AACrD,cAAc,eAAe,CAAC;AAC9B,cAAc,uBAAuB,CAAC;AACtC,cAAc,0BAA0B,CAAC;AACzC,cAAc,yBAAyB,CAAC;AACxC,cAAc,yBAAyB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,gCAAgC,CAAC;AAC/C,cAAc,4BAA4B,CAAC;AAC3C,cAAc,gCAAgC,CAAC;AAC/C,cAAc,6BAA6B,CAAC;AAC5C,cAAc,wCAAwC,CAAC;AACvD,cAAc,6BAA6B,CAAC;AAC5C,cAAc,iCAAiC,CAAC;AAChD,cAAc,kBAAkB,CAAC;AACjC,cAAc,oBAAoB,CAAC;AACnC,cAAc,wBAAwB,CAAC;AACvC,cAAc,qBAAqB,CAAC;AACpC,cAAc,qBAAqB,CAAC;AACpC,cAAc,iBAAiB,CAAC;AAChC,cAAc,mBAAmB,CAAC;AAClC,cAAc,wBAAwB,CAAC;AACvC,cAAc,0BAA0B,CAAC;AACzC,cAAc,uCAAuC,CAAC;AACtD,cAAc,kCAAkC,CAAC;AACjD,cAAc,gCAAgC,CAAC;AAC/C,cAAc,2BAA2B,CAAC;AAC1C,cAAc,kCAAkC,CAAC;AACjD,cAAc,0CAA0C,CAAC;AACzD,cAAc,mCAAmC,CAAC;AAClD,cAAc,+BAA+B,CAAC;AAC9C,cAAc,iCAAiC,CAAC;AAChD,cAAc,sCAAsC,CAAC;AACrD,cAAc,eAAe,CAAC;AAC9B,cAAc,uBAAuB,CAAC;AACtC,cAAc,0BAA0B,CAAC;AACzC,cAAc,yBAAyB,CAAC;AACxC,cAAc,yBAAyB,CAAC"}
@@ -44,7 +44,7 @@ const defaultRefreshSkewMs = 60_000;
44
44
  /** Refreshes in flight, keyed by the login they renew, so adapters that share a login share one renewal. */
45
45
  const inFlightRefreshes = new Map();
46
46
  /** Reported to Cline as this client's version. */
47
- const omnihilbrasVersion = '1.84.0';
47
+ const omnihilbrasVersion = '1.85.1';
48
48
  /** Cline only accepts WorkOS JWTs with an explicit prefix. */
49
49
  export function toClineAccessToken(token) {
50
50
  const trimmed = token.trim();
@@ -0,0 +1,229 @@
1
+ import type { ChatChunk, ChatRequest, ChatResponse, CredentialValidation, Model, ProviderAdapter, ProviderCredential, ProviderHealth, ProviderRequestContext } from '../../core/types.js';
2
+ /**
3
+ * Gemini Web.
4
+ *
5
+ * Not an API integration and not an OAuth flow: Google publishes no endpoint that accepts a browser
6
+ * session, so the only way to reach a model this way is to load `gemini.google.com` in a real browser,
7
+ * let the page solve its own challenges, type into the composer and read the answer out of the
8
+ * response stream. The same shape as `chatgpt-web`, and it carries the same warning — the credential is
9
+ * a **live session for a whole Google account**, not a token scoped to inference.
10
+ *
11
+ * The browser lives in the gateway, not here. This module owns the parts that can be reasoned about
12
+ * and tested without one: what a Gemini cookie is, what the `StreamGenerate` payload looks like, which
13
+ * models the UI can be driven to, and what refusals are honest to make before a browser is even opened.
14
+ */
15
+ /** The primary cookie, and the one a bare value is assumed to be. */
16
+ export declare const GEMINI_WEB_PRIMARY_COOKIE = "__Secure-1PSID";
17
+ /**
18
+ * The cookies Google rotates on its own schedule. They are read back out of the live browser jar after a
19
+ * run and merged into the stored credential, because a session whose `1PSIDTS` is not refreshed stops
20
+ * working while still parsing perfectly.
21
+ */
22
+ export declare const GEMINI_WEB_ROTATABLE_COOKIES: readonly ["__Secure-1PSID", "__Secure-1PSIDTS", "__Secure-1PSIDCC"];
23
+ export declare const GEMINI_WEB: {
24
+ /** The only origin this will talk to. */
25
+ readonly origin: "https://gemini.google.com";
26
+ readonly startUrl: "https://gemini.google.com/app";
27
+ /**
28
+ * Where the answer arrives. It is **observed**, never called: the page makes this request itself and the
29
+ * driver reads the response. The URL is matched by this substring, because the full path carries a service
30
+ * name that changes.
31
+ */
32
+ readonly streamMarker: "StreamGenerate";
33
+ /** The composer. A contenteditable, so its class is a styling hook and may change. */
34
+ readonly composer: ".ql-editor, [contenteditable=\"true\"]";
35
+ /**
36
+ * A link to Google's sign-in page, which is what a signed-out Gemini shows.
37
+ *
38
+ * Checked before the composer, because the signed-out page carries **hidden** contenteditable nodes: a check
39
+ * that only looked for the composer counted one of those and reported a dead session as connected.
40
+ */
41
+ readonly signedOutLink: "a[href*=\"accounts.google.com\"]";
42
+ /**
43
+ * The whole interaction is bounded: a navigation, a settling pause, and a hard cap on waiting for the
44
+ * answer. A page that never answers must fail, not hang.
45
+ */
46
+ readonly navigationTimeoutMs: 20000;
47
+ readonly settleMs: 3000;
48
+ readonly answerTimeoutMs: 30000;
49
+ };
50
+ /** The models the UI can be driven to, and how each is selected. */
51
+ export type GeminiWebModel = {
52
+ id: string;
53
+ name: string;
54
+ /**
55
+ * The model the page already opens to, so nothing is clicked. Claiming to have selected it when the UI
56
+ * reports it anyway would be a claim about a click that never happened.
57
+ */
58
+ isDefault?: boolean;
59
+ /**
60
+ * The menu button, the element that reports the active mode, and the pattern that read-back must match.
61
+ *
62
+ * **Unvalidated.** These are Gemini's UI hooks as best they can be known without a live account; when one
63
+ * is wrong the selection fails closed and says so rather than answering with the wrong model.
64
+ */
65
+ toggleSelector?: string;
66
+ indicatorSelector?: string;
67
+ indicatorPattern?: RegExp;
68
+ };
69
+ /**
70
+ * Gemini's web models.
71
+ *
72
+ * The ids are what this gateway serves; they are **not** Google API model ids, and asking for
73
+ * `gemini-2.5-pro` here is refused rather than silently answered by a different model. The list is short
74
+ * for the same reason the reference's is: the UI offers a handful of modes, and a mode that is not in this
75
+ * table cannot be chosen.
76
+ */
77
+ export declare const GEMINI_WEB_MODELS: readonly GeminiWebModel[];
78
+ export declare const geminiWebProviderId = "gemini-web";
79
+ /** The model resolved for a request, or `undefined` for an id the UI cannot be driven to. */
80
+ export declare function resolveGeminiWebModel(model: string | undefined): GeminiWebModel | undefined;
81
+ /** One cookie, as a name and a value. */
82
+ export type GeminiWebCookie = {
83
+ name: string;
84
+ value: string;
85
+ };
86
+ /**
87
+ * Reads the pasted credential.
88
+ *
89
+ * Three shapes are accepted, because three are what people actually paste: the bare value of
90
+ * `__Secure-1PSID`, a whole `Cookie:` header, and a JSON export from an extension. A bare value has no name
91
+ * in it, so the name is supplied — which is the whole reason this function exists rather than a split on
92
+ * `=`: `abc=def` is a header and `abcdef` is a value, and only one of those parses as a cookie.
93
+ */
94
+ export declare function normalizeGeminiWebCookie(raw: string, cookieName?: string): string;
95
+ /**
96
+ * Splits a `Cookie:` header into pairs, dropping the attributes that are not cookies.
97
+ *
98
+ * `path`, `domain`, `expires` and the rest appear in a copied header and are not sendable names — treating
99
+ * them as cookies sends `path=/` to Google, which is at best ignored and at worst a malformed request.
100
+ */
101
+ export declare function parseGeminiWebCookieHeader(header: string): GeminiWebCookie[];
102
+ /** Whether the credential holds at least one usable cookie. Format only — a browser answers the real question. */
103
+ export declare function geminiWebCookiePresent(raw: string): boolean;
104
+ /**
105
+ * Merges the cookies the live browser jar reports back into the stored header.
106
+ *
107
+ * Google replaces these three on its own schedule. A jar value that differs is the new one; a rotatable name
108
+ * present in the jar but absent from the original is appended, because a cookie the page minted is part of the
109
+ * session even though the user never pasted it. Everything else in the original is left alone — the driver
110
+ * only sends what Google set, and rewriting the rest would drop something the page needs.
111
+ */
112
+ export declare function mergeRotatedGeminiWebCookies(original: string, jar: readonly GeminiWebCookie[]): string;
113
+ /**
114
+ * Reads the answer out of a `StreamGenerate` body.
115
+ *
116
+ * The body is a `)]}'`-prefixed framing of length-prefixed lines, each holding a `wrb.fr` envelope whose third
117
+ * element is a JSON string. The answer is `inner[4][0][1]`, joined.
118
+ *
119
+ * **The frames are cumulative snapshots of the same answer, not increments** — each one contains everything so
120
+ * far — so concatenating them duplicates the whole reply. Only the last frame that produced text is kept.
121
+ * Grading this wrong is invisible on a one-word answer and unmissable on a paragraph, which is exactly the kind
122
+ * of bug a test has to pin.
123
+ */
124
+ export declare function parseGeminiWebStreamResponse(raw: string): string;
125
+ /**
126
+ * The browser, as the adapter sees it.
127
+ *
128
+ * Defined here and implemented in the gateway, so the SDK never depends on Playwright — the same boundary
129
+ * `chatgpt-web` uses. `available()` exists because a browser is an external requirement: a host without one
130
+ * must be told apart from a session that is refused, or the user is sent to fix the wrong thing.
131
+ */
132
+ export type GeminiWebDriver = {
133
+ /** Whether a browser is actually available, and what to do when it is not. */
134
+ available: () => Promise<{
135
+ ok: true;
136
+ } | {
137
+ ok: false;
138
+ reason: string;
139
+ }>;
140
+ /**
141
+ * Drives one turn and returns the answer.
142
+ *
143
+ * `onRotatedCookies` is how rotation reaches storage. Google replaces the three `__Secure-1PSID*` cookies on
144
+ * its own schedule, and only the live browser jar knows the new values — so the driver hands them back here
145
+ * rather than through the response, which has no field for them. Persisting is the gateway's job, and a
146
+ * failure to persist must never fail the answer: the turn already succeeded.
147
+ */
148
+ ask: (input: {
149
+ cookies: readonly GeminiWebCookie[];
150
+ model: GeminiWebModel | undefined;
151
+ messages: readonly {
152
+ role: string;
153
+ text: string;
154
+ }[];
155
+ timeoutMs: number;
156
+ signal?: AbortSignal;
157
+ onRotatedCookies?: (merged: string) => void | Promise<void>;
158
+ }) => Promise<{
159
+ text: string;
160
+ }>;
161
+ /** Confirms the session is signed in, by opening the page. Optional: a driver with no browser cannot. */
162
+ verify?: (input: {
163
+ cookie: string;
164
+ timeoutMs?: number;
165
+ signal?: AbortSignal;
166
+ }) => Promise<{
167
+ ok: boolean;
168
+ note?: string;
169
+ }>;
170
+ };
171
+ /**
172
+ * The prompt the page is driven with.
173
+ *
174
+ * Gemini's composer takes one turn, so the conversation is flattened into it: a system message becomes a
175
+ * `System:` block, and earlier turns become a transcript. The **last user message is byte-for-byte** what the
176
+ * person typed, because that is the part the model is answering.
177
+ */
178
+ export declare function buildGeminiWebPrompt(messages: readonly {
179
+ role: string;
180
+ text: string;
181
+ }[]): string;
182
+ export type GeminiWebAdapterOptions = {
183
+ driver: GeminiWebDriver;
184
+ /** The id used on records and errors. Defaults to `gemini-web`. */
185
+ id?: string;
186
+ /**
187
+ * Where a rotated cookie goes.
188
+ *
189
+ * Google replaces the `__Secure-1PSID*` cookies on its own schedule, and the refreshed values have to be
190
+ * written back or the connection stops working while its stored credential still parses. The same option
191
+ * name the other renewing adapters use (`claude-code`, `cline`). A failure here is swallowed by the caller,
192
+ * never by this adapter: the turn already succeeded and must not be reported as failed.
193
+ */
194
+ onTokensRefreshed?: (merged: string) => void | Promise<void>;
195
+ now?: () => number;
196
+ };
197
+ export declare class GeminiWebAdapter implements ProviderAdapter {
198
+ readonly id: string;
199
+ readonly name = "Gemini Web";
200
+ /**
201
+ * Streaming is not implemented, and saying otherwise would be false. The answer arrives when the page has
202
+ * finished rendering it; presenting that as a stream would claim tokens arriving over time when none do.
203
+ */
204
+ readonly capabilities: {
205
+ readonly chat: true;
206
+ readonly streaming: false;
207
+ readonly models: true;
208
+ };
209
+ private readonly driver;
210
+ private readonly onTokensRefreshed?;
211
+ constructor(options: GeminiWebAdapterOptions);
212
+ listModels(): Promise<Model[]>;
213
+ validateCredential(credential: ProviderCredential | undefined): Promise<CredentialValidation>;
214
+ /**
215
+ * The refusals that are honest to make before a browser is launched.
216
+ *
217
+ * A forced tool choice cannot be honoured — tools here are emulated in the prompt, and a caller that demanded
218
+ * a tool call would get prose — so it is refused rather than silently downgraded. An unknown model cannot be
219
+ * selected in the UI, so it is refused rather than answered by whichever mode the page happens to be in.
220
+ */
221
+ private refuseUnsupported;
222
+ chat(request: ChatRequest, context?: ProviderRequestContext): Promise<ChatResponse>;
223
+ /**
224
+ * Gemini Web has no stream. The whole answer is yielded once, honestly, rather than pretending.
225
+ */
226
+ streamChat(request: ChatRequest, context?: ProviderRequestContext): AsyncIterable<ChatChunk>;
227
+ healthCheck(context?: ProviderRequestContext): Promise<ProviderHealth>;
228
+ }
229
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/providers/gemini-web/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,438 @@
1
+ import { ProviderError } from '../../core/errors.js';
2
+ /**
3
+ * Gemini Web.
4
+ *
5
+ * Not an API integration and not an OAuth flow: Google publishes no endpoint that accepts a browser
6
+ * session, so the only way to reach a model this way is to load `gemini.google.com` in a real browser,
7
+ * let the page solve its own challenges, type into the composer and read the answer out of the
8
+ * response stream. The same shape as `chatgpt-web`, and it carries the same warning — the credential is
9
+ * a **live session for a whole Google account**, not a token scoped to inference.
10
+ *
11
+ * The browser lives in the gateway, not here. This module owns the parts that can be reasoned about
12
+ * and tested without one: what a Gemini cookie is, what the `StreamGenerate` payload looks like, which
13
+ * models the UI can be driven to, and what refusals are honest to make before a browser is even opened.
14
+ */
15
+ /** The primary cookie, and the one a bare value is assumed to be. */
16
+ export const GEMINI_WEB_PRIMARY_COOKIE = '__Secure-1PSID';
17
+ /**
18
+ * The cookies Google rotates on its own schedule. They are read back out of the live browser jar after a
19
+ * run and merged into the stored credential, because a session whose `1PSIDTS` is not refreshed stops
20
+ * working while still parsing perfectly.
21
+ */
22
+ export const GEMINI_WEB_ROTATABLE_COOKIES = ['__Secure-1PSID', '__Secure-1PSIDTS', '__Secure-1PSIDCC'];
23
+ export const GEMINI_WEB = {
24
+ /** The only origin this will talk to. */
25
+ origin: 'https://gemini.google.com',
26
+ startUrl: 'https://gemini.google.com/app',
27
+ /**
28
+ * Where the answer arrives. It is **observed**, never called: the page makes this request itself and the
29
+ * driver reads the response. The URL is matched by this substring, because the full path carries a service
30
+ * name that changes.
31
+ */
32
+ streamMarker: 'StreamGenerate',
33
+ /** The composer. A contenteditable, so its class is a styling hook and may change. */
34
+ composer: '.ql-editor, [contenteditable="true"]',
35
+ /**
36
+ * A link to Google's sign-in page, which is what a signed-out Gemini shows.
37
+ *
38
+ * Checked before the composer, because the signed-out page carries **hidden** contenteditable nodes: a check
39
+ * that only looked for the composer counted one of those and reported a dead session as connected.
40
+ */
41
+ signedOutLink: 'a[href*="accounts.google.com"]',
42
+ /**
43
+ * The whole interaction is bounded: a navigation, a settling pause, and a hard cap on waiting for the
44
+ * answer. A page that never answers must fail, not hang.
45
+ */
46
+ navigationTimeoutMs: 20_000,
47
+ settleMs: 3_000,
48
+ answerTimeoutMs: 30_000,
49
+ };
50
+ /**
51
+ * Gemini's web models.
52
+ *
53
+ * The ids are what this gateway serves; they are **not** Google API model ids, and asking for
54
+ * `gemini-2.5-pro` here is refused rather than silently answered by a different model. The list is short
55
+ * for the same reason the reference's is: the UI offers a handful of modes, and a mode that is not in this
56
+ * table cannot be chosen.
57
+ */
58
+ export const GEMINI_WEB_MODELS = [
59
+ { id: 'gemini-3.1-pro', name: 'Gemini 3.1 Pro', isDefault: true },
60
+ {
61
+ id: 'gemini-3.7-flash',
62
+ name: 'Gemini 3.7 Flash',
63
+ toggleSelector: '[data-test-id="bard-mode-menu-button"], button[aria-haspopup="menu"][aria-label*="model" i]',
64
+ indicatorSelector: '[data-test-id="bard-mode-menu-button"] .mode-title, [data-test-id="bard-mode-menu-button"]',
65
+ // `(?!.*lite)` so the plain Flash mode never matches the Flash-Lite label.
66
+ indicatorPattern: /\bflash\b(?!.*\blite\b)/i,
67
+ },
68
+ {
69
+ id: 'gemini-3.1-flash-lite',
70
+ name: 'Gemini 3.1 Flash-Lite',
71
+ toggleSelector: '[data-test-id="bard-mode-menu-button"], button[aria-haspopup="menu"][aria-label*="model" i]',
72
+ indicatorSelector: '[data-test-id="bard-mode-menu-button"] .mode-title, [data-test-id="bard-mode-menu-button"]',
73
+ indicatorPattern: /flash.*\blite\b/i,
74
+ },
75
+ ];
76
+ export const geminiWebProviderId = 'gemini-web';
77
+ /** The model resolved for a request, or `undefined` for an id the UI cannot be driven to. */
78
+ export function resolveGeminiWebModel(model) {
79
+ if (!model)
80
+ return undefined;
81
+ return GEMINI_WEB_MODELS.find((entry) => entry.id === model);
82
+ }
83
+ /**
84
+ * Reads the pasted credential.
85
+ *
86
+ * Three shapes are accepted, because three are what people actually paste: the bare value of
87
+ * `__Secure-1PSID`, a whole `Cookie:` header, and a JSON export from an extension. A bare value has no name
88
+ * in it, so the name is supplied — which is the whole reason this function exists rather than a split on
89
+ * `=`: `abc=def` is a header and `abcdef` is a value, and only one of those parses as a cookie.
90
+ */
91
+ export function normalizeGeminiWebCookie(raw, cookieName = GEMINI_WEB_PRIMARY_COOKIE) {
92
+ const trimmed = raw.trim();
93
+ if (!trimmed)
94
+ return '';
95
+ const pairs = cookiePairsFromJson(trimmed);
96
+ if (pairs.length > 0)
97
+ return pairs.map((pair) => `${pair.name}=${pair.value}`).join('; ');
98
+ return trimmed.includes('=') ? trimmed : `${cookieName}=${trimmed}`;
99
+ }
100
+ /** A JSON object export (`{...}` or `{cookies: {...}}`), or an empty list for anything else. */
101
+ function cookiePairsFromJson(raw) {
102
+ if (!raw.startsWith('{'))
103
+ return [];
104
+ let parsed;
105
+ try {
106
+ parsed = JSON.parse(raw);
107
+ }
108
+ catch {
109
+ return [];
110
+ }
111
+ if (typeof parsed !== 'object' || parsed === null || Array.isArray(parsed))
112
+ return [];
113
+ const record = parsed;
114
+ const source = typeof record.cookies === 'object' && record.cookies !== null && !Array.isArray(record.cookies)
115
+ ? record.cookies
116
+ : record;
117
+ return Object.entries(source)
118
+ .filter(([, value]) => typeof value === 'string' && value.trim() !== '')
119
+ .map(([name, value]) => ({ name, value: value.trim() }));
120
+ }
121
+ /**
122
+ * Splits a `Cookie:` header into pairs, dropping the attributes that are not cookies.
123
+ *
124
+ * `path`, `domain`, `expires` and the rest appear in a copied header and are not sendable names — treating
125
+ * them as cookies sends `path=/` to Google, which is at best ignored and at worst a malformed request.
126
+ */
127
+ export function parseGeminiWebCookieHeader(header) {
128
+ const attributes = new Set(['path', 'domain', 'expires', 'max-age', 'secure', 'httponly', 'samesite', 'priority', 'partitioned']);
129
+ const pairs = [];
130
+ for (const part of header.split(';')) {
131
+ const separator = part.indexOf('=');
132
+ if (separator <= 0)
133
+ continue;
134
+ const name = part.slice(0, separator).trim();
135
+ const value = part.slice(separator + 1).trim();
136
+ if (!name || !value)
137
+ continue;
138
+ if (attributes.has(name.toLowerCase()))
139
+ continue;
140
+ pairs.push({ name, value });
141
+ }
142
+ return pairs;
143
+ }
144
+ /** Whether the credential holds at least one usable cookie. Format only — a browser answers the real question. */
145
+ export function geminiWebCookiePresent(raw) {
146
+ return parseGeminiWebCookieHeader(normalizeGeminiWebCookie(raw)).length > 0;
147
+ }
148
+ /**
149
+ * Merges the cookies the live browser jar reports back into the stored header.
150
+ *
151
+ * Google replaces these three on its own schedule. A jar value that differs is the new one; a rotatable name
152
+ * present in the jar but absent from the original is appended, because a cookie the page minted is part of the
153
+ * session even though the user never pasted it. Everything else in the original is left alone — the driver
154
+ * only sends what Google set, and rewriting the rest would drop something the page needs.
155
+ */
156
+ export function mergeRotatedGeminiWebCookies(original, jar) {
157
+ const rotatable = new Set(GEMINI_WEB_ROTATABLE_COOKIES);
158
+ const merged = new Map();
159
+ for (const pair of parseGeminiWebCookieHeader(original))
160
+ merged.set(pair.name, pair.value);
161
+ for (const pair of jar) {
162
+ if (!rotatable.has(pair.name) || !pair.value)
163
+ continue;
164
+ merged.set(pair.name, pair.value);
165
+ }
166
+ return [...merged.entries()].map(([name, value]) => `${name}=${value}`).join('; ');
167
+ }
168
+ /**
169
+ * Reads the answer out of a `StreamGenerate` body.
170
+ *
171
+ * The body is a `)]}'`-prefixed framing of length-prefixed lines, each holding a `wrb.fr` envelope whose third
172
+ * element is a JSON string. The answer is `inner[4][0][1]`, joined.
173
+ *
174
+ * **The frames are cumulative snapshots of the same answer, not increments** — each one contains everything so
175
+ * far — so concatenating them duplicates the whole reply. Only the last frame that produced text is kept.
176
+ * Grading this wrong is invisible on a one-word answer and unmissable on a paragraph, which is exactly the kind
177
+ * of bug a test has to pin.
178
+ */
179
+ export function parseGeminiWebStreamResponse(raw) {
180
+ let text = '';
181
+ for (const line of raw.split('\n')) {
182
+ const trimmed = line.trim();
183
+ if (!trimmed || trimmed === ")]}'" || /^\d+$/.test(trimmed))
184
+ continue;
185
+ if (!trimmed.includes('wrb.fr'))
186
+ continue;
187
+ let envelope;
188
+ try {
189
+ envelope = JSON.parse(trimmed);
190
+ }
191
+ catch {
192
+ continue;
193
+ }
194
+ if (!Array.isArray(envelope) || !Array.isArray(envelope[0]) || envelope[0][0] !== 'wrb.fr')
195
+ continue;
196
+ const payload = envelope[0][2];
197
+ if (typeof payload !== 'string')
198
+ continue;
199
+ let inner;
200
+ try {
201
+ inner = JSON.parse(payload);
202
+ }
203
+ catch {
204
+ continue;
205
+ }
206
+ const parts = candidateText(inner);
207
+ if (parts)
208
+ text = parts;
209
+ }
210
+ return text;
211
+ }
212
+ /** `inner[4][0][1]` as text, or `undefined` when the shape is not the one that carries an answer. */
213
+ function candidateText(inner) {
214
+ if (!Array.isArray(inner))
215
+ return undefined;
216
+ const group = inner[4];
217
+ if (!Array.isArray(group) || !Array.isArray(group[0]))
218
+ return undefined;
219
+ const list = group[0][1];
220
+ if (!Array.isArray(list))
221
+ return undefined;
222
+ const text = list.filter((entry) => typeof entry === 'string').join('');
223
+ return text.length > 0 ? text : undefined;
224
+ }
225
+ function messageText(content) {
226
+ if (typeof content === 'string')
227
+ return content;
228
+ if (!Array.isArray(content))
229
+ return '';
230
+ return content
231
+ .map((part) => {
232
+ if (typeof part === 'string')
233
+ return part;
234
+ if (part && typeof part === 'object' && 'text' in part && typeof part.text === 'string')
235
+ return part.text;
236
+ return '';
237
+ })
238
+ .join('');
239
+ }
240
+ /**
241
+ * The prompt the page is driven with.
242
+ *
243
+ * Gemini's composer takes one turn, so the conversation is flattened into it: a system message becomes a
244
+ * `System:` block, and earlier turns become a transcript. The **last user message is byte-for-byte** what the
245
+ * person typed, because that is the part the model is answering.
246
+ */
247
+ export function buildGeminiWebPrompt(messages) {
248
+ const system = messages.filter((message) => message.role === 'system').map((message) => message.text).filter(Boolean);
249
+ const turns = messages.filter((message) => message.role !== 'system');
250
+ const current = turns[turns.length - 1];
251
+ const history = turns.slice(0, -1);
252
+ const userText = current?.text ?? '';
253
+ if (system.length === 0 && history.length === 0)
254
+ return userText;
255
+ const blocks = [];
256
+ if (system.length > 0)
257
+ blocks.push(`System:\n${system.join('\n\n')}`);
258
+ if (history.length > 0) {
259
+ blocks.push(`Previous conversation:\n${history.map((message) => `${message.role === 'assistant' ? 'Assistant' : 'User'}: ${message.text}`).join('\n\n')}`);
260
+ }
261
+ blocks.push(`Current user message:\n${userText}`);
262
+ return blocks.join('\n\n');
263
+ }
264
+ export class GeminiWebAdapter {
265
+ id;
266
+ name = 'Gemini Web';
267
+ /**
268
+ * Streaming is not implemented, and saying otherwise would be false. The answer arrives when the page has
269
+ * finished rendering it; presenting that as a stream would claim tokens arriving over time when none do.
270
+ */
271
+ capabilities = { chat: true, streaming: false, models: true };
272
+ driver;
273
+ onTokensRefreshed;
274
+ constructor(options) {
275
+ this.driver = options.driver;
276
+ this.id = options.id ?? geminiWebProviderId;
277
+ this.onTokensRefreshed = options.onTokensRefreshed;
278
+ }
279
+ async listModels() {
280
+ return GEMINI_WEB_MODELS.map((model) => ({ id: model.id, displayName: model.name, providerId: this.id }));
281
+ }
282
+ async validateCredential(credential) {
283
+ if (credential?.type !== 'api-key' || !geminiWebCookiePresent(credential.value)) {
284
+ throw new ProviderError('AUTHENTICATION_FAILED', 'Paste a Gemini session cookie to use this provider.', {
285
+ providerId: this.id,
286
+ publicMessage: 'Paste a Gemini session cookie (`__Secure-1PSID` and `__Secure-1PSIDTS`) to use this provider.',
287
+ });
288
+ }
289
+ return { status: 'valid', checkedAt: new Date().toISOString() };
290
+ }
291
+ /**
292
+ * The refusals that are honest to make before a browser is launched.
293
+ *
294
+ * A forced tool choice cannot be honoured — tools here are emulated in the prompt, and a caller that demanded
295
+ * a tool call would get prose — so it is refused rather than silently downgraded. An unknown model cannot be
296
+ * selected in the UI, so it is refused rather than answered by whichever mode the page happens to be in.
297
+ */
298
+ refuseUnsupported(request) {
299
+ const choice = request.toolChoice;
300
+ if (choice === 'required') {
301
+ throw new ProviderError('NOT_SUPPORTED', 'Gemini Web cannot be told to force a tool call.', {
302
+ providerId: this.id,
303
+ publicMessage: 'Gemini Web drives the web UI, which has no way to force a tool call. Send `tool_choice: "auto"` or omit it.',
304
+ });
305
+ }
306
+ if (request.model && !resolveGeminiWebModel(request.model)) {
307
+ const known = GEMINI_WEB_MODELS.map((model) => model.id).join(', ');
308
+ throw new ProviderError('NOT_SUPPORTED', `Gemini Web cannot select ${request.model}.`, {
309
+ providerId: this.id,
310
+ publicMessage: `Gemini Web drives the web UI, which offers ${known}. ${request.model} is not one of them.`,
311
+ });
312
+ }
313
+ }
314
+ async chat(request, context = {}) {
315
+ const credential = context.credential;
316
+ if (credential?.type !== 'api-key' || !geminiWebCookiePresent(credential.value)) {
317
+ throw new ProviderError('AUTHENTICATION_FAILED', 'Paste a Gemini session cookie to use this provider.', {
318
+ providerId: this.id,
319
+ publicMessage: 'Paste a Gemini session cookie (`__Secure-1PSID` and `__Secure-1PSIDTS`) to use this provider.',
320
+ });
321
+ }
322
+ this.refuseUnsupported(request);
323
+ const messages = request.messages.map((message) => ({ role: message.role, text: messageText(message.content) }));
324
+ const prompt = buildGeminiWebPrompt(messages);
325
+ if (!prompt.trim()) {
326
+ throw new ProviderError('INVALID_REQUEST', 'Gemini Web needs a user message to type into the page.', {
327
+ providerId: this.id,
328
+ publicMessage: 'Send at least one user message; Gemini Web types it into the page.',
329
+ });
330
+ }
331
+ const cookie = normalizeGeminiWebCookie(credential.value);
332
+ const available = await this.driver.available();
333
+ if (!available.ok) {
334
+ // Its own code, and not retryable: a missing browser will still be missing on the next attempt, and
335
+ // retrying it would burn the failover chain on an installation problem.
336
+ throw new ProviderError('PROVIDER_UNAVAILABLE', 'Gemini Web needs a browser that is not installed.', {
337
+ providerId: this.id,
338
+ retryable: false,
339
+ publicMessage: available.reason,
340
+ });
341
+ }
342
+ let answer;
343
+ try {
344
+ answer = await this.driver.ask({
345
+ cookies: parseGeminiWebCookieHeader(cookie),
346
+ model: resolveGeminiWebModel(request.model),
347
+ messages,
348
+ timeoutMs: GEMINI_WEB.answerTimeoutMs + GEMINI_WEB.navigationTimeoutMs + GEMINI_WEB.settleMs,
349
+ ...(context.signal ? { signal: context.signal } : {}),
350
+ // The merged header goes to storage, not to the response: a turn that succeeded must not be reported as
351
+ // failed because writing the refreshed cookie back did not work.
352
+ onRotatedCookies: (merged) => this.onTokensRefreshed?.(merged),
353
+ });
354
+ }
355
+ catch (error) {
356
+ throw normalizeDriverError(error, this.id);
357
+ }
358
+ const text = answer.text ?? '';
359
+ if (!text.trim()) {
360
+ throw new ProviderError('INVALID_RESPONSE', 'Gemini Web returned an empty answer.', {
361
+ providerId: this.id,
362
+ publicMessage: 'The page produced no answer. The session may have expired — check the cookie, then try again.',
363
+ });
364
+ }
365
+ return {
366
+ id: `gemini-web-${Date.now().toString(36)}`,
367
+ providerId: this.id,
368
+ model: request.model ?? GEMINI_WEB_MODELS[0].id,
369
+ createdAt: new Date().toISOString(),
370
+ message: { role: 'assistant', content: text },
371
+ finishReason: 'stop',
372
+ };
373
+ }
374
+ /**
375
+ * Gemini Web has no stream. The whole answer is yielded once, honestly, rather than pretending.
376
+ */
377
+ async *streamChat(request, context = {}) {
378
+ const response = await this.chat(request, context);
379
+ yield {
380
+ id: response.id,
381
+ providerId: response.providerId,
382
+ model: response.model,
383
+ delta: { role: 'assistant', content: messageText(response.message.content) },
384
+ finishReason: response.finishReason,
385
+ };
386
+ }
387
+ async healthCheck(context = {}) {
388
+ try {
389
+ await this.validateCredential(context.credential);
390
+ return { status: 'healthy', verified: 'credential', checkedAt: new Date().toISOString() };
391
+ }
392
+ catch (error) {
393
+ return {
394
+ status: 'unavailable',
395
+ verified: 'credential',
396
+ checkedAt: new Date().toISOString(),
397
+ ...(error instanceof ProviderError ? { errorCode: error.code } : {}),
398
+ };
399
+ }
400
+ }
401
+ }
402
+ /**
403
+ * A driver failure as a provider error.
404
+ *
405
+ * Three cases, in the order they should win — the same classification `chatgpt-web` arrived at for the same
406
+ * reasons, because a page that refuses is not one thing:
407
+ *
408
+ * - **signed out.** The cookie expired or Google revoked it. Not retryable, and no other provider fixes it:
409
+ * the user's next action is to copy fresher cookies. `AUTHENTICATION_FAILED` so the router stops rather than
410
+ * failing over, and the dashboard says "sign in again" rather than "Gemini is unavailable".
411
+ * - **blocked.** A bot-protection challenge. Also not retryable, and not the credential's fault, so
412
+ * `PROVIDER_UNAVAILABLE` — the operator waits, they do not re-copy a working cookie.
413
+ * - **anything else.** `PROVIDER_REQUEST_FAILED`, which the router may retry.
414
+ */
415
+ function driverFailureCode(message) {
416
+ if (/sign(ed)?[ -]?in|logged[ -]?out|session (has )?expired|no longer|unauthori[sz]ed|401|log in again/i.test(message))
417
+ return 'AUTHENTICATION_FAILED';
418
+ if (/challenge|unable to load|bot-protection|anti-bot/i.test(message))
419
+ return 'PROVIDER_UNAVAILABLE';
420
+ return 'PROVIDER_REQUEST_FAILED';
421
+ }
422
+ function normalizeDriverError(error, providerId) {
423
+ if (error instanceof ProviderError)
424
+ return error;
425
+ const message = error instanceof Error ? error.message : String(error);
426
+ const code = driverFailureCode(message);
427
+ const publicMessage = code === 'AUTHENTICATION_FAILED'
428
+ ? 'The Gemini session is no longer accepted. Copy fresh cookies from gemini.google.com while signed in, then connect again.'
429
+ : 'The Gemini page could not be driven to an answer. This usually means the session expired or the page changed.';
430
+ return new ProviderError(code, `Gemini Web could not complete the turn: ${message}`, {
431
+ providerId,
432
+ // A signed-out session is not a transient failure, so it must not be retried — and `retryable` is what the
433
+ // router reads.
434
+ retryable: code === 'PROVIDER_REQUEST_FAILED',
435
+ publicMessage,
436
+ });
437
+ }
438
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/providers/gemini-web/index.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hilbras/omnihilbras",
3
- "version": "1.84.0",
3
+ "version": "1.85.1",
4
4
  "description": "Typed provider SDK for the OmniHilbras gateway: normalized chat, streaming, model listing, and capability contracts for OpenAI, Anthropic, Gemini, and OpenAI-compatible providers.",
5
5
  "license": "MIT",
6
6
  "author": "Hilbras",