python-codex 0.2.7__py3-none-any.whl → 0.3.1__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 (85) hide show
  1. pycodex/__init__.py +14 -14
  2. pycodex/agent.py +465 -499
  3. pycodex/bootstrap.py +417 -0
  4. pycodex/cli.py +236 -510
  5. pycodex/compat.py +19 -5
  6. pycodex/context.py +222 -212
  7. pycodex/doctor.py +52 -48
  8. pycodex/events.py +857 -0
  9. pycodex/feishu_card.py +217 -163
  10. pycodex/feishu_link.py +43 -83
  11. pycodex/model.py +324 -253
  12. pycodex/model_metadata.py +19 -7
  13. pycodex/portable.py +76 -45
  14. pycodex/portable_server.py +32 -24
  15. pycodex/prompts/models.json +321 -883
  16. pycodex/protocol.py +177 -137
  17. pycodex/runtime.py +579 -176
  18. pycodex/runtime_services.py +204 -157
  19. pycodex/tools/__init__.py +1 -1
  20. pycodex/tools/apply_patch_tool.py +69 -48
  21. pycodex/tools/base_tool.py +89 -42
  22. pycodex/tools/clock_tool.py +58 -25
  23. pycodex/tools/close_agent_tool.py +2 -2
  24. pycodex/tools/code_mode_manager.py +77 -64
  25. pycodex/tools/exec_command_tool.py +26 -11
  26. pycodex/tools/exec_tool.py +4 -4
  27. pycodex/tools/grep_files_tool.py +12 -10
  28. pycodex/tools/ipython_tool.py +10 -13
  29. pycodex/tools/list_dir_tool.py +13 -9
  30. pycodex/tools/read_file_tool.py +29 -17
  31. pycodex/tools/request_permissions_tool.py +15 -5
  32. pycodex/tools/request_user_input_tool.py +13 -104
  33. pycodex/tools/resume_agent_tool.py +2 -2
  34. pycodex/tools/send_input_tool.py +11 -8
  35. pycodex/tools/shell_command_tool.py +7 -5
  36. pycodex/tools/shell_tool.py +7 -5
  37. pycodex/tools/spawn_agent_tool.py +7 -4
  38. pycodex/tools/unified_exec_manager.py +102 -69
  39. pycodex/tools/update_plan_tool.py +8 -5
  40. pycodex/tools/view_image_tool.py +7 -5
  41. pycodex/tools/wait_agent_tool.py +27 -4
  42. pycodex/tools/wait_tool.py +5 -4
  43. pycodex/tools/web_search_tool.py +4 -2
  44. pycodex/tools/write_stdin_tool.py +12 -11
  45. pycodex/utils/__init__.py +2 -17
  46. pycodex/utils/compactor.py +41 -72
  47. pycodex/utils/debug.py +2 -2
  48. pycodex/utils/dotenv.py +6 -7
  49. pycodex/utils/event_helpers.py +190 -0
  50. pycodex/utils/get_env.py +27 -70
  51. pycodex/{image_utils.py → utils/image_utils.py} +8 -11
  52. pycodex/utils/random_ids.py +1 -2
  53. pycodex/utils/session_persist.py +217 -163
  54. pycodex/utils/truncation.py +21 -45
  55. python_codex-0.3.1.dist-info/METADATA +743 -0
  56. python_codex-0.3.1.dist-info/RECORD +91 -0
  57. responses_server/__init__.py +1 -5
  58. responses_server/__main__.py +0 -1
  59. responses_server/app.py +34 -33
  60. responses_server/config.py +23 -23
  61. responses_server/messages_api.py +51 -53
  62. responses_server/payload_processors.py +25 -20
  63. responses_server/server.py +11 -11
  64. responses_server/session_store.py +14 -11
  65. responses_server/stream_router.py +209 -98
  66. responses_server/tools/custom_adapter.py +17 -16
  67. responses_server/tools/web_search.py +39 -36
  68. responses_server/trajectory_dump.py +36 -14
  69. workspace_server/__main__.py +0 -1
  70. workspace_server/app.py +465 -377
  71. workspace_server/owned_process.py +27 -0
  72. workspace_server/workspace.html +854 -228
  73. workspace_server/workspaces.html +94 -95
  74. workspace_server/workspaces.py +141 -84
  75. pycodex/collaboration.py +0 -20
  76. pycodex/interactive_session.py +0 -415
  77. pycodex/prompts/collaboration_default.md +0 -11
  78. pycodex/prompts/collaboration_plan.md +0 -128
  79. pycodex/utils/toolcall_visualize.py +0 -713
  80. pycodex/utils/visualize.py +0 -560
  81. python_codex-0.2.7.dist-info/METADATA +0 -455
  82. python_codex-0.2.7.dist-info/RECORD +0 -93
  83. {python_codex-0.2.7.dist-info → python_codex-0.3.1.dist-info}/WHEEL +0 -0
  84. {python_codex-0.2.7.dist-info → python_codex-0.3.1.dist-info}/entry_points.txt +0 -0
  85. {python_codex-0.2.7.dist-info → python_codex-0.3.1.dist-info}/licenses/LICENSE +0 -0
@@ -1,4 +1,3 @@
1
-
2
1
  """Provider-specific post-process hooks for canonical outgoing chat requests.
3
2
 
4
3
  Each downstream chat-completions provider may have its own payload quirks:
@@ -8,9 +7,10 @@ building one canonical `outcomming_request`, while `server.py` selects the
8
7
  appropriate hook from `CompatServerConfig.model_provider`.
9
8
  """
10
9
 
10
+ import typing
11
11
  from copy import deepcopy
12
12
  from typing import Callable, Optional
13
- import typing
13
+
14
14
  from typing_extensions import TypedDict
15
15
 
16
16
  ChatMessage = typing.Dict[str, object]
@@ -25,27 +25,29 @@ class OutgoingRequest(TypedDict):
25
25
  not rely on TypedDict inheritance.
26
26
  """
27
27
 
28
- model: 'str'
29
- messages: 'typing.List[ChatMessage]'
30
- stream: 'bool'
31
- chat_template_kwargs: 'Optional[typing.Dict[str, object]]'
32
- max_tokens: 'Optional[int]'
33
- tools: 'Optional[typing.List[typing.Dict[str, object]]]'
34
- tool_choice: 'Optional[object]'
35
- parallel_tool_calls: 'Optional[bool]'
36
- return_token_ids: 'Optional[bool]'
28
+ model: "str"
29
+ messages: "typing.List[ChatMessage]"
30
+ stream: "bool"
31
+ chat_template_kwargs: "Optional[typing.Dict[str, object]]"
32
+ max_tokens: "Optional[int]"
33
+ tools: "Optional[typing.List[typing.Dict[str, object]]]"
34
+ tool_choice: "Optional[object]"
35
+ parallel_tool_calls: "Optional[bool]"
36
+ return_token_ids: "Optional[bool]"
37
37
 
38
38
 
39
39
  PayloadPostProcessor = Callable[[OutgoingRequest], OutgoingRequest]
40
40
 
41
41
 
42
- def _identity(outcomming_request: 'OutgoingRequest') -> 'OutgoingRequest':
42
+ def _identity(outcomming_request: "OutgoingRequest") -> "OutgoingRequest":
43
43
  """Keep the canonical request unchanged."""
44
44
 
45
45
  return outcomming_request
46
46
 
47
47
 
48
- def _drop_developer_messages(outcomming_request: 'OutgoingRequest') -> 'OutgoingRequest':
48
+ def _drop_developer_messages(
49
+ outcomming_request: "OutgoingRequest",
50
+ ) -> "OutgoingRequest":
49
51
  """Remove all developer-role messages for providers that reject them."""
50
52
 
51
53
  outcomming_request["messages"] = [
@@ -55,17 +57,20 @@ def _drop_developer_messages(outcomming_request: 'OutgoingRequest') -> 'Outgoing
55
57
  ]
56
58
  return outcomming_request
57
59
 
58
- def _replace_developer_messages(outcomming_request: 'OutgoingRequest') -> 'OutgoingRequest':
60
+
61
+ def _replace_developer_messages(
62
+ outcomming_request: "OutgoingRequest",
63
+ ) -> "OutgoingRequest":
59
64
  """Replace all developer-role messages to system-role messages"""
60
65
 
61
- for message in outcomming_request['messages']:
66
+ for message in outcomming_request["messages"]:
62
67
  if message.get("role") == "developer":
63
- message['role'] = "system"
68
+ message["role"] = "system"
64
69
 
65
70
  return outcomming_request
66
71
 
67
72
 
68
- PAYLOAD_POST_PROCESSORS: 'typing.Dict[str, PayloadPostProcessor]' = {
73
+ PAYLOAD_POST_PROCESSORS: "typing.Dict[str, PayloadPostProcessor]" = {
69
74
  "stepfun": _replace_developer_messages,
70
75
  "vllm": _identity,
71
76
  }
@@ -73,9 +78,9 @@ PAYLOAD_POST_PROCESSORS: 'typing.Dict[str, PayloadPostProcessor]' = {
73
78
 
74
79
 
75
80
  def post_process_outcomming_request(
76
- outcomming_request: 'OutgoingRequest',
77
- model_provider: 'typing.Union[str, None]',
78
- ) -> 'OutgoingRequest':
81
+ outcomming_request: "OutgoingRequest",
82
+ model_provider: "typing.Union[str, None]",
83
+ ) -> "OutgoingRequest":
79
84
  """Apply the provider-specific payload hook to one outgoing request.
80
85
 
81
86
  This is the single wrapper around `PAYLOAD_POST_PROCESSORS`: it normalizes
@@ -1,43 +1,43 @@
1
+ import typing
1
2
 
2
3
  from .config import CompatServerConfig
3
4
  from .payload_processors import post_process_outcomming_request
4
5
  from .session_store import SessionStore
5
6
  from .stream_router import StreamRouter
6
7
  from .trajectory_dump import TrajectoryDumpWriter
7
- import typing
8
8
 
9
9
 
10
10
  class ResponseServer:
11
11
  def __init__(
12
12
  self,
13
- config: 'CompatServerConfig',
14
- session_store: 'typing.Union[SessionStore, None]' = None,
15
- stream_router: 'typing.Union[StreamRouter, None]' = None,
16
- ) -> 'None':
13
+ config: "CompatServerConfig",
14
+ session_store: "typing.Union[SessionStore, None]" = None,
15
+ stream_router: "typing.Union[StreamRouter, None]" = None,
16
+ ) -> "None":
17
17
  self._config = config
18
18
  self._session_store = session_store or SessionStore()
19
19
  self._stream_router = stream_router or StreamRouter(config)
20
20
  self._trajectory_dump = TrajectoryDumpWriter.from_env()
21
21
 
22
22
  @property
23
- def config(self) -> 'CompatServerConfig':
23
+ def config(self) -> "CompatServerConfig":
24
24
  return self._config
25
25
 
26
26
  @property
27
- def session_store(self) -> 'SessionStore':
27
+ def session_store(self) -> "SessionStore":
28
28
  return self._session_store
29
29
 
30
30
  @property
31
- def stream_router(self) -> 'StreamRouter':
31
+ def stream_router(self) -> "StreamRouter":
32
32
  return self._stream_router
33
33
 
34
- def list_models(self) -> 'typing.Dict[str, object]':
34
+ def list_models(self) -> "typing.Dict[str, object]":
35
35
  return self._stream_router.list_models()
36
36
 
37
37
  def start_response_stream(
38
38
  self,
39
- request_body: 'typing.Dict[str, object]',
40
- request_headers: 'typing.Dict[str, str]',
39
+ request_body: "typing.Dict[str, object]",
40
+ request_headers: "typing.Dict[str, str]",
41
41
  ):
42
42
  outcomming_request = self._stream_router.build_outcomming_request(request_body)
43
43
  if self._trajectory_dump is not None:
@@ -1,25 +1,28 @@
1
-
2
- from dataclasses import dataclass
3
1
  import threading
4
2
  import time
5
3
  import typing
4
+ from dataclasses import dataclass
6
5
 
7
6
 
8
- @dataclass(frozen=True, )
7
+ @dataclass(
8
+ frozen=True,
9
+ )
9
10
  class StoredResponse:
10
- response_id: 'str'
11
- session_id: 'typing.Union[str, None]'
12
- model: 'str'
13
- created_at: 'float'
11
+ response_id: "str"
12
+ session_id: "typing.Union[str, None]"
13
+ model: "str"
14
+ created_at: "float"
14
15
 
15
16
 
16
17
  class SessionStore:
17
- def __init__(self) -> 'None':
18
+ def __init__(self) -> "None":
18
19
  self._lock = threading.Lock()
19
20
  self._next_response_number = 1
20
- self._responses: 'typing.Dict[str, StoredResponse]' = {}
21
+ self._responses: "typing.Dict[str, StoredResponse]" = {}
21
22
 
22
- def create_response(self, session_id: 'typing.Union[str, None]', model: 'str') -> 'StoredResponse':
23
+ def create_response(
24
+ self, session_id: "typing.Union[str, None]", model: "str"
25
+ ) -> "StoredResponse":
23
26
  with self._lock:
24
27
  response_id = f"resp_{self._next_response_number:08d}"
25
28
  self._next_response_number += 1
@@ -32,6 +35,6 @@ class SessionStore:
32
35
  self._responses[response_id] = stored
33
36
  return stored
34
37
 
35
- def get_response(self, response_id: 'str') -> 'typing.Union[StoredResponse, None]':
38
+ def get_response(self, response_id: "str") -> "typing.Union[StoredResponse, None]":
36
39
  with self._lock:
37
40
  return self._responses.get(response_id)