deepagents-code 0.1.57__tar.gz → 0.1.59__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_code-0.1.57 → deepagents_code-0.1.59}/CHANGELOG.md +46 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/DEVELOPMENT.md +5 -1
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/PKG-INFO +25 -24
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/THREAT_MODEL.md +24 -1
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/_ask_user_types.py +225 -31
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/_build_info.py +1 -1
- deepagents_code-0.1.59/deepagents_code/_debug.py +371 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/_env_vars.py +56 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/_session_stats.py +90 -6
- deepagents_code-0.1.59/deepagents_code/_tool_errors.py +20 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/_tool_stream.py +297 -137
- deepagents_code-0.1.59/deepagents_code/_tracing.py +58 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/_version.py +1 -1
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/agent.py +105 -14
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/app.py +565 -730
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/ask_user.py +20 -24
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/auto_mode.py +33 -3
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/client/commands/config.py +303 -29
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/client/launch/server_manager.py +1 -1
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/client/non_interactive.py +9 -2
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/cold_cache.py +19 -6
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/config.py +253 -65
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/config_manifest.py +817 -305
- deepagents_code-0.1.59/deepagents_code/configuration/__init__.py +42 -0
- deepagents_code-0.1.59/deepagents_code/configuration/paths.py +161 -0
- deepagents_code-0.1.59/deepagents_code/configuration/providers.py +523 -0
- deepagents_code-0.1.59/deepagents_code/configuration/resolver.py +593 -0
- deepagents_code-0.1.59/deepagents_code/configuration/service.py +736 -0
- deepagents_code-0.1.59/deepagents_code/configuration/types.py +87 -0
- deepagents_code-0.1.59/deepagents_code/configuration/writer.py +147 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/doctor.py +38 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/goal_rubric.py +2 -2
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/goal_tools.py +3 -7
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/hooks/capabilities.py +2 -2
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/hooks/interrupt.py +2 -2
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/hooks/loading.py +1 -2
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/hooks/models/config.py +5 -2
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/hooks/models/domain.py +4 -4
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/hooks/models/wire.py +4 -4
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/hooks/presenter.py +3 -3
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/hooks/runner.py +21 -1
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/hooks/server_middleware.py +7 -20
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/input.py +1 -1
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/integrations/sandbox_config.py +76 -25
- deepagents_code-0.1.59/deepagents_code/json_types.py +16 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/main.py +321 -30
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/managed_tools.py +1 -46
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/mcp_auth.py +42 -8
- deepagents_code-0.1.59/deepagents_code/mcp_disabled.py +510 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/mcp_tools.py +381 -15
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/model_config.py +812 -178
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/plugins/adapters/skills.py +10 -7
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/project_utils.py +2 -2
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/server_graph.py +5 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/sessions.py +4 -2
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/skills/merge.py +9 -7
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/system_prompt.md +1 -14
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/terminal_escape.py +11 -2
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/theme.py +40 -16
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/tool_catalog.py +1 -1
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/tui/textual_adapter.py +6 -2
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/tui/widgets/_inline_prompt.py +8 -14
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/tui/widgets/_paste_textarea.py +268 -85
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/tui/widgets/ask_user.py +31 -28
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/tui/widgets/auth.py +31 -15
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/tui/widgets/auto_mode_notice.py +13 -12
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/tui/widgets/chat_input.py +267 -91
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/tui/widgets/mcp_viewer.py +92 -45
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/tui/widgets/messages.py +279 -44
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/tui/widgets/model_selector.py +4 -4
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/tui/widgets/notification_center.py +8 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/tui/widgets/startup_tip.py +1 -1
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/tui/widgets/status.py +193 -8
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/tui/widgets/yolo_mode_notice.py +2 -2
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/update_check.py +190 -113
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/pyproject.toml +21 -20
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/scripts/install.sh +17 -7
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/tests/unit_tests/conftest.py +49 -1
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/tests/unit_tests/hooks/test_execution.py +41 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/tests/unit_tests/smoke_tests/snapshots/system_prompt_interactive_local.md +0 -13
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/tests/unit_tests/smoke_tests/test_system_prompt.py +1 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/tests/unit_tests/test__tool_stream.py +244 -10
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/tests/unit_tests/test_agent.py +68 -1
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/tests/unit_tests/test_app.py +381 -210
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/tests/unit_tests/test_ask_user_middleware.py +300 -23
- deepagents_code-0.1.59/tests/unit_tests/test_ask_user_types.py +422 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/tests/unit_tests/test_auto_mode.py +209 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/tests/unit_tests/test_charset.py +3 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/tests/unit_tests/test_cold_cache.py +16 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/tests/unit_tests/test_config.py +14 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/tests/unit_tests/test_config_manifest.py +747 -0
- deepagents_code-0.1.59/tests/unit_tests/test_configuration.py +3152 -0
- deepagents_code-0.1.59/tests/unit_tests/test_configuration_resolution.py +499 -0
- deepagents_code-0.1.59/tests/unit_tests/test_configuration_resolver.py +215 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/tests/unit_tests/test_cursor_blink.py +39 -3
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/tests/unit_tests/test_debug.py +95 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/tests/unit_tests/test_end_to_end.py +52 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/tests/unit_tests/test_input_parsing.py +1 -2
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/tests/unit_tests/test_install_script.py +9 -4
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/tests/unit_tests/test_main.py +296 -24
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/tests/unit_tests/test_managed_tools.py +3 -66
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/tests/unit_tests/test_mcp_auth.py +75 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/tests/unit_tests/test_mcp_disabled.py +48 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/tests/unit_tests/test_mcp_tools.py +382 -91
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/tests/unit_tests/test_model_config.py +25 -6
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/tests/unit_tests/test_non_interactive.py +188 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/tests/unit_tests/test_offload.py +309 -20
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/tests/unit_tests/test_remote_client.py +12 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/tests/unit_tests/test_sandbox_config.py +23 -2
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/tests/unit_tests/test_server_graph.py +9 -7
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/tests/unit_tests/test_session_stats.py +244 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/tests/unit_tests/test_terminal_escape.py +10 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/tests/unit_tests/test_terminal_progress_preference.py +39 -3
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/tests/unit_tests/test_theme.py +12 -1
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/tests/unit_tests/test_threads_resume.py +1 -0
- deepagents_code-0.1.59/tests/unit_tests/test_tracing.py +72 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/tests/unit_tests/test_update_check.py +86 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/tests/unit_tests/tui/modals/plugin_manager/test_structure.py +63 -12
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/tests/unit_tests/tui/test_textual_adapter.py +40 -17
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/tests/unit_tests/tui/widgets/test_ask_user.py +143 -46
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/tests/unit_tests/tui/widgets/test_auth_widgets.py +67 -91
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/tests/unit_tests/tui/widgets/test_chat_input.py +1066 -13
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/tests/unit_tests/tui/widgets/test_inline_prompt.py +63 -5
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/tests/unit_tests/tui/widgets/test_mcp_viewer.py +206 -14
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/tests/unit_tests/tui/widgets/test_messages.py +327 -25
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/tests/unit_tests/tui/widgets/test_model_selector.py +9 -9
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/tests/unit_tests/tui/widgets/test_notification_center.py +23 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/tests/unit_tests/tui/widgets/test_status.py +446 -3
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/tests/unit_tests/tui/widgets/test_thread_selector.py +21 -0
- deepagents_code-0.1.59/tests/unit_tests/tui/widgets/test_yolo_mode_notice.py +8 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/uv.lock +74 -811
- deepagents_code-0.1.57/deepagents_code/_debug.py +0 -148
- deepagents_code-0.1.57/deepagents_code/json_types.py +0 -12
- deepagents_code-0.1.57/deepagents_code/mcp_disabled.py +0 -212
- deepagents_code-0.1.57/tests/unit_tests/test_ask_user_types.py +0 -118
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/.gitignore +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/AGENTS.md +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/ARCHITECTURE.md +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/COMMANDS.md +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/HOOKS.md +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/LICENSE +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/Makefile +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/PRICING.md +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/README.md +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/__init__.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/__main__.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/_cli_context.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/_constants.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/_debug_buffer.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/_dep_floor_check.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/_fake_models.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/_git.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/_glm_5p2_profile.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/_invocation.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/_markdown.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/_paths.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/_repository_bounds.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/_server_config.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/_startup_error.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/_testing_models.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/_textual_patches.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/acp.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/app.tcss +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/approval_mode.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/auth_display.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/auth_store.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/built_in_skills/__init__.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/built_in_skills/deepagents-thread-inspector/SKILL.md +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/built_in_skills/deepagents-thread-inspector/scripts/inspect_sessions.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/built_in_skills/remember/SKILL.md +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/built_in_skills/skill-creator/SKILL.md +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/built_in_skills/skill-creator/scripts/init_skill.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/built_in_skills/skill-creator/scripts/quick_validate.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/bundled_prices.README.md +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/bundled_prices.json +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/client/__init__.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/client/commands/__init__.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/client/commands/auth.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/client/commands/extras.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/client/commands/mcp.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/client/commands/tools.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/client/launch/__init__.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/client/launch/server.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/client/remote_client.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/clipboard.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/command_registry.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/configurable_model.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/cost_tracking.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/default_agent_prompt.md +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/diff_utils.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/editor.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/event_bus.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/extras_info.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/file_ops.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/formatting.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/goal_state_notice.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/hooks/__init__.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/hooks/client.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/hooks/client_lifecycle.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/hooks/context.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/hooks/engine.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/hooks/env.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/hooks/envelope.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/hooks/legacy.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/hooks/manager.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/hooks/migration.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/hooks/models/__init__.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/hooks/models/adapters.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/hooks/models/transport.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/hooks/permissions.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/hooks/projection.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/hooks/reducer.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/hooks/runtime.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/hooks/snapshot.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/hooks/tools.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/hooks/transcript.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/hooks/trust.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/hooks/validate_terminal_sequence.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/integrations/__init__.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/integrations/openai_codex.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/integrations/sandbox_factory.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/integrations/sandbox_provider.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/integrations/sandbox_registry.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/iterm_cursor_guide.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/local_context.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/mcp_config.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/mcp_login_service.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/mcp_oauth_ui.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/mcp_providers/__init__.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/mcp_providers/_registry.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/mcp_providers/base.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/mcp_providers/github.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/mcp_providers/slack.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/media_utils.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/memory_guard.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/notifications.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/offload.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/offload_middleware.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/onboarding.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/output.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/paste_collapse.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/plugins/__init__.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/plugins/_json.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/plugins/adapters/__init__.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/plugins/adapters/hooks.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/plugins/adapters/mcp.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/plugins/adapters/skills_middleware.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/plugins/commands_cli.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/plugins/discovery.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/plugins/manifest.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/plugins/marketplace.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/plugins/models.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/plugins/store.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/plugins/substitution.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/py.typed +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/reasoning_effort.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/reliable_rubric.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/resume_state.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/skills/__init__.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/skills/commands.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/skills/invocation.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/skills/load.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/skills/trust.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/state_migration.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/subagents.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/terminal_capabilities.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/tool_display.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/tools.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/tui/__init__.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/tui/modals/__init__.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/tui/modals/cold_cache.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/tui/modals/plugin_manager/__init__.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/tui/modals/plugin_manager/content.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/tui/modals/plugin_manager/models.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/tui/modals/plugin_manager/plugin_manager.tcss +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/tui/modals/plugin_manager/state.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/tui/modals/plugin_manager/tabs.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/tui/modals/resume_compact.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/tui/screens/__init__.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/tui/widgets/__init__.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/tui/widgets/_copy_spans.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/tui/widgets/_js_eval_display.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/tui/widgets/_links.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/tui/widgets/agent_selector.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/tui/widgets/approval.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/tui/widgets/autocomplete.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/tui/widgets/codex_auth.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/tui/widgets/context_usage.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/tui/widgets/cwd_switch.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/tui/widgets/debug_console.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/tui/widgets/diff.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/tui/widgets/effort_selector.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/tui/widgets/goal_review.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/tui/widgets/goal_status.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/tui/widgets/history.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/tui/widgets/install_confirm.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/tui/widgets/launch_init.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/tui/widgets/loading.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/tui/widgets/mcp_login.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/tui/widgets/mcp_reconnect.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/tui/widgets/message_store.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/tui/widgets/notification_detail.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/tui/widgets/notification_settings.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/tui/widgets/restart_prompt.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/tui/widgets/skill_trust.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/tui/widgets/subagent_panel.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/tui/widgets/theme_selector.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/tui/widgets/thread_agent_switch.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/tui/widgets/thread_selector.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/tui/widgets/tool_renderers.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/tui/widgets/tool_widgets.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/tui/widgets/update_available.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/tui/widgets/update_confirm.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/tui/widgets/update_progress.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/tui/widgets/welcome.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/ui.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/deepagents_code/unicode_security.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/examples/skills/arxiv-search/SKILL.md +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/examples/skills/arxiv-search/arxiv_search.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/examples/skills/langgraph-docs/SKILL.md +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/examples/skills/skill-creator/SKILL.md +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/examples/skills/skill-creator/scripts/init_skill.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/examples/skills/skill-creator/scripts/quick_validate.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/examples/skills/web-research/SKILL.md +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/hatch_build.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/images/tui.png +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/scripts/check_imports.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/scripts/debug_server.sh +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/scripts/generate_commands_catalog.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/tests/README.md +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/tests/integration_tests/__init__.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/tests/integration_tests/benchmarks/__init__.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/tests/integration_tests/benchmarks/test_codspeed_import_benchmarks.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/tests/integration_tests/benchmarks/test_local_context_benchmarks.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/tests/integration_tests/benchmarks/test_startup_benchmarks.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/tests/integration_tests/conftest.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/tests/integration_tests/test_acp_mode.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/tests/integration_tests/test_auto_approve_remote.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/tests/integration_tests/test_compact_resume.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/tests/integration_tests/test_goal_criteria_remote.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/tests/integration_tests/test_offload_server_side.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/tests/integration_tests/test_sandbox_factory.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/tests/integration_tests/test_sandbox_operations.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/tests/unit_tests/__init__.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/tests/unit_tests/client/__init__.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/tests/unit_tests/client/commands/__init__.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/tests/unit_tests/client/commands/test_auth.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/tests/unit_tests/client/commands/test_extras.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/tests/unit_tests/client/commands/test_mcp.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/tests/unit_tests/client/commands/test_tools.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/tests/unit_tests/data/coding_agent_v1_validator.json +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/tests/unit_tests/hooks/__init__.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/tests/unit_tests/hooks/models/__init__.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/tests/unit_tests/hooks/models/test_models.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/tests/unit_tests/hooks/test_client_lifecycle.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/tests/unit_tests/hooks/test_configuration.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/tests/unit_tests/hooks/test_engine.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/tests/unit_tests/hooks/test_manager.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/tests/unit_tests/hooks/test_presenter.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/tests/unit_tests/hooks/test_server_lifecycle.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/tests/unit_tests/hooks/test_transcript.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/tests/unit_tests/hooks/test_trust.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/tests/unit_tests/plugins/__init__.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/tests/unit_tests/plugins/test_marketplace.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/tests/unit_tests/plugins/test_plugin_hooks.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/tests/unit_tests/plugins/test_plugins_p0.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/tests/unit_tests/plugins/test_store.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/tests/unit_tests/skills/__init__.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/tests/unit_tests/skills/test_commands.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/tests/unit_tests/skills/test_load.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/tests/unit_tests/skills/test_merge.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/tests/unit_tests/skills/test_skill_trust.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/tests/unit_tests/skills/test_skills_json.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/tests/unit_tests/skills/test_thread_inspector.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/tests/unit_tests/smoke_tests/__init__.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/tests/unit_tests/smoke_tests/conftest.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/tests/unit_tests/test_acp.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/tests/unit_tests/test_agent_friendly.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/tests/unit_tests/test_approval_mode.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/tests/unit_tests/test_args.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/tests/unit_tests/test_auth_display.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/tests/unit_tests/test_auth_store.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/tests/unit_tests/test_auth_web_search_restart.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/tests/unit_tests/test_clipboard.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/tests/unit_tests/test_coding_agent_metadata.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/tests/unit_tests/test_command_registry.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/tests/unit_tests/test_compact_tool.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/tests/unit_tests/test_config_recursion_limit.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/tests/unit_tests/test_configurable_model.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/tests/unit_tests/test_cost_tracking.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/tests/unit_tests/test_cursor_style.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/tests/unit_tests/test_debug_buffer.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/tests/unit_tests/test_debug_console.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/tests/unit_tests/test_dep_floor_check.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/tests/unit_tests/test_diff_utils.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/tests/unit_tests/test_doctor.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/tests/unit_tests/test_editor.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/tests/unit_tests/test_env_vars.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/tests/unit_tests/test_event_bus.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/tests/unit_tests/test_exception_handling.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/tests/unit_tests/test_extras_info.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/tests/unit_tests/test_file_ops.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/tests/unit_tests/test_formatting.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/tests/unit_tests/test_git.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/tests/unit_tests/test_glm_5p2_profile.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/tests/unit_tests/test_goal_criteria_client.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/tests/unit_tests/test_goal_rubric.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/tests/unit_tests/test_goal_state_notice.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/tests/unit_tests/test_goal_state_persistence.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/tests/unit_tests/test_goal_tools.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/tests/unit_tests/test_hatch_build.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/tests/unit_tests/test_hooks.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/tests/unit_tests/test_imports.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/tests/unit_tests/test_install_command.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/tests/unit_tests/test_invocation.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/tests/unit_tests/test_iterm_cursor_guide.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/tests/unit_tests/test_json_types.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/tests/unit_tests/test_local_context.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/tests/unit_tests/test_main_acp_mode.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/tests/unit_tests/test_main_args.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/tests/unit_tests/test_mcp_config.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/tests/unit_tests/test_mcp_login_service.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/tests/unit_tests/test_mcp_oauth_ui.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/tests/unit_tests/test_media_utils.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/tests/unit_tests/test_memory_guard.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/tests/unit_tests/test_model_switch.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/tests/unit_tests/test_notifications.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/tests/unit_tests/test_onboarding.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/tests/unit_tests/test_openai_codex_integration.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/tests/unit_tests/test_output.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/tests/unit_tests/test_paths.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/tests/unit_tests/test_reasoning_effort.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/tests/unit_tests/test_reliable_rubric.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/tests/unit_tests/test_reload.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/tests/unit_tests/test_repository_bounds.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/tests/unit_tests/test_resume_state.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/tests/unit_tests/test_rubric_cli.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/tests/unit_tests/test_sandbox_factory.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/tests/unit_tests/test_sandbox_provider.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/tests/unit_tests/test_sandbox_registry.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/tests/unit_tests/test_server.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/tests/unit_tests/test_server_config.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/tests/unit_tests/test_server_helpers.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/tests/unit_tests/test_server_manager.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/tests/unit_tests/test_sessions.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/tests/unit_tests/test_shell_allow_list.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/tests/unit_tests/test_skill_invocation.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/tests/unit_tests/test_startup_blocking.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/tests/unit_tests/test_startup_fast_paths.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/tests/unit_tests/test_state_migration.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/tests/unit_tests/test_subagents.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/tests/unit_tests/test_terminal_capabilities.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/tests/unit_tests/test_textual_patches.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/tests/unit_tests/test_tool_catalog.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/tests/unit_tests/test_tool_display.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/tests/unit_tests/test_tracing_replicas.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/tests/unit_tests/test_transcript_virtualization.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/tests/unit_tests/test_ui.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/tests/unit_tests/test_unicode_security.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/tests/unit_tests/test_version.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/tests/unit_tests/tools/__init__.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/tests/unit_tests/tools/test_current_thread.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/tests/unit_tests/tools/test_fetch_url.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/tests/unit_tests/tools/test_tool_arg_schemas.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/tests/unit_tests/tui/__init__.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/tests/unit_tests/tui/modals/__init__.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/tests/unit_tests/tui/modals/plugin_manager/__init__.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/tests/unit_tests/tui/modals/test_cold_cache.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/tests/unit_tests/tui/test_subagent_stream.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/tests/unit_tests/tui/widgets/__init__.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/tests/unit_tests/tui/widgets/test_agent_selector.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/tests/unit_tests/tui/widgets/test_approval.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/tests/unit_tests/tui/widgets/test_auto_mode_notice.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/tests/unit_tests/tui/widgets/test_autocomplete.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/tests/unit_tests/tui/widgets/test_copy_spans.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/tests/unit_tests/tui/widgets/test_cwd_switch.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/tests/unit_tests/tui/widgets/test_diff.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/tests/unit_tests/tui/widgets/test_goal_review.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/tests/unit_tests/tui/widgets/test_history.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/tests/unit_tests/tui/widgets/test_install_confirm.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/tests/unit_tests/tui/widgets/test_launch_init.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/tests/unit_tests/tui/widgets/test_links.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/tests/unit_tests/tui/widgets/test_loading.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/tests/unit_tests/tui/widgets/test_mcp_login_modal.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/tests/unit_tests/tui/widgets/test_mcp_reconnect.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/tests/unit_tests/tui/widgets/test_message_store.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/tests/unit_tests/tui/widgets/test_notification_detail.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/tests/unit_tests/tui/widgets/test_notification_settings.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/tests/unit_tests/tui/widgets/test_restart_prompt.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/tests/unit_tests/tui/widgets/test_skill_trust_screen.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/tests/unit_tests/tui/widgets/test_startup_tip.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/tests/unit_tests/tui/widgets/test_subagent_panel.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/tests/unit_tests/tui/widgets/test_thread_agent_switch.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/tests/unit_tests/tui/widgets/test_tool_renderers.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/tests/unit_tests/tui/widgets/test_update_available.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/tests/unit_tests/tui/widgets/test_update_confirm.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/tests/unit_tests/tui/widgets/test_update_progress.py +0 -0
- {deepagents_code-0.1.57 → deepagents_code-0.1.59}/tests/unit_tests/tui/widgets/test_welcome.py +0 -0
|
@@ -2,6 +2,52 @@
|
|
|
2
2
|
|
|
3
3
|
# Deep Agents Code Changelog
|
|
4
4
|
|
|
5
|
+
## [0.1.59](https://github.com/langchain-ai/deepagents/compare/deepagents-code==0.1.58...deepagents-code==0.1.59) (2026-08-20)
|
|
6
|
+
|
|
7
|
+
### Features
|
|
8
|
+
|
|
9
|
+
- Added support for `managed_config.toml` configuration ([#5604](https://github.com/langchain-ai/deepagents/issues/5604))
|
|
10
|
+
- Multi-select `ask_user` answers are now encoded as JSON arrays ([#5660](https://github.com/langchain-ai/deepagents/issues/5660))
|
|
11
|
+
- Made teardown usage stats configurable ([#5696](https://github.com/langchain-ai/deepagents/issues/5696))
|
|
12
|
+
- Footer pickers now open on click ([#5674](https://github.com/langchain-ai/deepagents/issues/5674))
|
|
13
|
+
- Replaced Gemini 3.6 Flash with Gemini 3.7 Flash ([#5681](https://github.com/langchain-ai/deepagents/issues/5681))
|
|
14
|
+
|
|
15
|
+
### Bug fixes
|
|
16
|
+
|
|
17
|
+
- Made tool argument validation errors recoverable ([#5659](https://github.com/langchain-ai/deepagents/issues/5659))
|
|
18
|
+
- Improved streaming performance for tool-call arguments to run in linear time ([#5712](https://github.com/langchain-ai/deepagents/issues/5712))
|
|
19
|
+
- Fixed durable-mask config resolution with ranked resolver behavior ([#5672](https://github.com/langchain-ai/deepagents/issues/5672))
|
|
20
|
+
- Skipped background sync in Apple Terminal ([#5666](https://github.com/langchain-ai/deepagents/issues/5666))
|
|
21
|
+
- Hid thread IDs when tracing is disabled ([#5692](https://github.com/langchain-ai/deepagents/issues/5692))
|
|
22
|
+
- Kept installed providers visible in `/auth` ([#5689](https://github.com/langchain-ai/deepagents/issues/5689))
|
|
23
|
+
- Preloaded the auth UI before notification handoff ([#5697](https://github.com/langchain-ai/deepagents/issues/5697))
|
|
24
|
+
- Updated and clarified UI copy across Auto mode, YOLO hints, classifier notices, `/tokens`, line-number toggles, review failures, onboarding Tavily cancellation, and OpenAI subscription login labels ([#5685](https://github.com/langchain-ai/deepagents/issues/5685), [#5694](https://github.com/langchain-ai/deepagents/issues/5694), [#5684](https://github.com/langchain-ai/deepagents/issues/5684), [#5687](https://github.com/langchain-ai/deepagents/issues/5687), [#5680](https://github.com/langchain-ai/deepagents/issues/5680), [#5688](https://github.com/langchain-ai/deepagents/issues/5688), [#5686](https://github.com/langchain-ai/deepagents/issues/5686), [#5691](https://github.com/langchain-ai/deepagents/issues/5691), [#5693](https://github.com/langchain-ai/deepagents/issues/5693))
|
|
25
|
+
- Removed the `Muse Spark 1.1` recommendation ([#5683](https://github.com/langchain-ai/deepagents/issues/5683))
|
|
26
|
+
|
|
27
|
+
## [0.1.58](https://github.com/langchain-ai/deepagents/compare/deepagents-code==0.1.57...deepagents-code==0.1.58) (2026-08-19)
|
|
28
|
+
|
|
29
|
+
### Breaking Changes
|
|
30
|
+
|
|
31
|
+
- `deepagents-code` now requires Python 3.12 or newer. ([#5603](https://github.com/langchain-ai/deepagents/issues/5603))
|
|
32
|
+
|
|
33
|
+
### Features
|
|
34
|
+
|
|
35
|
+
- Added OpenRouter `z-ai/glm-5.3` to the model switcher. ([#5641](https://github.com/langchain-ai/deepagents/issues/5641))
|
|
36
|
+
- Added support for re-authenticating MCP servers from the viewer. ([#5637](https://github.com/langchain-ai/deepagents/issues/5637))
|
|
37
|
+
- Footer pickers can now be opened with `ctrl+click`. ([#5611](https://github.com/langchain-ai/deepagents/issues/5611))
|
|
38
|
+
- Resume hints now account for `TERM_PROGRAM` support before showing terminal-specific guidance. ([#5580](https://github.com/langchain-ai/deepagents/issues/5580))
|
|
39
|
+
|
|
40
|
+
### Fixes
|
|
41
|
+
|
|
42
|
+
- Completed the `dcode config` command surface. ([#5581](https://github.com/langchain-ai/deepagents/issues/5581))
|
|
43
|
+
- Made `/offload` interruptible. ([#5590](https://github.com/langchain-ai/deepagents/issues/5590))
|
|
44
|
+
- Improved chat and footer UI behavior: rapid typing stays visible, double-click collapses a resized chat input, and the MCP footer wraps on narrow windows. ([#5424](https://github.com/langchain-ai/deepagents/issues/5424), [#5578](https://github.com/langchain-ai/deepagents/issues/5578), [#5651](https://github.com/langchain-ai/deepagents/issues/5651))
|
|
45
|
+
- Captured stdio MCP server stderr in the logger. ([#5610](https://github.com/langchain-ai/deepagents/issues/5610))
|
|
46
|
+
- Drained hook pipes after timeout. ([#5606](https://github.com/langchain-ai/deepagents/issues/5606))
|
|
47
|
+
- Grouped resume trace rounds. ([#5593](https://github.com/langchain-ai/deepagents/issues/5593))
|
|
48
|
+
- Omitted web-search prompt guidance when web search is unavailable. ([#5602](https://github.com/langchain-ai/deepagents/issues/5602))
|
|
49
|
+
- Resolved message pointer shapes per cell. ([#5592](https://github.com/langchain-ai/deepagents/issues/5592))
|
|
50
|
+
|
|
5
51
|
## [0.1.57](https://github.com/langchain-ai/deepagents/compare/deepagents-code==0.1.56...deepagents-code==0.1.57) (2026-08-18)
|
|
6
52
|
|
|
7
53
|
### Features
|
|
@@ -138,6 +138,10 @@ tail -f /tmp/deepagents_debug.log
|
|
|
138
138
|
|
|
139
139
|
To send it elsewhere, also `export DEEPAGENTS_CODE_DEBUG_FILE=<path>`. The handler appends across runs, so a single file accumulates every session.
|
|
140
140
|
|
|
141
|
+
The file is created or tightened to user-only access. A symlink at the path is refused. If the file cannot be secured, no file handler is attached and a warning goes to stderr. Use the in-app Debug Console in that case.
|
|
142
|
+
|
|
143
|
+
Stdio MCP server stderr is captured here at `DEBUG`. This keeps server-side failures visible when the TUI cannot show process stderr. Each record is one line, capped at 4096 characters. Characters in the Unicode `C` categories are removed, which includes control and format characters. The ESC byte of an ANSI sequence is removed but the rest stays as literal text, so the log is not free of escape-sequence residue. The text comes from the server. It can contain credentials or other sensitive values. Enable `DEBUG` logging only if you accept that risk, and do not share the log file.
|
|
144
|
+
|
|
141
145
|
### In-app Debug Console (`Ctrl+\`)
|
|
142
146
|
|
|
143
147
|
Press `Ctrl+\` (or run the hidden `/debug` command) inside a session to toggle a read-only Debug Console overlay. It shows a point-in-time session/runtime snapshot (version, model, thread, cwd, auto-approve, sandbox, MCP servers, token usage, debug-log path) plus a live tail of recent `deepagents_code.*` log records.
|
|
@@ -168,7 +172,7 @@ uv pip install --python ~/.local/share/dcode-dev/bin/python -e <repo>/libs/code
|
|
|
168
172
|
ln -sf ~/.local/share/dcode-dev/bin/dcode ~/.local/bin/dcode-dev
|
|
169
173
|
```
|
|
170
174
|
|
|
171
|
-
The `--python 3.13` is illustrative — any interpreter satisfying the package's `requires-python` (currently `>=3.
|
|
175
|
+
The `--python 3.13` is illustrative — any interpreter satisfying the package's `requires-python` (currently `>=3.12`) works; omit the flag to let `uv` pick.
|
|
172
176
|
|
|
173
177
|
> **Why `uv venv` + `uv pip install -e` rather than `uv sync` or `uv tool install --editable`?** This builds an isolated venv *outside* the workspace's locked environment, so the dev binary can be re-resolved on demand without disturbing the released tool or the repo's `uv.lock`. (`uv pip` and `uv venv` are first-class `uv` subcommands here, not bare `pip`.)
|
|
174
178
|
|
|
@@ -1,15 +1,17 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: deepagents-code
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.59
|
|
4
4
|
Summary: Terminal coding agent built on the Deep Agents SDK - works with any model, with persistent memory, customizable skills, subagents, and approval controls.
|
|
5
|
-
Project-URL: Homepage, https://
|
|
6
|
-
Project-URL: Documentation, https://
|
|
5
|
+
Project-URL: Homepage, https://www.langchain.com/dcode
|
|
6
|
+
Project-URL: Documentation, https://docs.langchain.com/oss/deepagents/code/overview
|
|
7
7
|
Project-URL: Repository, https://github.com/langchain-ai/deepagents
|
|
8
8
|
Project-URL: Issues, https://github.com/langchain-ai/deepagents/issues
|
|
9
9
|
Project-URL: Changelog, https://github.com/langchain-ai/deepagents/blob/main/libs/code/CHANGELOG.md
|
|
10
10
|
Project-URL: Twitter, https://x.com/langchain_oss
|
|
11
11
|
Project-URL: Slack, https://www.langchain.com/join-community
|
|
12
12
|
Project-URL: Reddit, https://www.reddit.com/r/LangChain/
|
|
13
|
+
Author: LangChain
|
|
14
|
+
Maintainer: LangChain
|
|
13
15
|
License: MIT
|
|
14
16
|
License-File: LICENSE
|
|
15
17
|
Keywords: agents,ai,cli,deep-agent,langchain,langgraph,llm,terminal
|
|
@@ -18,32 +20,31 @@ Classifier: Environment :: Console
|
|
|
18
20
|
Classifier: Intended Audience :: Developers
|
|
19
21
|
Classifier: License :: OSI Approved :: MIT License
|
|
20
22
|
Classifier: Programming Language :: Python :: 3
|
|
21
|
-
Classifier: Programming Language :: Python :: 3.11
|
|
22
23
|
Classifier: Programming Language :: Python :: 3.12
|
|
23
24
|
Classifier: Programming Language :: Python :: 3.13
|
|
24
25
|
Classifier: Programming Language :: Python :: 3.14
|
|
25
26
|
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
26
27
|
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
27
28
|
Classifier: Topic :: Terminals
|
|
28
|
-
Requires-Python: <4.0,>=3.
|
|
29
|
+
Requires-Python: <4.0,>=3.12
|
|
29
30
|
Requires-Dist: aiosqlite<1.0.0,>=0.22.1
|
|
30
31
|
Requires-Dist: anyio<5.0.0,>=4.14.2
|
|
31
32
|
Requires-Dist: deepagents-acp<1.0.0,>=0.0.10
|
|
32
|
-
Requires-Dist: deepagents==0.7.
|
|
33
|
+
Requires-Dist: deepagents==0.7.8
|
|
33
34
|
Requires-Dist: filelock<3.30,>=3.29.7
|
|
34
|
-
Requires-Dist: genai-prices<0.2.0,>=0.1.
|
|
35
|
+
Requires-Dist: genai-prices<0.2.0,>=0.1.4
|
|
35
36
|
Requires-Dist: httpx<1.0.0,>=0.28.1
|
|
36
|
-
Requires-Dist: langchain-anthropic<2.0.0,>=1.
|
|
37
|
-
Requires-Dist: langchain-google-genai<5.0.0,>=4.3.
|
|
37
|
+
Requires-Dist: langchain-anthropic<2.0.0,>=1.6.1
|
|
38
|
+
Requires-Dist: langchain-google-genai<5.0.0,>=4.3.4
|
|
38
39
|
Requires-Dist: langchain-mcp-adapters<1.0.0,>=0.3.2
|
|
39
|
-
Requires-Dist: langchain-openai<2.0.0,>=1.
|
|
40
|
+
Requires-Dist: langchain-openai<2.0.0,>=1.6.0
|
|
40
41
|
Requires-Dist: langchain-quickjs<0.4.0,>=0.3.4
|
|
41
|
-
Requires-Dist: langchain<2.0.0,>=1.3.
|
|
42
|
+
Requires-Dist: langchain<2.0.0,>=1.3.16
|
|
42
43
|
Requires-Dist: langgraph-checkpoint-sqlite<4.0.0,>=3.1.1
|
|
43
44
|
Requires-Dist: langgraph-cli[inmem]<1.0.0,>=0.4.31
|
|
44
|
-
Requires-Dist: langgraph-runtime-inmem<1.0.0,>=0.32.
|
|
45
|
-
Requires-Dist: langgraph-sdk<1.0.0,>=0.4.
|
|
46
|
-
Requires-Dist: langsmith[sandbox]>=0.
|
|
45
|
+
Requires-Dist: langgraph-runtime-inmem<1.0.0,>=0.32.6
|
|
46
|
+
Requires-Dist: langgraph-sdk<1.0.0,>=0.4.3
|
|
47
|
+
Requires-Dist: langsmith[sandbox]>=0.11.1
|
|
47
48
|
Requires-Dist: markdownify<2.0.0,>=1.2.3
|
|
48
49
|
Requires-Dist: mcp<2.0.0,>=1.28.1
|
|
49
50
|
Requires-Dist: packaging>=26.2
|
|
@@ -65,13 +66,13 @@ Provides-Extra: agentcore
|
|
|
65
66
|
Requires-Dist: langchain-agentcore-codeinterpreter<1.0.0,>=0.0.5; extra == 'agentcore'
|
|
66
67
|
Provides-Extra: all-providers
|
|
67
68
|
Requires-Dist: aiohttp<3.15.0,>=3.14.3; extra == 'all-providers'
|
|
68
|
-
Requires-Dist: langchain-anthropic<2.0.0,>=1.
|
|
69
|
-
Requires-Dist: langchain-aws<2.0.0,>=1.7.
|
|
69
|
+
Requires-Dist: langchain-anthropic<2.0.0,>=1.6.1; extra == 'all-providers'
|
|
70
|
+
Requires-Dist: langchain-aws<2.0.0,>=1.7.2; extra == 'all-providers'
|
|
70
71
|
Requires-Dist: langchain-baseten<1.0.0,>=0.2.3; extra == 'all-providers'
|
|
71
72
|
Requires-Dist: langchain-cohere<1.0.0,>=0.6.0; extra == 'all-providers'
|
|
72
73
|
Requires-Dist: langchain-deepseek<2.0.0,>=1.1.0; extra == 'all-providers'
|
|
73
74
|
Requires-Dist: langchain-fireworks<2.0.0,>=1.5.2; extra == 'all-providers'
|
|
74
|
-
Requires-Dist: langchain-google-genai<5.0.0,>=4.3.
|
|
75
|
+
Requires-Dist: langchain-google-genai<5.0.0,>=4.3.4; extra == 'all-providers'
|
|
75
76
|
Requires-Dist: langchain-google-vertexai<4.0.0,>=3.2.4; extra == 'all-providers'
|
|
76
77
|
Requires-Dist: langchain-groq<2.0.0,>=1.1.3; extra == 'all-providers'
|
|
77
78
|
Requires-Dist: langchain-huggingface<2.0.0,>=1.2.2; extra == 'all-providers'
|
|
@@ -81,8 +82,8 @@ Requires-Dist: langchain-meta<2.0.0,>=0.5.0; extra == 'all-providers'
|
|
|
81
82
|
Requires-Dist: langchain-mistralai<2.0.0,>=1.1.6; extra == 'all-providers'
|
|
82
83
|
Requires-Dist: langchain-nvidia-ai-endpoints<2.0.0,>=1.4.3; extra == 'all-providers'
|
|
83
84
|
Requires-Dist: langchain-ollama<2.0.0,>=1.1.0; extra == 'all-providers'
|
|
84
|
-
Requires-Dist: langchain-openai<2.0.0,>=1.
|
|
85
|
-
Requires-Dist: langchain-openrouter<2.0.0,>=0.2.
|
|
85
|
+
Requires-Dist: langchain-openai<2.0.0,>=1.6.0; extra == 'all-providers'
|
|
86
|
+
Requires-Dist: langchain-openrouter<2.0.0,>=0.2.8; extra == 'all-providers'
|
|
86
87
|
Requires-Dist: langchain-perplexity<2.0.0,>=1.4.0; extra == 'all-providers'
|
|
87
88
|
Requires-Dist: langchain-together<2.0.0,>=0.4.0; extra == 'all-providers'
|
|
88
89
|
Requires-Dist: langchain-xai<2.0.0,>=1.3.0; extra == 'all-providers'
|
|
@@ -93,11 +94,11 @@ Requires-Dist: langchain-modal>=0.0.5; extra == 'all-sandboxes'
|
|
|
93
94
|
Requires-Dist: langchain-runloop>=0.0.6; extra == 'all-sandboxes'
|
|
94
95
|
Requires-Dist: langchain-vercel-sandbox>=0.0.1; extra == 'all-sandboxes'
|
|
95
96
|
Provides-Extra: anthropic
|
|
96
|
-
Requires-Dist: langchain-anthropic<2.0.0,>=1.
|
|
97
|
+
Requires-Dist: langchain-anthropic<2.0.0,>=1.6.1; extra == 'anthropic'
|
|
97
98
|
Provides-Extra: baseten
|
|
98
99
|
Requires-Dist: langchain-baseten<1.0.0,>=0.2.3; extra == 'baseten'
|
|
99
100
|
Provides-Extra: bedrock
|
|
100
|
-
Requires-Dist: langchain-aws<2.0.0,>=1.7.
|
|
101
|
+
Requires-Dist: langchain-aws<2.0.0,>=1.7.2; extra == 'bedrock'
|
|
101
102
|
Provides-Extra: cohere
|
|
102
103
|
Requires-Dist: langchain-cohere<1.0.0,>=0.6.0; extra == 'cohere'
|
|
103
104
|
Provides-Extra: daytona
|
|
@@ -107,7 +108,7 @@ Requires-Dist: langchain-deepseek<2.0.0,>=1.1.0; extra == 'deepseek'
|
|
|
107
108
|
Provides-Extra: fireworks
|
|
108
109
|
Requires-Dist: langchain-fireworks<2.0.0,>=1.5.2; extra == 'fireworks'
|
|
109
110
|
Provides-Extra: google-genai
|
|
110
|
-
Requires-Dist: langchain-google-genai<5.0.0,>=4.3.
|
|
111
|
+
Requires-Dist: langchain-google-genai<5.0.0,>=4.3.4; extra == 'google-genai'
|
|
111
112
|
Provides-Extra: groq
|
|
112
113
|
Requires-Dist: langchain-groq<2.0.0,>=1.1.3; extra == 'groq'
|
|
113
114
|
Provides-Extra: huggingface
|
|
@@ -131,9 +132,9 @@ Requires-Dist: langchain-nvidia-ai-endpoints<2.0.0,>=1.4.3; extra == 'nvidia'
|
|
|
131
132
|
Provides-Extra: ollama
|
|
132
133
|
Requires-Dist: langchain-ollama<2.0.0,>=1.1.0; extra == 'ollama'
|
|
133
134
|
Provides-Extra: openai
|
|
134
|
-
Requires-Dist: langchain-openai<2.0.0,>=1.
|
|
135
|
+
Requires-Dist: langchain-openai<2.0.0,>=1.6.0; extra == 'openai'
|
|
135
136
|
Provides-Extra: openrouter
|
|
136
|
-
Requires-Dist: langchain-openrouter<2.0.0,>=0.2.
|
|
137
|
+
Requires-Dist: langchain-openrouter<2.0.0,>=0.2.8; extra == 'openrouter'
|
|
137
138
|
Provides-Extra: perplexity
|
|
138
139
|
Requires-Dist: langchain-perplexity<2.0.0,>=1.4.0; extra == 'perplexity'
|
|
139
140
|
Provides-Extra: quickjs
|
|
@@ -50,6 +50,7 @@
|
|
|
50
50
|
6. The LangGraph dev server subprocess binds to `127.0.0.1` by default (`client/launch/server.py:_DEFAULT_HOST`) and is ephemeral — started and stopped per CLI session.
|
|
51
51
|
7. `DA_SERVER_*` environment variables are readable only by the CLI process and its child server subprocess (OS process isolation assumption).
|
|
52
52
|
8. Users who set `class_path` in `config.toml` accept the same trust model as `pyproject.toml` build scripts — they control their own machine.
|
|
53
|
+
9. Administrators deploy and protect the fixed `managed_config.toml` path with operating-system controls; the CLI does not validate its owner or mode and never writes it.
|
|
53
54
|
|
|
54
55
|
---
|
|
55
56
|
|
|
@@ -129,7 +130,7 @@
|
|
|
129
130
|
| C6 | Hook Runtime | Fires subprocess commands on agent lifecycle events | framework-controlled | No³ | `hooks.runtime.HooksRuntime`, `hooks.runner.run_command_handler` |
|
|
130
131
|
| C7 | Sandbox Integration | Creates/destroys remote sandboxes (Daytona, LangSmith, Modal, Runloop, AgentCore) | framework-controlled | No⁴ | `integrations.sandbox_factory.create_sandbox` |
|
|
131
132
|
| C8 | Session Persistence | SQLite checkpoint store for LangGraph thread state | framework-controlled | Yes | `sessions.get_db_path`, `sessions.generate_thread_id` |
|
|
132
|
-
| C9 | Configuration System | TOML
|
|
133
|
+
| C9 | Configuration System | Managed/user TOML, env vars, `AGENTS.md` system prompts, model config | administrator/user-controlled | N/A | `configuration`, `config.settings`, `model_config.ModelConfig`, fixed managed path, `~/.deepagents/config.toml` |
|
|
133
134
|
| C10 | Unicode/URL Safety | Detects hidden Unicode, checks URL domain spoofing for approval UI warnings | framework-controlled | Yes | `unicode_security.detect_dangerous_unicode`, `unicode_security.check_url_safety` |
|
|
134
135
|
| C11 | LangGraph Dev Server | Subprocess running `langgraph dev` with `LANGGRAPH_AUTH_TYPE=noop`; managed by `ServerProcess` | framework-controlled | Yes⁵ | `client.launch.server.ServerProcess.start`, `client.launch.server.generate_langgraph_json`, `client.launch.server_manager.start_server_and_get_agent` |
|
|
135
136
|
| C12 | Remote Agent Client | HTTP+SSE client wrapping `RemoteGraph`; connects to C11 on localhost | framework-controlled | Yes⁵ | `client.remote_client.RemoteAgent.astream`, `client.remote_client.RemoteAgent.aget_state` |
|
|
@@ -207,6 +208,7 @@
|
|
|
207
208
|
| TB9 | LocalContextMiddleware → Host Env | Bash detect script output (git info, project files, Makefile) injected into system prompt | Script is framework-generated static code; 30s timeout; exit-code check | Content of Makefile, pyproject.toml, git branch names, directory listing |
|
|
208
209
|
| TB10 | RemoteAgent → LangGraph Dev Server | CLI communicates with agent via HTTP+SSE on localhost | Server bound to `127.0.0.1` (`client/launch/server.py:_DEFAULT_HOST`); ephemeral per session | No authentication (`LANGGRAPH_AUTH_TYPE=noop`); any localhost process can reach the API |
|
|
209
210
|
| TB11 | Config File → Code Execution | `class_path` in `config.toml` triggers `importlib.import_module()`; project/global `.env` values are loaded into the process environment and can reach Bash startup hooks | Format validation (`module:ClassName`); `issubclass(BaseChatModel)` check; dotenv loading denies shell startup / environment-hijack keys (`BASH_ENV`, `ENV`) | Module-level side effects execute during import; user controls config file; project files in the working directory influence execution |
|
|
211
|
+
| TB12 | Managed Config → Runtime | A fixed administrator-deployed TOML file overrides CLI, environment, and user preferences | Fixed non-redirectable path; the CLI never writes the file; fail-closed startup for every command except diagnostics; typed resolution; diagnostics remain available | Filesystem ownership/mode and privileged deployment are outside the CLI; a host administrator can weaken or strengthen policy |
|
|
210
212
|
|
|
211
213
|
### Boundary Details
|
|
212
214
|
|
|
@@ -261,6 +263,26 @@
|
|
|
261
263
|
- **Inside (dotenv)**: `config._load_dotenv` loads project and global `.env` values with `override=False` and drops shell startup / environment-hijack keys (`BASH_ENV`, `ENV`, and related) so a project `.env` cannot register a script that Bash would source at startup. The preview path (`_preview_dotenv_environ`) applies the same denylist so a dry-run config change cannot report a value a real reload would reject.
|
|
262
264
|
- **Outside (dotenv)**: All other `.env` keys are applied to the process environment, and any project file in the working directory (`.env`, `Makefile`, build scripts) can still influence execution. See T12.
|
|
263
265
|
|
|
266
|
+
#### TB12: Managed Config → Runtime
|
|
267
|
+
|
|
268
|
+
- **Inside**: The resolver reads one fixed OS path. The writer rejects that path, so the managed source is read-only by guard and not only by convention. Valid managed values take the highest precedence. The rules are:
|
|
269
|
+
- Tables deep-merge. Deny lists union. An explicit managed allow or trust list replaces lower-precedence grants.
|
|
270
|
+
- A managed scalar replaces a colliding user table at any depth, so a user cannot defeat policy by changing the shape of a key. This holds on the top-level merge and inside a structured table: both apply the manifest validator, so the effective value and the audited provenance agree.
|
|
271
|
+
- A wrong-typed managed scalar is skipped, and the lower-precedence value stays in effect.
|
|
272
|
+
- Inside a structured table (`[models.providers]`, `[themes]`, `[async_subagents]`, `[sandboxes.providers]`, `[ui.terminal_themes]`, `[threads.columns]`) the dedicated typed reader validates instead. A wrong-typed managed leaf there can displace a valid user leaf, after which the reader falls back to the built-in default.
|
|
273
|
+
- An enforced key whose managed value cannot be applied stops every command except the diagnostics listed below. It also blocks `/reload`. Skipping it would leave the user's CLI flag or environment variable in force. The enforced keys are `startup.mode`, `startup.yolo_switcher`, `shell.allow_list`, `skills.extra_allowed_dirs`, `interpreter.enable_interpreter`, `interpreter.ptc`, `interpreter.ptc_acknowledge_unsafe`, `models.auto_classifier`, `runtime.recursion_limit`, `sandboxes.default`, and `tracing.langsmith_redact`.
|
|
274
|
+
- Three conditions make an enforced key unapplicable: a wrong-typed value, a `runtime.recursion_limit` outside its bounds, and a key made unreachable by a scalar ancestor (`startup = "manual"` in place of `[startup]` and `mode`). A managed `[sandboxes].default` that names an unavailable backend stops a sandboxed launch.
|
|
275
|
+
- A scalar at a known section is rejected for the same reason, so it cannot replace the user's whole section. `[effort]` is included, although it has no manifest option.
|
|
276
|
+
- Any other rejected managed value is ignored, and `dcode doctor` and `dcode config` name it. An ignored key is never silent.
|
|
277
|
+
- A missing file is accepted and applies no policy.
|
|
278
|
+
- A present unreadable, undecodable, or syntactically corrupt file blocks every command except `--help`, `--version`, `help`, `config`, `doctor`, and `auth path`. It also blocks `/reload`.
|
|
279
|
+
- On Windows, a ProgramData directory that cannot be read from the registry blocks the same commands. The path would be a guess, and an empty read at a guessed path does not prove that no policy is deployed. Reporting it as a missing file made every managed setting silently inert on a host whose ProgramData is relocated.
|
|
280
|
+
- A failed `/reload` keeps the last snapshot that parsed cleanly, so policy is never dropped mid-session.
|
|
281
|
+
- An unusable user `config.toml` drops only the user layer, so managed policy still applies.
|
|
282
|
+
- A deny list that cannot be read is treated as denying everything, never as empty. This covers a managed `[mcp].disabled_servers` that is neither an array of names nor a comma-separated string, and a `[mcp]` section that is not a table. A managed `[mcp].enabled_project_server_approvals` that is not an array is treated the same way: the key is present, so policy means to narrow access, and reading its presence as absence would keep both the user's approvals and the `DEEPAGENTS_CODE_DANGEROUSLY_ENABLE_PROJECT_MCP_SERVERS` bypass in force.
|
|
283
|
+
- **Outside**: Ownership, permission-mode validation, privileged installation, and `sudo` policy are deployment responsibilities. Anyone who can replace the administrator-managed file can control model, sandbox, interpreter, MCP trust, and other supported runtime settings. On macOS, note that stock `/Library/Application Support` is group-writable by `admin`, so any admin-group member can create the file and grant themselves policy. Deployments that rely on this boundary must tighten ownership and mode on the `dcode` directory.
|
|
284
|
+
- **Crossing mechanism**: Synchronous local file read through `configuration.TomlFileProvider`, followed by typed resolution and CLI/server startup gates.
|
|
285
|
+
|
|
264
286
|
---
|
|
265
287
|
|
|
266
288
|
## Data Flows
|
|
@@ -292,6 +314,7 @@
|
|
|
292
314
|
| DF23 | C9 Config | C17 Model Config | `class_path` string from `config.toml` | — | TB11 | TOML parse → importlib |
|
|
293
315
|
| DF24 | C5 MCP Config | MCP Subprocess | `env` dict from `.mcp.json` forwarded to stdio subprocess | DC1 | TB4 | subprocess environment |
|
|
294
316
|
| DF25 | C3 Agent | C7 Sandbox | Conversation messages for offload | DC5 | TB6 | `backend.awrite()` |
|
|
317
|
+
| DF26 | Administrator | C9 Config | Managed TOML policy | DC1 | TB12 | Fixed local file read |
|
|
295
318
|
|
|
296
319
|
### Flow Details
|
|
297
320
|
|
|
@@ -11,6 +11,7 @@ side produces it and which reads it.
|
|
|
11
11
|
|
|
12
12
|
from __future__ import annotations
|
|
13
13
|
|
|
14
|
+
import json
|
|
14
15
|
from typing import Annotated, Literal, NotRequired, assert_never, get_args
|
|
15
16
|
|
|
16
17
|
from pydantic import Field
|
|
@@ -61,23 +62,97 @@ same as being *rendered* as a choice list: the TUI has its own exhaustive
|
|
|
61
62
|
dispatch in `_QuestionWidget.compose`.
|
|
62
63
|
"""
|
|
63
64
|
|
|
64
|
-
MULTI_SELECT_ANSWER_SEPARATOR = ", "
|
|
65
|
-
"""Separator joining the selected values of a `multi_select` answer."""
|
|
66
65
|
|
|
67
|
-
|
|
68
|
-
"""
|
|
66
|
+
def encode_multi_select_answer(values: list[str]) -> str:
|
|
67
|
+
"""Encode the selected values of a `multi_select` answer for the wire.
|
|
69
68
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
69
|
+
The answer stays one string so `answers: list[str]` keeps one slot per
|
|
70
|
+
question, positionally matched. JSON is self-delimiting, so values carrying
|
|
71
|
+
commas, quotes, or newlines round-trip exactly.
|
|
72
|
+
|
|
73
|
+
The encoding is opaque to a consumer that only moves the answer around. A
|
|
74
|
+
consumer that tests whether the user answered at all must go through
|
|
75
|
+
`ask_user_answer_is_empty`: an unselected `multi_select` encodes as the
|
|
76
|
+
*truthy* string `[]`, so a bare `.strip()` reads it as answered.
|
|
77
|
+
|
|
78
|
+
Args:
|
|
79
|
+
values: Selected values — toggled predefined choices in choice-list
|
|
80
|
+
order, then custom Other values in slot order.
|
|
81
|
+
|
|
82
|
+
Returns:
|
|
83
|
+
The values as a JSON array, e.g. `["a", "b"]`. An empty selection
|
|
84
|
+
encodes as `[]`. The result never contains a line feed or carriage
|
|
85
|
+
return, so it cannot split a blank-line-separated transcript block.
|
|
86
|
+
`ensure_ascii=False` does pass U+2028 and U+2029 through literally, so
|
|
87
|
+
do not read this as "the result is a single line to every consumer" —
|
|
88
|
+
the guarantee is about the block separator only.
|
|
89
|
+
"""
|
|
90
|
+
return json.dumps(values, ensure_ascii=False)
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
def decode_multi_select_answer(raw: str) -> list[str] | None:
|
|
94
|
+
"""Decode a `multi_select` answer produced by `encode_multi_select_answer`.
|
|
95
|
+
|
|
96
|
+
Args:
|
|
97
|
+
raw: The raw answer string for a `multi_select` question. Must already
|
|
98
|
+
be a `str`: a non-string raises `TypeError` out of `json.loads`
|
|
99
|
+
rather than returning `None`. Every call site establishes that
|
|
100
|
+
first — `_parse_answers` coerces non-string answers,
|
|
101
|
+
`_validated_ask_user_answers` checks `isinstance(answer, str)`, and
|
|
102
|
+
the display path passes a slice of the transcript.
|
|
103
|
+
|
|
104
|
+
Returns:
|
|
105
|
+
The selected values, or `None` when `raw` is not a JSON array of
|
|
106
|
+
strings. Callers choose the policy for `None`; the one thing none of
|
|
107
|
+
them may do is fall back to splitting on `", "`, which mis-splits a
|
|
108
|
+
value that contains a comma.
|
|
109
|
+
"""
|
|
110
|
+
try:
|
|
111
|
+
decoded = json.loads(raw)
|
|
112
|
+
except (json.JSONDecodeError, RecursionError):
|
|
113
|
+
return None
|
|
114
|
+
if not isinstance(decoded, list) or not all(
|
|
115
|
+
isinstance(value, str) for value in decoded
|
|
116
|
+
):
|
|
117
|
+
return None
|
|
118
|
+
return decoded
|
|
74
119
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
`
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
120
|
+
|
|
121
|
+
def ask_user_answer_is_empty(answer: str, question_type: object) -> bool:
|
|
122
|
+
"""Return whether an `ask_user` answer counts as "no answer".
|
|
123
|
+
|
|
124
|
+
The single definition of emptiness for an answer, shared by the TUI (which
|
|
125
|
+
blocks submitting a required question) and by the Auto authorization path
|
|
126
|
+
(which keeps unanswered questions out of the consent evidence). Both sides
|
|
127
|
+
must agree: an answer the TUI accepts as empty must not read as consent
|
|
128
|
+
evidence downstream.
|
|
129
|
+
|
|
130
|
+
A bare `.strip()` is wrong for `multi_select`, whose empty encoding is the
|
|
131
|
+
truthy string `[]`. Every other type is empty when it is blank.
|
|
132
|
+
|
|
133
|
+
Args:
|
|
134
|
+
answer: The raw answer string for the question.
|
|
135
|
+
question_type: The paired question's `type`. Anything other than
|
|
136
|
+
`'multi_select'` — including a malformed or missing type — takes the
|
|
137
|
+
blank test.
|
|
138
|
+
|
|
139
|
+
Returns:
|
|
140
|
+
`True` when the question has no substantive answer.
|
|
141
|
+
"""
|
|
142
|
+
if question_type == "multi_select":
|
|
143
|
+
# A malformed encoding counts as empty, which is the fail-closed side of
|
|
144
|
+
# both call sites: the TUI re-prompts a *required* question (an optional
|
|
145
|
+
# one submits unchanged), and Auto withholds the answer from the consent
|
|
146
|
+
# evidence rather than passing an undecodable string to the classifier.
|
|
147
|
+
#
|
|
148
|
+
# This makes emptiness asymmetric across types for the `(cancelled)` and
|
|
149
|
+
# `(error: ...)` placeholders, which are not JSON: on a `multi_select`
|
|
150
|
+
# they read as empty and are withheld from the evidence, while the same
|
|
151
|
+
# placeholder on a `text` question becomes a row. Withholding is the
|
|
152
|
+
# safe direction, so the asymmetry is acceptable — but it is real, and a
|
|
153
|
+
# future caller counting answered questions across types will see it.
|
|
154
|
+
return not decode_multi_select_answer(answer)
|
|
155
|
+
return not answer.strip()
|
|
81
156
|
|
|
82
157
|
|
|
83
158
|
class Choice(TypedDict):
|
|
@@ -88,7 +163,11 @@ class Choice(TypedDict):
|
|
|
88
163
|
Field(
|
|
89
164
|
description=(
|
|
90
165
|
"The display label for this choice. Also the text returned as "
|
|
91
|
-
"the answer when this choice is selected."
|
|
166
|
+
"the answer when this choice is selected. A 'multi_select' answer "
|
|
167
|
+
"is a JSON array, so a value may contain commas, quotes, and "
|
|
168
|
+
"newlines; JSON escaping keeps it exact. A 'multiple_choice' "
|
|
169
|
+
"value is returned on its own with no escaping, so keep that "
|
|
170
|
+
"one to a single line."
|
|
92
171
|
)
|
|
93
172
|
),
|
|
94
173
|
]
|
|
@@ -108,10 +187,9 @@ class Question(TypedDict):
|
|
|
108
187
|
"one or more predefined options. Both choice types always append an "
|
|
109
188
|
"'Other' free-form option automatically; multi-select can accept "
|
|
110
189
|
"multiple custom Other values (filling one reveals another). A "
|
|
111
|
-
"'multi_select' answer comes back as the selected
|
|
112
|
-
|
|
113
|
-
"is selected on an optional question the answer is
|
|
114
|
-
"string."
|
|
190
|
+
"'multi_select' answer comes back as a JSON array of the selected "
|
|
191
|
+
'values (including any custom Other text), e.g. ["a", "b"]; if '
|
|
192
|
+
"nothing is selected on an optional question the answer is []."
|
|
115
193
|
)
|
|
116
194
|
),
|
|
117
195
|
]
|
|
@@ -124,9 +202,10 @@ class Question(TypedDict):
|
|
|
124
202
|
"Options for 'multiple_choice' and 'multi_select' questions. "
|
|
125
203
|
"Every choice needs a non-empty 'value'. An 'Other' free-form "
|
|
126
204
|
"option is always appended automatically for both types; "
|
|
127
|
-
"multi-select may collect multiple custom Other values. "
|
|
128
|
-
"'multi_select'
|
|
129
|
-
"
|
|
205
|
+
"multi-select may collect multiple custom Other values. A "
|
|
206
|
+
"'multi_select' answer is a JSON array of the selected "
|
|
207
|
+
"values, so values (including custom Other text) may "
|
|
208
|
+
"contain commas, quotes, and newlines."
|
|
130
209
|
)
|
|
131
210
|
),
|
|
132
211
|
]
|
|
@@ -170,6 +249,10 @@ MAX_ASK_USER_AUTHORIZATION_ANSWER_CHARS = 4000
|
|
|
170
249
|
# These limits bound the receipt-anchored question/answer evidence copied into
|
|
171
250
|
# Auto's classifier prompt. Questions are model-generated and otherwise have no
|
|
172
251
|
# schema length constraint, so they must not be able to exhaust that context.
|
|
252
|
+
# The answer budget is measured on the answer as it travels the wire, which for
|
|
253
|
+
# `multi_select` is the JSON encoding: escaping and quoting count toward the
|
|
254
|
+
# limit, so a selection can cross it while its decoded values would not.
|
|
255
|
+
# Crossing it withholds the receipt, which is the fail-closed direction.
|
|
173
256
|
MAX_ASK_USER_AUTHORIZATION_QUESTION_CHARS = 4000
|
|
174
257
|
MAX_ASK_USER_AUTHORIZATION_QUESTION_TOTAL_CHARS = 8000
|
|
175
258
|
|
|
@@ -205,6 +288,20 @@ AskUserWidgetResult = AskUserAnswered | AskUserCancelled
|
|
|
205
288
|
"""Discriminated union for the ask_user widget Future result."""
|
|
206
289
|
|
|
207
290
|
|
|
291
|
+
ASK_USER_NOTHING_SELECTED = "(nothing selected)"
|
|
292
|
+
"""Display-only placeholder for a `multi_select` the user left unselected.
|
|
293
|
+
|
|
294
|
+
Distinct from `ASK_USER_NO_ANSWER`, which marks a *missing* answer: this one
|
|
295
|
+
marks an answer that arrived and selected nothing. Only
|
|
296
|
+
`render_ask_user_transcript_for_display` produces it, and only for a human — the
|
|
297
|
+
transcript the model reads keeps the `[]` encoding.
|
|
298
|
+
|
|
299
|
+
In-band like the other placeholders, so a `multi_select` value spelled
|
|
300
|
+
`(nothing selected)` renders indistinguishably from an empty selection. The
|
|
301
|
+
result feeds no trust decision, so this costs legibility in a corner case
|
|
302
|
+
rather than correctness.
|
|
303
|
+
"""
|
|
304
|
+
|
|
208
305
|
ASK_USER_NO_ANSWER = "(no answer)"
|
|
209
306
|
"""Placeholder for a question with no positionally matching answer.
|
|
210
307
|
|
|
@@ -327,15 +424,25 @@ def format_ask_user_transcript(questions: list[Question], answers: list[str]) ->
|
|
|
327
424
|
r"""Render questions and answers as the `Q:`/`A:` transcript.
|
|
328
425
|
|
|
329
426
|
This is the text the `ask_user` tool returns to the model and persists in the
|
|
330
|
-
thread. The TUI renders that authoritative text literally
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
427
|
+
thread. The TUI renders that authoritative text literally, except for the
|
|
428
|
+
display-only re-render in `render_ask_user_transcript_for_display`, which
|
|
429
|
+
anchors on the known question text and gives up rather than guess.
|
|
430
|
+
|
|
431
|
+
Answers of every type are interpolated unescaped, so the encoding is not
|
|
432
|
+
unambiguously decodable: an answer containing a blank line followed by a
|
|
433
|
+
literal `Q: <text>\nA:` header is indistinguishable from a real block
|
|
434
|
+
boundary. Only the model reads it that way today. Any future decoder must
|
|
435
|
+
anchor on the known question text rather than on a generic `Q: ` pattern,
|
|
436
|
+
or a crafted answer can fabricate an extra question/answer pair.
|
|
437
|
+
|
|
438
|
+
For an answer `encode_multi_select_answer` produced, the JSON encoding does
|
|
439
|
+
close the hazard above: no encoded value can carry a raw line feed, so it
|
|
440
|
+
cannot fabricate a block boundary. This function cannot *rely* on that,
|
|
441
|
+
because it does not validate answers and not every answer is encoded — the
|
|
442
|
+
cancel and error paths in `_parse_answers` substitute `(cancelled)` and
|
|
443
|
+
`(error: ...)` placeholders for every question whatever its type, and a
|
|
444
|
+
non-TUI client resuming the interrupt can put arbitrary text in a
|
|
445
|
+
`multi_select` slot.
|
|
339
446
|
|
|
340
447
|
Args:
|
|
341
448
|
questions: Questions that were asked. Callers must pass questions whose
|
|
@@ -354,3 +461,90 @@ def format_ask_user_transcript(questions: list[Question], answers: list[str]) ->
|
|
|
354
461
|
for i, question in enumerate(questions)
|
|
355
462
|
]
|
|
356
463
|
return "\n\n".join(blocks)
|
|
464
|
+
|
|
465
|
+
|
|
466
|
+
def render_ask_user_transcript_for_display(
|
|
467
|
+
questions: list[Question], transcript: str
|
|
468
|
+
) -> str | None:
|
|
469
|
+
r"""Re-render a transcript with `multi_select` answers unpacked for a human.
|
|
470
|
+
|
|
471
|
+
The transcript is built for the model, where a `multi_select` answer is a
|
|
472
|
+
JSON array. A person reading the same text sees the quoting and, worse, sees
|
|
473
|
+
a multi-line custom answer flattened to a literal `\n`. This unpacks those
|
|
474
|
+
answers back to one value per line, leaving every other answer untouched.
|
|
475
|
+
|
|
476
|
+
Recovering the answers means splitting the transcript, which
|
|
477
|
+
`format_ask_user_transcript` warns is not unambiguously decodable. So this
|
|
478
|
+
anchors on the known question text, the mitigation that docstring
|
|
479
|
+
prescribes, and gives up rather than guessing: a transcript that does not
|
|
480
|
+
match the questions exactly returns `None` and must be rendered literally.
|
|
481
|
+
An answer may itself contain a later `Q: ...` block verbatim (pasting
|
|
482
|
+
transcript-like text into a text answer is legitimate), so a separator must
|
|
483
|
+
be unique to be trusted — with duplicates, the first occurrence would
|
|
484
|
+
swallow the real blocks into the wrong answer and misattribute the rest.
|
|
485
|
+
The result is display-only and feeds no trust decision.
|
|
486
|
+
|
|
487
|
+
Two things this deliberately does not do. It does not reject trailing
|
|
488
|
+
content: the last answer runs to the end of the transcript, so junk appended
|
|
489
|
+
after the final block is indistinguishable from answer text and is
|
|
490
|
+
re-emitted verbatim. And it does not handle three or more identically worded
|
|
491
|
+
questions — their shared anchor makes the separator non-unique, so a
|
|
492
|
+
perfectly well-formed transcript falls back to literal rendering. Both are
|
|
493
|
+
display-only outcomes.
|
|
494
|
+
|
|
495
|
+
Args:
|
|
496
|
+
questions: The questions that produced `transcript`, in order.
|
|
497
|
+
transcript: Output of `format_ask_user_transcript` for those questions.
|
|
498
|
+
|
|
499
|
+
Returns:
|
|
500
|
+
The re-rendered transcript, or `None` when `transcript` does not parse
|
|
501
|
+
as exactly these questions — including when no answer needed
|
|
502
|
+
unpacking, so the caller keeps its literal rendering. The two
|
|
503
|
+
cases share one sentinel because the caller wants the same literal
|
|
504
|
+
rendering either way. A caller that wants to report an unexpected
|
|
505
|
+
`None` should first check that a `multi_select` is present at all,
|
|
506
|
+
which is what the TUI row does.
|
|
507
|
+
"""
|
|
508
|
+
if not questions:
|
|
509
|
+
return None
|
|
510
|
+
anchors = [f"Q: {question.get('question', '')}\nA: " for question in questions]
|
|
511
|
+
answers: list[str] = []
|
|
512
|
+
position = 0
|
|
513
|
+
for index, anchor in enumerate(anchors):
|
|
514
|
+
if not transcript.startswith(anchor, position):
|
|
515
|
+
return None
|
|
516
|
+
position += len(anchor)
|
|
517
|
+
if index + 1 == len(anchors):
|
|
518
|
+
# The final answer runs to the end, so there is nothing left to
|
|
519
|
+
# check: trailing junk cannot be told apart from answer text.
|
|
520
|
+
answers.append(transcript[position:])
|
|
521
|
+
break
|
|
522
|
+
separator = f"\n\n{anchors[index + 1]}"
|
|
523
|
+
end = transcript.find(separator, position)
|
|
524
|
+
# `end` indexes the first of the two newlines, so `end + 2` is the `Q`
|
|
525
|
+
# of the next anchor. Re-searching from there cannot re-find this match,
|
|
526
|
+
# and cannot miss one that overlaps it: an occurrence starting at
|
|
527
|
+
# `end + 1` would need `transcript[end + 2]` to be a newline, and it is
|
|
528
|
+
# the `Q`. So the check establishes exactly one separator ahead.
|
|
529
|
+
if end == -1 or transcript.find(separator, end + 2) != -1:
|
|
530
|
+
return None
|
|
531
|
+
answers.append(transcript[position:end])
|
|
532
|
+
position = end + 2
|
|
533
|
+
|
|
534
|
+
changed = False
|
|
535
|
+
blocks: list[str] = []
|
|
536
|
+
for question, answer in zip(questions, answers, strict=True):
|
|
537
|
+
rendered = answer
|
|
538
|
+
if question.get("type") == "multi_select":
|
|
539
|
+
values = decode_multi_select_answer(answer)
|
|
540
|
+
if values is not None:
|
|
541
|
+
# One per line, so a value that itself spans lines stays
|
|
542
|
+
# legible. This trades away distinguishability: `["a", "b"]` and
|
|
543
|
+
# `["a\nb"]` render identically. Legibility is the point here and
|
|
544
|
+
# nothing downstream parses the result, so the trade is fine.
|
|
545
|
+
rendered = "\n".join(values) if values else ASK_USER_NOTHING_SELECTED
|
|
546
|
+
changed = changed or rendered != answer
|
|
547
|
+
blocks.append(f"Q: {question.get('question', '')}\nA: {rendered}")
|
|
548
|
+
if not changed:
|
|
549
|
+
return None
|
|
550
|
+
return "\n\n".join(blocks)
|