@pwguler/pi-pengepul-provider 0.5.1 → 0.5.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/README.md CHANGED
@@ -141,6 +141,11 @@ box:
141
141
  }
142
142
  ```
143
143
 
144
+ `env` is read off the credential by this provider, not by pi core: a provider
145
+ that brings its own `resolve()` has to hand the values back, and pengepul does.
146
+ Re-add them after `/login pengepul` — pi replaces the whole credential on login,
147
+ so a key rotation drops the block and, with it, the tier.
148
+
144
149
  Idle warming covers gaps up to 30 minutes, pi's own safety limit, and pi only
145
150
  triggers it when the expected saving clears a threshold of its own — a small
146
151
  prompt is left to expire rather than refreshed. The long tier is what carries a
@@ -20,6 +20,8 @@ export interface PengepulCredential {
20
20
  type?: unknown
21
21
  key?: unknown
22
22
  baseUrl?: unknown
23
+ /** Provider-scoped environment values pi stores alongside the key. */
24
+ env?: unknown
23
25
  }
24
26
 
25
27
  function nonEmptyString(value: unknown): string | undefined {
@@ -38,6 +40,32 @@ export function credentialApiKey(credential: PengepulCredential | undefined): st
38
40
  return nonEmptyString(credential?.key)
39
41
  }
40
42
 
43
+ /**
44
+ * The provider-scoped environment the credential carries, when it holds any.
45
+ *
46
+ * pi core fills an `AuthResult.env` from here only for providers that bring no
47
+ * `resolve()` of their own; this provider brings one, so the values have to be
48
+ * passed through or they never reach a request. They are how a user sets
49
+ * `PI_CACHE_RETENTION=long` for the relay without exporting it in every shell
50
+ * that starts pi, and losing them is silent: the cache quietly falls back to
51
+ * the five-minute tier and re-bills whole prefixes.
52
+ *
53
+ * Non-string values are dropped rather than stringified — an env var is a
54
+ * string, and a nested object here is a typo, not a value.
55
+ */
56
+ export function credentialEnv(
57
+ credential: PengepulCredential | undefined,
58
+ ): Record<string, string> | undefined {
59
+ const raw = credential?.env
60
+ if (typeof raw !== "object" || raw === null || Array.isArray(raw)) return undefined
61
+
62
+ const env: Record<string, string> = {}
63
+ for (const [name, value] of Object.entries(raw)) {
64
+ if (typeof value === "string") env[name] = value
65
+ }
66
+ return Object.keys(env).length > 0 ? env : undefined
67
+ }
68
+
41
69
  export interface RelayBaseSources {
42
70
  /** The `PENGEPUL_BASE_URL` environment value. */
43
71
  environment?: string | undefined
@@ -30,6 +30,7 @@ import { anthropicMessagesApi, lazyStream, openAICompletionsApi } from "@earendi
30
30
  import { API_KEY_ENV, RELAY_BASE_ENV } from "./config.ts"
31
31
  import {
32
32
  credentialApiKey,
33
+ credentialEnv,
33
34
  credentialRelayBase,
34
35
  resolveApiKey,
35
36
  resolveRelayBase,
@@ -211,9 +212,21 @@ export function createPengepulProvider(options: PengepulProviderOptions): Provid
211
212
  resolve: async (input): Promise<AuthResult | undefined> => {
212
213
  const resolved = resolveKey(input.credential)
213
214
  if (!resolved) return undefined
215
+ const env = credentialEnv(input.credential as PengepulCredential | undefined)
214
216
  // No `baseUrl` here on purpose: pi would apply it to every model and
215
217
  // collapse the two dialect base URLs into one.
216
- return { auth: { apiKey: resolved.key }, source: resolved.source }
218
+ //
219
+ // `env` is here because pi only reads it off the credential itself
220
+ // when the provider brings no `resolve()` of its own — this one does,
221
+ // so a value like PI_CACHE_RETENTION=long is dropped unless it is
222
+ // handed back. Dropping it is silent and costs money: the cache falls
223
+ // back to the five-minute tier and re-bills the prefix on every
224
+ // return.
225
+ return {
226
+ auth: { apiKey: resolved.key },
227
+ ...(env ? { env } : {}),
228
+ source: resolved.source,
229
+ }
217
230
  },
218
231
  },
219
232
  },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pwguler/pi-pengepul-provider",
3
- "version": "0.5.1",
3
+ "version": "0.5.2",
4
4
  "type": "module",
5
5
  "description": "pi custom provider for pengepul, a relay that pools your Claude/Codex subscriptions. Key and relay base live in auth.json; both native wires (Anthropic Messages, OpenAI Chat Completions) come from one catalog.",
6
6
  "license": "MIT",