@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
|
@@ -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;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { FetchImpl } from "../types";
|
|
1
2
|
import type { AwsCredentials } from "./aws-sigv4";
|
|
2
3
|
export type AwsIniFile = Record<string, Record<string, string>>;
|
|
3
4
|
export interface AwsCredentialSourceOptions {
|
|
@@ -16,4 +17,8 @@ export declare function classifyAwsProfileCapability(profile: string, credential
|
|
|
16
17
|
export declare function hasResolvableAwsProfileSource(options?: AwsCredentialSourceOptions & {
|
|
17
18
|
onScan?: () => void;
|
|
18
19
|
}, now?: number): boolean;
|
|
20
|
+
/** Probe only the IMDSv2 token and role endpoints; never request role credentials for status. */
|
|
21
|
+
export declare function hasAwsInstanceProfileCredentialSource(options?: {
|
|
22
|
+
fetch?: FetchImpl;
|
|
23
|
+
}): Promise<boolean>;
|
|
19
24
|
export declare function isValidBedrockBearerToken(token: string | undefined): token is string;
|
|
@@ -14,8 +14,15 @@
|
|
|
14
14
|
* (default 60s). Concurrent callers waiting on a refresh share the same in-flight promise.
|
|
15
15
|
*/
|
|
16
16
|
import type { FetchImpl } from "../types";
|
|
17
|
+
export type VertexCredentialSource = "explicit-file" | "default-file" | "metadata-server";
|
|
18
|
+
/** Match the region-label constraint used before Vertex interpolates a location into the request host. */
|
|
19
|
+
export declare function isValidVertexLocation(location: string): boolean;
|
|
17
20
|
/** Test seam: the ADC credentials file path as resolved from trusted env. */
|
|
18
21
|
export declare function resolveAdcCredentialsPathForTest(): string | undefined;
|
|
22
|
+
/** Resolve the source of a currently usable ADC credential without acquiring an access token. */
|
|
23
|
+
export declare function getVertexCredentialSource(options?: {
|
|
24
|
+
fetch?: FetchImpl;
|
|
25
|
+
}): Promise<VertexCredentialSource | undefined>;
|
|
19
26
|
/**
|
|
20
27
|
* Returns a Bearer access token suitable for the `Authorization` header on Vertex AI calls.
|
|
21
28
|
* The token is cached in module scope and refreshed `GOOGLE_VERTEX_REFRESH_SKEW_MS` ms before it expires.
|
|
@@ -29,15 +29,20 @@ export declare const ANTIGRAVITY_SYSTEM_INSTRUCTION = "You are Antigravity, a po
|
|
|
29
29
|
/**
|
|
30
30
|
* Antigravity / Cloud Code Assist user agent.
|
|
31
31
|
*
|
|
32
|
-
*
|
|
33
|
-
*
|
|
32
|
+
* Field-evidence-based default: A/B/A test on Windows+Ultra (subscriber) confirmed that
|
|
33
|
+
* 'antigravity/cli/1.3.4 (os_type=darwin; arch=arm64; aidev_client; auth_method=oauth)'
|
|
34
|
+
* unlocks Gemini 4 Argon (low/medium/high) and Gemini 3.8 Flash (low/medium/high) models,
|
|
35
|
+
* plus Opus 5.5. Reverting to 'antigravity-ide' hides Argon models again. Pro accounts
|
|
36
|
+
* receive 'gemini-4-argon-disabled' with disabled:true, confirming the UA gates model
|
|
37
|
+
* visibility by account tier. The darwin/arm64 values were tested on Windows and worked,
|
|
38
|
+
* suggesting this is not platform-specific but rather a client identity string.
|
|
34
39
|
*
|
|
35
|
-
*
|
|
36
|
-
*
|
|
40
|
+
* Historical note: Disassembly (0x5ecb1dd) showed the IDE binary loads 'antigravity-ide';
|
|
41
|
+
* this appears to be outdated or a fallback for older clients.
|
|
37
42
|
*
|
|
38
|
-
*
|
|
43
|
+
* Overridable via PI_AI_ANTIGRAVITY_USER_AGENT environment variable.
|
|
39
44
|
*/
|
|
40
|
-
export declare
|
|
45
|
+
export declare function getAntigravityUserAgent(): string;
|
|
41
46
|
export declare const getAntigravityRequestHeaders: () => {
|
|
42
47
|
"User-Agent": string;
|
|
43
48
|
};
|
|
@@ -1707,7 +1707,8 @@ export declare const openaiChatRequestSchema: z.ZodObject<{
|
|
|
1707
1707
|
flex: "flex";
|
|
1708
1708
|
priority: "priority";
|
|
1709
1709
|
scale: "scale";
|
|
1710
|
-
|
|
1710
|
+
ultrafast: "ultrafast";
|
|
1711
|
+
}>>>, z.ZodTransform<NonNullable<"auto" | "default" | "flex" | "priority" | "scale" | "ultrafast"> | undefined, "auto" | "default" | "flex" | "priority" | "scale" | "ultrafast" | null | undefined>>;
|
|
1711
1712
|
metadata: z.ZodPipe<z.ZodOptional<z.ZodNullable<z.ZodRecord<z.ZodString, z.ZodUnknown>>>, z.ZodTransform<Record<string, unknown> | undefined, Record<string, unknown> | null | undefined>>;
|
|
1712
1713
|
logprobs: z.ZodOptional<z.ZodUnknown>;
|
|
1713
1714
|
top_logprobs: z.ZodOptional<z.ZodUnknown>;
|
|
@@ -33,7 +33,7 @@ export interface OpenAICompletionsOptions extends StreamOptions {
|
|
|
33
33
|
repetitionGuard?: RepetitionGuardOptions;
|
|
34
34
|
}
|
|
35
35
|
export declare const streamOpenAICompletions: StreamFunction<"openai-completions">;
|
|
36
|
-
export declare function parseChunkUsage(rawUsage: object, model: Model<"openai-completions">, premiumRequests: number | undefined): AssistantMessage["usage"];
|
|
36
|
+
export declare function parseChunkUsage(rawUsage: object, model: Model<"openai-completions">, premiumRequests: number | undefined, serviceTier?: ServiceTier): AssistantMessage["usage"];
|
|
37
37
|
export declare function convertMessages(model: Model<"openai-completions">, context: Context, compat: ResolvedOpenAICompat): ChatCompletionMessageParam[];
|
|
38
38
|
/**
|
|
39
39
|
* Detect compatibility settings from provider and baseUrl for known providers.
|
|
@@ -43,6 +43,7 @@ export declare function appendResponsesToolResultMessages<TApi extends Api>(mess
|
|
|
43
43
|
export interface ProcessResponsesStreamOptions {
|
|
44
44
|
onFirstToken?: () => void;
|
|
45
45
|
onOutputItemDone?: (item: ResponseOutputItem) => void;
|
|
46
|
+
serviceTier?: ServiceTier;
|
|
46
47
|
}
|
|
47
48
|
export declare function processResponsesStream<TApi extends Api>(openaiStream: AsyncIterable<OpenAI.Responses.ResponseStreamEvent>, output: AssistantMessage, stream: AssistantMessageEventStream, model: Model<TApi>, options?: ProcessResponsesStreamOptions): Promise<boolean>;
|
|
48
49
|
/**
|
|
@@ -99,7 +100,7 @@ type CommonSamplingOptions = Pick<StreamOptions, "temperature" | "topP" | "topK"
|
|
|
99
100
|
* Apply the common `StreamOptions` → Responses sampling-parameter mapping (max output tokens,
|
|
100
101
|
* temperature, top-p/k, min-p, presence/repetition penalties, service tier). Mutates `params`.
|
|
101
102
|
*/
|
|
102
|
-
export declare function applyCommonResponsesSamplingParams<P extends CommonResponsesParams>(params: P, options: CommonSamplingOptions | undefined, provider: string, supportsServiceTier?: boolean): void;
|
|
103
|
+
export declare function applyCommonResponsesSamplingParams<P extends CommonResponsesParams>(params: P, options: CommonSamplingOptions | undefined, provider: string, supportsServiceTier?: boolean, modelSupportsUltrafastTier?: boolean): void;
|
|
103
104
|
type ReasoningOptions = {
|
|
104
105
|
reasoning?: string;
|
|
105
106
|
reasoningSummary?: "auto" | "detailed" | "concise" | null;
|
package/dist/types/stream.d.ts
CHANGED
|
@@ -1,7 +1,19 @@
|
|
|
1
1
|
import type { Effort } from "./model-thinking";
|
|
2
2
|
import type { AnthropicOptions } from "./providers/anthropic";
|
|
3
|
-
import type { Api, AssistantMessage, Context, Model, OptionsForApi, SimpleStreamOptions, ToolChoice } from "./types";
|
|
3
|
+
import type { Api, AssistantMessage, Context, FetchImpl, Model, OptionsForApi, SimpleStreamOptions, ToolChoice } from "./types";
|
|
4
4
|
import { AssistantMessageEventStream } from "./utils/event-stream";
|
|
5
|
+
export type EnvApiKeyCredentialSource = {
|
|
6
|
+
kind: "environment";
|
|
7
|
+
name: string;
|
|
8
|
+
} | {
|
|
9
|
+
kind: "google-adc";
|
|
10
|
+
source: "explicit-file" | "default-file" | "metadata-server";
|
|
11
|
+
} | {
|
|
12
|
+
kind: "aws";
|
|
13
|
+
source: "bearer-token" | "environment-credentials" | "profile" | "instance-profile";
|
|
14
|
+
} | {
|
|
15
|
+
kind: "unknown";
|
|
16
|
+
};
|
|
5
17
|
/**
|
|
6
18
|
* Get API key for provider from known environment variables, e.g. OPENAI_API_KEY.
|
|
7
19
|
*
|
|
@@ -9,6 +21,26 @@ import { AssistantMessageEventStream } from "./utils/event-stream";
|
|
|
9
21
|
* loaded into $env for app/tool execution, but must not silently fund GJC model requests.
|
|
10
22
|
*/
|
|
11
23
|
export declare function getEnvApiKey(provider: string): string | undefined;
|
|
24
|
+
/**
|
|
25
|
+
* List configured environment variable names consulted for a provider's
|
|
26
|
+
* environment credential. Values are never returned. This intentionally uses
|
|
27
|
+
* the same credential-only environment reader as {@link getEnvApiKey}.
|
|
28
|
+
*/
|
|
29
|
+
export declare function getEnvApiKeyEnvNames(provider: string): string[];
|
|
30
|
+
/** Describe the selected source without exposing credential values or unvalidated ADC files. */
|
|
31
|
+
export declare function getEnvApiKeyCredentialSource(provider: string, options?: {
|
|
32
|
+
fetch?: FetchImpl;
|
|
33
|
+
}): Promise<EnvApiKeyCredentialSource | undefined>;
|
|
34
|
+
/** Enumerate usable credential candidates in provider dispatch precedence without exposing credentials. */
|
|
35
|
+
export declare function getEnvApiKeyCredentialSources(provider: string, options?: {
|
|
36
|
+
fetch?: FetchImpl;
|
|
37
|
+
}): Promise<EnvApiKeyCredentialSource[]>;
|
|
38
|
+
/** Resolve Vertex ADC provenance, including metadata-server credentials, without acquiring a token. */
|
|
39
|
+
export declare function getGoogleVertexCredentialSource(options?: {
|
|
40
|
+
fetch?: FetchImpl;
|
|
41
|
+
}): Promise<EnvApiKeyCredentialSource | undefined>;
|
|
42
|
+
/** Name of the environment variable whose value is selected by `getEnvApiKey`, when identifiable. */
|
|
43
|
+
export declare function getEnvApiKeyEnvName(provider: string): Promise<string | undefined>;
|
|
12
44
|
/**
|
|
13
45
|
* Enumerate every provider that has an env-var fallback for `getEnvApiKey`.
|
|
14
46
|
* Used by `gjc auth-broker migrate --include-env` to discover env-sourced keys
|
package/dist/types/types.d.ts
CHANGED
|
@@ -89,6 +89,8 @@ export interface ToolChoiceCompat {
|
|
|
89
89
|
supportsToolChoice?: boolean;
|
|
90
90
|
/** Legacy flag for forced tool_choice support. */
|
|
91
91
|
supportsForcedToolChoice?: boolean;
|
|
92
|
+
/** Whether the provider supports OpenAI ultrafast service tier. Default: false. */
|
|
93
|
+
supportsUltrafastTier?: boolean;
|
|
92
94
|
}
|
|
93
95
|
export type CacheRetention = "none" | "short" | "long";
|
|
94
96
|
/**
|
|
@@ -107,9 +109,11 @@ export type CacheRetention = "none" | "short" | "long";
|
|
|
107
109
|
* - `"openai-only"` → `"priority"` on `openai` and `OpenAI code provider`; ignored elsewhere.
|
|
108
110
|
* - `"Anthropic model-only"` → `"priority"` on direct `anthropic` (not Bedrock/Vertex Anthropic model).
|
|
109
111
|
*/
|
|
110
|
-
export type ServiceTier = "auto" | "default" | "flex" | "scale" | "priority" | "openai-only" | "claude-only";
|
|
112
|
+
export type ServiceTier = "auto" | "default" | "flex" | "scale" | "priority" | "ultrafast" | "openai-only" | "claude-only";
|
|
111
113
|
/** Resolved tier — one of the values that providers actually consume on the wire. */
|
|
112
114
|
export type ResolvedServiceTier = Exclude<ServiceTier, "openai-only" | "claude-only">;
|
|
115
|
+
/** Parse a provider-reported service tier, leaving unknown response values for request fallback. */
|
|
116
|
+
export declare function parseResolvedServiceTier(value: unknown): ResolvedServiceTier | undefined;
|
|
113
117
|
/**
|
|
114
118
|
* Resolves a possibly scoped `ServiceTier` to the effective tier for the
|
|
115
119
|
* given provider. Scoped values match their target family and otherwise
|
|
@@ -119,13 +123,19 @@ export declare function resolveServiceTier(serviceTier: ServiceTier | null | und
|
|
|
119
123
|
/**
|
|
120
124
|
* True when the (possibly scoped) tier should be sent as an OpenAI-compatible
|
|
121
125
|
* `service_tier` request field. Custom providers must explicitly opt in through
|
|
122
|
-
* `compat.supportsServiceTier
|
|
126
|
+
* `compat.supportsServiceTier` for the existing tiers or a model-specific
|
|
127
|
+
* `supportsUltrafastTier` capability for ultrafast; unknown providers remain fail-closed.
|
|
128
|
+
*
|
|
129
|
+
* Note: ultrafast has an additional gating requirement via `modelSupportsUltrafastTier`
|
|
130
|
+
* to ensure it is only sent to models that explicitly support it.
|
|
123
131
|
*/
|
|
124
|
-
export declare function shouldSendServiceTier(serviceTier: ServiceTier | null | undefined, provider: Provider | undefined, supportsServiceTier?: boolean): boolean;
|
|
132
|
+
export declare function shouldSendServiceTier(serviceTier: ServiceTier | null | undefined, provider: Provider | undefined, supportsServiceTier?: boolean, supportsUltrafastTier?: boolean): boolean;
|
|
125
133
|
/**
|
|
126
134
|
* True when a priority tier is realized as a fast-mode request on the provider's
|
|
127
135
|
* wire protocol. Custom OpenAI-compatible proxies opt in explicitly rather than
|
|
128
136
|
* inheriting support merely because their API shape resembles OpenAI.
|
|
137
|
+
*
|
|
138
|
+
* Note: ultrafast is distinct from priority and is not considered fast-mode.
|
|
129
139
|
*/
|
|
130
140
|
export declare function isFastModeEffectiveForProvider(serviceTier: ServiceTier | null | undefined, provider: Provider | undefined, supportsServiceTier?: boolean): boolean;
|
|
131
141
|
/**
|
|
@@ -611,6 +621,8 @@ export interface AssistantMessage {
|
|
|
611
621
|
provider: Provider;
|
|
612
622
|
model: string;
|
|
613
623
|
responseId?: string;
|
|
624
|
+
/** Effective service tier reported by the provider, or the sent tier when the provider omits it. */
|
|
625
|
+
serviceTier?: ResolvedServiceTier;
|
|
614
626
|
usage: Usage;
|
|
615
627
|
stopReason: StopReason;
|
|
616
628
|
errorMessage?: string;
|
|
@@ -905,6 +917,7 @@ export type AssistantMessageEvent = {
|
|
|
905
917
|
contentIndex?: undefined;
|
|
906
918
|
reason: Extract<StopReason, "aborted" | "error">;
|
|
907
919
|
error: AssistantMessage;
|
|
920
|
+
partial?: AssistantMessage;
|
|
908
921
|
} | {
|
|
909
922
|
type: "toolChoiceIncapability";
|
|
910
923
|
contentIndex?: undefined;
|
|
@@ -949,6 +962,12 @@ export interface OpenAICompat extends ToolChoiceCompat {
|
|
|
949
962
|
* preserves or intentionally realizes OpenAI priority processing.
|
|
950
963
|
*/
|
|
951
964
|
supportsServiceTier?: boolean;
|
|
965
|
+
/**
|
|
966
|
+
* Whether the model explicitly supports the ultrafast service tier.
|
|
967
|
+
* Only models that set this flag will send ultrafast tier to the API.
|
|
968
|
+
* Models: gpt-6-astra and gpt-6.1-sol.
|
|
969
|
+
*/
|
|
970
|
+
supportsUltrafastTier?: boolean;
|
|
952
971
|
/**
|
|
953
972
|
* Tool names the provider reserves for its own built-ins and refuses to
|
|
954
973
|
* accept as custom function declarations. A colliding tool is **dropped**
|
|
@@ -1170,6 +1189,8 @@ export interface Model<TApi extends Api = any> {
|
|
|
1170
1189
|
requestTransform?: ModelRequestTransform;
|
|
1171
1190
|
/** Default prompt-cache retention preference for this model when the request omits one. */
|
|
1172
1191
|
cacheRetention?: CacheRetention;
|
|
1192
|
+
/** Configured inter-event idle timeout for this model, in milliseconds. */
|
|
1193
|
+
streamIdleTimeoutMs?: number;
|
|
1173
1194
|
/** Provider-assigned priority value (lower = higher priority). */
|
|
1174
1195
|
priority?: number;
|
|
1175
1196
|
/** Canonical thinking capability metadata for this model. */
|
|
@@ -1194,3 +1215,5 @@ export interface Model<TApi extends Api = any> {
|
|
|
1194
1215
|
}
|
|
1195
1216
|
/** True when a model explicitly opts into OpenAI-compatible `service_tier` forwarding. */
|
|
1196
1217
|
export declare function modelSupportsServiceTier(model: Pick<Model, "compat"> | undefined): boolean;
|
|
1218
|
+
/** True when a model explicitly opts into OpenAI ultrafast service tier support. */
|
|
1219
|
+
export declare function modelSupportsUltrafastTier(model: Pick<Model, "compat"> | undefined): boolean;
|
package/dist/types/usage.d.ts
CHANGED
|
@@ -230,6 +230,9 @@ export interface UsageCredential {
|
|
|
230
230
|
email?: string;
|
|
231
231
|
enterpriseUrl?: string;
|
|
232
232
|
profileArn?: string;
|
|
233
|
+
/** Organization the OAuth token is scoped to; usage limits are per organization. */
|
|
234
|
+
organizationId?: string;
|
|
235
|
+
organizationName?: string;
|
|
233
236
|
mcpBinding?: UsageMCPOAuthBinding;
|
|
234
237
|
metadata?: Record<string, unknown>;
|
|
235
238
|
}
|
|
@@ -1,4 +1,10 @@
|
|
|
1
|
+
import { logger } from "@gajae-code/utils";
|
|
1
2
|
import type { Model } from "../../types";
|
|
3
|
+
/**
|
|
4
|
+
* Returns the default Antigravity discovery User-Agent.
|
|
5
|
+
* Can be overridden via PI_AI_ANTIGRAVITY_USER_AGENT environment variable.
|
|
6
|
+
*/
|
|
7
|
+
export declare function getDefaultAntigravityUserAgent(): string;
|
|
2
8
|
/**
|
|
3
9
|
* Raw model metadata returned by Antigravity's `fetchAvailableModels` endpoint.
|
|
4
10
|
*/
|
|
@@ -15,6 +21,12 @@ export interface AntigravityDiscoveryApiModel {
|
|
|
15
21
|
modelProvider?: string;
|
|
16
22
|
isInternal?: boolean;
|
|
17
23
|
supportsVideo?: boolean;
|
|
24
|
+
/** Account-specific entitlement status */
|
|
25
|
+
entitlement?: string;
|
|
26
|
+
/** Whether the model is disabled for this account */
|
|
27
|
+
disabled?: boolean;
|
|
28
|
+
/** Per-account quota/tier information */
|
|
29
|
+
quota?: string;
|
|
18
30
|
}
|
|
19
31
|
/**
|
|
20
32
|
* Grouping metadata used by Antigravity to surface recommended model ids.
|
|
@@ -43,7 +55,7 @@ export interface FetchAntigravityDiscoveryModelsOptions {
|
|
|
43
55
|
token: string;
|
|
44
56
|
/** Optional endpoint override. Defaults to Antigravity fallback endpoints. */
|
|
45
57
|
endpoint?: string;
|
|
46
|
-
/**
|
|
58
|
+
/** Optional Google Cloud project ID for tier-gated model discovery. */
|
|
47
59
|
project?: string;
|
|
48
60
|
/** Optional user agent override. */
|
|
49
61
|
userAgent?: string;
|
|
@@ -57,6 +69,8 @@ export interface FetchAntigravityDiscoveryModelsOptions {
|
|
|
57
69
|
* Default: `google-antigravity`.
|
|
58
70
|
*/
|
|
59
71
|
targetProvider?: "google-antigravity" | "google-gemini-cli";
|
|
72
|
+
/** Optional logger for debug diagnostics. */
|
|
73
|
+
logger?: Pick<typeof logger, "debug">;
|
|
60
74
|
}
|
|
61
75
|
/**
|
|
62
76
|
* Fetches discoverable Antigravity models and normalizes them into canonical model entries.
|
|
@@ -65,3 +79,4 @@ export interface FetchAntigravityDiscoveryModelsOptions {
|
|
|
65
79
|
* Returns `[]` only when the endpoint responds successfully with no usable models.
|
|
66
80
|
*/
|
|
67
81
|
export declare function fetchAntigravityDiscoveryModels(options: FetchAntigravityDiscoveryModelsOptions): Promise<Model<"google-gemini-cli">[] | null>;
|
|
82
|
+
export declare function getAntigravityDiscoveryUserAgent(): string;
|
|
@@ -23,11 +23,12 @@ export declare function getStreamIdleTimeoutRemediationMs(): number;
|
|
|
23
23
|
* Returns the idle timeout used for OpenAI-family streaming transports.
|
|
24
24
|
*
|
|
25
25
|
* Honors `GJC_OPENAI_STREAM_IDLE_TIMEOUT_MS` first (`PI_OPENAI_STREAM_IDLE_TIMEOUT_MS` is the legacy alias). Set `=0` to disable.
|
|
26
|
+
* A configured model timeout takes precedence over the built-in provider/model floors; environment overrides win over it.
|
|
26
27
|
* When `provider` is given, long-reasoning hosts (xAI Grok and Grok Build) use that floor instead of the 120s default.
|
|
27
28
|
* Grok models reached through other OpenAI-compatible hosts (`openrouter/x-ai/grok-*`, kilo, litellm, …) get the
|
|
28
29
|
* same floor keyed on the model id, because long-reasoning silence is a property of the model (#4797).
|
|
29
30
|
*/
|
|
30
|
-
export declare function getOpenAIStreamIdleTimeoutMs(provider?: string, modelId?: string): number | undefined;
|
|
31
|
+
export declare function getOpenAIStreamIdleTimeoutMs(provider?: string, modelId?: string, configuredTimeoutMs?: number): number | undefined;
|
|
31
32
|
/**
|
|
32
33
|
* Returns the timeout used while waiting for the first stream event.
|
|
33
34
|
* The first token can legitimately take longer than later inter-event gaps,
|
|
@@ -57,7 +58,7 @@ export declare function getStreamFirstEventTimeoutMs(idleTimeoutMs?: number, fal
|
|
|
57
58
|
* window so a short post-connect first-event budget cannot kill legitimate
|
|
58
59
|
* slow setup.
|
|
59
60
|
*/
|
|
60
|
-
export declare function resolveOpenAISdkRequestTimeoutMs(provider: string, streamFirstEventTimeoutOverride?: number, modelId?: string): number | undefined;
|
|
61
|
+
export declare function resolveOpenAISdkRequestTimeoutMs(provider: string, streamFirstEventTimeoutOverride?: number, modelId?: string, configuredIdleTimeoutMs?: number, effectiveIdleTimeoutOverride?: number): number | undefined;
|
|
61
62
|
/**
|
|
62
63
|
* Resolves the Anthropic SDK client `timeout` so stalled-before-headers requests
|
|
63
64
|
* are bounded. The Anthropic first-event watchdog deliberately arms only once
|
|
@@ -1,33 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* GLM ZCode OAuth flow (UNOFFICIAL, opt-in).
|
|
3
|
-
*
|
|
4
|
-
* Replicates how the ZCode desktop app turns a Z.AI login into usable GLM model
|
|
5
|
-
* access. This is NOT an official Z.AI OAuth client: it reuses ZCode's authorize
|
|
6
|
-
* page, broker, and a custom-protocol redirect. It may break at any time and may
|
|
7
|
-
* violate ZCode/Z.AI Terms of Service. Endpoints/client id are overridable via
|
|
8
|
-
* `ZCODE_OAUTH_*` environment variables.
|
|
9
|
-
*
|
|
10
|
-
* Verified end-to-end against the ZCode host bundle (`resolveZaiApiKey` /
|
|
11
|
-
* `resolveBizApiKey`) and live traffic:
|
|
12
|
-
* 1. Authorize: GET {authorize}?redirect_uri=zcode://oauth/callback&response_type=code&client_id=...&state=...
|
|
13
|
-
* (custom-protocol redirect → a CLI cannot catch it, so the user pastes the code/redirect URL)
|
|
14
|
-
* 2. Broker: POST {broker} { provider:"zai", code, redirect_uri, state }
|
|
15
|
-
* → { data: { token: <ZCode JWT>, zai: { access_token: <upstream Z.AI token> } } }
|
|
16
|
-
* 3. Business: POST {z/login} { token: <upstream Z.AI token> } → { data: { access_token: <business token> } }
|
|
17
|
-
* 4. Provision: with the business token, GET getCustomerInfo → default org/project,
|
|
18
|
-
* GET/POST .../api_keys (find/create a key named "zcode-api-key"),
|
|
19
|
-
* GET .../api_keys/copy/{id} → secretKey ⇒ a real Z.AI API key "{id}.{secret}".
|
|
20
|
-
*
|
|
21
|
-
* Credential mapping:
|
|
22
|
-
* - `access` = the provisioned **Z.AI API key** ("{id}.{secret}"). Model requests go to
|
|
23
|
-
* `https://api.z.ai/api/anthropic/v1/messages` with `Authorization: Bearer <key>`
|
|
24
|
-
* (exactly like a dashboard key) — NO zcode.z.ai gateway, NO captcha.
|
|
25
|
-
* - `refresh` = the upstream Z.AI OAuth access token (used to re-provision the key).
|
|
26
|
-
* The API key is long-lived, so `expires` is set far in the future.
|
|
27
|
-
*
|
|
28
|
-
* This provider must NEVER force `isOAuth=true`: the key is a plain Z.AI API key, and
|
|
29
|
-
* api.z.ai is not api.anthropic.com, so the Anthropic path already emits a plain bearer.
|
|
30
|
-
*/
|
|
31
1
|
import { OAuthCallbackFlow } from "./callback-server";
|
|
32
2
|
import type { OAuthController, OAuthCredentials } from "./types";
|
|
33
3
|
export declare const GLM_ZCODE_REFRESH_SKEW_MS: number;
|
|
@@ -7,6 +7,15 @@ export type OAuthCredentials = {
|
|
|
7
7
|
email?: string;
|
|
8
8
|
accountId?: string;
|
|
9
9
|
profileArn?: string;
|
|
10
|
+
/**
|
|
11
|
+
* Organization the token is scoped to. One Anthropic account can belong to
|
|
12
|
+
* several organizations (e.g. a Team workspace and a personal Max plan); each
|
|
13
|
+
* login is bound to exactly one of them, so the organization is part of the
|
|
14
|
+
* credential's identity.
|
|
15
|
+
*/
|
|
16
|
+
organizationId?: string;
|
|
17
|
+
/** Display name of {@link organizationId}. */
|
|
18
|
+
organizationName?: string;
|
|
10
19
|
};
|
|
11
20
|
export type OAuthProvider = "kiro" | "alibaba-token-plan" | "anthropic" | "bizrouter" | "mara" | "cerebras" | "cloudflare-ai-gateway" | "cursor" | "deepseek" | "deepinfra" | "fireworks" | "firepass" | "fugu" | "github-copilot" | "google-gemini-cli" | "google-antigravity" | "gitlab-duo" | "huggingface" | "kimi-code" | "kilo" | "kagi" | "litellm" | "lm-studio" | "minimax-code" | "minimax-code-cn" | "moonshot" | "nvidia" | "nanogpt" | "ollama" | "ollama-cloud" | "openai-codex" | "openai-codex-device" | "opencode-go" | "opencode-zen" | "commandcode-goat" | "opengateway" | "openrouter" | "parallel" | "perplexity" | "qianfan" | "qwen-portal" | "sglang" | "synthetic" | "tavily" | "together" | "venice" | "vercel-ai-gateway" | "vllm" | "xai" | "glm-zcode" | "xiaomi" | "xiaomi-token-plan-sgp" | "xiaomi-token-plan-ams" | "xiaomi-token-plan-cn" | "zenmux" | "opencodex" | "zai";
|
|
12
21
|
export type OAuthProviderId = OAuthProvider | (string & {});
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"type": "module",
|
|
3
3
|
"name": "@gajae-code/ai",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.19.0",
|
|
5
5
|
"description": "Unified LLM API with automatic model discovery and provider configuration",
|
|
6
6
|
"homepage": "https://gajae-code.com",
|
|
7
7
|
"author": "Yeachan-Heo and Gajae Code Contributors",
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
},
|
|
31
31
|
"scripts": {
|
|
32
32
|
"check": "biome check . && bun run check:types",
|
|
33
|
-
"check:types": "tsc -p tsconfig.json --noEmit",
|
|
33
|
+
"check:types": "bun ../coding-agent/scripts/generate-docs-index.ts && tsc -p tsconfig.json --noEmit",
|
|
34
34
|
"lint": "biome lint .",
|
|
35
35
|
"test": "bun test",
|
|
36
36
|
"fix": "biome check --write --unsafe .",
|
|
@@ -41,8 +41,8 @@
|
|
|
41
41
|
"@agentclientprotocol/sdk": "1.3.0",
|
|
42
42
|
"@anthropic-ai/sdk": "^0.94.0",
|
|
43
43
|
"@bufbuild/protobuf": "^2.12.0",
|
|
44
|
-
"@gajae-code/natives": "0.
|
|
45
|
-
"@gajae-code/utils": "0.
|
|
44
|
+
"@gajae-code/natives": "0.19.0",
|
|
45
|
+
"@gajae-code/utils": "0.19.0",
|
|
46
46
|
"openai": "^6.36.0",
|
|
47
47
|
"partial-json": "^0.1.7",
|
|
48
48
|
"zod": "4.4.3"
|
|
@@ -23,6 +23,7 @@ import {
|
|
|
23
23
|
type CachedUsagePresentation,
|
|
24
24
|
type CredentialDispatchTicket,
|
|
25
25
|
type CredentialInventoryRecord,
|
|
26
|
+
formatOAuthIdentityLabel,
|
|
26
27
|
type MCPOAuthRefreshClient,
|
|
27
28
|
type OAuthCredential,
|
|
28
29
|
REMOTE_REFRESH_SENTINEL,
|
|
@@ -1106,6 +1107,8 @@ export class RemoteAuthCredentialStore implements AuthCredentialStore {
|
|
|
1106
1107
|
email: current.email,
|
|
1107
1108
|
projectId: current.projectId,
|
|
1108
1109
|
enterpriseUrl: current.enterpriseUrl,
|
|
1110
|
+
organizationId: current.organizationId,
|
|
1111
|
+
organizationName: current.organizationName,
|
|
1109
1112
|
});
|
|
1110
1113
|
const observed = this.#snapshot.credentials.find(candidate => candidate.id === credentialId);
|
|
1111
1114
|
if (
|
|
@@ -1315,7 +1318,7 @@ export class RemoteAuthCredentialStore implements AuthCredentialStore {
|
|
|
1315
1318
|
return null;
|
|
1316
1319
|
}
|
|
1317
1320
|
if (!reports) return null;
|
|
1318
|
-
return matchUsageReport(reports, provider, credential);
|
|
1321
|
+
return matchUsageReport(reports, provider, credential, this.#usageMatchContext(provider));
|
|
1319
1322
|
}
|
|
1320
1323
|
|
|
1321
1324
|
/**
|
|
@@ -1346,6 +1349,18 @@ export class RemoteAuthCredentialStore implements AuthCredentialStore {
|
|
|
1346
1349
|
});
|
|
1347
1350
|
}
|
|
1348
1351
|
|
|
1352
|
+
#usageMatchContext(provider: string): UsageMatchContext {
|
|
1353
|
+
let credentialCount = 0;
|
|
1354
|
+
const claimedOrganizationIds = new Set<string>();
|
|
1355
|
+
for (const entry of this.#snapshot.credentials) {
|
|
1356
|
+
if (entry.provider !== provider || entry.credential.type !== "oauth") continue;
|
|
1357
|
+
credentialCount += 1;
|
|
1358
|
+
const organizationId = normalizeOrganizationId(entry.credential.organizationId);
|
|
1359
|
+
if (organizationId) claimedOrganizationIds.add(organizationId);
|
|
1360
|
+
}
|
|
1361
|
+
return { credentialCount, claimedOrganizationIds };
|
|
1362
|
+
}
|
|
1363
|
+
|
|
1349
1364
|
#identityDigestForEntry(entry: SnapshotEntry): string {
|
|
1350
1365
|
const credential = entry.credential;
|
|
1351
1366
|
const identity =
|
|
@@ -1356,6 +1371,7 @@ export class RemoteAuthCredentialStore implements AuthCredentialStore {
|
|
|
1356
1371
|
projectId: credential.projectId ?? null,
|
|
1357
1372
|
enterpriseUrl: credential.enterpriseUrl ?? null,
|
|
1358
1373
|
mcpBinding: credential.mcpBinding ?? null,
|
|
1374
|
+
...(credential.organizationId ? { organizationId: credential.organizationId } : {}),
|
|
1359
1375
|
}
|
|
1360
1376
|
: { type: credential.type };
|
|
1361
1377
|
return createHash("sha256")
|
|
@@ -1382,7 +1398,12 @@ export class RemoteAuthCredentialStore implements AuthCredentialStore {
|
|
|
1382
1398
|
if (this.#usageCacheEpoch !== epoch) return;
|
|
1383
1399
|
for (const entry of this.#snapshot.credentials) {
|
|
1384
1400
|
if (entry.credential.type !== "oauth") continue;
|
|
1385
|
-
const report = matchUsageReport(
|
|
1401
|
+
const report = matchUsageReport(
|
|
1402
|
+
reports,
|
|
1403
|
+
entry.provider,
|
|
1404
|
+
entry.credential,
|
|
1405
|
+
this.#usageMatchContext(entry.provider),
|
|
1406
|
+
);
|
|
1386
1407
|
if (!report) continue;
|
|
1387
1408
|
const fetchedAt = Number.isFinite(report.fetchedAt) ? report.fetchedAt : Date.now();
|
|
1388
1409
|
this.recordUsagePresentation({
|
|
@@ -1485,7 +1506,7 @@ function isErrorStatus(error: unknown, status: number): boolean {
|
|
|
1485
1506
|
|
|
1486
1507
|
function snapshotIdentityLabel(entry: SnapshotEntry): string | null {
|
|
1487
1508
|
if (entry.credential.type !== "oauth") return null;
|
|
1488
|
-
return entry.credential
|
|
1509
|
+
return formatOAuthIdentityLabel(entry.credential);
|
|
1489
1510
|
}
|
|
1490
1511
|
|
|
1491
1512
|
function safePresentationUsageReport(report: UsageReport): SafeUsageReport {
|
|
@@ -1531,20 +1552,45 @@ function cloneUsagePresentation(observation: CachedUsagePresentation): CachedUsa
|
|
|
1531
1552
|
};
|
|
1532
1553
|
}
|
|
1533
1554
|
|
|
1555
|
+
/** Facts about the provider's stored credentials that a usage report match must respect. */
|
|
1556
|
+
interface UsageMatchContext {
|
|
1557
|
+
/** Stored OAuth credentials for the provider; a report without identity can only belong to a sole credential. */
|
|
1558
|
+
credentialCount: number;
|
|
1559
|
+
/** Organizations the provider's stored credentials are scoped to. */
|
|
1560
|
+
claimedOrganizationIds: ReadonlySet<string>;
|
|
1561
|
+
}
|
|
1562
|
+
|
|
1534
1563
|
/**
|
|
1535
1564
|
* Match a broker-supplied usage report to a specific OAuth credential. The
|
|
1536
1565
|
* broker returns aggregate reports across all credentials it manages, so we
|
|
1537
|
-
* pick the one whose identity (accountId / email / projectId)
|
|
1538
|
-
* the credential the caller is asking about.
|
|
1566
|
+
* pick the one whose identity (accountId / email / projectId) and organization
|
|
1567
|
+
* line up with the credential the caller is asking about. Missing or ambiguous
|
|
1568
|
+
* usage data is safer than assigning another credential's limits.
|
|
1539
1569
|
*
|
|
1540
|
-
*
|
|
1541
|
-
*
|
|
1542
|
-
*
|
|
1570
|
+
* Ownership must be shown by the report itself. A lone returned report is not
|
|
1571
|
+
* evidence: when one credential's usage fetch fails, the broker returns only
|
|
1572
|
+
* the others' reports. So a report is taken without an identity match only
|
|
1573
|
+
* when the provider has a single stored credential. A credential stored
|
|
1574
|
+
* without an organization never takes a report whose organization another
|
|
1575
|
+
* stored credential claims.
|
|
1543
1576
|
*/
|
|
1544
|
-
function matchUsageReport(
|
|
1545
|
-
|
|
1577
|
+
function matchUsageReport(
|
|
1578
|
+
reports: UsageReport[],
|
|
1579
|
+
provider: Provider,
|
|
1580
|
+
credential: OAuthCredential,
|
|
1581
|
+
context: UsageMatchContext,
|
|
1582
|
+
): UsageReport | null {
|
|
1583
|
+
const organizationId = normalizeOrganizationId(credential.organizationId);
|
|
1584
|
+
const candidates = reports.filter(report => {
|
|
1585
|
+
if (report.provider !== provider) return false;
|
|
1586
|
+
const reportOrganizationId = normalizeOrganizationId(
|
|
1587
|
+
readMetadataString((report.metadata ?? {}) as Record<string, unknown>, "orgId"),
|
|
1588
|
+
);
|
|
1589
|
+
if (organizationId) return reportOrganizationId === organizationId;
|
|
1590
|
+
return reportOrganizationId === undefined || !context.claimedOrganizationIds.has(reportOrganizationId);
|
|
1591
|
+
});
|
|
1546
1592
|
if (candidates.length === 0) return null;
|
|
1547
|
-
if (candidates.length === 1) return candidates[0];
|
|
1593
|
+
if (candidates.length === 1 && context.credentialCount === 1) return candidates[0];
|
|
1548
1594
|
const accountId = credential.accountId?.trim().toLowerCase();
|
|
1549
1595
|
const email = credential.email?.trim().toLowerCase();
|
|
1550
1596
|
const projectId = credential.projectId?.trim().toLowerCase();
|
|
@@ -1554,6 +1600,11 @@ function matchUsageReport(reports: UsageReport[], provider: Provider, credential
|
|
|
1554
1600
|
return null;
|
|
1555
1601
|
}
|
|
1556
1602
|
|
|
1603
|
+
function normalizeOrganizationId(organizationId: string | undefined): string | undefined {
|
|
1604
|
+
const normalized = organizationId?.trim().toLowerCase();
|
|
1605
|
+
return normalized ? normalized : undefined;
|
|
1606
|
+
}
|
|
1607
|
+
|
|
1557
1608
|
function reportMatchesIdentity(
|
|
1558
1609
|
report: UsageReport,
|
|
1559
1610
|
accountId: string | undefined,
|
|
@@ -45,6 +45,8 @@ export const oauthCredentialSchema = z
|
|
|
45
45
|
projectId: z.string().optional(),
|
|
46
46
|
email: z.string().optional(),
|
|
47
47
|
accountId: z.string().optional(),
|
|
48
|
+
organizationId: z.string().optional(),
|
|
49
|
+
organizationName: z.string().optional(),
|
|
48
50
|
mcpBinding: mcpOAuthBindingSchema.optional(),
|
|
49
51
|
})
|
|
50
52
|
.strict();
|
|
@@ -589,8 +589,9 @@ export function redactGatewayStream(events: AssistantMessageEventStream): Assist
|
|
|
589
589
|
async function* redactedEvents(): AsyncGenerator<AssistantMessageEvent> {
|
|
590
590
|
try {
|
|
591
591
|
for await (const event of events) {
|
|
592
|
-
if (event.type === "error")
|
|
593
|
-
|
|
592
|
+
if (event.type === "error") {
|
|
593
|
+
yield { type: "error", reason: event.reason, error: redactGatewayMessage(event.error) };
|
|
594
|
+
} else yield event;
|
|
594
595
|
}
|
|
595
596
|
} catch (error) {
|
|
596
597
|
throw redactGatewayError(error);
|