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.
Files changed (379) hide show
  1. zjcode-0.0.1/.gitignore +258 -0
  2. zjcode-0.0.1/AGENTS.md +136 -0
  3. zjcode-0.0.1/ARCHITECTURE.md +70 -0
  4. zjcode-0.0.1/CHANGELOG.md +618 -0
  5. zjcode-0.0.1/COMMANDS.md +55 -0
  6. zjcode-0.0.1/DEVELOPMENT.md +215 -0
  7. zjcode-0.0.1/Makefile +126 -0
  8. zjcode-0.0.1/PKG-INFO +220 -0
  9. zjcode-0.0.1/README.md +72 -0
  10. zjcode-0.0.1/THREAT_MODEL.md +496 -0
  11. zjcode-0.0.1/bump-version.py +250 -0
  12. zjcode-0.0.1/dcode-dev.ps1 +32 -0
  13. zjcode-0.0.1/deepagents_code/__init__.py +42 -0
  14. zjcode-0.0.1/deepagents_code/__main__.py +6 -0
  15. zjcode-0.0.1/deepagents_code/_ask_user_types.py +90 -0
  16. zjcode-0.0.1/deepagents_code/_cli_context.py +96 -0
  17. zjcode-0.0.1/deepagents_code/_constants.py +41 -0
  18. zjcode-0.0.1/deepagents_code/_debug.py +148 -0
  19. zjcode-0.0.1/deepagents_code/_debug_buffer.py +204 -0
  20. zjcode-0.0.1/deepagents_code/_env_vars.py +411 -0
  21. zjcode-0.0.1/deepagents_code/_fake_models.py +66 -0
  22. zjcode-0.0.1/deepagents_code/_git.py +521 -0
  23. zjcode-0.0.1/deepagents_code/_paths.py +69 -0
  24. zjcode-0.0.1/deepagents_code/_server_config.py +576 -0
  25. zjcode-0.0.1/deepagents_code/_session_stats.py +235 -0
  26. zjcode-0.0.1/deepagents_code/_startup_error.py +45 -0
  27. zjcode-0.0.1/deepagents_code/_testing_models.py +305 -0
  28. zjcode-0.0.1/deepagents_code/_textual_patches.py +420 -0
  29. zjcode-0.0.1/deepagents_code/_tool_stream.py +694 -0
  30. zjcode-0.0.1/deepagents_code/_version.py +46 -0
  31. zjcode-0.0.1/deepagents_code/agent.py +1976 -0
  32. zjcode-0.0.1/deepagents_code/app.py +19239 -0
  33. zjcode-0.0.1/deepagents_code/app.tcss +438 -0
  34. zjcode-0.0.1/deepagents_code/approval_mode.py +131 -0
  35. zjcode-0.0.1/deepagents_code/ask_user.py +306 -0
  36. zjcode-0.0.1/deepagents_code/auth_display.py +185 -0
  37. zjcode-0.0.1/deepagents_code/auth_store.py +545 -0
  38. zjcode-0.0.1/deepagents_code/built_in_skills/__init__.py +5 -0
  39. zjcode-0.0.1/deepagents_code/built_in_skills/remember/SKILL.md +118 -0
  40. zjcode-0.0.1/deepagents_code/built_in_skills/skill-creator/SKILL.md +383 -0
  41. zjcode-0.0.1/deepagents_code/built_in_skills/skill-creator/scripts/init_skill.py +366 -0
  42. zjcode-0.0.1/deepagents_code/built_in_skills/skill-creator/scripts/quick_validate.py +158 -0
  43. zjcode-0.0.1/deepagents_code/client/__init__.py +1 -0
  44. zjcode-0.0.1/deepagents_code/client/commands/__init__.py +1 -0
  45. zjcode-0.0.1/deepagents_code/client/commands/auth.py +541 -0
  46. zjcode-0.0.1/deepagents_code/client/commands/config.py +714 -0
  47. zjcode-0.0.1/deepagents_code/client/commands/mcp.py +250 -0
  48. zjcode-0.0.1/deepagents_code/client/commands/tools.py +416 -0
  49. zjcode-0.0.1/deepagents_code/client/launch/__init__.py +1 -0
  50. zjcode-0.0.1/deepagents_code/client/launch/server.py +978 -0
  51. zjcode-0.0.1/deepagents_code/client/launch/server_manager.py +540 -0
  52. zjcode-0.0.1/deepagents_code/client/non_interactive.py +1758 -0
  53. zjcode-0.0.1/deepagents_code/client/remote_client.py +794 -0
  54. zjcode-0.0.1/deepagents_code/clipboard.py +217 -0
  55. zjcode-0.0.1/deepagents_code/command_registry.py +450 -0
  56. zjcode-0.0.1/deepagents_code/config.py +4829 -0
  57. zjcode-0.0.1/deepagents_code/config_manifest.py +1451 -0
  58. zjcode-0.0.1/deepagents_code/configurable_model.py +577 -0
  59. zjcode-0.0.1/deepagents_code/default_agent_prompt.md +12 -0
  60. zjcode-0.0.1/deepagents_code/doctor.py +559 -0
  61. zjcode-0.0.1/deepagents_code/editor.py +142 -0
  62. zjcode-0.0.1/deepagents_code/event_bus.py +411 -0
  63. zjcode-0.0.1/deepagents_code/extras_info.py +661 -0
  64. zjcode-0.0.1/deepagents_code/file_ops.py +576 -0
  65. zjcode-0.0.1/deepagents_code/formatting.py +135 -0
  66. zjcode-0.0.1/deepagents_code/goal_rubric.py +497 -0
  67. zjcode-0.0.1/deepagents_code/goal_tools.py +459 -0
  68. zjcode-0.0.1/deepagents_code/hooks.py +348 -0
  69. zjcode-0.0.1/deepagents_code/input.py +1041 -0
  70. zjcode-0.0.1/deepagents_code/integrations/__init__.py +1 -0
  71. zjcode-0.0.1/deepagents_code/integrations/openai_codex.py +551 -0
  72. zjcode-0.0.1/deepagents_code/integrations/sandbox_config.py +198 -0
  73. zjcode-0.0.1/deepagents_code/integrations/sandbox_factory.py +1124 -0
  74. zjcode-0.0.1/deepagents_code/integrations/sandbox_provider.py +137 -0
  75. zjcode-0.0.1/deepagents_code/integrations/sandbox_registry.py +350 -0
  76. zjcode-0.0.1/deepagents_code/iterm_cursor_guide.py +176 -0
  77. zjcode-0.0.1/deepagents_code/local_context.py +926 -0
  78. zjcode-0.0.1/deepagents_code/main.py +3985 -0
  79. zjcode-0.0.1/deepagents_code/managed_tools.py +642 -0
  80. zjcode-0.0.1/deepagents_code/mcp_auth.py +1950 -0
  81. zjcode-0.0.1/deepagents_code/mcp_config.py +176 -0
  82. zjcode-0.0.1/deepagents_code/mcp_disabled.py +212 -0
  83. zjcode-0.0.1/deepagents_code/mcp_login_service.py +281 -0
  84. zjcode-0.0.1/deepagents_code/mcp_oauth_ui.py +199 -0
  85. zjcode-0.0.1/deepagents_code/mcp_providers/__init__.py +23 -0
  86. zjcode-0.0.1/deepagents_code/mcp_providers/_registry.py +39 -0
  87. zjcode-0.0.1/deepagents_code/mcp_providers/base.py +133 -0
  88. zjcode-0.0.1/deepagents_code/mcp_providers/github.py +102 -0
  89. zjcode-0.0.1/deepagents_code/mcp_providers/slack.py +175 -0
  90. zjcode-0.0.1/deepagents_code/mcp_tools.py +2427 -0
  91. zjcode-0.0.1/deepagents_code/mcp_trust.py +207 -0
  92. zjcode-0.0.1/deepagents_code/media_utils.py +826 -0
  93. zjcode-0.0.1/deepagents_code/memory_guard.py +474 -0
  94. zjcode-0.0.1/deepagents_code/model_config.py +4156 -0
  95. zjcode-0.0.1/deepagents_code/notifications.py +247 -0
  96. zjcode-0.0.1/deepagents_code/offload.py +402 -0
  97. zjcode-0.0.1/deepagents_code/onboarding.py +223 -0
  98. zjcode-0.0.1/deepagents_code/output.py +69 -0
  99. zjcode-0.0.1/deepagents_code/paste_collapse.py +103 -0
  100. zjcode-0.0.1/deepagents_code/project_utils.py +231 -0
  101. zjcode-0.0.1/deepagents_code/py.typed +0 -0
  102. zjcode-0.0.1/deepagents_code/reasoning_effort.py +641 -0
  103. zjcode-0.0.1/deepagents_code/reliable_rubric.py +97 -0
  104. zjcode-0.0.1/deepagents_code/resume_state.py +237 -0
  105. zjcode-0.0.1/deepagents_code/server_graph.py +310 -0
  106. zjcode-0.0.1/deepagents_code/session_end_summary.py +329 -0
  107. zjcode-0.0.1/deepagents_code/sessions.py +1716 -0
  108. zjcode-0.0.1/deepagents_code/skills/__init__.py +18 -0
  109. zjcode-0.0.1/deepagents_code/skills/commands.py +1252 -0
  110. zjcode-0.0.1/deepagents_code/skills/invocation.py +112 -0
  111. zjcode-0.0.1/deepagents_code/skills/load.py +196 -0
  112. zjcode-0.0.1/deepagents_code/skills/trust.py +547 -0
  113. zjcode-0.0.1/deepagents_code/state_migration.py +136 -0
  114. zjcode-0.0.1/deepagents_code/subagents.py +278 -0
  115. zjcode-0.0.1/deepagents_code/system_prompt.md +204 -0
  116. zjcode-0.0.1/deepagents_code/terminal_capabilities.py +115 -0
  117. zjcode-0.0.1/deepagents_code/terminal_escape.py +287 -0
  118. zjcode-0.0.1/deepagents_code/theme.py +891 -0
  119. zjcode-0.0.1/deepagents_code/todo_list_prompt.md +12 -0
  120. zjcode-0.0.1/deepagents_code/tool_catalog.py +509 -0
  121. zjcode-0.0.1/deepagents_code/tool_display.py +367 -0
  122. zjcode-0.0.1/deepagents_code/tools.py +516 -0
  123. zjcode-0.0.1/deepagents_code/tui/__init__.py +1 -0
  124. zjcode-0.0.1/deepagents_code/tui/textual_adapter.py +2553 -0
  125. zjcode-0.0.1/deepagents_code/tui/widgets/__init__.py +9 -0
  126. zjcode-0.0.1/deepagents_code/tui/widgets/_js_eval_display.py +139 -0
  127. zjcode-0.0.1/deepagents_code/tui/widgets/_links.py +261 -0
  128. zjcode-0.0.1/deepagents_code/tui/widgets/agent_selector.py +420 -0
  129. zjcode-0.0.1/deepagents_code/tui/widgets/approval.py +602 -0
  130. zjcode-0.0.1/deepagents_code/tui/widgets/ask_user.py +515 -0
  131. zjcode-0.0.1/deepagents_code/tui/widgets/auth.py +1997 -0
  132. zjcode-0.0.1/deepagents_code/tui/widgets/autocomplete.py +890 -0
  133. zjcode-0.0.1/deepagents_code/tui/widgets/chat_input.py +3181 -0
  134. zjcode-0.0.1/deepagents_code/tui/widgets/codex_auth.py +452 -0
  135. zjcode-0.0.1/deepagents_code/tui/widgets/cwd_switch.py +242 -0
  136. zjcode-0.0.1/deepagents_code/tui/widgets/debug_console.py +868 -0
  137. zjcode-0.0.1/deepagents_code/tui/widgets/diff.py +252 -0
  138. zjcode-0.0.1/deepagents_code/tui/widgets/effort_selector.py +189 -0
  139. zjcode-0.0.1/deepagents_code/tui/widgets/goal_review.py +390 -0
  140. zjcode-0.0.1/deepagents_code/tui/widgets/goal_status.py +50 -0
  141. zjcode-0.0.1/deepagents_code/tui/widgets/history.py +194 -0
  142. zjcode-0.0.1/deepagents_code/tui/widgets/install_confirm.py +248 -0
  143. zjcode-0.0.1/deepagents_code/tui/widgets/launch_init.py +482 -0
  144. zjcode-0.0.1/deepagents_code/tui/widgets/loading.py +227 -0
  145. zjcode-0.0.1/deepagents_code/tui/widgets/mcp_login.py +539 -0
  146. zjcode-0.0.1/deepagents_code/tui/widgets/mcp_reconnect.py +212 -0
  147. zjcode-0.0.1/deepagents_code/tui/widgets/mcp_viewer.py +1634 -0
  148. zjcode-0.0.1/deepagents_code/tui/widgets/message_store.py +999 -0
  149. zjcode-0.0.1/deepagents_code/tui/widgets/messages.py +3846 -0
  150. zjcode-0.0.1/deepagents_code/tui/widgets/model_selector.py +2343 -0
  151. zjcode-0.0.1/deepagents_code/tui/widgets/notification_center.py +456 -0
  152. zjcode-0.0.1/deepagents_code/tui/widgets/notification_detail.py +257 -0
  153. zjcode-0.0.1/deepagents_code/tui/widgets/notification_settings.py +170 -0
  154. zjcode-0.0.1/deepagents_code/tui/widgets/restart_prompt.py +158 -0
  155. zjcode-0.0.1/deepagents_code/tui/widgets/skill_trust.py +131 -0
  156. zjcode-0.0.1/deepagents_code/tui/widgets/startup_tip.py +91 -0
  157. zjcode-0.0.1/deepagents_code/tui/widgets/status.py +781 -0
  158. zjcode-0.0.1/deepagents_code/tui/widgets/subagent_panel.py +969 -0
  159. zjcode-0.0.1/deepagents_code/tui/widgets/theme_selector.py +401 -0
  160. zjcode-0.0.1/deepagents_code/tui/widgets/thread_selector.py +2564 -0
  161. zjcode-0.0.1/deepagents_code/tui/widgets/tool_renderers.py +190 -0
  162. zjcode-0.0.1/deepagents_code/tui/widgets/tool_widgets.py +304 -0
  163. zjcode-0.0.1/deepagents_code/tui/widgets/update_available.py +311 -0
  164. zjcode-0.0.1/deepagents_code/tui/widgets/update_confirm.py +184 -0
  165. zjcode-0.0.1/deepagents_code/tui/widgets/update_progress.py +327 -0
  166. zjcode-0.0.1/deepagents_code/tui/widgets/welcome.py +508 -0
  167. zjcode-0.0.1/deepagents_code/turn_end_summary.py +522 -0
  168. zjcode-0.0.1/deepagents_code/ui.py +858 -0
  169. zjcode-0.0.1/deepagents_code/unicode_security.py +563 -0
  170. zjcode-0.0.1/deepagents_code/update_check.py +3124 -0
  171. 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
  172. 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
  173. 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
  174. 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
  175. zjcode-0.0.1/doc/2026-07-08-windows-dev-deployment-script.md +64 -0
  176. 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
  177. 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
  178. 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
  179. 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
  180. 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
  181. zjcode-0.0.1/doc/2026-07-18-session-end-summary/345/206/205/347/275/256.md +74 -0
  182. 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
  183. 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
  184. zjcode-0.0.1/examples/skills/arxiv-search/SKILL.md +33 -0
  185. zjcode-0.0.1/examples/skills/arxiv-search/arxiv_search.py +61 -0
  186. zjcode-0.0.1/examples/skills/langgraph-docs/SKILL.md +28 -0
  187. zjcode-0.0.1/examples/skills/skill-creator/SKILL.md +385 -0
  188. zjcode-0.0.1/examples/skills/skill-creator/scripts/init_skill.py +311 -0
  189. zjcode-0.0.1/examples/skills/skill-creator/scripts/quick_validate.py +152 -0
  190. zjcode-0.0.1/examples/skills/web-research/SKILL.md +77 -0
  191. zjcode-0.0.1/hatch_build.py +67 -0
  192. zjcode-0.0.1/images/tui.png +0 -0
  193. zjcode-0.0.1/pyproject.toml +325 -0
  194. zjcode-0.0.1/run-dcode-dev.ps1 +107 -0
  195. zjcode-0.0.1/run-dcode-dev.sh +34 -0
  196. zjcode-0.0.1/run-publish.sh +18 -0
  197. zjcode-0.0.1/run-setup-dev-env.sh +101 -0
  198. zjcode-0.0.1/scripts/benchmark_huoshan_models.py +822 -0
  199. zjcode-0.0.1/scripts/benchmark_report_20260712_151546.md +234 -0
  200. zjcode-0.0.1/scripts/benchmark_results_20260712_151546.json +2862 -0
  201. zjcode-0.0.1/scripts/check_imports.py +44 -0
  202. zjcode-0.0.1/scripts/debug_server.sh +66 -0
  203. zjcode-0.0.1/scripts/generate_commands_catalog.py +135 -0
  204. zjcode-0.0.1/scripts/install.sh +1980 -0
  205. zjcode-0.0.1/setup-dev-env.ps1 +141 -0
  206. zjcode-0.0.1/tests/README.md +11 -0
  207. zjcode-0.0.1/tests/integration_tests/__init__.py +0 -0
  208. zjcode-0.0.1/tests/integration_tests/benchmarks/__init__.py +0 -0
  209. zjcode-0.0.1/tests/integration_tests/benchmarks/test_codspeed_import_benchmarks.py +185 -0
  210. zjcode-0.0.1/tests/integration_tests/benchmarks/test_startup_benchmarks.py +337 -0
  211. zjcode-0.0.1/tests/integration_tests/conftest.py +39 -0
  212. zjcode-0.0.1/tests/integration_tests/test_acp_mode.py +117 -0
  213. zjcode-0.0.1/tests/integration_tests/test_auto_approve_remote.py +201 -0
  214. zjcode-0.0.1/tests/integration_tests/test_compact_resume.py +204 -0
  215. zjcode-0.0.1/tests/integration_tests/test_sandbox_factory.py +348 -0
  216. zjcode-0.0.1/tests/integration_tests/test_sandbox_operations.py +1179 -0
  217. zjcode-0.0.1/tests/unit_tests/__init__.py +0 -0
  218. zjcode-0.0.1/tests/unit_tests/client/__init__.py +1 -0
  219. zjcode-0.0.1/tests/unit_tests/client/commands/__init__.py +1 -0
  220. zjcode-0.0.1/tests/unit_tests/client/commands/test_auth.py +1003 -0
  221. zjcode-0.0.1/tests/unit_tests/client/commands/test_mcp.py +344 -0
  222. zjcode-0.0.1/tests/unit_tests/client/commands/test_tools.py +564 -0
  223. zjcode-0.0.1/tests/unit_tests/conftest.py +334 -0
  224. zjcode-0.0.1/tests/unit_tests/data/coding_agent_v1_validator.json +241 -0
  225. zjcode-0.0.1/tests/unit_tests/skills/__init__.py +1 -0
  226. zjcode-0.0.1/tests/unit_tests/skills/test_commands.py +1625 -0
  227. zjcode-0.0.1/tests/unit_tests/skills/test_load.py +856 -0
  228. zjcode-0.0.1/tests/unit_tests/skills/test_skill_trust.py +528 -0
  229. zjcode-0.0.1/tests/unit_tests/skills/test_skills_json.py +154 -0
  230. zjcode-0.0.1/tests/unit_tests/smoke_tests/__init__.py +0 -0
  231. zjcode-0.0.1/tests/unit_tests/smoke_tests/conftest.py +28 -0
  232. zjcode-0.0.1/tests/unit_tests/smoke_tests/snapshots/system_prompt_interactive_local.md +538 -0
  233. zjcode-0.0.1/tests/unit_tests/smoke_tests/test_system_prompt.py +199 -0
  234. zjcode-0.0.1/tests/unit_tests/test__tool_stream.py +503 -0
  235. zjcode-0.0.1/tests/unit_tests/test_agent.py +4149 -0
  236. zjcode-0.0.1/tests/unit_tests/test_agent_friendly.py +613 -0
  237. zjcode-0.0.1/tests/unit_tests/test_app.py +25908 -0
  238. zjcode-0.0.1/tests/unit_tests/test_approval_mode.py +129 -0
  239. zjcode-0.0.1/tests/unit_tests/test_args.py +869 -0
  240. zjcode-0.0.1/tests/unit_tests/test_ask_user_middleware.py +221 -0
  241. zjcode-0.0.1/tests/unit_tests/test_auth_display.py +238 -0
  242. zjcode-0.0.1/tests/unit_tests/test_auth_store.py +434 -0
  243. zjcode-0.0.1/tests/unit_tests/test_auth_web_search_restart.py +609 -0
  244. zjcode-0.0.1/tests/unit_tests/test_charset.py +377 -0
  245. zjcode-0.0.1/tests/unit_tests/test_clipboard.py +474 -0
  246. zjcode-0.0.1/tests/unit_tests/test_coding_agent_metadata.py +255 -0
  247. zjcode-0.0.1/tests/unit_tests/test_command_registry.py +389 -0
  248. zjcode-0.0.1/tests/unit_tests/test_compact_tool.py +40 -0
  249. zjcode-0.0.1/tests/unit_tests/test_config.py +6268 -0
  250. zjcode-0.0.1/tests/unit_tests/test_config_manifest.py +1933 -0
  251. zjcode-0.0.1/tests/unit_tests/test_configurable_model.py +1304 -0
  252. zjcode-0.0.1/tests/unit_tests/test_cursor_blink.py +59 -0
  253. zjcode-0.0.1/tests/unit_tests/test_cursor_style.py +56 -0
  254. zjcode-0.0.1/tests/unit_tests/test_debug.py +347 -0
  255. zjcode-0.0.1/tests/unit_tests/test_debug_buffer.py +269 -0
  256. zjcode-0.0.1/tests/unit_tests/test_debug_console.py +862 -0
  257. zjcode-0.0.1/tests/unit_tests/test_doctor.py +578 -0
  258. zjcode-0.0.1/tests/unit_tests/test_editor.py +274 -0
  259. zjcode-0.0.1/tests/unit_tests/test_end_to_end.py +435 -0
  260. zjcode-0.0.1/tests/unit_tests/test_env_vars.py +135 -0
  261. zjcode-0.0.1/tests/unit_tests/test_error_handling.py +34 -0
  262. zjcode-0.0.1/tests/unit_tests/test_event_bus.py +445 -0
  263. zjcode-0.0.1/tests/unit_tests/test_exception_handling.py +252 -0
  264. zjcode-0.0.1/tests/unit_tests/test_extras_info.py +609 -0
  265. zjcode-0.0.1/tests/unit_tests/test_file_ops.py +277 -0
  266. zjcode-0.0.1/tests/unit_tests/test_formatting.py +226 -0
  267. zjcode-0.0.1/tests/unit_tests/test_git.py +589 -0
  268. zjcode-0.0.1/tests/unit_tests/test_goal_rubric.py +697 -0
  269. zjcode-0.0.1/tests/unit_tests/test_goal_tools.py +473 -0
  270. zjcode-0.0.1/tests/unit_tests/test_hatch_build.py +159 -0
  271. zjcode-0.0.1/tests/unit_tests/test_hooks.py +600 -0
  272. zjcode-0.0.1/tests/unit_tests/test_imports.py +29 -0
  273. zjcode-0.0.1/tests/unit_tests/test_input_parsing.py +482 -0
  274. zjcode-0.0.1/tests/unit_tests/test_install_command.py +1135 -0
  275. zjcode-0.0.1/tests/unit_tests/test_install_script.py +2832 -0
  276. zjcode-0.0.1/tests/unit_tests/test_iterm_cursor_guide.py +256 -0
  277. zjcode-0.0.1/tests/unit_tests/test_local_context.py +1948 -0
  278. zjcode-0.0.1/tests/unit_tests/test_main.py +2971 -0
  279. zjcode-0.0.1/tests/unit_tests/test_main_acp_mode.py +199 -0
  280. zjcode-0.0.1/tests/unit_tests/test_main_args.py +2850 -0
  281. zjcode-0.0.1/tests/unit_tests/test_managed_tools.py +1009 -0
  282. zjcode-0.0.1/tests/unit_tests/test_mcp_auth.py +3011 -0
  283. zjcode-0.0.1/tests/unit_tests/test_mcp_config.py +214 -0
  284. zjcode-0.0.1/tests/unit_tests/test_mcp_disabled.py +182 -0
  285. zjcode-0.0.1/tests/unit_tests/test_mcp_login_service.py +291 -0
  286. zjcode-0.0.1/tests/unit_tests/test_mcp_oauth_ui.py +422 -0
  287. zjcode-0.0.1/tests/unit_tests/test_mcp_tools.py +4434 -0
  288. zjcode-0.0.1/tests/unit_tests/test_mcp_trust.py +158 -0
  289. zjcode-0.0.1/tests/unit_tests/test_media_utils.py +1150 -0
  290. zjcode-0.0.1/tests/unit_tests/test_memory_guard.py +523 -0
  291. zjcode-0.0.1/tests/unit_tests/test_model_config.py +6334 -0
  292. zjcode-0.0.1/tests/unit_tests/test_model_switch.py +1381 -0
  293. zjcode-0.0.1/tests/unit_tests/test_non_interactive.py +3286 -0
  294. zjcode-0.0.1/tests/unit_tests/test_notifications.py +206 -0
  295. zjcode-0.0.1/tests/unit_tests/test_offload.py +1513 -0
  296. zjcode-0.0.1/tests/unit_tests/test_offload_dict_messages.py +335 -0
  297. zjcode-0.0.1/tests/unit_tests/test_onboarding.py +292 -0
  298. zjcode-0.0.1/tests/unit_tests/test_openai_codex_integration.py +692 -0
  299. zjcode-0.0.1/tests/unit_tests/test_output.py +62 -0
  300. zjcode-0.0.1/tests/unit_tests/test_paths.py +44 -0
  301. zjcode-0.0.1/tests/unit_tests/test_reasoning_effort.py +715 -0
  302. zjcode-0.0.1/tests/unit_tests/test_reliable_rubric.py +167 -0
  303. zjcode-0.0.1/tests/unit_tests/test_reload.py +1035 -0
  304. zjcode-0.0.1/tests/unit_tests/test_remote_client.py +1076 -0
  305. zjcode-0.0.1/tests/unit_tests/test_resume_state.py +300 -0
  306. zjcode-0.0.1/tests/unit_tests/test_rubric_cli.py +352 -0
  307. zjcode-0.0.1/tests/unit_tests/test_sandbox_config.py +140 -0
  308. zjcode-0.0.1/tests/unit_tests/test_sandbox_factory.py +1423 -0
  309. zjcode-0.0.1/tests/unit_tests/test_sandbox_provider.py +50 -0
  310. zjcode-0.0.1/tests/unit_tests/test_sandbox_registry.py +313 -0
  311. zjcode-0.0.1/tests/unit_tests/test_server.py +1674 -0
  312. zjcode-0.0.1/tests/unit_tests/test_server_config.py +437 -0
  313. zjcode-0.0.1/tests/unit_tests/test_server_graph.py +424 -0
  314. zjcode-0.0.1/tests/unit_tests/test_server_helpers.py +190 -0
  315. zjcode-0.0.1/tests/unit_tests/test_server_manager.py +628 -0
  316. zjcode-0.0.1/tests/unit_tests/test_session_end_summary.py +132 -0
  317. zjcode-0.0.1/tests/unit_tests/test_session_stats.py +282 -0
  318. zjcode-0.0.1/tests/unit_tests/test_sessions.py +3051 -0
  319. zjcode-0.0.1/tests/unit_tests/test_shell_allow_list.py +719 -0
  320. zjcode-0.0.1/tests/unit_tests/test_skill_invocation.py +1003 -0
  321. zjcode-0.0.1/tests/unit_tests/test_startup_fast_paths.py +256 -0
  322. zjcode-0.0.1/tests/unit_tests/test_state_migration.py +204 -0
  323. zjcode-0.0.1/tests/unit_tests/test_subagents.py +731 -0
  324. zjcode-0.0.1/tests/unit_tests/test_terminal_capabilities.py +203 -0
  325. zjcode-0.0.1/tests/unit_tests/test_terminal_escape.py +386 -0
  326. zjcode-0.0.1/tests/unit_tests/test_terminal_progress_preference.py +68 -0
  327. zjcode-0.0.1/tests/unit_tests/test_textual_patches.py +261 -0
  328. zjcode-0.0.1/tests/unit_tests/test_theme.py +3105 -0
  329. zjcode-0.0.1/tests/unit_tests/test_threads_resume.py +350 -0
  330. zjcode-0.0.1/tests/unit_tests/test_tool_catalog.py +558 -0
  331. zjcode-0.0.1/tests/unit_tests/test_tool_display.py +573 -0
  332. zjcode-0.0.1/tests/unit_tests/test_tracing_replicas.py +70 -0
  333. zjcode-0.0.1/tests/unit_tests/test_transcript_virtualization.py +240 -0
  334. zjcode-0.0.1/tests/unit_tests/test_turn_end_summary.py +252 -0
  335. zjcode-0.0.1/tests/unit_tests/test_ui.py +421 -0
  336. zjcode-0.0.1/tests/unit_tests/test_unicode_security.py +315 -0
  337. zjcode-0.0.1/tests/unit_tests/test_update_check.py +4867 -0
  338. zjcode-0.0.1/tests/unit_tests/test_version.py +1443 -0
  339. zjcode-0.0.1/tests/unit_tests/tools/__init__.py +0 -0
  340. zjcode-0.0.1/tests/unit_tests/tools/test_current_thread.py +27 -0
  341. zjcode-0.0.1/tests/unit_tests/tools/test_fetch_url.py +605 -0
  342. zjcode-0.0.1/tests/unit_tests/tui/__init__.py +0 -0
  343. zjcode-0.0.1/tests/unit_tests/tui/test_subagent_stream.py +41 -0
  344. zjcode-0.0.1/tests/unit_tests/tui/test_textual_adapter.py +6975 -0
  345. zjcode-0.0.1/tests/unit_tests/tui/widgets/__init__.py +0 -0
  346. zjcode-0.0.1/tests/unit_tests/tui/widgets/test_agent_selector.py +466 -0
  347. zjcode-0.0.1/tests/unit_tests/tui/widgets/test_approval.py +641 -0
  348. zjcode-0.0.1/tests/unit_tests/tui/widgets/test_ask_user.py +1055 -0
  349. zjcode-0.0.1/tests/unit_tests/tui/widgets/test_auth_widgets.py +3045 -0
  350. zjcode-0.0.1/tests/unit_tests/tui/widgets/test_autocomplete.py +1354 -0
  351. zjcode-0.0.1/tests/unit_tests/tui/widgets/test_chat_input.py +5146 -0
  352. zjcode-0.0.1/tests/unit_tests/tui/widgets/test_cwd_switch.py +231 -0
  353. zjcode-0.0.1/tests/unit_tests/tui/widgets/test_diff.py +140 -0
  354. zjcode-0.0.1/tests/unit_tests/tui/widgets/test_goal_review.py +341 -0
  355. zjcode-0.0.1/tests/unit_tests/tui/widgets/test_history.py +334 -0
  356. zjcode-0.0.1/tests/unit_tests/tui/widgets/test_install_confirm.py +167 -0
  357. zjcode-0.0.1/tests/unit_tests/tui/widgets/test_launch_init.py +560 -0
  358. zjcode-0.0.1/tests/unit_tests/tui/widgets/test_links.py +301 -0
  359. zjcode-0.0.1/tests/unit_tests/tui/widgets/test_loading.py +161 -0
  360. zjcode-0.0.1/tests/unit_tests/tui/widgets/test_mcp_login_modal.py +409 -0
  361. zjcode-0.0.1/tests/unit_tests/tui/widgets/test_mcp_reconnect.py +130 -0
  362. zjcode-0.0.1/tests/unit_tests/tui/widgets/test_mcp_viewer.py +2207 -0
  363. zjcode-0.0.1/tests/unit_tests/tui/widgets/test_message_store.py +1144 -0
  364. zjcode-0.0.1/tests/unit_tests/tui/widgets/test_messages.py +4480 -0
  365. zjcode-0.0.1/tests/unit_tests/tui/widgets/test_model_selector.py +3619 -0
  366. zjcode-0.0.1/tests/unit_tests/tui/widgets/test_notification_center.py +367 -0
  367. zjcode-0.0.1/tests/unit_tests/tui/widgets/test_notification_detail.py +133 -0
  368. zjcode-0.0.1/tests/unit_tests/tui/widgets/test_restart_prompt.py +127 -0
  369. zjcode-0.0.1/tests/unit_tests/tui/widgets/test_skill_trust_screen.py +78 -0
  370. zjcode-0.0.1/tests/unit_tests/tui/widgets/test_startup_tip.py +85 -0
  371. zjcode-0.0.1/tests/unit_tests/tui/widgets/test_status.py +1064 -0
  372. zjcode-0.0.1/tests/unit_tests/tui/widgets/test_subagent_panel.py +549 -0
  373. zjcode-0.0.1/tests/unit_tests/tui/widgets/test_thread_selector.py +5019 -0
  374. zjcode-0.0.1/tests/unit_tests/tui/widgets/test_tool_renderers.py +216 -0
  375. zjcode-0.0.1/tests/unit_tests/tui/widgets/test_update_available.py +185 -0
  376. zjcode-0.0.1/tests/unit_tests/tui/widgets/test_update_confirm.py +106 -0
  377. zjcode-0.0.1/tests/unit_tests/tui/widgets/test_update_progress.py +275 -0
  378. zjcode-0.0.1/tests/unit_tests/tui/widgets/test_welcome.py +851 -0
  379. zjcode-0.0.1/uv.lock +7207 -0
@@ -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).