ai-cc-router 0.2.1 → 0.2.2
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.
|
@@ -136,7 +136,7 @@ export function writeAddonScript(target) {
|
|
|
136
136
|
writeFileSync(ADDON_PATH, src, "utf-8");
|
|
137
137
|
}
|
|
138
138
|
else {
|
|
139
|
-
// Inline fallback — minimal addon
|
|
139
|
+
// Inline fallback — minimal addon (only redirects /v1/messages and /v1/models)
|
|
140
140
|
const script = `
|
|
141
141
|
import os
|
|
142
142
|
from mitmproxy import http
|
|
@@ -144,10 +144,13 @@ from urllib.parse import urlparse
|
|
|
144
144
|
|
|
145
145
|
_target = os.environ.get("CC_ROUTER_TARGET", ${JSON.stringify(target)}).rstrip("/")
|
|
146
146
|
_p = urlparse(_target)
|
|
147
|
+
_REDIRECT_PREFIXES = ("/v1/messages", "/v1/models")
|
|
147
148
|
|
|
148
149
|
def request(flow: http.HTTPFlow) -> None:
|
|
149
150
|
if flow.request.pretty_host != "api.anthropic.com":
|
|
150
151
|
return
|
|
152
|
+
if not flow.request.path.startswith(_REDIRECT_PREFIXES):
|
|
153
|
+
return
|
|
151
154
|
flow.request.scheme = _p.scheme
|
|
152
155
|
flow.request.host = _p.hostname or "localhost"
|
|
153
156
|
flow.request.port = _p.port or (443 if _p.scheme == "https" else 80)
|
package/package.json
CHANGED
package/src/interceptor/addon.py
CHANGED
|
@@ -1,11 +1,16 @@
|
|
|
1
|
-
# mitmproxy addon — redirects
|
|
1
|
+
# mitmproxy addon — redirects ONLY /v1/messages traffic to CC-Router.
|
|
2
2
|
#
|
|
3
|
-
#
|
|
4
|
-
#
|
|
3
|
+
# Claude Desktop sends many types of requests to api.anthropic.com:
|
|
4
|
+
# /v1/messages → LLM inference (this is what we redirect)
|
|
5
|
+
# /v1/messages/count_tokens → token counting (redirect too)
|
|
6
|
+
# /v1/oauth/* → session auth (must NOT redirect)
|
|
7
|
+
# /v1/environments/* → bridge/cowork (must NOT redirect)
|
|
8
|
+
# /v1/models → model listing (redirect — CC-Router proxies this)
|
|
9
|
+
# /api/* → desktop features (must NOT redirect)
|
|
5
10
|
#
|
|
6
|
-
#
|
|
7
|
-
#
|
|
8
|
-
#
|
|
11
|
+
# Only /v1/messages* and /v1/models are safe to redirect because CC-Router
|
|
12
|
+
# injects its own OAuth token. Everything else carries the user's own
|
|
13
|
+
# session token for features CC-Router doesn't handle.
|
|
9
14
|
|
|
10
15
|
import os
|
|
11
16
|
from urllib.parse import urlparse
|
|
@@ -16,22 +21,27 @@ _target_raw = os.environ.get("CC_ROUTER_TARGET", "http://localhost:3456")
|
|
|
16
21
|
_target = _target_raw.rstrip("/")
|
|
17
22
|
_target_parsed = urlparse(_target)
|
|
18
23
|
|
|
19
|
-
# Fail closed on boot if the target is unusable — better than silently
|
|
20
|
-
# forwarding to a broken URL and seeing Claude Desktop timeout.
|
|
21
24
|
if not _target_parsed.scheme or not _target_parsed.netloc:
|
|
22
25
|
raise RuntimeError(f"CC_ROUTER_TARGET is not a valid URL: {_target_raw!r}")
|
|
23
26
|
|
|
27
|
+
# Paths that CC-Router can handle (it injects its own OAuth token)
|
|
28
|
+
_REDIRECT_PREFIXES = (
|
|
29
|
+
"/v1/messages",
|
|
30
|
+
"/v1/models",
|
|
31
|
+
)
|
|
32
|
+
|
|
24
33
|
|
|
25
34
|
def request(flow: http.HTTPFlow) -> None:
|
|
26
35
|
if flow.request.pretty_host != "api.anthropic.com":
|
|
27
36
|
return
|
|
28
37
|
|
|
29
|
-
#
|
|
30
|
-
|
|
38
|
+
# Only redirect inference and model-listing paths
|
|
39
|
+
if not flow.request.path.startswith(_REDIRECT_PREFIXES):
|
|
40
|
+
return
|
|
41
|
+
|
|
31
42
|
flow.request.scheme = _target_parsed.scheme
|
|
32
43
|
flow.request.host = _target_parsed.hostname or "localhost"
|
|
33
44
|
flow.request.port = _target_parsed.port or (443 if _target_parsed.scheme == "https" else 80)
|
|
34
|
-
# Rewrite the Host header so CC-Router sees itself, not api.anthropic.com.
|
|
35
45
|
flow.request.headers["host"] = flow.request.host + (
|
|
36
46
|
f":{flow.request.port}"
|
|
37
47
|
if flow.request.port not in (80, 443)
|