codex-agent-framework 0.1.23__tar.gz → 0.1.25__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.23 → codex_agent_framework-0.1.25}/CHANGELOG.md +23 -0
- {codex_agent_framework-0.1.23/codex_agent_framework.egg-info → codex_agent_framework-0.1.25}/PKG-INFO +5 -3
- {codex_agent_framework-0.1.23 → codex_agent_framework-0.1.25}/README.md +4 -2
- {codex_agent_framework-0.1.23 → codex_agent_framework-0.1.25}/codex_agent/__init__.py +23 -3
- {codex_agent_framework-0.1.23 → codex_agent_framework-0.1.25}/codex_agent/agent.py +65 -74
- {codex_agent_framework-0.1.23 → codex_agent_framework-0.1.25}/codex_agent/ai.py +41 -2
- {codex_agent_framework-0.1.23 → codex_agent_framework-0.1.25}/codex_agent/builtin_commands.py +7 -21
- {codex_agent_framework-0.1.23 → codex_agent_framework-0.1.25}/codex_agent/builtin_plugins/bash/__init__.py +7 -0
- codex_agent_framework-0.1.25/codex_agent/builtin_plugins/bash/requirements.txt +1 -0
- codex_agent_framework-0.1.25/codex_agent/builtin_plugins/browser/requirements.txt +2 -0
- {codex_agent_framework-0.1.23 → codex_agent_framework-0.1.25}/codex_agent/builtin_plugins/content/__init__.py +10 -0
- codex_agent_framework-0.1.25/codex_agent/builtin_plugins/content/requirements.txt +11 -0
- codex_agent_framework-0.1.25/codex_agent/builtin_plugins/desktop/requirements.txt +4 -0
- codex_agent_framework-0.1.25/codex_agent/builtin_plugins/environment/__init__.py +285 -0
- codex_agent_framework-0.1.25/codex_agent/builtin_plugins/environment/requirements.txt +1 -0
- codex_agent_framework-0.1.25/codex_agent/builtin_plugins/files/__init__.py +40 -0
- codex_agent_framework-0.1.25/codex_agent/builtin_plugins/files/requirements.txt +10 -0
- codex_agent_framework-0.1.25/codex_agent/builtin_plugins/image_generation/__init__.py +75 -0
- codex_agent_framework-0.1.25/codex_agent/builtin_plugins/image_generation/requirements.txt +3 -0
- codex_agent_framework-0.1.25/codex_agent/builtin_plugins/interface/requirements.txt +1 -0
- codex_agent_framework-0.1.25/codex_agent/builtin_plugins/memory/requirements.txt +2 -0
- codex_agent_framework-0.1.25/codex_agent/builtin_plugins/planner/requirements.txt +1 -0
- {codex_agent_framework-0.1.23 → codex_agent_framework-0.1.25}/codex_agent/builtin_plugins/python/__init__.py +9 -0
- codex_agent_framework-0.1.25/codex_agent/builtin_plugins/python/requirements.txt +2 -0
- codex_agent_framework-0.1.25/codex_agent/builtin_plugins/realtime/__init__.py +131 -0
- codex_agent_framework-0.1.25/codex_agent/builtin_plugins/realtime/audio.py +382 -0
- codex_agent_framework-0.1.25/codex_agent/builtin_plugins/realtime/bridge.py +340 -0
- codex_agent_framework-0.1.25/codex_agent/builtin_plugins/realtime/manager.py +263 -0
- codex_agent_framework-0.1.25/codex_agent/builtin_plugins/realtime/requirements.txt +6 -0
- codex_agent_framework-0.1.25/codex_agent/builtin_plugins/realtime/session.py +275 -0
- codex_agent_framework-0.1.25/codex_agent/builtin_plugins/scheduler/requirements.txt +1 -0
- {codex_agent_framework-0.1.23 → codex_agent_framework-0.1.25}/codex_agent/builtin_plugins/subagents/__init__.py +2 -1
- {codex_agent_framework-0.1.23 → codex_agent_framework-0.1.25}/codex_agent/builtin_plugins/subagents/profiles/explorer.json +1 -2
- codex_agent_framework-0.1.25/codex_agent/builtin_plugins/subagents/requirements.txt +1 -0
- codex_agent_framework-0.1.25/codex_agent/builtin_plugins/tts/__init__.py +330 -0
- codex_agent_framework-0.1.25/codex_agent/builtin_plugins/tts/requirements.txt +4 -0
- {codex_agent_framework-0.1.23 → codex_agent_framework-0.1.25}/codex_agent/cli/main.py +0 -1
- {codex_agent_framework-0.1.23 → codex_agent_framework-0.1.25}/codex_agent/command.py +39 -13
- codex_agent_framework-0.1.25/codex_agent/config.py +257 -0
- {codex_agent_framework-0.1.23 → codex_agent_framework-0.1.25}/codex_agent/event.py +100 -2
- {codex_agent_framework-0.1.23 → codex_agent_framework-0.1.25}/codex_agent/hooks.py +25 -3
- {codex_agent_framework-0.1.23 → codex_agent_framework-0.1.25}/codex_agent/mainloop.py +75 -3
- codex_agent_framework-0.1.25/codex_agent/plugin.py +559 -0
- codex_agent_framework-0.1.25/codex_agent/prompts/system_prompt.txt +55 -0
- {codex_agent_framework-0.1.23 → codex_agent_framework-0.1.25}/codex_agent/provider.py +27 -9
- {codex_agent_framework-0.1.23 → codex_agent_framework-0.1.25}/codex_agent/server/core.py +34 -2
- {codex_agent_framework-0.1.23 → codex_agent_framework-0.1.25}/codex_agent/sessions.py +64 -13
- {codex_agent_framework-0.1.23 → codex_agent_framework-0.1.25}/codex_agent/status.py +5 -0
- {codex_agent_framework-0.1.23 → codex_agent_framework-0.1.25}/codex_agent/tool.py +34 -29
- {codex_agent_framework-0.1.23 → codex_agent_framework-0.1.25}/codex_agent/tui/chat.py +211 -10
- codex_agent_framework-0.1.25/codex_agent/version.py +1 -0
- {codex_agent_framework-0.1.23 → codex_agent_framework-0.1.25/codex_agent_framework.egg-info}/PKG-INFO +5 -3
- {codex_agent_framework-0.1.23 → codex_agent_framework-0.1.25}/codex_agent_framework.egg-info/SOURCES.txt +23 -2
- {codex_agent_framework-0.1.23 → codex_agent_framework-0.1.25}/pyproject.toml +2 -2
- {codex_agent_framework-0.1.23 → codex_agent_framework-0.1.25}/tests/test_agent.py +851 -29
- {codex_agent_framework-0.1.23 → codex_agent_framework-0.1.25}/tests/test_ai.py +44 -1
- {codex_agent_framework-0.1.23 → codex_agent_framework-0.1.25}/tests/test_chat.py +165 -1
- {codex_agent_framework-0.1.23 → codex_agent_framework-0.1.25}/tests/test_cli_headless.py +2 -2
- {codex_agent_framework-0.1.23 → codex_agent_framework-0.1.25}/tests/test_server.py +21 -1
- codex_agent_framework-0.1.23/codex_agent/builtin_plugins/environment/__init__.py +0 -21
- codex_agent_framework-0.1.23/codex_agent/builtin_plugins/files/__init__.py +0 -28
- codex_agent_framework-0.1.23/codex_agent/config.py +0 -172
- codex_agent_framework-0.1.23/codex_agent/plugin.py +0 -248
- codex_agent_framework-0.1.23/codex_agent/prompts/system_prompt.txt +0 -83
- codex_agent_framework-0.1.23/codex_agent/version.py +0 -1
- codex_agent_framework-0.1.23/codex_agent/voice.py +0 -362
- {codex_agent_framework-0.1.23 → codex_agent_framework-0.1.25}/LICENSE +0 -0
- {codex_agent_framework-0.1.23 → codex_agent_framework-0.1.25}/MANIFEST.in +0 -0
- {codex_agent_framework-0.1.23 → codex_agent_framework-0.1.25}/codex_agent/__main__.py +0 -0
- {codex_agent_framework-0.1.23 → codex_agent_framework-0.1.25}/codex_agent/agent_runtime.py +0 -0
- {codex_agent_framework-0.1.23 → codex_agent_framework-0.1.25}/codex_agent/browser.py +0 -0
- {codex_agent_framework-0.1.23 → codex_agent_framework-0.1.25}/codex_agent/builtin_plugins/__init__.py +0 -0
- {codex_agent_framework-0.1.23 → codex_agent_framework-0.1.25}/codex_agent/builtin_plugins/browser/__init__.py +0 -0
- {codex_agent_framework-0.1.23 → codex_agent_framework-0.1.25}/codex_agent/builtin_plugins/content/system.py +0 -0
- {codex_agent_framework-0.1.23 → codex_agent_framework-0.1.25}/codex_agent/builtin_plugins/content/vision.py +0 -0
- {codex_agent_framework-0.1.23 → codex_agent_framework-0.1.25}/codex_agent/builtin_plugins/desktop/__init__.py +0 -0
- {codex_agent_framework-0.1.23 → codex_agent_framework-0.1.25}/codex_agent/builtin_plugins/files/tools.py +0 -0
- {codex_agent_framework-0.1.23/codex_agent/prompts → codex_agent_framework-0.1.25/codex_agent/builtin_plugins/image_generation}/image_generation_system_prompt.txt +0 -0
- {codex_agent_framework-0.1.23 → codex_agent_framework-0.1.25}/codex_agent/builtin_plugins/interface/__init__.py +0 -0
- {codex_agent_framework-0.1.23 → codex_agent_framework-0.1.25}/codex_agent/builtin_plugins/memory/__init__.py +0 -0
- {codex_agent_framework-0.1.23 → codex_agent_framework-0.1.25}/codex_agent/builtin_plugins/planner/__init__.py +0 -0
- {codex_agent_framework-0.1.23 → codex_agent_framework-0.1.25}/codex_agent/builtin_plugins/scheduler/__init__.py +0 -0
- {codex_agent_framework-0.1.23 → codex_agent_framework-0.1.25}/codex_agent/cli/__init__.py +0 -0
- {codex_agent_framework-0.1.23 → codex_agent_framework-0.1.25}/codex_agent/cli/headless.py +0 -0
- {codex_agent_framework-0.1.23 → codex_agent_framework-0.1.25}/codex_agent/cli/output.py +0 -0
- {codex_agent_framework-0.1.23 → codex_agent_framework-0.1.25}/codex_agent/cli/root.py +0 -0
- {codex_agent_framework-0.1.23 → codex_agent_framework-0.1.25}/codex_agent/cli/runner.py +0 -0
- {codex_agent_framework-0.1.23 → codex_agent_framework-0.1.25}/codex_agent/client.py +0 -0
- {codex_agent_framework-0.1.23 → codex_agent_framework-0.1.25}/codex_agent/context.py +0 -0
- {codex_agent_framework-0.1.23 → codex_agent_framework-0.1.25}/codex_agent/desktop.py +0 -0
- {codex_agent_framework-0.1.23 → codex_agent_framework-0.1.25}/codex_agent/get_text/__init__.py +0 -0
- {codex_agent_framework-0.1.23 → codex_agent_framework-0.1.25}/codex_agent/get_text/default_gitignore +0 -0
- {codex_agent_framework-0.1.23 → codex_agent_framework-0.1.25}/codex_agent/get_text/get_text.py +0 -0
- {codex_agent_framework-0.1.23 → codex_agent_framework-0.1.25}/codex_agent/get_text/simpler_get_text.py +0 -0
- {codex_agent_framework-0.1.23 → codex_agent_framework-0.1.25}/codex_agent/image.py +0 -0
- {codex_agent_framework-0.1.23 → codex_agent_framework-0.1.25}/codex_agent/latex.py +0 -0
- {codex_agent_framework-0.1.23 → codex_agent_framework-0.1.25}/codex_agent/message.py +0 -0
- {codex_agent_framework-0.1.23 → codex_agent_framework-0.1.25}/codex_agent/runtime.py +0 -0
- {codex_agent_framework-0.1.23 → codex_agent_framework-0.1.25}/codex_agent/scheduler.py +0 -0
- {codex_agent_framework-0.1.23 → codex_agent_framework-0.1.25}/codex_agent/scripts/install-system-dependencies.sh +0 -0
- {codex_agent_framework-0.1.23 → codex_agent_framework-0.1.25}/codex_agent/server/__init__.py +0 -0
- {codex_agent_framework-0.1.23 → codex_agent_framework-0.1.25}/codex_agent/server/app.py +0 -0
- {codex_agent_framework-0.1.23 → codex_agent_framework-0.1.25}/codex_agent/service.py +0 -0
- {codex_agent_framework-0.1.23 → codex_agent_framework-0.1.25}/codex_agent/stream.py +0 -0
- {codex_agent_framework-0.1.23 → codex_agent_framework-0.1.25}/codex_agent/stream_utils.py +0 -0
- {codex_agent_framework-0.1.23 → codex_agent_framework-0.1.25}/codex_agent/tray.py +0 -0
- {codex_agent_framework-0.1.23 → codex_agent_framework-0.1.25}/codex_agent/tui/__init__.py +0 -0
- {codex_agent_framework-0.1.23 → codex_agent_framework-0.1.25}/codex_agent/tui/lifecycle.py +0 -0
- {codex_agent_framework-0.1.23 → codex_agent_framework-0.1.25}/codex_agent/utils.py +0 -0
- {codex_agent_framework-0.1.23 → codex_agent_framework-0.1.25}/codex_agent/worker.py +0 -0
- {codex_agent_framework-0.1.23 → codex_agent_framework-0.1.25}/codex_agent_framework.egg-info/dependency_links.txt +0 -0
- {codex_agent_framework-0.1.23 → codex_agent_framework-0.1.25}/codex_agent_framework.egg-info/entry_points.txt +0 -0
- {codex_agent_framework-0.1.23 → codex_agent_framework-0.1.25}/codex_agent_framework.egg-info/requires.txt +0 -0
- {codex_agent_framework-0.1.23 → codex_agent_framework-0.1.25}/codex_agent_framework.egg-info/top_level.txt +0 -0
- {codex_agent_framework-0.1.23 → codex_agent_framework-0.1.25}/dependencies.txt +0 -0
- {codex_agent_framework-0.1.23 → codex_agent_framework-0.1.25}/setup.cfg +0 -0
- {codex_agent_framework-0.1.23 → codex_agent_framework-0.1.25}/tests/test_agent_runtime.py +0 -0
- {codex_agent_framework-0.1.23 → codex_agent_framework-0.1.25}/tests/test_browser.py +0 -0
- {codex_agent_framework-0.1.23 → codex_agent_framework-0.1.25}/tests/test_builtin_config.py +0 -0
- {codex_agent_framework-0.1.23 → codex_agent_framework-0.1.25}/tests/test_cli.py +0 -0
- {codex_agent_framework-0.1.23 → codex_agent_framework-0.1.25}/tests/test_cli_root.py +0 -0
- {codex_agent_framework-0.1.23 → codex_agent_framework-0.1.25}/tests/test_client.py +0 -0
- {codex_agent_framework-0.1.23 → codex_agent_framework-0.1.25}/tests/test_events.py +0 -0
- {codex_agent_framework-0.1.23 → codex_agent_framework-0.1.25}/tests/test_get_text_browser.py +0 -0
- {codex_agent_framework-0.1.23 → codex_agent_framework-0.1.25}/tests/test_hooks.py +0 -0
- {codex_agent_framework-0.1.23 → codex_agent_framework-0.1.25}/tests/test_image_message.py +0 -0
- {codex_agent_framework-0.1.23 → codex_agent_framework-0.1.25}/tests/test_local_desktop.py +0 -0
- {codex_agent_framework-0.1.23 → codex_agent_framework-0.1.25}/tests/test_memory.py +0 -0
- {codex_agent_framework-0.1.23 → codex_agent_framework-0.1.25}/tests/test_messages.py +0 -0
- {codex_agent_framework-0.1.23 → codex_agent_framework-0.1.25}/tests/test_planner.py +0 -0
- {codex_agent_framework-0.1.23 → codex_agent_framework-0.1.25}/tests/test_scheduler.py +0 -0
- {codex_agent_framework-0.1.23 → codex_agent_framework-0.1.25}/tests/test_service.py +0 -0
- {codex_agent_framework-0.1.23 → codex_agent_framework-0.1.25}/tests/test_tray.py +0 -0
- {codex_agent_framework-0.1.23 → codex_agent_framework-0.1.25}/tests/test_tui.py +0 -0
- {codex_agent_framework-0.1.23 → codex_agent_framework-0.1.25}/tests/test_utils.py +0 -0
- {codex_agent_framework-0.1.23 → codex_agent_framework-0.1.25}/tests/test_worker.py +0 -0
|
@@ -4,6 +4,29 @@ 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.25] - 2026-05-12
|
|
8
|
+
### Added
|
|
9
|
+
- Add bundled plugin `requirements.txt` metadata for built-in capabilities and move image generation, realtime voice, and TTS into plugin-scoped packages.
|
|
10
|
+
- Add a selectable Textual TUI conversation pane with mouse scrolling, Ctrl+C selection copy, lazy older-transcript loading, and bottom-aware auto-scroll during streaming.
|
|
11
|
+
|
|
12
|
+
### Changed
|
|
13
|
+
- Continue migrating built-in capability instructions and dependencies toward the plugin-first architecture.
|
|
14
|
+
- Remove legacy voice and prompt files that are now owned by dedicated built-in plugins.
|
|
15
|
+
|
|
16
|
+
### Tests
|
|
17
|
+
- Expand regression coverage across agent/plugin/runtime/chat behavior; the current suite validates at 546 passed.
|
|
18
|
+
|
|
19
|
+
## [0.1.24] - 2026-05-10
|
|
20
|
+
### Added
|
|
21
|
+
- Add dedicated slash-command lifecycle events, `SlashCommandStartEvent` and `SlashCommandDoneEvent`, with command name, arguments, status, result, and error metadata.
|
|
22
|
+
|
|
23
|
+
### Changed
|
|
24
|
+
- Show slash-command progress directly in the Textual TUI with running/done/failed status lines so commands such as `/compact` and `/help` no longer appear silent while executing.
|
|
25
|
+
- Render slash-command results and errors immediately in the TUI after completion.
|
|
26
|
+
|
|
27
|
+
### Tests
|
|
28
|
+
- Add regression coverage for slash-command lifecycle events, failed command reporting, and TUI rendering of command progress, results, and errors.
|
|
29
|
+
|
|
7
30
|
## [0.1.23] - 2026-05-10
|
|
8
31
|
### Added
|
|
9
32
|
- Add the SDK `Agent.stream(prompt=None)` API for iterating turn events while still exposing the final `AgentTurn` through `.turn`.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: codex-agent-framework
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.25
|
|
4
4
|
Summary: A lightweight event-driven Codex agent runtime.
|
|
5
5
|
Author: Baptiste
|
|
6
6
|
License-Expression: MIT
|
|
@@ -567,7 +567,7 @@ logs/ detached server/tray logs
|
|
|
567
567
|
memory.json durable semantic memory entries
|
|
568
568
|
planner.json persistent named todos
|
|
569
569
|
wakeups.json scheduled autonomous wakeups
|
|
570
|
-
|
|
570
|
+
agent.config.json persisted agent configuration
|
|
571
571
|
```
|
|
572
572
|
|
|
573
573
|
Override it with:
|
|
@@ -610,7 +610,7 @@ python -m pytest
|
|
|
610
610
|
The current tree validates at:
|
|
611
611
|
|
|
612
612
|
```text
|
|
613
|
-
|
|
613
|
+
546 passed
|
|
614
614
|
```
|
|
615
615
|
|
|
616
616
|
Build distributions:
|
|
@@ -624,6 +624,8 @@ python -m twine check dist/*
|
|
|
624
624
|
|
|
625
625
|
## Recent releases
|
|
626
626
|
|
|
627
|
+
- `0.1.25`: move built-in capabilities further into plugin-scoped modules, add bundled plugin requirement metadata, and replace the TUI conversation pane with a selectable rich chat area that preserves mouse scrolling, copy selection, lazy transcript loading, and bottom-aware auto-scroll.
|
|
628
|
+
- `0.1.24`: add slash-command lifecycle events and TUI progress/result rendering so commands such as `/compact` and `/help` show running, done, failed, result, and error feedback instead of going silent.
|
|
627
629
|
- `0.1.23`: add SDK event streaming with `Agent.stream()`, root `Agent.add_plugin()`, a faster README flow, the `~/.codex-agent` runtime default, text-first voice defaults, safer prompt templating limited to system messages, smarter `codex-agent` local-server attachment, and clearer TUI tool-call progress lines.
|
|
628
630
|
- `0.1.22`: harden FastAPI/SSE and TUI streaming after a stabilization audit; add finite SSE read timeouts, stale-subscriber shutdown, persisted turn-event locking, synchronous replay delta flushes, process-runtime startup guards, isolated event handlers, and shared version metadata.
|
|
629
631
|
- `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.
|
|
@@ -518,7 +518,7 @@ logs/ detached server/tray logs
|
|
|
518
518
|
memory.json durable semantic memory entries
|
|
519
519
|
planner.json persistent named todos
|
|
520
520
|
wakeups.json scheduled autonomous wakeups
|
|
521
|
-
|
|
521
|
+
agent.config.json persisted agent configuration
|
|
522
522
|
```
|
|
523
523
|
|
|
524
524
|
Override it with:
|
|
@@ -561,7 +561,7 @@ python -m pytest
|
|
|
561
561
|
The current tree validates at:
|
|
562
562
|
|
|
563
563
|
```text
|
|
564
|
-
|
|
564
|
+
546 passed
|
|
565
565
|
```
|
|
566
566
|
|
|
567
567
|
Build distributions:
|
|
@@ -575,6 +575,8 @@ python -m twine check dist/*
|
|
|
575
575
|
|
|
576
576
|
## Recent releases
|
|
577
577
|
|
|
578
|
+
- `0.1.25`: move built-in capabilities further into plugin-scoped modules, add bundled plugin requirement metadata, and replace the TUI conversation pane with a selectable rich chat area that preserves mouse scrolling, copy selection, lazy transcript loading, and bottom-aware auto-scroll.
|
|
579
|
+
- `0.1.24`: add slash-command lifecycle events and TUI progress/result rendering so commands such as `/compact` and `/help` show running, done, failed, result, and error feedback instead of going silent.
|
|
578
580
|
- `0.1.23`: add SDK event streaming with `Agent.stream()`, root `Agent.add_plugin()`, a faster README flow, the `~/.codex-agent` runtime default, text-first voice defaults, safer prompt templating limited to system messages, smarter `codex-agent` local-server attachment, and clearer TUI tool-call progress lines.
|
|
579
581
|
- `0.1.22`: harden FastAPI/SSE and TUI streaming after a stabilization audit; add finite SSE read timeouts, stale-subscriber shutdown, persisted turn-event locking, synchronous replay delta flushes, process-runtime startup guards, isolated event handlers, and shared version metadata.
|
|
580
582
|
- `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.
|
|
@@ -13,6 +13,7 @@ from .event import (
|
|
|
13
13
|
AssistantTurnStartEvent,
|
|
14
14
|
AudioPlaybackEvent,
|
|
15
15
|
CompactionCompletedEvent,
|
|
16
|
+
CompactionFailedEvent,
|
|
16
17
|
CompactionRequestedEvent,
|
|
17
18
|
Event,
|
|
18
19
|
EventBus,
|
|
@@ -25,8 +26,17 @@ from .event import (
|
|
|
25
26
|
ResponseReasoningDeltaEvent,
|
|
26
27
|
ResponseStartEvent,
|
|
27
28
|
ResponseToolCallsDeltaEvent,
|
|
29
|
+
RealtimeApiEvent,
|
|
30
|
+
RealtimeErrorEvent,
|
|
31
|
+
RealtimeSessionRefreshEvent,
|
|
32
|
+
RealtimeStartedEvent,
|
|
33
|
+
RealtimeStartingEvent,
|
|
34
|
+
RealtimeStoppedEvent,
|
|
35
|
+
RuntimeStateChangedEvent,
|
|
28
36
|
ServerToolCallEvent,
|
|
29
37
|
SessionDeletedEvent,
|
|
38
|
+
SlashCommandDoneEvent,
|
|
39
|
+
SlashCommandStartEvent,
|
|
30
40
|
SubagentEvent,
|
|
31
41
|
SessionLoadedEvent,
|
|
32
42
|
ToolCallDoneEvent,
|
|
@@ -48,14 +58,14 @@ from .message import (
|
|
|
48
58
|
)
|
|
49
59
|
from .image import ImageMessage
|
|
50
60
|
from .mainloop import MainLoopManager
|
|
51
|
-
from .plugin import Plugin, PluginsManager, event_handler, hook_handler
|
|
61
|
+
from .plugin import Plugin, PluginsManager, event_handler, hook_handler, stream_processor
|
|
52
62
|
from .command import AgentCommand, AgentFuture, AgentTurn, CommandManager, command
|
|
53
63
|
from .stream import AgentStream
|
|
54
64
|
from .provider import ProvidersManager, provider
|
|
55
65
|
from .runtime import RuntimeManager
|
|
56
66
|
from .sessions import AgentSession, SessionsManager
|
|
57
67
|
from .status import StatusManager
|
|
58
|
-
from .tool import
|
|
68
|
+
from .tool import ServerTool, Tool, ToolsManager, WebSearchTool, get_agent, get_current_call_id, tool
|
|
59
69
|
from .worker import SummarizerWorker, TurnSummaryWorker, Worker
|
|
60
70
|
from .version import __version__
|
|
61
71
|
|
|
@@ -76,6 +86,7 @@ __all__ = [
|
|
|
76
86
|
"AssistantTurnStartEvent",
|
|
77
87
|
"AudioPlaybackEvent",
|
|
78
88
|
"CompactionCompletedEvent",
|
|
89
|
+
"CompactionFailedEvent",
|
|
79
90
|
"CompactionRequestedEvent",
|
|
80
91
|
"Event",
|
|
81
92
|
"EventBus",
|
|
@@ -88,8 +99,17 @@ __all__ = [
|
|
|
88
99
|
"ResponseReasoningDeltaEvent",
|
|
89
100
|
"ResponseStartEvent",
|
|
90
101
|
"ResponseToolCallsDeltaEvent",
|
|
102
|
+
"RealtimeApiEvent",
|
|
103
|
+
"RealtimeErrorEvent",
|
|
104
|
+
"RealtimeSessionRefreshEvent",
|
|
105
|
+
"RealtimeStartedEvent",
|
|
106
|
+
"RealtimeStartingEvent",
|
|
107
|
+
"RealtimeStoppedEvent",
|
|
108
|
+
"RuntimeStateChangedEvent",
|
|
91
109
|
"ServerToolCallEvent",
|
|
92
110
|
"SessionDeletedEvent",
|
|
111
|
+
"SlashCommandDoneEvent",
|
|
112
|
+
"SlashCommandStartEvent",
|
|
93
113
|
"SubagentEvent",
|
|
94
114
|
"SessionLoadedEvent",
|
|
95
115
|
"ToolCallDoneEvent",
|
|
@@ -112,6 +132,7 @@ __all__ = [
|
|
|
112
132
|
"PluginsManager",
|
|
113
133
|
"event_handler",
|
|
114
134
|
"hook_handler",
|
|
135
|
+
"stream_processor",
|
|
115
136
|
"ProvidersManager",
|
|
116
137
|
"AgentCommand",
|
|
117
138
|
"AgentFuture",
|
|
@@ -124,7 +145,6 @@ __all__ = [
|
|
|
124
145
|
"AgentSession",
|
|
125
146
|
"SessionsManager",
|
|
126
147
|
"StatusManager",
|
|
127
|
-
"ImageGenerationTool",
|
|
128
148
|
"ServerTool",
|
|
129
149
|
"Tool",
|
|
130
150
|
"ToolsManager",
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
from .utils import text_content, ensure_runtime_dir, upload_file_to_folder, project_python_env, runtime_join, root_join
|
|
2
2
|
import os
|
|
3
|
-
from
|
|
3
|
+
from modict import modict
|
|
4
|
+
from .message import DeveloperMessage, ServerToolResponseMessage, ToolResultMessage, UserMessage, message_from_data
|
|
4
5
|
from .image import ImageMessage
|
|
5
6
|
from .command import CommandManager
|
|
6
7
|
from .config import ConfigManager
|
|
@@ -13,11 +14,9 @@ from .runtime import RuntimeManager
|
|
|
13
14
|
from .scheduler import AgentScheduler
|
|
14
15
|
from .sessions import SessionsManager
|
|
15
16
|
from .status import StatusManager
|
|
16
|
-
from .tool import
|
|
17
|
+
from .tool import ToolsManager, reset_current_agent, set_current_agent
|
|
17
18
|
from .ai import AIClient
|
|
18
|
-
from .
|
|
19
|
-
from .latex import LaTeXProcessor
|
|
20
|
-
from .event import AssistantInterruptRequestedEvent, AssistantInterrupted, AssistantInterruptedEvent, AudioPlaybackEvent, EventBus
|
|
19
|
+
from .event import AssistantInterruptRequestedEvent, AssistantInterrupted, AssistantInterruptedEvent, EventBus
|
|
21
20
|
from threading import Event as ThreadEvent
|
|
22
21
|
|
|
23
22
|
class Agent:
|
|
@@ -51,7 +50,8 @@ class Agent:
|
|
|
51
50
|
self.runtime=RuntimeManager(self)
|
|
52
51
|
self.scheduler=AgentScheduler(self)
|
|
53
52
|
self.hooks=HookManager(self)
|
|
54
|
-
self.
|
|
53
|
+
self.stream_processors=modict()
|
|
54
|
+
self.stream_processor_owners={}
|
|
55
55
|
self.mainloop_manager=MainLoopManager(self)
|
|
56
56
|
self._interrupt_requested=ThreadEvent()
|
|
57
57
|
self.current_session_id=None
|
|
@@ -63,9 +63,6 @@ class Agent:
|
|
|
63
63
|
self.command_manager.init_folder()
|
|
64
64
|
self.plugins_manager.init_folder()
|
|
65
65
|
self.ai=AIClient(self)
|
|
66
|
-
self.voice=VoiceProcessor(self)
|
|
67
|
-
self.latex=LaTeXProcessor()
|
|
68
|
-
self.content_processors=[self.voice]
|
|
69
66
|
self.command_manager.init_builtin()
|
|
70
67
|
self.plugins_manager.init_builtin()
|
|
71
68
|
self.plugins_manager.init_runtime()
|
|
@@ -74,13 +71,13 @@ class Agent:
|
|
|
74
71
|
self.tools_manager.apply_config_exclusions()
|
|
75
72
|
self.start_new_session() if session == "new" else self.load_session(session)
|
|
76
73
|
|
|
77
|
-
def on(self, event_type, handler=None):
|
|
74
|
+
def on(self, event_type, handler=None, owner=None):
|
|
78
75
|
"""Register an event handler.
|
|
79
76
|
|
|
80
77
|
Can be used as ``agent.on(ResponseContentDeltaEvent, handler)`` or as
|
|
81
78
|
``@agent.on(ResponseContentDeltaEvent)``.
|
|
82
79
|
"""
|
|
83
|
-
return self.events.on(event_type, handler)
|
|
80
|
+
return self.events.on(event_type, handler, owner=owner)
|
|
84
81
|
|
|
85
82
|
def emit(self, event_type, **data):
|
|
86
83
|
event = self.events.emit(event_type, **data)
|
|
@@ -203,8 +200,13 @@ class Agent:
|
|
|
203
200
|
def save_session(self):
|
|
204
201
|
return self.sessions_manager.save()
|
|
205
202
|
|
|
206
|
-
def compact_session(self, client=None, model=None, instructions=None):
|
|
207
|
-
return self.sessions_manager.compact(
|
|
203
|
+
def compact_session(self, client=None, model=None, instructions=None, max_completed_turns=None):
|
|
204
|
+
return self.sessions_manager.compact(
|
|
205
|
+
client=client,
|
|
206
|
+
model=model,
|
|
207
|
+
instructions=instructions,
|
|
208
|
+
max_completed_turns=max_completed_turns,
|
|
209
|
+
)
|
|
208
210
|
|
|
209
211
|
def add_message(self,msg,pending=False):
|
|
210
212
|
"""Queue a message for the next pending flush, except tool results."""
|
|
@@ -238,7 +240,7 @@ class Agent:
|
|
|
238
240
|
self.add_message(img,pending=pending)
|
|
239
241
|
return img
|
|
240
242
|
|
|
241
|
-
def add_tool(self,func=None,name=None,description=None,parameters=None,required=None,tool_type=None,format=None):
|
|
243
|
+
def add_tool(self,func=None,name=None,description=None,parameters=None,required=None,tool_type=None,format=None,owner=None):
|
|
242
244
|
return self.tools_manager.add(
|
|
243
245
|
func=func,
|
|
244
246
|
name=name,
|
|
@@ -247,18 +249,59 @@ class Agent:
|
|
|
247
249
|
required=required,
|
|
248
250
|
tool_type=tool_type,
|
|
249
251
|
format=format,
|
|
252
|
+
owner=owner,
|
|
250
253
|
)
|
|
251
254
|
|
|
252
|
-
def add_provider(self, func=None, name=None):
|
|
253
|
-
return self.providers_manager.add(func=func, name=name)
|
|
255
|
+
def add_provider(self, func=None, name=None, owner=None):
|
|
256
|
+
return self.providers_manager.add(func=func, name=name, owner=owner)
|
|
254
257
|
|
|
255
|
-
def add_command(self, func=None, name=None):
|
|
256
|
-
return self.command_manager.add(func, name=name)
|
|
258
|
+
def add_command(self, func=None, name=None, owner=None):
|
|
259
|
+
return self.command_manager.add(func, name=name, owner=owner)
|
|
257
260
|
|
|
258
261
|
def add_plugin(self, plugin):
|
|
259
262
|
return self.plugins_manager.add_plugin(plugin)
|
|
260
263
|
|
|
261
|
-
def
|
|
264
|
+
def load_builtin_plugin(self, name):
|
|
265
|
+
return self.plugins_manager.load_builtin_plugin(name)
|
|
266
|
+
|
|
267
|
+
def load_runtime_plugin(self, name_or_path):
|
|
268
|
+
return self.plugins_manager.load_runtime_plugin(name_or_path)
|
|
269
|
+
|
|
270
|
+
def unload_plugin(self, plugin_or_name, timeout=None):
|
|
271
|
+
return self.plugins_manager.unload_plugin(plugin_or_name, timeout=timeout)
|
|
272
|
+
|
|
273
|
+
def reload_plugin(self, plugin_or_name, timeout=None):
|
|
274
|
+
return self.plugins_manager.reload_plugin(plugin_or_name, timeout=timeout)
|
|
275
|
+
|
|
276
|
+
def add_stream_processor(self, key, processor, owner=None):
|
|
277
|
+
processors = self.stream_processors.setdefault(str(key), [])
|
|
278
|
+
processors.append(processor)
|
|
279
|
+
if owner is not None:
|
|
280
|
+
self.stream_processor_owners.setdefault(str(key), {})[processor] = owner
|
|
281
|
+
return processor
|
|
282
|
+
|
|
283
|
+
def get_stream_processors(self, key):
|
|
284
|
+
return list(self.stream_processors.get(str(key), []))
|
|
285
|
+
|
|
286
|
+
def remove_stream_processors_by_owner(self, owner):
|
|
287
|
+
removed = modict()
|
|
288
|
+
for key, processors in list(self.stream_processors.items()):
|
|
289
|
+
owners = self.stream_processor_owners.get(key, {})
|
|
290
|
+
kept = []
|
|
291
|
+
for processor in processors:
|
|
292
|
+
if owners.get(processor) == owner:
|
|
293
|
+
removed.setdefault(key, []).append(processor)
|
|
294
|
+
owners.pop(processor, None)
|
|
295
|
+
else:
|
|
296
|
+
kept.append(processor)
|
|
297
|
+
if kept:
|
|
298
|
+
self.stream_processors[key] = kept
|
|
299
|
+
else:
|
|
300
|
+
self.stream_processors.pop(key, None)
|
|
301
|
+
self.stream_processor_owners.pop(key, None)
|
|
302
|
+
return removed
|
|
303
|
+
|
|
304
|
+
def add_hook(self, key, func=None, owner=None):
|
|
262
305
|
"""Register a runtime hook.
|
|
263
306
|
|
|
264
307
|
Hooks are callable extension points keyed by name. They are runtime
|
|
@@ -267,13 +310,13 @@ class Agent:
|
|
|
267
310
|
"""
|
|
268
311
|
if func is None:
|
|
269
312
|
def decorator(f):
|
|
270
|
-
return self.add_hook(key, f)
|
|
313
|
+
return self.add_hook(key, f, owner=owner)
|
|
271
314
|
return decorator
|
|
272
315
|
|
|
273
316
|
if hasattr(self, "mainloop_manager") and self.mainloop_manager.should_queue_state_command():
|
|
274
|
-
return self.submit("add_hook", key=key, func=func).wait().result
|
|
317
|
+
return self.submit("add_hook", key=key, func=func, owner=owner).wait().result
|
|
275
318
|
|
|
276
|
-
return self.hooks.add(key, func)
|
|
319
|
+
return self.hooks.add(key, func, owner=owner)
|
|
277
320
|
|
|
278
321
|
def has_hook(self, key):
|
|
279
322
|
return self.hooks.has(key)
|
|
@@ -298,44 +341,6 @@ class Agent:
|
|
|
298
341
|
def get_status(self):
|
|
299
342
|
return self.status_manager.get_status()
|
|
300
343
|
|
|
301
|
-
def create_image(
|
|
302
|
-
self,
|
|
303
|
-
prompt,
|
|
304
|
-
input_images=None,
|
|
305
|
-
model="gpt-5.4",
|
|
306
|
-
reasoning_effort="medium",
|
|
307
|
-
verbosity="medium",
|
|
308
|
-
output_format="png",
|
|
309
|
-
size=None,
|
|
310
|
-
quality=None,
|
|
311
|
-
background=None,
|
|
312
|
-
moderation=None,
|
|
313
|
-
):
|
|
314
|
-
"""Generate an image directly and return the saved image path."""
|
|
315
|
-
content = [{"type": "text", "text": prompt}]
|
|
316
|
-
for source in input_images or []:
|
|
317
|
-
content.extend(ImageMessage(content=source).content_to_response_parts())
|
|
318
|
-
|
|
319
|
-
system_prompt = text_content(os.path.join(os.path.dirname(__file__), "prompts", "image_generation_system_prompt.txt"))
|
|
320
|
-
message = self.ai.run(
|
|
321
|
-
messages=[SystemMessage(content=system_prompt), UserMessage(content=content)],
|
|
322
|
-
tools=[ImageGenerationTool(
|
|
323
|
-
output_format=output_format,
|
|
324
|
-
size=size,
|
|
325
|
-
quality=quality,
|
|
326
|
-
background=background,
|
|
327
|
-
moderation=moderation,
|
|
328
|
-
).to_response_tool()],
|
|
329
|
-
model=model,
|
|
330
|
-
reasoning_effort=reasoning_effort,
|
|
331
|
-
verbosity=verbosity,
|
|
332
|
-
)
|
|
333
|
-
for item in message.output_items:
|
|
334
|
-
if item.get("type") == "image_generation_call":
|
|
335
|
-
return ServerToolResponseMessage(item=item).content
|
|
336
|
-
else:
|
|
337
|
-
raise RuntimeError("The image_generation tool did not return an image.")
|
|
338
|
-
|
|
339
344
|
def get_response(self):
|
|
340
345
|
"""Run the model, emit response events, and store the final message.
|
|
341
346
|
|
|
@@ -366,20 +371,6 @@ class Agent:
|
|
|
366
371
|
self.sessions_manager.append_message(ServerToolResponseMessage(item=item))
|
|
367
372
|
return message
|
|
368
373
|
|
|
369
|
-
def speak(self,text,**kwargs):
|
|
370
|
-
audio=self.ai.text_to_audio(text,**kwargs)
|
|
371
|
-
if audio is not None:
|
|
372
|
-
self.emit(AudioPlaybackEvent, audio=audio)
|
|
373
|
-
|
|
374
|
-
def handle_audio_playback(self, event):
|
|
375
|
-
audio = event.get("audio")
|
|
376
|
-
if audio is None:
|
|
377
|
-
return None
|
|
378
|
-
if self.has_hook("audio_playback_hook"):
|
|
379
|
-
return self.run_hooks("audio_playback_hook", audio)
|
|
380
|
-
from .voice import silent_play
|
|
381
|
-
return silent_play(audio)
|
|
382
|
-
|
|
383
374
|
def listen(self, source, language=None, **kwargs):
|
|
384
375
|
"""
|
|
385
376
|
description: |
|
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
import queue
|
|
2
|
+
import threading
|
|
3
|
+
|
|
1
4
|
import numpy as np
|
|
2
5
|
from .message import AssistantMessage, MessageChunk, SystemMessage
|
|
3
6
|
from .utils import truncate
|
|
@@ -41,7 +44,7 @@ class ChunkStreamer(MappingStreamProcessor):
|
|
|
41
44
|
self.agent=agent
|
|
42
45
|
super().__init__(
|
|
43
46
|
defaults=dict(content='',reasoning='',tool_calls=None,output_items=None),
|
|
44
|
-
processors=dict(content=self.agent.
|
|
47
|
+
processors=dict(content=self.agent.get_stream_processors("content")),
|
|
45
48
|
type=MessageChunk,
|
|
46
49
|
threaded=threaded
|
|
47
50
|
)
|
|
@@ -254,7 +257,8 @@ class AIClient:
|
|
|
254
257
|
|
|
255
258
|
try:
|
|
256
259
|
tool_call_index = 0
|
|
257
|
-
for event in response:
|
|
260
|
+
for event in self._iter_response_events(response):
|
|
261
|
+
self.agent.mainloop_manager.touch_activity("response_stream")
|
|
258
262
|
if isinstance(event, ResponseCompleted):
|
|
259
263
|
self.agent.status_manager.cache_api_status(
|
|
260
264
|
usage=event.usage,
|
|
@@ -274,6 +278,41 @@ class AIClient:
|
|
|
274
278
|
raise AIBadRequestError(str(e)) from e
|
|
275
279
|
yield MessageChunk(content=f"Hmmm, sorry! There was an error while reading the Codex backend stream. Here is the error message I got:\n\n ```\n{str(e)}\n```")
|
|
276
280
|
|
|
281
|
+
def _iter_response_events(self, response):
|
|
282
|
+
timeout = float(self.agent.config.get("codex_stream_idle_timeout", 0) or 0)
|
|
283
|
+
if timeout <= 0:
|
|
284
|
+
yield from response
|
|
285
|
+
return
|
|
286
|
+
|
|
287
|
+
events = queue.Queue()
|
|
288
|
+
sentinel = object()
|
|
289
|
+
|
|
290
|
+
def consume():
|
|
291
|
+
try:
|
|
292
|
+
for event in response:
|
|
293
|
+
events.put(("event", event))
|
|
294
|
+
except BaseException as exc:
|
|
295
|
+
events.put(("error", exc))
|
|
296
|
+
finally:
|
|
297
|
+
events.put(("done", sentinel))
|
|
298
|
+
|
|
299
|
+
threading.Thread(target=consume, name="codex-response-stream", daemon=True).start()
|
|
300
|
+
while True:
|
|
301
|
+
try:
|
|
302
|
+
kind, value = events.get(timeout=timeout)
|
|
303
|
+
except queue.Empty as exc:
|
|
304
|
+
try:
|
|
305
|
+
self.abort()
|
|
306
|
+
finally:
|
|
307
|
+
raise AIClientError(
|
|
308
|
+
f"Codex backend stream produced no events for {timeout:g}s"
|
|
309
|
+
) from exc
|
|
310
|
+
if kind == "done":
|
|
311
|
+
break
|
|
312
|
+
if kind == "error":
|
|
313
|
+
raise value
|
|
314
|
+
yield value
|
|
315
|
+
|
|
277
316
|
def is_bad_request_error(self, exc):
|
|
278
317
|
response = getattr(exc, "response", None)
|
|
279
318
|
status_code = getattr(response, "status_code", None)
|
{codex_agent_framework-0.1.23 → codex_agent_framework-0.1.25}/codex_agent/builtin_commands.py
RENAMED
|
@@ -53,15 +53,20 @@ def help():
|
|
|
53
53
|
|
|
54
54
|
|
|
55
55
|
@command
|
|
56
|
-
def compact():
|
|
56
|
+
def compact(max_completed_turns=None):
|
|
57
57
|
agent = get_agent()
|
|
58
|
+
max_completed_turns = None if max_completed_turns in (None, "", "all") else int(max_completed_turns)
|
|
58
59
|
message = agent.compact_session(
|
|
59
60
|
model=agent.config.model,
|
|
60
61
|
instructions=agent.config_manager.system_message().content,
|
|
62
|
+
max_completed_turns=max_completed_turns,
|
|
61
63
|
)
|
|
62
64
|
if message is None:
|
|
63
65
|
return "Nothing to compact."
|
|
64
|
-
|
|
66
|
+
if message.get("status") == "failed":
|
|
67
|
+
return f"Compaction failed: {message.error}"
|
|
68
|
+
suffix = "" if max_completed_turns is None else f" from {max_completed_turns} completed turn(s)"
|
|
69
|
+
return f"Compacted {message.compacted_message_count} messages{suffix}."
|
|
65
70
|
|
|
66
71
|
|
|
67
72
|
@command
|
|
@@ -134,22 +139,3 @@ def verbosity(value=None):
|
|
|
134
139
|
if value is None:
|
|
135
140
|
return f"verbosity: {get_agent().config.verbosity!r}"
|
|
136
141
|
return update_model_config(verbosity=value)
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
@command
|
|
140
|
-
def voice(value=None):
|
|
141
|
-
agent = get_agent()
|
|
142
|
-
if value is None:
|
|
143
|
-
state = "on" if agent.config.get("voice_enabled", False) else "off"
|
|
144
|
-
return f"voice: {state}; voice={agent.config.get('voice')!r}"
|
|
145
|
-
|
|
146
|
-
lowered = str(value).lower()
|
|
147
|
-
if lowered in ("on", "true", "yes", "1"):
|
|
148
|
-
agent.config_manager.update(voice_enabled=True)
|
|
149
|
-
return f"Updated config: voice_enabled={agent.config.voice_enabled!r}"
|
|
150
|
-
if lowered in ("off", "false", "no", "0"):
|
|
151
|
-
agent.config_manager.update(voice_enabled=False)
|
|
152
|
-
return f"Updated config: voice_enabled={agent.config.voice_enabled!r}"
|
|
153
|
-
|
|
154
|
-
agent.config_manager.update(voice=str(value), voice_enabled=True)
|
|
155
|
-
return f"Updated config: voice={agent.config.voice!r}, voice_enabled={agent.config.voice_enabled!r}"
|
|
@@ -11,6 +11,13 @@ class BashPlugin(Plugin):
|
|
|
11
11
|
name = "bash"
|
|
12
12
|
description = "Run Bash commands on the local system."
|
|
13
13
|
prefix_tools = False
|
|
14
|
+
system_prompt = """
|
|
15
|
+
# Bash Tool
|
|
16
|
+
|
|
17
|
+
Via the `bash` tool you may execute shell commands on the user's local system. This can be useful to act on the local environment, inspect project state, or access the internet when appropriate.
|
|
18
|
+
|
|
19
|
+
Pass raw shell script text to the tool, not JSON, quotes, or a markdown code fence. Commands run with user privileges and the agent execution environment, so use discernment before running commands that could compromise sensitive data or system integrity.
|
|
20
|
+
"""
|
|
14
21
|
|
|
15
22
|
@tool(name="bash", tool_type="custom")
|
|
16
23
|
def bash(self, content=None):
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
# No plugin-specific Python dependencies.
|
|
@@ -11,6 +11,16 @@ class ContentPlugin(Plugin):
|
|
|
11
11
|
name = "content"
|
|
12
12
|
description = "Extract, observe, or open content from varied sources."
|
|
13
13
|
prefix_tools = False
|
|
14
|
+
system_prompt = """
|
|
15
|
+
# Content Tools
|
|
16
|
+
|
|
17
|
+
Use the specialized content tools to inspect or present non-plain-text sources and visual material:
|
|
18
|
+
- `view`: quickly access extracted content from folders, URLs, PDFs, DOCX, ODT, HTML, XLSX, archives, and other rich sources. It is convenient and broad, but not a strict source-of-truth reader for local UTF-8 files.
|
|
19
|
+
- `observe`: use AI vision capabilities on image files, screenshots, windows, screens, or URLs.
|
|
20
|
+
- `show`: open a local file, folder, or URL with the system default application/browser when the user should visually inspect it outside the chat.
|
|
21
|
+
|
|
22
|
+
Use `view` for broad extraction and discovery, but prefer the file plugin's `read` tool when you need faithful line-numbered local UTF-8 file content before editing.
|
|
23
|
+
"""
|
|
14
24
|
|
|
15
25
|
@tool(name="view")
|
|
16
26
|
def view(self, source, start_at_line: int = 1, search_query: str = None):
|