@oh-my-pi/pi-ai 15.10.5 → 15.10.7

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,20 @@
2
2
 
3
3
  ## [Unreleased]
4
4
 
5
+ ## [15.10.7] - 2026-06-08
6
+
7
+ ### Fixed
8
+
9
+ - Fixed first-party Anthropic requests returning HTTP 400 "Invalid `signature` in `thinking` block" after interrupting the model during its visible output. `transformMessages` stripped the signature from every `thinking` block of an `aborted`/`error` turn, including blocks that had already finished streaming — Anthropic delivers a block's signature at `content_block_stop` before the next block starts, so a thinking block followed by `text`/`tool_use` is fully signed. The valid signature was then replayed empty (`signature: ""`), which signature-enforcing Anthropic rejects, including when the provider is routed through an LLM gateway baseUrl. Only the single mid-stream block at the abort point is now treated as untrustworthy; completed thinking blocks keep their replayable signatures ([#2144](https://github.com/can1357/oh-my-pi/issues/2144)).
10
+ - Pinned a regression test against issue [#2123](https://github.com/can1357/oh-my-pi/issues/2123): OAuth requests to adaptive-thinking Claude Opus models (4.6+) ship a `context_management.edits[clear_thinking_20251015]` block paired with the `thinking` field, but the eager-todo prelude (and other paths that force `tool_choice` to `tool`/`any` on the first user turn) route through `disableThinkingIfToolChoiceForced`, which would strip `params.thinking` while leaving the orphan `context_management` behind. The Anthropic API then rejected the request with `400 ... clear_thinking_20251015 strategy requires thinking to be enabled or adaptive`. The fix that lands in [15.10.5] now drops both fields together; the new test locks the contract so the strategy can never outlive its enabling `thinking` payload again.
11
+ - Fixed Antigravity usage counters so exhausted Google/Gemini quota renders as `0% free` while separate Anthropic/OpenAI-backed Antigravity model counters remain visible independently, without replaying stale pre-fix cached usage reports.
12
+
13
+ ## [15.10.6] - 2026-06-08
14
+
15
+ ### Added
16
+
17
+ - Added AIML API as an OpenAI-compatible provider preset with `AIMLAPI_API_KEY` discovery ([#2105](https://github.com/can1357/oh-my-pi/issues/2105)).
18
+
5
19
  ## [15.10.5] - 2026-06-08
6
20
 
7
21
  ### Breaking Changes
@@ -106,6 +106,12 @@ export declare const XAI_OAUTH_CURATED_MODELS: readonly XAICuratedModel[];
106
106
  */
107
107
  export declare function buildXaiOAuthStaticSeed(baseUrl?: string): Model<"openai-responses">[];
108
108
  export declare function xaiOAuthModelManagerOptions(config?: XaiOAuthModelManagerConfig): ModelManagerOptions<"openai-responses">;
109
+ export declare function isLikelyAimlApiChatModelId(id: string): boolean;
110
+ export interface AimlApiModelManagerConfig {
111
+ apiKey?: string;
112
+ baseUrl?: string;
113
+ }
114
+ export declare function aimlApiModelManagerOptions(config?: AimlApiModelManagerConfig): ModelManagerOptions<"openai-completions">;
109
115
  export interface DeepSeekModelManagerConfig {
110
116
  apiKey?: string;
111
117
  baseUrl?: string;
@@ -0,0 +1,13 @@
1
+ import type { ModelManagerConfig } from "./types";
2
+ export declare const aimlApiProvider: {
3
+ readonly id: "aimlapi";
4
+ readonly name: "AIML API";
5
+ readonly defaultModel: "gpt-4o";
6
+ readonly createModelManagerOptions: (config: ModelManagerConfig) => import("..").ModelManagerOptions<"openai-completions", unknown>;
7
+ readonly dynamicModelsAuthoritative: true;
8
+ readonly catalogDiscovery: {
9
+ readonly label: "AIML API";
10
+ readonly envVars: readonly ["AIMLAPI_API_KEY"];
11
+ };
12
+ readonly envKeys: "AIMLAPI_API_KEY";
13
+ };
@@ -7,6 +7,17 @@ import type { ProviderDefinition } from "./types";
7
7
  * list for the loginable providers; non-login model providers are appended.
8
8
  */
9
9
  declare const ALL: ({
10
+ readonly id: "aimlapi";
11
+ readonly name: "AIML API";
12
+ readonly defaultModel: "gpt-4o";
13
+ readonly createModelManagerOptions: (config: import("./types").ModelManagerConfig) => import("..").ModelManagerOptions<"openai-completions", unknown>;
14
+ readonly dynamicModelsAuthoritative: true;
15
+ readonly catalogDiscovery: {
16
+ readonly label: "AIML API";
17
+ readonly envVars: readonly ["AIMLAPI_API_KEY"];
18
+ };
19
+ readonly envKeys: "AIMLAPI_API_KEY";
20
+ } | {
10
21
  readonly id: "alibaba-coding-plan";
11
22
  readonly name: "Alibaba Coding Plan";
12
23
  readonly defaultModel: "qwen3.5-plus";
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "type": "module",
3
3
  "name": "@oh-my-pi/pi-ai",
4
- "version": "15.10.5",
4
+ "version": "15.10.7",
5
5
  "description": "Unified LLM API with automatic model discovery and provider configuration",
6
6
  "homepage": "https://omp.sh",
7
7
  "author": "Can Boluk",
@@ -39,7 +39,7 @@
39
39
  },
40
40
  "dependencies": {
41
41
  "@bufbuild/protobuf": "^2.12.0",
42
- "@oh-my-pi/pi-utils": "15.10.5",
42
+ "@oh-my-pi/pi-utils": "15.10.7",
43
43
  "openai": "^6.39.0",
44
44
  "partial-json": "^0.1.7",
45
45
  "zod": "4.4.3"
@@ -492,6 +492,9 @@ const USAGE_FAILURE_BACKOFF_MS = 10_000;
492
492
  // Bumped from 3s — Claude usage retries up to 3 times with exponential backoff
493
493
  // (~3.5s total worst case); a tight per-request budget aborts retries mid-cycle.
494
494
  const DEFAULT_USAGE_REQUEST_TIMEOUT_MS = 10_000;
495
+ const USAGE_REPORT_CACHE_KEY_VERSION_OVERRIDES: Partial<Record<Provider, number>> = {
496
+ "google-antigravity": 2,
497
+ };
495
498
  const DEFAULT_OAUTH_REFRESH_TIMEOUT_MS = 10_000;
496
499
  /**
497
500
  * Refresh OAuth access tokens this many ms before their stated expiry. The
@@ -1638,15 +1641,19 @@ export class AuthStorage {
1638
1641
  #buildUsageReportCacheKey(request: UsageRequestDescriptor): string {
1639
1642
  const baseUrl = this.#normalizeUsageBaseUrl(request.baseUrl) || "default";
1640
1643
  const identity = this.#buildUsageCacheIdentity(request.credential);
1641
- return `report:${request.provider}:${baseUrl}:${identity}`;
1644
+ const versionOverride = USAGE_REPORT_CACHE_KEY_VERSION_OVERRIDES[request.provider];
1645
+ const providerKey = versionOverride === undefined ? request.provider : `${versionOverride}:${request.provider}`;
1646
+ return `report:${providerKey}:${baseUrl}:${identity}`;
1642
1647
  }
1643
1648
 
1644
1649
  #buildUsageReportsCacheKey(requests: ReadonlyArray<UsageRequestDescriptor>): string {
1645
1650
  const snapshot = requests
1646
- .map(
1647
- request =>
1648
- `${request.provider}:${this.#normalizeUsageBaseUrl(request.baseUrl) || "default"}:${this.#buildUsageCacheIdentity(request.credential)}`,
1649
- )
1651
+ .map(request => {
1652
+ const versionOverride = USAGE_REPORT_CACHE_KEY_VERSION_OVERRIDES[request.provider];
1653
+ const providerKey =
1654
+ versionOverride === undefined ? request.provider : `${versionOverride}:${request.provider}`;
1655
+ return `${providerKey}:${this.#normalizeUsageBaseUrl(request.baseUrl) || "default"}:${this.#buildUsageCacheIdentity(request.credential)}`;
1656
+ })
1650
1657
  .sort()
1651
1658
  .join("\n");
1652
1659
  return `reports:${Bun.hash(snapshot).toString(16)}`;