@pwguler/pi-pengepul-provider 0.3.0 → 0.4.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 +5 -0
- package/extensions/models.ts +76 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -53,6 +53,11 @@ prefixed `pengepul/<id>`. To try it without installing, use
|
|
|
53
53
|
`max_output_tokens`, `input_modalities`, `pricing`). Fields the relay omits
|
|
54
54
|
fall back to pi's builtin catalog for the same id, then to family
|
|
55
55
|
heuristics.
|
|
56
|
+
- Names the extended thinking levels (`xhigh`, `max`) that a model's own family
|
|
57
|
+
publishes. An id the catalogs have not caught up with — a point release the
|
|
58
|
+
relay already serves — takes them from the same family's previous minor, so
|
|
59
|
+
it does not sit at `high` until the next pi catalog update. Nothing to
|
|
60
|
+
configure: `thinkingLevelMap` is resolved per id here.
|
|
56
61
|
- Caches the catalog in pi's model store, so startup does not wait on the
|
|
57
62
|
network and a briefly absent relay is covered. The cached models are
|
|
58
63
|
re-pointed at the relay base configured now, so moving the relay does not
|
package/extensions/models.ts
CHANGED
|
@@ -259,6 +259,63 @@ function fallbackLevelMap(id: string): Record<string, string | null> | undefined
|
|
|
259
259
|
return id.toLowerCase().startsWith("commandcode/") ? { max: "max" } : undefined
|
|
260
260
|
}
|
|
261
261
|
|
|
262
|
+
/** The levels pi hides unless a map names them. */
|
|
263
|
+
const INHERITED_LEVELS = ["xhigh", "max"] as const
|
|
264
|
+
|
|
265
|
+
/**
|
|
266
|
+
* Extended levels a family's previous minor already carries.
|
|
267
|
+
*
|
|
268
|
+
* pi hides `xhigh` and `max` unless a model's map names them, so an id the
|
|
269
|
+
* catalogs have not caught up with - a Claude point release the relay serves
|
|
270
|
+
* today, before pi's catalog carries it - dropped to low/medium/high and could
|
|
271
|
+
* never send the top of a ladder its own family publishes: in the catalog Opus
|
|
272
|
+
* 4.5 names neither extension, 4.6 names max, and 4.7, 4.8 and 5 name xhigh and
|
|
273
|
+
* max. The previous minor's own entry is that answer, and the only evidence
|
|
274
|
+
* there is: the relay advertises no effort metadata, so `GET /v1/models` has
|
|
275
|
+
* nothing to say about levels and pi's map is the whole vocabulary.
|
|
276
|
+
*
|
|
277
|
+
* Add-only by construction. Only levels the sibling maps to a string come
|
|
278
|
+
* across, so an id that reaches this path can gain the top of the scale but
|
|
279
|
+
* never lose a level that works today, and never takes on a sibling's spelling
|
|
280
|
+
* for off/low/medium/high - the dialect rules downstream own those.
|
|
281
|
+
*
|
|
282
|
+
* Measured against the live catalog at the time of writing: exactly two ids
|
|
283
|
+
* enter this path, `anthropic/claude-opus-5-5` and
|
|
284
|
+
* `openrouter/anthropic/claude-opus-5.5`, each inheriting xhigh and max from
|
|
285
|
+
* `claude-opus-5`. No other family in that catalog was touched.
|
|
286
|
+
*/
|
|
287
|
+
function inheritedLevelMap(
|
|
288
|
+
id: string,
|
|
289
|
+
dialect: PengepulDialect,
|
|
290
|
+
lookup: BuiltinModelLookup | undefined,
|
|
291
|
+
): Record<string, string | null> | undefined {
|
|
292
|
+
const siblingId = previousMinorId(id)
|
|
293
|
+
const siblingMap = siblingId ? lookup?.(siblingId, dialect)?.thinkingLevelMap : undefined
|
|
294
|
+
if (!siblingMap) return undefined
|
|
295
|
+
|
|
296
|
+
const inherited: Record<string, string | null> = {}
|
|
297
|
+
for (const level of INHERITED_LEVELS) {
|
|
298
|
+
const mapped = siblingMap[level]
|
|
299
|
+
if (typeof mapped === "string") inherited[level] = mapped
|
|
300
|
+
}
|
|
301
|
+
return Object.keys(inherited).length > 0 ? inherited : undefined
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
/**
|
|
305
|
+
* The same id one minor older, keeping the routing namespace:
|
|
306
|
+
* `anthropic/claude-opus-5-5` -> `anthropic/claude-opus-5`, and the dotted
|
|
307
|
+
* `claude-opus-5.5` -> `claude-opus-5` for the Chat Completions spelling.
|
|
308
|
+
* Undefined when the name carries no trailing version segment to drop, which
|
|
309
|
+
* keeps qualifiers (`-preview`, `-flash`, `-fast`) out of the derivation.
|
|
310
|
+
*/
|
|
311
|
+
function previousMinorId(id: string): string | undefined {
|
|
312
|
+
const slash = id.lastIndexOf("/")
|
|
313
|
+
const name = slash === -1 ? id : id.slice(slash + 1)
|
|
314
|
+
const stripped = name.replace(/[.-]\d+$/, "")
|
|
315
|
+
if (stripped === name || stripped === "") return undefined
|
|
316
|
+
return slash === -1 ? stripped : `${id.slice(0, slash + 1)}${stripped}`
|
|
317
|
+
}
|
|
318
|
+
|
|
262
319
|
/**
|
|
263
320
|
* Resolve a model's metadata, most trustworthy source first:
|
|
264
321
|
* 1. what pengepul advertises (first-party for this relay),
|
|
@@ -266,6 +323,11 @@ function fallbackLevelMap(id: string): Record<string, string | null> | undefined
|
|
|
266
323
|
* 3. family heuristics.
|
|
267
324
|
* Sources merge per field, so a relay that sends only `context_window` still
|
|
268
325
|
* picks up pricing and modalities from the catalog.
|
|
326
|
+
*
|
|
327
|
+
* A catalog miss on a reasoning model still gets its extended levels from the
|
|
328
|
+
* family's previous minor where the catalog carries one (`inheritedLevelMap`);
|
|
329
|
+
* the namespace fallback for the Chat Completions wire then takes precedence
|
|
330
|
+
* over both.
|
|
269
331
|
*/
|
|
270
332
|
function metaFor(
|
|
271
333
|
entry: Record<string, unknown>,
|
|
@@ -294,7 +356,20 @@ function metaFor(
|
|
|
294
356
|
const fallback =
|
|
295
357
|
known || !reasoning || dialect !== "openai-completions" ? undefined : fallbackLevelMap(id)
|
|
296
358
|
|
|
297
|
-
|
|
359
|
+
// A catalog miss is not always silence: the family's previous minor answers
|
|
360
|
+
// for the levels the catalog has not named yet. Whatever the base resolved
|
|
361
|
+
// wins over it, so a relay that starts advertising a map still outranks this.
|
|
362
|
+
const inherited = known || !reasoning ? undefined : inheritedLevelMap(id, dialect, lookup)
|
|
363
|
+
const levelMap = inherited
|
|
364
|
+
? { ...inherited, ...(meta.thinkingLevelMap ?? {}) }
|
|
365
|
+
: meta.thinkingLevelMap
|
|
366
|
+
|
|
367
|
+
return {
|
|
368
|
+
...meta,
|
|
369
|
+
reasoning,
|
|
370
|
+
...(levelMap ? { thinkingLevelMap: levelMap } : {}),
|
|
371
|
+
...(fallback ? { thinkingLevelMap: fallback } : {}),
|
|
372
|
+
}
|
|
298
373
|
}
|
|
299
374
|
|
|
300
375
|
function toPengepulModel(
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pwguler/pi-pengepul-provider",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
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",
|