@axemere/gateway-google 0.1.9

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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Axemere LLC
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,30 @@
1
+ # @axemere/gateway-google
2
+
3
+ Google Generative AI drop-in wrapper for the [Axemere AI Gateway](https://axemere.ai).
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install @axemere/gateway-google @google/generative-ai
9
+ ```
10
+
11
+ ## Usage
12
+
13
+ ```ts
14
+ import { genaiClient } from "@axemere/gateway-google";
15
+ import { AiGatewayConfig } from "@axemere/gateway";
16
+
17
+ const ai = genaiClient(new AiGatewayConfig());
18
+ const model = ai.getGenerativeModel({ model: "gemini-1.5-flash" });
19
+ const result = await model.generateContent("Explain quantum entanglement in one sentence.");
20
+ console.log(result.response.text());
21
+ ```
22
+
23
+ The returned client is a standard `GoogleGenerativeAI` instance — no other code changes needed.
24
+
25
+ ## Configuration
26
+
27
+ Reads `AXEMERE_GATEWAY_URL` and `AXEMERE_GATEWAY_TOKEN` from the environment, or pass an
28
+ `AiGatewayConfig` instance explicitly.
29
+
30
+ See [@axemere/gateway](https://www.npmjs.com/package/@axemere/gateway) for all configuration options.
@@ -0,0 +1,33 @@
1
+ import { GoogleGenerativeAI } from "@google/generative-ai";
2
+ import type { ModelParams, RequestOptions } from "@google/generative-ai";
3
+ import { AiGatewayConfig } from "@axemere/gateway";
4
+ export { AiGatewayConfig };
5
+ /**
6
+ * GoogleGenerativeAI subclass that automatically routes all model requests
7
+ * through the Axemere AI Gateway. Gateway auth headers and base URL are injected
8
+ * into every getGenerativeModel() call without requiring the caller to pass
9
+ * requestOptions manually.
10
+ */
11
+ declare class GatewayGenerativeAI extends GoogleGenerativeAI {
12
+ private readonly _gatewayRequestOptions;
13
+ constructor(apiKey: string, gatewayRequestOptions: RequestOptions);
14
+ getGenerativeModel(modelParams: ModelParams, requestOptions?: RequestOptions): import("@google/generative-ai").GenerativeModel;
15
+ }
16
+ /**
17
+ * Creates a GoogleGenerativeAI client pre-configured to route through the Axemere AI Gateway.
18
+ *
19
+ * The returned client is a standard GoogleGenerativeAI instance — use it exactly as you would
20
+ * the official @google/generative-ai package. All requests are proxied through the gateway,
21
+ * which applies policy, budgets, and records usage.
22
+ *
23
+ * @param config - AiGatewayConfig instance (reads env vars if omitted).
24
+ * @returns A GoogleGenerativeAI instance with gateway routing applied to every model request.
25
+ *
26
+ * @example
27
+ * ```ts
28
+ * const ai = genaiClient(new AiGatewayConfig());
29
+ * const model = ai.getGenerativeModel({ model: "gemini-1.5-flash" });
30
+ * const result = await model.generateContent("Hello");
31
+ * ```
32
+ */
33
+ export declare function genaiClient(config?: AiGatewayConfig): GatewayGenerativeAI;
package/dist/index.js ADDED
@@ -0,0 +1,64 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.AiGatewayConfig = void 0;
4
+ exports.genaiClient = genaiClient;
5
+ const generative_ai_1 = require("@google/generative-ai");
6
+ const gateway_1 = require("@axemere/gateway");
7
+ Object.defineProperty(exports, "AiGatewayConfig", { enumerable: true, get: function () { return gateway_1.AiGatewayConfig; } });
8
+ /**
9
+ * GoogleGenerativeAI subclass that automatically routes all model requests
10
+ * through the Axemere AI Gateway. Gateway auth headers and base URL are injected
11
+ * into every getGenerativeModel() call without requiring the caller to pass
12
+ * requestOptions manually.
13
+ */
14
+ class GatewayGenerativeAI extends generative_ai_1.GoogleGenerativeAI {
15
+ constructor(apiKey, gatewayRequestOptions) {
16
+ super(apiKey);
17
+ this._gatewayRequestOptions = gatewayRequestOptions;
18
+ }
19
+ getGenerativeModel(modelParams, requestOptions) {
20
+ // Merge gateway defaults under caller-supplied options so callers can
21
+ // still override baseUrl or add their own custom headers.
22
+ const merged = {
23
+ ...this._gatewayRequestOptions,
24
+ ...requestOptions,
25
+ };
26
+ // Merge customHeaders: gateway headers first, caller headers win on conflict.
27
+ // Note: x-goog-api-key cannot be set via customHeaders (SDK enforces this),
28
+ // so the placeholder key is forwarded as-is. The gateway recognises
29
+ // PLACEHOLDER_API_KEY ("axemere-proxy-managed") and does not treat it as BYOK.
30
+ const gwHeaders = new Headers(this._gatewayRequestOptions.customHeaders ?? {});
31
+ if (requestOptions?.customHeaders) {
32
+ const callerHeaders = new Headers(requestOptions.customHeaders);
33
+ callerHeaders.forEach((val, key) => gwHeaders.set(key, val));
34
+ }
35
+ merged.customHeaders = gwHeaders;
36
+ return super.getGenerativeModel(modelParams, merged);
37
+ }
38
+ }
39
+ /**
40
+ * Creates a GoogleGenerativeAI client pre-configured to route through the Axemere AI Gateway.
41
+ *
42
+ * The returned client is a standard GoogleGenerativeAI instance — use it exactly as you would
43
+ * the official @google/generative-ai package. All requests are proxied through the gateway,
44
+ * which applies policy, budgets, and records usage.
45
+ *
46
+ * @param config - AiGatewayConfig instance (reads env vars if omitted).
47
+ * @returns A GoogleGenerativeAI instance with gateway routing applied to every model request.
48
+ *
49
+ * @example
50
+ * ```ts
51
+ * const ai = genaiClient(new AiGatewayConfig());
52
+ * const model = ai.getGenerativeModel({ model: "gemini-1.5-flash" });
53
+ * const result = await model.generateContent("Hello");
54
+ * ```
55
+ */
56
+ function genaiClient(config) {
57
+ const cfg = config ?? new gateway_1.AiGatewayConfig();
58
+ const headers = (0, gateway_1.aiGatewayHeaders)(cfg, { targetHost: "generativelanguage.googleapis.com" });
59
+ const gatewayRequestOptions = {
60
+ baseUrl: cfg.gateway_url,
61
+ customHeaders: new Headers(headers),
62
+ };
63
+ return new GatewayGenerativeAI(gateway_1.PLACEHOLDER_API_KEY, gatewayRequestOptions);
64
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,54 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const generative_ai_1 = require("@google/generative-ai");
4
+ const gateway_1 = require("@axemere/gateway");
5
+ const index_1 = require("./index");
6
+ describe("genaiClient()", () => {
7
+ it("returns a GoogleGenerativeAI instance", () => {
8
+ const cfg = new gateway_1.AiGatewayConfig({ gateway_url: "http://localhost:7080" });
9
+ const client = (0, index_1.genaiClient)(cfg);
10
+ expect(client).toBeInstanceOf(generative_ai_1.GoogleGenerativeAI);
11
+ });
12
+ it("constructs with default config when no config passed", () => {
13
+ delete process.env["AXEMERE_GATEWAY_URL"];
14
+ delete process.env["AXEMERE_GATEWAY_TOKEN"];
15
+ expect(() => (0, index_1.genaiClient)()).not.toThrow();
16
+ });
17
+ it("injects Authorization header from gateway_token", () => {
18
+ const cfg = new gateway_1.AiGatewayConfig({
19
+ gateway_url: "http://localhost:7080",
20
+ gateway_token: "tok_test",
21
+ });
22
+ const client = (0, index_1.genaiClient)(cfg);
23
+ // Retrieve the options injected into getGenerativeModel by calling it and
24
+ // inspecting the GenerativeModel's private _requestOptions.
25
+ const model = client.getGenerativeModel({ model: "gemini-1.5-flash" });
26
+ const opts = model
27
+ ._requestOptions;
28
+ expect(opts.customHeaders.get("Authorization")).toBe("Bearer tok_test");
29
+ });
30
+ it("sets baseUrl to the gateway URL", () => {
31
+ const cfg = new gateway_1.AiGatewayConfig({ gateway_url: "http://localhost:7080" });
32
+ const client = (0, index_1.genaiClient)(cfg);
33
+ const model = client.getGenerativeModel({ model: "gemini-1.5-flash" });
34
+ const opts = model
35
+ ._requestOptions;
36
+ expect(opts.baseUrl).toBe("http://localhost:7080");
37
+ });
38
+ it("sets X-MVGC-Target-Host to generativelanguage.googleapis.com", () => {
39
+ const cfg = new gateway_1.AiGatewayConfig({ gateway_url: "http://localhost:7080" });
40
+ const client = (0, index_1.genaiClient)(cfg);
41
+ const model = client.getGenerativeModel({ model: "gemini-1.5-flash" });
42
+ const opts = model
43
+ ._requestOptions;
44
+ expect(opts.customHeaders.get("X-MVGC-Target-Host")).toBe("generativelanguage.googleapis.com");
45
+ });
46
+ it("caller requestOptions override gateway defaults", () => {
47
+ const cfg = new gateway_1.AiGatewayConfig({ gateway_url: "http://localhost:7080" });
48
+ const client = (0, index_1.genaiClient)(cfg);
49
+ const model = client.getGenerativeModel({ model: "gemini-1.5-flash" }, { baseUrl: "http://other-gateway:9090" });
50
+ const opts = model
51
+ ._requestOptions;
52
+ expect(opts.baseUrl).toBe("http://other-gateway:9090");
53
+ });
54
+ });
package/package.json ADDED
@@ -0,0 +1,53 @@
1
+ {
2
+ "name": "@axemere/gateway-google",
3
+ "version": "0.1.9",
4
+ "description": "Axemere AI Gateway SDK — Google Generative AI wrapper",
5
+ "main": "dist/index.js",
6
+ "types": "dist/index.d.ts",
7
+ "files": [
8
+ "dist",
9
+ "README.md"
10
+ ],
11
+ "license": "MIT",
12
+ "engines": {
13
+ "node": ">=18"
14
+ },
15
+ "repository": {
16
+ "type": "git",
17
+ "url": "https://github.com/Axemere-LLC/axemere-node.git",
18
+ "directory": "packages/gateway-google"
19
+ },
20
+ "publishConfig": {
21
+ "access": "public"
22
+ },
23
+ "peerDependencies": {
24
+ "@google/generative-ai": ">=0.21.0"
25
+ },
26
+ "dependencies": {
27
+ "@axemere/gateway": "0.1.9"
28
+ },
29
+ "devDependencies": {
30
+ "@google/generative-ai": "^0.24.0",
31
+ "typescript": "^5.4.0",
32
+ "@types/node": "^20.0.0",
33
+ "@types/jest": "^29.0.0",
34
+ "jest": "^29.0.0",
35
+ "ts-jest": "^29.0.0"
36
+ },
37
+ "jest": {
38
+ "preset": "ts-jest",
39
+ "testEnvironment": "node",
40
+ "transform": {
41
+ "^.+\\.tsx?$": [
42
+ "ts-jest",
43
+ {
44
+ "useESM": false
45
+ }
46
+ ]
47
+ }
48
+ },
49
+ "scripts": {
50
+ "build": "tsc",
51
+ "test": "jest"
52
+ }
53
+ }