@bastani/pi-ai 0.9.20-alpha.5 → 0.9.20-alpha.7
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 +29 -0
- package/README.md +4 -2
- package/dist/api/anthropic-messages.d.ts.map +1 -1
- package/dist/api/anthropic-messages.js +81 -11
- package/dist/api/anthropic-messages.js.map +1 -1
- package/dist/api/openai-completions.d.ts.map +1 -1
- package/dist/api/openai-completions.js +5 -2
- package/dist/api/openai-completions.js.map +1 -1
- package/dist/api/openai-responses-shared.d.ts +3 -0
- package/dist/api/openai-responses-shared.d.ts.map +1 -1
- package/dist/api/openai-responses-shared.js +8 -2
- package/dist/api/openai-responses-shared.js.map +1 -1
- package/dist/auth/oauth/load.d.ts +2 -0
- package/dist/auth/oauth/load.d.ts.map +1 -1
- package/dist/auth/oauth/load.js +5 -0
- package/dist/auth/oauth/load.js.map +1 -1
- package/dist/auth/oauth/meta.d.ts +17 -0
- package/dist/auth/oauth/meta.d.ts.map +1 -0
- package/dist/auth/oauth/meta.js +190 -0
- package/dist/auth/oauth/meta.js.map +1 -0
- package/dist/bun-oauth.d.ts.map +1 -1
- package/dist/bun-oauth.js +2 -0
- package/dist/bun-oauth.js.map +1 -1
- package/dist/decision-models.d.ts +21 -0
- package/dist/decision-models.d.ts.map +1 -0
- package/dist/decision-models.generated.d.ts +3 -0
- package/dist/decision-models.generated.d.ts.map +1 -0
- package/dist/decision-models.generated.js +47 -0
- package/dist/decision-models.generated.js.map +1 -0
- package/dist/decision-models.js +8 -0
- package/dist/decision-models.js.map +1 -0
- package/dist/env-api-keys.d.ts.map +1 -1
- package/dist/env-api-keys.js +1 -0
- package/dist/env-api-keys.js.map +1 -1
- package/dist/image-models.generated.d.ts +15 -0
- package/dist/image-models.generated.d.ts.map +1 -1
- package/dist/image-models.generated.js +15 -0
- package/dist/image-models.generated.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/models.generated.d.ts +2 -0
- package/dist/models.generated.d.ts.map +1 -1
- package/dist/models.generated.js +2 -0
- package/dist/models.generated.js.map +1 -1
- package/dist/providers/all.d.ts.map +1 -1
- package/dist/providers/all.js +2 -0
- package/dist/providers/all.js.map +1 -1
- package/dist/providers/data/.manifest.json +1 -1
- package/dist/providers/data/amazon-bedrock.json +1 -1
- package/dist/providers/data/ant-ling.json +1 -1
- package/dist/providers/data/anthropic.json +1 -1
- package/dist/providers/data/azure-openai-responses.json +1 -1
- package/dist/providers/data/baseten.json +1 -1
- package/dist/providers/data/cerebras.json +1 -1
- package/dist/providers/data/cloudflare-ai-gateway.json +1 -1
- package/dist/providers/data/cloudflare-workers-ai.json +1 -1
- package/dist/providers/data/deepseek.json +1 -1
- package/dist/providers/data/fireworks.json +1 -1
- package/dist/providers/data/github-copilot.json +1 -1
- package/dist/providers/data/google-vertex.json +1 -1
- package/dist/providers/data/google.json +1 -1
- package/dist/providers/data/groq.json +1 -1
- package/dist/providers/data/huggingface.json +1 -1
- package/dist/providers/data/kimi-coding.json +1 -1
- package/dist/providers/data/meta.json +1 -0
- package/dist/providers/data/minimax-cn.json +1 -1
- package/dist/providers/data/minimax.json +1 -1
- package/dist/providers/data/mistral.json +1 -1
- package/dist/providers/data/moonshotai-cn.json +1 -1
- package/dist/providers/data/moonshotai.json +1 -1
- package/dist/providers/data/nvidia.json +1 -1
- package/dist/providers/data/openai-codex.json +1 -1
- package/dist/providers/data/openai.json +1 -1
- package/dist/providers/data/opencode-go.json +1 -1
- package/dist/providers/data/opencode.json +1 -1
- package/dist/providers/data/openrouter.json +1 -1
- package/dist/providers/data/qwen-token-plan-cn.json +1 -1
- package/dist/providers/data/qwen-token-plan-individual.json +1 -1
- package/dist/providers/data/qwen-token-plan.json +1 -1
- package/dist/providers/data/radius.json +1 -1
- package/dist/providers/data/together.json +1 -1
- package/dist/providers/data/vercel-ai-gateway.json +1 -1
- package/dist/providers/data/xai.json +1 -1
- package/dist/providers/data/xiaomi-token-plan-ams.json +1 -1
- package/dist/providers/data/xiaomi-token-plan-cn.json +1 -1
- package/dist/providers/data/xiaomi-token-plan-sgp.json +1 -1
- package/dist/providers/data/xiaomi.json +1 -1
- package/dist/providers/data/zai-coding-cn.json +1 -1
- package/dist/providers/data/zai.json +1 -1
- package/dist/providers/faux.d.ts +1 -0
- package/dist/providers/faux.d.ts.map +1 -1
- package/dist/providers/faux.js +1 -0
- package/dist/providers/faux.js.map +1 -1
- package/dist/providers/meta.d.ts +3 -0
- package/dist/providers/meta.d.ts.map +1 -0
- package/dist/providers/meta.js +24 -0
- package/dist/providers/meta.js.map +1 -0
- package/dist/providers/meta.models.d.ts +3 -0
- package/dist/providers/meta.models.d.ts.map +1 -0
- package/dist/providers/meta.models.js +6 -0
- package/dist/providers/meta.models.js.map +1 -0
- package/dist/types.d.ts +26 -2
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/package.json +3 -2
|
@@ -43,13 +43,13 @@ function getCacheControl(model, cacheRetention, env) {
|
|
|
43
43
|
// Stealth mode: Mimic Claude Code's tool naming exactly
|
|
44
44
|
//
|
|
45
45
|
// Anthropic gates newer models on the `claude-cli/<version>` user agent alone and rejects an
|
|
46
|
-
// older one with `claude_code_version_too_old`. `claude-fable-5-1` requires >= 2.1.251
|
|
47
|
-
// against the live API: 2.1.250 -> 400, 2.1.251 -> 200
|
|
48
|
-
//
|
|
49
|
-
//
|
|
50
|
-
// this value; a caller can override it for
|
|
51
|
-
// lowercase `user-agent` key is merged last.
|
|
52
|
-
const claudeCodeVersion = "2.1.
|
|
46
|
+
// older one with `claude_code_version_too_old`. `claude-fable-5-1` requires >= 2.1.251 (bisected
|
|
47
|
+
// against the live API: 2.1.250 -> 400, 2.1.251 -> 200) and Claude Opus 5.5 requires >= 2.1.280,
|
|
48
|
+
// the floor the API names in its rejection. This is pinned to the highest published minimum
|
|
49
|
+
// among shipped models rather than the newest release; every model this provider ships answers
|
|
50
|
+
// 200 at 2.1.280. Raise it only when a model rejects this value; a caller can override it for
|
|
51
|
+
// one client through the `headers` option, whose lowercase `user-agent` key is merged last.
|
|
52
|
+
const claudeCodeVersion = "2.1.280";
|
|
53
53
|
// Claude Code 2.x tool names (canonical casing)
|
|
54
54
|
// Source: https://cchistory.mariozechner.at/data/prompts-2.1.11.md
|
|
55
55
|
// To update: https://github.com/badlogic/cchistory
|
|
@@ -129,6 +129,61 @@ const SERVER_SIDE_FALLBACK_BETA = "server-side-fallback-2026-07-01";
|
|
|
129
129
|
const THINKING_BINDING_CONTROLS_BETA = "thinking-binding-controls-2026-08-01";
|
|
130
130
|
const MID_CONVERSATION_OUTPUT_CONFIG_BETA = "mid-conversation-output-config-2026-07-01";
|
|
131
131
|
const MID_CONVERSATION_TOOL_CHANGES_BETA = "mid-conversation-tool-changes-2026-07-01";
|
|
132
|
+
const FAST_MODE_BETA = "fast-mode-2026-02-01";
|
|
133
|
+
/**
|
|
134
|
+
* Fast mode bills every token category at twice the standard rate for each supported model, across
|
|
135
|
+
* the full context window, and prompt-caching multipliers stack on top.
|
|
136
|
+
* https://platform.claude.com/docs/en/build-with-claude/fast-mode#pricing
|
|
137
|
+
*/
|
|
138
|
+
const FAST_MODE_PRICE_MULTIPLIER = 2;
|
|
139
|
+
function requestedSpeed(model) {
|
|
140
|
+
return model.fastRoute?.speed;
|
|
141
|
+
}
|
|
142
|
+
function upstreamModelId(model) {
|
|
143
|
+
return model.fastRoute?.upstreamModelId ?? model.id;
|
|
144
|
+
}
|
|
145
|
+
function reportedSpeed(usage) {
|
|
146
|
+
const speed = usage?.speed;
|
|
147
|
+
return speed === "fast" || speed === "standard" ? speed : undefined;
|
|
148
|
+
}
|
|
149
|
+
function applyFastModePricing(usage) {
|
|
150
|
+
usage.cost.input *= FAST_MODE_PRICE_MULTIPLIER;
|
|
151
|
+
usage.cost.output *= FAST_MODE_PRICE_MULTIPLIER;
|
|
152
|
+
usage.cost.cacheRead *= FAST_MODE_PRICE_MULTIPLIER;
|
|
153
|
+
usage.cost.cacheWrite *= FAST_MODE_PRICE_MULTIPLIER;
|
|
154
|
+
usage.cost.total = usage.cost.input + usage.cost.output + usage.cost.cacheRead + usage.cost.cacheWrite;
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* Reject a payload hook that rewrote a field the model's fast route owns.
|
|
158
|
+
*
|
|
159
|
+
* A fast variant is recorded, persisted, and billed under its own `-fast` identity, so a hook that
|
|
160
|
+
* changes the upstream model or drops `speed: "fast"` would send a different request under that
|
|
161
|
+
* identity. Refusing loudly surfaces the misconfigured hook instead of silently restoring the route.
|
|
162
|
+
*/
|
|
163
|
+
function assertPayloadPreservesFastRoute(model, payload) {
|
|
164
|
+
const fastRoute = model.fastRoute;
|
|
165
|
+
if (fastRoute?.speed === undefined)
|
|
166
|
+
return;
|
|
167
|
+
const remedy = `A fast model variant must send its route's upstream model and speed, because it is recorded, persisted, ` +
|
|
168
|
+
`and billed under its own identity. Select the normal model "${model.provider}/${fastRoute.baseModelId}" ` +
|
|
169
|
+
`if the request needs different routing`;
|
|
170
|
+
if (typeof payload !== "object" || payload === null || Array.isArray(payload)) {
|
|
171
|
+
throw new Error(`A request hook changed payload for fast model "${model.provider}/${model.id}" to a value that cannot carry ` +
|
|
172
|
+
`the route's upstream model and speed. ${remedy}, or return an object that preserves those fields.`);
|
|
173
|
+
}
|
|
174
|
+
const record = payload;
|
|
175
|
+
const conflicts = [];
|
|
176
|
+
if (record.model !== fastRoute.upstreamModelId) {
|
|
177
|
+
conflicts.push(`model (expected "${fastRoute.upstreamModelId}", got ${JSON.stringify(record.model)})`);
|
|
178
|
+
}
|
|
179
|
+
if (record.speed !== fastRoute.speed) {
|
|
180
|
+
conflicts.push(`speed (expected ${JSON.stringify(fastRoute.speed)}, got ${JSON.stringify(record.speed)})`);
|
|
181
|
+
}
|
|
182
|
+
if (conflicts.length === 0)
|
|
183
|
+
return;
|
|
184
|
+
throw new Error(`A request hook changed ${conflicts.join(" and ")} for fast model "${model.provider}/${model.id}". ` +
|
|
185
|
+
`${remedy}, or stop rewriting those fields.`);
|
|
186
|
+
}
|
|
132
187
|
/**
|
|
133
188
|
* Stable deferred tool declared whenever native tool changes are in use. Anthropic adds
|
|
134
189
|
* hidden prompt scaffolding as soon as any tool has `defer_loading`; declaring this
|
|
@@ -220,7 +275,7 @@ function addEarlierAttemptCosts(output, model, servingModel, event) {
|
|
|
220
275
|
if (!iteration.output_tokens)
|
|
221
276
|
continue;
|
|
222
277
|
// Price at the rates of the model that ran the attempt, which is not the serving model.
|
|
223
|
-
const attemptCost = iteration.model === model
|
|
278
|
+
const attemptCost = iteration.model === upstreamModelId(model)
|
|
224
279
|
? model.cost
|
|
225
280
|
: iteration.model === servingModel.id
|
|
226
281
|
? servingModel.cost
|
|
@@ -485,6 +540,7 @@ export const stream = (model, context, options) => {
|
|
|
485
540
|
let client;
|
|
486
541
|
let isOAuth;
|
|
487
542
|
let usageModel = model;
|
|
543
|
+
let servedSpeed = requestedSpeed(model);
|
|
488
544
|
if (options?.client) {
|
|
489
545
|
client = options.client;
|
|
490
546
|
isOAuth = false;
|
|
@@ -515,6 +571,7 @@ export const stream = (model, context, options) => {
|
|
|
515
571
|
if (nextParams !== undefined) {
|
|
516
572
|
params = nextParams;
|
|
517
573
|
}
|
|
574
|
+
assertPayloadPreservesFastRoute(model, params);
|
|
518
575
|
const requestOptions = {
|
|
519
576
|
...(streamDeadline.signal ? { signal: streamDeadline.signal } : {}),
|
|
520
577
|
...(options?.timeoutMs !== undefined ? { timeout: options.timeoutMs } : {}),
|
|
@@ -532,9 +589,9 @@ export const stream = (model, context, options) => {
|
|
|
532
589
|
if (event.type === "message_start") {
|
|
533
590
|
output.responseId = event.message.id;
|
|
534
591
|
const responseModel = event.message.model;
|
|
535
|
-
if (responseModel !== model
|
|
592
|
+
if (responseModel !== upstreamModelId(model))
|
|
536
593
|
output.responseModel = responseModel;
|
|
537
|
-
const fallbackCost = responseModel === model
|
|
594
|
+
const fallbackCost = responseModel === upstreamModelId(model)
|
|
538
595
|
? undefined
|
|
539
596
|
: model.compat?.allowedFallbackModels?.find((fallback) => fallback.provider === model.provider && fallback.model === responseModel)?.cost;
|
|
540
597
|
usageModel = fallbackCost ? { ...model, id: responseModel, cost: fallbackCost } : model;
|
|
@@ -549,6 +606,9 @@ export const stream = (model, context, options) => {
|
|
|
549
606
|
output.usage.totalTokens =
|
|
550
607
|
output.usage.input + output.usage.output + output.usage.cacheRead + output.usage.cacheWrite;
|
|
551
608
|
calculateCost(usageModel, output.usage);
|
|
609
|
+
servedSpeed = reportedSpeed(event.message.usage) ?? servedSpeed;
|
|
610
|
+
if (servedSpeed === "fast")
|
|
611
|
+
applyFastModePricing(output.usage);
|
|
552
612
|
inputTransformations = getInputTransformations(event.message) ?? inputTransformations;
|
|
553
613
|
}
|
|
554
614
|
else if (event.type === "content_block_start") {
|
|
@@ -744,6 +804,9 @@ export const stream = (model, context, options) => {
|
|
|
744
804
|
output.usage.totalTokens =
|
|
745
805
|
output.usage.input + output.usage.output + output.usage.cacheRead + output.usage.cacheWrite;
|
|
746
806
|
calculateCost(usageModel, output.usage);
|
|
807
|
+
servedSpeed = reportedSpeed(event.usage) ?? servedSpeed;
|
|
808
|
+
if (servedSpeed === "fast")
|
|
809
|
+
applyFastModePricing(output.usage);
|
|
747
810
|
// A non-empty final fallback report supersedes the request-start report with
|
|
748
811
|
// the serving model's transformations. An empty report must not erase drops
|
|
749
812
|
// already reported at message_start.
|
|
@@ -868,6 +931,8 @@ function createClient(model, apiKey, interleavedThinking, useFineGrainedToolStre
|
|
|
868
931
|
}
|
|
869
932
|
if (useNativeToolChanges)
|
|
870
933
|
betaFeatures.push(MID_CONVERSATION_TOOL_CHANGES_BETA);
|
|
934
|
+
if (requestedSpeed(model) === "fast")
|
|
935
|
+
betaFeatures.push(FAST_MODE_BETA);
|
|
871
936
|
const uniqueBetaFeatures = [...new Set(betaFeatures)];
|
|
872
937
|
// Copilot: Bearer auth, selective betas.
|
|
873
938
|
if (model.provider === "github-copilot") {
|
|
@@ -959,6 +1024,8 @@ function getNativeToolChangeBetas(model, context, isOAuth, options) {
|
|
|
959
1024
|
features.push(THINKING_BINDING_CONTROLS_BETA);
|
|
960
1025
|
if (supportsMidConvoEffort(model))
|
|
961
1026
|
features.push(MID_CONVERSATION_OUTPUT_CONFIG_BETA, THINKING_BINDING_CONTROLS_BETA);
|
|
1027
|
+
if (requestedSpeed(model) === "fast")
|
|
1028
|
+
features.push(FAST_MODE_BETA);
|
|
962
1029
|
return [...new Set(features)];
|
|
963
1030
|
}
|
|
964
1031
|
function buildParams(model, context, isOAuthToken, options) {
|
|
@@ -979,7 +1046,7 @@ function buildParams(model, context, isOAuthToken, options) {
|
|
|
979
1046
|
const converted = convertMessages(conversationMessages, isOAuthToken, cacheControl, compat.allowEmptySignature, supportsMidConvoEffort(model) ? model.provider : undefined, nativeToolChanges);
|
|
980
1047
|
const activeEffort = options?.effort ?? "high";
|
|
981
1048
|
const params = {
|
|
982
|
-
model: model
|
|
1049
|
+
model: upstreamModelId(model),
|
|
983
1050
|
messages: (supportsMidConvoEffort(model)
|
|
984
1051
|
? insertThinkingLevelMessages(converted, activeEffort)
|
|
985
1052
|
: converted.messages),
|
|
@@ -988,6 +1055,9 @@ function buildParams(model, context, isOAuthToken, options) {
|
|
|
988
1055
|
};
|
|
989
1056
|
if (nativeToolChanges)
|
|
990
1057
|
params.betas = getNativeToolChangeBetas(model, context, isOAuthToken, options);
|
|
1058
|
+
const speed = requestedSpeed(model);
|
|
1059
|
+
if (speed !== undefined)
|
|
1060
|
+
params.speed = speed;
|
|
991
1061
|
// For OAuth tokens, we MUST include Claude Code identity
|
|
992
1062
|
if (isOAuthToken) {
|
|
993
1063
|
params.system = [
|