@oh-my-pi/pi-ai 14.0.2 → 14.0.4

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,12 @@
2
2
 
3
3
  ## [Unreleased]
4
4
 
5
+ ## [14.0.3] - 2026-04-09
6
+
7
+ ### Fixed
8
+
9
+ - Fixed Ollama discovery cache normalization so cached models upgrade to the OpenAI Responses transport after the provider change
10
+
5
11
  ## [14.0.0] - 2026-04-08
6
12
  ### Breaking Changes
7
13
 
@@ -1988,4 +1994,4 @@ _Dedicated to Peter's shoulder ([@steipete](https://twitter.com/steipete))_
1988
1994
 
1989
1995
  ## [0.9.4] - 2025-11-26
1990
1996
 
1991
- Initial release with multi-provider LLM support.
1997
+ Initial release with multi-provider LLM support.
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "type": "module",
3
3
  "name": "@oh-my-pi/pi-ai",
4
- "version": "14.0.2",
4
+ "version": "14.0.4",
5
5
  "description": "Unified LLM API with automatic model discovery and provider configuration",
6
6
  "homepage": "https://github.com/can1357/oh-my-pi",
7
7
  "author": "Can Boluk",
@@ -45,7 +45,7 @@
45
45
  "@aws-sdk/client-bedrock-runtime": "^3",
46
46
  "@bufbuild/protobuf": "^2.11",
47
47
  "@google/genai": "^1.43",
48
- "@oh-my-pi/pi-utils": "14.0.2",
48
+ "@oh-my-pi/pi-utils": "14.0.4",
49
49
  "@sinclair/typebox": "^0.34",
50
50
  "@smithy/node-http-handler": "^4.4",
51
51
  "ajv": "^8.18",
@@ -225,7 +225,7 @@ function toOllamaNativeBaseUrl(baseUrl: string): string {
225
225
  return baseUrl.endsWith("/v1") ? baseUrl.slice(0, -3) : baseUrl;
226
226
  }
227
227
 
228
- async function fetchOllamaNativeModels(baseUrl: string): Promise<Model<"openai-completions">[] | null> {
228
+ async function fetchOllamaNativeModels(baseUrl: string): Promise<Model<"openai-responses">[] | null> {
229
229
  const nativeBaseUrl = toOllamaNativeBaseUrl(baseUrl);
230
230
  let response: Response;
231
231
  try {
@@ -241,7 +241,7 @@ async function fetchOllamaNativeModels(baseUrl: string): Promise<Model<"openai-c
241
241
  }
242
242
  const payload = (await response.json()) as { models?: Array<{ name?: string; model?: string }> };
243
243
  const entries = payload.models ?? [];
244
- const models: Model<"openai-completions">[] = [];
244
+ const models: Model<"openai-responses">[] = [];
245
245
  for (const entry of entries) {
246
246
  const id = entry.model ?? entry.name;
247
247
  if (!id) {
@@ -250,7 +250,7 @@ async function fetchOllamaNativeModels(baseUrl: string): Promise<Model<"openai-c
250
250
  models.push({
251
251
  id,
252
252
  name: entry.name ?? id,
253
- api: "openai-completions",
253
+ api: "openai-responses",
254
254
  provider: "ollama",
255
255
  baseUrl,
256
256
  reasoning: false,
@@ -602,19 +602,15 @@ export interface OllamaModelManagerConfig {
602
602
  baseUrl?: string;
603
603
  }
604
604
 
605
- export function ollamaModelManagerOptions(
606
- config?: OllamaModelManagerConfig,
607
- ): ModelManagerOptions<"openai-completions"> {
605
+ export function ollamaModelManagerOptions(config?: OllamaModelManagerConfig): ModelManagerOptions<"openai-responses"> {
608
606
  const apiKey = config?.apiKey;
609
607
  const baseUrl = normalizeOllamaBaseUrl(config?.baseUrl);
610
- const references = createBundledReferenceMap<"openai-completions">(
611
- "ollama" as Parameters<typeof getBundledModels>[0],
612
- );
608
+ const references = createBundledReferenceMap<"openai-responses">("ollama" as Parameters<typeof getBundledModels>[0]);
613
609
  return {
614
610
  providerId: "ollama",
615
611
  fetchDynamicModels: async () => {
616
612
  const openAiCompatible = await fetchOpenAICompatibleModels({
617
- api: "openai-completions",
613
+ api: "openai-responses",
618
614
  provider: "ollama",
619
615
  baseUrl,
620
616
  apiKey,
@@ -19,7 +19,7 @@ import {
19
19
  type ToolConfiguration,
20
20
  ToolResultStatus,
21
21
  } from "@aws-sdk/client-bedrock-runtime";
22
- import { $env } from "@oh-my-pi/pi-utils";
22
+ import { $env, $flag } from "@oh-my-pi/pi-utils";
23
23
  import { NodeHttpHandler } from "@smithy/node-http-handler";
24
24
  import type { Effort } from "../model-thinking";
25
25
  import { mapEffortToAnthropicAdaptiveEffort, requireSupportedEffort } from "../model-thinking";
@@ -102,14 +102,14 @@ export const streamBedrock: StreamFunction<"bedrock-converse-stream"> = (
102
102
  config.region = config.region || $env.AWS_REGION || $env.AWS_DEFAULT_REGION;
103
103
 
104
104
  // Support proxies that don't need authentication
105
- if ($env.AWS_BEDROCK_SKIP_AUTH === "1") {
105
+ if ($flag("AWS_BEDROCK_SKIP_AUTH")) {
106
106
  config.credentials = {
107
107
  accessKeyId: "dummy-access-key",
108
108
  secretAccessKey: "dummy-secret-key",
109
109
  };
110
110
  }
111
111
 
112
- if ($env.AWS_BEDROCK_FORCE_HTTP1 === "1") {
112
+ if ($flag("AWS_BEDROCK_FORCE_HTTP1")) {
113
113
  config.requestHandler = new NodeHttpHandler();
114
114
  }
115
115
  }
@@ -379,7 +379,7 @@ function supportsPromptCaching(model: Model<"bedrock-converse-stream">): boolean
379
379
  if (id.includes("claude-haiku")) return true;
380
380
  // Application inference profiles don't contain the model name in the ARN.
381
381
  // Allow users to force cache points via environment variable.
382
- if (typeof process !== "undefined" && process.env.AWS_BEDROCK_FORCE_CACHE === "1") return true;
382
+ if (typeof process !== "undefined" && $flag("AWS_BEDROCK_FORCE_CACHE")) return true;
383
383
  return false;
384
384
  }
385
385
 
@@ -1,5 +1,5 @@
1
1
  import * as os from "node:os";
2
- import { $env, abortableSleep, asRecord, logger, readSseJson, structuredCloneJSON } from "@oh-my-pi/pi-utils";
2
+ import { $env, $flag, abortableSleep, asRecord, logger, readSseJson, structuredCloneJSON } from "@oh-my-pi/pi-utils";
3
3
  import type OpenAI from "openai";
4
4
  import type {
5
5
  ResponseFunctionToolCall,
@@ -90,7 +90,7 @@ export function buildCodexSystemPrompt(args: { userSystemPrompt?: string }): Cod
90
90
  };
91
91
  }
92
92
 
93
- const CODEX_DEBUG = $env.PI_CODEX_DEBUG === "1" || $env.PI_CODEX_DEBUG === "true";
93
+ const CODEX_DEBUG = $flag("PI_CODEX_DEBUG");
94
94
  const CODEX_MAX_RETRIES = 5;
95
95
  const CODEX_RETRYABLE_STATUS = new Set([408, 429, 500, 502, 503, 504]);
96
96
  const CODEX_RETRY_DELAY_MS = 500;
@@ -197,7 +197,7 @@ function parseCodexPositiveInteger(value: string | undefined, fallback: number):
197
197
  }
198
198
 
199
199
  function isCodexWebSocketEnvEnabled(): boolean {
200
- return $env.PI_CODEX_WEBSOCKET === "1" || $env.PI_CODEX_WEBSOCKET === "true";
200
+ return $flag("PI_CODEX_WEBSOCKET");
201
201
  }
202
202
 
203
203
  function getCodexWebSocketRetryBudget(): number {
@@ -49,7 +49,7 @@ export function detectOpenAICompat(model: Model<"openai-completions">, resolvedB
49
49
 
50
50
  const isCerebras = provider === "cerebras" || baseUrl.includes("cerebras.ai");
51
51
  const isZai = provider === "zai" || baseUrl.includes("api.z.ai");
52
- const isKimiModel = model.id.includes("moonshotai/kimi");
52
+ const isKimiModel = model.id.includes("moonshotai/kimi") || /^kimi[-.]/i.test(model.id);
53
53
  const isAlibaba = provider === "alibaba-coding-plan" || baseUrl.includes("dashscope");
54
54
  const isQwen = model.id.toLowerCase().includes("qwen");
55
55
 
@@ -1,3 +1,4 @@
1
+ import { $flag } from "@oh-my-pi/pi-utils";
1
2
  import { type TUnsafe, Type } from "@sinclair/typebox";
2
3
  import { areJsonValuesEqual } from "./equality";
3
4
  import { COMBINATOR_KEYS, NON_STRUCTURAL_SCHEMA_KEYS } from "./fields";
@@ -26,7 +27,7 @@ export function StringEnum<const T extends readonly string[]>(
26
27
  });
27
28
  }
28
29
 
29
- export const NO_STRICT = Bun.env.PI_NO_STRICT === "1";
30
+ export const NO_STRICT = $flag("PI_NO_STRICT");
30
31
 
31
32
  const strictSchemaCache = new WeakMap<Record<string, unknown>, { schema: Record<string, unknown>; strict: boolean }>();
32
33
  function hasUnrepresentableStrictObjectMap(schema: Record<string, unknown>, seen?: WeakSet<object>): boolean {