codex-agent-framework 0.1.11__tar.gz → 0.1.12__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.
Files changed (67) hide show
  1. {codex_agent_framework-0.1.11 → codex_agent_framework-0.1.12}/CHANGELOG.md +14 -0
  2. {codex_agent_framework-0.1.11/codex_agent_framework.egg-info → codex_agent_framework-0.1.12}/PKG-INFO +4 -4
  3. {codex_agent_framework-0.1.11 → codex_agent_framework-0.1.12}/README.md +2 -1
  4. {codex_agent_framework-0.1.11 → codex_agent_framework-0.1.12}/codex_agent/agent.py +53 -11
  5. codex_agent_framework-0.1.12/codex_agent/browser.py +651 -0
  6. codex_agent_framework-0.1.12/codex_agent/builtin_providers.py +74 -0
  7. {codex_agent_framework-0.1.11 → codex_agent_framework-0.1.12}/codex_agent/builtin_tools.py +197 -1
  8. {codex_agent_framework-0.1.11 → codex_agent_framework-0.1.12}/codex_agent/get_text/get_text.py +22 -44
  9. {codex_agent_framework-0.1.11 → codex_agent_framework-0.1.12}/codex_agent/prompts/system_prompt.txt +3 -1
  10. {codex_agent_framework-0.1.11 → codex_agent_framework-0.1.12}/codex_agent/utils.py +1 -0
  11. {codex_agent_framework-0.1.11 → codex_agent_framework-0.1.12/codex_agent_framework.egg-info}/PKG-INFO +4 -4
  12. {codex_agent_framework-0.1.11 → codex_agent_framework-0.1.12}/codex_agent_framework.egg-info/SOURCES.txt +3 -1
  13. {codex_agent_framework-0.1.11 → codex_agent_framework-0.1.12}/codex_agent_framework.egg-info/requires.txt +1 -2
  14. {codex_agent_framework-0.1.11 → codex_agent_framework-0.1.12}/pyproject.toml +2 -3
  15. {codex_agent_framework-0.1.11 → codex_agent_framework-0.1.12}/tests/test_agent.py +52 -2
  16. codex_agent_framework-0.1.12/tests/test_browser.py +235 -0
  17. codex_agent_framework-0.1.12/tests/test_get_text_browser.py +55 -0
  18. codex_agent_framework-0.1.11/codex_agent/builtin_providers.py +0 -42
  19. codex_agent_framework-0.1.11/codex_agent/get_webdriver.py +0 -44
  20. {codex_agent_framework-0.1.11 → codex_agent_framework-0.1.12}/LICENSE +0 -0
  21. {codex_agent_framework-0.1.11 → codex_agent_framework-0.1.12}/MANIFEST.in +0 -0
  22. {codex_agent_framework-0.1.11 → codex_agent_framework-0.1.12}/codex_agent/__init__.py +0 -0
  23. {codex_agent_framework-0.1.11 → codex_agent_framework-0.1.12}/codex_agent/__main__.py +0 -0
  24. {codex_agent_framework-0.1.11 → codex_agent_framework-0.1.12}/codex_agent/agent_runtime.py +0 -0
  25. {codex_agent_framework-0.1.11 → codex_agent_framework-0.1.12}/codex_agent/ai.py +0 -0
  26. {codex_agent_framework-0.1.11 → codex_agent_framework-0.1.12}/codex_agent/builtin_commands.py +0 -0
  27. {codex_agent_framework-0.1.11 → codex_agent_framework-0.1.12}/codex_agent/chat.py +0 -0
  28. {codex_agent_framework-0.1.11 → codex_agent_framework-0.1.12}/codex_agent/client.py +0 -0
  29. {codex_agent_framework-0.1.11 → codex_agent_framework-0.1.12}/codex_agent/command.py +0 -0
  30. {codex_agent_framework-0.1.11 → codex_agent_framework-0.1.12}/codex_agent/event.py +0 -0
  31. {codex_agent_framework-0.1.11 → codex_agent_framework-0.1.12}/codex_agent/get_text/__init__.py +0 -0
  32. {codex_agent_framework-0.1.11 → codex_agent_framework-0.1.12}/codex_agent/get_text/default_gitignore +0 -0
  33. {codex_agent_framework-0.1.11 → codex_agent_framework-0.1.12}/codex_agent/get_text/simpler_get_text.py +0 -0
  34. {codex_agent_framework-0.1.11 → codex_agent_framework-0.1.12}/codex_agent/image.py +0 -0
  35. {codex_agent_framework-0.1.11 → codex_agent_framework-0.1.12}/codex_agent/latex.py +0 -0
  36. {codex_agent_framework-0.1.11 → codex_agent_framework-0.1.12}/codex_agent/memory.py +0 -0
  37. {codex_agent_framework-0.1.11 → codex_agent_framework-0.1.12}/codex_agent/message.py +0 -0
  38. {codex_agent_framework-0.1.11 → codex_agent_framework-0.1.12}/codex_agent/prompts/image_generation_system_prompt.txt +0 -0
  39. {codex_agent_framework-0.1.11 → codex_agent_framework-0.1.12}/codex_agent/provider.py +0 -0
  40. {codex_agent_framework-0.1.11 → codex_agent_framework-0.1.12}/codex_agent/scheduler.py +0 -0
  41. {codex_agent_framework-0.1.11 → codex_agent_framework-0.1.12}/codex_agent/server.py +0 -0
  42. {codex_agent_framework-0.1.11 → codex_agent_framework-0.1.12}/codex_agent/service.py +0 -0
  43. {codex_agent_framework-0.1.11 → codex_agent_framework-0.1.12}/codex_agent/stream_utils.py +0 -0
  44. {codex_agent_framework-0.1.11 → codex_agent_framework-0.1.12}/codex_agent/tool.py +0 -0
  45. {codex_agent_framework-0.1.11 → codex_agent_framework-0.1.12}/codex_agent/tray.py +0 -0
  46. {codex_agent_framework-0.1.11 → codex_agent_framework-0.1.12}/codex_agent/tui.py +0 -0
  47. {codex_agent_framework-0.1.11 → codex_agent_framework-0.1.12}/codex_agent/voice.py +0 -0
  48. {codex_agent_framework-0.1.11 → codex_agent_framework-0.1.12}/codex_agent/worker.py +0 -0
  49. {codex_agent_framework-0.1.11 → codex_agent_framework-0.1.12}/codex_agent_framework.egg-info/dependency_links.txt +0 -0
  50. {codex_agent_framework-0.1.11 → codex_agent_framework-0.1.12}/codex_agent_framework.egg-info/entry_points.txt +0 -0
  51. {codex_agent_framework-0.1.11 → codex_agent_framework-0.1.12}/codex_agent_framework.egg-info/top_level.txt +0 -0
  52. {codex_agent_framework-0.1.11 → codex_agent_framework-0.1.12}/setup.cfg +0 -0
  53. {codex_agent_framework-0.1.11 → codex_agent_framework-0.1.12}/tests/test_ai.py +0 -0
  54. {codex_agent_framework-0.1.11 → codex_agent_framework-0.1.12}/tests/test_chat.py +0 -0
  55. {codex_agent_framework-0.1.11 → codex_agent_framework-0.1.12}/tests/test_cli.py +0 -0
  56. {codex_agent_framework-0.1.11 → codex_agent_framework-0.1.12}/tests/test_client.py +0 -0
  57. {codex_agent_framework-0.1.11 → codex_agent_framework-0.1.12}/tests/test_events.py +0 -0
  58. {codex_agent_framework-0.1.11 → codex_agent_framework-0.1.12}/tests/test_image_message.py +0 -0
  59. {codex_agent_framework-0.1.11 → codex_agent_framework-0.1.12}/tests/test_memory.py +0 -0
  60. {codex_agent_framework-0.1.11 → codex_agent_framework-0.1.12}/tests/test_messages.py +0 -0
  61. {codex_agent_framework-0.1.11 → codex_agent_framework-0.1.12}/tests/test_scheduler.py +0 -0
  62. {codex_agent_framework-0.1.11 → codex_agent_framework-0.1.12}/tests/test_server.py +0 -0
  63. {codex_agent_framework-0.1.11 → codex_agent_framework-0.1.12}/tests/test_service.py +0 -0
  64. {codex_agent_framework-0.1.11 → codex_agent_framework-0.1.12}/tests/test_tray.py +0 -0
  65. {codex_agent_framework-0.1.11 → codex_agent_framework-0.1.12}/tests/test_tui.py +0 -0
  66. {codex_agent_framework-0.1.11 → codex_agent_framework-0.1.12}/tests/test_utils.py +0 -0
  67. {codex_agent_framework-0.1.11 → codex_agent_framework-0.1.12}/tests/test_worker.py +0 -0
@@ -3,6 +3,20 @@
3
3
  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
+
7
+ ## [0.1.12] - 2026-05-05
8
+ ### Added
9
+ - Add a persistent Playwright/Chromium browser controller with tools to open/close the browser, select tabs, navigate, click, fill, select options, press keys, inspect action snapshots, and capture screenshots.
10
+ - Add `browser_goto(url)` to navigate the active tab without opening or switching tabs.
11
+ - Add screenshot-backed visual fallback for pages where DOM snapshots are insufficient, including PDF viewers and image-heavy pages.
12
+
13
+ ### Changed
14
+ - Replace the Selenium/Gecko rendered extraction path with Playwright-managed Chromium.
15
+ - Update web extraction dependencies and documentation to install Chromium with Playwright.
16
+
17
+ ### Tests
18
+ - Add browser controller and rendered extraction regression coverage.
19
+
6
20
  ## [0.1.11] - 2026-05-05
7
21
  ### Added
8
22
  - Add a separate `view` tool for folders, URLs, rich document extraction, and Python object inspection.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: codex-agent-framework
3
- Version: 0.1.11
3
+ Version: 0.1.12
4
4
  Summary: A lightweight event-driven Codex agent runtime.
5
5
  Author: Baptiste
6
6
  License-Expression: MIT
@@ -20,7 +20,6 @@ Requires-Dist: beautifulsoup4
20
20
  Requires-Dist: codex-backend-sdk
21
21
  Requires-Dist: fastapi
22
22
  Requires-Dist: filetype
23
- Requires-Dist: get-gecko-driver
24
23
  Requires-Dist: modict
25
24
  Requires-Dist: numpy
26
25
  Requires-Dist: odfpy
@@ -28,6 +27,7 @@ Requires-Dist: openai
28
27
  Requires-Dist: openpyxl
29
28
  Requires-Dist: pathspec
30
29
  Requires-Dist: pillow
30
+ Requires-Dist: playwright
31
31
  Requires-Dist: pydub
32
32
  Requires-Dist: pypdf
33
33
  Requires-Dist: pynteract
@@ -36,7 +36,6 @@ Requires-Dist: PyYAML
36
36
  Requires-Dist: regex
37
37
  Requires-Dist: requests
38
38
  Requires-Dist: rich
39
- Requires-Dist: selenium
40
39
  Requires-Dist: textual
41
40
  Requires-Dist: tiktoken
42
41
  Requires-Dist: trafilatura
@@ -73,7 +72,7 @@ It provides a reusable `Agent` abstraction with persistent sessions, local tools
73
72
  - Python 3.10 or newer.
74
73
  - A working model backend configuration compatible with `codex-backend-sdk` / OpenAI usage.
75
74
  - GTK 3 plus Ayatana AppIndicator or AppIndicator bindings are needed for the tray controller on Linux.
76
- - Firefox / GeckoDriver may be needed for Selenium-backed web extraction paths.
75
+ - Playwright's managed Chromium browser is used for rendered web extraction when static fetching is insufficient. Install it with `python -m playwright install chromium` if needed.
77
76
 
78
77
  ## Installation
79
78
 
@@ -400,6 +399,7 @@ python -m build
400
399
  The distribution includes prompt text files and `codex_agent/get_text/default_gitignore` through package data and `MANIFEST.in`.
401
400
 
402
401
  ## Recent changes
402
+ - `0.1.12`: add a persistent Playwright/Chromium browser controller with tab navigation, DOM/action snapshots, screenshots, form/click/key tools, and `browser_goto(url)` for active-tab navigation.
403
403
  - `0.1.11`: split strict line-numbered UTF-8 `read` from unnumbered extracted `view`, preserve blank lines in read snippets, and show persistent+temporary message counts in the TUI status bar.
404
404
  - `0.1.10`: persist only backend compaction summaries, drop bulky compacted conversation payloads, and refresh context status after compaction.
405
405
  - `0.1.9`: maintenance packaging release after validating the local execution environment and deploy workflow.
@@ -25,7 +25,7 @@ It provides a reusable `Agent` abstraction with persistent sessions, local tools
25
25
  - Python 3.10 or newer.
26
26
  - A working model backend configuration compatible with `codex-backend-sdk` / OpenAI usage.
27
27
  - GTK 3 plus Ayatana AppIndicator or AppIndicator bindings are needed for the tray controller on Linux.
28
- - Firefox / GeckoDriver may be needed for Selenium-backed web extraction paths.
28
+ - Playwright's managed Chromium browser is used for rendered web extraction when static fetching is insufficient. Install it with `python -m playwright install chromium` if needed.
29
29
 
30
30
  ## Installation
31
31
 
@@ -352,6 +352,7 @@ python -m build
352
352
  The distribution includes prompt text files and `codex_agent/get_text/default_gitignore` through package data and `MANIFEST.in`.
353
353
 
354
354
  ## Recent changes
355
+ - `0.1.12`: add a persistent Playwright/Chromium browser controller with tab navigation, DOM/action snapshots, screenshots, form/click/key tools, and `browser_goto(url)` for active-tab navigation.
355
356
  - `0.1.11`: split strict line-numbered UTF-8 `read` from unnumbered extracted `view`, preserve blank lines in read snippets, and show persistent+temporary message counts in the TUI status bar.
356
357
  - `0.1.10`: persist only backend compaction summaries, drop bulky compacted conversation payloads, and refresh context status after compaction.
357
358
  - `0.1.9`: maintenance packaging release after validating the local execution environment and deploy workflow.
@@ -952,9 +952,10 @@ class Agent:
952
952
  def add_provider(self, func=None, name=None):
953
953
  """Register an ephemeral context provider.
954
954
 
955
- Providers are called each time context is built. They must return a
956
- string or None. Returned strings are wrapped in ProviderMessage and are
957
- not persisted to the session.
955
+ Providers are called each time context is built. They may return None,
956
+ a string, a Message instance, or a list/tuple mixing strings and Message
957
+ instances. Strings are wrapped in ProviderMessage; Message instances are
958
+ passed through as already formatted ephemeral context.
958
959
  """
959
960
  if func is None:
960
961
  def decorator(f):
@@ -1090,11 +1091,52 @@ class Agent:
1090
1091
  return [msg for msg in self.session.messages if filter(msg)]
1091
1092
  return sort(self.session.messages)
1092
1093
 
1094
+ def provider_context_wrapper(self, provider_name, content):
1095
+ return f'<context_provider name="{provider_name}">\n{content}\n</context_provider>'
1096
+
1097
+ def provider_message_from_output(self, provider_name, output):
1098
+ if isinstance(output, str):
1099
+ return ProviderMessage(name=provider_name, content=output)
1100
+ if not isinstance(output, Message):
1101
+ raise TypeError(
1102
+ f"Provider {provider_name!r} items must be str or Message, got {type(output).__name__}."
1103
+ )
1104
+
1105
+ message = output.copy()
1106
+ if isinstance(message, ProviderMessage):
1107
+ if not message.get("name"):
1108
+ message.name = provider_name
1109
+ return message
1110
+
1111
+ if isinstance(message, ImageMessage):
1112
+ description = message.get("description") or "Image provided by an ephemeral context provider."
1113
+ message.description = self.provider_context_wrapper(provider_name, description)
1114
+ return message
1115
+
1116
+ content = message.get("content")
1117
+ if isinstance(content, str):
1118
+ message.content = self.provider_context_wrapper(provider_name, content)
1119
+ elif isinstance(content, list):
1120
+ wrapped_parts = []
1121
+ for part in content:
1122
+ if isinstance(part, str):
1123
+ wrapped_parts.append(self.provider_context_wrapper(provider_name, part))
1124
+ elif isinstance(part, dict) and part.get("type") == "text":
1125
+ part = dict(part)
1126
+ part["text"] = self.provider_context_wrapper(provider_name, part.get("text", ""))
1127
+ wrapped_parts.append(part)
1128
+ else:
1129
+ wrapped_parts.append(part)
1130
+ message.content = wrapped_parts
1131
+ return message
1132
+
1093
1133
  def get_providers_messages(self):
1094
- """Retrieves messages from all registered providers.
1134
+ """Retrieves ephemeral messages from all registered providers.
1095
1135
 
1096
- Returns:
1097
- List of ProviderMessage objects generated by providers.
1136
+ Providers may return None, a string, a Message, or a list/tuple of
1137
+ strings and Messages. Each output item becomes its own message; strings
1138
+ are wrapped in ProviderMessage, while existing Messages keep their type
1139
+ and only their textual content is marked as provider context.
1098
1140
  """
1099
1141
  provider_msgs=[]
1100
1142
  for provider_name, provider in self.providers.items():
@@ -1105,11 +1147,11 @@ class Agent:
1105
1147
  reset_current_agent(agent_context)
1106
1148
  if provider_output is None:
1107
1149
  continue
1108
- if not isinstance(provider_output, str):
1109
- raise TypeError(
1110
- f"Provider {provider_name!r} must return str or None, got {type(provider_output).__name__}."
1111
- )
1112
- provider_msgs.append(ProviderMessage(name=provider_name, content=provider_output))
1150
+ outputs = provider_output if isinstance(provider_output, (list, tuple)) else [provider_output]
1151
+ for output in outputs:
1152
+ if output is None:
1153
+ continue
1154
+ provider_msgs.append(self.provider_message_from_output(provider_name, output))
1113
1155
  return provider_msgs
1114
1156
 
1115
1157
  def context_status(self):