@routerxjs/core 0.0.1

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.
@@ -0,0 +1,71 @@
1
+ // src/router/Router.ts
2
+ var Router = class {
3
+ providers;
4
+ defaultProviderId;
5
+ constructor(config) {
6
+ this.providers = config.providers;
7
+ this.defaultProviderId = config.defaultProviderId;
8
+ }
9
+ /**
10
+ * Find the best provider for a given model
11
+ */
12
+ route(model) {
13
+ const candidates = this.providers.filter((p) => p.enabled !== false).filter((p) => p.models.includes(model)).sort((a, b) => (a.priority ?? 100) - (b.priority ?? 100));
14
+ if (candidates.length > 0) {
15
+ return { provider: candidates[0], model };
16
+ }
17
+ if (this.defaultProviderId) {
18
+ const defaultProvider = this.providers.find(
19
+ (p) => p.id === this.defaultProviderId && p.enabled !== false
20
+ );
21
+ if (defaultProvider) {
22
+ return { provider: defaultProvider, model };
23
+ }
24
+ }
25
+ return null;
26
+ }
27
+ /**
28
+ * List all available models across all providers
29
+ */
30
+ listModels() {
31
+ const models = [];
32
+ for (const provider of this.providers) {
33
+ if (provider.enabled === false) continue;
34
+ for (const model of provider.models) {
35
+ models.push({
36
+ model,
37
+ providerId: provider.id,
38
+ protocol: provider.protocol
39
+ });
40
+ }
41
+ }
42
+ return models;
43
+ }
44
+ /**
45
+ * Add a provider at runtime
46
+ */
47
+ addProvider(provider) {
48
+ const existing = this.providers.findIndex((p) => p.id === provider.id);
49
+ if (existing >= 0) {
50
+ this.providers[existing] = provider;
51
+ } else {
52
+ this.providers.push(provider);
53
+ }
54
+ }
55
+ /**
56
+ * Remove a provider
57
+ */
58
+ removeProvider(id) {
59
+ const idx = this.providers.findIndex((p) => p.id === id);
60
+ if (idx >= 0) {
61
+ this.providers.splice(idx, 1);
62
+ return true;
63
+ }
64
+ return false;
65
+ }
66
+ };
67
+
68
+ export {
69
+ Router
70
+ };
71
+ //# sourceMappingURL=chunk-PQO5XDOQ.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/router/Router.ts"],"sourcesContent":["/**\n * Router — model matching and provider selection\n *\n * Given a model name, find the best provider to serve it.\n */\n\nimport type { RegisteredProvider, RouteResult, RouterConfig } from \"./types\";\n\nexport class Router {\n private providers: RegisteredProvider[];\n private defaultProviderId?: string;\n\n constructor(config: RouterConfig) {\n this.providers = config.providers;\n this.defaultProviderId = config.defaultProviderId;\n }\n\n /**\n * Find the best provider for a given model\n */\n route(model: string): RouteResult | null {\n // Find providers that explicitly list this model\n const candidates = this.providers\n .filter((p) => p.enabled !== false)\n .filter((p) => p.models.includes(model))\n .sort((a, b) => (a.priority ?? 100) - (b.priority ?? 100));\n\n if (candidates.length > 0) {\n return { provider: candidates[0], model };\n }\n\n // Fallback to default provider\n if (this.defaultProviderId) {\n const defaultProvider = this.providers.find(\n (p) => p.id === this.defaultProviderId && p.enabled !== false\n );\n if (defaultProvider) {\n return { provider: defaultProvider, model };\n }\n }\n\n return null;\n }\n\n /**\n * List all available models across all providers\n */\n listModels(): Array<{ model: string; providerId: string; protocol: string }> {\n const models: Array<{ model: string; providerId: string; protocol: string }> = [];\n for (const provider of this.providers) {\n if (provider.enabled === false) continue;\n for (const model of provider.models) {\n models.push({\n model,\n providerId: provider.id,\n protocol: provider.protocol,\n });\n }\n }\n return models;\n }\n\n /**\n * Add a provider at runtime\n */\n addProvider(provider: RegisteredProvider): void {\n const existing = this.providers.findIndex((p) => p.id === provider.id);\n if (existing >= 0) {\n this.providers[existing] = provider;\n } else {\n this.providers.push(provider);\n }\n }\n\n /**\n * Remove a provider\n */\n removeProvider(id: string): boolean {\n const idx = this.providers.findIndex((p) => p.id === id);\n if (idx >= 0) {\n this.providers.splice(idx, 1);\n return true;\n }\n return false;\n }\n}\n"],"mappings":";AAQO,IAAM,SAAN,MAAa;AAAA,EACV;AAAA,EACA;AAAA,EAER,YAAY,QAAsB;AAChC,SAAK,YAAY,OAAO;AACxB,SAAK,oBAAoB,OAAO;AAAA,EAClC;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,OAAmC;AAEvC,UAAM,aAAa,KAAK,UACrB,OAAO,CAAC,MAAM,EAAE,YAAY,KAAK,EACjC,OAAO,CAAC,MAAM,EAAE,OAAO,SAAS,KAAK,CAAC,EACtC,KAAK,CAAC,GAAG,OAAO,EAAE,YAAY,QAAQ,EAAE,YAAY,IAAI;AAE3D,QAAI,WAAW,SAAS,GAAG;AACzB,aAAO,EAAE,UAAU,WAAW,CAAC,GAAG,MAAM;AAAA,IAC1C;AAGA,QAAI,KAAK,mBAAmB;AAC1B,YAAM,kBAAkB,KAAK,UAAU;AAAA,QACrC,CAAC,MAAM,EAAE,OAAO,KAAK,qBAAqB,EAAE,YAAY;AAAA,MAC1D;AACA,UAAI,iBAAiB;AACnB,eAAO,EAAE,UAAU,iBAAiB,MAAM;AAAA,MAC5C;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,aAA6E;AAC3E,UAAM,SAAyE,CAAC;AAChF,eAAW,YAAY,KAAK,WAAW;AACrC,UAAI,SAAS,YAAY,MAAO;AAChC,iBAAW,SAAS,SAAS,QAAQ;AACnC,eAAO,KAAK;AAAA,UACV;AAAA,UACA,YAAY,SAAS;AAAA,UACrB,UAAU,SAAS;AAAA,QACrB,CAAC;AAAA,MACH;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,YAAY,UAAoC;AAC9C,UAAM,WAAW,KAAK,UAAU,UAAU,CAAC,MAAM,EAAE,OAAO,SAAS,EAAE;AACrE,QAAI,YAAY,GAAG;AACjB,WAAK,UAAU,QAAQ,IAAI;AAAA,IAC7B,OAAO;AACL,WAAK,UAAU,KAAK,QAAQ;AAAA,IAC9B;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,eAAe,IAAqB;AAClC,UAAM,MAAM,KAAK,UAAU,UAAU,CAAC,MAAM,EAAE,OAAO,EAAE;AACvD,QAAI,OAAO,GAAG;AACZ,WAAK,UAAU,OAAO,KAAK,CAAC;AAC5B,aAAO;AAAA,IACT;AACA,WAAO;AAAA,EACT;AACF;","names":[]}
@@ -0,0 +1 @@
1
+ export { ProviderProtocol, RegisteredProvider, RouteResult, Router, RouterConfig } from './router/index.js';
package/dist/index.js ADDED
@@ -0,0 +1,7 @@
1
+ import {
2
+ Router
3
+ } from "./chunk-PQO5XDOQ.js";
4
+ export {
5
+ Router
6
+ };
7
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
@@ -0,0 +1,80 @@
1
+ /**
2
+ * Router Types — routing configuration and model matching
3
+ */
4
+ /**
5
+ * Supported upstream provider protocols
6
+ */
7
+ type ProviderProtocol = "openai-compatible" | "anthropic";
8
+ /**
9
+ * A registered upstream provider with its capabilities
10
+ */
11
+ interface RegisteredProvider {
12
+ /** Unique provider ID */
13
+ id: string;
14
+ /** Display name */
15
+ name: string;
16
+ /** Protocol this provider speaks */
17
+ protocol: ProviderProtocol;
18
+ /** API key */
19
+ apiKey: string;
20
+ /** Custom base URL */
21
+ baseUrl?: string;
22
+ /** Models this provider can serve */
23
+ models: string[];
24
+ /** Priority for model matching (lower = higher priority) */
25
+ priority?: number;
26
+ /** Whether this provider is enabled */
27
+ enabled?: boolean;
28
+ }
29
+ /**
30
+ * The result of routing a request to a provider
31
+ */
32
+ interface RouteResult {
33
+ /** The matched provider */
34
+ provider: RegisteredProvider;
35
+ /** The model to use (may be remapped) */
36
+ model: string;
37
+ }
38
+ /**
39
+ * Router configuration
40
+ */
41
+ interface RouterConfig {
42
+ /** Registered providers */
43
+ providers: RegisteredProvider[];
44
+ /** Default provider ID (fallback when no model match) */
45
+ defaultProviderId?: string;
46
+ }
47
+
48
+ /**
49
+ * Router — model matching and provider selection
50
+ *
51
+ * Given a model name, find the best provider to serve it.
52
+ */
53
+
54
+ declare class Router {
55
+ private providers;
56
+ private defaultProviderId?;
57
+ constructor(config: RouterConfig);
58
+ /**
59
+ * Find the best provider for a given model
60
+ */
61
+ route(model: string): RouteResult | null;
62
+ /**
63
+ * List all available models across all providers
64
+ */
65
+ listModels(): Array<{
66
+ model: string;
67
+ providerId: string;
68
+ protocol: string;
69
+ }>;
70
+ /**
71
+ * Add a provider at runtime
72
+ */
73
+ addProvider(provider: RegisteredProvider): void;
74
+ /**
75
+ * Remove a provider
76
+ */
77
+ removeProvider(id: string): boolean;
78
+ }
79
+
80
+ export { type ProviderProtocol, type RegisteredProvider, type RouteResult, Router, type RouterConfig };
@@ -0,0 +1,7 @@
1
+ import {
2
+ Router
3
+ } from "../chunk-PQO5XDOQ.js";
4
+ export {
5
+ Router
6
+ };
7
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
package/package.json ADDED
@@ -0,0 +1,29 @@
1
+ {
2
+ "name": "@routerxjs/core",
3
+ "version": "0.0.1",
4
+ "type": "module",
5
+ "main": "./dist/index.js",
6
+ "types": "./dist/index.d.ts",
7
+ "exports": {
8
+ ".": {
9
+ "types": "./dist/index.d.ts",
10
+ "import": "./dist/index.js"
11
+ },
12
+ "./router": {
13
+ "types": "./dist/router/index.d.ts",
14
+ "import": "./dist/router/index.js"
15
+ }
16
+ },
17
+ "files": [
18
+ "dist",
19
+ "src"
20
+ ],
21
+ "scripts": {
22
+ "build": "tsup",
23
+ "typecheck": "tsc --noEmit",
24
+ "test": "bun test"
25
+ },
26
+ "devDependencies": {
27
+ "typescript": "^5.9.3"
28
+ }
29
+ }
package/src/index.ts ADDED
@@ -0,0 +1,9 @@
1
+ // Router
2
+
3
+ export type {
4
+ ProviderProtocol,
5
+ RegisteredProvider,
6
+ RouteResult,
7
+ RouterConfig,
8
+ } from "./router/index";
9
+ export { Router } from "./router/index";
@@ -0,0 +1,86 @@
1
+ /**
2
+ * Router — model matching and provider selection
3
+ *
4
+ * Given a model name, find the best provider to serve it.
5
+ */
6
+
7
+ import type { RegisteredProvider, RouteResult, RouterConfig } from "./types";
8
+
9
+ export class Router {
10
+ private providers: RegisteredProvider[];
11
+ private defaultProviderId?: string;
12
+
13
+ constructor(config: RouterConfig) {
14
+ this.providers = config.providers;
15
+ this.defaultProviderId = config.defaultProviderId;
16
+ }
17
+
18
+ /**
19
+ * Find the best provider for a given model
20
+ */
21
+ route(model: string): RouteResult | null {
22
+ // Find providers that explicitly list this model
23
+ const candidates = this.providers
24
+ .filter((p) => p.enabled !== false)
25
+ .filter((p) => p.models.includes(model))
26
+ .sort((a, b) => (a.priority ?? 100) - (b.priority ?? 100));
27
+
28
+ if (candidates.length > 0) {
29
+ return { provider: candidates[0], model };
30
+ }
31
+
32
+ // Fallback to default provider
33
+ if (this.defaultProviderId) {
34
+ const defaultProvider = this.providers.find(
35
+ (p) => p.id === this.defaultProviderId && p.enabled !== false
36
+ );
37
+ if (defaultProvider) {
38
+ return { provider: defaultProvider, model };
39
+ }
40
+ }
41
+
42
+ return null;
43
+ }
44
+
45
+ /**
46
+ * List all available models across all providers
47
+ */
48
+ listModels(): Array<{ model: string; providerId: string; protocol: string }> {
49
+ const models: Array<{ model: string; providerId: string; protocol: string }> = [];
50
+ for (const provider of this.providers) {
51
+ if (provider.enabled === false) continue;
52
+ for (const model of provider.models) {
53
+ models.push({
54
+ model,
55
+ providerId: provider.id,
56
+ protocol: provider.protocol,
57
+ });
58
+ }
59
+ }
60
+ return models;
61
+ }
62
+
63
+ /**
64
+ * Add a provider at runtime
65
+ */
66
+ addProvider(provider: RegisteredProvider): void {
67
+ const existing = this.providers.findIndex((p) => p.id === provider.id);
68
+ if (existing >= 0) {
69
+ this.providers[existing] = provider;
70
+ } else {
71
+ this.providers.push(provider);
72
+ }
73
+ }
74
+
75
+ /**
76
+ * Remove a provider
77
+ */
78
+ removeProvider(id: string): boolean {
79
+ const idx = this.providers.findIndex((p) => p.id === id);
80
+ if (idx >= 0) {
81
+ this.providers.splice(idx, 1);
82
+ return true;
83
+ }
84
+ return false;
85
+ }
86
+ }
@@ -0,0 +1,7 @@
1
+ export { Router } from "./Router";
2
+ export type {
3
+ ProviderProtocol,
4
+ RegisteredProvider,
5
+ RouteResult,
6
+ RouterConfig,
7
+ } from "./types";
@@ -0,0 +1,59 @@
1
+ /**
2
+ * Router Types — routing configuration and model matching
3
+ */
4
+
5
+ /**
6
+ * Supported upstream provider protocols
7
+ */
8
+ export type ProviderProtocol = "openai-compatible" | "anthropic";
9
+
10
+ /**
11
+ * A registered upstream provider with its capabilities
12
+ */
13
+ export interface RegisteredProvider {
14
+ /** Unique provider ID */
15
+ id: string;
16
+
17
+ /** Display name */
18
+ name: string;
19
+
20
+ /** Protocol this provider speaks */
21
+ protocol: ProviderProtocol;
22
+
23
+ /** API key */
24
+ apiKey: string;
25
+
26
+ /** Custom base URL */
27
+ baseUrl?: string;
28
+
29
+ /** Models this provider can serve */
30
+ models: string[];
31
+
32
+ /** Priority for model matching (lower = higher priority) */
33
+ priority?: number;
34
+
35
+ /** Whether this provider is enabled */
36
+ enabled?: boolean;
37
+ }
38
+
39
+ /**
40
+ * The result of routing a request to a provider
41
+ */
42
+ export interface RouteResult {
43
+ /** The matched provider */
44
+ provider: RegisteredProvider;
45
+
46
+ /** The model to use (may be remapped) */
47
+ model: string;
48
+ }
49
+
50
+ /**
51
+ * Router configuration
52
+ */
53
+ export interface RouterConfig {
54
+ /** Registered providers */
55
+ providers: RegisteredProvider[];
56
+
57
+ /** Default provider ID (fallback when no model match) */
58
+ defaultProviderId?: string;
59
+ }