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

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 (166) hide show
  1. package/CHANGELOG.md +27 -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 +1 -0
  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/utils/block-symbols.d.ts +20 -0
  42. package/dist/types/utils/openai-http.d.ts +4 -8
  43. package/dist/types/utils/retry.d.ts +2 -14
  44. package/dist/types/utils/thinking-loop.d.ts +3 -1
  45. package/package.json +8 -4
  46. package/src/api-registry.ts +3 -1
  47. package/src/auth-broker/discover.ts +7 -2
  48. package/src/auth-broker/remote-store.ts +8 -7
  49. package/src/auth-gateway/server.ts +27 -115
  50. package/src/auth-retry.ts +9 -21
  51. package/src/auth-storage.ts +34 -49
  52. package/src/dialect/demotion.ts +31 -0
  53. package/src/dialect/factory.ts +0 -2
  54. package/src/dialect/index.ts +2 -0
  55. package/src/dialect/owned-stream.ts +0 -1
  56. package/src/dialect/thinking.ts +22 -10
  57. package/src/error/abort.ts +18 -0
  58. package/src/error/auth-classify.ts +30 -0
  59. package/src/error/auth.ts +48 -0
  60. package/src/error/aws.ts +31 -0
  61. package/src/error/classes.ts +186 -0
  62. package/src/error/finalize.ts +69 -0
  63. package/src/error/flags.ts +486 -0
  64. package/src/error/format.ts +36 -0
  65. package/src/error/gateway.ts +96 -0
  66. package/src/error/index.ts +13 -0
  67. package/src/error/oauth.ts +58 -0
  68. package/src/error/provider.ts +56 -0
  69. package/src/{rate-limit-utils.ts → error/rate-limit.ts} +9 -3
  70. package/src/error/retryable.ts +70 -0
  71. package/src/error/validation.ts +44 -0
  72. package/src/index.ts +1 -3
  73. package/src/providers/amazon-bedrock.ts +61 -57
  74. package/src/providers/anthropic-client.ts +13 -41
  75. package/src/providers/anthropic-messages-server.ts +9 -2
  76. package/src/providers/anthropic.ts +84 -147
  77. package/src/providers/aws-credentials.ts +41 -11
  78. package/src/providers/aws-eventstream.ts +12 -21
  79. package/src/providers/azure-openai-responses.ts +27 -17
  80. package/src/providers/cursor.ts +59 -53
  81. package/src/providers/devin.ts +28 -20
  82. package/src/providers/gitlab-duo-workflow.ts +30 -10
  83. package/src/providers/gitlab-duo.ts +22 -6
  84. package/src/providers/google-auth.ts +15 -5
  85. package/src/providers/google-gemini-cli.ts +46 -60
  86. package/src/providers/google-shared.ts +40 -38
  87. package/src/providers/google-vertex.ts +3 -2
  88. package/src/providers/google.ts +5 -1
  89. package/src/providers/mock.ts +10 -7
  90. package/src/providers/ollama.ts +34 -29
  91. package/src/providers/openai-chat-server.ts +2 -1
  92. package/src/providers/openai-codex/request-transformer.ts +13 -12
  93. package/src/providers/openai-codex/response-handler.ts +1 -1
  94. package/src/providers/openai-codex-responses.ts +931 -1012
  95. package/src/providers/openai-completions.ts +46 -36
  96. package/src/providers/openai-responses-server-schema.ts +3 -0
  97. package/src/providers/openai-responses-server.ts +82 -30
  98. package/src/providers/openai-responses-wire.ts +1 -1
  99. package/src/providers/openai-responses.ts +46 -22
  100. package/src/providers/openai-shared.ts +118 -51
  101. package/src/providers/pi-native-client.ts +12 -18
  102. package/src/providers/pi-native-server.ts +9 -6
  103. package/src/providers/register-builtins.ts +5 -2
  104. package/src/providers/transform-messages.ts +31 -63
  105. package/src/registry/alibaba-coding-plan.ts +6 -5
  106. package/src/registry/api-key-login.ts +4 -3
  107. package/src/registry/api-key-validation.ts +4 -3
  108. package/src/registry/cloudflare-ai-gateway.ts +4 -3
  109. package/src/registry/coreweave.ts +2 -1
  110. package/src/registry/deepseek.ts +2 -1
  111. package/src/registry/google-antigravity.ts +2 -1
  112. package/src/registry/google-gemini-cli.ts +2 -1
  113. package/src/registry/kagi.ts +4 -3
  114. package/src/registry/kilo.ts +32 -10
  115. package/src/registry/litellm.ts +4 -3
  116. package/src/registry/llama-cpp.ts +3 -2
  117. package/src/registry/lm-studio.ts +3 -2
  118. package/src/registry/nvidia.ts +7 -7
  119. package/src/registry/oauth/anthropic.ts +23 -6
  120. package/src/registry/oauth/callback-server.ts +5 -3
  121. package/src/registry/oauth/cursor.ts +18 -4
  122. package/src/registry/oauth/devin.ts +14 -3
  123. package/src/registry/oauth/github-copilot.ts +21 -10
  124. package/src/registry/oauth/gitlab-duo-workflow.ts +15 -3
  125. package/src/registry/oauth/gitlab-duo.ts +30 -6
  126. package/src/registry/oauth/google-antigravity.ts +14 -5
  127. package/src/registry/oauth/google-gemini-cli.ts +24 -7
  128. package/src/registry/oauth/google-oauth-shared.ts +6 -3
  129. package/src/registry/oauth/index.ts +19 -8
  130. package/src/registry/oauth/kimi.ts +40 -10
  131. package/src/registry/oauth/openai-codex.ts +26 -11
  132. package/src/registry/oauth/opencode.ts +4 -3
  133. package/src/registry/oauth/perplexity.ts +33 -11
  134. package/src/registry/oauth/xai-oauth.ts +62 -18
  135. package/src/registry/oauth/xiaomi.ts +21 -9
  136. package/src/registry/ollama-cloud.ts +5 -4
  137. package/src/registry/ollama.ts +3 -2
  138. package/src/registry/parallel.ts +4 -3
  139. package/src/registry/qwen-portal.ts +4 -3
  140. package/src/registry/tavily.ts +4 -3
  141. package/src/registry/vercel-ai-gateway.ts +4 -3
  142. package/src/registry/vllm.ts +3 -2
  143. package/src/stream.ts +79 -24
  144. package/src/types.ts +6 -0
  145. package/src/usage/claude.ts +2 -1
  146. package/src/usage/github-copilot.ts +4 -3
  147. package/src/usage/google-antigravity.ts +2 -1
  148. package/src/utils/abort.ts +4 -2
  149. package/src/utils/block-symbols.ts +32 -0
  150. package/src/utils/event-stream.ts +15 -3
  151. package/src/utils/http-inspector.ts +4 -4
  152. package/src/utils/idle-iterator.ts +6 -5
  153. package/src/utils/openai-http.ts +11 -46
  154. package/src/utils/parse-bind.ts +7 -5
  155. package/src/utils/proxy.ts +2 -1
  156. package/src/utils/retry.ts +7 -23
  157. package/src/utils/schema/normalize.ts +3 -2
  158. package/src/utils/thinking-loop.ts +15 -11
  159. package/src/utils/validation.ts +4 -3
  160. package/dist/types/dialect/pi.d.ts +0 -9
  161. package/dist/types/errors.d.ts +0 -24
  162. package/dist/types/utils/overflow.d.ts +0 -55
  163. package/src/dialect/pi.md +0 -55
  164. package/src/dialect/pi.ts +0 -600
  165. package/src/errors.ts +0 -32
  166. package/src/utils/overflow.ts +0 -140
@@ -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;
@@ -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
@@ -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.
@@ -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.2",
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.2",
42
+ "@oh-my-pi/pi-utils": "16.2.2",
43
+ "@oh-my-pi/pi-wire": "16.2.2",
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
 
@@ -15,6 +15,7 @@ import {
15
15
  } from "@oh-my-pi/pi-utils";
16
16
  import { YAML } from "bun";
17
17
  import { AuthStorage } from "../auth-storage";
18
+ import * as AIError from "../error";
18
19
  import { AuthBrokerClient } from "./client";
19
20
  import { RemoteAuthCredentialStore } from "./remote-store";
20
21
  import { readAuthBrokerSnapshotCache, writeAuthBrokerSnapshotCache } from "./snapshot-cache";
@@ -137,7 +138,8 @@ export async function resolveAuthBrokerConfig(
137
138
  const token =
138
139
  (envToken && envToken.length > 0 ? envToken : undefined) ?? configToken ?? (await readTokenFile()) ?? undefined;
139
140
  if (!token) {
140
- throw new Error(
141
+ throw new AIError.MissingApiKeyError(
142
+ undefined,
141
143
  `OMP_AUTH_BROKER_URL is set (${url}) but no bearer token is available. ` +
142
144
  `Set OMP_AUTH_BROKER_TOKEN, the \`auth.broker.token\` config entry, or place one at ${getAuthBrokerTokenFilePath()}.`,
143
145
  );
@@ -190,7 +192,10 @@ export async function discoverAuthStorage(options: DiscoverAuthStorageOptions =
190
192
  }
191
193
  if (!initialSnapshot) {
192
194
  const initialResult = await client.fetchSnapshot();
193
- if (initialResult.status !== 200) throw new Error("Auth broker returned no initial snapshot");
195
+ if (initialResult.status !== 200)
196
+ throw new AIError.AuthBrokerError("Auth broker returned no initial snapshot", {
197
+ status: initialResult.status,
198
+ });
194
199
  initialSnapshot = initialResult.snapshot;
195
200
  persist?.(initialSnapshot);
196
201
  }
@@ -17,6 +17,7 @@ import {
17
17
  REMOTE_REFRESH_SENTINEL,
18
18
  type StoredAuthCredential,
19
19
  } from "../auth-storage";
20
+ import * as AIError from "../error";
20
21
  import type { OAuthCredentials } from "../registry/oauth/types";
21
22
  import type { Provider } from "../types";
22
23
  import type { UsageReport } from "../usage";
@@ -313,26 +314,26 @@ export class RemoteAuthCredentialStore implements AuthCredentialStore {
313
314
  async markCredentialSuspect(credentialId: number, opts: { signal?: AbortSignal } = {}): Promise<void> {
314
315
  const { entry } = await this.#client.refreshCredential(credentialId, opts.signal);
315
316
  if (entry.credential.type !== "oauth") {
316
- throw new Error(`Broker returned non-OAuth credential for id=${credentialId}`);
317
+ throw new AIError.AuthBrokerError(`Broker returned non-OAuth credential for id=${credentialId}`);
317
318
  }
318
319
  this.#applyCredentialEntry(entry);
319
320
  this.#maybeRefreshSnapshot("suspect credential refresh");
320
321
  }
321
322
 
322
323
  replaceAuthCredentialsForProvider(_provider: string, _credentials: AuthCredential[]): StoredAuthCredential[] {
323
- throw new Error(
324
+ throw new AIError.AuthBrokerError(
324
325
  "RemoteAuthCredentialStore is read-only on the client. Use `omp auth-broker login <provider>` to mutate credentials.",
325
326
  );
326
327
  }
327
328
 
328
329
  upsertAuthCredentialForProvider(_provider: string, _credential: AuthCredential): StoredAuthCredential[] {
329
- throw new Error(
330
+ throw new AIError.AuthBrokerError(
330
331
  "RemoteAuthCredentialStore is read-only on the client. Use `omp auth-broker login <provider>` to mutate credentials.",
331
332
  );
332
333
  }
333
334
 
334
335
  deleteAuthCredentialsForProvider(_provider: string, _disabledCause: string): void {
335
- throw new Error(
336
+ throw new AIError.AuthBrokerError(
336
337
  "RemoteAuthCredentialStore is read-only on the client. Use `omp auth-broker logout <provider>` to mutate credentials.",
337
338
  );
338
339
  }
@@ -487,7 +488,7 @@ export class RemoteAuthCredentialStore implements AuthCredentialStore {
487
488
  });
488
489
  }
489
490
  if (entry.credential.type !== "oauth") {
490
- throw new Error(`Broker returned non-OAuth credential for id=${credentialId}`);
491
+ throw new AIError.AuthBrokerError(`Broker returned non-OAuth credential for id=${credentialId}`);
491
492
  }
492
493
  const refreshed = entry.credential;
493
494
  return {
@@ -538,11 +539,11 @@ export class RemoteAuthCredentialStore implements AuthCredentialStore {
538
539
  */
539
540
  #raceWithSignal<T>(promise: Promise<T>, signal?: AbortSignal): Promise<T> {
540
541
  if (!signal) return promise;
541
- if (signal.aborted) return Promise.reject(new Error("auth-broker request aborted"));
542
+ if (signal.aborted) return Promise.reject(new AIError.AbortError("auth-broker request aborted"));
542
543
  return new Promise<T>((resolve, reject) => {
543
544
  const onAbort = (): void => {
544
545
  signal.removeEventListener("abort", onAbort);
545
- reject(new Error("auth-broker request aborted"));
546
+ reject(new AIError.AbortError("auth-broker request aborted"));
546
547
  };
547
548
  signal.addEventListener("abort", onAbort, { once: true });
548
549
  promise.then(