deepagents-cli 0.0.31__tar.gz → 0.0.32__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.
- {deepagents_cli-0.0.31 → deepagents_cli-0.0.32}/CHANGELOG.md +11 -0
- {deepagents_cli-0.0.31 → deepagents_cli-0.0.32}/PKG-INFO +4 -4
- {deepagents_cli-0.0.31 → deepagents_cli-0.0.32}/README.md +2 -2
- deepagents_cli-0.0.32/deepagents_cli/_version.py +3 -0
- {deepagents_cli-0.0.31 → deepagents_cli-0.0.32}/deepagents_cli/agent.py +62 -14
- {deepagents_cli-0.0.31 → deepagents_cli-0.0.32}/deepagents_cli/app.py +69 -36
- {deepagents_cli-0.0.31 → deepagents_cli-0.0.32}/deepagents_cli/main.py +21 -4
- {deepagents_cli-0.0.31 → deepagents_cli-0.0.32}/deepagents_cli/non_interactive.py +4 -2
- deepagents_cli-0.0.32/deepagents_cli/output.py +69 -0
- {deepagents_cli-0.0.31 → deepagents_cli-0.0.32}/deepagents_cli/sessions.py +31 -6
- {deepagents_cli-0.0.31 → deepagents_cli-0.0.32}/deepagents_cli/skills/commands.py +145 -37
- {deepagents_cli-0.0.31 → deepagents_cli-0.0.32}/deepagents_cli/ui.py +60 -52
- {deepagents_cli-0.0.31 → deepagents_cli-0.0.32}/deepagents_cli/widgets/chat_input.py +18 -0
- {deepagents_cli-0.0.31 → deepagents_cli-0.0.32}/deepagents_cli/widgets/welcome.py +22 -11
- {deepagents_cli-0.0.31 → deepagents_cli-0.0.32}/pyproject.toml +2 -2
- {deepagents_cli-0.0.31 → deepagents_cli-0.0.32}/scripts/install.sh +1 -1
- deepagents_cli-0.0.32/tests/unit_tests/skills/test_skills_json.py +154 -0
- {deepagents_cli-0.0.31 → deepagents_cli-0.0.32}/tests/unit_tests/test_agent.py +94 -0
- {deepagents_cli-0.0.31 → deepagents_cli-0.0.32}/tests/unit_tests/test_args.py +47 -0
- {deepagents_cli-0.0.31 → deepagents_cli-0.0.32}/tests/unit_tests/test_chat_input.py +41 -0
- {deepagents_cli-0.0.31 → deepagents_cli-0.0.32}/tests/unit_tests/test_compact.py +1 -4
- deepagents_cli-0.0.32/tests/unit_tests/test_output.py +62 -0
- {deepagents_cli-0.0.31 → deepagents_cli-0.0.32}/tests/unit_tests/test_sessions.py +112 -0
- {deepagents_cli-0.0.31 → deepagents_cli-0.0.32}/tests/unit_tests/test_version.py +0 -2
- {deepagents_cli-0.0.31 → deepagents_cli-0.0.32}/tests/unit_tests/test_welcome.py +105 -1
- {deepagents_cli-0.0.31 → deepagents_cli-0.0.32}/uv.lock +20 -20
- deepagents_cli-0.0.31/deepagents_cli/_version.py +0 -3
- {deepagents_cli-0.0.31 → deepagents_cli-0.0.32}/.gitignore +0 -0
- {deepagents_cli-0.0.31 → deepagents_cli-0.0.32}/Makefile +0 -0
- {deepagents_cli-0.0.31 → deepagents_cli-0.0.32}/deepagents_cli/__init__.py +0 -0
- {deepagents_cli-0.0.31 → deepagents_cli-0.0.32}/deepagents_cli/__main__.py +0 -0
- {deepagents_cli-0.0.31 → deepagents_cli-0.0.32}/deepagents_cli/app.tcss +0 -0
- {deepagents_cli-0.0.31 → deepagents_cli-0.0.32}/deepagents_cli/ask_user.py +0 -0
- {deepagents_cli-0.0.31 → deepagents_cli-0.0.32}/deepagents_cli/built_in_skills/__init__.py +0 -0
- {deepagents_cli-0.0.31 → deepagents_cli-0.0.32}/deepagents_cli/built_in_skills/skill-creator/SKILL.md +0 -0
- {deepagents_cli-0.0.31 → deepagents_cli-0.0.32}/deepagents_cli/built_in_skills/skill-creator/scripts/init_skill.py +0 -0
- {deepagents_cli-0.0.31 → deepagents_cli-0.0.32}/deepagents_cli/built_in_skills/skill-creator/scripts/quick_validate.py +0 -0
- {deepagents_cli-0.0.31 → deepagents_cli-0.0.32}/deepagents_cli/clipboard.py +0 -0
- {deepagents_cli-0.0.31 → deepagents_cli-0.0.32}/deepagents_cli/config.py +0 -0
- {deepagents_cli-0.0.31 → deepagents_cli-0.0.32}/deepagents_cli/default_agent_prompt.md +0 -0
- {deepagents_cli-0.0.31 → deepagents_cli-0.0.32}/deepagents_cli/file_ops.py +0 -0
- {deepagents_cli-0.0.31 → deepagents_cli-0.0.32}/deepagents_cli/hooks.py +0 -0
- {deepagents_cli-0.0.31 → deepagents_cli-0.0.32}/deepagents_cli/input.py +0 -0
- {deepagents_cli-0.0.31 → deepagents_cli-0.0.32}/deepagents_cli/integrations/__init__.py +0 -0
- {deepagents_cli-0.0.31 → deepagents_cli-0.0.32}/deepagents_cli/integrations/daytona.py +0 -0
- {deepagents_cli-0.0.31 → deepagents_cli-0.0.32}/deepagents_cli/integrations/langsmith.py +0 -0
- {deepagents_cli-0.0.31 → deepagents_cli-0.0.32}/deepagents_cli/integrations/modal.py +0 -0
- {deepagents_cli-0.0.31 → deepagents_cli-0.0.32}/deepagents_cli/integrations/runloop.py +0 -0
- {deepagents_cli-0.0.31 → deepagents_cli-0.0.32}/deepagents_cli/integrations/sandbox_factory.py +0 -0
- {deepagents_cli-0.0.31 → deepagents_cli-0.0.32}/deepagents_cli/integrations/sandbox_provider.py +0 -0
- {deepagents_cli-0.0.31 → deepagents_cli-0.0.32}/deepagents_cli/local_context.py +0 -0
- {deepagents_cli-0.0.31 → deepagents_cli-0.0.32}/deepagents_cli/mcp_tools.py +0 -0
- {deepagents_cli-0.0.31 → deepagents_cli-0.0.32}/deepagents_cli/mcp_trust.py +0 -0
- {deepagents_cli-0.0.31 → deepagents_cli-0.0.32}/deepagents_cli/media_utils.py +0 -0
- {deepagents_cli-0.0.31 → deepagents_cli-0.0.32}/deepagents_cli/model_config.py +0 -0
- {deepagents_cli-0.0.31 → deepagents_cli-0.0.32}/deepagents_cli/project_utils.py +0 -0
- {deepagents_cli-0.0.31 → deepagents_cli-0.0.32}/deepagents_cli/py.typed +0 -0
- {deepagents_cli-0.0.31 → deepagents_cli-0.0.32}/deepagents_cli/skills/__init__.py +0 -0
- {deepagents_cli-0.0.31 → deepagents_cli-0.0.32}/deepagents_cli/skills/load.py +0 -0
- {deepagents_cli-0.0.31 → deepagents_cli-0.0.32}/deepagents_cli/subagents.py +0 -0
- {deepagents_cli-0.0.31 → deepagents_cli-0.0.32}/deepagents_cli/system_prompt.md +0 -0
- {deepagents_cli-0.0.31 → deepagents_cli-0.0.32}/deepagents_cli/textual_adapter.py +0 -0
- {deepagents_cli-0.0.31 → deepagents_cli-0.0.32}/deepagents_cli/tool_display.py +0 -0
- {deepagents_cli-0.0.31 → deepagents_cli-0.0.32}/deepagents_cli/tools.py +0 -0
- {deepagents_cli-0.0.31 → deepagents_cli-0.0.32}/deepagents_cli/unicode_security.py +0 -0
- {deepagents_cli-0.0.31 → deepagents_cli-0.0.32}/deepagents_cli/update_check.py +0 -0
- {deepagents_cli-0.0.31 → deepagents_cli-0.0.32}/deepagents_cli/widgets/__init__.py +0 -0
- {deepagents_cli-0.0.31 → deepagents_cli-0.0.32}/deepagents_cli/widgets/_links.py +0 -0
- {deepagents_cli-0.0.31 → deepagents_cli-0.0.32}/deepagents_cli/widgets/approval.py +0 -0
- {deepagents_cli-0.0.31 → deepagents_cli-0.0.32}/deepagents_cli/widgets/ask_user.py +0 -0
- {deepagents_cli-0.0.31 → deepagents_cli-0.0.32}/deepagents_cli/widgets/autocomplete.py +0 -0
- {deepagents_cli-0.0.31 → deepagents_cli-0.0.32}/deepagents_cli/widgets/diff.py +0 -0
- {deepagents_cli-0.0.31 → deepagents_cli-0.0.32}/deepagents_cli/widgets/history.py +0 -0
- {deepagents_cli-0.0.31 → deepagents_cli-0.0.32}/deepagents_cli/widgets/loading.py +0 -0
- {deepagents_cli-0.0.31 → deepagents_cli-0.0.32}/deepagents_cli/widgets/mcp_viewer.py +0 -0
- {deepagents_cli-0.0.31 → deepagents_cli-0.0.32}/deepagents_cli/widgets/message_store.py +0 -0
- {deepagents_cli-0.0.31 → deepagents_cli-0.0.32}/deepagents_cli/widgets/messages.py +0 -0
- {deepagents_cli-0.0.31 → deepagents_cli-0.0.32}/deepagents_cli/widgets/model_selector.py +0 -0
- {deepagents_cli-0.0.31 → deepagents_cli-0.0.32}/deepagents_cli/widgets/status.py +0 -0
- {deepagents_cli-0.0.31 → deepagents_cli-0.0.32}/deepagents_cli/widgets/thread_selector.py +0 -0
- {deepagents_cli-0.0.31 → deepagents_cli-0.0.32}/deepagents_cli/widgets/tool_renderers.py +0 -0
- {deepagents_cli-0.0.31 → deepagents_cli-0.0.32}/deepagents_cli/widgets/tool_widgets.py +0 -0
- {deepagents_cli-0.0.31 → deepagents_cli-0.0.32}/examples/skills/arxiv-search/SKILL.md +0 -0
- {deepagents_cli-0.0.31 → deepagents_cli-0.0.32}/examples/skills/arxiv-search/arxiv_search.py +0 -0
- {deepagents_cli-0.0.31 → deepagents_cli-0.0.32}/examples/skills/langgraph-docs/SKILL.md +0 -0
- {deepagents_cli-0.0.31 → deepagents_cli-0.0.32}/examples/skills/skill-creator/SKILL.md +0 -0
- {deepagents_cli-0.0.31 → deepagents_cli-0.0.32}/examples/skills/skill-creator/scripts/init_skill.py +0 -0
- {deepagents_cli-0.0.31 → deepagents_cli-0.0.32}/examples/skills/skill-creator/scripts/quick_validate.py +0 -0
- {deepagents_cli-0.0.31 → deepagents_cli-0.0.32}/examples/skills/web-research/SKILL.md +0 -0
- {deepagents_cli-0.0.31 → deepagents_cli-0.0.32}/images/cli.png +0 -0
- {deepagents_cli-0.0.31 → deepagents_cli-0.0.32}/scripts/check_imports.py +0 -0
- {deepagents_cli-0.0.31 → deepagents_cli-0.0.32}/tests/README.md +0 -0
- {deepagents_cli-0.0.31 → deepagents_cli-0.0.32}/tests/integration_tests/__init__.py +0 -0
- {deepagents_cli-0.0.31 → deepagents_cli-0.0.32}/tests/integration_tests/benchmarks/__init__.py +0 -0
- {deepagents_cli-0.0.31 → deepagents_cli-0.0.32}/tests/integration_tests/benchmarks/test_startup_benchmarks.py +0 -0
- {deepagents_cli-0.0.31 → deepagents_cli-0.0.32}/tests/integration_tests/conftest.py +0 -0
- {deepagents_cli-0.0.31 → deepagents_cli-0.0.32}/tests/integration_tests/test_acp_mode.py +0 -0
- {deepagents_cli-0.0.31 → deepagents_cli-0.0.32}/tests/integration_tests/test_sandbox_factory.py +0 -0
- {deepagents_cli-0.0.31 → deepagents_cli-0.0.32}/tests/integration_tests/test_sandbox_operations.py +0 -0
- {deepagents_cli-0.0.31 → deepagents_cli-0.0.32}/tests/unit_tests/__init__.py +0 -0
- {deepagents_cli-0.0.31 → deepagents_cli-0.0.32}/tests/unit_tests/conftest.py +0 -0
- {deepagents_cli-0.0.31 → deepagents_cli-0.0.32}/tests/unit_tests/skills/__init__.py +0 -0
- {deepagents_cli-0.0.31 → deepagents_cli-0.0.32}/tests/unit_tests/skills/test_commands.py +0 -0
- {deepagents_cli-0.0.31 → deepagents_cli-0.0.32}/tests/unit_tests/skills/test_load.py +0 -0
- {deepagents_cli-0.0.31 → deepagents_cli-0.0.32}/tests/unit_tests/test_app.py +0 -0
- {deepagents_cli-0.0.31 → deepagents_cli-0.0.32}/tests/unit_tests/test_approval.py +0 -0
- {deepagents_cli-0.0.31 → deepagents_cli-0.0.32}/tests/unit_tests/test_ask_user.py +0 -0
- {deepagents_cli-0.0.31 → deepagents_cli-0.0.32}/tests/unit_tests/test_ask_user_middleware.py +0 -0
- {deepagents_cli-0.0.31 → deepagents_cli-0.0.32}/tests/unit_tests/test_autocomplete.py +0 -0
- {deepagents_cli-0.0.31 → deepagents_cli-0.0.32}/tests/unit_tests/test_charset.py +0 -0
- {deepagents_cli-0.0.31 → deepagents_cli-0.0.32}/tests/unit_tests/test_compact_tool.py +0 -0
- {deepagents_cli-0.0.31 → deepagents_cli-0.0.32}/tests/unit_tests/test_config.py +0 -0
- {deepagents_cli-0.0.31 → deepagents_cli-0.0.32}/tests/unit_tests/test_end_to_end.py +0 -0
- {deepagents_cli-0.0.31 → deepagents_cli-0.0.32}/tests/unit_tests/test_exception_handling.py +0 -0
- {deepagents_cli-0.0.31 → deepagents_cli-0.0.32}/tests/unit_tests/test_file_ops.py +0 -0
- {deepagents_cli-0.0.31 → deepagents_cli-0.0.32}/tests/unit_tests/test_history.py +0 -0
- {deepagents_cli-0.0.31 → deepagents_cli-0.0.32}/tests/unit_tests/test_hooks.py +0 -0
- {deepagents_cli-0.0.31 → deepagents_cli-0.0.32}/tests/unit_tests/test_imports.py +0 -0
- {deepagents_cli-0.0.31 → deepagents_cli-0.0.32}/tests/unit_tests/test_input_parsing.py +0 -0
- {deepagents_cli-0.0.31 → deepagents_cli-0.0.32}/tests/unit_tests/test_local_context.py +0 -0
- {deepagents_cli-0.0.31 → deepagents_cli-0.0.32}/tests/unit_tests/test_main.py +0 -0
- {deepagents_cli-0.0.31 → deepagents_cli-0.0.32}/tests/unit_tests/test_main_acp_mode.py +0 -0
- {deepagents_cli-0.0.31 → deepagents_cli-0.0.32}/tests/unit_tests/test_main_args.py +0 -0
- {deepagents_cli-0.0.31 → deepagents_cli-0.0.32}/tests/unit_tests/test_mcp_tools.py +0 -0
- {deepagents_cli-0.0.31 → deepagents_cli-0.0.32}/tests/unit_tests/test_mcp_trust.py +0 -0
- {deepagents_cli-0.0.31 → deepagents_cli-0.0.32}/tests/unit_tests/test_mcp_viewer.py +0 -0
- {deepagents_cli-0.0.31 → deepagents_cli-0.0.32}/tests/unit_tests/test_media_utils.py +0 -0
- {deepagents_cli-0.0.31 → deepagents_cli-0.0.32}/tests/unit_tests/test_message_store.py +0 -0
- {deepagents_cli-0.0.31 → deepagents_cli-0.0.32}/tests/unit_tests/test_messages.py +0 -0
- {deepagents_cli-0.0.31 → deepagents_cli-0.0.32}/tests/unit_tests/test_model_config.py +0 -0
- {deepagents_cli-0.0.31 → deepagents_cli-0.0.32}/tests/unit_tests/test_model_selector.py +0 -0
- {deepagents_cli-0.0.31 → deepagents_cli-0.0.32}/tests/unit_tests/test_model_switch.py +0 -0
- {deepagents_cli-0.0.31 → deepagents_cli-0.0.32}/tests/unit_tests/test_non_interactive.py +0 -0
- {deepagents_cli-0.0.31 → deepagents_cli-0.0.32}/tests/unit_tests/test_reload.py +0 -0
- {deepagents_cli-0.0.31 → deepagents_cli-0.0.32}/tests/unit_tests/test_shell_allow_list.py +0 -0
- {deepagents_cli-0.0.31 → deepagents_cli-0.0.32}/tests/unit_tests/test_status.py +0 -0
- {deepagents_cli-0.0.31 → deepagents_cli-0.0.32}/tests/unit_tests/test_subagents.py +0 -0
- {deepagents_cli-0.0.31 → deepagents_cli-0.0.32}/tests/unit_tests/test_textual_adapter.py +0 -0
- {deepagents_cli-0.0.31 → deepagents_cli-0.0.32}/tests/unit_tests/test_thread_selector.py +0 -0
- {deepagents_cli-0.0.31 → deepagents_cli-0.0.32}/tests/unit_tests/test_token_tracker.py +0 -0
- {deepagents_cli-0.0.31 → deepagents_cli-0.0.32}/tests/unit_tests/test_ui.py +0 -0
- {deepagents_cli-0.0.31 → deepagents_cli-0.0.32}/tests/unit_tests/test_unicode_security.py +0 -0
- {deepagents_cli-0.0.31 → deepagents_cli-0.0.32}/tests/unit_tests/test_update_check.py +0 -0
- {deepagents_cli-0.0.31 → deepagents_cli-0.0.32}/tests/unit_tests/tools/__init__.py +0 -0
- {deepagents_cli-0.0.31 → deepagents_cli-0.0.32}/tests/unit_tests/tools/test_fetch_url.py +0 -0
|
@@ -1,5 +1,16 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.0.32](https://github.com/langchain-ai/deepagents/compare/deepagents-cli==0.0.31...deepagents-cli==0.0.32) (2026-03-11)
|
|
4
|
+
|
|
5
|
+
### Features
|
|
6
|
+
|
|
7
|
+
* Add token breakdown to `/tokens` and simplify `/compact` messages ([#1782](https://github.com/langchain-ai/deepagents/issues/1782)) ([2f37bff](https://github.com/langchain-ai/deepagents/commit/2f37bffa9d7a9ced6945abe4ab6bc3409bfb97b1))
|
|
8
|
+
* `--json` flag for machine-readable output ([#1768](https://github.com/langchain-ai/deepagents/issues/1768)) ([6f62496](https://github.com/langchain-ai/deepagents/commit/6f62496bb699dfa6086ee1850b83f38d3b1242fa))
|
|
9
|
+
|
|
10
|
+
### Bug Fixes
|
|
11
|
+
|
|
12
|
+
* Work around VS Code 1.110 space key regression ([#1748](https://github.com/langchain-ai/deepagents/issues/1748)) ([f5fe431](https://github.com/langchain-ai/deepagents/commit/f5fe4315143bf5b636cf42fc98cbfe3d99918cfc))
|
|
13
|
+
|
|
3
14
|
## [0.0.31](https://github.com/langchain-ai/deepagents/compare/deepagents-cli==0.0.30...deepagents-cli==0.0.31) (2026-03-09)
|
|
4
15
|
|
|
5
16
|
### Features
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: deepagents-cli
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.32
|
|
4
4
|
Summary: Terminal interface for Deep Agents - interactive AI agent with file operations, shell access, and sub-agent capabilities.
|
|
5
5
|
Project-URL: Homepage, https://docs.langchain.com/oss/python/deepagents/overview
|
|
6
6
|
Project-URL: Documentation, https://reference.langchain.com/python/deepagents/
|
|
@@ -26,7 +26,7 @@ Requires-Python: <4.0,>=3.11
|
|
|
26
26
|
Requires-Dist: aiosqlite<1.0.0,>=0.19.0
|
|
27
27
|
Requires-Dist: daytona<1.0.0,>=0.113.0
|
|
28
28
|
Requires-Dist: deepagents-acp>=0.0.4
|
|
29
|
-
Requires-Dist: deepagents==0.4.
|
|
29
|
+
Requires-Dist: deepagents==0.4.10
|
|
30
30
|
Requires-Dist: langchain-mcp-adapters<1.0.0,>=0.2.0
|
|
31
31
|
Requires-Dist: langchain-openai<2.0.0,>=1.1.8
|
|
32
32
|
Requires-Dist: langchain<2.0.0,>=1.2.10
|
|
@@ -114,12 +114,12 @@ Description-Content-Type: text/markdown
|
|
|
114
114
|
## Quick Install
|
|
115
115
|
|
|
116
116
|
```bash
|
|
117
|
-
curl -LsSf https://raw.githubusercontent.com/langchain-ai/deepagents/main/scripts/install.sh | bash
|
|
117
|
+
curl -LsSf https://raw.githubusercontent.com/langchain-ai/deepagents/main/libs/cli/scripts/install.sh | bash
|
|
118
118
|
```
|
|
119
119
|
|
|
120
120
|
```bash
|
|
121
121
|
# With model provider extras (OpenAI is included by default)
|
|
122
|
-
DEEPAGENTS_EXTRAS="anthropic,groq" curl -LsSf https://raw.githubusercontent.com/langchain-ai/deepagents/main/scripts/install.sh | bash
|
|
122
|
+
DEEPAGENTS_EXTRAS="anthropic,groq" curl -LsSf https://raw.githubusercontent.com/langchain-ai/deepagents/main/libs/cli/scripts/install.sh | bash
|
|
123
123
|
```
|
|
124
124
|
|
|
125
125
|
Or install directly with `uv`:
|
|
@@ -12,12 +12,12 @@
|
|
|
12
12
|
## Quick Install
|
|
13
13
|
|
|
14
14
|
```bash
|
|
15
|
-
curl -LsSf https://raw.githubusercontent.com/langchain-ai/deepagents/main/scripts/install.sh | bash
|
|
15
|
+
curl -LsSf https://raw.githubusercontent.com/langchain-ai/deepagents/main/libs/cli/scripts/install.sh | bash
|
|
16
16
|
```
|
|
17
17
|
|
|
18
18
|
```bash
|
|
19
19
|
# With model provider extras (OpenAI is included by default)
|
|
20
|
-
DEEPAGENTS_EXTRAS="anthropic,groq" curl -LsSf https://raw.githubusercontent.com/langchain-ai/deepagents/main/scripts/install.sh | bash
|
|
20
|
+
DEEPAGENTS_EXTRAS="anthropic,groq" curl -LsSf https://raw.githubusercontent.com/langchain-ai/deepagents/main/libs/cli/scripts/install.sh | bash
|
|
21
21
|
```
|
|
22
22
|
|
|
23
23
|
Or install directly with `uv`:
|
|
@@ -31,6 +31,7 @@ if TYPE_CHECKING:
|
|
|
31
31
|
from langgraph.runtime import Runtime
|
|
32
32
|
|
|
33
33
|
from deepagents_cli.mcp_tools import MCPServerInfo
|
|
34
|
+
from deepagents_cli.output import OutputFormat
|
|
34
35
|
|
|
35
36
|
from deepagents_cli.config import (
|
|
36
37
|
COLORS,
|
|
@@ -61,11 +62,20 @@ REQUIRE_COMPACT_TOOL_APPROVAL: bool = True
|
|
|
61
62
|
"""When `True`, `compact_conversation` requires HITL approval like other gated tools."""
|
|
62
63
|
|
|
63
64
|
|
|
64
|
-
def list_agents() -> None:
|
|
65
|
-
"""List all available agents.
|
|
65
|
+
def list_agents(*, output_format: OutputFormat = "text") -> None:
|
|
66
|
+
"""List all available agents.
|
|
67
|
+
|
|
68
|
+
Args:
|
|
69
|
+
output_format: Output format — `'text'` (Rich) or `'json'`.
|
|
70
|
+
"""
|
|
66
71
|
agents_dir = settings.user_deepagents_dir
|
|
67
72
|
|
|
68
73
|
if not agents_dir.exists() or not any(agents_dir.iterdir()):
|
|
74
|
+
if output_format == "json":
|
|
75
|
+
from deepagents_cli.output import write_json
|
|
76
|
+
|
|
77
|
+
write_json("list", [])
|
|
78
|
+
return
|
|
69
79
|
console.print("[yellow]No agents found.[/yellow]")
|
|
70
80
|
console.print(
|
|
71
81
|
"[dim]Agents will be created in ~/.deepagents/ "
|
|
@@ -74,6 +84,24 @@ def list_agents() -> None:
|
|
|
74
84
|
)
|
|
75
85
|
return
|
|
76
86
|
|
|
87
|
+
if output_format == "json":
|
|
88
|
+
from deepagents_cli.output import write_json
|
|
89
|
+
|
|
90
|
+
agents = []
|
|
91
|
+
for agent_path in sorted(agents_dir.iterdir()):
|
|
92
|
+
if agent_path.is_dir():
|
|
93
|
+
agent_name = agent_path.name
|
|
94
|
+
agents.append(
|
|
95
|
+
{
|
|
96
|
+
"name": agent_name,
|
|
97
|
+
"path": str(agent_path),
|
|
98
|
+
"has_agents_md": (agent_path / "AGENTS.md").exists(),
|
|
99
|
+
"is_default": agent_name == DEFAULT_AGENT_NAME,
|
|
100
|
+
}
|
|
101
|
+
)
|
|
102
|
+
write_json("list", agents)
|
|
103
|
+
return
|
|
104
|
+
|
|
77
105
|
console.print("\n[bold]Available Agents:[/bold]\n", style=COLORS["primary"])
|
|
78
106
|
|
|
79
107
|
for agent_path in sorted(agents_dir.iterdir()):
|
|
@@ -101,8 +129,19 @@ def list_agents() -> None:
|
|
|
101
129
|
console.print()
|
|
102
130
|
|
|
103
131
|
|
|
104
|
-
def reset_agent(
|
|
105
|
-
|
|
132
|
+
def reset_agent(
|
|
133
|
+
agent_name: str,
|
|
134
|
+
source_agent: str | None = None,
|
|
135
|
+
*,
|
|
136
|
+
output_format: OutputFormat = "text",
|
|
137
|
+
) -> None:
|
|
138
|
+
"""Reset an agent to default or copy from another agent.
|
|
139
|
+
|
|
140
|
+
Args:
|
|
141
|
+
agent_name: Name of the agent to reset.
|
|
142
|
+
source_agent: Copy AGENTS.md from this agent instead of default.
|
|
143
|
+
output_format: Output format — `'text'` (Rich) or `'json'`.
|
|
144
|
+
"""
|
|
106
145
|
agents_dir = settings.user_deepagents_dir
|
|
107
146
|
agent_dir = agents_dir / agent_name
|
|
108
147
|
|
|
@@ -125,14 +164,28 @@ def reset_agent(agent_name: str, source_agent: str | None = None) -> None:
|
|
|
125
164
|
|
|
126
165
|
if agent_dir.exists():
|
|
127
166
|
shutil.rmtree(agent_dir)
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
167
|
+
if output_format != "json":
|
|
168
|
+
console.print(
|
|
169
|
+
f"Removed existing agent directory: {agent_dir}", style=COLORS["tool"]
|
|
170
|
+
)
|
|
131
171
|
|
|
132
172
|
agent_dir.mkdir(parents=True, exist_ok=True)
|
|
133
173
|
agent_md = agent_dir / "AGENTS.md"
|
|
134
174
|
agent_md.write_text(source_content)
|
|
135
175
|
|
|
176
|
+
if output_format == "json":
|
|
177
|
+
from deepagents_cli.output import write_json
|
|
178
|
+
|
|
179
|
+
write_json(
|
|
180
|
+
"reset",
|
|
181
|
+
{
|
|
182
|
+
"agent": agent_name,
|
|
183
|
+
"reset_to": source_agent or "default",
|
|
184
|
+
"path": str(agent_dir),
|
|
185
|
+
},
|
|
186
|
+
)
|
|
187
|
+
return
|
|
188
|
+
|
|
136
189
|
console.print(
|
|
137
190
|
f"{get_glyphs().checkmark} Agent '{agent_name}' reset to {action_desc}",
|
|
138
191
|
style=COLORS["primary"],
|
|
@@ -713,15 +766,10 @@ def create_cli_agent(
|
|
|
713
766
|
|
|
714
767
|
model = resolve_model(model)
|
|
715
768
|
|
|
716
|
-
from deepagents.middleware.summarization import
|
|
717
|
-
SummarizationToolMiddleware,
|
|
718
|
-
create_summarization_middleware,
|
|
719
|
-
)
|
|
769
|
+
from deepagents.middleware.summarization import create_summarization_tool_middleware
|
|
720
770
|
|
|
721
771
|
agent_middleware.append(
|
|
722
|
-
|
|
723
|
-
create_summarization_middleware(model, composite_backend)
|
|
724
|
-
)
|
|
772
|
+
create_summarization_tool_middleware(model, composite_backend)
|
|
725
773
|
)
|
|
726
774
|
|
|
727
775
|
# Create the agent
|
|
@@ -148,10 +148,7 @@ def _format_compact_limit(
|
|
|
148
148
|
percent = float(keep_value) * 100
|
|
149
149
|
if context_limit is not None:
|
|
150
150
|
token_limit = max(1, int(context_limit * float(keep_value)))
|
|
151
|
-
return (
|
|
152
|
-
f"{format_token_count(token_limit)} tokens "
|
|
153
|
-
f"({percent:.0f}% of {format_token_count(context_limit)})"
|
|
154
|
-
)
|
|
151
|
+
return f"{format_token_count(token_limit)} tokens"
|
|
155
152
|
return f"{percent:.0f}% of context window"
|
|
156
153
|
|
|
157
154
|
return "current retention threshold"
|
|
@@ -1588,19 +1585,25 @@ class DeepAgentsApp(App):
|
|
|
1588
1585
|
if context_limit is not None:
|
|
1589
1586
|
limit_str = format_token_count(context_limit)
|
|
1590
1587
|
pct = count / context_limit * 100
|
|
1591
|
-
usage = (
|
|
1592
|
-
f"{formatted} / {limit_str} tokens "
|
|
1593
|
-
f"({pct:.0f}%, includes system prompt + tools)"
|
|
1594
|
-
)
|
|
1588
|
+
usage = f"{formatted} / {limit_str} tokens ({pct:.0f}%)"
|
|
1595
1589
|
else:
|
|
1596
|
-
usage = f"{formatted} tokens used
|
|
1590
|
+
usage = f"{formatted} tokens used"
|
|
1591
|
+
|
|
1592
|
+
msg = f"{usage} \u00b7 {model_name}" if model_name else usage
|
|
1597
1593
|
|
|
1598
|
-
|
|
1594
|
+
conv_tokens = await self._get_conversation_token_count()
|
|
1595
|
+
if conv_tokens is not None:
|
|
1596
|
+
overhead = max(0, count - conv_tokens)
|
|
1597
|
+
overhead_str = format_token_count(overhead)
|
|
1598
|
+
conv_str = format_token_count(conv_tokens)
|
|
1599
1599
|
|
|
1600
|
-
|
|
1601
|
-
|
|
1602
|
-
|
|
1603
|
-
msg
|
|
1600
|
+
overhead_unit = " tokens" if overhead < 1000 else "" # noqa: PLR2004 # not bothersome, cosmetic
|
|
1601
|
+
conv_unit = " tokens" if conv_tokens < 1000 else "" # noqa: PLR2004 # not bothersome, cosmetic
|
|
1602
|
+
|
|
1603
|
+
msg += (
|
|
1604
|
+
f"\n\u251c System prompt + tools: ~{overhead_str}{overhead_unit} (fixed)" # noqa: E501
|
|
1605
|
+
f"\n\u2514 Conversation: ~{conv_str}{conv_unit}"
|
|
1606
|
+
)
|
|
1604
1607
|
|
|
1605
1608
|
await self._mount_message(AppMessage(msg))
|
|
1606
1609
|
else:
|
|
@@ -1610,7 +1613,7 @@ class DeepAgentsApp(App):
|
|
|
1610
1613
|
parts: list[str] = ["No token usage yet"]
|
|
1611
1614
|
if context_limit is not None:
|
|
1612
1615
|
limit_str = format_token_count(context_limit)
|
|
1613
|
-
parts.append(f"{limit_str} context window")
|
|
1616
|
+
parts.append(f"{limit_str} token context window")
|
|
1614
1617
|
if model_name:
|
|
1615
1618
|
parts.append(model_name)
|
|
1616
1619
|
|
|
@@ -1723,12 +1726,11 @@ class DeepAgentsApp(App):
|
|
|
1723
1726
|
|
|
1724
1727
|
self.call_after_refresh(_scroll_after_command)
|
|
1725
1728
|
|
|
1726
|
-
async def
|
|
1727
|
-
"""Return
|
|
1729
|
+
async def _get_conversation_token_count(self) -> int | None:
|
|
1730
|
+
"""Return the approximate conversation-only token count.
|
|
1728
1731
|
|
|
1729
1732
|
Returns:
|
|
1730
|
-
|
|
1731
|
-
`None` if state is unavailable.
|
|
1733
|
+
Token count as an integer, or `None` if state is unavailable.
|
|
1732
1734
|
"""
|
|
1733
1735
|
if not self._agent:
|
|
1734
1736
|
return None
|
|
@@ -1746,9 +1748,38 @@ class DeepAgentsApp(App):
|
|
|
1746
1748
|
messages = state.values.get("messages", [])
|
|
1747
1749
|
if not messages:
|
|
1748
1750
|
return None
|
|
1749
|
-
|
|
1750
|
-
|
|
1751
|
-
|
|
1751
|
+
return count_tokens_approximately(messages)
|
|
1752
|
+
except Exception: # best-effort for /tokens display
|
|
1753
|
+
logger.debug("Failed to retrieve conversation token count", exc_info=True)
|
|
1754
|
+
return None
|
|
1755
|
+
|
|
1756
|
+
def _resolve_compact_budget_str(self) -> str | None:
|
|
1757
|
+
"""Resolve the compaction retention budget as a human-readable string.
|
|
1758
|
+
|
|
1759
|
+
Instantiates a model and computes summarization defaults, so this is
|
|
1760
|
+
not a trivial accessor.
|
|
1761
|
+
|
|
1762
|
+
Returns:
|
|
1763
|
+
A string like `"20.0K (10% of 200.0K)"` or
|
|
1764
|
+
`"last 6 messages"`, or `None` if the budget cannot be determined.
|
|
1765
|
+
"""
|
|
1766
|
+
try:
|
|
1767
|
+
from deepagents.middleware.summarization import (
|
|
1768
|
+
compute_summarization_defaults,
|
|
1769
|
+
)
|
|
1770
|
+
|
|
1771
|
+
model_spec = f"{settings.model_provider}:{settings.model_name}"
|
|
1772
|
+
result = create_model(
|
|
1773
|
+
model_spec,
|
|
1774
|
+
profile_overrides=self._profile_override,
|
|
1775
|
+
)
|
|
1776
|
+
defaults = compute_summarization_defaults(result.model)
|
|
1777
|
+
return _format_compact_limit(
|
|
1778
|
+
defaults["keep"],
|
|
1779
|
+
settings.model_context_limit,
|
|
1780
|
+
)
|
|
1781
|
+
except Exception: # best-effort for /tokens display
|
|
1782
|
+
logger.debug("Failed to compute compaction budget string", exc_info=True)
|
|
1752
1783
|
return None
|
|
1753
1784
|
|
|
1754
1785
|
async def _handle_compact(self) -> None:
|
|
@@ -1760,9 +1791,9 @@ class DeepAgentsApp(App):
|
|
|
1760
1791
|
instead of the full history.
|
|
1761
1792
|
|
|
1762
1793
|
Compaction is a no-op when the conversation's total token count is
|
|
1763
|
-
within the `keep` budget
|
|
1764
|
-
|
|
1765
|
-
|
|
1794
|
+
within the `keep` budget. Until that threshold is exceeded the user
|
|
1795
|
+
sees "Nothing to compact" with the retention budget and a pointer to
|
|
1796
|
+
`/tokens` for a full breakdown.
|
|
1766
1797
|
"""
|
|
1767
1798
|
if not self._agent or not self._lc_thread_id or not self._backend:
|
|
1768
1799
|
await self._mount_message(
|
|
@@ -1876,27 +1907,29 @@ class DeepAgentsApp(App):
|
|
|
1876
1907
|
and context_limit is not None
|
|
1877
1908
|
and total_context > context_limit
|
|
1878
1909
|
):
|
|
1879
|
-
# Case A:
|
|
1880
|
-
#
|
|
1910
|
+
# Case A: total context exceeds model limit but
|
|
1911
|
+
# conversation is within keep budget — excess is
|
|
1912
|
+
# system prompt + tool overhead that compaction
|
|
1913
|
+
# cannot reduce
|
|
1881
1914
|
total_str = format_token_count(total_context)
|
|
1882
1915
|
await self._mount_message(
|
|
1883
1916
|
AppMessage(
|
|
1884
1917
|
f"Nothing to compact \u2014 conversation is only "
|
|
1885
|
-
f"~{conv_str} tokens.\n"
|
|
1886
|
-
f"Total context ({total_str}) is mostly
|
|
1887
|
-
f"prompt and tool overhead, which
|
|
1888
|
-
f"cannot reduce.\n"
|
|
1889
|
-
f"
|
|
1918
|
+
f"~{conv_str} tokens.\n\n"
|
|
1919
|
+
f"Total context ({total_str} tokens) is mostly "
|
|
1920
|
+
f"system prompt and tool overhead, which "
|
|
1921
|
+
f"compaction cannot reduce.\n\n"
|
|
1922
|
+
f"Use /tokens for a full breakdown."
|
|
1890
1923
|
)
|
|
1891
1924
|
)
|
|
1892
1925
|
else:
|
|
1893
1926
|
# Case B: genuinely within budget
|
|
1894
1927
|
await self._mount_message(
|
|
1895
1928
|
AppMessage(
|
|
1896
|
-
"Nothing to compact
|
|
1897
|
-
"within the
|
|
1898
|
-
f"
|
|
1899
|
-
f"
|
|
1929
|
+
f"Nothing to compact \u2014 conversation "
|
|
1930
|
+
f"(~{conv_str} tokens) is within the "
|
|
1931
|
+
f"retention budget ({compact_limit}).\n\n"
|
|
1932
|
+
f"Use /tokens for a full breakdown."
|
|
1900
1933
|
)
|
|
1901
1934
|
)
|
|
1902
1935
|
return
|
|
@@ -141,6 +141,7 @@ def parse_args() -> argparse.Namespace:
|
|
|
141
141
|
Returns:
|
|
142
142
|
Parsed arguments namespace.
|
|
143
143
|
"""
|
|
144
|
+
from deepagents_cli.output import add_json_output_arg
|
|
144
145
|
from deepagents_cli.skills import setup_skills_parser
|
|
145
146
|
from deepagents_cli.ui import (
|
|
146
147
|
build_help_parent,
|
|
@@ -226,6 +227,7 @@ def parse_args() -> argparse.Namespace:
|
|
|
226
227
|
add_help=False,
|
|
227
228
|
parents=help_parent(show_list_help),
|
|
228
229
|
)
|
|
230
|
+
add_json_output_arg(subparsers.choices["list"])
|
|
229
231
|
|
|
230
232
|
reset_parser = subparsers.add_parser(
|
|
231
233
|
"reset",
|
|
@@ -233,12 +235,17 @@ def parse_args() -> argparse.Namespace:
|
|
|
233
235
|
add_help=False,
|
|
234
236
|
parents=help_parent(show_reset_help),
|
|
235
237
|
)
|
|
238
|
+
add_json_output_arg(reset_parser)
|
|
236
239
|
reset_parser.add_argument("--agent", required=True, help="Name of agent to reset")
|
|
237
240
|
reset_parser.add_argument(
|
|
238
241
|
"--target", dest="source_agent", help="Copy prompt from another agent"
|
|
239
242
|
)
|
|
240
243
|
|
|
241
|
-
setup_skills_parser(
|
|
244
|
+
setup_skills_parser(
|
|
245
|
+
subparsers,
|
|
246
|
+
make_help_action=_make_help_action,
|
|
247
|
+
add_output_args=add_json_output_arg,
|
|
248
|
+
)
|
|
242
249
|
|
|
243
250
|
threads_parser = subparsers.add_parser(
|
|
244
251
|
"threads",
|
|
@@ -246,6 +253,7 @@ def parse_args() -> argparse.Namespace:
|
|
|
246
253
|
add_help=False,
|
|
247
254
|
parents=help_parent(show_threads_help),
|
|
248
255
|
)
|
|
256
|
+
add_json_output_arg(threads_parser)
|
|
249
257
|
threads_sub = threads_parser.add_subparsers(dest="threads_command")
|
|
250
258
|
|
|
251
259
|
threads_list = threads_sub.add_parser(
|
|
@@ -255,6 +263,7 @@ def parse_args() -> argparse.Namespace:
|
|
|
255
263
|
add_help=False,
|
|
256
264
|
parents=help_parent(show_threads_list_help),
|
|
257
265
|
)
|
|
266
|
+
add_json_output_arg(threads_list)
|
|
258
267
|
threads_list.add_argument(
|
|
259
268
|
"--agent", default=None, help="Filter by agent name (default: show all)"
|
|
260
269
|
)
|
|
@@ -296,6 +305,7 @@ def parse_args() -> argparse.Namespace:
|
|
|
296
305
|
add_help=False,
|
|
297
306
|
parents=help_parent(show_threads_delete_help),
|
|
298
307
|
)
|
|
308
|
+
add_json_output_arg(threads_delete)
|
|
299
309
|
threads_delete.add_argument("thread_id", help="Thread ID to delete")
|
|
300
310
|
|
|
301
311
|
# Default interactive mode — argument order here determines the
|
|
@@ -395,6 +405,8 @@ def parse_args() -> argparse.Namespace:
|
|
|
395
405
|
"instead of streaming token-by-token. Requires -n or piped stdin.",
|
|
396
406
|
)
|
|
397
407
|
|
|
408
|
+
add_json_output_arg(parser, default="text")
|
|
409
|
+
|
|
398
410
|
parser.add_argument(
|
|
399
411
|
"--auto-approve",
|
|
400
412
|
action="store_true",
|
|
@@ -1204,6 +1216,8 @@ def cli_main() -> None:
|
|
|
1204
1216
|
sys.exit(1)
|
|
1205
1217
|
sys.exit(0)
|
|
1206
1218
|
|
|
1219
|
+
output_format = getattr(args, "output_format", "text")
|
|
1220
|
+
|
|
1207
1221
|
if args.command == "help":
|
|
1208
1222
|
from deepagents_cli.ui import show_help
|
|
1209
1223
|
|
|
@@ -1211,11 +1225,11 @@ def cli_main() -> None:
|
|
|
1211
1225
|
elif args.command == "list":
|
|
1212
1226
|
from deepagents_cli.agent import list_agents
|
|
1213
1227
|
|
|
1214
|
-
list_agents()
|
|
1228
|
+
list_agents(output_format=output_format)
|
|
1215
1229
|
elif args.command == "reset":
|
|
1216
1230
|
from deepagents_cli.agent import reset_agent
|
|
1217
1231
|
|
|
1218
|
-
reset_agent(args.agent, args.source_agent)
|
|
1232
|
+
reset_agent(args.agent, args.source_agent, output_format=output_format)
|
|
1219
1233
|
elif args.command == "skills":
|
|
1220
1234
|
from deepagents_cli.skills import execute_skills_command
|
|
1221
1235
|
|
|
@@ -1238,10 +1252,13 @@ def cli_main() -> None:
|
|
|
1238
1252
|
branch=getattr(args, "branch", None),
|
|
1239
1253
|
verbose=getattr(args, "verbose", False),
|
|
1240
1254
|
relative=getattr(args, "relative", None),
|
|
1255
|
+
output_format=output_format,
|
|
1241
1256
|
)
|
|
1242
1257
|
)
|
|
1243
1258
|
elif args.threads_command == "delete":
|
|
1244
|
-
asyncio.run(
|
|
1259
|
+
asyncio.run(
|
|
1260
|
+
delete_thread_command(args.thread_id, output_format=output_format)
|
|
1261
|
+
)
|
|
1245
1262
|
else:
|
|
1246
1263
|
# No subcommand provided, show threads help screen
|
|
1247
1264
|
show_threads_help()
|
|
@@ -773,10 +773,9 @@ async def run_non_interactive(
|
|
|
773
773
|
thread_url_lookup: ThreadUrlLookupState | None = None
|
|
774
774
|
if not quiet:
|
|
775
775
|
thread_url_lookup = _start_langsmith_thread_url_lookup(thread_id)
|
|
776
|
-
console.print("[dim]Running task non-interactively...[/dim]")
|
|
776
|
+
console.print("[dim]Running task non-interactively...[/dim]", highlight=False)
|
|
777
777
|
header = _build_non_interactive_header(assistant_id, thread_id)
|
|
778
778
|
console.print(header)
|
|
779
|
-
console.print()
|
|
780
779
|
|
|
781
780
|
sandbox_backend = None
|
|
782
781
|
exit_stack = contextlib.ExitStack()
|
|
@@ -869,6 +868,9 @@ async def run_non_interactive(
|
|
|
869
868
|
assistant_id=assistant_id, backend=composite_backend
|
|
870
869
|
)
|
|
871
870
|
|
|
871
|
+
if not quiet:
|
|
872
|
+
console.print()
|
|
873
|
+
|
|
872
874
|
await _run_agent_loop(
|
|
873
875
|
agent,
|
|
874
876
|
message,
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
"""Machine-readable JSON output helpers for CLI subcommands.
|
|
2
|
+
|
|
3
|
+
This module deliberately stays stdlib-only so it can be imported from CLI
|
|
4
|
+
startup paths without pulling in unnecessary dependency trees.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
import argparse
|
|
10
|
+
import json
|
|
11
|
+
import sys
|
|
12
|
+
from typing import Literal
|
|
13
|
+
|
|
14
|
+
OutputFormat = Literal["text", "json"]
|
|
15
|
+
"""Accepted internal output modes for CLI subcommands."""
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def add_json_output_arg(
|
|
19
|
+
parser: argparse.ArgumentParser, *, default: OutputFormat | None = None
|
|
20
|
+
) -> None:
|
|
21
|
+
"""Add a `--json` flag to an argparse parser.
|
|
22
|
+
|
|
23
|
+
Args:
|
|
24
|
+
parser: Parser to update.
|
|
25
|
+
default: Default output format for this parser.
|
|
26
|
+
|
|
27
|
+
Pass `None` for subparsers so parent parser values are preserved.
|
|
28
|
+
"""
|
|
29
|
+
if default is None:
|
|
30
|
+
parser.add_argument(
|
|
31
|
+
"--json",
|
|
32
|
+
dest="output_format",
|
|
33
|
+
action="store_const",
|
|
34
|
+
const="json",
|
|
35
|
+
default=argparse.SUPPRESS,
|
|
36
|
+
help="Emit machine-readable JSON for this command",
|
|
37
|
+
)
|
|
38
|
+
else:
|
|
39
|
+
parser.add_argument(
|
|
40
|
+
"--json",
|
|
41
|
+
dest="output_format",
|
|
42
|
+
action="store_const",
|
|
43
|
+
const="json",
|
|
44
|
+
default=default,
|
|
45
|
+
help="Emit machine-readable JSON for this command",
|
|
46
|
+
)
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def write_json(command: str, data: list | dict) -> None:
|
|
50
|
+
"""Write a JSON envelope to stdout and flush.
|
|
51
|
+
|
|
52
|
+
The envelope is a single-line JSON object with a stable schema:
|
|
53
|
+
|
|
54
|
+
```json
|
|
55
|
+
{"schema_version": 1, "command": "...", "data": ...}
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
Args:
|
|
59
|
+
command: Self-documenting command name (e.g. `'list'`,
|
|
60
|
+
`'threads list'`).
|
|
61
|
+
data: Payload — typically a list for listing commands or a dict
|
|
62
|
+
for action/info commands.
|
|
63
|
+
|
|
64
|
+
`default=str` is used so that `Path` and `datetime` objects
|
|
65
|
+
serialize without error.
|
|
66
|
+
"""
|
|
67
|
+
envelope = {"schema_version": 1, "command": command, "data": data}
|
|
68
|
+
sys.stdout.write(json.dumps(envelope, default=str) + "\n")
|
|
69
|
+
sys.stdout.flush()
|
|
@@ -18,6 +18,8 @@ if TYPE_CHECKING:
|
|
|
18
18
|
from langgraph.checkpoint.serde.jsonplus import JsonPlusSerializer
|
|
19
19
|
from langgraph.checkpoint.sqlite.aio import AsyncSqliteSaver
|
|
20
20
|
|
|
21
|
+
from deepagents_cli.output import OutputFormat
|
|
22
|
+
|
|
21
23
|
logger = logging.getLogger(__name__)
|
|
22
24
|
|
|
23
25
|
_aiosqlite_patched = False
|
|
@@ -964,6 +966,8 @@ async def list_threads_command(
|
|
|
964
966
|
branch: str | None = None,
|
|
965
967
|
verbose: bool = False,
|
|
966
968
|
relative: bool | None = None,
|
|
969
|
+
*,
|
|
970
|
+
output_format: OutputFormat = "text",
|
|
967
971
|
) -> None:
|
|
968
972
|
"""CLI handler for `deepagents threads list`.
|
|
969
973
|
|
|
@@ -986,10 +990,8 @@ async def list_threads_command(
|
|
|
986
990
|
relative: Show timestamps as relative time (e.g., '5m ago').
|
|
987
991
|
|
|
988
992
|
When `None`, reads from config (`~/.deepagents/config.toml`).
|
|
993
|
+
output_format: Output format — `'text'` (Rich) or `'json'`.
|
|
989
994
|
"""
|
|
990
|
-
from rich.table import Table
|
|
991
|
-
|
|
992
|
-
from deepagents_cli.config import COLORS, console
|
|
993
995
|
from deepagents_cli.model_config import (
|
|
994
996
|
load_thread_relative_time,
|
|
995
997
|
load_thread_sort_order,
|
|
@@ -1018,6 +1020,16 @@ async def list_threads_command(
|
|
|
1018
1020
|
threads, include_message_count=False, include_initial_prompt=True
|
|
1019
1021
|
)
|
|
1020
1022
|
|
|
1023
|
+
if output_format == "json":
|
|
1024
|
+
from deepagents_cli.output import write_json
|
|
1025
|
+
|
|
1026
|
+
write_json("threads list", list(threads))
|
|
1027
|
+
return
|
|
1028
|
+
|
|
1029
|
+
from rich.table import Table
|
|
1030
|
+
|
|
1031
|
+
from deepagents_cli.config import COLORS, console
|
|
1032
|
+
|
|
1021
1033
|
if not threads:
|
|
1022
1034
|
filters = []
|
|
1023
1035
|
if agent_name:
|
|
@@ -1090,12 +1102,25 @@ async def list_threads_command(
|
|
|
1090
1102
|
console.print()
|
|
1091
1103
|
|
|
1092
1104
|
|
|
1093
|
-
async def delete_thread_command(
|
|
1094
|
-
|
|
1095
|
-
|
|
1105
|
+
async def delete_thread_command(
|
|
1106
|
+
thread_id: str, *, output_format: OutputFormat = "text"
|
|
1107
|
+
) -> None:
|
|
1108
|
+
"""CLI handler for: deepagents threads delete.
|
|
1096
1109
|
|
|
1110
|
+
Args:
|
|
1111
|
+
thread_id: ID of the thread to delete.
|
|
1112
|
+
output_format: Output format — `'text'` (Rich) or `'json'`.
|
|
1113
|
+
"""
|
|
1097
1114
|
deleted = await delete_thread(thread_id)
|
|
1098
1115
|
|
|
1116
|
+
if output_format == "json":
|
|
1117
|
+
from deepagents_cli.output import write_json
|
|
1118
|
+
|
|
1119
|
+
write_json("threads delete", {"thread_id": thread_id, "deleted": deleted})
|
|
1120
|
+
return
|
|
1121
|
+
|
|
1122
|
+
from deepagents_cli.config import console
|
|
1123
|
+
|
|
1099
1124
|
if deleted:
|
|
1100
1125
|
console.print(f"[green]Thread '{thread_id}' deleted.[/green]")
|
|
1101
1126
|
else:
|