@oh-my-pi/pi-ai 7.0.0 → 8.0.1

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@oh-my-pi/pi-ai",
3
- "version": "7.0.0",
3
+ "version": "8.0.1",
4
4
  "description": "Unified LLM API with automatic model discovery and provider configuration",
5
5
  "type": "module",
6
6
  "main": "./src/index.ts",
@@ -10,14 +10,16 @@
10
10
  },
11
11
  "files": [
12
12
  "src",
13
- "README.md"
13
+ "README.md",
14
+ "tsconfig.json"
14
15
  ],
15
16
  "scripts": {
16
17
  "generate-models": "bun scripts/generate-models.ts",
17
- "test": "bun test"
18
+ "test": "bun test",
19
+ "prepublishOnly": "cp tsconfig.publish.json tsconfig.json"
18
20
  },
19
21
  "dependencies": {
20
- "@oh-my-pi/pi-utils": "7.0.0",
22
+ "@oh-my-pi/pi-utils": "8.0.0",
21
23
  "@anthropic-ai/sdk": "0.71.2",
22
24
  "@aws-sdk/client-bedrock-runtime": "^3.968.0",
23
25
  "@bufbuild/protobuf": "^2.10.2",
@@ -18,7 +18,7 @@ import {
18
18
  ToolResultStatus,
19
19
  } from "@aws-sdk/client-bedrock-runtime";
20
20
 
21
- import { calculateCost } from "../models";
21
+ import { calculateCost } from "$ai/models";
22
22
  import type {
23
23
  Api,
24
24
  AssistantMessage,
@@ -34,10 +34,10 @@ import type {
34
34
  Tool,
35
35
  ToolCall,
36
36
  ToolResultMessage,
37
- } from "../types";
38
- import { AssistantMessageEventStream } from "../utils/event-stream";
39
- import { parseStreamingJson } from "../utils/json-parse";
40
- import { sanitizeSurrogates } from "../utils/sanitize-unicode";
37
+ } from "$ai/types";
38
+ import { AssistantMessageEventStream } from "$ai/utils/event-stream";
39
+ import { parseStreamingJson } from "$ai/utils/json-parse";
40
+ import { sanitizeSurrogates } from "$ai/utils/sanitize-unicode";
41
41
  import { transformMessages } from "./transform-messages";
42
42
 
43
43
  export interface BedrockOptions extends StreamOptions {
@@ -4,8 +4,8 @@ import type {
4
4
  MessageCreateParamsStreaming,
5
5
  MessageParam,
6
6
  } from "@anthropic-ai/sdk/resources/messages";
7
- import { calculateCost } from "../models";
8
- import { getEnvApiKey, OUTPUT_FALLBACK_BUFFER } from "../stream";
7
+ import { calculateCost } from "$ai/models";
8
+ import { getEnvApiKey, OUTPUT_FALLBACK_BUFFER } from "$ai/stream";
9
9
  import type {
10
10
  Api,
11
11
  AssistantMessage,
@@ -21,11 +21,11 @@ import type {
21
21
  Tool,
22
22
  ToolCall,
23
23
  ToolResultMessage,
24
- } from "../types";
25
- import { AssistantMessageEventStream } from "../utils/event-stream";
26
- import { parseStreamingJson } from "../utils/json-parse";
27
- import { formatErrorMessageWithRetryAfter } from "../utils/retry-after";
28
- import { sanitizeSurrogates } from "../utils/sanitize-unicode";
24
+ } from "$ai/types";
25
+ import { AssistantMessageEventStream } from "$ai/utils/event-stream";
26
+ import { parseStreamingJson } from "$ai/utils/json-parse";
27
+ import { formatErrorMessageWithRetryAfter } from "$ai/utils/retry-after";
28
+ import { sanitizeSurrogates } from "$ai/utils/sanitize-unicode";
29
29
 
30
30
  import { transformMessages } from "./transform-messages";
31
31
 
@@ -4,7 +4,7 @@ import http2 from "node:http2";
4
4
  import { create, fromBinary, fromJson, type JsonValue, toBinary, toJson } from "@bufbuild/protobuf";
5
5
  import { ValueSchema } from "@bufbuild/protobuf/wkt";
6
6
  import JSON5 from "json5";
7
- import { calculateCost } from "../models";
7
+ import { calculateCost } from "$ai/models";
8
8
  import type {
9
9
  Api,
10
10
  AssistantMessage,
@@ -23,10 +23,10 @@ import type {
23
23
  Tool,
24
24
  ToolCall,
25
25
  ToolResultMessage,
26
- } from "../types";
27
- import { AssistantMessageEventStream } from "../utils/event-stream";
28
- import { parseStreamingJson } from "../utils/json-parse";
29
- import { formatErrorMessageWithRetryAfter } from "../utils/retry-after";
26
+ } from "$ai/types";
27
+ import { AssistantMessageEventStream } from "$ai/utils/event-stream";
28
+ import { parseStreamingJson } from "$ai/utils/json-parse";
29
+ import { formatErrorMessageWithRetryAfter } from "$ai/utils/retry-after";
30
30
  import type { McpToolDefinition } from "./cursor/gen/agent_pb";
31
31
  import {
32
32
  AgentClientMessageSchema,
@@ -6,8 +6,8 @@ import type {
6
6
  UsageProvider,
7
7
  UsageReport,
8
8
  UsageWindow,
9
- } from "../usage";
10
- import { refreshGoogleCloudToken } from "../utils/oauth/google-gemini-cli";
9
+ } from "$ai/usage";
10
+ import { refreshGoogleCloudToken } from "$ai/utils/oauth/google-gemini-cli";
11
11
 
12
12
  const DEFAULT_ENDPOINT = "https://cloudcode-pa.googleapis.com";
13
13
  const CACHE_TTL_MS = 60_000;
@@ -7,7 +7,7 @@
7
7
  import { createHash } from "node:crypto";
8
8
  import type { Content, ThinkingConfig } from "@google/genai";
9
9
  import { abortableSleep } from "@oh-my-pi/pi-utils";
10
- import { calculateCost } from "../models";
10
+ import { calculateCost } from "$ai/models";
11
11
  import type {
12
12
  Api,
13
13
  AssistantMessage,
@@ -18,9 +18,9 @@ import type {
18
18
  TextContent,
19
19
  ThinkingContent,
20
20
  ToolCall,
21
- } from "../types";
22
- import { AssistantMessageEventStream } from "../utils/event-stream";
23
- import { sanitizeSurrogates } from "../utils/sanitize-unicode";
21
+ } from "$ai/types";
22
+ import { AssistantMessageEventStream } from "$ai/utils/event-stream";
23
+ import { sanitizeSurrogates } from "$ai/utils/sanitize-unicode";
24
24
  import {
25
25
  convertMessages,
26
26
  convertTools,
@@ -3,8 +3,8 @@
3
3
  */
4
4
 
5
5
  import { type Content, FinishReason, FunctionCallingConfigMode, type Part, type Schema } from "@google/genai";
6
- import type { Context, ImageContent, Model, StopReason, TextContent, Tool } from "../types";
7
- import { sanitizeSurrogates } from "../utils/sanitize-unicode";
6
+ import type { Context, ImageContent, Model, StopReason, TextContent, Tool } from "$ai/types";
7
+ import { sanitizeSurrogates } from "$ai/utils/sanitize-unicode";
8
8
  import { transformMessages } from "./transform-messages";
9
9
 
10
10
  type GoogleApiType = "google-generative-ai" | "google-gemini-cli" | "google-vertex";
@@ -5,7 +5,7 @@ import {
5
5
  type ThinkingConfig,
6
6
  ThinkingLevel,
7
7
  } from "@google/genai";
8
- import { calculateCost } from "../models";
8
+ import { calculateCost } from "$ai/models";
9
9
  import type {
10
10
  Api,
11
11
  AssistantMessage,
@@ -16,10 +16,10 @@ import type {
16
16
  TextContent,
17
17
  ThinkingContent,
18
18
  ToolCall,
19
- } from "../types";
20
- import { AssistantMessageEventStream } from "../utils/event-stream";
21
- import { formatErrorMessageWithRetryAfter } from "../utils/retry-after";
22
- import { sanitizeSurrogates } from "../utils/sanitize-unicode";
19
+ } from "$ai/types";
20
+ import { AssistantMessageEventStream } from "$ai/utils/event-stream";
21
+ import { formatErrorMessageWithRetryAfter } from "$ai/utils/retry-after";
22
+ import { sanitizeSurrogates } from "$ai/utils/sanitize-unicode";
23
23
  import type { GoogleThinkingLevel } from "./google-gemini-cli";
24
24
  import {
25
25
  convertMessages,
@@ -4,8 +4,8 @@ import {
4
4
  GoogleGenAI,
5
5
  type ThinkingConfig,
6
6
  } from "@google/genai";
7
- import { calculateCost } from "../models";
8
- import { getEnvApiKey } from "../stream";
7
+ import { calculateCost } from "$ai/models";
8
+ import { getEnvApiKey } from "$ai/stream";
9
9
  import type {
10
10
  Api,
11
11
  AssistantMessage,
@@ -16,10 +16,10 @@ import type {
16
16
  TextContent,
17
17
  ThinkingContent,
18
18
  ToolCall,
19
- } from "../types";
20
- import { AssistantMessageEventStream } from "../utils/event-stream";
21
- import { formatErrorMessageWithRetryAfter } from "../utils/retry-after";
22
- import { sanitizeSurrogates } from "../utils/sanitize-unicode";
19
+ } from "$ai/types";
20
+ import { AssistantMessageEventStream } from "$ai/utils/event-stream";
21
+ import { formatErrorMessageWithRetryAfter } from "$ai/utils/retry-after";
22
+ import { sanitizeSurrogates } from "$ai/utils/sanitize-unicode";
23
23
  import type { GoogleThinkingLevel } from "./google-gemini-cli";
24
24
  import {
25
25
  convertMessages,
@@ -9,9 +9,8 @@ import type {
9
9
  ResponseOutputMessage,
10
10
  ResponseReasoningItem,
11
11
  } from "openai/resources/responses/responses";
12
- import packageJson from "../../package.json" with { type: "json" };
13
- import { calculateCost } from "../models";
14
- import { getEnvApiKey } from "../stream";
12
+ import { calculateCost } from "$ai/models";
13
+ import { getEnvApiKey } from "$ai/stream";
15
14
  import type {
16
15
  Api,
17
16
  AssistantMessage,
@@ -24,11 +23,12 @@ import type {
24
23
  ThinkingContent,
25
24
  Tool,
26
25
  ToolCall,
27
- } from "../types";
28
- import { AssistantMessageEventStream } from "../utils/event-stream";
29
- import { parseStreamingJson } from "../utils/json-parse";
30
- import { formatErrorMessageWithRetryAfter } from "../utils/retry-after";
31
- import { sanitizeSurrogates } from "../utils/sanitize-unicode";
26
+ } from "$ai/types";
27
+ import { AssistantMessageEventStream } from "$ai/utils/event-stream";
28
+ import { parseStreamingJson } from "$ai/utils/json-parse";
29
+ import { formatErrorMessageWithRetryAfter } from "$ai/utils/retry-after";
30
+ import { sanitizeSurrogates } from "$ai/utils/sanitize-unicode";
31
+ import packageJson from "../../package.json" with { type: "json" };
32
32
  import {
33
33
  CODEX_BASE_URL,
34
34
  JWT_CLAIM_PATH,
@@ -8,8 +8,8 @@ import type {
8
8
  ChatCompletionMessageParam,
9
9
  ChatCompletionToolMessageParam,
10
10
  } from "openai/resources/chat/completions";
11
- import { calculateCost } from "../models";
12
- import { getEnvApiKey } from "../stream";
11
+ import { calculateCost } from "$ai/models";
12
+ import { getEnvApiKey } from "$ai/stream";
13
13
  import type {
14
14
  AssistantMessage,
15
15
  Context,
@@ -23,11 +23,12 @@ import type {
23
23
  ThinkingContent,
24
24
  Tool,
25
25
  ToolCall,
26
- } from "../types";
27
- import { AssistantMessageEventStream } from "../utils/event-stream";
28
- import { parseStreamingJson } from "../utils/json-parse";
29
- import { formatErrorMessageWithRetryAfter } from "../utils/retry-after";
30
- import { sanitizeSurrogates } from "../utils/sanitize-unicode";
26
+ ToolResultMessage,
27
+ } from "$ai/types";
28
+ import { AssistantMessageEventStream } from "$ai/utils/event-stream";
29
+ import { parseStreamingJson } from "$ai/utils/json-parse";
30
+ import { formatErrorMessageWithRetryAfter } from "$ai/utils/retry-after";
31
+ import { sanitizeSurrogates } from "$ai/utils/sanitize-unicode";
31
32
  import { transformMessages } from "./transform-messages";
32
33
 
33
34
  /**
@@ -464,7 +465,7 @@ function maybeAddOpenRouterAnthropicCacheControl(
464
465
  }
465
466
  }
466
467
 
467
- function convertMessages(
468
+ export function convertMessages(
468
469
  model: Model<"openai-completions">,
469
470
  context: Context,
470
471
  compat: Required<OpenAICompat>,
@@ -481,7 +482,8 @@ function convertMessages(
481
482
 
482
483
  let lastRole: string | null = null;
483
484
 
484
- for (const msg of transformedMessages) {
485
+ for (let i = 0; i < transformedMessages.length; i++) {
486
+ const msg = transformedMessages[i];
485
487
  // Some providers (e.g. Mistral/Devstral) don't allow user messages directly after tool results
486
488
  // Insert a synthetic assistant message to bridge the gap
487
489
  if (compat.requiresAssistantAfterToolResult && lastRole === "toolResult" && msg.role === "user") {
@@ -605,55 +607,73 @@ function convertMessages(
605
607
  }
606
608
  params.push(assistantMsg);
607
609
  } else if (msg.role === "toolResult") {
608
- // Extract text and image content
609
- const textResult = msg.content
610
- .filter((c) => c.type === "text")
611
- .map((c) => (c as any).text)
612
- .join("\n");
613
- const hasImages = msg.content.some((c) => c.type === "image");
614
-
615
- // Always send tool result with text (or placeholder if only images)
616
- const hasText = textResult.length > 0;
617
- // Some providers (e.g. Mistral) require the 'name' field in tool results
618
- const toolResultMsg: ChatCompletionToolMessageParam = {
619
- role: "tool",
620
- content: sanitizeSurrogates(hasText ? textResult : "(see attached image)"),
621
- tool_call_id: normalizeMistralToolId(msg.toolCallId, compat.requiresMistralToolIds),
622
- };
623
- if (compat.requiresToolResultName && msg.toolName) {
624
- (toolResultMsg as any).name = msg.toolName;
610
+ // Batch consecutive tool results and collect all images
611
+ const imageBlocks: Array<{ type: "image_url"; image_url: { url: string } }> = [];
612
+ let j = i;
613
+
614
+ for (; j < transformedMessages.length && transformedMessages[j].role === "toolResult"; j++) {
615
+ const toolMsg = transformedMessages[j] as ToolResultMessage;
616
+
617
+ // Extract text and image content
618
+ const textResult = toolMsg.content
619
+ .filter((c) => c.type === "text")
620
+ .map((c) => (c as any).text)
621
+ .join("\n");
622
+ const hasImages = toolMsg.content.some((c) => c.type === "image");
623
+
624
+ // Always send tool result with text (or placeholder if only images)
625
+ const hasText = textResult.length > 0;
626
+ // Some providers (e.g. Mistral) require the 'name' field in tool results
627
+ const toolResultMsg: ChatCompletionToolMessageParam = {
628
+ role: "tool",
629
+ content: sanitizeSurrogates(hasText ? textResult : "(see attached image)"),
630
+ tool_call_id: normalizeMistralToolId(toolMsg.toolCallId, compat.requiresMistralToolIds),
631
+ };
632
+ if (compat.requiresToolResultName && toolMsg.toolName) {
633
+ (toolResultMsg as any).name = toolMsg.toolName;
634
+ }
635
+ params.push(toolResultMsg);
636
+
637
+ if (hasImages && model.input.includes("image")) {
638
+ for (const block of toolMsg.content) {
639
+ if (block.type === "image") {
640
+ imageBlocks.push({
641
+ type: "image_url",
642
+ image_url: {
643
+ url: `data:${(block as any).mimeType};base64,${(block as any).data}`,
644
+ },
645
+ });
646
+ }
647
+ }
648
+ }
625
649
  }
626
- params.push(toolResultMsg);
627
-
628
- // If there are images and model supports them, send a follow-up user message with images
629
- if (hasImages && model.input.includes("image")) {
630
- const contentBlocks: Array<
631
- { type: "text"; text: string } | { type: "image_url"; image_url: { url: string } }
632
- > = [];
633
-
634
- // Add text prefix
635
- contentBlocks.push({
636
- type: "text",
637
- text: "Attached image(s) from tool result:",
638
- });
639
650
 
640
- // Add images
641
- for (const block of msg.content) {
642
- if (block.type === "image") {
643
- contentBlocks.push({
644
- type: "image_url",
645
- image_url: {
646
- url: `data:${(block as any).mimeType};base64,${(block as any).data}`,
647
- },
648
- });
649
- }
651
+ i = j - 1;
652
+
653
+ // After all consecutive tool results, add a single user message with all images
654
+ if (imageBlocks.length > 0) {
655
+ if (compat.requiresAssistantAfterToolResult) {
656
+ params.push({
657
+ role: "assistant",
658
+ content: "I have processed the tool results.",
659
+ });
650
660
  }
651
661
 
652
662
  params.push({
653
663
  role: "user",
654
- content: contentBlocks,
664
+ content: [
665
+ {
666
+ type: "text",
667
+ text: "Attached image(s) from tool result:",
668
+ },
669
+ ...imageBlocks,
670
+ ],
655
671
  });
672
+ lastRole = "user";
673
+ } else {
674
+ lastRole = "toolResult";
656
675
  }
676
+ continue;
657
677
  }
658
678
 
659
679
  lastRole = msg.role;
@@ -10,8 +10,8 @@ import type {
10
10
  ResponseOutputMessage,
11
11
  ResponseReasoningItem,
12
12
  } from "openai/resources/responses/responses";
13
- import { calculateCost } from "../models";
14
- import { getEnvApiKey } from "../stream";
13
+ import { calculateCost } from "$ai/models";
14
+ import { getEnvApiKey } from "$ai/stream";
15
15
  import type {
16
16
  Api,
17
17
  AssistantMessage,
@@ -24,11 +24,11 @@ import type {
24
24
  ThinkingContent,
25
25
  Tool,
26
26
  ToolCall,
27
- } from "../types";
28
- import { AssistantMessageEventStream } from "../utils/event-stream";
29
- import { parseStreamingJson } from "../utils/json-parse";
30
- import { formatErrorMessageWithRetryAfter } from "../utils/retry-after";
31
- import { sanitizeSurrogates } from "../utils/sanitize-unicode";
27
+ } from "$ai/types";
28
+ import { AssistantMessageEventStream } from "$ai/utils/event-stream";
29
+ import { parseStreamingJson } from "$ai/utils/json-parse";
30
+ import { formatErrorMessageWithRetryAfter } from "$ai/utils/retry-after";
31
+ import { sanitizeSurrogates } from "$ai/utils/sanitize-unicode";
32
32
  import { transformMessages } from "./transform-messages";
33
33
 
34
34
  /** Fast deterministic hash to shorten long strings */
@@ -507,6 +507,15 @@ function convertMessages(
507
507
  }
508
508
  } else if (msg.role === "assistant") {
509
509
  const output: ResponseInput = [];
510
+ const assistantMsg = msg as AssistantMessage;
511
+
512
+ // Check if this message is from a different model (same provider, different model ID).
513
+ // For such messages, tool call IDs with fc_ prefix need to be stripped to avoid
514
+ // OpenAI's reasoning/function_call pairing validation errors.
515
+ const isDifferentModel =
516
+ assistantMsg.model !== model.id &&
517
+ assistantMsg.provider === model.provider &&
518
+ assistantMsg.api === model.api;
510
519
 
511
520
  for (const block of msg.content) {
512
521
  // Do not submit thinking blocks if the completion had an error (i.e. abort)
@@ -535,11 +544,19 @@ function convertMessages(
535
544
  } else if (block.type === "toolCall" && msg.stopReason !== "error") {
536
545
  const toolCall = block as ToolCall;
537
546
  const normalized = normalizeResponsesToolCallId(toolCall.id);
547
+ const callId = normalized.callId;
548
+ // For different-model messages, set id to undefined to avoid pairing validation.
549
+ // OpenAI tracks which fc_xxx IDs were paired with rs_xxx reasoning items.
550
+ // By omitting the id, we avoid triggering that validation (like cross-provider does).
551
+ let itemId: string | undefined = normalized.itemId;
552
+ if (isDifferentModel && itemId?.startsWith("fc_")) {
553
+ itemId = undefined;
554
+ }
538
555
  knownCallIds.add(normalized.callId);
539
556
  output.push({
540
557
  type: "function_call",
541
- id: normalized.itemId,
542
- call_id: normalized.callId,
558
+ id: itemId,
559
+ call_id: callId,
543
560
  name: toolCall.name,
544
561
  arguments: JSON.stringify(toolCall.arguments),
545
562
  });
@@ -1,4 +1,4 @@
1
- import type { Api, AssistantMessage, Message, Model, ToolCall, ToolResultMessage } from "../types";
1
+ import type { Api, AssistantMessage, Message, Model, ToolCall, ToolResultMessage } from "$ai/types";
2
2
 
3
3
  /**
4
4
  * Normalize tool call ID for cross-provider compatibility.
@@ -7,7 +7,7 @@ import type {
7
7
  UsageReport,
8
8
  UsageStatus,
9
9
  UsageWindow,
10
- } from "../usage";
10
+ } from "$ai/usage";
11
11
 
12
12
  const DEFAULT_ENDPOINT = "https://api.anthropic.com/api/oauth";
13
13
  const DEFAULT_CACHE_TTL_MS = 60_000;
@@ -14,7 +14,7 @@ import type {
14
14
  UsageReport,
15
15
  UsageStatus,
16
16
  UsageWindow,
17
- } from "../usage";
17
+ } from "$ai/usage";
18
18
 
19
19
  const COPILOT_HEADERS = {
20
20
  "User-Agent": "GitHubCopilotChat/0.35.0",
@@ -7,8 +7,8 @@ import type {
7
7
  UsageReport,
8
8
  UsageStatus,
9
9
  UsageWindow,
10
- } from "../usage";
11
- import { refreshAntigravityToken } from "../utils/oauth/google-antigravity";
10
+ } from "$ai/usage";
11
+ import { refreshAntigravityToken } from "$ai/utils/oauth/google-antigravity";
12
12
 
13
13
  interface AntigravityQuotaInfo {
14
14
  remainingFraction?: number;
@@ -1,5 +1,5 @@
1
1
  import { Buffer } from "node:buffer";
2
- import { CODEX_BASE_URL } from "../providers/openai-codex/constants";
2
+ import { CODEX_BASE_URL } from "$ai/providers/openai-codex/constants";
3
3
  import type {
4
4
  UsageAmount,
5
5
  UsageCache,
@@ -9,7 +9,7 @@ import type {
9
9
  UsageProvider,
10
10
  UsageReport,
11
11
  UsageWindow,
12
- } from "../usage";
12
+ } from "$ai/usage";
13
13
 
14
14
  const CODEX_USAGE_PATH = "wham/usage";
15
15
  const DEFAULT_CACHE_TTL_MS = 60_000;
package/src/usage/zai.ts CHANGED
@@ -7,7 +7,7 @@ import type {
7
7
  UsageReport,
8
8
  UsageStatus,
9
9
  UsageWindow,
10
- } from "../usage";
10
+ } from "$ai/usage";
11
11
 
12
12
  const DEFAULT_ENDPOINT = "https://api.z.ai";
13
13
  const QUOTA_PATH = "/api/monitor/usage/quota/limit";
@@ -1,4 +1,4 @@
1
- import type { AssistantMessage, AssistantMessageEvent } from "../types";
1
+ import type { AssistantMessage, AssistantMessageEvent } from "$ai/types";
2
2
 
3
3
  // Generic event stream class for async iteration
4
4
  export class EventStream<T, R = T> implements AsyncIterable<T> {
@@ -3,7 +3,7 @@
3
3
  */
4
4
 
5
5
  import { abortableSleep } from "@oh-my-pi/pi-utils";
6
- import { getModels } from "../../models";
6
+ import { getModels } from "$ai/models";
7
7
  import type { OAuthCredentials } from "./types";
8
8
 
9
9
  const decode = (s: string) => atob(s);
@@ -1,4 +1,4 @@
1
- import type { AssistantMessage } from "../types";
1
+ import type { AssistantMessage } from "$ai/types";
2
2
 
3
3
  /**
4
4
  * Regex patterns to detect context overflow errors from different providers.
@@ -5,7 +5,7 @@ import addFormatsModule from "ajv-formats";
5
5
  const Ajv = (AjvModule as any).default || AjvModule;
6
6
  const addFormats = (addFormatsModule as any).default || addFormatsModule;
7
7
 
8
- import type { Tool, ToolCall } from "../types";
8
+ import type { Tool, ToolCall } from "$ai/types";
9
9
 
10
10
  // ============================================================================
11
11
  // Type Coercion Utilities
package/tsconfig.json ADDED
@@ -0,0 +1,25 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2024",
4
+ "module": "ESNext",
5
+ "lib": ["ES2024"],
6
+ "strict": true,
7
+ "esModuleInterop": true,
8
+ "skipLibCheck": true,
9
+ "forceConsistentCasingInFileNames": true,
10
+ "moduleResolution": "Bundler",
11
+ "resolveJsonModule": true,
12
+ "allowImportingTsExtensions": true,
13
+ "experimentalDecorators": true,
14
+ "emitDecoratorMetadata": true,
15
+ "useDefineForClassFields": false,
16
+ "types": ["bun", "node"],
17
+ "noEmit": true,
18
+ "baseUrl": ".",
19
+ "paths": {
20
+ "$ai/*": ["./src/*"]
21
+ }
22
+ },
23
+ "include": ["src/**/*.ts"],
24
+ "exclude": ["node_modules", "dist", "**/*.test.ts", "test/**"]
25
+ }