opencode-apigee 0.1.0 → 0.2.0

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/README.md CHANGED
@@ -71,10 +71,32 @@ config.
71
71
  | `clientId` | `APIGEE_CLIENT_ID` | `apigee.client.id` | |
72
72
  | `clientSecret` | `APIGEE_CLIENT_SECRET` | `apigee.client.secret` | Prefer `opencode auth login` over the config file |
73
73
  | `models` | `APIGEE_MODELS` | `apigee.agents` | Model ids the gateway publishes (array, or comma-separated) |
74
+ | `apiVersion` | `APIGEE_API_VERSION` | `vertex.api.version` | Vertex API version in the path, default `v1` (e.g. `v1beta1`) |
75
+ | `baseUrl` | `APIGEE_BASE_URL` | `vertex.base.url` | The whole URL up to `/models`, for a gateway that doesn't mount Vertex at the standard path. May use `{project}`, `{location}`, `{version}`; with it, `gateway` isn't needed |
74
76
  | `providerId` | | | Provider id in OpenCode, default `apigee` |
75
77
  | `name` | | | Display name, default `Gemini via Apigee` |
76
78
  | `airelay` | | | `false` to ignore AI Relay's config |
77
79
 
80
+ ### A gateway with its own path
81
+
82
+ By default requests go to
83
+ `https://<gateway>/<apiVersion>/projects/<project>/locations/<location>/publishers/google/models/<model>:streamGenerateContent`.
84
+ A gateway that mounts Vertex under a prefix only needs the prefix in `gateway`
85
+ (`"gateway": "https://gw.example.com/genai"`); one on another version sets
86
+ `apiVersion`; one with a different shape altogether gives `baseUrl` — everything
87
+ before `/models`:
88
+
89
+ ```json
90
+ ["opencode-apigee", {
91
+ "baseUrl": "https://gw.example.com/ai/{version}/vertex/{project}/{location}",
92
+ "apiVersion": "v1beta1",
93
+ "project": "my-gcp-project",
94
+ "tokenUrl": "https://auth.example.com/oauth/token",
95
+ "clientId": "my-client-id",
96
+ "models": ["gemini-3.8-flash"]
97
+ }]
98
+ ```
99
+
78
100
  A model you describe yourself under `provider.apigee.models` in
79
101
  `opencode.json` keeps your description; the plugin only adds the rest.
80
102
 
package/dist/index.js CHANGED
@@ -39,7 +39,7 @@ export const ApigeePlugin = async (_input, rawOptions) => {
39
39
  // A model the user described in opencode.json keeps their description.
40
40
  models: { ...models, ...(existing.models ?? {}) },
41
41
  options: {
42
- ...(settings.gateway && settings.project ? { baseURL: baseUrl(settings) } : {}),
42
+ ...(settings.baseUrl || (settings.gateway && settings.project) ? { baseURL: baseUrl(settings) } : {}),
43
43
  ...(existing.options ?? {}),
44
44
  },
45
45
  };
@@ -9,6 +9,14 @@ export interface ApigeeSettings {
9
9
  clientSecret: string;
10
10
  /** Model ids the gateway publishes. */
11
11
  models: string[];
12
+ /** Vertex API version in the path (default `v1`). */
13
+ apiVersion: string;
14
+ /**
15
+ * The whole base URL — everything before `/models/<id>:…` — used instead of the
16
+ * standard path, for a gateway that does not mount Vertex the standard way.
17
+ * May use `{project}`, `{location}` and `{version}`.
18
+ */
19
+ baseUrl: string;
12
20
  }
13
21
  /** Plugin options, as written in opencode.json: `["opencode-apigee", { ... }]`. */
14
22
  export interface ApigeeOptions {
@@ -19,6 +27,10 @@ export interface ApigeeOptions {
19
27
  clientId?: string;
20
28
  clientSecret?: string;
21
29
  models?: string[] | string;
30
+ /** Vertex API version in the path, e.g. `v1beta1` (default `v1`). */
31
+ apiVersion?: string;
32
+ /** Full base URL up to `/models`, replacing the standard path; may use `{project}`, `{location}`, `{version}`. */
33
+ baseUrl?: string;
22
34
  /** Provider id in OpenCode (default `apigee`). */
23
35
  providerId?: string;
24
36
  /** Display name in OpenCode (default `Gemini via Apigee`). */
@@ -39,6 +51,8 @@ export declare function resolveSettings(options?: ApigeeOptions, env?: Record<st
39
51
  /**
40
52
  * The Vertex publisher path on the gateway. `@ai-sdk/google` appends
41
53
  * `/models/<id>:streamGenerateContent`, which together is Vertex's own URL.
54
+ * Gateways differ in version and in where they mount Vertex, so neither is
55
+ * fixed: `apiVersion` changes the one, `baseUrl` replaces the whole path.
42
56
  */
43
57
  export declare function baseUrl(s: ApigeeSettings): string;
44
58
  /** AI Relay's config file, or nothing. Its path follows AIRELAY_CONFIG like AI Relay itself. */
package/dist/settings.js CHANGED
@@ -18,11 +18,15 @@ export function resolveSettings(options = {}, env = process.env, storedSecret, a
18
18
  clientId: pick(options.clientId, "APIGEE_CLIENT_ID", "apigee.client.id") ?? "",
19
19
  clientSecret: nonBlank(storedSecret) ?? pick(options.clientSecret, "APIGEE_CLIENT_SECRET", "apigee.client.secret") ?? "",
20
20
  models,
21
+ apiVersion: pick(options.apiVersion, "APIGEE_API_VERSION", "vertex.api.version")?.replace(/^\/+|\/+$/g, "") ?? "v1",
22
+ baseUrl: pick(options.baseUrl, "APIGEE_BASE_URL", "vertex.base.url") ?? "",
21
23
  };
22
24
  const missing = [];
23
- if (!settings.gateway)
24
- missing.push("gateway (APIGEE_GATEWAY)");
25
- if (!settings.project)
25
+ // With a full base URL, the gateway and project are only needed where it names them.
26
+ const needs = (part) => !settings.baseUrl || settings.baseUrl.includes(`{${part}}`);
27
+ if (!settings.baseUrl && !settings.gateway)
28
+ missing.push("gateway (APIGEE_GATEWAY) or baseUrl (APIGEE_BASE_URL)");
29
+ if (needs("project") && !settings.project)
26
30
  missing.push("project (APIGEE_PROJECT)");
27
31
  if (!settings.tokenUrl)
28
32
  missing.push("tokenUrl (APIGEE_TOKEN_URL)");
@@ -35,10 +39,20 @@ export function resolveSettings(options = {}, env = process.env, storedSecret, a
35
39
  /**
36
40
  * The Vertex publisher path on the gateway. `@ai-sdk/google` appends
37
41
  * `/models/<id>:streamGenerateContent`, which together is Vertex's own URL.
42
+ * Gateways differ in version and in where they mount Vertex, so neither is
43
+ * fixed: `apiVersion` changes the one, `baseUrl` replaces the whole path.
38
44
  */
39
45
  export function baseUrl(s) {
46
+ const fill = (t) => t
47
+ .replaceAll("{project}", encodeURIComponent(s.project))
48
+ .replaceAll("{location}", encodeURIComponent(s.location))
49
+ .replaceAll("{version}", s.apiVersion);
50
+ if (s.baseUrl) {
51
+ const url = fill(s.baseUrl);
52
+ return (/^https?:\/\//i.test(url) ? url : `https://${url}`).replace(/\/+$/, "");
53
+ }
40
54
  const gateway = /^https?:\/\//i.test(s.gateway) ? s.gateway : `https://${s.gateway}`;
41
- return `${gateway.replace(/\/+$/, "")}/v1/projects/${encodeURIComponent(s.project)}/locations/${encodeURIComponent(s.location)}/publishers/google`;
55
+ return `${gateway.replace(/\/+$/, "")}/${s.apiVersion}/projects/${encodeURIComponent(s.project)}/locations/${encodeURIComponent(s.location)}/publishers/google`;
42
56
  }
43
57
  /** AI Relay's config file, or nothing. Its path follows AIRELAY_CONFIG like AI Relay itself. */
44
58
  export function readAirelayConfig(env = process.env) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "opencode-apigee",
3
- "version": "0.1.0",
3
+ "version": "0.2.0",
4
4
  "description": "OpenCode provider plugin: Gemini on Vertex AI behind an Apigee gateway (OAuth client credentials).",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -11,18 +11,29 @@
11
11
  "types": "./dist/index.d.ts"
12
12
  }
13
13
  },
14
- "files": ["dist", "README.md", "LICENSE"],
14
+ "files": [
15
+ "dist",
16
+ "README.md",
17
+ "LICENSE"
18
+ ],
15
19
  "scripts": {
16
20
  "build": "tsc -p tsconfig.json",
17
21
  "test": "bun test",
18
22
  "prepublishOnly": "bun run build && bun test"
19
23
  },
20
- "keywords": ["opencode", "opencode-plugin", "apigee", "vertex", "gemini", "google"],
24
+ "keywords": [
25
+ "opencode",
26
+ "opencode-plugin",
27
+ "apigee",
28
+ "vertex",
29
+ "gemini",
30
+ "google"
31
+ ],
21
32
  "author": "Chelayel",
22
33
  "license": "MIT",
23
34
  "repository": {
24
35
  "type": "git",
25
- "url": "https://github.com/Chelayel/opencode-apigee"
36
+ "url": "git+https://github.com/Chelayel/opencode-apigee.git"
26
37
  },
27
38
  "peerDependencies": {
28
39
  "@opencode-ai/plugin": ">=1.0.0"