codex-agent-framework 0.1.20__tar.gz → 0.1.22__tar.gz
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.
- {codex_agent_framework-0.1.20 → codex_agent_framework-0.1.22}/CHANGELOG.md +40 -0
- {codex_agent_framework-0.1.20/codex_agent_framework.egg-info → codex_agent_framework-0.1.22}/PKG-INFO +23 -8
- {codex_agent_framework-0.1.20 → codex_agent_framework-0.1.22}/README.md +22 -7
- {codex_agent_framework-0.1.20 → codex_agent_framework-0.1.22}/codex_agent/__init__.py +6 -1
- {codex_agent_framework-0.1.20 → codex_agent_framework-0.1.22}/codex_agent/agent.py +29 -18
- {codex_agent_framework-0.1.20 → codex_agent_framework-0.1.22}/codex_agent/agent_runtime.py +58 -45
- {codex_agent_framework-0.1.20 → codex_agent_framework-0.1.22}/codex_agent/builtin_plugins/memory/__init__.py +2 -1
- codex_agent_framework-0.1.22/codex_agent/builtin_plugins/subagents/__init__.py +220 -0
- codex_agent_framework-0.1.22/codex_agent/builtin_plugins/subagents/profiles/explorer.json +12 -0
- {codex_agent_framework-0.1.20 → codex_agent_framework-0.1.22}/codex_agent/client.py +21 -13
- {codex_agent_framework-0.1.20 → codex_agent_framework-0.1.22}/codex_agent/command.py +108 -11
- {codex_agent_framework-0.1.20 → codex_agent_framework-0.1.22}/codex_agent/config.py +3 -2
- {codex_agent_framework-0.1.20 → codex_agent_framework-0.1.22}/codex_agent/context.py +20 -10
- {codex_agent_framework-0.1.20 → codex_agent_framework-0.1.22}/codex_agent/event.py +49 -10
- {codex_agent_framework-0.1.20 → codex_agent_framework-0.1.22}/codex_agent/mainloop.py +87 -19
- {codex_agent_framework-0.1.20 → codex_agent_framework-0.1.22}/codex_agent/message.py +34 -6
- {codex_agent_framework-0.1.20 → codex_agent_framework-0.1.22}/codex_agent/plugin.py +12 -3
- {codex_agent_framework-0.1.20 → codex_agent_framework-0.1.22}/codex_agent/prompts/system_prompt.txt +11 -8
- {codex_agent_framework-0.1.20 → codex_agent_framework-0.1.22}/codex_agent/provider.py +1 -1
- {codex_agent_framework-0.1.20 → codex_agent_framework-0.1.22}/codex_agent/scheduler.py +2 -2
- {codex_agent_framework-0.1.20 → codex_agent_framework-0.1.22}/codex_agent/server/app.py +2 -1
- {codex_agent_framework-0.1.20 → codex_agent_framework-0.1.22}/codex_agent/server/core.py +96 -59
- {codex_agent_framework-0.1.20 → codex_agent_framework-0.1.22}/codex_agent/sessions.py +312 -32
- {codex_agent_framework-0.1.20 → codex_agent_framework-0.1.22}/codex_agent/stream_utils.py +63 -37
- {codex_agent_framework-0.1.20 → codex_agent_framework-0.1.22}/codex_agent/tool.py +37 -4
- {codex_agent_framework-0.1.20 → codex_agent_framework-0.1.22}/codex_agent/tui/chat.py +76 -9
- {codex_agent_framework-0.1.20 → codex_agent_framework-0.1.22}/codex_agent/utils.py +9 -0
- codex_agent_framework-0.1.22/codex_agent/version.py +1 -0
- {codex_agent_framework-0.1.20 → codex_agent_framework-0.1.22/codex_agent_framework.egg-info}/PKG-INFO +23 -8
- {codex_agent_framework-0.1.20 → codex_agent_framework-0.1.22}/codex_agent_framework.egg-info/SOURCES.txt +3 -0
- {codex_agent_framework-0.1.20 → codex_agent_framework-0.1.22}/pyproject.toml +2 -2
- {codex_agent_framework-0.1.20 → codex_agent_framework-0.1.22}/tests/test_agent.py +726 -65
- {codex_agent_framework-0.1.20 → codex_agent_framework-0.1.22}/tests/test_chat.py +72 -1
- {codex_agent_framework-0.1.20 → codex_agent_framework-0.1.22}/tests/test_client.py +2 -2
- {codex_agent_framework-0.1.20 → codex_agent_framework-0.1.22}/tests/test_events.py +18 -0
- {codex_agent_framework-0.1.20 → codex_agent_framework-0.1.22}/tests/test_memory.py +10 -6
- {codex_agent_framework-0.1.20 → codex_agent_framework-0.1.22}/tests/test_messages.py +13 -1
- {codex_agent_framework-0.1.20 → codex_agent_framework-0.1.22}/tests/test_scheduler.py +5 -4
- {codex_agent_framework-0.1.20 → codex_agent_framework-0.1.22}/tests/test_server.py +79 -13
- {codex_agent_framework-0.1.20 → codex_agent_framework-0.1.22}/LICENSE +0 -0
- {codex_agent_framework-0.1.20 → codex_agent_framework-0.1.22}/MANIFEST.in +0 -0
- {codex_agent_framework-0.1.20 → codex_agent_framework-0.1.22}/codex_agent/__main__.py +0 -0
- {codex_agent_framework-0.1.20 → codex_agent_framework-0.1.22}/codex_agent/ai.py +0 -0
- {codex_agent_framework-0.1.20 → codex_agent_framework-0.1.22}/codex_agent/browser.py +0 -0
- {codex_agent_framework-0.1.20 → codex_agent_framework-0.1.22}/codex_agent/builtin_commands.py +0 -0
- {codex_agent_framework-0.1.20 → codex_agent_framework-0.1.22}/codex_agent/builtin_plugins/__init__.py +0 -0
- {codex_agent_framework-0.1.20 → codex_agent_framework-0.1.22}/codex_agent/builtin_plugins/bash/__init__.py +0 -0
- {codex_agent_framework-0.1.20 → codex_agent_framework-0.1.22}/codex_agent/builtin_plugins/browser/__init__.py +0 -0
- {codex_agent_framework-0.1.20 → codex_agent_framework-0.1.22}/codex_agent/builtin_plugins/content/__init__.py +0 -0
- {codex_agent_framework-0.1.20 → codex_agent_framework-0.1.22}/codex_agent/builtin_plugins/content/system.py +0 -0
- {codex_agent_framework-0.1.20 → codex_agent_framework-0.1.22}/codex_agent/builtin_plugins/content/vision.py +0 -0
- {codex_agent_framework-0.1.20 → codex_agent_framework-0.1.22}/codex_agent/builtin_plugins/desktop/__init__.py +0 -0
- {codex_agent_framework-0.1.20 → codex_agent_framework-0.1.22}/codex_agent/builtin_plugins/environment/__init__.py +0 -0
- {codex_agent_framework-0.1.20 → codex_agent_framework-0.1.22}/codex_agent/builtin_plugins/files/__init__.py +0 -0
- {codex_agent_framework-0.1.20 → codex_agent_framework-0.1.22}/codex_agent/builtin_plugins/files/tools.py +0 -0
- {codex_agent_framework-0.1.20 → codex_agent_framework-0.1.22}/codex_agent/builtin_plugins/interface/__init__.py +0 -0
- {codex_agent_framework-0.1.20 → codex_agent_framework-0.1.22}/codex_agent/builtin_plugins/planner/__init__.py +0 -0
- {codex_agent_framework-0.1.20 → codex_agent_framework-0.1.22}/codex_agent/builtin_plugins/python/__init__.py +0 -0
- {codex_agent_framework-0.1.20 → codex_agent_framework-0.1.22}/codex_agent/builtin_plugins/scheduler/__init__.py +0 -0
- {codex_agent_framework-0.1.20 → codex_agent_framework-0.1.22}/codex_agent/cli/__init__.py +0 -0
- {codex_agent_framework-0.1.20 → codex_agent_framework-0.1.22}/codex_agent/cli/headless.py +0 -0
- {codex_agent_framework-0.1.20 → codex_agent_framework-0.1.22}/codex_agent/cli/main.py +0 -0
- {codex_agent_framework-0.1.20 → codex_agent_framework-0.1.22}/codex_agent/cli/output.py +0 -0
- {codex_agent_framework-0.1.20 → codex_agent_framework-0.1.22}/codex_agent/cli/root.py +0 -0
- {codex_agent_framework-0.1.20 → codex_agent_framework-0.1.22}/codex_agent/cli/runner.py +0 -0
- {codex_agent_framework-0.1.20 → codex_agent_framework-0.1.22}/codex_agent/desktop.py +0 -0
- {codex_agent_framework-0.1.20 → codex_agent_framework-0.1.22}/codex_agent/get_text/__init__.py +0 -0
- {codex_agent_framework-0.1.20 → codex_agent_framework-0.1.22}/codex_agent/get_text/default_gitignore +0 -0
- {codex_agent_framework-0.1.20 → codex_agent_framework-0.1.22}/codex_agent/get_text/get_text.py +0 -0
- {codex_agent_framework-0.1.20 → codex_agent_framework-0.1.22}/codex_agent/get_text/simpler_get_text.py +0 -0
- {codex_agent_framework-0.1.20 → codex_agent_framework-0.1.22}/codex_agent/hooks.py +0 -0
- {codex_agent_framework-0.1.20 → codex_agent_framework-0.1.22}/codex_agent/image.py +0 -0
- {codex_agent_framework-0.1.20 → codex_agent_framework-0.1.22}/codex_agent/latex.py +0 -0
- {codex_agent_framework-0.1.20 → codex_agent_framework-0.1.22}/codex_agent/prompts/image_generation_system_prompt.txt +0 -0
- {codex_agent_framework-0.1.20 → codex_agent_framework-0.1.22}/codex_agent/runtime.py +0 -0
- {codex_agent_framework-0.1.20 → codex_agent_framework-0.1.22}/codex_agent/scripts/install-system-dependencies.sh +0 -0
- {codex_agent_framework-0.1.20 → codex_agent_framework-0.1.22}/codex_agent/server/__init__.py +0 -0
- {codex_agent_framework-0.1.20 → codex_agent_framework-0.1.22}/codex_agent/service.py +0 -0
- {codex_agent_framework-0.1.20 → codex_agent_framework-0.1.22}/codex_agent/status.py +0 -0
- {codex_agent_framework-0.1.20 → codex_agent_framework-0.1.22}/codex_agent/tray.py +0 -0
- {codex_agent_framework-0.1.20 → codex_agent_framework-0.1.22}/codex_agent/tui/__init__.py +0 -0
- {codex_agent_framework-0.1.20 → codex_agent_framework-0.1.22}/codex_agent/tui/lifecycle.py +0 -0
- {codex_agent_framework-0.1.20 → codex_agent_framework-0.1.22}/codex_agent/voice.py +0 -0
- {codex_agent_framework-0.1.20 → codex_agent_framework-0.1.22}/codex_agent/worker.py +0 -0
- {codex_agent_framework-0.1.20 → codex_agent_framework-0.1.22}/codex_agent_framework.egg-info/dependency_links.txt +0 -0
- {codex_agent_framework-0.1.20 → codex_agent_framework-0.1.22}/codex_agent_framework.egg-info/entry_points.txt +0 -0
- {codex_agent_framework-0.1.20 → codex_agent_framework-0.1.22}/codex_agent_framework.egg-info/requires.txt +0 -0
- {codex_agent_framework-0.1.20 → codex_agent_framework-0.1.22}/codex_agent_framework.egg-info/top_level.txt +0 -0
- {codex_agent_framework-0.1.20 → codex_agent_framework-0.1.22}/dependencies.txt +0 -0
- {codex_agent_framework-0.1.20 → codex_agent_framework-0.1.22}/setup.cfg +0 -0
- {codex_agent_framework-0.1.20 → codex_agent_framework-0.1.22}/tests/test_agent_runtime.py +0 -0
- {codex_agent_framework-0.1.20 → codex_agent_framework-0.1.22}/tests/test_ai.py +0 -0
- {codex_agent_framework-0.1.20 → codex_agent_framework-0.1.22}/tests/test_browser.py +0 -0
- {codex_agent_framework-0.1.20 → codex_agent_framework-0.1.22}/tests/test_builtin_config.py +0 -0
- {codex_agent_framework-0.1.20 → codex_agent_framework-0.1.22}/tests/test_cli.py +0 -0
- {codex_agent_framework-0.1.20 → codex_agent_framework-0.1.22}/tests/test_cli_headless.py +0 -0
- {codex_agent_framework-0.1.20 → codex_agent_framework-0.1.22}/tests/test_cli_root.py +0 -0
- {codex_agent_framework-0.1.20 → codex_agent_framework-0.1.22}/tests/test_get_text_browser.py +0 -0
- {codex_agent_framework-0.1.20 → codex_agent_framework-0.1.22}/tests/test_hooks.py +0 -0
- {codex_agent_framework-0.1.20 → codex_agent_framework-0.1.22}/tests/test_image_message.py +0 -0
- {codex_agent_framework-0.1.20 → codex_agent_framework-0.1.22}/tests/test_local_desktop.py +0 -0
- {codex_agent_framework-0.1.20 → codex_agent_framework-0.1.22}/tests/test_planner.py +0 -0
- {codex_agent_framework-0.1.20 → codex_agent_framework-0.1.22}/tests/test_service.py +0 -0
- {codex_agent_framework-0.1.20 → codex_agent_framework-0.1.22}/tests/test_tray.py +0 -0
- {codex_agent_framework-0.1.20 → codex_agent_framework-0.1.22}/tests/test_tui.py +0 -0
- {codex_agent_framework-0.1.20 → codex_agent_framework-0.1.22}/tests/test_utils.py +0 -0
- {codex_agent_framework-0.1.20 → codex_agent_framework-0.1.22}/tests/test_worker.py +0 -0
|
@@ -4,6 +4,46 @@ All notable changes to this project will be documented in this file.
|
|
|
4
4
|
|
|
5
5
|
This project loosely follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) and uses semantic versioning where practical.
|
|
6
6
|
|
|
7
|
+
## [0.1.22] - 2026-05-10
|
|
8
|
+
### Changed
|
|
9
|
+
- Harden the FastAPI/SSE bridge and Textual TUI streaming path after a stabilization audit: finite SSE read timeouts, batched live deltas, synchronous replay delta flushes, and explicit stale-subscriber replacement shutdowns.
|
|
10
|
+
- Improve process-backed runtime robustness with guarded startup, isolated event handlers, and clearer cached status/turn-state updates.
|
|
11
|
+
- Consolidate shared helpers for type hierarchy, turn outcomes, atomic session writes, tool exclusion matching, context truncation, and subagent child creation while removing smaller duplicated or dead helper paths.
|
|
12
|
+
- Publish the package version from a single `codex_agent.version` module and use it for FastAPI metadata.
|
|
13
|
+
|
|
14
|
+
### Fixed
|
|
15
|
+
- Prevent stale SSE subscribers from lingering silently when a replacement TUI stream connects.
|
|
16
|
+
- Avoid concurrent subscriber-table mutation during event publication and serialize persisted turn-event rewrite/append operations.
|
|
17
|
+
- Preserve replay ordering in the TUI so caught-up deltas render before newly batched live stream deltas.
|
|
18
|
+
- Keep one failing process-runtime event handler from stopping delivery to later handlers.
|
|
19
|
+
|
|
20
|
+
### Tests
|
|
21
|
+
- Validate post-restart API/import/runtime smoke tests after a real server restart.
|
|
22
|
+
- Validate `pyflakes codex_agent tests`, targeted server/client/chat smoke tests, and the full suite at 489 passing tests.
|
|
23
|
+
|
|
24
|
+
## [0.1.21] - 2026-05-10
|
|
25
|
+
### Added
|
|
26
|
+
- Add the structured `AgentTurn` API: `agent(...)` and `AgentFuture.wait()` now return a turn object with `result`, `completed`, `reason`, `messages`, and `events`.
|
|
27
|
+
- Add resumable non-terminal turns for `auto_proceed=False`; turns that need another model step pause with `reason="requires_next_step"` and continue through `agent.resume_turn(turn)`.
|
|
28
|
+
- Add `agent.set_turn_result(data)` for tools/plugins that need to explicitly finish the current turn with a structured result.
|
|
29
|
+
- Add the built-in `subagents` plugin with profile-based child agents, compact parent results, child-local `set_result`, `SubagentEvent` relay, and a packaged read-only `explorer` profile.
|
|
30
|
+
- Add hierarchical `types` to messages and events while keeping `type` as the concrete computed type.
|
|
31
|
+
- Add configurable `exclude_tools` matching by public or canonical plugin tool names.
|
|
32
|
+
|
|
33
|
+
### Changed
|
|
34
|
+
- Treat scheduled and post-restart wakeups as internal `DeveloperMessage` entries instead of user-authored messages.
|
|
35
|
+
- Make `AssistantTurnEndEvent` expose a terminal `reason` rather than carrying a raw result payload.
|
|
36
|
+
- Capture turn-local events and messages on `AgentTurn` so embedded callers can inspect what happened without replaying the whole session.
|
|
37
|
+
- Include packaged subagent profile JSON files in distributions.
|
|
38
|
+
- Refresh the packaged default system prompt around agent identity, clarification, durable fixes, and concise final reporting.
|
|
39
|
+
|
|
40
|
+
### Fixed
|
|
41
|
+
- Preserve coherent turn state across suspended/resumed turns, including stable turn IDs, non-terminal suspension without a turn-end event, and terminal completion on resume.
|
|
42
|
+
|
|
43
|
+
### Tests
|
|
44
|
+
- Validate the full suite at 483 passing tests.
|
|
45
|
+
- Validate post-restart wakeups after a real server restart and smoke-test `auto_proceed=False` `AgentTurn` suspension/resume behavior.
|
|
46
|
+
|
|
7
47
|
## [0.1.20] - 2026-05-09
|
|
8
48
|
### Added
|
|
9
49
|
- Make runtime plugins the single user-facing extension unit for tools, providers, commands, prompt sections, hooks, and events.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: codex-agent-framework
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.22
|
|
4
4
|
Summary: A lightweight event-driven Codex agent runtime.
|
|
5
5
|
Author: Baptiste
|
|
6
6
|
License-Expression: MIT
|
|
@@ -286,10 +286,17 @@ agent = Agent(
|
|
|
286
286
|
voice_enabled=False,
|
|
287
287
|
)
|
|
288
288
|
|
|
289
|
-
|
|
290
|
-
|
|
289
|
+
turn = agent("Summarize this repository in three practical bullet points.")
|
|
290
|
+
|
|
291
|
+
print("Completed:", turn.completed)
|
|
292
|
+
print("Reason:", turn.reason)
|
|
293
|
+
print("Result:", turn.result)
|
|
294
|
+
for message in turn.messages:
|
|
295
|
+
print(message.as_string())
|
|
291
296
|
```
|
|
292
297
|
|
|
298
|
+
`agent(...)` returns an `AgentTurn`, not a raw string. `turn.result` is the useful final result, while `turn.messages` and `turn.events` contain the messages and events produced by that command. If `auto_proceed=False`, a tool-using turn can pause with `completed=False` and `reason="requires_next_step"`; call `agent.resume_turn(turn)` to continue the same turn object until it reaches a terminal reason such as `completed`, `result_set`, `interrupted`, or `error`.
|
|
299
|
+
|
|
293
300
|
Resume the latest session interactively:
|
|
294
301
|
|
|
295
302
|
```python
|
|
@@ -398,7 +405,7 @@ def repo():
|
|
|
398
405
|
|
|
399
406
|
agent = Agent(session="latest", voice_enabled=False)
|
|
400
407
|
agent.add_command(repo)
|
|
401
|
-
print(agent("/repo"))
|
|
408
|
+
print(agent("/repo").result)
|
|
402
409
|
```
|
|
403
410
|
|
|
404
411
|
### Add stateful plugins
|
|
@@ -593,8 +600,11 @@ The default agent exposes local tools and plugin tools to the model. Plugin tool
|
|
|
593
600
|
| Scheduler plugin | `scheduler_schedule`, `scheduler_cancel`, `scheduler_list`, `scheduler_restart_and_wakeup` | Future turns, periodic wakeups, post-restart continuation. |
|
|
594
601
|
| Browser plugin | `browser_open`, `browser_goto`, `browser_click`, `browser_fill`, `browser_press`, ... | Persistent Playwright/Chromium automation with active-tab context. |
|
|
595
602
|
| Desktop plugin | `desktop_start_session`, `desktop_run_commands`, `desktop_stop_session` | Screenshot-backed Linux desktop automation. |
|
|
603
|
+
| Subagents plugin | `subagents_run` | Run an ephemeral child agent from a predefined profile and return a compact structured result. |
|
|
596
604
|
|
|
597
|
-
Built-ins are intentionally packaged as plugins. Current built-in plugin modules include `files`, `content`, `bash`, `python`, `interface`, `environment`, `memory`, `planner`, `scheduler`, `browser`, and `
|
|
605
|
+
Built-ins are intentionally packaged as plugins. Current built-in plugin modules include `files`, `content`, `bash`, `python`, `interface`, `environment`, `memory`, `planner`, `scheduler`, `browser`, `desktop`, and `subagents`.
|
|
606
|
+
|
|
607
|
+
The `subagents` plugin ships profile JSON files inside the package, starting with `explorer`, a read-only codebase inspection agent. Parent agents choose an existing profile and task; child agents receive their own config, tools, prompt, and temporary session instead of inheriting the parent's runtime implicitly.
|
|
598
608
|
|
|
599
609
|
Built-in plugins are configurable. `None` means load all plugins, an empty list means load none, and an explicit list selects specific plugin module names:
|
|
600
610
|
|
|
@@ -703,8 +713,11 @@ Useful exported events include:
|
|
|
703
713
|
- `ToolCallStartEvent` / `ToolCallDoneEvent`
|
|
704
714
|
- `SessionLoadedEvent` / `SessionDeletedEvent`
|
|
705
715
|
- `AssistantInterruptedEvent`
|
|
716
|
+
- `SubagentEvent`
|
|
706
717
|
- `AudioPlaybackEvent`
|
|
707
718
|
|
|
719
|
+
Messages and events expose hierarchical `types` as well as the final computed `type`, so listeners can subscribe to broad classes such as all events or to precise concrete event types.
|
|
720
|
+
|
|
708
721
|
Plugins can also register event and hook handlers with decorators:
|
|
709
722
|
|
|
710
723
|
```python
|
|
@@ -833,13 +846,13 @@ The tests isolate `AGENT_RUNTIME_DIR` automatically, so they should not create o
|
|
|
833
846
|
The current tree validates at:
|
|
834
847
|
|
|
835
848
|
```text
|
|
836
|
-
|
|
849
|
+
489 passed
|
|
837
850
|
```
|
|
838
851
|
|
|
839
|
-
The published `0.1.
|
|
852
|
+
The published `0.1.22` release was validated at:
|
|
840
853
|
|
|
841
854
|
```text
|
|
842
|
-
|
|
855
|
+
489 passed
|
|
843
856
|
```
|
|
844
857
|
|
|
845
858
|
## Packaging
|
|
@@ -857,6 +870,8 @@ The distribution includes prompt text files, `codex_agent/get_text/default_gitig
|
|
|
857
870
|
|
|
858
871
|
## Recent changes
|
|
859
872
|
|
|
873
|
+
- `0.1.22`: harden FastAPI/SSE and TUI streaming after a stabilization audit, including finite SSE read timeouts, stale-subscriber shutdown, persisted turn-event locking, synchronous replay delta flushes, process-runtime startup guards, and isolated event handlers.
|
|
874
|
+
- `0.1.21`: add structured `AgentTurn` returns with messages/events, resumable non-terminal turns for `auto_proceed=False`, profile-based subagents, hierarchical message/event types, and internal wakeups as developer messages.
|
|
860
875
|
- `0.1.20`: make runtime plugins the single user-facing extension unit for tools/providers/commands, remove legacy direct runtime tool/provider loading, split tool/provider managers, and keep system-prompt templating on an explicit minimal namespace.
|
|
861
876
|
- `0.1.19`: prune compacted raw session history after compaction, keep only the latest compaction anchor plus the new compaction and any unfinished remainder, and drop older redundant compaction summaries from active session files.
|
|
862
877
|
- `0.1.18`: make `start server/tray` detach by default, move durable memory fully into the memory plugin, keep wakeups as a core runtime primitive, expose RAG memory timestamps/sources, and move browser/desktop backend controllers into core modules with plugins as facades.
|
|
@@ -237,10 +237,17 @@ agent = Agent(
|
|
|
237
237
|
voice_enabled=False,
|
|
238
238
|
)
|
|
239
239
|
|
|
240
|
-
|
|
241
|
-
|
|
240
|
+
turn = agent("Summarize this repository in three practical bullet points.")
|
|
241
|
+
|
|
242
|
+
print("Completed:", turn.completed)
|
|
243
|
+
print("Reason:", turn.reason)
|
|
244
|
+
print("Result:", turn.result)
|
|
245
|
+
for message in turn.messages:
|
|
246
|
+
print(message.as_string())
|
|
242
247
|
```
|
|
243
248
|
|
|
249
|
+
`agent(...)` returns an `AgentTurn`, not a raw string. `turn.result` is the useful final result, while `turn.messages` and `turn.events` contain the messages and events produced by that command. If `auto_proceed=False`, a tool-using turn can pause with `completed=False` and `reason="requires_next_step"`; call `agent.resume_turn(turn)` to continue the same turn object until it reaches a terminal reason such as `completed`, `result_set`, `interrupted`, or `error`.
|
|
250
|
+
|
|
244
251
|
Resume the latest session interactively:
|
|
245
252
|
|
|
246
253
|
```python
|
|
@@ -349,7 +356,7 @@ def repo():
|
|
|
349
356
|
|
|
350
357
|
agent = Agent(session="latest", voice_enabled=False)
|
|
351
358
|
agent.add_command(repo)
|
|
352
|
-
print(agent("/repo"))
|
|
359
|
+
print(agent("/repo").result)
|
|
353
360
|
```
|
|
354
361
|
|
|
355
362
|
### Add stateful plugins
|
|
@@ -544,8 +551,11 @@ The default agent exposes local tools and plugin tools to the model. Plugin tool
|
|
|
544
551
|
| Scheduler plugin | `scheduler_schedule`, `scheduler_cancel`, `scheduler_list`, `scheduler_restart_and_wakeup` | Future turns, periodic wakeups, post-restart continuation. |
|
|
545
552
|
| Browser plugin | `browser_open`, `browser_goto`, `browser_click`, `browser_fill`, `browser_press`, ... | Persistent Playwright/Chromium automation with active-tab context. |
|
|
546
553
|
| Desktop plugin | `desktop_start_session`, `desktop_run_commands`, `desktop_stop_session` | Screenshot-backed Linux desktop automation. |
|
|
554
|
+
| Subagents plugin | `subagents_run` | Run an ephemeral child agent from a predefined profile and return a compact structured result. |
|
|
547
555
|
|
|
548
|
-
Built-ins are intentionally packaged as plugins. Current built-in plugin modules include `files`, `content`, `bash`, `python`, `interface`, `environment`, `memory`, `planner`, `scheduler`, `browser`, and `
|
|
556
|
+
Built-ins are intentionally packaged as plugins. Current built-in plugin modules include `files`, `content`, `bash`, `python`, `interface`, `environment`, `memory`, `planner`, `scheduler`, `browser`, `desktop`, and `subagents`.
|
|
557
|
+
|
|
558
|
+
The `subagents` plugin ships profile JSON files inside the package, starting with `explorer`, a read-only codebase inspection agent. Parent agents choose an existing profile and task; child agents receive their own config, tools, prompt, and temporary session instead of inheriting the parent's runtime implicitly.
|
|
549
559
|
|
|
550
560
|
Built-in plugins are configurable. `None` means load all plugins, an empty list means load none, and an explicit list selects specific plugin module names:
|
|
551
561
|
|
|
@@ -654,8 +664,11 @@ Useful exported events include:
|
|
|
654
664
|
- `ToolCallStartEvent` / `ToolCallDoneEvent`
|
|
655
665
|
- `SessionLoadedEvent` / `SessionDeletedEvent`
|
|
656
666
|
- `AssistantInterruptedEvent`
|
|
667
|
+
- `SubagentEvent`
|
|
657
668
|
- `AudioPlaybackEvent`
|
|
658
669
|
|
|
670
|
+
Messages and events expose hierarchical `types` as well as the final computed `type`, so listeners can subscribe to broad classes such as all events or to precise concrete event types.
|
|
671
|
+
|
|
659
672
|
Plugins can also register event and hook handlers with decorators:
|
|
660
673
|
|
|
661
674
|
```python
|
|
@@ -784,13 +797,13 @@ The tests isolate `AGENT_RUNTIME_DIR` automatically, so they should not create o
|
|
|
784
797
|
The current tree validates at:
|
|
785
798
|
|
|
786
799
|
```text
|
|
787
|
-
|
|
800
|
+
489 passed
|
|
788
801
|
```
|
|
789
802
|
|
|
790
|
-
The published `0.1.
|
|
803
|
+
The published `0.1.22` release was validated at:
|
|
791
804
|
|
|
792
805
|
```text
|
|
793
|
-
|
|
806
|
+
489 passed
|
|
794
807
|
```
|
|
795
808
|
|
|
796
809
|
## Packaging
|
|
@@ -808,6 +821,8 @@ The distribution includes prompt text files, `codex_agent/get_text/default_gitig
|
|
|
808
821
|
|
|
809
822
|
## Recent changes
|
|
810
823
|
|
|
824
|
+
- `0.1.22`: harden FastAPI/SSE and TUI streaming after a stabilization audit, including finite SSE read timeouts, stale-subscriber shutdown, persisted turn-event locking, synchronous replay delta flushes, process-runtime startup guards, and isolated event handlers.
|
|
825
|
+
- `0.1.21`: add structured `AgentTurn` returns with messages/events, resumable non-terminal turns for `auto_proceed=False`, profile-based subagents, hierarchical message/event types, and internal wakeups as developer messages.
|
|
811
826
|
- `0.1.20`: make runtime plugins the single user-facing extension unit for tools/providers/commands, remove legacy direct runtime tool/provider loading, split tool/provider managers, and keep system-prompt templating on an explicit minimal namespace.
|
|
812
827
|
- `0.1.19`: prune compacted raw session history after compaction, keep only the latest compaction anchor plus the new compaction and any unfinished remainder, and drop older redundant compaction summaries from active session files.
|
|
813
828
|
- `0.1.18`: make `start server/tray` detach by default, move durable memory fully into the memory plugin, keep wakeups as a core runtime primitive, expose RAG memory timestamps/sources, and move browser/desktop backend controllers into core modules with plugins as facades.
|
|
@@ -27,6 +27,7 @@ from .event import (
|
|
|
27
27
|
ResponseToolCallsDeltaEvent,
|
|
28
28
|
ServerToolCallEvent,
|
|
29
29
|
SessionDeletedEvent,
|
|
30
|
+
SubagentEvent,
|
|
30
31
|
SessionLoadedEvent,
|
|
31
32
|
ToolCallDoneEvent,
|
|
32
33
|
ToolCallStartEvent,
|
|
@@ -48,13 +49,14 @@ from .message import (
|
|
|
48
49
|
from .image import ImageMessage
|
|
49
50
|
from .mainloop import MainLoopManager
|
|
50
51
|
from .plugin import Plugin, PluginsManager, event_handler, hook_handler
|
|
51
|
-
from .command import AgentCommand, AgentFuture, CommandManager, command
|
|
52
|
+
from .command import AgentCommand, AgentFuture, AgentTurn, CommandManager, command
|
|
52
53
|
from .provider import ProvidersManager, provider
|
|
53
54
|
from .runtime import RuntimeManager
|
|
54
55
|
from .sessions import AgentSession, SessionsManager
|
|
55
56
|
from .status import StatusManager
|
|
56
57
|
from .tool import ImageGenerationTool, ServerTool, Tool, ToolsManager, WebSearchTool, get_agent, get_current_call_id, tool
|
|
57
58
|
from .worker import SummarizerWorker, TurnSummaryWorker, Worker
|
|
59
|
+
from .version import __version__
|
|
58
60
|
|
|
59
61
|
__all__ = [
|
|
60
62
|
"Agent",
|
|
@@ -87,6 +89,7 @@ __all__ = [
|
|
|
87
89
|
"ResponseToolCallsDeltaEvent",
|
|
88
90
|
"ServerToolCallEvent",
|
|
89
91
|
"SessionDeletedEvent",
|
|
92
|
+
"SubagentEvent",
|
|
90
93
|
"SessionLoadedEvent",
|
|
91
94
|
"ToolCallDoneEvent",
|
|
92
95
|
"ToolCallStartEvent",
|
|
@@ -111,6 +114,7 @@ __all__ = [
|
|
|
111
114
|
"ProvidersManager",
|
|
112
115
|
"AgentCommand",
|
|
113
116
|
"AgentFuture",
|
|
117
|
+
"AgentTurn",
|
|
114
118
|
"CommandManager",
|
|
115
119
|
"command",
|
|
116
120
|
"provider",
|
|
@@ -129,4 +133,5 @@ __all__ = [
|
|
|
129
133
|
"SummarizerWorker",
|
|
130
134
|
"TurnSummaryWorker",
|
|
131
135
|
"Worker",
|
|
136
|
+
"__version__",
|
|
132
137
|
]
|
|
@@ -14,7 +14,7 @@ from .scheduler import AgentScheduler
|
|
|
14
14
|
from .sessions import SessionsManager
|
|
15
15
|
from .status import StatusManager
|
|
16
16
|
from .tool import ImageGenerationTool, ToolsManager, reset_current_agent, set_current_agent
|
|
17
|
-
from .ai import
|
|
17
|
+
from .ai import AIClient
|
|
18
18
|
from .voice import VoiceProcessor
|
|
19
19
|
from .latex import LaTeXProcessor
|
|
20
20
|
from .event import AssistantInterruptRequestedEvent, AssistantInterrupted, AssistantInterruptedEvent, AudioPlaybackEvent, EventBus
|
|
@@ -71,6 +71,7 @@ class Agent:
|
|
|
71
71
|
self.plugins_manager.init_runtime()
|
|
72
72
|
self.command_manager.init_runtime()
|
|
73
73
|
self.tools_manager.init_server_tools()
|
|
74
|
+
self.tools_manager.apply_config_exclusions()
|
|
74
75
|
self.start_new_session() if session == "new" else self.load_session(session)
|
|
75
76
|
|
|
76
77
|
def on(self, event_type, handler=None):
|
|
@@ -82,7 +83,11 @@ class Agent:
|
|
|
82
83
|
return self.events.on(event_type, handler)
|
|
83
84
|
|
|
84
85
|
def emit(self, event_type, **data):
|
|
85
|
-
|
|
86
|
+
event = self.events.emit(event_type, **data)
|
|
87
|
+
mainloop_manager = getattr(self, "mainloop_manager", None)
|
|
88
|
+
if mainloop_manager is not None:
|
|
89
|
+
mainloop_manager.record_event(event)
|
|
90
|
+
return event
|
|
86
91
|
|
|
87
92
|
@property
|
|
88
93
|
def busy(self):
|
|
@@ -104,28 +109,35 @@ class Agent:
|
|
|
104
109
|
def start_turn(self):
|
|
105
110
|
return self.mainloop_manager.start_turn()
|
|
106
111
|
|
|
112
|
+
def resume_turn(self, turn):
|
|
113
|
+
future = self.mainloop_manager.resume_turn(turn)
|
|
114
|
+
return None if future is None else future.wait()
|
|
115
|
+
|
|
107
116
|
def submit_command(self, prompt):
|
|
108
117
|
return self.command_manager.submit(prompt)
|
|
109
118
|
|
|
110
119
|
def submit_message(self, message):
|
|
111
120
|
return self.mainloop_manager.submit_message(message)
|
|
112
121
|
|
|
122
|
+
def set_turn_result(self, data):
|
|
123
|
+
return self.mainloop_manager.set_turn_result(data)
|
|
124
|
+
|
|
113
125
|
def list_wakeups(self, include_done=True):
|
|
114
126
|
return self.scheduler.list(include_done=include_done)
|
|
115
127
|
|
|
116
128
|
def schedule_wakeup(self, **kwargs):
|
|
117
129
|
if self.mainloop_manager.should_queue_state_command():
|
|
118
|
-
return self.submit("schedule_wakeup", **kwargs).wait()
|
|
130
|
+
return self.submit("schedule_wakeup", **kwargs).wait().result
|
|
119
131
|
return self.scheduler.schedule(**kwargs)
|
|
120
132
|
|
|
121
133
|
def cancel_wakeup(self, job_id):
|
|
122
134
|
if self.mainloop_manager.should_queue_state_command():
|
|
123
|
-
return self.submit("cancel_wakeup", job_id=job_id).wait()
|
|
135
|
+
return self.submit("cancel_wakeup", job_id=job_id).wait().result
|
|
124
136
|
return self.scheduler.cancel(job_id)
|
|
125
137
|
|
|
126
138
|
def delete_wakeup(self, job_id):
|
|
127
139
|
if self.mainloop_manager.should_queue_state_command():
|
|
128
|
-
return self.submit("delete_wakeup", job_id=job_id).wait()
|
|
140
|
+
return self.submit("delete_wakeup", job_id=job_id).wait().result
|
|
129
141
|
return self.scheduler.delete(job_id)
|
|
130
142
|
|
|
131
143
|
def interrupt(self, reason="user"):
|
|
@@ -256,7 +268,7 @@ class Agent:
|
|
|
256
268
|
return decorator
|
|
257
269
|
|
|
258
270
|
if hasattr(self, "mainloop_manager") and self.mainloop_manager.should_queue_state_command():
|
|
259
|
-
return self.submit("add_hook", key=key, func=func).wait()
|
|
271
|
+
return self.submit("add_hook", key=key, func=func).wait().result
|
|
260
272
|
|
|
261
273
|
return self.hooks.add(key, func)
|
|
262
274
|
|
|
@@ -327,6 +339,10 @@ class Agent:
|
|
|
327
339
|
Returns:
|
|
328
340
|
Message: The aggregated assistant message with content and/or tool calls.
|
|
329
341
|
"""
|
|
342
|
+
if self.session and not self.session.is_sane():
|
|
343
|
+
repair = self.session.repair()
|
|
344
|
+
if repair.repaired:
|
|
345
|
+
self.status_manager.invalidate_context_cache()
|
|
330
346
|
messages = self.context_manager.get_context()
|
|
331
347
|
if self.context_manager.should_auto_compact(messages):
|
|
332
348
|
self.compact_session(
|
|
@@ -335,21 +351,16 @@ class Agent:
|
|
|
335
351
|
)
|
|
336
352
|
messages = self.context_manager.get_context()
|
|
337
353
|
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
)
|
|
345
|
-
except AIBadRequestError:
|
|
346
|
-
self.sessions_manager.restore_api_success_backup()
|
|
347
|
-
raise
|
|
354
|
+
message=self.ai.run(
|
|
355
|
+
messages=messages,
|
|
356
|
+
tools=self.tools_manager.get_response_tools(),
|
|
357
|
+
prompt_cache_key=self.current_session_id,
|
|
358
|
+
**self.config.extract('model','reasoning_effort','verbosity','parallel_tool_calls')
|
|
359
|
+
)
|
|
348
360
|
self.sessions_manager.append_message(message)
|
|
349
361
|
for item in message.output_items:
|
|
350
362
|
if self.tools_manager.server_tool_for_item(item):
|
|
351
363
|
self.sessions_manager.append_message(ServerToolResponseMessage(item=item))
|
|
352
|
-
self.sessions_manager.save_api_success_backup()
|
|
353
364
|
return message
|
|
354
365
|
|
|
355
366
|
def speak(self,text,**kwargs):
|
|
@@ -431,7 +442,7 @@ class Agent:
|
|
|
431
442
|
|
|
432
443
|
return dest_path
|
|
433
444
|
|
|
434
|
-
def __call__(self,prompt=None)
|
|
445
|
+
def __call__(self, prompt=None):
|
|
435
446
|
return self.mainloop_manager.call(prompt=prompt)
|
|
436
447
|
|
|
437
448
|
def interact(self):
|
|
@@ -262,6 +262,8 @@ class ProcessAgentRuntime(AgentRuntime):
|
|
|
262
262
|
self.event_handlers = []
|
|
263
263
|
self.pending = {}
|
|
264
264
|
self.pending_lock = threading.Lock()
|
|
265
|
+
self.start_lock = threading.RLock()
|
|
266
|
+
self.starting = False
|
|
265
267
|
self.running = threading.Event()
|
|
266
268
|
self.cache = modict(
|
|
267
269
|
busy=False,
|
|
@@ -277,24 +279,28 @@ class ProcessAgentRuntime(AgentRuntime):
|
|
|
277
279
|
)
|
|
278
280
|
|
|
279
281
|
def start(self):
|
|
280
|
-
|
|
282
|
+
with self.start_lock:
|
|
283
|
+
if self.process and self.process.is_alive():
|
|
284
|
+
return self
|
|
285
|
+
self.starting = True
|
|
286
|
+
self.running.set()
|
|
287
|
+
self.process = self.context.Process(
|
|
288
|
+
target=agent_worker_main,
|
|
289
|
+
args=(self.command_queue, self.response_queue, self.event_queue, self.agent_kwargs),
|
|
290
|
+
name="codex-agent-worker",
|
|
291
|
+
daemon=True,
|
|
292
|
+
)
|
|
293
|
+
self.process.start()
|
|
294
|
+
self.event_thread = threading.Thread(target=self._event_loop, name="agent-runtime-events", daemon=True)
|
|
295
|
+
self.event_thread.start()
|
|
296
|
+
try:
|
|
297
|
+
self.call("start", timeout=self.command_timeout, autostart=False)
|
|
298
|
+
self.refresh_cache()
|
|
299
|
+
except Exception:
|
|
300
|
+
pass
|
|
301
|
+
finally:
|
|
302
|
+
self.starting = False
|
|
281
303
|
return self
|
|
282
|
-
self.running.set()
|
|
283
|
-
self.process = self.context.Process(
|
|
284
|
-
target=agent_worker_main,
|
|
285
|
-
args=(self.command_queue, self.response_queue, self.event_queue, self.agent_kwargs),
|
|
286
|
-
name="codex-agent-worker",
|
|
287
|
-
daemon=True,
|
|
288
|
-
)
|
|
289
|
-
self.process.start()
|
|
290
|
-
self.event_thread = threading.Thread(target=self._event_loop, name="agent-runtime-events", daemon=True)
|
|
291
|
-
self.event_thread.start()
|
|
292
|
-
try:
|
|
293
|
-
self.call("start", timeout=self.command_timeout)
|
|
294
|
-
self.refresh_cache()
|
|
295
|
-
except Exception:
|
|
296
|
-
pass
|
|
297
|
-
return self
|
|
298
304
|
|
|
299
305
|
def stop(self, timeout=None):
|
|
300
306
|
timeout = timeout or 2.0
|
|
@@ -332,14 +338,14 @@ class ProcessAgentRuntime(AgentRuntime):
|
|
|
332
338
|
self.cache[key] = self.call(command, timeout=self.status_timeout)
|
|
333
339
|
except Exception:
|
|
334
340
|
pass
|
|
335
|
-
|
|
336
|
-
self.cache.busy = bool(status.get("busy", self.cache.busy))
|
|
337
|
-
self.cache.current_turn_id = status.get("current_turn_id", self.cache.current_turn_id)
|
|
338
|
-
self.cache.current_session_id = status.get("session_id", self.cache.current_session_id)
|
|
341
|
+
self.update_status_cache(self.cache.get("status") or {})
|
|
339
342
|
return self.cache
|
|
340
343
|
|
|
341
|
-
def call(self, name, payload=None, timeout=None):
|
|
342
|
-
|
|
344
|
+
def call(self, name, payload=None, timeout=None, autostart=True):
|
|
345
|
+
if not (self.process and self.process.is_alive()):
|
|
346
|
+
if not autostart or self.starting:
|
|
347
|
+
raise AgentRuntimeError("agent worker process is not running")
|
|
348
|
+
self.start()
|
|
343
349
|
command_id = str(uuid.uuid4())
|
|
344
350
|
future = _RuntimeFuture(command_id)
|
|
345
351
|
with self.pending_lock:
|
|
@@ -377,24 +383,39 @@ class ProcessAgentRuntime(AgentRuntime):
|
|
|
377
383
|
else:
|
|
378
384
|
future.set_error(AgentRuntimeError(response.get("error") or "agent worker command failed"))
|
|
379
385
|
|
|
386
|
+
def update_status_cache(self, status):
|
|
387
|
+
status = modict(status or {})
|
|
388
|
+
self.cache.status = status
|
|
389
|
+
self.cache.busy = bool(status.get("busy", self.cache.busy))
|
|
390
|
+
self.cache.current_turn_id = status.get("current_turn_id", self.cache.current_turn_id)
|
|
391
|
+
self.cache.current_session_id = status.get("session_id", self.cache.current_session_id)
|
|
392
|
+
return status
|
|
393
|
+
|
|
394
|
+
def mark_turn_started(self, turn_id=None):
|
|
395
|
+
self.cache.busy = True
|
|
396
|
+
if turn_id is not None:
|
|
397
|
+
self.cache.current_turn_id = turn_id
|
|
398
|
+
|
|
399
|
+
def mark_turn_finished(self):
|
|
400
|
+
self.cache.busy = False
|
|
401
|
+
self.cache.current_turn_id = None
|
|
402
|
+
|
|
380
403
|
def _handle_event(self, event):
|
|
381
404
|
event_type = event.get("type")
|
|
382
405
|
if event_type == "assistant_turn_start_event":
|
|
383
|
-
self.
|
|
406
|
+
self.mark_turn_started(event.get("turn_id"))
|
|
384
407
|
elif event_type in ("assistant_turn_end_event", "assistant_turn_error_event"):
|
|
385
|
-
self.
|
|
386
|
-
self.cache.current_turn_id = None
|
|
408
|
+
self.mark_turn_finished()
|
|
387
409
|
elif event_type == "session_loaded_event":
|
|
388
410
|
self.cache.current_session_id = event.get("session_id")
|
|
389
411
|
self.cache.session = event.get("session") or self.cache.session
|
|
390
412
|
elif event_type == "compaction_completed_event" and event.get("status"):
|
|
391
|
-
|
|
392
|
-
self.cache.status = status
|
|
393
|
-
self.cache.busy = bool(status.get("busy", self.cache.busy))
|
|
394
|
-
self.cache.current_turn_id = status.get("current_turn_id", self.cache.current_turn_id)
|
|
395
|
-
self.cache.current_session_id = status.get("session_id", self.cache.current_session_id)
|
|
413
|
+
self.update_status_cache(event.status)
|
|
396
414
|
for handler in list(self.event_handlers):
|
|
397
|
-
|
|
415
|
+
try:
|
|
416
|
+
handler(event)
|
|
417
|
+
except Exception:
|
|
418
|
+
continue
|
|
398
419
|
|
|
399
420
|
@property
|
|
400
421
|
def busy(self):
|
|
@@ -410,12 +431,7 @@ class ProcessAgentRuntime(AgentRuntime):
|
|
|
410
431
|
|
|
411
432
|
def get_status(self):
|
|
412
433
|
try:
|
|
413
|
-
|
|
414
|
-
self.cache.status = status
|
|
415
|
-
self.cache.busy = bool(status.get("busy", self.cache.busy))
|
|
416
|
-
self.cache.current_turn_id = status.get("current_turn_id", self.cache.current_turn_id)
|
|
417
|
-
self.cache.current_session_id = status.get("session_id", self.cache.current_session_id)
|
|
418
|
-
return status
|
|
434
|
+
return self.update_status_cache(self.call("get_status", timeout=self.status_timeout))
|
|
419
435
|
except Exception:
|
|
420
436
|
status = modict(self.cache.status or {})
|
|
421
437
|
status.setdefault("busy", self.cache.busy)
|
|
@@ -429,7 +445,7 @@ class ProcessAgentRuntime(AgentRuntime):
|
|
|
429
445
|
payload = dict(values or {})
|
|
430
446
|
payload.update(kwargs)
|
|
431
447
|
result = self.call("update_config", {"values": payload, "save": save}, timeout=self.command_timeout)
|
|
432
|
-
self.cache
|
|
448
|
+
self.cache["config"] = result
|
|
433
449
|
return result
|
|
434
450
|
|
|
435
451
|
def session(self):
|
|
@@ -478,8 +494,7 @@ class ProcessAgentRuntime(AgentRuntime):
|
|
|
478
494
|
return None
|
|
479
495
|
turn_id = self.call("start_turn", timeout=1.0)
|
|
480
496
|
if turn_id is not None:
|
|
481
|
-
self.
|
|
482
|
-
self.cache.current_turn_id = turn_id
|
|
497
|
+
self.mark_turn_started(turn_id)
|
|
483
498
|
return turn_id
|
|
484
499
|
|
|
485
500
|
def submit_command(self, prompt):
|
|
@@ -487,16 +502,14 @@ class ProcessAgentRuntime(AgentRuntime):
|
|
|
487
502
|
return None
|
|
488
503
|
turn_id = self.call("submit_command", {"prompt": prompt}, timeout=1.0)
|
|
489
504
|
if turn_id is not None:
|
|
490
|
-
self.
|
|
491
|
-
self.cache.current_turn_id = turn_id
|
|
505
|
+
self.mark_turn_started(turn_id)
|
|
492
506
|
return turn_id
|
|
493
507
|
|
|
494
508
|
def submit_message(self, message):
|
|
495
509
|
result = self.call("submit_message", {"message": message}, timeout=1.0)
|
|
496
510
|
turn_id = result.get("turn_id") if isinstance(result, dict) else None
|
|
497
511
|
if turn_id is not None:
|
|
498
|
-
self.
|
|
499
|
-
self.cache.current_turn_id = turn_id
|
|
512
|
+
self.mark_turn_started(turn_id)
|
|
500
513
|
return result
|
|
501
514
|
|
|
502
515
|
def schedule_wakeup(self, **kwargs):
|
|
@@ -370,6 +370,7 @@ You can manage memory explicitly with the memory tools:
|
|
|
370
370
|
Use your memory tools judiciously and proactively to create durable records of important information that should persist beyond the current session.
|
|
371
371
|
Do not over-memorize routine exchanges, transient implementation details, or information that is only useful within the current turn.
|
|
372
372
|
Prefer durable facts, preferences, decisions, and important outcomes.
|
|
373
|
+
Memory entries should be rather short (one paragraph) and semantically well scoped for more efficient retrieval.
|
|
373
374
|
Keep your memory tidy and up to date by editing or deleting outdated or irrelevant entries.
|
|
374
375
|
When automatic memory archiving is enabled, completed turns are summarized into memory in the background when they contain something worth remembering.
|
|
375
376
|
"""
|
|
@@ -469,7 +470,7 @@ When automatic memory archiving is enabled, completed turns are summarized into
|
|
|
469
470
|
|
|
470
471
|
@event_handler(AssistantTurnEndEvent)
|
|
471
472
|
def archive_completed_turn(self, event):
|
|
472
|
-
if event.get("
|
|
473
|
+
if event.get("reason") != "completed":
|
|
473
474
|
return None
|
|
474
475
|
if not self.config.auto_archive:
|
|
475
476
|
return None
|