codex-agent-framework 0.1.46__tar.gz → 0.1.48__tar.gz
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.
- {codex_agent_framework-0.1.46 → codex_agent_framework-0.1.48}/CHANGELOG.md +17 -0
- {codex_agent_framework-0.1.46/codex_agent_framework.egg-info → codex_agent_framework-0.1.48}/PKG-INFO +1 -1
- {codex_agent_framework-0.1.46 → codex_agent_framework-0.1.48}/codex_agent/ai.py +39 -16
- {codex_agent_framework-0.1.46 → codex_agent_framework-0.1.48}/codex_agent/config.py +1 -0
- codex_agent_framework-0.1.48/codex_agent/version.py +1 -0
- {codex_agent_framework-0.1.46 → codex_agent_framework-0.1.48/codex_agent_framework.egg-info}/PKG-INFO +1 -1
- {codex_agent_framework-0.1.46 → codex_agent_framework-0.1.48}/pyproject.toml +1 -1
- {codex_agent_framework-0.1.46 → codex_agent_framework-0.1.48}/tests/test_ai.py +43 -0
- codex_agent_framework-0.1.46/codex_agent/version.py +0 -1
- {codex_agent_framework-0.1.46 → codex_agent_framework-0.1.48}/LICENSE +0 -0
- {codex_agent_framework-0.1.46 → codex_agent_framework-0.1.48}/MANIFEST.in +0 -0
- {codex_agent_framework-0.1.46 → codex_agent_framework-0.1.48}/README.md +0 -0
- {codex_agent_framework-0.1.46 → codex_agent_framework-0.1.48}/codex_agent/__init__.py +0 -0
- {codex_agent_framework-0.1.46 → codex_agent_framework-0.1.48}/codex_agent/__main__.py +0 -0
- {codex_agent_framework-0.1.46 → codex_agent_framework-0.1.48}/codex_agent/agent.py +0 -0
- {codex_agent_framework-0.1.46 → codex_agent_framework-0.1.48}/codex_agent/agent_runtime.py +0 -0
- {codex_agent_framework-0.1.46 → codex_agent_framework-0.1.48}/codex_agent/browser.py +0 -0
- {codex_agent_framework-0.1.46 → codex_agent_framework-0.1.48}/codex_agent/builtin_commands.py +0 -0
- {codex_agent_framework-0.1.46 → codex_agent_framework-0.1.48}/codex_agent/builtin_plugins/__init__.py +0 -0
- {codex_agent_framework-0.1.46 → codex_agent_framework-0.1.48}/codex_agent/builtin_plugins/bash/__init__.py +0 -0
- {codex_agent_framework-0.1.46 → codex_agent_framework-0.1.48}/codex_agent/builtin_plugins/bash/requirements.txt +0 -0
- {codex_agent_framework-0.1.46 → codex_agent_framework-0.1.48}/codex_agent/builtin_plugins/browser/__init__.py +0 -0
- {codex_agent_framework-0.1.46 → codex_agent_framework-0.1.48}/codex_agent/builtin_plugins/browser/requirements.txt +0 -0
- {codex_agent_framework-0.1.46 → codex_agent_framework-0.1.48}/codex_agent/builtin_plugins/content/__init__.py +0 -0
- {codex_agent_framework-0.1.46 → codex_agent_framework-0.1.48}/codex_agent/builtin_plugins/content/requirements.txt +0 -0
- {codex_agent_framework-0.1.46 → codex_agent_framework-0.1.48}/codex_agent/builtin_plugins/content/system.py +0 -0
- {codex_agent_framework-0.1.46 → codex_agent_framework-0.1.48}/codex_agent/builtin_plugins/content/vision.py +0 -0
- {codex_agent_framework-0.1.46 → codex_agent_framework-0.1.48}/codex_agent/builtin_plugins/context/__init__.py +0 -0
- {codex_agent_framework-0.1.46 → codex_agent_framework-0.1.48}/codex_agent/builtin_plugins/desktop/__init__.py +0 -0
- {codex_agent_framework-0.1.46 → codex_agent_framework-0.1.48}/codex_agent/builtin_plugins/desktop/requirements.txt +0 -0
- {codex_agent_framework-0.1.46 → codex_agent_framework-0.1.48}/codex_agent/builtin_plugins/environment/__init__.py +0 -0
- {codex_agent_framework-0.1.46 → codex_agent_framework-0.1.48}/codex_agent/builtin_plugins/environment/requirements.txt +0 -0
- {codex_agent_framework-0.1.46 → codex_agent_framework-0.1.48}/codex_agent/builtin_plugins/files/__init__.py +0 -0
- {codex_agent_framework-0.1.46 → codex_agent_framework-0.1.48}/codex_agent/builtin_plugins/files/requirements.txt +0 -0
- {codex_agent_framework-0.1.46 → codex_agent_framework-0.1.48}/codex_agent/builtin_plugins/files/tools.py +0 -0
- {codex_agent_framework-0.1.46 → codex_agent_framework-0.1.48}/codex_agent/builtin_plugins/image_generation/__init__.py +0 -0
- {codex_agent_framework-0.1.46 → codex_agent_framework-0.1.48}/codex_agent/builtin_plugins/image_generation/image_generation_system_prompt.txt +0 -0
- {codex_agent_framework-0.1.46 → codex_agent_framework-0.1.48}/codex_agent/builtin_plugins/image_generation/requirements.txt +0 -0
- {codex_agent_framework-0.1.46 → codex_agent_framework-0.1.48}/codex_agent/builtin_plugins/interface/__init__.py +0 -0
- {codex_agent_framework-0.1.46 → codex_agent_framework-0.1.48}/codex_agent/builtin_plugins/interface/requirements.txt +0 -0
- {codex_agent_framework-0.1.46 → codex_agent_framework-0.1.48}/codex_agent/builtin_plugins/memory/__init__.py +0 -0
- {codex_agent_framework-0.1.46 → codex_agent_framework-0.1.48}/codex_agent/builtin_plugins/memory/requirements.txt +0 -0
- {codex_agent_framework-0.1.46 → codex_agent_framework-0.1.48}/codex_agent/builtin_plugins/planner/__init__.py +0 -0
- {codex_agent_framework-0.1.46 → codex_agent_framework-0.1.48}/codex_agent/builtin_plugins/planner/requirements.txt +0 -0
- {codex_agent_framework-0.1.46 → codex_agent_framework-0.1.48}/codex_agent/builtin_plugins/python/__init__.py +0 -0
- {codex_agent_framework-0.1.46 → codex_agent_framework-0.1.48}/codex_agent/builtin_plugins/python/requirements.txt +0 -0
- {codex_agent_framework-0.1.46 → codex_agent_framework-0.1.48}/codex_agent/builtin_plugins/realtime/__init__.py +0 -0
- {codex_agent_framework-0.1.46 → codex_agent_framework-0.1.48}/codex_agent/builtin_plugins/realtime/audio.py +0 -0
- {codex_agent_framework-0.1.46 → codex_agent_framework-0.1.48}/codex_agent/builtin_plugins/realtime/bridge.py +0 -0
- {codex_agent_framework-0.1.46 → codex_agent_framework-0.1.48}/codex_agent/builtin_plugins/realtime/manager.py +0 -0
- {codex_agent_framework-0.1.46 → codex_agent_framework-0.1.48}/codex_agent/builtin_plugins/realtime/requirements.txt +0 -0
- {codex_agent_framework-0.1.46 → codex_agent_framework-0.1.48}/codex_agent/builtin_plugins/realtime/session.py +0 -0
- {codex_agent_framework-0.1.46 → codex_agent_framework-0.1.48}/codex_agent/builtin_plugins/scheduler/__init__.py +0 -0
- {codex_agent_framework-0.1.46 → codex_agent_framework-0.1.48}/codex_agent/builtin_plugins/scheduler/requirements.txt +0 -0
- {codex_agent_framework-0.1.46 → codex_agent_framework-0.1.48}/codex_agent/builtin_plugins/subagents/__init__.py +0 -0
- {codex_agent_framework-0.1.46 → codex_agent_framework-0.1.48}/codex_agent/builtin_plugins/subagents/profiles/explorer.json +0 -0
- {codex_agent_framework-0.1.46 → codex_agent_framework-0.1.48}/codex_agent/builtin_plugins/subagents/requirements.txt +0 -0
- {codex_agent_framework-0.1.46 → codex_agent_framework-0.1.48}/codex_agent/builtin_plugins/tts/__init__.py +0 -0
- {codex_agent_framework-0.1.46 → codex_agent_framework-0.1.48}/codex_agent/builtin_plugins/tts/requirements.txt +0 -0
- {codex_agent_framework-0.1.46 → codex_agent_framework-0.1.48}/codex_agent/cli/__init__.py +0 -0
- {codex_agent_framework-0.1.46 → codex_agent_framework-0.1.48}/codex_agent/cli/headless.py +0 -0
- {codex_agent_framework-0.1.46 → codex_agent_framework-0.1.48}/codex_agent/cli/main.py +0 -0
- {codex_agent_framework-0.1.46 → codex_agent_framework-0.1.48}/codex_agent/cli/output.py +0 -0
- {codex_agent_framework-0.1.46 → codex_agent_framework-0.1.48}/codex_agent/cli/root.py +0 -0
- {codex_agent_framework-0.1.46 → codex_agent_framework-0.1.48}/codex_agent/cli/runner.py +0 -0
- {codex_agent_framework-0.1.46 → codex_agent_framework-0.1.48}/codex_agent/client.py +0 -0
- {codex_agent_framework-0.1.46 → codex_agent_framework-0.1.48}/codex_agent/command.py +0 -0
- {codex_agent_framework-0.1.46 → codex_agent_framework-0.1.48}/codex_agent/context.py +0 -0
- {codex_agent_framework-0.1.46 → codex_agent_framework-0.1.48}/codex_agent/desktop.py +0 -0
- {codex_agent_framework-0.1.46 → codex_agent_framework-0.1.48}/codex_agent/event.py +0 -0
- {codex_agent_framework-0.1.46 → codex_agent_framework-0.1.48}/codex_agent/get_text/__init__.py +0 -0
- {codex_agent_framework-0.1.46 → codex_agent_framework-0.1.48}/codex_agent/get_text/default_gitignore +0 -0
- {codex_agent_framework-0.1.46 → codex_agent_framework-0.1.48}/codex_agent/get_text/get_text.py +0 -0
- {codex_agent_framework-0.1.46 → codex_agent_framework-0.1.48}/codex_agent/get_text/simpler_get_text.py +0 -0
- {codex_agent_framework-0.1.46 → codex_agent_framework-0.1.48}/codex_agent/hooks.py +0 -0
- {codex_agent_framework-0.1.46 → codex_agent_framework-0.1.48}/codex_agent/image.py +0 -0
- {codex_agent_framework-0.1.46 → codex_agent_framework-0.1.48}/codex_agent/latex.py +0 -0
- {codex_agent_framework-0.1.46 → codex_agent_framework-0.1.48}/codex_agent/mainloop.py +0 -0
- {codex_agent_framework-0.1.46 → codex_agent_framework-0.1.48}/codex_agent/message.py +0 -0
- {codex_agent_framework-0.1.46 → codex_agent_framework-0.1.48}/codex_agent/plugin.py +0 -0
- {codex_agent_framework-0.1.46 → codex_agent_framework-0.1.48}/codex_agent/prompts/system_prompt.txt +0 -0
- {codex_agent_framework-0.1.46 → codex_agent_framework-0.1.48}/codex_agent/provider.py +0 -0
- {codex_agent_framework-0.1.46 → codex_agent_framework-0.1.48}/codex_agent/runtime.py +0 -0
- {codex_agent_framework-0.1.46 → codex_agent_framework-0.1.48}/codex_agent/scheduler.py +0 -0
- {codex_agent_framework-0.1.46 → codex_agent_framework-0.1.48}/codex_agent/scripts/install-system-dependencies.sh +0 -0
- {codex_agent_framework-0.1.46 → codex_agent_framework-0.1.48}/codex_agent/server/__init__.py +0 -0
- {codex_agent_framework-0.1.46 → codex_agent_framework-0.1.48}/codex_agent/server/app.py +0 -0
- {codex_agent_framework-0.1.46 → codex_agent_framework-0.1.48}/codex_agent/server/core.py +0 -0
- {codex_agent_framework-0.1.46 → codex_agent_framework-0.1.48}/codex_agent/service.py +0 -0
- {codex_agent_framework-0.1.46 → codex_agent_framework-0.1.48}/codex_agent/sessions.py +0 -0
- {codex_agent_framework-0.1.46 → codex_agent_framework-0.1.48}/codex_agent/status.py +0 -0
- {codex_agent_framework-0.1.46 → codex_agent_framework-0.1.48}/codex_agent/stream.py +0 -0
- {codex_agent_framework-0.1.46 → codex_agent_framework-0.1.48}/codex_agent/stream_utils.py +0 -0
- {codex_agent_framework-0.1.46 → codex_agent_framework-0.1.48}/codex_agent/tool.py +0 -0
- {codex_agent_framework-0.1.46 → codex_agent_framework-0.1.48}/codex_agent/tray.py +0 -0
- {codex_agent_framework-0.1.46 → codex_agent_framework-0.1.48}/codex_agent/tui/__init__.py +0 -0
- {codex_agent_framework-0.1.46 → codex_agent_framework-0.1.48}/codex_agent/tui/app.py +0 -0
- {codex_agent_framework-0.1.46 → codex_agent_framework-0.1.48}/codex_agent/tui/chat.py +0 -0
- {codex_agent_framework-0.1.46 → codex_agent_framework-0.1.48}/codex_agent/tui/lifecycle.py +0 -0
- {codex_agent_framework-0.1.46 → codex_agent_framework-0.1.48}/codex_agent/tui/log.py +0 -0
- {codex_agent_framework-0.1.46 → codex_agent_framework-0.1.48}/codex_agent/tui/state.py +0 -0
- {codex_agent_framework-0.1.46 → codex_agent_framework-0.1.48}/codex_agent/tui/status_bar.py +0 -0
- {codex_agent_framework-0.1.46 → codex_agent_framework-0.1.48}/codex_agent/tui/style.py +0 -0
- {codex_agent_framework-0.1.46 → codex_agent_framework-0.1.48}/codex_agent/tui/transcript.py +0 -0
- {codex_agent_framework-0.1.46 → codex_agent_framework-0.1.48}/codex_agent/utils.py +0 -0
- {codex_agent_framework-0.1.46 → codex_agent_framework-0.1.48}/codex_agent/worker.py +0 -0
- {codex_agent_framework-0.1.46 → codex_agent_framework-0.1.48}/codex_agent_framework.egg-info/SOURCES.txt +0 -0
- {codex_agent_framework-0.1.46 → codex_agent_framework-0.1.48}/codex_agent_framework.egg-info/dependency_links.txt +0 -0
- {codex_agent_framework-0.1.46 → codex_agent_framework-0.1.48}/codex_agent_framework.egg-info/entry_points.txt +0 -0
- {codex_agent_framework-0.1.46 → codex_agent_framework-0.1.48}/codex_agent_framework.egg-info/requires.txt +0 -0
- {codex_agent_framework-0.1.46 → codex_agent_framework-0.1.48}/codex_agent_framework.egg-info/top_level.txt +0 -0
- {codex_agent_framework-0.1.46 → codex_agent_framework-0.1.48}/dependencies.txt +0 -0
- {codex_agent_framework-0.1.46 → codex_agent_framework-0.1.48}/setup.cfg +0 -0
- {codex_agent_framework-0.1.46 → codex_agent_framework-0.1.48}/tests/test_agent.py +0 -0
- {codex_agent_framework-0.1.46 → codex_agent_framework-0.1.48}/tests/test_agent_audio_hooks.py +0 -0
- {codex_agent_framework-0.1.46 → codex_agent_framework-0.1.48}/tests/test_agent_commands.py +0 -0
- {codex_agent_framework-0.1.46 → codex_agent_framework-0.1.48}/tests/test_agent_context.py +0 -0
- {codex_agent_framework-0.1.46 → codex_agent_framework-0.1.48}/tests/test_agent_desktop.py +0 -0
- {codex_agent_framework-0.1.46 → codex_agent_framework-0.1.48}/tests/test_agent_environment.py +0 -0
- {codex_agent_framework-0.1.46 → codex_agent_framework-0.1.48}/tests/test_agent_image_generation.py +0 -0
- {codex_agent_framework-0.1.46 → codex_agent_framework-0.1.48}/tests/test_agent_observe.py +0 -0
- {codex_agent_framework-0.1.46 → codex_agent_framework-0.1.48}/tests/test_agent_plugins.py +0 -0
- {codex_agent_framework-0.1.46 → codex_agent_framework-0.1.48}/tests/test_agent_providers_config.py +0 -0
- {codex_agent_framework-0.1.46 → codex_agent_framework-0.1.48}/tests/test_agent_realtime.py +0 -0
- {codex_agent_framework-0.1.46 → codex_agent_framework-0.1.48}/tests/test_agent_response.py +0 -0
- {codex_agent_framework-0.1.46 → codex_agent_framework-0.1.48}/tests/test_agent_runtime.py +0 -0
- {codex_agent_framework-0.1.46 → codex_agent_framework-0.1.48}/tests/test_agent_sessions.py +0 -0
- {codex_agent_framework-0.1.46 → codex_agent_framework-0.1.48}/tests/test_agent_subagents.py +0 -0
- {codex_agent_framework-0.1.46 → codex_agent_framework-0.1.48}/tests/test_agent_tools.py +0 -0
- {codex_agent_framework-0.1.46 → codex_agent_framework-0.1.48}/tests/test_agent_turns.py +0 -0
- {codex_agent_framework-0.1.46 → codex_agent_framework-0.1.48}/tests/test_browser.py +0 -0
- {codex_agent_framework-0.1.46 → codex_agent_framework-0.1.48}/tests/test_builtin_config.py +0 -0
- {codex_agent_framework-0.1.46 → codex_agent_framework-0.1.48}/tests/test_chat.py +0 -0
- {codex_agent_framework-0.1.46 → codex_agent_framework-0.1.48}/tests/test_cli.py +0 -0
- {codex_agent_framework-0.1.46 → codex_agent_framework-0.1.48}/tests/test_cli_headless.py +0 -0
- {codex_agent_framework-0.1.46 → codex_agent_framework-0.1.48}/tests/test_cli_root.py +0 -0
- {codex_agent_framework-0.1.46 → codex_agent_framework-0.1.48}/tests/test_client.py +0 -0
- {codex_agent_framework-0.1.46 → codex_agent_framework-0.1.48}/tests/test_events.py +0 -0
- {codex_agent_framework-0.1.46 → codex_agent_framework-0.1.48}/tests/test_get_text_browser.py +0 -0
- {codex_agent_framework-0.1.46 → codex_agent_framework-0.1.48}/tests/test_hooks.py +0 -0
- {codex_agent_framework-0.1.46 → codex_agent_framework-0.1.48}/tests/test_image_message.py +0 -0
- {codex_agent_framework-0.1.46 → codex_agent_framework-0.1.48}/tests/test_local_desktop.py +0 -0
- {codex_agent_framework-0.1.46 → codex_agent_framework-0.1.48}/tests/test_memory.py +0 -0
- {codex_agent_framework-0.1.46 → codex_agent_framework-0.1.48}/tests/test_messages.py +0 -0
- {codex_agent_framework-0.1.46 → codex_agent_framework-0.1.48}/tests/test_planner.py +0 -0
- {codex_agent_framework-0.1.46 → codex_agent_framework-0.1.48}/tests/test_scheduler.py +0 -0
- {codex_agent_framework-0.1.46 → codex_agent_framework-0.1.48}/tests/test_server.py +0 -0
- {codex_agent_framework-0.1.46 → codex_agent_framework-0.1.48}/tests/test_service.py +0 -0
- {codex_agent_framework-0.1.46 → codex_agent_framework-0.1.48}/tests/test_tui.py +0 -0
- {codex_agent_framework-0.1.46 → codex_agent_framework-0.1.48}/tests/test_utils.py +0 -0
- {codex_agent_framework-0.1.46 → codex_agent_framework-0.1.48}/tests/test_worker.py +0 -0
|
@@ -4,6 +4,23 @@ All notable changes to this project will be documented in this file.
|
|
|
4
4
|
|
|
5
5
|
This project loosely follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) and uses semantic versioning where practical.
|
|
6
6
|
|
|
7
|
+
## [0.1.48] - 2026-05-16
|
|
8
|
+
### Changed
|
|
9
|
+
- Make OpenAI API key validation configurable with `validate_openai_api_key` while preserving validation by default.
|
|
10
|
+
- Cache successful or failed OpenAI API key validation by key fingerprint to avoid repeated `models.list()` checks across clients using the same key.
|
|
11
|
+
- Update development docs for the current 556-test offline CI count.
|
|
12
|
+
|
|
13
|
+
### Tests
|
|
14
|
+
- Add coverage for cached OpenAI key validation and disabled validation, then validate with targeted AI/config/response coverage plus the 556-test offline CI suite.
|
|
15
|
+
|
|
16
|
+
## [0.1.47] - 2026-05-16
|
|
17
|
+
### Changed
|
|
18
|
+
- Document the current alpha public API contract for SDK and plugin users, including preferred surfaces such as `Agent`, `AgentTurn`, decorators, `Plugin`, hooks, events, and `agent.add_*` helpers.
|
|
19
|
+
- Clarify that manager internals are not the recommended extension surface for application or plugin code.
|
|
20
|
+
|
|
21
|
+
### Tests
|
|
22
|
+
- Validate the documentation update with the 554-test offline CI suite.
|
|
23
|
+
|
|
7
24
|
## [0.1.46] - 2026-05-16
|
|
8
25
|
### Changed
|
|
9
26
|
- Clarify README product positioning as an open-source, hackable, local-first Codex-style harness with explicit control over sessions, tools, plugins, runtime state, and UI surfaces.
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import hashlib
|
|
1
2
|
import queue
|
|
2
3
|
import threading
|
|
3
4
|
|
|
@@ -61,6 +62,9 @@ MAX_EMBEDDING_INPUT_TOKENS = 7500
|
|
|
61
62
|
class AIClient:
|
|
62
63
|
"""Client for Codex backend LLM/embedding/STT calls plus OpenAI-key TTS/token helpers."""
|
|
63
64
|
|
|
65
|
+
_api_key_validation_cache = {}
|
|
66
|
+
_api_key_validation_lock = threading.Lock()
|
|
67
|
+
|
|
64
68
|
def __init__(self, agent):
|
|
65
69
|
"""Initialize AI clients from agent config.
|
|
66
70
|
|
|
@@ -74,15 +78,15 @@ class AIClient:
|
|
|
74
78
|
@property
|
|
75
79
|
def client(self):
|
|
76
80
|
if self._client is None:
|
|
77
|
-
api_key=self.
|
|
81
|
+
api_key = self.openai_api_key()
|
|
78
82
|
try:
|
|
79
83
|
self._client = OpenAI(api_key=api_key, timeout=180, max_retries=3)
|
|
80
|
-
if not self.api_key_is_valid():
|
|
81
|
-
self._client=None
|
|
82
|
-
raise
|
|
84
|
+
if self.agent.config.get("validate_openai_api_key", True) and not self.api_key_is_valid(api_key):
|
|
85
|
+
self._client = None
|
|
86
|
+
raise self.authentication_error()
|
|
83
87
|
except OpenAIError:
|
|
84
|
-
self._client=None
|
|
85
|
-
raise
|
|
88
|
+
self._client = None
|
|
89
|
+
raise self.authentication_error()
|
|
86
90
|
return self._client
|
|
87
91
|
|
|
88
92
|
@property
|
|
@@ -97,19 +101,38 @@ class AIClient:
|
|
|
97
101
|
if self._codex_client is not None and hasattr(self._codex_client, "abort"):
|
|
98
102
|
self._codex_client.abort()
|
|
99
103
|
|
|
100
|
-
def
|
|
101
|
-
"""
|
|
102
|
-
|
|
104
|
+
def openai_api_key(self):
|
|
105
|
+
return self.agent.config.get("openai_api_key") or os.getenv("OPENAI_API_KEY")
|
|
106
|
+
|
|
107
|
+
def authentication_error(self):
|
|
108
|
+
return APIAuthenticationError(
|
|
109
|
+
"Missing or invalid OpenAI API key. You can pass it when creating the agent with "
|
|
110
|
+
"`agent=Agent(openai_api_key='your_api_key')` or via `agent.config.openai_api_key` "
|
|
111
|
+
"or set the OPENAI_API_KEY environment variable. You can get an API key at "
|
|
112
|
+
"https://platform.openai.com/account/api-keys."
|
|
113
|
+
)
|
|
114
|
+
|
|
115
|
+
def api_key_cache_key(self, api_key):
|
|
116
|
+
return hashlib.sha256((api_key or "").encode()).hexdigest()
|
|
117
|
+
|
|
118
|
+
def api_key_is_valid(self, api_key=None):
|
|
119
|
+
"""Verify the OpenAI API key once per key value."""
|
|
120
|
+
api_key = self.openai_api_key() if api_key is None else api_key
|
|
121
|
+
cache_key = self.api_key_cache_key(api_key)
|
|
122
|
+
with self._api_key_validation_lock:
|
|
123
|
+
if cache_key in self._api_key_validation_cache:
|
|
124
|
+
return self._api_key_validation_cache[cache_key]
|
|
103
125
|
|
|
104
|
-
Returns:
|
|
105
|
-
bool: True if API key is valid, False otherwise
|
|
106
|
-
"""
|
|
107
126
|
try:
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
127
|
+
validation_client = self._client or OpenAI(api_key=api_key, timeout=180, max_retries=3)
|
|
128
|
+
validation_client.models.list()
|
|
129
|
+
valid = True
|
|
111
130
|
except Exception:
|
|
112
|
-
|
|
131
|
+
valid = False
|
|
132
|
+
|
|
133
|
+
with self._api_key_validation_lock:
|
|
134
|
+
self._api_key_validation_cache[cache_key] = valid
|
|
135
|
+
return valid
|
|
113
136
|
|
|
114
137
|
def text_to_audio(self, model=None, voice=None, input='', voice_instructions='', **kwargs):
|
|
115
138
|
"""
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "0.1.48"
|
|
@@ -84,6 +84,49 @@ class FakeAgent:
|
|
|
84
84
|
self.mainloop_manager = FakeMainLoopManager()
|
|
85
85
|
|
|
86
86
|
|
|
87
|
+
class FakeModels:
|
|
88
|
+
def __init__(self):
|
|
89
|
+
self.calls = 0
|
|
90
|
+
|
|
91
|
+
def list(self):
|
|
92
|
+
self.calls += 1
|
|
93
|
+
return []
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
class FakeOpenAIValidationClient:
|
|
97
|
+
instances = []
|
|
98
|
+
|
|
99
|
+
def __init__(self, **kwargs):
|
|
100
|
+
self.kwargs = kwargs
|
|
101
|
+
self.models = FakeModels()
|
|
102
|
+
self.__class__.instances.append(self)
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
def test_openai_api_key_validation_is_cached_by_key(monkeypatch):
|
|
106
|
+
AIClient._api_key_validation_cache.clear()
|
|
107
|
+
FakeOpenAIValidationClient.instances = []
|
|
108
|
+
monkeypatch.setattr("codex_agent.ai.OpenAI", FakeOpenAIValidationClient)
|
|
109
|
+
|
|
110
|
+
first = AIClient(FakeAgent(openai_api_key="sk-test"))
|
|
111
|
+
second = AIClient(FakeAgent(openai_api_key="sk-test"))
|
|
112
|
+
|
|
113
|
+
assert first.client is FakeOpenAIValidationClient.instances[0]
|
|
114
|
+
assert second.client is FakeOpenAIValidationClient.instances[1]
|
|
115
|
+
assert FakeOpenAIValidationClient.instances[0].models.calls == 1
|
|
116
|
+
assert FakeOpenAIValidationClient.instances[1].models.calls == 0
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
def test_openai_api_key_validation_can_be_disabled(monkeypatch):
|
|
120
|
+
AIClient._api_key_validation_cache.clear()
|
|
121
|
+
FakeOpenAIValidationClient.instances = []
|
|
122
|
+
monkeypatch.setattr("codex_agent.ai.OpenAI", FakeOpenAIValidationClient)
|
|
123
|
+
|
|
124
|
+
ai = AIClient(FakeAgent(openai_api_key="sk-test", validate_openai_api_key=False))
|
|
125
|
+
|
|
126
|
+
assert ai.client is FakeOpenAIValidationClient.instances[0]
|
|
127
|
+
assert FakeOpenAIValidationClient.instances[0].models.calls == 0
|
|
128
|
+
|
|
129
|
+
|
|
87
130
|
def test_embed_content_truncates_input_to_embedding_token_budget():
|
|
88
131
|
ai = AIClient(agent=None)
|
|
89
132
|
ai._codex_client = FakeCodexClient()
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
__version__ = "0.1.46"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{codex_agent_framework-0.1.46 → codex_agent_framework-0.1.48}/codex_agent/builtin_commands.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{codex_agent_framework-0.1.46 → codex_agent_framework-0.1.48}/codex_agent/get_text/__init__.py
RENAMED
|
File without changes
|
{codex_agent_framework-0.1.46 → codex_agent_framework-0.1.48}/codex_agent/get_text/default_gitignore
RENAMED
|
File without changes
|
{codex_agent_framework-0.1.46 → codex_agent_framework-0.1.48}/codex_agent/get_text/get_text.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{codex_agent_framework-0.1.46 → codex_agent_framework-0.1.48}/codex_agent/prompts/system_prompt.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{codex_agent_framework-0.1.46 → codex_agent_framework-0.1.48}/codex_agent/server/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{codex_agent_framework-0.1.46 → codex_agent_framework-0.1.48}/tests/test_agent_audio_hooks.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{codex_agent_framework-0.1.46 → codex_agent_framework-0.1.48}/tests/test_agent_environment.py
RENAMED
|
File without changes
|
{codex_agent_framework-0.1.46 → codex_agent_framework-0.1.48}/tests/test_agent_image_generation.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{codex_agent_framework-0.1.46 → codex_agent_framework-0.1.48}/tests/test_agent_providers_config.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{codex_agent_framework-0.1.46 → codex_agent_framework-0.1.48}/tests/test_get_text_browser.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|