@oh-my-pi/pi-ai 18.3.0 → 18.3.1
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 +14 -0
- package/THIRD-PARTY-NOTICES.txt +2 -2
- package/dist/types/auth/policy.d.ts +8 -1
- package/dist/types/auth/pool.d.ts +8 -0
- package/dist/types/auth/types.d.ts +17 -7
- package/dist/types/auth/usage.d.ts +2 -0
- package/dist/types/auth-broker/discover.d.ts +22 -1
- package/dist/types/auth-storage.d.ts +35 -11
- package/dist/types/error/rate-limit.d.ts +3 -2
- package/dist/types/index.d.ts +1 -0
- package/dist/types/providers/anthropic-slow-mode.d.ts +94 -0
- package/dist/types/providers/anthropic-wire.d.ts +4 -0
- package/dist/types/providers/mock.d.ts +3 -1
- package/dist/types/providers/openai-codex/live-steering.d.ts +77 -0
- package/dist/types/providers/transform-messages.d.ts +9 -1
- package/dist/types/types.d.ts +55 -0
- package/dist/types/usage/xai-oauth.d.ts +6 -1
- package/dist/types/utils/http-inspector.d.ts +6 -0
- package/package.json +6 -6
- package/src/auth/policy.ts +27 -6
- package/src/auth/pool.ts +35 -2
- package/src/auth/refresh.ts +2 -2
- package/src/auth/types.ts +17 -7
- package/src/auth/usage.ts +5 -0
- package/src/auth-broker/discover.ts +57 -27
- package/src/auth-storage.ts +121 -35
- package/src/error/flags.ts +2 -1
- package/src/error/rate-limit.ts +8 -4
- package/src/index.ts +1 -0
- package/src/providers/anthropic-slow-mode.ts +195 -0
- package/src/providers/anthropic-wire.ts +4 -0
- package/src/providers/anthropic.ts +322 -22
- package/src/providers/cowork-fetch.ts +11 -4
- package/src/providers/google-shared.ts +30 -7
- package/src/providers/inference-headers.ts +7 -1
- package/src/providers/mock.ts +4 -0
- package/src/providers/openai-codex/live-steering.ts +237 -0
- package/src/providers/openai-codex-responses.ts +372 -73
- package/src/providers/transform-messages.ts +27 -7
- package/src/stream.ts +2 -0
- package/src/types.ts +58 -0
- package/src/usage/registry.ts +2 -1
- package/src/usage/xai-oauth.ts +31 -1
- package/src/utils/http-inspector.ts +21 -2
- package/src/utils/openrouter-headers.ts +3 -3
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,20 @@
|
|
|
2
2
|
|
|
3
3
|
## [Unreleased]
|
|
4
4
|
|
|
5
|
+
## [18.3.1] - 2026-09-25
|
|
6
|
+
|
|
7
|
+
### Added
|
|
8
|
+
|
|
9
|
+
- Added live steering support for GPT-6 models, allowing queued user messages to be delivered during an active streaming response.
|
|
10
|
+
- Added the `anthropicSlowMode` stream option for first-party Claude OAuth requests, enabling slow-mode rate-limit handling, per-account rate-limit reporting, and server-paced retries during capacity limits.
|
|
11
|
+
- Added support for capturing and redeeming Anthropic fallback credit tokens, including prompt-cache repricing for classifier refusals.
|
|
12
|
+
- Added Vercel AI Gateway app attribution by sending `http-referer: https://omp.sh/` and `x-title: omp` by default; user-provided header values take precedence.
|
|
13
|
+
|
|
14
|
+
### Fixed
|
|
15
|
+
|
|
16
|
+
- Fixed account selection for OpenCode Go and SuperGrok (xai-oauth) so accounts without available funds or included quota are skipped in favor of eligible accounts.
|
|
17
|
+
- Improved visibility into automatically disabled authentication credentials by logging a warning and including the affected account details in credential-disabled events.
|
|
18
|
+
|
|
5
19
|
## [18.3.0] - 2026-09-24
|
|
6
20
|
|
|
7
21
|
### Added
|
package/THIRD-PARTY-NOTICES.txt
CHANGED
|
@@ -78,8 +78,8 @@ below.
|
|
|
78
78
|
uutils coreutils (https://github.com/uutils/coreutils), MIT
|
|
79
79
|
--------------------------------------------------------------------------------
|
|
80
80
|
Covers: base32, base64, basename, cat, cksum (shared checksum machinery),
|
|
81
|
-
b2sum, md5sum, sha1sum, sha224sum, sha256sum, sha384sum, sha512sum, comm,
|
|
82
|
-
date, dirname, head, hostname, ln, ls, mkdir, mktemp, mv, nproc, paste,
|
|
81
|
+
b2sum, md5sum, sha1sum, sha224sum, sha256sum, sha384sum, sha512sum, comm, cp,
|
|
82
|
+
cut, date, dirname, head, hostname, ln, ls, mkdir, mktemp, mv, nproc, paste,
|
|
83
83
|
printenv, readlink, realpath, rm, seq, sort, stat, tac, tail, tee, touch, tr,
|
|
84
84
|
truncate, uname, uniq, wc, whoami, yes.
|
|
85
85
|
|
|
@@ -4,8 +4,15 @@ export declare function matchesAuthAccountSelector(selector: AuthAccountSelector
|
|
|
4
4
|
/** Validated per-account routing policies (priority/reserve) plus the global reserve fallback. */
|
|
5
5
|
export declare class AccountPolicies {
|
|
6
6
|
#private;
|
|
7
|
-
readonly defaultReservePct: number;
|
|
8
7
|
constructor(policies: AuthAccountPolicies, defaultReservePct: number | undefined);
|
|
8
|
+
/** Global usage reserve (0–100) for accounts without a per-account `reservePct`. */
|
|
9
|
+
get defaultReservePct(): number;
|
|
10
|
+
/**
|
|
11
|
+
* Replace the policy set and global reserve in place (live settings change).
|
|
12
|
+
* Validates the configuration and every provider in `storedCredentials` before
|
|
13
|
+
* committing; on error the previous policies stay active.
|
|
14
|
+
*/
|
|
15
|
+
replace(policies: AuthAccountPolicies, defaultReservePct: number | undefined, storedCredentials?: ReadonlyMap<string, readonly AuthCredential[]>): void;
|
|
9
16
|
validateUsageCapability(provider: string, canFetchUsage: boolean): void;
|
|
10
17
|
validateFor(provider: string, credentials: readonly AuthCredential[]): void;
|
|
11
18
|
/**
|
|
@@ -8,6 +8,8 @@ export type StoredCredential = {
|
|
|
8
8
|
id: number;
|
|
9
9
|
credential: AuthCredential;
|
|
10
10
|
};
|
|
11
|
+
/** {@link CredentialDisabledEvent} for a torn-down row, carrying the account identity it was signed in as. */
|
|
12
|
+
export declare function credentialDisabledEvent(provider: string, row: StoredCredential, disabledCause: string): CredentialDisabledEvent;
|
|
11
13
|
/** Credential equality used for snapshot change detection. */
|
|
12
14
|
export declare function authCredentialEquals(left: AuthCredential, right: AuthCredential): boolean;
|
|
13
15
|
/** Dependencies for credential validation, corruption handling, and assignment reset. */
|
|
@@ -61,6 +63,12 @@ export declare class CredentialPool implements CredentialsApi {
|
|
|
61
63
|
* one extra `data_version` read and no second reload.
|
|
62
64
|
*/
|
|
63
65
|
adoptExternalChanges(): Promise<void>;
|
|
66
|
+
/**
|
|
67
|
+
* Take over the subscribers, buffered disable events, and generation counter of
|
|
68
|
+
* the pool this one replaces (store swap). Listener sets are shared, so
|
|
69
|
+
* unsubscribe functions handed out by `previous` keep working.
|
|
70
|
+
*/
|
|
71
|
+
adoptSubscribers(previous: CredentialPool): void;
|
|
64
72
|
onGeneration(listener: (generation: number) => void): () => void;
|
|
65
73
|
bump(reason: string): void;
|
|
66
74
|
/**
|
|
@@ -251,9 +251,11 @@ export interface AuthCredentialSnapshot {
|
|
|
251
251
|
/**
|
|
252
252
|
* Event payload describing a credential that was just soft-disabled.
|
|
253
253
|
*
|
|
254
|
-
*
|
|
255
|
-
* (`invalid_grant`, `401/403` not from a network blip, etc.)
|
|
256
|
-
*
|
|
254
|
+
* Fired for automatic disables: a definitive OAuth refresh failure
|
|
255
|
+
* (`invalid_grant`, `401/403` not from a network blip, etc.), an upstream
|
|
256
|
+
* token invalidation, and an auth-broker disable. The disabled_cause string is
|
|
257
|
+
* the verbatim error captured for forensics. Every emission is also logged as
|
|
258
|
+
* a warning.
|
|
257
259
|
*
|
|
258
260
|
* Subscribers can use this to surface a notification, banner, or auto-launch
|
|
259
261
|
* a re-login flow instead of letting the credential silently disappear.
|
|
@@ -261,6 +263,14 @@ export interface AuthCredentialSnapshot {
|
|
|
261
263
|
export interface CredentialDisabledEvent {
|
|
262
264
|
provider: string;
|
|
263
265
|
disabledCause: string;
|
|
266
|
+
/** Database row id of the disabled credential (matches {@link StoredAuthCredential.id}). */
|
|
267
|
+
credentialId?: number;
|
|
268
|
+
/** Account identity recorded on the disabled OAuth credential, when the provider supplied one. */
|
|
269
|
+
email?: string;
|
|
270
|
+
accountId?: string;
|
|
271
|
+
/** Organization/workspace the credential was scoped to (Anthropic/ChatGPT multi-subscription). */
|
|
272
|
+
orgId?: string;
|
|
273
|
+
orgName?: string;
|
|
264
274
|
}
|
|
265
275
|
/** Configuration supplied when constructing credential storage. */
|
|
266
276
|
export type AuthStorageOptions = {
|
|
@@ -280,10 +290,10 @@ export type AuthStorageOptions = {
|
|
|
280
290
|
configValueResolver?: (config: string) => Promise<string | undefined>;
|
|
281
291
|
/**
|
|
282
292
|
* Optional callback fired when AuthStorage automatically disables a
|
|
283
|
-
* credential because something detected it as no longer usable
|
|
284
|
-
*
|
|
285
|
-
*
|
|
286
|
-
*
|
|
293
|
+
* credential because something detected it as no longer usable (see
|
|
294
|
+
* {@link CredentialDisabledEvent}). NOT fired for user-initiated `remove()`
|
|
295
|
+
* (the user already knows) or dedup of duplicate credentials
|
|
296
|
+
* (uninteresting hygiene).
|
|
287
297
|
*/
|
|
288
298
|
onCredentialDisabled?: (event: CredentialDisabledEvent) => void | Promise<void>;
|
|
289
299
|
/**
|
|
@@ -53,6 +53,8 @@ export declare class UsageService implements UsageApi {
|
|
|
53
53
|
* built-in fallback. Removing the override restores that resolver unchanged.
|
|
54
54
|
*/
|
|
55
55
|
setProvider(provider: Provider, usageProvider: UsageProvider, apiKey?: string): void;
|
|
56
|
+
/** Carry runtime usage provider overrides over from the service this one replaces (store swap). */
|
|
57
|
+
adoptRuntimeProviders(previous: UsageService): void;
|
|
56
58
|
/** Remove a runtime usage provider override and restore configured/default resolution. */
|
|
57
59
|
removeProvider(provider: Provider): void;
|
|
58
60
|
/** Preserve the persisted OAuth row's login anchor and subtype metadata on usage-path refresh. */
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type AuthAccountPolicies, AuthStorage, type AuthStorageOptions } from "../auth-storage.js";
|
|
1
|
+
import { type AuthAccountPolicies, type AuthCredentialStore, AuthStorage, type AuthStorageOptions } from "../auth-storage.js";
|
|
2
2
|
import { type AuthBrokerAccountPool } from "./remote-store.js";
|
|
3
3
|
export interface AuthBrokerClientConfig {
|
|
4
4
|
url: string;
|
|
@@ -44,6 +44,27 @@ export declare function loadAuthBrokerAccountPool(): Promise<AuthBrokerAccountPo
|
|
|
44
44
|
* available, matching the TUI behavior.
|
|
45
45
|
*/
|
|
46
46
|
export declare function resolveAuthBrokerConfig(options?: ResolveAuthBrokerConfigOptions): Promise<AuthBrokerClientConfig | null>;
|
|
47
|
+
export interface OpenAuthCredentialStoreOptions {
|
|
48
|
+
/** Broker to connect to; `null` opens the local SQLite store under `agentDir`. */
|
|
49
|
+
brokerConfig: AuthBrokerClientConfig | null;
|
|
50
|
+
agentDir?: string;
|
|
51
|
+
cachePath?: string;
|
|
52
|
+
sourceLabel?: string;
|
|
53
|
+
/** Programmatic pool for SDK hosts. Takes precedence over the environment file. */
|
|
54
|
+
accountPool?: AuthBrokerAccountPool;
|
|
55
|
+
}
|
|
56
|
+
/** Credential store opened by {@link openAuthCredentialStore} plus its diagnostics label. */
|
|
57
|
+
export interface OpenedAuthCredentialStore {
|
|
58
|
+
store: AuthCredentialStore;
|
|
59
|
+
sourceLabel: string;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Open the credential store {@link discoverAuthStorage} would use for
|
|
63
|
+
* `brokerConfig`: the remote broker store (fails fast when the broker has no
|
|
64
|
+
* usable snapshot) or the local SQLite store. Also feeds
|
|
65
|
+
* {@link AuthStorage.replaceStore} when broker settings change at runtime.
|
|
66
|
+
*/
|
|
67
|
+
export declare function openAuthCredentialStore(options: OpenAuthCredentialStoreOptions): Promise<OpenedAuthCredentialStore>;
|
|
47
68
|
/**
|
|
48
69
|
* Create an AuthStorage instance, using the broker when configured and falling
|
|
49
70
|
* back to the local SQLite store otherwise. This is the single source of truth
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { AuthCredentialStore } from "./auth/store.js";
|
|
2
|
-
import type { AuthApiKeyOptions, AuthStorageOptions, BlocksApi, CredentialsApi, HealthApi, KeysApi, LimitsApi, OAuthApi, ResetsApi, SessionsApi, UsageApi } from "./auth/types.js";
|
|
2
|
+
import type { AuthAccountPolicies, AuthApiKeyOptions, AuthStorageOptions, BlocksApi, CredentialsApi, HealthApi, KeysApi, LimitsApi, OAuthApi, ResetsApi, SessionsApi, UsageApi } from "./auth/types.js";
|
|
3
3
|
export { isSqliteBusyError, isSqliteCorruptionError, SqliteAuthCredentialStore } from "./auth/sqlite-credential-store.js";
|
|
4
4
|
export * from "./auth/store.js";
|
|
5
5
|
export * from "./auth/types.js";
|
|
@@ -7,28 +7,52 @@ export * from "./auth/types.js";
|
|
|
7
7
|
* Credential management over an {@link AuthCredentialStore}: multi-account
|
|
8
8
|
* selection with usage-aware ranking, rate-limit blocks, OAuth refresh, and
|
|
9
9
|
* usage reporting. See the module doc for the namespace layout.
|
|
10
|
+
*
|
|
11
|
+
* Namespaces resolve against the current store on every access, so holders of
|
|
12
|
+
* this instance follow {@link AuthStorage.replaceStore} without re-wiring.
|
|
10
13
|
*/
|
|
11
14
|
export declare class AuthStorage {
|
|
12
15
|
#private;
|
|
16
|
+
constructor(store: AuthCredentialStore, options?: AuthStorageOptions);
|
|
13
17
|
/** Stored credential rows, change/disable events, broker snapshot. */
|
|
14
|
-
|
|
18
|
+
get credentials(): CredentialsApi;
|
|
15
19
|
/** Provider auth cascade and key overrides. */
|
|
16
|
-
|
|
20
|
+
get keys(): KeysApi;
|
|
17
21
|
/** OAuth login, account access, listings, refresh. */
|
|
18
|
-
|
|
22
|
+
get oauth(): OAuthApi;
|
|
19
23
|
/** Session → account pins. */
|
|
20
|
-
|
|
24
|
+
get sessions(): SessionsApi;
|
|
21
25
|
/** Usage reports, header ingestion, history. */
|
|
22
|
-
|
|
26
|
+
get usage(): UsageApi;
|
|
23
27
|
/** Model pool health and per-credential probes. */
|
|
24
|
-
|
|
28
|
+
get health(): HealthApi;
|
|
25
29
|
/** Usage-limit marking and credential rotation. */
|
|
26
|
-
|
|
30
|
+
get limits(): LimitsApi;
|
|
27
31
|
/** Saved rate-limit resets. */
|
|
28
|
-
|
|
32
|
+
get resets(): ResetsApi;
|
|
29
33
|
/** Persisted rate-limit blocks (auth-broker server seam). */
|
|
30
|
-
|
|
31
|
-
|
|
34
|
+
get blocks(): BlocksApi;
|
|
35
|
+
/**
|
|
36
|
+
* Apply new account routing policy (live `auth.accountPolicies` /
|
|
37
|
+
* `retry.usageReservePct` change). Throws a configuration error, leaving the
|
|
38
|
+
* active policy untouched, when the policy is malformed or does not match the
|
|
39
|
+
* stored OAuth accounts.
|
|
40
|
+
*/
|
|
41
|
+
setAccountPolicies(config: {
|
|
42
|
+
accountPolicies: AuthAccountPolicies;
|
|
43
|
+
defaultReservePct: number;
|
|
44
|
+
}): void;
|
|
45
|
+
/**
|
|
46
|
+
* Swap the backing credential store in place (live `auth.broker.url` change).
|
|
47
|
+
* Loads `store` into fresh store-bound state — pins, blocks, and usage caches are
|
|
48
|
+
* keyed by the old store's row ids — then closes the previous store. Runtime key
|
|
49
|
+
* overrides, account policies, usage-provider overrides, and credential event
|
|
50
|
+
* subscribers carry over. On a load failure `store` is closed and the current
|
|
51
|
+
* store stays active.
|
|
52
|
+
*/
|
|
53
|
+
replaceStore(store: AuthCredentialStore, options?: {
|
|
54
|
+
sourceLabel?: string;
|
|
55
|
+
}): Promise<void>;
|
|
32
56
|
/** Open the SQLite store at `dbPath` and wrap it (standalone use, e.g. the pi-ai CLI). */
|
|
33
57
|
static create(dbPath: string, options?: AuthStorageOptions): Promise<AuthStorage>;
|
|
34
58
|
/** Close the underlying credential store; the instance must not be reused. */
|
|
@@ -26,8 +26,9 @@ export declare function calculateRateLimitBackoffMs(reason: RateLimitReason): nu
|
|
|
26
26
|
* account-local usage cap rather than a bad credential or a transient blip.
|
|
27
27
|
* HTTP 402 Payment Required represents an account-billing cap (xAI
|
|
28
28
|
* Grok Build "usage balance exhausted", DeepSeek "Insufficient Balance",
|
|
29
|
-
* OpenRouter credit exhaustion)
|
|
30
|
-
*
|
|
29
|
+
* OpenCode Go "Insufficient account funds", OpenRouter credit exhaustion)
|
|
30
|
+
* when opaque, payment/deactivation/balance/funds-worded, or
|
|
31
|
+
* QUOTA_EXHAUSTED/CONCURRENT_LIMIT. Informative non-quota 402s (e.g.
|
|
31
32
|
* endpoint subscription requirements) remain non-usage-limits. Always combine
|
|
32
33
|
* with {@link isUsageLimitOutcome} when a message is available.
|
|
33
34
|
*/
|
package/dist/types/index.d.ts
CHANGED
|
@@ -21,6 +21,7 @@ export * from "./providers/anthropic-identity.js";
|
|
|
21
21
|
export * from "./providers/anthropic-state.js";
|
|
22
22
|
export type * from "./providers/anthropic-client.js";
|
|
23
23
|
export * from "./providers/anthropic-user-profiles.js";
|
|
24
|
+
export * from "./providers/anthropic-slow-mode.js";
|
|
24
25
|
export type * from "./providers/apple-foundation-models.js";
|
|
25
26
|
export type * from "./providers/azure-openai-responses.js";
|
|
26
27
|
export type * from "./providers/cursor.js";
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Anthropic subscription "slow mode" (Claude Code's `/low-priority`).
|
|
3
|
+
*
|
|
4
|
+
* After a Claude subscription account hits its 5-hour session limit, Anthropic
|
|
5
|
+
* may offer to keep serving it on spare capacity. A request opts in with
|
|
6
|
+
* `anthropic-usage-limit: slow`; the server reports the lane state back in
|
|
7
|
+
* `anthropic-ratelimit-unified-slow-*` response headers, and answers "no spare
|
|
8
|
+
* capacity right now" with a 429 `slot_busy` or a 529 overload that the client
|
|
9
|
+
* retries after the server-stated interval.
|
|
10
|
+
*
|
|
11
|
+
* This module owns the wire contract only (header names, parsing). The mode's
|
|
12
|
+
* state machine lives with the caller, which plugs into the Anthropic provider
|
|
13
|
+
* through {@link AnthropicSlowModeHooks}.
|
|
14
|
+
*/
|
|
15
|
+
import type { HeadersLike } from "../utils/retry-after.js";
|
|
16
|
+
/** Request header that opts a first-party OAuth request into the slow lane. */
|
|
17
|
+
export declare const ANTHROPIC_USAGE_LIMIT_HEADER = "anthropic-usage-limit";
|
|
18
|
+
/** {@link ANTHROPIC_USAGE_LIMIT_HEADER} value selecting the slow lane. */
|
|
19
|
+
export declare const ANTHROPIC_SLOW_USAGE_LIMIT = "slow";
|
|
20
|
+
/** Server-side experiment arm; only `treatment` accounts may enter the slow lane. */
|
|
21
|
+
export type AnthropicSlowOffer = "treatment" | "control";
|
|
22
|
+
/** `anthropic-ratelimit-unified-slow-status` values; unknown strings map to `unrecognized`. */
|
|
23
|
+
export type AnthropicSlowStatus = "active" | "not_needed" | "slot_busy" | "weekly_limit" | "budget_exhausted" | "ineligible" | "off" | "unrecognized";
|
|
24
|
+
/** Slow-lane facts carried by one Anthropic response (success or error). */
|
|
25
|
+
export interface AnthropicSlowModeSignal {
|
|
26
|
+
offer?: AnthropicSlowOffer;
|
|
27
|
+
status?: AnthropicSlowStatus;
|
|
28
|
+
/** Server-stated interval between capacity retries. */
|
|
29
|
+
retryAfterMs?: number;
|
|
30
|
+
/** Server-stated ceiling on total time spent waiting for capacity. */
|
|
31
|
+
maxWaitMs?: number;
|
|
32
|
+
/** Fraction (0..1) of the weekly slow-lane allowance already used. */
|
|
33
|
+
budgetUtilization?: number;
|
|
34
|
+
/** Epoch seconds when the slow-lane allowance resets. */
|
|
35
|
+
budgetResetAtSec?: number;
|
|
36
|
+
/** Epoch seconds of `anthropic-ratelimit-unified-reset` (the limit that was hit). */
|
|
37
|
+
unifiedResetAtSec?: number;
|
|
38
|
+
/** Epoch seconds of the 5-hour window reset. */
|
|
39
|
+
fiveHourResetAtSec?: number;
|
|
40
|
+
/** Epoch seconds of the weekly window reset. */
|
|
41
|
+
weeklyResetAtSec?: number;
|
|
42
|
+
/** True when the response carries unified usage-limit claim headers (a limit wall). */
|
|
43
|
+
unifiedLimitClaim: boolean;
|
|
44
|
+
/** True when extra usage (overage) is serving this account. */
|
|
45
|
+
overageInUse: boolean;
|
|
46
|
+
}
|
|
47
|
+
/** One pre-content failure the provider hands to {@link AnthropicSlowModeHooks.onFailure}. */
|
|
48
|
+
export interface AnthropicSlowModeFailure {
|
|
49
|
+
/** Account lane of the failed request (see {@link AnthropicSlowModeHooks}). */
|
|
50
|
+
lane: string;
|
|
51
|
+
httpStatus?: number;
|
|
52
|
+
/** 529 or an `overloaded_error` envelope. */
|
|
53
|
+
overloaded: boolean;
|
|
54
|
+
signal?: AnthropicSlowModeSignal;
|
|
55
|
+
/** Whether the failed request carried `anthropic-usage-limit: slow`. */
|
|
56
|
+
sentSlow: boolean;
|
|
57
|
+
/** Milliseconds this request has already spent waiting for slow-lane capacity. */
|
|
58
|
+
waitedMs: number;
|
|
59
|
+
/** Capacity waits already taken by this request. */
|
|
60
|
+
attempts: number;
|
|
61
|
+
}
|
|
62
|
+
/** Retry decision returned by {@link AnthropicSlowModeHooks.onFailure}. */
|
|
63
|
+
export interface AnthropicSlowModeRetry {
|
|
64
|
+
/** Delay before resending; `0` resends immediately. */
|
|
65
|
+
delayMs: number;
|
|
66
|
+
/** True when the delay is a capacity wait (counts toward the max-wait budget). */
|
|
67
|
+
capacityWait: boolean;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Caller-owned slow-mode state machine. The Anthropic provider only consults
|
|
71
|
+
* it for first-party OAuth requests (`api.anthropic.com` with a subscription
|
|
72
|
+
* bearer); every other route ignores it.
|
|
73
|
+
*
|
|
74
|
+
* Slow-lane state belongs to one Claude account, so every call carries a
|
|
75
|
+
* `lane` key identifying the credential that served the request: `cred:<id>`
|
|
76
|
+
* for a stored credential, else `key:<hash>` of the bearer.
|
|
77
|
+
*/
|
|
78
|
+
export interface AnthropicSlowModeHooks {
|
|
79
|
+
/** Whether the next request on `lane` should carry `anthropic-usage-limit: slow`. */
|
|
80
|
+
isActive(lane: string): boolean;
|
|
81
|
+
/** Observe the slow-lane headers of a successful (2xx) response on `lane`. */
|
|
82
|
+
observe(signal: AnthropicSlowModeSignal, lane: string): void;
|
|
83
|
+
/**
|
|
84
|
+
* Decide how to react to a failure that arrived before any content. Return
|
|
85
|
+
* a retry to resend the request (with or without the slow header, per
|
|
86
|
+
* {@link isActive}), or `undefined` to let normal error handling run.
|
|
87
|
+
*/
|
|
88
|
+
onFailure(failure: AnthropicSlowModeFailure): AnthropicSlowModeRetry | undefined | Promise<AnthropicSlowModeRetry | undefined>;
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Parse the slow-lane and unified-limit headers relevant to slow mode.
|
|
92
|
+
* Returns `undefined` when the response carries none of them.
|
|
93
|
+
*/
|
|
94
|
+
export declare function parseAnthropicSlowModeHeaders(headers: HeadersLike): AnthropicSlowModeSignal | undefined;
|
|
@@ -298,6 +298,8 @@ export type MessageCreateParams = {
|
|
|
298
298
|
* header: `server-side-fallback-2026-06-01`.
|
|
299
299
|
*/
|
|
300
300
|
fallbacks?: FallbackParam[];
|
|
301
|
+
/** Fallback credit token redeemed from a prior refusal (`fallback-credit-2026-06-01` / `fallback-credit-2026-07-01`). */
|
|
302
|
+
fallback_credit_token?: string;
|
|
301
303
|
};
|
|
302
304
|
export type MessageCreateParamsStreaming = MessageCreateParams & {
|
|
303
305
|
stream: true;
|
|
@@ -404,6 +406,8 @@ export type StopDetails = {
|
|
|
404
406
|
type: string;
|
|
405
407
|
category?: string | null;
|
|
406
408
|
explanation?: string | null;
|
|
409
|
+
fallback_credit_token?: string | null;
|
|
410
|
+
fallback_has_prefill_claim?: boolean | null;
|
|
407
411
|
};
|
|
408
412
|
export type MessageDelta = {
|
|
409
413
|
stop_reason?: StopReason | null;
|
|
@@ -41,7 +41,7 @@
|
|
|
41
41
|
* // Inspect calls afterwards.
|
|
42
42
|
* expect(mock.calls).toHaveLength(2);
|
|
43
43
|
*/
|
|
44
|
-
import type { Api, Context, Model, SimpleStreamOptions, StopDetails, StopReason, Usage } from "../types.js";
|
|
44
|
+
import type { AnthropicFallbackCreditHandle, Api, Context, Model, SimpleStreamOptions, StopDetails, StopReason, Usage } from "../types.js";
|
|
45
45
|
import { AssistantMessageEventStream } from "../utils/event-stream.js";
|
|
46
46
|
/** The API string this provider serves. */
|
|
47
47
|
export declare const MOCK_API: "mock";
|
|
@@ -70,6 +70,8 @@ export interface MockResponse {
|
|
|
70
70
|
stopReason?: StopReason;
|
|
71
71
|
/** Structured terminal stop classification, e.g. Anthropic refusal metadata. */
|
|
72
72
|
stopDetails?: StopDetails | null;
|
|
73
|
+
/** In-memory fallback credit handle attached when a refusal response carries a fallback credit token. */
|
|
74
|
+
fallbackCreditHandle?: AnthropicFallbackCreditHandle;
|
|
73
75
|
/** Error text paired with an explicit `"error"` stop reason. */
|
|
74
76
|
errorMessage?: string;
|
|
75
77
|
/** Usage stats. Missing fields default to 0; missing `cost.total` is recomputed from components. */
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import type { LiveSteering, UserMessage } from "../../types.js";
|
|
2
|
+
import type { InputItem } from "./request-transformer.js";
|
|
3
|
+
/** Server acknowledgement of one `response.steer` submission. */
|
|
4
|
+
export type CodexSteerAck = {
|
|
5
|
+
accepted: true;
|
|
6
|
+
id: string;
|
|
7
|
+
} | {
|
|
8
|
+
accepted: false;
|
|
9
|
+
code?: string;
|
|
10
|
+
message?: string;
|
|
11
|
+
};
|
|
12
|
+
/** Socket surface the pump submits through. */
|
|
13
|
+
export interface CodexSteerSocket {
|
|
14
|
+
/** Sends `response.steer`; resolves on the matching acknowledgement, rejects when the socket closes first. */
|
|
15
|
+
steer(previousResponseId: string, input: InputItem[]): Promise<CodexSteerAck>;
|
|
16
|
+
}
|
|
17
|
+
/** Steering the server accepted, with the exact input items it queued. */
|
|
18
|
+
export interface CodexAcceptedSteer {
|
|
19
|
+
id: string;
|
|
20
|
+
items: InputItem[];
|
|
21
|
+
}
|
|
22
|
+
/** What a finished pump delivered into its response. */
|
|
23
|
+
export interface CodexSteerOutcome {
|
|
24
|
+
responseId: string | undefined;
|
|
25
|
+
accepted: CodexAcceptedSteer[];
|
|
26
|
+
/**
|
|
27
|
+
* A submission ended without an acknowledgement, so the server may or may
|
|
28
|
+
* not hold it. The caller must drop the socket rather than chain from it.
|
|
29
|
+
*/
|
|
30
|
+
uncertain: boolean;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Submits caller steering to one in-flight response. Stops after the first
|
|
34
|
+
* rejection: the server only rejects when the response no longer accepts input,
|
|
35
|
+
* and later submissions would reorder the caller's input.
|
|
36
|
+
*/
|
|
37
|
+
export declare class CodexSteerPump {
|
|
38
|
+
#private;
|
|
39
|
+
constructor(source: LiveSteering, socket: CodexSteerSocket, toInput: (messages: readonly UserMessage[]) => InputItem[] | undefined);
|
|
40
|
+
/** The response this pump steers, once started. */
|
|
41
|
+
get responseId(): string | undefined;
|
|
42
|
+
/** Starts submitting steering to `responseId`; later calls are ignored. */
|
|
43
|
+
start(responseId: string): void;
|
|
44
|
+
/** Stops claiming input, settles the submission in flight, and reports what the server accepted. */
|
|
45
|
+
finish(): Promise<CodexSteerOutcome>;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Converted steering input, or `undefined` when an item is not a plain user
|
|
49
|
+
* message (the only shape `response.steer` accepts).
|
|
50
|
+
*/
|
|
51
|
+
export declare function toSteerInputItems(items: readonly InputItem[]): InputItem[] | undefined;
|
|
52
|
+
/** How the request after a steered response continues on the server. */
|
|
53
|
+
export type CodexSteerPlan =
|
|
54
|
+
/** The server continues on its own: read its successor, send nothing. */
|
|
55
|
+
{
|
|
56
|
+
kind: "attach";
|
|
57
|
+
}
|
|
58
|
+
/** The server awaits tool output: send only `input`; it prepends the accepted steering itself. */
|
|
59
|
+
| {
|
|
60
|
+
kind: "create";
|
|
61
|
+
input: InputItem[];
|
|
62
|
+
}
|
|
63
|
+
/** The request cannot line up with the server's queue: drop the socket and replay in full. */
|
|
64
|
+
| {
|
|
65
|
+
kind: "discard";
|
|
66
|
+
};
|
|
67
|
+
/**
|
|
68
|
+
* Line the next request up with steering the server accepted for the previous
|
|
69
|
+
* response.
|
|
70
|
+
*
|
|
71
|
+
* `delta` is the chained input (new items after the previous response), or
|
|
72
|
+
* `undefined` when the chain broke. The accepted steering must appear in it, in
|
|
73
|
+
* order; what remains decides the plan: nothing means the server's automatic
|
|
74
|
+
* successor is exactly this request, tool output means the server is waiting
|
|
75
|
+
* for it, anything else runs concurrently with a successor and cannot be sent.
|
|
76
|
+
*/
|
|
77
|
+
export declare function planSteeredRequest(delta: readonly InputItem[] | undefined, steering: readonly InputItem[]): CodexSteerPlan;
|
|
@@ -18,12 +18,20 @@ import type { Api, AssistantMessage, Message, Model } from "../types.js";
|
|
|
18
18
|
*/
|
|
19
19
|
export declare const SENSITIVE_TOKEN_RE: RegExp;
|
|
20
20
|
/**
|
|
21
|
-
* Toggle outbound credential-pattern redaction
|
|
21
|
+
* Toggle process-wide outbound credential-pattern redaction (requests outside
|
|
22
|
+
* any {@link withCredentialRedaction} scope). When disabled (the default),
|
|
22
23
|
* {@link redactSensitiveCredentials} and {@link redactSensitiveInObject} are
|
|
23
24
|
* pass-throughs and outbound messages/system prompts leave the process
|
|
24
25
|
* unmodified.
|
|
25
26
|
*/
|
|
26
27
|
export declare function configureCredentialRedaction(enabled: boolean): void;
|
|
28
|
+
/**
|
|
29
|
+
* Runs `fn` with outbound credential-pattern redaction forced on or off for
|
|
30
|
+
* every request it starts (including the async work those requests spawn),
|
|
31
|
+
* overriding {@link configureCredentialRedaction}. Lets concurrent sessions in
|
|
32
|
+
* one process each apply their own policy.
|
|
33
|
+
*/
|
|
34
|
+
export declare function withCredentialRedaction<T>(enabled: boolean, fn: () => T): T;
|
|
27
35
|
export declare function redactSensitiveCredentials(text: string): string;
|
|
28
36
|
export declare function redactSensitiveInObject(val: unknown): {
|
|
29
37
|
result: unknown;
|
package/dist/types/types.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
export * from "@oh-my-pi/pi-catalog/effort";
|
|
2
2
|
export * from "@oh-my-pi/pi-catalog/types";
|
|
3
3
|
import type { Type } from "@oh-my-pi/omptype";
|
|
4
|
+
import type { AnthropicSlowModeHooks } from "./providers/anthropic-slow-mode.js";
|
|
4
5
|
import type { DeleteArgs, DeleteResult, DiagnosticsArgs, DiagnosticsResult, GrepArgs, GrepResult, LsArgs, LsResult, McpResult, PiBashExecArgs, PiBashExecResult, PiEditExecArgs, PiEditExecResult, PiFindExecArgs, PiFindExecResult, PiGrepExecArgs, PiGrepExecResult, PiLsExecArgs, PiLsExecResult, PiReadExecArgs, PiReadExecResult, PiWriteExecArgs, PiWriteExecResult, ReadArgs, ReadResult, ShellArgs, ShellResult, WriteArgs, WriteResult } from "@oh-my-pi/pi-catalog/discovery/cursor-proto";
|
|
5
6
|
import type { Effort } from "@oh-my-pi/pi-catalog/effort";
|
|
6
7
|
import type { Api, FetchImpl, Model, Provider, ThinkingBudgets, Usage } from "@oh-my-pi/pi-catalog/types";
|
|
@@ -338,6 +339,13 @@ export interface StreamOptions {
|
|
|
338
339
|
* Providers can use this to persist transport/session state between turns.
|
|
339
340
|
*/
|
|
340
341
|
providerSessionState?: Map<string, ProviderSessionState>;
|
|
342
|
+
/**
|
|
343
|
+
* Source of user steering a provider may deliver into the response it is
|
|
344
|
+
* streaming (OpenAI Responses `response.steer` over the Codex WebSocket).
|
|
345
|
+
* Providers without mid-response input ignore it; unclaimed steering stays
|
|
346
|
+
* with the caller for its next request.
|
|
347
|
+
*/
|
|
348
|
+
liveSteering?: LiveSteering;
|
|
341
349
|
/** Canonical Codex compaction classification; ignored by other providers. */
|
|
342
350
|
codexCompaction?: CodexCompactionRequestContext;
|
|
343
351
|
/** Codex Code Mode tool exposure snapshot emitted as `tool_namespaces_info` turn metadata; ignored by other providers. */
|
|
@@ -428,6 +436,39 @@ export interface StreamOptions {
|
|
|
428
436
|
cwd?: string;
|
|
429
437
|
/** Cursor exec/MCP tool handlers (cursor-agent only). */
|
|
430
438
|
execHandlers?: CursorExecHandlers;
|
|
439
|
+
/**
|
|
440
|
+
* Anthropic fallback credit redemption handle from a prior classifier refusal.
|
|
441
|
+
* When present, the Anthropic provider replays the frozen request body and betas with
|
|
442
|
+
* the new model and `fallback_credit_token` to redeem prompt cache credit.
|
|
443
|
+
*/
|
|
444
|
+
fallbackCreditRedemption?: AnthropicFallbackCreditHandle;
|
|
445
|
+
/**
|
|
446
|
+
* Anthropic subscription slow-mode state machine (Claude Code `/low-priority`).
|
|
447
|
+
* Consulted only for first-party OAuth `anthropic` requests: stamps
|
|
448
|
+
* `anthropic-usage-limit: slow` while active and decides capacity waits.
|
|
449
|
+
*/
|
|
450
|
+
anthropicSlowMode?: AnthropicSlowModeHooks;
|
|
451
|
+
}
|
|
452
|
+
/**
|
|
453
|
+
* Caller-owned queue of user steering that a provider pulls from while a
|
|
454
|
+
* response streams. See {@link StreamOptions.liveSteering}.
|
|
455
|
+
*/
|
|
456
|
+
export interface LiveSteering {
|
|
457
|
+
/** Resolves once steering may be claimable, or when `signal` aborts. Never consumes input. */
|
|
458
|
+
wait(signal: AbortSignal): Promise<void>;
|
|
459
|
+
/** Takes the queued steering as provider messages; `undefined` when none is deliverable now. */
|
|
460
|
+
claim(signal: AbortSignal): Promise<LiveSteerClaim | undefined>;
|
|
461
|
+
}
|
|
462
|
+
/**
|
|
463
|
+
* Steering taken from a {@link LiveSteering} source. The provider settles it
|
|
464
|
+
* exactly once; later calls are ignored.
|
|
465
|
+
*/
|
|
466
|
+
export interface LiveSteerClaim {
|
|
467
|
+
readonly messages: readonly UserMessage[];
|
|
468
|
+
/** The server owns the input: the caller records it right after the current response. */
|
|
469
|
+
accept(): void;
|
|
470
|
+
/** Not delivered: the caller sends the input with its next request. */
|
|
471
|
+
reject(): void;
|
|
431
472
|
}
|
|
432
473
|
export interface SimpleStreamOptions extends Omit<StreamOptions, "apiKey"> {
|
|
433
474
|
/**
|
|
@@ -794,6 +835,8 @@ export interface UserMessage {
|
|
|
794
835
|
synthetic?: boolean;
|
|
795
836
|
/** True when injected mid-turn as a steer; consumed by the agent's pre-LLM transform to wrap it for emphasis. Never rendered. */
|
|
796
837
|
steering?: boolean;
|
|
838
|
+
/** True when the provider delivered this steer into the response it was streaming (`response.steer`). Display-only; never sent. */
|
|
839
|
+
liveSteered?: boolean;
|
|
797
840
|
/** Timestamp of a client-side history rewrite represented by this message. */
|
|
798
841
|
historyRewriteAt?: number;
|
|
799
842
|
/** Who initiated this message for billing/attribution semantics. */
|
|
@@ -910,6 +953,8 @@ export interface AssistantMessage {
|
|
|
910
953
|
requestControls?: AnthropicRequestControls;
|
|
911
954
|
/** Provider-specific opaque payload used to reconstruct transport-native history. */
|
|
912
955
|
providerPayload?: ProviderPayload;
|
|
956
|
+
/** In-memory fallback credit handle attached when a refusal response carries a fallback credit token. */
|
|
957
|
+
fallbackCreditHandle?: AnthropicFallbackCreditHandle;
|
|
913
958
|
timestamp: number;
|
|
914
959
|
duration?: number;
|
|
915
960
|
ttft?: number;
|
|
@@ -1262,3 +1307,13 @@ export type AssistantMessageEvent = {
|
|
|
1262
1307
|
reason: Extract<StopReason, "aborted" | "error">;
|
|
1263
1308
|
error: AssistantMessage;
|
|
1264
1309
|
};
|
|
1310
|
+
export interface AnthropicFallbackCreditHandle {
|
|
1311
|
+
token: string;
|
|
1312
|
+
prefillClaim?: boolean | null;
|
|
1313
|
+
params: unknown;
|
|
1314
|
+
betas?: readonly string[];
|
|
1315
|
+
betaHeader?: string;
|
|
1316
|
+
expiresAt: number;
|
|
1317
|
+
/** The refused response's content, in `AssistantMessage` block form. */
|
|
1318
|
+
refusedContent?: AssistantMessage["content"];
|
|
1319
|
+
}
|
|
@@ -8,5 +8,10 @@
|
|
|
8
8
|
* Only OAuth access credentials are accepted; paid API keys are a separate
|
|
9
9
|
* product and must never be sent here.
|
|
10
10
|
*/
|
|
11
|
-
import type { UsageProvider } from "../usage.js";
|
|
11
|
+
import type { CredentialRankingStrategy, UsageProvider } from "../usage.js";
|
|
12
12
|
export declare const xaiOauthUsageProvider: UsageProvider;
|
|
13
|
+
/**
|
|
14
|
+
* Ranks SuperGrok accounts by weekly credits (or unified monthly included quota).
|
|
15
|
+
* xAI reports no short window, so the meter maps to `secondary`, which drives drain ranking.
|
|
16
|
+
*/
|
|
17
|
+
export declare const xaiOauthRankingStrategy: CredentialRankingStrategy;
|
|
@@ -32,6 +32,12 @@ export declare function buildHttp400DumpPayload(dump: RawHttpRequestDump, error:
|
|
|
32
32
|
* are excluded: 429/5xx are retried, so persisting them here would write one
|
|
33
33
|
* dump per attempt. */
|
|
34
34
|
export declare function shouldDumpRejectedRequest(error: unknown): boolean;
|
|
35
|
+
/**
|
|
36
|
+
* Remove the local request-dump lines {@link appendRawHttpRequestDumpFor400} appends,
|
|
37
|
+
* leaving only the provider-facing error text. Hosts that relay provider errors
|
|
38
|
+
* (RPC `prompt_result`) must not leak OMP-local file paths.
|
|
39
|
+
*/
|
|
40
|
+
export declare function stripRawHttpRequestDiagnostics(message: string): string;
|
|
35
41
|
export declare function appendRawHttpRequestDumpFor400(message: string, error: unknown, dump: RawHttpRequestDump | undefined): Promise<string>;
|
|
36
42
|
export declare function finalizeErrorMessage(error: unknown, rawRequestDump: RawHttpRequestDump | undefined, capturedErrorResponse?: CapturedHttpErrorResponse): Promise<string>;
|
|
37
43
|
/**
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@oh-my-pi/pi-ai",
|
|
3
|
-
"version": "18.3.
|
|
3
|
+
"version": "18.3.1",
|
|
4
4
|
"description": "Unified LLM API with automatic model discovery and provider configuration",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"ai",
|
|
@@ -155,11 +155,11 @@
|
|
|
155
155
|
"fmt": "oxfmt --no-error-on-unmatched-pattern 'src/**/*.{ts,tsx}' '{test,bench,examples,scripts}/**/*.ts' '*.ts'"
|
|
156
156
|
},
|
|
157
157
|
"dependencies": {
|
|
158
|
-
"@oh-my-pi/omptype": "18.3.
|
|
159
|
-
"@oh-my-pi/pi-catalog": "18.3.
|
|
160
|
-
"@oh-my-pi/pi-natives": "18.3.
|
|
161
|
-
"@oh-my-pi/pi-utils": "18.3.
|
|
162
|
-
"@oh-my-pi/pi-wire": "18.3.
|
|
158
|
+
"@oh-my-pi/omptype": "18.3.1",
|
|
159
|
+
"@oh-my-pi/pi-catalog": "18.3.1",
|
|
160
|
+
"@oh-my-pi/pi-natives": "18.3.1",
|
|
161
|
+
"@oh-my-pi/pi-utils": "18.3.1",
|
|
162
|
+
"@oh-my-pi/pi-wire": "18.3.1"
|
|
163
163
|
},
|
|
164
164
|
"devDependencies": {
|
|
165
165
|
"@types/bun": "^1.3.14"
|