@oh-my-pi/pi-catalog 17.1.2 → 17.1.4
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/CHANGELOG.md +19 -0
- package/dist/types/identity/family.d.ts +9 -0
- package/dist/types/model-cache.d.ts +1 -1
- package/dist/types/model-manager.d.ts +10 -1
- package/dist/types/provider-models/openai-compat.d.ts +2 -2
- package/dist/types/types.d.ts +12 -2
- package/dist/types/wire/alibaba-token-plan.d.ts +17 -1
- package/package.json +3 -3
- package/src/build.ts +34 -9
- package/src/compat/anthropic.ts +18 -4
- package/src/compat/bedrock.ts +12 -0
- package/src/compat/openai.ts +2 -0
- package/src/identity/family.ts +13 -0
- package/src/model-cache.ts +15 -7
- package/src/model-manager.ts +42 -13
- package/src/models.json +5371 -2112
- package/src/provider-models/openai-compat.ts +25 -3
- package/src/types.ts +13 -1
- package/src/wire/alibaba-token-plan.ts +31 -4
|
@@ -7,6 +7,7 @@ import {
|
|
|
7
7
|
import { Effort, THINKING_EFFORTS } from "../effort";
|
|
8
8
|
import { FIREWORKS_FAST_SUFFIX, toFireworksPublicModelId } from "../fireworks-model-id";
|
|
9
9
|
import {
|
|
10
|
+
anthropicModelSupportsThinking,
|
|
10
11
|
isGlmVisionModelId,
|
|
11
12
|
isGrokReasoningEffortCapable,
|
|
12
13
|
isKimiK3ModelId,
|
|
@@ -17,7 +18,7 @@ import type { ModelManagerOptions } from "../model-manager";
|
|
|
17
18
|
import { getBundledModels } from "../models";
|
|
18
19
|
import type { Api, FetchImpl, Model, ModelSpec, OpenAICompat, Provider, ThinkingConfig } from "../types";
|
|
19
20
|
import { discoveryFetch, isAnthropicOAuthToken, isRecord, toBoolean, toNumber, toPositiveNumber } from "../utils";
|
|
20
|
-
import { parseAlibabaTokenPlanCredential } from "../wire/alibaba-token-plan";
|
|
21
|
+
import { ALIBABA_TOKEN_PLAN_BASE_URL, parseAlibabaTokenPlanCredential } from "../wire/alibaba-token-plan";
|
|
21
22
|
import { coreWeaveProjectHeaders } from "../wire/coreweave";
|
|
22
23
|
import {
|
|
23
24
|
COPILOT_API_HEADERS,
|
|
@@ -2434,7 +2435,7 @@ export function alibabaCodingPlanModelManagerOptions(
|
|
|
2434
2435
|
// Alibaba Token Plan
|
|
2435
2436
|
// ---------------------------------------------------------------------------
|
|
2436
2437
|
|
|
2437
|
-
export
|
|
2438
|
+
export { ALIBABA_TOKEN_PLAN_BASE_URL };
|
|
2438
2439
|
|
|
2439
2440
|
const ALIBABA_TOKEN_PLAN_COST = { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 } as const;
|
|
2440
2441
|
const ALIBABA_TOKEN_PLAN_COMPAT: OpenAICompat = {
|
|
@@ -2556,7 +2557,10 @@ export function alibabaTokenPlanModelManagerOptions(
|
|
|
2556
2557
|
): ModelManagerOptions<"openai-completions"> {
|
|
2557
2558
|
const credential = config?.apiKey ? parseAlibabaTokenPlanCredential(config.apiKey) : undefined;
|
|
2558
2559
|
const apiKey = credential?.token;
|
|
2559
|
-
|
|
2560
|
+
// A region-locked credential (China/custom) dictates the discovery endpoint:
|
|
2561
|
+
// its key only authenticates against its own region, so fetching /models from
|
|
2562
|
+
// any other base URL would 401 (#6682).
|
|
2563
|
+
const baseUrl = credential?.baseUrl ?? config?.baseUrl ?? ALIBABA_TOKEN_PLAN_BASE_URL;
|
|
2560
2564
|
return {
|
|
2561
2565
|
providerId: "alibaba-token-plan",
|
|
2562
2566
|
dynamicModelsAuthoritative: true,
|
|
@@ -4279,6 +4283,13 @@ export function githubCopilotModelManagerOptions(config?: GithubCopilotModelMana
|
|
|
4279
4283
|
return {
|
|
4280
4284
|
providerId: "github-copilot",
|
|
4281
4285
|
dropCachedModelIdsOnStaticMismatch: COPILOT_CACHE_INVALIDATED_MODEL_IDS,
|
|
4286
|
+
// COPILOT_API_HEADERS are compile-time constants (User-Agent + API
|
|
4287
|
+
// version), not credentials. The cache omits all request headers for
|
|
4288
|
+
// safety and can only restore them from a bundled static entry — so a
|
|
4289
|
+
// Copilot model with no bundled reference (e.g. a freshly served
|
|
4290
|
+
// claude-opus-5 and its synthesized -1m sibling) is dropped on offline
|
|
4291
|
+
// reads. Declaring the constant lets the cache restore it by value.
|
|
4292
|
+
restorableHeaderFallback: { ...COPILOT_API_HEADERS },
|
|
4282
4293
|
...(apiKey && {
|
|
4283
4294
|
fetchDynamicModels: async () => {
|
|
4284
4295
|
const longContextVariants: ModelSpec<Api>[] = [];
|
|
@@ -4377,6 +4388,17 @@ export function githubCopilotModelManagerOptions(config?: GithubCopilotModelMana
|
|
|
4377
4388
|
contextWindow: defaultTierWindow,
|
|
4378
4389
|
maxTokens,
|
|
4379
4390
|
headers: { ...COPILOT_API_HEADERS },
|
|
4391
|
+
// Copilot's `/models` advertises no reasoning bit, so a
|
|
4392
|
+
// thinking-capable Claude with no bundled reference would
|
|
4393
|
+
// fall back to `reasoning: false` and lose its effort dial.
|
|
4394
|
+
// Gate on the id classifier (not the transport alone) so a
|
|
4395
|
+
// lagging enterprise catalog serving a pre-thinking Claude
|
|
4396
|
+
// (<= 3.5) over the Messages proxy is not handed a fabricated
|
|
4397
|
+
// dial it would reject; a modern reference-less model (e.g.
|
|
4398
|
+
// claude-opus-5) is marked so `buildModel` derives the ladder.
|
|
4399
|
+
...(api === "anthropic-messages" && anthropicModelSupportsThinking(defaults.id)
|
|
4400
|
+
? { reasoning: true }
|
|
4401
|
+
: {}),
|
|
4380
4402
|
...(api === "openai-completions"
|
|
4381
4403
|
? {
|
|
4382
4404
|
compat: {
|
package/src/types.ts
CHANGED
|
@@ -341,6 +341,12 @@ export interface OpenAICompat {
|
|
|
341
341
|
* to opt a host out.
|
|
342
342
|
*/
|
|
343
343
|
toolSchemaFlavor?: "moonshot-mfjs" | "grammar" | "none";
|
|
344
|
+
/**
|
|
345
|
+
* Stream-watchdog first-event timeout in ms.
|
|
346
|
+
* Set to `0` to allow unbounded prompt processing. Default: auto-detected
|
|
347
|
+
* (disabled for local OpenAI-compatible backends).
|
|
348
|
+
*/
|
|
349
|
+
streamFirstEventTimeoutMs?: number;
|
|
344
350
|
/**
|
|
345
351
|
* Stream-watchdog idle-timeout floor in ms for slow reasoning hosts.
|
|
346
352
|
* Default: auto-detected (GLM coding-plan hosts, direct DeepSeek reasoning).
|
|
@@ -565,6 +571,8 @@ export interface ResolvedOpenAISharedCompat {
|
|
|
565
571
|
requiresAssistantContentForToolCalls: boolean;
|
|
566
572
|
stripDeepseekSpecialTokens: boolean;
|
|
567
573
|
streamMarkupHealingPattern?: OpenAIStreamMarkupHealingPattern;
|
|
574
|
+
/** See {@link OpenAICompat.streamFirstEventTimeoutMs}. */
|
|
575
|
+
streamFirstEventTimeoutMs?: number;
|
|
568
576
|
reasoningDeltasMayBeCumulative: boolean;
|
|
569
577
|
emptyLengthFinishIsContextError: boolean;
|
|
570
578
|
usesOpenAIToolCallIdLimit: boolean;
|
|
@@ -645,6 +653,7 @@ export type ResolvedOpenAICompat = ResolvedOpenAISharedCompat &
|
|
|
645
653
|
| "extraBody"
|
|
646
654
|
| "toolStrictMode"
|
|
647
655
|
| "toolSchemaFlavor"
|
|
656
|
+
| "streamFirstEventTimeoutMs"
|
|
648
657
|
| "streamIdleTimeoutMs"
|
|
649
658
|
| "cacheControlFormat"
|
|
650
659
|
| "thinkingKeep"
|
|
@@ -816,6 +825,8 @@ export interface Model<TApi extends Api = Api> {
|
|
|
816
825
|
supportsTools?: boolean;
|
|
817
826
|
/** Whether this model accepts the GA OpenAI Responses `{ type: "computer" }` native tool. */
|
|
818
827
|
supportsComputerUse?: boolean;
|
|
828
|
+
/** Verbatim explicit computer-use support from the spec; undefined when `buildModel` inferred the runtime value. */
|
|
829
|
+
supportsComputerUseConfig?: boolean;
|
|
819
830
|
/** GitLab Duo Workflow root namespace selected during catalog discovery. */
|
|
820
831
|
gitlabDuoWorkflowRootNamespaceId?: string;
|
|
821
832
|
/** Cursor `max_mode` request flag returned by `GetUsableModels` for premium models that require max mode. */
|
|
@@ -901,7 +912,8 @@ export interface Model<TApi extends Api = Api> {
|
|
|
901
912
|
* vocabulary of `buildModel`. Identical to `Model` except `compat` carries the
|
|
902
913
|
* sparse override shape and nothing is resolved yet.
|
|
903
914
|
*/
|
|
904
|
-
export interface ModelSpec<TApi extends Api = Api>
|
|
915
|
+
export interface ModelSpec<TApi extends Api = Api>
|
|
916
|
+
extends Omit<Model<TApi>, "compat" | "compatConfig" | "supportsComputerUseConfig"> {
|
|
905
917
|
/** Sparse compatibility overrides; resolved into `Model.compat` by `buildModel`. */
|
|
906
918
|
compat?: CompatConfigOf<TApi>;
|
|
907
919
|
}
|
|
@@ -1,6 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* International (Singapore) Token Plan endpoint. Default region; keys issued by
|
|
3
|
+
* the international product authenticate only here.
|
|
4
|
+
*/
|
|
5
|
+
export const ALIBABA_TOKEN_PLAN_BASE_URL = "https://token-plan.ap-southeast-1.maas.aliyuncs.com/compatible-mode/v1";
|
|
6
|
+
/**
|
|
7
|
+
* China (Beijing) Token Plan endpoint (百炼 Token Plan). Keys are region-locked:
|
|
8
|
+
* a Beijing-issued key is rejected by the international endpoint with
|
|
9
|
+
* `invalid_api_key`, and vice versa (#6682).
|
|
10
|
+
*/
|
|
11
|
+
export const ALIBABA_TOKEN_PLAN_CN_BASE_URL = "https://token-plan.cn-beijing.maas.aliyuncs.com/compatible-mode/v1";
|
|
12
|
+
|
|
1
13
|
export interface AlibabaTokenPlanCredential {
|
|
2
14
|
token: string;
|
|
3
15
|
cookie?: string;
|
|
16
|
+
/**
|
|
17
|
+
* Region base URL the key authenticates against. Absent means the default
|
|
18
|
+
* international endpoint ({@link ALIBABA_TOKEN_PLAN_BASE_URL}).
|
|
19
|
+
*/
|
|
20
|
+
baseUrl?: string;
|
|
4
21
|
}
|
|
5
22
|
|
|
6
23
|
const TOKEN_PATTERN = /^sk-[A-Za-z0-9._~+/-]+={0,2}$/;
|
|
@@ -10,18 +27,28 @@ export function parseAlibabaTokenPlanCredential(value: string): AlibabaTokenPlan
|
|
|
10
27
|
if (!trimmed) return null;
|
|
11
28
|
if (!trimmed.startsWith("{")) return TOKEN_PATTERN.test(trimmed) ? { token: trimmed } : null;
|
|
12
29
|
try {
|
|
13
|
-
const parsed = JSON.parse(trimmed) as { token?: unknown; cookie?: unknown };
|
|
30
|
+
const parsed = JSON.parse(trimmed) as { token?: unknown; cookie?: unknown; baseUrl?: unknown };
|
|
14
31
|
if (typeof parsed.token !== "string" || !TOKEN_PATTERN.test(parsed.token.trim())) return null;
|
|
15
32
|
if (parsed.cookie !== undefined && typeof parsed.cookie !== "string") return null;
|
|
33
|
+
if (parsed.baseUrl !== undefined && typeof parsed.baseUrl !== "string") return null;
|
|
16
34
|
const token = parsed.token.trim();
|
|
17
35
|
const cookie = parsed.cookie?.trim();
|
|
18
|
-
|
|
36
|
+
const baseUrl = parsed.baseUrl?.trim();
|
|
37
|
+
const credential: AlibabaTokenPlanCredential = { token };
|
|
38
|
+
if (cookie) credential.cookie = cookie;
|
|
39
|
+
if (baseUrl) credential.baseUrl = baseUrl;
|
|
40
|
+
return credential;
|
|
19
41
|
} catch {
|
|
20
42
|
return null;
|
|
21
43
|
}
|
|
22
44
|
}
|
|
23
45
|
|
|
24
|
-
export function serializeAlibabaTokenPlanCredential(token: string, cookie: string): string {
|
|
46
|
+
export function serializeAlibabaTokenPlanCredential(token: string, cookie: string, baseUrl?: string): string {
|
|
25
47
|
const trimmedCookie = cookie.trim();
|
|
26
|
-
|
|
48
|
+
const trimmedBaseUrl = baseUrl?.trim();
|
|
49
|
+
if (!trimmedCookie && !trimmedBaseUrl) return token;
|
|
50
|
+
const payload: { token: string; cookie?: string; baseUrl?: string } = { token };
|
|
51
|
+
if (trimmedCookie) payload.cookie = trimmedCookie;
|
|
52
|
+
if (trimmedBaseUrl) payload.baseUrl = trimmedBaseUrl;
|
|
53
|
+
return JSON.stringify(payload);
|
|
27
54
|
}
|