@oh-my-pi/pi-ai 17.2.14 → 17.2.15
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 +7 -0
- package/dist/types/registry/amazon-bedrock.d.ts +1 -2
- package/dist/types/registry/aws.d.ts +3 -1
- package/dist/types/registry/registry.d.ts +1 -1
- package/dist/types/types.d.ts +3 -2
- package/package.json +5 -5
- package/src/providers/google-antigravity-forced-tool.md +1 -0
- package/src/providers/google-gemini-cli.ts +8 -0
- package/src/providers/google-shared.ts +12 -7
- package/src/registry/amazon-bedrock.ts +1 -1
- package/src/registry/aws.ts +3 -2
- package/src/stream.ts +27 -15
- package/src/types.ts +3 -2
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,13 @@
|
|
|
2
2
|
|
|
3
3
|
## [Unreleased]
|
|
4
4
|
|
|
5
|
+
## [17.2.15] - 2026-08-12
|
|
6
|
+
|
|
7
|
+
### Fixed
|
|
8
|
+
|
|
9
|
+
- Fixed an issue where AWS_BEDROCK_SKIP_AUTH failed to expose Amazon Bedrock models when AWS credential files were unavailable.
|
|
10
|
+
- Fixed an issue where forceReasoningOff was ignored by Anthropic and Google transports, which allowed native thinking alongside a caller-supplied external scratchpad.
|
|
11
|
+
|
|
5
12
|
## [17.2.14] - 2026-08-11
|
|
6
13
|
|
|
7
14
|
### Added
|
|
@@ -1,8 +1,7 @@
|
|
|
1
|
-
import { resolveAwsRegistryApiKey } from "./aws.js";
|
|
2
1
|
export declare const amazonBedrockProvider: {
|
|
3
2
|
readonly id: "amazon-bedrock";
|
|
4
3
|
readonly name: "Amazon Bedrock";
|
|
5
|
-
readonly envKeys:
|
|
4
|
+
readonly envKeys: () => string | undefined;
|
|
6
5
|
readonly mapSimpleOptions: (options: import("../index.js").SimpleStreamOptions) => {
|
|
7
6
|
region: string | undefined;
|
|
8
7
|
profile: string | undefined;
|
|
@@ -8,6 +8,8 @@ export interface AwsBedrockProviderOptions extends Readonly<Record<string, unkno
|
|
|
8
8
|
}
|
|
9
9
|
export declare function hasAwsCredentialSource(): boolean;
|
|
10
10
|
/** Registry key marker for AWS transports that resolve their own bearer/IAM credentials. */
|
|
11
|
-
export declare function resolveAwsRegistryApiKey(
|
|
11
|
+
export declare function resolveAwsRegistryApiKey(options?: {
|
|
12
|
+
allowSkipAuth?: boolean;
|
|
13
|
+
}): string | undefined;
|
|
12
14
|
/** Resolve a real AWS bearer token while filtering the registry's auth marker. */
|
|
13
15
|
export declare function resolveAwsBearerToken(apiKey?: string, bearerToken?: string): string | undefined;
|
|
@@ -25,7 +25,7 @@ declare const ALL: ({
|
|
|
25
25
|
} | {
|
|
26
26
|
readonly id: "amazon-bedrock";
|
|
27
27
|
readonly name: "Amazon Bedrock";
|
|
28
|
-
readonly envKeys:
|
|
28
|
+
readonly envKeys: () => string | undefined;
|
|
29
29
|
readonly mapSimpleOptions: (options: import("../index.js").SimpleStreamOptions) => {
|
|
30
30
|
region: string | undefined;
|
|
31
31
|
profile: string | undefined;
|
package/dist/types/types.d.ts
CHANGED
|
@@ -295,8 +295,9 @@ export interface StreamOptions {
|
|
|
295
295
|
*/
|
|
296
296
|
statefulResponses?: boolean;
|
|
297
297
|
/**
|
|
298
|
-
*
|
|
299
|
-
*
|
|
298
|
+
* Disable native reasoning when the caller supplies an external scratchpad.
|
|
299
|
+
* OpenAI Responses emits `reasoning: { effort: "none" }`; Anthropic and
|
|
300
|
+
* Google transports use their native thinking-off controls.
|
|
300
301
|
*/
|
|
301
302
|
forceReasoningOff?: boolean;
|
|
302
303
|
/**
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"type": "module",
|
|
3
3
|
"name": "@oh-my-pi/pi-ai",
|
|
4
|
-
"version": "17.2.
|
|
4
|
+
"version": "17.2.15",
|
|
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,10 +38,10 @@
|
|
|
38
38
|
},
|
|
39
39
|
"dependencies": {
|
|
40
40
|
"@bufbuild/protobuf": "^2.12.1",
|
|
41
|
-
"@oh-my-pi/omptype": "17.2.
|
|
42
|
-
"@oh-my-pi/pi-catalog": "17.2.
|
|
43
|
-
"@oh-my-pi/pi-utils": "17.2.
|
|
44
|
-
"@oh-my-pi/pi-wire": "17.2.
|
|
41
|
+
"@oh-my-pi/omptype": "17.2.15",
|
|
42
|
+
"@oh-my-pi/pi-catalog": "17.2.15",
|
|
43
|
+
"@oh-my-pi/pi-utils": "17.2.15",
|
|
44
|
+
"@oh-my-pi/pi-wire": "17.2.15"
|
|
45
45
|
},
|
|
46
46
|
"devDependencies": {
|
|
47
47
|
"@bufbuild/protoc-gen-es": "^2.12.1",
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
TOOL-ONLY TURN. This turn accepts a tool call and nothing else; a text reply here is discarded unread and you will be re-prompted. Emit the tool call now.
|
|
@@ -36,6 +36,7 @@ import { armPreResponseTimeout, getStreamFirstEventTimeoutMs, iterateWithIdleTim
|
|
|
36
36
|
// the stream provider trusts the access token threaded through `options.apiKey`.
|
|
37
37
|
import { normalizeSchemaForCCA } from "../utils/schema";
|
|
38
38
|
import { StreamMarkupHealing, type StreamMarkupHealingEvent } from "../utils/stream-markup-healing";
|
|
39
|
+
import forcedToolDirective from "./google-antigravity-forced-tool.md" with { type: "text" };
|
|
39
40
|
import type { Content, FunctionCallingConfigMode, ThinkingConfig } from "./google-shared";
|
|
40
41
|
import {
|
|
41
42
|
convertMessages,
|
|
@@ -1347,6 +1348,13 @@ export function buildRequest(
|
|
|
1347
1348
|
},
|
|
1348
1349
|
};
|
|
1349
1350
|
}
|
|
1351
|
+
// Cloud Code Assist drops `toolConfig` on Antigravity's Gemini routes:
|
|
1352
|
+
// the backend answers in text under `mode: "ANY"` and still emits calls
|
|
1353
|
+
// under `"NONE"`. Claude routes implement it, so only Gemini needs the
|
|
1354
|
+
// forced choice restated in the transcript.
|
|
1355
|
+
if (isAntigravity && !isClaudeModel(model.id) && request.toolConfig?.functionCallingConfig.mode === "ANY") {
|
|
1356
|
+
contents.push({ role: "user", parts: [{ text: forcedToolDirective }] });
|
|
1357
|
+
}
|
|
1350
1358
|
}
|
|
1351
1359
|
// Antigravity's default tool mode is VALIDATED (verified for Gemini and
|
|
1352
1360
|
// Claude); an explicit non-auto tool choice above wins.
|
|
@@ -858,13 +858,18 @@ export function buildGoogleGenerateContentParams<T extends "google-generative-ai
|
|
|
858
858
|
config.toolConfig = undefined;
|
|
859
859
|
}
|
|
860
860
|
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
861
|
+
const thinking = options.thinking;
|
|
862
|
+
if (
|
|
863
|
+
thinking &&
|
|
864
|
+
model.reasoning &&
|
|
865
|
+
(thinking.enabled || thinking.level !== undefined || thinking.budgetTokens !== undefined)
|
|
866
|
+
) {
|
|
867
|
+
const cfg: ThinkingConfig = { includeThoughts: thinking.enabled && !options.hideThinkingSummary };
|
|
868
|
+
if (thinking.level !== undefined) {
|
|
869
|
+
// GoogleThinkingLevel mirrors the SDK's ThinkingLevel string enum values 1:1.
|
|
870
|
+
cfg.thinkingLevel = thinking.level as ThinkingLevel;
|
|
871
|
+
} else if (thinking.budgetTokens !== undefined) {
|
|
872
|
+
cfg.thinkingBudget = thinking.budgetTokens;
|
|
868
873
|
}
|
|
869
874
|
config.thinkingConfig = cfg;
|
|
870
875
|
}
|
|
@@ -5,7 +5,7 @@ export const amazonBedrockProvider = {
|
|
|
5
5
|
id: "amazon-bedrock",
|
|
6
6
|
name: "Amazon Bedrock",
|
|
7
7
|
// Amazon Bedrock accepts bearer tokens, IAM keys, profiles, ECS/IRSA credential chains.
|
|
8
|
-
envKeys: resolveAwsRegistryApiKey,
|
|
8
|
+
envKeys: () => resolveAwsRegistryApiKey({ allowSkipAuth: true }),
|
|
9
9
|
mapSimpleOptions: options => {
|
|
10
10
|
const awsOptions = options.providerOptions as AwsBedrockProviderOptions | undefined;
|
|
11
11
|
return {
|
package/src/registry/aws.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as fs from "node:fs";
|
|
2
|
-
import { $env } from "@oh-my-pi/pi-utils";
|
|
2
|
+
import { $env, $flag } from "@oh-my-pi/pi-utils";
|
|
3
3
|
import { hasConfiguredAwsProfile } from "../utils/aws-profile";
|
|
4
4
|
import { AUTHENTICATED_SENTINEL } from "./types";
|
|
5
5
|
|
|
@@ -53,7 +53,8 @@ export function hasAwsCredentialSource(): boolean {
|
|
|
53
53
|
}
|
|
54
54
|
|
|
55
55
|
/** Registry key marker for AWS transports that resolve their own bearer/IAM credentials. */
|
|
56
|
-
export function resolveAwsRegistryApiKey(): string | undefined {
|
|
56
|
+
export function resolveAwsRegistryApiKey(options?: { allowSkipAuth?: boolean }): string | undefined {
|
|
57
|
+
if (options?.allowSkipAuth && $flag("AWS_BEDROCK_SKIP_AUTH")) return AUTHENTICATED_SENTINEL;
|
|
57
58
|
return hasAwsCredentialSource() ? AUTHENTICATED_SENTINEL : undefined;
|
|
58
59
|
}
|
|
59
60
|
|
package/src/stream.ts
CHANGED
|
@@ -1408,6 +1408,17 @@ function resolveOpenAiReasoningEffort<TApi extends Api>(
|
|
|
1408
1408
|
return requireSupportedEffort(model, reasoning);
|
|
1409
1409
|
}
|
|
1410
1410
|
|
|
1411
|
+
function resolveGoogleThinkingOff<TApi extends Api>(model: Model<TApi>): NonNullable<GoogleOptions["thinking"]> {
|
|
1412
|
+
const thinking: NonNullable<GoogleOptions["thinking"]> = { enabled: false };
|
|
1413
|
+
if (!model.reasoning || !model.thinking) return thinking;
|
|
1414
|
+
if (model.thinking.mode === "budget" && (!model.thinking.requiresEffort || model.thinking.suppressWhenOff)) {
|
|
1415
|
+
thinking.budgetTokens = 0;
|
|
1416
|
+
} else if (model.thinking.mode === "google-level" && model.thinking.suppressWhenOff) {
|
|
1417
|
+
thinking.level = "MINIMAL";
|
|
1418
|
+
}
|
|
1419
|
+
return thinking;
|
|
1420
|
+
}
|
|
1421
|
+
|
|
1411
1422
|
const castApi = <TApi extends Api>(api: OptionsForApi<TApi>): OptionsForApi<Api> => api as OptionsForApi<Api>;
|
|
1412
1423
|
|
|
1413
1424
|
/**
|
|
@@ -1428,13 +1439,13 @@ function normalizeMandatoryReasoningOptions<TApi extends Api>(
|
|
|
1428
1439
|
!model.reasoning ||
|
|
1429
1440
|
!model.thinking?.requiresEffort ||
|
|
1430
1441
|
model.thinking.suppressWhenOff ||
|
|
1431
|
-
(options?.reasoning !== undefined && !options.disableReasoning)
|
|
1442
|
+
(options?.reasoning !== undefined && !options.disableReasoning && !options.forceReasoningOff)
|
|
1432
1443
|
) {
|
|
1433
1444
|
return options;
|
|
1434
1445
|
}
|
|
1435
1446
|
const floor = minimumSupportedEffort(model);
|
|
1436
1447
|
if (floor === undefined) return options;
|
|
1437
|
-
return { ...options, reasoning: floor, disableReasoning: undefined };
|
|
1448
|
+
return { ...options, reasoning: floor, disableReasoning: undefined, forceReasoningOff: undefined };
|
|
1438
1449
|
}
|
|
1439
1450
|
|
|
1440
1451
|
function supportsExplicitOpenAIResponsesPromptCache(compat: unknown): boolean {
|
|
@@ -1515,12 +1526,12 @@ function mapOptionsForApi<TApi extends Api>(
|
|
|
1515
1526
|
switch (model.api) {
|
|
1516
1527
|
case "anthropic-messages": {
|
|
1517
1528
|
// Explicitly disable thinking when reasoning is not specified, the caller
|
|
1518
|
-
// disabled it, or the model doesn't
|
|
1519
|
-
// SimpleStreamOptions
|
|
1520
|
-
//
|
|
1521
|
-
// models already clamp
|
|
1529
|
+
// disabled it, an external scratchpad replaces it, or the model doesn't
|
|
1530
|
+
// support it. These SimpleStreamOptions flags never reach AnthropicOptions
|
|
1531
|
+
// on their own, so fold them into thinkingEnabled here (mandatory-reasoning
|
|
1532
|
+
// models already clamp them away in normalizeMandatoryReasoningOptions).
|
|
1522
1533
|
const reasoning = options?.reasoning;
|
|
1523
|
-
if (!reasoning || !model.reasoning || options?.disableReasoning) {
|
|
1534
|
+
if (!reasoning || !model.reasoning || options?.disableReasoning || options?.forceReasoningOff) {
|
|
1524
1535
|
return castApi<"anthropic-messages">({
|
|
1525
1536
|
...base,
|
|
1526
1537
|
requestModelId: resolveWireModelId(model, undefined),
|
|
@@ -1725,14 +1736,14 @@ function mapOptionsForApi<TApi extends Api>(
|
|
|
1725
1736
|
});
|
|
1726
1737
|
|
|
1727
1738
|
case "google-generative-ai": {
|
|
1728
|
-
// Explicitly disable thinking when reasoning is
|
|
1729
|
-
//
|
|
1739
|
+
// Explicitly disable thinking when reasoning is absent, unsupported, or
|
|
1740
|
+
// replaced by the caller's external scratchpad. Gemini defaults thinking on.
|
|
1730
1741
|
const reasoning = options?.reasoning;
|
|
1731
|
-
if (!reasoning || !model.reasoning) {
|
|
1742
|
+
if (!reasoning || !model.reasoning || options?.disableReasoning || options?.forceReasoningOff) {
|
|
1732
1743
|
return castApi<"google-generative-ai">({
|
|
1733
1744
|
...base,
|
|
1734
1745
|
serviceTier: options?.serviceTier,
|
|
1735
|
-
thinking:
|
|
1746
|
+
thinking: resolveGoogleThinkingOff(model),
|
|
1736
1747
|
toolChoice: mapGoogleToolChoice(options?.toolChoice),
|
|
1737
1748
|
cachedContent: options?.cachedContent,
|
|
1738
1749
|
});
|
|
@@ -1772,7 +1783,7 @@ function mapOptionsForApi<TApi extends Api>(
|
|
|
1772
1783
|
case "google-gemini-cli": {
|
|
1773
1784
|
const reasoning = options?.reasoning;
|
|
1774
1785
|
const toolChoice = mapGoogleToolChoice(options?.toolChoice);
|
|
1775
|
-
if (reasoning && model.reasoning) {
|
|
1786
|
+
if (reasoning && model.reasoning && !options?.disableReasoning && !options?.forceReasoningOff) {
|
|
1776
1787
|
const effort = requireSupportedEffort(model, reasoning);
|
|
1777
1788
|
|
|
1778
1789
|
// Gemini 3+ models use thinkingLevel instead of thinkingBudget
|
|
@@ -1831,13 +1842,14 @@ function mapOptionsForApi<TApi extends Api>(
|
|
|
1831
1842
|
}
|
|
1832
1843
|
|
|
1833
1844
|
case "google-vertex": {
|
|
1834
|
-
// Explicitly disable thinking when reasoning is
|
|
1845
|
+
// Explicitly disable thinking when reasoning is absent, unsupported, or
|
|
1846
|
+
// replaced by the caller's external scratchpad.
|
|
1835
1847
|
const reasoning = options?.reasoning;
|
|
1836
|
-
if (!reasoning || !model.reasoning) {
|
|
1848
|
+
if (!reasoning || !model.reasoning || options?.disableReasoning || options?.forceReasoningOff) {
|
|
1837
1849
|
return castApi<"google-vertex">({
|
|
1838
1850
|
...base,
|
|
1839
1851
|
serviceTier: options?.serviceTier,
|
|
1840
|
-
thinking:
|
|
1852
|
+
thinking: resolveGoogleThinkingOff(model),
|
|
1841
1853
|
toolChoice: mapGoogleToolChoice(options?.toolChoice),
|
|
1842
1854
|
cachedContent: options?.cachedContent,
|
|
1843
1855
|
});
|
package/src/types.ts
CHANGED
|
@@ -479,8 +479,9 @@ export interface StreamOptions {
|
|
|
479
479
|
*/
|
|
480
480
|
statefulResponses?: boolean;
|
|
481
481
|
/**
|
|
482
|
-
*
|
|
483
|
-
*
|
|
482
|
+
* Disable native reasoning when the caller supplies an external scratchpad.
|
|
483
|
+
* OpenAI Responses emits `reasoning: { effort: "none" }`; Anthropic and
|
|
484
|
+
* Google transports use their native thinking-off controls.
|
|
484
485
|
*/
|
|
485
486
|
forceReasoningOff?: boolean;
|
|
486
487
|
/**
|