@hebo-ai/gateway 0.6.2-rc0 → 0.6.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/README.md +3 -3
- package/dist/endpoints/chat-completions/converters.js +26 -21
- package/dist/endpoints/chat-completions/handler.js +2 -0
- package/dist/endpoints/chat-completions/otel.js +1 -1
- package/dist/endpoints/chat-completions/schema.d.ts +4 -18
- package/dist/endpoints/chat-completions/schema.js +14 -17
- package/dist/endpoints/embeddings/handler.js +2 -0
- package/dist/endpoints/embeddings/otel.js +5 -0
- package/dist/endpoints/embeddings/schema.d.ts +6 -0
- package/dist/endpoints/embeddings/schema.js +4 -1
- package/dist/endpoints/models/converters.js +3 -3
- package/dist/lifecycle.js +2 -2
- package/dist/logger/default.js +3 -3
- package/dist/logger/index.d.ts +2 -5
- package/dist/middleware/common.js +1 -0
- package/dist/middleware/utils.js +0 -3
- package/dist/models/amazon/middleware.js +8 -5
- package/dist/models/anthropic/middleware.js +13 -13
- package/dist/models/catalog.js +5 -1
- package/dist/models/cohere/middleware.js +7 -5
- package/dist/models/google/middleware.d.ts +1 -1
- package/dist/models/google/middleware.js +29 -25
- package/dist/models/openai/middleware.js +13 -9
- package/dist/models/voyage/middleware.js +2 -1
- package/dist/providers/bedrock/middleware.js +21 -23
- package/dist/providers/registry.js +3 -0
- package/dist/telemetry/fetch.js +7 -2
- package/dist/telemetry/gen-ai.js +15 -12
- package/dist/telemetry/memory.d.ts +1 -1
- package/dist/telemetry/memory.js +30 -14
- package/dist/telemetry/span.js +1 -1
- package/dist/telemetry/stream.js +30 -23
- package/dist/utils/env.js +4 -2
- package/dist/utils/preset.js +1 -0
- package/dist/utils/response.js +3 -1
- package/package.json +36 -50
- package/src/config.ts +0 -98
- package/src/endpoints/chat-completions/converters.test.ts +0 -631
- package/src/endpoints/chat-completions/converters.ts +0 -899
- package/src/endpoints/chat-completions/handler.test.ts +0 -391
- package/src/endpoints/chat-completions/handler.ts +0 -201
- package/src/endpoints/chat-completions/index.ts +0 -4
- package/src/endpoints/chat-completions/otel.test.ts +0 -315
- package/src/endpoints/chat-completions/otel.ts +0 -214
- package/src/endpoints/chat-completions/schema.ts +0 -364
- package/src/endpoints/embeddings/converters.ts +0 -51
- package/src/endpoints/embeddings/handler.test.ts +0 -133
- package/src/endpoints/embeddings/handler.ts +0 -137
- package/src/endpoints/embeddings/index.ts +0 -4
- package/src/endpoints/embeddings/otel.ts +0 -40
- package/src/endpoints/embeddings/schema.ts +0 -36
- package/src/endpoints/models/converters.ts +0 -56
- package/src/endpoints/models/handler.test.ts +0 -122
- package/src/endpoints/models/handler.ts +0 -37
- package/src/endpoints/models/index.ts +0 -3
- package/src/endpoints/models/schema.ts +0 -37
- package/src/errors/ai-sdk.ts +0 -99
- package/src/errors/gateway.ts +0 -17
- package/src/errors/openai.ts +0 -57
- package/src/errors/utils.ts +0 -47
- package/src/gateway.ts +0 -50
- package/src/index.ts +0 -19
- package/src/lifecycle.ts +0 -135
- package/src/logger/default.ts +0 -105
- package/src/logger/index.ts +0 -42
- package/src/middleware/common.test.ts +0 -215
- package/src/middleware/common.ts +0 -163
- package/src/middleware/debug.ts +0 -37
- package/src/middleware/matcher.ts +0 -161
- package/src/middleware/utils.ts +0 -34
- package/src/models/amazon/index.ts +0 -2
- package/src/models/amazon/middleware.test.ts +0 -133
- package/src/models/amazon/middleware.ts +0 -79
- package/src/models/amazon/presets.ts +0 -104
- package/src/models/anthropic/index.ts +0 -2
- package/src/models/anthropic/middleware.test.ts +0 -643
- package/src/models/anthropic/middleware.ts +0 -148
- package/src/models/anthropic/presets.ts +0 -191
- package/src/models/catalog.ts +0 -13
- package/src/models/cohere/index.ts +0 -2
- package/src/models/cohere/middleware.test.ts +0 -138
- package/src/models/cohere/middleware.ts +0 -76
- package/src/models/cohere/presets.ts +0 -186
- package/src/models/google/index.ts +0 -2
- package/src/models/google/middleware.test.ts +0 -298
- package/src/models/google/middleware.ts +0 -137
- package/src/models/google/presets.ts +0 -118
- package/src/models/meta/index.ts +0 -1
- package/src/models/meta/presets.ts +0 -143
- package/src/models/openai/index.ts +0 -2
- package/src/models/openai/middleware.test.ts +0 -189
- package/src/models/openai/middleware.ts +0 -103
- package/src/models/openai/presets.ts +0 -280
- package/src/models/types.ts +0 -114
- package/src/models/voyage/index.ts +0 -2
- package/src/models/voyage/middleware.test.ts +0 -28
- package/src/models/voyage/middleware.ts +0 -23
- package/src/models/voyage/presets.ts +0 -126
- package/src/providers/anthropic/canonical.ts +0 -17
- package/src/providers/anthropic/index.ts +0 -1
- package/src/providers/bedrock/canonical.ts +0 -87
- package/src/providers/bedrock/index.ts +0 -2
- package/src/providers/bedrock/middleware.test.ts +0 -303
- package/src/providers/bedrock/middleware.ts +0 -128
- package/src/providers/cohere/canonical.ts +0 -26
- package/src/providers/cohere/index.ts +0 -1
- package/src/providers/groq/canonical.ts +0 -21
- package/src/providers/groq/index.ts +0 -1
- package/src/providers/openai/canonical.ts +0 -16
- package/src/providers/openai/index.ts +0 -1
- package/src/providers/registry.test.ts +0 -44
- package/src/providers/registry.ts +0 -165
- package/src/providers/types.ts +0 -20
- package/src/providers/vertex/canonical.ts +0 -17
- package/src/providers/vertex/index.ts +0 -1
- package/src/providers/voyage/canonical.ts +0 -16
- package/src/providers/voyage/index.ts +0 -1
- package/src/telemetry/ai-sdk.ts +0 -46
- package/src/telemetry/baggage.ts +0 -27
- package/src/telemetry/fetch.ts +0 -62
- package/src/telemetry/gen-ai.ts +0 -113
- package/src/telemetry/http.ts +0 -62
- package/src/telemetry/index.ts +0 -1
- package/src/telemetry/memory.ts +0 -36
- package/src/telemetry/span.ts +0 -85
- package/src/telemetry/stream.ts +0 -64
- package/src/types.ts +0 -223
- package/src/utils/env.ts +0 -7
- package/src/utils/headers.ts +0 -27
- package/src/utils/preset.ts +0 -65
- package/src/utils/request.test.ts +0 -75
- package/src/utils/request.ts +0 -52
- package/src/utils/response.ts +0 -84
- package/src/utils/url.ts +0 -26
|
@@ -1,148 +0,0 @@
|
|
|
1
|
-
import type { LanguageModelMiddleware } from "ai";
|
|
2
|
-
|
|
3
|
-
import type {
|
|
4
|
-
ChatCompletionsCacheControl,
|
|
5
|
-
ChatCompletionsReasoningConfig,
|
|
6
|
-
ChatCompletionsReasoningEffort,
|
|
7
|
-
} from "../../endpoints/chat-completions/schema";
|
|
8
|
-
|
|
9
|
-
import { modelMiddlewareMatcher } from "../../middleware/matcher";
|
|
10
|
-
import { calculateReasoningBudgetFromEffort } from "../../middleware/utils";
|
|
11
|
-
|
|
12
|
-
const isClaude = (family: "opus" | "sonnet" | "haiku", version: string) => {
|
|
13
|
-
const dashed = version.replace(".", "-");
|
|
14
|
-
|
|
15
|
-
return (modelId: string) =>
|
|
16
|
-
modelId.includes(`claude-${family}-${version}`) ||
|
|
17
|
-
modelId.includes(`claude-${family}-${dashed}`);
|
|
18
|
-
};
|
|
19
|
-
|
|
20
|
-
const isClaude4 = (modelId: string) => modelId.includes("claude-") && modelId.includes("-4");
|
|
21
|
-
|
|
22
|
-
const isOpus46 = isClaude("opus", "4.6");
|
|
23
|
-
const isOpus45 = isClaude("opus", "4.5");
|
|
24
|
-
const isOpus4 = isClaude("opus", "4");
|
|
25
|
-
const isSonnet46 = isClaude("sonnet", "4.6");
|
|
26
|
-
|
|
27
|
-
export function mapClaudeReasoningEffort(effort: ChatCompletionsReasoningEffort, modelId: string) {
|
|
28
|
-
if (isOpus46(modelId)) {
|
|
29
|
-
switch (effort) {
|
|
30
|
-
case "none":
|
|
31
|
-
case "minimal":
|
|
32
|
-
case "low":
|
|
33
|
-
return "low";
|
|
34
|
-
case "medium":
|
|
35
|
-
return "medium";
|
|
36
|
-
case "high":
|
|
37
|
-
return "high";
|
|
38
|
-
case "xhigh":
|
|
39
|
-
case "max":
|
|
40
|
-
return "max";
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
switch (effort) {
|
|
45
|
-
case "none":
|
|
46
|
-
case "minimal":
|
|
47
|
-
case "low":
|
|
48
|
-
return "low";
|
|
49
|
-
case "medium":
|
|
50
|
-
return "medium";
|
|
51
|
-
case "high":
|
|
52
|
-
case "xhigh":
|
|
53
|
-
case "max":
|
|
54
|
-
return "high";
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
function getMaxOutputTokens(modelId: string): number {
|
|
59
|
-
if (isOpus46(modelId)) return 128_000;
|
|
60
|
-
if (isOpus45(modelId)) return 64_000;
|
|
61
|
-
if (isOpus4(modelId)) return 32_000;
|
|
62
|
-
return 64_000;
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
// Documentation:
|
|
66
|
-
// https://platform.claude.com/docs/en/build-with-claude/effort
|
|
67
|
-
// https://platform.claude.com/docs/en/build-with-claude/extended-thinking
|
|
68
|
-
// https://platform.claude.com/docs/en/build-with-claude/adaptive-thinking
|
|
69
|
-
export const claudeReasoningMiddleware: LanguageModelMiddleware = {
|
|
70
|
-
specificationVersion: "v3",
|
|
71
|
-
// oxlint-disable-next-line require-await
|
|
72
|
-
transformParams: async ({ params, model }) => {
|
|
73
|
-
const unknown = params.providerOptions?.["unknown"];
|
|
74
|
-
if (!unknown) return params;
|
|
75
|
-
|
|
76
|
-
const reasoning = unknown["reasoning"] as ChatCompletionsReasoningConfig;
|
|
77
|
-
if (!reasoning) return params;
|
|
78
|
-
|
|
79
|
-
const target = (params.providerOptions!["anthropic"] ??= {});
|
|
80
|
-
const modelId = model.modelId;
|
|
81
|
-
const clampedMaxTokens =
|
|
82
|
-
reasoning.max_tokens && Math.min(reasoning.max_tokens, getMaxOutputTokens(modelId));
|
|
83
|
-
|
|
84
|
-
if (!reasoning.enabled) {
|
|
85
|
-
target["thinking"] = { type: "disabled" };
|
|
86
|
-
} else if (reasoning.effort) {
|
|
87
|
-
if (isClaude4(modelId)) {
|
|
88
|
-
target["effort"] = mapClaudeReasoningEffort(reasoning.effort, modelId);
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
if (isOpus46(modelId)) {
|
|
92
|
-
target["thinking"] = clampedMaxTokens
|
|
93
|
-
? { type: "adaptive", budgetTokens: clampedMaxTokens }
|
|
94
|
-
: { type: "adaptive" };
|
|
95
|
-
} else if (isSonnet46(modelId)) {
|
|
96
|
-
target["thinking"] = clampedMaxTokens
|
|
97
|
-
? { type: "enabled", budgetTokens: clampedMaxTokens }
|
|
98
|
-
: { type: "adaptive" };
|
|
99
|
-
} else {
|
|
100
|
-
target["thinking"] = { type: "enabled" };
|
|
101
|
-
if (clampedMaxTokens) {
|
|
102
|
-
target["thinking"]["budgetTokens"] = clampedMaxTokens;
|
|
103
|
-
} else {
|
|
104
|
-
// FUTURE: warn that reasoning.max_tokens was computed
|
|
105
|
-
target["thinking"]["budgetTokens"] = calculateReasoningBudgetFromEffort(
|
|
106
|
-
reasoning.effort,
|
|
107
|
-
params.maxOutputTokens ?? getMaxOutputTokens(modelId),
|
|
108
|
-
1024,
|
|
109
|
-
);
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
} else if (clampedMaxTokens) {
|
|
113
|
-
target["thinking"] = {
|
|
114
|
-
type: "enabled",
|
|
115
|
-
budgetTokens: clampedMaxTokens,
|
|
116
|
-
};
|
|
117
|
-
} else {
|
|
118
|
-
target["thinking"] = { type: "enabled" };
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
delete unknown["reasoning"];
|
|
122
|
-
|
|
123
|
-
return params;
|
|
124
|
-
},
|
|
125
|
-
};
|
|
126
|
-
|
|
127
|
-
// https://platform.claude.com/docs/en/build-with-claude/prompt-caching
|
|
128
|
-
export const claudePromptCachingMiddleware: LanguageModelMiddleware = {
|
|
129
|
-
specificationVersion: "v3",
|
|
130
|
-
// oxlint-disable-next-line require-await
|
|
131
|
-
transformParams: async ({ params }) => {
|
|
132
|
-
const unknown = params.providerOptions?.["unknown"];
|
|
133
|
-
if (!unknown) return params;
|
|
134
|
-
|
|
135
|
-
const cacheControl = unknown["cache_control"] as ChatCompletionsCacheControl;
|
|
136
|
-
if (cacheControl) {
|
|
137
|
-
(params.providerOptions!["anthropic"] ??= {})["cacheControl"] = cacheControl;
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
delete unknown["cache_control"];
|
|
141
|
-
|
|
142
|
-
return params;
|
|
143
|
-
},
|
|
144
|
-
};
|
|
145
|
-
|
|
146
|
-
modelMiddlewareMatcher.useForModel(["anthropic/claude-*3*7*", "anthropic/claude-*4*"], {
|
|
147
|
-
language: [claudeReasoningMiddleware, claudePromptCachingMiddleware],
|
|
148
|
-
});
|
|
@@ -1,191 +0,0 @@
|
|
|
1
|
-
import type { CanonicalProviderId } from "../../providers/types";
|
|
2
|
-
import type { CanonicalModelId, CatalogModel } from "../types";
|
|
3
|
-
|
|
4
|
-
import { presetFor, type DeepPartial } from "../../utils/preset";
|
|
5
|
-
|
|
6
|
-
const CLAUDE_BASE = {
|
|
7
|
-
modalities: {
|
|
8
|
-
input: ["text", "image", "file"] as const,
|
|
9
|
-
output: ["text"] as const,
|
|
10
|
-
},
|
|
11
|
-
capabilities: ["attachments", "tool_call", "structured_output", "temperature"],
|
|
12
|
-
context: 200000,
|
|
13
|
-
providers: ["anthropic", "bedrock", "vertex"] as const satisfies readonly CanonicalProviderId[],
|
|
14
|
-
} satisfies DeepPartial<CatalogModel>;
|
|
15
|
-
|
|
16
|
-
const CLAUDE_PDF_MODALITIES = {
|
|
17
|
-
modalities: {
|
|
18
|
-
input: ["text", "image", "pdf", "file"] as const,
|
|
19
|
-
output: ["text"] as const,
|
|
20
|
-
},
|
|
21
|
-
} satisfies DeepPartial<CatalogModel>;
|
|
22
|
-
|
|
23
|
-
export const claudeHaiku45 = presetFor<CanonicalModelId, CatalogModel>()(
|
|
24
|
-
"anthropic/claude-haiku-4.5" as const,
|
|
25
|
-
{
|
|
26
|
-
...CLAUDE_BASE,
|
|
27
|
-
...CLAUDE_PDF_MODALITIES,
|
|
28
|
-
name: "Claude Haiku 4.5",
|
|
29
|
-
capabilities: [...CLAUDE_BASE.capabilities, "reasoning"],
|
|
30
|
-
created: "2025-10-01",
|
|
31
|
-
knowledge: "2025-07",
|
|
32
|
-
} satisfies DeepPartial<CatalogModel>,
|
|
33
|
-
);
|
|
34
|
-
|
|
35
|
-
export const claudeHaiku35 = presetFor<CanonicalModelId, CatalogModel>()(
|
|
36
|
-
"anthropic/claude-haiku-3.5" as const,
|
|
37
|
-
{
|
|
38
|
-
...CLAUDE_BASE,
|
|
39
|
-
...CLAUDE_PDF_MODALITIES,
|
|
40
|
-
name: "Claude Haiku 3.5",
|
|
41
|
-
created: "2024-10-22",
|
|
42
|
-
knowledge: "2024-07",
|
|
43
|
-
} satisfies DeepPartial<CatalogModel>,
|
|
44
|
-
);
|
|
45
|
-
|
|
46
|
-
export const claudeHaiku3 = presetFor<CanonicalModelId, CatalogModel>()(
|
|
47
|
-
"anthropic/claude-haiku-3" as const,
|
|
48
|
-
{
|
|
49
|
-
...CLAUDE_BASE,
|
|
50
|
-
name: "Claude Haiku 3",
|
|
51
|
-
created: "2024-03-07",
|
|
52
|
-
knowledge: "2023-08",
|
|
53
|
-
} satisfies DeepPartial<CatalogModel>,
|
|
54
|
-
);
|
|
55
|
-
|
|
56
|
-
export const claudeSonnet45 = presetFor<CanonicalModelId, CatalogModel>()(
|
|
57
|
-
"anthropic/claude-sonnet-4.5" as const,
|
|
58
|
-
{
|
|
59
|
-
...CLAUDE_BASE,
|
|
60
|
-
...CLAUDE_PDF_MODALITIES,
|
|
61
|
-
name: "Claude Sonnet 4.5",
|
|
62
|
-
capabilities: [...CLAUDE_BASE.capabilities, "reasoning"],
|
|
63
|
-
created: "2025-09-29",
|
|
64
|
-
knowledge: "2025-07",
|
|
65
|
-
} satisfies DeepPartial<CatalogModel>,
|
|
66
|
-
);
|
|
67
|
-
|
|
68
|
-
export const claudeSonnet46 = presetFor<CanonicalModelId, CatalogModel>()(
|
|
69
|
-
"anthropic/claude-sonnet-4.6" as const,
|
|
70
|
-
{
|
|
71
|
-
...CLAUDE_BASE,
|
|
72
|
-
...CLAUDE_PDF_MODALITIES,
|
|
73
|
-
name: "Claude Sonnet 4.6",
|
|
74
|
-
capabilities: [...CLAUDE_BASE.capabilities, "reasoning"],
|
|
75
|
-
created: "2026-02-17",
|
|
76
|
-
knowledge: "2025-08",
|
|
77
|
-
} satisfies DeepPartial<CatalogModel>,
|
|
78
|
-
);
|
|
79
|
-
|
|
80
|
-
export const claudeSonnet4 = presetFor<CanonicalModelId, CatalogModel>()(
|
|
81
|
-
"anthropic/claude-sonnet-4" as const,
|
|
82
|
-
{
|
|
83
|
-
...CLAUDE_BASE,
|
|
84
|
-
...CLAUDE_PDF_MODALITIES,
|
|
85
|
-
name: "Claude Sonnet 4",
|
|
86
|
-
capabilities: [...CLAUDE_BASE.capabilities, "reasoning"],
|
|
87
|
-
created: "2025-05-14",
|
|
88
|
-
knowledge: "2025-03",
|
|
89
|
-
} satisfies DeepPartial<CatalogModel>,
|
|
90
|
-
);
|
|
91
|
-
|
|
92
|
-
export const claudeSonnet37 = presetFor<CanonicalModelId, CatalogModel>()(
|
|
93
|
-
"anthropic/claude-sonnet-3.7" as const,
|
|
94
|
-
{
|
|
95
|
-
...CLAUDE_BASE,
|
|
96
|
-
...CLAUDE_PDF_MODALITIES,
|
|
97
|
-
name: "Claude Sonnet 3.7",
|
|
98
|
-
capabilities: [...CLAUDE_BASE.capabilities, "reasoning"],
|
|
99
|
-
created: "2025-02-19",
|
|
100
|
-
knowledge: "2024-10",
|
|
101
|
-
} satisfies DeepPartial<CatalogModel>,
|
|
102
|
-
);
|
|
103
|
-
|
|
104
|
-
export const claudeSonnet35 = presetFor<CanonicalModelId, CatalogModel>()(
|
|
105
|
-
"anthropic/claude-sonnet-3.5" as const,
|
|
106
|
-
{
|
|
107
|
-
...CLAUDE_BASE,
|
|
108
|
-
...CLAUDE_PDF_MODALITIES,
|
|
109
|
-
name: "Claude Sonnet 3.5",
|
|
110
|
-
created: "2024-10-22",
|
|
111
|
-
knowledge: "2024-04",
|
|
112
|
-
} satisfies DeepPartial<CatalogModel>,
|
|
113
|
-
);
|
|
114
|
-
|
|
115
|
-
export const claudeOpus45 = presetFor<CanonicalModelId, CatalogModel>()(
|
|
116
|
-
"anthropic/claude-opus-4.5" as const,
|
|
117
|
-
{
|
|
118
|
-
...CLAUDE_BASE,
|
|
119
|
-
...CLAUDE_PDF_MODALITIES,
|
|
120
|
-
name: "Claude Opus 4.5",
|
|
121
|
-
capabilities: [...CLAUDE_BASE.capabilities, "reasoning"],
|
|
122
|
-
created: "2025-11-01",
|
|
123
|
-
knowledge: "2025-05",
|
|
124
|
-
} satisfies DeepPartial<CatalogModel>,
|
|
125
|
-
);
|
|
126
|
-
|
|
127
|
-
export const claudeOpus46 = presetFor<CanonicalModelId, CatalogModel>()(
|
|
128
|
-
"anthropic/claude-opus-4.6" as const,
|
|
129
|
-
{
|
|
130
|
-
...CLAUDE_BASE,
|
|
131
|
-
...CLAUDE_PDF_MODALITIES,
|
|
132
|
-
name: "Claude Opus 4.6",
|
|
133
|
-
capabilities: [...CLAUDE_BASE.capabilities, "reasoning"],
|
|
134
|
-
created: "2026-02-05",
|
|
135
|
-
knowledge: "2025-05",
|
|
136
|
-
} satisfies DeepPartial<CatalogModel>,
|
|
137
|
-
);
|
|
138
|
-
|
|
139
|
-
export const claudeOpus41 = presetFor<CanonicalModelId, CatalogModel>()(
|
|
140
|
-
"anthropic/claude-opus-4.1" as const,
|
|
141
|
-
{
|
|
142
|
-
...CLAUDE_BASE,
|
|
143
|
-
...CLAUDE_PDF_MODALITIES,
|
|
144
|
-
name: "Claude Opus 4.1",
|
|
145
|
-
capabilities: [...CLAUDE_BASE.capabilities, "reasoning"],
|
|
146
|
-
created: "2025-08-05",
|
|
147
|
-
knowledge: "2025-03",
|
|
148
|
-
} satisfies DeepPartial<CatalogModel>,
|
|
149
|
-
);
|
|
150
|
-
|
|
151
|
-
export const claudeOpus4 = presetFor<CanonicalModelId, CatalogModel>()(
|
|
152
|
-
"anthropic/claude-opus-4" as const,
|
|
153
|
-
{
|
|
154
|
-
...CLAUDE_BASE,
|
|
155
|
-
...CLAUDE_PDF_MODALITIES,
|
|
156
|
-
name: "Claude Opus 4",
|
|
157
|
-
capabilities: [...CLAUDE_BASE.capabilities, "reasoning"],
|
|
158
|
-
created: "2025-05-14",
|
|
159
|
-
knowledge: "2025-03",
|
|
160
|
-
} satisfies DeepPartial<CatalogModel>,
|
|
161
|
-
);
|
|
162
|
-
|
|
163
|
-
const claudeAtomic = {
|
|
164
|
-
"v4.6": [claudeSonnet46, claudeOpus46],
|
|
165
|
-
"v4.5": [claudeHaiku45, claudeSonnet45, claudeOpus45],
|
|
166
|
-
"v4.1": [claudeOpus41],
|
|
167
|
-
v4: [claudeSonnet4, claudeOpus4],
|
|
168
|
-
"v3.7": [claudeSonnet37],
|
|
169
|
-
"v3.5": [claudeSonnet35, claudeHaiku35],
|
|
170
|
-
v3: [claudeHaiku3],
|
|
171
|
-
haiku: [claudeHaiku45, claudeHaiku35, claudeHaiku3],
|
|
172
|
-
sonnet: [claudeSonnet46, claudeSonnet45, claudeSonnet4, claudeSonnet37, claudeSonnet35],
|
|
173
|
-
opus: [claudeOpus46, claudeOpus45, claudeOpus41, claudeOpus4],
|
|
174
|
-
} as const;
|
|
175
|
-
|
|
176
|
-
const claudeGroups = {
|
|
177
|
-
"v4.x": [
|
|
178
|
-
...claudeAtomic["v4.6"],
|
|
179
|
-
...claudeAtomic["v4.5"],
|
|
180
|
-
...claudeAtomic["v4.1"],
|
|
181
|
-
...claudeAtomic["v4"],
|
|
182
|
-
],
|
|
183
|
-
"v3.x": [...claudeAtomic["v3.7"], ...claudeAtomic["v3.5"], ...claudeAtomic["v3"]],
|
|
184
|
-
} as const;
|
|
185
|
-
|
|
186
|
-
export const claude = {
|
|
187
|
-
...claudeAtomic,
|
|
188
|
-
...claudeGroups,
|
|
189
|
-
latest: [...claudeAtomic["v4.6"]],
|
|
190
|
-
all: Object.values(claudeAtomic).flat(),
|
|
191
|
-
} as const;
|
package/src/models/catalog.ts
DELETED
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import type { ModelCatalog } from "./types";
|
|
2
|
-
|
|
3
|
-
type ModelCatalogInput =
|
|
4
|
-
| ModelCatalog
|
|
5
|
-
| (() => ModelCatalog)
|
|
6
|
-
| ModelCatalog[]
|
|
7
|
-
| (() => ModelCatalog)[];
|
|
8
|
-
|
|
9
|
-
export function defineModelCatalog(...inputs: ModelCatalogInput[]): ModelCatalog {
|
|
10
|
-
const catalogs = inputs.flat().map((input) => (typeof input === "function" ? input() : input));
|
|
11
|
-
|
|
12
|
-
return Object.assign({}, ...catalogs);
|
|
13
|
-
}
|
|
@@ -1,138 +0,0 @@
|
|
|
1
|
-
import { MockLanguageModelV3 } from "ai/test";
|
|
2
|
-
import { expect, test } from "bun:test";
|
|
3
|
-
|
|
4
|
-
import { modelMiddlewareMatcher } from "../../middleware/matcher";
|
|
5
|
-
import { CANONICAL_MODEL_IDS } from "../../models/types";
|
|
6
|
-
import { cohereDimensionsMiddleware, cohereReasoningMiddleware } from "./middleware";
|
|
7
|
-
|
|
8
|
-
test("cohere middleware > matching patterns", () => {
|
|
9
|
-
const languageMatching = [
|
|
10
|
-
"cohere/command-a-reasoning",
|
|
11
|
-
] satisfies (typeof CANONICAL_MODEL_IDS)[number][];
|
|
12
|
-
|
|
13
|
-
const languageNonMatching = [
|
|
14
|
-
"cohere/command-a",
|
|
15
|
-
"cohere/command-r-plus",
|
|
16
|
-
] satisfies (typeof CANONICAL_MODEL_IDS)[number][];
|
|
17
|
-
|
|
18
|
-
for (const id of languageMatching) {
|
|
19
|
-
const middleware = modelMiddlewareMatcher.resolve({ kind: "text", modelId: id });
|
|
20
|
-
expect(middleware).toContain(cohereReasoningMiddleware);
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
for (const id of languageNonMatching) {
|
|
24
|
-
const middleware = modelMiddlewareMatcher.resolve({ kind: "text", modelId: id });
|
|
25
|
-
expect(middleware).not.toContain(cohereReasoningMiddleware);
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
const embeddingMatching = [
|
|
29
|
-
"cohere/embed-v4.0",
|
|
30
|
-
"cohere/embed-english-v3.0",
|
|
31
|
-
] satisfies (typeof CANONICAL_MODEL_IDS)[number][];
|
|
32
|
-
|
|
33
|
-
const embeddingNonMatching = [
|
|
34
|
-
"cohere/command-a",
|
|
35
|
-
] satisfies (typeof CANONICAL_MODEL_IDS)[number][];
|
|
36
|
-
|
|
37
|
-
for (const id of embeddingMatching) {
|
|
38
|
-
const middleware = modelMiddlewareMatcher.resolve({ kind: "embedding", modelId: id });
|
|
39
|
-
expect(middleware).toContain(cohereDimensionsMiddleware);
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
for (const id of embeddingNonMatching) {
|
|
43
|
-
const middleware = modelMiddlewareMatcher.resolve({ kind: "embedding", modelId: id });
|
|
44
|
-
expect(middleware).not.toContain(cohereDimensionsMiddleware);
|
|
45
|
-
}
|
|
46
|
-
});
|
|
47
|
-
|
|
48
|
-
test("cohereReasoningMiddleware > should map effort to thinking budget", async () => {
|
|
49
|
-
const params = {
|
|
50
|
-
prompt: [],
|
|
51
|
-
maxOutputTokens: 2000,
|
|
52
|
-
providerOptions: {
|
|
53
|
-
unknown: {
|
|
54
|
-
reasoning: { enabled: true, effort: "medium" },
|
|
55
|
-
},
|
|
56
|
-
},
|
|
57
|
-
};
|
|
58
|
-
|
|
59
|
-
const result = await cohereReasoningMiddleware.transformParams!({
|
|
60
|
-
type: "generate",
|
|
61
|
-
params,
|
|
62
|
-
model: new MockLanguageModelV3(),
|
|
63
|
-
});
|
|
64
|
-
|
|
65
|
-
expect(result).toEqual({
|
|
66
|
-
prompt: [],
|
|
67
|
-
maxOutputTokens: 2000,
|
|
68
|
-
providerOptions: {
|
|
69
|
-
cohere: {
|
|
70
|
-
thinking: {
|
|
71
|
-
type: "enabled",
|
|
72
|
-
tokenBudget: 1024,
|
|
73
|
-
},
|
|
74
|
-
},
|
|
75
|
-
unknown: {},
|
|
76
|
-
},
|
|
77
|
-
});
|
|
78
|
-
});
|
|
79
|
-
|
|
80
|
-
test("cohereReasoningMiddleware > should disable reasoning when requested", async () => {
|
|
81
|
-
const params = {
|
|
82
|
-
prompt: [],
|
|
83
|
-
providerOptions: {
|
|
84
|
-
unknown: {
|
|
85
|
-
reasoning: { enabled: false },
|
|
86
|
-
},
|
|
87
|
-
},
|
|
88
|
-
};
|
|
89
|
-
|
|
90
|
-
const result = await cohereReasoningMiddleware.transformParams!({
|
|
91
|
-
type: "generate",
|
|
92
|
-
params,
|
|
93
|
-
model: new MockLanguageModelV3(),
|
|
94
|
-
});
|
|
95
|
-
|
|
96
|
-
expect(result).toEqual({
|
|
97
|
-
prompt: [],
|
|
98
|
-
providerOptions: {
|
|
99
|
-
cohere: {
|
|
100
|
-
thinking: {
|
|
101
|
-
type: "disabled",
|
|
102
|
-
},
|
|
103
|
-
},
|
|
104
|
-
unknown: {},
|
|
105
|
-
},
|
|
106
|
-
});
|
|
107
|
-
});
|
|
108
|
-
|
|
109
|
-
test("cohereReasoningMiddleware > should default reasoning budget when enabled without effort", async () => {
|
|
110
|
-
const params = {
|
|
111
|
-
prompt: [],
|
|
112
|
-
maxOutputTokens: 4000,
|
|
113
|
-
providerOptions: {
|
|
114
|
-
unknown: {
|
|
115
|
-
reasoning: { enabled: true },
|
|
116
|
-
},
|
|
117
|
-
},
|
|
118
|
-
};
|
|
119
|
-
|
|
120
|
-
const result = await cohereReasoningMiddleware.transformParams!({
|
|
121
|
-
type: "generate",
|
|
122
|
-
params,
|
|
123
|
-
model: new MockLanguageModelV3(),
|
|
124
|
-
});
|
|
125
|
-
|
|
126
|
-
expect(result).toEqual({
|
|
127
|
-
prompt: [],
|
|
128
|
-
maxOutputTokens: 4000,
|
|
129
|
-
providerOptions: {
|
|
130
|
-
cohere: {
|
|
131
|
-
thinking: {
|
|
132
|
-
type: "enabled",
|
|
133
|
-
},
|
|
134
|
-
},
|
|
135
|
-
unknown: {},
|
|
136
|
-
},
|
|
137
|
-
});
|
|
138
|
-
});
|
|
@@ -1,76 +0,0 @@
|
|
|
1
|
-
import type { EmbeddingModelMiddleware, LanguageModelMiddleware } from "ai";
|
|
2
|
-
|
|
3
|
-
import type { ChatCompletionsReasoningConfig } from "../../endpoints/chat-completions/schema";
|
|
4
|
-
|
|
5
|
-
import { modelMiddlewareMatcher } from "../../middleware/matcher";
|
|
6
|
-
import { calculateReasoningBudgetFromEffort } from "../../middleware/utils";
|
|
7
|
-
|
|
8
|
-
// Convert `dimensions` (OpenAI) to `outputDimension` (Cohere)
|
|
9
|
-
export const cohereDimensionsMiddleware: EmbeddingModelMiddleware = {
|
|
10
|
-
specificationVersion: "v3",
|
|
11
|
-
// oxlint-disable-next-line require-await
|
|
12
|
-
transformParams: async ({ params, model }) => {
|
|
13
|
-
const unknown = params.providerOptions?.["unknown"];
|
|
14
|
-
if (!unknown) return params;
|
|
15
|
-
|
|
16
|
-
const modelId = model.modelId;
|
|
17
|
-
if (
|
|
18
|
-
modelId.includes("cohere/embed-english-light") ||
|
|
19
|
-
modelId.includes("cohere/embed-multilingual-light")
|
|
20
|
-
) {
|
|
21
|
-
delete unknown["dimensions"];
|
|
22
|
-
return params;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
const dimensions = unknown["dimensions"] as number;
|
|
26
|
-
if (!dimensions) return params;
|
|
27
|
-
|
|
28
|
-
(params.providerOptions!["cohere"] ??= {})["outputDimension"] = dimensions;
|
|
29
|
-
delete unknown["dimensions"];
|
|
30
|
-
|
|
31
|
-
return params;
|
|
32
|
-
},
|
|
33
|
-
};
|
|
34
|
-
|
|
35
|
-
const COHERE_MAX_OUTPUT_TOKENS = 32000;
|
|
36
|
-
export const cohereReasoningMiddleware: LanguageModelMiddleware = {
|
|
37
|
-
specificationVersion: "v3",
|
|
38
|
-
// oxlint-disable-next-line require-await
|
|
39
|
-
transformParams: async ({ params }) => {
|
|
40
|
-
const unknown = params.providerOptions?.["unknown"];
|
|
41
|
-
if (!unknown) return params;
|
|
42
|
-
|
|
43
|
-
const reasoning = unknown["reasoning"] as ChatCompletionsReasoningConfig;
|
|
44
|
-
if (!reasoning) return params;
|
|
45
|
-
|
|
46
|
-
const target = (params.providerOptions!["cohere"] ??= {});
|
|
47
|
-
|
|
48
|
-
if (!reasoning.enabled) {
|
|
49
|
-
target["thinking"] = { type: "disabled" };
|
|
50
|
-
} else if (reasoning.max_tokens) {
|
|
51
|
-
target["thinking"] = { type: "enabled", tokenBudget: reasoning.max_tokens };
|
|
52
|
-
} else if (reasoning.effort) {
|
|
53
|
-
// FUTURE: warn that reasoning.max_tokens was computed
|
|
54
|
-
target["thinking"] = {
|
|
55
|
-
type: "enabled",
|
|
56
|
-
tokenBudget: calculateReasoningBudgetFromEffort(
|
|
57
|
-
reasoning.effort,
|
|
58
|
-
params.maxOutputTokens ?? COHERE_MAX_OUTPUT_TOKENS,
|
|
59
|
-
1024,
|
|
60
|
-
),
|
|
61
|
-
};
|
|
62
|
-
} else {
|
|
63
|
-
target["thinking"] = { type: "enabled" };
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
delete unknown["reasoning"];
|
|
67
|
-
|
|
68
|
-
return params;
|
|
69
|
-
},
|
|
70
|
-
};
|
|
71
|
-
|
|
72
|
-
modelMiddlewareMatcher.useForModel("cohere/embed-*", { embedding: [cohereDimensionsMiddleware] });
|
|
73
|
-
|
|
74
|
-
modelMiddlewareMatcher.useForModel("cohere/command-a-reasoning", {
|
|
75
|
-
language: [cohereReasoningMiddleware],
|
|
76
|
-
});
|