@oh-my-pi/pi-ai 18.2.7 → 18.2.9

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 (133) hide show
  1. package/CHANGELOG.md +49 -18
  2. package/dist/types/auth-gateway/dispatch.d.ts +80 -0
  3. package/dist/types/auth-gateway/http.d.ts +5 -6
  4. package/dist/types/auth-gateway/index.d.ts +1 -0
  5. package/dist/types/auth-gateway/routes/embeddings.d.ts +3 -0
  6. package/dist/types/auth-gateway/routes/images.d.ts +3 -0
  7. package/dist/types/auth-gateway/routes/rerank.d.ts +3 -0
  8. package/dist/types/auth-gateway/routes/speech.d.ts +2 -0
  9. package/dist/types/auth-gateway/routes/systemone.d.ts +2 -0
  10. package/dist/types/auth-gateway/routes/transcriptions.d.ts +3 -0
  11. package/dist/types/auth-gateway/routes/video.d.ts +7 -0
  12. package/dist/types/auth-gateway/server.d.ts +10 -16
  13. package/dist/types/auth-gateway/types.d.ts +5 -0
  14. package/dist/types/auth-storage.d.ts +35 -32
  15. package/dist/types/embeddings/index.d.ts +7 -0
  16. package/dist/types/embeddings/openai-embeddings.d.ts +15 -0
  17. package/dist/types/embeddings/types.d.ts +15 -0
  18. package/dist/types/images/google-antigravity.d.ts +9 -0
  19. package/dist/types/images/google-generative-ai.d.ts +3 -0
  20. package/dist/types/images/index.d.ts +14 -0
  21. package/dist/types/images/openai-hosted.d.ts +3 -0
  22. package/dist/types/images/openai-images.d.ts +5 -0
  23. package/dist/types/images/openrouter-images.d.ts +3 -0
  24. package/dist/types/images/shared.d.ts +34 -0
  25. package/dist/types/images/types.d.ts +31 -0
  26. package/dist/types/index.d.ts +8 -1
  27. package/dist/types/judgment/typesafe.d.ts +2 -0
  28. package/dist/types/providers/amazon-bedrock.d.ts +7 -0
  29. package/dist/types/providers/claude-code-fingerprint.d.ts +22 -3
  30. package/dist/types/providers/embeddings-server.d.ts +32 -0
  31. package/dist/types/providers/google-gemini-cli.d.ts +0 -2
  32. package/dist/types/providers/images-server.d.ts +22 -0
  33. package/dist/types/providers/openai-chat-server-schema.d.ts +2 -2
  34. package/dist/types/providers/rerank-server.d.ts +35 -0
  35. package/dist/types/providers/speech-server.d.ts +8 -0
  36. package/dist/types/providers/systemone-server.d.ts +26 -0
  37. package/dist/types/providers/transcriptions-server.d.ts +32 -0
  38. package/dist/types/providers/video-server.d.ts +39 -0
  39. package/dist/types/rerank/index.d.ts +7 -0
  40. package/dist/types/rerank/openrouter-rerank.d.ts +15 -0
  41. package/dist/types/rerank/types.d.ts +17 -0
  42. package/dist/types/speech/index.d.ts +13 -0
  43. package/dist/types/speech/openai-speech.d.ts +3 -0
  44. package/dist/types/speech/transport.d.ts +7 -0
  45. package/dist/types/speech/types.d.ts +24 -0
  46. package/dist/types/speech/xai-tts.d.ts +7 -0
  47. package/dist/types/transcription/index.d.ts +7 -0
  48. package/dist/types/transcription/openai-transcriptions.d.ts +15 -0
  49. package/dist/types/transcription/types.d.ts +41 -0
  50. package/dist/types/usage/claude-api.d.ts +22 -0
  51. package/dist/types/usage/claude-reset.d.ts +44 -0
  52. package/dist/types/usage.d.ts +111 -5
  53. package/dist/types/utils/schema/json-schema-validator.d.ts +5 -2
  54. package/dist/types/utils/tool-call-loop-guard.d.ts +1 -1
  55. package/dist/types/video/index.d.ts +11 -0
  56. package/dist/types/video/openrouter-video.d.ts +19 -0
  57. package/dist/types/video/types.d.ts +62 -0
  58. package/package.json +30 -6
  59. package/src/auth/sqlite-credential-store.ts +44 -1
  60. package/src/auth-broker/remote-store.ts +6 -6
  61. package/src/auth-broker/wire-schemas.ts +14 -0
  62. package/src/auth-gateway/dispatch.ts +273 -0
  63. package/src/auth-gateway/http.ts +6 -7
  64. package/src/auth-gateway/index.ts +1 -0
  65. package/src/auth-gateway/routes/embeddings.ts +98 -0
  66. package/src/auth-gateway/routes/images.ts +131 -0
  67. package/src/auth-gateway/routes/rerank.ts +87 -0
  68. package/src/auth-gateway/routes/speech.ts +101 -0
  69. package/src/auth-gateway/routes/systemone.ts +116 -0
  70. package/src/auth-gateway/routes/transcriptions.ts +98 -0
  71. package/src/auth-gateway/routes/video.ts +243 -0
  72. package/src/auth-gateway/server.ts +127 -260
  73. package/src/auth-gateway/types.ts +5 -0
  74. package/src/auth-storage.ts +263 -140
  75. package/src/embeddings/index.ts +17 -0
  76. package/src/embeddings/openai-embeddings.ts +141 -0
  77. package/src/embeddings/types.ts +14 -0
  78. package/src/error/flags.ts +10 -0
  79. package/src/error/rate-limit.ts +1 -1
  80. package/src/images/google-antigravity.ts +180 -0
  81. package/src/images/google-generative-ai.ts +92 -0
  82. package/src/images/index.ts +59 -0
  83. package/src/images/openai-hosted.ts +185 -0
  84. package/src/images/openai-images.ts +110 -0
  85. package/src/images/openrouter-images.ts +33 -0
  86. package/src/images/shared.ts +193 -0
  87. package/src/images/types.ts +36 -0
  88. package/src/index.ts +8 -1
  89. package/src/judgment/typesafe.ts +5 -0
  90. package/src/providers/amazon-bedrock.ts +55 -5
  91. package/src/providers/anthropic.ts +45 -11
  92. package/src/providers/aws-credentials.ts +124 -11
  93. package/src/providers/claude-code-fingerprint.ts +55 -3
  94. package/src/providers/embeddings-server.ts +151 -0
  95. package/src/providers/gitlab-duo.ts +20 -4
  96. package/src/providers/google-gemini-cli.ts +0 -8
  97. package/src/providers/google-shared.ts +1 -18
  98. package/src/providers/images-server.ts +159 -0
  99. package/src/providers/openai-chat-server-schema.ts +1 -1
  100. package/src/providers/openai-chat-server.ts +3 -1
  101. package/src/providers/openai-codex-responses.ts +27 -5
  102. package/src/providers/openai-completions.ts +122 -19
  103. package/src/providers/pi-native-server.ts +1 -0
  104. package/src/providers/rerank-server.ts +166 -0
  105. package/src/providers/speech-server.ts +53 -0
  106. package/src/providers/systemone-server.ts +73 -0
  107. package/src/providers/transcriptions-server.ts +243 -0
  108. package/src/providers/video-server.ts +286 -0
  109. package/src/registry/oauth/anthropic.ts +2 -3
  110. package/src/rerank/index.ts +13 -0
  111. package/src/rerank/openrouter-rerank.ts +136 -0
  112. package/src/rerank/types.ts +20 -0
  113. package/src/speech/index.ts +35 -0
  114. package/src/speech/openai-speech.ts +26 -0
  115. package/src/speech/transport.ts +66 -0
  116. package/src/speech/types.ts +37 -0
  117. package/src/speech/xai-tts.ts +41 -0
  118. package/src/stream.ts +13 -4
  119. package/src/transcription/index.ts +17 -0
  120. package/src/transcription/openai-transcriptions.ts +133 -0
  121. package/src/transcription/types.ts +46 -0
  122. package/src/usage/alibaba-token-plan.ts +7 -1
  123. package/src/usage/claude-api.ts +66 -0
  124. package/src/usage/claude-reset.ts +638 -0
  125. package/src/usage/claude.ts +37 -59
  126. package/src/usage/kimi.ts +32 -1
  127. package/src/usage.ts +52 -5
  128. package/src/utils/schema/json-schema-validator.ts +23 -10
  129. package/src/utils/tool-call-loop-guard.ts +2 -2
  130. package/src/utils/validation.ts +145 -50
  131. package/src/video/index.ts +34 -0
  132. package/src/video/openrouter-video.ts +210 -0
  133. package/src/video/types.ts +72 -0
@@ -62,11 +62,29 @@ export interface UsageLimit {
62
62
  * Per-credit detail for a saved/banked rate-limit reset.
63
63
  *
64
64
  * Populated when the provider's listing endpoint returns individual credit
65
- * metadata (e.g. OpenAI Codex `wham/rate-limit-reset-credits`). Callers that
65
+ * metadata (e.g. OpenAI Codex credits or Claude Cedar grants). Callers that
66
66
  * only need the count can ignore this; display layers use `expiresAt` to show
67
67
  * when banked resets expire ([#3339](https://github.com/can1357/oh-my-pi/issues/3339)).
68
68
  */
69
69
  export interface UsageResetCreditDetail {
70
+ /** Opaque provider credit/grant identifier. */
71
+ id?: string;
72
+ /** Human-facing name for the reset. */
73
+ title?: string;
74
+ /** Provider reset program/family. */
75
+ program?: string;
76
+ /** Resets still banked in this credit/grant. */
77
+ remainingCount?: number;
78
+ /** Whether the provider says this credit can be redeemed now. */
79
+ usable?: boolean;
80
+ /** Whether redemption requires an exhausted covered limit. */
81
+ requiresLimit?: boolean;
82
+ /** Normalized {@link UsageLimit.id}s this credit resets. */
83
+ clears?: string[];
84
+ /** Normalized limit ids currently preventing redemption. */
85
+ blocking?: string[];
86
+ /** Used fractions for covered limits, keyed by normalized limit id. */
87
+ usedFractions?: Record<string, number>;
70
88
  /** ISO timestamp when the credit was granted. */
71
89
  grantedAt?: string;
72
90
  /** ISO timestamp when the credit expires and can no longer be redeemed. */
@@ -74,17 +92,31 @@ export interface UsageResetCreditDetail {
74
92
  /** Backend status, e.g. `available`, `redeemed`. */
75
93
  status?: string;
76
94
  }
95
+ /** Reset credit carrying the provider id required by its consume endpoint. */
96
+ export interface UsageResetCredit extends UsageResetCreditDetail {
97
+ id: string;
98
+ }
77
99
  /**
78
100
  * Saved/banked rate-limit resets an account can redeem on demand.
79
101
  *
80
102
  * Surfaced by providers that let users defer a usage-window reset and spend it
81
- * later (OpenAI Codex "saved rate limit resets"). The redeem itself is a
82
- * separate, provider-specific action; this is the read-only count for display.
103
+ * later (OpenAI Codex and Claude Cedar resets). The redeem itself is a
104
+ * separate, provider-specific action; this is the read-only state for display.
83
105
  */
84
106
  export interface UsageResetCredits {
85
- /** Number of resets available to redeem right now. */
107
+ /** Number of banked resets, including grants that are not currently usable. */
86
108
  availableCount: number;
87
- /** Individual credit details (expiry dates, etc.) when the provider exposes them. */
109
+ /** Number of resets the provider says can be redeemed now. */
110
+ redeemableCount?: number;
111
+ /** Provider-selected credit/grant eligible for the next redemption. */
112
+ nextCreditId?: string;
113
+ /** Whether this account is eligible for the reset program. */
114
+ eligible?: boolean;
115
+ /** Provider reason the program or its credits are unavailable. */
116
+ reason?: string;
117
+ /** ISO timestamp until which redemption is cooling down. */
118
+ cooldownUntil?: string;
119
+ /** Individual credit details (expiry dates, coverage, etc.) when exposed. */
88
120
  credits?: UsageResetCreditDetail[];
89
121
  }
90
122
  /** Aggregated usage report for a provider. */
@@ -321,28 +353,74 @@ export declare const usageLimitSchema: import("@oh-my-pi/omptype").FluentType<{
321
353
  } | undefined;
322
354
  }>;
323
355
  export declare const usageResetCreditDetailSchema: import("@oh-my-pi/omptype").FluentType<{
356
+ blocking?: string[] | undefined;
357
+ clears?: string[] | undefined;
324
358
  expiresAt?: string | undefined;
325
359
  grantedAt?: string | undefined;
360
+ id?: string | undefined;
361
+ program?: string | undefined;
362
+ remainingCount?: number | undefined;
363
+ requiresLimit?: boolean | undefined;
326
364
  status?: string | undefined;
365
+ title?: string | undefined;
366
+ usable?: boolean | undefined;
367
+ usedFractions?: Record<string, number> | undefined;
327
368
  }, {
369
+ blocking?: string[] | undefined;
370
+ clears?: string[] | undefined;
328
371
  expiresAt?: string | undefined;
329
372
  grantedAt?: string | undefined;
373
+ id?: string | undefined;
374
+ program?: string | undefined;
375
+ remainingCount?: number | undefined;
376
+ requiresLimit?: boolean | undefined;
330
377
  status?: string | undefined;
378
+ title?: string | undefined;
379
+ usable?: boolean | undefined;
380
+ usedFractions?: Record<string, number> | undefined;
331
381
  }>;
332
382
  export declare const usageResetCreditsSchema: import("@oh-my-pi/omptype").FluentType<{
333
383
  availableCount: number;
384
+ cooldownUntil?: string | undefined;
334
385
  credits?: {
386
+ blocking?: string[] | undefined;
387
+ clears?: string[] | undefined;
335
388
  expiresAt?: string | undefined;
336
389
  grantedAt?: string | undefined;
390
+ id?: string | undefined;
391
+ program?: string | undefined;
392
+ remainingCount?: number | undefined;
393
+ requiresLimit?: boolean | undefined;
337
394
  status?: string | undefined;
395
+ title?: string | undefined;
396
+ usable?: boolean | undefined;
397
+ usedFractions?: Record<string, number> | undefined;
338
398
  }[] | undefined;
399
+ eligible?: boolean | undefined;
400
+ nextCreditId?: string | undefined;
401
+ reason?: string | undefined;
402
+ redeemableCount?: number | undefined;
339
403
  }, {
340
404
  availableCount: number;
405
+ cooldownUntil?: string | undefined;
341
406
  credits?: {
407
+ blocking?: string[] | undefined;
408
+ clears?: string[] | undefined;
342
409
  expiresAt?: string | undefined;
343
410
  grantedAt?: string | undefined;
411
+ id?: string | undefined;
412
+ program?: string | undefined;
413
+ remainingCount?: number | undefined;
414
+ requiresLimit?: boolean | undefined;
344
415
  status?: string | undefined;
416
+ title?: string | undefined;
417
+ usable?: boolean | undefined;
418
+ usedFractions?: Record<string, number> | undefined;
345
419
  }[] | undefined;
420
+ eligible?: boolean | undefined;
421
+ nextCreditId?: string | undefined;
422
+ reason?: string | undefined;
423
+ redeemableCount?: number | undefined;
346
424
  }>;
347
425
  export declare const usageReportSchema: import("@oh-my-pi/omptype").FluentType<{
348
426
  fetchedAt: number;
@@ -384,11 +462,25 @@ export declare const usageReportSchema: import("@oh-my-pi/omptype").FluentType<{
384
462
  raw?: unknown;
385
463
  resetCredits?: {
386
464
  availableCount: number;
465
+ cooldownUntil?: string | undefined;
387
466
  credits?: {
467
+ blocking?: string[] | undefined;
468
+ clears?: string[] | undefined;
388
469
  expiresAt?: string | undefined;
389
470
  grantedAt?: string | undefined;
471
+ id?: string | undefined;
472
+ program?: string | undefined;
473
+ remainingCount?: number | undefined;
474
+ requiresLimit?: boolean | undefined;
390
475
  status?: string | undefined;
476
+ title?: string | undefined;
477
+ usable?: boolean | undefined;
478
+ usedFractions?: Record<string, number> | undefined;
391
479
  }[] | undefined;
480
+ eligible?: boolean | undefined;
481
+ nextCreditId?: string | undefined;
482
+ reason?: string | undefined;
483
+ redeemableCount?: number | undefined;
392
484
  } | undefined;
393
485
  }, {
394
486
  fetchedAt: number;
@@ -430,11 +522,25 @@ export declare const usageReportSchema: import("@oh-my-pi/omptype").FluentType<{
430
522
  raw?: unknown;
431
523
  resetCredits?: {
432
524
  availableCount: number;
525
+ cooldownUntil?: string | undefined;
433
526
  credits?: {
527
+ blocking?: string[] | undefined;
528
+ clears?: string[] | undefined;
434
529
  expiresAt?: string | undefined;
435
530
  grantedAt?: string | undefined;
531
+ id?: string | undefined;
532
+ program?: string | undefined;
533
+ remainingCount?: number | undefined;
534
+ requiresLimit?: boolean | undefined;
436
535
  status?: string | undefined;
536
+ title?: string | undefined;
537
+ usable?: boolean | undefined;
538
+ usedFractions?: Record<string, number> | undefined;
437
539
  }[] | undefined;
540
+ eligible?: boolean | undefined;
541
+ nextCreditId?: string | undefined;
542
+ reason?: string | undefined;
543
+ redeemableCount?: number | undefined;
438
544
  } | undefined;
439
545
  }>;
440
546
  /** Optional logger for usage fetchers. */
@@ -16,7 +16,10 @@ export interface JsonSchemaValidationResult {
16
16
  success: boolean;
17
17
  issues: JsonSchemaValidationIssue[];
18
18
  }
19
+ /** The unique discriminator-selected branch, or undefined when selection is ambiguous or absent. */
20
+ export declare function getTagSelectedUnionBranch(branches: readonly unknown[], value: unknown): unknown;
19
21
  /** Whether any same-instance schema declaration or constraint owns this property name. */
20
22
  export declare function schemaDefinesProperty(schema: unknown, key: string): boolean;
21
- export declare function validateJsonSchemaValue(schema: unknown, value: unknown): JsonSchemaValidationResult;
22
- export declare function isJsonSchemaValueValid(schema: unknown, value: unknown): boolean;
23
+ export declare function validateJsonSchemaValue(schema: unknown, value: unknown, root?: unknown): JsonSchemaValidationResult;
24
+ /** Validate a subschema using its complete schema's local-reference context. */
25
+ export declare function isJsonSchemaValueValid(schema: unknown, value: unknown, root?: unknown): boolean;
@@ -21,6 +21,6 @@ export interface RepeatedToolCallDetection {
21
21
  export declare class ToolCallLoopGuard {
22
22
  #private;
23
23
  constructor(options: ToolCallLoopGuardOptions);
24
- /** Records one completed turn and returns the threshold hit, if any. */
24
+ /** Records one completed turn and reports repetitions at or beyond the threshold. */
25
25
  recordTurn(turn: ToolCallLoopTurn): RepeatedToolCallDetection | null;
26
26
  }
@@ -0,0 +1,11 @@
1
+ import type { Api, Model } from "@oh-my-pi/pi-catalog/types";
2
+ import { type VideoOptions } from "./openrouter-video.js";
3
+ import type { VideoContent, VideoGenerationRequest, VideoJob } from "./types.js";
4
+ export * from "./openrouter-video.js";
5
+ export * from "./types.js";
6
+ /** Submit an asynchronous video generation job through the model's transport. */
7
+ export declare function submitVideo(model: Model<Api>, request: VideoGenerationRequest, options: VideoOptions): Promise<VideoJob>;
8
+ /** Poll an asynchronous video generation job through the model's transport. */
9
+ export declare function pollVideo(model: Model<Api>, jobId: string, options: VideoOptions): Promise<VideoJob>;
10
+ /** Stream generated video content through the model's transport. */
11
+ export declare function downloadVideo(model: Model<Api>, jobId: string, options: VideoOptions): Promise<VideoContent>;
@@ -0,0 +1,19 @@
1
+ import type { Api, FetchImpl, Model } from "@oh-my-pi/pi-catalog/types";
2
+ import { type ApiKey } from "../auth-retry.js";
3
+ import * as AIError from "../error/index.js";
4
+ import type { VideoContent, VideoGenerationRequest, VideoJob } from "./types.js";
5
+ export interface VideoOptions {
6
+ apiKey: ApiKey;
7
+ fetch?: FetchImpl;
8
+ signal?: AbortSignal;
9
+ }
10
+ /** Non-2xx response from an OpenRouter video endpoint. */
11
+ export declare class VideoApiError extends AIError.ProviderHttpError {
12
+ readonly name = "VideoApiError";
13
+ }
14
+ /** Submit an asynchronous OpenRouter video generation job. */
15
+ export declare function submitOpenRouterVideo(model: Model<Api>, request: VideoGenerationRequest, options: VideoOptions): Promise<VideoJob>;
16
+ /** Poll an asynchronous OpenRouter video generation job. */
17
+ export declare function pollOpenRouterVideo(model: Model<Api>, jobId: string, options: VideoOptions): Promise<VideoJob>;
18
+ /** Stream generated video bytes from OpenRouter without buffering them in memory. */
19
+ export declare function downloadOpenRouterVideo(model: Model<Api>, jobId: string, options: VideoOptions): Promise<VideoContent>;
@@ -0,0 +1,62 @@
1
+ import type { Usage } from "@oh-my-pi/pi-catalog/types";
2
+ export type VideoResolution = "360p" | "480p" | "720p" | "768p" | "1080p" | "1K" | "2K" | "4K";
3
+ export type VideoAspectRatio = "16:9" | "9:16" | "1:1" | "4:3" | "3:4" | "3:2" | "2:3" | "21:9" | "9:21";
4
+ export interface VideoImageReference {
5
+ type: "image_url";
6
+ imageUrl: {
7
+ url: string;
8
+ };
9
+ }
10
+ export interface VideoFrameImage extends VideoImageReference {
11
+ frameType: "first_frame" | "last_frame";
12
+ }
13
+ export interface VideoAudioReference {
14
+ type: "audio_url";
15
+ audioUrl: {
16
+ url: string;
17
+ };
18
+ }
19
+ export interface VideoVideoReference {
20
+ type: "video_url";
21
+ videoUrl: {
22
+ url: string;
23
+ };
24
+ }
25
+ export type VideoInputReference = VideoImageReference | VideoAudioReference | VideoVideoReference;
26
+ /** Canonical camel-case form of OpenRouter's asynchronous video submit request. */
27
+ export interface VideoGenerationRequest {
28
+ prompt?: string;
29
+ duration?: number;
30
+ resolution?: VideoResolution;
31
+ aspectRatio?: VideoAspectRatio;
32
+ size?: string;
33
+ frameImages?: VideoFrameImage[];
34
+ inputReferences?: VideoInputReference[];
35
+ generateAudio?: boolean;
36
+ seed?: number;
37
+ callbackUrl?: string;
38
+ provider?: {
39
+ options?: Record<string, unknown>;
40
+ };
41
+ previousJobId?: string;
42
+ sessionId?: string;
43
+ trace?: Record<string, unknown>;
44
+ user?: string;
45
+ creativity?: number;
46
+ upscaleFactor?: number;
47
+ }
48
+ export type VideoJobStatus = "queued" | "processing" | "pending" | "in_progress" | "completed" | "failed" | "cancelled" | "expired";
49
+ export interface VideoJob {
50
+ id: string;
51
+ status: VideoJobStatus;
52
+ pollingUrl?: string;
53
+ generationId?: string;
54
+ contentUrls?: string[];
55
+ error?: string;
56
+ usage?: Usage;
57
+ }
58
+ export interface VideoContent {
59
+ body: ReadableStream<Uint8Array>;
60
+ contentType: string;
61
+ contentLength?: number;
62
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@oh-my-pi/pi-ai",
3
- "version": "18.2.7",
3
+ "version": "18.2.9",
4
4
  "description": "Unified LLM API with automatic model discovery and provider configuration",
5
5
  "keywords": [
6
6
  "ai",
@@ -45,10 +45,34 @@
45
45
  "types": "./dist/types/error/index.d.ts",
46
46
  "import": "./src/error/index.ts"
47
47
  },
48
+ "./embeddings": {
49
+ "types": "./dist/types/embeddings/index.d.ts",
50
+ "import": "./src/embeddings/index.ts"
51
+ },
48
52
  "./judgment": {
49
53
  "types": "./dist/types/judgment/index.d.ts",
50
54
  "import": "./src/judgment/index.ts"
51
55
  },
56
+ "./rerank": {
57
+ "types": "./dist/types/rerank/index.d.ts",
58
+ "import": "./src/rerank/index.ts"
59
+ },
60
+ "./speech": {
61
+ "types": "./dist/types/speech/index.d.ts",
62
+ "import": "./src/speech/index.ts"
63
+ },
64
+ "./images": {
65
+ "types": "./dist/types/images/index.d.ts",
66
+ "import": "./src/images/index.ts"
67
+ },
68
+ "./transcription": {
69
+ "types": "./dist/types/transcription/index.d.ts",
70
+ "import": "./src/transcription/index.ts"
71
+ },
72
+ "./video": {
73
+ "types": "./dist/types/video/index.d.ts",
74
+ "import": "./src/video/index.ts"
75
+ },
52
76
  "./*": {
53
77
  "types": "./dist/types/*.d.ts",
54
78
  "import": "./src/*.ts"
@@ -128,11 +152,11 @@
128
152
  "fmt": "oxfmt --no-error-on-unmatched-pattern 'src/**/*.{ts,tsx}' '{test,bench,examples,scripts}/**/*.ts' '*.ts'"
129
153
  },
130
154
  "dependencies": {
131
- "@oh-my-pi/omptype": "18.2.7",
132
- "@oh-my-pi/pi-catalog": "18.2.7",
133
- "@oh-my-pi/pi-natives": "18.2.7",
134
- "@oh-my-pi/pi-utils": "18.2.7",
135
- "@oh-my-pi/pi-wire": "18.2.7"
155
+ "@oh-my-pi/omptype": "18.2.9",
156
+ "@oh-my-pi/pi-catalog": "18.2.9",
157
+ "@oh-my-pi/pi-natives": "18.2.9",
158
+ "@oh-my-pi/pi-utils": "18.2.9",
159
+ "@oh-my-pi/pi-wire": "18.2.9"
136
160
  },
137
161
  "devDependencies": {
138
162
  "@types/bun": "^1.3.14"
@@ -88,7 +88,7 @@ type SerializedCredentialRecord = {
88
88
  identityKey: string | null;
89
89
  };
90
90
 
91
- const AUTH_SCHEMA_VERSION = 7;
91
+ const AUTH_SCHEMA_VERSION = 8;
92
92
  const SQLITE_NOW_EPOCH = "CAST(strftime('%s','now') AS INTEGER)";
93
93
  const LEGACY_CODEX_BLOCK_PROVIDER_KEY = "openai-codex:oauth";
94
94
  const LEGACY_CODEX_BLOCK_SCOPE = "shared";
@@ -970,6 +970,9 @@ export class SqliteAuthCredentialStore implements AuthCredentialStore {
970
970
  if (fromVersion < 7) {
971
971
  this.#migrateAuthSchemaV6ToV7();
972
972
  }
973
+ if (fromVersion < 8) {
974
+ this.#migrateAuthSchemaV7ToV8();
975
+ }
973
976
  }
974
977
 
975
978
  #migrateAuthSchemaV0ToV1(): void {
@@ -1141,6 +1144,46 @@ export class SqliteAuthCredentialStore implements AuthCredentialStore {
1141
1144
  migrate.immediate();
1142
1145
  }
1143
1146
 
1147
+ #migrateAuthSchemaV7ToV8(): void {
1148
+ const migrate = this.#db.transaction(() => {
1149
+ // SingularityAPI split into two providers — the pay-as-you-go universal
1150
+ // gateway and the slot-reserved lanes — and keys stored under the
1151
+ // retired shared id belong to one or the other by format: the gateway
1152
+ // issues `sk-sapi-...` while the lanes issue plain `sk-...` (both
1153
+ // observed live 2026-09-22), and neither key is accepted by the other
1154
+ // host. Route each stored credential to the product that serves it
1155
+ // instead of orphaning it under an id nothing reads anymore.
1156
+ const select = this.#db.prepare(
1157
+ "SELECT id, credential_type, data FROM auth_credentials WHERE provider = 'singularityapi'",
1158
+ );
1159
+ let rows: Array<{ id: number; credential_type: string; data: string }>;
1160
+ try {
1161
+ rows = select.all() as Array<{ id: number; credential_type: string; data: string }>;
1162
+ } finally {
1163
+ select.finalize();
1164
+ }
1165
+ for (const row of rows) {
1166
+ let provider = "singularityapi-tech";
1167
+ try {
1168
+ const parsed = JSON.parse(row.data) as { key?: unknown };
1169
+ if (typeof parsed.key === "string" && parsed.key.startsWith("sk-sapi-")) {
1170
+ provider = "singularityapi-dev";
1171
+ }
1172
+ } catch {
1173
+ // Unparsable payload takes the lane default; whichever product the
1174
+ // key really belongs to then answers 401 and the owner re-logs in.
1175
+ }
1176
+ this.#db.run("UPDATE auth_credentials SET provider = ? WHERE id = ?", [provider, row.id]);
1177
+ this.#db.run(
1178
+ "UPDATE auth_credential_blocks SET provider_key = ? WHERE credential_id = ? AND provider_key = ?",
1179
+ [`${provider}:${row.credential_type}`, row.id, `singularityapi:${row.credential_type}`],
1180
+ );
1181
+ }
1182
+ this.#writeAuthSchemaVersion(8);
1183
+ });
1184
+ migrate.immediate();
1185
+ }
1186
+
1144
1187
  #backfillCredentialIdentityKeys(): void {
1145
1188
  const selectRowsStmt = this.#db.prepare(
1146
1189
  "SELECT id, provider, credential_type, data, disabled_cause, identity_key FROM auth_credentials WHERE identity_key IS NULL ORDER BY id ASC",
@@ -175,8 +175,8 @@ function usageOverlayKey(
175
175
  const accountId = ids.accountId?.trim().toLowerCase();
176
176
  const email = ids.email?.trim().toLowerCase();
177
177
  const projectId = ids.projectId?.trim().toLowerCase();
178
- if (accountId) base = `account:${accountId}`;
179
- else if (email) base = `email:${email}`;
178
+ if (email) base = `email:${email}`;
179
+ else if (accountId) base = `account:${accountId}`;
180
180
  else if (projectId) base = `project:${projectId}`;
181
181
  const orgId = ids.orgId?.trim().toLowerCase();
182
182
  if (orgId) return base ? `${provider}\0org:${orgId}|${base}` : `${provider}\0org:${orgId}`;
@@ -1556,6 +1556,10 @@ function reportMatchesIdentity(
1556
1556
  projectId: string | undefined,
1557
1557
  ): boolean {
1558
1558
  const metadata = (report.metadata ?? {}) as Record<string, unknown>;
1559
+ const metaEmail = readMetadataString(metadata, "email")?.toLowerCase();
1560
+ // Email identifies the member within shared Team workspace account/org ids.
1561
+ // When both sides provide it, a mismatch is decisive.
1562
+ if (email && metaEmail) return metaEmail === email;
1559
1563
  if (accountId) {
1560
1564
  const metaAccount = readMetadataString(metadata, "accountId") ?? readMetadataString(metadata, "account_id");
1561
1565
  if (metaAccount && metaAccount.toLowerCase() === accountId) return true;
@@ -1563,10 +1567,6 @@ function reportMatchesIdentity(
1563
1567
  if (limit.scope.accountId?.toLowerCase() === accountId) return true;
1564
1568
  }
1565
1569
  }
1566
- if (email) {
1567
- const metaEmail = readMetadataString(metadata, "email");
1568
- if (metaEmail && metaEmail.toLowerCase() === email) return true;
1569
- }
1570
1570
  if (projectId) {
1571
1571
  const metaProject = readMetadataString(metadata, "projectId") ?? readMetadataString(metadata, "project_id");
1572
1572
  if (metaProject && metaProject.toLowerCase() === projectId) return true;
@@ -235,7 +235,21 @@ const usageLimitSchema = type({
235
235
 
236
236
  const usageResetCreditsSchema = type({
237
237
  availableCount: "number",
238
+ "redeemableCount?": "number",
239
+ "nextCreditId?": "string",
240
+ "eligible?": "boolean",
241
+ "reason?": "string",
242
+ "cooldownUntil?": "string",
238
243
  "credits?": type({
244
+ "id?": "string",
245
+ "title?": "string",
246
+ "program?": "string",
247
+ "remainingCount?": "number",
248
+ "usable?": "boolean",
249
+ "requiresLimit?": "boolean",
250
+ "clears?": "string[]",
251
+ "blocking?": "string[]",
252
+ "usedFractions?": { "[string]": "number" },
239
253
  "grantedAt?": "string",
240
254
  "expiresAt?": "string",
241
255
  "status?": "string",