context-lens 0.5.4 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +32 -4
- package/dist/analysis/ingest.d.ts.map +1 -1
- package/dist/analysis/ingest.js +8 -2
- package/dist/analysis/ingest.js.map +1 -1
- package/dist/cli-utils.d.ts +2 -0
- package/dist/cli-utils.d.ts.map +1 -1
- package/dist/cli-utils.js +49 -3
- package/dist/cli-utils.js.map +1 -1
- package/dist/cli.js +156 -14
- package/dist/cli.js.map +1 -1
- package/dist/core/conversation.d.ts +1 -0
- package/dist/core/conversation.d.ts.map +1 -1
- package/dist/core/conversation.js +12 -1
- package/dist/core/conversation.js.map +1 -1
- package/dist/core/models.d.ts +7 -1
- package/dist/core/models.d.ts.map +1 -1
- package/dist/core/models.js +95 -13
- package/dist/core/models.js.map +1 -1
- package/dist/core/routing.d.ts +0 -7
- package/dist/core/routing.d.ts.map +1 -1
- package/dist/core/routing.js +18 -4
- package/dist/core/routing.js.map +1 -1
- package/dist/core/session-format.d.ts.map +1 -1
- package/dist/proxy/capture.d.ts +3 -25
- package/dist/proxy/capture.d.ts.map +1 -1
- package/dist/proxy/capture.js +1 -3
- package/dist/proxy/capture.js.map +1 -1
- package/dist/proxy/config.d.ts +1 -2
- package/dist/proxy/config.d.ts.map +1 -1
- package/dist/proxy/config.js +0 -1
- package/dist/proxy/config.js.map +1 -1
- package/dist/proxy/server.d.ts +8 -19
- package/dist/proxy/server.d.ts.map +1 -1
- package/dist/proxy/server.js +97 -44
- package/dist/proxy/server.js.map +1 -1
- package/dist/server/api.d.ts.map +1 -1
- package/dist/server/api.js +62 -4
- package/dist/server/api.js.map +1 -1
- package/dist/server/store.d.ts +7 -0
- package/dist/server/store.d.ts.map +1 -1
- package/dist/server/store.js +73 -0
- package/dist/server/store.js.map +1 -1
- package/dist/server/tags-store.d.ts +33 -0
- package/dist/server/tags-store.d.ts.map +1 -0
- package/dist/server/tags-store.js +150 -0
- package/dist/server/tags-store.js.map +1 -0
- package/dist/types.d.ts +4 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/version.generated.d.ts +1 -1
- package/dist/version.generated.js +1 -1
- package/mitm_addon.py +18 -0
- package/package.json +4 -3
- package/ui/dist/assets/index-CC_AtJBy.css +1 -0
- package/ui/dist/assets/index-If9FfL3y.js +36 -0
- package/ui/dist/index.html +2 -2
- package/dist/proxy/forward.d.ts +0 -20
- package/dist/proxy/forward.d.ts.map +0 -1
- package/dist/proxy/forward.js +0 -210
- package/dist/proxy/forward.js.map +0 -1
- package/dist/proxy/headers.d.ts +0 -16
- package/dist/proxy/headers.d.ts.map +0 -1
- package/dist/proxy/headers.js +0 -37
- package/dist/proxy/headers.js.map +0 -1
- package/dist/proxy/routing.d.ts +0 -45
- package/dist/proxy/routing.d.ts.map +0 -1
- package/dist/proxy/routing.js +0 -139
- package/dist/proxy/routing.js.map +0 -1
- package/ui/dist/assets/index-D1eb5Vsp.css +0 -1
- package/ui/dist/assets/index-JtXLWNzT.js +0 -35
package/ui/dist/index.html
CHANGED
|
@@ -8,8 +8,8 @@
|
|
|
8
8
|
<link rel="preconnect" href="https://fonts.googleapis.com">
|
|
9
9
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
|
10
10
|
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500;600;700&display=swap" rel="stylesheet">
|
|
11
|
-
<script type="module" crossorigin src="/assets/index-
|
|
12
|
-
<link rel="stylesheet" crossorigin href="/assets/index-
|
|
11
|
+
<script type="module" crossorigin src="/assets/index-If9FfL3y.js"></script>
|
|
12
|
+
<link rel="stylesheet" crossorigin href="/assets/index-CC_AtJBy.css">
|
|
13
13
|
</head>
|
|
14
14
|
<body>
|
|
15
15
|
<div id="app"></div>
|
package/dist/proxy/forward.d.ts
DELETED
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* HTTP forwarding logic for the proxy.
|
|
3
|
-
*
|
|
4
|
-
* Receives incoming requests, forwards them to the appropriate LLM upstream,
|
|
5
|
-
* captures the raw request/response pair to disk, and pipes the response
|
|
6
|
-
* back to the client. Zero external dependencies.
|
|
7
|
-
*/
|
|
8
|
-
import http from "node:http";
|
|
9
|
-
import type { CaptureData } from "./capture.js";
|
|
10
|
-
import { type Upstreams } from "./routing.js";
|
|
11
|
-
export interface ForwardOptions {
|
|
12
|
-
upstreams: Upstreams;
|
|
13
|
-
allowTargetOverride: boolean;
|
|
14
|
-
onCapture: (capture: CaptureData) => void;
|
|
15
|
-
}
|
|
16
|
-
/**
|
|
17
|
-
* Create the main proxy request handler.
|
|
18
|
-
*/
|
|
19
|
-
export declare function createProxyHandler(opts: ForwardOptions): (req: http.IncomingMessage, res: http.ServerResponse) => void;
|
|
20
|
-
//# sourceMappingURL=forward.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"forward.d.ts","sourceRoot":"","sources":["../../src/proxy/forward.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,IAAI,MAAM,WAAW,CAAC;AAI7B,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAEhD,OAAO,EAIL,KAAK,SAAS,EACf,MAAM,cAAc,CAAC;AAEtB,MAAM,WAAW,cAAc;IAC7B,SAAS,EAAE,SAAS,CAAC;IACrB,mBAAmB,EAAE,OAAO,CAAC;IAC7B,SAAS,EAAE,CAAC,OAAO,EAAE,WAAW,KAAK,IAAI,CAAC;CAC3C;AAgHD;;GAEG;AACH,wBAAgB,kBAAkB,CAChC,IAAI,EAAE,cAAc,GACnB,CAAC,GAAG,EAAE,IAAI,CAAC,eAAe,EAAE,GAAG,EAAE,IAAI,CAAC,cAAc,KAAK,IAAI,CAuJ/D"}
|
package/dist/proxy/forward.js
DELETED
|
@@ -1,210 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* HTTP forwarding logic for the proxy.
|
|
3
|
-
*
|
|
4
|
-
* Receives incoming requests, forwards them to the appropriate LLM upstream,
|
|
5
|
-
* captures the raw request/response pair to disk, and pipes the response
|
|
6
|
-
* back to the client. Zero external dependencies.
|
|
7
|
-
*/
|
|
8
|
-
import http from "node:http";
|
|
9
|
-
import https from "node:https";
|
|
10
|
-
import url from "node:url";
|
|
11
|
-
import { selectHeaders } from "./headers.js";
|
|
12
|
-
import { classifyRequest, extractSource, resolveTargetUrl, } from "./routing.js";
|
|
13
|
-
/**
|
|
14
|
-
* Build headers to send to the upstream, stripping proxy-internal ones.
|
|
15
|
-
*/
|
|
16
|
-
function buildForwardHeaders(reqHeaders, targetHost, bodyLength) {
|
|
17
|
-
const forwardHeaders = { ...reqHeaders };
|
|
18
|
-
delete forwardHeaders["x-target-url"];
|
|
19
|
-
delete forwardHeaders.host;
|
|
20
|
-
if (targetHost) {
|
|
21
|
-
forwardHeaders.host = targetHost;
|
|
22
|
-
}
|
|
23
|
-
if (bodyLength != null) {
|
|
24
|
-
delete forwardHeaders["transfer-encoding"];
|
|
25
|
-
forwardHeaders["content-length"] = bodyLength;
|
|
26
|
-
}
|
|
27
|
-
return forwardHeaders;
|
|
28
|
-
}
|
|
29
|
-
/**
|
|
30
|
-
* Wire up error/close handlers between client response and upstream request.
|
|
31
|
-
*/
|
|
32
|
-
function attachLifecycleHandlers(res, proxyReq) {
|
|
33
|
-
res.on("close", () => {
|
|
34
|
-
if (!proxyReq.destroyed)
|
|
35
|
-
proxyReq.destroy();
|
|
36
|
-
});
|
|
37
|
-
proxyReq.on("error", (err) => {
|
|
38
|
-
if (res.destroyed)
|
|
39
|
-
return;
|
|
40
|
-
const detail = err.message || ("code" in err ? err.code : "unknown");
|
|
41
|
-
console.error("Proxy error:", detail);
|
|
42
|
-
if (!res.headersSent) {
|
|
43
|
-
res.writeHead(502, { "Content-Type": "application/json" });
|
|
44
|
-
}
|
|
45
|
-
if (!res.destroyed) {
|
|
46
|
-
res.end(JSON.stringify({ error: "Proxy error", details: err.message }));
|
|
47
|
-
}
|
|
48
|
-
});
|
|
49
|
-
}
|
|
50
|
-
/**
|
|
51
|
-
* Resolve headers for routing, filtering x-target-url when not allowed.
|
|
52
|
-
*/
|
|
53
|
-
function headersForResolution(headers, remoteAddr, allowTargetOverride) {
|
|
54
|
-
const h = headers;
|
|
55
|
-
if (h["x-target-url"] &&
|
|
56
|
-
!(allowTargetOverride && isLocalRemote(remoteAddr))) {
|
|
57
|
-
const { "x-target-url": _drop, ...rest } = h;
|
|
58
|
-
return rest;
|
|
59
|
-
}
|
|
60
|
-
return h;
|
|
61
|
-
}
|
|
62
|
-
function isLocalRemote(addr) {
|
|
63
|
-
if (!addr)
|
|
64
|
-
return false;
|
|
65
|
-
return addr === "127.0.0.1" || addr === "::1" || addr === "::ffff:127.0.0.1";
|
|
66
|
-
}
|
|
67
|
-
/**
|
|
68
|
-
* Forward a non-POST request (GET /v1/models, OPTIONS, etc.) without capturing.
|
|
69
|
-
*/
|
|
70
|
-
function forwardPassthrough(req, res, targetUrl, body) {
|
|
71
|
-
const targetParsed = url.parse(targetUrl);
|
|
72
|
-
const forwardHeaders = buildForwardHeaders(req.headers, targetParsed.host, body ? body.length : undefined);
|
|
73
|
-
const protocol = targetParsed.protocol === "https:" ? https : http;
|
|
74
|
-
const proxyReq = protocol.request({
|
|
75
|
-
hostname: targetParsed.hostname,
|
|
76
|
-
port: targetParsed.port,
|
|
77
|
-
path: targetParsed.path,
|
|
78
|
-
method: req.method,
|
|
79
|
-
headers: forwardHeaders,
|
|
80
|
-
}, (proxyRes) => {
|
|
81
|
-
if (!res.headersSent)
|
|
82
|
-
res.writeHead(proxyRes.statusCode, proxyRes.headers);
|
|
83
|
-
proxyRes.pipe(res);
|
|
84
|
-
proxyRes.on("error", (err) => {
|
|
85
|
-
console.error("Upstream response error (forward):", err.message);
|
|
86
|
-
if (!res.destroyed)
|
|
87
|
-
res.end();
|
|
88
|
-
});
|
|
89
|
-
});
|
|
90
|
-
attachLifecycleHandlers(res, proxyReq);
|
|
91
|
-
if (body)
|
|
92
|
-
proxyReq.write(body);
|
|
93
|
-
proxyReq.end();
|
|
94
|
-
}
|
|
95
|
-
/**
|
|
96
|
-
* Create the main proxy request handler.
|
|
97
|
-
*/
|
|
98
|
-
export function createProxyHandler(opts) {
|
|
99
|
-
return function handleProxy(req, res) {
|
|
100
|
-
const parsedUrl = url.parse(req.url);
|
|
101
|
-
const { source, cleanPath } = extractSource(parsedUrl.pathname);
|
|
102
|
-
const search = parsedUrl.search || null;
|
|
103
|
-
const routingHeaders = headersForResolution(req.headers, req.socket.remoteAddress, opts.allowTargetOverride);
|
|
104
|
-
const { targetUrl, provider } = resolveTargetUrl(cleanPath, search, routingHeaders, opts.upstreams);
|
|
105
|
-
const { apiFormat } = classifyRequest(cleanPath, routingHeaders);
|
|
106
|
-
const hasAuth = !!req.headers.authorization;
|
|
107
|
-
const sourceTag = source ? `[${source}]` : "";
|
|
108
|
-
console.log(`${req.method} ${req.url} → ${targetUrl} [${provider}] ${sourceTag} auth=${hasAuth}`);
|
|
109
|
-
// Non-POST requests: pass through without capturing
|
|
110
|
-
if (req.method !== "POST") {
|
|
111
|
-
forwardPassthrough(req, res, targetUrl, null);
|
|
112
|
-
return;
|
|
113
|
-
}
|
|
114
|
-
// Buffer the request body
|
|
115
|
-
const chunks = [];
|
|
116
|
-
let clientAborted = false;
|
|
117
|
-
req.on("data", (chunk) => {
|
|
118
|
-
chunks.push(chunk);
|
|
119
|
-
});
|
|
120
|
-
req.on("error", () => {
|
|
121
|
-
clientAborted = true;
|
|
122
|
-
});
|
|
123
|
-
req.on("end", () => {
|
|
124
|
-
if (clientAborted)
|
|
125
|
-
return;
|
|
126
|
-
const bodyBuffer = Buffer.concat(chunks);
|
|
127
|
-
const bodyText = bodyBuffer.toString("utf8");
|
|
128
|
-
// Try to parse as JSON (for the capture file), but forward regardless
|
|
129
|
-
let bodyJson = null;
|
|
130
|
-
try {
|
|
131
|
-
bodyJson = JSON.parse(bodyText);
|
|
132
|
-
}
|
|
133
|
-
catch {
|
|
134
|
-
// Not JSON; capture as null, forward the raw bytes
|
|
135
|
-
}
|
|
136
|
-
const targetParsed = url.parse(targetUrl);
|
|
137
|
-
const forwardHeaders = buildForwardHeaders(req.headers, targetParsed.host, bodyBuffer.length);
|
|
138
|
-
const protocol = targetParsed.protocol === "https:" ? https : http;
|
|
139
|
-
const startTime = performance.now();
|
|
140
|
-
let firstByteTime = 0;
|
|
141
|
-
let requestSentTime = 0;
|
|
142
|
-
const reqBytes = bodyBuffer.length;
|
|
143
|
-
const proxyReq = protocol.request({
|
|
144
|
-
hostname: targetParsed.hostname,
|
|
145
|
-
port: targetParsed.port,
|
|
146
|
-
path: targetParsed.path,
|
|
147
|
-
method: req.method,
|
|
148
|
-
headers: forwardHeaders,
|
|
149
|
-
}, (proxyRes) => {
|
|
150
|
-
console.log(` ← ${proxyRes.statusCode} ${proxyRes.statusMessage}`);
|
|
151
|
-
res.writeHead(proxyRes.statusCode, proxyRes.headers);
|
|
152
|
-
const isStreaming = proxyRes.headers["content-type"]?.includes("text/event-stream");
|
|
153
|
-
let respBytes = 0;
|
|
154
|
-
const respChunks = [];
|
|
155
|
-
proxyRes.on("data", (chunk) => {
|
|
156
|
-
if (!firstByteTime)
|
|
157
|
-
firstByteTime = performance.now();
|
|
158
|
-
respBytes += chunk.length;
|
|
159
|
-
respChunks.push(chunk);
|
|
160
|
-
if (!res.destroyed)
|
|
161
|
-
res.write(chunk);
|
|
162
|
-
});
|
|
163
|
-
proxyRes.on("end", () => {
|
|
164
|
-
const endTime = performance.now();
|
|
165
|
-
if (!firstByteTime)
|
|
166
|
-
firstByteTime = endTime;
|
|
167
|
-
const respBody = Buffer.concat(respChunks).toString("utf8");
|
|
168
|
-
const capture = {
|
|
169
|
-
timestamp: new Date().toISOString(),
|
|
170
|
-
method: req.method,
|
|
171
|
-
path: cleanPath,
|
|
172
|
-
source,
|
|
173
|
-
provider,
|
|
174
|
-
apiFormat,
|
|
175
|
-
targetUrl,
|
|
176
|
-
requestHeaders: selectHeaders(req.headers),
|
|
177
|
-
requestBody: bodyJson,
|
|
178
|
-
requestBytes: reqBytes,
|
|
179
|
-
responseStatus: proxyRes.statusCode || 0,
|
|
180
|
-
responseHeaders: selectHeaders(proxyRes.headers),
|
|
181
|
-
responseBody: respBody,
|
|
182
|
-
responseIsStreaming: !!isStreaming,
|
|
183
|
-
responseBytes: respBytes,
|
|
184
|
-
timings: {
|
|
185
|
-
send_ms: Math.round(Math.max(0, (requestSentTime || firstByteTime) - startTime)),
|
|
186
|
-
wait_ms: Math.round(Math.max(0, firstByteTime - (requestSentTime || startTime))),
|
|
187
|
-
receive_ms: Math.round(endTime - firstByteTime),
|
|
188
|
-
total_ms: Math.round(endTime - startTime),
|
|
189
|
-
},
|
|
190
|
-
};
|
|
191
|
-
opts.onCapture(capture);
|
|
192
|
-
if (!res.destroyed)
|
|
193
|
-
res.end();
|
|
194
|
-
});
|
|
195
|
-
proxyRes.on("error", (err) => {
|
|
196
|
-
console.error("Upstream response error:", err.message);
|
|
197
|
-
if (!res.destroyed)
|
|
198
|
-
res.end();
|
|
199
|
-
});
|
|
200
|
-
});
|
|
201
|
-
attachLifecycleHandlers(res, proxyReq);
|
|
202
|
-
proxyReq.on("finish", () => {
|
|
203
|
-
requestSentTime = performance.now();
|
|
204
|
-
});
|
|
205
|
-
proxyReq.write(bodyBuffer);
|
|
206
|
-
proxyReq.end();
|
|
207
|
-
});
|
|
208
|
-
};
|
|
209
|
-
}
|
|
210
|
-
//# sourceMappingURL=forward.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"forward.js","sourceRoot":"","sources":["../../src/proxy/forward.ts"],"names":[],"mappings":"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"}
|
package/dist/proxy/headers.d.ts
DELETED
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Header redaction for the proxy.
|
|
3
|
-
*
|
|
4
|
-
* The proxy captures headers for debugging but must never persist secrets.
|
|
5
|
-
* This is the single source of truth for what gets stripped.
|
|
6
|
-
*/
|
|
7
|
-
/** Case-insensitive set of header names that must never be persisted. */
|
|
8
|
-
export declare const SENSITIVE_HEADERS: Set<string>;
|
|
9
|
-
/**
|
|
10
|
-
* Select a safe subset of headers for capture.
|
|
11
|
-
*
|
|
12
|
-
* Drops sensitive headers and keeps only string-valued entries
|
|
13
|
-
* (Node can represent multi-valued headers as arrays).
|
|
14
|
-
*/
|
|
15
|
-
export declare function selectHeaders(headers: Record<string, any>): Record<string, string>;
|
|
16
|
-
//# sourceMappingURL=headers.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"headers.d.ts","sourceRoot":"","sources":["../../src/proxy/headers.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,yEAAyE;AACzE,eAAO,MAAM,iBAAiB,aAY5B,CAAC;AAEH;;;;;GAKG;AACH,wBAAgB,aAAa,CAC3B,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAC3B,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAOxB"}
|
package/dist/proxy/headers.js
DELETED
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Header redaction for the proxy.
|
|
3
|
-
*
|
|
4
|
-
* The proxy captures headers for debugging but must never persist secrets.
|
|
5
|
-
* This is the single source of truth for what gets stripped.
|
|
6
|
-
*/
|
|
7
|
-
/** Case-insensitive set of header names that must never be persisted. */
|
|
8
|
-
export const SENSITIVE_HEADERS = new Set([
|
|
9
|
-
"authorization",
|
|
10
|
-
"x-api-key",
|
|
11
|
-
"cookie",
|
|
12
|
-
"set-cookie",
|
|
13
|
-
"x-target-url",
|
|
14
|
-
"proxy-authorization",
|
|
15
|
-
"x-auth-token",
|
|
16
|
-
"x-forwarded-authorization",
|
|
17
|
-
"www-authenticate",
|
|
18
|
-
"proxy-authenticate",
|
|
19
|
-
"x-goog-api-key",
|
|
20
|
-
]);
|
|
21
|
-
/**
|
|
22
|
-
* Select a safe subset of headers for capture.
|
|
23
|
-
*
|
|
24
|
-
* Drops sensitive headers and keeps only string-valued entries
|
|
25
|
-
* (Node can represent multi-valued headers as arrays).
|
|
26
|
-
*/
|
|
27
|
-
export function selectHeaders(headers) {
|
|
28
|
-
const result = {};
|
|
29
|
-
for (const [key, val] of Object.entries(headers)) {
|
|
30
|
-
if (SENSITIVE_HEADERS.has(key.toLowerCase()))
|
|
31
|
-
continue;
|
|
32
|
-
if (typeof val === "string")
|
|
33
|
-
result[key] = val;
|
|
34
|
-
}
|
|
35
|
-
return result;
|
|
36
|
-
}
|
|
37
|
-
//# sourceMappingURL=headers.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"headers.js","sourceRoot":"","sources":["../../src/proxy/headers.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,yEAAyE;AACzE,MAAM,CAAC,MAAM,iBAAiB,GAAG,IAAI,GAAG,CAAC;IACvC,eAAe;IACf,WAAW;IACX,QAAQ;IACR,YAAY;IACZ,cAAc;IACd,qBAAqB;IACrB,cAAc;IACd,2BAA2B;IAC3B,kBAAkB;IAClB,oBAAoB;IACpB,gBAAgB;CACjB,CAAC,CAAC;AAEH;;;;;GAKG;AACH,MAAM,UAAU,aAAa,CAC3B,OAA4B;IAE5B,MAAM,MAAM,GAA2B,EAAE,CAAC;IAC1C,KAAK,MAAM,CAAC,GAAG,EAAE,GAAG,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;QACjD,IAAI,iBAAiB,CAAC,GAAG,CAAC,GAAG,CAAC,WAAW,EAAE,CAAC;YAAE,SAAS;QACvD,IAAI,OAAO,GAAG,KAAK,QAAQ;YAAE,MAAM,CAAC,GAAG,CAAC,GAAG,GAAG,CAAC;IACjD,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC"}
|
package/dist/proxy/routing.d.ts
DELETED
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Request routing for the proxy.
|
|
3
|
-
*
|
|
4
|
-
* Detects which LLM provider a request targets, extracts source tool tags,
|
|
5
|
-
* and resolves the upstream URL. Zero external dependencies.
|
|
6
|
-
*/
|
|
7
|
-
export type Provider = "anthropic" | "openai" | "chatgpt" | "gemini" | "vertex" | "unknown";
|
|
8
|
-
export type ApiFormat = "anthropic-messages" | "chatgpt-backend" | "responses" | "chat-completions" | "gemini" | "raw" | "unknown";
|
|
9
|
-
export interface Upstreams {
|
|
10
|
-
openai: string;
|
|
11
|
-
anthropic: string;
|
|
12
|
-
chatgpt: string;
|
|
13
|
-
gemini: string;
|
|
14
|
-
geminiCodeAssist: string;
|
|
15
|
-
vertex: string;
|
|
16
|
-
}
|
|
17
|
-
export interface ExtractSourceResult {
|
|
18
|
-
source: string | null;
|
|
19
|
-
cleanPath: string;
|
|
20
|
-
}
|
|
21
|
-
export interface ResolveTargetResult {
|
|
22
|
-
targetUrl: string;
|
|
23
|
-
provider: Provider;
|
|
24
|
-
}
|
|
25
|
-
/**
|
|
26
|
-
* Classify an incoming request into `{ provider, apiFormat }`.
|
|
27
|
-
*
|
|
28
|
-
* All path/format heuristics live here to avoid drift between
|
|
29
|
-
* routing and detection.
|
|
30
|
-
*/
|
|
31
|
-
export declare function classifyRequest(pathname: string, headers: Record<string, string | undefined>): {
|
|
32
|
-
provider: Provider;
|
|
33
|
-
apiFormat: ApiFormat;
|
|
34
|
-
};
|
|
35
|
-
/**
|
|
36
|
-
* Extract a "source tool" tag from a request path.
|
|
37
|
-
*
|
|
38
|
-
* Example: `/claude/v1/messages` => `{ source: 'claude', cleanPath: '/v1/messages' }`.
|
|
39
|
-
*/
|
|
40
|
-
export declare function extractSource(pathname: string): ExtractSourceResult;
|
|
41
|
-
/**
|
|
42
|
-
* Determine the final upstream target URL for a request.
|
|
43
|
-
*/
|
|
44
|
-
export declare function resolveTargetUrl(pathname: string, search: string | null, headers: Record<string, string | undefined>, upstreams: Upstreams): ResolveTargetResult;
|
|
45
|
-
//# sourceMappingURL=routing.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"routing.d.ts","sourceRoot":"","sources":["../../src/proxy/routing.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,MAAM,MAAM,QAAQ,GAChB,WAAW,GACX,QAAQ,GACR,SAAS,GACT,QAAQ,GACR,QAAQ,GACR,SAAS,CAAC;AAEd,MAAM,MAAM,SAAS,GACjB,oBAAoB,GACpB,iBAAiB,GACjB,WAAW,GACX,kBAAkB,GAClB,QAAQ,GACR,KAAK,GACL,SAAS,CAAC;AAEd,MAAM,WAAW,SAAS;IACxB,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,gBAAgB,EAAE,MAAM,CAAC;IACzB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,mBAAmB;IAClC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,mBAAmB;IAClC,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,QAAQ,CAAC;CACpB;AAuBD;;;;;GAKG;AACH,wBAAgB,eAAe,CAC7B,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,GAC1C;IAAE,QAAQ,EAAE,QAAQ,CAAC;IAAC,SAAS,EAAE,SAAS,CAAA;CAAE,CA2C9C;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,mBAAmB,CAmBnE;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAC9B,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM,GAAG,IAAI,EACrB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,EAC3C,SAAS,EAAE,SAAS,GACnB,mBAAmB,CAqCrB"}
|
package/dist/proxy/routing.js
DELETED
|
@@ -1,139 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Request routing for the proxy.
|
|
3
|
-
*
|
|
4
|
-
* Detects which LLM provider a request targets, extracts source tool tags,
|
|
5
|
-
* and resolves the upstream URL. Zero external dependencies.
|
|
6
|
-
*/
|
|
7
|
-
// --- Implementation ---
|
|
8
|
-
/**
|
|
9
|
-
* URL path segments that represent API resources rather than "source tool" prefixes.
|
|
10
|
-
*
|
|
11
|
-
* Example: `/v1/messages` should not treat `v1` as a source tag.
|
|
12
|
-
*/
|
|
13
|
-
const API_PATH_SEGMENTS = new Set([
|
|
14
|
-
"v1",
|
|
15
|
-
"v1beta",
|
|
16
|
-
"v1beta1",
|
|
17
|
-
"v1alpha",
|
|
18
|
-
"v1internal",
|
|
19
|
-
"responses",
|
|
20
|
-
"chat",
|
|
21
|
-
"models",
|
|
22
|
-
"embeddings",
|
|
23
|
-
"backend-api",
|
|
24
|
-
"api",
|
|
25
|
-
]);
|
|
26
|
-
/**
|
|
27
|
-
* Classify an incoming request into `{ provider, apiFormat }`.
|
|
28
|
-
*
|
|
29
|
-
* All path/format heuristics live here to avoid drift between
|
|
30
|
-
* routing and detection.
|
|
31
|
-
*/
|
|
32
|
-
export function classifyRequest(pathname, headers) {
|
|
33
|
-
// ChatGPT backend traffic (Codex subscription)
|
|
34
|
-
// /codex/responses is the path used by Pi's openai-codex provider
|
|
35
|
-
if (pathname.match(/^\/(api|backend-api|codex)\//))
|
|
36
|
-
return { provider: "chatgpt", apiFormat: "chatgpt-backend" };
|
|
37
|
-
// Anthropic Messages API
|
|
38
|
-
if (pathname.includes("/v1/messages"))
|
|
39
|
-
return { provider: "anthropic", apiFormat: "anthropic-messages" };
|
|
40
|
-
if (pathname.includes("/v1/complete"))
|
|
41
|
-
return { provider: "anthropic", apiFormat: "unknown" };
|
|
42
|
-
if (headers["anthropic-version"])
|
|
43
|
-
return { provider: "anthropic", apiFormat: "unknown" };
|
|
44
|
-
// Vertex AI: must come BEFORE Gemini (Vertex paths also contain :generateContent)
|
|
45
|
-
// Matches /v1beta1/projects/{project}/locations/{location}/publishers/google/models/{model}:generateContent
|
|
46
|
-
const isVertexPath = pathname.match(/\/v1[^/]*\/projects\/[^/]+\/locations\/[^/]+\/publishers\/google\/models\//);
|
|
47
|
-
if (isVertexPath) {
|
|
48
|
-
return { provider: "vertex", apiFormat: "gemini" };
|
|
49
|
-
}
|
|
50
|
-
// Gemini: must come BEFORE openai catch-all (which matches /models/)
|
|
51
|
-
const isGeminiPath = pathname.includes(":generateContent") ||
|
|
52
|
-
pathname.includes(":streamGenerateContent") ||
|
|
53
|
-
pathname.match(/\/v1(beta|alpha)\/models\//) ||
|
|
54
|
-
pathname.includes("/v1internal:");
|
|
55
|
-
if (isGeminiPath || headers["x-goog-api-key"])
|
|
56
|
-
return { provider: "gemini", apiFormat: "gemini" };
|
|
57
|
-
// OpenAI
|
|
58
|
-
if (pathname.includes("/responses"))
|
|
59
|
-
return { provider: "openai", apiFormat: "responses" };
|
|
60
|
-
if (pathname.includes("/chat/completions"))
|
|
61
|
-
return { provider: "openai", apiFormat: "chat-completions" };
|
|
62
|
-
if (pathname.match(/\/(models|embeddings)/))
|
|
63
|
-
return { provider: "openai", apiFormat: "unknown" };
|
|
64
|
-
if (headers.authorization?.startsWith("Bearer sk-"))
|
|
65
|
-
return { provider: "openai", apiFormat: "unknown" };
|
|
66
|
-
return { provider: "unknown", apiFormat: "unknown" };
|
|
67
|
-
}
|
|
68
|
-
/**
|
|
69
|
-
* Extract a "source tool" tag from a request path.
|
|
70
|
-
*
|
|
71
|
-
* Example: `/claude/v1/messages` => `{ source: 'claude', cleanPath: '/v1/messages' }`.
|
|
72
|
-
*/
|
|
73
|
-
export function extractSource(pathname) {
|
|
74
|
-
const match = pathname.match(/^\/([^/]+)(\/.*)?$/);
|
|
75
|
-
if (match?.[2] && !API_PATH_SEGMENTS.has(match[1])) {
|
|
76
|
-
let decoded = match[1];
|
|
77
|
-
try {
|
|
78
|
-
decoded = decodeURIComponent(match[1]);
|
|
79
|
-
}
|
|
80
|
-
catch {
|
|
81
|
-
decoded = match[1];
|
|
82
|
-
}
|
|
83
|
-
if (decoded.includes("/") ||
|
|
84
|
-
decoded.includes("\\") ||
|
|
85
|
-
decoded.includes("..")) {
|
|
86
|
-
return { source: null, cleanPath: pathname };
|
|
87
|
-
}
|
|
88
|
-
return { source: decoded, cleanPath: match[2] || "/" };
|
|
89
|
-
}
|
|
90
|
-
return { source: null, cleanPath: pathname };
|
|
91
|
-
}
|
|
92
|
-
/**
|
|
93
|
-
* Determine the final upstream target URL for a request.
|
|
94
|
-
*/
|
|
95
|
-
export function resolveTargetUrl(pathname, search, headers, upstreams) {
|
|
96
|
-
const provider = classifyRequest(pathname, headers).provider;
|
|
97
|
-
const qs = search || "";
|
|
98
|
-
let targetUrl = headers["x-target-url"];
|
|
99
|
-
if (!targetUrl) {
|
|
100
|
-
if (provider === "chatgpt") {
|
|
101
|
-
// Paths from Pi's openai-codex provider arrive as /codex/responses
|
|
102
|
-
// (without the /backend-api prefix). Prepend it if missing.
|
|
103
|
-
const chatgptPath = pathname.match(/^\/(api|backend-api)\//)
|
|
104
|
-
? pathname
|
|
105
|
-
: `/backend-api${pathname}`;
|
|
106
|
-
targetUrl = upstreams.chatgpt + chatgptPath + qs;
|
|
107
|
-
}
|
|
108
|
-
else if (provider === "anthropic") {
|
|
109
|
-
targetUrl = upstreams.anthropic + pathname + qs;
|
|
110
|
-
}
|
|
111
|
-
else if (provider === "gemini") {
|
|
112
|
-
const isCodeAssist = pathname.includes("/v1internal");
|
|
113
|
-
targetUrl =
|
|
114
|
-
(isCodeAssist ? upstreams.geminiCodeAssist : upstreams.gemini) +
|
|
115
|
-
pathname +
|
|
116
|
-
qs;
|
|
117
|
-
}
|
|
118
|
-
else if (provider === "vertex") {
|
|
119
|
-
// Extract location from Vertex path to build the regional endpoint.
|
|
120
|
-
// Path: /v1beta1/projects/{project}/locations/{location}/...
|
|
121
|
-
const locMatch = pathname.match(/\/locations\/([^/]+)\//);
|
|
122
|
-
const location = locMatch?.[1];
|
|
123
|
-
if (location && location !== "global") {
|
|
124
|
-
targetUrl = `https://${location}-aiplatform.googleapis.com${pathname}${qs}`;
|
|
125
|
-
}
|
|
126
|
-
else {
|
|
127
|
-
targetUrl = `${upstreams.vertex}${pathname}${qs}`;
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
else {
|
|
131
|
-
targetUrl = upstreams.openai + pathname + qs;
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
else if (!targetUrl.startsWith("http")) {
|
|
135
|
-
targetUrl = targetUrl + pathname + qs;
|
|
136
|
-
}
|
|
137
|
-
return { targetUrl, provider };
|
|
138
|
-
}
|
|
139
|
-
//# sourceMappingURL=routing.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"routing.js","sourceRoot":"","sources":["../../src/proxy/routing.ts"],"names":[],"mappings":"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"}
|