fix(agent): preload jiter native parser
This commit is contained in:
@ -4,3 +4,5 @@ These modules contain pure utility functions and self-contained classes
|
|||||||
that were previously embedded in the 3,600-line run_agent.py. Extracting
|
that were previously embedded in the 3,600-line run_agent.py. Extracting
|
||||||
them makes run_agent.py focused on the AIAgent orchestrator class.
|
them makes run_agent.py focused on the AIAgent orchestrator class.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
from . import jiter_preload as _jiter_preload # noqa: F401
|
||||||
|
|||||||
39
agent/jiter_preload.py
Normal file
39
agent/jiter_preload.py
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
"""Best-effort early import for the OpenAI SDK's native streaming parser.
|
||||||
|
|
||||||
|
The OpenAI SDK imports ``jiter`` while constructing streaming chat-completion
|
||||||
|
responses. On some Windows installs the native extension can be imported
|
||||||
|
directly from the Hermes venv, but the first import fails when it happens later
|
||||||
|
inside the threaded streaming request path. Loading it once during agent
|
||||||
|
package import avoids that import-order failure while preserving the normal
|
||||||
|
SDK error path for genuinely missing or broken installs.
|
||||||
|
"""
|
||||||
|
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import importlib
|
||||||
|
|
||||||
|
_JITER_PRELOADED = False
|
||||||
|
_JITER_PRELOAD_ERROR: Exception | None = None
|
||||||
|
|
||||||
|
|
||||||
|
def preload_jiter_native_extension() -> bool:
|
||||||
|
"""Import jiter's native extension early if it is available."""
|
||||||
|
|
||||||
|
global _JITER_PRELOADED, _JITER_PRELOAD_ERROR
|
||||||
|
|
||||||
|
if _JITER_PRELOADED:
|
||||||
|
return True
|
||||||
|
|
||||||
|
try:
|
||||||
|
importlib.import_module("jiter.jiter")
|
||||||
|
from jiter import from_json as _from_json # noqa: F401
|
||||||
|
except Exception as exc:
|
||||||
|
_JITER_PRELOAD_ERROR = exc
|
||||||
|
return False
|
||||||
|
|
||||||
|
_JITER_PRELOADED = True
|
||||||
|
_JITER_PRELOAD_ERROR = None
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
preload_jiter_native_extension()
|
||||||
25
tests/agent/test_jiter_preload.py
Normal file
25
tests/agent/test_jiter_preload.py
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import importlib
|
||||||
|
import sys
|
||||||
|
|
||||||
|
from agent import jiter_preload
|
||||||
|
|
||||||
|
|
||||||
|
def test_preload_jiter_native_extension_loads_sdk_parser_dependency():
|
||||||
|
assert jiter_preload.preload_jiter_native_extension() is True
|
||||||
|
assert "jiter.jiter" in sys.modules
|
||||||
|
|
||||||
|
|
||||||
|
def test_preload_jiter_native_extension_is_best_effort(monkeypatch):
|
||||||
|
monkeypatch.setattr(jiter_preload, "_JITER_PRELOADED", False)
|
||||||
|
|
||||||
|
def _raise_missing(name: str):
|
||||||
|
assert name == "jiter.jiter"
|
||||||
|
raise ModuleNotFoundError(name)
|
||||||
|
|
||||||
|
monkeypatch.setattr(importlib, "import_module", _raise_missing)
|
||||||
|
|
||||||
|
assert jiter_preload.preload_jiter_native_extension() is False
|
||||||
|
assert jiter_preload._JITER_PRELOADED is False
|
||||||
|
assert isinstance(jiter_preload._JITER_PRELOAD_ERROR, ModuleNotFoundError)
|
||||||
Reference in New Issue
Block a user