@oh-my-pi/pi-ai 18.1.10 → 18.1.12

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 CHANGED
@@ -2,6 +2,19 @@
2
2
 
3
3
  ## [Unreleased]
4
4
 
5
+ ## [18.1.12] - 2026-09-06
6
+
7
+ ### Added
8
+
9
+ - Added Muse Code subscription sign-in, credential refresh, inference, and quota reporting in `/usage`, with durable rate-limit backoff so quota refresh recovers instead of repeatedly retrying.
10
+
11
+ ## [18.1.11] - 2026-09-05
12
+
13
+ ### Fixed
14
+
15
+ - Fixed OpenCode Go usage polls (`GET /zen/go/v1/usage`) missing `x-opencode-session` and omp's `User-Agent`: background polls now attribute with the stable install id so the requests OpenCode flags as `Bun fetch` carry the required session header.
16
+ - GitHub Copilot sign-in now requests only basic profile access, restoring login for Enterprise organizations that reject repository, gist, and Codespaces permissions ([#10656](https://github.com/can1357/oh-my-pi/issues/10656)).
17
+
5
18
  ## [18.1.9] - 2026-09-04
6
19
 
7
20
  ### Added
@@ -27,6 +40,7 @@
27
40
  ### Fixed
28
41
 
29
42
  - Fixed DeepSeek-family Responses replay (e.g. opencode-go) rejecting a resumed thinking-mode turn with `400 The reasoning_text in the thinking mode must be passed back to the API` when compaction dropped the turn's reasoning; a non-empty placeholder is now synthesized instead of an empty `reasoning_text` ([#10690](https://github.com/can1357/oh-my-pi/issues/10690)).
43
+ - Fixed pi-native streams treating a connection that closed before its terminal event as a successful empty response; incomplete streams and namespaced gateway 5xx failures now remain retryable.
30
44
 
31
45
  ## [18.1.6] - 2026-09-03
32
46
 
@@ -50,6 +64,7 @@
50
64
  - Anthropic and OpenRouter credit-exhaustion errors now automatically switch to a sibling account instead of stopping the turn with a retry hint.
51
65
  - Fixed OpenCode Go and Zen requests by including the required stable per-conversation session identification.
52
66
  - Improved Anthropic prompt caching so explicit cache breakpoints preserve reusable tools and system prompts when the message tail changes.
67
+ - Anthropic and OpenRouter 402 credit-exhaustion errors ("would exceed your available credits", "Insufficient credits") now switch to a sibling account instead of stopping the turn with a retry hint.
53
68
 
54
69
  ## [18.1.5] - 2026-09-03
55
70
 
@@ -496,10 +496,40 @@ export { isDefinitiveOAuthFailure } from "./error/auth-classify.js";
496
496
  * multi-hour) retry-after when it is sooner. `retryAtMs` is `undefined` when
497
497
  * no sibling credentials exist at all, or when the session has no tracked
498
498
  * credential to rotate away from.
499
+ *
500
+ * `blockedUntilMs` (epoch ms) is the just-blocked credential's own unblock
501
+ * deadline — the later of the caller's retry-after and any exhausted window
502
+ * the usage report reveals. Callers that wait the account out (instead of
503
+ * rotating) must sleep until this, not the error-text hint alone.
504
+ *
505
+ * `priorBlockedUntilMs` (epoch ms) is the live block deadline the map already
506
+ * stored for this credential before this call. The merged `blockedUntilMs`
507
+ * masks a pre-existing block shorter than this call's own heuristic
508
+ * fallback (`Math.max` in the mark), so callers that replace that heuristic
509
+ * with an authoritative report window must consult the prior deadline to
510
+ * keep honoring the earlier response's provider-stated block.
511
+ *
512
+ * `priorBlockedUntilTimed` is `true` when that prior deadline came from
513
+ * provider-stated timing (a parsed hint or usage-report reset) rather than
514
+ * another session's heuristic guess — only timed priors may extend a wait
515
+ * past an authoritative report window. Persisted blocks carry no provenance
516
+ * and count as untimed: a stale persisted heuristic must not outrank a
517
+ * fresh complete report (longer persisted deadlines still win through the
518
+ * merged `blockedUntilMs`).
519
+ *
520
+ * `reportResetAtMs` (epoch ms) is present only when the usage report is a
521
+ * complete authority for the wait: every exhausted window carries a future
522
+ * reset, so sleeping until the latest one can actually clear the account. A
523
+ * permanent cap alongside a timed window (or no report at all) leaves it
524
+ * unset, and the heuristic fallback alone must never authorize a wait.
499
525
  */
500
526
  export interface UsageLimitMarkResult {
501
527
  switched: boolean;
502
528
  retryAtMs?: number;
529
+ blockedUntilMs?: number;
530
+ priorBlockedUntilMs?: number;
531
+ priorBlockedUntilTimed?: boolean;
532
+ reportResetAtMs?: number;
503
533
  }
504
534
  export type ModelUsageHealthState = "healthy" | "reserve" | "depleted" | "unknown";
505
535
  export interface ModelUsageAccountHealth {
@@ -1013,6 +1043,12 @@ export declare class AuthStorage {
1013
1043
  */
1014
1044
  markUsageLimitReached(provider: string, sessionId: string | undefined, options?: {
1015
1045
  retryAfterMs?: number;
1046
+ /**
1047
+ * Whether `retryAfterMs` came from provider-stated timing (a parsed
1048
+ * retry hint) rather than a heuristic/default guess. A report reset
1049
+ * extending the block counts as provider timing regardless.
1050
+ */
1051
+ providerTimed?: boolean;
1016
1052
  baseUrl?: string;
1017
1053
  modelId?: string;
1018
1054
  apiKey?: string;
@@ -22,6 +22,8 @@ export type OAuthErrorKind =
22
22
  | "configuration"
23
23
  /** Cloud project provisioning / onboarding (loadCodeAssist, onboardUser). */
24
24
  | "provisioning"
25
+ /** Subscription/payment gate: plan required or purchase action needed. */
26
+ | "entitlement"
25
27
  /** OIDC / endpoint discovery failed. */
26
28
  | "discovery";
27
29
  export interface OAuthErrorOptions {
@@ -35,6 +35,7 @@ export * from "./usage/github-copilot.js";
35
35
  export * from "./usage/google-antigravity.js";
36
36
  export * from "./usage/kimi.js";
37
37
  export * from "./usage/minimax-code.js";
38
+ export * from "./usage/muse-code.js";
38
39
  export * from "./usage/ollama.js";
39
40
  export * from "./usage/openai-codex.js";
40
41
  export * from "./usage/openai-codex-reset.js";
@@ -357,11 +357,12 @@ export declare function resolveOpenAICompletionsOutputClamp(model: Model<"openai
357
357
  /**
358
358
  * Provider-specific Responses API output clamp.
359
359
  *
360
- * Meta documents a 131,072-token output limit for Muse Spark 1.1, so native
361
- * Meta requests may use the model's full advertised cap instead of the
362
- * conservative 64k OpenAI-compatible default.
360
+ * Models whose compiled provider policy opts in may use their full advertised
361
+ * output cap instead of the conservative 64k OpenAI-compatible default.
363
362
  */
364
- export declare function resolveOpenAIResponsesOutputClamp(model: Pick<Model, "provider" | "maxTokens">): number | undefined;
363
+ export declare function resolveOpenAIResponsesOutputClamp(model: Pick<Model, "maxTokens"> & {
364
+ compat: Pick<ResolvedOpenAISharedCompat, "clampOutputToModelMax">;
365
+ }): number | undefined;
365
366
  /**
366
367
  * Enable `tool_stream` for Z.AI/GLM-5.2 reasoning models when tools are present
367
368
  * (GLM-5.2 streams tool-call arguments incrementally and needs the flag to do so).
@@ -659,7 +660,7 @@ type CommonSamplingOptions = Pick<StreamOptions, "temperature" | "topP" | "topK"
659
660
  * reflect the model's context window rather than the upstream output limit.
660
661
  */
661
662
  export declare function applyCommonResponsesSamplingParams<P extends CommonResponsesParams>(params: P, options: CommonSamplingOptions | undefined, model: Pick<Model, "provider" | "api" | "id" | "omitMaxOutputTokens" | "maxTokens" | "identity"> & {
662
- compat: Pick<ResolvedOpenAISharedCompat, "supportsSamplingParams" | "supportsPenaltyAndStopParams">;
663
+ compat: Pick<ResolvedOpenAISharedCompat, "supportsSamplingParams" | "supportsPenaltyAndStopParams" | "clampOutputToModelMax">;
663
664
  }): void;
664
665
  type ReasoningOptions = {
665
666
  reasoning?: string;
@@ -0,0 +1,3 @@
1
+ import type { ProviderTransport } from "./build.js";
2
+ /** Muse stores both the Meta account token and its subscription-minted Model API key in one OAuth bearer. */
3
+ export declare const museCodeTransport: ProviderTransport;
@@ -22,6 +22,7 @@ export declare function unregisterOAuthProviders(sourceId: string): void;
22
22
  * Refresh a built-in OAuth grant, cancelling provider work when refresh ownership ends.
23
23
  */
24
24
  export declare function refreshOAuthToken(provider: OAuthProvider, credentials: OAuthCredentials, signal?: AbortSignal): Promise<OAuthCredentials>;
25
+ export declare function normalizeOAuthCredentialExpiry<T extends OAuthCredentials>(provider: string, credentials: T): T;
25
26
  /**
26
27
  * Build API-key bytes for a provider from an already-fresh OAuth credential.
27
28
  *
@@ -0,0 +1,67 @@
1
+ import type { AfterExchangeHook } from "../hooks/types.js";
2
+ import type { FetchImpl } from "../../types.js";
3
+ declare const museCodeKeyResponseSchema: import("@oh-my-pi/omptype").FluentType<{
4
+ action_url?: string | null | undefined;
5
+ api_key?: string | undefined;
6
+ is_subs_active?: boolean | undefined;
7
+ require_payment?: boolean | undefined;
8
+ require_payment_action_url?: string | undefined;
9
+ subs_tier_id?: string | undefined;
10
+ subs_tier_name?: string | undefined;
11
+ subs_usage?: {
12
+ weekly?: {
13
+ resets_at?: string | number | undefined;
14
+ used_percent?: number | undefined;
15
+ window_duration_mins?: number | undefined;
16
+ } | null | undefined;
17
+ window?: {
18
+ resets_at?: string | number | undefined;
19
+ used_percent?: number | undefined;
20
+ window_duration_mins?: number | undefined;
21
+ } | null | undefined;
22
+ } | null | undefined;
23
+ user_email?: string | undefined;
24
+ user_id?: string | undefined;
25
+ }, {
26
+ action_url?: string | null | undefined;
27
+ api_key?: string | undefined;
28
+ is_subs_active?: boolean | undefined;
29
+ require_payment?: boolean | undefined;
30
+ require_payment_action_url?: string | undefined;
31
+ subs_tier_id?: string | undefined;
32
+ subs_tier_name?: string | undefined;
33
+ subs_usage?: {
34
+ weekly?: {
35
+ resets_at?: string | number | undefined;
36
+ used_percent?: number | undefined;
37
+ window_duration_mins?: number | undefined;
38
+ } | null | undefined;
39
+ window?: {
40
+ resets_at?: string | number | undefined;
41
+ used_percent?: number | undefined;
42
+ window_duration_mins?: number | undefined;
43
+ } | null | undefined;
44
+ } | null | undefined;
45
+ user_email?: string | undefined;
46
+ user_id?: string | undefined;
47
+ }>;
48
+ export type MuseCodeKeyResponse = typeof museCodeKeyResponseSchema.infer;
49
+ declare const museCodeCredentialSchema: import("@oh-my-pi/omptype").FluentType<{
50
+ apiKey: string;
51
+ oauthAccessToken: string;
52
+ }, {
53
+ apiKey: string;
54
+ oauthAccessToken: string;
55
+ }>;
56
+ export type MuseCodeCredential = typeof museCodeCredentialSchema.infer;
57
+ export interface MuseCodeKeyRequestOptions {
58
+ fetch?: FetchImpl;
59
+ signal?: AbortSignal;
60
+ /** Ask Meta to onboard the account during an interactive login exchange. */
61
+ onboard?: boolean;
62
+ }
63
+ export declare function parseMuseCodeCredential(value: string): MuseCodeCredential;
64
+ export declare function requestMuseCodeKey(accessToken: string, options?: MuseCodeKeyRequestOptions): Promise<MuseCodeKeyResponse>;
65
+ /** Exchange Meta account access for the Model API key authorized by a Muse subscription. */
66
+ export declare const attachMuseCodeApiKey: AfterExchangeHook;
67
+ export {};
@@ -0,0 +1,2 @@
1
+ import type { UsageProvider } from "../usage.js";
2
+ export declare const museCodeUsageProvider: UsageProvider;
@@ -478,6 +478,8 @@ export interface UsageProvider {
478
478
  validatesCredentials?: boolean;
479
479
  /** Whether a failed refresh may serve the previous successful report. Defaults to true. */
480
480
  retainLastGoodOnFailure?: boolean;
481
+ /** Provider-specific cool-down after a failed refresh. Defaults to the shared short backoff. */
482
+ failureBackoffMs?: number;
481
483
  }
482
484
  /** Request context used when ranking usage for a specific model. */
483
485
  export interface CredentialRankingContext {
@@ -16,5 +16,7 @@ export interface JsonSchemaValidationResult {
16
16
  success: boolean;
17
17
  issues: JsonSchemaValidationIssue[];
18
18
  }
19
+ /** Whether any same-instance schema declaration or constraint owns this property name. */
20
+ export declare function schemaDefinesProperty(schema: unknown, key: string): boolean;
19
21
  export declare function validateJsonSchemaValue(schema: unknown, value: unknown): JsonSchemaValidationResult;
20
22
  export declare function isJsonSchemaValueValid(schema: unknown, value: unknown): boolean;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@oh-my-pi/pi-ai",
3
- "version": "18.1.10",
3
+ "version": "18.1.12",
4
4
  "description": "Unified LLM API with automatic model discovery and provider configuration",
5
5
  "keywords": [
6
6
  "ai",
@@ -124,11 +124,11 @@
124
124
  "fmt": "oxfmt --no-error-on-unmatched-pattern 'src/**/*.{ts,tsx}' '{test,bench,examples,scripts}/**/*.ts' '*.ts'"
125
125
  },
126
126
  "dependencies": {
127
- "@oh-my-pi/omptype": "18.1.10",
128
- "@oh-my-pi/pi-catalog": "18.1.10",
129
- "@oh-my-pi/pi-natives": "18.1.10",
130
- "@oh-my-pi/pi-utils": "18.1.10",
131
- "@oh-my-pi/pi-wire": "18.1.10"
127
+ "@oh-my-pi/omptype": "18.1.12",
128
+ "@oh-my-pi/pi-catalog": "18.1.12",
129
+ "@oh-my-pi/pi-natives": "18.1.12",
130
+ "@oh-my-pi/pi-utils": "18.1.12",
131
+ "@oh-my-pi/pi-wire": "18.1.12"
132
132
  },
133
133
  "devDependencies": {
134
134
  "@types/bun": "^1.3.14"
@@ -251,6 +251,7 @@ async function refreshGatewayApiKeyAfterAuthError(
251
251
  const retryAfterMs = extractRetryHint(undefined, message);
252
252
  const { switched, retryAtMs } = await storage.markUsageLimitReached(provider, sessionId, {
253
253
  retryAfterMs,
254
+ providerTimed: retryAfterMs !== undefined,
254
255
  baseUrl: model.baseUrl,
255
256
  modelId: model.id,
256
257
  apiKey: oldKey,