@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,118 +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 GEMINI_BASE = {
|
|
7
|
-
modalities: {
|
|
8
|
-
input: ["text", "image", "pdf", "file", "audio", "video"] as const,
|
|
9
|
-
output: ["text"] as const,
|
|
10
|
-
},
|
|
11
|
-
capabilities: [
|
|
12
|
-
"attachments",
|
|
13
|
-
"reasoning",
|
|
14
|
-
"tool_call",
|
|
15
|
-
"structured_output",
|
|
16
|
-
"temperature",
|
|
17
|
-
] as const,
|
|
18
|
-
context: 1048576,
|
|
19
|
-
providers: ["vertex"] as const satisfies readonly CanonicalProviderId[],
|
|
20
|
-
} satisfies DeepPartial<CatalogModel>;
|
|
21
|
-
|
|
22
|
-
const GEMINI_EMBEDDINGS_BASE = {
|
|
23
|
-
modalities: {
|
|
24
|
-
input: ["text"] as const,
|
|
25
|
-
output: ["embedding"] as const,
|
|
26
|
-
},
|
|
27
|
-
providers: ["vertex"] as const satisfies readonly CanonicalProviderId[],
|
|
28
|
-
} satisfies DeepPartial<CatalogModel>;
|
|
29
|
-
|
|
30
|
-
export const geminiEmbedding001 = presetFor<CanonicalModelId, CatalogModel>()(
|
|
31
|
-
"google/embedding-001" as const,
|
|
32
|
-
{
|
|
33
|
-
...GEMINI_EMBEDDINGS_BASE,
|
|
34
|
-
name: "Gemini Embedding 001",
|
|
35
|
-
created: "2025-05-20",
|
|
36
|
-
context: 8192,
|
|
37
|
-
} satisfies CatalogModel,
|
|
38
|
-
);
|
|
39
|
-
|
|
40
|
-
export const gemini3FlashPreview = presetFor<CanonicalModelId, CatalogModel>()(
|
|
41
|
-
"google/gemini-3-flash-preview" as const,
|
|
42
|
-
{
|
|
43
|
-
...GEMINI_BASE,
|
|
44
|
-
name: "Gemini 3 Flash (Preview)",
|
|
45
|
-
created: "2025-12-17",
|
|
46
|
-
knowledge: "2025-01",
|
|
47
|
-
} satisfies DeepPartial<CatalogModel>,
|
|
48
|
-
);
|
|
49
|
-
|
|
50
|
-
export const gemini31FlashLitePreview = presetFor<CanonicalModelId, CatalogModel>()(
|
|
51
|
-
"google/gemini-3.1-flash-lite-preview" as const,
|
|
52
|
-
{
|
|
53
|
-
...GEMINI_BASE,
|
|
54
|
-
name: "Gemini 3.1 Flash-Lite (Preview)",
|
|
55
|
-
created: "2026-03-03",
|
|
56
|
-
knowledge: "2025-01",
|
|
57
|
-
} satisfies DeepPartial<CatalogModel>,
|
|
58
|
-
);
|
|
59
|
-
|
|
60
|
-
export const gemini31ProPreview = presetFor<CanonicalModelId, CatalogModel>()(
|
|
61
|
-
"google/gemini-3.1-pro-preview" as const,
|
|
62
|
-
{
|
|
63
|
-
...GEMINI_BASE,
|
|
64
|
-
name: "Gemini 3.1 Pro (Preview)",
|
|
65
|
-
created: "2026-02-19",
|
|
66
|
-
knowledge: "2025-01",
|
|
67
|
-
} satisfies DeepPartial<CatalogModel>,
|
|
68
|
-
);
|
|
69
|
-
|
|
70
|
-
export const gemini25FlashLite = presetFor<CanonicalModelId, CatalogModel>()(
|
|
71
|
-
"google/gemini-2.5-flash-lite" as const,
|
|
72
|
-
{
|
|
73
|
-
...GEMINI_BASE,
|
|
74
|
-
name: "Gemini 2.5 Flash Lite",
|
|
75
|
-
created: "2025-06-17",
|
|
76
|
-
knowledge: "2025-01",
|
|
77
|
-
} satisfies DeepPartial<CatalogModel>,
|
|
78
|
-
);
|
|
79
|
-
|
|
80
|
-
export const gemini25Flash = presetFor<CanonicalModelId, CatalogModel>()(
|
|
81
|
-
"google/gemini-2.5-flash" as const,
|
|
82
|
-
{
|
|
83
|
-
...GEMINI_BASE,
|
|
84
|
-
name: "Gemini 2.5 Flash",
|
|
85
|
-
created: "2025-03-20",
|
|
86
|
-
knowledge: "2025-01",
|
|
87
|
-
} satisfies DeepPartial<CatalogModel>,
|
|
88
|
-
);
|
|
89
|
-
|
|
90
|
-
export const gemini25Pro = presetFor<CanonicalModelId, CatalogModel>()(
|
|
91
|
-
"google/gemini-2.5-pro" as const,
|
|
92
|
-
{
|
|
93
|
-
...GEMINI_BASE,
|
|
94
|
-
name: "Gemini 2.5 Pro",
|
|
95
|
-
created: "2025-03-20",
|
|
96
|
-
knowledge: "2025-01",
|
|
97
|
-
} satisfies DeepPartial<CatalogModel>,
|
|
98
|
-
);
|
|
99
|
-
|
|
100
|
-
const geminiAtomic = {
|
|
101
|
-
"v2.5": [gemini25FlashLite, gemini25Flash, gemini25Pro],
|
|
102
|
-
"v3-preview": [gemini3FlashPreview, gemini31FlashLitePreview, gemini31ProPreview],
|
|
103
|
-
embeddings: [geminiEmbedding001],
|
|
104
|
-
} as const;
|
|
105
|
-
|
|
106
|
-
const geminiGroups = {
|
|
107
|
-
"v2.x": [...geminiAtomic["v2.5"]],
|
|
108
|
-
"v3.x": [...geminiAtomic["v3-preview"]],
|
|
109
|
-
} as const;
|
|
110
|
-
|
|
111
|
-
export const gemini = {
|
|
112
|
-
...geminiAtomic,
|
|
113
|
-
...geminiGroups,
|
|
114
|
-
latest: [...geminiAtomic["v2.5"]],
|
|
115
|
-
preview: [...geminiAtomic["v3-preview"]],
|
|
116
|
-
embeddings: [...geminiAtomic["embeddings"]],
|
|
117
|
-
all: Object.values(geminiAtomic).flat(),
|
|
118
|
-
} as const;
|
package/src/models/meta/index.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export * from "./presets";
|
|
@@ -1,143 +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 LLAMA_3_BASE = {
|
|
7
|
-
modalities: {
|
|
8
|
-
input: ["text", "file"] as const,
|
|
9
|
-
output: ["text"] as const,
|
|
10
|
-
},
|
|
11
|
-
capabilities: ["attachments", "tool_call", "temperature"] as const,
|
|
12
|
-
context: 128000,
|
|
13
|
-
providers: ["groq", "bedrock", "vertex"] as const satisfies readonly CanonicalProviderId[],
|
|
14
|
-
} satisfies DeepPartial<CatalogModel>;
|
|
15
|
-
|
|
16
|
-
export const llama31_8b = presetFor<CanonicalModelId, CatalogModel>()(
|
|
17
|
-
"meta/llama-3.1-8b" as const,
|
|
18
|
-
{
|
|
19
|
-
...LLAMA_3_BASE,
|
|
20
|
-
name: "Llama 3.1 8B",
|
|
21
|
-
created: "2024-07-23",
|
|
22
|
-
knowledge: "2023-12",
|
|
23
|
-
} satisfies CatalogModel,
|
|
24
|
-
);
|
|
25
|
-
|
|
26
|
-
export const llama31_70b = presetFor<CanonicalModelId, CatalogModel>()(
|
|
27
|
-
"meta/llama-3.1-70b" as const,
|
|
28
|
-
{
|
|
29
|
-
...LLAMA_3_BASE,
|
|
30
|
-
name: "Llama 3.1 70B",
|
|
31
|
-
created: "2024-07-23",
|
|
32
|
-
knowledge: "2023-12",
|
|
33
|
-
} satisfies CatalogModel,
|
|
34
|
-
);
|
|
35
|
-
|
|
36
|
-
export const llama31_405b = presetFor<CanonicalModelId, CatalogModel>()(
|
|
37
|
-
"meta/llama-3.1-405b" as const,
|
|
38
|
-
{
|
|
39
|
-
...LLAMA_3_BASE,
|
|
40
|
-
name: "Llama 3.1 405B",
|
|
41
|
-
created: "2024-07-23",
|
|
42
|
-
knowledge: "2023-12",
|
|
43
|
-
} satisfies CatalogModel,
|
|
44
|
-
);
|
|
45
|
-
|
|
46
|
-
export const llama32_1b = presetFor<CanonicalModelId, CatalogModel>()(
|
|
47
|
-
"meta/llama-3.2-1b" as const,
|
|
48
|
-
{
|
|
49
|
-
...LLAMA_3_BASE,
|
|
50
|
-
name: "Llama 3.2 1B",
|
|
51
|
-
created: "2024-09-25",
|
|
52
|
-
knowledge: "2023-12",
|
|
53
|
-
} satisfies CatalogModel,
|
|
54
|
-
);
|
|
55
|
-
|
|
56
|
-
export const llama32_3b = presetFor<CanonicalModelId, CatalogModel>()(
|
|
57
|
-
"meta/llama-3.2-3b" as const,
|
|
58
|
-
{
|
|
59
|
-
...LLAMA_3_BASE,
|
|
60
|
-
name: "Llama 3.2 3B",
|
|
61
|
-
created: "2024-09-25",
|
|
62
|
-
knowledge: "2023-12",
|
|
63
|
-
} satisfies CatalogModel,
|
|
64
|
-
);
|
|
65
|
-
|
|
66
|
-
export const llama32_11b = presetFor<CanonicalModelId, CatalogModel>()(
|
|
67
|
-
"meta/llama-3.2-11b" as const,
|
|
68
|
-
{
|
|
69
|
-
...LLAMA_3_BASE,
|
|
70
|
-
name: "Llama 3.2 11B",
|
|
71
|
-
created: "2024-09-25",
|
|
72
|
-
knowledge: "2023-12",
|
|
73
|
-
} satisfies CatalogModel,
|
|
74
|
-
);
|
|
75
|
-
|
|
76
|
-
export const llama32_90b = presetFor<CanonicalModelId, CatalogModel>()(
|
|
77
|
-
"meta/llama-3.2-90b" as const,
|
|
78
|
-
{
|
|
79
|
-
...LLAMA_3_BASE,
|
|
80
|
-
name: "Llama 3.2 90B",
|
|
81
|
-
created: "2024-09-25",
|
|
82
|
-
knowledge: "2023-12",
|
|
83
|
-
} satisfies CatalogModel,
|
|
84
|
-
);
|
|
85
|
-
|
|
86
|
-
export const llama33_70b = presetFor<CanonicalModelId, CatalogModel>()(
|
|
87
|
-
"meta/llama-3.3-70b" as const,
|
|
88
|
-
{
|
|
89
|
-
...LLAMA_3_BASE,
|
|
90
|
-
name: "Llama 3.3 70B",
|
|
91
|
-
created: "2024-12-06",
|
|
92
|
-
knowledge: "2023-12",
|
|
93
|
-
} satisfies CatalogModel,
|
|
94
|
-
);
|
|
95
|
-
|
|
96
|
-
const LLAMA_4_BASE = {
|
|
97
|
-
modalities: {
|
|
98
|
-
input: ["text", "image", "file"] as const,
|
|
99
|
-
output: ["text"] as const,
|
|
100
|
-
},
|
|
101
|
-
capabilities: ["attachments", "tool_call", "temperature"] as const,
|
|
102
|
-
context: 1000000,
|
|
103
|
-
providers: ["groq", "vertex", "bedrock"] as const,
|
|
104
|
-
} satisfies DeepPartial<CatalogModel>;
|
|
105
|
-
|
|
106
|
-
export const llama4Scout = presetFor<CanonicalModelId, CatalogModel>()(
|
|
107
|
-
"meta/llama-4-scout" as const,
|
|
108
|
-
{
|
|
109
|
-
...LLAMA_4_BASE,
|
|
110
|
-
name: "Llama 4 Scout",
|
|
111
|
-
created: "2025-08-05",
|
|
112
|
-
knowledge: "2024-06",
|
|
113
|
-
} satisfies CatalogModel,
|
|
114
|
-
);
|
|
115
|
-
|
|
116
|
-
export const llama4Maverick = presetFor<CanonicalModelId, CatalogModel>()(
|
|
117
|
-
"meta/llama-4-maverick" as const,
|
|
118
|
-
{
|
|
119
|
-
...LLAMA_4_BASE,
|
|
120
|
-
name: "Llama 4 Maverick",
|
|
121
|
-
created: "2025-08-05",
|
|
122
|
-
knowledge: "2024-06",
|
|
123
|
-
} satisfies CatalogModel,
|
|
124
|
-
);
|
|
125
|
-
|
|
126
|
-
const llamaAtomic = {
|
|
127
|
-
"v3.1": [llama31_8b, llama31_70b, llama31_405b],
|
|
128
|
-
"v3.2": [llama32_1b, llama32_3b, llama32_11b, llama32_90b],
|
|
129
|
-
"v3.3": [llama33_70b],
|
|
130
|
-
v4: [llama4Scout, llama4Maverick],
|
|
131
|
-
} as const;
|
|
132
|
-
|
|
133
|
-
const llamaGroups = {
|
|
134
|
-
"v3.x": [...llamaAtomic["v3.1"], ...llamaAtomic["v3.2"], ...llamaAtomic["v3.3"]],
|
|
135
|
-
"v4.x": [...llamaAtomic["v4"]],
|
|
136
|
-
} as const;
|
|
137
|
-
|
|
138
|
-
export const llama = {
|
|
139
|
-
...llamaAtomic,
|
|
140
|
-
...llamaGroups,
|
|
141
|
-
latest: [...llamaAtomic["v4"]],
|
|
142
|
-
all: Object.values(llamaAtomic).flat(),
|
|
143
|
-
} as const;
|
|
@@ -1,189 +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 {
|
|
7
|
-
openAIDimensionsMiddleware,
|
|
8
|
-
openAIPromptCachingMiddleware,
|
|
9
|
-
openAIReasoningMiddleware,
|
|
10
|
-
} from "./middleware";
|
|
11
|
-
|
|
12
|
-
test("openAI middleware > matching patterns", () => {
|
|
13
|
-
const languageMatching = [
|
|
14
|
-
"openai/gpt-5",
|
|
15
|
-
"openai/gpt-5.2-chat",
|
|
16
|
-
"openai/gpt-5.3-codex",
|
|
17
|
-
"openai/gpt-oss-20b",
|
|
18
|
-
] satisfies (typeof CANONICAL_MODEL_IDS)[number][];
|
|
19
|
-
|
|
20
|
-
const languageNonMatching = [
|
|
21
|
-
"openai/text-embedding-3-small",
|
|
22
|
-
"anthropic/claude-sonnet-3.7",
|
|
23
|
-
] satisfies (typeof CANONICAL_MODEL_IDS)[number][];
|
|
24
|
-
|
|
25
|
-
for (const id of languageMatching) {
|
|
26
|
-
const middleware = modelMiddlewareMatcher.resolve({ kind: "text", modelId: id });
|
|
27
|
-
expect(middleware).toContain(openAIReasoningMiddleware);
|
|
28
|
-
expect(middleware).toContain(openAIPromptCachingMiddleware);
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
for (const id of languageNonMatching) {
|
|
32
|
-
const middleware = modelMiddlewareMatcher.resolve({ kind: "text", modelId: id });
|
|
33
|
-
expect(middleware).not.toContain(openAIReasoningMiddleware);
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
const embeddingMatching = [
|
|
37
|
-
"openai/text-embedding-3-small",
|
|
38
|
-
"openai/text-embedding-3-large",
|
|
39
|
-
] satisfies (typeof CANONICAL_MODEL_IDS)[number][];
|
|
40
|
-
|
|
41
|
-
const embeddingNonMatching = ["openai/gpt-5"] satisfies (typeof CANONICAL_MODEL_IDS)[number][];
|
|
42
|
-
|
|
43
|
-
for (const id of embeddingMatching) {
|
|
44
|
-
const middleware = modelMiddlewareMatcher.resolve({ kind: "embedding", modelId: id });
|
|
45
|
-
expect(middleware).toContain(openAIDimensionsMiddleware);
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
for (const id of embeddingNonMatching) {
|
|
49
|
-
const middleware = modelMiddlewareMatcher.resolve({ kind: "embedding", modelId: id });
|
|
50
|
-
expect(middleware).not.toContain(openAIDimensionsMiddleware);
|
|
51
|
-
}
|
|
52
|
-
});
|
|
53
|
-
|
|
54
|
-
test("openAIPromptCachingMiddleware > should map key and retention", async () => {
|
|
55
|
-
const params = {
|
|
56
|
-
prompt: [],
|
|
57
|
-
providerOptions: {
|
|
58
|
-
unknown: {
|
|
59
|
-
prompt_cache_key: "tenant:shared:legal-v1",
|
|
60
|
-
prompt_cache_retention: "24h",
|
|
61
|
-
},
|
|
62
|
-
},
|
|
63
|
-
};
|
|
64
|
-
|
|
65
|
-
const result = await openAIPromptCachingMiddleware.transformParams!({
|
|
66
|
-
type: "generate",
|
|
67
|
-
params,
|
|
68
|
-
model: new MockLanguageModelV3({ modelId: "openai/gpt-5" }),
|
|
69
|
-
});
|
|
70
|
-
|
|
71
|
-
expect(result.providerOptions).toEqual({
|
|
72
|
-
openai: {
|
|
73
|
-
promptCacheKey: "tenant:shared:legal-v1",
|
|
74
|
-
promptCacheRetention: "24h",
|
|
75
|
-
},
|
|
76
|
-
unknown: {},
|
|
77
|
-
});
|
|
78
|
-
});
|
|
79
|
-
|
|
80
|
-
test("openAIReasoningMiddleware > should map reasoning effort to OpenAI provider options", async () => {
|
|
81
|
-
const params = {
|
|
82
|
-
prompt: [],
|
|
83
|
-
providerOptions: {
|
|
84
|
-
unknown: {
|
|
85
|
-
reasoning: { enabled: true, effort: "high" },
|
|
86
|
-
},
|
|
87
|
-
},
|
|
88
|
-
};
|
|
89
|
-
|
|
90
|
-
const result = await openAIReasoningMiddleware.transformParams!({
|
|
91
|
-
type: "generate",
|
|
92
|
-
params,
|
|
93
|
-
model: new MockLanguageModelV3({ modelId: "openai/gpt-5" }),
|
|
94
|
-
});
|
|
95
|
-
|
|
96
|
-
expect(result).toEqual({
|
|
97
|
-
prompt: [],
|
|
98
|
-
providerOptions: {
|
|
99
|
-
openai: {
|
|
100
|
-
reasoningEffort: "high",
|
|
101
|
-
},
|
|
102
|
-
unknown: {},
|
|
103
|
-
},
|
|
104
|
-
});
|
|
105
|
-
});
|
|
106
|
-
|
|
107
|
-
test("openAIReasoningMiddleware > should disable reasoning when requested (standard model)", async () => {
|
|
108
|
-
const params = {
|
|
109
|
-
prompt: [],
|
|
110
|
-
providerOptions: {
|
|
111
|
-
unknown: {
|
|
112
|
-
reasoning: { enabled: false },
|
|
113
|
-
},
|
|
114
|
-
},
|
|
115
|
-
};
|
|
116
|
-
|
|
117
|
-
const result = await openAIReasoningMiddleware.transformParams!({
|
|
118
|
-
type: "generate",
|
|
119
|
-
params,
|
|
120
|
-
model: new MockLanguageModelV3({ modelId: "openai/gpt-5" }),
|
|
121
|
-
});
|
|
122
|
-
|
|
123
|
-
expect(result).toEqual({
|
|
124
|
-
prompt: [],
|
|
125
|
-
providerOptions: {
|
|
126
|
-
openai: {
|
|
127
|
-
reasoningEffort: "none",
|
|
128
|
-
},
|
|
129
|
-
unknown: {},
|
|
130
|
-
},
|
|
131
|
-
});
|
|
132
|
-
});
|
|
133
|
-
|
|
134
|
-
test("openAIReasoningMiddleware > should map reasoning for gpt-oss models", async () => {
|
|
135
|
-
const cases = [
|
|
136
|
-
{ reasoning: { enabled: false }, expected: "low" },
|
|
137
|
-
{ reasoning: { enabled: true }, expected: "low" },
|
|
138
|
-
{ reasoning: { enabled: true, effort: "none" }, expected: "low" },
|
|
139
|
-
{ reasoning: { enabled: true, effort: "minimal" }, expected: "low" },
|
|
140
|
-
{ reasoning: { enabled: true, effort: "low" }, expected: "low" },
|
|
141
|
-
{ reasoning: { enabled: true, effort: "medium" }, expected: "medium" },
|
|
142
|
-
{ reasoning: { enabled: true, effort: "high" }, expected: "high" },
|
|
143
|
-
{ reasoning: { enabled: true, effort: "xhigh" }, expected: "high" },
|
|
144
|
-
] as const;
|
|
145
|
-
|
|
146
|
-
await Promise.all(
|
|
147
|
-
cases.map(async ({ reasoning, expected }) => {
|
|
148
|
-
const params = {
|
|
149
|
-
prompt: [],
|
|
150
|
-
providerOptions: {
|
|
151
|
-
unknown: { reasoning },
|
|
152
|
-
},
|
|
153
|
-
};
|
|
154
|
-
|
|
155
|
-
const result = await openAIReasoningMiddleware.transformParams!({
|
|
156
|
-
type: "generate",
|
|
157
|
-
params,
|
|
158
|
-
model: new MockLanguageModelV3({ modelId: "openai/gpt-oss-20b" }),
|
|
159
|
-
});
|
|
160
|
-
|
|
161
|
-
expect(result.providerOptions?.openai.reasoningEffort).toBe(expected);
|
|
162
|
-
}),
|
|
163
|
-
);
|
|
164
|
-
});
|
|
165
|
-
|
|
166
|
-
test("openAIReasoningMiddleware > should default reasoning effort when enabled without effort", async () => {
|
|
167
|
-
const params = {
|
|
168
|
-
prompt: [],
|
|
169
|
-
providerOptions: {
|
|
170
|
-
unknown: {
|
|
171
|
-
reasoning: { enabled: true },
|
|
172
|
-
},
|
|
173
|
-
},
|
|
174
|
-
};
|
|
175
|
-
|
|
176
|
-
const result = await openAIReasoningMiddleware.transformParams!({
|
|
177
|
-
type: "generate",
|
|
178
|
-
params,
|
|
179
|
-
model: new MockLanguageModelV3({ modelId: "openai/gpt-5" }),
|
|
180
|
-
});
|
|
181
|
-
|
|
182
|
-
expect(result).toEqual({
|
|
183
|
-
prompt: [],
|
|
184
|
-
providerOptions: {
|
|
185
|
-
openai: {},
|
|
186
|
-
unknown: {},
|
|
187
|
-
},
|
|
188
|
-
});
|
|
189
|
-
});
|
|
@@ -1,103 +0,0 @@
|
|
|
1
|
-
import type { EmbeddingModelMiddleware, LanguageModelMiddleware } from "ai";
|
|
2
|
-
|
|
3
|
-
import type {
|
|
4
|
-
ChatCompletionsReasoningConfig,
|
|
5
|
-
ChatCompletionsReasoningEffort,
|
|
6
|
-
} from "../../endpoints/chat-completions/schema";
|
|
7
|
-
|
|
8
|
-
import { modelMiddlewareMatcher } from "../../middleware/matcher";
|
|
9
|
-
|
|
10
|
-
// Convert `dimensions` (OpenAI) to `dimensions` (OpenAI)
|
|
11
|
-
export const openAIDimensionsMiddleware: EmbeddingModelMiddleware = {
|
|
12
|
-
specificationVersion: "v3",
|
|
13
|
-
// oxlint-disable-next-line require-await
|
|
14
|
-
transformParams: async ({ params }) => {
|
|
15
|
-
const unknown = params.providerOptions?.["unknown"];
|
|
16
|
-
if (!unknown) return params;
|
|
17
|
-
|
|
18
|
-
const dimensions = unknown["dimensions"] as number;
|
|
19
|
-
if (!dimensions) return params;
|
|
20
|
-
|
|
21
|
-
(params.providerOptions!["openai"] ??= {})["dimensions"] = dimensions;
|
|
22
|
-
delete unknown["dimensions"];
|
|
23
|
-
|
|
24
|
-
return params;
|
|
25
|
-
},
|
|
26
|
-
};
|
|
27
|
-
|
|
28
|
-
function mapGptOssReasoningEffort(
|
|
29
|
-
effort?: ChatCompletionsReasoningEffort,
|
|
30
|
-
): "low" | "medium" | "high" {
|
|
31
|
-
switch (effort) {
|
|
32
|
-
case "medium":
|
|
33
|
-
return "medium";
|
|
34
|
-
case "high":
|
|
35
|
-
case "xhigh":
|
|
36
|
-
case "max":
|
|
37
|
-
return "high";
|
|
38
|
-
default:
|
|
39
|
-
return "low";
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
export const openAIReasoningMiddleware: LanguageModelMiddleware = {
|
|
44
|
-
specificationVersion: "v3",
|
|
45
|
-
// oxlint-disable-next-line require-await
|
|
46
|
-
transformParams: async ({ params, model }) => {
|
|
47
|
-
const unknown = params.providerOptions?.["unknown"];
|
|
48
|
-
if (!unknown) return params;
|
|
49
|
-
|
|
50
|
-
const reasoning = unknown["reasoning"] as ChatCompletionsReasoningConfig;
|
|
51
|
-
if (!reasoning) return params;
|
|
52
|
-
|
|
53
|
-
const target = (params.providerOptions!["openai"] ??= {});
|
|
54
|
-
const isGptOss = model.modelId.includes("gpt-oss");
|
|
55
|
-
|
|
56
|
-
if (isGptOss) {
|
|
57
|
-
// FUTURE: warn that unable to disable reasoning for gpt-oss models
|
|
58
|
-
target["reasoningEffort"] = mapGptOssReasoningEffort(reasoning.effort);
|
|
59
|
-
} else if (reasoning.enabled === false) {
|
|
60
|
-
target["reasoningEffort"] = "none";
|
|
61
|
-
} else if (reasoning.effort) {
|
|
62
|
-
target["reasoningEffort"] = reasoning.effort;
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
// FUTURE: warn that reasoning.max_tokens (not supported) was ignored
|
|
66
|
-
|
|
67
|
-
delete unknown["reasoning"];
|
|
68
|
-
|
|
69
|
-
return params;
|
|
70
|
-
},
|
|
71
|
-
};
|
|
72
|
-
|
|
73
|
-
// https://developers.openai.com/api/docs/guides/prompt-caching/
|
|
74
|
-
export const openAIPromptCachingMiddleware: LanguageModelMiddleware = {
|
|
75
|
-
specificationVersion: "v3",
|
|
76
|
-
// oxlint-disable-next-line require-await
|
|
77
|
-
transformParams: async ({ params }) => {
|
|
78
|
-
const unknown = params.providerOptions?.["unknown"];
|
|
79
|
-
if (!unknown) return params;
|
|
80
|
-
|
|
81
|
-
const key = unknown["prompt_cache_key"] as string | undefined;
|
|
82
|
-
const retention = unknown["prompt_cache_retention"] as "in_memory" | "24h" | undefined;
|
|
83
|
-
|
|
84
|
-
if (key || retention) {
|
|
85
|
-
const target = (params.providerOptions!["openai"] ??= {});
|
|
86
|
-
if (key) target["promptCacheKey"] = key;
|
|
87
|
-
if (retention) target["promptCacheRetention"] = retention;
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
delete unknown["prompt_cache_key"];
|
|
91
|
-
delete unknown["prompt_cache_retention"];
|
|
92
|
-
|
|
93
|
-
return params;
|
|
94
|
-
},
|
|
95
|
-
};
|
|
96
|
-
|
|
97
|
-
modelMiddlewareMatcher.useForModel("openai/text-embedding-*", {
|
|
98
|
-
embedding: [openAIDimensionsMiddleware],
|
|
99
|
-
});
|
|
100
|
-
|
|
101
|
-
modelMiddlewareMatcher.useForModel("openai/gpt-*", {
|
|
102
|
-
language: [openAIReasoningMiddleware, openAIPromptCachingMiddleware],
|
|
103
|
-
});
|