@yan162/changewayguard 6.8.26 → 6.8.27

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 (45) hide show
  1. package/dist/gateway/dist/activity.d.ts +52 -0
  2. package/dist/gateway/dist/activity.d.ts.map +1 -0
  3. package/dist/gateway/dist/activity.js +111 -0
  4. package/dist/gateway/dist/activity.js.map +1 -0
  5. package/dist/gateway/dist/config.d.ts +50 -0
  6. package/dist/gateway/dist/config.d.ts.map +1 -0
  7. package/dist/gateway/dist/config.js +200 -0
  8. package/dist/gateway/dist/config.js.map +1 -0
  9. package/dist/gateway/dist/handlers/anthropic.d.ts +12 -0
  10. package/dist/gateway/dist/handlers/anthropic.d.ts.map +1 -0
  11. package/dist/gateway/dist/handlers/anthropic.js +254 -0
  12. package/dist/gateway/dist/handlers/anthropic.js.map +1 -0
  13. package/dist/gateway/dist/handlers/gemini.d.ts +12 -0
  14. package/dist/gateway/dist/handlers/gemini.d.ts.map +1 -0
  15. package/dist/gateway/dist/handlers/gemini.js +101 -0
  16. package/dist/gateway/dist/handlers/gemini.js.map +1 -0
  17. package/dist/gateway/dist/handlers/models.d.ts +4 -0
  18. package/dist/gateway/dist/handlers/models.d.ts.map +1 -0
  19. package/dist/gateway/dist/handlers/models.js +36 -0
  20. package/dist/gateway/dist/handlers/models.js.map +1 -0
  21. package/dist/gateway/dist/handlers/openai.d.ts +16 -0
  22. package/dist/gateway/dist/handlers/openai.d.ts.map +1 -0
  23. package/dist/gateway/dist/handlers/openai.js +254 -0
  24. package/dist/gateway/dist/handlers/openai.js.map +1 -0
  25. package/dist/gateway/dist/index.d.ts +27 -0
  26. package/dist/gateway/dist/index.d.ts.map +1 -0
  27. package/dist/gateway/dist/index.js +290 -0
  28. package/dist/gateway/dist/index.js.map +1 -0
  29. package/dist/gateway/dist/mapping-store.d.ts +38 -0
  30. package/dist/gateway/dist/mapping-store.d.ts.map +1 -0
  31. package/dist/gateway/dist/mapping-store.js +74 -0
  32. package/dist/gateway/dist/mapping-store.js.map +1 -0
  33. package/dist/gateway/dist/restorer.d.ts +63 -0
  34. package/dist/gateway/dist/restorer.d.ts.map +1 -0
  35. package/dist/gateway/dist/restorer.js +284 -0
  36. package/dist/gateway/dist/restorer.js.map +1 -0
  37. package/dist/gateway/dist/sanitizer.d.ts +17 -0
  38. package/dist/gateway/dist/sanitizer.d.ts.map +1 -0
  39. package/dist/gateway/dist/sanitizer.js +228 -0
  40. package/dist/gateway/dist/sanitizer.js.map +1 -0
  41. package/dist/gateway/dist/types.d.ts +53 -0
  42. package/dist/gateway/dist/types.d.ts.map +1 -0
  43. package/dist/gateway/dist/types.js +5 -0
  44. package/dist/gateway/dist/types.js.map +1 -0
  45. package/package.json +1 -1
@@ -0,0 +1,254 @@
1
+ /**
2
+ * AI Security Gateway - Anthropic Messages API handler
3
+ *
4
+ * Handles POST /v1/messages requests in Anthropic's native format.
5
+ */
6
+ import { sanitize } from "../sanitizer.js";
7
+ import { restore, createStreamRestorer } from "../restorer.js";
8
+ import { generateRequestId, logSanitizeEvent, logRestoreEvent } from "../activity.js";
9
+ /**
10
+ * Handle Anthropic API request
11
+ */
12
+ export async function handleAnthropicRequest(req, res, backend) {
13
+ try {
14
+ const requestId = generateRequestId();
15
+ const sanitizeStart = Date.now();
16
+ // 1. Parse request body
17
+ const body = await readBody(req);
18
+ const requestData = JSON.parse(body);
19
+ const { model, messages, system, tools, max_tokens, temperature, stream = false, ...rest } = requestData;
20
+ // 2. Sanitize messages
21
+ const { sanitized: sanitizedMessages, mappingTable, redactionCount } = sanitize(messages);
22
+ // 3. Sanitize system prompt if present
23
+ let systemRedactionCount = 0;
24
+ const sanitizedSystem = system
25
+ ? (() => {
26
+ const result = sanitize(system);
27
+ systemRedactionCount = result.redactionCount;
28
+ return result.sanitized;
29
+ })()
30
+ : system;
31
+ const totalRedactionCount = redactionCount + systemRedactionCount;
32
+ // Log sanitization event
33
+ if (totalRedactionCount > 0) {
34
+ logSanitizeEvent({
35
+ requestId,
36
+ backend: "anthropic",
37
+ endpoint: "/v1/messages",
38
+ model,
39
+ mappingTable,
40
+ redactionCount: totalRedactionCount,
41
+ durationMs: Date.now() - sanitizeStart,
42
+ });
43
+ }
44
+ // Note: We reuse the same mapping table so placeholders are consistent
45
+ // Debug: log what was sanitized
46
+ if (totalRedactionCount > 0) {
47
+ console.log(`[ai-security-gateway] Sanitized ${totalRedactionCount} items`);
48
+ }
49
+ // 4. Build sanitized request
50
+ const sanitizedRequest = {
51
+ model,
52
+ messages: sanitizedMessages,
53
+ ...(system && { system: sanitizedSystem }),
54
+ ...(tools && { tools }),
55
+ max_tokens,
56
+ ...(temperature !== undefined && { temperature }),
57
+ stream,
58
+ ...rest,
59
+ };
60
+ // 5. Forward to real Anthropic API
61
+ // Note: baseUrl already includes the full path prefix (e.g., /v1)
62
+ const apiUrl = `${backend.baseUrl}/messages`;
63
+ const response = await fetch(apiUrl, {
64
+ method: "POST",
65
+ headers: {
66
+ "Content-Type": "application/json",
67
+ "anthropic-version": req.headers["anthropic-version"] || "2023-06-01",
68
+ "x-api-key": backend.apiKey,
69
+ },
70
+ body: JSON.stringify(sanitizedRequest),
71
+ });
72
+ if (!response.ok) {
73
+ // Forward error response
74
+ res.writeHead(response.status, { "Content-Type": "application/json" });
75
+ const errorBody = await response.text();
76
+ res.end(errorBody);
77
+ return;
78
+ }
79
+ // 7. Handle streaming or non-streaming response
80
+ if (stream) {
81
+ await handleAnthropicStream(response, res, mappingTable, requestId, model);
82
+ }
83
+ else {
84
+ await handleAnthropicNonStream(response, res, mappingTable, requestId, model);
85
+ }
86
+ }
87
+ catch (error) {
88
+ console.error("[ai-security-gateway] Anthropic handler error:", error);
89
+ res.writeHead(500, { "Content-Type": "application/json" });
90
+ res.end(JSON.stringify({
91
+ error: "Internal gateway error",
92
+ message: error instanceof Error ? error.message : String(error),
93
+ }));
94
+ }
95
+ }
96
+ /**
97
+ * Handle streaming response with smart placeholder restoration
98
+ *
99
+ * Uses StreamRestorer to detect `__` and buffer potential placeholders.
100
+ * Only buffers when necessary, maintaining streaming UX.
101
+ */
102
+ async function handleAnthropicStream(response, res, mappingTable, requestId, model) {
103
+ const restoreStart = Date.now();
104
+ // Debug: log mapping table size
105
+ if (mappingTable.size > 0) {
106
+ console.log(`[ai-security-gateway] Streaming with ${mappingTable.size} placeholders to restore`);
107
+ }
108
+ // Set SSE headers
109
+ res.writeHead(200, {
110
+ "Content-Type": "text/event-stream",
111
+ "Cache-Control": "no-cache",
112
+ "Connection": "keep-alive",
113
+ });
114
+ const reader = response.body?.getReader();
115
+ if (!reader) {
116
+ res.end();
117
+ return;
118
+ }
119
+ const decoder = new TextDecoder();
120
+ let lineBuffer = "";
121
+ // Create stream restorer for text content
122
+ const streamRestorer = createStreamRestorer(mappingTable);
123
+ try {
124
+ while (true) {
125
+ const { done, value } = await reader.read();
126
+ if (done)
127
+ break;
128
+ // Decode chunk
129
+ lineBuffer += decoder.decode(value, { stream: true });
130
+ // Process complete lines
131
+ const lines = lineBuffer.split("\n");
132
+ lineBuffer = lines.pop() || ""; // Keep incomplete line in buffer
133
+ for (const line of lines) {
134
+ if (!line.trim()) {
135
+ res.write("\n");
136
+ continue;
137
+ }
138
+ // Handle event lines (pass through)
139
+ if (line.startsWith("event:")) {
140
+ res.write(line + "\n");
141
+ continue;
142
+ }
143
+ // Handle data lines
144
+ if (!line.startsWith("data: ")) {
145
+ res.write(line + "\n");
146
+ continue;
147
+ }
148
+ const dataContent = line.slice(6);
149
+ try {
150
+ const parsed = JSON.parse(dataContent);
151
+ // Check for text delta
152
+ if (parsed.type === "content_block_delta" && parsed.delta?.type === "text_delta") {
153
+ const textContent = parsed.delta.text;
154
+ if (textContent !== undefined && mappingTable.size > 0) {
155
+ // Process text through stream restorer
156
+ const restored = streamRestorer.process(textContent);
157
+ if (restored.length > 0) {
158
+ // We have restorable content - output it
159
+ const restoredChunk = {
160
+ ...parsed,
161
+ delta: { ...parsed.delta, text: restored },
162
+ };
163
+ res.write(`data: ${JSON.stringify(restoredChunk)}\n`);
164
+ }
165
+ // If restorer is buffering, don't output anything yet
166
+ }
167
+ else {
168
+ // No text content or no mappings - pass through
169
+ res.write(line + "\n");
170
+ }
171
+ }
172
+ else {
173
+ // Non-text events - pass through
174
+ res.write(line + "\n");
175
+ }
176
+ }
177
+ catch {
178
+ // Not valid JSON, pass through
179
+ res.write(line + "\n");
180
+ }
181
+ }
182
+ }
183
+ // Write any remaining line buffer
184
+ if (lineBuffer.trim()) {
185
+ res.write(lineBuffer + "\n");
186
+ }
187
+ // Finalize stream restorer - flush any remaining buffered content
188
+ const finalContent = streamRestorer.finalize();
189
+ if (finalContent.length > 0) {
190
+ // Create a final text delta chunk with remaining content
191
+ const finalChunk = {
192
+ type: "content_block_delta",
193
+ index: 0,
194
+ delta: { type: "text_delta", text: finalContent },
195
+ };
196
+ res.write(`data: ${JSON.stringify(finalChunk)}\n`);
197
+ }
198
+ // Log restoration event
199
+ if (mappingTable.size > 0) {
200
+ logRestoreEvent({
201
+ requestId,
202
+ backend: "anthropic",
203
+ endpoint: "/v1/messages",
204
+ model,
205
+ mappingTable,
206
+ restorationCount: mappingTable.size,
207
+ durationMs: Date.now() - restoreStart,
208
+ });
209
+ }
210
+ res.end();
211
+ }
212
+ catch (error) {
213
+ console.error("[ai-security-gateway] Stream error:", error);
214
+ res.end();
215
+ }
216
+ }
217
+ /**
218
+ * Handle non-streaming response
219
+ */
220
+ async function handleAnthropicNonStream(response, res, mappingTable, requestId, model) {
221
+ const restoreStart = Date.now();
222
+ const responseBody = await response.text();
223
+ const responseData = JSON.parse(responseBody);
224
+ // Restore placeholders in response
225
+ const restoredData = restore(responseData, mappingTable);
226
+ // Log restoration event
227
+ if (mappingTable.size > 0) {
228
+ logRestoreEvent({
229
+ requestId,
230
+ backend: "anthropic",
231
+ endpoint: "/v1/messages",
232
+ model,
233
+ mappingTable,
234
+ restorationCount: mappingTable.size,
235
+ durationMs: Date.now() - restoreStart,
236
+ });
237
+ }
238
+ res.writeHead(200, { "Content-Type": "application/json" });
239
+ res.end(JSON.stringify(restoredData));
240
+ }
241
+ /**
242
+ * Read request body as string
243
+ */
244
+ function readBody(req) {
245
+ return new Promise((resolve, reject) => {
246
+ let body = "";
247
+ req.on("data", (chunk) => {
248
+ body += chunk.toString();
249
+ });
250
+ req.on("end", () => resolve(body));
251
+ req.on("error", reject);
252
+ });
253
+ }
254
+ //# sourceMappingURL=anthropic.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"anthropic.js","sourceRoot":"","sources":["../../src/handlers/anthropic.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH,OAAO,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAC3C,OAAO,EAAE,OAAO,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAC;AAC/D,OAAO,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAEtF;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,sBAAsB,CAC1C,GAAoB,EACpB,GAAmB,EACnB,OAAsB;IAEtB,IAAI,CAAC;QACH,MAAM,SAAS,GAAG,iBAAiB,EAAE,CAAC;QACtC,MAAM,aAAa,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAEjC,wBAAwB;QACxB,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,GAAG,CAAC,CAAC;QACjC,MAAM,WAAW,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAErC,MAAM,EACJ,KAAK,EACL,QAAQ,EACR,MAAM,EACN,KAAK,EACL,UAAU,EACV,WAAW,EACX,MAAM,GAAG,KAAK,EACd,GAAG,IAAI,EACR,GAAG,WAAW,CAAC;QAEhB,uBAAuB;QACvB,MAAM,EAAE,SAAS,EAAE,iBAAiB,EAAE,YAAY,EAAE,cAAc,EAAE,GAAG,QAAQ,CAAC,QAAQ,CAAC,CAAC;QAE1F,uCAAuC;QACvC,IAAI,oBAAoB,GAAG,CAAC,CAAC;QAC7B,MAAM,eAAe,GAAG,MAAM;YAC5B,CAAC,CAAC,CAAC,GAAG,EAAE;gBACJ,MAAM,MAAM,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC;gBAChC,oBAAoB,GAAG,MAAM,CAAC,cAAc,CAAC;gBAC7C,OAAO,MAAM,CAAC,SAAS,CAAC;YAC1B,CAAC,CAAC,EAAE;YACN,CAAC,CAAC,MAAM,CAAC;QAEX,MAAM,mBAAmB,GAAG,cAAc,GAAG,oBAAoB,CAAC;QAElE,yBAAyB;QACzB,IAAI,mBAAmB,GAAG,CAAC,EAAE,CAAC;YAC5B,gBAAgB,CAAC;gBACf,SAAS;gBACT,OAAO,EAAE,WAAW;gBACpB,QAAQ,EAAE,cAAc;gBACxB,KAAK;gBACL,YAAY;gBACZ,cAAc,EAAE,mBAAmB;gBACnC,UAAU,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,aAAa;aACvC,CAAC,CAAC;QACL,CAAC;QAED,uEAAuE;QAEvE,gCAAgC;QAChC,IAAI,mBAAmB,GAAG,CAAC,EAAE,CAAC;YAC5B,OAAO,CAAC,GAAG,CAAC,mCAAmC,mBAAmB,QAAQ,CAAC,CAAC;QAC9E,CAAC;QAED,6BAA6B;QAC7B,MAAM,gBAAgB,GAAG;YACvB,KAAK;YACL,QAAQ,EAAE,iBAAiB;YAC3B,GAAG,CAAC,MAAM,IAAI,EAAE,MAAM,EAAE,eAAe,EAAE,CAAC;YAC1C,GAAG,CAAC,KAAK,IAAI,EAAE,KAAK,EAAE,CAAC;YACvB,UAAU;YACV,GAAG,CAAC,WAAW,KAAK,SAAS,IAAI,EAAE,WAAW,EAAE,CAAC;YACjD,MAAM;YACN,GAAG,IAAI;SACR,CAAC;QAEF,mCAAmC;QACnC,kEAAkE;QAClE,MAAM,MAAM,GAAG,GAAG,OAAO,CAAC,OAAO,WAAW,CAAC;QAC7C,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,MAAM,EAAE;YACnC,MAAM,EAAE,MAAM;YACd,OAAO,EAAE;gBACP,cAAc,EAAE,kBAAkB;gBAClC,mBAAmB,EAAE,GAAG,CAAC,OAAO,CAAC,mBAAmB,CAAW,IAAI,YAAY;gBAC/E,WAAW,EAAE,OAAO,CAAC,MAAM;aAC5B;YACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,gBAAgB,CAAC;SACvC,CAAC,CAAC;QAEH,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;YACjB,yBAAyB;YACzB,GAAG,CAAC,SAAS,CAAC,QAAQ,CAAC,MAAM,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE,CAAC,CAAC;YACvE,MAAM,SAAS,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;YACxC,GAAG,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;YACnB,OAAO;QACT,CAAC;QAED,gDAAgD;QAChD,IAAI,MAAM,EAAE,CAAC;YACX,MAAM,qBAAqB,CAAC,QAAQ,EAAE,GAAG,EAAE,YAAY,EAAE,SAAS,EAAE,KAAK,CAAC,CAAC;QAC7E,CAAC;aAAM,CAAC;YACN,MAAM,wBAAwB,CAAC,QAAQ,EAAE,GAAG,EAAE,YAAY,EAAE,SAAS,EAAE,KAAK,CAAC,CAAC;QAChF,CAAC;IACH,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,KAAK,CAAC,gDAAgD,EAAE,KAAK,CAAC,CAAC;QACvE,GAAG,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE,CAAC,CAAC;QAC3D,GAAG,CAAC,GAAG,CACL,IAAI,CAAC,SAAS,CAAC;YACb,KAAK,EAAE,wBAAwB;YAC/B,OAAO,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC;SAChE,CAAC,CACH,CAAC;IACJ,CAAC;AACH,CAAC;AAED;;;;;GAKG;AACH,KAAK,UAAU,qBAAqB,CAClC,QAAkB,EAClB,GAAmB,EACnB,YAA0B,EAC1B,SAAiB,EACjB,KAAc;IAEd,MAAM,YAAY,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IAEhC,gCAAgC;IAChC,IAAI,YAAY,CAAC,IAAI,GAAG,CAAC,EAAE,CAAC;QAC1B,OAAO,CAAC,GAAG,CAAC,wCAAwC,YAAY,CAAC,IAAI,0BAA0B,CAAC,CAAC;IACnG,CAAC;IAED,kBAAkB;IAClB,GAAG,CAAC,SAAS,CAAC,GAAG,EAAE;QACjB,cAAc,EAAE,mBAAmB;QACnC,eAAe,EAAE,UAAU;QAC3B,YAAY,EAAE,YAAY;KAC3B,CAAC,CAAC;IAEH,MAAM,MAAM,GAAG,QAAQ,CAAC,IAAI,EAAE,SAAS,EAAE,CAAC;IAC1C,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,GAAG,CAAC,GAAG,EAAE,CAAC;QACV,OAAO;IACT,CAAC;IAED,MAAM,OAAO,GAAG,IAAI,WAAW,EAAE,CAAC;IAClC,IAAI,UAAU,GAAG,EAAE,CAAC;IAEpB,0CAA0C;IAC1C,MAAM,cAAc,GAAG,oBAAoB,CAAC,YAAY,CAAC,CAAC;IAE1D,IAAI,CAAC;QACH,OAAO,IAAI,EAAE,CAAC;YACZ,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,MAAM,MAAM,CAAC,IAAI,EAAE,CAAC;YAC5C,IAAI,IAAI;gBAAE,MAAM;YAEhB,eAAe;YACf,UAAU,IAAI,OAAO,CAAC,MAAM,CAAC,KAAK,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;YAEtD,yBAAyB;YACzB,MAAM,KAAK,GAAG,UAAU,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;YACrC,UAAU,GAAG,KAAK,CAAC,GAAG,EAAE,IAAI,EAAE,CAAC,CAAC,iCAAiC;YAEjE,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;gBACzB,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,EAAE,CAAC;oBACjB,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;oBAChB,SAAS;gBACX,CAAC;gBAED,oCAAoC;gBACpC,IAAI,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;oBAC9B,GAAG,CAAC,KAAK,CAAC,IAAI,GAAG,IAAI,CAAC,CAAC;oBACvB,SAAS;gBACX,CAAC;gBAED,oBAAoB;gBACpB,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;oBAC/B,GAAG,CAAC,KAAK,CAAC,IAAI,GAAG,IAAI,CAAC,CAAC;oBACvB,SAAS;gBACX,CAAC;gBAED,MAAM,WAAW,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;gBAElC,IAAI,CAAC;oBACH,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,WAAW,CAAsB,CAAC;oBAE5D,uBAAuB;oBACvB,IAAI,MAAM,CAAC,IAAI,KAAK,qBAAqB,IAAI,MAAM,CAAC,KAAK,EAAE,IAAI,KAAK,YAAY,EAAE,CAAC;wBACjF,MAAM,WAAW,GAAG,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC;wBAEtC,IAAI,WAAW,KAAK,SAAS,IAAI,YAAY,CAAC,IAAI,GAAG,CAAC,EAAE,CAAC;4BACvD,uCAAuC;4BACvC,MAAM,QAAQ,GAAG,cAAc,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC;4BAErD,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gCACxB,yCAAyC;gCACzC,MAAM,aAAa,GAAG;oCACpB,GAAG,MAAM;oCACT,KAAK,EAAE,EAAE,GAAG,MAAM,CAAC,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE;iCAC3C,CAAC;gCACF,GAAG,CAAC,KAAK,CAAC,SAAS,IAAI,CAAC,SAAS,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC;4BACxD,CAAC;4BACD,sDAAsD;wBACxD,CAAC;6BAAM,CAAC;4BACN,gDAAgD;4BAChD,GAAG,CAAC,KAAK,CAAC,IAAI,GAAG,IAAI,CAAC,CAAC;wBACzB,CAAC;oBACH,CAAC;yBAAM,CAAC;wBACN,iCAAiC;wBACjC,GAAG,CAAC,KAAK,CAAC,IAAI,GAAG,IAAI,CAAC,CAAC;oBACzB,CAAC;gBACH,CAAC;gBAAC,MAAM,CAAC;oBACP,+BAA+B;oBAC/B,GAAG,CAAC,KAAK,CAAC,IAAI,GAAG,IAAI,CAAC,CAAC;gBACzB,CAAC;YACH,CAAC;QACH,CAAC;QAED,kCAAkC;QAClC,IAAI,UAAU,CAAC,IAAI,EAAE,EAAE,CAAC;YACtB,GAAG,CAAC,KAAK,CAAC,UAAU,GAAG,IAAI,CAAC,CAAC;QAC/B,CAAC;QAED,kEAAkE;QAClE,MAAM,YAAY,GAAG,cAAc,CAAC,QAAQ,EAAE,CAAC;QAC/C,IAAI,YAAY,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC5B,yDAAyD;YACzD,MAAM,UAAU,GAAsB;gBACpC,IAAI,EAAE,qBAAqB;gBAC3B,KAAK,EAAE,CAAC;gBACR,KAAK,EAAE,EAAE,IAAI,EAAE,YAAY,EAAE,IAAI,EAAE,YAAY,EAAE;aAClD,CAAC;YACF,GAAG,CAAC,KAAK,CAAC,SAAS,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;QACrD,CAAC;QAED,wBAAwB;QACxB,IAAI,YAAY,CAAC,IAAI,GAAG,CAAC,EAAE,CAAC;YAC1B,eAAe,CAAC;gBACd,SAAS;gBACT,OAAO,EAAE,WAAW;gBACpB,QAAQ,EAAE,cAAc;gBACxB,KAAK;gBACL,YAAY;gBACZ,gBAAgB,EAAE,YAAY,CAAC,IAAI;gBACnC,UAAU,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,YAAY;aACtC,CAAC,CAAC;QACL,CAAC;QAED,GAAG,CAAC,GAAG,EAAE,CAAC;IACZ,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,KAAK,CAAC,qCAAqC,EAAE,KAAK,CAAC,CAAC;QAC5D,GAAG,CAAC,GAAG,EAAE,CAAC;IACZ,CAAC;AACH,CAAC;AAeD;;GAEG;AACH,KAAK,UAAU,wBAAwB,CACrC,QAAkB,EAClB,GAAmB,EACnB,YAA0B,EAC1B,SAAiB,EACjB,KAAc;IAEd,MAAM,YAAY,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IAChC,MAAM,YAAY,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;IAC3C,MAAM,YAAY,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC;IAE9C,mCAAmC;IACnC,MAAM,YAAY,GAAG,OAAO,CAAC,YAAY,EAAE,YAAY,CAAC,CAAC;IAEzD,wBAAwB;IACxB,IAAI,YAAY,CAAC,IAAI,GAAG,CAAC,EAAE,CAAC;QAC1B,eAAe,CAAC;YACd,SAAS;YACT,OAAO,EAAE,WAAW;YACpB,QAAQ,EAAE,cAAc;YACxB,KAAK;YACL,YAAY;YACZ,gBAAgB,EAAE,YAAY,CAAC,IAAI;YACnC,UAAU,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,YAAY;SACtC,CAAC,CAAC;IACL,CAAC;IAED,GAAG,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE,CAAC,CAAC;IAC3D,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,YAAY,CAAC,CAAC,CAAC;AACxC,CAAC;AAED;;GAEG;AACH,SAAS,QAAQ,CAAC,GAAoB;IACpC,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACrC,IAAI,IAAI,GAAG,EAAE,CAAC;QACd,GAAG,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,KAAK,EAAE,EAAE;YACvB,IAAI,IAAI,KAAK,CAAC,QAAQ,EAAE,CAAC;QAC3B,CAAC,CAAC,CAAC;QACH,GAAG,CAAC,EAAE,CAAC,KAAK,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;QACnC,GAAG,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;IAC1B,CAAC,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,12 @@
1
+ /**
2
+ * AI Security Gateway - Google Gemini API handler
3
+ *
4
+ * Handles POST /v1/models/:model:generateContent requests in Gemini's format.
5
+ */
6
+ import type { IncomingMessage, ServerResponse } from "node:http";
7
+ import type { BackendConfig } from "../types.js";
8
+ /**
9
+ * Handle Gemini API request
10
+ */
11
+ export declare function handleGeminiRequest(req: IncomingMessage, res: ServerResponse, backend: BackendConfig, modelName: string): Promise<void>;
12
+ //# sourceMappingURL=gemini.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gemini.d.ts","sourceRoot":"","sources":["../../src/handlers/gemini.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AACjE,OAAO,KAAK,EAAE,aAAa,EAAgB,MAAM,aAAa,CAAC;AAK/D;;GAEG;AACH,wBAAsB,mBAAmB,CACvC,GAAG,EAAE,eAAe,EACpB,GAAG,EAAE,cAAc,EACnB,OAAO,EAAE,aAAa,EACtB,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,IAAI,CAAC,CAuFf"}
@@ -0,0 +1,101 @@
1
+ /**
2
+ * AI Security Gateway - Google Gemini API handler
3
+ *
4
+ * Handles POST /v1/models/:model:generateContent requests in Gemini's format.
5
+ */
6
+ import { sanitize } from "../sanitizer.js";
7
+ import { restore } from "../restorer.js";
8
+ import { generateRequestId, logSanitizeEvent, logRestoreEvent } from "../activity.js";
9
+ /**
10
+ * Handle Gemini API request
11
+ */
12
+ export async function handleGeminiRequest(req, res, backend, modelName) {
13
+ try {
14
+ const requestId = generateRequestId();
15
+ const sanitizeStart = Date.now();
16
+ // 1. Parse request body
17
+ const body = await readBody(req);
18
+ const requestData = JSON.parse(body);
19
+ const { contents, tools, generationConfig, ...rest } = requestData;
20
+ // 2. Sanitize contents (Gemini uses "contents" instead of "messages")
21
+ const { sanitized: sanitizedContents, mappingTable, redactionCount } = sanitize(contents);
22
+ // Log sanitization event
23
+ if (redactionCount > 0) {
24
+ logSanitizeEvent({
25
+ requestId,
26
+ backend: "gemini",
27
+ endpoint: `/v1/models/${modelName}:generateContent`,
28
+ model: modelName,
29
+ mappingTable,
30
+ redactionCount,
31
+ durationMs: Date.now() - sanitizeStart,
32
+ });
33
+ }
34
+ // 3. Build sanitized request
35
+ const sanitizedRequest = {
36
+ contents: sanitizedContents,
37
+ ...(tools && { tools }),
38
+ ...(generationConfig && { generationConfig }),
39
+ ...rest,
40
+ };
41
+ // 4. Forward to Gemini API
42
+ const apiUrl = `${backend.baseUrl}/v1/models/${modelName}:generateContent`;
43
+ const response = await fetch(apiUrl, {
44
+ method: "POST",
45
+ headers: {
46
+ "Content-Type": "application/json",
47
+ "x-goog-api-key": backend.apiKey,
48
+ },
49
+ body: JSON.stringify(sanitizedRequest),
50
+ });
51
+ if (!response.ok) {
52
+ // Forward error response
53
+ res.writeHead(response.status, { "Content-Type": "application/json" });
54
+ const errorBody = await response.text();
55
+ res.end(errorBody);
56
+ return;
57
+ }
58
+ // 6. Handle response (Gemini typically doesn't stream in same way)
59
+ const restoreStart = Date.now();
60
+ const responseBody = await response.text();
61
+ const responseData = JSON.parse(responseBody);
62
+ // Restore placeholders in response
63
+ const restoredData = restore(responseData, mappingTable);
64
+ // Log restoration event
65
+ if (mappingTable.size > 0) {
66
+ logRestoreEvent({
67
+ requestId,
68
+ backend: "gemini",
69
+ endpoint: `/v1/models/${modelName}:generateContent`,
70
+ model: modelName,
71
+ mappingTable,
72
+ restorationCount: mappingTable.size,
73
+ durationMs: Date.now() - restoreStart,
74
+ });
75
+ }
76
+ res.writeHead(200, { "Content-Type": "application/json" });
77
+ res.end(JSON.stringify(restoredData));
78
+ }
79
+ catch (error) {
80
+ console.error("[ai-security-gateway] Gemini handler error:", error);
81
+ res.writeHead(500, { "Content-Type": "application/json" });
82
+ res.end(JSON.stringify({
83
+ error: "Internal gateway error",
84
+ message: error instanceof Error ? error.message : String(error),
85
+ }));
86
+ }
87
+ }
88
+ /**
89
+ * Read request body as string
90
+ */
91
+ function readBody(req) {
92
+ return new Promise((resolve, reject) => {
93
+ let body = "";
94
+ req.on("data", (chunk) => {
95
+ body += chunk.toString();
96
+ });
97
+ req.on("end", () => resolve(body));
98
+ req.on("error", reject);
99
+ });
100
+ }
101
+ //# sourceMappingURL=gemini.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gemini.js","sourceRoot":"","sources":["../../src/handlers/gemini.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH,OAAO,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAC3C,OAAO,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC;AACzC,OAAO,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAEtF;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,mBAAmB,CACvC,GAAoB,EACpB,GAAmB,EACnB,OAAsB,EACtB,SAAiB;IAEjB,IAAI,CAAC;QACH,MAAM,SAAS,GAAG,iBAAiB,EAAE,CAAC;QACtC,MAAM,aAAa,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAEjC,wBAAwB;QACxB,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,GAAG,CAAC,CAAC;QACjC,MAAM,WAAW,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAErC,MAAM,EAAE,QAAQ,EAAE,KAAK,EAAE,gBAAgB,EAAE,GAAG,IAAI,EAAE,GAAG,WAAW,CAAC;QAEnE,sEAAsE;QACtE,MAAM,EAAE,SAAS,EAAE,iBAAiB,EAAE,YAAY,EAAE,cAAc,EAAE,GAAG,QAAQ,CAAC,QAAQ,CAAC,CAAC;QAE1F,yBAAyB;QACzB,IAAI,cAAc,GAAG,CAAC,EAAE,CAAC;YACvB,gBAAgB,CAAC;gBACf,SAAS;gBACT,OAAO,EAAE,QAAQ;gBACjB,QAAQ,EAAE,cAAc,SAAS,kBAAkB;gBACnD,KAAK,EAAE,SAAS;gBAChB,YAAY;gBACZ,cAAc;gBACd,UAAU,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,aAAa;aACvC,CAAC,CAAC;QACL,CAAC;QAED,6BAA6B;QAC7B,MAAM,gBAAgB,GAAG;YACvB,QAAQ,EAAE,iBAAiB;YAC3B,GAAG,CAAC,KAAK,IAAI,EAAE,KAAK,EAAE,CAAC;YACvB,GAAG,CAAC,gBAAgB,IAAI,EAAE,gBAAgB,EAAE,CAAC;YAC7C,GAAG,IAAI;SACR,CAAC;QAEF,2BAA2B;QAC3B,MAAM,MAAM,GAAG,GAAG,OAAO,CAAC,OAAO,cAAc,SAAS,kBAAkB,CAAC;QAC3E,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,MAAM,EAAE;YACnC,MAAM,EAAE,MAAM;YACd,OAAO,EAAE;gBACP,cAAc,EAAE,kBAAkB;gBAClC,gBAAgB,EAAE,OAAO,CAAC,MAAM;aACjC;YACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,gBAAgB,CAAC;SACvC,CAAC,CAAC;QAEH,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;YACjB,yBAAyB;YACzB,GAAG,CAAC,SAAS,CAAC,QAAQ,CAAC,MAAM,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE,CAAC,CAAC;YACvE,MAAM,SAAS,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;YACxC,GAAG,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;YACnB,OAAO;QACT,CAAC;QAED,mEAAmE;QACnE,MAAM,YAAY,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAChC,MAAM,YAAY,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;QAC3C,MAAM,YAAY,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC;QAE9C,mCAAmC;QACnC,MAAM,YAAY,GAAG,OAAO,CAAC,YAAY,EAAE,YAAY,CAAC,CAAC;QAEzD,wBAAwB;QACxB,IAAI,YAAY,CAAC,IAAI,GAAG,CAAC,EAAE,CAAC;YAC1B,eAAe,CAAC;gBACd,SAAS;gBACT,OAAO,EAAE,QAAQ;gBACjB,QAAQ,EAAE,cAAc,SAAS,kBAAkB;gBACnD,KAAK,EAAE,SAAS;gBAChB,YAAY;gBACZ,gBAAgB,EAAE,YAAY,CAAC,IAAI;gBACnC,UAAU,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,YAAY;aACtC,CAAC,CAAC;QACL,CAAC;QAED,GAAG,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE,CAAC,CAAC;QAC3D,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,YAAY,CAAC,CAAC,CAAC;IACxC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,KAAK,CAAC,6CAA6C,EAAE,KAAK,CAAC,CAAC;QACpE,GAAG,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE,CAAC,CAAC;QAC3D,GAAG,CAAC,GAAG,CACL,IAAI,CAAC,SAAS,CAAC;YACb,KAAK,EAAE,wBAAwB;YAC/B,OAAO,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC;SAChE,CAAC,CACH,CAAC;IACJ,CAAC;AACH,CAAC;AAED;;GAEG;AACH,SAAS,QAAQ,CAAC,GAAoB;IACpC,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACrC,IAAI,IAAI,GAAG,EAAE,CAAC;QACd,GAAG,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,KAAK,EAAE,EAAE;YACvB,IAAI,IAAI,KAAK,CAAC,QAAQ,EAAE,CAAC;QAC3B,CAAC,CAAC,CAAC;QACH,GAAG,CAAC,EAAE,CAAC,KAAK,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;QACnC,GAAG,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;IAC1B,CAAC,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,4 @@
1
+ import type { ServerResponse } from "node:http";
2
+ import type { GatewayConfig } from "../types.js";
3
+ export declare function handleModelsRequest(res: ServerResponse, config: GatewayConfig): Promise<void>;
4
+ //# sourceMappingURL=models.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"models.d.ts","sourceRoot":"","sources":["../../src/handlers/models.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAChD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAGjD,wBAAsB,mBAAmB,CACvC,GAAG,EAAE,cAAc,EACnB,MAAM,EAAE,aAAa,GACpB,OAAO,CAAC,IAAI,CAAC,CAqCf"}
@@ -0,0 +1,36 @@
1
+ import { findDefaultBackend } from "../config.js";
2
+ export async function handleModelsRequest(res, config) {
3
+ try {
4
+ // Find an OpenAI-compatible backend for models listing
5
+ const resolved = findDefaultBackend("openai", config);
6
+ if (!resolved) {
7
+ res.writeHead(500, { "Content-Type": "application/json" });
8
+ res.end(JSON.stringify({ error: "No OpenAI-compatible backend configured" }));
9
+ return;
10
+ }
11
+ const { backend } = resolved;
12
+ const modelsUrl = `${backend.baseUrl}/v1/models`;
13
+ const headers = {
14
+ "Authorization": `Bearer ${backend.apiKey}`,
15
+ };
16
+ if (backend.referer) {
17
+ headers["HTTP-Referer"] = backend.referer;
18
+ }
19
+ if (backend.title) {
20
+ headers["X-Title"] = backend.title;
21
+ }
22
+ const response = await fetch(modelsUrl, { headers });
23
+ const body = await response.text();
24
+ res.writeHead(response.status, { "Content-Type": "application/json" });
25
+ res.end(body);
26
+ }
27
+ catch (error) {
28
+ console.error("[ai-security-gateway] Models request error:", error);
29
+ res.writeHead(500, { "Content-Type": "application/json" });
30
+ res.end(JSON.stringify({
31
+ error: "Internal gateway error",
32
+ message: error instanceof Error ? error.message : String(error),
33
+ }));
34
+ }
35
+ }
36
+ //# sourceMappingURL=models.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"models.js","sourceRoot":"","sources":["../../src/handlers/models.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,kBAAkB,EAAqB,MAAM,cAAc,CAAC;AAErE,MAAM,CAAC,KAAK,UAAU,mBAAmB,CACvC,GAAmB,EACnB,MAAqB;IAErB,IAAI,CAAC;QACH,uDAAuD;QACvD,MAAM,QAAQ,GAAG,kBAAkB,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;QACtD,IAAI,CAAC,QAAQ,EAAE,CAAC;YACd,GAAG,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE,CAAC,CAAC;YAC3D,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,yCAAyC,EAAE,CAAC,CAAC,CAAC;YAC9E,OAAO;QACT,CAAC;QAED,MAAM,EAAE,OAAO,EAAE,GAAG,QAAQ,CAAC;QAC7B,MAAM,SAAS,GAAG,GAAG,OAAO,CAAC,OAAO,YAAY,CAAC;QACjD,MAAM,OAAO,GAA2B;YACtC,eAAe,EAAE,UAAU,OAAO,CAAC,MAAM,EAAE;SAC5C,CAAC;QAEF,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;YACpB,OAAO,CAAC,cAAc,CAAC,GAAG,OAAO,CAAC,OAAO,CAAC;QAC5C,CAAC;QACD,IAAI,OAAO,CAAC,KAAK,EAAE,CAAC;YAClB,OAAO,CAAC,SAAS,CAAC,GAAG,OAAO,CAAC,KAAK,CAAC;QACrC,CAAC;QAED,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,SAAS,EAAE,EAAE,OAAO,EAAE,CAAC,CAAC;QACrD,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;QACnC,GAAG,CAAC,SAAS,CAAC,QAAQ,CAAC,MAAM,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE,CAAC,CAAC;QACvE,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IAChB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,KAAK,CAAC,6CAA6C,EAAE,KAAK,CAAC,CAAC;QACpE,GAAG,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE,CAAC,CAAC;QAC3D,GAAG,CAAC,GAAG,CACL,IAAI,CAAC,SAAS,CAAC;YACb,KAAK,EAAE,wBAAwB;YAC/B,OAAO,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC;SAChE,CAAC,CACH,CAAC;IACJ,CAAC;AACH,CAAC"}
@@ -0,0 +1,16 @@
1
+ /**
2
+ * AI Security Gateway - OpenAI Chat Completions API handler
3
+ *
4
+ * Handles POST /v1/chat/completions requests in OpenAI's format.
5
+ * Also compatible with OpenAI-compatible APIs (Kimi, DeepSeek, etc.)
6
+ */
7
+ import type { IncomingMessage, ServerResponse } from "node:http";
8
+ import type { BackendConfig } from "../types.js";
9
+ /**
10
+ * Handle OpenAI API request
11
+ *
12
+ * @param backend - Config for OpenAI-compatible backend
13
+ * @param extraHeaders - Optional additional headers (e.g., OpenRouter attribution)
14
+ */
15
+ export declare function handleOpenAIRequest(req: IncomingMessage, res: ServerResponse, backend: BackendConfig, extraHeaders?: Record<string, string>): Promise<void>;
16
+ //# sourceMappingURL=openai.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"openai.d.ts","sourceRoot":"","sources":["../../src/handlers/openai.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AACjE,OAAO,KAAK,EAAE,aAAa,EAAgB,MAAM,aAAa,CAAC;AAK/D;;;;;GAKG;AACH,wBAAsB,mBAAmB,CACvC,GAAG,EAAE,eAAe,EACpB,GAAG,EAAE,cAAc,EACnB,OAAO,EAAE,aAAa,EACtB,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GACpC,OAAO,CAAC,IAAI,CAAC,CAiGf"}