ai-gateway-kit 0.1.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/LICENSE +21 -0
- package/README.md +102 -0
- package/dist/gateway/createAIGateway.d.ts +11 -0
- package/dist/gateway/createAIGateway.d.ts.map +1 -0
- package/dist/gateway/createAIGateway.js +296 -0
- package/dist/gateway/createAIGateway.js.map +1 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +8 -0
- package/dist/index.js.map +1 -0
- package/dist/providers/gemini.d.ts +7 -0
- package/dist/providers/gemini.d.ts.map +1 -0
- package/dist/providers/gemini.js +52 -0
- package/dist/providers/gemini.js.map +1 -0
- package/dist/providers/github-models.d.ts +9 -0
- package/dist/providers/github-models.d.ts.map +1 -0
- package/dist/providers/github-models.js +93 -0
- package/dist/providers/github-models.js.map +1 -0
- package/dist/rate-limiter/rateLimitManager.d.ts +16 -0
- package/dist/rate-limiter/rateLimitManager.d.ts.map +1 -0
- package/dist/rate-limiter/rateLimitManager.js +146 -0
- package/dist/rate-limiter/rateLimitManager.js.map +1 -0
- package/dist/registry/modelRegistry.d.ts +9 -0
- package/dist/registry/modelRegistry.d.ts.map +1 -0
- package/dist/registry/modelRegistry.js +20 -0
- package/dist/registry/modelRegistry.js.map +1 -0
- package/dist/registry/presets.d.ts +7 -0
- package/dist/registry/presets.d.ts.map +1 -0
- package/dist/registry/presets.js +135 -0
- package/dist/registry/presets.js.map +1 -0
- package/dist/types/public.d.ts +203 -0
- package/dist/types/public.d.ts.map +1 -0
- package/dist/types/public.js +2 -0
- package/dist/types/public.js.map +1 -0
- package/dist/utils/errors.d.ts +6 -0
- package/dist/utils/errors.d.ts.map +1 -0
- package/dist/utils/errors.js +53 -0
- package/dist/utils/errors.js.map +1 -0
- package/package.json +69 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
# ai-gateway-kit
|
|
2
|
+
|
|
3
|
+
A boring, provider-agnostic AI Gateway for Node.js.
|
|
4
|
+
|
|
5
|
+
This library exists to solve the “production gateway” problems around LLM usage:
|
|
6
|
+
|
|
7
|
+
- **Capability-based routing** (agents request *capabilities*, not models)
|
|
8
|
+
- **Ordered fallback** (graceful degradation, never silent failure)
|
|
9
|
+
- **In-memory rate limiting** (instance-scoped by design)
|
|
10
|
+
- **Observability hooks** (you choose logging/metrics/tracing)
|
|
11
|
+
|
|
12
|
+
## Why capability-based routing?
|
|
13
|
+
|
|
14
|
+
Model names change, providers change, and quotas fluctuate.
|
|
15
|
+
A gateway that routes by *capability* lets your agents stay stable while the model fleet evolves.
|
|
16
|
+
|
|
17
|
+
Example capabilities:
|
|
18
|
+
- `fast_text`
|
|
19
|
+
- `deep_reasoning`
|
|
20
|
+
- `search`
|
|
21
|
+
- `speech_to_text`
|
|
22
|
+
|
|
23
|
+
## Why in-memory state?
|
|
24
|
+
|
|
25
|
+
This kit intentionally uses **in-memory** rate limit state.
|
|
26
|
+
|
|
27
|
+
- Works in serverless environments (Vercel-compatible)
|
|
28
|
+
- No shared storage dependency
|
|
29
|
+
- Predictable failure modes
|
|
30
|
+
|
|
31
|
+
Trade-off: **multi-instance deployments do not share quotas**. Each instance enforces limits based on its own in-memory view.
|
|
32
|
+
|
|
33
|
+
If you need cross-instance coordination, you can replace the in-memory `RateLimitManager` with your own implementation.
|
|
34
|
+
|
|
35
|
+
## This is not a chat wrapper
|
|
36
|
+
|
|
37
|
+
This library is infrastructure:
|
|
38
|
+
- routing
|
|
39
|
+
- backoff
|
|
40
|
+
- fallbacks
|
|
41
|
+
- hooks
|
|
42
|
+
|
|
43
|
+
It does **not** provide prompt templates, product policies, UI, or agent logic.
|
|
44
|
+
|
|
45
|
+
## Install
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
npm install @your-scope/ai-gateway-kit
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
## Quick start
|
|
52
|
+
|
|
53
|
+
```ts
|
|
54
|
+
import { createAIGateway } from "@your-scope/ai-gateway-kit";
|
|
55
|
+
|
|
56
|
+
const gateway = createAIGateway({
|
|
57
|
+
models: [
|
|
58
|
+
{
|
|
59
|
+
id: "gpt-4o-mini",
|
|
60
|
+
provider: "github",
|
|
61
|
+
capabilities: ["fast_text"],
|
|
62
|
+
limits: { rpm: 15, rpd: 150, tpmInput: 150000, tpmOutput: 20000, concurrency: 3 }
|
|
63
|
+
}
|
|
64
|
+
],
|
|
65
|
+
providers: {
|
|
66
|
+
github: {
|
|
67
|
+
type: "github-models",
|
|
68
|
+
token: process.env.GITHUB_TOKEN!
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
const result = await gateway.execute({
|
|
74
|
+
capability: "fast_text",
|
|
75
|
+
input: {
|
|
76
|
+
kind: "chat",
|
|
77
|
+
messages: [{ role: "user", content: "Say hi." }]
|
|
78
|
+
}
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
console.log(result.output);
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
## Providers
|
|
85
|
+
|
|
86
|
+
- GitHub Models: see `@your-scope/ai-gateway-kit/providers/github-models`
|
|
87
|
+
- Gemini: see `@your-scope/ai-gateway-kit/providers/gemini`
|
|
88
|
+
- Custom provider: implement `ProviderAdapter`
|
|
89
|
+
|
|
90
|
+
## Observability hooks
|
|
91
|
+
|
|
92
|
+
You can subscribe to lifecycle events without taking a dependency on any logging stack:
|
|
93
|
+
|
|
94
|
+
- `onRequestStart`
|
|
95
|
+
- `onRequestEnd`
|
|
96
|
+
- `onRateLimit`
|
|
97
|
+
- `onFallback`
|
|
98
|
+
- `onError`
|
|
99
|
+
|
|
100
|
+
## License
|
|
101
|
+
|
|
102
|
+
MIT
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { Capability, CapabilityRouter, Gateway, GatewayHooks, ModelDefinition, ProviderAdapter } from "../types/public.js";
|
|
2
|
+
export interface CreateAIGatewayConfig<C extends string = Capability> {
|
|
3
|
+
models?: readonly ModelDefinition<C>[];
|
|
4
|
+
providers: Record<string, ProviderAdapter<C>>;
|
|
5
|
+
router?: CapabilityRouter<C>;
|
|
6
|
+
hooks?: GatewayHooks<C>;
|
|
7
|
+
now?: () => number;
|
|
8
|
+
maxRecentRequests?: number;
|
|
9
|
+
}
|
|
10
|
+
export declare function createAIGateway<C extends string = Capability>(config: CreateAIGatewayConfig<C>): Gateway<C>;
|
|
11
|
+
//# sourceMappingURL=createAIGateway.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"createAIGateway.d.ts","sourceRoot":"","sources":["../../src/gateway/createAIGateway.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EACV,UAAU,EACV,gBAAgB,EAChB,OAAO,EAGP,YAAY,EAIZ,eAAe,EACf,eAAe,EAGhB,MAAM,oBAAoB,CAAC;AAY5B,MAAM,WAAW,qBAAqB,CAAC,CAAC,SAAS,MAAM,GAAG,UAAU;IAClE,MAAM,CAAC,EAAE,SAAS,eAAe,CAAC,CAAC,CAAC,EAAE,CAAC;IACvC,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC,CAAC,CAAC,CAAC;IAC9C,MAAM,CAAC,EAAE,gBAAgB,CAAC,CAAC,CAAC,CAAC;IAC7B,KAAK,CAAC,EAAE,YAAY,CAAC,CAAC,CAAC,CAAC;IACxB,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;IACnB,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC5B;AAED,wBAAgB,eAAe,CAAC,CAAC,SAAS,MAAM,GAAG,UAAU,EAC3D,MAAM,EAAE,qBAAqB,CAAC,CAAC,CAAC,GAC/B,OAAO,CAAC,CAAC,CAAC,CA8VZ"}
|
|
@@ -0,0 +1,296 @@
|
|
|
1
|
+
import { createModelRegistry } from "../registry/modelRegistry.js";
|
|
2
|
+
import { createInMemoryRateLimitManager } from "../rate-limiter/rateLimitManager.js";
|
|
3
|
+
import { normalizeToProviderError, parseRetryAfterMsFromText } from "../utils/errors.js";
|
|
4
|
+
export function createAIGateway(config) {
|
|
5
|
+
const now = config.now ?? (() => Date.now());
|
|
6
|
+
const hooks = config.hooks;
|
|
7
|
+
const maxRecent = config.maxRecentRequests ?? 100;
|
|
8
|
+
const registry = createModelRegistry();
|
|
9
|
+
const initialModels = config.models ?? [];
|
|
10
|
+
registry.register(initialModels);
|
|
11
|
+
const rateLimiter = createInMemoryRateLimitManager(initialModels, { now });
|
|
12
|
+
const recentRequests = [];
|
|
13
|
+
const agentLastUse = new Map();
|
|
14
|
+
const defaultRouter = {
|
|
15
|
+
getModelOrderForCapability(capability) {
|
|
16
|
+
const all = registry.getAllModels();
|
|
17
|
+
return all.filter((m) => m.capabilities.includes(capability)).map((m) => m.id);
|
|
18
|
+
}
|
|
19
|
+
};
|
|
20
|
+
const router = config.router ?? defaultRouter;
|
|
21
|
+
function pushRecent(entry) {
|
|
22
|
+
recentRequests.push(entry);
|
|
23
|
+
if (recentRequests.length > maxRecent)
|
|
24
|
+
recentRequests.shift();
|
|
25
|
+
}
|
|
26
|
+
function snapshot() {
|
|
27
|
+
const models = registry.getAllModels();
|
|
28
|
+
const rateLimits = rateLimiter.getAllSnapshots();
|
|
29
|
+
const availabilityByModel = new Map(rateLimits.map((s) => [
|
|
30
|
+
s.modelId,
|
|
31
|
+
s.availability === "throttled" ? "limited" : s.availability
|
|
32
|
+
]));
|
|
33
|
+
const modelRegistry = models.map((m) => ({
|
|
34
|
+
id: m.id,
|
|
35
|
+
provider: m.provider,
|
|
36
|
+
tier: m.tier ?? "",
|
|
37
|
+
capabilities: m.capabilities,
|
|
38
|
+
limits: m.limits,
|
|
39
|
+
isReasoning: m.isReasoning === true,
|
|
40
|
+
availability: availabilityByModel.get(m.id) ?? "available"
|
|
41
|
+
}));
|
|
42
|
+
const agentMappings = Array.from(agentLastUse.entries())
|
|
43
|
+
.map(([agentName, usage]) => {
|
|
44
|
+
const queue = router.getModelOrderForCapability(usage.capability);
|
|
45
|
+
return {
|
|
46
|
+
agentName,
|
|
47
|
+
capabilities: [usage.capability],
|
|
48
|
+
primaryModels: queue.slice(0, 2),
|
|
49
|
+
fallbackModels: queue.slice(2),
|
|
50
|
+
lastUsedModel: usage.modelId,
|
|
51
|
+
lastUsedTimestamp: usage.timestamp
|
|
52
|
+
};
|
|
53
|
+
})
|
|
54
|
+
.sort((a, b) => (b.lastUsedTimestamp ?? 0) - (a.lastUsedTimestamp ?? 0));
|
|
55
|
+
return {
|
|
56
|
+
timestamp: now(),
|
|
57
|
+
recentRequests: [...recentRequests].slice(-50).reverse(),
|
|
58
|
+
rateLimits,
|
|
59
|
+
models: models,
|
|
60
|
+
modelRegistry,
|
|
61
|
+
agentMappings
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
return {
|
|
65
|
+
registerModels(models) {
|
|
66
|
+
registry.register(models);
|
|
67
|
+
for (const model of models) {
|
|
68
|
+
rateLimiter.getSnapshot(model);
|
|
69
|
+
}
|
|
70
|
+
},
|
|
71
|
+
async execute(request) {
|
|
72
|
+
const requestId = `${now()}-${Math.random().toString(36).slice(2, 10)}`;
|
|
73
|
+
const startedAt = now();
|
|
74
|
+
const agentName = request.metadata?.agentName ?? "unknown";
|
|
75
|
+
const modelQueue = router.getModelOrderForCapability(request.capability);
|
|
76
|
+
if (modelQueue.length === 0) {
|
|
77
|
+
const latencyMs = now() - startedAt;
|
|
78
|
+
pushRecent({
|
|
79
|
+
requestId,
|
|
80
|
+
agentName,
|
|
81
|
+
capability: String(request.capability),
|
|
82
|
+
modelUsed: "none",
|
|
83
|
+
provider: "none",
|
|
84
|
+
status: "blocked",
|
|
85
|
+
latencyMs
|
|
86
|
+
});
|
|
87
|
+
throw new Error(`No models available for capability: ${String(request.capability)}`);
|
|
88
|
+
}
|
|
89
|
+
const attempts = [];
|
|
90
|
+
const rateLimitBlocks = [];
|
|
91
|
+
for (let attempt = 0; attempt < modelQueue.length; attempt += 1) {
|
|
92
|
+
const modelId = modelQueue[attempt];
|
|
93
|
+
if (modelId === undefined)
|
|
94
|
+
continue;
|
|
95
|
+
const model = registry.getModel(modelId);
|
|
96
|
+
if (!model) {
|
|
97
|
+
rateLimitBlocks.push({ modelId, reason: "Unknown model" });
|
|
98
|
+
continue;
|
|
99
|
+
}
|
|
100
|
+
const provider = config.providers[model.provider];
|
|
101
|
+
if (!provider) {
|
|
102
|
+
rateLimitBlocks.push({ modelId, reason: `No provider adapter registered for: ${model.provider}` });
|
|
103
|
+
continue;
|
|
104
|
+
}
|
|
105
|
+
const decision = rateLimiter.check(model);
|
|
106
|
+
if (!decision.allowed) {
|
|
107
|
+
rateLimitBlocks.push({ modelId, reason: decision.reason ?? "Rate limited" });
|
|
108
|
+
hooks?.onRateLimit?.({
|
|
109
|
+
requestId,
|
|
110
|
+
capability: request.capability,
|
|
111
|
+
modelId,
|
|
112
|
+
provider: model.provider,
|
|
113
|
+
decision
|
|
114
|
+
});
|
|
115
|
+
if (decision.hardStop) {
|
|
116
|
+
const latencyMs = now() - startedAt;
|
|
117
|
+
pushRecent({
|
|
118
|
+
requestId,
|
|
119
|
+
agentName,
|
|
120
|
+
capability: String(request.capability),
|
|
121
|
+
modelUsed: modelId,
|
|
122
|
+
provider: model.provider,
|
|
123
|
+
status: "blocked",
|
|
124
|
+
latencyMs
|
|
125
|
+
});
|
|
126
|
+
throw new Error(decision.reason ?? "Hard stop due to rate limit");
|
|
127
|
+
}
|
|
128
|
+
continue;
|
|
129
|
+
}
|
|
130
|
+
if (!rateLimiter.acquire(model)) {
|
|
131
|
+
rateLimitBlocks.push({ modelId, reason: "Concurrency limit reached" });
|
|
132
|
+
continue;
|
|
133
|
+
}
|
|
134
|
+
const attemptStartedAt = now();
|
|
135
|
+
hooks?.onRequestStart?.({
|
|
136
|
+
requestId,
|
|
137
|
+
capability: request.capability,
|
|
138
|
+
modelId,
|
|
139
|
+
provider: model.provider,
|
|
140
|
+
attempt,
|
|
141
|
+
startedAt: attemptStartedAt
|
|
142
|
+
});
|
|
143
|
+
try {
|
|
144
|
+
// Build options without undefined values for exactOptionalPropertyTypes
|
|
145
|
+
const execOptions = {};
|
|
146
|
+
if (request.options?.temperature !== undefined) {
|
|
147
|
+
execOptions.temperature = request.options.temperature;
|
|
148
|
+
}
|
|
149
|
+
if (request.options?.maxOutputTokens !== undefined) {
|
|
150
|
+
execOptions.maxOutputTokens = request.options.maxOutputTokens;
|
|
151
|
+
}
|
|
152
|
+
if (request.options?.responseFormat !== undefined) {
|
|
153
|
+
execOptions.responseFormat = request.options.responseFormat;
|
|
154
|
+
}
|
|
155
|
+
if (request.options?.useSearch !== undefined) {
|
|
156
|
+
execOptions.useSearch = request.options.useSearch;
|
|
157
|
+
}
|
|
158
|
+
if (request.options?.signal !== undefined) {
|
|
159
|
+
execOptions.signal = request.options.signal;
|
|
160
|
+
}
|
|
161
|
+
const executeRequest = {
|
|
162
|
+
model,
|
|
163
|
+
input: request.input
|
|
164
|
+
};
|
|
165
|
+
if (Object.keys(execOptions).length > 0) {
|
|
166
|
+
executeRequest.options = execOptions;
|
|
167
|
+
}
|
|
168
|
+
const result = await provider.execute(executeRequest);
|
|
169
|
+
rateLimiter.incrementDaily(model);
|
|
170
|
+
const attemptEndedAt = now();
|
|
171
|
+
attempts.push({
|
|
172
|
+
modelId,
|
|
173
|
+
provider: model.provider,
|
|
174
|
+
ok: true,
|
|
175
|
+
startedAt: attemptStartedAt,
|
|
176
|
+
endedAt: attemptEndedAt
|
|
177
|
+
});
|
|
178
|
+
hooks?.onRequestEnd?.({
|
|
179
|
+
requestId,
|
|
180
|
+
capability: request.capability,
|
|
181
|
+
modelId,
|
|
182
|
+
provider: model.provider,
|
|
183
|
+
attempt,
|
|
184
|
+
startedAt: attemptStartedAt,
|
|
185
|
+
endedAt: attemptEndedAt,
|
|
186
|
+
ok: true
|
|
187
|
+
});
|
|
188
|
+
const latencyMs = now() - startedAt;
|
|
189
|
+
const status = attempt === 0 ? "success" : "fallback";
|
|
190
|
+
agentLastUse.set(agentName, {
|
|
191
|
+
capability: request.capability,
|
|
192
|
+
modelId,
|
|
193
|
+
timestamp: now()
|
|
194
|
+
});
|
|
195
|
+
pushRecent({
|
|
196
|
+
requestId,
|
|
197
|
+
agentName,
|
|
198
|
+
capability: String(request.capability),
|
|
199
|
+
modelUsed: modelId,
|
|
200
|
+
provider: model.provider,
|
|
201
|
+
status,
|
|
202
|
+
latencyMs
|
|
203
|
+
});
|
|
204
|
+
return {
|
|
205
|
+
output: result.output,
|
|
206
|
+
modelUsed: modelId,
|
|
207
|
+
provider: model.provider,
|
|
208
|
+
attempts,
|
|
209
|
+
rateLimitBlocks,
|
|
210
|
+
executionTimeMs: latencyMs
|
|
211
|
+
};
|
|
212
|
+
}
|
|
213
|
+
catch (unknownError) {
|
|
214
|
+
const errMsg = String(unknownError?.message ?? "");
|
|
215
|
+
const retryHint = parseRetryAfterMsFromText(errMsg);
|
|
216
|
+
const providerError = normalizeToProviderError(unknownError, model.provider, retryHint !== undefined ? { retryAfterMsHint: retryHint } : undefined);
|
|
217
|
+
const errorInfo = {
|
|
218
|
+
isRateLimit: providerError.isRateLimit === true,
|
|
219
|
+
message: providerError.message
|
|
220
|
+
};
|
|
221
|
+
if (providerError.retryAfterMs !== undefined) {
|
|
222
|
+
errorInfo.retryAfterMs = providerError.retryAfterMs;
|
|
223
|
+
}
|
|
224
|
+
rateLimiter.registerProviderError(model, errorInfo);
|
|
225
|
+
const attemptEndedAt = now();
|
|
226
|
+
attempts.push({
|
|
227
|
+
modelId,
|
|
228
|
+
provider: model.provider,
|
|
229
|
+
ok: false,
|
|
230
|
+
errorMessage: providerError.message,
|
|
231
|
+
startedAt: attemptStartedAt,
|
|
232
|
+
endedAt: attemptEndedAt
|
|
233
|
+
});
|
|
234
|
+
hooks?.onError?.({
|
|
235
|
+
requestId,
|
|
236
|
+
capability: request.capability,
|
|
237
|
+
modelId,
|
|
238
|
+
provider: model.provider,
|
|
239
|
+
error: providerError
|
|
240
|
+
});
|
|
241
|
+
hooks?.onRequestEnd?.({
|
|
242
|
+
requestId,
|
|
243
|
+
capability: request.capability,
|
|
244
|
+
modelId,
|
|
245
|
+
provider: model.provider,
|
|
246
|
+
attempt,
|
|
247
|
+
startedAt: attemptStartedAt,
|
|
248
|
+
endedAt: attemptEndedAt,
|
|
249
|
+
ok: false
|
|
250
|
+
});
|
|
251
|
+
// If there is a next model, emit fallback.
|
|
252
|
+
const next = modelQueue[attempt + 1];
|
|
253
|
+
if (next !== undefined) {
|
|
254
|
+
hooks?.onFallback?.({
|
|
255
|
+
requestId,
|
|
256
|
+
capability: request.capability,
|
|
257
|
+
fromModelId: modelId,
|
|
258
|
+
toModelId: next,
|
|
259
|
+
reason: providerError.message
|
|
260
|
+
});
|
|
261
|
+
continue;
|
|
262
|
+
}
|
|
263
|
+
const latencyMs = now() - startedAt;
|
|
264
|
+
pushRecent({
|
|
265
|
+
requestId,
|
|
266
|
+
agentName,
|
|
267
|
+
capability: String(request.capability),
|
|
268
|
+
modelUsed: modelId,
|
|
269
|
+
provider: model.provider,
|
|
270
|
+
status: "error",
|
|
271
|
+
latencyMs
|
|
272
|
+
});
|
|
273
|
+
throw new Error(`All models failed for capability ${String(request.capability)}. Last error: ${providerError.message}`);
|
|
274
|
+
}
|
|
275
|
+
finally {
|
|
276
|
+
rateLimiter.release(model);
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
const latencyMs = now() - startedAt;
|
|
280
|
+
pushRecent({
|
|
281
|
+
requestId,
|
|
282
|
+
agentName,
|
|
283
|
+
capability: String(request.capability),
|
|
284
|
+
modelUsed: "none",
|
|
285
|
+
provider: "none",
|
|
286
|
+
status: "blocked",
|
|
287
|
+
latencyMs
|
|
288
|
+
});
|
|
289
|
+
throw new Error(`All models exhausted for capability: ${String(request.capability)}`);
|
|
290
|
+
},
|
|
291
|
+
getGatewayState() {
|
|
292
|
+
return snapshot();
|
|
293
|
+
}
|
|
294
|
+
};
|
|
295
|
+
}
|
|
296
|
+
//# sourceMappingURL=createAIGateway.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"createAIGateway.js","sourceRoot":"","sources":["../../src/gateway/createAIGateway.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export { createAIGateway } from "./gateway/createAIGateway.js";
|
|
2
|
+
export type { Gateway, GatewayExecuteRequest, GatewayExecuteResult, GatewayInput, GatewayMessage, GatewayHooks, GatewayStateSnapshot, CapabilityRouter, Capability, ModelDefinition, ProviderAdapter, ProviderExecuteRequest, ProviderExecuteResult, ProviderError, RateLimitDecision, RateLimitSnapshot, RateLimitManagerOptions } from "./types/public.js";
|
|
3
|
+
export { createInMemoryRateLimitManager } from "./rate-limiter/rateLimitManager.js";
|
|
4
|
+
export { createModelRegistry, registerModels } from "./registry/modelRegistry.js";
|
|
5
|
+
export { DEFAULT_CAPABILITY_ROUTING, DEFAULT_GEMINI_MODELS, DEFAULT_GITHUB_MODELS, getDefaultModels, createStaticCapabilityRouter } from "./registry/presets.js";
|
|
6
|
+
export { createGitHubModelsProvider } from "./providers/github-models.js";
|
|
7
|
+
export { createGeminiProvider } from "./providers/gemini.js";
|
|
8
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;AAC/D,YAAY,EACV,OAAO,EACP,qBAAqB,EACrB,oBAAoB,EACpB,YAAY,EACZ,cAAc,EACd,YAAY,EACZ,oBAAoB,EACpB,gBAAgB,EAChB,UAAU,EACV,eAAe,EACf,eAAe,EACf,sBAAsB,EACtB,qBAAqB,EACrB,aAAa,EACb,iBAAiB,EACjB,iBAAiB,EACjB,uBAAuB,EACxB,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EAAE,8BAA8B,EAAE,MAAM,oCAAoC,CAAC;AACpF,OAAO,EAAE,mBAAmB,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAElF,OAAO,EACL,0BAA0B,EAC1B,qBAAqB,EACrB,qBAAqB,EACrB,gBAAgB,EAChB,4BAA4B,EAC7B,MAAM,uBAAuB,CAAC;AAG/B,OAAO,EAAE,0BAA0B,EAAE,MAAM,8BAA8B,CAAC;AAC1E,OAAO,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export { createAIGateway } from "./gateway/createAIGateway.js";
|
|
2
|
+
export { createInMemoryRateLimitManager } from "./rate-limiter/rateLimitManager.js";
|
|
3
|
+
export { createModelRegistry, registerModels } from "./registry/modelRegistry.js";
|
|
4
|
+
export { DEFAULT_CAPABILITY_ROUTING, DEFAULT_GEMINI_MODELS, DEFAULT_GITHUB_MODELS, getDefaultModels, createStaticCapabilityRouter } from "./registry/presets.js";
|
|
5
|
+
// Provider adapters
|
|
6
|
+
export { createGitHubModelsProvider } from "./providers/github-models.js";
|
|
7
|
+
export { createGeminiProvider } from "./providers/gemini.js";
|
|
8
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;AAqB/D,OAAO,EAAE,8BAA8B,EAAE,MAAM,oCAAoC,CAAC;AACpF,OAAO,EAAE,mBAAmB,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAElF,OAAO,EACL,0BAA0B,EAC1B,qBAAqB,EACrB,qBAAqB,EACrB,gBAAgB,EAChB,4BAA4B,EAC7B,MAAM,uBAAuB,CAAC;AAE/B,oBAAoB;AACpB,OAAO,EAAE,0BAA0B,EAAE,MAAM,8BAA8B,CAAC;AAC1E,OAAO,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { ProviderAdapter, ProviderId } from "../types/public.js";
|
|
2
|
+
export interface GeminiProviderConfig {
|
|
3
|
+
id?: ProviderId;
|
|
4
|
+
apiKey: string;
|
|
5
|
+
}
|
|
6
|
+
export declare function createGeminiProvider<C extends string>(_config: GeminiProviderConfig): ProviderAdapter<C>;
|
|
7
|
+
//# sourceMappingURL=gemini.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gemini.d.ts","sourceRoot":"","sources":["../../src/providers/gemini.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAEV,eAAe,EAGf,UAAU,EACX,MAAM,oBAAoB,CAAC;AAE5B,MAAM,WAAW,oBAAoB;IACnC,EAAE,CAAC,EAAE,UAAU,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,wBAAgB,oBAAoB,CAAC,CAAC,SAAS,MAAM,EACnD,OAAO,EAAE,oBAAoB,GAC5B,eAAe,CAAC,CAAC,CAAC,CA+DpB"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
export function createGeminiProvider(_config) {
|
|
2
|
+
const id = _config.id ?? "gemini";
|
|
3
|
+
function toPrompts(input) {
|
|
4
|
+
if (input.kind === "prompt") {
|
|
5
|
+
return { systemPrompt: input.systemPrompt ?? null, userPrompt: input.userPrompt };
|
|
6
|
+
}
|
|
7
|
+
const systemPrompt = input.messages.find((m) => m.role === "system")?.content ?? null;
|
|
8
|
+
const userPrompt = input.messages
|
|
9
|
+
.filter((m) => m.role === "user")
|
|
10
|
+
.map((m) => m.content)
|
|
11
|
+
.join("\n\n");
|
|
12
|
+
return { systemPrompt, userPrompt };
|
|
13
|
+
}
|
|
14
|
+
async function execute(request) {
|
|
15
|
+
// Lazy import so core users don't need the dependency.
|
|
16
|
+
// @ts-expect-error -- peer dependency may not be installed at typecheck time
|
|
17
|
+
const mod = await import("@google/generative-ai");
|
|
18
|
+
const genAI = new mod.GoogleGenerativeAI(_config.apiKey);
|
|
19
|
+
const { systemPrompt, userPrompt } = toPrompts(request.input);
|
|
20
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
21
|
+
const modelConfig = {
|
|
22
|
+
model: request.model.id
|
|
23
|
+
};
|
|
24
|
+
if (systemPrompt !== null) {
|
|
25
|
+
modelConfig.systemInstruction = systemPrompt;
|
|
26
|
+
}
|
|
27
|
+
if (request.options?.useSearch) {
|
|
28
|
+
modelConfig.tools = [{ googleSearch: {} }];
|
|
29
|
+
}
|
|
30
|
+
const model = genAI.getGenerativeModel(modelConfig);
|
|
31
|
+
const responseMimeType = request.options?.responseFormat === "json" && !request.options?.useSearch
|
|
32
|
+
? "application/json"
|
|
33
|
+
: "text/plain";
|
|
34
|
+
const generationConfig = {
|
|
35
|
+
responseMimeType
|
|
36
|
+
};
|
|
37
|
+
if (request.options?.temperature !== undefined) {
|
|
38
|
+
generationConfig.temperature = request.options.temperature;
|
|
39
|
+
}
|
|
40
|
+
const result = await model.generateContent({
|
|
41
|
+
contents: [{ role: "user", parts: [{ text: userPrompt }] }],
|
|
42
|
+
generationConfig
|
|
43
|
+
});
|
|
44
|
+
const text = result.response.text();
|
|
45
|
+
if (!text) {
|
|
46
|
+
throw new Error(`Gemini model [${request.model.id}] returned empty content.`);
|
|
47
|
+
}
|
|
48
|
+
return { output: text };
|
|
49
|
+
}
|
|
50
|
+
return { id, execute };
|
|
51
|
+
}
|
|
52
|
+
//# sourceMappingURL=gemini.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gemini.js","sourceRoot":"","sources":["../../src/providers/gemini.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { ProviderAdapter, ProviderId } from "../types/public.js";
|
|
2
|
+
export interface GitHubModelsProviderConfig {
|
|
3
|
+
id?: ProviderId;
|
|
4
|
+
token: string;
|
|
5
|
+
endpoint?: string;
|
|
6
|
+
modelNameMap?: Record<string, string>;
|
|
7
|
+
}
|
|
8
|
+
export declare function createGitHubModelsProvider<C extends string>(config: GitHubModelsProviderConfig): ProviderAdapter<C>;
|
|
9
|
+
//# sourceMappingURL=github-models.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"github-models.d.ts","sourceRoot":"","sources":["../../src/providers/github-models.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAGV,eAAe,EAGf,UAAU,EACX,MAAM,oBAAoB,CAAC;AAE5B,MAAM,WAAW,0BAA0B;IACzC,EAAE,CAAC,EAAE,UAAU,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACvC;AAED,wBAAgB,0BAA0B,CAAC,CAAC,SAAS,MAAM,EACzD,MAAM,EAAE,0BAA0B,GACjC,eAAe,CAAC,CAAC,CAAC,CAqHpB"}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
export function createGitHubModelsProvider(config) {
|
|
2
|
+
const id = config.id ?? "github";
|
|
3
|
+
const endpoint = config.endpoint ?? "https://models.github.ai/inference/chat/completions";
|
|
4
|
+
const modelNameMap = {
|
|
5
|
+
"Meta-Llama-3.1-405B-Instruct": "meta/Meta-Llama-3.1-405B-Instruct",
|
|
6
|
+
"Llama-3.2-11B-Vision-Instruct": "meta/Llama-3.2-11B-Vision-Instruct",
|
|
7
|
+
"Mistral-Nemo": "mistral-ai/Mistral-Nemo-Instruct-2407",
|
|
8
|
+
...(config.modelNameMap ?? {})
|
|
9
|
+
};
|
|
10
|
+
function toMessages(input) {
|
|
11
|
+
if (input.kind === "chat")
|
|
12
|
+
return input.messages;
|
|
13
|
+
const messages = [];
|
|
14
|
+
if (input.systemPrompt)
|
|
15
|
+
messages.push({ role: "system", content: input.systemPrompt });
|
|
16
|
+
messages.push({ role: "user", content: input.userPrompt });
|
|
17
|
+
return messages;
|
|
18
|
+
}
|
|
19
|
+
function requiresJsonInstruction(modelId, responseFormat) {
|
|
20
|
+
return modelId === "gpt-4o-mini" && responseFormat === "json";
|
|
21
|
+
}
|
|
22
|
+
function ensureJsonInstruction(messages) {
|
|
23
|
+
const hasJson = messages.some((m) => m.content.toLowerCase().includes("json"));
|
|
24
|
+
if (hasJson)
|
|
25
|
+
return messages;
|
|
26
|
+
const systemIndex = messages.findIndex((m) => m.role === "system");
|
|
27
|
+
if (systemIndex >= 0) {
|
|
28
|
+
const existing = messages[systemIndex];
|
|
29
|
+
if (existing) {
|
|
30
|
+
const updated = [...messages];
|
|
31
|
+
updated[systemIndex] = {
|
|
32
|
+
role: existing.role,
|
|
33
|
+
content: `${existing.content}\n\nIMPORTANT: You must output valid JSON.`
|
|
34
|
+
};
|
|
35
|
+
return updated;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
return [{ role: "system", content: "You must output valid JSON." }, ...messages];
|
|
39
|
+
}
|
|
40
|
+
async function execute(request) {
|
|
41
|
+
const model = request.model;
|
|
42
|
+
const apiModelName = modelNameMap[model.id] ?? model.id;
|
|
43
|
+
let messages = toMessages(request.input);
|
|
44
|
+
if (requiresJsonInstruction(model.id, request.options?.responseFormat)) {
|
|
45
|
+
messages = ensureJsonInstruction(messages);
|
|
46
|
+
}
|
|
47
|
+
const payload = {
|
|
48
|
+
model: apiModelName,
|
|
49
|
+
messages,
|
|
50
|
+
stream: false
|
|
51
|
+
};
|
|
52
|
+
// GitHub reasoning models ignore temperature (keep parity with existing behavior)
|
|
53
|
+
const isReasoning = model.id.startsWith("o1") || model.id.startsWith("o3");
|
|
54
|
+
if (!isReasoning && typeof request.options?.temperature === "number") {
|
|
55
|
+
payload.temperature = request.options.temperature;
|
|
56
|
+
}
|
|
57
|
+
if (typeof request.options?.maxOutputTokens === "number") {
|
|
58
|
+
payload.max_tokens = request.options.maxOutputTokens;
|
|
59
|
+
}
|
|
60
|
+
if (request.options?.responseFormat === "json") {
|
|
61
|
+
payload.response_format = { type: "json_object" };
|
|
62
|
+
}
|
|
63
|
+
else if (request.options?.responseFormat === "text") {
|
|
64
|
+
payload.response_format = { type: "text" };
|
|
65
|
+
}
|
|
66
|
+
const fetchOptions = {
|
|
67
|
+
method: "POST",
|
|
68
|
+
headers: {
|
|
69
|
+
"Content-Type": "application/json",
|
|
70
|
+
Authorization: `Bearer ${config.token}`
|
|
71
|
+
},
|
|
72
|
+
body: JSON.stringify(payload)
|
|
73
|
+
};
|
|
74
|
+
if (request.options?.signal) {
|
|
75
|
+
fetchOptions.signal = request.options.signal;
|
|
76
|
+
}
|
|
77
|
+
const response = await fetch(endpoint, fetchOptions);
|
|
78
|
+
if (!response.ok) {
|
|
79
|
+
const errorText = await response.text();
|
|
80
|
+
const err = new Error(`GitHub Models API Error (${model.id}): ${response.status} ${response.statusText} - ${errorText}`);
|
|
81
|
+
err.status = response.status;
|
|
82
|
+
throw err;
|
|
83
|
+
}
|
|
84
|
+
const data = (await response.json());
|
|
85
|
+
const content = data.choices?.[0]?.message?.content ?? null;
|
|
86
|
+
if (!content) {
|
|
87
|
+
throw new Error(`GitHub Model [${model.id}] returned empty content.`);
|
|
88
|
+
}
|
|
89
|
+
return { output: content };
|
|
90
|
+
}
|
|
91
|
+
return { id, execute };
|
|
92
|
+
}
|
|
93
|
+
//# sourceMappingURL=github-models.js.map
|