python-codex 0.4.3__py3-none-any.whl → 0.4.4__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/agent.py CHANGED
@@ -253,6 +253,10 @@ class Agent:
253
253
  while True:
254
254
  phase = "pre_turn" if turn.iteration == 0 else "mid_turn"
255
255
  await self._maybe_auto_compact(turn.turn_id, phase)
256
+ manager = self.tool_registry.runtime_environment.subagent_manager
257
+ notifications = manager.take_pending_notifications()
258
+ if notifications:
259
+ self._append_history(notifications)
256
260
  if turn.iteration == 0:
257
261
  self._append_history(UserMessage(text=text) for text in texts)
258
262
  response = await self._sample(turn)
@@ -15,7 +15,7 @@ from ..events import (
15
15
  TurnInterruptedEvent,
16
16
  TurnStartedEvent,
17
17
  )
18
- from ..protocol import ConversationItem, ToolCall, ToolResult
18
+ from ..protocol import ConversationItem, ToolCall, ToolResult, UserMessage
19
19
  from ..utils import uuid7_string
20
20
  from ..utils.compat import Literal
21
21
 
@@ -221,6 +221,7 @@ class SubAgentManager:
221
221
  def __init__(self) -> "None":
222
222
  self._runtime_builder: "typing.Union[AgentRuntimeBuilder, None]" = None
223
223
  self._agents: "typing.Dict[str, ManagedAgent]" = {}
224
+ self._pending_notifications: "typing.List[UserMessage]" = []
224
225
  self._condition = None
225
226
  self._available_nicknames: "typing.List[str]" = []
226
227
  self._nickname_random = random.Random()
@@ -235,6 +236,11 @@ class SubAgentManager:
235
236
  ) -> "None":
236
237
  self._runtime_builder = builder
237
238
 
239
+ def take_pending_notifications(self) -> "typing.Tuple[UserMessage, ...]":
240
+ messages = tuple(self._pending_notifications)
241
+ self._pending_notifications.clear()
242
+ return messages
243
+
238
244
  async def spawn_agent(
239
245
  self,
240
246
  message: "typing.Union[str, None]",
@@ -396,8 +402,27 @@ class SubAgentManager:
396
402
  }
397
403
  elif isinstance(event, TurnInterruptedEvent):
398
404
  managed.last_status = {"errored": "TurnInterrupted: turn interrupted"}
399
- elif not isinstance(event, (TurnStartedEvent, CompactStartedEvent)):
405
+ elif isinstance(event, (TurnStartedEvent, CompactStartedEvent)):
406
+ asyncio.create_task(self._notify_waiters())
407
+ return
408
+ else:
400
409
  return
410
+ self._pending_notifications.append(
411
+ UserMessage(
412
+ text=(
413
+ "<subagent_notification>\n"
414
+ + json.dumps(
415
+ {
416
+ "agent_id": managed.agent_id,
417
+ "status": managed.last_status,
418
+ },
419
+ ensure_ascii=False,
420
+ separators=(",", ":"),
421
+ )
422
+ + "\n</subagent_notification>"
423
+ )
424
+ )
425
+ )
401
426
  asyncio.create_task(self._notify_waiters())
402
427
 
403
428
  async def _notify_waiters(self) -> "None":
@@ -9,10 +9,7 @@ Expected behavior:
9
9
  wait times out.
10
10
  """
11
11
 
12
- import json
13
- import typing
14
-
15
- from ..protocol import JSONDict, JSONValue, UserMessage
12
+ from ..protocol import JSONDict, JSONValue
16
13
  from .agent_tool_schemas import AGENT_STATUS_SCHEMA
17
14
  from .base_tool import BaseTool, ToolContext
18
15
  from .runtime_services import SubAgentManager
@@ -80,26 +77,6 @@ class WaitAgentTool(BaseTool):
80
77
  timeout_ms = self._timeout_ms(args)
81
78
  return await self._subagent_manager.wait_agents(agent_ids, timeout_ms)
82
79
 
83
- def follow_up_messages(
84
- self, output: "JSONValue"
85
- ) -> "typing.Tuple[UserMessage, ...]":
86
- if not isinstance(output, dict):
87
- return ()
88
- return tuple(
89
- UserMessage(
90
- text=(
91
- "<subagent_notification>\n"
92
- + json.dumps(
93
- {"agent_id": agent_id, "status": status},
94
- ensure_ascii=False,
95
- separators=(",", ":"),
96
- )
97
- + "\n</subagent_notification>"
98
- )
99
- )
100
- for agent_id, status in output["status"].items()
101
- )
102
-
103
80
  def _timeout_ms(self, args: "JSONDict") -> "int":
104
81
  value = int(args.get("timeout_ms", DEFAULT_WAIT_AGENT_TIMEOUT_MS))
105
82
  return min(
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: python-codex
3
- Version: 0.4.3
3
+ Version: 0.4.4
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
@@ -808,7 +808,9 @@ event JSON format.
808
808
  The global `get_agent_runtime_environment()` and
809
809
  separate `Agent(..., runtime_environment=...)` entry points are removed.
810
810
  - Each sub-agent gets its own context manager and runtime services. The sub-agent
811
- service retains terminal event status, rather than inspecting Task results.
811
+ service retains terminal event status and queues one notification per terminal
812
+ event. The parent consumes these notifications before its next normal model
813
+ request, without requiring `wait_agent`; an idle parent waits for its next turn.
812
814
  - Every Agent records its session, including direct and child Agents; external
813
815
  callers no longer construct or inject `SessionRolloutRecorder`. The outer queue
814
816
  remains optional and no worker starts implicitly. Empty initial history and a
@@ -1,6 +1,6 @@
1
1
  pycodex/__init__.py,sha256=fHEyhylULeRo-5xEnl-UxT5ZpBzbFzRW7vLwdy_7oxU,2660
2
2
  pycodex/__main__.py,sha256=MHKZ_ae3fSLGTLUUMOx15fWdeOnJSHhq-zslRP5F5Lc,79
3
- pycodex/agent.py,sha256=zCIG2DV0oQntLXHFj8FVRkgBp5TCC0YJ7sz0lni9J1s,21177
3
+ pycodex/agent.py,sha256=GF-mNTnxHW8qw-72QEXfGGvExZzl8c3m6emZBux6ddw,21418
4
4
  pycodex/bootstrap.py,sha256=U1X5kwORpS5JnPk9HhIiOVWPQzDLlk_ro_cY2knwL8I,12421
5
5
  pycodex/cli.py,sha256=MLvXpVwrb-HJuVWmPFmNMTR-4cqR3X08ZfAevYlVSQI,12646
6
6
  pycodex/context.py,sha256=yfNY2alT3caQQwhay47pSSrGUbgEAcLKhTVaZqtQ4yU,26610
@@ -37,7 +37,7 @@ pycodex/tools/read_file_tool.py,sha256=YK__uhIVldBjAQega5S_ZuZU5jgP_kLOwr-YhjAmR
37
37
  pycodex/tools/request_permissions_tool.py,sha256=nEt3_uw3lmFXyydqcN3PxuKwrEvaRPtfjA_U8nikCtU,3978
38
38
  pycodex/tools/request_user_input_tool.py,sha256=_7siHF2p3KiNDFwsTqKKIUw2kPCXMzLaR12PkZ1wdIQ,4050
39
39
  pycodex/tools/resume_agent_tool.py,sha256=bZvXEUNdc1RVD2N5Msjv63Rni62FQk4gj9LAXK1Vsy8,1613
40
- pycodex/tools/runtime_services.py,sha256=vZHIHGAeTA-DoEoHulAKvjcfHLXkuK1t3T0Mob9VJ8A,15044
40
+ pycodex/tools/runtime_services.py,sha256=KPLtB1e7jmqEN9rhXV70rUMlhYNFsXja4CypIunzXLU,15962
41
41
  pycodex/tools/send_input_tool.py,sha256=w63SKM05_e3oXvdaBtL-hk941TvkWKuTUDEqTSyWEMQ,3761
42
42
  pycodex/tools/shell_command_tool.py,sha256=US63I5xiV5zfO1Oox2yHUg7F6XoKzmyxtohfaQIsmrw,4216
43
43
  pycodex/tools/shell_tool.py,sha256=lqFH2XosfBg7yQKhpB7i4vLGz9sNQtEZihD0rjsmBCQ,4068
@@ -45,7 +45,7 @@ pycodex/tools/spawn_agent_tool.py,sha256=Jx5jYpxsH_CQ3BLkXYPZuIINW5deO_zY8tyw8kZ
45
45
  pycodex/tools/unified_exec_manager.py,sha256=XPN6PgBnjZ5WFZATNIqpWKUAuw8HMMD7mlfHJQjJQZM,14544
46
46
  pycodex/tools/update_plan_tool.py,sha256=xwrSrerw5qfkbFc9Ltx1OZEmD__CWtryOy3UhL0-Jp4,3198
47
47
  pycodex/tools/view_image_tool.py,sha256=SCoiIHaQ51oYjYX69MRxjAK9b1P6_wOCIuZqzsC2rj8,4082
48
- pycodex/tools/wait_agent_tool.py,sha256=9Os6RzzCxIU5KJI5l6MzdwO6QKLNxLFwFXGeDMfYlP4,3828
48
+ pycodex/tools/wait_agent_tool.py,sha256=pLsnk9TxSt4v7krC7s7vxi91pLisSNU0lATt9s-P_3E,3134
49
49
  pycodex/tools/wait_tool.py,sha256=0_OO_DvMsBhG3oDKZePTOjZTBq1lmWntXAzqIqvebdA,3206
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
@@ -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.3.dist-info/METADATA,sha256=hXum9V3ngy2KFpqKDcpssNeZrES-cHTFhiAGDTgGCcI,47510
87
- python_codex-0.4.3.dist-info/WHEEL,sha256=KGYbc1zXlYddvwxnNty23BeaKzh7YuoSIvIMO4jEhvw,87
88
- python_codex-0.4.3.dist-info/entry_points.txt,sha256=sNUVakoVuTrzJH505ZgRTQxmtRRPUHV_EH0i6EbYTyM,45
89
- python_codex-0.4.3.dist-info/licenses/LICENSE,sha256=0X8ifk312hYAORM4hlzg8wVSEXYKNmiPgWlB1YIy2Nw,10926
90
- python_codex-0.4.3.dist-info/RECORD,,
86
+ python_codex-0.4.4.dist-info/METADATA,sha256=or8DXQM9IhgXgr3AY-tLyPNAdE2oGvcqY8l8EfV-PGs,47674
87
+ python_codex-0.4.4.dist-info/WHEEL,sha256=KGYbc1zXlYddvwxnNty23BeaKzh7YuoSIvIMO4jEhvw,87
88
+ python_codex-0.4.4.dist-info/entry_points.txt,sha256=sNUVakoVuTrzJH505ZgRTQxmtRRPUHV_EH0i6EbYTyM,45
89
+ python_codex-0.4.4.dist-info/licenses/LICENSE,sha256=0X8ifk312hYAORM4hlzg8wVSEXYKNmiPgWlB1YIy2Nw,10926
90
+ python_codex-0.4.4.dist-info/RECORD,,