@oh-my-pi/pi-ai 8.1.0 → 8.2.0

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.
@@ -1,5 +1,5 @@
1
1
  import { Buffer } from "node:buffer";
2
- import { CODEX_BASE_URL } from "@oh-my-pi/pi-ai/providers/openai-codex/constants";
2
+ import { CODEX_BASE_URL } from "../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 "@oh-my-pi/pi-ai/usage";
12
+ } from "../usage";
13
13
 
14
14
  const CODEX_USAGE_PATH = "wham/usage";
15
15
  const DEFAULT_CACHE_TTL_MS = 60_000;
@@ -264,9 +264,9 @@ function buildUsageLimit(args: {
264
264
  function resolveCacheExpiry(args: { report: UsageReport | null; nowMs: number }): number {
265
265
  const { report, nowMs } = args;
266
266
  if (!report) return nowMs + DEFAULT_CACHE_TTL_MS;
267
- const exhausted = report.limits.some((limit) => limit.status === "exhausted");
267
+ const exhausted = report.limits.some(limit => limit.status === "exhausted");
268
268
  const resetCandidates = report.limits
269
- .map((limit) => limit.window?.resetsAt)
269
+ .map(limit => limit.window?.resetsAt)
270
270
  .filter((value): value is number => typeof value === "number" && Number.isFinite(value));
271
271
  const earliestReset = resetCandidates.length > 0 ? Math.min(...resetCandidates) : undefined;
272
272
  if (exhausted && earliestReset) return earliestReset;
package/src/usage/zai.ts CHANGED
@@ -7,7 +7,7 @@ import type {
7
7
  UsageReport,
8
8
  UsageStatus,
9
9
  UsageWindow,
10
- } from "@oh-my-pi/pi-ai/usage";
10
+ } from "../usage";
11
11
 
12
12
  const DEFAULT_ENDPOINT = "https://api.z.ai";
13
13
  const QUOTA_PATH = "/api/monitor/usage/quota/limit";
@@ -133,7 +133,7 @@ function buildCacheKey(params: UsageFetchParams): string {
133
133
 
134
134
  function resolveCacheExpiry(now: number, limits: UsageLimit[]): number {
135
135
  const earliestReset = limits
136
- .map((limit) => limit.window?.resetsAt)
136
+ .map(limit => limit.window?.resetsAt)
137
137
  .filter((value): value is number => typeof value === "number" && Number.isFinite(value))
138
138
  .reduce((min, value) => (min === undefined ? value : Math.min(min, value)), undefined as number | undefined);
139
139
  if (!earliestReset) return now + DEFAULT_CACHE_TTL_MS;
@@ -288,5 +288,5 @@ async function fetchZaiUsage(params: UsageFetchParams, ctx: UsageFetchContext):
288
288
  export const zaiUsageProvider: UsageProvider = {
289
289
  id: "zai",
290
290
  fetchUsage: fetchZaiUsage,
291
- supports: (params) => params.provider === "zai" && params.credential.type === "api_key",
291
+ supports: params => params.provider === "zai" && params.credential.type === "api_key",
292
292
  };
package/src/usage.ts CHANGED
@@ -4,7 +4,6 @@
4
4
  * Provides a normalized schema to represent multiple limit windows, model tiers,
5
5
  * and shared quotas across providers.
6
6
  */
7
-
8
7
  import type { Provider } from "./types";
9
8
 
10
9
  export type UsageUnit = "percent" | "tokens" | "requests" | "usd" | "minutes" | "bytes" | "unknown";
@@ -1,4 +1,4 @@
1
- import type { AssistantMessage, AssistantMessageEvent } from "@oh-my-pi/pi-ai/types";
1
+ import type { AssistantMessage, AssistantMessageEvent } from "../types";
2
2
 
3
3
  // Generic event stream class for async iteration
4
4
  export class EventStream<T, R = T> implements AsyncIterable<T> {
@@ -53,7 +53,7 @@ export class EventStream<T, R = T> implements AsyncIterable<T> {
53
53
  } else if (this.done) {
54
54
  return;
55
55
  } else {
56
- const result = await new Promise<IteratorResult<T>>((resolve) => this.waiting.push(resolve));
56
+ const result = await new Promise<IteratorResult<T>>(resolve => this.waiting.push(resolve));
57
57
  if (result.done) return;
58
58
  yield result.value;
59
59
  }
@@ -68,8 +68,8 @@ export class EventStream<T, R = T> implements AsyncIterable<T> {
68
68
  export class AssistantMessageEventStream extends EventStream<AssistantMessageEvent, AssistantMessage> {
69
69
  constructor() {
70
70
  super(
71
- (event) => event.type === "done" || event.type === "error",
72
- (event) => {
71
+ event => event.type === "done" || event.type === "error",
72
+ event => {
73
73
  if (event.type === "done") {
74
74
  return event.message;
75
75
  } else if (event.type === "error") {
@@ -1,7 +1,6 @@
1
1
  /**
2
2
  * Anthropic OAuth flow (Claude Pro/Max)
3
3
  */
4
-
5
4
  import { OAuthCallbackFlow } from "./callback-server";
6
5
  import { generatePKCE } from "./pkce";
7
6
  import type { OAuthController, OAuthCredentials } from "./types";
@@ -10,7 +10,6 @@
10
10
  * - generateAuthUrl(): Build provider-specific authorization URL
11
11
  * - exchangeToken(): Exchange authorization code for tokens
12
12
  */
13
-
14
13
  import templateHtml from "./oauth.html" with { type: "text" };
15
14
  import type { OAuthController, OAuthCredentials } from "./types";
16
15
 
@@ -63,7 +62,7 @@ export abstract class OAuthCallbackFlow {
63
62
  const bytes = new Uint8Array(16);
64
63
  crypto.getRandomValues(bytes);
65
64
  return Array.from(bytes)
66
- .map((value) => value.toString(16).padStart(2, "0"))
65
+ .map(value => value.toString(16).padStart(2, "0"))
67
66
  .join("");
68
67
  }
69
68
 
@@ -125,7 +124,7 @@ export abstract class OAuthCallbackFlow {
125
124
  hostname: DEFAULT_HOSTNAME,
126
125
  port,
127
126
  reusePort: false,
128
- fetch: (req) => this.handleCallback(req, expectedState),
127
+ fetch: req => this.handleCallback(req, expectedState),
129
128
  });
130
129
  }
131
130
 
@@ -1,9 +1,8 @@
1
1
  /**
2
2
  * GitHub Copilot OAuth flow
3
3
  */
4
-
5
- import { getModels } from "@oh-my-pi/pi-ai/models";
6
4
  import { abortableSleep } from "@oh-my-pi/pi-utils";
5
+ import { getModels } from "../../models";
7
6
  import type { OAuthCredentials } from "./types";
8
7
 
9
8
  const decode = (s: string) => atob(s);
@@ -279,7 +278,7 @@ async function enableAllGitHubCopilotModels(
279
278
  ): Promise<void> {
280
279
  const models = getModels("github-copilot");
281
280
  await Promise.all(
282
- models.map(async (model) => {
281
+ models.map(async model => {
283
282
  const success = await enableGitHubCopilotModel(token, model.id, enterpriseDomain);
284
283
  onProgress?.(model.id, success);
285
284
  }),
@@ -2,7 +2,6 @@
2
2
  * Antigravity OAuth flow (Gemini 3, Claude, GPT-OSS via Google Cloud)
3
3
  * Uses different OAuth credentials than google-gemini-cli for access to additional models.
4
4
  */
5
-
6
5
  import { OAuthCallbackFlow } from "./callback-server";
7
6
  import { generatePKCE } from "./pkce";
8
7
  import type { OAuthController, OAuthCredentials } from "./types";
@@ -2,7 +2,6 @@
2
2
  * Gemini CLI OAuth flow (Google Cloud Code Assist)
3
3
  * Standard Gemini models only (gemini-2.0-flash, gemini-2.5-*)
4
4
  */
5
-
6
5
  import { OAuthCallbackFlow } from "./callback-server";
7
6
  import { generatePKCE } from "./pkce";
8
7
  import type { OAuthController, OAuthCredentials } from "./types";
@@ -49,7 +48,7 @@ interface GoogleRpcErrorResponse {
49
48
 
50
49
  function getDefaultTier(allowedTiers?: Array<{ id?: string; isDefault?: boolean }>): { id?: string } {
51
50
  if (!allowedTiers || allowedTiers.length === 0) return { id: TIER_LEGACY };
52
- const defaultTier = allowedTiers.find((t) => t.isDefault);
51
+ const defaultTier = allowedTiers.find(t => t.isDefault);
53
52
  return defaultTier ?? { id: TIER_LEGACY };
54
53
  }
55
54
 
@@ -58,7 +57,7 @@ function isVpcScAffectedUser(payload: unknown): boolean {
58
57
  if (!("error" in payload)) return false;
59
58
  const error = (payload as GoogleRpcErrorResponse).error;
60
59
  if (!error?.details || !Array.isArray(error.details)) return false;
61
- return error.details.some((detail) => detail.reason === "SECURITY_POLICY_VIOLATED");
60
+ return error.details.some(detail => detail.reason === "SECURITY_POLICY_VIOLATED");
62
61
  }
63
62
 
64
63
  async function pollOperation(
@@ -1,3 +1,14 @@
1
+ // ============================================================================
2
+ // High-level API
3
+ // ============================================================================
4
+ import { refreshAnthropicToken } from "./anthropic";
5
+ import { refreshCursorToken } from "./cursor";
6
+ import { refreshGitHubCopilotToken } from "./github-copilot";
7
+ import { refreshAntigravityToken } from "./google-antigravity";
8
+ import { refreshGoogleCloudToken } from "./google-gemini-cli";
9
+ import { refreshOpenAICodexToken } from "./openai-codex";
10
+ import type { OAuthCredentials, OAuthProvider, OAuthProviderInfo } from "./types";
11
+
1
12
  /**
2
13
  * OAuth credential management for AI providers.
3
14
  *
@@ -36,18 +47,6 @@ export { loginOpenAICodex, refreshOpenAICodexToken } from "./openai-codex";
36
47
 
37
48
  export * from "./types";
38
49
 
39
- // ============================================================================
40
- // High-level API
41
- // ============================================================================
42
-
43
- import { refreshAnthropicToken } from "./anthropic";
44
- import { refreshCursorToken } from "./cursor";
45
- import { refreshGitHubCopilotToken } from "./github-copilot";
46
- import { refreshAntigravityToken } from "./google-antigravity";
47
- import { refreshGoogleCloudToken } from "./google-gemini-cli";
48
- import { refreshOpenAICodexToken } from "./openai-codex";
49
- import type { OAuthCredentials, OAuthProvider, OAuthProviderInfo } from "./types";
50
-
51
50
  /**
52
51
  * Refresh token for any OAuth provider.
53
52
  * Saves the new credentials and returns the new access token.
@@ -1,7 +1,6 @@
1
1
  /**
2
2
  * OpenAI Codex (ChatGPT OAuth) flow
3
3
  */
4
-
5
4
  import { OAuthCallbackFlow } from "./callback-server";
6
5
  import { generatePKCE } from "./pkce";
7
6
  import type { OAuthController, OAuthCredentials } from "./types";
@@ -1,4 +1,4 @@
1
- import type { AssistantMessage } from "@oh-my-pi/pi-ai/types";
1
+ import type { AssistantMessage } from "../types";
2
2
 
3
3
  /**
4
4
  * Regex patterns to detect context overflow errors from different providers.
@@ -85,7 +85,7 @@ export function isContextOverflow(message: AssistantMessage, contextWindow?: num
85
85
  // Case 1: Check error message patterns
86
86
  if (message.stopReason === "error" && message.errorMessage) {
87
87
  // Check known patterns
88
- if (OVERFLOW_PATTERNS.some((p) => p.test(message.errorMessage!))) {
88
+ if (OVERFLOW_PATTERNS.some(p => p.test(message.errorMessage!))) {
89
89
  return true;
90
90
  }
91
91
 
@@ -1,12 +1,11 @@
1
1
  import AjvModule from "ajv";
2
2
  import addFormatsModule from "ajv-formats";
3
+ import type { Tool, ToolCall } from "../types";
3
4
 
4
5
  // Handle both default and named exports (ESM/CJS interop)
5
6
  const Ajv = (AjvModule as any).default || AjvModule;
6
7
  const addFormats = (addFormatsModule as any).default || addFormatsModule;
7
8
 
8
- import type { Tool, ToolCall } from "@oh-my-pi/pi-ai/types";
9
-
10
9
  // ============================================================================
11
10
  // Type Coercion Utilities
12
11
  // ============================================================================
@@ -50,7 +49,7 @@ function normalizeExpectedTypes(typeParam: unknown): string[] {
50
49
  * Used to verify that a parsed JSON value is actually what the schema wants.
51
50
  */
52
51
  function matchesExpectedType(value: unknown, expectedTypes: string[]): boolean {
53
- return expectedTypes.some((type) => {
52
+ return expectedTypes.some(type => {
54
53
  switch (type) {
55
54
  case "string":
56
55
  return typeof value === "string";
@@ -157,7 +156,7 @@ function decodeJsonPointer(pointer: string): string[] {
157
156
  return pointer
158
157
  .split("/")
159
158
  .slice(1) // Remove leading empty segment from initial "/"
160
- .map((segment) => segment.replace(/~1/g, "/").replace(/~0/g, "~"));
159
+ .map(segment => segment.replace(/~1/g, "/").replace(/~0/g, "~"));
161
160
  }
162
161
 
163
162
  /**
@@ -310,7 +309,7 @@ if (!isBrowserExtension) {
310
309
  * @throws Error if tool is not found or validation fails
311
310
  */
312
311
  export function validateToolCall(tools: Tool[], toolCall: ToolCall): any {
313
- const tool = tools.find((t) => t.name === toolCall.name);
312
+ const tool = tools.find(t => t.name === toolCall.name);
314
313
  if (!tool) {
315
314
  throw new Error(`Tool "${toolCall.name}" not found`);
316
315
  }