pi-provider-litellm 3.0.0 → 3.0.1
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/package.json +1 -1
- package/src/index.ts +43 -4
- package/src/model-groups.ts +10 -10
- package/src/thinking-levels.ts +2 -2
- package/src/types.ts +2 -0
package/package.json
CHANGED
package/src/index.ts
CHANGED
|
@@ -1125,16 +1125,25 @@ async function refreshLiteLLM(
|
|
|
1125
1125
|
return { ...credentials, access, expires: tokenExpiresAt(access, EXPIRE_TOKEN_IMMEDIATELY) };
|
|
1126
1126
|
}
|
|
1127
1127
|
|
|
1128
|
+
async function configuredBaseUrl(
|
|
1129
|
+
definition: ProviderDefinition,
|
|
1130
|
+
ctx: { env(name: string): Promise<string | undefined> },
|
|
1131
|
+
credential?: ApiKeyCredential,
|
|
1132
|
+
): Promise<string | undefined> {
|
|
1133
|
+
return (
|
|
1134
|
+
cleanConfig(credential?.env?.[ENV_BASE_URL]) ??
|
|
1135
|
+
cleanConfig(definition.baseUrl) ??
|
|
1136
|
+
(definition.useDefaultEnv ? cleanConfig(await ctx.env(ENV_BASE_URL)) : undefined)
|
|
1137
|
+
);
|
|
1138
|
+
}
|
|
1139
|
+
|
|
1128
1140
|
async function resolveApiKeyAuth(
|
|
1129
1141
|
definition: ProviderDefinition,
|
|
1130
1142
|
ctx: { env(name: string): Promise<string | undefined> },
|
|
1131
1143
|
credential?: ApiKeyCredential,
|
|
1132
1144
|
executeHelpers = true,
|
|
1133
1145
|
) {
|
|
1134
|
-
const baseUrl =
|
|
1135
|
-
cleanConfig(credential?.env?.[ENV_BASE_URL]) ??
|
|
1136
|
-
cleanConfig(definition.baseUrl) ??
|
|
1137
|
-
(definition.useDefaultEnv ? cleanConfig(await ctx.env(ENV_BASE_URL)) : undefined);
|
|
1146
|
+
const baseUrl = await configuredBaseUrl(definition, ctx, credential);
|
|
1138
1147
|
const stored = credential?.key
|
|
1139
1148
|
? resolveConfigValue(credential.key, { executeCommands: executeHelpers })?.trim()
|
|
1140
1149
|
: undefined;
|
|
@@ -1209,6 +1218,7 @@ function createProviderAuth(
|
|
|
1209
1218
|
definition: ProviderDefinition,
|
|
1210
1219
|
clearOAuthRuntimeRoot?: () => void,
|
|
1211
1220
|
onLogin?: () => void,
|
|
1221
|
+
oauthRuntimeRoot?: () => { apiKey: string; root: string } | undefined,
|
|
1212
1222
|
): ProviderAuth {
|
|
1213
1223
|
function completeLogin<T extends Credential>(credential: T): T {
|
|
1214
1224
|
onLogin?.();
|
|
@@ -1255,6 +1265,34 @@ function createProviderAuth(
|
|
|
1255
1265
|
return fallback ? { type: "api_key", source: fallback } : undefined;
|
|
1256
1266
|
},
|
|
1257
1267
|
resolve: async ({ ctx, credential }) => {
|
|
1268
|
+
// Pi re-resolves auth through this api-key path whenever a caller passes an explicit
|
|
1269
|
+
// apiKey override — compaction and summarization both hand back the key they just
|
|
1270
|
+
// resolved — which bypasses the stored OAuth credential carrying the base URL. The
|
|
1271
|
+
// api-key path exports its root as env so it survives that round trip, but OAuth's
|
|
1272
|
+
// toAuth has no env to export, leaving an SSO session no record of its root. Read it
|
|
1273
|
+
// back from auth.json, the same fallback check() and seedModels() use, and export it
|
|
1274
|
+
// so the request carries the root rather than depending on in-memory state. auth.json is
|
|
1275
|
+
// shared, though: another Pi process logging in replaces the stored token while this one
|
|
1276
|
+
// still holds its own, so fall back to the root this process resolved for that exact
|
|
1277
|
+
// token. Only when nothing configures a root at all: a base URL that is set still
|
|
1278
|
+
// resolves, and still fails, on its own terms rather than silently rerouting.
|
|
1279
|
+
if (credential?.key && !(await configuredBaseUrl(definition, ctx, credential))) {
|
|
1280
|
+
const stored = readStoredCredential(definition.name, join(getAgentDir(), "auth.json"));
|
|
1281
|
+
const remembered = oauthRuntimeRoot?.();
|
|
1282
|
+
const root =
|
|
1283
|
+
stored?.type === "oauth" && stored.access === credential.key
|
|
1284
|
+
? requireCredentialRoot(resolveCredentialRoot(definition, stored), definition.name)
|
|
1285
|
+
: remembered?.apiKey === credential.key
|
|
1286
|
+
? remembered.root
|
|
1287
|
+
: undefined;
|
|
1288
|
+
if (root) {
|
|
1289
|
+
return {
|
|
1290
|
+
auth: { apiKey: credential.key, headers: resolveHeaders(definition), baseUrl: root },
|
|
1291
|
+
env: { [ENV_BASE_URL]: root },
|
|
1292
|
+
source: "OAuth",
|
|
1293
|
+
};
|
|
1294
|
+
}
|
|
1295
|
+
}
|
|
1258
1296
|
clearOAuthRuntimeRoot?.();
|
|
1259
1297
|
return resolveApiKeyAuth(definition, ctx, credential);
|
|
1260
1298
|
},
|
|
@@ -1867,6 +1905,7 @@ export default async function (pi: ExtensionAPI): Promise<void> {
|
|
|
1867
1905
|
definition,
|
|
1868
1906
|
() => oauthRuntimeRoots.delete(definition.name),
|
|
1869
1907
|
definition.name === PROVIDER_NAME ? resumeMcpDiscovery : undefined,
|
|
1908
|
+
() => oauthRuntimeRoots.get(definition.name),
|
|
1870
1909
|
);
|
|
1871
1910
|
if (auth.oauth) {
|
|
1872
1911
|
if (definition.name === PROVIDER_NAME) {
|
package/src/model-groups.ts
CHANGED
|
@@ -169,13 +169,12 @@ function explicitLimit(value: number | undefined): number | undefined {
|
|
|
169
169
|
|
|
170
170
|
const EXTENDED_LEVELS = THINKING_LEVEL_DEFINITIONS.map(([level]) => level);
|
|
171
171
|
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
} as const;
|
|
172
|
+
// Derived from the level table rather than restated: a second hand-written copy
|
|
173
|
+
// silently dropped `supports_medium_reasoning_effort` and
|
|
174
|
+
// `supports_high_reasoning_effort`, so those router flags were never read.
|
|
175
|
+
const LITELLM_LEVEL_FLAGS = Object.fromEntries(THINKING_LEVEL_DEFINITIONS.map(([level, , flag]) => [level, flag])) as {
|
|
176
|
+
[Definition in (typeof THINKING_LEVEL_DEFINITIONS)[number] as Definition[0]]: Definition[2];
|
|
177
|
+
};
|
|
179
178
|
|
|
180
179
|
function normalizeEffort(level: string): (typeof EXTENDED_LEVELS)[number] | undefined {
|
|
181
180
|
const normalized = level === "none" ? "off" : level;
|
|
@@ -273,9 +272,10 @@ export const NO_TRANSMISSIBLE_LEVELS = {
|
|
|
273
272
|
|
|
274
273
|
// Efforts the Responses API accepts. pi-ai passes an unmapped level through
|
|
275
274
|
// verbatim and reads `thinkingLevelMap.off` as the disable value, so a Chat-shaped
|
|
276
|
-
// map would emit `off`
|
|
277
|
-
//
|
|
278
|
-
|
|
275
|
+
// map would emit `off` as an effort. `none` is the disable spelling — pi-ai's own
|
|
276
|
+
// `openai/gpt-5.5` entry maps `off` to it, and its `openai/gpt-5.6-*` entries map
|
|
277
|
+
// `max` to itself, so `max` is a real Responses effort and not a Chat-only value.
|
|
278
|
+
const RESPONSES_EFFORTS = new Set(["none", "minimal", "low", "medium", "high", "xhigh", "max"]);
|
|
279
279
|
|
|
280
280
|
// A level map is only meaningful next to the compat that serializes it, and the
|
|
281
281
|
// two used to travel separately: five call sites each decided whether to copy
|
package/src/thinking-levels.ts
CHANGED
|
@@ -5,8 +5,8 @@ export const THINKING_LEVEL_DEFINITIONS = [
|
|
|
5
5
|
["off", "none", "supports_none_reasoning_effort"],
|
|
6
6
|
["minimal", "minimal", "supports_minimal_reasoning_effort"],
|
|
7
7
|
["low", "low", "supports_low_reasoning_effort"],
|
|
8
|
-
["medium", "medium",
|
|
9
|
-
["high", "high",
|
|
8
|
+
["medium", "medium", "supports_medium_reasoning_effort"],
|
|
9
|
+
["high", "high", "supports_high_reasoning_effort"],
|
|
10
10
|
["xhigh", "xhigh", "supports_xhigh_reasoning_effort"],
|
|
11
11
|
["max", "max", "supports_max_reasoning_effort"],
|
|
12
12
|
] as const;
|
package/src/types.ts
CHANGED
|
@@ -92,6 +92,8 @@ export interface ModelInfoEntry {
|
|
|
92
92
|
supports_none_reasoning_effort?: boolean;
|
|
93
93
|
supports_minimal_reasoning_effort?: boolean;
|
|
94
94
|
supports_low_reasoning_effort?: boolean;
|
|
95
|
+
supports_medium_reasoning_effort?: boolean;
|
|
96
|
+
supports_high_reasoning_effort?: boolean;
|
|
95
97
|
supports_xhigh_reasoning_effort?: boolean;
|
|
96
98
|
supports_max_reasoning_effort?: boolean;
|
|
97
99
|
supports_vision?: boolean;
|