@oh-my-pi/pi-ai 18.4.4 → 18.4.6
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 +23 -26
- package/dist/types/auth/cascade.d.ts +17 -6
- package/dist/types/auth/rank.d.ts +7 -1
- package/dist/types/auth/refresh.d.ts +8 -0
- package/dist/types/auth/types.d.ts +19 -2
- package/dist/types/auth-gateway/dispatch.d.ts +7 -7
- package/dist/types/auth-gateway/http.d.ts +4 -1
- package/dist/types/auth-gateway/types.d.ts +2 -0
- package/dist/types/auth-retry.d.ts +3 -1
- package/dist/types/index.d.ts +1 -0
- package/dist/types/providers/anthropic.d.ts +7 -0
- package/dist/types/providers/cursor/interaction-query.d.ts +4 -2
- package/dist/types/providers/cursor.d.ts +14 -12
- package/dist/types/providers/factory-droid/gemini.d.ts +15 -0
- package/dist/types/providers/factory-droid.d.ts +13 -0
- package/dist/types/providers/google-shared.d.ts +12 -0
- package/dist/types/providers/openai-chat-wire.d.ts +7 -2
- package/dist/types/providers/openai-completions.d.ts +1 -1
- package/dist/types/registry/oauth/device-code.d.ts +2 -2
- package/dist/types/registry/oauth/factory-droid.d.ts +3 -0
- package/dist/types/registry/oauth/types.d.ts +13 -3
- package/dist/types/types.d.ts +5 -0
- package/dist/types/usage/factory-droid.d.ts +11 -0
- package/dist/types/usage.d.ts +4 -0
- package/dist/types/utils/schema/allowlist.d.ts +2 -0
- package/dist/types/utils/schema/index.d.ts +1 -0
- package/package.json +6 -6
- package/src/api-registry.ts +1 -0
- package/src/auth/cascade.ts +51 -11
- package/src/auth/health.ts +3 -0
- package/src/auth/oauth.ts +4 -0
- package/src/auth/rank.ts +11 -1
- package/src/auth/refresh.ts +27 -2
- package/src/auth/select.ts +52 -24
- package/src/auth/types.ts +18 -2
- package/src/auth/usage-cache.ts +6 -0
- package/src/auth/usage.ts +10 -5
- package/src/auth-gateway/dispatch.ts +20 -20
- package/src/auth-gateway/http.ts +44 -2
- package/src/auth-gateway/routes/embeddings.ts +1 -1
- package/src/auth-gateway/routes/images.ts +1 -1
- package/src/auth-gateway/routes/rerank.ts +1 -1
- package/src/auth-gateway/routes/speech.ts +1 -1
- package/src/auth-gateway/routes/systemone.ts +1 -1
- package/src/auth-gateway/routes/transcriptions.ts +1 -1
- package/src/auth-gateway/routes/video.ts +4 -3
- package/src/auth-gateway/server.ts +40 -10
- package/src/auth-gateway/types.ts +2 -0
- package/src/auth-retry.ts +3 -1
- package/src/auth-storage.ts +3 -1
- package/src/index.ts +1 -0
- package/src/providers/amazon-bedrock.ts +10 -8
- package/src/providers/anthropic.ts +126 -16
- package/src/providers/cursor/interaction-query.ts +11 -8
- package/src/providers/cursor.ts +980 -314
- package/src/providers/factory-droid/droid-identity.md +1 -0
- package/src/providers/factory-droid/gemini.ts +538 -0
- package/src/providers/factory-droid.ts +623 -0
- package/src/providers/google-shared.ts +2 -2
- package/src/providers/openai-chat-wire.ts +11 -2
- package/src/providers/openai-completions.ts +106 -13
- package/src/registry/engine/device-code.ts +2 -2
- package/src/registry/engine/refresh.ts +1 -0
- package/src/registry/hooks/device-code.ts +1 -0
- package/src/registry/oauth/device-code.ts +19 -3
- package/src/registry/oauth/factory-droid.ts +62 -0
- package/src/registry/oauth/types.ts +13 -3
- package/src/stream.ts +38 -4
- package/src/types.ts +5 -0
- package/src/usage/cursor.ts +3 -4
- package/src/usage/factory-droid.ts +226 -0
- package/src/usage/registry.ts +3 -0
- package/src/usage/xai-oauth.ts +21 -8
- package/src/usage.ts +4 -0
- package/src/utils/schema/CONSTRAINTS.md +15 -0
- package/src/utils/schema/allowlist.ts +160 -0
- package/src/utils/schema/index.ts +1 -0
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,28 @@
|
|
|
2
2
|
|
|
3
3
|
## [Unreleased]
|
|
4
4
|
|
|
5
|
+
## [18.4.6] - 2026-10-01
|
|
6
|
+
|
|
7
|
+
### Fixed
|
|
8
|
+
|
|
9
|
+
- Fixed forced tool calls failing for Claude Opus 5.5 and Sonnet 5.5 through Amazon Bedrock, including required-tool retries in plan mode.
|
|
10
|
+
|
|
11
|
+
## [18.4.5] - 2026-09-30
|
|
12
|
+
|
|
13
|
+
### Added
|
|
14
|
+
|
|
15
|
+
- Added Factory Droid OAuth, HTTP streaming across Anthropic, OpenAI and Gemini protocols, and pool-aware usage reporting ([#8577](https://github.com/can1357/oh-my-pi/pull/8577) by [@will-bogusz](https://github.com/will-bogusz), continued in [#13276](https://github.com/can1357/oh-my-pi/pull/13276) by [@DusKing1](https://github.com/DusKing1)).
|
|
16
|
+
- `AuthStorage.keys.setConfig(provider, value, { fallback: true })` registers a key that is used only when no stored OAuth or `/login` credential exists, instead of overriding them; `removeConfig`/`clearConfig` also clear these fallbacks ([#13815](https://github.com/can1357/oh-my-pi/pull/13815) by [@H4vC](https://github.com/H4vC))
|
|
17
|
+
- Cursor turns now fall back to Cursor's HTTP/1 streaming transport when HTTP/2 is unavailable, surface Cursor's structured service errors, and resume from the last safe server checkpoint after a dropped stream ([#11613](https://github.com/can1357/oh-my-pi/pull/11613) by [@will-bogusz](https://github.com/will-bogusz)).
|
|
18
|
+
|
|
19
|
+
### Fixed
|
|
20
|
+
|
|
21
|
+
- Auth gateway checks for configured bearer tokens in URLs or forwarded/logged headers only after authentication; unauthorized requests use socket peers and redact unknown paths. Authenticated requests with misplaced tokens are rejected before provider dispatch ([#13827](https://github.com/can1357/oh-my-pi/pull/13827) by [@shawnkoh](https://github.com/shawnkoh)).
|
|
22
|
+
- Codex sessions no longer keep spending an account's credits after its plan limit is reached while another logged-in account still has plan usage left; new and ongoing sessions switch to that account, and credits are used only when no account has plan usage left ([#13889](https://github.com/can1357/oh-my-pi/issues/13889)).
|
|
23
|
+
- Runtime usage providers (`usage.setProvider`, extension `registerProvider({ usage })`) now key cached reports by their own `cacheVersion`, so reports written by processes without the override are no longer served to it ([#13814](https://github.com/can1357/oh-my-pi/issues/13814)).
|
|
24
|
+
- xAI OAuth accounts with active weekly credits no longer switch away solely because an uncertain monthly counter exceeds its limit ([#13806](https://github.com/can1357/oh-my-pi/issues/13806)).
|
|
25
|
+
- Cursor retries after a rejected conversation now keep the tool calls and results already completed in the turn, instead of re-sending the last message and redoing that work ([#11613](https://github.com/can1357/oh-my-pi/pull/11613) by [@will-bogusz](https://github.com/will-bogusz)).
|
|
26
|
+
|
|
5
27
|
## [18.4.4] - 2026-09-29
|
|
6
28
|
|
|
7
29
|
### Added
|
|
@@ -2294,29 +2316,4 @@
|
|
|
2294
2316
|
|
|
2295
2317
|
- Added the optional `ToolResultMessage.useless` flag: tools can declare a finished result contextually useless (zero matches, elapsed wait) so compaction passes may elide it once consumed. Never serialized to provider wire formats and never set together with `isError`.
|
|
2296
2318
|
|
|
2297
|
-
|
|
2298
|
-
|
|
2299
|
-
### Fixed
|
|
2300
|
-
|
|
2301
|
-
- Fixed Anthropic requests bypassing lone-surrogate sanitization after payload hooks or Anthropic-origin tool-call replay: the model itself can emit unpaired surrogate escapes in its own tool-argument JSON (streamed out fine, then rejected with `400 The request body is not valid JSON` on every subsequent request, bricking the session). The final Anthropic payload is now deep-sanitized with `toWellFormed()` immediately before SDK serialization; the pass is identity-preserving, so well-formed arguments stay byte-identical and prompt-cache prefixes are unaffected.
|
|
2302
|
-
|
|
2303
|
-
## [15.11.8] - 2026-06-12
|
|
2304
|
-
|
|
2305
|
-
### Breaking Changes
|
|
2306
|
-
|
|
2307
|
-
- Removed the Codex SSE stateful transport path, so SSE turns no longer send `previous_response_id` with delta input and now always send the full transcript
|
|
2308
|
-
|
|
2309
|
-
### Changed
|
|
2310
|
-
|
|
2311
|
-
- Scoped `x-codex-turn-state` handling to within-turn continuations so only tool-loop follow-ups include the turn-state header and new user turns start without it
|
|
2312
|
-
|
|
2313
|
-
### Removed
|
|
2314
|
-
|
|
2315
|
-
- Removed the `statefulResponses` option from `OpenAICodexResponsesOptions`, and SSE stateful mode is no longer controlled by the `PI_CODEX_STATEFUL`-style flag
|
|
2316
|
-
|
|
2317
|
-
### Fixed
|
|
2318
|
-
|
|
2319
|
-
- Fixed the platform OpenAI Responses and Codex websocket stale-chain classifiers missing the "Unsupported parameter: previous_response_id" rejection phrasing (FastAPI-style `detail` body with no `error.code`), so a chained turn now falls back to a full-transcript replay instead of surfacing the 400
|
|
2320
|
-
- Fixed the HTTP-400 raw-request dump for Codex SSE to record the body actually sent on the wire instead of the pre-transport request body, which made chained-request failures look like the rejected parameter was never sent
|
|
2321
|
-
|
|
2322
|
-
Older entries are archived in [packages\ai\CHANGELOG.md@07e9197a3012](https://github.com/can1357/oh-my-pi/blob/07e9197a3012f58c459f1faabeb324decc21f41d/packages\ai\CHANGELOG.md).
|
|
2319
|
+
Older entries are archived in [packages\ai\CHANGELOG.md@cd762117522c](https://github.com/can1357/oh-my-pi/blob/cd762117522cc4122cd45b8d2d14de5f7be5133b/packages\ai\CHANGELOG.md).
|
|
@@ -2,7 +2,7 @@ import { type ApiKeyResolver, type ResolvedApiKey } from "../auth-retry.js";
|
|
|
2
2
|
import type { SessionAffinity } from "./affinity.js";
|
|
3
3
|
import type { CredentialPool } from "./pool.js";
|
|
4
4
|
import type { CredentialSelector } from "./select.js";
|
|
5
|
-
import type { AuthApiKeyOptions, AuthCredential, AuthSource, AuthSourceOptions, KeysApi, LimitsApi } from "./types.js";
|
|
5
|
+
import type { AuthApiKeyOptions, AuthCredential, AuthSource, AuthSourceOptions, KeysApi, LimitsApi, OAuthRequestIdentity } from "./types.js";
|
|
6
6
|
/** Runtime (--api-key) and config (models.yml) key overrides plus the config-value resolver. */
|
|
7
7
|
export declare class KeyOverrides {
|
|
8
8
|
#private;
|
|
@@ -10,6 +10,8 @@ export declare class KeyOverrides {
|
|
|
10
10
|
has(provider: string): boolean;
|
|
11
11
|
runtimeKey(provider: string): string | undefined;
|
|
12
12
|
configKey(provider: string): string | undefined;
|
|
13
|
+
/** Config value consulted only after stored OAuth/login credentials. */
|
|
14
|
+
fallbackKey(provider: string): string | undefined;
|
|
13
15
|
/** Resolve a config value (env var name, "!command", literal) to the secret. */
|
|
14
16
|
resolve(config: string): Promise<string | undefined>;
|
|
15
17
|
/**
|
|
@@ -30,10 +32,17 @@ export declare class KeyOverrides {
|
|
|
30
32
|
*
|
|
31
33
|
* Lower priority than {@link KeyOverrides.setRuntime} so a CLI `--api-key`
|
|
32
34
|
* still wins for the duration of a single invocation.
|
|
35
|
+
*
|
|
36
|
+
* `fallback: true` instead ranks the value below stored OAuth and `/login`
|
|
37
|
+
* credentials (at the env-var tier). Providers that own a `/login` flow use
|
|
38
|
+
* this so their default key reference (e.g. an unset env-var name, which
|
|
39
|
+
* resolves to its literal text) cannot shadow the key the user logged in with.
|
|
33
40
|
*/
|
|
34
|
-
setConfig(provider: string, apiKeyConfig: string
|
|
41
|
+
setConfig(provider: string, apiKeyConfig: string, options?: {
|
|
42
|
+
fallback?: boolean;
|
|
43
|
+
}): void;
|
|
35
44
|
/**
|
|
36
|
-
* Remove a single config-sourced API key override.
|
|
45
|
+
* Remove a single config-sourced API key (override or fallback).
|
|
37
46
|
*/
|
|
38
47
|
removeConfig(provider: string): void;
|
|
39
48
|
/**
|
|
@@ -85,7 +94,7 @@ export declare class KeyCascade implements KeysApi {
|
|
|
85
94
|
/**
|
|
86
95
|
* Classify where a provider's auth comes from, following the same precedence
|
|
87
96
|
* as {@link KeyCascade.get}: runtime override → config override →
|
|
88
|
-
* stored OAuth → login-stored api_key → env var → stored api_key.
|
|
97
|
+
* stored OAuth → login-stored api_key → config fallback → env var → stored api_key.
|
|
89
98
|
* Returns undefined when no auth is configured.
|
|
90
99
|
*
|
|
91
100
|
* Compact, structured counterpart to {@link KeyCascade.describe}; `env`
|
|
@@ -107,7 +116,7 @@ export declare class KeyCascade implements KeysApi {
|
|
|
107
116
|
* Priority (first match wins): runtime override, config override, OAuth,
|
|
108
117
|
* login API key, environment variable, then another stored API key.
|
|
109
118
|
*/
|
|
110
|
-
get(provider: string, sessionId?: string, options?: AuthApiKeyOptions, onCredentialId?: (id: number) => void): Promise<string | undefined>;
|
|
119
|
+
get(provider: string, sessionId?: string, options?: AuthApiKeyOptions, onCredentialId?: (id: number, identity?: OAuthRequestIdentity) => void): Promise<string | undefined>;
|
|
111
120
|
/**
|
|
112
121
|
* Build an {@link ApiKeyResolver} backed by this storage, implementing the
|
|
113
122
|
* central a/b/c auth-retry policy:
|
|
@@ -140,7 +149,9 @@ export declare class KeyCascade implements KeysApi {
|
|
|
140
149
|
describe(provider: string, sessionId?: string): string | undefined;
|
|
141
150
|
setRuntime(provider: string, apiKey: string): void;
|
|
142
151
|
removeRuntime(provider: string): void;
|
|
143
|
-
setConfig(provider: string, apiKeyConfig: string
|
|
152
|
+
setConfig(provider: string, apiKeyConfig: string, options?: {
|
|
153
|
+
fallback?: boolean;
|
|
154
|
+
}): void;
|
|
144
155
|
removeConfig(provider: string): void;
|
|
145
156
|
clearConfig(): void;
|
|
146
157
|
setResolver(resolver: (config: string) => Promise<string | undefined>): void;
|
|
@@ -18,6 +18,11 @@ export type UsageCandidate<T extends AuthCredential> = {
|
|
|
18
18
|
inReserve?: boolean;
|
|
19
19
|
/** True only when reserve ranking had a usable remaining-fraction measurement. */
|
|
20
20
|
reserveMeasured?: boolean;
|
|
21
|
+
/**
|
|
22
|
+
* Present after ranking: the account's renewable allowance for this request is
|
|
23
|
+
* spent, so if it still serves it draws on paid overage such as Codex credits.
|
|
24
|
+
*/
|
|
25
|
+
allowanceSpent?: boolean;
|
|
21
26
|
};
|
|
22
27
|
/** OAuth credential eligible for usage ranking. */
|
|
23
28
|
export type OAuthCandidate = UsageCandidate<OAuthCredential>;
|
|
@@ -35,6 +40,7 @@ export type UsageRankedCandidate<T extends AuthCredential> = UsageCandidate<T> &
|
|
|
35
40
|
reserveMeasured?: boolean;
|
|
36
41
|
accountPriority: number;
|
|
37
42
|
hasPriorityBoost: boolean;
|
|
43
|
+
allowanceSpent: boolean;
|
|
38
44
|
usageMeasured: boolean;
|
|
39
45
|
planPriority: number;
|
|
40
46
|
secondaryUsed: number;
|
|
@@ -49,5 +55,5 @@ export type RankedOAuthCandidate = UsageRankedCandidate<OAuthCredential>;
|
|
|
49
55
|
export type RankedApiKeyCandidate = UsageRankedCandidate<ApiKeyCredential>;
|
|
50
56
|
/** Rank accounts by model-plan eligibility when a plan gate applies. */
|
|
51
57
|
export declare function planPriority(gate: PlanGate | undefined, report: UsageReport | null): number;
|
|
52
|
-
/** Sort ranked candidates by blocks, plan, reserve, boost, hot window, usage and drain. */
|
|
58
|
+
/** Sort ranked candidates by blocks, plan, spent allowance, reserve, boost, hot window, usage and drain. */
|
|
53
59
|
export declare function orderUsageRankedCandidates<T extends AuthCredential>(candidates: UsageRankedCandidate<T>[], planGated: boolean): UsageCandidate<T>[];
|
|
@@ -17,6 +17,13 @@ import { type AuthCredentialSnapshotEntry, type AuthStorageOptions, type OAuthCr
|
|
|
17
17
|
* the rotation cadence by <4%.
|
|
18
18
|
*/
|
|
19
19
|
export declare const OAUTH_REFRESH_SKEW_MS = 60000;
|
|
20
|
+
type OrganizationScope = Pick<OAuthCredentials, "orgId" | "region" | "inferenceRegion" | "activeOrganizationId" | "orgName">;
|
|
21
|
+
/**
|
|
22
|
+
* Organization-scoped identity after a refresh: refreshed values win; stored
|
|
23
|
+
* org/residency/inference scope carries over only while the organization is
|
|
24
|
+
* unchanged. The WorkOS selection always falls back to the stored one.
|
|
25
|
+
*/
|
|
26
|
+
export declare function mergeRefreshedOrganizationScope(current: OrganizationScope, refreshed: OrganizationScope): OrganizationScope;
|
|
20
27
|
/** Merge provider refresh bytes with the stored OAuth row, preserving subtype metadata for every refresh path. */
|
|
21
28
|
export declare function mergeRefreshedCredential<T extends OAuthCredential>(current: T, refreshed: OAuthCredentials): T;
|
|
22
29
|
/** Dependencies for lease-guarded OAuth refresh. */
|
|
@@ -57,3 +64,4 @@ export declare class OAuthRefresher {
|
|
|
57
64
|
*/
|
|
58
65
|
refreshById(id: number, signal?: AbortSignal, options?: OAuthRefreshByIdOptions): Promise<AuthCredentialSnapshotEntry>;
|
|
59
66
|
}
|
|
67
|
+
export {};
|
|
@@ -180,6 +180,9 @@ export type CompletionProbeCredential = {
|
|
|
180
180
|
email?: string;
|
|
181
181
|
enterpriseUrl?: string;
|
|
182
182
|
apiEndpoint?: string;
|
|
183
|
+
orgId?: string;
|
|
184
|
+
region?: string;
|
|
185
|
+
inferenceRegion?: "global" | "eu" | "us";
|
|
183
186
|
};
|
|
184
187
|
/**
|
|
185
188
|
* Caller-supplied bearer probe. Receives the post-refresh credential for a
|
|
@@ -422,6 +425,12 @@ export type AuthApiKeyOptions = {
|
|
|
422
425
|
/** Explicit provider-401 recovery; generic force refreshes leave this unset. */
|
|
423
426
|
refreshReason?: OAuthRefreshReason;
|
|
424
427
|
};
|
|
428
|
+
/** Non-secret identity bound to the OAuth credential selected for one request attempt. */
|
|
429
|
+
export interface OAuthRequestIdentity {
|
|
430
|
+
orgId?: string;
|
|
431
|
+
region?: string;
|
|
432
|
+
inferenceRegion?: "global" | "eu" | "us";
|
|
433
|
+
}
|
|
425
434
|
/**
|
|
426
435
|
* Refreshed OAuth access plus identity metadata returned by
|
|
427
436
|
* {@link AuthStorage.oauth.access}. Callers that authenticate via a bearer
|
|
@@ -441,6 +450,8 @@ export interface OAuthAccess {
|
|
|
441
450
|
/** Organization/workspace the credential is scoped to (Anthropic/ChatGPT multi-subscription). */
|
|
442
451
|
orgId?: string;
|
|
443
452
|
orgName?: string;
|
|
453
|
+
region?: string;
|
|
454
|
+
inferenceRegion?: "global" | "eu" | "us";
|
|
444
455
|
}
|
|
445
456
|
/**
|
|
446
457
|
* Identity slice of the credential a successful {@link AuthStorage.oauth.login}
|
|
@@ -848,10 +859,16 @@ export interface KeysApi {
|
|
|
848
859
|
*
|
|
849
860
|
* Lower priority than {@link setRuntimeApiKey} so a CLI `--api-key`
|
|
850
861
|
* still wins for the duration of a single invocation.
|
|
862
|
+
*
|
|
863
|
+
* `fallback: true` ranks the value below stored OAuth and `/login`
|
|
864
|
+
* credentials instead, so a provider's default key reference cannot shadow
|
|
865
|
+
* a key the user logged in with.
|
|
851
866
|
*/
|
|
852
|
-
setConfig(provider: string, apiKeyConfig: string
|
|
867
|
+
setConfig(provider: string, apiKeyConfig: string, options?: {
|
|
868
|
+
fallback?: boolean;
|
|
869
|
+
}): void;
|
|
853
870
|
/**
|
|
854
|
-
* Remove a single config-sourced API key override.
|
|
871
|
+
* Remove a single config-sourced API key (override or fallback).
|
|
855
872
|
*/
|
|
856
873
|
removeConfig(provider: string): void;
|
|
857
874
|
/**
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { ApiKeyResolver } from "../auth-retry.js";
|
|
1
|
+
import type { ApiKeyResolver, ResolvedApiKey } from "../auth-retry.js";
|
|
2
2
|
import type { AuthStorage } from "../auth-storage.js";
|
|
3
3
|
import { type GatewayErrorClassification } from "../error/gateway.js";
|
|
4
4
|
import type { Api, FetchImpl, Model, Usage } from "../types.js";
|
|
@@ -42,12 +42,12 @@ export declare function resolveGatewayAccount(storage: AuthStorage, provider: st
|
|
|
42
42
|
* Resolve the credential for one request from broker-backed storage.
|
|
43
43
|
*
|
|
44
44
|
* pi-ai clients never consult `AuthStorage`; the gateway resolves the bearer
|
|
45
|
-
*
|
|
46
|
-
*
|
|
47
|
-
*
|
|
48
|
-
* {@link classifyGatewayError}
|
|
45
|
+
* and its OAuth identity together (refreshing through the broker when needed).
|
|
46
|
+
* Keep this selection snapshot intact even if another request replaces the
|
|
47
|
+
* stored token before dispatch. Storage failures map through
|
|
48
|
+
* {@link classifyGatewayError}; a provider without any credential is a 401.
|
|
49
49
|
*/
|
|
50
|
-
export declare function resolveGatewayApiKey(storage: AuthStorage, model: Model<Api>, sessionId: string, signal: AbortSignal, peer: string): Promise<
|
|
50
|
+
export declare function resolveGatewayApiKey(storage: AuthStorage, model: Model<Api>, sessionId: string, signal: AbortSignal, peer: string): Promise<ResolvedApiKey | GatewayErrorClassification>;
|
|
51
51
|
/**
|
|
52
52
|
* Build the {@link ApiKeyResolver} handed to a pi-ai client for a gateway
|
|
53
53
|
* request. Drives the central a/b/c auth-retry policy server-side:
|
|
@@ -63,7 +63,7 @@ export declare function resolveGatewayApiKey(storage: AuthStorage, model: Model<
|
|
|
63
63
|
* routes that retain provider session state use it to re-key the account
|
|
64
64
|
* lease, one-shot routes pass `undefined`.
|
|
65
65
|
*/
|
|
66
|
-
export declare function buildGatewayApiKeyResolver(storage: AuthStorage, model: Model<Api>, sessionId: string, initialKey:
|
|
66
|
+
export declare function buildGatewayApiKeyResolver(storage: AuthStorage, model: Model<Api>, sessionId: string, initialKey: ResolvedApiKey, requestSignal: AbortSignal, format: string, peer: string, onResolvedKey?: (apiKey: string) => void): ApiKeyResolver;
|
|
67
67
|
/**
|
|
68
68
|
* Attribute one settled upstream request to the originating client via the
|
|
69
69
|
* broker's observed-usage channel (`AuthStorage.usage.observe`, batched
|
|
@@ -16,7 +16,10 @@ export declare function gatewayResponseHeaders(model: Model<Api>, info: {
|
|
|
16
16
|
costUsd?: number;
|
|
17
17
|
startedAt?: number;
|
|
18
18
|
}): Record<string, string>;
|
|
19
|
-
|
|
19
|
+
/** Use the socket peer unless the gateway explicitly trusts its reverse proxy. */
|
|
20
|
+
export declare function resolvePeer(req: Request, socketAddress: string, trustProxyHeaders?: boolean): string;
|
|
21
|
+
/** Keep configured gateway credentials out of URL and forwarded/logged request fields. */
|
|
22
|
+
export declare function hasMisplacedBearer(req: Request, url: URL, tokens: ReadonlySet<string>): boolean;
|
|
20
23
|
/**
|
|
21
24
|
* Constant-time byte comparison. Falls back to a manual XOR accumulator if
|
|
22
25
|
* `node:crypto.timingSafeEqual` isn't available. Always processes every byte
|
|
@@ -125,6 +125,8 @@ export interface AuthGatewayServerOptions {
|
|
|
125
125
|
bind?: string;
|
|
126
126
|
/** Accept any of these bearer tokens. Empty allows unauthenticated calls. */
|
|
127
127
|
bearerTokens: string[];
|
|
128
|
+
/** Honor forwarded peer headers only when the connecting proxy is trusted. Default false. */
|
|
129
|
+
trustProxyHeaders?: boolean;
|
|
128
130
|
/** Version surfaced on `/healthz`. */
|
|
129
131
|
version?: string;
|
|
130
132
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { LimitsApi, OAuthAccess, OAuthApi } from "./auth/types.js";
|
|
1
|
+
import type { LimitsApi, OAuthAccess, OAuthApi, OAuthRequestIdentity } from "./auth/types.js";
|
|
2
2
|
import { isAuthRetryableError } from "./error/auth-classify.js";
|
|
3
3
|
/**
|
|
4
4
|
* Context passed to an {@link ApiKeyResolver} on each resolution attempt.
|
|
@@ -42,6 +42,8 @@ export interface ResolvedApiKey {
|
|
|
42
42
|
* already sent it before that block.
|
|
43
43
|
*/
|
|
44
44
|
afterSiblingWait?: boolean;
|
|
45
|
+
/** Non-secret request scope belonging to this bearer, replaced on account rotation. */
|
|
46
|
+
oauthIdentity?: OAuthRequestIdentity;
|
|
45
47
|
}
|
|
46
48
|
export type ApiKeyResolution = string | ResolvedApiKey | undefined;
|
|
47
49
|
export type ApiKeyResolver = (ctx: ApiKeyResolveContext) => Promise<ApiKeyResolution> | ApiKeyResolution;
|
package/dist/types/index.d.ts
CHANGED
|
@@ -45,6 +45,7 @@ export * from "./usage.js";
|
|
|
45
45
|
export * from "./usage/claude.js";
|
|
46
46
|
export * from "./usage/claude-reset.js";
|
|
47
47
|
export * from "./usage/cursor.js";
|
|
48
|
+
export * from "./usage/factory-droid.js";
|
|
48
49
|
export * from "./usage/gemini.js";
|
|
49
50
|
export * from "./usage/github-copilot.js";
|
|
50
51
|
export * from "./usage/google-antigravity.js";
|
|
@@ -234,6 +234,13 @@ export declare function budgetThinkingOutput(maxTokens: number | undefined, budg
|
|
|
234
234
|
maxTokens: number;
|
|
235
235
|
budgetTokens: number;
|
|
236
236
|
};
|
|
237
|
+
/**
|
|
238
|
+
* Whether the conversation has stopped being thinking-led, so routes with
|
|
239
|
+
* `compat.stripThinkingHistory` drop the budget `thinking` config and replay
|
|
240
|
+
* history without thinking blocks. Exported so the factory-droid provider can
|
|
241
|
+
* gate its header-level interleaved beta on the same decision.
|
|
242
|
+
*/
|
|
243
|
+
export declare function shouldStripThinkingHistory(messages: readonly Message[]): boolean;
|
|
237
244
|
/**
|
|
238
245
|
* A single Anthropic conversation turn, including the mid-conversation
|
|
239
246
|
* `system` role (Opus 4.8+ and Fable/Mythos 5).
|
|
@@ -1,10 +1,12 @@
|
|
|
1
|
-
import type http2 from "node:http2";
|
|
2
1
|
import { type InteractionQuery } from "@oh-my-pi/pi-catalog/discovery/cursor-proto";
|
|
3
2
|
type ProtoUnknownField = {
|
|
4
3
|
no: number;
|
|
5
4
|
wireType: number;
|
|
6
5
|
data: Uint8Array;
|
|
7
6
|
};
|
|
7
|
+
interface CursorInteractionWriter {
|
|
8
|
+
write(frame: Uint8Array): void;
|
|
9
|
+
}
|
|
8
10
|
/** Wrap one Connect-protocol message: 1 flag byte + 4-byte big-endian length + payload. */
|
|
9
11
|
export declare function frameConnectMessage(data: Uint8Array, flags?: number): Buffer;
|
|
10
12
|
/** Well-formed protobuf-es `$unknown` entries on `message`; anything else on the bag is ignored. */
|
|
@@ -21,5 +23,5 @@ export declare function protoUnknownFields(message: object): ProtoUnknownField[]
|
|
|
21
23
|
* Unsupported interactive queries are rejected so the server is not stranded.
|
|
22
24
|
* VM setup is left unanswered rather than reporting a fake success.
|
|
23
25
|
*/
|
|
24
|
-
export declare function handleInteractionQuery(query: InteractionQuery, h2Request:
|
|
26
|
+
export declare function handleInteractionQuery(query: InteractionQuery, h2Request: CursorInteractionWriter): void;
|
|
25
27
|
export {};
|
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import http2 from "node:http2";
|
|
2
1
|
import type { CursorRule, McpToolDefinition } from "@oh-my-pi/pi-catalog/discovery/cursor-proto";
|
|
2
|
+
import { CURSOR_CLIENT_VERSION } from "@oh-my-pi/pi-catalog/wire/cursor";
|
|
3
3
|
import { type AgentServerMessage, type ConversationStateStructure } from "@oh-my-pi/pi-catalog/discovery/cursor-proto";
|
|
4
4
|
import { type JsonValue } from "@oh-my-pi/pi-catalog/discovery/protobuf";
|
|
5
5
|
import type { AssistantMessage, Context, CursorExecHandlerResult, CursorExecHandlers, CursorExecPairing, CursorTodoSyncHandler, CursorToolResultHandler, Message, Model, StreamFunction, StreamOptions, TextContent, ThinkingContent, Tool, ToolCall, ToolResultMessage } from "../types.js";
|
|
6
6
|
import { kCursorExecResolved, kStreamingBlockIndex, kStreamingBlockKind, kStreamingEnvelopeId, kStreamingLastParseLen, kStreamingPartialJson } from "../utils/block-symbols.js";
|
|
7
7
|
import { AssistantMessageEventStream } from "../utils/event-stream.js";
|
|
8
8
|
export declare const CURSOR_API_URL = "https://api2.cursor.sh";
|
|
9
|
-
export
|
|
9
|
+
export { CURSOR_CLIENT_VERSION };
|
|
10
10
|
export interface CursorOptions extends StreamOptions {
|
|
11
11
|
customSystemPrompt?: string;
|
|
12
12
|
conversationId?: string;
|
|
@@ -16,28 +16,31 @@ export interface CursorOptions extends StreamOptions {
|
|
|
16
16
|
externalToolExecutor?: boolean;
|
|
17
17
|
/** Wire model id selected after thinking-effort routing (`resolveWireModelId`). */
|
|
18
18
|
wireModelId?: string;
|
|
19
|
+
/** Run transport. `auto` starts with HTTP/2 and falls back on failed ALPN negotiation. */
|
|
20
|
+
transport?: "auto" | "http2" | "http1";
|
|
19
21
|
}
|
|
20
22
|
interface CursorRequestState {
|
|
21
23
|
conversationId: string;
|
|
22
24
|
blobStore: Map<string, Uint8Array>;
|
|
23
25
|
conversationState?: ConversationStateStructure;
|
|
24
|
-
|
|
26
|
+
resume?: boolean;
|
|
25
27
|
}
|
|
26
28
|
interface CursorGrpcRequest {
|
|
27
29
|
requestBytes: Uint8Array;
|
|
28
30
|
blobStore: Map<string, Uint8Array>;
|
|
29
31
|
conversationState: ConversationStateStructure;
|
|
30
32
|
}
|
|
33
|
+
interface CursorMessageWriter {
|
|
34
|
+
write(frame: Uint8Array): void;
|
|
35
|
+
}
|
|
31
36
|
/**
|
|
32
37
|
* Maps an opaque HTTP/2 negotiation failure into an actionable error.
|
|
33
38
|
*
|
|
34
|
-
*
|
|
35
|
-
* TLS-intercepting proxy that strips ALPN
|
|
36
|
-
*
|
|
37
|
-
*
|
|
38
|
-
*
|
|
39
|
-
* proceed. Replace the opaque message with one that names the cause and points
|
|
40
|
-
* at the `providers.cursor.baseUrl` workaround.
|
|
39
|
+
* Bun only opens an HTTP/2 session when TLS-ALPN negotiates `h2`. Behind a
|
|
40
|
+
* TLS-intercepting proxy that strips ALPN, the handshake can fail with
|
|
41
|
+
* `ERR_HTTP2_ERROR: h2 is not supported`. Automatic transport retries the
|
|
42
|
+
* official RunSSE/BidiAppend HTTP/1 path; this mapped error remains observable
|
|
43
|
+
* when a caller explicitly forces HTTP/2.
|
|
41
44
|
*
|
|
42
45
|
* Non-ALPN errors pass through untouched.
|
|
43
46
|
*/
|
|
@@ -106,7 +109,7 @@ export interface UsageState {
|
|
|
106
109
|
sawTokenDelta: boolean;
|
|
107
110
|
}
|
|
108
111
|
/** Exported for tests: drives one Cursor server message through the stream (exec waits mark the stream busy). */
|
|
109
|
-
export declare function handleServerMessage(msg: AgentServerMessage, output: AssistantMessage, stream: AssistantMessageEventStream, state: BlockState, blobStore: Map<string, Uint8Array>,
|
|
112
|
+
export declare function handleServerMessage(msg: AgentServerMessage, output: AssistantMessage, stream: AssistantMessageEventStream, state: BlockState, blobStore: Map<string, Uint8Array>, runTransport: CursorMessageWriter, execHandlers: CursorExecHandlers | undefined, onToolResult: CursorToolResultHandler | undefined, usageState: UsageState, requestContextTools: McpToolDefinition[], requestContextRules?: CursorRule[], onConversationCheckpoint?: (checkpoint: ConversationStateStructure) => void, externalToolExecutor?: boolean): Promise<void>;
|
|
110
113
|
/**
|
|
111
114
|
* Exported for tests: verifies handler is invoked with correct `this` when passed as bound.
|
|
112
115
|
*
|
|
@@ -259,4 +262,3 @@ export declare function buildCursorHistoryForTest(messages: Message[], activeUse
|
|
|
259
262
|
};
|
|
260
263
|
/** Builds the normalized Cursor Run request used by transport callers and request inspection hooks. */
|
|
261
264
|
export declare function buildGrpcRequest(model: Model<"cursor-agent">, context: Context, options: CursorOptions | undefined, state: CursorRequestState): Promise<CursorGrpcRequest>;
|
|
262
|
-
export {};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { RequestPolicy } from "@oh-my-pi/pi-catalog/compat/types";
|
|
2
|
+
import type { Effort } from "@oh-my-pi/pi-catalog/effort";
|
|
3
|
+
import type { Context, Model, StreamOptions } from "../../types.js";
|
|
4
|
+
import { AssistantMessageEventStream } from "../../utils/event-stream.js";
|
|
5
|
+
export interface FactoryDroidGeminiOptions extends StreamOptions {
|
|
6
|
+
/** Base URL including the `/api/llm/g/v1` namespace. */
|
|
7
|
+
baseUrl: string;
|
|
8
|
+
reasoning?: Effort;
|
|
9
|
+
disableReasoning?: boolean;
|
|
10
|
+
/** Additional droid identity headers (merged over the client's own). */
|
|
11
|
+
headers: Record<string, string>;
|
|
12
|
+
/** Thinking dialect selected by the route policy. */
|
|
13
|
+
thinkingDialect?: RequestPolicy["googleThinking"];
|
|
14
|
+
}
|
|
15
|
+
export declare function streamFactoryDroidGemini(model: Model<"factory-droid-agent">, context: Context, options: FactoryDroidGeminiOptions): AssistantMessageEventStream;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { Effort } from "@oh-my-pi/pi-catalog/effort";
|
|
2
|
+
import type { ServiceTier, StreamFunction, StreamOptions, ToolChoice } from "../types.js";
|
|
3
|
+
export interface FactoryDroidOptions extends StreamOptions {
|
|
4
|
+
reasoning?: Effort;
|
|
5
|
+
disableReasoning?: boolean;
|
|
6
|
+
toolChoice?: ToolChoice;
|
|
7
|
+
serviceTier?: ServiceTier;
|
|
8
|
+
/** OMP-native "omit thinking summaries" (anthropic adaptive display). */
|
|
9
|
+
hideThinkingSummary?: boolean;
|
|
10
|
+
/** OMP-native response verbosity (responses wire `text.verbosity`). */
|
|
11
|
+
textVerbosity?: "low" | "medium" | "high";
|
|
12
|
+
}
|
|
13
|
+
export declare const streamFactoryDroid: StreamFunction<"factory-droid-agent">;
|
|
@@ -75,6 +75,7 @@ export declare function isThinkingPart(part: Pick<Part, "thought" | "thoughtSign
|
|
|
75
75
|
* a signature from being overwritten with `undefined` within the same streamed block.
|
|
76
76
|
*/
|
|
77
77
|
export declare function retainThoughtSignature(existing: string | undefined, incoming: string | undefined): string | undefined;
|
|
78
|
+
export declare const SKIP_THOUGHT_SIGNATURE = "skip_thought_signature_validator";
|
|
78
79
|
/**
|
|
79
80
|
* Convert internal messages to Gemini Content[] format.
|
|
80
81
|
*/
|
|
@@ -212,3 +213,14 @@ export declare function streamGoogleGenAI<T extends "google-generative-ai" | "go
|
|
|
212
213
|
retainTextSignature?: boolean;
|
|
213
214
|
prepare: () => GoogleGenAIRequestPlan | Promise<GoogleGenAIRequestPlan>;
|
|
214
215
|
}): AssistantMessageEventStream;
|
|
216
|
+
/**
|
|
217
|
+
* Human-readable message for a non-2xx Google response.
|
|
218
|
+
*
|
|
219
|
+
* On a usage-limit status the RPC `status`/`details` residue is kept after the
|
|
220
|
+
* message: `parseGoogleRpcRateLimitReason` reads `RESOURCE_EXHAUSTED` plus the
|
|
221
|
+
* `google.rpc.ErrorInfo` reason to tell an account billing cap (terminal) from
|
|
222
|
+
* a per-minute throttle (retryable), and reducing the body to `error.message`
|
|
223
|
+
* hid both, so every billing 429 replayed as a transient rate limit (#13090).
|
|
224
|
+
* The Cloud Code Assist path keeps the whole raw body for the same reason.
|
|
225
|
+
*/
|
|
226
|
+
export declare function extractGoogleErrorMessage(errorText: string, status: number): string;
|
|
@@ -231,14 +231,19 @@ export interface ChatCompletionUserMessageParam {
|
|
|
231
231
|
/** Optional participant name. */
|
|
232
232
|
name?: string;
|
|
233
233
|
}
|
|
234
|
+
/** Mistral Medium 3.5 reasoning content part on assistant history. */
|
|
235
|
+
export interface ChatCompletionMistralThinkingPart {
|
|
236
|
+
type: "thinking";
|
|
237
|
+
thinking: ChatCompletionContentPartText[];
|
|
238
|
+
}
|
|
234
239
|
/** Assistant (model) message. */
|
|
235
240
|
export interface ChatCompletionAssistantMessageParam {
|
|
236
241
|
/** Always `assistant`. */
|
|
237
242
|
role: "assistant";
|
|
238
243
|
/** Data about a previous audio response from the model. */
|
|
239
244
|
audio?: ChatCompletionAssistantMessageParamAudio | null;
|
|
240
|
-
/** Message contents.
|
|
241
|
-
content?: string | Array<ChatCompletionContentPartText | ChatCompletionContentPartRefusal> | null;
|
|
245
|
+
/** Message contents. Mistral reasoning uses typed thinking parts in this array. */
|
|
246
|
+
content?: string | Array<ChatCompletionContentPartText | ChatCompletionContentPartRefusal | ChatCompletionMistralThinkingPart> | null;
|
|
242
247
|
/** Deprecated by OpenAI; replaced by `tool_calls`. */
|
|
243
248
|
function_call?: ChatCompletionAssistantMessageParamFunctionCall | null;
|
|
244
249
|
/** Optional participant name. */
|
|
@@ -42,5 +42,5 @@ export interface OpenAICompletionsOptions extends StreamOptions {
|
|
|
42
42
|
* assistant output commits the attempt.
|
|
43
43
|
*/
|
|
44
44
|
export declare const streamOpenAICompletions: StreamFunction<"openai-completions">;
|
|
45
|
-
export declare function parseChunkUsage(rawUsage: object, model: Model<"openai-completions">, premiumRequests: number | undefined, timestamp?: number): AssistantMessage["usage"];
|
|
45
|
+
export declare function parseChunkUsage(rawUsage: object, model: Model<"openai-completions">, premiumRequests: number | undefined, timestamp?: number, cachedTokensHeader?: number): AssistantMessage["usage"];
|
|
46
46
|
export declare function convertMessages(model: Model<"openai-completions">, context: Context, compat: ResolvedOpenAICompat): ChatCompletionMessageParam[];
|
|
@@ -12,8 +12,8 @@ export type OAuthDeviceCodePollResult<T> = {
|
|
|
12
12
|
};
|
|
13
13
|
/** Options for polling an RFC 8628-style OAuth device-code flow. */
|
|
14
14
|
export interface OAuthDeviceCodeFlowOptions<T> {
|
|
15
|
-
/** Poll the provider once and classify the response. */
|
|
16
|
-
poll(): OAuthDeviceCodePollResult<T> | Promise<OAuthDeviceCodePollResult<T>>;
|
|
15
|
+
/** Poll the provider once and classify the response. Signal includes caller cancellation and device-code expiry. */
|
|
16
|
+
poll(signal?: AbortSignal): OAuthDeviceCodePollResult<T> | Promise<OAuthDeviceCodePollResult<T>>;
|
|
17
17
|
/** Provider-requested polling cadence; defaults to RFC 8628's five seconds. */
|
|
18
18
|
intervalSeconds?: number;
|
|
19
19
|
/** Provider-issued expiry window for the device code. */
|
|
@@ -11,13 +11,23 @@ export type OAuthCredentials = {
|
|
|
11
11
|
apiEndpoint?: string;
|
|
12
12
|
/**
|
|
13
13
|
* Organization/workspace the token is scoped to (e.g. an Anthropic org
|
|
14
|
-
* UUID or
|
|
15
|
-
*
|
|
16
|
-
* subscriptions.
|
|
14
|
+
* UUID or canonical Factory org ID). Lets one account email hold
|
|
15
|
+
* credentials for multiple subscriptions.
|
|
17
16
|
*/
|
|
18
17
|
orgId?: string;
|
|
19
18
|
/** Human-readable organization name for display (may embed the email). */
|
|
20
19
|
orgName?: string;
|
|
20
|
+
/**
|
|
21
|
+
* Account residency region (e.g. `"eu"`), when the provider is
|
|
22
|
+
* region-partitioned. Captured at login; refreshed identity may update it
|
|
23
|
+
* when the account migrates, while failed lookups preserve the stored value.
|
|
24
|
+
* Residency selects the API host, not inference eligibility.
|
|
25
|
+
*/
|
|
26
|
+
region?: string;
|
|
27
|
+
/** Factory organization inference scope, independent of account residency. */
|
|
28
|
+
inferenceRegion?: "global" | "eu" | "us";
|
|
29
|
+
/** WorkOS selected organization; never used as a Factory API organization header. */
|
|
30
|
+
activeOrganizationId?: string;
|
|
21
31
|
/**
|
|
22
32
|
* Epoch ms of the interactive login that minted this grant. Set by
|
|
23
33
|
* `AuthStorage.oauth.login`; token refreshes preserve it. Providers with an
|
package/dist/types/types.d.ts
CHANGED
|
@@ -6,6 +6,7 @@ import type { DeleteArgs, DeleteResult, DiagnosticsArgs, DiagnosticsResult, Grep
|
|
|
6
6
|
import type { Effort } from "@oh-my-pi/pi-catalog/effort";
|
|
7
7
|
import type { Api, FetchImpl, Model, Provider, ThinkingBudgets, Usage } from "@oh-my-pi/pi-catalog/types";
|
|
8
8
|
import type { ApiKey } from "./auth-retry.js";
|
|
9
|
+
import type { OAuthRequestIdentity } from "./auth/types.js";
|
|
9
10
|
import type { BedrockOptions } from "./providers/amazon-bedrock.js";
|
|
10
11
|
import type { AnthropicOptions } from "./providers/anthropic.js";
|
|
11
12
|
import type { FallbackParam, StopDetails } from "./providers/anthropic-wire.js";
|
|
@@ -13,6 +14,7 @@ import type { AzureOpenAIResponsesOptions } from "./providers/azure-openai-respo
|
|
|
13
14
|
import type { CursorOptions } from "./providers/cursor.js";
|
|
14
15
|
import type { AppleFoundationModelsOptions } from "./providers/apple-foundation-models.js";
|
|
15
16
|
import type { DevinOptions } from "./providers/devin.js";
|
|
17
|
+
import type { FactoryDroidOptions } from "./providers/factory-droid.js";
|
|
16
18
|
import type { GitLabDuoWorkflowOptions } from "./providers/gitlab-duo-workflow.js";
|
|
17
19
|
import type { GoogleOptions } from "./providers/google.js";
|
|
18
20
|
import type { GoogleGeminiCliOptions } from "./providers/google-gemini-cli.js";
|
|
@@ -49,6 +51,7 @@ export interface ApiOptionsMap {
|
|
|
49
51
|
"google-vertex": GoogleVertexOptions;
|
|
50
52
|
"ollama-chat": OllamaChatOptions;
|
|
51
53
|
"cursor-agent": CursorOptions;
|
|
54
|
+
"factory-droid-agent": FactoryDroidOptions;
|
|
52
55
|
"gitlab-duo-agent": GitLabDuoWorkflowOptions;
|
|
53
56
|
"devin-agent": DevinOptions;
|
|
54
57
|
"apple-foundation-models": AppleFoundationModelsOptions;
|
|
@@ -247,6 +250,8 @@ export interface StreamOptions {
|
|
|
247
250
|
apiKey?: string;
|
|
248
251
|
/** @internal Stored credential row serving this request, when known. */
|
|
249
252
|
credentialId?: number;
|
|
253
|
+
/** @internal Non-secret identity of the bearer serving this attempt; never persisted in history. */
|
|
254
|
+
oauthIdentity?: OAuthRequestIdentity;
|
|
250
255
|
cacheRetention?: CacheRetention;
|
|
251
256
|
/**
|
|
252
257
|
* Anthropic preserved-thinking behavior when a signed block no longer matches
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { CredentialRankingStrategy, UsageProvider, UsageReport } from "../usage.js";
|
|
2
|
+
/**
|
|
3
|
+
* Parses `GET /api/billing/limits` into a usage report: per-pool
|
|
4
|
+
* (Standard credits / Droid Core)
|
|
5
|
+
* × per-window (5h / weekly / monthly) percent-used limits, plus the extra
|
|
6
|
+
* usage balance when present.
|
|
7
|
+
*/
|
|
8
|
+
export declare function parseFactoryDroidUsage(payload: unknown, fetchedAt?: number): UsageReport | null;
|
|
9
|
+
export declare const factoryDroidUsageProvider: UsageProvider;
|
|
10
|
+
/** Factory's Core and Standard credits have independent subscription windows. */
|
|
11
|
+
export declare const factoryDroidRankingStrategy: CredentialRankingStrategy;
|
package/dist/types/usage.d.ts
CHANGED
|
@@ -563,6 +563,10 @@ export interface UsageCredential {
|
|
|
563
563
|
/** Human-readable organization name for display. */
|
|
564
564
|
orgName?: string;
|
|
565
565
|
enterpriseUrl?: string;
|
|
566
|
+
/** Account residency used for region-aware provider routing. */
|
|
567
|
+
region?: string;
|
|
568
|
+
inferenceRegion?: "global" | "eu" | "us";
|
|
569
|
+
activeOrganizationId?: string;
|
|
566
570
|
metadata?: Record<string, unknown>;
|
|
567
571
|
apiEndpoint?: string;
|
|
568
572
|
}
|