Skip to content

Commit b4cff10

Browse files
committed
add possibility to add a custom headers to calls LLMs
1 parent 574a3bd commit b4cff10

File tree

2 files changed

+27
-10
lines changed

2 files changed

+27
-10
lines changed

src/seclab_taskflow_agent/agent.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
from agents.run import RunHooks
1616
from agents import Agent, Runner, AgentHooks, RunHooks, result, function_tool, Tool, RunContextWrapper, TContext, OpenAIChatCompletionsModel, set_default_openai_client, set_default_openai_api, set_tracing_disabled
1717

18-
from .capi import COPILOT_INTEGRATION_ID, get_AI_endpoint, get_AI_token, AI_API_ENDPOINT_ENUM
18+
from .capi import get_AI_endpoint, get_AI_token, get_custom_header, AI_API_ENDPOINT_ENUM
1919

2020
# grab our secrets from .env, this must be in .gitignore
2121
load_dotenv(find_dotenv(usecwd=True))
@@ -156,7 +156,7 @@ def __init__(self,
156156
agent_hooks: TaskAgentHooks | None = None):
157157
client = AsyncOpenAI(base_url=api_endpoint,
158158
api_key=get_AI_token(),
159-
default_headers={'Copilot-Integration-Id': COPILOT_INTEGRATION_ID})
159+
default_headers=get_custom_header())
160160
set_default_openai_client(client)
161161
# CAPI does not yet support the Responses API: https://github.com/github/copilot-api/issues/11185
162162
# as such we are implementing on chat completions for now

src/seclab_taskflow_agent/capi.py

Lines changed: 25 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,6 @@ def to_url(self):
2929
case _:
3030
raise ValueError(f"Unsupported endpoint: {self}")
3131

32-
COPILOT_INTEGRATION_ID = 'vscode-chat'
33-
3432
# you can also set https://api.githubcopilot.com if you prefer
3533
# but beware that your taskflows need to reference the correct model id
3634
# since different APIs use their own id schema, use -l with your desired
@@ -52,6 +50,26 @@ def get_AI_token():
5250
return token
5351
raise RuntimeError("AI_API_TOKEN environment variable is not set.")
5452

53+
def get_custom_header() -> dict[str, str]:
54+
"""
55+
Get custom header from environment variable CUSTOM_HEADER.
56+
Expected format: name:value
57+
Returns a dictionary that can be merged into request headers.
58+
"""
59+
custom_header = os.getenv('AI_API_CUSTOM_HEADER')
60+
if not custom_header:
61+
return {}
62+
63+
# Split on first colon to handle values that might contain colons
64+
parts = custom_header.split(':', 1)
65+
if len(parts) != 2:
66+
logging.warning(f"Invalid AI_API_CUSTOM_HEADER format. Expected 'name:value', got: {custom_header}")
67+
return {}
68+
69+
name, value = parts
70+
return {name.strip(): value.strip()}
71+
72+
5573
# assume we are >= python 3.9 for our type hints
5674
def list_capi_models(token: str) -> dict[str, dict]:
5775
"""Retrieve a dictionary of available CAPI models"""
@@ -69,12 +87,11 @@ def list_capi_models(token: str) -> dict[str, dict]:
6987
case _:
7088
raise ValueError(f"Unsupported Model Endpoint: {api_endpoint}\n"
7189
f"Supported endpoints: {[e.to_url() for e in AI_API_ENDPOINT_ENUM]}")
72-
r = httpx.get(httpx.URL(api_endpoint).join(models_catalog),
73-
headers={
74-
'Accept': 'application/json',
75-
'Authorization': f'Bearer {token}',
76-
'Copilot-Integration-Id': COPILOT_INTEGRATION_ID
77-
})
90+
headers = {
91+
'Accept': 'application/json',
92+
'Authorization': f'Bearer {token}',
93+
} | get_custom_header()
94+
r = httpx.get(httpx.URL(api_endpoint).join(models_catalog), headers=headers)
7895
r.raise_for_status()
7996
# CAPI vs Models API
8097
match netloc:

0 commit comments

Comments
 (0)