pi-bifrost-gateway 0.0.0-stage → 0.3.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/CHANGELOG.md ADDED
@@ -0,0 +1,53 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project are documented here. The format follows
4
+ [Keep a Changelog](https://keepachangelog.com/en/1.1.0/); versions respect
5
+ [SemVer](https://semver.org/).
6
+
7
+ ## [0.3.0] — 2026-10-18
8
+
9
+ ### Changed
10
+
11
+ - **BREAKING** `publishChains` now defaults to `false`. Chains mode fails
12
+ discovery loud when no usable routing rules exist — the conservative
13
+ default publishes only the upstream catalog and needs no governance.
14
+ Installs that want chain models set `publishChains: true` explicitly.
15
+
16
+ ### Added
17
+
18
+ - Member-catalog-only mode: with `publishChains: false`, discovery uses the
19
+ inference plane alone (`GET /v1/models`) — no management-API access — so
20
+ the full upstream catalogue publishes against a stock gateway with
21
+ governance disabled entirely. Previously discovery required chains and
22
+ management access unconditionally.
23
+ - `nativeProtocols` config (`responses` / `messages` toggles, both default
24
+ `false`): publish matching models as `openai-responses` /
25
+ `anthropic-messages` so claude-family and gpt-family chains talk their
26
+ native wire end to end through a gateway that serves the Responses API
27
+ and the Anthropic integration route. Optional `responsesModels` /
28
+ `messagesModels` exact-name lists replace the built-in family heuristic
29
+ for that surface.
30
+ - `managementApiKey` config: separate bearer for the management plane
31
+ (`/api/governance/*`, `/api/routing/rules`), for deployments whose
32
+ management API does not accept the inference virtual key. Defaults to the
33
+ VK; virtual-key self-identification always matches the inference
34
+ credential regardless.
35
+
36
+ ### Fixed
37
+
38
+ - History scrub: no personal paths anywhere in the repository tree or git
39
+ history.
40
+
41
+ ## [0.2.0] — never published
42
+
43
+ Prepared (files whitelist, repository/engines metadata, install docs) but
44
+ superseded by 0.3.0 before release; the version number was never occupied on
45
+ the registry.
46
+
47
+ ## [0.1.0] — 2026-10-08 (unpublished same day)
48
+
49
+ Initial release: chain models from VK routing rules, upstream member
50
+ catalog, `/login bifrost`, `/bifrost` status command, one-time
51
+ `gateway` → `bifrost` credential migration. Unpublished shortly after
52
+ release because its default gateway URL baked in a private address; replaced
53
+ by config/env-only URL resolution before any later publish.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Michael MacLeod
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 CHANGED
@@ -1,3 +1,148 @@
1
- # Temporary Holding Version
1
+ # pi-bifrost-gateway
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ Pi extension for a [Bifrost](https://github.com/maximhq/bifrost) LLM gateway:
4
+ publishes the gateway's models as first-class pi models — chain models from
5
+ the VK's routing rules, the full upstream model catalogue, or both — instead
6
+ of a hand-maintained `models.json` block. Optional per-family native
7
+ protocol surfaces let OpenAI-family models speak the Responses API and
8
+ Anthropic-family models speak Messages end to end.
9
+
10
+ Companion-package note: this is the management-API flavor (governance-aware:
11
+ virtual-key discovery and routing-rule chains). It fills the same provider
12
+ slot as [lxdlam/pi-bifrost-provider](https://github.com/lxdlam/pi-bifrost-provider)
13
+ (standalone-instance flavor) — install one OR the other, not both.
14
+
15
+ ## Install
16
+
17
+ From npm:
18
+
19
+ ```sh
20
+ pi install npm:pi-bifrost-gateway
21
+ ```
22
+
23
+ Or from a local checkout:
24
+
25
+ ```sh
26
+ pi install ~/repos/pi-bifrost-gateway
27
+ ```
28
+
29
+ Then configure it (`~/.pi/agent/pi-bifrost-gateway.json`) — there is **no
30
+ built-in gateway URL**, so an unconfigured install registers zero models:
31
+
32
+ ```json
33
+ {
34
+ "baseUrl": "https://your-bifrost.example/v1",
35
+ "publishChains": true,
36
+ "publishUpstream": false
37
+ }
38
+ ```
39
+
40
+ Auth: `/login bifrost` (stores the virtual key AND the gateway URL on the
41
+ credential in `auth.json` — sufficient on its own) or the `BIFROST_API_KEY`
42
+ env var.
43
+
44
+ ## How it works
45
+
46
+ Two publishing modes, selectable independently:
47
+
48
+ **Chains mode** (`publishChains: true`) — requires a gateway with
49
+ chains-first routing rules. `fetchModels` (runs on startup, `/model`,
50
+ `/reload`, `/login`) does, live:
51
+
52
+ 1. `GET /v1/models` (your VK Bearer) — member catalog with per-member pricing
53
+ and context windows.
54
+ 2. `GET /api/governance/virtual-keys` — matches your stored credential value
55
+ to discover which virtual key you are (the rule filter's `scope_id`).
56
+ 3. `GET /api/routing/rules?scope=virtual_key&scope_id=<vk>` — the VK's chain
57
+ rules; CEL `model == "x"` pairs give chain names, targets + `fallbacks[]`
58
+ give member ids.
59
+
60
+ From that it emits one pi model per chain (`bifrost/<chain>`, e.g.
61
+ `bifrost/glm-5.3-flash`), with `contextWindow` = min member window. A rules
62
+ set with no usable chains fails discovery loud.
63
+
64
+ **Member-only mode** (`publishChains: false`, the default) — the inference
65
+ plane alone: one `GET /v1/models` and the **full upstream catalogue** is
66
+ published as direct-selectable models (`provider/model`, e.g.
67
+ `hyper/glm-5.3-flash`) with real per-member pricing and context windows. No
68
+ management-API access at all, so it works against a stock gateway with
69
+ governance disabled entirely. Both modes can be combined (`publishChains:
70
+ true` + `publishUpstream: true`) — chains first, then the catalogue.
71
+
72
+ In both modes, `nativeProtocols` (see Configuration) can switch matching
73
+ model families from chat completions to their native wire — `openai-responses`
74
+ for the gpt family, `anthropic-messages` for the claude family — so the
75
+ client protocol matches what your gateway/upstream speaks.
76
+
77
+ ## Auth
78
+
79
+ `/login bifrost` prompts for **both** the gateway URL and the virtual key and
80
+ stores them together on the credential in `auth.json` (URL in the
81
+ credential's `BIFROST_URL` env slot) — after login no config file is needed.
82
+ Alternatively set `baseUrl` via config/`BIFROST_BASE_URL` env and `/login`
83
+ with the URL left blank to keep that ambient resolution.
84
+
85
+ URL precedence: login-stored credential URL → config-file `baseUrl` →
86
+ `BIFROST_BASE_URL` env. Key: stored credential → `BIFROST_API_KEY` env.
87
+ A stored credential under the legacy `gateway` provider id is migrated to
88
+ `bifrost` on load; re-running `/login bifrost` upgrades an old key-only
89
+ credential to carry its URL.
90
+
91
+ ## Configuration
92
+
93
+ `~/.pi/agent/pi-bifrost-gateway.json` (all keys optional). Defaults are
94
+ CONSERVATIVE — `publishChains` false, chat completions everywhere:
95
+
96
+ ```json
97
+ {
98
+ "publishChains": true,
99
+ "publishUpstream": true,
100
+ "nativeProtocols": { "responses": true, "messages": true }
101
+ }
102
+ ```
103
+
104
+ - `publishChains` (default **false**): emit the `bifrost/<chain>` models
105
+ from the VK's routing rules. Requires a gateway with chains-first
106
+ routing rules for the credential's VK; a rules set without usable
107
+ chains fails discovery loud. Leave it off (the default) for a stock
108
+ gateway — member-only mode needs no governance at all.
109
+ - `publishUpstream: false` hides the direct-selectable upstream catalog
110
+ (`hyper/glm-5.3-flash`, `pareto/glm-5.3-flash`, …) with real per-member
111
+ pricing. `publishMembers` is accepted as a legacy alias.
112
+ - `baseUrl` (optional) gateway `/v1` URL; then env `BIFROST_BASE_URL`. There
113
+ is NO built-in default URL: with neither set (and no URL stored by
114
+ `/login bifrost`), the plugin registers zero models.
115
+ - `managementApiKey` (optional) bearer for the management plane
116
+ (`/api/governance/virtual-keys`, `/api/routing/rules`). Defaults to the
117
+ inference credential (the VK) — correct for dashboard-auth-disabled
118
+ deployments that accept the VK on `/api/*`. Set it when the management
119
+ plane expects a different credential than inference. The VK-value match
120
+ (VK self-identification) always uses the INFERENCE credential, never
121
+ this key.
122
+ - `nativeProtocols` (optional; both toggles default **false**) selects the
123
+ client wire per model family:
124
+ - `responses: true` — models matching the built-in [OI]-native family
125
+ heuristic (`gpt-*` except `gpt-oss*`, `o<n>`, `codex*`) publish as
126
+ `openai-responses`. Requires a gateway serving `POST /v1/responses`.
127
+ - `messages: true` — models matching the built-in Anthropic family
128
+ heuristic (`claude-*` in the NAME) publish as `anthropic-messages`,
129
+ pointed at the gateway's `/anthropic` integration route. Requires a
130
+ gateway with the Anthropic integration prefix registered.
131
+ - `responsesModels` / `messagesModels` (optional arrays of exact bare
132
+ model names, e.g. `["gpt-6-luna"]`): when set, the list REPLACES the
133
+ built-in heuristic for that surface — list membership is the only path
134
+ to the native wire. Name matching is case-insensitive, last path
135
+ segment (the serving prefix never decides).
136
+ - Both off (default): every model publishes chat completions — the only
137
+ wire every Bifrost serves; the gateway translates at the boundary.
138
+
139
+ ## Cost
140
+
141
+ Chain models carry **zero** cost by design: pi recomputes cost from catalog
142
+ rates and cannot know which member actually served a chain request. Bifrost
143
+ `/api/logs` (cost + cost_breakdown per request) remains the system of record.
144
+ Upstream catalogue models carry real `$/Mtok` rates from `/v1/models`.
145
+
146
+ ## Commands
147
+
148
+ `/bifrost` — auth, baseUrl, config, and loaded-model status.
package/package.json CHANGED
@@ -1,6 +1,57 @@
1
1
  {
2
- "name": "pi-bifrost-gateway",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
6
- }
2
+ "name": "pi-bifrost-gateway",
3
+ "version": "0.3.0",
4
+ "description": "Pi extension for a Bifrost LLM gateway: chain models from VK routing rules and/or the full upstream model catalogue, with optional per-family native protocol surfaces",
5
+ "license": "MIT",
6
+ "keywords": [
7
+ "pi-package"
8
+ ],
9
+ "type": "module",
10
+ "pi": {
11
+ "extensions": [
12
+ "./src/index.ts"
13
+ ]
14
+ },
15
+ "scripts": {
16
+ "test": "vitest run",
17
+ "typecheck": "tsc --noEmit"
18
+ },
19
+ "dependencies": {},
20
+ "peerDependencies": {
21
+ "@earendil-works/pi-ai": "*",
22
+ "@earendil-works/pi-coding-agent": "*",
23
+ "typebox": "*"
24
+ },
25
+ "peerDependenciesMeta": {
26
+ "@earendil-works/pi-ai": {
27
+ "optional": false
28
+ },
29
+ "@earendil-works/pi-coding-agent": {
30
+ "optional": false
31
+ },
32
+ "typebox": {
33
+ "optional": false
34
+ }
35
+ },
36
+ "devDependencies": {
37
+ "@earendil-works/pi-ai": "^1.0.4",
38
+ "@earendil-works/pi-coding-agent": "^1.0.4",
39
+ "@types/node": "^24.0.0",
40
+ "typebox": "^1.3.36",
41
+ "typescript": "^6.0.3",
42
+ "vitest": "^5.0.3"
43
+ },
44
+ "files": [
45
+ "src",
46
+ "README.md",
47
+ "LICENSE",
48
+ "CHANGELOG.md"
49
+ ],
50
+ "repository": {
51
+ "type": "git",
52
+ "url": "git+https://github.com/MacLeodMike/pi-bifrost-gateway.git"
53
+ },
54
+ "engines": {
55
+ "node": ">=22"
56
+ }
57
+ }
package/src/bifrost.ts ADDED
@@ -0,0 +1,31 @@
1
+ /** Gateway constants: model id / endpoints. */
2
+
3
+ export const PROVIDER_ID = "bifrost";
4
+ export const PROVIDER_DISPLAY_NAME = "Bifrost Gateway";
5
+
6
+ /** Different relative to the configured /v1 base URL. */
7
+ export const INFERENCE_PATH_MODELS = "models";
8
+
9
+ /**
10
+ * No built-in default URL. The gateway address comes from /login (stored on
11
+ * the credential), the config file, or BIFROST_BASE_URL env. An install in
12
+ * none of those states must resolve to zero models (no network), never to a
13
+ * baked-in deployment address that would silently route another user's
14
+ * inference through a gateway they don't own.
15
+ */
16
+
17
+ /**
18
+ * Neutral createProvider-shape baseUrl used before a URL exists from any
19
+ * source above. NEVER requested: every published model carries its own
20
+ * discovery-time baseUrl, and discovery resolves the URL from
21
+ * credential-env → config → env before any fetch. An install in this state
22
+ * publishes zero models.
23
+ */
24
+ export const UNRESOLVED_BASE_URL = "http://localhost:8080/v1";
25
+
26
+ /** Management API paths (2026-10-08 live-verified on Bifrost v2.2.x). */
27
+ export const MANAGEMENT_PATH_VIRTUAL_KEYS = "/api/governance/virtual-keys";
28
+ export const MANAGEMENT_PATH_ROUTING_RULES = "/api/routing/rules";
29
+
30
+ /** Auth: env var for the virtual keys value; /login bifrost is the fallback. */
31
+ export const AUTH_ENV_KEYS = ["BIFROST_API_KEY"] as const;