python-codex 0.2.7__py3-none-any.whl → 0.3.0__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.
- pycodex/__init__.py +14 -14
- pycodex/agent.py +465 -499
- pycodex/bootstrap.py +417 -0
- pycodex/cli.py +236 -510
- pycodex/compat.py +19 -5
- pycodex/context.py +222 -212
- pycodex/doctor.py +52 -48
- pycodex/events.py +857 -0
- pycodex/feishu_card.py +217 -163
- pycodex/feishu_link.py +43 -83
- pycodex/model.py +324 -253
- pycodex/model_metadata.py +19 -7
- pycodex/portable.py +76 -45
- pycodex/portable_server.py +32 -24
- pycodex/prompts/models.json +245 -983
- pycodex/protocol.py +177 -137
- pycodex/runtime.py +579 -176
- pycodex/runtime_services.py +204 -157
- pycodex/tools/__init__.py +1 -1
- pycodex/tools/apply_patch_tool.py +69 -48
- pycodex/tools/base_tool.py +89 -42
- pycodex/tools/clock_tool.py +58 -25
- pycodex/tools/close_agent_tool.py +2 -2
- pycodex/tools/code_mode_manager.py +77 -64
- pycodex/tools/exec_command_tool.py +26 -11
- pycodex/tools/exec_tool.py +4 -4
- pycodex/tools/grep_files_tool.py +12 -10
- pycodex/tools/ipython_tool.py +10 -13
- pycodex/tools/list_dir_tool.py +13 -9
- pycodex/tools/read_file_tool.py +29 -17
- pycodex/tools/request_permissions_tool.py +15 -5
- pycodex/tools/request_user_input_tool.py +13 -104
- pycodex/tools/resume_agent_tool.py +2 -2
- pycodex/tools/send_input_tool.py +11 -8
- pycodex/tools/shell_command_tool.py +7 -5
- pycodex/tools/shell_tool.py +7 -5
- pycodex/tools/spawn_agent_tool.py +7 -4
- pycodex/tools/unified_exec_manager.py +102 -69
- pycodex/tools/update_plan_tool.py +8 -5
- pycodex/tools/view_image_tool.py +7 -5
- pycodex/tools/wait_agent_tool.py +27 -4
- pycodex/tools/wait_tool.py +5 -4
- pycodex/tools/web_search_tool.py +4 -2
- pycodex/tools/write_stdin_tool.py +12 -11
- pycodex/utils/__init__.py +2 -17
- pycodex/utils/compactor.py +41 -72
- pycodex/utils/debug.py +2 -2
- pycodex/utils/dotenv.py +6 -7
- pycodex/utils/event_helpers.py +190 -0
- pycodex/utils/get_env.py +27 -70
- pycodex/{image_utils.py → utils/image_utils.py} +8 -11
- pycodex/utils/random_ids.py +1 -2
- pycodex/utils/session_persist.py +217 -163
- pycodex/utils/truncation.py +21 -45
- python_codex-0.3.0.dist-info/METADATA +704 -0
- python_codex-0.3.0.dist-info/RECORD +90 -0
- responses_server/__init__.py +1 -5
- responses_server/__main__.py +0 -1
- responses_server/app.py +36 -31
- responses_server/config.py +23 -23
- responses_server/messages_api.py +51 -53
- responses_server/payload_processors.py +25 -20
- responses_server/server.py +11 -11
- responses_server/session_store.py +14 -11
- responses_server/stream_router.py +101 -98
- responses_server/tools/custom_adapter.py +17 -16
- responses_server/tools/web_search.py +39 -36
- responses_server/trajectory_dump.py +36 -14
- workspace_server/__main__.py +0 -1
- workspace_server/app.py +461 -375
- workspace_server/workspace.html +852 -228
- workspace_server/workspaces.html +94 -95
- workspace_server/workspaces.py +137 -79
- pycodex/collaboration.py +0 -20
- pycodex/interactive_session.py +0 -415
- pycodex/prompts/collaboration_default.md +0 -11
- pycodex/prompts/collaboration_plan.md +0 -128
- pycodex/utils/toolcall_visualize.py +0 -713
- pycodex/utils/visualize.py +0 -560
- python_codex-0.2.7.dist-info/METADATA +0 -455
- python_codex-0.2.7.dist-info/RECORD +0 -93
- {python_codex-0.2.7.dist-info → python_codex-0.3.0.dist-info}/WHEEL +0 -0
- {python_codex-0.2.7.dist-info → python_codex-0.3.0.dist-info}/entry_points.txt +0 -0
- {python_codex-0.2.7.dist-info → python_codex-0.3.0.dist-info}/licenses/LICENSE +0 -0
pycodex/utils/truncation.py
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
"""Shared truncation helpers for model-visible tool output."""
|
|
2
2
|
|
|
3
3
|
import math
|
|
4
|
+
import typing
|
|
5
|
+
from dataclasses import replace
|
|
4
6
|
|
|
5
7
|
from ..protocol import JSONValue, ToolResult
|
|
6
|
-
import typing
|
|
7
8
|
|
|
8
9
|
DEFAULT_MAX_OUTPUT_TOKENS = 10_000
|
|
9
10
|
TRUNCATION_SERIALIZATION_BUDGET_MULTIPLIER = 1.2
|
|
@@ -13,7 +14,7 @@ HISTORY_TOOL_OUTPUT_TOKENS = int(
|
|
|
13
14
|
APPROX_BYTES_PER_TOKEN = 4
|
|
14
15
|
|
|
15
16
|
|
|
16
|
-
def approx_token_count(text:
|
|
17
|
+
def approx_token_count(text: "str") -> "int":
|
|
17
18
|
"""Estimate token count using the upstream Codex 4-bytes-per-token rule."""
|
|
18
19
|
if not text:
|
|
19
20
|
return 0
|
|
@@ -24,7 +25,7 @@ def approx_token_count(text: 'str') -> 'int':
|
|
|
24
25
|
)
|
|
25
26
|
|
|
26
27
|
|
|
27
|
-
def formatted_truncate_text(text:
|
|
28
|
+
def formatted_truncate_text(text: "str", max_tokens: "int") -> "str":
|
|
28
29
|
"""Format a direct tool response with line count plus middle truncation."""
|
|
29
30
|
byte_budget = _approx_bytes_for_tokens(max_tokens)
|
|
30
31
|
if len(text.encode("utf-8")) <= byte_budget:
|
|
@@ -35,8 +36,8 @@ def formatted_truncate_text(text: 'str', max_tokens: 'int') -> 'str':
|
|
|
35
36
|
|
|
36
37
|
|
|
37
38
|
def truncate_tool_result_for_history(
|
|
38
|
-
result:
|
|
39
|
-
) ->
|
|
39
|
+
result: "ToolResult",
|
|
40
|
+
) -> "ToolResult":
|
|
40
41
|
"""Truncate model-visible ToolResult content before storing it in history."""
|
|
41
42
|
if result.content_items is not None:
|
|
42
43
|
truncated_content_items = _truncate_content_items(
|
|
@@ -45,41 +46,16 @@ def truncate_tool_result_for_history(
|
|
|
45
46
|
)
|
|
46
47
|
if truncated_content_items == result.content_items:
|
|
47
48
|
return result
|
|
48
|
-
return
|
|
49
|
-
call_id=result.call_id,
|
|
50
|
-
name=result.name,
|
|
51
|
-
output=result.output,
|
|
52
|
-
content_items=truncated_content_items,
|
|
53
|
-
success=result.success,
|
|
54
|
-
is_error=result.is_error,
|
|
55
|
-
tool_type=result.tool_type,
|
|
56
|
-
)
|
|
49
|
+
return replace(result, content_items=truncated_content_items)
|
|
57
50
|
|
|
58
51
|
output_text = _tool_output_text(result.output)
|
|
59
52
|
truncated_output = _truncate_text(output_text, HISTORY_TOOL_OUTPUT_TOKENS)
|
|
60
53
|
if truncated_output == output_text:
|
|
61
54
|
return result
|
|
62
|
-
return
|
|
63
|
-
call_id=result.call_id,
|
|
64
|
-
name=result.name,
|
|
65
|
-
output=truncated_output,
|
|
66
|
-
success=result.success,
|
|
67
|
-
is_error=result.is_error,
|
|
68
|
-
tool_type=result.tool_type,
|
|
69
|
-
)
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
def truncate_tool_results_for_history(
|
|
73
|
-
results: 'typing.Iterable[ToolResult]',
|
|
74
|
-
) -> 'typing.List[ToolResult]':
|
|
75
|
-
"""Apply history-layer truncation to a batch of completed tool results."""
|
|
76
|
-
return [
|
|
77
|
-
truncate_tool_result_for_history(result)
|
|
78
|
-
for result in results
|
|
79
|
-
]
|
|
55
|
+
return replace(result, output=truncated_output)
|
|
80
56
|
|
|
81
57
|
|
|
82
|
-
def _tool_output_text(output:
|
|
58
|
+
def _tool_output_text(output: "JSONValue") -> "str":
|
|
83
59
|
if isinstance(output, str):
|
|
84
60
|
return output
|
|
85
61
|
|
|
@@ -93,10 +69,10 @@ def _tool_output_text(output: 'JSONValue') -> 'str':
|
|
|
93
69
|
|
|
94
70
|
|
|
95
71
|
def _truncate_content_items(
|
|
96
|
-
content_items:
|
|
97
|
-
token_limit:
|
|
98
|
-
) ->
|
|
99
|
-
output:
|
|
72
|
+
content_items: "typing.Tuple[typing.Dict[str, typing.Any], ...]",
|
|
73
|
+
token_limit: "int",
|
|
74
|
+
) -> "typing.Tuple[typing.Dict[str, typing.Any], ...]":
|
|
75
|
+
output: "typing.List[typing.Dict[str, typing.Any]]" = []
|
|
100
76
|
remaining_budget = token_limit
|
|
101
77
|
omitted_text_items = 0
|
|
102
78
|
|
|
@@ -135,26 +111,26 @@ def _truncate_content_items(
|
|
|
135
111
|
return tuple(output)
|
|
136
112
|
|
|
137
113
|
|
|
138
|
-
def _approx_tokens_from_byte_count(byte_count:
|
|
114
|
+
def _approx_tokens_from_byte_count(byte_count: "int") -> "int":
|
|
139
115
|
if byte_count <= 0:
|
|
140
116
|
return 0
|
|
141
117
|
return (byte_count + APPROX_BYTES_PER_TOKEN - 1) // APPROX_BYTES_PER_TOKEN
|
|
142
118
|
|
|
143
119
|
|
|
144
|
-
def _approx_bytes_for_tokens(token_count:
|
|
120
|
+
def _approx_bytes_for_tokens(token_count: "int") -> "int":
|
|
145
121
|
return max(token_count, 0) * APPROX_BYTES_PER_TOKEN
|
|
146
122
|
|
|
147
123
|
|
|
148
|
-
def _split_budget(byte_budget:
|
|
124
|
+
def _split_budget(byte_budget: "int") -> "typing.Tuple[int, int]":
|
|
149
125
|
left_budget = byte_budget // 2
|
|
150
126
|
return left_budget, byte_budget - left_budget
|
|
151
127
|
|
|
152
128
|
|
|
153
129
|
def _split_string(
|
|
154
|
-
text:
|
|
155
|
-
beginning_bytes:
|
|
156
|
-
end_bytes:
|
|
157
|
-
) ->
|
|
130
|
+
text: "str",
|
|
131
|
+
beginning_bytes: "int",
|
|
132
|
+
end_bytes: "int",
|
|
133
|
+
) -> "typing.Tuple[str, str]":
|
|
158
134
|
if not text:
|
|
159
135
|
return "", ""
|
|
160
136
|
|
|
@@ -187,7 +163,7 @@ def _split_string(
|
|
|
187
163
|
return text[:prefix_end], text[suffix_start:]
|
|
188
164
|
|
|
189
165
|
|
|
190
|
-
def _truncate_text(text:
|
|
166
|
+
def _truncate_text(text: "str", max_tokens: "int") -> "str":
|
|
191
167
|
if not text:
|
|
192
168
|
return ""
|
|
193
169
|
|