@oh-my-pi/pi-ai 15.11.6 → 15.11.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 +16 -0
- package/dist/types/providers/anthropic.d.ts +5 -0
- package/dist/types/providers/google-gemini-cli.d.ts +16 -0
- package/package.json +3 -3
- package/src/providers/anthropic.ts +6 -1
- package/src/providers/google-gemini-cli.ts +24 -1
- package/src/providers/openai-completions.ts +11 -7
- package/src/stream.ts +81 -41
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,22 @@
|
|
|
2
2
|
|
|
3
3
|
## [Unreleased]
|
|
4
4
|
|
|
5
|
+
## [15.11.7] - 2026-06-12
|
|
6
|
+
|
|
7
|
+
### Added
|
|
8
|
+
|
|
9
|
+
- Added `requestModelId` and `thinking.suppress` options to `google-gemini-cli` so collapsed effort-tier variants serialize their per-effort upstream wire id, and thinking-off requests on models with `thinking.suppressWhenOff` send an explicit `thinkingConfig` (`includeThoughts: false` with `thinkingLevel: "MINIMAL"` or `thinkingBudget: 0`) — Cloud Code Assist re-applies the per-id baked server default when the config is omitted, silently thinking and billing the tokens
|
|
10
|
+
- Added mandatory-reasoning clamping: models baked with `thinking.requiresEffort` floor omitted or disabled reasoning to the lowest supported effort in every api mapping, and `disableReasoning` no longer emits OpenRouter `reasoning: { enabled: false }` for them — fixes `omp bench` and utility requests 400ing with "Reasoning is mandatory for this endpoint and cannot be disabled" on OpenRouter Gemini 3.x
|
|
11
|
+
|
|
12
|
+
### Changed
|
|
13
|
+
|
|
14
|
+
- Changed `google-gemini-cli` request mapping to route per-request wire ids via `resolveWireModelId`: the session effort picks the backing variant id (collapsed `gemini-3.5-flash` at high → `gemini-3.5-flash-low`; claude pairs route off → bare id, efforts → `-thinking`) while `AssistantMessage.model` and usage attribution stay on the logical id. A thinking budget clamped to zero now falls through to the thinking-off path (off routing plus suppression) instead of only disabling thinking
|
|
15
|
+
- Changed `openai-completions` and `anthropic-messages` to serialize per-request wire ids via `resolveWireModelId`, so collapsed `X`/`X-thinking` pairs on aggregators and custom providers switch to the thinking SKU when reasoning is enabled (previously only `google-gemini-cli` routed effort-tier variants)
|
|
16
|
+
|
|
17
|
+
### Fixed
|
|
18
|
+
|
|
19
|
+
- Fixed `google-gemini-cli` ignoring `Model.requestModelId` when serializing the request model id
|
|
20
|
+
|
|
5
21
|
## [15.11.5] - 2026-06-12
|
|
6
22
|
|
|
7
23
|
### Added
|
|
@@ -83,6 +83,11 @@ export interface AnthropicOptions extends StreamOptions {
|
|
|
83
83
|
* Ignored for adaptive-capable models.
|
|
84
84
|
*/
|
|
85
85
|
thinkingBudgetTokens?: number;
|
|
86
|
+
/**
|
|
87
|
+
* Upstream wire model id override for collapsed effort-tier variants.
|
|
88
|
+
* Serialized as `requestModelId ?? model.requestModelId ?? model.id`.
|
|
89
|
+
*/
|
|
90
|
+
requestModelId?: string;
|
|
86
91
|
/**
|
|
87
92
|
* Effort level for adaptive thinking.
|
|
88
93
|
* Controls how much thinking Claude allocates:
|
|
@@ -34,7 +34,23 @@ export interface GoogleGeminiCliOptions extends StreamOptions {
|
|
|
34
34
|
budgetTokens?: number;
|
|
35
35
|
/** Thinking level. Use for Gemini 3 models (LOW/HIGH for Pro, MINIMAL/LOW/MEDIUM/HIGH for Flash). */
|
|
36
36
|
level?: GoogleThinkingLevel;
|
|
37
|
+
/**
|
|
38
|
+
* Explicit wire suppression when `enabled` is false. Cloud Code Assist
|
|
39
|
+
* re-applies the per-id baked server default when thinkingConfig is
|
|
40
|
+
* omitted, so models with `thinking.suppressWhenOff` must send
|
|
41
|
+
* `includeThoughts: false` plus a MINIMAL level (or zero budget).
|
|
42
|
+
*/
|
|
43
|
+
suppress?: {
|
|
44
|
+
level: GoogleThinkingLevel;
|
|
45
|
+
} | {
|
|
46
|
+
budget: number;
|
|
47
|
+
};
|
|
37
48
|
};
|
|
49
|
+
/**
|
|
50
|
+
* Upstream wire model id override for collapsed effort-tier variants.
|
|
51
|
+
* Serialized as `requestModelId ?? model.requestModelId ?? model.id`.
|
|
52
|
+
*/
|
|
53
|
+
requestModelId?: string;
|
|
38
54
|
projectId?: string;
|
|
39
55
|
}
|
|
40
56
|
export { ANTIGRAVITY_SYSTEM_INSTRUCTION, getAntigravityUserAgent, getGeminiCliHeaders, getGeminiCliUserAgent, } from "@oh-my-pi/pi-catalog/wire/gemini-headers";
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"type": "module",
|
|
3
3
|
"name": "@oh-my-pi/pi-ai",
|
|
4
|
-
"version": "15.11.
|
|
4
|
+
"version": "15.11.7",
|
|
5
5
|
"description": "Unified LLM API with automatic model discovery and provider configuration",
|
|
6
6
|
"homepage": "https://omp.sh",
|
|
7
7
|
"author": "Can Boluk",
|
|
@@ -38,8 +38,8 @@
|
|
|
38
38
|
},
|
|
39
39
|
"dependencies": {
|
|
40
40
|
"@bufbuild/protobuf": "^2.12.0",
|
|
41
|
-
"@oh-my-pi/pi-catalog": "15.11.
|
|
42
|
-
"@oh-my-pi/pi-utils": "15.11.
|
|
41
|
+
"@oh-my-pi/pi-catalog": "15.11.7",
|
|
42
|
+
"@oh-my-pi/pi-utils": "15.11.7",
|
|
43
43
|
"openai": "^6.39.0",
|
|
44
44
|
"partial-json": "^0.1.7",
|
|
45
45
|
"zod": "4.4.3"
|
|
@@ -973,6 +973,11 @@ export interface AnthropicOptions extends StreamOptions {
|
|
|
973
973
|
* Ignored for adaptive-capable models.
|
|
974
974
|
*/
|
|
975
975
|
thinkingBudgetTokens?: number;
|
|
976
|
+
/**
|
|
977
|
+
* Upstream wire model id override for collapsed effort-tier variants.
|
|
978
|
+
* Serialized as `requestModelId ?? model.requestModelId ?? model.id`.
|
|
979
|
+
*/
|
|
980
|
+
requestModelId?: string;
|
|
976
981
|
/**
|
|
977
982
|
* Effort level for adaptive thinking.
|
|
978
983
|
* Controls how much thinking Claude allocates:
|
|
@@ -2816,7 +2821,7 @@ function buildParams(
|
|
|
2816
2821
|
// Build params in the canonical field order: model → messages → system → tools →
|
|
2817
2822
|
// metadata → max_tokens → thinking → context_management → output_config → stream.
|
|
2818
2823
|
const params: MessageCreateParamsStreaming = {
|
|
2819
|
-
model: model.requestModelId ?? model.id,
|
|
2824
|
+
model: options?.requestModelId ?? model.requestModelId ?? model.id,
|
|
2820
2825
|
messages: convertAnthropicMessages(context.messages, model, isOAuthToken),
|
|
2821
2826
|
...(systemBlocks && { system: systemBlocks }),
|
|
2822
2827
|
...(tools !== undefined && { tools }),
|
|
@@ -76,7 +76,19 @@ export interface GoogleGeminiCliOptions extends StreamOptions {
|
|
|
76
76
|
budgetTokens?: number;
|
|
77
77
|
/** Thinking level. Use for Gemini 3 models (LOW/HIGH for Pro, MINIMAL/LOW/MEDIUM/HIGH for Flash). */
|
|
78
78
|
level?: GoogleThinkingLevel;
|
|
79
|
+
/**
|
|
80
|
+
* Explicit wire suppression when `enabled` is false. Cloud Code Assist
|
|
81
|
+
* re-applies the per-id baked server default when thinkingConfig is
|
|
82
|
+
* omitted, so models with `thinking.suppressWhenOff` must send
|
|
83
|
+
* `includeThoughts: false` plus a MINIMAL level (or zero budget).
|
|
84
|
+
*/
|
|
85
|
+
suppress?: { level: GoogleThinkingLevel } | { budget: number };
|
|
79
86
|
};
|
|
87
|
+
/**
|
|
88
|
+
* Upstream wire model id override for collapsed effort-tier variants.
|
|
89
|
+
* Serialized as `requestModelId ?? model.requestModelId ?? model.id`.
|
|
90
|
+
*/
|
|
91
|
+
requestModelId?: string;
|
|
80
92
|
projectId?: string;
|
|
81
93
|
}
|
|
82
94
|
|
|
@@ -770,6 +782,17 @@ export function buildRequest(
|
|
|
770
782
|
} else if (options.thinking.budgetTokens !== undefined) {
|
|
771
783
|
generationConfig.thinkingConfig.thinkingBudget = options.thinking.budgetTokens;
|
|
772
784
|
}
|
|
785
|
+
} else if (options.thinking?.suppress && model.reasoning) {
|
|
786
|
+
// Explicit off: omitting thinkingConfig re-applies the per-id baked
|
|
787
|
+
// server default (the model silently thinks and bills the tokens).
|
|
788
|
+
const suppress = options.thinking.suppress;
|
|
789
|
+
generationConfig.thinkingConfig = { includeThoughts: false };
|
|
790
|
+
if ("level" in suppress) {
|
|
791
|
+
// Cast to any since our GoogleThinkingLevel mirrors Google's ThinkingLevel enum values
|
|
792
|
+
generationConfig.thinkingConfig.thinkingLevel = suppress.level as any;
|
|
793
|
+
} else {
|
|
794
|
+
generationConfig.thinkingConfig.thinkingBudget = suppress.budget;
|
|
795
|
+
}
|
|
773
796
|
}
|
|
774
797
|
|
|
775
798
|
const request: CloudCodeAssistRequest["request"] = {
|
|
@@ -840,7 +863,7 @@ export function buildRequest(
|
|
|
840
863
|
|
|
841
864
|
return {
|
|
842
865
|
project: projectId,
|
|
843
|
-
model: model.id,
|
|
866
|
+
model: options.requestModelId ?? model.requestModelId ?? model.id,
|
|
844
867
|
request,
|
|
845
868
|
...(isAntigravity
|
|
846
869
|
? {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { Effort } from "@oh-my-pi/pi-catalog/effort";
|
|
2
2
|
import { toFirepassWireModelId, toFireworksWireModelId } from "@oh-my-pi/pi-catalog/fireworks-model-id";
|
|
3
3
|
import { isDeepseekModelIdOrName } from "@oh-my-pi/pi-catalog/identity";
|
|
4
|
-
import { getSupportedEfforts } from "@oh-my-pi/pi-catalog/model-thinking";
|
|
4
|
+
import { getSupportedEfforts, resolveWireModelId } from "@oh-my-pi/pi-catalog/model-thinking";
|
|
5
5
|
import { calculateCost } from "@oh-my-pi/pi-catalog/models";
|
|
6
6
|
import type { ResolvedOpenAICompat } from "@oh-my-pi/pi-catalog/types";
|
|
7
7
|
import { parseGitHubCopilotApiKey } from "@oh-my-pi/pi-catalog/wire/github-copilot";
|
|
@@ -113,12 +113,16 @@ function resolveOpenAICompletionsModelId(
|
|
|
113
113
|
model: Model<"openai-completions">,
|
|
114
114
|
options: OpenAICompletionsOptions | undefined,
|
|
115
115
|
): string {
|
|
116
|
-
//
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
116
|
+
// Effort-tier variants route per request effort (off → bare id, efforts →
|
|
117
|
+
// the thinking backing id); catalog variants (Copilot long-context `-1m`
|
|
118
|
+
// entries) pin via `requestModelId`; everything else serializes `model.id`.
|
|
119
|
+
const effort =
|
|
120
|
+
options?.reasoning && !options.disableReasoning && model.reasoning ? (options.reasoning as Effort) : undefined;
|
|
121
|
+
const wireId = resolveWireModelId(model, effort);
|
|
122
|
+
if (model.provider === "firepass") return toFirepassWireModelId(wireId);
|
|
123
|
+
if (model.provider === "fireworks") return toFireworksWireModelId(wireId);
|
|
124
|
+
if (model.provider === "openrouter") return applyOpenRouterRoutingVariant(wireId, options?.openrouterVariant);
|
|
125
|
+
return wireId;
|
|
122
126
|
}
|
|
123
127
|
|
|
124
128
|
/**
|
package/src/stream.ts
CHANGED
|
@@ -3,7 +3,9 @@ import { isVertexExpressOpenAIUrl, isVertexRawPredictUrl } from "@oh-my-pi/pi-ca
|
|
|
3
3
|
import {
|
|
4
4
|
mapEffortToAnthropicAdaptiveEffort,
|
|
5
5
|
mapEffortToGoogleThinkingLevel,
|
|
6
|
+
minimumSupportedEffort,
|
|
6
7
|
requireSupportedEffort,
|
|
8
|
+
resolveWireModelId,
|
|
7
9
|
} from "@oh-my-pi/pi-catalog/model-thinking";
|
|
8
10
|
import { CATALOG_PROVIDERS, type ProviderCatalogEntry } from "@oh-my-pi/pi-catalog/provider-models";
|
|
9
11
|
import { $env, $pickenv, extractHttpStatusFromError } from "@oh-my-pi/pi-utils";
|
|
@@ -667,11 +669,39 @@ function resolveOpenAiReasoningEffort<TApi extends Api>(
|
|
|
667
669
|
|
|
668
670
|
const castApi = <TApi extends Api>(api: OptionsForApi<TApi>): OptionsForApi<Api> => api as OptionsForApi<Api>;
|
|
669
671
|
|
|
670
|
-
|
|
672
|
+
/**
|
|
673
|
+
* Mandatory-reasoning endpoints (`thinking.requiresEffort`) reject disabled
|
|
674
|
+
* or omitted thinking ("Reasoning is mandatory for this endpoint and cannot
|
|
675
|
+
* be disabled") — clamp to the lowest supported effort instead.
|
|
676
|
+
* `suppressWhenOff` models handle off provider-side via explicit wire
|
|
677
|
+
* suppression. Collapsed pairs interplay: pair derivation strips member
|
|
678
|
+
* flags (off routes to a bare SKU that CAN disable), while identity backfill
|
|
679
|
+
* re-flags pairs whose logical id is itself mandatory (Gemini 3.x) — there
|
|
680
|
+
* the clamp wins and the floored effort routes to the thinking SKU.
|
|
681
|
+
*/
|
|
682
|
+
function normalizeMandatoryReasoningOptions<TApi extends Api>(
|
|
671
683
|
model: Model<TApi>,
|
|
672
684
|
options?: SimpleStreamOptions,
|
|
685
|
+
): SimpleStreamOptions | undefined {
|
|
686
|
+
if (
|
|
687
|
+
!model.reasoning ||
|
|
688
|
+
!model.thinking?.requiresEffort ||
|
|
689
|
+
model.thinking.suppressWhenOff ||
|
|
690
|
+
(options?.reasoning !== undefined && !options.disableReasoning)
|
|
691
|
+
) {
|
|
692
|
+
return options;
|
|
693
|
+
}
|
|
694
|
+
const floor = minimumSupportedEffort(model);
|
|
695
|
+
if (floor === undefined) return options;
|
|
696
|
+
return { ...options, reasoning: floor, disableReasoning: undefined };
|
|
697
|
+
}
|
|
698
|
+
|
|
699
|
+
function mapOptionsForApi<TApi extends Api>(
|
|
700
|
+
model: Model<TApi>,
|
|
701
|
+
rawOptions?: SimpleStreamOptions,
|
|
673
702
|
apiKey?: string,
|
|
674
703
|
): OptionsForApi<TApi> {
|
|
704
|
+
const options = normalizeMandatoryReasoningOptions(model, rawOptions);
|
|
675
705
|
const base = {
|
|
676
706
|
temperature: options?.temperature,
|
|
677
707
|
topP: options?.topP,
|
|
@@ -707,6 +737,7 @@ function mapOptionsForApi<TApi extends Api>(
|
|
|
707
737
|
if (!reasoning || !model.reasoning) {
|
|
708
738
|
return castApi<"anthropic-messages">({
|
|
709
739
|
...base,
|
|
740
|
+
requestModelId: resolveWireModelId(model, undefined),
|
|
710
741
|
thinkingEnabled: false,
|
|
711
742
|
toolChoice: mapAnthropicToolChoice(options?.toolChoice),
|
|
712
743
|
thinkingDisplay: options?.hideThinkingSummary ? "omitted" : undefined,
|
|
@@ -718,6 +749,7 @@ function mapOptionsForApi<TApi extends Api>(
|
|
|
718
749
|
if (thinkingBudget <= 0) {
|
|
719
750
|
return castApi<"anthropic-messages">({
|
|
720
751
|
...base,
|
|
752
|
+
requestModelId: resolveWireModelId(model, undefined),
|
|
721
753
|
thinkingEnabled: false,
|
|
722
754
|
toolChoice: mapAnthropicToolChoice(options?.toolChoice),
|
|
723
755
|
thinkingDisplay: options?.hideThinkingSummary ? "omitted" : undefined,
|
|
@@ -731,6 +763,7 @@ function mapOptionsForApi<TApi extends Api>(
|
|
|
731
763
|
const effort = mapEffortToAnthropicAdaptiveEffort(model, reasoning);
|
|
732
764
|
return castApi<"anthropic-messages">({
|
|
733
765
|
...base,
|
|
766
|
+
requestModelId: resolveWireModelId(model, reasoning),
|
|
734
767
|
thinkingEnabled: true,
|
|
735
768
|
effort,
|
|
736
769
|
toolChoice: mapAnthropicToolChoice(options?.toolChoice),
|
|
@@ -742,6 +775,7 @@ function mapOptionsForApi<TApi extends Api>(
|
|
|
742
775
|
if (ANTHROPIC_USE_INTERLEAVED_THINKING) {
|
|
743
776
|
return castApi<"anthropic-messages">({
|
|
744
777
|
...base,
|
|
778
|
+
requestModelId: resolveWireModelId(model, reasoning),
|
|
745
779
|
thinkingEnabled: true,
|
|
746
780
|
thinkingBudgetTokens: thinkingBudget,
|
|
747
781
|
toolChoice: mapAnthropicToolChoice(options?.toolChoice),
|
|
@@ -762,6 +796,7 @@ function mapOptionsForApi<TApi extends Api>(
|
|
|
762
796
|
if (thinkingBudget <= 0) {
|
|
763
797
|
return castApi<"anthropic-messages">({
|
|
764
798
|
...base,
|
|
799
|
+
requestModelId: resolveWireModelId(model, undefined),
|
|
765
800
|
thinkingEnabled: false,
|
|
766
801
|
toolChoice: mapAnthropicToolChoice(options?.toolChoice),
|
|
767
802
|
thinkingDisplay: options?.hideThinkingSummary ? "omitted" : undefined,
|
|
@@ -771,6 +806,7 @@ function mapOptionsForApi<TApi extends Api>(
|
|
|
771
806
|
return castApi<"anthropic-messages">({
|
|
772
807
|
...base,
|
|
773
808
|
maxTokens,
|
|
809
|
+
requestModelId: resolveWireModelId(model, reasoning),
|
|
774
810
|
thinkingEnabled: true,
|
|
775
811
|
thinkingBudgetTokens: thinkingBudget,
|
|
776
812
|
toolChoice: mapAnthropicToolChoice(options?.toolChoice),
|
|
@@ -887,53 +923,57 @@ function mapOptionsForApi<TApi extends Api>(
|
|
|
887
923
|
|
|
888
924
|
case "google-gemini-cli": {
|
|
889
925
|
const reasoning = options?.reasoning;
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
926
|
+
const toolChoice = mapGoogleToolChoice(options?.toolChoice);
|
|
927
|
+
if (reasoning && model.reasoning) {
|
|
928
|
+
const effort = requireSupportedEffort(model, reasoning);
|
|
929
|
+
|
|
930
|
+
// Gemini 3+ models use thinkingLevel instead of thinkingBudget
|
|
931
|
+
if (model.thinking?.mode === "google-level") {
|
|
932
|
+
return castApi<"google-gemini-cli">({
|
|
933
|
+
...base,
|
|
934
|
+
requestModelId: resolveWireModelId(model, effort),
|
|
935
|
+
thinking: {
|
|
936
|
+
enabled: true,
|
|
937
|
+
level: mapEffortToGoogleThinkingLevel(effort),
|
|
938
|
+
},
|
|
939
|
+
toolChoice,
|
|
940
|
+
});
|
|
941
|
+
}
|
|
899
942
|
|
|
900
|
-
|
|
901
|
-
if (model.thinking?.mode === "google-level") {
|
|
902
|
-
return castApi<"google-gemini-cli">({
|
|
903
|
-
...base,
|
|
904
|
-
thinking: {
|
|
905
|
-
enabled: true,
|
|
906
|
-
level: mapEffortToGoogleThinkingLevel(effort),
|
|
907
|
-
},
|
|
908
|
-
toolChoice: mapGoogleToolChoice(options?.toolChoice),
|
|
909
|
-
});
|
|
910
|
-
}
|
|
943
|
+
let thinkingBudget = options.thinkingBudgets?.[effort] ?? GOOGLE_THINKING[effort];
|
|
911
944
|
|
|
912
|
-
|
|
945
|
+
// Caller's maxTokens is the desired output; add thinking budget on top, capped at model limit
|
|
946
|
+
const maxTokens = Math.min((base.maxTokens || 0) + thinkingBudget, model.maxTokens);
|
|
913
947
|
|
|
914
|
-
|
|
915
|
-
|
|
948
|
+
// If not enough room for thinking + output, reduce thinking budget
|
|
949
|
+
if (maxTokens <= thinkingBudget) {
|
|
950
|
+
thinkingBudget = Math.max(0, maxTokens - MIN_OUTPUT_TOKENS);
|
|
951
|
+
}
|
|
916
952
|
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
953
|
+
if (thinkingBudget > 0) {
|
|
954
|
+
return castApi<"google-gemini-cli">({
|
|
955
|
+
...base,
|
|
956
|
+
maxTokens,
|
|
957
|
+
requestModelId: resolveWireModelId(model, effort),
|
|
958
|
+
thinking: { enabled: true, budgetTokens: thinkingBudget },
|
|
959
|
+
toolChoice,
|
|
960
|
+
});
|
|
961
|
+
}
|
|
962
|
+
// Budget clamped to zero — fall through to the thinking-off path.
|
|
920
963
|
}
|
|
921
964
|
|
|
922
|
-
|
|
923
|
-
if (
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
toolChoice: mapGoogleToolChoice(options?.toolChoice),
|
|
928
|
-
});
|
|
929
|
-
} else {
|
|
930
|
-
return castApi<"google-gemini-cli">({
|
|
931
|
-
...base,
|
|
932
|
-
maxTokens,
|
|
933
|
-
thinking: { enabled: true, budgetTokens: thinkingBudget },
|
|
934
|
-
toolChoice: mapGoogleToolChoice(options?.toolChoice),
|
|
935
|
-
});
|
|
965
|
+
const thinking: GoogleGeminiCliOptions["thinking"] = { enabled: false };
|
|
966
|
+
if (model.reasoning && model.thinking?.suppressWhenOff) {
|
|
967
|
+
// CCA re-applies the per-id baked server default when the config
|
|
968
|
+
// is omitted; suppression must be explicit on the wire.
|
|
969
|
+
thinking.suppress = model.thinking.mode === "google-level" ? { level: "MINIMAL" } : { budget: 0 };
|
|
936
970
|
}
|
|
971
|
+
return castApi<"google-gemini-cli">({
|
|
972
|
+
...base,
|
|
973
|
+
requestModelId: resolveWireModelId(model, undefined),
|
|
974
|
+
thinking,
|
|
975
|
+
toolChoice,
|
|
976
|
+
});
|
|
937
977
|
}
|
|
938
978
|
|
|
939
979
|
case "google-vertex": {
|