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.
Files changed (39) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +102 -0
  3. package/dist/gateway/createAIGateway.d.ts +11 -0
  4. package/dist/gateway/createAIGateway.d.ts.map +1 -0
  5. package/dist/gateway/createAIGateway.js +296 -0
  6. package/dist/gateway/createAIGateway.js.map +1 -0
  7. package/dist/index.d.ts +8 -0
  8. package/dist/index.d.ts.map +1 -0
  9. package/dist/index.js +8 -0
  10. package/dist/index.js.map +1 -0
  11. package/dist/providers/gemini.d.ts +7 -0
  12. package/dist/providers/gemini.d.ts.map +1 -0
  13. package/dist/providers/gemini.js +52 -0
  14. package/dist/providers/gemini.js.map +1 -0
  15. package/dist/providers/github-models.d.ts +9 -0
  16. package/dist/providers/github-models.d.ts.map +1 -0
  17. package/dist/providers/github-models.js +93 -0
  18. package/dist/providers/github-models.js.map +1 -0
  19. package/dist/rate-limiter/rateLimitManager.d.ts +16 -0
  20. package/dist/rate-limiter/rateLimitManager.d.ts.map +1 -0
  21. package/dist/rate-limiter/rateLimitManager.js +146 -0
  22. package/dist/rate-limiter/rateLimitManager.js.map +1 -0
  23. package/dist/registry/modelRegistry.d.ts +9 -0
  24. package/dist/registry/modelRegistry.d.ts.map +1 -0
  25. package/dist/registry/modelRegistry.js +20 -0
  26. package/dist/registry/modelRegistry.js.map +1 -0
  27. package/dist/registry/presets.d.ts +7 -0
  28. package/dist/registry/presets.d.ts.map +1 -0
  29. package/dist/registry/presets.js +135 -0
  30. package/dist/registry/presets.js.map +1 -0
  31. package/dist/types/public.d.ts +203 -0
  32. package/dist/types/public.d.ts.map +1 -0
  33. package/dist/types/public.js +2 -0
  34. package/dist/types/public.js.map +1 -0
  35. package/dist/utils/errors.d.ts +6 -0
  36. package/dist/utils/errors.d.ts.map +1 -0
  37. package/dist/utils/errors.js +53 -0
  38. package/dist/utils/errors.js.map +1 -0
  39. 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":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,8BAA8B,CAAC;AACnE,OAAO,EAAE,8BAA8B,EAAE,MAAM,qCAAqC,CAAC;AACrF,OAAO,EAAE,wBAAwB,EAAE,yBAAyB,EAAE,MAAM,oBAAoB,CAAC;AAoCzF,MAAM,UAAU,eAAe,CAC7B,MAAgC;IAEhC,MAAM,GAAG,GAAG,MAAM,CAAC,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC;IAC7C,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC;IAC3B,MAAM,SAAS,GAAG,MAAM,CAAC,iBAAiB,IAAI,GAAG,CAAC;IAElD,MAAM,QAAQ,GAAG,mBAAmB,EAAK,CAAC;IAC1C,MAAM,aAAa,GAAG,MAAM,CAAC,MAAM,IAAI,EAAE,CAAC;IAC1C,QAAQ,CAAC,QAAQ,CAAC,aAAa,CAAC,CAAC;IAEjC,MAAM,WAAW,GAAG,8BAA8B,CAAI,aAAa,EAAE,EAAE,GAAG,EAAE,CAAC,CAAC;IAE9E,MAAM,cAAc,GAAoB,EAAE,CAAC;IAC3C,MAAM,YAAY,GAAG,IAAI,GAAG,EAGzB,CAAC;IAEJ,MAAM,aAAa,GAAwB;QACzC,0BAA0B,CAAC,UAAa;YACtC,MAAM,GAAG,GAAG,QAAQ,CAAC,YAAY,EAAE,CAAC;YACpC,OAAO,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,YAAY,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;QACjF,CAAC;KACF,CAAC;IAEF,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,IAAI,aAAa,CAAC;IAE9C,SAAS,UAAU,CAAC,KAAoB;QACtC,cAAc,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAC3B,IAAI,cAAc,CAAC,MAAM,GAAG,SAAS;YAAE,cAAc,CAAC,KAAK,EAAE,CAAC;IAChE,CAAC;IAED,SAAS,QAAQ;QACf,MAAM,MAAM,GAAG,QAAQ,CAAC,YAAY,EAAE,CAAC;QACvC,MAAM,UAAU,GAAG,WAAW,CAAC,eAAe,EAAE,CAAC;QAEjD,MAAM,mBAAmB,GAAG,IAAI,GAAG,CACjC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;YACpB,CAAC,CAAC,OAAO;YACT,CAAC,CAAC,YAAY,KAAK,WAAW,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,YAAY;SAC5D,CAAC,CACH,CAAC;QAEF,MAAM,aAAa,GAAgC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;YACpE,EAAE,EAAE,CAAC,CAAC,EAAE;YACR,QAAQ,EAAE,CAAC,CAAC,QAAQ;YACpB,IAAI,EAAE,CAAC,CAAC,IAAI,IAAI,EAAE;YAClB,YAAY,EAAE,CAAC,CAAC,YAAiC;YACjD,MAAM,EAAE,CAAC,CAAC,MAAM;YAChB,WAAW,EAAE,CAAC,CAAC,WAAW,KAAK,IAAI;YACnC,YAAY,EAAE,mBAAmB,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,WAAW;SAC3D,CAAC,CAAC,CAAC;QAEJ,MAAM,aAAa,GAA0B,KAAK,CAAC,IAAI,CAAC,YAAY,CAAC,OAAO,EAAE,CAAC;aAC5E,GAAG,CAAC,CAAC,CAAC,SAAS,EAAE,KAAK,CAAC,EAAE,EAAE;YAC1B,MAAM,KAAK,GAAG,MAAM,CAAC,0BAA0B,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;YAClE,OAAO;gBACL,SAAS;gBACT,YAAY,EAAE,CAAC,KAAK,CAAC,UAAoB,CAAC;gBAC1C,aAAa,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC;gBAChC,cAAc,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC;gBAC9B,aAAa,EAAE,KAAK,CAAC,OAAO;gBAC5B,iBAAiB,EAAE,KAAK,CAAC,SAAS;aACnC,CAAC;QACJ,CAAC,CAAC;aACD,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,iBAAiB,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,iBAAiB,IAAI,CAAC,CAAC,CAAC,CAAC;QAE3E,OAAO;YACL,SAAS,EAAE,GAAG,EAAE;YAChB,cAAc,EAAE,CAAC,GAAG,cAAc,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,OAAO,EAAE;YACxD,UAAU;YACV,MAAM,EAAE,MAAoC;YAC5C,aAAa;YACb,aAAa;SACd,CAAC;IACJ,CAAC;IAED,OAAO;QACL,cAAc,CAAC,MAAM;YACnB,QAAQ,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;YAC1B,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;gBAC3B,WAAW,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;YACjC,CAAC;QACH,CAAC;QAED,KAAK,CAAC,OAAO,CAAC,OAAiC;YAC7C,MAAM,SAAS,GAAG,GAAG,GAAG,EAAE,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC;YACxE,MAAM,SAAS,GAAG,GAAG,EAAE,CAAC;YACxB,MAAM,SAAS,GAAG,OAAO,CAAC,QAAQ,EAAE,SAAS,IAAI,SAAS,CAAC;YAE3D,MAAM,UAAU,GAAG,MAAM,CAAC,0BAA0B,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;YACzE,IAAI,UAAU,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBAC5B,MAAM,SAAS,GAAG,GAAG,EAAE,GAAG,SAAS,CAAC;gBACpC,UAAU,CAAC;oBACT,SAAS;oBACT,SAAS;oBACT,UAAU,EAAE,MAAM,CAAC,OAAO,CAAC,UAAU,CAAC;oBACtC,SAAS,EAAE,MAAM;oBACjB,QAAQ,EAAE,MAAM;oBAChB,MAAM,EAAE,SAAS;oBACjB,SAAS;iBACV,CAAC,CAAC;gBACH,MAAM,IAAI,KAAK,CAAC,uCAAuC,MAAM,CAAC,OAAO,CAAC,UAAU,CAAC,EAAE,CAAC,CAAC;YACvF,CAAC;YAED,MAAM,QAAQ,GAOR,EAAE,CAAC;YAET,MAAM,eAAe,GAA0C,EAAE,CAAC;YAElE,KAAK,IAAI,OAAO,GAAG,CAAC,EAAE,OAAO,GAAG,UAAU,CAAC,MAAM,EAAE,OAAO,IAAI,CAAC,EAAE,CAAC;gBAChE,MAAM,OAAO,GAAG,UAAU,CAAC,OAAO,CAAC,CAAC;gBACpC,IAAI,OAAO,KAAK,SAAS;oBAAE,SAAS;gBAEpC,MAAM,KAAK,GAAG,QAAQ,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;gBACzC,IAAI,CAAC,KAAK,EAAE,CAAC;oBACX,eAAe,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,eAAe,EAAE,CAAC,CAAC;oBAC3D,SAAS;gBACX,CAAC;gBAED,MAAM,QAAQ,GAAG,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;gBAClD,IAAI,CAAC,QAAQ,EAAE,CAAC;oBACd,eAAe,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,uCAAuC,KAAK,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;oBACnG,SAAS;gBACX,CAAC;gBAED,MAAM,QAAQ,GAAG,WAAW,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;gBAC1C,IAAI,CAAC,QAAQ,CAAC,OAAO,EAAE,CAAC;oBACtB,eAAe,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,CAAC,MAAM,IAAI,cAAc,EAAE,CAAC,CAAC;oBAC7E,KAAK,EAAE,WAAW,EAAE,CAAC;wBACnB,SAAS;wBACT,UAAU,EAAE,OAAO,CAAC,UAAU;wBAC9B,OAAO;wBACP,QAAQ,EAAE,KAAK,CAAC,QAAQ;wBACxB,QAAQ;qBACT,CAAC,CAAC;oBAEH,IAAI,QAAQ,CAAC,QAAQ,EAAE,CAAC;wBACtB,MAAM,SAAS,GAAG,GAAG,EAAE,GAAG,SAAS,CAAC;wBACpC,UAAU,CAAC;4BACT,SAAS;4BACT,SAAS;4BACT,UAAU,EAAE,MAAM,CAAC,OAAO,CAAC,UAAU,CAAC;4BACtC,SAAS,EAAE,OAAO;4BAClB,QAAQ,EAAE,KAAK,CAAC,QAAQ;4BACxB,MAAM,EAAE,SAAS;4BACjB,SAAS;yBACV,CAAC,CAAC;wBACH,MAAM,IAAI,KAAK,CAAC,QAAQ,CAAC,MAAM,IAAI,6BAA6B,CAAC,CAAC;oBACpE,CAAC;oBAED,SAAS;gBACX,CAAC;gBAED,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;oBAChC,eAAe,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,2BAA2B,EAAE,CAAC,CAAC;oBACvE,SAAS;gBACX,CAAC;gBAED,MAAM,gBAAgB,GAAG,GAAG,EAAE,CAAC;gBAC/B,KAAK,EAAE,cAAc,EAAE,CAAC;oBACtB,SAAS;oBACT,UAAU,EAAE,OAAO,CAAC,UAAU;oBAC9B,OAAO;oBACP,QAAQ,EAAE,KAAK,CAAC,QAAQ;oBACxB,OAAO;oBACP,SAAS,EAAE,gBAAgB;iBAC5B,CAAC,CAAC;gBAEH,IAAI,CAAC;oBACH,wEAAwE;oBACxE,MAAM,WAAW,GAAyC,EAAE,CAAC;oBAC7D,IAAI,OAAO,CAAC,OAAO,EAAE,WAAW,KAAK,SAAS,EAAE,CAAC;wBAC/C,WAAW,CAAC,WAAW,GAAG,OAAO,CAAC,OAAO,CAAC,WAAW,CAAC;oBACxD,CAAC;oBACD,IAAI,OAAO,CAAC,OAAO,EAAE,eAAe,KAAK,SAAS,EAAE,CAAC;wBACnD,WAAW,CAAC,eAAe,GAAG,OAAO,CAAC,OAAO,CAAC,eAAe,CAAC;oBAChE,CAAC;oBACD,IAAI,OAAO,CAAC,OAAO,EAAE,cAAc,KAAK,SAAS,EAAE,CAAC;wBAClD,WAAW,CAAC,cAAc,GAAG,OAAO,CAAC,OAAO,CAAC,cAAc,CAAC;oBAC9D,CAAC;oBACD,IAAI,OAAO,CAAC,OAAO,EAAE,SAAS,KAAK,SAAS,EAAE,CAAC;wBAC7C,WAAW,CAAC,SAAS,GAAG,OAAO,CAAC,OAAO,CAAC,SAAS,CAAC;oBACpD,CAAC;oBACD,IAAI,OAAO,CAAC,OAAO,EAAE,MAAM,KAAK,SAAS,EAAE,CAAC;wBAC1C,WAAW,CAAC,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC;oBAC9C,CAAC;oBAED,MAAM,cAAc,GAA8B;wBAChD,KAAK;wBACL,KAAK,EAAE,OAAO,CAAC,KAAK;qBACrB,CAAC;oBACF,IAAI,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;wBACxC,cAAc,CAAC,OAAO,GAAG,WAAW,CAAC;oBACvC,CAAC;oBAED,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,OAAO,CAAC,cAAc,CAAC,CAAC;oBAEtD,WAAW,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC;oBAElC,MAAM,cAAc,GAAG,GAAG,EAAE,CAAC;oBAC7B,QAAQ,CAAC,IAAI,CAAC;wBACZ,OAAO;wBACP,QAAQ,EAAE,KAAK,CAAC,QAAQ;wBACxB,EAAE,EAAE,IAAI;wBACR,SAAS,EAAE,gBAAgB;wBAC3B,OAAO,EAAE,cAAc;qBACxB,CAAC,CAAC;oBAEH,KAAK,EAAE,YAAY,EAAE,CAAC;wBACpB,SAAS;wBACT,UAAU,EAAE,OAAO,CAAC,UAAU;wBAC9B,OAAO;wBACP,QAAQ,EAAE,KAAK,CAAC,QAAQ;wBACxB,OAAO;wBACP,SAAS,EAAE,gBAAgB;wBAC3B,OAAO,EAAE,cAAc;wBACvB,EAAE,EAAE,IAAI;qBACT,CAAC,CAAC;oBAEH,MAAM,SAAS,GAAG,GAAG,EAAE,GAAG,SAAS,CAAC;oBACpC,MAAM,MAAM,GAA4B,OAAO,KAAK,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,UAAU,CAAC;oBAE/E,YAAY,CAAC,GAAG,CAAC,SAAS,EAAE;wBAC1B,UAAU,EAAE,OAAO,CAAC,UAAU;wBAC9B,OAAO;wBACP,SAAS,EAAE,GAAG,EAAE;qBACjB,CAAC,CAAC;oBAEH,UAAU,CAAC;wBACT,SAAS;wBACT,SAAS;wBACT,UAAU,EAAE,MAAM,CAAC,OAAO,CAAC,UAAU,CAAC;wBACtC,SAAS,EAAE,OAAO;wBAClB,QAAQ,EAAE,KAAK,CAAC,QAAQ;wBACxB,MAAM;wBACN,SAAS;qBACV,CAAC,CAAC;oBAEH,OAAO;wBACL,MAAM,EAAE,MAAM,CAAC,MAAM;wBACrB,SAAS,EAAE,OAAO;wBAClB,QAAQ,EAAE,KAAK,CAAC,QAAQ;wBACxB,QAAQ;wBACR,eAAe;wBACf,eAAe,EAAE,SAAS;qBAC3B,CAAC;gBACJ,CAAC;gBAAC,OAAO,YAAY,EAAE,CAAC;oBACtB,MAAM,MAAM,GAAG,MAAM,CAAE,YAAsC,EAAE,OAAO,IAAI,EAAE,CAAC,CAAC;oBAC9E,MAAM,SAAS,GAAG,yBAAyB,CAAC,MAAM,CAAC,CAAC;oBAEpD,MAAM,aAAa,GAAG,wBAAwB,CAC5C,YAAY,EACZ,KAAK,CAAC,QAAQ,EACd,SAAS,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,gBAAgB,EAAE,SAAS,EAAE,CAAC,CAAC,CAAC,SAAS,CACtE,CAAC;oBAEF,MAAM,SAAS,GAAqE;wBAClF,WAAW,EAAE,aAAa,CAAC,WAAW,KAAK,IAAI;wBAC/C,OAAO,EAAE,aAAa,CAAC,OAAO;qBAC/B,CAAC;oBACF,IAAI,aAAa,CAAC,YAAY,KAAK,SAAS,EAAE,CAAC;wBAC7C,SAAS,CAAC,YAAY,GAAG,aAAa,CAAC,YAAY,CAAC;oBACtD,CAAC;oBACD,WAAW,CAAC,qBAAqB,CAAC,KAAK,EAAE,SAAS,CAAC,CAAC;oBAEpD,MAAM,cAAc,GAAG,GAAG,EAAE,CAAC;oBAC7B,QAAQ,CAAC,IAAI,CAAC;wBACZ,OAAO;wBACP,QAAQ,EAAE,KAAK,CAAC,QAAQ;wBACxB,EAAE,EAAE,KAAK;wBACT,YAAY,EAAE,aAAa,CAAC,OAAO;wBACnC,SAAS,EAAE,gBAAgB;wBAC3B,OAAO,EAAE,cAAc;qBACxB,CAAC,CAAC;oBAEH,KAAK,EAAE,OAAO,EAAE,CAAC;wBACf,SAAS;wBACT,UAAU,EAAE,OAAO,CAAC,UAAU;wBAC9B,OAAO;wBACP,QAAQ,EAAE,KAAK,CAAC,QAAQ;wBACxB,KAAK,EAAE,aAAa;qBACrB,CAAC,CAAC;oBAEH,KAAK,EAAE,YAAY,EAAE,CAAC;wBACpB,SAAS;wBACT,UAAU,EAAE,OAAO,CAAC,UAAU;wBAC9B,OAAO;wBACP,QAAQ,EAAE,KAAK,CAAC,QAAQ;wBACxB,OAAO;wBACP,SAAS,EAAE,gBAAgB;wBAC3B,OAAO,EAAE,cAAc;wBACvB,EAAE,EAAE,KAAK;qBACV,CAAC,CAAC;oBAEH,2CAA2C;oBAC3C,MAAM,IAAI,GAAG,UAAU,CAAC,OAAO,GAAG,CAAC,CAAC,CAAC;oBACrC,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;wBACvB,KAAK,EAAE,UAAU,EAAE,CAAC;4BAClB,SAAS;4BACT,UAAU,EAAE,OAAO,CAAC,UAAU;4BAC9B,WAAW,EAAE,OAAO;4BACpB,SAAS,EAAE,IAAI;4BACf,MAAM,EAAE,aAAa,CAAC,OAAO;yBAC9B,CAAC,CAAC;wBACH,SAAS;oBACX,CAAC;oBAED,MAAM,SAAS,GAAG,GAAG,EAAE,GAAG,SAAS,CAAC;oBACpC,UAAU,CAAC;wBACT,SAAS;wBACT,SAAS;wBACT,UAAU,EAAE,MAAM,CAAC,OAAO,CAAC,UAAU,CAAC;wBACtC,SAAS,EAAE,OAAO;wBAClB,QAAQ,EAAE,KAAK,CAAC,QAAQ;wBACxB,MAAM,EAAE,OAAO;wBACf,SAAS;qBACV,CAAC,CAAC;oBAEH,MAAM,IAAI,KAAK,CACb,oCAAoC,MAAM,CAAC,OAAO,CAAC,UAAU,CAAC,iBAAiB,aAAa,CAAC,OAAO,EAAE,CACvG,CAAC;gBACJ,CAAC;wBAAS,CAAC;oBACT,WAAW,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;gBAC7B,CAAC;YACH,CAAC;YAED,MAAM,SAAS,GAAG,GAAG,EAAE,GAAG,SAAS,CAAC;YACpC,UAAU,CAAC;gBACT,SAAS;gBACT,SAAS;gBACT,UAAU,EAAE,MAAM,CAAC,OAAO,CAAC,UAAU,CAAC;gBACtC,SAAS,EAAE,MAAM;gBACjB,QAAQ,EAAE,MAAM;gBAChB,MAAM,EAAE,SAAS;gBACjB,SAAS;aACV,CAAC,CAAC;YAEH,MAAM,IAAI,KAAK,CAAC,wCAAwC,MAAM,CAAC,OAAO,CAAC,UAAU,CAAC,EAAE,CAAC,CAAC;QACxF,CAAC;QAED,eAAe;YACb,OAAO,QAAQ,EAAE,CAAC;QACpB,CAAC;KACF,CAAC;AACJ,CAAC"}
@@ -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