python-codex 0.1.2__py3-none-any.whl → 0.1.4__py3-none-any.whl

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 (60) hide show
  1. pycodex/__init__.py +5 -1
  2. pycodex/agent.py +89 -51
  3. pycodex/cli.py +152 -45
  4. pycodex/collaboration.py +6 -7
  5. pycodex/compat.py +99 -0
  6. pycodex/context.py +110 -87
  7. pycodex/doctor.py +40 -40
  8. pycodex/model.py +429 -90
  9. pycodex/portable.py +33 -33
  10. pycodex/portable_server.py +22 -21
  11. pycodex/prompts/models.json +30 -0
  12. pycodex/protocol.py +84 -86
  13. pycodex/runtime.py +36 -35
  14. pycodex/runtime_services.py +69 -69
  15. pycodex/tools/agent_tool_schemas.py +0 -2
  16. pycodex/tools/apply_patch_tool.py +45 -46
  17. pycodex/tools/base_tool.py +35 -36
  18. pycodex/tools/close_agent_tool.py +2 -4
  19. pycodex/tools/code_mode_manager.py +61 -61
  20. pycodex/tools/exec_command_tool.py +5 -6
  21. pycodex/tools/exec_runtime.js +3 -3
  22. pycodex/tools/exec_tool.py +2 -4
  23. pycodex/tools/grep_files_tool.py +10 -11
  24. pycodex/tools/list_dir_tool.py +8 -9
  25. pycodex/tools/read_file_tool.py +13 -14
  26. pycodex/tools/request_permissions_tool.py +2 -4
  27. pycodex/tools/request_user_input_tool.py +13 -14
  28. pycodex/tools/resume_agent_tool.py +2 -4
  29. pycodex/tools/send_input_tool.py +8 -9
  30. pycodex/tools/shell_command_tool.py +5 -6
  31. pycodex/tools/shell_tool.py +5 -6
  32. pycodex/tools/spawn_agent_tool.py +4 -5
  33. pycodex/tools/unified_exec_manager.py +62 -61
  34. pycodex/tools/update_plan_tool.py +4 -5
  35. pycodex/tools/view_image_tool.py +4 -5
  36. pycodex/tools/wait_agent_tool.py +2 -4
  37. pycodex/tools/wait_tool.py +4 -5
  38. pycodex/tools/web_search_tool.py +1 -3
  39. pycodex/tools/write_stdin_tool.py +4 -5
  40. pycodex/utils/__init__.py +4 -0
  41. pycodex/utils/compactor.py +189 -0
  42. pycodex/utils/dotenv.py +6 -6
  43. pycodex/utils/get_env.py +37 -33
  44. pycodex/utils/random_ids.py +1 -2
  45. pycodex/utils/session_persist.py +483 -0
  46. pycodex/utils/visualize.py +197 -83
  47. {python_codex-0.1.2.dist-info → python_codex-0.1.4.dist-info}/METADATA +32 -11
  48. python_codex-0.1.4.dist-info/RECORD +76 -0
  49. {python_codex-0.1.2.dist-info → python_codex-0.1.4.dist-info}/WHEEL +1 -1
  50. responses_server/app.py +32 -20
  51. responses_server/config.py +17 -17
  52. responses_server/payload_processors.py +26 -17
  53. responses_server/server.py +11 -11
  54. responses_server/session_store.py +10 -10
  55. responses_server/stream_router.py +83 -64
  56. responses_server/tools/custom_adapter.py +12 -12
  57. responses_server/tools/web_search.py +33 -33
  58. python_codex-0.1.2.dist-info/RECORD +0 -73
  59. {python_codex-0.1.2.dist-info → python_codex-0.1.4.dist-info}/entry_points.txt +0 -0
  60. {python_codex-0.1.2.dist-info → python_codex-0.1.4.dist-info}/licenses/LICENSE +0 -0
pycodex/doctor.py CHANGED
@@ -1,4 +1,3 @@
1
- from __future__ import annotations
2
1
 
3
2
  import asyncio
4
3
  import json
@@ -14,31 +13,32 @@ import requests
14
13
  from .model import ResponsesModelClient, ResponsesProviderConfig
15
14
  from .protocol import AssistantMessage, Prompt, UserMessage
16
15
  from .utils.dotenv import DOTENV_FILENAME, load_codex_dotenv
16
+ import typing
17
17
 
18
18
 
19
- @dataclass(slots=True)
19
+ @dataclass
20
20
  class DoctorCheck:
21
- name: str
22
- ok: bool
23
- detail: str
21
+ name: 'str'
22
+ ok: 'bool'
23
+ detail: 'str'
24
24
 
25
25
 
26
- @dataclass(slots=True)
26
+ @dataclass
27
27
  class DoctorReport:
28
- ok: bool
29
- config_path: str
30
- dotenv_path: str
31
- profile: str | None
32
- provider_name: str | None = None
33
- model: str | None = None
34
- base_url: str | None = None
35
- responses_url: str | None = None
36
- api_key_env: str | None = None
37
- api_key_loaded: bool = False
38
- checks: list[DoctorCheck] = field(default_factory=list)
39
- live_output_text: str | None = None
40
-
41
- def to_dict(self) -> dict[str, object]:
28
+ ok: 'bool'
29
+ config_path: 'str'
30
+ dotenv_path: 'str'
31
+ profile: 'typing.Union[str, None]'
32
+ provider_name: 'typing.Union[str, None]' = None
33
+ model: 'typing.Union[str, None]' = None
34
+ base_url: 'typing.Union[str, None]' = None
35
+ responses_url: 'typing.Union[str, None]' = None
36
+ api_key_env: 'typing.Union[str, None]' = None
37
+ api_key_loaded: 'bool' = False
38
+ checks: 'typing.List[DoctorCheck]' = field(default_factory=list)
39
+ live_output_text: 'typing.Union[str, None]' = None
40
+
41
+ def to_dict(self) -> 'typing.Dict[str, object]':
42
42
  return asdict(self)
43
43
 
44
44
 
@@ -79,11 +79,11 @@ def build_doctor_parser():
79
79
 
80
80
 
81
81
  async def collect_doctor_report(
82
- config_path: str | Path,
83
- profile: str | None = None,
84
- timeout_seconds: float = 120.0,
85
- skip_live: bool = False,
86
- ) -> DoctorReport:
82
+ config_path: 'typing.Union[str, Path]',
83
+ profile: 'typing.Union[str, None]' = None,
84
+ timeout_seconds: 'float' = 120.0,
85
+ skip_live: 'bool' = False,
86
+ ) -> 'DoctorReport':
87
87
  config_file = Path(config_path).expanduser().resolve()
88
88
  dotenv_file = config_file.parent / DOTENV_FILENAME
89
89
  report = DoctorReport(
@@ -227,7 +227,7 @@ async def collect_doctor_report(
227
227
  return _finalize_report(report)
228
228
 
229
229
 
230
- async def run_doctor_cli(args) -> int:
230
+ async def run_doctor_cli(args) -> 'int':
231
231
  report = await collect_doctor_report(
232
232
  args.config,
233
233
  args.profile,
@@ -243,7 +243,7 @@ async def run_doctor_cli(args) -> int:
243
243
  return 0 if report.ok else 1
244
244
 
245
245
 
246
- def format_doctor_report(report: DoctorReport) -> str:
246
+ def format_doctor_report(report: 'DoctorReport') -> 'str':
247
247
  lines = [
248
248
  f"config: {report.config_path}",
249
249
  f"dotenv: {report.dotenv_path}",
@@ -267,7 +267,7 @@ def format_doctor_report(report: DoctorReport) -> str:
267
267
  return "\n".join(lines)
268
268
 
269
269
 
270
- def _loaded_api_key(provider_config: ResponsesProviderConfig) -> str:
270
+ def _loaded_api_key(provider_config: 'ResponsesProviderConfig') -> 'str':
271
271
  try:
272
272
  return provider_config.api_key()
273
273
  except Exception:
@@ -275,11 +275,11 @@ def _loaded_api_key(provider_config: ResponsesProviderConfig) -> str:
275
275
 
276
276
 
277
277
  def _probe_transport(
278
- scheme: str,
279
- host: str,
280
- port: int,
281
- timeout_seconds: float,
282
- ) -> tuple[bool, str]:
278
+ scheme: 'str',
279
+ host: 'str',
280
+ port: 'int',
281
+ timeout_seconds: 'float',
282
+ ) -> 'typing.Tuple[bool, str]':
283
283
  started = time.perf_counter()
284
284
  try:
285
285
  with socket.create_connection((host, port), timeout=timeout_seconds) as sock:
@@ -298,7 +298,7 @@ def _probe_transport(
298
298
  return True, f"{label} {host}:{port} connected in {elapsed:.2f}s"
299
299
 
300
300
 
301
- def _proxy_detail(proxies: dict[str, str]) -> str:
301
+ def _proxy_detail(proxies: 'typing.Dict[str, str]') -> 'str':
302
302
  if not proxies:
303
303
  return "not configured"
304
304
  return ", ".join(
@@ -306,7 +306,7 @@ def _proxy_detail(proxies: dict[str, str]) -> str:
306
306
  )
307
307
 
308
308
 
309
- def _redact_proxy_url(value: str) -> str:
309
+ def _redact_proxy_url(value: 'str') -> 'str':
310
310
  parsed = urllib.parse.urlsplit(value)
311
311
  if not parsed.scheme or not parsed.netloc:
312
312
  return value
@@ -319,10 +319,10 @@ def _redact_proxy_url(value: str) -> str:
319
319
 
320
320
 
321
321
  async def _run_live_check(
322
- config_path: Path,
323
- profile: str | None,
324
- timeout_seconds: float,
325
- ) -> tuple[bool, str, str | None]:
322
+ config_path: 'Path',
323
+ profile: 'typing.Union[str, None]',
324
+ timeout_seconds: 'float',
325
+ ) -> 'typing.Tuple[bool, str, typing.Union[str, None]]':
326
326
  client = ResponsesModelClient.from_codex_config(
327
327
  config_path,
328
328
  profile,
@@ -355,6 +355,6 @@ async def _run_live_check(
355
355
  return True, f"completed in {elapsed:.2f}s", output_text
356
356
 
357
357
 
358
- def _finalize_report(report: DoctorReport) -> DoctorReport:
358
+ def _finalize_report(report: 'DoctorReport') -> 'DoctorReport':
359
359
  report.ok = all(check.ok for check in report.checks)
360
360
  return report