pi-zengate-models 1.0.1 → 1.0.2

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/CHANGELOG.md CHANGED
@@ -1,5 +1,21 @@
1
1
  # Changelog
2
2
 
3
+ ## [1.0.2] - 2026-11-04
4
+
5
+ - Read `baseUrl` and `apiKey` from the `opencode2api` provider in
6
+ `<agent-dir>/models.json` when the environment and `zengate.json` are empty.
7
+ A machine the gateway sync already prepared needs no second copy, and the
8
+ session warning stops for those machines.
9
+ - Name all three sources in that warning.
10
+ - Pin the install lines to `1.0.2`.
11
+
12
+ ## [Unreleased]
13
+
14
+ - Add `scripts/setup.ps1` and `scripts/setup.sh`. They ask for the gateway URL
15
+ and key, write `<agent-dir>/zengate.json` without a BOM, and move a stale
16
+ `models.json` that holds only the static provider.
17
+ - Document the text-editor route for a machine without an agent.
18
+
3
19
  ## [1.0.1] - 2026-11-04
4
20
 
5
21
  - Remove the built-in gateway URL. Every machine sets `OPENCODE2API_BASE_URL`
package/README.md CHANGED
@@ -22,16 +22,19 @@ This package ships no endpoint and no key. Each machine supplies both.
22
22
  ## Install
23
23
 
24
24
  ```bash
25
- pi install npm:pi-zengate-models
25
+ pi install npm:pi-zengate-models@1.0.2
26
26
  ```
27
27
 
28
28
  From git, or from a local checkout:
29
29
 
30
30
  ```bash
31
- pi install git:github.com/ham-zax/pi-zengate@v1.0.1
31
+ pi install git:github.com/ham-zax/pi-zengate@v1.0.2
32
32
  pi install /path/to/pi-zengate
33
33
  ```
34
34
 
35
+ Pin the npm version. An older `0.0.0-stage` publish still holds the `latest` tag
36
+ until it is removed, and that version has no extension.
37
+
35
38
  ## Configure
36
39
 
37
40
  Every machine needs its own gateway URL and key. Set them in the environment:
@@ -53,8 +56,35 @@ or in `<agent-dir>/zengate.json`, which avoids environment variables:
53
56
  ```
54
57
 
55
58
  `<agent-dir>` is `~/.pi/agent` by default, or `PI_CODING_AGENT_DIR` when set.
56
- The environment wins over the file. Without a URL the extension registers no
57
- provider and shows one warning per session.
59
+ The extension also reads `providers.opencode2api.baseUrl` and `.apiKey` from
60
+ `<agent-dir>/models.json`, so a machine the gateway sync prepared needs no second
61
+ copy. Precedence is environment, then `zengate.json`, then `models.json`. Without
62
+ any URL the extension registers no provider and warns once per session.
63
+
64
+ ## Setup helpers
65
+
66
+ The fastest manual way is a text editor. On Windows:
67
+
68
+ ```powershell
69
+ notepad "$env:USERPROFILE\.pi\agent\zengate.json"
70
+ ```
71
+
72
+ Paste the two fields, save, restart Pi. On Linux, macOS or WSL create
73
+ `~/.pi/agent/zengate.json` the same way.
74
+
75
+ Two scripts ask for the URL and the key and then write the file, so neither
76
+ script contains a secret:
77
+
78
+ ```powershell
79
+ iex (irm "<raw URL of scripts/setup.ps1>") # Windows
80
+ ```
81
+
82
+ ```bash
83
+ curl -fsSL "<raw URL of scripts/setup.sh>" | bash # Linux, macOS, WSL
84
+ ```
85
+
86
+ Both scripts write the file with mode `0600` and print the model count. A
87
+ `models.json` that holds only `opencode2api` moves to `models.json.disabled`.
58
88
 
59
89
  ## Verify
60
90
 
@@ -147,6 +147,10 @@ export function configPath(): string {
147
147
  return join(agentDir(), "zengate.json");
148
148
  }
149
149
 
150
+ export function modelsConfigPath(): string {
151
+ return join(agentDir(), "models.json");
152
+ }
153
+
150
154
  export function cachePath(): string {
151
155
  return join(agentDir(), "cache", "zengate-models.json");
152
156
  }
@@ -165,25 +169,49 @@ function normalizeBaseUrl(value: string): string {
165
169
  }
166
170
 
167
171
  /**
168
- * Settings precedence: environment, then <agent-dir>/zengate.json.
169
- * The config file lets a machine skip environment variables. This package ships
170
- * no endpoint: every machine supplies its own.
172
+ * A machine prepared by the gateway sync already holds the endpoint and the key
173
+ * in models.json. Read them so the client needs no second copy of either.
174
+ */
175
+ function gatewayFromModelsConfig(): { baseUrl?: string; apiKey?: string } {
176
+ const file = readJson(modelsConfigPath()) ?? {};
177
+ const providers = file.providers;
178
+ const provider =
179
+ providers && typeof providers === "object"
180
+ ? (providers as Record<string, unknown>)[PROVIDER_ID]
181
+ : undefined;
182
+ if (!provider || typeof provider !== "object") return {};
183
+ const record = provider as Record<string, unknown>;
184
+ const baseUrl =
185
+ typeof record.baseUrl === "string" && record.baseUrl.trim() ? record.baseUrl : undefined;
186
+ const apiKey =
187
+ typeof record.apiKey === "string" && record.apiKey.trim() ? record.apiKey.trim() : undefined;
188
+ return { baseUrl, apiKey };
189
+ }
190
+
191
+ /**
192
+ * Settings precedence: environment, then <agent-dir>/zengate.json, then the
193
+ * `opencode2api` provider in <agent-dir>/models.json. The last source means a
194
+ * machine the gateway sync already prepared needs no extra file. This package
195
+ * ships no endpoint: every machine supplies its own.
171
196
  */
172
197
  export function readSettings(): { baseUrl?: string; apiKey?: string; keySource: string } {
173
198
  const file = readJson(configPath()) ?? {};
174
199
  const fileBase = typeof file.baseUrl === "string" && file.baseUrl.trim() ? file.baseUrl : undefined;
175
200
  const fileKey = typeof file.apiKey === "string" && file.apiKey.trim() ? file.apiKey.trim() : undefined;
201
+ const synced = gatewayFromModelsConfig();
176
202
  const envBase = process.env[BASE_URL_ENV];
177
203
  const envKey = process.env[KEY_ENV]?.trim();
178
- const base = envBase || fileBase;
204
+ const base = envBase || fileBase || synced.baseUrl;
179
205
  return {
180
206
  baseUrl: base ? normalizeBaseUrl(base) : undefined,
181
- apiKey: envKey || fileKey,
182
- keySource: envKey ? KEY_ENV : fileKey ? "zengate.json" : "none",
207
+ apiKey: envKey || fileKey || synced.apiKey,
208
+ keySource: envKey ? KEY_ENV : fileKey ? "zengate.json" : synced.apiKey ? "models.json" : "none",
183
209
  };
184
210
  }
185
211
 
186
- const configureHint = (): string => `Set ${BASE_URL_ENV} or baseUrl in ${configPath()} to your gateway /v1 URL.`;
212
+ const configureHint = (): string =>
213
+ `No gateway endpoint found. Set ${BASE_URL_ENV}, baseUrl in ${configPath()}, ` +
214
+ `or providers.${PROVIDER_ID}.baseUrl in ${modelsConfigPath()}.`;
187
215
 
188
216
  export default async function (pi: ExtensionAPI) {
189
217
  const settings = readSettings();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-zengate-models",
3
- "version": "1.0.1",
3
+ "version": "1.0.2",
4
4
  "description": "Pi provider extension that discovers free models and their metadata from an OpenAI-compatible gateway catalog, with a local cache and no scheduler.",
5
5
  "keywords": [
6
6
  "pi-package",