|
9 | 9 | import click |
10 | 10 |
|
11 | 11 | from headroom import paths as _paths |
12 | | -from headroom.providers.registry import resolve_api_overrides, resolve_api_targets |
| 12 | +from headroom.providers.registry import ( |
| 13 | + resolve_api_overrides, |
| 14 | + resolve_api_targets, |
| 15 | + resolve_extra_headers, |
| 16 | +) |
13 | 17 | from headroom.proxy.modes import PROXY_MODE_CACHE, normalize_proxy_mode |
14 | 18 |
|
15 | 19 | from .main import main |
@@ -872,6 +876,22 @@ def dashboard(port: int, no_open: bool) -> None: |
872 | 876 | "Default: /tmp/headroom-embed-{port}.sock. " |
873 | 877 | "(env: HEADROOM_EMBEDDING_SERVER_SOCKET)", |
874 | 878 | ) |
| 879 | +@click.option( |
| 880 | + "--anthropic-extra-headers", |
| 881 | + default=None, |
| 882 | + help=( |
| 883 | + "JSON object of extra headers merged into (and overriding) headers forwarded to " |
| 884 | + 'the Anthropic endpoint, e.g. \'{"Api-Key": "..."}\' (env: ANTHROPIC_TARGET_API_HEADERS)' |
| 885 | + ), |
| 886 | +) |
| 887 | +@click.option( |
| 888 | + "--openai-extra-headers", |
| 889 | + default=None, |
| 890 | + help=( |
| 891 | + "JSON object of extra headers merged into (and overriding) headers forwarded to " |
| 892 | + "the OpenAI endpoint (env: OPENAI_TARGET_API_HEADERS)" |
| 893 | + ), |
| 894 | +) |
875 | 895 | @click.pass_context |
876 | 896 | def proxy( |
877 | 897 | ctx: click.Context, |
@@ -943,6 +963,8 @@ def proxy( |
943 | 963 | backend: str, |
944 | 964 | anyllm_provider: str, |
945 | 965 | anthropic_api_url: str | None, |
| 966 | + anthropic_extra_headers: str | None, |
| 967 | + openai_extra_headers: str | None, |
946 | 968 | openai_api_url: str | None, |
947 | 969 | gemini_api_url: str | None, |
948 | 970 | cloudcode_api_url: str | None, |
@@ -1047,6 +1069,17 @@ def proxy( |
1047 | 1069 | sys.exit(1) |
1048 | 1070 | os.environ["HEADROOM_INTERCEPT_ENABLED"] = "1" |
1049 | 1071 |
|
| 1072 | + try: |
| 1073 | + resolved_anthropic_extra_headers = resolve_extra_headers( |
| 1074 | + anthropic_extra_headers, "ANTHROPIC_TARGET_API_HEADERS" |
| 1075 | + ) |
| 1076 | + resolved_openai_extra_headers = resolve_extra_headers( |
| 1077 | + openai_extra_headers, "OPENAI_TARGET_API_HEADERS" |
| 1078 | + ) |
| 1079 | + except ValueError as exc: |
| 1080 | + click.secho(f"error: {exc}", fg="red", err=True) |
| 1081 | + sys.exit(1) |
| 1082 | + |
1050 | 1083 | provider_api_overrides = resolve_api_overrides( |
1051 | 1084 | anthropic_api_url=anthropic_api_url, |
1052 | 1085 | openai_api_url=openai_api_url, |
@@ -1110,6 +1143,8 @@ def proxy( |
1110 | 1143 | host=host, |
1111 | 1144 | port=port, |
1112 | 1145 | anthropic_api_url=provider_api_overrides.anthropic, |
| 1146 | + anthropic_extra_headers=resolved_anthropic_extra_headers, |
| 1147 | + openai_extra_headers=resolved_openai_extra_headers, |
1113 | 1148 | openai_api_url=provider_api_overrides.openai, |
1114 | 1149 | gemini_api_url=provider_api_overrides.gemini, |
1115 | 1150 | cloudcode_api_url=provider_api_overrides.cloudcode, |
|
0 commit comments