python-codex 0.4.0__py3-none-any.whl → 0.4.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.
pycodex/runtime.py CHANGED
@@ -307,7 +307,7 @@ class AgentRuntime:
307
307
  if not self.agent.history:
308
308
  return {"kind": "compact_empty"}
309
309
  result = await self.agent.compact()
310
- self.publish_state("history")
310
+ self.publish_state("compacted")
311
311
  return {
312
312
  "kind": "compacted",
313
313
  "original_item_count": result.original_item_count,
@@ -5,10 +5,9 @@ import inspect
5
5
  def run_async(awaitable):
6
6
  """Run an awaitable from synchronous code and return its real result.
7
7
 
8
- This helper is intended for sync call sites (for example, IPython cells)
9
- that need to call async agent APIs without managing the event loop
10
- themselves. It returns the underlying result directly and raises on
11
- failure instead of swallowing exceptions.
8
+ This helper lets synchronous callers use async agent APIs without
9
+ managing the event loop themselves. It returns the underlying result
10
+ directly and propagates exceptions.
12
11
  """
13
12
  try:
14
13
  running_loop = asyncio.get_running_loop()
@@ -3,6 +3,7 @@ import mmap
3
3
  import os
4
4
  import re
5
5
  import typing
6
+ from collections import deque
6
7
  from contextlib import closing
7
8
  from datetime import datetime
8
9
  from pathlib import Path
@@ -323,6 +324,33 @@ def conversation_history_to_turns(
323
324
  return tuple(turns)
324
325
 
325
326
 
327
+ def load_display_history(
328
+ rollout_path: "typing.Union[str, Path]",
329
+ limit: "int" = 80,
330
+ ) -> "typing.Tuple[typing.Union[typing.Tuple[str, str], None], ...]":
331
+ """Read visible turns across checkpoints; None marks a compaction."""
332
+ path = Path(rollout_path).expanduser().resolve()
333
+ turns = deque(maxlen=limit)
334
+ for entry in _iter_rollout_entries(path):
335
+ item_type = entry.get("type")
336
+ payload = entry.get("payload")
337
+ if not isinstance(payload, dict):
338
+ continue
339
+ if item_type == "compacted":
340
+ turns.append(None)
341
+ elif item_type == "event_msg" and payload.get("type") == "user_message":
342
+ turns.append((str(payload.get("message", "")), ""))
343
+ elif (
344
+ item_type == "response_item"
345
+ and payload.get("type") == "message"
346
+ and payload.get("role") == "assistant"
347
+ ):
348
+ if not turns or turns[-1] is None:
349
+ turns.append(("", ""))
350
+ turns[-1] = (turns[-1][0], _extract_response_message_text(payload))
351
+ return tuple(turns)
352
+
353
+
326
354
  def _drop_unmatched_tool_calls(
327
355
  history: "typing.List[ConversationItem]",
328
356
  ) -> "typing.List[ConversationItem]":
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: python-codex
3
- Version: 0.4.0
3
+ Version: 0.4.1
4
4
  Summary: A minimal Python extraction of Codex's main agent loop
5
5
  License-File: LICENSE
6
6
  Requires-Python: >=3.6.2
@@ -40,10 +40,14 @@ The import path remains `pycodex`; the CLI commands are `pycodex` and
40
40
 
41
41
  `python-codex` contains the Agent, runtime, CLI, standard tools, Responses
42
42
  compatibility server and portable storage support. `pycodex-ws` depends on the
43
- exact matching core version and contains the browser workspace, viewer assets,
44
- Feishu and IPython integrations, including their dependencies. It owns the
43
+ exact matching core version and contains the browser workspace, viewer assets
44
+ and optional Feishu integration. It owns the
45
45
  `workspace_server` and `pycodex_ws` modules and the `pycodex-ws` command.
46
46
 
47
+ The Feishu SDK is not installed automatically. Install it in the workspace's
48
+ Python environment with `python3 -m pip install lark-oapi` to enable `/link`.
49
+ If `lark_oapi` cannot be imported, `/link` reports that it is unavailable.
50
+
47
51
  Core does not require Pillow. Without it, `view_image` sends the original image
48
52
  bytes with `detail="original"`, including when `high` is requested. With Pillow
49
53
  installed, the default path retains resizing to a maximum dimension of 2048.
@@ -78,7 +82,7 @@ Relevant Rust reference points:
78
82
 
79
83
  ## Quick Start
80
84
 
81
- Install the core CLI, or install the workspace package to include all integrations:
85
+ Install the core CLI, or install the workspace package for the browser frontend:
82
86
 
83
87
  ```bash
84
88
  python3 -m pip install python-codex
@@ -86,7 +90,7 @@ python3 -m pip install pycodex-ws
86
90
  ```
87
91
 
88
92
  The core supports Python 3.6.2 or newer. The workspace package requires Python
89
- 3.7 or newer because of its Feishu SDK dependency. Commands are installed into
93
+ 3.7 or newer. Commands are installed into
90
94
  that interpreter's scripts directory. On a machine with multiple Python
91
95
  installations, select the same interpreter explicitly for startup:
92
96
 
@@ -118,7 +122,7 @@ uv run pycodex
118
122
 
119
123
  Tests are split by package. `uv run --dev pytest` runs both suites;
120
124
  `uv run --dev pytest packages/pycodex-ws/tests` runs workspace and integration
121
- tests. To check core without installing workspace or its SDKs, use a separate
125
+ tests. To check core without installing workspace, use a separate
122
126
  environment:
123
127
 
124
128
  ```bash
@@ -202,7 +206,7 @@ Supporting services live in `tools/`, `portable/` and `utils/`.
202
206
  - `pycodex/utils/image_utils.py`: image loading, resizing and data-URL preparation
203
207
  - `pycodex/prompts/`: vendored prompts and model metadata
204
208
  - `packages/pycodex-ws/workspace_server/`: Web board, API and file/diff viewers
205
- - `packages/pycodex-ws/pycodex_ws/`: Feishu, IPython and workspace assembly
209
+ - `packages/pycodex-ws/pycodex_ws/`: Feishu and workspace assembly
206
210
  - `packages/pycodex-ws/extensions/vscode/`: workspace's VS Code frontend, built separately as a VSIX
207
211
  - `tests/`: core tests
208
212
  - `packages/pycodex-ws/tests/`: workspace and cross-frontend integration tests
@@ -414,7 +418,8 @@ Current behavior:
414
418
  user instruction; this is intended for side-effect follow-ups such as
415
419
  Feishu notifications
416
420
  - `/link <feishu-email|open_id|chat_id>` in a workspace session attaches it
417
- to a Feishu card; multiple sessions in the same workspace process share
421
+ to a Feishu card when the optional `lark-oapi` SDK can be imported;
422
+ multiple sessions in the same workspace process share
418
423
  one Feishu long-connection listener and route card actions by message id
419
424
  - Feishu user OAuth stores its refresh token only in
420
425
  `~/.codex/.feishu_refresh_token` (mode `0600`). Run
@@ -735,8 +740,7 @@ CLI, Web and Feishu all use `AgentRuntime.submit_input`: not just `/model`
735
740
  and `/resume`, but every session command, steer/queue admission, interactive
736
741
  questions and permissions, state notifications and shutdown. Frontends only
737
742
  adapt input and render events. Web no longer imports or runs the CLI shell.
738
- IPython is the deliberate exception: `pycodex_ws.ipython.ipython_agent()` returns
739
- a bare Agent. Workspace assembly uses `pycodex_ws.build_runtime()` to add
743
+ Workspace assembly uses `pycodex_ws.build_runtime()` to add
740
744
  `/link` and `/unlink`; `pycodex.bootstrap.build_runtime()` provides core commands.
741
745
 
742
746
  ```python
@@ -7,7 +7,7 @@ pycodex/context.py,sha256=yfNY2alT3caQQwhay47pSSrGUbgEAcLKhTVaZqtQ4yU,26610
7
7
  pycodex/events.py,sha256=wysYXHLiCHzW3k1yaAuoRTw90NRhHPa3jtY0ANGOqH4,29694
8
8
  pycodex/model.py,sha256=3mWXTN-oV2Q50SgQYac45WT5Qk2NSmPTxSWyF-w8TRg,44583
9
9
  pycodex/protocol.py,sha256=uzUz_06iA4m9vAoqZeCGiJ4SocKZDzOfCJUU4Bpt5dI,12033
10
- pycodex/runtime.py,sha256=EM8VRfb7Mq2tj39s26lYbAFDzgzzK7qxtPS8RLenoLQ,23812
10
+ pycodex/runtime.py,sha256=3wHKoNjwzOgE6dXeT6Vbpu6Nf7RWqIfHwrjsmOnk81I,23814
11
11
  pycodex/portable/__init__.py,sha256=FmspRPmblYuZIVXMpXaxE1uosCaz2hZDpkpOzxDJQic,1084
12
12
  pycodex/portable/client.py,sha256=DOxzZljVfN1ynmhqrChX7NsT1IFSFVKzEn1J3wvV3XQ,16038
13
13
  pycodex/portable/server.py,sha256=w4YD71Sxb7MD5q57GPuIgx7AoicTv0R9xzX2kAaibPA,7503
@@ -50,7 +50,7 @@ pycodex/tools/wait_tool.py,sha256=0_OO_DvMsBhG3oDKZePTOjZTBq1lmWntXAzqIqvebdA,32
50
50
  pycodex/tools/web_search_tool.py,sha256=3ao1IvJw7MwcP35UKLbqrM-nlm5Z-UUFVdEzkJYOV1o,988
51
51
  pycodex/tools/write_stdin_tool.py,sha256=jvBDchLLmoDITd7g-ZVeEVXHRhWKkmnjM5laL-53FOM,3609
52
52
  pycodex/utils/__init__.py,sha256=ih_KyZ2_bajR5YlZ1QMTWOHnuEBda-S3gQ7PwnBtLZQ,453
53
- pycodex/utils/async_bridge.py,sha256=d21Pjim-nsQbSG5pJddd0WaQ03CzA3w3TINWDmmjWbg,1815
53
+ pycodex/utils/async_bridge.py,sha256=BXsKTUTUvUtPJnItQlulFRdV7opdKKDlsKLdtVTYshs,1732
54
54
  pycodex/utils/compactor.py,sha256=0tlszw1n54aMEGH6sL1U1dEgFSU5ioYL2NI5uSvHSiM,6119
55
55
  pycodex/utils/compat.py,sha256=QxcI4AQuUD-gE2494qPGezgm0OIX98qSHdAiof1JrlU,3550
56
56
  pycodex/utils/crypto.py,sha256=HRCXF26Ft3S8CG2X0YpZwa8GMU9YJ0Loo8Q9PMPMcNw,1249
@@ -62,7 +62,7 @@ pycodex/utils/get_env.py,sha256=L4S8h84tkgxZKvrxY7ezTgePbXepG-yIigUTKeY6uuE,6094
62
62
  pycodex/utils/image_utils.py,sha256=OUzUs0Cow4L8Z2np0EBeEUotAqqsCmRmhrV8AxZUXRw,2460
63
63
  pycodex/utils/model_metadata.py,sha256=uK3iI4yC7Ge7yN4I1_gQYalQ4MYKddz2qMwsmQb-P80,1337
64
64
  pycodex/utils/random_ids.py,sha256=jLTxZZ0MBbRdQOFDFWGVRjWzIo6FKSQ5ADXbQSLPp1s,379
65
- pycodex/utils/session_persist.py,sha256=v9KhmjUB2yCg55c85i8ZU1BWfc-WEMDPmpT0Rv4K8a8,22489
65
+ pycodex/utils/session_persist.py,sha256=_7Lz1jO7D0Qf16UVuZBKU_Si-k_cUVinnLMlsd1jVj4,23600
66
66
  pycodex/utils/truncation.py,sha256=5D6vAorT8EgXgjd7ASwtraAyIZdlCR-w5jKZqJxDzho,5446
67
67
  pycodex/utils/_aes_gcm/LICENSE,sha256=KvdHagY3sYIK34GldJaRi34sNnGwMVJIIoDhbC9MRu8,2805
68
68
  pycodex/utils/_aes_gcm/README.md,sha256=D9XGeewCgU2PVqJCO6WusUs0Mw2FbMnABCqaVktqCnE,3045
@@ -83,8 +83,8 @@ responses_server/trajectory_dump.py,sha256=5_Wy6tslszrqx3j1JeP_boyTbzIicKy8No84P
83
83
  responses_server/tools/__init__.py,sha256=ivsBSEy0SBUhY-Uea5v1XMLXShkwHdCVl0id-1FwdZg,150
84
84
  responses_server/tools/custom_adapter.py,sha256=SnIiNUdomff3APtTriURAC9YCeEdhCDjzGMEYusfUdk,8340
85
85
  responses_server/tools/web_search.py,sha256=pnKH9JyTScRehWpZS3HpXRvjWsQvC0QZqxjEOCT4ndg,8936
86
- python_codex-0.4.0.dist-info/METADATA,sha256=nb46V9WoOekFjc7X3Ep9U0NNoV7bf7DK8Io12_Uch8s,47415
87
- python_codex-0.4.0.dist-info/WHEEL,sha256=KGYbc1zXlYddvwxnNty23BeaKzh7YuoSIvIMO4jEhvw,87
88
- python_codex-0.4.0.dist-info/entry_points.txt,sha256=sNUVakoVuTrzJH505ZgRTQxmtRRPUHV_EH0i6EbYTyM,45
89
- python_codex-0.4.0.dist-info/licenses/LICENSE,sha256=0X8ifk312hYAORM4hlzg8wVSEXYKNmiPgWlB1YIy2Nw,10926
90
- python_codex-0.4.0.dist-info/RECORD,,
86
+ python_codex-0.4.1.dist-info/METADATA,sha256=oeFno9KHzkjQBQWXIQILZpJBRydqouzo7BqtpoKh9_g,47510
87
+ python_codex-0.4.1.dist-info/WHEEL,sha256=KGYbc1zXlYddvwxnNty23BeaKzh7YuoSIvIMO4jEhvw,87
88
+ python_codex-0.4.1.dist-info/entry_points.txt,sha256=sNUVakoVuTrzJH505ZgRTQxmtRRPUHV_EH0i6EbYTyM,45
89
+ python_codex-0.4.1.dist-info/licenses/LICENSE,sha256=0X8ifk312hYAORM4hlzg8wVSEXYKNmiPgWlB1YIy2Nw,10926
90
+ python_codex-0.4.1.dist-info/RECORD,,