@gajae-code/ai 0.18.11 → 0.19.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 +103 -0
- package/README.md +1 -1
- package/dist/types/auth-broker/wire-schemas.d.ts +30 -0
- package/dist/types/auth-storage.d.ts +98 -13
- package/dist/types/bedrock-claude-cache-policy.d.ts +1 -1
- package/dist/types/model-cache.d.ts +6 -4
- package/dist/types/model-manager.d.ts +2 -0
- package/dist/types/model-pricing.d.ts +8 -0
- package/dist/types/model-thinking.d.ts +11 -0
- package/dist/types/openai-completions-compat.d.ts +2 -1
- package/dist/types/provider-models/google.d.ts +2 -0
- package/dist/types/providers/amazon-bedrock.d.ts +17 -2
- package/dist/types/providers/anthropic.d.ts +25 -0
- package/dist/types/providers/aws-credential-config.d.ts +5 -0
- package/dist/types/providers/google-auth.d.ts +7 -0
- package/dist/types/providers/google-gemini-headers.d.ts +11 -6
- package/dist/types/providers/kiro-api-key.d.ts +5 -0
- package/dist/types/providers/openai-chat-server-schema.d.ts +2 -1
- package/dist/types/providers/openai-completions.d.ts +1 -1
- package/dist/types/providers/openai-responses-shared.d.ts +2 -1
- package/dist/types/stream.d.ts +33 -1
- package/dist/types/types.d.ts +26 -3
- package/dist/types/usage.d.ts +3 -0
- package/dist/types/utils/discovery/antigravity.d.ts +16 -1
- package/dist/types/utils/idle-iterator.d.ts +3 -2
- package/dist/types/utils/oauth/glm-zcode.d.ts +0 -30
- package/dist/types/utils/oauth/types.d.ts +9 -0
- package/package.json +4 -4
- package/src/auth-broker/remote-store.ts +62 -11
- package/src/auth-broker/wire-schemas.ts +2 -0
- package/src/auth-gateway/server.ts +3 -2
- package/src/auth-storage.ts +908 -246
- package/src/bedrock-claude-cache-policy.d.ts +1 -1
- package/src/bedrock-claude-cache-policy.ts +2 -2
- package/src/model-cache.ts +45 -10
- package/src/model-manager.ts +18 -6
- package/src/model-pricing.d.ts +8 -0
- package/src/model-pricing.ts +87 -0
- package/src/model-thinking.d.ts +11 -0
- package/src/model-thinking.ts +97 -12
- package/src/models.json +3176 -1670
- package/src/models.ts +10 -3
- package/src/openai-completions-compat.d.ts +2 -1
- package/src/openai-completions-compat.ts +5 -0
- package/src/provider-models/google.ts +11 -1
- package/src/provider-models/openai-compat.ts +26 -0
- package/src/providers/amazon-bedrock.d.ts +17 -2
- package/src/providers/amazon-bedrock.ts +76 -16
- package/src/providers/anthropic.d.ts +25 -0
- package/src/providers/anthropic.ts +230 -18
- package/src/providers/aws-credential-config.d.ts +5 -0
- package/src/providers/aws-credential-config.ts +29 -1
- package/src/providers/google-auth.d.ts +7 -0
- package/src/providers/google-auth.ts +165 -4
- package/src/providers/google-gemini-headers.d.ts +11 -6
- package/src/providers/google-gemini-headers.ts +16 -11
- package/src/providers/google-vertex.ts +2 -4
- package/src/providers/kiro-api-key.d.ts +5 -0
- package/src/providers/kiro-api-key.ts +379 -68
- package/src/providers/ollama.ts +19 -9
- package/src/providers/openai-anthropic-shim.ts +1 -0
- package/src/providers/openai-chat-server-schema.ts +1 -1
- package/src/providers/openai-chat-server.ts +14 -2
- package/src/providers/openai-codex-responses.ts +21 -14
- package/src/providers/openai-completions.d.ts +1 -1
- package/src/providers/openai-completions.ts +65 -4
- package/src/providers/openai-responses-server.ts +10 -1
- package/src/providers/openai-responses-shared.d.ts +2 -1
- package/src/providers/openai-responses-shared.ts +42 -1
- package/src/providers/openai-responses.ts +51 -10
- package/src/providers/pi-native-server.ts +1 -1
- package/src/providers/transform-messages.ts +32 -1
- package/src/stream.d.ts +33 -1
- package/src/stream.ts +111 -17
- package/src/types.d.ts +26 -3
- package/src/types.ts +55 -2
- package/src/usage/claude.ts +4 -2
- package/src/usage.ts +3 -0
- package/src/utils/discovery/antigravity.ts +192 -7
- package/src/utils/idle-iterator.d.ts +3 -2
- package/src/utils/idle-iterator.ts +30 -10
- package/src/utils/oauth/anthropic.ts +23 -22
- package/src/utils/oauth/api-key-validation.ts +34 -11
- package/src/utils/oauth/glm-zcode.d.ts +0 -30
- package/src/utils/oauth/glm-zcode.ts +15 -4
- package/src/utils/oauth/openai-codex.ts +41 -6
- package/src/utils/oauth/types.d.ts +9 -0
- package/src/utils/oauth/types.ts +9 -0
- package/src/utils/parse-bind.d.ts +35 -0
- package/src/utils/proxy.ts +35 -6
package/src/models.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { readFileSync } from "node:fs";
|
|
2
2
|
import { registerProviderSafetyStopModel } from "./adapter-internals/provider-safety-stop";
|
|
3
|
-
import { getOpenAIModelCost } from "./model-pricing";
|
|
3
|
+
import { getAnthropicCacheWriteOneHourRate, getAnthropicModelCost, getOpenAIModelCost } from "./model-pricing";
|
|
4
4
|
import { isRetiredModelKey } from "./model-retirements";
|
|
5
5
|
import { applyGeneratedModelPolicies, enrichModelThinking } from "./model-thinking";
|
|
6
6
|
// `with { type: "file" }` is embedded by `bun build --compile` and resolves to
|
|
@@ -105,11 +105,18 @@ export function getBundledModels(provider: GeneratedProvider): Model<Api>[] {
|
|
|
105
105
|
|
|
106
106
|
export function calculateCost<TApi extends Api>(model: Model<TApi>, usage: Usage): Usage["cost"] {
|
|
107
107
|
const inputTokens = usage.input + usage.cacheRead + usage.cacheWrite;
|
|
108
|
-
const pricing = getOpenAIModelCost(model, inputTokens) ?? model.cost;
|
|
108
|
+
const pricing = getAnthropicModelCost(model, inputTokens) ?? getOpenAIModelCost(model, inputTokens) ?? model.cost;
|
|
109
109
|
usage.cost.input = (pricing.input / 1000000) * usage.input;
|
|
110
110
|
usage.cost.output = (pricing.output / 1000000) * usage.output;
|
|
111
111
|
usage.cost.cacheRead = (pricing.cacheRead / 1000000) * usage.cacheRead;
|
|
112
|
-
|
|
112
|
+
const oneHourRate = getAnthropicCacheWriteOneHourRate(model, inputTokens);
|
|
113
|
+
// Bill the response's 1-hour cache-write tokens at the 1-hour rate; everything else
|
|
114
|
+
// (5-minute writes and any unattributed remainder) uses the model's cacheWrite rate.
|
|
115
|
+
const oneHourTokens =
|
|
116
|
+
oneHourRate === undefined ? 0 : Math.min(Math.max(usage.cttl?.ephemeral1h ?? 0, 0), usage.cacheWrite);
|
|
117
|
+
usage.cost.cacheWrite =
|
|
118
|
+
(pricing.cacheWrite / 1000000) * (usage.cacheWrite - oneHourTokens) +
|
|
119
|
+
((oneHourRate ?? 0) / 1000000) * oneHourTokens;
|
|
113
120
|
usage.cost.total = usage.cost.input + usage.cost.output + usage.cost.cacheRead + usage.cost.cacheWrite;
|
|
114
121
|
return usage.cost;
|
|
115
122
|
}
|
|
@@ -27,13 +27,14 @@ export declare function isDirectXaiReasoningEffortModel(model: {
|
|
|
27
27
|
api?: string;
|
|
28
28
|
baseUrl?: string;
|
|
29
29
|
}, resolvedBaseUrl?: string): boolean;
|
|
30
|
-
export type ResolvedOpenAICompat = Required<Omit<OpenAICompat, "openRouterRouting" | "vercelGatewayRouting" | "extraBody" | "toolStrictMode" | "toolChoiceSupport" | "supportsResponsesSessionAffinity" | "supportsServiceTier" | "reservedToolNames">> & {
|
|
30
|
+
export type ResolvedOpenAICompat = Required<Omit<OpenAICompat, "openRouterRouting" | "vercelGatewayRouting" | "extraBody" | "toolStrictMode" | "toolChoiceSupport" | "supportsResponsesSessionAffinity" | "supportsServiceTier" | "supportsUltrafastTier" | "reservedToolNames">> & {
|
|
31
31
|
openRouterRouting?: OpenAICompat["openRouterRouting"];
|
|
32
32
|
vercelGatewayRouting?: OpenAICompat["vercelGatewayRouting"];
|
|
33
33
|
extraBody?: OpenAICompat["extraBody"];
|
|
34
34
|
toolStrictMode: ResolvedToolStrictMode;
|
|
35
35
|
supportsResponsesSessionAffinity?: OpenAICompat["supportsResponsesSessionAffinity"];
|
|
36
36
|
supportsServiceTier?: OpenAICompat["supportsServiceTier"];
|
|
37
|
+
supportsUltrafastTier?: OpenAICompat["supportsUltrafastTier"];
|
|
37
38
|
/** Optional explicit capability override; resolved via deriveToolChoiceSupport. */
|
|
38
39
|
toolChoiceSupport?: OpenAICompat["toolChoiceSupport"];
|
|
39
40
|
};
|
|
@@ -146,6 +146,7 @@ export type ResolvedOpenAICompat = Required<
|
|
|
146
146
|
| "toolChoiceSupport"
|
|
147
147
|
| "supportsResponsesSessionAffinity"
|
|
148
148
|
| "supportsServiceTier"
|
|
149
|
+
| "supportsUltrafastTier"
|
|
149
150
|
| "reservedToolNames"
|
|
150
151
|
>
|
|
151
152
|
> & {
|
|
@@ -155,6 +156,7 @@ export type ResolvedOpenAICompat = Required<
|
|
|
155
156
|
toolStrictMode: ResolvedToolStrictMode;
|
|
156
157
|
supportsResponsesSessionAffinity?: OpenAICompat["supportsResponsesSessionAffinity"];
|
|
157
158
|
supportsServiceTier?: OpenAICompat["supportsServiceTier"];
|
|
159
|
+
supportsUltrafastTier?: OpenAICompat["supportsUltrafastTier"];
|
|
158
160
|
/** Optional explicit capability override; resolved via deriveToolChoiceSupport. */
|
|
159
161
|
toolChoiceSupport?: OpenAICompat["toolChoiceSupport"];
|
|
160
162
|
};
|
|
@@ -349,6 +351,8 @@ export function detectOpenAICompat(model: Model<"openai-completions">, resolvedB
|
|
|
349
351
|
supportsDeveloperRole: !isNonStandard,
|
|
350
352
|
sendSessionHeaders: false,
|
|
351
353
|
supportsResponsesSessionAffinity: false,
|
|
354
|
+
supportsServiceTier: false,
|
|
355
|
+
supportsUltrafastTier: false,
|
|
352
356
|
supportsMultipleSystemMessages: supportsMultipleSystemMessagesDefault,
|
|
353
357
|
supportsReasoningEffort:
|
|
354
358
|
hasAuditedReasoningEffortTransport &&
|
|
@@ -422,6 +426,7 @@ export function resolveOpenAICompat(
|
|
|
422
426
|
? model.compat.supportsResponsesSessionAffinity
|
|
423
427
|
: undefined) ?? detected.supportsResponsesSessionAffinity,
|
|
424
428
|
supportsServiceTier: model.compat.supportsServiceTier ?? detected.supportsServiceTier,
|
|
429
|
+
supportsUltrafastTier: model.compat.supportsUltrafastTier ?? detected.supportsUltrafastTier,
|
|
425
430
|
supportsMultipleSystemMessages:
|
|
426
431
|
model.compat.supportsMultipleSystemMessages ?? detected.supportsMultipleSystemMessages,
|
|
427
432
|
supportsReasoningEffort: model.compat.supportsReasoningEffort ?? detected.supportsReasoningEffort,
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { ModelManagerOptions } from "../model-manager";
|
|
2
|
-
import { fetchAntigravityDiscoveryModels } from "../utils/discovery/antigravity";
|
|
2
|
+
import { fetchAntigravityDiscoveryModels, getDefaultAntigravityUserAgent } from "../utils/discovery/antigravity";
|
|
3
3
|
import { fetchGeminiModels } from "../utils/discovery/gemini";
|
|
4
4
|
|
|
5
5
|
export interface GoogleModelManagerConfig {
|
|
@@ -14,11 +14,13 @@ export interface GoogleVertexModelManagerConfig {
|
|
|
14
14
|
export interface GoogleAntigravityModelManagerConfig {
|
|
15
15
|
oauthToken?: string;
|
|
16
16
|
endpoint?: string;
|
|
17
|
+
project?: string;
|
|
17
18
|
}
|
|
18
19
|
|
|
19
20
|
export interface GoogleGeminiCliModelManagerConfig {
|
|
20
21
|
oauthToken?: string;
|
|
21
22
|
endpoint?: string;
|
|
23
|
+
project?: string;
|
|
22
24
|
}
|
|
23
25
|
|
|
24
26
|
const CLOUD_CODE_ASSIST_ENDPOINT = "https://cloudcode-pa.googleapis.com";
|
|
@@ -48,14 +50,18 @@ export function googleAntigravityModelManagerOptions(
|
|
|
48
50
|
config?: GoogleAntigravityModelManagerConfig,
|
|
49
51
|
): ModelManagerOptions<"google-gemini-cli"> {
|
|
50
52
|
const token = config?.oauthToken;
|
|
53
|
+
const ua = getDefaultAntigravityUserAgent();
|
|
51
54
|
return {
|
|
52
55
|
providerId: "google-antigravity",
|
|
56
|
+
discoveryUserAgent: ua,
|
|
53
57
|
...(token
|
|
54
58
|
? {
|
|
55
59
|
fetchDynamicModels: () =>
|
|
56
60
|
fetchAntigravityDiscoveryModels({
|
|
57
61
|
token,
|
|
58
62
|
endpoint: config?.endpoint,
|
|
63
|
+
project: config?.project,
|
|
64
|
+
userAgent: ua,
|
|
59
65
|
}),
|
|
60
66
|
}
|
|
61
67
|
: undefined),
|
|
@@ -67,15 +73,19 @@ export function googleGeminiCliModelManagerOptions(
|
|
|
67
73
|
): ModelManagerOptions<"google-gemini-cli"> {
|
|
68
74
|
const token = config?.oauthToken;
|
|
69
75
|
const endpoint = config?.endpoint ?? CLOUD_CODE_ASSIST_ENDPOINT;
|
|
76
|
+
const ua = getDefaultAntigravityUserAgent();
|
|
70
77
|
return {
|
|
71
78
|
providerId: "google-gemini-cli",
|
|
79
|
+
discoveryUserAgent: ua,
|
|
72
80
|
...(token
|
|
73
81
|
? {
|
|
74
82
|
fetchDynamicModels: async () => {
|
|
75
83
|
const models = await fetchAntigravityDiscoveryModels({
|
|
76
84
|
token,
|
|
77
85
|
endpoint,
|
|
86
|
+
project: config?.project,
|
|
78
87
|
targetProvider: "google-gemini-cli",
|
|
88
|
+
userAgent: ua,
|
|
79
89
|
});
|
|
80
90
|
if (models === null) {
|
|
81
91
|
return null;
|
|
@@ -1316,6 +1316,31 @@ export function kiloModelManagerOptions(config?: KiloModelManagerConfig): ModelM
|
|
|
1316
1316
|
provider: "kilo",
|
|
1317
1317
|
baseUrl,
|
|
1318
1318
|
apiKey,
|
|
1319
|
+
// Kilo serves the OpenRouter catalog shape: nested limits/modalities and
|
|
1320
|
+
// per-token USD string prices (GJC costs are per million tokens).
|
|
1321
|
+
mapModel: (entry, defaults) => {
|
|
1322
|
+
const topProvider = isRecord(entry.top_provider) ? entry.top_provider : undefined;
|
|
1323
|
+
const architecture = isRecord(entry.architecture) ? entry.architecture : undefined;
|
|
1324
|
+
const pricing = isRecord(entry.pricing) ? entry.pricing : undefined;
|
|
1325
|
+
const params = Array.isArray(entry.supported_parameters) ? entry.supported_parameters : [];
|
|
1326
|
+
const perMillion = (value: unknown): number => {
|
|
1327
|
+
const perToken = toNumber(value);
|
|
1328
|
+
return perToken !== undefined && perToken >= 0 ? perToken * 1_000_000 : 0;
|
|
1329
|
+
};
|
|
1330
|
+
return {
|
|
1331
|
+
...defaults,
|
|
1332
|
+
reasoning: params.includes("reasoning"),
|
|
1333
|
+
input: toInputCapabilities(architecture?.input_modalities),
|
|
1334
|
+
cost: {
|
|
1335
|
+
input: perMillion(pricing?.prompt),
|
|
1336
|
+
output: perMillion(pricing?.completion),
|
|
1337
|
+
cacheRead: perMillion(pricing?.input_cache_read),
|
|
1338
|
+
cacheWrite: perMillion(pricing?.input_cache_write),
|
|
1339
|
+
},
|
|
1340
|
+
contextWindow: toPositiveNumber(entry.context_length, defaults.contextWindow),
|
|
1341
|
+
maxTokens: toPositiveNumber(topProvider?.max_completion_tokens, defaults.maxTokens),
|
|
1342
|
+
};
|
|
1343
|
+
},
|
|
1319
1344
|
}),
|
|
1320
1345
|
};
|
|
1321
1346
|
}
|
|
@@ -2125,6 +2150,7 @@ export function githubCopilotModelManagerOptions(config?: GithubCopilotModelMana
|
|
|
2125
2150
|
...(api === "openai-completions"
|
|
2126
2151
|
? {
|
|
2127
2152
|
compat: {
|
|
2153
|
+
...(reference.compat ?? {}),
|
|
2128
2154
|
supportsStore: false,
|
|
2129
2155
|
supportsDeveloperRole: false,
|
|
2130
2156
|
supportsReasoningEffort: false,
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
*/
|
|
9
9
|
import { parseBedrockClaudeGeneration } from "../bedrock-claude-cache-policy";
|
|
10
10
|
import type { Effort } from "../model-thinking";
|
|
11
|
-
import type { Model, StreamFunction, StreamOptions, ThinkingBudgets, Tool, ToolChoice } from "../types";
|
|
11
|
+
import type { AssistantMessage, CacheRetention, Model, StreamFunction, StreamOptions, ThinkingBudgets, Tool, ToolChoice } from "../types";
|
|
12
12
|
export type BedrockThinkingDisplay = "summarized" | "omitted";
|
|
13
13
|
export interface BedrockOptions extends StreamOptions {
|
|
14
14
|
region?: string;
|
|
@@ -51,7 +51,18 @@ interface WireToolConfig {
|
|
|
51
51
|
tools: WireToolSpec[];
|
|
52
52
|
toolChoice?: WireToolChoice;
|
|
53
53
|
}
|
|
54
|
+
interface MetadataEvent {
|
|
55
|
+
usage?: {
|
|
56
|
+
inputTokens?: number;
|
|
57
|
+
outputTokens?: number;
|
|
58
|
+
cacheReadInputTokens?: number;
|
|
59
|
+
cacheWriteInputTokens?: number;
|
|
60
|
+
totalTokens?: number;
|
|
61
|
+
};
|
|
62
|
+
}
|
|
54
63
|
export declare const streamBedrock: StreamFunction<"bedrock-converse-stream">;
|
|
64
|
+
/** Exported for unit tests of the usage-to-cost path. */
|
|
65
|
+
export declare function handleMetadata(event: MetadataEvent, model: Model<"bedrock-converse-stream">, output: AssistantMessage, cacheRetention: CacheRetention): void;
|
|
55
66
|
/**
|
|
56
67
|
* Check if the model supports prompt caching.
|
|
57
68
|
* Supported: Claude 3.5 Haiku, Claude 3.7 Sonnet, and every later Claude
|
|
@@ -71,5 +82,9 @@ export declare function stripBedrockForcedToolChoiceForRetry<T extends {
|
|
|
71
82
|
toolConfig?: {
|
|
72
83
|
toolChoice?: unknown;
|
|
73
84
|
};
|
|
74
|
-
|
|
85
|
+
additionalModelRequestFields?: Record<string, unknown>;
|
|
86
|
+
}>(body: T, thinking?: {
|
|
87
|
+
forced: Record<string, unknown> | undefined;
|
|
88
|
+
restored: Record<string, unknown>;
|
|
89
|
+
}): T;
|
|
75
90
|
export declare function convertToolConfig(tools: Tool[] | undefined, toolChoice: BedrockOptions["toolChoice"]): WireToolConfig | undefined;
|
|
@@ -10,10 +10,12 @@
|
|
|
10
10
|
import { $credentialEnv, $env, $flag, extractHttpStatusFromError, fetchWithRetry } from "@gajae-code/utils";
|
|
11
11
|
import { assertAwsRegionLabel } from "../adapter-internals/aws-region";
|
|
12
12
|
import { parseBedrockClaudeGeneration, supportsBedrockClaudePromptCaching } from "../bedrock-claude-cache-policy";
|
|
13
|
+
import { getAnthropicCacheWriteOneHourRate } from "../model-pricing";
|
|
13
14
|
import type { Effort } from "../model-thinking";
|
|
14
15
|
import {
|
|
15
16
|
mapEffortToAnthropicAdaptiveEffort,
|
|
16
17
|
requireSupportedEffort,
|
|
18
|
+
requiresAnthropicThinkingDisableWhenOff,
|
|
17
19
|
supportsAnthropicAdaptiveThinkingDisplay as supportsAdaptiveThinkingDisplay,
|
|
18
20
|
} from "../model-thinking";
|
|
19
21
|
import { calculateCost } from "../models";
|
|
@@ -52,6 +54,7 @@ import { decodeEventStream } from "./aws-eventstream";
|
|
|
52
54
|
import type { AwsCredentials } from "./aws-sigv4";
|
|
53
55
|
import { signRequest } from "./aws-sigv4";
|
|
54
56
|
import { transformMessages } from "./transform-messages";
|
|
57
|
+
import { NON_VISION_IMAGE_PLACEHOLDER } from "./vision-guard";
|
|
55
58
|
|
|
56
59
|
export type BedrockThinkingDisplay = "summarized" | "omitted";
|
|
57
60
|
|
|
@@ -212,12 +215,30 @@ export const streamBedrock: StreamFunction<"bedrock-converse-stream"> = (
|
|
|
212
215
|
const resolvedToolChoice = resolveToolChoice(model, options.toolChoice);
|
|
213
216
|
const toolConfig = convertToolConfig(context.tools, resolvedToolChoice.resolvedChoice);
|
|
214
217
|
let additionalModelRequestFields = buildAdditionalModelRequestFields(model, options);
|
|
218
|
+
// Selected reasoning fields before forced-tool normalization, restored if the forced
|
|
219
|
+
// tool choice is later dropped on retry (Haiku 5+ only; see below).
|
|
220
|
+
let unforcedModelRequestFields: Record<string, unknown> | undefined;
|
|
215
221
|
|
|
216
222
|
// Bedrock rejects thinking + forced tool_choice ("any" or specific tool).
|
|
217
223
|
// When the resolved tool_choice forces tool use, disable thinking to avoid API errors.
|
|
218
224
|
if (toolConfig?.toolChoice && additionalModelRequestFields) {
|
|
219
225
|
const tc = toolConfig.toolChoice;
|
|
220
|
-
if (tc.any || tc.tool)
|
|
226
|
+
if ((tc.any || tc.tool) && requiresAnthropicThinkingDisableWhenOff(model.id)) {
|
|
227
|
+
// Haiku 5+ enables adaptive thinking when the field is omitted, which a forced
|
|
228
|
+
// tool choice rejects, and applies the effort to tool-call arguments too: send an
|
|
229
|
+
// explicit `disabled` and keep the selected effort (capped at `high` while
|
|
230
|
+
// thinking is disabled).
|
|
231
|
+
const effort = (additionalModelRequestFields.output_config as { effort?: string } | undefined)?.effort;
|
|
232
|
+
unforcedModelRequestFields = additionalModelRequestFields;
|
|
233
|
+
additionalModelRequestFields = {
|
|
234
|
+
thinking: { type: "disabled" },
|
|
235
|
+
...(effort
|
|
236
|
+
? { output_config: { effort: effort === "xhigh" || effort === "max" ? "high" : effort } }
|
|
237
|
+
: {}),
|
|
238
|
+
};
|
|
239
|
+
} else if (tc.any || tc.tool) {
|
|
240
|
+
additionalModelRequestFields = undefined;
|
|
241
|
+
}
|
|
221
242
|
}
|
|
222
243
|
|
|
223
244
|
let commandInput: ConverseStreamRequest = {
|
|
@@ -306,7 +327,12 @@ export const streamBedrock: StreamFunction<"bedrock-converse-stream"> = (
|
|
|
306
327
|
reason,
|
|
307
328
|
registryKey: resolvedToolChoice.registryKey,
|
|
308
329
|
});
|
|
309
|
-
stripBedrockForcedToolChoiceForRetry(
|
|
330
|
+
stripBedrockForcedToolChoiceForRetry(
|
|
331
|
+
commandInput,
|
|
332
|
+
unforcedModelRequestFields
|
|
333
|
+
? { forced: additionalModelRequestFields, restored: unforcedModelRequestFields }
|
|
334
|
+
: undefined,
|
|
335
|
+
);
|
|
310
336
|
const retryBodyText = JSON.stringify(commandInput);
|
|
311
337
|
const retryBody = new TextEncoder().encode(retryBodyText);
|
|
312
338
|
if (rawRequestDump) rawRequestDump.body = commandInput;
|
|
@@ -428,7 +454,7 @@ export const streamBedrock: StreamFunction<"bedrock-converse-stream"> = (
|
|
|
428
454
|
break;
|
|
429
455
|
}
|
|
430
456
|
case "metadata": {
|
|
431
|
-
handleMetadata(payload as MetadataEvent, model, output);
|
|
457
|
+
handleMetadata(payload as MetadataEvent, model, output, cacheRetention);
|
|
432
458
|
break;
|
|
433
459
|
}
|
|
434
460
|
default:
|
|
@@ -579,13 +605,28 @@ function handleContentBlockDelta(
|
|
|
579
605
|
}
|
|
580
606
|
}
|
|
581
607
|
|
|
582
|
-
|
|
608
|
+
/** Exported for unit tests of the usage-to-cost path. */
|
|
609
|
+
export function handleMetadata(
|
|
610
|
+
event: MetadataEvent,
|
|
611
|
+
model: Model<"bedrock-converse-stream">,
|
|
612
|
+
output: AssistantMessage,
|
|
613
|
+
cacheRetention: CacheRetention,
|
|
614
|
+
): void {
|
|
583
615
|
if (event.usage) {
|
|
584
616
|
output.usage.input = event.usage.inputTokens || 0;
|
|
585
617
|
output.usage.output = event.usage.outputTokens || 0;
|
|
586
618
|
output.usage.cacheRead = event.usage.cacheReadInputTokens || 0;
|
|
587
619
|
output.usage.cacheWrite = event.usage.cacheWriteInputTokens || 0;
|
|
588
620
|
output.usage.totalTokens = event.usage.totalTokens || output.usage.input + output.usage.output;
|
|
621
|
+
// Converse reports aggregate cache writes only. Where 1-hour writes have their own rate
|
|
622
|
+
// (Haiku 5.5), the request's `ttl: "1h"` cache points mean every write was 1-hour.
|
|
623
|
+
if (
|
|
624
|
+
cacheRetention === "long" &&
|
|
625
|
+
output.usage.cacheWrite > 0 &&
|
|
626
|
+
getAnthropicCacheWriteOneHourRate(model, 0) !== undefined
|
|
627
|
+
) {
|
|
628
|
+
output.usage.cttl = { ephemeral1h: output.usage.cacheWrite };
|
|
629
|
+
}
|
|
589
630
|
calculateCost(model, output.usage);
|
|
590
631
|
}
|
|
591
632
|
}
|
|
@@ -673,12 +714,24 @@ function buildSystemPrompt(
|
|
|
673
714
|
return blocks;
|
|
674
715
|
}
|
|
675
716
|
|
|
717
|
+
function convertToolResultContent(
|
|
718
|
+
content: ToolResultMessage["content"],
|
|
719
|
+
supportsImages: boolean,
|
|
720
|
+
): Array<TextBlockWire | ImageBlockWire> {
|
|
721
|
+
return content.map(c => {
|
|
722
|
+
if (c.type !== "image") return { text: c.text.toWellFormed() };
|
|
723
|
+
if (!supportsImages) return { text: NON_VISION_IMAGE_PLACEHOLDER };
|
|
724
|
+
return { image: createImageBlock(c.mimeType, c.data) };
|
|
725
|
+
});
|
|
726
|
+
}
|
|
727
|
+
|
|
676
728
|
function convertMessages(
|
|
677
729
|
context: Context,
|
|
678
730
|
model: Model<"bedrock-converse-stream">,
|
|
679
731
|
cacheRetention: CacheRetention,
|
|
680
732
|
): WireMessage[] {
|
|
681
733
|
const result: WireMessage[] = [];
|
|
734
|
+
const supportsImages = model.input.includes("image");
|
|
682
735
|
const transformedMessages = transformMessages(context.messages, model, normalizeToolCallId);
|
|
683
736
|
|
|
684
737
|
for (let i = 0; i < transformedMessages.length; i++) {
|
|
@@ -702,7 +755,11 @@ function convertMessages(
|
|
|
702
755
|
break;
|
|
703
756
|
}
|
|
704
757
|
case "image":
|
|
705
|
-
contentBlocks.push(
|
|
758
|
+
contentBlocks.push(
|
|
759
|
+
supportsImages
|
|
760
|
+
? { image: createImageBlock(c.mimeType, c.data) }
|
|
761
|
+
: { text: NON_VISION_IMAGE_PLACEHOLDER },
|
|
762
|
+
);
|
|
706
763
|
break;
|
|
707
764
|
default:
|
|
708
765
|
throw new Error("Unknown user content type");
|
|
@@ -772,11 +829,7 @@ function convertMessages(
|
|
|
772
829
|
toolResults.push({
|
|
773
830
|
toolResult: {
|
|
774
831
|
toolUseId: normalizeToolCallId(m.toolCallId),
|
|
775
|
-
content: m.content
|
|
776
|
-
c.type === "image"
|
|
777
|
-
? { image: createImageBlock(c.mimeType, c.data) }
|
|
778
|
-
: { text: c.text.toWellFormed() },
|
|
779
|
-
),
|
|
832
|
+
content: convertToolResultContent(m.content, supportsImages),
|
|
780
833
|
status: m.isError ? "error" : "success",
|
|
781
834
|
},
|
|
782
835
|
});
|
|
@@ -787,11 +840,7 @@ function convertMessages(
|
|
|
787
840
|
toolResults.push({
|
|
788
841
|
toolResult: {
|
|
789
842
|
toolUseId: normalizeToolCallId(nextMsg.toolCallId),
|
|
790
|
-
content: nextMsg.content
|
|
791
|
-
c.type === "image"
|
|
792
|
-
? { image: createImageBlock(c.mimeType, c.data) }
|
|
793
|
-
: { text: c.text.toWellFormed() },
|
|
794
|
-
),
|
|
843
|
+
content: convertToolResultContent(nextMsg.content, supportsImages),
|
|
795
844
|
status: nextMsg.isError ? "error" : "success",
|
|
796
845
|
},
|
|
797
846
|
});
|
|
@@ -820,10 +869,18 @@ function convertMessages(
|
|
|
820
869
|
return result;
|
|
821
870
|
}
|
|
822
871
|
|
|
823
|
-
export function stripBedrockForcedToolChoiceForRetry<
|
|
872
|
+
export function stripBedrockForcedToolChoiceForRetry<
|
|
873
|
+
T extends { toolConfig?: { toolChoice?: unknown }; additionalModelRequestFields?: Record<string, unknown> },
|
|
874
|
+
>(body: T, thinking?: { forced: Record<string, unknown> | undefined; restored: Record<string, unknown> }): T {
|
|
824
875
|
if (body.toolConfig) {
|
|
825
876
|
body.toolConfig = { ...body.toolConfig, toolChoice: undefined };
|
|
826
877
|
}
|
|
878
|
+
// The forced request replaced the selected thinking fields with a disabled block; with the
|
|
879
|
+
// forced constraint gone, put the selected reasoning back. A payload the caller replaced via
|
|
880
|
+
// onPayload (not the object this provider sent) is left untouched.
|
|
881
|
+
if (thinking && body.additionalModelRequestFields === thinking.forced) {
|
|
882
|
+
body.additionalModelRequestFields = thinking.restored;
|
|
883
|
+
}
|
|
827
884
|
return body;
|
|
828
885
|
}
|
|
829
886
|
|
|
@@ -879,6 +936,9 @@ function buildAdditionalModelRequestFields(
|
|
|
879
936
|
options: BedrockOptions,
|
|
880
937
|
): Record<string, unknown> | undefined {
|
|
881
938
|
const reasoning = options.reasoning;
|
|
939
|
+
if (requiresAnthropicThinkingDisableWhenOff(model.id) && (!reasoning || !model.reasoning)) {
|
|
940
|
+
return { thinking: { type: "disabled" } };
|
|
941
|
+
}
|
|
882
942
|
if (!reasoning || !model.reasoning) return undefined;
|
|
883
943
|
|
|
884
944
|
const mode = model.thinking?.mode;
|
|
@@ -51,6 +51,16 @@ export declare function isAnthropicThinkingBlockMutationError(error: unknown): b
|
|
|
51
51
|
* than only the latest one.
|
|
52
52
|
*/
|
|
53
53
|
export declare function isAnthropicThinkingSignatureInvalidError(error: unknown): boolean;
|
|
54
|
+
/**
|
|
55
|
+
* 400 shape where Anthropic cannot decode one of the request's images:
|
|
56
|
+
* `{"type":"invalid_request_error","message":"Could not process image"}`.
|
|
57
|
+
* Observed for a truncated JPEG (no end-of-image marker) that local resizing
|
|
58
|
+
* also failed to decode and therefore forwarded unchanged. The body names no
|
|
59
|
+
* image, and the image stays in history, so without omission every later
|
|
60
|
+
* request of the session draws the same rejection.
|
|
61
|
+
*/
|
|
62
|
+
export declare function isAnthropicImageUnprocessableError(error: unknown): boolean;
|
|
63
|
+
export declare const ANTHROPIC_OMITTED_IMAGE_PLACEHOLDER = "[Image omitted: Anthropic could not process this image. The file may be corrupt or truncated; re-export or convert it before attaching it again.]";
|
|
54
64
|
/**
|
|
55
65
|
* CLIProxyAPI replaces Anthropic's rejection body wholesale instead of forwarding
|
|
56
66
|
* it: the client only ever sees
|
|
@@ -107,6 +117,14 @@ export interface CpaToolAliasRestoreFailure {
|
|
|
107
117
|
*/
|
|
108
118
|
export declare function parseCpaToolAliasRestoreFailure(error: unknown): CpaToolAliasRestoreFailure | undefined;
|
|
109
119
|
export declare function isCpaToolAliasRestoreFailure(error: unknown): boolean;
|
|
120
|
+
/**
|
|
121
|
+
* How many breakpoints we are still willing to generate after a gateway has
|
|
122
|
+
* rejected a previous attempt. `explicit` mode normally emits two (a reusable
|
|
123
|
+
* prefix anchor on the last assistant turn plus a refresh point on the current
|
|
124
|
+
* user turn), so stepping down to one still caches the prefix, and only the
|
|
125
|
+
* final step gives caching up entirely.
|
|
126
|
+
*/
|
|
127
|
+
type GeneratedCacheBudget = 2 | 1 | 0;
|
|
110
128
|
export declare const claudeCodeEntrypoint = "sdk-cli";
|
|
111
129
|
export declare const claudeToolPrefix: string;
|
|
112
130
|
export declare const claudeCodeSystemInstruction = "You are a Claude agent, built on Anthropic's Claude Agent SDK.";
|
|
@@ -218,6 +236,8 @@ export type AnthropicClientOptionsResult = {
|
|
|
218
236
|
fetchOptions?: AnthropicSdkClientOptions["fetchOptions"];
|
|
219
237
|
};
|
|
220
238
|
export declare function resolveGlmZcodeAnthropicBaseUrl(): string;
|
|
239
|
+
/** Compresses request bodies with gzip for first-party Anthropic endpoints only. */
|
|
240
|
+
export declare function wrapAnthropicFetchForGzip(baseFetch: FetchImpl): FetchImpl;
|
|
221
241
|
export declare function isProviderRetryableError(error: unknown, provider?: string): boolean;
|
|
222
242
|
export type AnthropicUsageLike = {
|
|
223
243
|
cache_creation?: {
|
|
@@ -251,6 +271,11 @@ type SystemBlockOptions = {
|
|
|
251
271
|
export declare function buildAnthropicSystemBlocks(systemPrompt: readonly string[] | undefined, options?: SystemBlockOptions): AnthropicSystemBlock[] | undefined;
|
|
252
272
|
export declare function normalizeExtraBetas(betas?: string[] | string): string[];
|
|
253
273
|
export declare function buildAnthropicClientOptions(args: AnthropicClientOptionsArgs): AnthropicClientOptionsResult;
|
|
274
|
+
type AnthropicCacheParams = MessageCreateParamsStreaming & {
|
|
275
|
+
cache_control?: AnthropicCacheControl;
|
|
276
|
+
};
|
|
277
|
+
type AnthropicCacheMode = "automatic" | "explicit" | "none";
|
|
278
|
+
export declare function applyPromptCaching(params: AnthropicCacheParams, cacheMode: AnthropicCacheMode, cacheControl?: AnthropicCacheControl, budget?: GeneratedCacheBudget): void;
|
|
254
279
|
export declare function normalizeCacheControlTtlOrdering(params: MessageCreateParamsStreaming): void;
|
|
255
280
|
export declare function convertAnthropicMessages(messages: Message[], model: Model<"anthropic-messages">, isOAuthToken: boolean, options?: {
|
|
256
281
|
repairLatestAssistantThinking?: boolean;
|