python-codex 0.1.2__py3-none-any.whl → 0.1.3__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 (56) hide show
  1. pycodex/__init__.py +5 -1
  2. pycodex/agent.py +39 -41
  3. pycodex/cli.py +43 -42
  4. pycodex/collaboration.py +6 -7
  5. pycodex/compat.py +99 -0
  6. pycodex/context.py +87 -87
  7. pycodex/doctor.py +40 -40
  8. pycodex/model.py +69 -69
  9. pycodex/portable.py +33 -33
  10. pycodex/portable_server.py +22 -21
  11. pycodex/protocol.py +84 -86
  12. pycodex/runtime.py +36 -35
  13. pycodex/runtime_services.py +69 -69
  14. pycodex/tools/agent_tool_schemas.py +0 -2
  15. pycodex/tools/apply_patch_tool.py +43 -44
  16. pycodex/tools/base_tool.py +35 -36
  17. pycodex/tools/close_agent_tool.py +2 -4
  18. pycodex/tools/code_mode_manager.py +61 -61
  19. pycodex/tools/exec_command_tool.py +5 -6
  20. pycodex/tools/exec_runtime.js +3 -3
  21. pycodex/tools/exec_tool.py +2 -4
  22. pycodex/tools/grep_files_tool.py +10 -11
  23. pycodex/tools/list_dir_tool.py +8 -9
  24. pycodex/tools/read_file_tool.py +13 -14
  25. pycodex/tools/request_permissions_tool.py +2 -4
  26. pycodex/tools/request_user_input_tool.py +13 -14
  27. pycodex/tools/resume_agent_tool.py +2 -4
  28. pycodex/tools/send_input_tool.py +8 -9
  29. pycodex/tools/shell_command_tool.py +5 -6
  30. pycodex/tools/shell_tool.py +5 -6
  31. pycodex/tools/spawn_agent_tool.py +4 -5
  32. pycodex/tools/unified_exec_manager.py +62 -61
  33. pycodex/tools/update_plan_tool.py +4 -5
  34. pycodex/tools/view_image_tool.py +4 -5
  35. pycodex/tools/wait_agent_tool.py +2 -4
  36. pycodex/tools/wait_tool.py +4 -5
  37. pycodex/tools/web_search_tool.py +1 -3
  38. pycodex/tools/write_stdin_tool.py +4 -5
  39. pycodex/utils/dotenv.py +6 -6
  40. pycodex/utils/get_env.py +37 -33
  41. pycodex/utils/random_ids.py +1 -2
  42. pycodex/utils/visualize.py +79 -79
  43. {python_codex-0.1.2.dist-info → python_codex-0.1.3.dist-info}/METADATA +15 -9
  44. python_codex-0.1.3.dist-info/RECORD +74 -0
  45. {python_codex-0.1.2.dist-info → python_codex-0.1.3.dist-info}/WHEEL +1 -1
  46. responses_server/app.py +29 -19
  47. responses_server/config.py +17 -17
  48. responses_server/payload_processors.py +16 -16
  49. responses_server/server.py +11 -11
  50. responses_server/session_store.py +10 -10
  51. responses_server/stream_router.py +58 -58
  52. responses_server/tools/custom_adapter.py +12 -12
  53. responses_server/tools/web_search.py +33 -33
  54. python_codex-0.1.2.dist-info/RECORD +0 -73
  55. {python_codex-0.1.2.dist-info → python_codex-0.1.3.dist-info}/entry_points.txt +0 -0
  56. {python_codex-0.1.2.dist-info → python_codex-0.1.3.dist-info}/licenses/LICENSE +0 -0
@@ -1,4 +1,3 @@
1
- from __future__ import annotations
2
1
 
3
2
  import json
4
3
  import ssl
@@ -21,6 +20,7 @@ from .tools.web_search import (
21
20
  hydrate_tool_call_names,
22
21
  partition_tool_calls,
23
22
  )
23
+ import typing
24
24
 
25
25
 
26
26
  class UnsupportedIncommingFeature(ValueError):
@@ -32,15 +32,15 @@ class OutcommingChatError(RuntimeError):
32
32
 
33
33
 
34
34
  class StreamRouter:
35
- def __init__(self, config: CompatServerConfig) -> None:
35
+ def __init__(self, config: 'CompatServerConfig') -> 'None':
36
36
  self._config = config
37
37
  self._mock_web_search = WebSearchTool()
38
38
 
39
39
  def _provider_capability(
40
40
  self,
41
- explicit_support: dict[str, bool],
42
- default: bool | None = None,
43
- ) -> bool:
41
+ explicit_support: 'typing.Dict[str, bool]',
42
+ default: 'typing.Union[bool, None]' = None,
43
+ ) -> 'bool':
44
44
  provider_name = str(self._config.model_provider or "").strip().lower()
45
45
  if provider_name in explicit_support:
46
46
  return explicit_support[provider_name]
@@ -50,7 +50,7 @@ class StreamRouter:
50
50
  return default
51
51
  raise KeyError("provider capability map is missing `vllm` fallback")
52
52
 
53
- def _supports_chat_reasoning(self) -> bool:
53
+ def _supports_chat_reasoning(self) -> 'bool':
54
54
  # Unknown providers inherit the vLLM compatibility behavior unless a
55
55
  # provider is explicitly declared otherwise.
56
56
  return self._provider_capability(
@@ -60,7 +60,7 @@ class StreamRouter:
60
60
  }
61
61
  )
62
62
 
63
- def _supports_stream_usage(self) -> bool:
63
+ def _supports_stream_usage(self) -> 'bool':
64
64
  return self._provider_capability(
65
65
  {
66
66
  "vllm": True,
@@ -70,8 +70,8 @@ class StreamRouter:
70
70
 
71
71
  def validate_incomming_request(
72
72
  self,
73
- incomming_request: dict[str, object],
74
- ) -> None:
73
+ incomming_request: 'typing.Dict[str, object]',
74
+ ) -> 'None':
75
75
  model = str(incomming_request.get("model", "")).strip()
76
76
  if not model:
77
77
  raise UnsupportedIncommingFeature("incomming request is missing `model`")
@@ -90,11 +90,11 @@ class StreamRouter:
90
90
 
91
91
  def collect_custom_tool_names(
92
92
  self,
93
- incomming_request: dict[str, object],
94
- ) -> set[str]:
93
+ incomming_request: 'typing.Dict[str, object]',
94
+ ) -> 'typing.Set[str]':
95
95
  return collect_custom_tool_names(incomming_request.get("tools") or [])
96
96
 
97
- def list_models(self) -> dict[str, object]:
97
+ def list_models(self) -> 'typing.Dict[str, object]':
98
98
  request = urllib.request.Request(
99
99
  self._config.outcomming_models_url(),
100
100
  headers=self._build_headers(accept="application/json"),
@@ -104,8 +104,8 @@ class StreamRouter:
104
104
 
105
105
  def build_outcomming_request(
106
106
  self,
107
- incomming_request: dict[str, object],
108
- ) -> dict[str, object]:
107
+ incomming_request: 'typing.Dict[str, object]',
108
+ ) -> 'typing.Dict[str, object]':
109
109
  model = str(incomming_request.get("model", "")).strip()
110
110
  if not model:
111
111
  raise UnsupportedIncommingFeature("incomming request is missing `model`")
@@ -121,7 +121,7 @@ class StreamRouter:
121
121
  if not isinstance(input_items, list):
122
122
  raise UnsupportedIncommingFeature("incomming `input` must be a list")
123
123
 
124
- payload: dict[str, object] = {
124
+ payload: 'typing.Dict[str, object]' = {
125
125
  "model": model,
126
126
  "messages": self._responses_input_to_chat_messages(
127
127
  instructions,
@@ -148,7 +148,7 @@ class StreamRouter:
148
148
 
149
149
  return payload
150
150
 
151
- def open_outcomming_stream(self, outcomming_request: dict[str, object]):
151
+ def open_outcomming_stream(self, outcomming_request: 'typing.Dict[str, object]'):
152
152
  request = urllib.request.Request(
153
153
  self._config.outcomming_chat_completions_url(),
154
154
  data=json.dumps(outcomming_request).encode("utf-8"),
@@ -180,9 +180,9 @@ class StreamRouter:
180
180
  def route_stream(
181
181
  self,
182
182
  incomming_stream,
183
- stored_response: StoredResponse,
184
- outcomming_request: dict[str, object],
185
- custom_tool_names: set[str] | None = None,
183
+ stored_response: 'StoredResponse',
184
+ outcomming_request: 'typing.Dict[str, object]',
185
+ custom_tool_names: 'typing.Union[typing.Set[str], None]' = None,
186
186
  ):
187
187
  yield (
188
188
  "response.created",
@@ -197,15 +197,15 @@ class StreamRouter:
197
197
  },
198
198
  )
199
199
 
200
- text_parts: list[str] = []
201
- reasoning_parts: list[str] = []
202
- latest_usage: dict[str, object] = {}
200
+ text_parts: 'typing.List[str]' = []
201
+ reasoning_parts: 'typing.List[str]' = []
202
+ latest_usage: 'typing.Dict[str, object]' = {}
203
203
  current_request = json.loads(json.dumps(outcomming_request))
204
204
  current_stream = incomming_stream
205
205
 
206
206
  while True:
207
- tool_calls: dict[int, dict[str, object]] = {}
208
- current_usage: dict[str, object] = {}
207
+ tool_calls: 'typing.Dict[int, typing.Dict[str, object]]' = {}
208
+ current_usage: 'typing.Dict[str, object]' = {}
209
209
  for chunk in current_stream:
210
210
  for event_name, payload in self._consume_chat_chunk(
211
211
  chunk,
@@ -290,16 +290,16 @@ class StreamRouter:
290
290
 
291
291
  def _responses_input_to_chat_messages(
292
292
  self,
293
- instructions: str,
294
- input_items: list[object],
295
- ) -> list[dict[str, object]]:
296
- messages: list[dict[str, object]] = []
293
+ instructions: 'str',
294
+ input_items: 'typing.List[object]',
295
+ ) -> 'typing.List[typing.Dict[str, object]]':
296
+ messages: 'typing.List[typing.Dict[str, object]]' = []
297
297
  if instructions:
298
298
  messages.append({"role": "developer", "content": instructions})
299
299
 
300
- pending_assistant: dict[str, object] | None = None
300
+ pending_assistant: 'typing.Union[typing.Dict[str, object], None]' = None
301
301
 
302
- def flush_pending_assistant() -> None:
302
+ def flush_pending_assistant() -> 'None':
303
303
  nonlocal pending_assistant
304
304
  if pending_assistant is None:
305
305
  return
@@ -420,7 +420,7 @@ class StreamRouter:
420
420
  flush_pending_assistant()
421
421
  return messages
422
422
 
423
- def _coalesce_content_text(self, raw_content: object) -> str:
423
+ def _coalesce_content_text(self, raw_content: 'object') -> 'str':
424
424
  if raw_content is None:
425
425
  return ""
426
426
  if isinstance(raw_content, str):
@@ -430,7 +430,7 @@ class StreamRouter:
430
430
  "message `content` must be a list or string"
431
431
  )
432
432
 
433
- text_parts: list[str] = []
433
+ text_parts: 'typing.List[str]' = []
434
434
  for part in raw_content:
435
435
  if not isinstance(part, dict):
436
436
  raise UnsupportedIncommingFeature(
@@ -445,17 +445,17 @@ class StreamRouter:
445
445
  )
446
446
  return "".join(text_parts)
447
447
 
448
- def _coalesce_tool_output_text(self, raw_output: object) -> str:
448
+ def _coalesce_tool_output_text(self, raw_output: 'object') -> 'str':
449
449
  if isinstance(raw_output, str):
450
450
  return raw_output
451
451
  if isinstance(raw_output, list):
452
452
  return self._coalesce_content_text(raw_output)
453
453
  return json.dumps(raw_output, ensure_ascii=False)
454
454
 
455
- def _coalesce_reasoning_text(self, raw_item: dict[str, object]) -> str:
455
+ def _coalesce_reasoning_text(self, raw_item: 'typing.Dict[str, object]') -> 'str':
456
456
  content = raw_item.get("content")
457
457
  if isinstance(content, list):
458
- text_parts: list[str] = []
458
+ text_parts: 'typing.List[str]' = []
459
459
  for part in content:
460
460
  if not isinstance(part, dict):
461
461
  continue
@@ -482,8 +482,8 @@ class StreamRouter:
482
482
  return value
483
483
  return ""
484
484
 
485
- def _translate_tools(self, incomming_tools: list[object]) -> list[dict[str, object]]:
486
- translated: list[dict[str, object]] = []
485
+ def _translate_tools(self, incomming_tools: 'typing.List[object]') -> 'typing.List[typing.Dict[str, object]]':
486
+ translated: 'typing.List[typing.Dict[str, object]]' = []
487
487
  for raw_tool in incomming_tools:
488
488
  if not isinstance(raw_tool, dict):
489
489
  raise UnsupportedIncommingFeature("tool definitions must be objects")
@@ -518,7 +518,7 @@ class StreamRouter:
518
518
  )
519
519
  return translated
520
520
 
521
- def _translate_tool_choice(self, raw_tool_choice: object) -> object:
521
+ def _translate_tool_choice(self, raw_tool_choice: 'object') -> 'object':
522
522
  if isinstance(raw_tool_choice, str):
523
523
  return raw_tool_choice
524
524
  if not isinstance(raw_tool_choice, dict):
@@ -541,13 +541,13 @@ class StreamRouter:
541
541
 
542
542
  def _consume_chat_chunk(
543
543
  self,
544
- payload: dict[str, object],
545
- reasoning_parts: list[str],
546
- text_parts: list[str],
547
- tool_calls: dict[int, dict[str, object]],
548
- current_usage: dict[str, object],
549
- ) -> list[tuple[str, dict[str, object]]]:
550
- events: list[tuple[str, dict[str, object]]] = []
544
+ payload: 'typing.Dict[str, object]',
545
+ reasoning_parts: 'typing.List[str]',
546
+ text_parts: 'typing.List[str]',
547
+ tool_calls: 'typing.Dict[int, typing.Dict[str, object]]',
548
+ current_usage: 'typing.Dict[str, object]',
549
+ ) -> 'typing.List[typing.Tuple[str, typing.Dict[str, object]]]':
550
+ events: 'typing.List[typing.Tuple[str, typing.Dict[str, object]]]' = []
551
551
  usage = payload.get("usage")
552
552
  if isinstance(usage, dict):
553
553
  self._capture_usage_snapshot(current_usage, usage)
@@ -627,9 +627,9 @@ class StreamRouter:
627
627
 
628
628
  def _capture_usage_snapshot(
629
629
  self,
630
- current_usage: dict[str, object],
631
- usage: dict[str, object],
632
- ) -> None:
630
+ current_usage: 'typing.Dict[str, object]',
631
+ usage: 'typing.Dict[str, object]',
632
+ ) -> 'None':
633
633
  scalar_mappings = (
634
634
  ("input_tokens", usage.get("input_tokens", usage.get("prompt_tokens"))),
635
635
  (
@@ -661,12 +661,12 @@ class StreamRouter:
661
661
 
662
662
  def _build_output_items(
663
663
  self,
664
- reasoning_parts: list[str],
665
- text_parts: list[str],
666
- tool_calls: dict[int, dict[str, object]],
667
- custom_tool_names: set[str],
668
- ) -> list[dict[str, object]]:
669
- items: list[dict[str, object]] = []
664
+ reasoning_parts: 'typing.List[str]',
665
+ text_parts: 'typing.List[str]',
666
+ tool_calls: 'typing.Dict[int, typing.Dict[str, object]]',
667
+ custom_tool_names: 'typing.Set[str]',
668
+ ) -> 'typing.List[typing.Dict[str, object]]':
669
+ items: 'typing.List[typing.Dict[str, object]]' = []
670
670
  reasoning_text = "".join(reasoning_parts)
671
671
  if reasoning_text:
672
672
  items.append(
@@ -731,7 +731,7 @@ class StreamRouter:
731
731
 
732
732
  return items
733
733
 
734
- def _request_json(self, request: urllib.request.Request) -> dict[str, object]:
734
+ def _request_json(self, request: 'urllib.request.Request') -> 'typing.Dict[str, object]':
735
735
  try:
736
736
  with urllib.request.urlopen(
737
737
  request,
@@ -749,7 +749,7 @@ class StreamRouter:
749
749
  f"outcomming request failed: {exc.reason}"
750
750
  ) from exc
751
751
 
752
- def _build_headers(self, accept: str) -> dict[str, str]:
752
+ def _build_headers(self, accept: 'str') -> 'typing.Dict[str, str]':
753
753
  headers = {
754
754
  "Accept": accept,
755
755
  "Content-Type": "application/json",
@@ -760,8 +760,8 @@ class StreamRouter:
760
760
  return headers
761
761
 
762
762
  def _iter_sse_events(self, response):
763
- event_name: str | None = None
764
- data_lines: list[str] = []
763
+ event_name: 'typing.Union[str, None]' = None
764
+ data_lines: 'typing.List[str]' = []
765
765
 
766
766
  for raw_line in response:
767
767
  line = raw_line.decode("utf-8", errors="replace").rstrip("\r\n")
@@ -1,7 +1,7 @@
1
- from __future__ import annotations
2
1
 
3
2
  from copy import deepcopy
4
3
  import json
4
+ import typing
5
5
 
6
6
 
7
7
  class CustomToolAdapterError(ValueError):
@@ -82,8 +82,8 @@ It is important to remember:
82
82
  """
83
83
 
84
84
 
85
- def collect_custom_tool_names(raw_tools: object) -> set[str]:
86
- names: set[str] = set()
85
+ def collect_custom_tool_names(raw_tools: 'object') -> 'typing.Set[str]':
86
+ names: 'typing.Set[str]' = set()
87
87
  if not isinstance(raw_tools, list):
88
88
  return names
89
89
  for raw_tool in raw_tools:
@@ -95,7 +95,7 @@ def collect_custom_tool_names(raw_tools: object) -> set[str]:
95
95
  return names
96
96
 
97
97
 
98
- def build_tool_definition(raw_tool: dict[str, object]) -> dict[str, object]:
98
+ def build_tool_definition(raw_tool: 'typing.Dict[str, object]') -> 'typing.Dict[str, object]':
99
99
  name = _required_tool_name(raw_tool)
100
100
  description = _build_description(raw_tool)
101
101
  input_description = (
@@ -125,7 +125,7 @@ def build_tool_definition(raw_tool: dict[str, object]) -> dict[str, object]:
125
125
  }
126
126
 
127
127
 
128
- def build_tool_call(raw_item: dict[str, object]) -> dict[str, object]:
128
+ def build_tool_call(raw_item: 'typing.Dict[str, object]') -> 'typing.Dict[str, object]':
129
129
  name = _required_item_name(raw_item)
130
130
  return {
131
131
  "id": str(raw_item.get("call_id", "")).strip() or name,
@@ -141,7 +141,7 @@ def build_tool_call(raw_item: dict[str, object]) -> dict[str, object]:
141
141
  }
142
142
 
143
143
 
144
- def build_output_item(tool_call: dict[str, object], index: int) -> dict[str, object]:
144
+ def build_output_item(tool_call: 'typing.Dict[str, object]', index: 'int') -> 'typing.Dict[str, object]':
145
145
  function = tool_call.get("function") or {}
146
146
  if not isinstance(function, dict):
147
147
  raise CustomToolAdapterError(
@@ -160,7 +160,7 @@ def build_output_item(tool_call: dict[str, object], index: int) -> dict[str, obj
160
160
  }
161
161
 
162
162
 
163
- def extract_input_text(raw_arguments: object) -> str:
163
+ def extract_input_text(raw_arguments: 'object') -> 'str':
164
164
  if isinstance(raw_arguments, dict):
165
165
  parsed = deepcopy(raw_arguments)
166
166
  else:
@@ -186,7 +186,7 @@ def extract_input_text(raw_arguments: object) -> str:
186
186
  return str(raw_arguments or "")
187
187
 
188
188
 
189
- def _build_description(raw_tool: dict[str, object]) -> str:
189
+ def _build_description(raw_tool: 'typing.Dict[str, object]') -> 'str':
190
190
  name = _tool_name(raw_tool)
191
191
  if name == APPLY_PATCH_NAME:
192
192
  return APPLY_PATCH_CHAT_DESCRIPTION
@@ -200,7 +200,7 @@ def _build_description(raw_tool: dict[str, object]) -> str:
200
200
 
201
201
  raw_format = raw_tool.get("format")
202
202
  if isinstance(raw_format, dict):
203
- format_lines: list[str] = []
203
+ format_lines: 'typing.List[str]' = []
204
204
  format_type = str(raw_format.get("type", "")).strip()
205
205
  syntax = str(raw_format.get("syntax", "")).strip()
206
206
  definition = str(raw_format.get("definition", "") or "").strip()
@@ -217,18 +217,18 @@ def _build_description(raw_tool: dict[str, object]) -> str:
217
217
  return "\n\n".join(parts)
218
218
 
219
219
 
220
- def _tool_name(raw_tool: dict[str, object]) -> str:
220
+ def _tool_name(raw_tool: 'typing.Dict[str, object]') -> 'str':
221
221
  return str(raw_tool.get("name", "")).strip()
222
222
 
223
223
 
224
- def _required_tool_name(raw_tool: dict[str, object]) -> str:
224
+ def _required_tool_name(raw_tool: 'typing.Dict[str, object]') -> 'str':
225
225
  name = _tool_name(raw_tool)
226
226
  if not name:
227
227
  raise CustomToolAdapterError("custom tool definition is missing `name`")
228
228
  return name
229
229
 
230
230
 
231
- def _required_item_name(raw_item: dict[str, object]) -> str:
231
+ def _required_item_name(raw_item: 'typing.Dict[str, object]') -> 'str':
232
232
  name = str(raw_item.get("name", "")).strip()
233
233
  if not name:
234
234
  raise CustomToolAdapterError("custom tool call is missing `name`")
@@ -1,10 +1,10 @@
1
- from __future__ import annotations
2
1
 
3
2
  from copy import deepcopy
4
3
  import json
5
4
 
6
5
  from pycodex.protocol import JSONValue
7
6
  from pycodex.tools.base_tool import BaseTool, ToolContext
7
+ import typing
8
8
 
9
9
 
10
10
  class WebSearchTool(BaseTool):
@@ -29,10 +29,10 @@ class WebSearchTool(BaseTool):
29
29
  }
30
30
  supports_parallel = False
31
31
 
32
- async def run(self, context: ToolContext, args: JSONValue) -> JSONValue:
32
+ async def run(self, context: 'ToolContext', args: 'JSONValue') -> 'JSONValue':
33
33
  del context
34
34
  query, queries = extract_queries(args)
35
- output_payload: dict[str, object] = {
35
+ output_payload: 'typing.Dict[str, object]' = {
36
36
  "results": [],
37
37
  "mock": True,
38
38
  }
@@ -43,7 +43,7 @@ class WebSearchTool(BaseTool):
43
43
  return output_payload
44
44
 
45
45
 
46
- def build_tool_definition(tool: WebSearchTool) -> dict[str, object]:
46
+ def build_tool_definition(tool: 'WebSearchTool') -> 'typing.Dict[str, object]':
47
47
  return {
48
48
  "type": "function",
49
49
  "name": tool.name,
@@ -57,13 +57,13 @@ def build_tool_definition(tool: WebSearchTool) -> dict[str, object]:
57
57
 
58
58
 
59
59
  def partition_tool_calls(
60
- tool: WebSearchTool,
61
- tool_calls: dict[int, dict[str, object]],
62
- outcomming_request: dict[str, object],
63
- ) -> tuple[list[dict[str, object]], dict[int, dict[str, object]]]:
60
+ tool: 'WebSearchTool',
61
+ tool_calls: 'typing.Dict[int, typing.Dict[str, object]]',
62
+ outcomming_request: 'typing.Dict[str, object]',
63
+ ) -> 'typing.Tuple[typing.List[typing.Dict[str, object]], typing.Dict[int, typing.Dict[str, object]]]':
64
64
  mock_tool_names = _collect_mock_tool_names(tool, outcomming_request)
65
- mock_calls: list[dict[str, object]] = []
66
- ordinary_tool_calls: dict[int, dict[str, object]] = {}
65
+ mock_calls: 'typing.List[typing.Dict[str, object]]' = []
66
+ ordinary_tool_calls: 'typing.Dict[int, typing.Dict[str, object]]' = {}
67
67
  for index in sorted(tool_calls):
68
68
  tool_call = tool_calls[index]
69
69
  function = tool_call.get("function") or {}
@@ -78,9 +78,9 @@ def partition_tool_calls(
78
78
 
79
79
 
80
80
  def hydrate_tool_call_names(
81
- tool_calls: dict[int, dict[str, object]],
82
- outcomming_request: dict[str, object],
83
- ) -> None:
81
+ tool_calls: 'typing.Dict[int, typing.Dict[str, object]]',
82
+ outcomming_request: 'typing.Dict[str, object]',
83
+ ) -> 'None':
84
84
  raw_tools = outcomming_request.get("tools") or []
85
85
  if not isinstance(raw_tools, list):
86
86
  return
@@ -104,15 +104,15 @@ def hydrate_tool_call_names(
104
104
 
105
105
 
106
106
  def build_output_items(
107
- mock_search_calls: list[dict[str, object]],
108
- ) -> list[dict[str, object]]:
109
- items: list[dict[str, object]] = []
107
+ mock_search_calls: 'typing.List[typing.Dict[str, object]]',
108
+ ) -> 'typing.List[typing.Dict[str, object]]':
109
+ items: 'typing.List[typing.Dict[str, object]]' = []
110
110
  for tool_call in mock_search_calls:
111
111
  function = tool_call.get("function") or {}
112
112
  if not isinstance(function, dict):
113
113
  continue
114
114
  query, queries = extract_queries(function.get("arguments"))
115
- action: dict[str, object] = {"type": "search"}
115
+ action: 'typing.Dict[str, object]' = {"type": "search"}
116
116
  if query:
117
117
  action["query"] = query
118
118
  if queries:
@@ -128,17 +128,17 @@ def build_output_items(
128
128
 
129
129
 
130
130
  def build_followup_request(
131
- tool: WebSearchTool,
132
- outcomming_request: dict[str, object],
133
- mock_search_calls: list[dict[str, object]],
134
- reasoning_text: str | None = None,
135
- ) -> dict[str, object]:
131
+ tool: 'WebSearchTool',
132
+ outcomming_request: 'typing.Dict[str, object]',
133
+ mock_search_calls: 'typing.List[typing.Dict[str, object]]',
134
+ reasoning_text: 'typing.Union[str, None]' = None,
135
+ ) -> 'typing.Dict[str, object]':
136
136
  followup_request = deepcopy(outcomming_request)
137
137
  messages = followup_request.get("messages") or []
138
138
  if not isinstance(messages, list):
139
139
  raise ValueError("outcomming request messages must be a list")
140
140
 
141
- assistant_tool_calls: list[dict[str, object]] = []
141
+ assistant_tool_calls: 'typing.List[typing.Dict[str, object]]' = []
142
142
  for tool_call in mock_search_calls:
143
143
  function = tool_call.get("function") or {}
144
144
  if not isinstance(function, dict):
@@ -154,7 +154,7 @@ def build_followup_request(
154
154
  }
155
155
  )
156
156
  if assistant_tool_calls:
157
- assistant_message: dict[str, object] = {
157
+ assistant_message: 'typing.Dict[str, object]' = {
158
158
  "role": "assistant",
159
159
  "tool_calls": assistant_tool_calls,
160
160
  }
@@ -187,7 +187,7 @@ def build_followup_request(
187
187
  return followup_request
188
188
 
189
189
 
190
- def extract_queries(raw_arguments: JSONValue) -> tuple[str, list[str]]:
190
+ def extract_queries(raw_arguments: 'JSONValue') -> 'typing.Tuple[str, typing.List[str]]':
191
191
  if isinstance(raw_arguments, dict):
192
192
  parsed = raw_arguments
193
193
  else:
@@ -211,7 +211,7 @@ def extract_queries(raw_arguments: JSONValue) -> tuple[str, list[str]]:
211
211
 
212
212
  query = str(parsed.get("query", "")).strip()
213
213
  queries_value = parsed.get("queries") or []
214
- queries: list[str] = []
214
+ queries: 'typing.List[str]' = []
215
215
  if isinstance(queries_value, list):
216
216
  for value in queries_value:
217
217
  normalized = str(value).strip()
@@ -224,7 +224,7 @@ def extract_queries(raw_arguments: JSONValue) -> tuple[str, list[str]]:
224
224
  return query, queries
225
225
 
226
226
 
227
- def is_mock_tool(tool: WebSearchTool, raw_tool: object) -> bool:
227
+ def is_mock_tool(tool: 'WebSearchTool', raw_tool: 'object') -> 'bool':
228
228
  if not isinstance(raw_tool, dict) or raw_tool.get("type") != "function":
229
229
  return False
230
230
  function = raw_tool.get("function") or {}
@@ -237,10 +237,10 @@ def is_mock_tool(tool: WebSearchTool, raw_tool: object) -> bool:
237
237
 
238
238
 
239
239
  def _collect_mock_tool_names(
240
- tool: WebSearchTool,
241
- outcomming_request: dict[str, object],
242
- ) -> set[str]:
243
- names: set[str] = set()
240
+ tool: 'WebSearchTool',
241
+ outcomming_request: 'typing.Dict[str, object]',
242
+ ) -> 'typing.Set[str]':
243
+ names: 'typing.Set[str]' = set()
244
244
  raw_tools = outcomming_request.get("tools") or []
245
245
  if not isinstance(raw_tools, list):
246
246
  return names
@@ -250,9 +250,9 @@ def _collect_mock_tool_names(
250
250
  return names
251
251
 
252
252
 
253
- def _build_mock_output(raw_arguments: JSONValue) -> dict[str, object]:
253
+ def _build_mock_output(raw_arguments: 'JSONValue') -> 'typing.Dict[str, object]':
254
254
  query, queries = extract_queries(raw_arguments)
255
- output_payload: dict[str, object] = {
255
+ output_payload: 'typing.Dict[str, object]' = {
256
256
  "results": [],
257
257
  "mock": True,
258
258
  }
@@ -1,73 +0,0 @@
1
- pycodex/__init__.py,sha256=T11JU1QHEk81TchhrTAOqVkvUUiQGlesk9PNaivjPrU,3052
2
- pycodex/agent.py,sha256=ApIneWSqDxryf9hdmTRFL65AH4e-sn0MWuuR80951Ec,10069
3
- pycodex/cli.py,sha256=ju4aF_kwbraqZ-NfoymzB6CjvvMX22afeXDvse2ykf8,24676
4
- pycodex/collaboration.py,sha256=XAM2enljzHMjzZVlLxbOQF0JhWgKW4qaaDfVcUdE47g,632
5
- pycodex/context.py,sha256=8-Eg1TE4-GVbEfW0fNZjDWhjLypK3jBlKZY1haYYVPY,23143
6
- pycodex/doctor.py,sha256=VN-qetM2qJCNRNTZXBMe44VSrEOu8kUXE01luLMF050,10357
7
- pycodex/model.py,sha256=ZqXSucpzBm0kn2XfhBdKebdwvJQH1Jc9xMqBfPwOKGM,19672
8
- pycodex/portable.py,sha256=Y2pY08pDiWITY0QYgH3F9YKpOe2EYtxE0qqSmrCkp_g,15260
9
- pycodex/portable_server.py,sha256=xhEwySCJ41WnsowXM-Db6kkmCOVM02Lmd4pbN6hZzh0,7232
10
- pycodex/protocol.py,sha256=8mQ7I-y9bxYueSr7d_yGj2Tw69t47OCgwvmxhwihdFw,10807
11
- pycodex/runtime.py,sha256=tfEuyZmnTP625BQ0NMm-AGhjfQpXcv2EaZLtCJTnEmM,7757
12
- pycodex/runtime_services.py,sha256=hmdwFiOZ1DPEJ5T8vfDSLfujgGQBPrzPQkn6uX_9vZ8,12503
13
- pycodex/prompts/collaboration_default.md,sha256=MBTmPuMubeWfZgIeFVj49wwnwD4n_o3fVYAbgWKwu6Q,955
14
- pycodex/prompts/collaboration_plan.md,sha256=IzjQAA5oHJz-3FmJdOjsJ4LHq6LW1tlEYMoy09n0HKk,8777
15
- pycodex/prompts/default_base_instructions.md,sha256=D65mcj6bo4CDvVom-D9cbJRJVNquo0NghKt164_fRsg,20923
16
- pycodex/prompts/exec_tools.json,sha256=2wYLsjL6VGzMnhFNCxE9IA_kxsxUspN68lr7JOlZq54,23369
17
- pycodex/prompts/models.json,sha256=Xmuy5-FiiWdAe-Zz9w_-_kdEcRvIVssS1PugQSA64i8,251450
18
- pycodex/prompts/subagent_tools.json,sha256=2ZOXyAiAaai2aazIlXdjjXb7cra5gZ2WYYbPltPaiYg,6199
19
- pycodex/prompts/permissions/approval_policy/never.md,sha256=QceTG6wjkaJARjYr0HYV1aPnPcpGcrkRUW-smWRr6MQ,120
20
- pycodex/prompts/permissions/approval_policy/on_failure.md,sha256=dfJjpXkpO6_ANdCKxbVJ8o4vyLxevrJWfKsGHTqtbkc,289
21
- pycodex/prompts/permissions/approval_policy/on_request.md,sha256=hVQalzh0FAdkKzw5u-N4H7-LtC9ijVDlYsh3OKsZKzo,3661
22
- pycodex/prompts/permissions/approval_policy/on_request_rule_request_permission.md,sha256=mOinishp1k-wlPsaEuIOMn5GoVm_dAIsWIuEMmv2r7o,1725
23
- pycodex/prompts/permissions/approval_policy/unless_trusted.md,sha256=XHpi1Lfx1iIXFbbQ_ho_kGstA3JN-RLho291HM30UNw,247
24
- pycodex/prompts/permissions/sandbox_mode/danger_full_access.md,sha256=nZ7YHacBd3cAHKRZc9XClOOOnXJPXPh0WFBueh5C2D0,197
25
- pycodex/prompts/permissions/sandbox_mode/read_only.md,sha256=2rAPEXsBYCcuttI5j3euS-3uv_v97catIsnhxlSQSIM,173
26
- pycodex/prompts/permissions/sandbox_mode/workspace_write.md,sha256=lVN-LwrBbHqlv5yVjcd_mU8tzZW8jfKpTatJKIZu9HI,277
27
- pycodex/tools/__init__.py,sha256=aSLXrr_31KGQgDfRow5zVIc-2-KdXlHaCE6qUnE4HWI,1772
28
- pycodex/tools/agent_tool_schemas.py,sha256=adzoo0L6jCM7rLF-O1mNrq85HENQ_oKakjzwP6id1Yk,2069
29
- pycodex/tools/apply_patch_tool.py,sha256=8hHxoWxWovAYdhr0XzDCZwljtMlApp7-TMZtyxe3adY,13691
30
- pycodex/tools/base_tool.py,sha256=34NaExjTCyDn333MzlU4ShQ9WHocW3WREfg9ifdAqY4,5299
31
- pycodex/tools/close_agent_tool.py,sha256=InKhe2gFWOcqE187J3XYrCckecsyAR48VeVmGdYhKWE,1623
32
- pycodex/tools/code_mode_manager.py,sha256=pEczPyCq-3DpJlTtfUEpl4JAGolz8cOpI8mBc7gdrn0,18603
33
- pycodex/tools/exec_command_tool.py,sha256=_fWfkQLGeINb2-cniY9CWskkAPjC9hE8pfjcBKkWXAg,3459
34
- pycodex/tools/exec_runtime.js,sha256=ZczdhrzpSZ-qNnJDDJOe8Ap86HpzHb2FZ_vSpHszgLs,3625
35
- pycodex/tools/exec_tool.py,sha256=xJfEpcQXpL3OX-ZzKxQ2sI781OuEqpeyPvVkkwhgZ1c,1415
36
- pycodex/tools/grep_files_tool.py,sha256=twsx1KsvOWh8mi-lbycAtEyh6PeLxtNzl9LzdjwgAf4,4742
37
- pycodex/tools/list_dir_tool.py,sha256=7S0RsE-NL04G47FmFZtzo-N-O3fPCYQFF0HrjEVuv3U,4749
38
- pycodex/tools/read_file_tool.py,sha256=GVamhSNEZ1F1IU_og9GgSCzV12TL5t5b1fOUlzTOQBQ,8084
39
- pycodex/tools/request_permissions_tool.py,sha256=GzYG-mc1ifTiIM8xK8WD-vPGUKpYgMX9zyqq9O6K-EE,3036
40
- pycodex/tools/request_user_input_tool.py,sha256=hVqCYGPLA29uxBblIjUIoIrzXVg5KZ8PcxJ84obgNro,5715
41
- pycodex/tools/resume_agent_tool.py,sha256=vF-vLtx90bOuSjLFvn9vgqrKiznIbwpmZ3HVJlCP1LE,1640
42
- pycodex/tools/send_input_tool.py,sha256=z9PR5VoFd9SF4A-ol04Op8AXQF_3YLE74C6coiTXsZ0,3546
43
- pycodex/tools/shell_command_tool.py,sha256=Bbah_5HirG1BJOIiqzuMa8kNHNYVPCUvxCFa09eRU6A,3500
44
- pycodex/tools/shell_tool.py,sha256=BWSaEJZwfQg9Ta-ld2wqeXqavrZC7Y8qgF_vBEOxfYA,3678
45
- pycodex/tools/spawn_agent_tool.py,sha256=LfJlGI0Ecp9HWNLlTubyybFq-xeRNChILq9ozT7piA8,3556
46
- pycodex/tools/unified_exec_manager.py,sha256=ZEaMXmO83Iu20V4dwxAuUjy4EF5IHqHmwnTvFJh8zGc,13330
47
- pycodex/tools/update_plan_tool.py,sha256=l_EG39bEw5K9BIUKoSUsXYDb0W7aLn8SviKSb-bs7Os,2887
48
- pycodex/tools/view_image_tool.py,sha256=yB915Jd3he4RjPANdm-dYdvio24OXKhBkAsp-9WVPBg,3924
49
- pycodex/tools/wait_agent_tool.py,sha256=1tJ5spBtpZ_MjoMv5xmZz5WWKl7UwMqHIJ3SYKXEPZw,2596
50
- pycodex/tools/wait_tool.py,sha256=G4YhaYeWAvUedzxTDAxbczVmXXUp7H2OKWO3qZlEyyk,2324
51
- pycodex/tools/web_search_tool.py,sha256=hq78XF6MRvmNyPFSIp5eI0eYn9ryKdKvvoIOFNU3tuY,987
52
- pycodex/tools/write_stdin_tool.py,sha256=DghlwPJnAqDoRBYyh1zeXRsfTXoQUdLJ8JQfrdE4RLs,2542
53
- pycodex/utils/__init__.py,sha256=Hj_0a7RhkAblWkaHyFhpi0cs2nSjJ1NdavbkBgEHieY,1024
54
- pycodex/utils/dotenv.py,sha256=sOpu6PA1VrsPZK13ynh3nZg3-u9pdiCXkW648v3pwZQ,1789
55
- pycodex/utils/get_env.py,sha256=Ehh0mVPhkDlPMd1WXhrz1UqjPCePg8YfZH7zrtu1EOQ,6894
56
- pycodex/utils/random_ids.py,sha256=vOEVgkwKeQXaHoEVU7IfsPPjKUABkGIeQ7lu9MZctU8,413
57
- pycodex/utils/visualize.py,sha256=fK79pTfOwMmRrQujAosGt0nGyyJjpz0GfpWY8BkK91c,35369
58
- responses_server/__init__.py,sha256=3yPv_zeGT7P11tTnmj5kXktISLNsNW-02MUnnbiZcb0,394
59
- responses_server/__main__.py,sha256=9SRp-Yw7ShGxc6DhSIXcDLKgGEdAVm3oBZ59rBOPjT0,62
60
- responses_server/app.py,sha256=VJSceVaXxbPLu9KGafLIt5fiGvxrqVTkWeOg81O5-FQ,7016
61
- responses_server/config.py,sha256=XAJmvvLiCYN5jCUcP_6uZyoW79OzxigMbik8X-ZTdKE,2174
62
- responses_server/payload_processors.py,sha256=_3Sl7HLG00BgN_TKcvT3_3drCDAq1MAeK1HxbRXNta4,3019
63
- responses_server/server.py,sha256=Q-gjtHzb7K1Guex10G38PgH9hxqJgdzYnBV7Ycy9L7Y,2049
64
- responses_server/session_store.py,sha256=oP3aFHsGmEMoXuUcxNh6B4vzp6KwaeRdLzM-3AOwM98,1078
65
- responses_server/stream_router.py,sha256=uYPjrlBUnNqiuQQ91eKmwDfNF6e5NYDtf5C8BdPRPRc,29536
66
- responses_server/tools/__init__.py,sha256=ivsBSEy0SBUhY-Uea5v1XMLXShkwHdCVl0id-1FwdZg,150
67
- responses_server/tools/custom_adapter.py,sha256=ivROeI8D9B1saS7skGLXnwF7fbsjAmEVSbeMceYno4E,8238
68
- responses_server/tools/web_search.py,sha256=HR9E5uMxWU07khsaIO9zvdg1GCCrWNy73263zfMaxsw,8565
69
- python_codex-0.1.2.dist-info/METADATA,sha256=wy8bEToZxyf9Cio-upoAS8XmC3MscN8wiKTVXp9MW9g,13969
70
- python_codex-0.1.2.dist-info/WHEEL,sha256=QccIxa26bgl1E6uMy58deGWi-0aeIkkangHcxk2kWfw,87
71
- python_codex-0.1.2.dist-info/entry_points.txt,sha256=sNUVakoVuTrzJH505ZgRTQxmtRRPUHV_EH0i6EbYTyM,45
72
- python_codex-0.1.2.dist-info/licenses/LICENSE,sha256=0X8ifk312hYAORM4hlzg8wVSEXYKNmiPgWlB1YIy2Nw,10926
73
- python_codex-0.1.2.dist-info/RECORD,,