context-lens 0.3.2 → 0.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +52 -16
- package/dist/analysis/ingest.d.ts +13 -0
- package/dist/analysis/ingest.d.ts.map +1 -0
- package/dist/analysis/ingest.js +75 -0
- package/dist/analysis/ingest.js.map +1 -0
- package/dist/analysis/server.d.ts +10 -0
- package/dist/analysis/server.d.ts.map +1 -0
- package/dist/analysis/server.js +95 -0
- package/dist/analysis/server.js.map +1 -0
- package/dist/analysis/watcher.d.ts +55 -0
- package/dist/analysis/watcher.d.ts.map +1 -0
- package/dist/analysis/watcher.js +170 -0
- package/dist/analysis/watcher.js.map +1 -0
- package/dist/cli-utils.d.ts +16 -0
- package/dist/cli-utils.d.ts.map +1 -1
- package/dist/cli-utils.js +185 -3
- package/dist/cli-utils.js.map +1 -1
- package/dist/cli.js +629 -88
- package/dist/cli.js.map +1 -1
- package/dist/core/conversation.d.ts +8 -1
- package/dist/core/conversation.d.ts.map +1 -1
- package/dist/core/conversation.js +38 -12
- package/dist/core/conversation.js.map +1 -1
- package/dist/core/parse.d.ts.map +1 -1
- package/dist/core/parse.js +17 -1
- package/dist/core/parse.js.map +1 -1
- package/dist/core/session-analysis.d.ts +100 -0
- package/dist/core/session-analysis.d.ts.map +1 -0
- package/dist/core/session-analysis.js +435 -0
- package/dist/core/session-analysis.js.map +1 -0
- package/dist/core/session-format.d.ts +20 -0
- package/dist/core/session-format.d.ts.map +1 -0
- package/dist/core/session-format.js +298 -0
- package/dist/core/session-format.js.map +1 -0
- package/dist/core.d.ts +4 -0
- package/dist/core.d.ts.map +1 -1
- package/dist/core.js +2 -0
- package/dist/core.js.map +1 -1
- package/dist/lhar/reader.d.ts +22 -0
- package/dist/lhar/reader.d.ts.map +1 -0
- package/dist/lhar/reader.js +43 -0
- package/dist/lhar/reader.js.map +1 -0
- package/dist/lhar/record.d.ts.map +1 -1
- package/dist/lhar/record.js +3 -0
- package/dist/lhar/record.js.map +1 -1
- package/dist/lhar/response.d.ts +8 -0
- package/dist/lhar/response.d.ts.map +1 -1
- package/dist/lhar/response.js +44 -0
- package/dist/lhar/response.js.map +1 -1
- package/dist/lhar/tools.d.ts +17 -0
- package/dist/lhar/tools.d.ts.map +1 -0
- package/dist/lhar/tools.js +48 -0
- package/dist/lhar/tools.js.map +1 -0
- package/dist/lhar-types.generated.d.ts +34 -0
- package/dist/lhar-types.generated.d.ts.map +1 -1
- package/dist/lhar.d.ts +4 -1
- package/dist/lhar.d.ts.map +1 -1
- package/dist/lhar.js +5 -1
- package/dist/lhar.js.map +1 -1
- package/dist/proxy/capture.d.ts +40 -0
- package/dist/proxy/capture.d.ts.map +1 -0
- package/dist/proxy/capture.js +56 -0
- package/dist/proxy/capture.js.map +1 -0
- package/dist/proxy/config.d.ts +16 -0
- package/dist/proxy/config.d.ts.map +1 -0
- package/dist/proxy/config.js +34 -0
- package/dist/proxy/config.js.map +1 -0
- package/dist/proxy/forward.d.ts +20 -0
- package/dist/proxy/forward.d.ts.map +1 -0
- package/dist/proxy/forward.js +210 -0
- package/dist/proxy/forward.js.map +1 -0
- package/dist/proxy/headers.d.ts +16 -0
- package/dist/proxy/headers.d.ts.map +1 -0
- package/dist/proxy/headers.js +37 -0
- package/dist/proxy/headers.js.map +1 -0
- package/dist/proxy/routing.d.ts +44 -0
- package/dist/proxy/routing.d.ts.map +1 -0
- package/dist/proxy/routing.js +114 -0
- package/dist/proxy/routing.js.map +1 -0
- package/dist/proxy/server.d.ts +27 -0
- package/dist/proxy/server.d.ts.map +1 -0
- package/dist/proxy/server.js +55 -0
- package/dist/proxy/server.js.map +1 -0
- package/dist/schemas.d.ts +328 -0
- package/dist/schemas.d.ts.map +1 -0
- package/dist/schemas.js +249 -0
- package/dist/schemas.js.map +1 -0
- package/dist/server/api.d.ts +3 -4
- package/dist/server/api.d.ts.map +1 -1
- package/dist/server/api.js +195 -220
- package/dist/server/api.js.map +1 -1
- package/dist/server/store.d.ts +23 -7
- package/dist/server/store.d.ts.map +1 -1
- package/dist/server/store.js +141 -50
- package/dist/server/store.js.map +1 -1
- package/dist/server/webui.d.ts +5 -2
- package/dist/server/webui.d.ts.map +1 -1
- package/dist/server/webui.js +32 -13
- package/dist/server/webui.js.map +1 -1
- package/dist/server-utils.d.ts +1 -2
- package/dist/server-utils.d.ts.map +1 -1
- package/dist/server-utils.js +0 -2
- package/dist/server-utils.js.map +1 -1
- package/dist/types.d.ts +1 -1
- 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 +99 -28
- package/package.json +12 -5
- package/schema/lhar.schema.json +50 -0
- package/dist/server/config.d.ts +0 -13
- package/dist/server/config.d.ts.map +0 -1
- package/dist/server/config.js +0 -36
- package/dist/server/config.js.map +0 -1
- package/dist/server/proxy.d.ts +0 -13
- package/dist/server/proxy.d.ts.map +0 -1
- package/dist/server/proxy.js +0 -218
- package/dist/server/proxy.js.map +0 -1
- package/dist/server/static.d.ts +0 -9
- package/dist/server/static.d.ts.map +0 -1
- package/dist/server/static.js +0 -78
- package/dist/server/static.js.map +0 -1
- package/dist/server.d.ts +0 -3
- package/dist/server.d.ts.map +0 -1
- package/dist/server.js +0 -43
- package/dist/server.js.map +0 -1
package/mitm_addon.py
CHANGED
|
@@ -4,16 +4,20 @@ mitmproxy addon for Context Lens.
|
|
|
4
4
|
Captures LLM API requests passing through mitmproxy and forwards them
|
|
5
5
|
to Context Lens's ingest API for visualization.
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|
|
7
|
+
This addon is used for Codex (subscription mode) and other tools that
|
|
8
|
+
connect directly to their APIs over HTTPS and cannot be redirected to
|
|
9
|
+
a custom base URL. The CLI starts mitmproxy automatically when needed.
|
|
9
10
|
|
|
10
|
-
|
|
11
|
-
|
|
11
|
+
Manual usage:
|
|
12
|
+
context-lens background start
|
|
13
|
+
mitmdump -p 8888 -s mitm_addon.py
|
|
14
|
+
https_proxy=http://localhost:8888 SSL_CERT_FILE=~/.mitmproxy/mitmproxy-ca-cert.pem codex "prompt"
|
|
12
15
|
|
|
13
16
|
View at http://localhost:4041
|
|
14
17
|
"""
|
|
15
18
|
|
|
16
19
|
import json
|
|
20
|
+
import time
|
|
17
21
|
import urllib.request
|
|
18
22
|
from mitmproxy import http
|
|
19
23
|
|
|
@@ -23,7 +27,7 @@ INGEST_URL = "http://localhost:4041/api/ingest"
|
|
|
23
27
|
CAPTURE_PATTERNS = [
|
|
24
28
|
# Codex subscription
|
|
25
29
|
("chatgpt.com", "/backend-api/codex/responses", "chatgpt", "codex"),
|
|
26
|
-
# OpenAI API
|
|
30
|
+
# OpenAI API
|
|
27
31
|
("api.openai.com", "/v1/responses", "openai", "openai"),
|
|
28
32
|
("api.openai.com", "/v1/chat/completions", "openai", "openai"),
|
|
29
33
|
# Anthropic API
|
|
@@ -41,6 +45,28 @@ def match_request(flow: http.HTTPFlow):
|
|
|
41
45
|
return None, None
|
|
42
46
|
|
|
43
47
|
|
|
48
|
+
def _detect_api_format(path: str) -> str:
|
|
49
|
+
"""Detect API format from the request path."""
|
|
50
|
+
if "/backend-api/" in path:
|
|
51
|
+
return "responses"
|
|
52
|
+
if "/responses" in path:
|
|
53
|
+
return "responses"
|
|
54
|
+
if "/chat/completions" in path:
|
|
55
|
+
return "chat-completions"
|
|
56
|
+
if "/v1/messages" in path:
|
|
57
|
+
return "anthropic-messages"
|
|
58
|
+
return "unknown"
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
def _parse_sse_response(text: str) -> str:
|
|
62
|
+
"""Parse SSE event stream, extracting data lines as raw text.
|
|
63
|
+
|
|
64
|
+
Returns the raw SSE text for the capture. The analysis server
|
|
65
|
+
handles SSE parsing during ingestion.
|
|
66
|
+
"""
|
|
67
|
+
return text
|
|
68
|
+
|
|
69
|
+
|
|
44
70
|
def response(flow: http.HTTPFlow):
|
|
45
71
|
"""Called when a response is received."""
|
|
46
72
|
if flow.request.method != "POST":
|
|
@@ -50,34 +76,77 @@ def response(flow: http.HTTPFlow):
|
|
|
50
76
|
if not provider:
|
|
51
77
|
return
|
|
52
78
|
|
|
79
|
+
# Parse request body (mitmproxy auto-decompresses zstd/gzip)
|
|
53
80
|
try:
|
|
54
|
-
|
|
55
|
-
|
|
81
|
+
request_text = flow.request.get_text()
|
|
82
|
+
request_body = json.loads(request_text)
|
|
83
|
+
except (json.JSONDecodeError, ValueError, Exception) as e:
|
|
84
|
+
print(f"[context-lens] Could not parse request body: {e}")
|
|
56
85
|
return
|
|
57
86
|
|
|
87
|
+
# Get response body (may be JSON or SSE event stream)
|
|
88
|
+
response_body = ""
|
|
89
|
+
response_is_streaming = False
|
|
58
90
|
try:
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
91
|
+
response_text = flow.response.get_text()
|
|
92
|
+
content_type = flow.response.headers.get("content-type", "")
|
|
93
|
+
if "text/event-stream" in content_type or response_text.startswith("event:"):
|
|
94
|
+
response_body = response_text
|
|
95
|
+
response_is_streaming = True
|
|
96
|
+
else:
|
|
97
|
+
response_body = response_text
|
|
98
|
+
except Exception as e:
|
|
99
|
+
print(f"[context-lens] Could not read response body: {e}")
|
|
100
|
+
response_body = ""
|
|
101
|
+
|
|
102
|
+
# Build capture in the same format as proxy/capture.ts
|
|
103
|
+
api_format = _detect_api_format(flow.request.path)
|
|
104
|
+
|
|
105
|
+
# Select safe headers (no auth tokens)
|
|
106
|
+
safe_request_headers = {}
|
|
107
|
+
for k, v in flow.request.headers.items():
|
|
108
|
+
lower = k.lower()
|
|
109
|
+
if lower in ("content-type", "content-encoding", "accept",
|
|
110
|
+
"user-agent", "anthropic-version", "openai-beta",
|
|
111
|
+
"x-request-id"):
|
|
112
|
+
safe_request_headers[k] = v
|
|
113
|
+
|
|
114
|
+
safe_response_headers = {}
|
|
115
|
+
for k, v in flow.response.headers.items():
|
|
116
|
+
lower = k.lower()
|
|
117
|
+
if lower in ("content-type", "x-request-id", "x-ratelimit-limit-requests",
|
|
118
|
+
"x-ratelimit-remaining-requests", "x-ratelimit-limit-tokens",
|
|
119
|
+
"x-ratelimit-remaining-tokens", "openai-processing-ms",
|
|
120
|
+
"anthropic-ratelimit-requests-limit",
|
|
121
|
+
"anthropic-ratelimit-requests-remaining"):
|
|
122
|
+
safe_response_headers[k] = v
|
|
123
|
+
|
|
124
|
+
capture = {
|
|
125
|
+
"timestamp": time.strftime("%Y-%m-%dT%H:%M:%S.000Z", time.gmtime()),
|
|
126
|
+
"method": "POST",
|
|
127
|
+
"path": flow.request.path,
|
|
128
|
+
"source": source,
|
|
75
129
|
"provider": provider,
|
|
76
130
|
"apiFormat": api_format,
|
|
77
|
-
"
|
|
78
|
-
"
|
|
79
|
-
"
|
|
80
|
-
|
|
131
|
+
"targetUrl": flow.request.pretty_url,
|
|
132
|
+
"requestHeaders": safe_request_headers,
|
|
133
|
+
"requestBody": request_body,
|
|
134
|
+
"requestBytes": len(flow.request.raw_content),
|
|
135
|
+
"responseStatus": flow.response.status_code,
|
|
136
|
+
"responseHeaders": safe_response_headers,
|
|
137
|
+
"responseBody": response_body,
|
|
138
|
+
"responseIsStreaming": response_is_streaming,
|
|
139
|
+
"responseBytes": len(flow.response.raw_content),
|
|
140
|
+
"timings": {
|
|
141
|
+
"send_ms": 0,
|
|
142
|
+
"wait_ms": 0,
|
|
143
|
+
"receive_ms": 0,
|
|
144
|
+
"total_ms": int((flow.response.timestamp_end - flow.request.timestamp_start) * 1000)
|
|
145
|
+
if flow.response.timestamp_end and flow.request.timestamp_start else 0,
|
|
146
|
+
},
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
payload = json.dumps(capture).encode()
|
|
81
150
|
|
|
82
151
|
try:
|
|
83
152
|
req = urllib.request.Request(
|
|
@@ -85,6 +154,8 @@ def response(flow: http.HTTPFlow):
|
|
|
85
154
|
data=payload,
|
|
86
155
|
headers={"Content-Type": "application/json"},
|
|
87
156
|
)
|
|
88
|
-
urllib.request.urlopen(req, timeout=
|
|
157
|
+
urllib.request.urlopen(req, timeout=5)
|
|
158
|
+
model = request_body.get("model", "unknown")
|
|
159
|
+
print(f"[context-lens] Captured {source}/{provider} request (model={model})")
|
|
89
160
|
except Exception as e:
|
|
90
161
|
print(f"[context-lens] Failed to ingest: {e}")
|
package/package.json
CHANGED
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "context-lens",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.1",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Local HTTP proxy that intercepts LLM API calls and visualizes context windows",
|
|
6
|
-
"main": "dist/server.js",
|
|
6
|
+
"main": "dist/proxy/server.js",
|
|
7
7
|
"bin": {
|
|
8
|
-
"context-lens": "./dist/cli.js"
|
|
8
|
+
"context-lens": "./dist/cli.js",
|
|
9
|
+
"context-lens-proxy": "./dist/proxy/server.js",
|
|
10
|
+
"context-lens-analysis": "./dist/analysis/server.js"
|
|
9
11
|
},
|
|
10
12
|
"scripts": {
|
|
11
13
|
"generate:types": "json2ts schema/lhar.schema.json src/lhar-types.generated.ts --unreachableDefinitions",
|
|
@@ -13,10 +15,10 @@
|
|
|
13
15
|
"build": "pnpm run generate:version && pnpm run generate:types && tsc",
|
|
14
16
|
"clean:test": "node -e \"require('node:fs').rmSync('dist-test', { recursive: true, force: true })\"",
|
|
15
17
|
"build:test": "pnpm run generate:version && pnpm run generate:types && pnpm run clean:test && tsc -p tsconfig.test.json",
|
|
16
|
-
"start": "node dist/
|
|
18
|
+
"start": "node dist/cli.js",
|
|
17
19
|
"test": "pnpm run build:test && node --test --experimental-test-isolation=none 'dist-test/test/**/*.test.js'",
|
|
18
20
|
"dev": "tsc --watch",
|
|
19
|
-
"postbuild": "chmod +x dist/cli.js",
|
|
21
|
+
"postbuild": "chmod +x dist/cli.js dist/proxy/server.js dist/analysis/server.js",
|
|
20
22
|
"lint": "biome check .",
|
|
21
23
|
"lint:fix": "biome check --write .",
|
|
22
24
|
"prepublishOnly": "pnpm run build"
|
|
@@ -58,5 +60,10 @@
|
|
|
58
60
|
"@types/node": "^25.2.2",
|
|
59
61
|
"json-schema-to-typescript": "^15.0.4",
|
|
60
62
|
"typescript": "^5.9.3"
|
|
63
|
+
},
|
|
64
|
+
"dependencies": {
|
|
65
|
+
"@hono/node-server": "^1.19.9",
|
|
66
|
+
"hono": "^4.11.9",
|
|
67
|
+
"valibot": "^1.2.0"
|
|
61
68
|
}
|
|
62
69
|
}
|
package/schema/lhar.schema.json
CHANGED
|
@@ -21,6 +21,46 @@
|
|
|
21
21
|
]
|
|
22
22
|
},
|
|
23
23
|
|
|
24
|
+
"ToolDefinitionEntry": {
|
|
25
|
+
"type": "object",
|
|
26
|
+
"description": "A tool/function available to the model in this request.",
|
|
27
|
+
"properties": {
|
|
28
|
+
"name": { "type": "string" },
|
|
29
|
+
"description": {
|
|
30
|
+
"oneOf": [
|
|
31
|
+
{ "type": "string" },
|
|
32
|
+
{ "type": "null" }
|
|
33
|
+
]
|
|
34
|
+
}
|
|
35
|
+
},
|
|
36
|
+
"required": ["name", "description"],
|
|
37
|
+
"additionalProperties": false
|
|
38
|
+
},
|
|
39
|
+
|
|
40
|
+
"ToolCallEntry": {
|
|
41
|
+
"type": "object",
|
|
42
|
+
"description": "A tool invocation found in the conversation history of this request.",
|
|
43
|
+
"properties": {
|
|
44
|
+
"name": { "type": "string" },
|
|
45
|
+
"call_id": {
|
|
46
|
+
"oneOf": [
|
|
47
|
+
{ "type": "string" },
|
|
48
|
+
{ "type": "null" }
|
|
49
|
+
]
|
|
50
|
+
},
|
|
51
|
+
"arguments": {
|
|
52
|
+
"description": "The arguments passed to the tool. Object when parsed, string when raw/unparsed.",
|
|
53
|
+
"oneOf": [
|
|
54
|
+
{ "type": "object" },
|
|
55
|
+
{ "type": "string" },
|
|
56
|
+
{ "type": "null" }
|
|
57
|
+
]
|
|
58
|
+
}
|
|
59
|
+
},
|
|
60
|
+
"required": ["name", "call_id", "arguments"],
|
|
61
|
+
"additionalProperties": false
|
|
62
|
+
},
|
|
63
|
+
|
|
24
64
|
"CompositionEntry": {
|
|
25
65
|
"type": "object",
|
|
26
66
|
"properties": {
|
|
@@ -256,6 +296,16 @@
|
|
|
256
296
|
"required": ["tokens_added_this_turn", "cumulative_tokens", "compaction_detected"],
|
|
257
297
|
"additionalProperties": false
|
|
258
298
|
},
|
|
299
|
+
"tool_definitions": {
|
|
300
|
+
"type": "array",
|
|
301
|
+
"description": "Tool/function schemas available to the model in this request.",
|
|
302
|
+
"items": { "$ref": "#/definitions/ToolDefinitionEntry" }
|
|
303
|
+
},
|
|
304
|
+
"tool_calls": {
|
|
305
|
+
"type": "array",
|
|
306
|
+
"description": "Tool invocations found in the conversation history of this request.",
|
|
307
|
+
"items": { "$ref": "#/definitions/ToolCallEntry" }
|
|
308
|
+
},
|
|
259
309
|
"security": {
|
|
260
310
|
"type": "object",
|
|
261
311
|
"properties": {
|
package/dist/server/config.d.ts
DELETED
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import type { PrivacyLevel, Upstreams } from "../types.js";
|
|
2
|
-
export interface ServerConfig {
|
|
3
|
-
upstreams: Upstreams;
|
|
4
|
-
bindHost: string;
|
|
5
|
-
allowTargetOverride: boolean;
|
|
6
|
-
dataDir: string;
|
|
7
|
-
stateFile: string;
|
|
8
|
-
maxSessions: number;
|
|
9
|
-
maxCompactMessages: number;
|
|
10
|
-
privacy: PrivacyLevel;
|
|
11
|
-
}
|
|
12
|
-
export declare function loadServerConfig(baseDir: string): ServerConfig;
|
|
13
|
-
//# sourceMappingURL=config.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/server/config.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAE3D,MAAM,WAAW,YAAY;IAC3B,SAAS,EAAE,SAAS,CAAC;IACrB,QAAQ,EAAE,MAAM,CAAC;IACjB,mBAAmB,EAAE,OAAO,CAAC;IAC7B,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,OAAO,EAAE,YAAY,CAAC;CACvB;AAED,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,YAAY,CA8C9D"}
|
package/dist/server/config.js
DELETED
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
import path from "node:path";
|
|
2
|
-
export function loadServerConfig(baseDir) {
|
|
3
|
-
// Upstream targets, configurable via env vars
|
|
4
|
-
const UPSTREAM_OPENAI_URL = process.env.UPSTREAM_OPENAI_URL || "https://api.openai.com/v1";
|
|
5
|
-
const UPSTREAM_ANTHROPIC_URL = process.env.UPSTREAM_ANTHROPIC_URL || "https://api.anthropic.com";
|
|
6
|
-
const UPSTREAM_CHATGPT_URL = process.env.UPSTREAM_CHATGPT_URL || "https://chatgpt.com";
|
|
7
|
-
const UPSTREAM_GEMINI_URL = process.env.UPSTREAM_GEMINI_URL ||
|
|
8
|
-
"https://generativelanguage.googleapis.com";
|
|
9
|
-
const UPSTREAM_GEMINI_CODE_ASSIST_URL = process.env.UPSTREAM_GEMINI_CODE_ASSIST_URL ||
|
|
10
|
-
"https://cloudcode-pa.googleapis.com";
|
|
11
|
-
// Safety defaults:
|
|
12
|
-
// - Bind only to localhost unless explicitly overridden.
|
|
13
|
-
// - Do not honor `x-target-url` unless explicitly enabled (prevents accidental open-proxy/SSRF).
|
|
14
|
-
const bindHost = process.env.CONTEXT_LENS_BIND_HOST || "127.0.0.1";
|
|
15
|
-
const allowTargetOverride = process.env.CONTEXT_LENS_ALLOW_TARGET_OVERRIDE === "1";
|
|
16
|
-
const privacyEnv = (process.env.CONTEXT_LENS_PRIVACY || "standard").toLowerCase();
|
|
17
|
-
const privacy = privacyEnv === "minimal" || privacyEnv === "full" ? privacyEnv : "standard";
|
|
18
|
-
const dataDir = path.join(baseDir, "..", "data");
|
|
19
|
-
return {
|
|
20
|
-
upstreams: {
|
|
21
|
-
openai: UPSTREAM_OPENAI_URL,
|
|
22
|
-
anthropic: UPSTREAM_ANTHROPIC_URL,
|
|
23
|
-
chatgpt: UPSTREAM_CHATGPT_URL,
|
|
24
|
-
gemini: UPSTREAM_GEMINI_URL,
|
|
25
|
-
geminiCodeAssist: UPSTREAM_GEMINI_CODE_ASSIST_URL,
|
|
26
|
-
},
|
|
27
|
-
bindHost,
|
|
28
|
-
allowTargetOverride,
|
|
29
|
-
dataDir,
|
|
30
|
-
stateFile: path.join(dataDir, "state.jsonl"),
|
|
31
|
-
maxSessions: 100,
|
|
32
|
-
maxCompactMessages: 60,
|
|
33
|
-
privacy,
|
|
34
|
-
};
|
|
35
|
-
}
|
|
36
|
-
//# sourceMappingURL=config.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/server/config.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAC;AAe7B,MAAM,UAAU,gBAAgB,CAAC,OAAe;IAC9C,8CAA8C;IAC9C,MAAM,mBAAmB,GACvB,OAAO,CAAC,GAAG,CAAC,mBAAmB,IAAI,2BAA2B,CAAC;IACjE,MAAM,sBAAsB,GAC1B,OAAO,CAAC,GAAG,CAAC,sBAAsB,IAAI,2BAA2B,CAAC;IACpE,MAAM,oBAAoB,GACxB,OAAO,CAAC,GAAG,CAAC,oBAAoB,IAAI,qBAAqB,CAAC;IAC5D,MAAM,mBAAmB,GACvB,OAAO,CAAC,GAAG,CAAC,mBAAmB;QAC/B,2CAA2C,CAAC;IAC9C,MAAM,+BAA+B,GACnC,OAAO,CAAC,GAAG,CAAC,+BAA+B;QAC3C,qCAAqC,CAAC;IAExC,mBAAmB;IACnB,yDAAyD;IACzD,iGAAiG;IACjG,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,sBAAsB,IAAI,WAAW,CAAC;IACnE,MAAM,mBAAmB,GACvB,OAAO,CAAC,GAAG,CAAC,kCAAkC,KAAK,GAAG,CAAC;IAEzD,MAAM,UAAU,GAAG,CACjB,OAAO,CAAC,GAAG,CAAC,oBAAoB,IAAI,UAAU,CAC/C,CAAC,WAAW,EAAE,CAAC;IAChB,MAAM,OAAO,GACX,UAAU,KAAK,SAAS,IAAI,UAAU,KAAK,MAAM,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,UAAU,CAAC;IAE9E,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,IAAI,EAAE,MAAM,CAAC,CAAC;IAEjD,OAAO;QACL,SAAS,EAAE;YACT,MAAM,EAAE,mBAAmB;YAC3B,SAAS,EAAE,sBAAsB;YACjC,OAAO,EAAE,oBAAoB;YAC7B,MAAM,EAAE,mBAAmB;YAC3B,gBAAgB,EAAE,+BAA+B;SAClD;QACD,QAAQ;QACR,mBAAmB;QACnB,OAAO;QACP,SAAS,EAAE,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,aAAa,CAAC;QAC5C,WAAW,EAAE,GAAG;QAChB,kBAAkB,EAAE,EAAE;QACtB,OAAO;KACR,CAAC;AACJ,CAAC"}
|
package/dist/server/proxy.d.ts
DELETED
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import http from "node:http";
|
|
2
|
-
import url from "node:url";
|
|
3
|
-
import type { Upstreams } from "../types.js";
|
|
4
|
-
import type { Store } from "./store.js";
|
|
5
|
-
export declare function forwardRequest(req: http.IncomingMessage, res: http.ServerResponse, parsedUrl: url.UrlWithStringQuery, body: Buffer | null, opts: {
|
|
6
|
-
upstreams: Upstreams;
|
|
7
|
-
allowTargetOverride: boolean;
|
|
8
|
-
}): void;
|
|
9
|
-
export declare function createProxyHandler(store: Store, opts: {
|
|
10
|
-
upstreams: Upstreams;
|
|
11
|
-
allowTargetOverride: boolean;
|
|
12
|
-
}): (req: http.IncomingMessage, res: http.ServerResponse) => void;
|
|
13
|
-
//# sourceMappingURL=proxy.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"proxy.d.ts","sourceRoot":"","sources":["../../src/server/proxy.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,OAAO,GAAG,MAAM,UAAU,CAAC;AAS3B,OAAO,KAAK,EAA4B,SAAS,EAAE,MAAM,aAAa,CAAC;AACvE,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AA6CxC,wBAAgB,cAAc,CAC5B,GAAG,EAAE,IAAI,CAAC,eAAe,EACzB,GAAG,EAAE,IAAI,CAAC,cAAc,EACxB,SAAS,EAAE,GAAG,CAAC,kBAAkB,EACjC,IAAI,EAAE,MAAM,GAAG,IAAI,EACnB,IAAI,EAAE;IAAE,SAAS,EAAE,SAAS,CAAC;IAAC,mBAAmB,EAAE,OAAO,CAAA;CAAE,GAC3D,IAAI,CA2CN;AAED,wBAAgB,kBAAkB,CAChC,KAAK,EAAE,KAAK,EACZ,IAAI,EAAE;IAAE,SAAS,EAAE,SAAS,CAAC;IAAC,mBAAmB,EAAE,OAAO,CAAA;CAAE,GAC3D,CAAC,GAAG,EAAE,IAAI,CAAC,eAAe,EAAE,GAAG,EAAE,IAAI,CAAC,cAAc,KAAK,IAAI,CA8N/D"}
|
package/dist/server/proxy.js
DELETED
|
@@ -1,218 +0,0 @@
|
|
|
1
|
-
import http from "node:http";
|
|
2
|
-
import https from "node:https";
|
|
3
|
-
import url from "node:url";
|
|
4
|
-
import { detectApiFormat, estimateTokens, extractSource, parseContextInfo, resolveTargetUrl, } from "../core.js";
|
|
5
|
-
import { headersForResolution, selectHeaders } from "../server-utils.js";
|
|
6
|
-
function buildForwardHeaders(reqHeaders, targetHost, bodyLength) {
|
|
7
|
-
const forwardHeaders = { ...reqHeaders };
|
|
8
|
-
delete forwardHeaders["x-target-url"];
|
|
9
|
-
delete forwardHeaders.host;
|
|
10
|
-
if (targetHost) {
|
|
11
|
-
forwardHeaders.host = targetHost;
|
|
12
|
-
}
|
|
13
|
-
if (bodyLength != null) {
|
|
14
|
-
delete forwardHeaders["transfer-encoding"];
|
|
15
|
-
forwardHeaders["content-length"] = bodyLength;
|
|
16
|
-
}
|
|
17
|
-
return forwardHeaders;
|
|
18
|
-
}
|
|
19
|
-
function attachProxyLifecycleHandlers(res, proxyReq) {
|
|
20
|
-
// Abort upstream request if client disconnects
|
|
21
|
-
res.on("close", () => {
|
|
22
|
-
if (!proxyReq.destroyed)
|
|
23
|
-
proxyReq.destroy();
|
|
24
|
-
});
|
|
25
|
-
proxyReq.on("error", (err) => {
|
|
26
|
-
// Suppress errors from client-initiated disconnects
|
|
27
|
-
if (res.destroyed)
|
|
28
|
-
return;
|
|
29
|
-
const detail = err.message || ("code" in err ? err.code : "unknown");
|
|
30
|
-
console.error("Proxy error:", detail);
|
|
31
|
-
if (!res.headersSent) {
|
|
32
|
-
res.writeHead(502, { "Content-Type": "application/json" });
|
|
33
|
-
}
|
|
34
|
-
if (!res.destroyed) {
|
|
35
|
-
res.end(JSON.stringify({ error: "Proxy error", details: err.message }));
|
|
36
|
-
}
|
|
37
|
-
});
|
|
38
|
-
}
|
|
39
|
-
export function forwardRequest(req, res, parsedUrl, body, opts) {
|
|
40
|
-
const { targetUrl } = resolveTargetUrl({ pathname: parsedUrl.pathname, search: parsedUrl.search }, headersForResolution(req.headers, req.socket.remoteAddress, opts.allowTargetOverride), opts.upstreams);
|
|
41
|
-
const targetParsed = url.parse(targetUrl);
|
|
42
|
-
// When we buffer the body, replace chunked encoding with exact content-length
|
|
43
|
-
const forwardHeaders = buildForwardHeaders(req.headers, targetParsed.host, body ? body.length : undefined);
|
|
44
|
-
const protocol = targetParsed.protocol === "https:" ? https : http;
|
|
45
|
-
const proxyReq = protocol.request({
|
|
46
|
-
hostname: targetParsed.hostname,
|
|
47
|
-
port: targetParsed.port,
|
|
48
|
-
path: targetParsed.path,
|
|
49
|
-
method: req.method,
|
|
50
|
-
headers: forwardHeaders,
|
|
51
|
-
}, (proxyRes) => {
|
|
52
|
-
if (!res.headersSent)
|
|
53
|
-
res.writeHead(proxyRes.statusCode, proxyRes.headers);
|
|
54
|
-
proxyRes.pipe(res);
|
|
55
|
-
proxyRes.on("error", (err) => {
|
|
56
|
-
console.error("Upstream response error (forward):", err.message);
|
|
57
|
-
if (!res.destroyed)
|
|
58
|
-
res.end();
|
|
59
|
-
});
|
|
60
|
-
});
|
|
61
|
-
attachProxyLifecycleHandlers(res, proxyReq);
|
|
62
|
-
if (body)
|
|
63
|
-
proxyReq.write(body);
|
|
64
|
-
proxyReq.end();
|
|
65
|
-
}
|
|
66
|
-
export function createProxyHandler(store, opts) {
|
|
67
|
-
return function handleProxy(req, res) {
|
|
68
|
-
const parsedUrl = url.parse(req.url);
|
|
69
|
-
const { source, cleanPath } = extractSource(parsedUrl.pathname);
|
|
70
|
-
// Use clean path (without source prefix) for routing
|
|
71
|
-
const cleanUrl = { ...parsedUrl, pathname: cleanPath };
|
|
72
|
-
const { targetUrl, provider } = resolveTargetUrl({ pathname: cleanPath, search: parsedUrl.search }, headersForResolution(req.headers, req.socket.remoteAddress, opts.allowTargetOverride), opts.upstreams);
|
|
73
|
-
const hasAuth = !!req.headers.authorization;
|
|
74
|
-
const sourceTag = source ? `[${source}]` : "";
|
|
75
|
-
console.log(`${req.method} ${req.url} → ${targetUrl} [${provider}] ${sourceTag} auth=${hasAuth}`);
|
|
76
|
-
// For non-POST requests (GET /v1/models, OPTIONS, etc.), pass through directly
|
|
77
|
-
if (req.method !== "POST") {
|
|
78
|
-
forwardRequest(req, res, cleanUrl, null, opts);
|
|
79
|
-
return;
|
|
80
|
-
}
|
|
81
|
-
// Collect body as raw Buffers to avoid corrupting multi-byte UTF-8 at chunk boundaries
|
|
82
|
-
const chunks = [];
|
|
83
|
-
let clientAborted = false;
|
|
84
|
-
req.on("data", (chunk) => {
|
|
85
|
-
chunks.push(chunk);
|
|
86
|
-
});
|
|
87
|
-
req.on("error", () => {
|
|
88
|
-
clientAborted = true;
|
|
89
|
-
});
|
|
90
|
-
req.on("end", () => {
|
|
91
|
-
if (clientAborted)
|
|
92
|
-
return;
|
|
93
|
-
const bodyBuffer = Buffer.concat(chunks);
|
|
94
|
-
const body = bodyBuffer.toString("utf8");
|
|
95
|
-
let bodyData;
|
|
96
|
-
try {
|
|
97
|
-
bodyData = JSON.parse(body);
|
|
98
|
-
}
|
|
99
|
-
catch (_e) {
|
|
100
|
-
console.log(` ⚠ Body is not JSON (${bodyBuffer.length} bytes), capturing raw`);
|
|
101
|
-
// Still capture the raw request even if body isn't JSON
|
|
102
|
-
const rawInfo = {
|
|
103
|
-
provider,
|
|
104
|
-
apiFormat: "raw",
|
|
105
|
-
model: "unknown",
|
|
106
|
-
systemTokens: 0,
|
|
107
|
-
toolsTokens: 0,
|
|
108
|
-
messagesTokens: estimateTokens(body),
|
|
109
|
-
totalTokens: estimateTokens(body),
|
|
110
|
-
systemPrompts: [],
|
|
111
|
-
tools: [],
|
|
112
|
-
messages: [
|
|
113
|
-
{
|
|
114
|
-
role: "raw",
|
|
115
|
-
content: body.substring(0, 2000),
|
|
116
|
-
tokens: estimateTokens(body),
|
|
117
|
-
},
|
|
118
|
-
],
|
|
119
|
-
};
|
|
120
|
-
store.storeRequest(rawInfo, { raw: true }, source, undefined, undefined, selectHeaders(req.headers));
|
|
121
|
-
forwardRequest(req, res, cleanUrl, bodyBuffer, opts);
|
|
122
|
-
return;
|
|
123
|
-
}
|
|
124
|
-
console.log(` ✓ Parsed JSON body (${Object.keys(bodyData).join(", ")})`);
|
|
125
|
-
const apiFormat = detectApiFormat(cleanPath);
|
|
126
|
-
// Gemini: model is in the URL path, not in the body
|
|
127
|
-
if (apiFormat === "gemini" && !bodyData.model) {
|
|
128
|
-
const modelMatch = cleanPath.match(/\/models\/([^/:]+)/);
|
|
129
|
-
if (modelMatch)
|
|
130
|
-
bodyData.model = modelMatch[1];
|
|
131
|
-
}
|
|
132
|
-
const contextInfo = parseContextInfo(provider, bodyData, apiFormat);
|
|
133
|
-
// Skip capturing utility endpoints (count_tokens, etc.). Not real conversation turns
|
|
134
|
-
const isUtilityEndpoint = /\/count_tokens\b|:countTokens\b|:loadCodeAssist\b|:retrieveUserQuota\b|:listExperiments\b|:onboardUser\b|:fetchAdminControls\b|:recordCodeAssistMetrics\b/.test(cleanPath);
|
|
135
|
-
const targetParsed = url.parse(targetUrl);
|
|
136
|
-
// Ensure content-length matches the exact bytes we forward
|
|
137
|
-
const forwardHeaders = buildForwardHeaders(req.headers, targetParsed.host, bodyBuffer.length);
|
|
138
|
-
// Make request to actual API
|
|
139
|
-
const protocol = targetParsed.protocol === "https:" ? https : http;
|
|
140
|
-
const startTime = performance.now();
|
|
141
|
-
let firstByteTime = 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
|
-
// Forward response headers
|
|
152
|
-
res.writeHead(proxyRes.statusCode, proxyRes.headers);
|
|
153
|
-
const httpStatus = proxyRes.statusCode || 0;
|
|
154
|
-
// Handle streaming vs non-streaming
|
|
155
|
-
const isStreaming = proxyRes.headers["content-type"]?.includes("text/event-stream");
|
|
156
|
-
let respBytes = 0;
|
|
157
|
-
const capturedReqHeaders = selectHeaders(req.headers);
|
|
158
|
-
const capturedResHeaders = selectHeaders(proxyRes.headers);
|
|
159
|
-
// Collect response as Buffer[] to avoid corrupting multi-byte UTF-8 at chunk boundaries
|
|
160
|
-
const respChunks = [];
|
|
161
|
-
proxyRes.on("data", (chunk) => {
|
|
162
|
-
if (!firstByteTime)
|
|
163
|
-
firstByteTime = performance.now();
|
|
164
|
-
respBytes += chunk.length;
|
|
165
|
-
respChunks.push(chunk);
|
|
166
|
-
if (!res.destroyed)
|
|
167
|
-
res.write(chunk);
|
|
168
|
-
});
|
|
169
|
-
proxyRes.on("end", () => {
|
|
170
|
-
const endTime = performance.now();
|
|
171
|
-
if (!firstByteTime)
|
|
172
|
-
firstByteTime = endTime;
|
|
173
|
-
const meta = {
|
|
174
|
-
httpStatus,
|
|
175
|
-
timings: {
|
|
176
|
-
send_ms: Math.round(firstByteTime - startTime),
|
|
177
|
-
wait_ms: Math.round(firstByteTime - startTime),
|
|
178
|
-
receive_ms: Math.round(endTime - firstByteTime),
|
|
179
|
-
total_ms: Math.round(endTime - startTime),
|
|
180
|
-
tokens_per_second: null,
|
|
181
|
-
},
|
|
182
|
-
requestBytes: reqBytes,
|
|
183
|
-
responseBytes: respBytes,
|
|
184
|
-
targetUrl,
|
|
185
|
-
requestHeaders: capturedReqHeaders,
|
|
186
|
-
responseHeaders: capturedResHeaders,
|
|
187
|
-
};
|
|
188
|
-
const respBody = Buffer.concat(respChunks).toString("utf8");
|
|
189
|
-
if (!isUtilityEndpoint) {
|
|
190
|
-
if (isStreaming) {
|
|
191
|
-
store.storeRequest(contextInfo, { streaming: true, chunks: respBody }, source, bodyData, meta, capturedReqHeaders);
|
|
192
|
-
}
|
|
193
|
-
else {
|
|
194
|
-
try {
|
|
195
|
-
const responseData = JSON.parse(respBody);
|
|
196
|
-
store.storeRequest(contextInfo, responseData, source, bodyData, meta, capturedReqHeaders);
|
|
197
|
-
}
|
|
198
|
-
catch (_e) {
|
|
199
|
-
store.storeRequest(contextInfo, { raw: respBody }, source, bodyData, meta, capturedReqHeaders);
|
|
200
|
-
}
|
|
201
|
-
}
|
|
202
|
-
}
|
|
203
|
-
if (!res.destroyed)
|
|
204
|
-
res.end();
|
|
205
|
-
});
|
|
206
|
-
proxyRes.on("error", (err) => {
|
|
207
|
-
console.error("Upstream response error:", err.message);
|
|
208
|
-
if (!res.destroyed)
|
|
209
|
-
res.end();
|
|
210
|
-
});
|
|
211
|
-
});
|
|
212
|
-
attachProxyLifecycleHandlers(res, proxyReq);
|
|
213
|
-
proxyReq.write(bodyBuffer);
|
|
214
|
-
proxyReq.end();
|
|
215
|
-
});
|
|
216
|
-
};
|
|
217
|
-
}
|
|
218
|
-
//# sourceMappingURL=proxy.js.map
|
package/dist/server/proxy.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"proxy.js","sourceRoot":"","sources":["../../src/server/proxy.ts"],"names":[],"mappings":"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"}
|
package/dist/server/static.d.ts
DELETED
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import type http from "node:http";
|
|
2
|
-
/**
|
|
3
|
-
* Create a static file handler that serves from `uiDir` if it exists,
|
|
4
|
-
* otherwise falls back to serving `fallbackHtml` at `/`.
|
|
5
|
-
*
|
|
6
|
-
* Returns a function that handles the request, always responds.
|
|
7
|
-
*/
|
|
8
|
-
export declare function createStaticHandler(uiDir: string | null, fallbackHtml: string): (req: http.IncomingMessage, res: http.ServerResponse) => void;
|
|
9
|
-
//# sourceMappingURL=static.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"static.d.ts","sourceRoot":"","sources":["../../src/server/static.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAgBlC;;;;;GAKG;AACH,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,MAAM,GAAG,IAAI,EACpB,YAAY,EAAE,MAAM,GACnB,CAAC,GAAG,EAAE,IAAI,CAAC,eAAe,EAAE,GAAG,EAAE,IAAI,CAAC,cAAc,KAAK,IAAI,CA+D/D"}
|