python-codex 0.1.1__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 (59) hide show
  1. pycodex/__init__.py +5 -1
  2. pycodex/agent.py +39 -41
  3. pycodex/cli.py +51 -43
  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 +72 -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 +3 -5
  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 +79 -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 +57 -34
  41. pycodex/utils/random_ids.py +1 -2
  42. pycodex/utils/visualize.py +79 -79
  43. {python_codex-0.1.1.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.1.dist-info → python_codex-0.1.3.dist-info}/WHEEL +1 -1
  46. responses_server/__init__.py +17 -0
  47. responses_server/__main__.py +5 -0
  48. responses_server/app.py +227 -0
  49. responses_server/config.py +63 -0
  50. responses_server/payload_processors.py +86 -0
  51. responses_server/server.py +63 -0
  52. responses_server/session_store.py +37 -0
  53. responses_server/stream_router.py +784 -0
  54. responses_server/tools/__init__.py +4 -0
  55. responses_server/tools/custom_adapter.py +235 -0
  56. responses_server/tools/web_search.py +263 -0
  57. python_codex-0.1.1.dist-info/RECORD +0 -62
  58. {python_codex-0.1.1.dist-info → python_codex-0.1.3.dist-info}/entry_points.txt +0 -0
  59. {python_codex-0.1.1.dist-info → python_codex-0.1.3.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,4 @@
1
+ from .custom_adapter import collect_custom_tool_names
2
+ from .web_search import WebSearchTool
3
+
4
+ __all__ = ["WebSearchTool", "collect_custom_tool_names"]
@@ -0,0 +1,235 @@
1
+
2
+ from copy import deepcopy
3
+ import json
4
+ import typing
5
+
6
+
7
+ class CustomToolAdapterError(ValueError):
8
+ pass
9
+
10
+
11
+ # Mirrors the chat-completions apply_patch function tool text from
12
+ # `codex-rs/core/src/tools/handlers/apply_patch.rs`.
13
+ APPLY_PATCH_NAME = "apply_patch"
14
+ APPLY_PATCH_CHAT_INPUT_DESCRIPTION = "The entire contents of the apply_patch command"
15
+ APPLY_PATCH_CHAT_DESCRIPTION = """Use the `apply_patch` tool to edit files.
16
+ Your patch language is a stripped-down, file-oriented diff format designed to be easy to parse and safe to apply. You can think of it as a high-level envelope:
17
+
18
+ *** Begin Patch
19
+ [ one or more file sections ]
20
+ *** End Patch
21
+
22
+ Within that envelope, you get a sequence of file operations.
23
+ You MUST include a header to specify the action you are taking.
24
+ Each operation starts with one of three headers:
25
+
26
+ *** Add File: <path> - create a new file. Every following line is a + line (the initial contents).
27
+ *** Delete File: <path> - remove an existing file. Nothing follows.
28
+ *** Update File: <path> - patch an existing file in place (optionally with a rename).
29
+
30
+ May be immediately followed by *** Move to: <new path> if you want to rename the file.
31
+ Then one or more "hunks", each introduced by @@ (optionally followed by a hunk header).
32
+ Within a hunk each line starts with:
33
+
34
+ For instructions on [context_before] and [context_after]:
35
+ - By default, show 3 lines of code immediately above and 3 lines immediately below each change. If a change is within 3 lines of a previous change, do NOT duplicate the first change's [context_after] lines in the second change's [context_before] lines.
36
+ - If 3 lines of context is insufficient to uniquely identify the snippet of code within the file, use the @@ operator to indicate the class or function to which the snippet belongs. For instance, we might have:
37
+ @@ class BaseClass
38
+ [3 lines of pre-context]
39
+ - [old_code]
40
+ + [new_code]
41
+ [3 lines of post-context]
42
+
43
+ - If a code block is repeated so many times in a class or function such that even a single `@@` statement and 3 lines of context cannot uniquely identify the snippet of code, you can use multiple `@@` statements to jump to the right context. For instance:
44
+
45
+ @@ class BaseClass
46
+ @@ \t def method():
47
+ [3 lines of pre-context]
48
+ - [old_code]
49
+ + [new_code]
50
+ [3 lines of post-context]
51
+
52
+ The full grammar definition is below:
53
+ Patch := Begin { FileOp } End
54
+ Begin := "*** Begin Patch" NEWLINE
55
+ End := "*** End Patch" NEWLINE
56
+ FileOp := AddFile | DeleteFile | UpdateFile
57
+ AddFile := "*** Add File: " path NEWLINE { "+" line NEWLINE }
58
+ DeleteFile := "*** Delete File: " path NEWLINE
59
+ UpdateFile := "*** Update File: " path NEWLINE [ MoveTo ] { Hunk }
60
+ MoveTo := "*** Move to: " newPath NEWLINE
61
+ Hunk := "@@" [ header ] NEWLINE { HunkLine } [ "*** End of File" NEWLINE ]
62
+ HunkLine := (" " | "-" | "+") text NEWLINE
63
+
64
+ A full patch can combine several operations:
65
+
66
+ *** Begin Patch
67
+ *** Add File: hello.txt
68
+ +Hello world
69
+ *** Update File: src/app.py
70
+ *** Move to: src/main.py
71
+ @@ def greet():
72
+ -print("Hi")
73
+ +print("Hello, world!")
74
+ *** Delete File: obsolete.txt
75
+ *** End Patch
76
+
77
+ It is important to remember:
78
+
79
+ - You must include a header with your intended action (Add/Delete/Update)
80
+ - You must prefix new lines with `+` even when creating a new file
81
+ - File references can only be relative, NEVER ABSOLUTE.
82
+ """
83
+
84
+
85
+ def collect_custom_tool_names(raw_tools: 'object') -> 'typing.Set[str]':
86
+ names: 'typing.Set[str]' = set()
87
+ if not isinstance(raw_tools, list):
88
+ return names
89
+ for raw_tool in raw_tools:
90
+ if not isinstance(raw_tool, dict) or raw_tool.get("type") != "custom":
91
+ continue
92
+ name = _tool_name(raw_tool)
93
+ if name:
94
+ names.add(name)
95
+ return names
96
+
97
+
98
+ def build_tool_definition(raw_tool: 'typing.Dict[str, object]') -> 'typing.Dict[str, object]':
99
+ name = _required_tool_name(raw_tool)
100
+ description = _build_description(raw_tool)
101
+ input_description = (
102
+ APPLY_PATCH_CHAT_INPUT_DESCRIPTION
103
+ if name == APPLY_PATCH_NAME
104
+ else "Raw tool input. Pass the freeform payload verbatim as a single string."
105
+ )
106
+ return {
107
+ "type": "function",
108
+ "name": name,
109
+ "function": {
110
+ "name": name,
111
+ "description": description,
112
+ "parameters": {
113
+ "type": "object",
114
+ "properties": {
115
+ "input": {
116
+ "type": "string",
117
+ "description": input_description,
118
+ }
119
+ },
120
+ "required": ["input"],
121
+ "additionalProperties": False,
122
+ },
123
+ "strict": False,
124
+ },
125
+ }
126
+
127
+
128
+ def build_tool_call(raw_item: 'typing.Dict[str, object]') -> 'typing.Dict[str, object]':
129
+ name = _required_item_name(raw_item)
130
+ return {
131
+ "id": str(raw_item.get("call_id", "")).strip() or name,
132
+ "type": "function",
133
+ "function": {
134
+ "name": name,
135
+ "arguments": json.dumps(
136
+ {"input": str(raw_item.get("input", "") or "")},
137
+ ensure_ascii=False,
138
+ separators=(",", ":"),
139
+ ),
140
+ },
141
+ }
142
+
143
+
144
+ def build_output_item(tool_call: 'typing.Dict[str, object]', index: 'int') -> 'typing.Dict[str, object]':
145
+ function = tool_call.get("function") or {}
146
+ if not isinstance(function, dict):
147
+ raise CustomToolAdapterError(
148
+ "outcomming custom tool call is missing function payload"
149
+ )
150
+ name = str(function.get("name", "")).strip()
151
+ if not name:
152
+ raise CustomToolAdapterError(
153
+ "outcomming custom tool call is missing `name`"
154
+ )
155
+ return {
156
+ "type": "custom_tool_call",
157
+ "call_id": str(tool_call.get("id", "")).strip() or f"call_{index}",
158
+ "name": name,
159
+ "input": extract_input_text(function.get("arguments")),
160
+ }
161
+
162
+
163
+ def extract_input_text(raw_arguments: 'object') -> 'str':
164
+ if isinstance(raw_arguments, dict):
165
+ parsed = deepcopy(raw_arguments)
166
+ else:
167
+ parsed = None
168
+
169
+ raw_text = raw_arguments if isinstance(raw_arguments, str) else None
170
+ if parsed is None and raw_text is not None:
171
+ try:
172
+ parsed = json.loads(raw_text or "{}")
173
+ except json.JSONDecodeError:
174
+ return raw_text
175
+
176
+ if isinstance(parsed, dict) and "input" in parsed:
177
+ value = parsed.get("input")
178
+ if isinstance(value, str):
179
+ return value
180
+ return json.dumps(value, ensure_ascii=False)
181
+
182
+ if raw_text is not None:
183
+ return raw_text
184
+ if parsed is not None:
185
+ return json.dumps(parsed, ensure_ascii=False)
186
+ return str(raw_arguments or "")
187
+
188
+
189
+ def _build_description(raw_tool: 'typing.Dict[str, object]') -> 'str':
190
+ name = _tool_name(raw_tool)
191
+ if name == APPLY_PATCH_NAME:
192
+ return APPLY_PATCH_CHAT_DESCRIPTION
193
+
194
+ description = str(raw_tool.get("description", "") or "").strip()
195
+ parts = [description] if description else []
196
+ parts.append(
197
+ "Chat-completions compatibility: provide the raw tool payload in the "
198
+ "`input` string field."
199
+ )
200
+
201
+ raw_format = raw_tool.get("format")
202
+ if isinstance(raw_format, dict):
203
+ format_lines: 'typing.List[str]' = []
204
+ format_type = str(raw_format.get("type", "")).strip()
205
+ syntax = str(raw_format.get("syntax", "")).strip()
206
+ definition = str(raw_format.get("definition", "") or "").strip()
207
+ if format_type:
208
+ format_lines.append(f"Input format type: {format_type}")
209
+ if syntax:
210
+ format_lines.append(f"Input format syntax: {syntax}")
211
+ if definition:
212
+ format_lines.append("Input format definition:")
213
+ format_lines.append(definition)
214
+ if format_lines:
215
+ parts.append("\n".join(format_lines))
216
+
217
+ return "\n\n".join(parts)
218
+
219
+
220
+ def _tool_name(raw_tool: 'typing.Dict[str, object]') -> 'str':
221
+ return str(raw_tool.get("name", "")).strip()
222
+
223
+
224
+ def _required_tool_name(raw_tool: 'typing.Dict[str, object]') -> 'str':
225
+ name = _tool_name(raw_tool)
226
+ if not name:
227
+ raise CustomToolAdapterError("custom tool definition is missing `name`")
228
+ return name
229
+
230
+
231
+ def _required_item_name(raw_item: 'typing.Dict[str, object]') -> 'str':
232
+ name = str(raw_item.get("name", "")).strip()
233
+ if not name:
234
+ raise CustomToolAdapterError("custom tool call is missing `name`")
235
+ return name
@@ -0,0 +1,263 @@
1
+
2
+ from copy import deepcopy
3
+ import json
4
+
5
+ from pycodex.protocol import JSONValue
6
+ from pycodex.tools.base_tool import BaseTool, ToolContext
7
+ import typing
8
+
9
+
10
+ class WebSearchTool(BaseTool):
11
+ name = "web_search"
12
+ description = (
13
+ "Mock web search tool for Responses compatibility. Returns empty results."
14
+ )
15
+ input_schema = {
16
+ "type": "object",
17
+ "properties": {
18
+ "query": {
19
+ "type": "string",
20
+ "description": "Primary search query.",
21
+ },
22
+ "queries": {
23
+ "type": "array",
24
+ "description": "Optional batch of search queries.",
25
+ "items": {"type": "string"},
26
+ },
27
+ },
28
+ "required": ["query"],
29
+ }
30
+ supports_parallel = False
31
+
32
+ async def run(self, context: 'ToolContext', args: 'JSONValue') -> 'JSONValue':
33
+ del context
34
+ query, queries = extract_queries(args)
35
+ output_payload: 'typing.Dict[str, object]' = {
36
+ "results": [],
37
+ "mock": True,
38
+ }
39
+ if query:
40
+ output_payload["query"] = query
41
+ if queries:
42
+ output_payload["queries"] = queries
43
+ return output_payload
44
+
45
+
46
+ def build_tool_definition(tool: 'WebSearchTool') -> 'typing.Dict[str, object]':
47
+ return {
48
+ "type": "function",
49
+ "name": tool.name,
50
+ "function": {
51
+ "name": tool.name,
52
+ "description": tool.description,
53
+ "parameters": deepcopy(tool.input_schema),
54
+ "strict": False,
55
+ },
56
+ }
57
+
58
+
59
+ def partition_tool_calls(
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
+ mock_tool_names = _collect_mock_tool_names(tool, outcomming_request)
65
+ mock_calls: 'typing.List[typing.Dict[str, object]]' = []
66
+ ordinary_tool_calls: 'typing.Dict[int, typing.Dict[str, object]]' = {}
67
+ for index in sorted(tool_calls):
68
+ tool_call = tool_calls[index]
69
+ function = tool_call.get("function") or {}
70
+ tool_name = ""
71
+ if isinstance(function, dict):
72
+ tool_name = str(function.get("name", "")).strip()
73
+ if tool_name in mock_tool_names:
74
+ mock_calls.append(tool_call)
75
+ continue
76
+ ordinary_tool_calls[index] = tool_call
77
+ return mock_calls, ordinary_tool_calls
78
+
79
+
80
+ def hydrate_tool_call_names(
81
+ tool_calls: 'typing.Dict[int, typing.Dict[str, object]]',
82
+ outcomming_request: 'typing.Dict[str, object]',
83
+ ) -> 'None':
84
+ raw_tools = outcomming_request.get("tools") or []
85
+ if not isinstance(raw_tools, list):
86
+ return
87
+ for index, tool_call in tool_calls.items():
88
+ function = tool_call.get("function") or {}
89
+ if not isinstance(function, dict):
90
+ continue
91
+ if str(function.get("name", "")).strip():
92
+ continue
93
+ if index >= len(raw_tools):
94
+ continue
95
+ raw_tool = raw_tools[index]
96
+ if not isinstance(raw_tool, dict) or raw_tool.get("type") != "function":
97
+ continue
98
+ raw_function = raw_tool.get("function") or {}
99
+ if not isinstance(raw_function, dict):
100
+ continue
101
+ name = str(raw_function.get("name", "")).strip()
102
+ if name:
103
+ function["name"] = name
104
+
105
+
106
+ def build_output_items(
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
+ for tool_call in mock_search_calls:
111
+ function = tool_call.get("function") or {}
112
+ if not isinstance(function, dict):
113
+ continue
114
+ query, queries = extract_queries(function.get("arguments"))
115
+ action: 'typing.Dict[str, object]' = {"type": "search"}
116
+ if query:
117
+ action["query"] = query
118
+ if queries:
119
+ action["queries"] = queries
120
+ items.append(
121
+ {
122
+ "type": "web_search_call",
123
+ "id": str(tool_call.get("id", "")).strip() or "ws_mock",
124
+ "action": action,
125
+ }
126
+ )
127
+ return items
128
+
129
+
130
+ def build_followup_request(
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
+ followup_request = deepcopy(outcomming_request)
137
+ messages = followup_request.get("messages") or []
138
+ if not isinstance(messages, list):
139
+ raise ValueError("outcomming request messages must be a list")
140
+
141
+ assistant_tool_calls: 'typing.List[typing.Dict[str, object]]' = []
142
+ for tool_call in mock_search_calls:
143
+ function = tool_call.get("function") or {}
144
+ if not isinstance(function, dict):
145
+ continue
146
+ assistant_tool_calls.append(
147
+ {
148
+ "id": str(tool_call.get("id", "")).strip() or "ws_mock",
149
+ "type": "function",
150
+ "function": {
151
+ "name": str(function.get("name", "")).strip() or tool.name,
152
+ "arguments": str(function.get("arguments", "") or "{}"),
153
+ },
154
+ }
155
+ )
156
+ if assistant_tool_calls:
157
+ assistant_message: 'typing.Dict[str, object]' = {
158
+ "role": "assistant",
159
+ "tool_calls": assistant_tool_calls,
160
+ }
161
+ if reasoning_text:
162
+ assistant_message["reasoning"] = reasoning_text
163
+ messages.append(assistant_message)
164
+
165
+ for tool_call in mock_search_calls:
166
+ tool_output = _build_mock_output((tool_call.get("function") or {}).get("arguments"))
167
+ messages.append(
168
+ {
169
+ "role": "tool",
170
+ "tool_call_id": str(tool_call.get("id", "")).strip() or "ws_mock",
171
+ "content": json.dumps(tool_output, ensure_ascii=False),
172
+ }
173
+ )
174
+
175
+ followup_request["messages"] = messages
176
+ raw_tools = followup_request.get("tools") or []
177
+ if isinstance(raw_tools, list):
178
+ filtered_tools = [
179
+ raw_tool for raw_tool in raw_tools if not is_mock_tool(tool, raw_tool)
180
+ ]
181
+ if filtered_tools:
182
+ followup_request["tools"] = filtered_tools
183
+ else:
184
+ followup_request.pop("tools", None)
185
+ followup_request.pop("tool_choice", None)
186
+ followup_request.pop("parallel_tool_calls", None)
187
+ return followup_request
188
+
189
+
190
+ def extract_queries(raw_arguments: 'JSONValue') -> 'typing.Tuple[str, typing.List[str]]':
191
+ if isinstance(raw_arguments, dict):
192
+ parsed = raw_arguments
193
+ else:
194
+ parsed = None
195
+
196
+ if isinstance(raw_arguments, str):
197
+ raw_text = raw_arguments
198
+ else:
199
+ raw_text = str(raw_arguments or "")
200
+
201
+ if parsed is None:
202
+ try:
203
+ parsed = json.loads(raw_text or "{}")
204
+ except json.JSONDecodeError:
205
+ query = raw_text.strip()
206
+ return query, [query] if query else []
207
+
208
+ if not isinstance(parsed, dict):
209
+ query = raw_text.strip()
210
+ return query, [query] if query else []
211
+
212
+ query = str(parsed.get("query", "")).strip()
213
+ queries_value = parsed.get("queries") or []
214
+ queries: 'typing.List[str]' = []
215
+ if isinstance(queries_value, list):
216
+ for value in queries_value:
217
+ normalized = str(value).strip()
218
+ if normalized:
219
+ queries.append(normalized)
220
+ if not query and queries:
221
+ query = queries[0]
222
+ if query and query not in queries:
223
+ queries.insert(0, query)
224
+ return query, queries
225
+
226
+
227
+ def is_mock_tool(tool: 'WebSearchTool', raw_tool: 'object') -> 'bool':
228
+ if not isinstance(raw_tool, dict) or raw_tool.get("type") != "function":
229
+ return False
230
+ function = raw_tool.get("function") or {}
231
+ if not isinstance(function, dict):
232
+ return False
233
+ return (
234
+ str(function.get("name", "")).strip() == tool.name
235
+ and str(function.get("description", "")).strip() == tool.description
236
+ )
237
+
238
+
239
+ def _collect_mock_tool_names(
240
+ tool: 'WebSearchTool',
241
+ outcomming_request: 'typing.Dict[str, object]',
242
+ ) -> 'typing.Set[str]':
243
+ names: 'typing.Set[str]' = set()
244
+ raw_tools = outcomming_request.get("tools") or []
245
+ if not isinstance(raw_tools, list):
246
+ return names
247
+ for raw_tool in raw_tools:
248
+ if is_mock_tool(tool, raw_tool):
249
+ names.add(tool.name)
250
+ return names
251
+
252
+
253
+ def _build_mock_output(raw_arguments: 'JSONValue') -> 'typing.Dict[str, object]':
254
+ query, queries = extract_queries(raw_arguments)
255
+ output_payload: 'typing.Dict[str, object]' = {
256
+ "results": [],
257
+ "mock": True,
258
+ }
259
+ if query:
260
+ output_payload["query"] = query
261
+ if queries:
262
+ output_payload["queries"] = queries
263
+ return output_payload
@@ -1,62 +0,0 @@
1
- pycodex/__init__.py,sha256=T11JU1QHEk81TchhrTAOqVkvUUiQGlesk9PNaivjPrU,3052
2
- pycodex/agent.py,sha256=ApIneWSqDxryf9hdmTRFL65AH4e-sn0MWuuR80951Ec,10069
3
- pycodex/cli.py,sha256=JKHedrIgFaQgAc9h3P1MHvJTvUjL5dv7gxgHh-LCsDs,24520
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=IIpv96YuxdWX2D1yu-HmtCx3Og-fYDPrA29vgAlyvJE,12331
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=b3_HSlyA0qB9rJulSckLBXOcKS3Lw5xvsQXU-wpNpCs,1414
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=dyuGfaljXTuV4_Bf5Y6OwFGj5_Kb1LW-sh9ni5mMF1Y,12602
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=3l_KA8JCWW9mrKE9FiV2mTx10-e5MUbxaU8jbn3JaRs,6265
56
- pycodex/utils/random_ids.py,sha256=vOEVgkwKeQXaHoEVU7IfsPPjKUABkGIeQ7lu9MZctU8,413
57
- pycodex/utils/visualize.py,sha256=fK79pTfOwMmRrQujAosGt0nGyyJjpz0GfpWY8BkK91c,35369
58
- python_codex-0.1.1.dist-info/METADATA,sha256=3w9Sv_prpkT9BQ7zYh4NUCDV3eVlcoaq2Pv6yAkacOc,13969
59
- python_codex-0.1.1.dist-info/WHEEL,sha256=QccIxa26bgl1E6uMy58deGWi-0aeIkkangHcxk2kWfw,87
60
- python_codex-0.1.1.dist-info/entry_points.txt,sha256=sNUVakoVuTrzJH505ZgRTQxmtRRPUHV_EH0i6EbYTyM,45
61
- python_codex-0.1.1.dist-info/licenses/LICENSE,sha256=0X8ifk312hYAORM4hlzg8wVSEXYKNmiPgWlB1YIy2Nw,10926
62
- python_codex-0.1.1.dist-info/RECORD,,