@hebo-ai/gateway 0.1.2 → 0.2.0
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 +172 -67
- package/dist/config.js +2 -12
- package/dist/endpoints/chat-completions/converters.d.ts +28 -24
- package/dist/endpoints/chat-completions/converters.js +99 -73
- package/dist/endpoints/chat-completions/handler.js +36 -30
- package/dist/endpoints/chat-completions/schema.d.ts +394 -272
- package/dist/endpoints/chat-completions/schema.js +124 -57
- package/dist/endpoints/embeddings/converters.d.ts +4 -4
- package/dist/endpoints/embeddings/converters.js +8 -9
- package/dist/endpoints/embeddings/handler.js +32 -26
- package/dist/endpoints/embeddings/schema.d.ts +28 -38
- package/dist/endpoints/embeddings/schema.js +10 -10
- package/dist/endpoints/models/converters.d.ts +2 -2
- package/dist/endpoints/models/converters.js +9 -12
- package/dist/endpoints/models/handler.js +8 -9
- package/dist/endpoints/models/schema.d.ts +37 -31
- package/dist/endpoints/models/schema.js +23 -12
- package/dist/gateway.d.ts +8 -9
- package/dist/gateway.js +7 -10
- package/dist/index.d.ts +2 -0
- package/dist/index.js +2 -0
- package/dist/lifecycle.d.ts +2 -0
- package/dist/{utils/hooks.js → lifecycle.js} +16 -8
- package/dist/middleware/common.d.ts +4 -0
- package/dist/middleware/common.js +44 -0
- package/dist/middleware/matcher.d.ts +18 -0
- package/dist/middleware/matcher.js +83 -0
- package/dist/models/amazon/index.d.ts +2 -0
- package/dist/models/amazon/index.js +2 -0
- package/dist/models/amazon/middleware.d.ts +2 -0
- package/dist/models/amazon/middleware.js +20 -0
- package/dist/models/amazon/presets.d.ts +2390 -0
- package/dist/models/amazon/presets.js +80 -0
- package/dist/models/anthropic/index.d.ts +2 -0
- package/dist/models/anthropic/index.js +2 -0
- package/dist/models/anthropic/middleware.d.ts +5 -0
- package/dist/models/anthropic/middleware.js +67 -0
- package/dist/models/anthropic/presets.d.ts +4106 -0
- package/dist/models/anthropic/presets.js +113 -0
- package/dist/models/catalog.d.ts +3 -1
- package/dist/models/catalog.js +3 -2
- package/dist/models/cohere/index.d.ts +2 -0
- package/dist/models/cohere/index.js +2 -0
- package/dist/models/cohere/middleware.d.ts +2 -0
- package/dist/models/cohere/middleware.js +18 -0
- package/dist/models/cohere/presets.d.ts +2918 -0
- package/dist/models/cohere/presets.js +129 -0
- package/dist/models/google/index.d.ts +2 -0
- package/dist/models/google/index.js +2 -0
- package/dist/models/google/middleware.d.ts +2 -0
- package/dist/models/google/middleware.js +20 -0
- package/dist/models/{presets/gemini.d.ts → google/presets.d.ts} +400 -174
- package/dist/models/{presets/gemini.js → google/presets.js} +20 -5
- package/dist/models/meta/index.d.ts +1 -0
- package/dist/models/meta/index.js +1 -0
- package/dist/models/meta/presets.d.ts +3254 -0
- package/dist/models/{presets/llama.js → meta/presets.js} +44 -7
- package/dist/models/openai/index.d.ts +2 -0
- package/dist/models/openai/index.js +2 -0
- package/dist/models/openai/middleware.d.ts +2 -0
- package/dist/models/openai/middleware.js +20 -0
- package/dist/models/openai/presets.d.ts +6252 -0
- package/dist/models/openai/presets.js +206 -0
- package/dist/models/types.d.ts +3 -3
- package/dist/models/types.js +27 -0
- package/dist/models/voyage/index.d.ts +2 -0
- package/dist/models/voyage/index.js +2 -0
- package/dist/models/voyage/middleware.d.ts +2 -0
- package/dist/models/voyage/middleware.js +18 -0
- package/dist/models/{presets/voyage.d.ts → voyage/presets.d.ts} +322 -323
- package/dist/providers/anthropic/canonical.d.ts +3 -0
- package/dist/providers/anthropic/canonical.js +9 -0
- package/dist/providers/anthropic/index.d.ts +1 -0
- package/dist/providers/anthropic/index.js +1 -0
- package/dist/providers/bedrock/canonical.d.ts +15 -0
- package/dist/providers/{canonical/bedrock.js → bedrock/canonical.js} +13 -15
- package/dist/providers/bedrock/index.d.ts +1 -0
- package/dist/providers/bedrock/index.js +1 -0
- package/dist/providers/cohere/canonical.d.ts +3 -0
- package/dist/providers/{canonical/cohere.js → cohere/canonical.js} +6 -6
- package/dist/providers/cohere/index.d.ts +1 -0
- package/dist/providers/cohere/index.js +1 -0
- package/dist/providers/groq/canonical.d.ts +3 -0
- package/dist/providers/groq/canonical.js +12 -0
- package/dist/providers/groq/index.d.ts +1 -0
- package/dist/providers/groq/index.js +1 -0
- package/dist/providers/openai/canonical.d.ts +3 -0
- package/dist/providers/openai/canonical.js +8 -0
- package/dist/providers/openai/index.d.ts +1 -0
- package/dist/providers/openai/index.js +1 -0
- package/dist/providers/registry.d.ts +16 -26
- package/dist/providers/registry.js +19 -26
- package/dist/providers/types.d.ts +1 -1
- package/dist/providers/types.js +1 -0
- package/dist/providers/vertex/canonical.d.ts +3 -0
- package/dist/providers/vertex/canonical.js +8 -0
- package/dist/providers/vertex/index.d.ts +1 -0
- package/dist/providers/vertex/index.js +1 -0
- package/dist/providers/voyage/canonical.d.ts +3 -0
- package/dist/providers/voyage/canonical.js +7 -0
- package/dist/providers/voyage/index.d.ts +1 -0
- package/dist/providers/voyage/index.js +1 -0
- package/dist/types.d.ts +60 -30
- package/dist/utils/errors.js +2 -0
- package/dist/utils/preset.d.ts +1 -7
- package/dist/utils/preset.js +1 -1
- package/dist/utils/response.d.ts +1 -0
- package/dist/utils/response.js +10 -0
- package/package.json +79 -70
- package/src/config.ts +2 -18
- package/src/endpoints/chat-completions/converters.test.ts +39 -0
- package/src/endpoints/chat-completions/converters.ts +191 -112
- package/src/endpoints/chat-completions/handler.test.ts +47 -18
- package/src/endpoints/chat-completions/handler.ts +40 -34
- package/src/endpoints/chat-completions/schema.ts +161 -88
- package/src/endpoints/embeddings/converters.ts +15 -11
- package/src/endpoints/embeddings/handler.test.ts +27 -30
- package/src/endpoints/embeddings/handler.ts +34 -28
- package/src/endpoints/embeddings/schema.ts +10 -10
- package/src/endpoints/models/converters.ts +22 -14
- package/src/endpoints/models/handler.test.ts +26 -29
- package/src/endpoints/models/handler.ts +10 -12
- package/src/endpoints/models/schema.ts +26 -20
- package/src/gateway.ts +10 -24
- package/src/index.ts +3 -0
- package/src/{utils/hooks.ts → lifecycle.ts} +21 -11
- package/src/middleware/common.ts +68 -0
- package/src/middleware/matcher.ts +117 -0
- package/src/models/amazon/index.ts +2 -0
- package/src/models/amazon/middleware.ts +25 -0
- package/src/models/amazon/presets.ts +104 -0
- package/src/models/anthropic/index.ts +2 -0
- package/src/models/anthropic/middleware.test.ts +184 -0
- package/src/models/anthropic/middleware.ts +75 -0
- package/src/models/anthropic/presets.ts +161 -0
- package/src/models/catalog.ts +10 -2
- package/src/models/cohere/index.ts +2 -0
- package/src/models/cohere/middleware.ts +23 -0
- package/src/models/cohere/presets.ts +181 -0
- package/src/models/google/index.ts +2 -0
- package/src/models/google/middleware.ts +25 -0
- package/src/models/{presets/gemini.ts → google/presets.ts} +25 -5
- package/src/models/meta/index.ts +1 -0
- package/src/models/{presets/llama.ts → meta/presets.ts} +68 -7
- package/src/models/openai/index.ts +2 -0
- package/src/models/openai/middleware.ts +25 -0
- package/src/models/openai/presets.ts +269 -0
- package/src/models/types.ts +29 -2
- package/src/models/voyage/index.ts +2 -0
- package/src/models/voyage/middleware.ts +23 -0
- package/src/providers/anthropic/canonical.ts +17 -0
- package/src/providers/anthropic/index.ts +1 -0
- package/src/providers/{canonical/bedrock.ts → bedrock/canonical.ts} +22 -32
- package/src/providers/bedrock/index.ts +1 -0
- package/src/providers/cohere/canonical.ts +26 -0
- package/src/providers/cohere/index.ts +1 -0
- package/src/providers/groq/canonical.ts +21 -0
- package/src/providers/groq/index.ts +1 -0
- package/src/providers/openai/canonical.ts +16 -0
- package/src/providers/openai/index.ts +1 -0
- package/src/providers/registry.test.ts +12 -10
- package/src/providers/registry.ts +43 -43
- package/src/providers/types.ts +1 -0
- package/src/providers/vertex/canonical.ts +17 -0
- package/src/providers/vertex/index.ts +1 -0
- package/src/providers/voyage/canonical.ts +16 -0
- package/src/providers/voyage/index.ts +1 -0
- package/src/types.ts +64 -28
- package/src/utils/errors.ts +2 -0
- package/src/utils/preset.ts +2 -6
- package/src/utils/response.ts +15 -0
- package/dist/models/presets/claude.d.ts +0 -1165
- package/dist/models/presets/claude.js +0 -40
- package/dist/models/presets/cohere.d.ts +0 -383
- package/dist/models/presets/cohere.js +0 -26
- package/dist/models/presets/gpt-oss.d.ts +0 -779
- package/dist/models/presets/gpt-oss.js +0 -40
- package/dist/models/presets/llama.d.ts +0 -1400
- package/dist/providers/canonical/anthropic.d.ts +0 -25
- package/dist/providers/canonical/anthropic.js +0 -14
- package/dist/providers/canonical/bedrock.d.ts +0 -26
- package/dist/providers/canonical/cohere.d.ts +0 -17
- package/dist/providers/canonical/groq.d.ts +0 -17
- package/dist/providers/canonical/groq.js +0 -10
- package/dist/providers/canonical/openai.d.ts +0 -17
- package/dist/providers/canonical/openai.js +0 -8
- package/dist/providers/canonical/vertex.d.ts +0 -17
- package/dist/providers/canonical/vertex.js +0 -10
- package/dist/providers/canonical/voyage.d.ts +0 -17
- package/dist/providers/canonical/voyage.js +0 -8
- package/dist/utils/hooks.d.ts +0 -2
- package/src/models/presets/claude.ts +0 -59
- package/src/models/presets/cohere.ts +0 -37
- package/src/models/presets/gpt-oss.ts +0 -55
- package/src/providers/canonical/anthropic.ts +0 -32
- package/src/providers/canonical/cohere.ts +0 -36
- package/src/providers/canonical/groq.ts +0 -25
- package/src/providers/canonical/openai.ts +0 -16
- package/src/providers/canonical/vertex.ts +0 -18
- package/src/providers/canonical/voyage.ts +0 -16
- package/dist/models/{presets/voyage.js → voyage/presets.js} +10 -10
- package/src/models/{presets/voyage.ts → voyage/presets.ts} +10 -10
|
@@ -1,36 +1,42 @@
|
|
|
1
|
-
import * as z from "zod
|
|
2
|
-
export declare const ModelSchema: z.
|
|
3
|
-
id: z.
|
|
4
|
-
object: z.
|
|
5
|
-
created: z.
|
|
6
|
-
owned_by: z.
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
1
|
+
import * as z from "zod";
|
|
2
|
+
export declare const ModelSchema: z.ZodObject<{
|
|
3
|
+
id: z.ZodString;
|
|
4
|
+
object: z.ZodLiteral<"model">;
|
|
5
|
+
created: z.ZodInt;
|
|
6
|
+
owned_by: z.ZodString;
|
|
7
|
+
name: z.ZodOptional<z.ZodString>;
|
|
8
|
+
knowledge: z.ZodOptional<z.ZodString>;
|
|
9
|
+
context: z.ZodOptional<z.ZodInt>;
|
|
10
|
+
architecture: z.ZodOptional<z.ZodObject<{
|
|
11
|
+
modality: z.ZodOptional<z.ZodString>;
|
|
12
|
+
input_modalities: z.ZodOptional<z.ZodReadonly<z.ZodArray<z.ZodString>>>;
|
|
13
|
+
output_modalities: z.ZodOptional<z.ZodReadonly<z.ZodArray<z.ZodString>>>;
|
|
12
14
|
}, z.core.$strip>>;
|
|
13
|
-
endpoints: z.
|
|
14
|
-
tag: z.
|
|
15
|
-
}, z.core.$strip
|
|
16
|
-
|
|
15
|
+
endpoints: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
16
|
+
tag: z.ZodString;
|
|
17
|
+
}, z.core.$strip>>>;
|
|
18
|
+
capabilities: z.ZodOptional<z.ZodReadonly<z.ZodArray<z.ZodString>>>;
|
|
19
|
+
}, z.core.$loose>;
|
|
17
20
|
export type Model = z.infer<typeof ModelSchema>;
|
|
18
|
-
export declare const ModelListSchema: z.
|
|
19
|
-
object: z.
|
|
20
|
-
data: z.
|
|
21
|
-
id: z.
|
|
22
|
-
object: z.
|
|
23
|
-
created: z.
|
|
24
|
-
owned_by: z.
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
tag: z.ZodMiniString<string>;
|
|
21
|
+
export declare const ModelListSchema: z.ZodObject<{
|
|
22
|
+
object: z.ZodLiteral<"list">;
|
|
23
|
+
data: z.ZodArray<z.ZodObject<{
|
|
24
|
+
id: z.ZodString;
|
|
25
|
+
object: z.ZodLiteral<"model">;
|
|
26
|
+
created: z.ZodInt;
|
|
27
|
+
owned_by: z.ZodString;
|
|
28
|
+
name: z.ZodOptional<z.ZodString>;
|
|
29
|
+
knowledge: z.ZodOptional<z.ZodString>;
|
|
30
|
+
context: z.ZodOptional<z.ZodInt>;
|
|
31
|
+
architecture: z.ZodOptional<z.ZodObject<{
|
|
32
|
+
modality: z.ZodOptional<z.ZodString>;
|
|
33
|
+
input_modalities: z.ZodOptional<z.ZodReadonly<z.ZodArray<z.ZodString>>>;
|
|
34
|
+
output_modalities: z.ZodOptional<z.ZodReadonly<z.ZodArray<z.ZodString>>>;
|
|
33
35
|
}, z.core.$strip>>;
|
|
34
|
-
|
|
36
|
+
endpoints: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
37
|
+
tag: z.ZodString;
|
|
38
|
+
}, z.core.$strip>>>;
|
|
39
|
+
capabilities: z.ZodOptional<z.ZodReadonly<z.ZodArray<z.ZodString>>>;
|
|
40
|
+
}, z.core.$loose>>;
|
|
35
41
|
}, z.core.$strip>;
|
|
36
42
|
export type ModelList = z.infer<typeof ModelListSchema>;
|
|
@@ -1,19 +1,30 @@
|
|
|
1
|
-
import * as z from "zod
|
|
2
|
-
export const ModelSchema = z.
|
|
1
|
+
import * as z from "zod";
|
|
2
|
+
export const ModelSchema = z.looseObject({
|
|
3
|
+
// Core
|
|
3
4
|
id: z.string(),
|
|
4
5
|
object: z.literal("model"),
|
|
5
|
-
created: z.
|
|
6
|
+
created: z.int().nonnegative(),
|
|
6
7
|
owned_by: z.string(),
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
8
|
+
// Extensions
|
|
9
|
+
name: z.string().optional().meta({ extension: true }),
|
|
10
|
+
knowledge: z.string().optional().meta({ extension: true }),
|
|
11
|
+
context: z.int().nonnegative().optional().meta({ extension: true }),
|
|
12
|
+
architecture: z
|
|
13
|
+
.object({
|
|
14
|
+
modality: z.string().optional(),
|
|
15
|
+
input_modalities: z.array(z.string()).readonly().optional(),
|
|
16
|
+
output_modalities: z.array(z.string()).readonly().optional(),
|
|
17
|
+
})
|
|
18
|
+
.optional()
|
|
19
|
+
.meta({ extension: true }),
|
|
20
|
+
endpoints: z
|
|
21
|
+
.array(z.object({
|
|
14
22
|
tag: z.string(),
|
|
15
|
-
}))
|
|
16
|
-
|
|
23
|
+
}))
|
|
24
|
+
.optional()
|
|
25
|
+
.meta({ extension: true }),
|
|
26
|
+
capabilities: z.array(z.string()).readonly().optional().meta({ extension: true }),
|
|
27
|
+
});
|
|
17
28
|
export const ModelListSchema = z.object({
|
|
18
29
|
object: z.literal("list"),
|
|
19
30
|
data: z.array(ModelSchema),
|
package/dist/gateway.d.ts
CHANGED
|
@@ -1,10 +1,9 @@
|
|
|
1
|
-
import type { Endpoint, GatewayConfig
|
|
2
|
-
declare
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
1
|
+
import type { Endpoint, GatewayConfig } from "./types";
|
|
2
|
+
export declare function gateway(config: GatewayConfig): {
|
|
3
|
+
handler: (req: Request, state?: Record<string, unknown>) => Promise<Response>;
|
|
4
|
+
routes: {
|
|
5
|
+
readonly "/chat/completions": Endpoint;
|
|
6
|
+
readonly "/embeddings": Endpoint;
|
|
7
|
+
readonly "/models": Endpoint;
|
|
8
|
+
};
|
|
6
9
|
};
|
|
7
|
-
type GatewayRoutes = ReturnType<typeof buildRoutes>;
|
|
8
|
-
export declare function gateway(config: GatewayConfigBase): HeboGateway<GatewayRoutes>;
|
|
9
|
-
export declare function gateway(config: GatewayConfigRegistry): HeboGateway<GatewayRoutes>;
|
|
10
|
-
export {};
|
package/dist/gateway.js
CHANGED
|
@@ -1,25 +1,22 @@
|
|
|
1
|
-
import { parseConfig } from "./config";
|
|
2
1
|
import { chatCompletions } from "./endpoints/chat-completions/handler";
|
|
3
2
|
import { embeddings } from "./endpoints/embeddings/handler";
|
|
4
3
|
import { models } from "./endpoints/models/handler";
|
|
5
|
-
const buildRoutes = (config) => ({
|
|
6
|
-
["/chat/completions"]: chatCompletions(config),
|
|
7
|
-
["/embeddings"]: embeddings(config),
|
|
8
|
-
["/models"]: models(config),
|
|
9
|
-
});
|
|
10
4
|
export function gateway(config) {
|
|
11
|
-
const parsedConfig = parseConfig(config);
|
|
12
5
|
const basePath = (config.basePath ?? "").replace(/\/+$/, "");
|
|
13
|
-
const routes =
|
|
6
|
+
const routes = {
|
|
7
|
+
["/chat/completions"]: chatCompletions(config),
|
|
8
|
+
["/embeddings"]: embeddings(config),
|
|
9
|
+
["/models"]: models(config),
|
|
10
|
+
};
|
|
14
11
|
const routeEntries = Object.entries(routes);
|
|
15
|
-
const handler = (req) => {
|
|
12
|
+
const handler = (req, state) => {
|
|
16
13
|
let pathname = new URL(req.url).pathname;
|
|
17
14
|
if (basePath && pathname.startsWith(basePath)) {
|
|
18
15
|
pathname = pathname.slice(basePath.length);
|
|
19
16
|
}
|
|
20
17
|
for (const [route, endpoint] of routeEntries) {
|
|
21
18
|
if (pathname === route || pathname.startsWith(route + "/")) {
|
|
22
|
-
return endpoint.handler(req);
|
|
19
|
+
return endpoint.handler(req, state);
|
|
23
20
|
}
|
|
24
21
|
}
|
|
25
22
|
return Promise.resolve(new Response("Not Found", { status: 404 }));
|
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { parseConfig } from "./config";
|
|
2
|
+
import { createErrorResponse } from "./utils/errors";
|
|
2
3
|
const maybeApplyRequestPatch = (request, patch) => {
|
|
3
4
|
if (!patch.headers && patch.body === undefined)
|
|
4
5
|
return request;
|
|
@@ -15,27 +16,34 @@ const maybeApplyRequestPatch = (request, patch) => {
|
|
|
15
16
|
init.body = patch.body;
|
|
16
17
|
return new Request(request, init);
|
|
17
18
|
};
|
|
18
|
-
export const
|
|
19
|
-
const
|
|
19
|
+
export const withLifecycle = (run, config) => {
|
|
20
|
+
const parsedConfig = parseConfig(config);
|
|
21
|
+
const handler = async (request, state) => {
|
|
22
|
+
const context = {
|
|
23
|
+
request,
|
|
24
|
+
state: state ?? {},
|
|
25
|
+
providers: parsedConfig.providers,
|
|
26
|
+
models: parsedConfig.models,
|
|
27
|
+
};
|
|
20
28
|
let beforeResult;
|
|
21
29
|
try {
|
|
22
|
-
beforeResult = await hooks?.before?.(
|
|
30
|
+
beforeResult = await parsedConfig.hooks?.before?.(context);
|
|
23
31
|
}
|
|
24
32
|
catch (error) {
|
|
25
33
|
return createErrorResponse("INTERNAL_SERVER_ERROR", error, 500);
|
|
26
34
|
}
|
|
27
35
|
if (beforeResult instanceof Response)
|
|
28
36
|
return beforeResult;
|
|
29
|
-
|
|
30
|
-
|
|
37
|
+
context.request = beforeResult ? maybeApplyRequestPatch(request, beforeResult) : request;
|
|
38
|
+
context.response = await run(context);
|
|
31
39
|
let after;
|
|
32
40
|
try {
|
|
33
|
-
after = await hooks?.after?.(
|
|
41
|
+
after = await parsedConfig.hooks?.after?.(context);
|
|
34
42
|
}
|
|
35
43
|
catch (error) {
|
|
36
44
|
return createErrorResponse("INTERNAL_SERVER_ERROR", error, 500);
|
|
37
45
|
}
|
|
38
|
-
return after ?? response;
|
|
46
|
+
return after ?? context.response;
|
|
39
47
|
};
|
|
40
48
|
return handler;
|
|
41
49
|
};
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { EmbeddingModelMiddleware, LanguageModelMiddleware } from "ai";
|
|
2
|
+
import type { ProviderId } from "../providers/types";
|
|
3
|
+
export declare function forwardParamsMiddleware(providerName: ProviderId): LanguageModelMiddleware;
|
|
4
|
+
export declare function forwardParamsEmbeddingMiddleware(providerName: ProviderId): EmbeddingModelMiddleware;
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
function snakeToCamel(key) {
|
|
2
|
+
return key.replaceAll(/_([a-z])/g, (_, c) => c.toUpperCase());
|
|
3
|
+
}
|
|
4
|
+
function camelizeKeysDeep(value) {
|
|
5
|
+
if (value === null || typeof value !== "object")
|
|
6
|
+
return value;
|
|
7
|
+
if (Array.isArray(value)) {
|
|
8
|
+
return value.map((v) => camelizeKeysDeep(v));
|
|
9
|
+
}
|
|
10
|
+
const out = {};
|
|
11
|
+
for (const [k, v] of Object.entries(value)) {
|
|
12
|
+
if (v === undefined || v === null)
|
|
13
|
+
continue;
|
|
14
|
+
out[snakeToCamel(k)] = camelizeKeysDeep(v);
|
|
15
|
+
}
|
|
16
|
+
return out;
|
|
17
|
+
}
|
|
18
|
+
function forwardParamsForMiddleware(_kind, providerName) {
|
|
19
|
+
return {
|
|
20
|
+
specificationVersion: "v3",
|
|
21
|
+
// eslint-disable-next-line require-await
|
|
22
|
+
transformParams: async (options) => {
|
|
23
|
+
const { params } = options;
|
|
24
|
+
const providerOptions = params.providerOptions;
|
|
25
|
+
if (!providerOptions)
|
|
26
|
+
return params;
|
|
27
|
+
const target = (providerOptions[providerName] ??= {});
|
|
28
|
+
for (const key in providerOptions) {
|
|
29
|
+
if (key === providerName)
|
|
30
|
+
continue;
|
|
31
|
+
Object.assign(target, camelizeKeysDeep(providerOptions[key]));
|
|
32
|
+
if (key === "unknown")
|
|
33
|
+
delete providerOptions[key];
|
|
34
|
+
}
|
|
35
|
+
return params;
|
|
36
|
+
},
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
export function forwardParamsMiddleware(providerName) {
|
|
40
|
+
return forwardParamsForMiddleware("language", providerName);
|
|
41
|
+
}
|
|
42
|
+
export function forwardParamsEmbeddingMiddleware(providerName) {
|
|
43
|
+
return forwardParamsForMiddleware("embedding", providerName);
|
|
44
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { EmbeddingModelMiddleware, LanguageModelMiddleware } from "ai";
|
|
2
|
+
import type { ModelId } from "../models/types";
|
|
3
|
+
import type { ProviderId } from "../providers/types";
|
|
4
|
+
type MiddlewareEntry = {
|
|
5
|
+
language?: LanguageModelMiddleware | LanguageModelMiddleware[];
|
|
6
|
+
embedding?: EmbeddingModelMiddleware | EmbeddingModelMiddleware[];
|
|
7
|
+
};
|
|
8
|
+
declare class ModelMiddlewareMatcher {
|
|
9
|
+
private model;
|
|
10
|
+
private provider;
|
|
11
|
+
useForModel(patterns: ModelId | readonly ModelId[], entry: MiddlewareEntry): void;
|
|
12
|
+
useForProvider(patterns: ProviderId | readonly ProviderId[], entry: MiddlewareEntry): void;
|
|
13
|
+
for(modelId: ModelId, providerId: ProviderId): LanguageModelMiddleware[];
|
|
14
|
+
forEmbedding(modelId: ModelId, providerId: ProviderId): EmbeddingModelMiddleware[];
|
|
15
|
+
}
|
|
16
|
+
export declare const modelMiddlewareMatcher: ModelMiddlewareMatcher;
|
|
17
|
+
export type { ModelMiddlewareMatcher };
|
|
18
|
+
export declare function extractProviderNamespace(id: string): string;
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { forwardParamsMiddleware, forwardParamsEmbeddingMiddleware } from "./common";
|
|
2
|
+
class SimpleMatcher {
|
|
3
|
+
rules = [];
|
|
4
|
+
cache = new Map();
|
|
5
|
+
static MAX_CACHE = 500;
|
|
6
|
+
use(pattern, entry) {
|
|
7
|
+
this.cache.clear();
|
|
8
|
+
const stored = { language: [], embedding: [] };
|
|
9
|
+
if (entry.language)
|
|
10
|
+
stored.language.push(...toArray(entry.language));
|
|
11
|
+
if (entry.embedding)
|
|
12
|
+
stored.embedding.push(...toArray(entry.embedding));
|
|
13
|
+
this.rules.push({ pattern, test: compilePattern(pattern), stored });
|
|
14
|
+
}
|
|
15
|
+
match(key) {
|
|
16
|
+
const cached = this.cache.get(key);
|
|
17
|
+
if (cached)
|
|
18
|
+
return cached;
|
|
19
|
+
const out = [];
|
|
20
|
+
for (const r of this.rules)
|
|
21
|
+
if (r.test(key))
|
|
22
|
+
out.push(r.stored);
|
|
23
|
+
if (this.cache.size >= SimpleMatcher.MAX_CACHE) {
|
|
24
|
+
let n = Math.ceil(SimpleMatcher.MAX_CACHE * 0.2);
|
|
25
|
+
for (const key of this.cache.keys()) {
|
|
26
|
+
this.cache.delete(key);
|
|
27
|
+
if (--n === 0)
|
|
28
|
+
break;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
this.cache.set(key, out);
|
|
32
|
+
return out;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
class ModelMiddlewareMatcher {
|
|
36
|
+
model = new SimpleMatcher();
|
|
37
|
+
provider = new SimpleMatcher();
|
|
38
|
+
useForModel(patterns, entry) {
|
|
39
|
+
for (const pattern of toArray(patterns)) {
|
|
40
|
+
this.model.use(pattern, entry);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
useForProvider(patterns, entry) {
|
|
44
|
+
for (const pattern of toArray(patterns)) {
|
|
45
|
+
this.provider.use(pattern, entry);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
for(modelId, providerId) {
|
|
49
|
+
const out = [];
|
|
50
|
+
for (const s of this.model.match(modelId))
|
|
51
|
+
out.push(...s.language);
|
|
52
|
+
out.push(forwardParamsMiddleware(extractProviderNamespace(providerId)));
|
|
53
|
+
for (const s of this.provider.match(providerId))
|
|
54
|
+
out.push(...s.language);
|
|
55
|
+
return out;
|
|
56
|
+
}
|
|
57
|
+
forEmbedding(modelId, providerId) {
|
|
58
|
+
const out = [];
|
|
59
|
+
for (const s of this.model.match(modelId))
|
|
60
|
+
out.push(...s.embedding);
|
|
61
|
+
out.push(forwardParamsEmbeddingMiddleware(extractProviderNamespace(providerId)));
|
|
62
|
+
for (const s of this.provider.match(providerId))
|
|
63
|
+
out.push(...s.embedding);
|
|
64
|
+
return out;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
export const modelMiddlewareMatcher = new ModelMiddlewareMatcher();
|
|
68
|
+
const toArray = (v) => (Array.isArray(v) ? v : [v]);
|
|
69
|
+
function compilePattern(pattern) {
|
|
70
|
+
if (!pattern.includes("*"))
|
|
71
|
+
return (key) => key === pattern;
|
|
72
|
+
const re = new RegExp(`^${pattern
|
|
73
|
+
.split("*")
|
|
74
|
+
.map((p) => p.replaceAll(/[-\\^$+?.()|[\]{}]/g, "\\$&"))
|
|
75
|
+
.join(".*")}$`);
|
|
76
|
+
return (key) => re.test(key);
|
|
77
|
+
}
|
|
78
|
+
export function extractProviderNamespace(id) {
|
|
79
|
+
const firstDot = id.indexOf(".");
|
|
80
|
+
const head = firstDot === -1 ? id : id.slice(0, firstDot);
|
|
81
|
+
const dash = head.indexOf("-");
|
|
82
|
+
return dash === -1 ? head : head.slice(dash + 1);
|
|
83
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { modelMiddlewareMatcher } from "../../middleware/matcher";
|
|
2
|
+
// Convert `dimensions` (OpenAI) to `embeddingDimension` (Nova)
|
|
3
|
+
export const novaEmbeddingModelMiddleware = {
|
|
4
|
+
specificationVersion: "v3",
|
|
5
|
+
// eslint-disable-next-line require-await
|
|
6
|
+
transformParams: async ({ params }) => {
|
|
7
|
+
const unknown = params.providerOptions?.["unknown"];
|
|
8
|
+
if (!unknown)
|
|
9
|
+
return params;
|
|
10
|
+
let dimensions = unknown["dimensions"];
|
|
11
|
+
if (!dimensions)
|
|
12
|
+
dimensions = 1024;
|
|
13
|
+
(params.providerOptions["nova"] ??= {})["embeddingDimension"] = dimensions;
|
|
14
|
+
delete unknown["dimensions"];
|
|
15
|
+
return params;
|
|
16
|
+
},
|
|
17
|
+
};
|
|
18
|
+
modelMiddlewareMatcher.useForModel("amazon/nova-*embeddings*", {
|
|
19
|
+
embedding: novaEmbeddingModelMiddleware,
|
|
20
|
+
});
|