@oh-my-pi/pi-ai 18.4.3 → 18.4.5

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.
Files changed (121) hide show
  1. package/CHANGELOG.md +36 -42
  2. package/dist/types/auth/cascade.d.ts +17 -6
  3. package/dist/types/auth/rank.d.ts +7 -1
  4. package/dist/types/auth/refresh.d.ts +8 -0
  5. package/dist/types/auth/types.d.ts +19 -2
  6. package/dist/types/auth-broker/protocol.d.ts +12 -0
  7. package/dist/types/auth-gateway/dispatch.d.ts +7 -7
  8. package/dist/types/auth-gateway/http.d.ts +4 -1
  9. package/dist/types/auth-gateway/types.d.ts +2 -0
  10. package/dist/types/auth-retry.d.ts +3 -1
  11. package/dist/types/dialect/rendering.d.ts +4 -0
  12. package/dist/types/images/shared.d.ts +5 -2
  13. package/dist/types/index.d.ts +1 -0
  14. package/dist/types/providers/anthropic-wire.d.ts +9 -1
  15. package/dist/types/providers/anthropic.d.ts +24 -0
  16. package/dist/types/providers/aws-sigv4.d.ts +5 -0
  17. package/dist/types/providers/bedrock-anthropic.d.ts +9 -0
  18. package/dist/types/providers/bedrock-request-metadata.d.ts +2 -0
  19. package/dist/types/providers/cursor/interaction-query.d.ts +14 -2
  20. package/dist/types/providers/cursor.d.ts +14 -12
  21. package/dist/types/providers/factory-droid/gemini.d.ts +15 -0
  22. package/dist/types/providers/factory-droid.d.ts +13 -0
  23. package/dist/types/providers/google-shared.d.ts +12 -0
  24. package/dist/types/providers/openai-chat-wire.d.ts +9 -4
  25. package/dist/types/providers/openai-codex/request-transformer.d.ts +1 -1
  26. package/dist/types/providers/openai-completions.d.ts +1 -1
  27. package/dist/types/providers/openai-responses-wire.d.ts +2 -2
  28. package/dist/types/providers/xai-base-url.d.ts +17 -0
  29. package/dist/types/registry/oauth/device-code.d.ts +2 -2
  30. package/dist/types/registry/oauth/factory-droid.d.ts +3 -0
  31. package/dist/types/registry/oauth/types.d.ts +13 -3
  32. package/dist/types/types.d.ts +19 -3
  33. package/dist/types/usage/factory-droid.d.ts +11 -0
  34. package/dist/types/usage/shared.d.ts +13 -1
  35. package/dist/types/usage.d.ts +4 -0
  36. package/dist/types/utils/schema/allowlist.d.ts +2 -0
  37. package/dist/types/utils/schema/index.d.ts +1 -0
  38. package/package.json +6 -6
  39. package/src/api-registry.ts +1 -0
  40. package/src/auth/cascade.ts +51 -11
  41. package/src/auth/health.ts +3 -0
  42. package/src/auth/oauth.ts +4 -0
  43. package/src/auth/rank.ts +11 -1
  44. package/src/auth/refresh.ts +27 -2
  45. package/src/auth/select.ts +52 -24
  46. package/src/auth/types.ts +18 -2
  47. package/src/auth/usage-cache.ts +6 -0
  48. package/src/auth/usage.ts +10 -5
  49. package/src/auth-broker/client.ts +1 -12
  50. package/src/auth-broker/protocol.ts +32 -0
  51. package/src/auth-broker/remote-store.ts +4 -40
  52. package/src/auth-broker/server.ts +1 -20
  53. package/src/auth-broker/snapshot-cache.ts +1 -9
  54. package/src/auth-gateway/dispatch.ts +20 -20
  55. package/src/auth-gateway/http.ts +44 -2
  56. package/src/auth-gateway/routes/embeddings.ts +1 -1
  57. package/src/auth-gateway/routes/images.ts +1 -1
  58. package/src/auth-gateway/routes/rerank.ts +1 -1
  59. package/src/auth-gateway/routes/speech.ts +1 -1
  60. package/src/auth-gateway/routes/systemone.ts +1 -1
  61. package/src/auth-gateway/routes/transcriptions.ts +1 -1
  62. package/src/auth-gateway/routes/video.ts +4 -3
  63. package/src/auth-gateway/server.ts +40 -10
  64. package/src/auth-gateway/types.ts +2 -0
  65. package/src/auth-retry.ts +3 -1
  66. package/src/auth-storage.ts +3 -1
  67. package/src/dialect/anthropic.ts +3 -25
  68. package/src/dialect/minimax.ts +3 -24
  69. package/src/dialect/rendering.ts +18 -0
  70. package/src/dialect/xml.ts +3 -19
  71. package/src/images/openai-images.ts +10 -4
  72. package/src/images/shared.ts +9 -4
  73. package/src/index.ts +1 -0
  74. package/src/providers/amazon-bedrock.ts +3 -6
  75. package/src/providers/anthropic-compaction.ts +10 -1
  76. package/src/providers/anthropic-wire.ts +12 -1
  77. package/src/providers/anthropic.ts +184 -31
  78. package/src/providers/aws-sigv4.ts +1 -1
  79. package/src/providers/bedrock-anthropic.ts +30 -0
  80. package/src/providers/bedrock-request-metadata.ts +6 -0
  81. package/src/providers/connect-error-detail.ts +1 -5
  82. package/src/providers/cursor/interaction-query.ts +15 -10
  83. package/src/providers/cursor.ts +996 -326
  84. package/src/providers/factory-droid/droid-identity.md +1 -0
  85. package/src/providers/factory-droid/gemini.ts +538 -0
  86. package/src/providers/factory-droid.ts +623 -0
  87. package/src/providers/google-shared.ts +10 -4
  88. package/src/providers/openai-chat-wire.ts +13 -4
  89. package/src/providers/openai-codex/request-transformer.ts +1 -1
  90. package/src/providers/openai-codex-responses.ts +19 -14
  91. package/src/providers/openai-completions.ts +106 -13
  92. package/src/providers/openai-responses-wire.ts +2 -2
  93. package/src/providers/openai-shared.ts +4 -0
  94. package/src/providers/xai-base-url.ts +32 -0
  95. package/src/registry/engine/device-code.ts +2 -2
  96. package/src/registry/engine/refresh.ts +1 -0
  97. package/src/registry/hooks/device-code.ts +1 -0
  98. package/src/registry/oauth/device-code.ts +19 -3
  99. package/src/registry/oauth/factory-droid.ts +62 -0
  100. package/src/registry/oauth/types.ts +13 -3
  101. package/src/stream.ts +38 -4
  102. package/src/types.ts +40 -4
  103. package/src/usage/claude.ts +4 -11
  104. package/src/usage/cline-pass.ts +2 -14
  105. package/src/usage/cursor.ts +12 -5
  106. package/src/usage/factory-droid.ts +226 -0
  107. package/src/usage/openai-codex.ts +3 -5
  108. package/src/usage/registry.ts +3 -0
  109. package/src/usage/shared.ts +28 -1
  110. package/src/usage/synthetic.ts +4 -40
  111. package/src/usage/umans.ts +8 -36
  112. package/src/usage/xai-oauth.ts +21 -8
  113. package/src/usage/zai.ts +10 -38
  114. package/src/usage.ts +4 -0
  115. package/src/utils/http-inspector.ts +4 -8
  116. package/src/utils/schema/CONSTRAINTS.md +15 -0
  117. package/src/utils/schema/allowlist.ts +160 -0
  118. package/src/utils/schema/index.ts +1 -0
  119. package/src/utils/schema/json-schema-validator.ts +23 -26
  120. package/src/utils/schema/meta-validator.ts +4 -7
  121. package/src/utils/schema/wire.ts +17 -21
package/CHANGELOG.md CHANGED
@@ -2,6 +2,41 @@
2
2
 
3
3
  ## [Unreleased]
4
4
 
5
+ ## [18.4.5] - 2026-09-30
6
+
7
+ ### Added
8
+
9
+ - 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)).
10
+ - `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))
11
+ - 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)).
12
+
13
+ ### Fixed
14
+
15
+ - 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)).
16
+ - 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)).
17
+ - 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)).
18
+ - 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)).
19
+ - 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)).
20
+
21
+ ## [18.4.4] - 2026-09-29
22
+
23
+ ### Added
24
+
25
+ - Added the `ultrafast` service tier. It is sent to the OpenAI API as-is, and to Codex only for models that list it in their discovered service tiers; other providers never receive it. On Codex websockets, switching into or out of `ultrafast` starts a new response chain instead of reusing `previous_response_id`, matching the Codex CLI. Ultrafast turns are costed at standard rates because no Ultrafast price is published yet ([#13782](https://github.com/can1357/oh-my-pi/pull/13782) by [@H4vC](https://github.com/H4vC)).
26
+
27
+ ### Changed
28
+
29
+ - Changed to fall back to adaptive thinking when between_tools is used with xhigh effort
30
+ - xAI requests (`xai`, `xai-oauth` chat and image generation) honor `XAI_BASE_URL` again when the model uses the bundled `https://api.x.ai/v1` endpoint; a custom `baseUrl` from models.yml still wins, and `xai-oauth` OAuth access tokens always stay on the bundled endpoint.
31
+
32
+ ### Fixed
33
+
34
+ - Fixed Claude on Amazon Bedrock's Anthropic Messages routes (`/anthropic` on bedrock-runtime and bedrock-mantle): runtime requests no longer fail with a request-metadata 400, and both routes use Anthropic's on-demand compaction ([#13311](https://github.com/can1357/oh-my-pi/pull/13311) by [@mustafaabidali](https://github.com/mustafaabidali)).
35
+ - `/usage` no longer shows an always-empty `gpt-4 requests` row for Cursor accounts on usage-based plans; the Cursor Models and Other Models meters remain ([#13726](https://github.com/can1357/oh-my-pi/pull/13726) by [@will-bogusz](https://github.com/will-bogusz)).
36
+ - Cursor turns routed through an HTTP proxy now finish instead of hanging after the response completes ([#13724](https://github.com/can1357/oh-my-pi/pull/13724) by [@will-bogusz](https://github.com/will-bogusz)).
37
+ - Fixed Codex requests sending `priority` (and `scale`) to models whose discovered service tiers list other tiers but not that one, matching the Codex CLI; an empty or missing list is treated as not reported, so `priority` is still sent and `/fast` keeps working on accounts whose `/models` lists no tiers (`flex` is always allowed) ([#13782](https://github.com/can1357/oh-my-pi/pull/13782) by [@H4vC](https://github.com/H4vC)).
38
+ - Fixed Codex priority cost: a turn the backend reports as served at `default` is no longer billed at the priority multiplier ([#13782](https://github.com/can1357/oh-my-pi/pull/13782) by [@H4vC](https://github.com/H4vC)).
39
+
5
40
  ## [18.4.3] - 2026-09-28
6
41
 
7
42
  ### Added
@@ -2275,45 +2310,4 @@
2275
2310
 
2276
2311
  - 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`.
2277
2312
 
2278
- ## [15.12.0] - 2026-06-12
2279
-
2280
- ### Fixed
2281
-
2282
- - 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.
2283
-
2284
- ## [15.11.8] - 2026-06-12
2285
-
2286
- ### Breaking Changes
2287
-
2288
- - 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
2289
-
2290
- ### Changed
2291
-
2292
- - 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
2293
-
2294
- ### Removed
2295
-
2296
- - Removed the `statefulResponses` option from `OpenAICodexResponsesOptions`, and SSE stateful mode is no longer controlled by the `PI_CODEX_STATEFUL`-style flag
2297
-
2298
- ### Fixed
2299
-
2300
- - 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
2301
- - 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
2302
-
2303
- ## [15.11.7] - 2026-06-12
2304
-
2305
- ### Added
2306
-
2307
- - Added `requestModelId` and `thinking.suppress` options to `google-gemini-cli` so collapsed effort-tier variants serialize their per-effort upstream wire id, and thinking-off requests on models with `thinking.suppressWhenOff` send an explicit `thinkingConfig` (`includeThoughts: false` with `thinkingLevel: "MINIMAL"` or `thinkingBudget: 0`) — Cloud Code Assist re-applies the per-id baked server default when the config is omitted, silently thinking and billing the tokens
2308
- - Added mandatory-reasoning clamping: models baked with `thinking.requiresEffort` floor omitted or disabled reasoning to the lowest supported effort in every api mapping, and `disableReasoning` no longer emits OpenRouter `reasoning: { enabled: false }` for them — fixes `omp bench` and utility requests 400ing with "Reasoning is mandatory for this endpoint and cannot be disabled" on OpenRouter Gemini 3.x
2309
-
2310
- ### Changed
2311
-
2312
- - Changed `google-gemini-cli` request mapping to route per-request wire ids via `resolveWireModelId`: the session effort picks the backing variant id (collapsed `gemini-3.5-flash` at high → `gemini-3.5-flash-low`; claude pairs route off → bare id, efforts → `-thinking`) while `AssistantMessage.model` and usage attribution stay on the logical id. A thinking budget clamped to zero now falls through to the thinking-off path (off routing plus suppression) instead of only disabling thinking
2313
- - Changed `openai-completions` and `anthropic-messages` to serialize per-request wire ids via `resolveWireModelId`, so collapsed `X`/`X-thinking` pairs on aggregators and custom providers switch to the thinking SKU when reasoning is enabled (previously only `google-gemini-cli` routed effort-tier variants)
2314
-
2315
- ### Fixed
2316
-
2317
- - Fixed `google-gemini-cli` ignoring `Model.requestModelId` when serializing the request model id
2318
-
2319
- Older entries are archived in [packages/ai/CHANGELOG.md@689a3418cb45](https://github.com/can1357/oh-my-pi/blob/689a3418cb45d54a459cde2e1abf3f66f50e47a4/packages/ai/CHANGELOG.md).
2313
+ 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): void;
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): void;
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): void;
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
  /**
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Auth-broker wire-protocol helpers shared by the server and the client store.
3
+ */
4
+ import type { CredentialBlockSnapshot } from "./types.js";
5
+ /** Parse a snapshot `ETag` / `If-None-Match` value (`"N"`, `W/"N"`, or bare `N`) into a generation. */
6
+ export declare function parseGenerationTag(header: string | null): number | undefined;
7
+ /**
8
+ * Canonical order for a credential's block snapshots. The server and the client
9
+ * store both sort with it, because block lists are compared positionally; the
10
+ * `updatedAtMs` tiebreak keeps otherwise-identical blocks in one stable order.
11
+ */
12
+ export declare function compareCredentialBlockSnapshots(a: CredentialBlockSnapshot, b: CredentialBlockSnapshot): number;
@@ -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
- * (an OAuth access token refreshed through the broker when needed) and hands
46
- * it to the client. Returns the key, or the error classification the route
47
- * should encode in its own envelope: storage failures map through
48
- * {@link classifyGatewayError}, a provider without any credential is a 401.
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<string | GatewayErrorClassification>;
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: string, requestSignal: AbortSignal, format: string, peer: string, onResolvedKey?: (apiKey: string) => void): ApiKeyResolver;
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
- export declare function resolvePeer(req: Request): string;
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;
@@ -1,4 +1,5 @@
1
1
  import type { AssistantMessage, Message, ToolCall } from "../types.js";
2
+ import { type ToolArgShape } from "./coercion.js";
2
3
  import type { DialectRenderOptions, DialectToolResult } from "./types.js";
3
4
  export declare function renderToolResponseResults(results: readonly DialectToolResult[]): string;
4
5
  export declare function kimiCallId(name: string, id: string, index: number): string;
@@ -15,6 +16,9 @@ export declare function pyCall(name: string, args: Record<string, unknown>): str
15
16
  export declare function pyValue(value: unknown): string;
16
17
  export declare function escapeXmlAttr(value: string): string;
17
18
  export declare function escapeXmlText(value: string): string;
19
+ /** Render one Anthropic-style `<invoke>`; declared string args stay raw, everything else is JSON. */
20
+ export declare function renderInvoke(call: ToolCall, shape: ToolArgShape | undefined): string;
21
+ export declare function renderInvokes(calls: readonly ToolCall[], tools: NonNullable<DialectRenderOptions["tools"]>): string;
18
22
  export type AssistantTranscriptParts = {
19
23
  readonly text: string;
20
24
  readonly thinking: string;
@@ -10,9 +10,11 @@ export declare function usageFromWire(value: unknown): Usage;
10
10
  export declare function imageBaseUrl(model: Model): string;
11
11
  export declare function modelHeaders(model: Model, signal?: AbortSignal): Promise<Record<string, string>>;
12
12
  export declare function errorMessage(rawText: string): string;
13
+ /** Request URL, or a builder for routes that depend on the bearer (xAI's `XAI_BASE_URL` rule). */
14
+ type ImageRequestUrl = string | ((bearer: string) => string);
13
15
  export declare function postJson(options: {
14
16
  model: Model;
15
- url: string;
17
+ url: ImageRequestUrl;
16
18
  body: unknown;
17
19
  apiKey: ApiKey;
18
20
  fetch: FetchImpl;
@@ -20,7 +22,7 @@ export declare function postJson(options: {
20
22
  }): Promise<unknown>;
21
23
  export declare function postMultipart(options: {
22
24
  model: Model;
23
- url: string;
25
+ url: ImageRequestUrl;
24
26
  body: FormData;
25
27
  apiKey: ApiKey;
26
28
  fetch: FetchImpl;
@@ -32,3 +34,4 @@ export declare function decodeImageResponse(value: unknown, fetch: FetchImpl, si
32
34
  }>;
33
35
  export declare function toDataUrl(image: GeneratedImage): string;
34
36
  export declare function resolveOpenAIImageSize(aspectRatio?: string, imageSize?: string): string | undefined;
37
+ export {};
@@ -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";
@@ -225,7 +225,15 @@ export type ThinkingConfigAdaptive = {
225
225
  /** Preserved-thinking prefix mismatch policy. */
226
226
  block_binding?: ThinkingBlockBinding;
227
227
  };
228
- export type ThinkingConfigParam = ThinkingConfigEnabled | ThinkingConfigDisabled | ThinkingConfigAdaptive;
228
+ /**
229
+ * Sonnet 5.5's replacement for `disabled`: no up-front thinking, progress
230
+ * updates between tool calls only. Takes no other field, and effort above
231
+ * `high` is rejected alongside it.
232
+ */
233
+ export type ThinkingConfigBetweenTools = {
234
+ type: "between_tools";
235
+ };
236
+ export type ThinkingConfigParam = ThinkingConfigEnabled | ThinkingConfigDisabled | ThinkingConfigAdaptive | ThinkingConfigBetweenTools;
229
237
  export type OutputConfig = {
230
238
  /** Adaptive-thinking effort level (effort beta). */
231
239
  effort?: "low" | "medium" | "high" | "xhigh" | "max" | null;
@@ -217,6 +217,30 @@ type SystemBlockOptions = {
217
217
  export declare function buildAnthropicSystemBlocks(systemPrompt: readonly string[] | undefined, options?: SystemBlockOptions): AnthropicSystemBlock[] | undefined;
218
218
  export declare function normalizeExtraBetas(betas?: string[] | string): string[];
219
219
  export declare function buildAnthropicClientOptions(args: AnthropicClientOptionsArgs): AnthropicClientOptionsResult;
220
+ /**
221
+ * True when enabled thinking on `model` is budget thinking
222
+ * (`thinking.type: "enabled"` with `budget_tokens`) rather than adaptive.
223
+ */
224
+ export declare function usesBudgetThinking(model: Model<"anthropic-messages">): boolean;
225
+ /** The most output tokens a request to `model` may ask for (`max_tokens` ceiling). */
226
+ export declare function anthropicOutputLimit(model: Model<"anthropic-messages">): number;
227
+ /**
228
+ * The `max_tokens` and thinking budget of budget thinking: `max_tokens`
229
+ * rises to leave {@link OUTPUT_FALLBACK_BUFFER} visible output tokens after
230
+ * the budget, within `maxAllowedTokens`, and the budget shrinks when that
231
+ * ceiling leaves less (a non-positive budget means the ceiling is too low).
232
+ */
233
+ export declare function budgetThinkingOutput(maxTokens: number | undefined, budgetTokens: number, maxAllowedTokens: number): {
234
+ maxTokens: number;
235
+ budgetTokens: number;
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;
220
244
  /**
221
245
  * A single Anthropic conversation turn, including the mid-conversation
222
246
  * `system` role (Opus 4.8+ and Fable/Mythos 5).
@@ -33,6 +33,11 @@ export interface SignParams {
33
33
  /** Override clock for deterministic tests. */
34
34
  date?: Date;
35
35
  }
36
+ /** Coerce a possibly-ArrayBufferLike-backed `Uint8Array` into one over a fresh
37
+ * `ArrayBuffer`, which is what `crypto.subtle.{digest,sign,importKey}` requires
38
+ * under the strict TS DOM typings. No-op when already strict.
39
+ */
40
+ export declare function asStrict(bytes: Uint8Array): Uint8Array<ArrayBuffer>;
36
41
  export declare function toHex(bytes: Uint8Array): string;
37
42
  export declare function sha256(data: Uint8Array | string): Promise<Uint8Array>;
38
43
  export declare function sha256Hex(data: Uint8Array | string): Promise<string>;
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Fit an Anthropic request body to Bedrock's Anthropic Messages API
3
+ * (`compat.bedrockMessagesApi`): both `/anthropic` routes reject the tool
4
+ * `strict` field, and bedrock-runtime rejects a `metadata.user_id` outside
5
+ * Bedrock's request-metadata pattern. A user id that fits is kept, otherwise
6
+ * its embedded session id, otherwise the metadata is dropped. Mutates and
7
+ * returns `payload`.
8
+ */
9
+ export declare function fitBedrockAnthropicPayload<T>(payload: T): T;
@@ -0,0 +1,2 @@
1
+ /** Check Bedrock's request-metadata character and length limits. Keys must also be nonempty. */
2
+ export declare function isBedrockRequestMetadataValue(value: string): boolean;
@@ -1,5 +1,16 @@
1
- import type http2 from "node:http2";
2
1
  import { type InteractionQuery } from "@oh-my-pi/pi-catalog/discovery/cursor-proto";
2
+ type ProtoUnknownField = {
3
+ no: number;
4
+ wireType: number;
5
+ data: Uint8Array;
6
+ };
7
+ interface CursorInteractionWriter {
8
+ write(frame: Uint8Array): void;
9
+ }
10
+ /** Wrap one Connect-protocol message: 1 flag byte + 4-byte big-endian length + payload. */
11
+ export declare function frameConnectMessage(data: Uint8Array, flags?: number): Buffer;
12
+ /** Well-formed protobuf-es `$unknown` entries on `message`; anything else on the bag is ignored. */
13
+ export declare function protoUnknownFields(message: object): ProtoUnknownField[];
3
14
  /**
4
15
  * Answer a Cursor `interaction_query` so the Run RPC can continue.
5
16
  *
@@ -12,4 +23,5 @@ import { type InteractionQuery } from "@oh-my-pi/pi-catalog/discovery/cursor-pro
12
23
  * Unsupported interactive queries are rejected so the server is not stranded.
13
24
  * VM setup is left unanswered rather than reporting a fake success.
14
25
  */
15
- export declare function handleInteractionQuery(query: InteractionQuery, h2Request: http2.ClientHttp2Stream): void;
26
+ export declare function handleInteractionQuery(query: InteractionQuery, h2Request: CursorInteractionWriter): void;
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 declare const CURSOR_CLIENT_VERSION = "cli-2026.07.23-e383d2b";
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
- rotatedFresh?: boolean;
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
- * bun only opens an HTTP/2 session when TLS-ALPN negotiates `h2`. Behind a
35
- * TLS-intercepting proxy that strips ALPN (e.g. Zscaler), the handshake yields
36
- * no `h2` protocol and bun throws `ERR_HTTP2_ERROR: h2 is not supported`. The
37
- * Cursor run RPC is HTTP/2-only (the ALB rejects HTTP/1.1 with 464), so there
38
- * is no h1 fallback the way model discovery has one — the run simply cannot
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>, h2Request: http2.ClientHttp2Stream, execHandlers: CursorExecHandlers | undefined, onToolResult: CursorToolResultHandler | undefined, usageState: UsageState, requestContextTools: McpToolDefinition[], requestContextRules?: CursorRule[], onConversationCheckpoint?: (checkpoint: ConversationStateStructure) => void, externalToolExecutor?: boolean): Promise<void>;
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;