@oh-my-pi/pi-ai 16.2.1 → 16.2.3

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 (170) hide show
  1. package/CHANGELOG.md +36 -0
  2. package/dist/types/auth-gateway/server.d.ts +0 -19
  3. package/dist/types/auth-retry.d.ts +2 -10
  4. package/dist/types/auth-storage.d.ts +1 -2
  5. package/dist/types/dialect/demotion.d.ts +22 -0
  6. package/dist/types/dialect/index.d.ts +2 -0
  7. package/dist/types/error/abort.d.ts +14 -0
  8. package/dist/types/error/auth-classify.d.ts +16 -0
  9. package/dist/types/error/auth.d.ts +27 -0
  10. package/dist/types/error/aws.d.ts +23 -0
  11. package/dist/types/error/classes.d.ts +102 -0
  12. package/dist/types/error/finalize.d.ts +39 -0
  13. package/dist/types/error/flags.d.ts +70 -0
  14. package/dist/types/error/format.d.ts +20 -0
  15. package/dist/types/error/gateway.d.ts +20 -0
  16. package/dist/types/error/index.d.ts +13 -0
  17. package/dist/types/error/oauth.d.ts +43 -0
  18. package/dist/types/error/provider.d.ts +42 -0
  19. package/dist/types/{rate-limit-utils.d.ts → error/rate-limit.d.ts} +14 -1
  20. package/dist/types/error/retryable.d.ts +27 -0
  21. package/dist/types/error/validation.d.ts +32 -0
  22. package/dist/types/index.d.ts +1 -3
  23. package/dist/types/providers/amazon-bedrock.d.ts +0 -5
  24. package/dist/types/providers/anthropic-client.d.ts +2 -16
  25. package/dist/types/providers/anthropic.d.ts +6 -1
  26. package/dist/types/providers/aws-eventstream.d.ts +2 -1
  27. package/dist/types/providers/cursor.d.ts +8 -7
  28. package/dist/types/providers/google-gemini-cli.d.ts +0 -5
  29. package/dist/types/providers/google-shared.d.ts +0 -5
  30. package/dist/types/providers/ollama.d.ts +0 -5
  31. package/dist/types/providers/openai-codex/request-transformer.d.ts +2 -2
  32. package/dist/types/providers/openai-codex/response-handler.d.ts +1 -1
  33. package/dist/types/providers/openai-codex-responses.d.ts +2 -2
  34. package/dist/types/providers/openai-responses-server-schema.d.ts +6 -0
  35. package/dist/types/providers/openai-responses-wire.d.ts +1 -1
  36. package/dist/types/providers/openai-responses.d.ts +3 -2
  37. package/dist/types/providers/openai-shared.d.ts +8 -6
  38. package/dist/types/providers/pi-native-client.d.ts +0 -9
  39. package/dist/types/registry/oauth/xai-oauth.d.ts +0 -9
  40. package/dist/types/types.d.ts +6 -0
  41. package/dist/types/usage/openai-codex-base-url.d.ts +17 -0
  42. package/dist/types/utils/block-symbols.d.ts +20 -0
  43. package/dist/types/utils/openai-http.d.ts +4 -8
  44. package/dist/types/utils/retry.d.ts +2 -14
  45. package/dist/types/utils/stream-markup-healing.d.ts +14 -5
  46. package/dist/types/utils/thinking-loop.d.ts +3 -1
  47. package/package.json +8 -4
  48. package/src/api-registry.ts +3 -1
  49. package/src/auth-broker/discover.ts +7 -2
  50. package/src/auth-broker/remote-store.ts +8 -7
  51. package/src/auth-gateway/server.ts +27 -115
  52. package/src/auth-retry.ts +9 -21
  53. package/src/auth-storage.ts +34 -49
  54. package/src/dialect/demotion.ts +31 -0
  55. package/src/dialect/factory.ts +0 -2
  56. package/src/dialect/index.ts +2 -0
  57. package/src/dialect/owned-stream.ts +0 -1
  58. package/src/dialect/thinking.ts +22 -10
  59. package/src/error/abort.ts +18 -0
  60. package/src/error/auth-classify.ts +30 -0
  61. package/src/error/auth.ts +48 -0
  62. package/src/error/aws.ts +31 -0
  63. package/src/error/classes.ts +186 -0
  64. package/src/error/finalize.ts +69 -0
  65. package/src/error/flags.ts +486 -0
  66. package/src/error/format.ts +36 -0
  67. package/src/error/gateway.ts +96 -0
  68. package/src/error/index.ts +13 -0
  69. package/src/error/oauth.ts +58 -0
  70. package/src/error/provider.ts +56 -0
  71. package/src/{rate-limit-utils.ts → error/rate-limit.ts} +9 -3
  72. package/src/error/retryable.ts +70 -0
  73. package/src/error/validation.ts +44 -0
  74. package/src/index.ts +1 -3
  75. package/src/providers/amazon-bedrock.ts +61 -57
  76. package/src/providers/anthropic-client.ts +13 -41
  77. package/src/providers/anthropic-messages-server.ts +9 -2
  78. package/src/providers/anthropic.ts +84 -147
  79. package/src/providers/aws-credentials.ts +41 -11
  80. package/src/providers/aws-eventstream.ts +12 -21
  81. package/src/providers/azure-openai-responses.ts +27 -17
  82. package/src/providers/cursor.ts +59 -53
  83. package/src/providers/devin.ts +28 -20
  84. package/src/providers/gitlab-duo-workflow.ts +30 -10
  85. package/src/providers/gitlab-duo.ts +22 -6
  86. package/src/providers/google-auth.ts +15 -5
  87. package/src/providers/google-gemini-cli.ts +46 -60
  88. package/src/providers/google-shared.ts +40 -38
  89. package/src/providers/google-vertex.ts +3 -2
  90. package/src/providers/google.ts +5 -1
  91. package/src/providers/mock.ts +10 -7
  92. package/src/providers/ollama.ts +40 -30
  93. package/src/providers/openai-chat-server.ts +2 -1
  94. package/src/providers/openai-codex/request-transformer.ts +13 -12
  95. package/src/providers/openai-codex/response-handler.ts +1 -1
  96. package/src/providers/openai-codex-responses.ts +931 -1012
  97. package/src/providers/openai-completions.ts +46 -36
  98. package/src/providers/openai-responses-server-schema.ts +3 -0
  99. package/src/providers/openai-responses-server.ts +82 -30
  100. package/src/providers/openai-responses-wire.ts +1 -1
  101. package/src/providers/openai-responses.ts +50 -24
  102. package/src/providers/openai-shared.ts +118 -51
  103. package/src/providers/pi-native-client.ts +12 -18
  104. package/src/providers/pi-native-server.ts +9 -6
  105. package/src/providers/register-builtins.ts +5 -2
  106. package/src/providers/transform-messages.ts +31 -63
  107. package/src/registry/alibaba-coding-plan.ts +6 -5
  108. package/src/registry/api-key-login.ts +4 -3
  109. package/src/registry/api-key-validation.ts +4 -3
  110. package/src/registry/cloudflare-ai-gateway.ts +4 -3
  111. package/src/registry/coreweave.ts +2 -1
  112. package/src/registry/deepseek.ts +2 -1
  113. package/src/registry/google-antigravity.ts +2 -1
  114. package/src/registry/google-gemini-cli.ts +2 -1
  115. package/src/registry/kagi.ts +4 -3
  116. package/src/registry/kilo.ts +32 -10
  117. package/src/registry/litellm.ts +4 -3
  118. package/src/registry/llama-cpp.ts +3 -2
  119. package/src/registry/lm-studio.ts +3 -2
  120. package/src/registry/nvidia.ts +7 -7
  121. package/src/registry/oauth/anthropic.ts +23 -6
  122. package/src/registry/oauth/callback-server.ts +5 -3
  123. package/src/registry/oauth/cursor.ts +18 -4
  124. package/src/registry/oauth/devin.ts +14 -3
  125. package/src/registry/oauth/github-copilot.ts +21 -10
  126. package/src/registry/oauth/gitlab-duo-workflow.ts +15 -3
  127. package/src/registry/oauth/gitlab-duo.ts +30 -6
  128. package/src/registry/oauth/google-antigravity.ts +14 -5
  129. package/src/registry/oauth/google-gemini-cli.ts +24 -7
  130. package/src/registry/oauth/google-oauth-shared.ts +6 -3
  131. package/src/registry/oauth/index.ts +19 -8
  132. package/src/registry/oauth/kimi.ts +40 -10
  133. package/src/registry/oauth/openai-codex.ts +26 -11
  134. package/src/registry/oauth/opencode.ts +4 -3
  135. package/src/registry/oauth/perplexity.ts +33 -11
  136. package/src/registry/oauth/xai-oauth.ts +62 -18
  137. package/src/registry/oauth/xiaomi.ts +21 -9
  138. package/src/registry/ollama-cloud.ts +5 -4
  139. package/src/registry/ollama.ts +3 -2
  140. package/src/registry/parallel.ts +4 -3
  141. package/src/registry/qwen-portal.ts +4 -3
  142. package/src/registry/tavily.ts +4 -3
  143. package/src/registry/vercel-ai-gateway.ts +4 -3
  144. package/src/registry/vllm.ts +3 -2
  145. package/src/stream.ts +79 -24
  146. package/src/types.ts +6 -0
  147. package/src/usage/claude.ts +2 -1
  148. package/src/usage/github-copilot.ts +4 -3
  149. package/src/usage/google-antigravity.ts +2 -1
  150. package/src/usage/openai-codex-base-url.ts +30 -10
  151. package/src/utils/abort.ts +4 -2
  152. package/src/utils/block-symbols.ts +32 -0
  153. package/src/utils/event-stream.ts +15 -3
  154. package/src/utils/http-inspector.ts +4 -4
  155. package/src/utils/idle-iterator.ts +6 -5
  156. package/src/utils/openai-http.ts +11 -46
  157. package/src/utils/parse-bind.ts +7 -5
  158. package/src/utils/proxy.ts +2 -1
  159. package/src/utils/retry.ts +7 -23
  160. package/src/utils/schema/normalize.ts +3 -2
  161. package/src/utils/stream-markup-healing.ts +41 -18
  162. package/src/utils/thinking-loop.ts +15 -11
  163. package/src/utils/validation.ts +4 -3
  164. package/dist/types/dialect/pi.d.ts +0 -9
  165. package/dist/types/errors.d.ts +0 -24
  166. package/dist/types/utils/overflow.d.ts +0 -55
  167. package/src/dialect/pi.md +0 -55
  168. package/src/dialect/pi.ts +0 -600
  169. package/src/errors.ts +0 -32
  170. package/src/utils/overflow.ts +0 -140
@@ -0,0 +1,32 @@
1
+ /**
2
+ * Caller-supplied input failed validation before/while building a provider
3
+ * request: bad request body, malformed tool arguments, unsupported content
4
+ * type, a schema that cannot be normalized, an unknown tool, etc.
5
+ *
6
+ * This is a programmer/config/contract error, not a transient provider fault —
7
+ * it is never retried.
8
+ */
9
+ export declare class ValidationError extends Error {
10
+ constructor(message: string, options?: {
11
+ cause?: unknown;
12
+ });
13
+ }
14
+ /** A referenced tool was not found in the active tool set. */
15
+ export declare class ToolNotFoundError extends ValidationError {
16
+ constructor(toolName: string);
17
+ }
18
+ /**
19
+ * Provider/auth configuration was missing or malformed (env var pointing at a
20
+ * missing file, missing projectId, bad bind string, mTLS half-configured, …).
21
+ */
22
+ export declare class ConfigurationError extends Error {
23
+ constructor(message: string, options?: {
24
+ cause?: unknown;
25
+ });
26
+ }
27
+ /** A request was abandoned because it exceeded a stream/idle/first-event deadline. */
28
+ export declare class StreamTimeoutError extends Error {
29
+ constructor(message?: string, options?: {
30
+ cause?: unknown;
31
+ });
32
+ }
@@ -6,7 +6,7 @@ export type { AuthGatewayBootOptions, ModelResolver } from "./auth-gateway/serve
6
6
  export * from "./auth-gateway/types";
7
7
  export * from "./auth-retry";
8
8
  export * from "./auth-storage";
9
- export * from "./errors";
9
+ export * from "./error/rate-limit";
10
10
  export * from "./provider-details";
11
11
  export * from "./providers/anthropic";
12
12
  export * from "./providers/anthropic-client";
@@ -24,7 +24,6 @@ export * from "./providers/openai-codex-responses";
24
24
  export * from "./providers/openai-completions";
25
25
  export * from "./providers/openai-responses";
26
26
  export * from "./providers/synthetic";
27
- export * from "./rate-limit-utils";
28
27
  export * from "./registry";
29
28
  export * from "./stream";
30
29
  export * from "./types";
@@ -43,7 +42,6 @@ export * from "./usage/zai";
43
42
  export * from "./utils/anthropic-auth";
44
43
  export * from "./utils/event-stream";
45
44
  export * from "./utils/openrouter-headers";
46
- export * from "./utils/overflow";
47
45
  export * from "./utils/retry";
48
46
  export * from "./utils/schema";
49
47
  export * from "./utils/thinking-loop";
@@ -7,12 +7,7 @@
7
7
  * Bun's native `HTTPS_PROXY` support.
8
8
  */
9
9
  import type { Effort } from "@oh-my-pi/pi-catalog/effort";
10
- import { ProviderHttpError } from "../errors";
11
10
  import type { StreamFunction, StreamOptions, ThinkingBudgets } from "../types";
12
- /** Non-2xx response (or in-stream exception event) from the Bedrock runtime API. */
13
- export declare class BedrockApiError extends ProviderHttpError {
14
- readonly name = "BedrockApiError";
15
- }
16
11
  export type BedrockThinkingDisplay = "summarized" | "omitted";
17
12
  export interface BedrockOptions extends StreamOptions {
18
13
  region?: string;
@@ -1,4 +1,5 @@
1
- import { ProviderHttpError } from "../errors";
1
+ import { AnthropicApiError, AnthropicConnectionError, AnthropicConnectionTimeoutError } from "../error";
2
+ export { AnthropicApiError, AnthropicConnectionError, AnthropicConnectionTimeoutError };
2
3
  import type { FetchImpl } from "../types";
3
4
  import type { MessageCreateParamsStreaming } from "./anthropic-wire";
4
5
  /** Per-request options accepted by {@link AnthropicMessages.create}. */
@@ -43,21 +44,6 @@ export interface AnthropicClientOptions {
43
44
  fetch?: FetchImpl;
44
45
  fetchOptions?: AnthropicFetchOptions;
45
46
  }
46
- /** Non-2xx response from the Anthropic API. */
47
- export declare class AnthropicApiError extends ProviderHttpError {
48
- readonly headers: Headers;
49
- readonly requestId: string | null;
50
- constructor(status: number, message: string, headers: Headers);
51
- static fromResponse(response: Response): Promise<AnthropicApiError>;
52
- }
53
- /** Network-level failure (DNS, TLS, socket reset) after retries were exhausted. */
54
- export declare class AnthropicConnectionError extends Error {
55
- constructor(cause: unknown);
56
- }
57
- /** No response headers arrived within the configured request timeout. */
58
- export declare class AnthropicConnectionTimeoutError extends Error {
59
- constructor();
60
- }
61
47
  /** Server-suggested delay (`retry-after-ms`, then `retry-after` seconds or HTTP date). */
62
48
  export declare function retryDelayFromHeaders(headers: Headers | undefined): number | undefined;
63
49
  export declare function calculateAnthropicRetryDelayMs(attempt: number): number;
@@ -24,7 +24,6 @@ type AnthropicCacheControl = NonNullable<TextBlockParam["cache_control"]>;
24
24
  * hasn't been materialized yet.
25
25
  */
26
26
  export declare function clearAnthropicFastModeFallback(providerSessionState: Map<string, ProviderSessionState> | undefined): void;
27
- export declare function isAnthropicFastModeUnsupportedError(error: unknown): boolean;
28
27
  export declare const claudeCodeVersion = "2.1.165";
29
28
  export declare const claudeAgentSdkVersion = "0.3.165";
30
29
  export declare const claudeClientVersion = "1.11187.4";
@@ -173,6 +172,12 @@ export type AnthropicClientOptionsResult = {
173
172
  * omitted there.
174
173
  */
175
174
  export declare function resolveAnthropicCustomHeadersForBaseUrl(baseUrl: string | undefined): Record<string, string> | undefined;
175
+ /**
176
+ * Whether an Anthropic (or Copilot-over-Anthropic) stream error should be
177
+ * retried. The classification lives in {@link AIError.isProviderRetryableError};
178
+ * this wrapper injects the Copilot-specific `model_not_supported` transient
179
+ * check, which the error module must not import directly.
180
+ */
176
181
  export declare function isProviderRetryableError(error: unknown, provider?: string): boolean;
177
182
  export type AnthropicUsageLike = {
178
183
  cache_creation?: {
@@ -21,7 +21,8 @@ export interface EventStreamMessage {
21
21
  headers: Record<string, string>;
22
22
  payload: Uint8Array;
23
23
  }
24
- export declare function crc32(bytes: Uint8Array, seed?: number): number;
24
+ /** CRC32 (IEEE / zlib polynomial 0xEDB88320), matches `@aws-crypto/crc32`. */
25
+ export declare function crc32(bytes: Uint8Array): number;
25
26
  /**
26
27
  * Decode a single, fully buffered eventstream message. Throws if the framing is
27
28
  * malformed or either CRC mismatches. Used by both `decodeEventStream` (the
@@ -1,5 +1,6 @@
1
1
  import { type JsonValue } from "@bufbuild/protobuf";
2
2
  import type { AssistantMessage, CursorExecHandlerResult, CursorExecHandlers, CursorToolResultHandler, Message, StreamFunction, StreamOptions, TextContent, ThinkingContent, ToolCall, ToolResultMessage } from "../types";
3
+ import { kStreamingBlockIndex, kStreamingBlockKind, kStreamingPartialJson } from "../utils/block-symbols";
3
4
  import { AssistantMessageEventStream } from "../utils/event-stream";
4
5
  export declare const CURSOR_API_URL = "https://api2.cursor.sh";
5
6
  export declare const CURSOR_CLIENT_VERSION = "cli-2026.01.09-231024f";
@@ -11,24 +12,24 @@ export interface CursorOptions extends StreamOptions {
11
12
  }
12
13
  export declare const streamCursor: StreamFunction<"cursor-agent">;
13
14
  export type ToolCallState = ToolCall & {
14
- index: number;
15
- partialJson?: string;
16
- kind: "mcp" | "todo";
15
+ [kStreamingBlockIndex]: number;
16
+ [kStreamingPartialJson]?: string;
17
+ [kStreamingBlockKind]: "mcp" | "todo";
17
18
  };
18
19
  export interface BlockState {
19
20
  currentTextBlock: (TextContent & {
20
- index: number;
21
+ [kStreamingBlockIndex]: number;
21
22
  }) | null;
22
23
  currentThinkingBlock: (ThinkingContent & {
23
- index: number;
24
+ [kStreamingBlockIndex]: number;
24
25
  }) | null;
25
26
  currentToolCall: ToolCallState | null;
26
27
  firstTokenTime: number | undefined;
27
28
  setTextBlock: (b: (TextContent & {
28
- index: number;
29
+ [kStreamingBlockIndex]: number;
29
30
  }) | null) => void;
30
31
  setThinkingBlock: (b: (ThinkingContent & {
31
- index: number;
32
+ [kStreamingBlockIndex]: number;
32
33
  }) | null) => void;
33
34
  setToolCall: (t: ToolCallState | null) => void;
34
35
  setFirstTokenTime: () => void;
@@ -1,4 +1,3 @@
1
- import { ProviderHttpError } from "../errors";
2
1
  import type { Context, Model, ProviderSessionState, StreamFunction, StreamOptions } from "../types";
3
2
  import type { Content, FunctionCallingConfigMode, ThinkingConfig } from "./google-shared";
4
3
  import { type GoogleThinkingLevel } from "./google-shared";
@@ -7,10 +6,6 @@ import { type GoogleThinkingLevel } from "./google-shared";
7
6
  * `import { GoogleThinkingLevel } from "./google-gemini-cli"` callers keep working.
8
7
  */
9
8
  export type { GoogleThinkingLevel };
10
- /** Non-2xx response (or in-stream error chunk) from the Cloud Code Assist API. */
11
- export declare class GeminiCliApiError extends ProviderHttpError {
12
- readonly name = "GeminiCliApiError";
13
- }
14
9
  export interface GoogleGeminiCliOptions extends StreamOptions {
15
10
  /**
16
11
  * Tool selection mode. String forms map directly to Gemini
@@ -1,17 +1,12 @@
1
1
  /**
2
2
  * Shared utilities for Google Generative AI and Google Cloud Code Assist providers.
3
3
  */
4
- import { ProviderHttpError } from "../errors";
5
4
  import type { AssistantMessage, Context, FetchImpl, Model, StopReason, StreamOptions, TextContent, ThinkingContent, Tool, ToolCall } from "../types";
6
5
  import { AssistantMessageEventStream } from "../utils/event-stream";
7
6
  import { normalizeSchemaForGoogle } from "../utils/schema";
8
7
  import type { Content, FinishReason, FunctionCallingConfigMode, GenerateContentParameters, GenerateContentResponse, Part } from "./google-types";
9
8
  export type { Content, FunctionCallingConfigMode, GenerateContentParameters, GenerateContentResponse, ThinkingConfig, } from "./google-types";
10
9
  export { normalizeSchemaForGoogle };
11
- /** Non-2xx response (or in-stream error chunk) from the Google Generative Language / Vertex API. */
12
- export declare class GoogleApiError extends ProviderHttpError {
13
- readonly name = "GoogleApiError";
14
- }
15
10
  type GoogleApiType = "google-generative-ai" | "google-gemini-cli" | "google-vertex";
16
11
  /**
17
12
  * Thinking level for Gemini 3 models. Mirrors Google's `ThinkingLevel` enum values.
@@ -1,9 +1,4 @@
1
- import { ProviderHttpError } from "../errors";
2
1
  import type { StreamFunction, StreamOptions, ToolChoice } from "../types";
3
- /** Non-2xx response from the Ollama `/api/chat` endpoint. */
4
- export declare class OllamaApiError extends ProviderHttpError {
5
- readonly name = "OllamaApiError";
6
- }
7
2
  export interface OllamaChatOptions extends StreamOptions {
8
3
  reasoning?: "minimal" | "low" | "medium" | "high" | "xhigh";
9
4
  disableReasoning?: boolean;
@@ -9,11 +9,11 @@ export interface ReasoningConfig {
9
9
  export interface CodexRequestOptions {
10
10
  reasoningEffort?: ReasoningConfig["effort"];
11
11
  reasoningSummary?: ReasoningConfig["summary"] | null;
12
- /** Explicit `reasoning.context` override. Defaults to `all_turns` under {@link CodexRequestOptions.responsesLite}, otherwise omitted (server default is `current_turn`). */
12
+ /** Explicit `reasoning.context` override; defaults to `all_turns` for every Codex request when unset. */
13
13
  reasoningContext?: CodexReasoningContext;
14
14
  textVerbosity?: "low" | "medium" | "high";
15
15
  include?: string[];
16
- /** Responses Lite transport contract: strips image detail and defaults `reasoning.context` to `all_turns`, mirroring codex-rs. */
16
+ /** Responses Lite transport contract: strips image detail and disables parallel tool calling, mirroring codex-rs. */
17
17
  responsesLite?: boolean;
18
18
  }
19
19
  export interface InputItem {
@@ -1,4 +1,4 @@
1
- import { ProviderHttpError } from "../../errors";
1
+ import { ProviderHttpError } from "../../error";
2
2
  export type CodexRateLimit = {
3
3
  used_percent?: number;
4
4
  window_minutes?: number;
@@ -4,7 +4,7 @@ import type { ResponseInput } from "./openai-responses-wire";
4
4
  export interface OpenAICodexResponsesOptions extends StreamOptions {
5
5
  reasoning?: "none" | "minimal" | "low" | "medium" | "high" | "xhigh";
6
6
  reasoningSummary?: "auto" | "concise" | "detailed" | null;
7
- /** `reasoning.context` replay scope. Defaults to `all_turns` under {@link OpenAICodexResponsesOptions.responsesLite}, otherwise omitted (server default is `current_turn`). */
7
+ /** `reasoning.context` replay scope; defaults to `all_turns` for every Codex request when unset. */
8
8
  reasoningContext?: CodexReasoningContext;
9
9
  textVerbosity?: "low" | "medium" | "high";
10
10
  include?: string[];
@@ -17,7 +17,7 @@ export interface OpenAICodexResponsesOptions extends StreamOptions {
17
17
  * `x-openai-internal-codex-responses-lite: true` on HTTP requests and on the
18
18
  * WebSocket upgrade (the marker is connection-scoped there, so lite and
19
19
  * non-lite turns never share a pooled socket), strips image detail from
20
- * input, and defaults `reasoning.context` to `all_turns` — mirroring codex-rs.
20
+ * input, and disables parallel tool calling — mirroring codex-rs.
21
21
  */
22
22
  responsesLite?: boolean;
23
23
  /**
@@ -81,6 +81,7 @@ export declare const inputItemSchema: import("arktype/internal/variants/object.t
81
81
  })[] | undefined;
82
82
  } | {
83
83
  type?: "message" | undefined;
84
+ id?: string | undefined;
84
85
  role: "assistant";
85
86
  content?: string | ({
86
87
  type: "text";
@@ -92,6 +93,8 @@ export declare const inputItemSchema: import("arktype/internal/variants/object.t
92
93
  type: "refusal";
93
94
  refusal: string;
94
95
  })[] | undefined;
96
+ status?: "completed" | "in_progress" | "incomplete" | undefined;
97
+ phase?: "commentary" | "final_answer" | null | undefined;
95
98
  } | {
96
99
  type: "reasoning";
97
100
  id?: string | undefined;
@@ -221,6 +224,7 @@ export declare const openaiResponsesRequestSchema: import("arktype/internal/vari
221
224
  })[] | undefined;
222
225
  } | {
223
226
  type?: "message" | undefined;
227
+ id?: string | undefined;
224
228
  role: "assistant";
225
229
  content?: string | ({
226
230
  type: "text";
@@ -232,6 +236,8 @@ export declare const openaiResponsesRequestSchema: import("arktype/internal/vari
232
236
  type: "refusal";
233
237
  refusal: string;
234
238
  })[] | undefined;
239
+ status?: "completed" | "in_progress" | "incomplete" | undefined;
240
+ phase?: "commentary" | "final_answer" | null | undefined;
235
241
  } | {
236
242
  type: "reasoning";
237
243
  id?: string | undefined;
@@ -5627,7 +5627,7 @@ export interface ResponseCreateParamsBase {
5627
5627
  * - [Conversation state](https://platform.openai.com/docs/guides/conversation-state)
5628
5628
  * - [Function calling](https://platform.openai.com/docs/guides/function-calling)
5629
5629
  */
5630
- input?: string | ResponseInput;
5630
+ input?: ResponseInput;
5631
5631
  /**
5632
5632
  * A system (or developer) message inserted into the model's context.
5633
5633
  *
@@ -7,6 +7,7 @@ export interface OpenAIResponsesOptions extends StreamOptions {
7
7
  reasoning?: "minimal" | "low" | "medium" | "high" | "xhigh";
8
8
  reasoningSummary?: "auto" | "detailed" | "concise" | null;
9
9
  serviceTier?: ServiceTier;
10
+ textVerbosity?: "low" | "medium" | "high";
10
11
  toolChoice?: ToolChoice;
11
12
  openrouterVariant?: string;
12
13
  maxTokensExplicit?: boolean;
@@ -117,9 +118,9 @@ export declare function buildParams(model: Model<"openai-responses">, context: C
117
118
  * runtime path only consumes that metadata.
118
119
  * @internal Exported for tests.
119
120
  */
120
- export declare function supportsFreeformApplyPatch(model: Model<"openai-responses">): boolean;
121
+ export declare function supportsFreeformApplyPatch(model: Model<"openai-responses" | "azure-openai-responses" | "openai-codex-responses">): boolean;
121
122
  /** @internal Exported for tests. */
122
123
  export declare function mapOpenAIResponsesToolChoiceForTools(choice: ToolChoice | undefined, tools: Tool[], model: Model<"openai-responses">): OpenAIResponsesToolChoice;
123
124
  /** @internal Exported for tests. */
124
- export declare function convertTools(tools: Tool[], strictMode: boolean, model: Model<"openai-responses">, onQuarantine?: (toolName: string, schemaPath: string) => void): OpenAITool[];
125
+ export declare function convertTools(tools: Tool[], strictMode: boolean, model: Model<"openai-responses" | "azure-openai-responses" | "openai-codex-responses">, onQuarantine?: (toolName: string, schemaPath: string) => void): OpenAITool[];
125
126
  export {};
@@ -1,9 +1,11 @@
1
1
  import type { OpenAICompat, OpenAIReasoningDisableMode, OpenAIStreamMarkupHealingPattern, OpenRouterRouting, ResolvedOpenAICompat, ResolvedOpenAIResponsesCompat, ResolvedOpenAISharedCompat, VercelGatewayRouting } from "@oh-my-pi/pi-catalog/types";
2
2
  import { type Api, type AssistantMessage, type CacheRetention, type Context, type ImageContent, type Message, type MessageAttribution, type Model, type Provider, type ResolvedServiceTier, type ServiceTier, type StopReason, type StreamOptions, type TextContent, type TextSignatureV1, type ThinkingContent, type Tool, type ToolCall, type ToolResultMessage } from "../types";
3
+ import { kStreamingLastParseLen, kStreamingPartialJson } from "../utils/block-symbols";
3
4
  import type { AssistantMessageEventStream } from "../utils/event-stream";
4
5
  import type { CapturedHttpErrorResponse } from "../utils/http-inspector";
5
6
  import type { ChatCompletionCreateParamsStreaming } from "./openai-chat-wire";
6
- import type { ResponseContentPartAddedEvent, ResponseCreateParamsStreaming, ResponseInput, ResponseInputContent, ResponseOutputItem, ResponseOutputMessage, ResponseReasoningItem, ResponseStatus, ResponseStreamEvent } from "./openai-responses-wire";
7
+ import type { InputItem } from "./openai-codex/request-transformer";
8
+ import type { ResponseContentPartAddedEvent, ResponseCreateParamsStreaming, ResponseInput, ResponseInputContent, ResponseInputItem, ResponseOutputItem, ResponseOutputMessage, ResponseReasoningItem, ResponseStatus, ResponseStreamEvent } from "./openai-responses-wire";
7
9
  export interface OpenAIModelIdentity {
8
10
  provider: string;
9
11
  id: string;
@@ -373,8 +375,8 @@ export declare function appendResponsesToolResultMessages<TApi extends Api>(mess
373
375
  * each decoder's existing behavior byte-for-byte.
374
376
  */
375
377
  type ResponsesToolCallBlock = ToolCall & {
376
- partialJson: string;
377
- lastParseLen?: number;
378
+ [kStreamingPartialJson]: string;
379
+ [kStreamingLastParseLen]?: number;
378
380
  };
379
381
  export declare function appendReasoningSummaryPart(item: ResponseReasoningItem, part: ResponseReasoningItem["summary"][number]): void;
380
382
  export declare function appendReasoningSummaryTextDelta(item: ResponseReasoningItem, block: ThinkingContent, delta: string, stream: AssistantMessageEventStream, output: AssistantMessage, contentIndex: number): void;
@@ -494,9 +496,9 @@ export declare function populateResponsesUsageFromResponse(output: AssistantMess
494
496
  * `client_metadata` (e.g. rotating turn ids) is excluded from the option
495
497
  * comparison; codex-rs excludes it from the same check.
496
498
  */
497
- export declare function buildResponsesDeltaInput<TItem>(previous: {
498
- input?: unknown;
499
+ export declare function buildResponsesDeltaInput<TItem extends ResponseInputItem | InputItem>(previous: {
500
+ input?: TItem[];
499
501
  } | undefined, previousResponseItems: readonly TItem[] | undefined, current: {
500
- input?: unknown;
502
+ input?: TItem[];
501
503
  }): TItem[] | null;
502
504
  export {};
@@ -1,13 +1,4 @@
1
- import { ProviderHttpError } from "../errors";
2
1
  import type { Api, AssistantMessageEventStream as AssistantMessageEventStreamType, Context, Model, SimpleStreamOptions } from "../types";
3
- /**
4
- * Non-2xx response from the auth-gateway `/v1/pi/stream` endpoint. `code`
5
- * carries the gateway's error-type token (`authentication_error`,
6
- * `rate_limit_error`, `upstream_error`, ...).
7
- */
8
- export declare class AuthGatewayError extends ProviderHttpError {
9
- constructor(message: string, status: number, headers?: Headers, code?: string);
10
- }
11
2
  /**
12
3
  * Stream a turn through an `omp auth-gateway` over the pi-native protocol.
13
4
  *
@@ -1,12 +1,3 @@
1
- /**
2
- * xAI Grok (SuperGrok Subscription) OAuth flow.
3
- *
4
- * Loopback PKCE flow on `127.0.0.1:56121/callback`. One token unlocks Grok-4.x
5
- * chat, Grok Imagine image generation, and Grok Voice TTS via subsequent
6
- * commits. Endpoint discovery is hardened against MITM via
7
- * {@link validateXAIEndpoint}: any non-HTTPS or non-`x.ai`/`*.x.ai` host is
8
- * rejected on every call site, not just the first.
9
- */
10
1
  import type { FetchImpl } from "../../types";
11
2
  import { OAuthCallbackFlow } from "./callback-server";
12
3
  import type { OAuthController, OAuthCredentials } from "./types";
@@ -20,6 +20,7 @@ import type { OllamaChatOptions } from "./providers/ollama";
20
20
  import type { OpenAICodexResponsesOptions } from "./providers/openai-codex-responses";
21
21
  import type { OpenAICompletionsOptions } from "./providers/openai-completions";
22
22
  import type { OpenAIResponsesOptions } from "./providers/openai-responses";
23
+ import type { kStreamingPartialJson } from "./utils/block-symbols";
23
24
  import type { AssistantMessageEventStream } from "./utils/event-stream";
24
25
  export type { StopDetails } from "./providers/anthropic-wire";
25
26
  export type { AssistantMessageEventStream } from "./utils/event-stream";
@@ -303,6 +304,8 @@ export interface SimpleStreamOptions extends Omit<StreamOptions, "apiKey"> {
303
304
  * Useful when the UI hides thinking blocks anyway and the summary is wasted bandwidth.
304
305
  */
305
306
  hideThinkingSummary?: boolean;
307
+ /** OpenAI Responses/Codex `text.verbosity` response detail level. */
308
+ textVerbosity?: "low" | "medium" | "high";
306
309
  /** Custom token budgets for thinking levels (token-based providers only) */
307
310
  thinkingBudgets?: ThinkingBudgets;
308
311
  /** Cursor exec handlers for local tool execution */
@@ -369,6 +372,7 @@ export interface ToolCall {
369
372
  id: string;
370
373
  name: string;
371
374
  arguments: Record<string, unknown>;
375
+ [kStreamingPartialJson]?: string;
372
376
  thoughtSignature?: string;
373
377
  intent?: string;
374
378
  /**
@@ -442,6 +446,8 @@ export interface AssistantMessage {
442
446
  errorMessage?: string;
443
447
  /** HTTP status surfaced by the provider when the request failed. Populated by every provider's catch block alongside `errorMessage` so consumers (auth retry, telemetry, UI) can branch without regex-scraping the message. */
444
448
  errorStatus?: number;
449
+ /** Structured machine-readable error classifier; see `utils/error-id.ts` for bit layout and helpers. */
450
+ errorId?: number;
445
451
  /**
446
452
  * Stable identifiers for request features the provider silently dropped
447
453
  * during this turn (e.g. `"priority"`). Set when a server-side rejection
@@ -1 +1,18 @@
1
+ /**
2
+ * Resolve the base URL for ChatGPT account-API requests (`wham/usage`,
3
+ * `wham/rate-limit-reset-credits`).
4
+ *
5
+ * These endpoints live on the canonical ChatGPT origin and authenticate with
6
+ * the Codex OAuth bearer minted for that origin. They are NOT part of the
7
+ * `/responses` API surface that streaming proxies (Headroom, 9router, etc.)
8
+ * forward, so a `providers.openai-codex.baseUrl` override pointed at such a
9
+ * proxy MUST NOT be used here — doing so 404s and silently breaks
10
+ * `/usage show` (issue #3679).
11
+ *
12
+ * Accepted overrides are the canonical `chatgpt.com` / `chat.openai.com`
13
+ * origins. Any extra path (e.g. a streaming override like
14
+ * `/backend-api/codex/responses`) is normalized to `${origin}/backend-api`,
15
+ * since the account endpoints always live directly under `/backend-api`. Any
16
+ * other host falls back to {@link CODEX_BASE_URL}.
17
+ */
1
18
  export declare function normalizeCodexBaseUrl(baseUrl?: string): string;
@@ -0,0 +1,20 @@
1
+ /** Stores streamed tool-call argument JSON for live renderers and parser recovery. */
2
+ export declare const kStreamingPartialJson: unique symbol;
3
+ /** Carries streamed tool-call argument JSON without exposing a string-keyed property. */
4
+ export type StreamingPartialJsonCarrier = object & {
5
+ [kStreamingPartialJson]?: string;
6
+ };
7
+ /** Reads streamed tool-call argument JSON from a block or event snapshot. */
8
+ export declare function getStreamingPartialJson(block: StreamingPartialJsonCarrier | null | undefined): string | undefined;
9
+ /** Writes streamed tool-call argument JSON to a block or clears it with `undefined`. */
10
+ export declare function setStreamingPartialJson(block: StreamingPartialJsonCarrier, value: string | undefined): void;
11
+ /** Clears streamed tool-call argument JSON without deleting or changing object shape. */
12
+ export declare function clearStreamingPartialJson(block: StreamingPartialJsonCarrier): void;
13
+ /** Stores a provider-local stream block index without exposing a string-keyed property. */
14
+ export declare const kStreamingBlockIndex: unique symbol;
15
+ /** Stores the last parsed argument prefix length for throttled streaming JSON parsing. */
16
+ export declare const kStreamingLastParseLen: unique symbol;
17
+ /** Marks streamed tool-call arguments that already received an authoritative done payload. */
18
+ export declare const kStreamingArgumentsDone: unique symbol;
19
+ /** Classifies Cursor's in-flight tool-call kind without leaking provider-private state. */
20
+ export declare const kStreamingBlockKind: unique symbol;
@@ -15,14 +15,10 @@
15
15
  * chain-state detectors, which regex over `error.message`.
16
16
  */
17
17
  import { type SseEventObserver } from "@oh-my-pi/pi-utils";
18
- import { ProviderHttpError } from "../errors";
18
+ import * as AIError from "../error";
19
+ import { OpenAIHttpError } from "../error";
20
+ export { OpenAIHttpError };
19
21
  import type { FetchImpl } from "../types";
20
- import type { CapturedHttpErrorResponse } from "./http-inspector";
21
- /** Non-2xx response from an OpenAI-wire endpoint, with the decoded body attached. */
22
- export declare class OpenAIHttpError extends ProviderHttpError {
23
- readonly captured: CapturedHttpErrorResponse;
24
- constructor(message: string, captured: CapturedHttpErrorResponse, code: string | undefined);
25
- }
26
22
  export interface OpenAIStreamRequestInit {
27
23
  url: string;
28
24
  headers: Record<string, string>;
@@ -55,4 +51,4 @@ export interface OpenAIStreamHandle<TEvent> {
55
51
  */
56
52
  export declare function postOpenAIStream<TEvent>(init: OpenAIStreamRequestInit): Promise<OpenAIStreamHandle<TEvent>>;
57
53
  /** Decode a non-2xx response into an {@link OpenAIHttpError} without consuming it twice. */
58
- export declare function captureOpenAIHttpError(response: Response): Promise<OpenAIHttpError>;
54
+ export declare function captureOpenAIHttpError(response: Response): Promise<AIError.OpenAIHttpError>;
@@ -1,17 +1,5 @@
1
- /**
2
- * GitHub Copilot intermittently rejects preview models (gpt-5.3-codex,
3
- * gpt-5.4, gpt-5.4-mini, ...) with HTTP 400 `model_not_supported`, even
4
- * though the model is listed as enabled on the user's account via `/models`.
5
- *
6
- * Root cause: Copilot's request-routing backend is rolled out per OAuth
7
- * client. Our OAuth client id is shared with opencode; VS Code uses its own
8
- * client and sees full availability, so the same account may succeed in VS
9
- * Code and flap between 200/400 here. See opencode#13313 and copilot-cli#2597.
10
- *
11
- * Retrying the identical request 2-3 times almost always lands on a backend
12
- * that has the model, so we wrap the initial request with a short retry loop.
13
- */
14
- export declare function isCopilotTransientModelError(error: unknown): boolean;
1
+ import { isCopilotTransientModelError } from "../error/flags";
2
+ export { isCopilotTransientModelError };
15
3
  /**
16
4
  * Wrap an initial Copilot request so transient `model_not_supported` 400s are
17
5
  * retried a small number of times. No-op for non-Copilot providers.
@@ -29,6 +29,12 @@ export type StreamMarkupHealingEvent = {
29
29
  * State machine that consumes streamed visible text and emits cleaned text,
30
30
  * thinking deltas, and reconstructed tool calls.
31
31
  *
32
+ * A {@link ThinkingInbandScanner} always heals leaked reasoning idioms
33
+ * (`<think>`, `<thinking>`, ` ```thinking `, Gemma/Harmony channels, …) out of
34
+ * the visible channel. For Kimi / DeepSeek-DSML the provider tool-call grammar
35
+ * runs first and its cleaned text is piped through that thinking healer, so a
36
+ * model can leak tool-call markup and reasoning in the same stream.
37
+ *
32
38
  * Feed only one stream channel (usually `delta.content` / `message.content`).
33
39
  * Mixing reasoning and visible text into the same instance can corrupt held-back
34
40
  * partial tag buffers.
@@ -71,8 +77,11 @@ export declare class StreamMarkupHealing {
71
77
  export declare function modelMayLeakKimiToolCalls(provider: string, modelId: string): boolean;
72
78
  /** Cheap model/provider gate for DeepSeek DSML envelope leaks. */
73
79
  export declare function modelMayLeakDsmlToolCalls(provider: string, modelId: string): boolean;
74
- /** Cheap model/provider gate for MiniMax plain thinking tag leaks. */
75
- export declare function modelMayLeakThinkingTags(provider: string, modelId: string): boolean;
76
- export declare function getStreamMarkupHealingPattern(provider: string, modelId: string, options?: {
77
- readonly parseThinkingTags?: boolean;
78
- }): StreamMarkupHealingPattern | undefined;
80
+ /**
81
+ * Pick the leaked-markup healer for an OpenAI-compatible / Ollama visible-text
82
+ * stream. Kimi chat-template tokens and DeepSeek DSML envelopes need their
83
+ * dedicated tool-call grammars; every other model uses `"thinking"`. All three
84
+ * patterns run the generic {@link ThinkingInbandScanner}, so leaked reasoning
85
+ * idioms (e.g. a Gemini ` ```thinking ` fence on OpenRouter) are always healed.
86
+ */
87
+ export declare function getStreamMarkupHealingPattern(provider: string, modelId: string): StreamMarkupHealingPattern;
@@ -84,7 +84,9 @@ export declare function guardThinkingLoopStream(inner: AssistantMessageEventStre
84
84
  * Apply the loop guard around a provider dispatch. For non-guarded models
85
85
  * (or when disabled) this is a transparent pass-through. For guarded models it injects a
86
86
  * guard abort signal into the provider call so a detected loop tears down the
87
- * upstream, then wraps the returned stream.
87
+ * upstream, then wraps the returned stream. The guard only raises the retryable
88
+ * stall; bounding the re-samples and the final cook pass lives in the
89
+ * result-awaiting caller.
88
90
  */
89
91
  export declare function withGeminiThinkingLoopGuard<O extends {
90
92
  signal?: AbortSignal;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "type": "module",
3
3
  "name": "@oh-my-pi/pi-ai",
4
- "version": "16.2.1",
4
+ "version": "16.2.3",
5
5
  "description": "Unified LLM API with automatic model discovery and provider configuration",
6
6
  "homepage": "https://omp.sh",
7
7
  "author": "Can Boluk",
@@ -38,9 +38,9 @@
38
38
  },
39
39
  "dependencies": {
40
40
  "@bufbuild/protobuf": "^2.12.0",
41
- "@oh-my-pi/pi-catalog": "16.2.1",
42
- "@oh-my-pi/pi-utils": "16.2.1",
43
- "@oh-my-pi/pi-wire": "16.2.1",
41
+ "@oh-my-pi/pi-catalog": "16.2.3",
42
+ "@oh-my-pi/pi-utils": "16.2.3",
43
+ "@oh-my-pi/pi-wire": "16.2.3",
44
44
  "arktype": "^2.2.0",
45
45
  "zod": "^4"
46
46
  },
@@ -62,6 +62,10 @@
62
62
  "types": "./dist/types/index.d.ts",
63
63
  "import": "./src/index.ts"
64
64
  },
65
+ "./error": {
66
+ "types": "./dist/types/error/index.d.ts",
67
+ "import": "./src/error/index.ts"
68
+ },
65
69
  "./*": {
66
70
  "types": "./dist/types/*.d.ts",
67
71
  "import": "./src/*.ts"
@@ -4,6 +4,8 @@
4
4
  * Allows extensions to register streaming functions for custom API types
5
5
  * (e.g., "vertex-claude-api") that are not built into stream.ts.
6
6
  */
7
+
8
+ import * as AIError from "./error";
7
9
  import type {
8
10
  Api,
9
11
  AssistantMessageEventStream,
@@ -60,7 +62,7 @@ const customApiRegistry = new Map<string, RegisteredCustomApi>();
60
62
 
61
63
  function assertCustomApiName(api: string): void {
62
64
  if (BUILTIN_APIS.has(api as KnownApi)) {
63
- throw new Error(`Cannot register custom API "${api}": built-in API names are reserved.`);
65
+ throw new AIError.ConfigurationError(`Cannot register custom API "${api}": built-in API names are reserved.`);
64
66
  }
65
67
  }
66
68