python-codex 0.2.6__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 +18 -14
- pycodex/agent.py +468 -462
- pycodex/bootstrap.py +417 -0
- pycodex/cli.py +236 -436
- 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 +329 -252
- pycodex/model_metadata.py +19 -7
- pycodex/portable.py +90 -52
- pycodex/portable_server.py +32 -24
- pycodex/prompts/models.json +235 -803
- pycodex/protocol.py +177 -137
- pycodex/runtime.py +579 -174
- pycodex/runtime_services.py +204 -157
- pycodex/tools/__init__.py +4 -1
- pycodex/tools/apply_patch_tool.py +69 -48
- pycodex/tools/base_tool.py +89 -42
- pycodex/tools/clock_tool.py +201 -0
- 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 +13 -13
- 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 +50 -66
- 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/utils/image_utils.py +76 -0
- pycodex/utils/random_ids.py +1 -2
- pycodex/utils/session_persist.py +263 -161
- 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 +25 -22
- responses_server/messages_api.py +96 -49
- responses_server/payload_processors.py +25 -19
- responses_server/server.py +11 -11
- responses_server/session_store.py +14 -11
- responses_server/stream_router.py +196 -107
- responses_server/tools/custom_adapter.py +17 -16
- responses_server/tools/web_search.py +39 -36
- responses_server/trajectory_dump.py +51 -13
- workspace_server/__main__.py +0 -1
- workspace_server/app.py +470 -384
- workspace_server/workspace.html +859 -232
- workspace_server/workspaces.html +94 -95
- workspace_server/workspaces.py +168 -100
- 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 -553
- python_codex-0.2.6.dist-info/METADATA +0 -441
- python_codex-0.2.6.dist-info/RECORD +0 -91
- {python_codex-0.2.6.dist-info → python_codex-0.3.0.dist-info}/WHEEL +0 -0
- {python_codex-0.2.6.dist-info → python_codex-0.3.0.dist-info}/entry_points.txt +0 -0
- {python_codex-0.2.6.dist-info → python_codex-0.3.0.dist-info}/licenses/LICENSE +0 -0
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
"""Image preparation helpers for the Python Codex prototype.
|
|
2
|
+
|
|
3
|
+
Original Codex mapping:
|
|
4
|
+
- Corresponds to `codex-rs/utils/image/src/lib.rs`.
|
|
5
|
+
|
|
6
|
+
Expected behavior:
|
|
7
|
+
- Resize images down to `MAX_DIMENSION` on the longest side before they are
|
|
8
|
+
attached to a model request, matching upstream `PromptImageMode::ResizeToFit`.
|
|
9
|
+
- Keep the original bytes when the caller asks for `original` detail or the
|
|
10
|
+
image already fits.
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
import base64
|
|
14
|
+
import io
|
|
15
|
+
import mimetypes
|
|
16
|
+
import typing
|
|
17
|
+
from pathlib import Path
|
|
18
|
+
|
|
19
|
+
from PIL import Image
|
|
20
|
+
|
|
21
|
+
MAX_DIMENSION = 2048
|
|
22
|
+
|
|
23
|
+
_PRESERVABLE_MIME_TYPES = ("image/png", "image/jpeg", "image/webp")
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
class ImageProcessingError(RuntimeError):
|
|
27
|
+
pass
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def load_image_data_url(
|
|
31
|
+
path: "Path",
|
|
32
|
+
resize_to_fit: "bool" = True,
|
|
33
|
+
) -> "str":
|
|
34
|
+
mime_type, _ = mimetypes.guess_type(path.name)
|
|
35
|
+
if not mime_type or not mime_type.startswith("image/"):
|
|
36
|
+
raise ImageProcessingError(
|
|
37
|
+
"`{0}` does not look like an image file".format(path)
|
|
38
|
+
)
|
|
39
|
+
|
|
40
|
+
image_bytes = path.read_bytes()
|
|
41
|
+
if resize_to_fit:
|
|
42
|
+
mime_type, image_bytes = _resize_to_fit(mime_type, image_bytes)
|
|
43
|
+
encoded = base64.b64encode(image_bytes).decode("ascii")
|
|
44
|
+
return "data:{0};base64,{1}".format(mime_type, encoded)
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def _resize_to_fit(
|
|
48
|
+
mime_type: "str",
|
|
49
|
+
image_bytes: "bytes",
|
|
50
|
+
) -> "typing.Tuple[str, bytes]":
|
|
51
|
+
with Image.open(io.BytesIO(image_bytes)) as image:
|
|
52
|
+
width, height = image.size
|
|
53
|
+
if width <= MAX_DIMENSION and height <= MAX_DIMENSION:
|
|
54
|
+
return mime_type, image_bytes
|
|
55
|
+
|
|
56
|
+
scale = float(MAX_DIMENSION) / float(max(width, height))
|
|
57
|
+
target_size = (
|
|
58
|
+
max(1, int(width * scale)),
|
|
59
|
+
max(1, int(height * scale)),
|
|
60
|
+
)
|
|
61
|
+
resized = image.resize(target_size, Image.BILINEAR)
|
|
62
|
+
target_mime = mime_type if mime_type in _PRESERVABLE_MIME_TYPES else "image/png"
|
|
63
|
+
if target_mime == "image/jpeg":
|
|
64
|
+
resized = resized.convert("RGB")
|
|
65
|
+
save_format, save_kwargs = "JPEG", {"quality": 85}
|
|
66
|
+
elif target_mime == "image/webp":
|
|
67
|
+
resized = resized.convert("RGBA")
|
|
68
|
+
save_format, save_kwargs = "WEBP", {"lossless": True}
|
|
69
|
+
else:
|
|
70
|
+
resized = resized.convert("RGBA")
|
|
71
|
+
save_format, save_kwargs = "PNG", {}
|
|
72
|
+
|
|
73
|
+
buffer = io.BytesIO()
|
|
74
|
+
resized.save(buffer, format=save_format, **save_kwargs)
|
|
75
|
+
|
|
76
|
+
return target_mime, buffer.getvalue()
|
pycodex/utils/random_ids.py
CHANGED