Skip to content

Commit 86a0539

Browse files
author
Sebastian Braun
committed
fix(indexer): forward extra_headers/timeout to PageIndex's llm_params
Header-only gateway auth (litellm.extra_headers, e.g. a proxy Bearer token with no LLM_API_KEY) never reached PageIndex's own LLM calls, only api_key/base_url did (see #219) - PageIndex's internal indexing calls had no credentials at all in that setup and failed with AuthenticationError.
1 parent cd23188 commit 86a0539

2 files changed

Lines changed: 54 additions & 14 deletions

File tree

‎openkb/indexer.py‎

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -163,14 +163,17 @@ def _build_index_config(config: dict[str, Any], bundle=None) -> IndexConfig:
163163
working against a pinned PageIndex that predates it (``IndexConfig``
164164
forbids unknown kwargs).
165165
166-
``bundle``'s ``api_key``/``base_url`` (the same credentials ``compiler.py``'s
167-
own LLM calls use — see :func:`openkb.config.resolve_credential_bundle`) are
168-
forwarded as PageIndex's own per-call ``llm_params`` (see #219): without
169-
this, PageIndex's internal indexing calls (TOC/tree/summary generation)
170-
fall back to LiteLLM's default provider-key/env-var lookup, which doesn't
171-
know about a KB's custom ``LLM_API_KEY``/gateway ``base_url``. Guarded by
172-
the same ``model_fields`` check as ``max_concurrency`` above, so it
173-
degrades gracefully against an older pinned PageIndex.
166+
``bundle``'s ``api_key``/``base_url``/``extra_headers``/``timeout`` (the
167+
same credentials ``compiler.py``'s own LLM calls use — see
168+
:func:`openkb.config.resolve_credential_bundle`) are forwarded as
169+
PageIndex's own per-call ``llm_params`` (see #219): without this,
170+
PageIndex's internal indexing calls (TOC/tree/summary generation) fall
171+
back to LiteLLM's default provider-key/env-var lookup, which doesn't know
172+
about a KB's custom ``LLM_API_KEY``/gateway ``base_url`` — or, for
173+
gateways authenticated purely via a header (e.g. an ``Authorization:
174+
Bearer`` proxy token in ``litellm.extra_headers``), has no credentials at
175+
all. Guarded by the same ``model_fields`` check as ``max_concurrency``
176+
above, so it degrades gracefully against an older pinned PageIndex.
174177
"""
175178
kwargs: dict[str, Any] = {
176179
"if_add_node_text": True,
@@ -189,8 +192,13 @@ def _build_index_config(config: dict[str, Any], bundle=None) -> IndexConfig:
189192
if bundle is not None:
190193
llm_params = {
191194
key: value
192-
for key, value in {"api_key": bundle.api_key, "base_url": bundle.base_url}.items()
193-
if value
195+
for key, value in {
196+
"api_key": bundle.api_key,
197+
"base_url": bundle.base_url,
198+
"extra_headers": bundle.extra_headers,
199+
"timeout": bundle.timeout,
200+
}.items()
201+
if value or (key == "timeout" and value is not None)
194202
}
195203
if llm_params:
196204
if "llm_params" in IndexConfig.model_fields:

‎tests/test_indexer.py‎

Lines changed: 36 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -99,15 +99,18 @@ def test_no_warning_when_supported(self, monkeypatch, caplog):
9999

100100

101101
class _FakeBundle:
102-
def __init__(self, api_key=None, base_url=None):
102+
def __init__(self, api_key=None, base_url=None, extra_headers=None, timeout=None):
103103
self.api_key = api_key
104104
self.base_url = base_url
105+
self.extra_headers = extra_headers or {}
106+
self.timeout = timeout
105107

106108

107109
class TestBuildIndexConfigLlmParams:
108-
"""``bundle``'s api_key/base_url must reach PageIndex's own LLM calls via
109-
``IndexConfig(llm_params=...)`` (#219) — without this they silently fall
110-
back to LiteLLM's default provider-key/env-var lookup."""
110+
"""``bundle``'s api_key/base_url/extra_headers/timeout must reach PageIndex's
111+
own LLM calls via ``IndexConfig(llm_params=...)`` (#219) — without this they
112+
silently fall back to LiteLLM's default provider-key/env-var lookup (or, for
113+
header-only gateway auth, have no credentials at all)."""
111114

112115
def test_forwards_api_key_and_base_url_when_supported(self, monkeypatch):
113116
monkeypatch.setattr("openkb.indexer.IndexConfig", _FakeIndexConfigWithConcurrency)
@@ -138,6 +141,35 @@ def test_does_not_forward_when_unsupported(self, monkeypatch, caplog):
138141
assert not hasattr(cfg, "llm_params")
139142
assert "llm_params" in caplog.text
140143

144+
def test_forwards_extra_headers_and_timeout_when_supported(self, monkeypatch):
145+
monkeypatch.setattr("openkb.indexer.IndexConfig", _FakeIndexConfigWithConcurrency)
146+
bundle = _FakeBundle(extra_headers={"Authorization": "Bearer proxy-token"}, timeout=30.0)
147+
cfg = _build_index_config({}, bundle)
148+
assert cfg.llm_params == {
149+
"extra_headers": {"Authorization": "Bearer proxy-token"},
150+
"timeout": 30.0,
151+
}
152+
153+
def test_empty_extra_headers_is_not_forwarded(self, monkeypatch):
154+
monkeypatch.setattr("openkb.indexer.IndexConfig", _FakeIndexConfigWithConcurrency)
155+
cfg = _build_index_config({}, _FakeBundle(extra_headers={}))
156+
assert not hasattr(cfg, "llm_params")
157+
158+
def test_zero_timeout_is_forwarded(self, monkeypatch):
159+
# timeout=0 is falsy but a deliberately-set value — must not be filtered
160+
# out the same way an unset (None) timeout is.
161+
monkeypatch.setattr("openkb.indexer.IndexConfig", _FakeIndexConfigWithConcurrency)
162+
cfg = _build_index_config({}, _FakeBundle(timeout=0))
163+
assert cfg.llm_params == {"timeout": 0}
164+
165+
def test_header_only_gateway_auth_is_forwarded_without_api_key(self, monkeypatch):
166+
# Regression: proxy/gateway setups that authenticate purely via a
167+
# header (no LLM_API_KEY) must still reach PageIndex's LLM calls.
168+
monkeypatch.setattr("openkb.indexer.IndexConfig", _FakeIndexConfigWithConcurrency)
169+
bundle = _FakeBundle(extra_headers={"Authorization": "Bearer proxy-token"})
170+
cfg = _build_index_config({}, bundle)
171+
assert cfg.llm_params == {"extra_headers": {"Authorization": "Bearer proxy-token"}}
172+
141173

142174
class TestClosePageindexClient:
143175
"""Best-effort close of PageIndex's local SQLite connection(s) — see #249."""

0 commit comments

Comments
 (0)