@oh-my-pi/pi-catalog 18.9.0 → 18.9.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.
- package/CHANGELOG.md +12 -0
- package/dist/types/compat/auth-ids.d.ts +2 -2
- package/dist/types/compat/judgment-questions.d.ts +7 -0
- package/dist/types/compat/provider-ids.d.ts +1 -1
- package/dist/types/compat/types.d.ts +2 -0
- package/dist/types/provider-models/openai-compat.d.ts +1 -1
- package/dist/types/provider-models/special.d.ts +2 -0
- package/dist/types/types.d.ts +11 -1
- package/dist/types/wire/cloudflare-ai-gateway.d.ts +0 -10
- package/dist/types/wire/cloudflare.d.ts +10 -0
- package/package.json +4 -4
- package/src/compat/auth-ids.ts +2 -0
- package/src/compat/axes.ts +6 -1
- package/src/compat/judgment-questions.ts +12 -0
- package/src/compat/provider-ids.ts +1 -0
- package/src/compat/resolve.ts +3 -0
- package/src/compat/rules/README.md +3 -1
- package/src/compat/rules/auth/_order.kdl +1 -1
- package/src/compat/rules/auth/cloudflare-workers-ai.kdl +9 -0
- package/src/compat/rules/classes/qwen.kdl +2 -1
- package/src/compat/rules/providers/cloudflare-workers-ai.kdl +34 -0
- package/src/compat/rules/providers/groq.kdl +21 -0
- package/src/compat/rules/providers/judgment-questions.kdl +53 -0
- package/src/compat/rules/providers/openai.kdl +15 -0
- package/src/compat/rules.json +1 -1
- package/src/compat/types.ts +2 -0
- package/src/models.json +1 -1
- package/src/provider-models/descriptors.ts +2 -0
- package/src/provider-models/openai-compat.ts +26 -2
- package/src/provider-models/special.ts +9 -0
- package/src/types.ts +14 -0
- package/src/wire/cloudflare-ai-gateway.ts +0 -36
- package/src/wire/cloudflare.ts +40 -0
|
@@ -79,6 +79,7 @@ import {
|
|
|
79
79
|
zhipuCodingPlanModelManagerOptions,
|
|
80
80
|
} from "./openai-compat";
|
|
81
81
|
import {
|
|
82
|
+
cloudflareWorkersAiModelManagerOptions,
|
|
82
83
|
cursorModelManagerOptions,
|
|
83
84
|
devinModelManagerOptions,
|
|
84
85
|
factoryDroidModelManagerOptions,
|
|
@@ -105,6 +106,7 @@ const MODEL_MANAGER_FACTORIES: Readonly<Partial<Record<KnownProvider, ModelManag
|
|
|
105
106
|
cerebras: config => cerebrasModelManagerOptions(config),
|
|
106
107
|
"charm-hyper": config => charmHyperModelManagerOptions(config),
|
|
107
108
|
"cloudflare-ai-gateway": config => cloudflareAiGatewayModelManagerOptions(config),
|
|
109
|
+
"cloudflare-workers-ai": () => cloudflareWorkersAiModelManagerOptions(),
|
|
108
110
|
commandcode: config => commandCodeModelManagerOptions(config),
|
|
109
111
|
coralbricks: config => coralbricksModelManagerOptions(config),
|
|
110
112
|
cursor: config => cursorModelManagerOptions(config),
|
|
@@ -1071,8 +1071,8 @@ export interface OpenAIModelManagerConfig {
|
|
|
1071
1071
|
fetch?: FetchImpl;
|
|
1072
1072
|
}
|
|
1073
1073
|
|
|
1074
|
-
export function openaiModelManagerOptions(config?: OpenAIModelManagerConfig): ModelManagerOptions<
|
|
1075
|
-
|
|
1074
|
+
export function openaiModelManagerOptions(config?: OpenAIModelManagerConfig): ModelManagerOptions<Api> {
|
|
1075
|
+
const options = createOpenAICompatibleModelManagerOptions({
|
|
1076
1076
|
api: "openai-responses",
|
|
1077
1077
|
providerId: "openai",
|
|
1078
1078
|
defaultBaseUrl: OPENAI_API_BASE_URL,
|
|
@@ -1081,6 +1081,30 @@ export function openaiModelManagerOptions(config?: OpenAIModelManagerConfig): Mo
|
|
|
1081
1081
|
filterModel: (_entry, model, references) => isLikelyOpenAIResponsesModelId(model.id, references),
|
|
1082
1082
|
mapModel: mapWithBundledReference,
|
|
1083
1083
|
});
|
|
1084
|
+
const fetchDiscovered = options.fetchDynamicModels;
|
|
1085
|
+
if (!fetchDiscovered) return options;
|
|
1086
|
+
return {
|
|
1087
|
+
...options,
|
|
1088
|
+
fetchDynamicModels: async () => appendUnbundledSeedModels("openai", await fetchDiscovered()),
|
|
1089
|
+
};
|
|
1090
|
+
}
|
|
1091
|
+
|
|
1092
|
+
/**
|
|
1093
|
+
* Append the authored seed rows that neither discovery nor the bundled catalog
|
|
1094
|
+
* carries yet: a seed added since the last models.json regeneration (the
|
|
1095
|
+
* Decisions judge row) reaches runtime through a successful discovery. Seeds
|
|
1096
|
+
* already bundled keep resolving through the bundled slice, and the static
|
|
1097
|
+
* catalog (and with it the cache fingerprint) stays the bundled one.
|
|
1098
|
+
*/
|
|
1099
|
+
function appendUnbundledSeedModels(
|
|
1100
|
+
providerId: GeneratedProvider,
|
|
1101
|
+
discovered: readonly ModelSpec<Api>[] | null,
|
|
1102
|
+
): readonly ModelSpec<Api>[] | null {
|
|
1103
|
+
if (!discovered) return null;
|
|
1104
|
+
const known = new Set(getBundledModels(providerId).map(model => model.id));
|
|
1105
|
+
for (const model of discovered) known.add(model.id);
|
|
1106
|
+
const seeds = seedModels(providerId).filter(seed => !known.has(seed.id));
|
|
1107
|
+
return seeds.length === 0 ? discovered : [...discovered, ...seeds.map(seed => ({ ...seed }))];
|
|
1084
1108
|
}
|
|
1085
1109
|
|
|
1086
1110
|
/**
|
|
@@ -405,6 +405,15 @@ export function webModelManagerOptions(): ModelManagerOptions<"web-search"> {
|
|
|
405
405
|
};
|
|
406
406
|
}
|
|
407
407
|
|
|
408
|
+
/** Cloudflare Workers AI judges: the authored Clef rows; the account id resolves per request. */
|
|
409
|
+
export function cloudflareWorkersAiModelManagerOptions(): ModelManagerOptions<"workers-ai-systemone"> {
|
|
410
|
+
return {
|
|
411
|
+
providerId: "cloudflare-workers-ai",
|
|
412
|
+
cacheProviderId: resolveModelCacheProviderId("cloudflare-workers-ai"),
|
|
413
|
+
staticModels: seedModels<"workers-ai-systemone">("cloudflare-workers-ai"),
|
|
414
|
+
};
|
|
415
|
+
}
|
|
416
|
+
|
|
408
417
|
/** Credentials and endpoint overrides for the TypeSafe catalog manager. */
|
|
409
418
|
export interface TypeSafeModelManagerConfig {
|
|
410
419
|
apiKey?: string;
|
package/src/types.ts
CHANGED
|
@@ -51,6 +51,8 @@ export const RUNNER_APIS = [
|
|
|
51
51
|
"web-search",
|
|
52
52
|
"typesafe",
|
|
53
53
|
"openrouter-decisions",
|
|
54
|
+
"openai-decisions",
|
|
55
|
+
"workers-ai-systemone",
|
|
54
56
|
"openai-images",
|
|
55
57
|
"openrouter-images",
|
|
56
58
|
"xai-tts",
|
|
@@ -65,6 +67,8 @@ export const RUNNER_API_KINDS: Record<Exclude<(typeof RUNNER_APIS)[number], "loc
|
|
|
65
67
|
"web-search": "search",
|
|
66
68
|
typesafe: "judge",
|
|
67
69
|
"openrouter-decisions": "judge",
|
|
70
|
+
"openai-decisions": "judge",
|
|
71
|
+
"workers-ai-systemone": "judge",
|
|
68
72
|
"openai-images": "image",
|
|
69
73
|
"openrouter-images": "image",
|
|
70
74
|
"xai-tts": "tts",
|
|
@@ -829,6 +833,14 @@ export interface BedrockCompat {
|
|
|
829
833
|
* choices to `auto` when this is false. Default: true.
|
|
830
834
|
*/
|
|
831
835
|
supportsForcedToolChoice?: boolean;
|
|
836
|
+
/**
|
|
837
|
+
* Whether the endpoint accepts thinking-binding controls (`thinking.block_binding`,
|
|
838
|
+
* the `thinking-binding-controls-2026-08-01` beta and the `/input_transformations`
|
|
839
|
+
* response path) on prefix-bound models. Only consulted when
|
|
840
|
+
* `thinking.prefixBinding` is set; `false` omits the controls while keeping the
|
|
841
|
+
* local prefix-binding safeguards. Default: true.
|
|
842
|
+
*/
|
|
843
|
+
supportsThinkingBindingControls?: boolean;
|
|
832
844
|
}
|
|
833
845
|
|
|
834
846
|
/** Fully-resolved Bedrock Converse prompt-cache capabilities, materialized once by `buildModel`. */
|
|
@@ -844,6 +856,8 @@ export interface ResolvedBedrockCompat {
|
|
|
844
856
|
/** See {@link BedrockCompat.supportsSamplingParams}. */
|
|
845
857
|
supportsSamplingParams?: boolean;
|
|
846
858
|
supportsForcedToolChoice: boolean;
|
|
859
|
+
/** See {@link BedrockCompat.supportsThinkingBindingControls}. */
|
|
860
|
+
supportsThinkingBindingControls: boolean;
|
|
847
861
|
/**
|
|
848
862
|
* Stream-watchdog idle-timeout fallback in ms for hosts with no keepalive
|
|
849
863
|
* events; 0 disables the idle watchdog. Undefined defers to
|
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
import { isRecord } from "../utils";
|
|
2
|
-
|
|
3
1
|
/** Provider-native AI Gateway prefix before the upstream route segment. */
|
|
4
2
|
export const CLOUDFLARE_AI_GATEWAY_BASE_URL = "https://gateway.ai.cloudflare.com/v1/<account>/<gateway>";
|
|
5
3
|
/** Anthropic Messages passthrough endpoint. */
|
|
@@ -8,37 +6,3 @@ export const CLOUDFLARE_AI_GATEWAY_ANTHROPIC_BASE_URL = `${CLOUDFLARE_AI_GATEWAY
|
|
|
8
6
|
export const CLOUDFLARE_AI_GATEWAY_OPENAI_BASE_URL = `${CLOUDFLARE_AI_GATEWAY_BASE_URL}/openai`;
|
|
9
7
|
/** OpenAI-compatible Workers AI endpoint. */
|
|
10
8
|
export const CLOUDFLARE_AI_GATEWAY_COMPAT_BASE_URL = `${CLOUDFLARE_AI_GATEWAY_BASE_URL}/compat`;
|
|
11
|
-
|
|
12
|
-
/** Opaque API-key credential payload persisted by Cloudflare AI Gateway login. */
|
|
13
|
-
export interface CloudflareAiGatewayCredential {
|
|
14
|
-
token: string;
|
|
15
|
-
accountId?: string;
|
|
16
|
-
gatewayId?: string;
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
/** Parse both structured login credentials and legacy plain gateway tokens. */
|
|
20
|
-
export function parseCloudflareAiGatewayCredential(value: string): CloudflareAiGatewayCredential | null {
|
|
21
|
-
const trimmed = value.trim();
|
|
22
|
-
if (!trimmed) return null;
|
|
23
|
-
if (!trimmed.startsWith("{")) return { token: trimmed };
|
|
24
|
-
try {
|
|
25
|
-
const parsed: unknown = JSON.parse(trimmed);
|
|
26
|
-
if (!isRecord(parsed)) return null;
|
|
27
|
-
if (typeof parsed.token !== "string" || !parsed.token.trim()) return null;
|
|
28
|
-
if (parsed.accountId !== undefined && typeof parsed.accountId !== "string") return null;
|
|
29
|
-
if (parsed.gatewayId !== undefined && typeof parsed.gatewayId !== "string") return null;
|
|
30
|
-
const credential: CloudflareAiGatewayCredential = { token: parsed.token.trim() };
|
|
31
|
-
const accountId = parsed.accountId?.trim();
|
|
32
|
-
const gatewayId = parsed.gatewayId?.trim();
|
|
33
|
-
if (accountId) credential.accountId = accountId;
|
|
34
|
-
if (gatewayId) credential.gatewayId = gatewayId;
|
|
35
|
-
return credential;
|
|
36
|
-
} catch {
|
|
37
|
-
return null;
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
/** Serialize the gateway token with the routing identifiers collected during login. */
|
|
42
|
-
export function serializeCloudflareAiGatewayCredential(token: string, accountId: string, gatewayId: string): string {
|
|
43
|
-
return JSON.stringify({ token: token.trim(), accountId: accountId.trim(), gatewayId: gatewayId.trim() });
|
|
44
|
-
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { isRecord } from "../utils";
|
|
2
|
+
|
|
3
|
+
/** Cloudflare credential persisted by the AI Gateway and Workers AI logins: a bearer token plus the routing ids collected at login. */
|
|
4
|
+
export interface CloudflareCredential {
|
|
5
|
+
token: string;
|
|
6
|
+
accountId?: string;
|
|
7
|
+
gatewayId?: string;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
/** Parses a structured login credential or a legacy plain token; null when empty or malformed. */
|
|
11
|
+
export function parseCloudflareCredential(value: string): CloudflareCredential | null {
|
|
12
|
+
const trimmed = value.trim();
|
|
13
|
+
if (!trimmed) return null;
|
|
14
|
+
if (!trimmed.startsWith("{")) return { token: trimmed };
|
|
15
|
+
try {
|
|
16
|
+
const parsed: unknown = JSON.parse(trimmed);
|
|
17
|
+
if (!isRecord(parsed)) return null;
|
|
18
|
+
if (typeof parsed.token !== "string" || !parsed.token.trim()) return null;
|
|
19
|
+
if (parsed.accountId !== undefined && typeof parsed.accountId !== "string") return null;
|
|
20
|
+
if (parsed.gatewayId !== undefined && typeof parsed.gatewayId !== "string") return null;
|
|
21
|
+
const credential: CloudflareCredential = { token: parsed.token.trim() };
|
|
22
|
+
const accountId = parsed.accountId?.trim();
|
|
23
|
+
const gatewayId = parsed.gatewayId?.trim();
|
|
24
|
+
if (accountId) credential.accountId = accountId;
|
|
25
|
+
if (gatewayId) credential.gatewayId = gatewayId;
|
|
26
|
+
return credential;
|
|
27
|
+
} catch {
|
|
28
|
+
return null;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/** Serializes a login credential, trimming fields and omitting empty optional ids. */
|
|
33
|
+
export function serializeCloudflareCredential(credential: CloudflareCredential): string {
|
|
34
|
+
const serialized: CloudflareCredential = { token: credential.token.trim() };
|
|
35
|
+
const accountId = credential.accountId?.trim();
|
|
36
|
+
const gatewayId = credential.gatewayId?.trim();
|
|
37
|
+
if (accountId) serialized.accountId = accountId;
|
|
38
|
+
if (gatewayId) serialized.gatewayId = gatewayId;
|
|
39
|
+
return JSON.stringify(serialized);
|
|
40
|
+
}
|