zjcode 0.0.1__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.
- zjcode-0.0.1/.gitignore +258 -0
- zjcode-0.0.1/AGENTS.md +136 -0
- zjcode-0.0.1/ARCHITECTURE.md +70 -0
- zjcode-0.0.1/CHANGELOG.md +618 -0
- zjcode-0.0.1/COMMANDS.md +55 -0
- zjcode-0.0.1/DEVELOPMENT.md +215 -0
- zjcode-0.0.1/Makefile +126 -0
- zjcode-0.0.1/PKG-INFO +220 -0
- zjcode-0.0.1/README.md +72 -0
- zjcode-0.0.1/THREAT_MODEL.md +496 -0
- zjcode-0.0.1/bump-version.py +250 -0
- zjcode-0.0.1/dcode-dev.ps1 +32 -0
- zjcode-0.0.1/deepagents_code/__init__.py +42 -0
- zjcode-0.0.1/deepagents_code/__main__.py +6 -0
- zjcode-0.0.1/deepagents_code/_ask_user_types.py +90 -0
- zjcode-0.0.1/deepagents_code/_cli_context.py +96 -0
- zjcode-0.0.1/deepagents_code/_constants.py +41 -0
- zjcode-0.0.1/deepagents_code/_debug.py +148 -0
- zjcode-0.0.1/deepagents_code/_debug_buffer.py +204 -0
- zjcode-0.0.1/deepagents_code/_env_vars.py +411 -0
- zjcode-0.0.1/deepagents_code/_fake_models.py +66 -0
- zjcode-0.0.1/deepagents_code/_git.py +521 -0
- zjcode-0.0.1/deepagents_code/_paths.py +69 -0
- zjcode-0.0.1/deepagents_code/_server_config.py +576 -0
- zjcode-0.0.1/deepagents_code/_session_stats.py +235 -0
- zjcode-0.0.1/deepagents_code/_startup_error.py +45 -0
- zjcode-0.0.1/deepagents_code/_testing_models.py +305 -0
- zjcode-0.0.1/deepagents_code/_textual_patches.py +420 -0
- zjcode-0.0.1/deepagents_code/_tool_stream.py +694 -0
- zjcode-0.0.1/deepagents_code/_version.py +46 -0
- zjcode-0.0.1/deepagents_code/agent.py +1976 -0
- zjcode-0.0.1/deepagents_code/app.py +19239 -0
- zjcode-0.0.1/deepagents_code/app.tcss +438 -0
- zjcode-0.0.1/deepagents_code/approval_mode.py +131 -0
- zjcode-0.0.1/deepagents_code/ask_user.py +306 -0
- zjcode-0.0.1/deepagents_code/auth_display.py +185 -0
- zjcode-0.0.1/deepagents_code/auth_store.py +545 -0
- zjcode-0.0.1/deepagents_code/built_in_skills/__init__.py +5 -0
- zjcode-0.0.1/deepagents_code/built_in_skills/remember/SKILL.md +118 -0
- zjcode-0.0.1/deepagents_code/built_in_skills/skill-creator/SKILL.md +383 -0
- zjcode-0.0.1/deepagents_code/built_in_skills/skill-creator/scripts/init_skill.py +366 -0
- zjcode-0.0.1/deepagents_code/built_in_skills/skill-creator/scripts/quick_validate.py +158 -0
- zjcode-0.0.1/deepagents_code/client/__init__.py +1 -0
- zjcode-0.0.1/deepagents_code/client/commands/__init__.py +1 -0
- zjcode-0.0.1/deepagents_code/client/commands/auth.py +541 -0
- zjcode-0.0.1/deepagents_code/client/commands/config.py +714 -0
- zjcode-0.0.1/deepagents_code/client/commands/mcp.py +250 -0
- zjcode-0.0.1/deepagents_code/client/commands/tools.py +416 -0
- zjcode-0.0.1/deepagents_code/client/launch/__init__.py +1 -0
- zjcode-0.0.1/deepagents_code/client/launch/server.py +978 -0
- zjcode-0.0.1/deepagents_code/client/launch/server_manager.py +540 -0
- zjcode-0.0.1/deepagents_code/client/non_interactive.py +1758 -0
- zjcode-0.0.1/deepagents_code/client/remote_client.py +794 -0
- zjcode-0.0.1/deepagents_code/clipboard.py +217 -0
- zjcode-0.0.1/deepagents_code/command_registry.py +450 -0
- zjcode-0.0.1/deepagents_code/config.py +4829 -0
- zjcode-0.0.1/deepagents_code/config_manifest.py +1451 -0
- zjcode-0.0.1/deepagents_code/configurable_model.py +577 -0
- zjcode-0.0.1/deepagents_code/default_agent_prompt.md +12 -0
- zjcode-0.0.1/deepagents_code/doctor.py +559 -0
- zjcode-0.0.1/deepagents_code/editor.py +142 -0
- zjcode-0.0.1/deepagents_code/event_bus.py +411 -0
- zjcode-0.0.1/deepagents_code/extras_info.py +661 -0
- zjcode-0.0.1/deepagents_code/file_ops.py +576 -0
- zjcode-0.0.1/deepagents_code/formatting.py +135 -0
- zjcode-0.0.1/deepagents_code/goal_rubric.py +497 -0
- zjcode-0.0.1/deepagents_code/goal_tools.py +459 -0
- zjcode-0.0.1/deepagents_code/hooks.py +348 -0
- zjcode-0.0.1/deepagents_code/input.py +1041 -0
- zjcode-0.0.1/deepagents_code/integrations/__init__.py +1 -0
- zjcode-0.0.1/deepagents_code/integrations/openai_codex.py +551 -0
- zjcode-0.0.1/deepagents_code/integrations/sandbox_config.py +198 -0
- zjcode-0.0.1/deepagents_code/integrations/sandbox_factory.py +1124 -0
- zjcode-0.0.1/deepagents_code/integrations/sandbox_provider.py +137 -0
- zjcode-0.0.1/deepagents_code/integrations/sandbox_registry.py +350 -0
- zjcode-0.0.1/deepagents_code/iterm_cursor_guide.py +176 -0
- zjcode-0.0.1/deepagents_code/local_context.py +926 -0
- zjcode-0.0.1/deepagents_code/main.py +3985 -0
- zjcode-0.0.1/deepagents_code/managed_tools.py +642 -0
- zjcode-0.0.1/deepagents_code/mcp_auth.py +1950 -0
- zjcode-0.0.1/deepagents_code/mcp_config.py +176 -0
- zjcode-0.0.1/deepagents_code/mcp_disabled.py +212 -0
- zjcode-0.0.1/deepagents_code/mcp_login_service.py +281 -0
- zjcode-0.0.1/deepagents_code/mcp_oauth_ui.py +199 -0
- zjcode-0.0.1/deepagents_code/mcp_providers/__init__.py +23 -0
- zjcode-0.0.1/deepagents_code/mcp_providers/_registry.py +39 -0
- zjcode-0.0.1/deepagents_code/mcp_providers/base.py +133 -0
- zjcode-0.0.1/deepagents_code/mcp_providers/github.py +102 -0
- zjcode-0.0.1/deepagents_code/mcp_providers/slack.py +175 -0
- zjcode-0.0.1/deepagents_code/mcp_tools.py +2427 -0
- zjcode-0.0.1/deepagents_code/mcp_trust.py +207 -0
- zjcode-0.0.1/deepagents_code/media_utils.py +826 -0
- zjcode-0.0.1/deepagents_code/memory_guard.py +474 -0
- zjcode-0.0.1/deepagents_code/model_config.py +4156 -0
- zjcode-0.0.1/deepagents_code/notifications.py +247 -0
- zjcode-0.0.1/deepagents_code/offload.py +402 -0
- zjcode-0.0.1/deepagents_code/onboarding.py +223 -0
- zjcode-0.0.1/deepagents_code/output.py +69 -0
- zjcode-0.0.1/deepagents_code/paste_collapse.py +103 -0
- zjcode-0.0.1/deepagents_code/project_utils.py +231 -0
- zjcode-0.0.1/deepagents_code/py.typed +0 -0
- zjcode-0.0.1/deepagents_code/reasoning_effort.py +641 -0
- zjcode-0.0.1/deepagents_code/reliable_rubric.py +97 -0
- zjcode-0.0.1/deepagents_code/resume_state.py +237 -0
- zjcode-0.0.1/deepagents_code/server_graph.py +310 -0
- zjcode-0.0.1/deepagents_code/session_end_summary.py +329 -0
- zjcode-0.0.1/deepagents_code/sessions.py +1716 -0
- zjcode-0.0.1/deepagents_code/skills/__init__.py +18 -0
- zjcode-0.0.1/deepagents_code/skills/commands.py +1252 -0
- zjcode-0.0.1/deepagents_code/skills/invocation.py +112 -0
- zjcode-0.0.1/deepagents_code/skills/load.py +196 -0
- zjcode-0.0.1/deepagents_code/skills/trust.py +547 -0
- zjcode-0.0.1/deepagents_code/state_migration.py +136 -0
- zjcode-0.0.1/deepagents_code/subagents.py +278 -0
- zjcode-0.0.1/deepagents_code/system_prompt.md +204 -0
- zjcode-0.0.1/deepagents_code/terminal_capabilities.py +115 -0
- zjcode-0.0.1/deepagents_code/terminal_escape.py +287 -0
- zjcode-0.0.1/deepagents_code/theme.py +891 -0
- zjcode-0.0.1/deepagents_code/todo_list_prompt.md +12 -0
- zjcode-0.0.1/deepagents_code/tool_catalog.py +509 -0
- zjcode-0.0.1/deepagents_code/tool_display.py +367 -0
- zjcode-0.0.1/deepagents_code/tools.py +516 -0
- zjcode-0.0.1/deepagents_code/tui/__init__.py +1 -0
- zjcode-0.0.1/deepagents_code/tui/textual_adapter.py +2553 -0
- zjcode-0.0.1/deepagents_code/tui/widgets/__init__.py +9 -0
- zjcode-0.0.1/deepagents_code/tui/widgets/_js_eval_display.py +139 -0
- zjcode-0.0.1/deepagents_code/tui/widgets/_links.py +261 -0
- zjcode-0.0.1/deepagents_code/tui/widgets/agent_selector.py +420 -0
- zjcode-0.0.1/deepagents_code/tui/widgets/approval.py +602 -0
- zjcode-0.0.1/deepagents_code/tui/widgets/ask_user.py +515 -0
- zjcode-0.0.1/deepagents_code/tui/widgets/auth.py +1997 -0
- zjcode-0.0.1/deepagents_code/tui/widgets/autocomplete.py +890 -0
- zjcode-0.0.1/deepagents_code/tui/widgets/chat_input.py +3181 -0
- zjcode-0.0.1/deepagents_code/tui/widgets/codex_auth.py +452 -0
- zjcode-0.0.1/deepagents_code/tui/widgets/cwd_switch.py +242 -0
- zjcode-0.0.1/deepagents_code/tui/widgets/debug_console.py +868 -0
- zjcode-0.0.1/deepagents_code/tui/widgets/diff.py +252 -0
- zjcode-0.0.1/deepagents_code/tui/widgets/effort_selector.py +189 -0
- zjcode-0.0.1/deepagents_code/tui/widgets/goal_review.py +390 -0
- zjcode-0.0.1/deepagents_code/tui/widgets/goal_status.py +50 -0
- zjcode-0.0.1/deepagents_code/tui/widgets/history.py +194 -0
- zjcode-0.0.1/deepagents_code/tui/widgets/install_confirm.py +248 -0
- zjcode-0.0.1/deepagents_code/tui/widgets/launch_init.py +482 -0
- zjcode-0.0.1/deepagents_code/tui/widgets/loading.py +227 -0
- zjcode-0.0.1/deepagents_code/tui/widgets/mcp_login.py +539 -0
- zjcode-0.0.1/deepagents_code/tui/widgets/mcp_reconnect.py +212 -0
- zjcode-0.0.1/deepagents_code/tui/widgets/mcp_viewer.py +1634 -0
- zjcode-0.0.1/deepagents_code/tui/widgets/message_store.py +999 -0
- zjcode-0.0.1/deepagents_code/tui/widgets/messages.py +3846 -0
- zjcode-0.0.1/deepagents_code/tui/widgets/model_selector.py +2343 -0
- zjcode-0.0.1/deepagents_code/tui/widgets/notification_center.py +456 -0
- zjcode-0.0.1/deepagents_code/tui/widgets/notification_detail.py +257 -0
- zjcode-0.0.1/deepagents_code/tui/widgets/notification_settings.py +170 -0
- zjcode-0.0.1/deepagents_code/tui/widgets/restart_prompt.py +158 -0
- zjcode-0.0.1/deepagents_code/tui/widgets/skill_trust.py +131 -0
- zjcode-0.0.1/deepagents_code/tui/widgets/startup_tip.py +91 -0
- zjcode-0.0.1/deepagents_code/tui/widgets/status.py +781 -0
- zjcode-0.0.1/deepagents_code/tui/widgets/subagent_panel.py +969 -0
- zjcode-0.0.1/deepagents_code/tui/widgets/theme_selector.py +401 -0
- zjcode-0.0.1/deepagents_code/tui/widgets/thread_selector.py +2564 -0
- zjcode-0.0.1/deepagents_code/tui/widgets/tool_renderers.py +190 -0
- zjcode-0.0.1/deepagents_code/tui/widgets/tool_widgets.py +304 -0
- zjcode-0.0.1/deepagents_code/tui/widgets/update_available.py +311 -0
- zjcode-0.0.1/deepagents_code/tui/widgets/update_confirm.py +184 -0
- zjcode-0.0.1/deepagents_code/tui/widgets/update_progress.py +327 -0
- zjcode-0.0.1/deepagents_code/tui/widgets/welcome.py +508 -0
- zjcode-0.0.1/deepagents_code/turn_end_summary.py +522 -0
- zjcode-0.0.1/deepagents_code/ui.py +858 -0
- zjcode-0.0.1/deepagents_code/unicode_security.py +563 -0
- zjcode-0.0.1/deepagents_code/update_check.py +3124 -0
- zjcode-0.0.1/doc/2025-01-24-/347/211/210/346/234/254/345/215/207/347/272/247/344/270/216Web/351/203/250/347/275/262.md +318 -0
- zjcode-0.0.1/doc/2025-07-27-/345/244/215/345/210/266/346/214/211/351/222/256-CopyTurnButton/345/256/236/347/216/260.md +33 -0
- zjcode-0.0.1/doc/2025-07-27-/351/241/271/347/233/256/345/210/206/346/236/220-deepagents-code/346/236/266/346/236/204/344/270/216/346/250/241/345/235/227/346/246/202/350/247/210.md +174 -0
- zjcode-0.0.1/doc/2026-01-24-/351/243/236/344/271/246/346/216/245/345/205/245deepagents/350/260/203/347/240/224.md +78 -0
- zjcode-0.0.1/doc/2026-07-08-windows-dev-deployment-script.md +64 -0
- zjcode-0.0.1/doc/2026-07-11-/345/233/276/347/211/207/347/262/230/350/264/264BadRequestError-Agent/345/244/261/346/225/210/344/277/256/345/244/215.md +125 -0
- zjcode-0.0.1/doc/2026-07-12-/346/257/217/350/275/256/346/211/223/345/215/260/346/250/241/345/236/213/345/223/215/345/272/224/345/205/203/346/225/260/346/215/256.md +214 -0
- zjcode-0.0.1/doc/2026-07-12-/347/201/253/345/261/261/345/274/225/346/223/216/345/220/204/346/250/241/345/236/213/347/274/226/347/240/201/350/203/275/345/212/233/350/257/246/347/273/206/350/257/204/346/265/213/346/212/245/345/221/212.md +391 -0
- zjcode-0.0.1/doc/2026-07-12-/347/201/253/345/261/261/345/274/225/346/223/216/346/250/241/345/236/213/347/274/226/347/240/201/350/203/275/345/212/233/345/237/272/345/207/206/346/265/213/350/257/225.md +189 -0
- zjcode-0.0.1/doc/2026-07-15-learn/345/210/206/346/224/257/344/277/256/345/244/215-/346/265/213/350/257/225/344/270/216lint/345/205/250/347/273/277.md +95 -0
- zjcode-0.0.1/doc/2026-07-18-session-end-summary/345/206/205/347/275/256.md +74 -0
- zjcode-0.0.1/doc/2026-07-18-/345/267/245/345/205/267/347/273/204/351/273/230/350/256/244/345/261/225/345/274/200.md +1027 -0
- zjcode-0.0.1/doc/2026-07-19-/345/210/207/346/215/242/345/210/260/345/205/254/345/274/200PyPI.md +139 -0
- zjcode-0.0.1/examples/skills/arxiv-search/SKILL.md +33 -0
- zjcode-0.0.1/examples/skills/arxiv-search/arxiv_search.py +61 -0
- zjcode-0.0.1/examples/skills/langgraph-docs/SKILL.md +28 -0
- zjcode-0.0.1/examples/skills/skill-creator/SKILL.md +385 -0
- zjcode-0.0.1/examples/skills/skill-creator/scripts/init_skill.py +311 -0
- zjcode-0.0.1/examples/skills/skill-creator/scripts/quick_validate.py +152 -0
- zjcode-0.0.1/examples/skills/web-research/SKILL.md +77 -0
- zjcode-0.0.1/hatch_build.py +67 -0
- zjcode-0.0.1/images/tui.png +0 -0
- zjcode-0.0.1/pyproject.toml +325 -0
- zjcode-0.0.1/run-dcode-dev.ps1 +107 -0
- zjcode-0.0.1/run-dcode-dev.sh +34 -0
- zjcode-0.0.1/run-publish.sh +18 -0
- zjcode-0.0.1/run-setup-dev-env.sh +101 -0
- zjcode-0.0.1/scripts/benchmark_huoshan_models.py +822 -0
- zjcode-0.0.1/scripts/benchmark_report_20260712_151546.md +234 -0
- zjcode-0.0.1/scripts/benchmark_results_20260712_151546.json +2862 -0
- zjcode-0.0.1/scripts/check_imports.py +44 -0
- zjcode-0.0.1/scripts/debug_server.sh +66 -0
- zjcode-0.0.1/scripts/generate_commands_catalog.py +135 -0
- zjcode-0.0.1/scripts/install.sh +1980 -0
- zjcode-0.0.1/setup-dev-env.ps1 +141 -0
- zjcode-0.0.1/tests/README.md +11 -0
- zjcode-0.0.1/tests/integration_tests/__init__.py +0 -0
- zjcode-0.0.1/tests/integration_tests/benchmarks/__init__.py +0 -0
- zjcode-0.0.1/tests/integration_tests/benchmarks/test_codspeed_import_benchmarks.py +185 -0
- zjcode-0.0.1/tests/integration_tests/benchmarks/test_startup_benchmarks.py +337 -0
- zjcode-0.0.1/tests/integration_tests/conftest.py +39 -0
- zjcode-0.0.1/tests/integration_tests/test_acp_mode.py +117 -0
- zjcode-0.0.1/tests/integration_tests/test_auto_approve_remote.py +201 -0
- zjcode-0.0.1/tests/integration_tests/test_compact_resume.py +204 -0
- zjcode-0.0.1/tests/integration_tests/test_sandbox_factory.py +348 -0
- zjcode-0.0.1/tests/integration_tests/test_sandbox_operations.py +1179 -0
- zjcode-0.0.1/tests/unit_tests/__init__.py +0 -0
- zjcode-0.0.1/tests/unit_tests/client/__init__.py +1 -0
- zjcode-0.0.1/tests/unit_tests/client/commands/__init__.py +1 -0
- zjcode-0.0.1/tests/unit_tests/client/commands/test_auth.py +1003 -0
- zjcode-0.0.1/tests/unit_tests/client/commands/test_mcp.py +344 -0
- zjcode-0.0.1/tests/unit_tests/client/commands/test_tools.py +564 -0
- zjcode-0.0.1/tests/unit_tests/conftest.py +334 -0
- zjcode-0.0.1/tests/unit_tests/data/coding_agent_v1_validator.json +241 -0
- zjcode-0.0.1/tests/unit_tests/skills/__init__.py +1 -0
- zjcode-0.0.1/tests/unit_tests/skills/test_commands.py +1625 -0
- zjcode-0.0.1/tests/unit_tests/skills/test_load.py +856 -0
- zjcode-0.0.1/tests/unit_tests/skills/test_skill_trust.py +528 -0
- zjcode-0.0.1/tests/unit_tests/skills/test_skills_json.py +154 -0
- zjcode-0.0.1/tests/unit_tests/smoke_tests/__init__.py +0 -0
- zjcode-0.0.1/tests/unit_tests/smoke_tests/conftest.py +28 -0
- zjcode-0.0.1/tests/unit_tests/smoke_tests/snapshots/system_prompt_interactive_local.md +538 -0
- zjcode-0.0.1/tests/unit_tests/smoke_tests/test_system_prompt.py +199 -0
- zjcode-0.0.1/tests/unit_tests/test__tool_stream.py +503 -0
- zjcode-0.0.1/tests/unit_tests/test_agent.py +4149 -0
- zjcode-0.0.1/tests/unit_tests/test_agent_friendly.py +613 -0
- zjcode-0.0.1/tests/unit_tests/test_app.py +25908 -0
- zjcode-0.0.1/tests/unit_tests/test_approval_mode.py +129 -0
- zjcode-0.0.1/tests/unit_tests/test_args.py +869 -0
- zjcode-0.0.1/tests/unit_tests/test_ask_user_middleware.py +221 -0
- zjcode-0.0.1/tests/unit_tests/test_auth_display.py +238 -0
- zjcode-0.0.1/tests/unit_tests/test_auth_store.py +434 -0
- zjcode-0.0.1/tests/unit_tests/test_auth_web_search_restart.py +609 -0
- zjcode-0.0.1/tests/unit_tests/test_charset.py +377 -0
- zjcode-0.0.1/tests/unit_tests/test_clipboard.py +474 -0
- zjcode-0.0.1/tests/unit_tests/test_coding_agent_metadata.py +255 -0
- zjcode-0.0.1/tests/unit_tests/test_command_registry.py +389 -0
- zjcode-0.0.1/tests/unit_tests/test_compact_tool.py +40 -0
- zjcode-0.0.1/tests/unit_tests/test_config.py +6268 -0
- zjcode-0.0.1/tests/unit_tests/test_config_manifest.py +1933 -0
- zjcode-0.0.1/tests/unit_tests/test_configurable_model.py +1304 -0
- zjcode-0.0.1/tests/unit_tests/test_cursor_blink.py +59 -0
- zjcode-0.0.1/tests/unit_tests/test_cursor_style.py +56 -0
- zjcode-0.0.1/tests/unit_tests/test_debug.py +347 -0
- zjcode-0.0.1/tests/unit_tests/test_debug_buffer.py +269 -0
- zjcode-0.0.1/tests/unit_tests/test_debug_console.py +862 -0
- zjcode-0.0.1/tests/unit_tests/test_doctor.py +578 -0
- zjcode-0.0.1/tests/unit_tests/test_editor.py +274 -0
- zjcode-0.0.1/tests/unit_tests/test_end_to_end.py +435 -0
- zjcode-0.0.1/tests/unit_tests/test_env_vars.py +135 -0
- zjcode-0.0.1/tests/unit_tests/test_error_handling.py +34 -0
- zjcode-0.0.1/tests/unit_tests/test_event_bus.py +445 -0
- zjcode-0.0.1/tests/unit_tests/test_exception_handling.py +252 -0
- zjcode-0.0.1/tests/unit_tests/test_extras_info.py +609 -0
- zjcode-0.0.1/tests/unit_tests/test_file_ops.py +277 -0
- zjcode-0.0.1/tests/unit_tests/test_formatting.py +226 -0
- zjcode-0.0.1/tests/unit_tests/test_git.py +589 -0
- zjcode-0.0.1/tests/unit_tests/test_goal_rubric.py +697 -0
- zjcode-0.0.1/tests/unit_tests/test_goal_tools.py +473 -0
- zjcode-0.0.1/tests/unit_tests/test_hatch_build.py +159 -0
- zjcode-0.0.1/tests/unit_tests/test_hooks.py +600 -0
- zjcode-0.0.1/tests/unit_tests/test_imports.py +29 -0
- zjcode-0.0.1/tests/unit_tests/test_input_parsing.py +482 -0
- zjcode-0.0.1/tests/unit_tests/test_install_command.py +1135 -0
- zjcode-0.0.1/tests/unit_tests/test_install_script.py +2832 -0
- zjcode-0.0.1/tests/unit_tests/test_iterm_cursor_guide.py +256 -0
- zjcode-0.0.1/tests/unit_tests/test_local_context.py +1948 -0
- zjcode-0.0.1/tests/unit_tests/test_main.py +2971 -0
- zjcode-0.0.1/tests/unit_tests/test_main_acp_mode.py +199 -0
- zjcode-0.0.1/tests/unit_tests/test_main_args.py +2850 -0
- zjcode-0.0.1/tests/unit_tests/test_managed_tools.py +1009 -0
- zjcode-0.0.1/tests/unit_tests/test_mcp_auth.py +3011 -0
- zjcode-0.0.1/tests/unit_tests/test_mcp_config.py +214 -0
- zjcode-0.0.1/tests/unit_tests/test_mcp_disabled.py +182 -0
- zjcode-0.0.1/tests/unit_tests/test_mcp_login_service.py +291 -0
- zjcode-0.0.1/tests/unit_tests/test_mcp_oauth_ui.py +422 -0
- zjcode-0.0.1/tests/unit_tests/test_mcp_tools.py +4434 -0
- zjcode-0.0.1/tests/unit_tests/test_mcp_trust.py +158 -0
- zjcode-0.0.1/tests/unit_tests/test_media_utils.py +1150 -0
- zjcode-0.0.1/tests/unit_tests/test_memory_guard.py +523 -0
- zjcode-0.0.1/tests/unit_tests/test_model_config.py +6334 -0
- zjcode-0.0.1/tests/unit_tests/test_model_switch.py +1381 -0
- zjcode-0.0.1/tests/unit_tests/test_non_interactive.py +3286 -0
- zjcode-0.0.1/tests/unit_tests/test_notifications.py +206 -0
- zjcode-0.0.1/tests/unit_tests/test_offload.py +1513 -0
- zjcode-0.0.1/tests/unit_tests/test_offload_dict_messages.py +335 -0
- zjcode-0.0.1/tests/unit_tests/test_onboarding.py +292 -0
- zjcode-0.0.1/tests/unit_tests/test_openai_codex_integration.py +692 -0
- zjcode-0.0.1/tests/unit_tests/test_output.py +62 -0
- zjcode-0.0.1/tests/unit_tests/test_paths.py +44 -0
- zjcode-0.0.1/tests/unit_tests/test_reasoning_effort.py +715 -0
- zjcode-0.0.1/tests/unit_tests/test_reliable_rubric.py +167 -0
- zjcode-0.0.1/tests/unit_tests/test_reload.py +1035 -0
- zjcode-0.0.1/tests/unit_tests/test_remote_client.py +1076 -0
- zjcode-0.0.1/tests/unit_tests/test_resume_state.py +300 -0
- zjcode-0.0.1/tests/unit_tests/test_rubric_cli.py +352 -0
- zjcode-0.0.1/tests/unit_tests/test_sandbox_config.py +140 -0
- zjcode-0.0.1/tests/unit_tests/test_sandbox_factory.py +1423 -0
- zjcode-0.0.1/tests/unit_tests/test_sandbox_provider.py +50 -0
- zjcode-0.0.1/tests/unit_tests/test_sandbox_registry.py +313 -0
- zjcode-0.0.1/tests/unit_tests/test_server.py +1674 -0
- zjcode-0.0.1/tests/unit_tests/test_server_config.py +437 -0
- zjcode-0.0.1/tests/unit_tests/test_server_graph.py +424 -0
- zjcode-0.0.1/tests/unit_tests/test_server_helpers.py +190 -0
- zjcode-0.0.1/tests/unit_tests/test_server_manager.py +628 -0
- zjcode-0.0.1/tests/unit_tests/test_session_end_summary.py +132 -0
- zjcode-0.0.1/tests/unit_tests/test_session_stats.py +282 -0
- zjcode-0.0.1/tests/unit_tests/test_sessions.py +3051 -0
- zjcode-0.0.1/tests/unit_tests/test_shell_allow_list.py +719 -0
- zjcode-0.0.1/tests/unit_tests/test_skill_invocation.py +1003 -0
- zjcode-0.0.1/tests/unit_tests/test_startup_fast_paths.py +256 -0
- zjcode-0.0.1/tests/unit_tests/test_state_migration.py +204 -0
- zjcode-0.0.1/tests/unit_tests/test_subagents.py +731 -0
- zjcode-0.0.1/tests/unit_tests/test_terminal_capabilities.py +203 -0
- zjcode-0.0.1/tests/unit_tests/test_terminal_escape.py +386 -0
- zjcode-0.0.1/tests/unit_tests/test_terminal_progress_preference.py +68 -0
- zjcode-0.0.1/tests/unit_tests/test_textual_patches.py +261 -0
- zjcode-0.0.1/tests/unit_tests/test_theme.py +3105 -0
- zjcode-0.0.1/tests/unit_tests/test_threads_resume.py +350 -0
- zjcode-0.0.1/tests/unit_tests/test_tool_catalog.py +558 -0
- zjcode-0.0.1/tests/unit_tests/test_tool_display.py +573 -0
- zjcode-0.0.1/tests/unit_tests/test_tracing_replicas.py +70 -0
- zjcode-0.0.1/tests/unit_tests/test_transcript_virtualization.py +240 -0
- zjcode-0.0.1/tests/unit_tests/test_turn_end_summary.py +252 -0
- zjcode-0.0.1/tests/unit_tests/test_ui.py +421 -0
- zjcode-0.0.1/tests/unit_tests/test_unicode_security.py +315 -0
- zjcode-0.0.1/tests/unit_tests/test_update_check.py +4867 -0
- zjcode-0.0.1/tests/unit_tests/test_version.py +1443 -0
- zjcode-0.0.1/tests/unit_tests/tools/__init__.py +0 -0
- zjcode-0.0.1/tests/unit_tests/tools/test_current_thread.py +27 -0
- zjcode-0.0.1/tests/unit_tests/tools/test_fetch_url.py +605 -0
- zjcode-0.0.1/tests/unit_tests/tui/__init__.py +0 -0
- zjcode-0.0.1/tests/unit_tests/tui/test_subagent_stream.py +41 -0
- zjcode-0.0.1/tests/unit_tests/tui/test_textual_adapter.py +6975 -0
- zjcode-0.0.1/tests/unit_tests/tui/widgets/__init__.py +0 -0
- zjcode-0.0.1/tests/unit_tests/tui/widgets/test_agent_selector.py +466 -0
- zjcode-0.0.1/tests/unit_tests/tui/widgets/test_approval.py +641 -0
- zjcode-0.0.1/tests/unit_tests/tui/widgets/test_ask_user.py +1055 -0
- zjcode-0.0.1/tests/unit_tests/tui/widgets/test_auth_widgets.py +3045 -0
- zjcode-0.0.1/tests/unit_tests/tui/widgets/test_autocomplete.py +1354 -0
- zjcode-0.0.1/tests/unit_tests/tui/widgets/test_chat_input.py +5146 -0
- zjcode-0.0.1/tests/unit_tests/tui/widgets/test_cwd_switch.py +231 -0
- zjcode-0.0.1/tests/unit_tests/tui/widgets/test_diff.py +140 -0
- zjcode-0.0.1/tests/unit_tests/tui/widgets/test_goal_review.py +341 -0
- zjcode-0.0.1/tests/unit_tests/tui/widgets/test_history.py +334 -0
- zjcode-0.0.1/tests/unit_tests/tui/widgets/test_install_confirm.py +167 -0
- zjcode-0.0.1/tests/unit_tests/tui/widgets/test_launch_init.py +560 -0
- zjcode-0.0.1/tests/unit_tests/tui/widgets/test_links.py +301 -0
- zjcode-0.0.1/tests/unit_tests/tui/widgets/test_loading.py +161 -0
- zjcode-0.0.1/tests/unit_tests/tui/widgets/test_mcp_login_modal.py +409 -0
- zjcode-0.0.1/tests/unit_tests/tui/widgets/test_mcp_reconnect.py +130 -0
- zjcode-0.0.1/tests/unit_tests/tui/widgets/test_mcp_viewer.py +2207 -0
- zjcode-0.0.1/tests/unit_tests/tui/widgets/test_message_store.py +1144 -0
- zjcode-0.0.1/tests/unit_tests/tui/widgets/test_messages.py +4480 -0
- zjcode-0.0.1/tests/unit_tests/tui/widgets/test_model_selector.py +3619 -0
- zjcode-0.0.1/tests/unit_tests/tui/widgets/test_notification_center.py +367 -0
- zjcode-0.0.1/tests/unit_tests/tui/widgets/test_notification_detail.py +133 -0
- zjcode-0.0.1/tests/unit_tests/tui/widgets/test_restart_prompt.py +127 -0
- zjcode-0.0.1/tests/unit_tests/tui/widgets/test_skill_trust_screen.py +78 -0
- zjcode-0.0.1/tests/unit_tests/tui/widgets/test_startup_tip.py +85 -0
- zjcode-0.0.1/tests/unit_tests/tui/widgets/test_status.py +1064 -0
- zjcode-0.0.1/tests/unit_tests/tui/widgets/test_subagent_panel.py +549 -0
- zjcode-0.0.1/tests/unit_tests/tui/widgets/test_thread_selector.py +5019 -0
- zjcode-0.0.1/tests/unit_tests/tui/widgets/test_tool_renderers.py +216 -0
- zjcode-0.0.1/tests/unit_tests/tui/widgets/test_update_available.py +185 -0
- zjcode-0.0.1/tests/unit_tests/tui/widgets/test_update_confirm.py +106 -0
- zjcode-0.0.1/tests/unit_tests/tui/widgets/test_update_progress.py +275 -0
- zjcode-0.0.1/tests/unit_tests/tui/widgets/test_welcome.py +851 -0
- zjcode-0.0.1/uv.lock +7207 -0
zjcode-0.0.1/.gitignore
ADDED
|
@@ -0,0 +1,258 @@
|
|
|
1
|
+
# Byte-compiled / optimized / DLL files
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[codz]
|
|
4
|
+
*$py.class
|
|
5
|
+
|
|
6
|
+
# C extensions
|
|
7
|
+
*.so
|
|
8
|
+
|
|
9
|
+
# Distribution / packaging
|
|
10
|
+
.Python
|
|
11
|
+
build/
|
|
12
|
+
develop-eggs/
|
|
13
|
+
dist/
|
|
14
|
+
downloads/
|
|
15
|
+
eggs/
|
|
16
|
+
.eggs/
|
|
17
|
+
lib/
|
|
18
|
+
!libs/cli/frontend/src/lib/
|
|
19
|
+
lib64/
|
|
20
|
+
parts/
|
|
21
|
+
sdist/
|
|
22
|
+
var/
|
|
23
|
+
wheels/
|
|
24
|
+
share/python-wheels/
|
|
25
|
+
*.egg-info/
|
|
26
|
+
.installed.cfg
|
|
27
|
+
*.egg
|
|
28
|
+
MANIFEST
|
|
29
|
+
|
|
30
|
+
# PyInstaller
|
|
31
|
+
# Usually these files are written by a python script from a template
|
|
32
|
+
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
|
33
|
+
*.manifest
|
|
34
|
+
*.spec
|
|
35
|
+
|
|
36
|
+
# Installer logs
|
|
37
|
+
pip-log.txt
|
|
38
|
+
pip-delete-this-directory.txt
|
|
39
|
+
|
|
40
|
+
# Unit test / coverage reports
|
|
41
|
+
htmlcov/
|
|
42
|
+
.tox/
|
|
43
|
+
.nox/
|
|
44
|
+
.coverage
|
|
45
|
+
.coverage.*
|
|
46
|
+
.cache
|
|
47
|
+
nosetests.xml
|
|
48
|
+
coverage.xml
|
|
49
|
+
*.cover
|
|
50
|
+
*.py.cover
|
|
51
|
+
.hypothesis/
|
|
52
|
+
.pytest_cache/
|
|
53
|
+
cover/
|
|
54
|
+
|
|
55
|
+
# Translations
|
|
56
|
+
*.mo
|
|
57
|
+
*.pot
|
|
58
|
+
|
|
59
|
+
# Django stuff:
|
|
60
|
+
*.log
|
|
61
|
+
local_settings.py
|
|
62
|
+
db.sqlite3
|
|
63
|
+
db.sqlite3-journal
|
|
64
|
+
|
|
65
|
+
# Flask stuff:
|
|
66
|
+
instance/
|
|
67
|
+
.webassets-cache
|
|
68
|
+
|
|
69
|
+
# Scrapy stuff:
|
|
70
|
+
.scrapy
|
|
71
|
+
|
|
72
|
+
# Sphinx documentation
|
|
73
|
+
docs/_build/
|
|
74
|
+
|
|
75
|
+
# PyBuilder
|
|
76
|
+
.pybuilder/
|
|
77
|
+
target/
|
|
78
|
+
|
|
79
|
+
# Jupyter Notebook
|
|
80
|
+
.ipynb_checkpoints
|
|
81
|
+
|
|
82
|
+
# IPython
|
|
83
|
+
profile_default/
|
|
84
|
+
ipython_config.py
|
|
85
|
+
|
|
86
|
+
# pyenv
|
|
87
|
+
# For a library or package, you might want to ignore these files since the code is
|
|
88
|
+
# intended to run in multiple environments; otherwise, check them in:
|
|
89
|
+
# .python-version
|
|
90
|
+
|
|
91
|
+
# pipenv
|
|
92
|
+
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
|
|
93
|
+
# However, in case of collaboration, if having platform-specific dependencies or dependencies
|
|
94
|
+
# having no cross-platform support, pipenv may install dependencies that don't work, or not
|
|
95
|
+
# install all needed dependencies.
|
|
96
|
+
#Pipfile.lock
|
|
97
|
+
|
|
98
|
+
# UV
|
|
99
|
+
# Similar to Pipfile.lock, it is generally recommended to include uv.lock in version control.
|
|
100
|
+
# This is especially recommended for binary packages to ensure reproducibility, and is more
|
|
101
|
+
# commonly ignored for libraries.
|
|
102
|
+
#uv.lock
|
|
103
|
+
.local_deps/
|
|
104
|
+
|
|
105
|
+
# poetry
|
|
106
|
+
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
|
|
107
|
+
# This is especially recommended for binary packages to ensure reproducibility, and is more
|
|
108
|
+
# commonly ignored for libraries.
|
|
109
|
+
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
|
|
110
|
+
#poetry.lock
|
|
111
|
+
#poetry.toml
|
|
112
|
+
|
|
113
|
+
# pdm
|
|
114
|
+
# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
|
|
115
|
+
# pdm recommends including project-wide configuration in pdm.toml, but excluding .pdm-python.
|
|
116
|
+
# https://pdm-project.org/en/latest/usage/project/#working-with-version-control
|
|
117
|
+
#pdm.lock
|
|
118
|
+
#pdm.toml
|
|
119
|
+
.pdm-python
|
|
120
|
+
.pdm-build/
|
|
121
|
+
|
|
122
|
+
# pixi
|
|
123
|
+
# Similar to Pipfile.lock, it is generally recommended to include pixi.lock in version control.
|
|
124
|
+
#pixi.lock
|
|
125
|
+
# Pixi creates a virtual environment in the .pixi directory, just like venv module creates one
|
|
126
|
+
# in the .venv directory. It is recommended not to include this directory in version control.
|
|
127
|
+
.pixi
|
|
128
|
+
|
|
129
|
+
# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
|
|
130
|
+
__pypackages__/
|
|
131
|
+
|
|
132
|
+
# Celery stuff
|
|
133
|
+
celerybeat-schedule
|
|
134
|
+
celerybeat.pid
|
|
135
|
+
|
|
136
|
+
# SageMath parsed files
|
|
137
|
+
*.sage.py
|
|
138
|
+
|
|
139
|
+
# Environments
|
|
140
|
+
.env
|
|
141
|
+
.env.*
|
|
142
|
+
.envrc
|
|
143
|
+
env.local
|
|
144
|
+
*.env.local
|
|
145
|
+
.venv
|
|
146
|
+
env/
|
|
147
|
+
venv/
|
|
148
|
+
ENV/
|
|
149
|
+
env.bak/
|
|
150
|
+
venv.bak/
|
|
151
|
+
|
|
152
|
+
# Local credentials and secrets
|
|
153
|
+
*.pem
|
|
154
|
+
*.key
|
|
155
|
+
*.crt
|
|
156
|
+
*.p12
|
|
157
|
+
*.pfx
|
|
158
|
+
*.jks
|
|
159
|
+
credentials.json
|
|
160
|
+
token.json
|
|
161
|
+
Cookies
|
|
162
|
+
Cookies.db
|
|
163
|
+
cookies.sqlite
|
|
164
|
+
cookies.txt
|
|
165
|
+
|
|
166
|
+
# Spyder project settings
|
|
167
|
+
.spyderproject
|
|
168
|
+
.spyproject
|
|
169
|
+
|
|
170
|
+
# Rope project settings
|
|
171
|
+
.ropeproject
|
|
172
|
+
|
|
173
|
+
# mkdocs documentation
|
|
174
|
+
/site
|
|
175
|
+
|
|
176
|
+
# mypy
|
|
177
|
+
.mypy_cache/
|
|
178
|
+
.dmypy.json
|
|
179
|
+
dmypy.json
|
|
180
|
+
|
|
181
|
+
# Pyre type checker
|
|
182
|
+
.pyre/
|
|
183
|
+
|
|
184
|
+
# pytype static type analyzer
|
|
185
|
+
.pytype/
|
|
186
|
+
|
|
187
|
+
# Cython debug symbols
|
|
188
|
+
cython_debug/
|
|
189
|
+
|
|
190
|
+
# PyCharm
|
|
191
|
+
# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
|
|
192
|
+
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
|
|
193
|
+
# and can be added to the global gitignore or merged into this file. For a more nuclear
|
|
194
|
+
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
|
|
195
|
+
#.idea/
|
|
196
|
+
|
|
197
|
+
# Abstra
|
|
198
|
+
# Abstra is an AI-powered process automation framework.
|
|
199
|
+
# Ignore directories containing user credentials, local state, and settings.
|
|
200
|
+
# Learn more at https://abstra.io/docs
|
|
201
|
+
.abstra/
|
|
202
|
+
|
|
203
|
+
# Visual Studio Code
|
|
204
|
+
# Visual Studio Code specific template is maintained in a separate VisualStudioCode.gitignore
|
|
205
|
+
# that can be found at https://github.com/github/gitignore/blob/main/Global/VisualStudioCode.gitignore
|
|
206
|
+
# and can be added to the global gitignore or merged into this file. However, if you prefer,
|
|
207
|
+
# you could uncomment the following to ignore the entire vscode folder
|
|
208
|
+
# .vscode/
|
|
209
|
+
|
|
210
|
+
# Ruff stuff:
|
|
211
|
+
.ruff_cache/
|
|
212
|
+
|
|
213
|
+
# PyPI configuration file
|
|
214
|
+
.pypirc
|
|
215
|
+
|
|
216
|
+
# Cursor
|
|
217
|
+
# Cursor is an AI-powered code editor. `.cursorignore` specifies files/directories to
|
|
218
|
+
# exclude from AI features like autocomplete and code analysis. Recommended for sensitive data
|
|
219
|
+
# refer to https://docs.cursor.com/context/ignore-files
|
|
220
|
+
.cursorignore
|
|
221
|
+
.cursorindexingignore
|
|
222
|
+
|
|
223
|
+
# Marimo
|
|
224
|
+
marimo/_static/
|
|
225
|
+
marimo/_lsp/
|
|
226
|
+
__marimo__/
|
|
227
|
+
|
|
228
|
+
# LangGraph
|
|
229
|
+
.langgraph_api
|
|
230
|
+
|
|
231
|
+
#claude
|
|
232
|
+
.claude
|
|
233
|
+
|
|
234
|
+
# Harbor local job output
|
|
235
|
+
jobs/
|
|
236
|
+
|
|
237
|
+
.idea
|
|
238
|
+
TEXTUAL_REFACTOR_PLAN.md
|
|
239
|
+
libs/cli/TEXTUAL_PROGRESS.md
|
|
240
|
+
|
|
241
|
+
/tmp/
|
|
242
|
+
|
|
243
|
+
# macOS
|
|
244
|
+
.DS_Store
|
|
245
|
+
*/tmp/.DS_Store
|
|
246
|
+
|
|
247
|
+
CLAUDE.md
|
|
248
|
+
.worktrees/
|
|
249
|
+
|
|
250
|
+
# Frontend build artifacts (source tree; package data under libs/cli/deepagents_cli/deploy/frontend_dist/ is tracked)
|
|
251
|
+
libs/cli/frontend/node_modules/
|
|
252
|
+
libs/cli/frontend/dist/
|
|
253
|
+
node_modules/
|
|
254
|
+
|
|
255
|
+
# Generated at build time by libs/code/hatch_build.py (stamps the release commit)
|
|
256
|
+
libs/code/deepagents_code/_build_info.py
|
|
257
|
+
|
|
258
|
+
.obsidian/
|
zjcode-0.0.1/AGENTS.md
ADDED
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
# `libs/code` agent guide
|
|
2
|
+
|
|
3
|
+
`deepagents-code` is the interactive coding agent — the Textual REPL, headless `-x` mode, MCP integration, skills, sandbox bootstrap, and slash-command surface. Forked from `deepagents-cli` at the 0.1.0 split.
|
|
4
|
+
|
|
5
|
+
For monorepo-wide conventions (commit titles, lint, testing, docs, CI, benchmarks), see the root `AGENTS.md`. For a high-level map of the package (client/server processes, request lifecycle, module map), see `ARCHITECTURE.md`.
|
|
6
|
+
|
|
7
|
+
## Textual (terminal UI framework)
|
|
8
|
+
|
|
9
|
+
`deepagents-code` uses [Textual](https://textual.textualize.io/).
|
|
10
|
+
|
|
11
|
+
**Key Textual resources:**
|
|
12
|
+
|
|
13
|
+
- **Guide:** <https://textual.textualize.io/guide/>
|
|
14
|
+
- **Widget gallery:** <https://textual.textualize.io/widget_gallery/>
|
|
15
|
+
- **CSS reference:** <https://textual.textualize.io/styles/>
|
|
16
|
+
- **API reference:** <https://textual.textualize.io/api/>
|
|
17
|
+
|
|
18
|
+
### Styled text in widgets
|
|
19
|
+
|
|
20
|
+
Prefer Textual's `Content` (`textual.content`) over Rich's `Text` for widget rendering. `Content` is immutable (like `str`) and integrates natively with Textual's rendering pipeline. Rich `Text` is still correct for code that renders via Rich's `Console.print()` (e.g., `non_interactive.py`, `main.py`).
|
|
21
|
+
|
|
22
|
+
IMPORTANT: `Content` requires **Textual's** `Style` (`textual.style.Style`) for rendering, not Rich's `Style` (`rich.style.Style`). Mixing Rich `Style` objects into `Content` spans will cause `TypeError` during widget rendering. String styles (`"bold cyan"`, `"dim"`) work for non-link styling. For links, use `TStyle(link=url)`.
|
|
23
|
+
|
|
24
|
+
**Never use f-string interpolation in Rich markup** (e.g., `f"[bold]{var}[/bold]"`). If `var` contains square brackets, the markup breaks or throws. Use `Content` methods instead:
|
|
25
|
+
|
|
26
|
+
- `Content.from_markup("[bold]$var[/bold]", var=value)` — for inline markup templates. `$var` substitution auto-escapes dynamic content. **Use when the variable is external/user-controlled** (tool args, file paths, user messages, diff content, error messages from exceptions).
|
|
27
|
+
- `Content.styled(text, "bold")` — single style applied to plain text. No markup parsing. Use for static strings or when the variable is internal/trusted (glyphs, ints, enum-like status values). Avoid `Content.styled(f"..{var}..", style)` when `var` is user-controlled — while `styled` doesn't parse markup, the f-string pattern is fragile and inconsistent with the `from_markup` convention.
|
|
28
|
+
- `Content.assemble("prefix: ", (text, "bold"), " ", other_content)` — for composing pre-built `Content` objects, `(text, style)` tuples, and plain strings. Plain strings are treated as plain text (no markup parsing). Use for structural composition, especially when parts use `TStyle(link=url)`.
|
|
29
|
+
- `content.join(parts)` — like `str.join()` for `Content` objects.
|
|
30
|
+
|
|
31
|
+
**Decision rule:** if the value could ever come from outside the codebase (user input, tool output, API responses, file contents), use `from_markup` with `$var`. If it's a hardcoded string, glyph, or computed int, `styled` is fine.
|
|
32
|
+
|
|
33
|
+
### `App.notify()` defaults to `markup=True`
|
|
34
|
+
|
|
35
|
+
Textual's `App.notify(message)` parses the message string as Rich markup by default. Any dynamic content (exception messages, file paths, user input, command strings) containing brackets `[]`, ANSI escape codes, or `=` will cause a `MarkupError` crash in Textual's Toast renderer. Always pass `markup=False` when the message contains f-string interpolated variables. Hardcoded string literals are safe with the default.
|
|
36
|
+
|
|
37
|
+
### Rich `console.print()` and number highlighting
|
|
38
|
+
|
|
39
|
+
`console.print()` defaults to `highlight=True`, which runs `ReprHighlighter` and auto-applies bold + cyan to any detected numbers. This visually overrides subtle styles like `dim` (bold cancels dim in most terminals). Pass `highlight=False` on any `console.print()` call where the content contains numbers and consistent dim/subtle styling matters.
|
|
40
|
+
|
|
41
|
+
### Glyphs and spinners — reuse, don't redefine
|
|
42
|
+
|
|
43
|
+
Charset-dependent characters and animations have **single sources of truth**. Reuse them instead of hand-rolling new ones — copies drift, and (more subtly) a hardcoded Unicode literal won't degrade to ASCII on terminals that need it.
|
|
44
|
+
|
|
45
|
+
- **Glyphs** (checkmarks, arrows, ellipsis, cursor, box-drawing, branch icon, etc.): pull from `get_glyphs()` (`config.Glyphs`). Each glyph has a Unicode and an ASCII variant; `get_glyphs()` returns the right set for the active terminal. Never inline `"✓"`, `"…"`, `"›"`, and friends.
|
|
46
|
+
- **Animated spinners**: reuse the `Spinner` class in `tui/widgets/loading.py`, which wraps `get_glyphs().spinner_frames` (braille on Unicode, `(-) (\) (|) (/)` on ASCII) and exposes `next_frame()`/`current_frame()`. Do **not** define your own frame tuples or interval constants for a spinner — drive a `Spinner` on a `set_interval`. The status-bar reconnect indicator (`tui/widgets/status.py`) is the reference example; it ticks at the same 0.1s cadence as `LoadingWidget`. All connection/queue progress lives in the status bar — the welcome banner deliberately stays out of it, so there are currently no bespoke spinners to carve an exception for.
|
|
47
|
+
|
|
48
|
+
### Textual patterns used in this codebase
|
|
49
|
+
|
|
50
|
+
- **Workers** (`@work` decorator) for async operations - see [Workers guide](https://textual.textualize.io/guide/workers/)
|
|
51
|
+
- **Message passing** for widget communication - see [Events guide](https://textual.textualize.io/guide/events/)
|
|
52
|
+
- **Reactive attributes** for state management - see [Reactivity guide](https://textual.textualize.io/guide/reactivity/)
|
|
53
|
+
|
|
54
|
+
### Testing Textual apps
|
|
55
|
+
|
|
56
|
+
- Use `textual.pilot` for async UI testing - see [Testing guide](https://textual.textualize.io/guide/testing/)
|
|
57
|
+
- Snapshot testing available for visual regression - see repo `notes/snapshot_testing.md`
|
|
58
|
+
- For modal flows, test the real interaction path with keypresses when possible. Unit tests that call action methods or resume handlers directly can miss focus and modal-stack bugs.
|
|
59
|
+
- Do not open another modal or refocus the base chat input directly inside a modal dismiss callback. Preserve the non-blocking `push_screen(..., callback)` flow and schedule follow-up UI work with `call_after_refresh` so the dismissing modal fully unwinds first.
|
|
60
|
+
- Be cautious replacing `push_screen(..., callback)` with an awaited modal result inside slash-command handlers; awaiting can block the Textual message pump and break keyboard navigation in the active modal.
|
|
61
|
+
|
|
62
|
+
### Typing and test doubles
|
|
63
|
+
|
|
64
|
+
When fixing `ty` diagnostics, do not mechanically replace `# type: ignore[...]` with `cast(...)`. First try to improve the actual type shape: narrower annotations, typed futures/callbacks, covariant read-only types such as `Mapping`/`Sequence`, local mock variables, or `monkeypatch.setattr(...)`. Treat `cast("Any", ...)` as a last resort.
|
|
65
|
+
|
|
66
|
+
For Textual tests that intentionally replace concrete app methods with `MagicMock` or `AsyncMock`, prefer `monkeypatch.setattr(...)` or one small documented dynamic helper over repeated `cast("Any", app)` expressions. Assert on local mock variables instead of re-reading mocked methods from the concrete object when possible.
|
|
67
|
+
|
|
68
|
+
Casts are acceptable when the type violation is the point of the test (for example, passing a wrong runtime type to exercise defensive validation) or when a third-party overload is narrower than verified runtime behavior. In those cases, keep the cast narrowly scoped and add a short comment explaining why it is intentional.
|
|
69
|
+
|
|
70
|
+
## SDK dependency pin
|
|
71
|
+
|
|
72
|
+
`deepagents-code` pins an exact `deepagents==X.Y.Z` version in `pyproject.toml`. When developing features that depend on new SDK functionality, bump this pin as part of the same PR. A CI check verifies the pin is not older than the current SDK version at release time (unless bypassed with `dangerous-skip-sdk-pin-check`); pins ahead of the workspace SDK are allowed for intentional prerelease coordination.
|
|
73
|
+
|
|
74
|
+
For a persistent editable `dcode-dev` install that stays separate from a released install, see [Local dev installs](./DEVELOPMENT.md#local-dev-installs) in the development guide.
|
|
75
|
+
|
|
76
|
+
## Startup performance
|
|
77
|
+
|
|
78
|
+
`deepagents-code` must stay fast to launch. Never import heavy packages (e.g., `deepagents`, LangChain, LangGraph) at module level or in the argument-parsing path. These imports pull in large dependency trees and add seconds to every invocation, including trivial commands like `deepagents-code -v`.
|
|
79
|
+
|
|
80
|
+
- Keep top-level imports in `main.py` and other entry-point modules minimal.
|
|
81
|
+
- Defer heavy imports to the point where they are actually needed (inside functions/methods).
|
|
82
|
+
- To read another package's version without importing it, use `importlib.metadata.version("package-name")`.
|
|
83
|
+
- Feature-gate checks on the startup hot path (before background workers fire) must be lightweight — env var lookups, small file reads. Never pull in expensive modules just to decide whether to skip a feature.
|
|
84
|
+
- When adding logic that already exists elsewhere (e.g., editable-install detection), import the existing cached implementation rather than duplicating it.
|
|
85
|
+
- Features that run shell commands must never do so *silently* by default. Either gate them behind an explicit env var or config key (opt-in), or — if default-enabled — announce the action before running it and offer a documented opt-out. Auto-update is the sole default-enabled exception: it shows a one-time migration notice and skips the first install when enabled only by the opt-out default, prints the upgrade it is about to perform, is overridable via `DEEPAGENTS_CODE_AUTO_UPDATE` / `[update].auto_update`, and is always disabled for editable installs.
|
|
86
|
+
- Background workers that spawn subprocesses must set a timeout to avoid blocking indefinitely.
|
|
87
|
+
|
|
88
|
+
## Logging
|
|
89
|
+
|
|
90
|
+
Debug logging is configured **once**, on the `deepagents_code` package logger, by the `configure_debug_logging` call in `deepagents_code/__init__.py`. Child module loggers (`logging.getLogger(__name__)`) reach the shared debug file via propagation.
|
|
91
|
+
|
|
92
|
+
- Do **not** add per-module `configure_debug_logging(logger)` calls. They are redundant now that the package logger is configured at import, and they reintroduce the duplicate-handler problem the single-config approach solves.
|
|
93
|
+
- Every module should create its logger with `logging.getLogger(__name__)` so it stays inside the `deepagents_code.*` hierarchy and inherits the package handler. Don't set `logger.propagate = False` or attach your own handlers.
|
|
94
|
+
- The **file** handler only attaches when `DEEPAGENTS_CODE_DEBUG` is truthy; that path is a single env-var read, so it's safe on the startup hot path. See `DEVELOPMENT.md` for the `DEEPAGENTS_CODE_DEBUG` / `DEEPAGENTS_CODE_DEBUG_FILE` / `DEEPAGENTS_CODE_LOG_LEVEL` env vars.
|
|
95
|
+
- Separately, an **always-on in-memory ring buffer** (`_debug_buffer.install_log_buffer`, called from `__init__.py` right before `configure_debug_logging`) attaches unconditionally at import so the in-app Debug Console (`Ctrl+\`) can tail recent `deepagents_code.*` records without file logging. It captures `INFO` and above by default (or `DEEPAGENTS_CODE_LOG_LEVEL`), and may lower the package logger to `INFO` for the process lifetime. It never spills to the terminal (a handler is always found, so `lastResort` is skipped) and is bounded (a `deque` of 1000 records), so it's cheap enough to keep on. Because it installs *before* `configure_debug_logging`, warnings that helper emits at startup are captured and visible in the console.
|
|
96
|
+
|
|
97
|
+
## CLI help screen
|
|
98
|
+
|
|
99
|
+
The `deepagents-code --help` screen is hand-maintained in `ui.show_help()`, separate from the argparse definitions in `main.parse_args()`. When adding a new CLI flag, update **both** files. A drift-detection test (`test_args.TestHelpScreenDrift`) fails if a flag is registered in argparse but missing from the help screen.
|
|
100
|
+
|
|
101
|
+
## Splash screen tips
|
|
102
|
+
|
|
103
|
+
When adding a user-facing CLI feature (new slash command, keybinding, workflow), add a corresponding entry to the `_TIPS` dict in `deepagents_code/tui/widgets/startup_tip.py`, mapping the tip text to a relative selection weight (higher = shown more often). One tip is chosen at random above the input on startup to help users discover features. Keep tips short and action-oriented (e.g., `"Press ctrl+x to compose prompts in your external editor"`).
|
|
104
|
+
|
|
105
|
+
## Slash commands
|
|
106
|
+
|
|
107
|
+
Slash commands are defined as `SlashCommand` entries in the `COMMANDS` tuple in `deepagents_code/command_registry.py`. Each entry declares the command name, description, `bypass_tier` (queue-bypass classification), optional `hidden_keywords` for fuzzy matching, and optional `aliases`. Bypass-tier frozensets and the `SLASH_COMMANDS` autocomplete list are derived automatically — no other file should hard-code command metadata.
|
|
108
|
+
|
|
109
|
+
To add a new slash command: (1) add a `SlashCommand` entry to `COMMANDS`, (2) set the appropriate `bypass_tier`, (3) add a handler branch in `_handle_command` in `app.py`, (4) run `make commands-catalog` if you changed command names, aliases, descriptions, visibility, or hidden-command metadata, then (5) run `make lint && make test` — the drift test will catch any mismatch.
|
|
110
|
+
|
|
111
|
+
## Adding a new model provider
|
|
112
|
+
|
|
113
|
+
`deepagents-code` supports LangChain-based chat model providers as optional dependencies. To add a new provider, update these files (all entries alphabetically sorted):
|
|
114
|
+
|
|
115
|
+
1. `deepagents_code/model_config.py` — add `"provider_name": "ENV_VAR_NAME"` to `PROVIDER_API_KEY_ENV`
|
|
116
|
+
2. `deepagents_code/model_config.py` — if the provider reads a *dedicated* endpoint env var, add `"provider_name": ("CANONICAL_BASE_URL", "ALTERNATE", ...)` to `PROVIDER_BASE_URL_ENV` (see guidelines below); omit the provider entirely when it has no provider-specific endpoint variable
|
|
117
|
+
3. `pyproject.toml` — add `provider = ["langchain-provider>=X.Y.Z,<N.0.0"]` to `[project.optional-dependencies]` and include it in the `all-providers` composite extra
|
|
118
|
+
4. `deepagents_code/model_config.py` — add `"provider_name"` to `RETRY_PARAM_BY_PROVIDER` if the provider's chat model accepts `max_retries`
|
|
119
|
+
5. `deepagents_code/tui/widgets/auth.py` — add `"provider_name": "Display Name"` to `PROVIDER_DISPLAY_NAMES` so the `/auth` UI shows a branded label instead of the title-cased key, and (if the provider issues API keys from a self-serve page) `"provider_name": "https://…"` to `PROVIDER_API_KEY_URLS` so the prompt links straight to the key page
|
|
120
|
+
6. `tests/unit_tests/test_model_config.py` — add `assert PROVIDER_API_KEY_ENV["provider_name"] == "ENV_VAR_NAME"` to `TestProviderApiKeyEnv.test_contains_major_providers`, and pin any `PROVIDER_BASE_URL_ENV` entry with a matching assertion
|
|
121
|
+
|
|
122
|
+
### `PROVIDER_BASE_URL_ENV` guidelines
|
|
123
|
+
|
|
124
|
+
`PROVIDER_BASE_URL_ENV` pairs a provider with the endpoint env var(s) its LangChain integration and SDK read, so a stored `/auth` endpoint resolves and an inherited gateway URL cannot leak. Before adding an entry:
|
|
125
|
+
|
|
126
|
+
- **Verify against source — never infer from naming.** Read both the `langchain-<provider>` chat model (look for `from_env` / `get_from_dict_or_env` / `secret_from_env`, or a `Field` default on the `base_url`/`endpoint` alias) and the underlying vendor SDK, and record the exact env var name each reads. The integration and the SDK often read different names (e.g. `GROQ_API_BASE` vs `GROQ_BASE_URL`).
|
|
127
|
+
- **Canonical name first.** Element `[0]` is written by `apply_stored_credentials` and read by `get_base_url`; every other name the integration or SDK may read goes in the tuple so it is cleared too. By convention the SDK's `*_BASE_URL`-style name is canonical and the integration's `*_API_BASE`/`*_API_URL` name is the alternate.
|
|
128
|
+
- **Never list another provider's shared var.** OpenAI-compatible providers (e.g. `deepseek`, `openrouter`, `together`, `xai`, `baseten`) sit on the `openai` SDK, whose only endpoint var is the shared `OPENAI_BASE_URL`. Listing it under those providers would clobber the user's real OpenAI endpoint when their credential is written or cleared — list only the provider's own var (e.g. `DEEPSEEK_API_BASE`), or nothing.
|
|
129
|
+
- **Omit providers with no dedicated var.** When the endpoint is a hardcoded default plus a constructor arg (`baseten`), an `api_base` arg resolved per-provider inside the library (`litellm`), or derived from the region (`google_vertexai`), leave the provider out. A `/auth` endpoint still resolves through `get_base_url`'s stored-credential step and reaches the model as the `base_url` kwarg.
|
|
130
|
+
|
|
131
|
+
**Not required** unless the provider's models have a distinctive name prefix (like `gpt-*`, `claude*`, `gemini*`):
|
|
132
|
+
|
|
133
|
+
- `detect_provider()` in `config.py` — only needed for auto-detection from bare model names
|
|
134
|
+
- `Settings.has_*` property in `config.py` — only needed if referenced by `detect_provider()` fallback logic
|
|
135
|
+
|
|
136
|
+
Model discovery, credential checking, and UI integration are automatic once `PROVIDER_API_KEY_ENV` is populated and the `langchain-*` package is installed.
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
# Deep Agents Code Architecture
|
|
2
|
+
|
|
3
|
+
## What this package is
|
|
4
|
+
|
|
5
|
+
`deepagents-code` is a prebuilt terminal coding agent built on top of the `deepagents` SDK. It is a reference implementation: one design for packaging the SDK into a useful coding-agent product, based on patterns that have worked well in our experience.
|
|
6
|
+
|
|
7
|
+
The SDK provides the agent harness. This package shows how to combine that harness with a terminal experience, persistence, tools, skills, and optional sandboxed execution.
|
|
8
|
+
|
|
9
|
+
## The big picture
|
|
10
|
+
|
|
11
|
+
Deep Agents Code has two runtime halves:
|
|
12
|
+
|
|
13
|
+
```text
|
|
14
|
+
┌──────────────────── Terminal client ─────────────────────┐
|
|
15
|
+
│ Presents interactive or headless output │
|
|
16
|
+
│ Collects user input and approvals │
|
|
17
|
+
└──────────────────────────┬───────────────────────────────┘
|
|
18
|
+
│ streaming protocol
|
|
19
|
+
▼
|
|
20
|
+
┌──────────────────── Agent server ────────────────────────┐
|
|
21
|
+
│ Runs the coding agent graph │
|
|
22
|
+
│ Connects the model, tools, memory, skills, and backend │
|
|
23
|
+
└──────────────────────────────────────────────────────────┘
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
The client and server run in separate processes. The client owns presentation and input. The server owns the agent runtime. Keeping that boundary narrow makes the UI responsive while letting the agent use LangGraph's streaming, checkpointing, and resume behavior.
|
|
27
|
+
|
|
28
|
+
## Request flow
|
|
29
|
+
|
|
30
|
+
A request follows the same shape in interactive and headless mode:
|
|
31
|
+
|
|
32
|
+
1. The client receives user input.
|
|
33
|
+
2. The client sends that input to the agent server.
|
|
34
|
+
3. The server runs the agent and streams events back.
|
|
35
|
+
4. The client renders those events and collects any needed human response.
|
|
36
|
+
5. Session state is preserved so the conversation can continue later.
|
|
37
|
+
|
|
38
|
+
Headless mode uses the same agent runtime as the interactive UI, but swaps the terminal interface for machine-friendly input and output.
|
|
39
|
+
|
|
40
|
+
## Configuration and extension
|
|
41
|
+
|
|
42
|
+
Configuration is layered across user, project, session, and runtime scopes. That lets teams share project defaults while individual users keep their own credentials, preferences, skills, and local settings.
|
|
43
|
+
|
|
44
|
+
The main extension points are:
|
|
45
|
+
|
|
46
|
+
- **Skills and subagents** for reusable agent workflows
|
|
47
|
+
- **Tools and MCP servers** for external capabilities
|
|
48
|
+
- **Sandboxes** for changing where tool execution happens
|
|
49
|
+
- **Hooks and commands** for integrating with local workflows
|
|
50
|
+
|
|
51
|
+
These pieces are designed to compose. A project can provide shared defaults and integrations, while each user can layer personal configuration on top.
|
|
52
|
+
|
|
53
|
+
## Design tradeoffs
|
|
54
|
+
|
|
55
|
+
This architecture optimizes for:
|
|
56
|
+
|
|
57
|
+
- A responsive local terminal experience
|
|
58
|
+
- A reusable agent core that can be tested apart from the UI
|
|
59
|
+
- Durable sessions that can be resumed
|
|
60
|
+
- Controlled tool execution, locally or in a sandbox
|
|
61
|
+
- Practical extension points without rewriting the core app
|
|
62
|
+
|
|
63
|
+
The main cost is the client/server boundary. When debugging, first decide which side owns the failure: presentation and input usually belong to the client; model execution, tools, memory, and graph startup usually belong to the server.
|
|
64
|
+
|
|
65
|
+
## Where to go next
|
|
66
|
+
|
|
67
|
+
- For local setup and debugging, see [`DEVELOPMENT.md`](./DEVELOPMENT.md).
|
|
68
|
+
- For command behavior, see [`COMMANDS.md`](./COMMANDS.md).
|
|
69
|
+
- For security boundaries, see [`THREAT_MODEL.md`](./THREAT_MODEL.md).
|
|
70
|
+
- For package-specific coding conventions, see [`AGENTS.md`](./AGENTS.md).
|