@oh-my-pi/pi-ai 16.2.5 → 16.2.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 +28 -0
- package/dist/types/auth-storage.d.ts +11 -10
- package/dist/types/providers/__tests__/kimi-code-thinking.test.d.ts +1 -0
- package/dist/types/providers/google-auth.d.ts +8 -0
- package/dist/types/providers/google-interactions.d.ts +65 -0
- package/dist/types/providers/google-shared.d.ts +20 -5
- package/dist/types/providers/google-types.d.ts +5 -0
- package/dist/types/providers/openai-codex/request-transformer.d.ts +1 -1
- package/dist/types/providers/openai-codex-responses.d.ts +1 -1
- package/dist/types/providers/openai-shared.d.ts +3 -3
- package/dist/types/types.d.ts +80 -30
- package/dist/types/utils/leaked-thinking-stream.d.ts +29 -0
- package/package.json +4 -4
- package/src/auth-storage.ts +56 -52
- package/src/providers/__tests__/kimi-code-thinking.test.ts +112 -0
- package/src/providers/anthropic.ts +11 -10
- package/src/providers/google-auth.ts +25 -0
- package/src/providers/google-gemini-cli.ts +90 -41
- package/src/providers/google-interactions.ts +753 -0
- package/src/providers/google-shared.ts +74 -13
- package/src/providers/google-types.ts +5 -1
- package/src/providers/google-vertex.ts +117 -26
- package/src/providers/google.ts +61 -19
- package/src/providers/openai-chat-server.ts +2 -2
- package/src/providers/openai-codex/request-transformer.ts +17 -4
- package/src/providers/openai-codex-responses.ts +23 -5
- package/src/providers/openai-shared.ts +5 -11
- package/src/stream.ts +34 -12
- package/src/types.ts +164 -51
- package/src/usage/google-antigravity.ts +59 -5
- package/src/utils/leaked-thinking-stream.ts +260 -0
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,34 @@
|
|
|
2
2
|
|
|
3
3
|
## [Unreleased]
|
|
4
4
|
|
|
5
|
+
## [16.2.7] - 2026-06-30
|
|
6
|
+
|
|
7
|
+
### Added
|
|
8
|
+
|
|
9
|
+
- Added service tier support for Google Gemini and Vertex AI, including model-specific service tier configurations via ServiceTierByFamily.
|
|
10
|
+
- Added Google Vertex AI Interactions API support for Gemini 3+ models by default, with automatic fallback to :streamGenerateContent and a useInteractionsApi: false option to force standard generation.
|
|
11
|
+
- Added support for explicit Vertex bearer access tokens via GOOGLE_CLOUD_ACCESS_TOKEN or CLOUDSDK_AUTH_ACCESS_TOKEN environment variables.
|
|
12
|
+
|
|
13
|
+
### Changed
|
|
14
|
+
|
|
15
|
+
- Updated service tier logic to use per-provider configurations instead of global scopes.
|
|
16
|
+
- Refactored priority request billing and accounting to better align with specific provider capabilities.
|
|
17
|
+
- Updated API key resolution precedence so explicit environment variables (e.g., GEMINI_API_KEY) override stored or broker-migrated static API keys, while deliberate OAuth logins still take highest precedence.
|
|
18
|
+
|
|
19
|
+
### Fixed
|
|
20
|
+
|
|
21
|
+
- Improved Vertex AI reliability by automatically falling back to global endpoints on 404 errors.
|
|
22
|
+
- Fixed safety setting application for Google Vertex AI models.
|
|
23
|
+
- Fixed Kimi Code's Anthropic-compatible request path to keep thinking enabled and downgrade forced tool choice for Kimi K2.7 Code title generation.
|
|
24
|
+
- Fixed leaked reasoning fences (such as ```thinking or <think>) across all providers by splitting them into structured thinking blocks during streaming.
|
|
25
|
+
- Fixed Codex requests failing with unsupported all_turns errors on older models (gpt-5.1 and gpt-5.3) by gating the reasoning.context: "all_turns" default to gpt-5.4+ models.
|
|
26
|
+
|
|
27
|
+
## [16.2.6] - 2026-06-29
|
|
28
|
+
|
|
29
|
+
### Fixed
|
|
30
|
+
|
|
31
|
+
- Fixed Antigravity usage reporting to correctly infer daily and weekly quota windows from unlabeled reset-only rows, preventing Cloud Code Assist payloads from collapsing these counters into the default category.
|
|
32
|
+
|
|
5
33
|
## [16.2.5] - 2026-06-28
|
|
6
34
|
|
|
7
35
|
### Fixed
|
|
@@ -650,8 +650,8 @@ export declare class AuthStorage {
|
|
|
650
650
|
/**
|
|
651
651
|
* Classify where a provider's auth comes from, following the same precedence
|
|
652
652
|
* as {@link AuthStorage.getApiKey}: runtime override → config override →
|
|
653
|
-
* stored
|
|
654
|
-
*
|
|
653
|
+
* stored OAuth → env var → stored api_key → fallback resolver. Returns
|
|
654
|
+
* undefined when no auth is configured.
|
|
655
655
|
*
|
|
656
656
|
* Compact, structured counterpart to {@link describeCredentialSource}.
|
|
657
657
|
*/
|
|
@@ -778,12 +778,12 @@ export declare class AuthStorage {
|
|
|
778
778
|
peekApiKey(provider: string): Promise<string | undefined>;
|
|
779
779
|
/**
|
|
780
780
|
* Get API key for a provider.
|
|
781
|
-
* Priority:
|
|
781
|
+
* Priority (first match wins):
|
|
782
782
|
* 1. Runtime override (CLI --api-key)
|
|
783
783
|
* 2. Config override (models.yml `providers.<name>.apiKey`)
|
|
784
|
-
* 3.
|
|
785
|
-
* 4.
|
|
786
|
-
* 5.
|
|
784
|
+
* 3. OAuth token from storage (auto-refreshed)
|
|
785
|
+
* 4. Environment variable
|
|
786
|
+
* 5. Stored API key (e.g. a broker-migrated copy) — last resort, so an explicit env var wins
|
|
787
787
|
* 6. Fallback resolver (models.yml custom providers, last-resort)
|
|
788
788
|
*/
|
|
789
789
|
getApiKey(provider: string, sessionId?: string, options?: AuthApiKeyOptions): Promise<string | undefined>;
|
|
@@ -945,12 +945,13 @@ export declare class AuthStorage {
|
|
|
945
945
|
/**
|
|
946
946
|
* Describe where the active credential for a provider came from.
|
|
947
947
|
*
|
|
948
|
-
*
|
|
948
|
+
* Mirrors {@link AuthStorage.getApiKey} precedence, highest first:
|
|
949
949
|
* 1. Runtime override (`--api-key`).
|
|
950
950
|
* 2. Config override (`models.yml` `providers.<name>.apiKey`).
|
|
951
|
-
* 3. Stored credential
|
|
952
|
-
*
|
|
953
|
-
*
|
|
951
|
+
* 3. Stored OAuth credential.
|
|
952
|
+
* 4. Env var — overrides a stored static api_key (e.g. a stale broker copy).
|
|
953
|
+
* 5. Stored api_key credential.
|
|
954
|
+
* 6. Fallback resolver.
|
|
954
955
|
*
|
|
955
956
|
* The string is purely informational; consumers must not parse it.
|
|
956
957
|
*/
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -22,3 +22,11 @@ export declare function getVertexAccessToken(options?: {
|
|
|
22
22
|
}): Promise<string>;
|
|
23
23
|
/** Test seam: clears every cached token. */
|
|
24
24
|
export declare function __resetVertexTokenCache(): void;
|
|
25
|
+
/**
|
|
26
|
+
* Sync best-effort probe for a usable Vertex bearer credential source — an explicit access-token
|
|
27
|
+
* env var, `GOOGLE_APPLICATION_CREDENTIALS`, a user ADC file, or a GCP runtime whose metadata
|
|
28
|
+
* server can mint ADC (GCE/Cloud Run/App Engine/Functions). Lets callers prefer the bearer
|
|
29
|
+
* Interactions transport only when ADC is actually reachable, without paying the async
|
|
30
|
+
* metadata-probe cost for API-key-only setups.
|
|
31
|
+
*/
|
|
32
|
+
export declare function hasVertexBearerCredentialsHint(): boolean;
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import type { Context, FetchImpl, Model, ProviderSessionState } from "../types";
|
|
2
|
+
import { AssistantMessageEventStream } from "../utils/event-stream";
|
|
3
|
+
import { type GoogleSharedStreamOptions } from "./google-shared";
|
|
4
|
+
type GoogleInteractionsApi = "google-generative-ai" | "google-vertex";
|
|
5
|
+
/** Provider session state storing the last Gemini Interactions response id. */
|
|
6
|
+
export interface GoogleInteractionsProviderSessionState extends ProviderSessionState {
|
|
7
|
+
lastInteractionId?: string;
|
|
8
|
+
}
|
|
9
|
+
/** Conversation anchor for continuing an Interactions turn from a prior assistant response. */
|
|
10
|
+
export interface InteractionAnchor {
|
|
11
|
+
id?: string;
|
|
12
|
+
messageIndex?: number;
|
|
13
|
+
}
|
|
14
|
+
/** Provider-specific URL, headers, and fetch implementation for an Interactions request. */
|
|
15
|
+
export interface GoogleInteractionsPlan {
|
|
16
|
+
url: string;
|
|
17
|
+
headers: Record<string, string>;
|
|
18
|
+
fetch?: FetchImpl;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Streams Gemini Interactions API model-mode responses for direct Google and Vertex providers.
|
|
22
|
+
*
|
|
23
|
+
* `fallback`, when supplied, is the legacy `:streamGenerateContent` stream factory. It runs
|
|
24
|
+
* transparently — forwarding its events into this stream — when the Interactions attempt fails
|
|
25
|
+
* before any content is emitted with a signal that the model/endpoint does not support
|
|
26
|
+
* Interactions (HTTP 404/400). Provide it only for auto-selected Interactions requests so an
|
|
27
|
+
* explicit `useInteractionsApi: true` still surfaces failures.
|
|
28
|
+
*/
|
|
29
|
+
export declare function streamGoogleInteractions<T extends GoogleInteractionsApi>(args: {
|
|
30
|
+
model: Model<T>;
|
|
31
|
+
context: Context;
|
|
32
|
+
options: GoogleSharedStreamOptions | undefined;
|
|
33
|
+
api: T;
|
|
34
|
+
anchor: InteractionAnchor;
|
|
35
|
+
state: GoogleInteractionsProviderSessionState | undefined;
|
|
36
|
+
prepare: () => GoogleInteractionsPlan | Promise<GoogleInteractionsPlan>;
|
|
37
|
+
fallback?: () => AssistantMessageEventStream;
|
|
38
|
+
}): AssistantMessageEventStream;
|
|
39
|
+
/**
|
|
40
|
+
* Whether a model is served by the Gemini Interactions API. Interactions is a Gemini 3-era
|
|
41
|
+
* transport, so the catalog subset that supports it is Gemini 3.0+. Older Gemini and non-Gemini
|
|
42
|
+
* ids keep `:streamGenerateContent`, which covers the full catalog.
|
|
43
|
+
*/
|
|
44
|
+
export declare function modelSupportsInteractions(model: Pick<Model, "id">): boolean;
|
|
45
|
+
/**
|
|
46
|
+
* Resolves whether a Google provider call should use Interactions and which lineage anchor to send.
|
|
47
|
+
*
|
|
48
|
+
* Precedence: explicit `useInteractionsApi: false` always wins (force generateContent); otherwise
|
|
49
|
+
* Interactions engages when explicitly requested, when continuing a stored interaction
|
|
50
|
+
* (`previousInteractionId`/assistant lineage/session state), or when `autoEligible` (the
|
|
51
|
+
* zero-config default for the capable model subset on the official endpoint). `auto` flags the
|
|
52
|
+
* last case for the caller — it is the only mode that wires up the generateContent fallback.
|
|
53
|
+
*/
|
|
54
|
+
export declare function resolveInteractionDispatch(args: {
|
|
55
|
+
context: Context;
|
|
56
|
+
options: GoogleSharedStreamOptions | undefined;
|
|
57
|
+
provider: string;
|
|
58
|
+
autoEligible: boolean;
|
|
59
|
+
}): {
|
|
60
|
+
useInteractions: boolean;
|
|
61
|
+
auto: boolean;
|
|
62
|
+
anchor: InteractionAnchor;
|
|
63
|
+
state: GoogleInteractionsProviderSessionState | undefined;
|
|
64
|
+
};
|
|
65
|
+
export {};
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Shared utilities for Google Generative AI and Google Cloud Code Assist providers.
|
|
3
3
|
*/
|
|
4
|
-
import type { AssistantMessage, Context, FetchImpl, Model, StopReason, StreamOptions, TextContent, ThinkingContent, Tool, ToolCall } from "../types";
|
|
4
|
+
import type { AssistantMessage, Context, FetchImpl, Model, ServiceTier, StopReason, StreamOptions, TextContent, ThinkingContent, Tool, ToolCall } from "../types";
|
|
5
5
|
import { AssistantMessageEventStream } from "../utils/event-stream";
|
|
6
6
|
import { normalizeSchemaForGoogle } from "../utils/schema";
|
|
7
7
|
import type { Content, FinishReason, FunctionCallingConfigMode, GenerateContentParameters, GenerateContentResponse, Part } from "./google-types";
|
|
@@ -33,6 +33,21 @@ export interface GoogleSharedStreamOptions extends StreamOptions {
|
|
|
33
33
|
budgetTokens?: number;
|
|
34
34
|
level?: GoogleThinkingLevel;
|
|
35
35
|
};
|
|
36
|
+
/** Gemini/Vertex serving tier (`flex`/`priority`); other values are omitted. */
|
|
37
|
+
serviceTier?: ServiceTier;
|
|
38
|
+
/**
|
|
39
|
+
* Continues a Gemini Interactions API conversation from a stored interaction.
|
|
40
|
+
* When set on the direct Google provider, the request uses `/interactions`
|
|
41
|
+
* with `previous_interaction_id` instead of the legacy generateContent stream.
|
|
42
|
+
*/
|
|
43
|
+
previousInteractionId?: string;
|
|
44
|
+
/**
|
|
45
|
+
* Uses the Gemini Interactions API for direct Google requests, storing the
|
|
46
|
+
* returned interaction id on the assistant response for follow-up turns.
|
|
47
|
+
*/
|
|
48
|
+
useInteractionsApi?: boolean;
|
|
49
|
+
/** Overrides Interactions API request storage; default is the API default (`true`). */
|
|
50
|
+
storeInteraction?: boolean;
|
|
36
51
|
}
|
|
37
52
|
/**
|
|
38
53
|
* Determines whether a streamed Gemini `Part` should be treated as "thinking".
|
|
@@ -60,10 +75,6 @@ export declare function isThinkingPart(part: Pick<Part, "thought" | "thoughtSign
|
|
|
60
75
|
* a signature from being overwritten with `undefined` within the same streamed block.
|
|
61
76
|
*/
|
|
62
77
|
export declare function retainThoughtSignature(existing: string | undefined, incoming: string | undefined): string | undefined;
|
|
63
|
-
/**
|
|
64
|
-
* Claude models via Google APIs require explicit tool call IDs in function calls/responses.
|
|
65
|
-
*/
|
|
66
|
-
export declare function requiresToolCallId(modelId: string): boolean;
|
|
67
78
|
/**
|
|
68
79
|
* Convert internal messages to Gemini Content[] format.
|
|
69
80
|
*/
|
|
@@ -127,6 +138,8 @@ export declare function pushToolCallEvents(toolCall: ToolCall, contentIndex: num
|
|
|
127
138
|
* `text_start` / `thinking_start` event. `onBeforeStartEvent` lets the SSE consumer
|
|
128
139
|
* inject its `ensureStarted()` first-token side effect into the canonical event order.
|
|
129
140
|
*/
|
|
141
|
+
export declare function startTextOrThinkingBlock(isThinking: true, output: AssistantMessage, stream: AssistantMessageEventStream, onBeforeStartEvent?: () => void): ThinkingContent;
|
|
142
|
+
export declare function startTextOrThinkingBlock(isThinking: false, output: AssistantMessage, stream: AssistantMessageEventStream, onBeforeStartEvent?: () => void): TextContent;
|
|
130
143
|
export declare function startTextOrThinkingBlock(isThinking: boolean, output: AssistantMessage, stream: AssistantMessageEventStream, onBeforeStartEvent?: () => void): TextContent | ThinkingContent;
|
|
131
144
|
/**
|
|
132
145
|
* Drives the chunked `generateContentStream` iterator into an `AssistantMessage` and
|
|
@@ -178,6 +191,8 @@ export interface GoogleGenAIRequestPlan {
|
|
|
178
191
|
url: string;
|
|
179
192
|
headers: Record<string, string>;
|
|
180
193
|
fetch?: FetchImpl;
|
|
194
|
+
/** Optional URL retried once when {@link url} returns 404 (regional Vertex endpoint missing a global-only model). */
|
|
195
|
+
fallbackUrl?: string;
|
|
181
196
|
}
|
|
182
197
|
export declare function streamGoogleGenAI<T extends "google-generative-ai" | "google-vertex">(args: {
|
|
183
198
|
model: Model<T>;
|
|
@@ -106,6 +106,11 @@ export interface GenerateContentConfig {
|
|
|
106
106
|
safetySettings?: Array<Record<string, unknown>>;
|
|
107
107
|
cachedContent?: string;
|
|
108
108
|
thinkingConfig?: ThinkingConfig;
|
|
109
|
+
/**
|
|
110
|
+
* Gemini/Vertex serving tier. Serialized to the request body root as
|
|
111
|
+
* `serviceTier` (camelCase) by the transformer in `google-shared.ts`.
|
|
112
|
+
*/
|
|
113
|
+
serviceTier?: "auto" | "default" | "flex" | "scale" | "priority";
|
|
109
114
|
abortSignal?: AbortSignal;
|
|
110
115
|
}
|
|
111
116
|
/** Top-level argument to `generateContentStream`. */
|
|
@@ -9,7 +9,7 @@ export interface ReasoningConfig {
|
|
|
9
9
|
export interface CodexRequestOptions {
|
|
10
10
|
reasoningEffort?: ReasoningConfig["effort"];
|
|
11
11
|
reasoningSummary?: ReasoningConfig["summary"] | null;
|
|
12
|
-
/** Explicit `reasoning.context` override; defaults to `all_turns`
|
|
12
|
+
/** Explicit `reasoning.context` override; defaults to `all_turns` when unset. The `all_turns` value is gated to gpt-5.4+ Codex models — older ids reject it, so it is suppressed and `context` omitted. */
|
|
13
13
|
reasoningContext?: CodexReasoningContext;
|
|
14
14
|
textVerbosity?: "low" | "medium" | "high";
|
|
15
15
|
include?: string[];
|
|
@@ -4,7 +4,7 @@ import type { ResponseInput } from "./openai-responses-wire";
|
|
|
4
4
|
export interface OpenAICodexResponsesOptions extends StreamOptions {
|
|
5
5
|
reasoning?: "none" | "minimal" | "low" | "medium" | "high" | "xhigh";
|
|
6
6
|
reasoningSummary?: "auto" | "concise" | "detailed" | null;
|
|
7
|
-
/** `reasoning.context` replay scope; defaults to `all_turns`
|
|
7
|
+
/** `reasoning.context` replay scope; defaults to `all_turns` when unset. The `all_turns` value is gated to gpt-5.4+ Codex models — older ids reject it, so it is suppressed and `context` omitted. */
|
|
8
8
|
reasoningContext?: CodexReasoningContext;
|
|
9
9
|
textVerbosity?: "low" | "medium" | "high";
|
|
10
10
|
include?: string[];
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { OpenAICompat, OpenAIReasoningDisableMode, OpenAIStreamMarkupHealingPattern, OpenRouterRouting, ResolvedOpenAICompat, ResolvedOpenAIResponsesCompat, ResolvedOpenAISharedCompat, VercelGatewayRouting } from "@oh-my-pi/pi-catalog/types";
|
|
2
|
-
import { type Api, type AssistantMessage, type CacheRetention, type Context, type ImageContent, type Message, type MessageAttribution, type Model, type Provider, type
|
|
2
|
+
import { type Api, type AssistantMessage, type CacheRetention, type Context, type ImageContent, type Message, type MessageAttribution, type Model, type Provider, type ServiceTier, type StopReason, type StreamOptions, type TextContent, type TextSignatureV1, type ThinkingContent, type Tool, type ToolCall, type ToolResultMessage } from "../types";
|
|
3
3
|
import { kStreamingLastParseLen, kStreamingPartialJson } from "../utils/block-symbols";
|
|
4
4
|
import type { AssistantMessageEventStream } from "../utils/event-stream";
|
|
5
5
|
import type { CapturedHttpErrorResponse } from "../utils/http-inspector";
|
|
@@ -55,7 +55,7 @@ export interface OpenAIRequestSetup {
|
|
|
55
55
|
}
|
|
56
56
|
export declare function resolveOpenAIRequestSetup(model: OpenAIRequestSetupModel, options: OpenAIRequestSetupOptions): OpenAIRequestSetup;
|
|
57
57
|
export declare function applyOpenAIServiceTier(params: {
|
|
58
|
-
service_tier?:
|
|
58
|
+
service_tier?: ServiceTier | null | undefined;
|
|
59
59
|
}, serviceTier: ServiceTier | null | undefined, provider: Provider | undefined): void;
|
|
60
60
|
/**
|
|
61
61
|
* Adjust resolved cost by the service tier OpenAI actually billed — parity with
|
|
@@ -207,7 +207,7 @@ export type OpenAICompletionsParams = Omit<ChatCompletionCreateParamsStreaming,
|
|
|
207
207
|
enabled: false;
|
|
208
208
|
};
|
|
209
209
|
reasoning_effort?: string | null;
|
|
210
|
-
service_tier?:
|
|
210
|
+
service_tier?: ServiceTier;
|
|
211
211
|
tool_stream?: boolean;
|
|
212
212
|
provider?: OpenAICompat["openRouterRouting"];
|
|
213
213
|
providerOptions?: {
|
package/dist/types/types.d.ts
CHANGED
|
@@ -73,48 +73,82 @@ export type ToolChoice = "auto" | "none" | "any" | "required" | {
|
|
|
73
73
|
};
|
|
74
74
|
export type CacheRetention = "none" | "short" | "long";
|
|
75
75
|
/**
|
|
76
|
-
* Service tier hint for processing priority / cost control.
|
|
76
|
+
* Service tier hint for processing priority / cost control. These are the
|
|
77
|
+
* values providers consume on the wire:
|
|
77
78
|
*
|
|
78
|
-
*
|
|
79
|
-
*
|
|
80
|
-
* (
|
|
81
|
-
* `
|
|
79
|
+
* - OpenAI / OpenAI-Codex: sent verbatim as the `service_tier` field
|
|
80
|
+
* (`flex`/`scale`/`priority`).
|
|
81
|
+
* - Google (Gemini API + Vertex AI): sent as the top-level `serviceTier`
|
|
82
|
+
* field (`flex`/`priority`).
|
|
83
|
+
* - OpenRouter: passed through as `service_tier`; OpenRouter realizes it for
|
|
84
|
+
* the OpenAI- and Google-family upstreams it supports and ignores it
|
|
85
|
+
* otherwise.
|
|
86
|
+
* - Direct Anthropic: `"priority"` is translated into `speed: "fast"` plus the
|
|
87
|
+
* fast-mode beta on supported Opus models. Other tiers are ignored.
|
|
82
88
|
*
|
|
83
|
-
*
|
|
84
|
-
*
|
|
85
|
-
|
|
86
|
-
|
|
89
|
+
* Per-family scoping is expressed by {@link ServiceTierByFamily}, not by
|
|
90
|
+
* scoped sentinel values — see {@link serviceTierFamily}.
|
|
91
|
+
*/
|
|
92
|
+
export type ServiceTier = "auto" | "default" | "flex" | "scale" | "priority";
|
|
93
|
+
/** Provider families that expose an independent service-tier knob. */
|
|
94
|
+
export type ServiceTierFamily = "openai" | "anthropic" | "google";
|
|
95
|
+
/**
|
|
96
|
+
* Per-family service-tier selection. A request consults only the entry for the
|
|
97
|
+
* family its model belongs to (see {@link resolveModelServiceTier}), so a user
|
|
98
|
+
* can opt one family into priority without affecting the others when switching
|
|
99
|
+
* models mid-session.
|
|
100
|
+
*/
|
|
101
|
+
export type ServiceTierByFamily = Partial<Record<ServiceTierFamily, ServiceTier>>;
|
|
102
|
+
/**
|
|
103
|
+
* Classify a model into the service-tier family whose knob governs it, or
|
|
104
|
+
* `undefined` when the model exposes no serving-priority control.
|
|
87
105
|
*
|
|
88
|
-
*
|
|
89
|
-
*
|
|
106
|
+
* OpenRouter models are classified by id namespace (`anthropic/`, `google/`,
|
|
107
|
+
* `openai/`); Claude on Bedrock/Vertex (api `anthropic-messages`) is the
|
|
108
|
+
* anthropic family even though its provider is `amazon-bedrock`/`google-vertex`.
|
|
90
109
|
*/
|
|
91
|
-
export
|
|
92
|
-
/** Resolved tier — one of the values that providers actually consume on the wire. */
|
|
93
|
-
export type ResolvedServiceTier = Exclude<ServiceTier, "openai-only" | "claude-only">;
|
|
110
|
+
export declare function serviceTierFamily(model: Pick<Model, "provider" | "api" | "id">): ServiceTierFamily | undefined;
|
|
94
111
|
/**
|
|
95
|
-
*
|
|
96
|
-
*
|
|
97
|
-
* collapse to `undefined`; unscoped values pass through unchanged.
|
|
112
|
+
* Reduce a per-family tier map to the single wire tier for `model` — the entry
|
|
113
|
+
* for the model's family, or `undefined` when the model has no family.
|
|
98
114
|
*/
|
|
99
|
-
export declare function
|
|
115
|
+
export declare function resolveModelServiceTier(tiers: ServiceTierByFamily | null | undefined, model: Pick<Model, "provider" | "api" | "id">): ServiceTier | undefined;
|
|
100
116
|
/**
|
|
101
|
-
* True when the
|
|
102
|
-
*
|
|
103
|
-
* accept `flex`/`
|
|
104
|
-
* Priority serving path
|
|
105
|
-
*
|
|
106
|
-
* providers, and scope mismatches all return false.
|
|
117
|
+
* True when the tier should be sent on the wire as the provider's service-tier
|
|
118
|
+
* request field. OpenAI / OpenAI-Codex accept `flex`/`scale`/`priority`; Google
|
|
119
|
+
* (Gemini API + Vertex) and OpenRouter accept `flex`/`priority`; Fireworks
|
|
120
|
+
* Serverless realizes only its Priority serving path. Anthropic is absent — it
|
|
121
|
+
* realizes `priority` via `speed: "fast"`, not a service-tier field.
|
|
107
122
|
*/
|
|
108
123
|
export declare function shouldSendServiceTier(serviceTier: ServiceTier | null | undefined, provider: Provider | undefined): boolean;
|
|
109
124
|
/**
|
|
110
|
-
*
|
|
111
|
-
*
|
|
112
|
-
*
|
|
113
|
-
*
|
|
125
|
+
* True when `priority` will actually be realized on the wire for `model`.
|
|
126
|
+
* Direct Anthropic realizes fast mode; OpenAI/Google/Fireworks emit the
|
|
127
|
+
* service-tier field; OpenRouter realizes it only for its OpenAI- and
|
|
128
|
+
* Google-family upstreams. Bedrock/Vertex Claude and OpenRouter Anthropic
|
|
129
|
+
* models do not realize priority and return `false`.
|
|
130
|
+
*/
|
|
131
|
+
export declare function realizesPriorityServiceTier(serviceTier: ServiceTier | null | undefined, model: Pick<Model, "provider" | "api" | "id">): boolean;
|
|
132
|
+
/**
|
|
133
|
+
* Premium-request weight contributed by a priority request to a provider that
|
|
134
|
+
* realizes it and bills extra. Mirrors GitHub Copilot's `premiumRequests`
|
|
135
|
+
* accounting so the "premium requests" stat aggregates priority traffic across
|
|
136
|
+
* the OpenAI family, direct Anthropic fast mode, and Google priority.
|
|
114
137
|
*
|
|
115
|
-
* Returns 1
|
|
138
|
+
* Returns 1 only when priority is actually realized on the wire for `model`
|
|
139
|
+
* (see {@link realizesPriorityServiceTier}) and the provider bills it as a
|
|
140
|
+
* premium request. OpenRouter is excluded — it bills per its own pricing, not
|
|
141
|
+
* Copilot-premium semantics — as are Bedrock/Vertex Claude, where priority is
|
|
142
|
+
* silently dropped.
|
|
143
|
+
*/
|
|
144
|
+
export declare function getPriorityPremiumRequests(serviceTier: ServiceTier | null | undefined, model: Pick<Model, "provider" | "api" | "id">): number;
|
|
145
|
+
/**
|
|
146
|
+
* Coerce a persisted service-tier value to a {@link ServiceTierByFamily}. Newer
|
|
147
|
+
* sessions store the family map directly; legacy sessions stored a single
|
|
148
|
+
* scalar — `"priority"` applied everywhere, `"openai-only"`/`"claude-only"`
|
|
149
|
+
* scoped to one family, and the remaining values were OpenAI-only semantics.
|
|
116
150
|
*/
|
|
117
|
-
export declare function
|
|
151
|
+
export declare function coerceServiceTierByFamily(value: unknown): ServiceTierByFamily | undefined;
|
|
118
152
|
export interface ProviderSessionState {
|
|
119
153
|
close(): void;
|
|
120
154
|
}
|
|
@@ -204,6 +238,22 @@ export interface StreamOptions {
|
|
|
204
238
|
* Providers can use this to persist transport/session state between turns.
|
|
205
239
|
*/
|
|
206
240
|
providerSessionState?: Map<string, ProviderSessionState>;
|
|
241
|
+
/**
|
|
242
|
+
* Force Gemini model-mode Interactions API transport for providers that support it.
|
|
243
|
+
* When unset, those providers may still use Interactions to continue known
|
|
244
|
+
* server-side conversation lineage via `previousInteractionId` or stored state.
|
|
245
|
+
*/
|
|
246
|
+
useInteractionsApi?: boolean;
|
|
247
|
+
/**
|
|
248
|
+
* Whether supported Interactions transports should store server-side conversation
|
|
249
|
+
* state and return response ids for follow-up turns. Defaults to true.
|
|
250
|
+
*/
|
|
251
|
+
storeInteraction?: boolean;
|
|
252
|
+
/**
|
|
253
|
+
* Explicit Interactions response id to continue. Mutually exclusive with
|
|
254
|
+
* `storeInteraction: false` because the follow-up itself must be storable.
|
|
255
|
+
*/
|
|
256
|
+
previousInteractionId?: string;
|
|
207
257
|
/**
|
|
208
258
|
* Optional per-provider concurrent request cap for LLM stream calls. Keys are
|
|
209
259
|
* provider ids (`model.provider`); positive numeric values cap in-flight
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Central live healing for leaked reasoning markup in the visible text channel.
|
|
3
|
+
*
|
|
4
|
+
* Some providers emit their canonical reasoning idioms (` ```thinking `,
|
|
5
|
+
* `<think>`, Gemma/Harmony channels, …) into the *visible* text stream instead
|
|
6
|
+
* of a structured thinking part. {@link wrapLeakedThinkingStream} re-projects any
|
|
7
|
+
* provider stream into a fresh {@link AssistantMessageEventStream}, splitting the
|
|
8
|
+
* leaked fences out into proper `thinking` blocks *live* as deltas arrive — so
|
|
9
|
+
* every provider gets the same healing, not just the three with provider-local
|
|
10
|
+
* {@link StreamMarkupHealing} loops.
|
|
11
|
+
*
|
|
12
|
+
* The healing is idempotent: a second pass over already-clean text finds no
|
|
13
|
+
* fences, so wrapping a provider that already heals (or wrapping twice) is a
|
|
14
|
+
* harmless pass-through. Signatures are load-bearing for Google/Gemini/Vertex
|
|
15
|
+
* thought round-tripping, so text sub-blocks carry the source `textSignature`,
|
|
16
|
+
* forwarded thinking blocks their `thinkingSignature`, and forwarded tool calls
|
|
17
|
+
* their `thoughtSignature`.
|
|
18
|
+
*
|
|
19
|
+
* Modeled on {@link wrapInbandToolStream} / `InbandStreamProjector` in
|
|
20
|
+
* `../dialect/owned-stream.ts`, minus all in-band tool-call grammar: tool-call
|
|
21
|
+
* events are forwarded verbatim.
|
|
22
|
+
*/
|
|
23
|
+
import { AssistantMessageEventStream } from "./event-stream";
|
|
24
|
+
/**
|
|
25
|
+
* Wrap a provider stream so leaked reasoning fences are healed into thinking
|
|
26
|
+
* blocks live, for every provider. Returns a new stream that re-projects the
|
|
27
|
+
* inner one; the inner stream is fully consumed.
|
|
28
|
+
*/
|
|
29
|
+
export declare function wrapLeakedThinkingStream(inner: AssistantMessageEventStream): AssistantMessageEventStream;
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"type": "module",
|
|
3
3
|
"name": "@oh-my-pi/pi-ai",
|
|
4
|
-
"version": "16.2.
|
|
4
|
+
"version": "16.2.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,9 +38,9 @@
|
|
|
38
38
|
},
|
|
39
39
|
"dependencies": {
|
|
40
40
|
"@bufbuild/protobuf": "^2.12.0",
|
|
41
|
-
"@oh-my-pi/pi-catalog": "16.2.
|
|
42
|
-
"@oh-my-pi/pi-utils": "16.2.
|
|
43
|
-
"@oh-my-pi/pi-wire": "16.2.
|
|
41
|
+
"@oh-my-pi/pi-catalog": "16.2.7",
|
|
42
|
+
"@oh-my-pi/pi-utils": "16.2.7",
|
|
43
|
+
"@oh-my-pi/pi-wire": "16.2.7",
|
|
44
44
|
"arktype": "^2.2.0",
|
|
45
45
|
"zod": "^4"
|
|
46
46
|
},
|