@scemoon/cdh 1.0.6 → 1.0.7

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 (550) hide show
  1. package/package.json +2 -2
  2. package/ai-dlc-skill/SKILL.md +0 -77
  3. package/ai-dlc-skill/agents/deliver-agent.md +0 -24
  4. package/ai-dlc-skill/agents/master.md +0 -50
  5. package/ai-dlc-skill/agents/plan-agent.md +0 -23
  6. package/ai-dlc-skill/agents/understand-agent.md +0 -23
  7. package/ai-dlc-skill/agents/verify-agent.md +0 -27
  8. package/ai-dlc-skill/architecture/project-structure.md +0 -78
  9. package/ai-dlc-skill/brownfield/README.md +0 -30
  10. package/ai-dlc-skill/brownfield/generate-context.sh +0 -64
  11. package/ai-dlc-skill/brownfield/scripts/deps.sh +0 -27
  12. package/ai-dlc-skill/brownfield/scripts/discover.sh +0 -34
  13. package/ai-dlc-skill/brownfield/scripts/extract-api.sh +0 -45
  14. package/ai-dlc-skill/components/backend.md +0 -34
  15. package/ai-dlc-skill/components/desktop.md +0 -30
  16. package/ai-dlc-skill/components/mya.md +0 -29
  17. package/ai-dlc-skill/components/native.md +0 -30
  18. package/ai-dlc-skill/components/tta.md +0 -29
  19. package/ai-dlc-skill/components/web.md +0 -31
  20. package/ai-dlc-skill/components/wxa.md +0 -29
  21. package/ai-dlc-skill/contracts/README.md +0 -25
  22. package/ai-dlc-skill/core/adaptive-flow.md +0 -36
  23. package/ai-dlc-skill/core/security.md +0 -29
  24. package/ai-dlc-skill/cross-tool/cline/export.sh +0 -31
  25. package/ai-dlc-skill/cross-tool/copilot/export.sh +0 -47
  26. package/ai-dlc-skill/cross-tool/cursor/export.sh +0 -32
  27. package/ai-dlc-skill/cross-tool/export.sh +0 -22
  28. package/ai-dlc-skill/cross-tool/onecode/config.yaml.tpl +0 -17
  29. package/ai-dlc-skill/cross-tool/onecode/export-skills.sh +0 -35
  30. package/ai-dlc-skill/cross-tool/onecode/export.sh +0 -54
  31. package/ai-dlc-skill/phases/deliver/entry.md +0 -26
  32. package/ai-dlc-skill/phases/deliver/lifecycle.md +0 -185
  33. package/ai-dlc-skill/phases/deliver/prompt.md +0 -40
  34. package/ai-dlc-skill/phases/deliver/rules.md +0 -61
  35. package/ai-dlc-skill/phases/plan/entry.md +0 -25
  36. package/ai-dlc-skill/phases/plan/lifecycle.md +0 -204
  37. package/ai-dlc-skill/phases/plan/prompt.md +0 -38
  38. package/ai-dlc-skill/phases/plan/rules.md +0 -25
  39. package/ai-dlc-skill/phases/understand/entry.md +0 -26
  40. package/ai-dlc-skill/phases/understand/lifecycle.md +0 -184
  41. package/ai-dlc-skill/phases/understand/prompt.md +0 -41
  42. package/ai-dlc-skill/phases/understand/rules.md +0 -37
  43. package/ai-dlc-skill/phases/verify/entry.md +0 -26
  44. package/ai-dlc-skill/phases/verify/lifecycle.md +0 -192
  45. package/ai-dlc-skill/phases/verify/prompt.md +0 -43
  46. package/ai-dlc-skill/phases/verify/rules.md +0 -73
  47. package/ai-dlc-skill/practices/bdd.md +0 -91
  48. package/ai-dlc-skill/practices/sdd.md +0 -84
  49. package/ai-dlc-skill/practices/tdd.md +0 -95
  50. package/ai-dlc-skill/providers/README.md +0 -114
  51. package/ai-dlc-skill/providers/aliyun/deployment.yaml +0 -66
  52. package/ai-dlc-skill/providers/aliyun/preview.yaml +0 -84
  53. package/ai-dlc-skill/providers/aliyun/provider.yaml +0 -160
  54. package/ai-dlc-skill/providers/tcb/deployment.yaml +0 -69
  55. package/ai-dlc-skill/providers/tcb/preview.yaml +0 -83
  56. package/ai-dlc-skill/providers/tcb/provider.yaml +0 -172
  57. package/ai-dlc-skill/requirements.md +0 -140
  58. package/ai-dlc-skill/skill.yaml +0 -147
  59. package/ai-dlc-skill/templates/integration/CHANGELOG.md +0 -41
  60. package/ai-dlc-skill/templates/integration/asyncapi.yaml +0 -43
  61. package/ai-dlc-skill/templates/integration/contract-diff.md +0 -63
  62. package/ai-dlc-skill/templates/integration/contract-spec.md +0 -49
  63. package/ai-dlc-skill/templates/integration/openapi.yaml +0 -18
  64. package/ai-dlc-skill/templates/integration/runtime-contract.yaml +0 -36
  65. package/ai-dlc-skill/templates/plan/design.md +0 -49
  66. package/ai-dlc-skill/templates/plan/task-list.md +0 -32
  67. package/ai-dlc-skill/templates/project/README.md +0 -126
  68. package/ai-dlc-skill/templates/project/template.md +0 -119
  69. package/ai-dlc-skill/templates/understand/feature.feature +0 -23
  70. package/ai-dlc-skill/templates/understand/intent.md +0 -29
  71. package/ai-dlc-skill/templates/understand/spec-delta.md +0 -47
  72. package/ai-dlc-skill/templates/verify/test-unit.py +0 -27
  73. package/ai-dlc-skill/walkthrough/collect.sh +0 -50
  74. package/ai-dlc-skill/walkthrough/template.md +0 -54
  75. package/ai-dlc-skill/workflows/ai-dlc.yaml +0 -110
  76. package/ai-dlc-skill/workflows/deployment.yaml +0 -199
  77. package/cdh/__init__.py +0 -0
  78. package/cdh/__main__.py +0 -4
  79. package/cdh/__pycache__/__init__.cpython-314.pyc +0 -0
  80. package/cdh/__pycache__/cdh_mcp_injector.cpython-314.pyc +0 -0
  81. package/cdh/__pycache__/cdh_mcp_loader.cpython-314.pyc +0 -0
  82. package/cdh/__pycache__/cdh_mcp_manager.cpython-314.pyc +0 -0
  83. package/cdh/__pycache__/cdh_session_aggregator.cpython-314.pyc +0 -0
  84. package/cdh/__pycache__/cdh_skill_loader.cpython-314.pyc +0 -0
  85. package/cdh/__pycache__/cdh_skill_manager.cpython-314.pyc +0 -0
  86. package/cdh/__pycache__/cli.cpython-313.pyc +0 -0
  87. package/cdh/__pycache__/cli.cpython-314.pyc +0 -0
  88. package/cdh/__pycache__/scaffold.cpython-314.pyc +0 -0
  89. package/cdh/cdh_mcp_injector.py +0 -115
  90. package/cdh/cdh_mcp_loader.py +0 -67
  91. package/cdh/cdh_mcp_manager.py +0 -73
  92. package/cdh/cdh_session_aggregator.py +0 -258
  93. package/cdh/cdh_skill_manager.py +0 -105
  94. package/cdh/cli.py +0 -807
  95. package/cdh/scaffold.py +0 -728
  96. package/onecode/__init__.py +0 -1
  97. package/onecode/__main__.py +0 -4
  98. package/onecode/__pycache__/__init__.cpython-314.pyc +0 -0
  99. package/onecode/__pycache__/cli.cpython-314.pyc +0 -0
  100. package/onecode/__pycache__/commands.cpython-314.pyc +0 -0
  101. package/onecode/__pycache__/config.cpython-314.pyc +0 -0
  102. package/onecode/__pycache__/config_screen.cpython-314.pyc +0 -0
  103. package/onecode/__pycache__/migrate.cpython-314.pyc +0 -0
  104. package/onecode/agent/__init__.py +0 -0
  105. package/onecode/agent/__pycache__/__init__.cpython-314.pyc +0 -0
  106. package/onecode/agent/__pycache__/cdh_loader.cpython-314.pyc +0 -0
  107. package/onecode/agent/__pycache__/context.cpython-314.pyc +0 -0
  108. package/onecode/agent/__pycache__/engine.cpython-314.pyc +0 -0
  109. package/onecode/agent/__pycache__/hooks.cpython-314.pyc +0 -0
  110. package/onecode/agent/__pycache__/onecode_agent_acp.cpython-314.pyc +0 -0
  111. package/onecode/agent/__pycache__/permissions.cpython-314.pyc +0 -0
  112. package/onecode/agent/__pycache__/permissions_store.cpython-314.pyc +0 -0
  113. package/onecode/agent/__pycache__/project_doc.cpython-314.pyc +0 -0
  114. package/onecode/agent/__pycache__/session.cpython-314.pyc +0 -0
  115. package/onecode/agent/agents/__init__.py +0 -29
  116. package/onecode/agent/agents/__pycache__/__init__.cpython-314.pyc +0 -0
  117. package/onecode/agent/agents/__pycache__/types.cpython-314.pyc +0 -0
  118. package/onecode/agent/agents/types.py +0 -589
  119. package/onecode/agent/attachments.py +0 -112
  120. package/onecode/agent/cdh_loader.py +0 -267
  121. package/onecode/agent/context.py +0 -343
  122. package/onecode/agent/engine.py +0 -2700
  123. package/onecode/agent/hooks.py +0 -86
  124. package/onecode/agent/onecode_agent_acp.py +0 -2743
  125. package/onecode/agent/onecode_agent_acp.py.bak +0 -2447
  126. package/onecode/agent/permissions.py +0 -150
  127. package/onecode/agent/permissions_store.py +0 -62
  128. package/onecode/agent/project_doc.py +0 -19
  129. package/onecode/agent/session.py +0 -195
  130. package/onecode/agent/snapshot.py +0 -144
  131. package/onecode/agent/tools/__init__.py +0 -17
  132. package/onecode/agent/tools/__pycache__/__init__.cpython-314.pyc +0 -0
  133. package/onecode/agent/tools/__pycache__/agent_tools.cpython-314.pyc +0 -0
  134. package/onecode/agent/tools/__pycache__/apply_patch_tool.cpython-314.pyc +0 -0
  135. package/onecode/agent/tools/__pycache__/bash_tool.cpython-314.pyc +0 -0
  136. package/onecode/agent/tools/__pycache__/communication_tools.cpython-314.pyc +0 -0
  137. package/onecode/agent/tools/__pycache__/config_tool.cpython-314.pyc +0 -0
  138. package/onecode/agent/tools/__pycache__/cron_tools.cpython-314.pyc +0 -0
  139. package/onecode/agent/tools/__pycache__/errors.cpython-314.pyc +0 -0
  140. package/onecode/agent/tools/__pycache__/file_ops.cpython-314.pyc +0 -0
  141. package/onecode/agent/tools/__pycache__/file_tools.cpython-314.pyc +0 -0
  142. package/onecode/agent/tools/__pycache__/git_tools.cpython-314.pyc +0 -0
  143. package/onecode/agent/tools/__pycache__/lsp_tools.cpython-314.pyc +0 -0
  144. package/onecode/agent/tools/__pycache__/mcp_tools.cpython-314.pyc +0 -0
  145. package/onecode/agent/tools/__pycache__/permission_handler.cpython-314.pyc +0 -0
  146. package/onecode/agent/tools/__pycache__/permissions.cpython-314.pyc +0 -0
  147. package/onecode/agent/tools/__pycache__/protocol.cpython-314.pyc +0 -0
  148. package/onecode/agent/tools/__pycache__/registry.cpython-314.pyc +0 -0
  149. package/onecode/agent/tools/__pycache__/sandbox.cpython-314.pyc +0 -0
  150. package/onecode/agent/tools/__pycache__/schema_validation.cpython-314.pyc +0 -0
  151. package/onecode/agent/tools/__pycache__/skill_tools.cpython-314.pyc +0 -0
  152. package/onecode/agent/tools/__pycache__/todo_tools.cpython-314.pyc +0 -0
  153. package/onecode/agent/tools/__pycache__/web_tools.cpython-314.pyc +0 -0
  154. package/onecode/agent/tools/agent_tools.py +0 -132
  155. package/onecode/agent/tools/apply_patch_tool.py +0 -138
  156. package/onecode/agent/tools/bash_tool.py +0 -111
  157. package/onecode/agent/tools/communication_tools.py +0 -148
  158. package/onecode/agent/tools/config_tool.py +0 -130
  159. package/onecode/agent/tools/cron_tools.py +0 -178
  160. package/onecode/agent/tools/errors.py +0 -17
  161. package/onecode/agent/tools/file_ops.py +0 -221
  162. package/onecode/agent/tools/file_tools.py +0 -225
  163. package/onecode/agent/tools/git_tools.py +0 -88
  164. package/onecode/agent/tools/lsp_tools.py +0 -404
  165. package/onecode/agent/tools/mcp_tools.py +0 -127
  166. package/onecode/agent/tools/permission_handler.py +0 -46
  167. package/onecode/agent/tools/permissions.py +0 -77
  168. package/onecode/agent/tools/protocol.py +0 -20
  169. package/onecode/agent/tools/registry.py +0 -201
  170. package/onecode/agent/tools/sandbox.py +0 -358
  171. package/onecode/agent/tools/schema_validation.py +0 -100
  172. package/onecode/agent/tools/skill_tools.py +0 -52
  173. package/onecode/agent/tools/todo_tools.py +0 -207
  174. package/onecode/agent/tools/web_tools.py +0 -169
  175. package/onecode/builtin_skills/agent-browser/SKILL.md +0 -212
  176. package/onecode/builtin_skills/agent-browser/skill.yaml +0 -8
  177. package/onecode/builtin_skills/git/SKILL.md +0 -64
  178. package/onecode/builtin_skills/git/skill.yaml +0 -7
  179. package/onecode/builtin_skills/shell/SKILL.md +0 -58
  180. package/onecode/builtin_skills/shell/skill.yaml +0 -8
  181. package/onecode/builtin_skills/skill-creator/SKILL.md +0 -106
  182. package/onecode/builtin_skills/skill-creator/skill.yaml +0 -8
  183. package/onecode/cli.py +0 -935
  184. package/onecode/cloud/__init__.py +0 -0
  185. package/onecode/cloud/base.py +0 -20
  186. package/onecode/codebase/__init__.py +0 -69
  187. package/onecode/codebase/__pycache__/__init__.cpython-314.pyc +0 -0
  188. package/onecode/codebase/__pycache__/chunker.cpython-314.pyc +0 -0
  189. package/onecode/codebase/__pycache__/indexer.cpython-314.pyc +0 -0
  190. package/onecode/codebase/__pycache__/retriever.cpython-314.pyc +0 -0
  191. package/onecode/codebase/__pycache__/storage.cpython-314.pyc +0 -0
  192. package/onecode/codebase/__pycache__/tools.cpython-314.pyc +0 -0
  193. package/onecode/codebase/chunker.py +0 -125
  194. package/onecode/codebase/indexer.py +0 -149
  195. package/onecode/codebase/retriever.py +0 -203
  196. package/onecode/codebase/storage.py +0 -131
  197. package/onecode/codebase/tools.py +0 -59
  198. package/onecode/commands.py +0 -596
  199. package/onecode/config.py +0 -314
  200. package/onecode/config_screen.py +0 -600
  201. package/onecode/cron/__init__.py +0 -3
  202. package/onecode/lsp/__init__.py +0 -3
  203. package/onecode/mcp/__init__.py +0 -4
  204. package/onecode/mcp/__pycache__/__init__.cpython-314.pyc +0 -0
  205. package/onecode/mcp/__pycache__/client.cpython-314.pyc +0 -0
  206. package/onecode/mcp/__pycache__/manager.cpython-314.pyc +0 -0
  207. package/onecode/mcp/client.py +0 -193
  208. package/onecode/mcp/manager.py +0 -190
  209. package/onecode/memory/__init__.py +0 -49
  210. package/onecode/memory/__pycache__/__init__.cpython-314.pyc +0 -0
  211. package/onecode/memory/__pycache__/backend.cpython-314.pyc +0 -0
  212. package/onecode/memory/__pycache__/offload.cpython-314.pyc +0 -0
  213. package/onecode/memory/__pycache__/pyramid.cpython-314.pyc +0 -0
  214. package/onecode/memory/__pycache__/recall.cpython-314.pyc +0 -0
  215. package/onecode/memory/__pycache__/symbolic.cpython-314.pyc +0 -0
  216. package/onecode/memory/backend.py +0 -159
  217. package/onecode/memory/pyramid.py +0 -133
  218. package/onecode/memory/recall.py +0 -203
  219. package/onecode/migrate.py +0 -122
  220. package/onecode/models/__init__.py +0 -4
  221. package/onecode/models/__pycache__/__init__.cpython-314.pyc +0 -0
  222. package/onecode/models/__pycache__/errors.cpython-314.pyc +0 -0
  223. package/onecode/models/__pycache__/messages.cpython-314.pyc +0 -0
  224. package/onecode/models/__pycache__/provider.cpython-314.pyc +0 -0
  225. package/onecode/models/__pycache__/registry.cpython-314.pyc +0 -0
  226. package/onecode/models/errors.py +0 -104
  227. package/onecode/models/messages.py +0 -739
  228. package/onecode/models/provider.py +0 -699
  229. package/onecode/models/providers/__init__.py +0 -17
  230. package/onecode/models/providers/__pycache__/__init__.cpython-314.pyc +0 -0
  231. package/onecode/models/providers/__pycache__/anthropic_provider.cpython-314.pyc +0 -0
  232. package/onecode/models/providers/__pycache__/deepseek_provider.cpython-314.pyc +0 -0
  233. package/onecode/models/providers/__pycache__/glm_provider.cpython-314.pyc +0 -0
  234. package/onecode/models/providers/__pycache__/minimax_provider.cpython-314.pyc +0 -0
  235. package/onecode/models/providers/__pycache__/minimaxi_provider.cpython-314.pyc +0 -0
  236. package/onecode/models/providers/__pycache__/ollama_provider.cpython-314.pyc +0 -0
  237. package/onecode/models/providers/__pycache__/openai_provider.cpython-314.pyc +0 -0
  238. package/onecode/models/providers/anthropic_provider.py +0 -273
  239. package/onecode/models/providers/deepseek_provider.py +0 -212
  240. package/onecode/models/providers/glm_provider.py +0 -195
  241. package/onecode/models/providers/minimax_provider.py +0 -158
  242. package/onecode/models/providers/minimaxi_provider.py +0 -417
  243. package/onecode/models/providers/ollama_provider.py +0 -100
  244. package/onecode/models/providers/openai_provider.py +0 -237
  245. package/onecode/models/registry.py +0 -212
  246. package/onecode/server/__init__.py +0 -3
  247. package/onecode/server/app.py +0 -224
  248. package/onecode/skills/__init__.py +0 -11
  249. package/onecode/skills/__pycache__/__init__.cpython-314.pyc +0 -0
  250. package/onecode/skills/__pycache__/argument_substitution.cpython-314.pyc +0 -0
  251. package/onecode/skills/__pycache__/bootstrap.cpython-314.pyc +0 -0
  252. package/onecode/skills/__pycache__/create.cpython-314.pyc +0 -0
  253. package/onecode/skills/__pycache__/frontmatter.cpython-314.pyc +0 -0
  254. package/onecode/skills/__pycache__/loader.cpython-314.pyc +0 -0
  255. package/onecode/skills/__pycache__/manager.cpython-314.pyc +0 -0
  256. package/onecode/skills/__pycache__/model.cpython-314.pyc +0 -0
  257. package/onecode/skills/argument_substitution.py +0 -38
  258. package/onecode/skills/bootstrap.py +0 -124
  259. package/onecode/skills/create.py +0 -56
  260. package/onecode/skills/frontmatter.py +0 -33
  261. package/onecode/skills/loader.py +0 -139
  262. package/onecode/skills/manager.py +0 -75
  263. package/onecode/skills/model.py +0 -43
  264. package/onecode/storage/__init__.py +0 -0
  265. package/onecode/storage/activity.py +0 -63
  266. package/onecode/storage/project.py +0 -54
  267. package/onecode/storage/session.py +0 -112
  268. package/onecode/tasks/__init__.py +0 -26
  269. package/onecode/tasks/manager.py +0 -232
  270. package/onecode/tasks/models.py +0 -240
  271. package/onecode/trace/__init__.py +0 -0
  272. package/onecode/trace/tracer.py +0 -173
  273. package/onecode/utils/__init__.py +0 -0
  274. package/onecode/utils/helpers.py +0 -20
  275. package/pyproject.toml +0 -74
  276. package/tui/__init__.py +0 -46
  277. package/tui/__main__.py +0 -4
  278. package/tui/__pycache__/__init__.cpython-314.pyc +0 -0
  279. package/tui/__pycache__/_loop.cpython-314.pyc +0 -0
  280. package/tui/__pycache__/_path_fuzzy_search.cpython-314.pyc +0 -0
  281. package/tui/__pycache__/_path_match.cpython-314.pyc +0 -0
  282. package/tui/__pycache__/about.cpython-314.pyc +0 -0
  283. package/tui/__pycache__/agent.cpython-314.pyc +0 -0
  284. package/tui/__pycache__/agent_schema.cpython-314.pyc +0 -0
  285. package/tui/__pycache__/agents.cpython-314.pyc +0 -0
  286. package/tui/__pycache__/answer.cpython-314.pyc +0 -0
  287. package/tui/__pycache__/app.cpython-313.pyc +0 -0
  288. package/tui/__pycache__/app.cpython-314.pyc +0 -0
  289. package/tui/__pycache__/atomic.cpython-314.pyc +0 -0
  290. package/tui/__pycache__/complete.cpython-314.pyc +0 -0
  291. package/tui/__pycache__/constants.cpython-314.pyc +0 -0
  292. package/tui/__pycache__/conversation_markdown.cpython-314.pyc +0 -0
  293. package/tui/__pycache__/danger.cpython-314.pyc +0 -0
  294. package/tui/__pycache__/db.cpython-314.pyc +0 -0
  295. package/tui/__pycache__/dec.cpython-314.pyc +0 -0
  296. package/tui/__pycache__/directory.cpython-314.pyc +0 -0
  297. package/tui/__pycache__/directory_suggester.cpython-314.pyc +0 -0
  298. package/tui/__pycache__/directory_watcher.cpython-314.pyc +0 -0
  299. package/tui/__pycache__/format_path.cpython-314.pyc +0 -0
  300. package/tui/__pycache__/fuzzy.cpython-314.pyc +0 -0
  301. package/tui/__pycache__/fuzzy_index.cpython-314.pyc +0 -0
  302. package/tui/__pycache__/history.cpython-314.pyc +0 -0
  303. package/tui/__pycache__/jsonrpc.cpython-314.pyc +0 -0
  304. package/tui/__pycache__/menus.cpython-314.pyc +0 -0
  305. package/tui/__pycache__/message_log.cpython-314.pyc +0 -0
  306. package/tui/__pycache__/messages.cpython-314.pyc +0 -0
  307. package/tui/__pycache__/path_complete.cpython-314.pyc +0 -0
  308. package/tui/__pycache__/path_filter.cpython-314.pyc +0 -0
  309. package/tui/__pycache__/paths.cpython-314.pyc +0 -0
  310. package/tui/__pycache__/pill.cpython-314.pyc +0 -0
  311. package/tui/__pycache__/platform_commands.cpython-314.pyc +0 -0
  312. package/tui/__pycache__/protocol.cpython-314.pyc +0 -0
  313. package/tui/__pycache__/session_tracker.cpython-314.pyc +0 -0
  314. package/tui/__pycache__/settings.cpython-314.pyc +0 -0
  315. package/tui/__pycache__/settings_schema.cpython-314.pyc +0 -0
  316. package/tui/__pycache__/shell.cpython-314.pyc +0 -0
  317. package/tui/__pycache__/shell_read.cpython-314.pyc +0 -0
  318. package/tui/__pycache__/slash_command.cpython-314.pyc +0 -0
  319. package/tui/__pycache__/version.cpython-314.pyc +0 -0
  320. package/tui/_loop.py +0 -86
  321. package/tui/_path_fuzzy_search.py +0 -48
  322. package/tui/_path_match.py +0 -141
  323. package/tui/about.py +0 -95
  324. package/tui/acp/__pycache__/agent.cpython-314.pyc +0 -0
  325. package/tui/acp/__pycache__/api.cpython-314.pyc +0 -0
  326. package/tui/acp/__pycache__/encode_tool_call_id.cpython-314.pyc +0 -0
  327. package/tui/acp/__pycache__/messages.cpython-314.pyc +0 -0
  328. package/tui/acp/__pycache__/prompt.cpython-314.pyc +0 -0
  329. package/tui/acp/__pycache__/protocol.cpython-314.pyc +0 -0
  330. package/tui/acp/agent.py +0 -1002
  331. package/tui/acp/api.py +0 -73
  332. package/tui/acp/encode_tool_call_id.py +0 -12
  333. package/tui/acp/messages.py +0 -203
  334. package/tui/acp/prompt.py +0 -53
  335. package/tui/acp/protocol.py +0 -499
  336. package/tui/agent.py +0 -70
  337. package/tui/agent_schema.py +0 -76
  338. package/tui/agents.py +0 -46
  339. package/tui/ansi/__init__.py +0 -1
  340. package/tui/ansi/__pycache__/__init__.cpython-314.pyc +0 -0
  341. package/tui/ansi/__pycache__/_ansi.cpython-314.pyc +0 -0
  342. package/tui/ansi/__pycache__/_ansi_colors.cpython-314.pyc +0 -0
  343. package/tui/ansi/__pycache__/_control_codes.cpython-314.pyc +0 -0
  344. package/tui/ansi/__pycache__/_keys.cpython-314.pyc +0 -0
  345. package/tui/ansi/__pycache__/_sgr_styles.cpython-314.pyc +0 -0
  346. package/tui/ansi/__pycache__/_stream_parser.cpython-314.pyc +0 -0
  347. package/tui/ansi/_ansi.py +0 -1689
  348. package/tui/ansi/_ansi_colors.py +0 -264
  349. package/tui/ansi/_control_codes.py +0 -37
  350. package/tui/ansi/_keys.py +0 -251
  351. package/tui/ansi/_sgr_styles.py +0 -64
  352. package/tui/ansi/_stream_parser.py +0 -418
  353. package/tui/answer.py +0 -12
  354. package/tui/app.py +0 -1266
  355. package/tui/atomic.py +0 -37
  356. package/tui/cli.py +0 -313
  357. package/tui/code_analyze.py +0 -27
  358. package/tui/complete.py +0 -38
  359. package/tui/constants.py +0 -61
  360. package/tui/conversation_markdown.py +0 -30
  361. package/tui/danger.py +0 -372
  362. package/tui/data/agents/ampcode.com.toml +0 -52
  363. package/tui/data/agents/augmentcode.com.toml +0 -41
  364. package/tui/data/agents/cdh.cloud-dev-harness.toml +0 -23
  365. package/tui/data/agents/claude.com.toml +0 -41
  366. package/tui/data/agents/copilot.github.com.toml +0 -29
  367. package/tui/data/agents/crowai.dev.toml +0 -36
  368. package/tui/data/agents/cursor.com.toml +0 -38
  369. package/tui/data/agents/deepagents.langchain.com +0 -34
  370. package/tui/data/agents/docker.com.toml +0 -60
  371. package/tui/data/agents/geminicli.com.toml +0 -28
  372. package/tui/data/agents/goose.ai.toml +0 -52
  373. package/tui/data/agents/inference.huggingface.co.toml +0 -41
  374. package/tui/data/agents/kimi.com.toml +0 -35
  375. package/tui/data/agents/kiro.dev.toml +0 -43
  376. package/tui/data/agents/onecode.dev.toml +0 -22
  377. package/tui/data/agents/openai.com.toml +0 -53
  378. package/tui/data/agents/openclaw.ai.toml +0 -37
  379. package/tui/data/agents/opencode.ai.toml +0 -39
  380. package/tui/data/agents/openhands.dev.toml +0 -46
  381. package/tui/data/agents/stakpak.dev.toml +0 -62
  382. package/tui/data/agents/vibe.mistral.ai.toml +0 -31
  383. package/tui/data/agents/vtcode.dev.toml +0 -63
  384. package/tui/data/images/frog.png +0 -0
  385. package/tui/data/sounds/question.wav +0 -0
  386. package/tui/data/sounds/turn-over.wav +0 -0
  387. package/tui/db.py +0 -213
  388. package/tui/dec.py +0 -332
  389. package/tui/directory.py +0 -234
  390. package/tui/directory_suggester.py +0 -93
  391. package/tui/directory_watcher.py +0 -231
  392. package/tui/format_path.py +0 -25
  393. package/tui/fuzzy.py +0 -140
  394. package/tui/fuzzy_index.py +0 -275
  395. package/tui/gist.py +0 -33
  396. package/tui/history.py +0 -138
  397. package/tui/jsonrpc.py +0 -578
  398. package/tui/menus.py +0 -14
  399. package/tui/message_log.py +0 -69
  400. package/tui/messages.py +0 -144
  401. package/tui/option_content.py +0 -51
  402. package/tui/os.py +0 -0
  403. package/tui/path_complete.py +0 -217
  404. package/tui/path_filter.py +0 -124
  405. package/tui/paths.py +0 -87
  406. package/tui/pill.py +0 -23
  407. package/tui/platform_commands.py +0 -52
  408. package/tui/prompt/__pycache__/extract.cpython-314.pyc +0 -0
  409. package/tui/prompt/__pycache__/resource.cpython-314.pyc +0 -0
  410. package/tui/prompt/extract.py +0 -19
  411. package/tui/prompt/resource.py +0 -68
  412. package/tui/protocol.py +0 -28
  413. package/tui/screens/__init__.py +0 -0
  414. package/tui/screens/__pycache__/__init__.cpython-314.pyc +0 -0
  415. package/tui/screens/__pycache__/agent_modal.cpython-314.pyc +0 -0
  416. package/tui/screens/__pycache__/component_picker.cpython-314.pyc +0 -0
  417. package/tui/screens/__pycache__/diff_screen.cpython-314.pyc +0 -0
  418. package/tui/screens/__pycache__/log.cpython-314.pyc +0 -0
  419. package/tui/screens/__pycache__/main.cpython-313.pyc +0 -0
  420. package/tui/screens/__pycache__/main.cpython-314.pyc +0 -0
  421. package/tui/screens/__pycache__/permissions.cpython-314.pyc +0 -0
  422. package/tui/screens/__pycache__/projects_app.cpython-314.pyc +0 -0
  423. package/tui/screens/__pycache__/projects_screen.cpython-314.pyc +0 -0
  424. package/tui/screens/__pycache__/sessions.cpython-314.pyc +0 -0
  425. package/tui/screens/__pycache__/store.cpython-314.pyc +0 -0
  426. package/tui/screens/__pycache__/tool_content_screen.cpython-314.pyc +0 -0
  427. package/tui/screens/action_modal.py +0 -94
  428. package/tui/screens/agent_modal.py +0 -175
  429. package/tui/screens/command_edit_modal.py +0 -74
  430. package/tui/screens/component_picker.py +0 -168
  431. package/tui/screens/diff_screen.py +0 -84
  432. package/tui/screens/log.py +0 -553
  433. package/tui/screens/main.py +0 -385
  434. package/tui/screens/main.tcss +0 -655
  435. package/tui/screens/permissions.py +0 -404
  436. package/tui/screens/permissions.tcss +0 -72
  437. package/tui/screens/projects.tcss +0 -80
  438. package/tui/screens/projects_app.py +0 -347
  439. package/tui/screens/projects_screen.py +0 -284
  440. package/tui/screens/session_resume_modal.py +0 -172
  441. package/tui/screens/session_resume_modal.tcss +0 -35
  442. package/tui/screens/sessions.py +0 -164
  443. package/tui/screens/sessions.tcss +0 -119
  444. package/tui/screens/settings.py +0 -254
  445. package/tui/screens/settings.tcss +0 -101
  446. package/tui/screens/store.py +0 -500
  447. package/tui/screens/store.tcss +0 -274
  448. package/tui/screens/tool_content_screen.py +0 -59
  449. package/tui/session_tracker.py +0 -123
  450. package/tui/settings.py +0 -353
  451. package/tui/settings_schema.py +0 -431
  452. package/tui/shell.py +0 -304
  453. package/tui/shell_read.py +0 -42
  454. package/tui/slash_command.py +0 -34
  455. package/tui/tui.tcss +0 -246
  456. package/tui/twitter.py +0 -38
  457. package/tui/version.py +0 -80
  458. package/tui/visuals/__init__.py +0 -0
  459. package/tui/visuals/__pycache__/__init__.cpython-314.pyc +0 -0
  460. package/tui/visuals/__pycache__/columns.cpython-314.pyc +0 -0
  461. package/tui/visuals/columns.py +0 -272
  462. package/tui/widgets/__init__.py +0 -0
  463. package/tui/widgets/__pycache__/__init__.cpython-314.pyc +0 -0
  464. package/tui/widgets/__pycache__/acp_content.cpython-314.pyc +0 -0
  465. package/tui/widgets/__pycache__/agent_response.cpython-314.pyc +0 -0
  466. package/tui/widgets/__pycache__/agent_thought.cpython-314.pyc +0 -0
  467. package/tui/widgets/__pycache__/ask_user.cpython-314.pyc +0 -0
  468. package/tui/widgets/__pycache__/condensed_path.cpython-314.pyc +0 -0
  469. package/tui/widgets/__pycache__/context_stats.cpython-314.pyc +0 -0
  470. package/tui/widgets/__pycache__/conversation.cpython-314.pyc +0 -0
  471. package/tui/widgets/__pycache__/diff_view.cpython-314.pyc +0 -0
  472. package/tui/widgets/__pycache__/directory_input.cpython-314.pyc +0 -0
  473. package/tui/widgets/__pycache__/flash.cpython-314.pyc +0 -0
  474. package/tui/widgets/__pycache__/future_text.cpython-314.pyc +0 -0
  475. package/tui/widgets/__pycache__/grid_select.cpython-314.pyc +0 -0
  476. package/tui/widgets/__pycache__/highlighted_textarea.cpython-314.pyc +0 -0
  477. package/tui/widgets/__pycache__/load_more.cpython-314.pyc +0 -0
  478. package/tui/widgets/__pycache__/mandelbrot.cpython-314.pyc +0 -0
  479. package/tui/widgets/__pycache__/markdown_note.cpython-314.pyc +0 -0
  480. package/tui/widgets/__pycache__/menu.cpython-314.pyc +0 -0
  481. package/tui/widgets/__pycache__/modified_files.cpython-314.pyc +0 -0
  482. package/tui/widgets/__pycache__/non_selectable_label.cpython-314.pyc +0 -0
  483. package/tui/widgets/__pycache__/note.cpython-314.pyc +0 -0
  484. package/tui/widgets/__pycache__/path_search.cpython-314.pyc +0 -0
  485. package/tui/widgets/__pycache__/plan.cpython-314.pyc +0 -0
  486. package/tui/widgets/__pycache__/project_directory_tree.cpython-314.pyc +0 -0
  487. package/tui/widgets/__pycache__/project_grid_select.cpython-314.pyc +0 -0
  488. package/tui/widgets/__pycache__/project_summary.cpython-314.pyc +0 -0
  489. package/tui/widgets/__pycache__/prompt.cpython-314.pyc +0 -0
  490. package/tui/widgets/__pycache__/question.cpython-314.pyc +0 -0
  491. package/tui/widgets/__pycache__/session_grid_select.cpython-314.pyc +0 -0
  492. package/tui/widgets/__pycache__/session_summary.cpython-314.pyc +0 -0
  493. package/tui/widgets/__pycache__/session_tabs.cpython-314.pyc +0 -0
  494. package/tui/widgets/__pycache__/shell_result.cpython-314.pyc +0 -0
  495. package/tui/widgets/__pycache__/shell_terminal.cpython-314.pyc +0 -0
  496. package/tui/widgets/__pycache__/side_bar.cpython-314.pyc +0 -0
  497. package/tui/widgets/__pycache__/slash_complete.cpython-314.pyc +0 -0
  498. package/tui/widgets/__pycache__/strike_text.cpython-314.pyc +0 -0
  499. package/tui/widgets/__pycache__/subagent.cpython-314.pyc +0 -0
  500. package/tui/widgets/__pycache__/subagent_screen.cpython-314.pyc +0 -0
  501. package/tui/widgets/__pycache__/terminal.cpython-314.pyc +0 -0
  502. package/tui/widgets/__pycache__/throbber.cpython-314.pyc +0 -0
  503. package/tui/widgets/__pycache__/tool_call.cpython-314.pyc +0 -0
  504. package/tui/widgets/__pycache__/user_input.cpython-314.pyc +0 -0
  505. package/tui/widgets/acp_content.py +0 -70
  506. package/tui/widgets/agent_response.py +0 -76
  507. package/tui/widgets/agent_thought.py +0 -167
  508. package/tui/widgets/ask_user.py +0 -264
  509. package/tui/widgets/command_pane.py +0 -223
  510. package/tui/widgets/condensed_path.py +0 -115
  511. package/tui/widgets/context_stats.py +0 -66
  512. package/tui/widgets/conversation.py +0 -2641
  513. package/tui/widgets/danger_warning.py +0 -65
  514. package/tui/widgets/diff_view.py +0 -69
  515. package/tui/widgets/directory_input.py +0 -8
  516. package/tui/widgets/flash.py +0 -81
  517. package/tui/widgets/future_text.py +0 -126
  518. package/tui/widgets/grid_select.py +0 -234
  519. package/tui/widgets/highlighted_textarea.py +0 -180
  520. package/tui/widgets/load_more.py +0 -24
  521. package/tui/widgets/mandelbrot.py +0 -294
  522. package/tui/widgets/markdown_note.py +0 -13
  523. package/tui/widgets/menu.py +0 -147
  524. package/tui/widgets/modified_files.py +0 -306
  525. package/tui/widgets/non_selectable_label.py +0 -5
  526. package/tui/widgets/note.py +0 -18
  527. package/tui/widgets/path_search.py +0 -492
  528. package/tui/widgets/plan.py +0 -285
  529. package/tui/widgets/project_directory_tree.py +0 -102
  530. package/tui/widgets/project_grid_select.py +0 -64
  531. package/tui/widgets/project_summary.py +0 -33
  532. package/tui/widgets/prompt.py +0 -795
  533. package/tui/widgets/question.py +0 -360
  534. package/tui/widgets/session_grid_select.py +0 -230
  535. package/tui/widgets/session_summary.py +0 -115
  536. package/tui/widgets/session_tabs.py +0 -188
  537. package/tui/widgets/shell_result.py +0 -35
  538. package/tui/widgets/shell_terminal.py +0 -40
  539. package/tui/widgets/side_bar.py +0 -124
  540. package/tui/widgets/slash_complete.py +0 -235
  541. package/tui/widgets/strike_text.py +0 -70
  542. package/tui/widgets/subagent.py +0 -287
  543. package/tui/widgets/subagent_screen.py +0 -709
  544. package/tui/widgets/terminal.py +0 -576
  545. package/tui/widgets/terminal_tool.py +0 -360
  546. package/tui/widgets/throbber.py +0 -100
  547. package/tui/widgets/tool_call.py +0 -398
  548. package/tui/widgets/user_input.py +0 -23
  549. package/tui/widgets/version.py +0 -5
  550. package/tui/widgets/welcome.py +0 -31
@@ -1,709 +0,0 @@
1
- from __future__ import annotations
2
-
3
- import asyncio
4
- import logging
5
- from pathlib import Path
6
- from typing import ClassVar
7
-
8
- from textual import on
9
- from textual.app import ComposeResult
10
- from textual.binding import Binding, BindingType
11
- from textual.containers import Grid, Vertical, VerticalGroup, VerticalScroll
12
- from textual.css.query import NoMatches
13
- from textual.geometry import Offset, Region, Spacing
14
- from textual.layouts.grid import GridLayout
15
- from textual.layouts.vertical import WidgetPlacement
16
- from textual.reactive import reactive
17
- from textual.screen import Screen
18
- from textual.widget import Widget
19
- from textual.widgets import Header, Static
20
-
21
- from rich.segment import Segment
22
- from textual.strip import Strip
23
-
24
- from tui.menus import MenuItem
25
- from tui.protocol import BlockProtocol, ExpandProtocol, MenuProtocol
26
- from tui.widgets.agent_response import AgentResponse
27
- from tui.widgets.agent_thought import AgentThought
28
- from tui.widgets.conversation import Cursor
29
- from tui.widgets.menu import Menu
30
- from tui.widgets.subagent import SubAgent
31
- from tui.widgets.tool_call import ToolCall as ToolCallWidget
32
-
33
- _sa_logger = logging.getLogger("tui.widgets.subagent_screen")
34
- _DEBUG_LOG = Path.home() / ".cdh" / "logs" / "subagent_cursor_debug.log"
35
-
36
- _TODO_TOOLS: frozenset[str] = frozenset({
37
- "TodoCreate", "TodoGet", "TodoList", "TodoUpdate",
38
- "TodoOutput", "TodoStop", "TodoClear",
39
- })
40
-
41
- _SELECTABLE_BLOCK_TYPES: tuple[type[Widget], ...] = (
42
- AgentResponse,
43
- AgentThought,
44
- ToolCallWidget,
45
- )
46
-
47
-
48
- def _is_selectable(child: Widget) -> bool:
49
- return isinstance(child, _SELECTABLE_BLOCK_TYPES)
50
-
51
-
52
- class SubAgentCursorContainer(Vertical):
53
- def render_lines(self, crop: Region) -> list[Strip]:
54
- rich_style = self.visual_style.rich_style
55
- strips = [Strip([Segment("▌", rich_style)], cell_length=1)] * crop.height
56
- if crop.y == 0 and strips:
57
- strips[0] = Strip([Segment(" ", rich_style)], cell_length=1)
58
- return strips
59
-
60
-
61
- class SubAgentContentsGrid(Grid):
62
- BLANK = True
63
-
64
- def pre_layout(self, layout) -> None:
65
- assert isinstance(layout, GridLayout)
66
- layout.stretch_height = True
67
-
68
-
69
- class SubAgentScreen(Screen):
70
- """Full-screen view of a SubAgent output.
71
-
72
- Renders identically to the main Conversation:
73
- - AgentResponse for streaming text (MarkdownStream)
74
- - ToolCall cards mounted inline between text blocks
75
- - AgentThought (thinking) as inline siblings at position of occurrence
76
- - All widgets as siblings in a single #content container
77
- - Vertical-bar block cursor in a left-side CursorContainer, matching
78
- Conversation's visual treatment.
79
-
80
- Mirrors Conversation's block cursor: Ctrl+J/K move between blocks,
81
- Enter opens a Menu (copy / maximize), Ctrl+X toggles expand/collapse
82
- on ExpandProtocol blocks.
83
- """
84
-
85
- BINDINGS: ClassVar[list[BindingType]] = [
86
- Binding("escape", "app.pop_screen", "Back", priority=True),
87
- Binding("ctrl+j", "cursor_down", "Next block", show=False, priority=True),
88
- Binding("ctrl+k", "cursor_up", "Prev block", show=False, priority=True),
89
- Binding("enter", "select_block", "Block menu", show=False, priority=True),
90
- Binding("ctrl+x", "toggle_expand", "Toggle expand", show=False, priority=True),
91
- Binding("up", "scroll_up", "Up", priority=True),
92
- Binding("down", "scroll_down", "Down", priority=True),
93
- Binding("pageup", "scroll_page_up", "Page Up", priority=True),
94
- Binding("pagedown", "scroll_page_down", "Page Down", priority=True),
95
- Binding("home", "scroll_home", "Home", priority=True),
96
- Binding("end", "scroll_end", "End", priority=True),
97
- ]
98
-
99
- DEFAULT_CSS = """
100
- SubAgentScreen {
101
- background: $surface;
102
- padding-left: 1;
103
- }
104
-
105
- #scroll {
106
- height: 1fr;
107
- overflow-y: auto;
108
- scrollbar-gutter: stable;
109
- }
110
-
111
- #content-grid {
112
- layout: grid;
113
- grid-size: 2 1;
114
- grid-columns: 1 1fr;
115
- grid-gutter: 0;
116
- height: auto;
117
- width: 1fr;
118
- }
119
-
120
- #cursor-container {
121
- width: 1;
122
- height: auto;
123
- color: $foreground 7%;
124
- }
125
-
126
- #cursor-container > Cursor {
127
- height: 0;
128
- width: 1;
129
- border-left: outer $text-accent;
130
- visibility: visible;
131
- &.-blink {
132
- border-left: outer $text-accent 20%;
133
- }
134
- }
135
-
136
- #content {
137
- layout: stream;
138
- width: 1fr;
139
- overflow: hidden;
140
- height: auto;
141
- padding: 0 0 0 0;
142
- }
143
-
144
- #content > AgentResponse {
145
- min-height: 1;
146
- padding: 0 0 0 0;
147
- overflow-x: auto;
148
- scrollbar-size-horizontal: 0;
149
- layout: stream;
150
- }
151
-
152
- #content > ToolCall {
153
- margin: 0 0 0 1 !important;
154
- width: 1fr;
155
- layout: stream;
156
- height: auto;
157
- }
158
-
159
- #content > AgentThought {
160
- margin: 1 1 1 0;
161
- }
162
-
163
- #content > ToolCall ToolCallHeader {
164
- color: $text-secondary;
165
- pointer: pointer;
166
- width: auto;
167
- max-width: 1fr;
168
- margin: 0 1 0 0;
169
- text-wrap: nowrap;
170
- text-overflow: ellipsis;
171
- }
172
-
173
- #content > ToolCall #tool-content {
174
- display: none;
175
- }
176
-
177
- #content > ToolCall.-has-content #tool-content {
178
- margin: 1 1 1 0;
179
- }
180
-
181
- #content > ToolCall.-expanded #tool-content {
182
- display: block;
183
- max-height: 60vh;
184
- overflow-y: hidden;
185
- }
186
-
187
- #content > ToolCall.-expanded ToolCallHeader {
188
- text-wrap: wrap;
189
- text-overflow: fold;
190
- }
191
-
192
- #content > AgentResponse > MarkdownBlock:last-child,
193
- #content > AgentThought > #thought-content MarkdownBlock:last-child {
194
- margin-bottom: 0;
195
- }
196
-
197
- #footer {
198
- dock: bottom;
199
- height: 1;
200
- padding: 0 1;
201
- color: $text-muted;
202
- background: $boost;
203
- }
204
- """
205
-
206
- class Content(VerticalGroup, can_focus=False):
207
- """Matches Conversation.Contents — strips bottom margin from last child."""
208
-
209
- def process_layout(
210
- self, placements: list[WidgetPlacement]
211
- ) -> list[WidgetPlacement]:
212
- if placements:
213
- last = placements[-1]
214
- top, right, _bottom, left = last.margin
215
- placements[-1] = last._replace(
216
- margin=Spacing(top, right, 0, left)
217
- )
218
- return placements
219
-
220
- cursor_offset: reactive[int] = reactive(-1)
221
-
222
- def __init__(self, subagent: SubAgent) -> None:
223
- super().__init__()
224
- _DEBUG_LOG.parent.mkdir(parents=True, exist_ok=True)
225
- _sa_logger.addHandler(logging.FileHandler(str(_DEBUG_LOG), mode="w"))
226
- _sa_logger.setLevel(logging.DEBUG)
227
- self.subagent = subagent
228
- self._event_lock = asyncio.Lock()
229
- self._current_response: AgentResponse | None = None
230
- self._current_thought: AgentThought | None = None
231
- self._auto_follow = True
232
- self._active_menu: Menu | None = None
233
-
234
- def compose(self) -> ComposeResult:
235
- yield Header(show_clock=False)
236
- with VerticalScroll(id="scroll"):
237
- with SubAgentContentsGrid(id="content-grid"):
238
- with SubAgentCursorContainer(id="cursor-container"):
239
- yield Cursor()
240
- yield self.Content(id="content")
241
- yield Static(
242
- "[$text-muted]esc[/] 返回 "
243
- "[$text-muted]ctrl+j/k[/] 移动 "
244
- "[$text-muted]enter[/] 菜单 "
245
- "[$text-muted]ctrl+x[/] 折叠 "
246
- "[$text-muted]↑↓[/] 滚动",
247
- id="footer",
248
- )
249
-
250
- # ── Lifecycle ──
251
-
252
- async def on_mount(self) -> None:
253
- # Subscribe first so we don't miss events during replay
254
- self.subagent._screen_handler = self._on_event
255
- # Replay all existing events with yields so the UI can render progressively
256
- await self._replay_all()
257
- try:
258
- self.query_one("#scroll", VerticalScroll).focus()
259
- except Exception:
260
- pass
261
-
262
- def on_unmount(self) -> None:
263
- self.subagent._screen_handler = None
264
- self._current_response = None
265
- self._current_thought = None
266
-
267
- def check_action(self, action: str, parameters: tuple[object, ...]) -> bool | None:
268
- if self._active_menu is not None and action in (
269
- "select_block",
270
- "scroll_up",
271
- "scroll_down",
272
- "scroll_page_up",
273
- "scroll_page_down",
274
- "scroll_home",
275
- "scroll_end",
276
- "app.pop_screen",
277
- ):
278
- return False
279
- return True
280
-
281
- # ── Event processing ──
282
-
283
- async def _replay_all(self) -> None:
284
- """Process every event already in ``subagent._events``.
285
-
286
- Each event is followed by ``await asyncio.sleep(0)`` so the layout
287
- can settle between mounts – this avoids a long blocking stall
288
- before the screen becomes visible.
289
- """
290
- try:
291
- container = self.query_one("#content", VerticalGroup)
292
- for event_type, data in self.subagent._events:
293
- await self._handle_one(container, event_type, data)
294
- await asyncio.sleep(0)
295
- await self._flush_streams()
296
- self._post_process()
297
- except Exception:
298
- _sa_logger.exception("_replay_all failed")
299
-
300
- async def _on_event(self, event_type: str, data) -> None:
301
- """Handle a single real-time event from the SubAgent.
302
-
303
- Called via ``run_worker`` inside ``SubAgent.*`` methods.
304
- The lock serialises concurrently-scheduled workers.
305
- """
306
- async with self._event_lock:
307
- try:
308
- container = self.query_one("#content", VerticalGroup)
309
- await self._handle_one(container, event_type, data)
310
- self._post_process()
311
- except Exception:
312
- _sa_logger.exception("_on_event failed")
313
-
314
- async def _handle_one(self, container: VerticalGroup, event_type: str, data) -> None:
315
- """Dispatch a single event to the appropriate handler."""
316
- if event_type == "thinking":
317
- await self._handle_thinking(container, data)
318
- elif event_type == "text":
319
- self._complete_current_thought()
320
- await self._handle_text(container, data)
321
- elif event_type == "tool":
322
- self._complete_current_thought()
323
- await self._handle_tool(container, data)
324
- elif event_type == "complete":
325
- self._complete_current_thought()
326
-
327
- def _post_process(self) -> None:
328
- """Common work after every event – title, footer, cursor, scroll."""
329
- try:
330
- if self._current_thought is not None and not self._current_thought._completed:
331
- if self.subagent._status in ("completed", "failed"):
332
- self._current_thought.mark_completed()
333
- self._current_thought = None
334
- self._update_title()
335
- self._update_footer()
336
- self._refresh_block_cursor()
337
- if self._auto_follow:
338
- self.call_after_refresh(self._scroll_to_end)
339
- except Exception:
340
- _sa_logger.exception("_post_process failed")
341
-
342
- async def _handle_thinking(self, container: VerticalGroup, fragment: str) -> None:
343
- if self._current_thought is None:
344
- self._current_thought = AgentThought(fragment)
345
- await container.mount(self._current_thought)
346
- else:
347
- await self._current_thought.append_fragment(fragment)
348
-
349
- async def _handle_text(self, container: VerticalGroup, fragment: str) -> None:
350
- if self._current_response is None:
351
- self._current_response = AgentResponse("")
352
- await container.mount(self._current_response)
353
- await self._current_response.append_fragment(fragment)
354
-
355
- async def _handle_tool(self, container: VerticalGroup, data) -> None:
356
- tool_id, tc = data
357
- self._current_response = None
358
-
359
- # Skip todo tool calls — not relevant in subagent view
360
- title = tc.get("title", "") if isinstance(tc, dict) else ""
361
- tool_name = title.split(":")[0] if ":" in title else title
362
- if tool_name in _TODO_TOOLS:
363
- return
364
-
365
- scr_id = f"scr-{tool_id}"
366
- try:
367
- existing: ToolCallWidget = container.get_child_by_id(scr_id) # type: ignore[assignment]
368
- await existing.update_tool_call(tc)
369
- except NoMatches:
370
- await container.mount(ToolCallWidget(tc, id=scr_id))
371
- except Exception:
372
- _sa_logger.exception("_handle_tool failed %s", tool_id)
373
-
374
- def _complete_current_thought(self) -> None:
375
- if self._current_thought is not None and not self._current_thought._completed:
376
- self._current_thought.mark_completed()
377
- self._current_thought = None
378
-
379
- def _scroll_to_end(self) -> None:
380
- try:
381
- self.query_one("#scroll", VerticalScroll).scroll_end(animate=True)
382
- except Exception:
383
- pass
384
-
385
- async def _flush_streams(self) -> None:
386
- """Ensure all markdown streams have finished processing before cursor navigation."""
387
- try:
388
- container = self.query_one("#content", VerticalGroup)
389
- except Exception:
390
- return
391
- for child in container.children:
392
- stream = getattr(child, "_stream", None)
393
- if stream is not None:
394
- _sa_logger.warning(
395
- "▓ flush stream | widget=%s | task_alive=%s",
396
- type(child).__name__,
397
- stream._task is not None and not stream._task.done() if stream._task else False,
398
- )
399
- try:
400
- await stream.stop()
401
- except Exception:
402
- pass
403
- else:
404
- _sa_logger.warning(
405
- "▓ no stream | widget=%s | children=%s",
406
- type(child).__name__,
407
- len(child.children) if hasattr(child, 'children') else '?',
408
- )
409
-
410
- # ── Block cursor ──
411
-
412
- def _selectable_children(self) -> list[Widget]:
413
- try:
414
- container = self.query_one("#content", VerticalGroup)
415
- except Exception:
416
- return []
417
- return [child for child in container.children if _is_selectable(child)]
418
-
419
- @property
420
- def cursor_block(self) -> Widget | None:
421
- if self.cursor_offset == -1:
422
- return None
423
- children = self._selectable_children()
424
- if not children or self.cursor_offset >= len(children):
425
- return None
426
- return children[self.cursor_offset]
427
-
428
- @property
429
- def cursor_block_child(self) -> Widget | None:
430
- if (block := self.cursor_block) is not None:
431
- if isinstance(block, BlockProtocol):
432
- inner = block.get_cursor_block()
433
- if inner is not None:
434
- _sa_logger.warning(
435
- "┃ child inner=%s children=%s attached=%s",
436
- type(inner).__name__,
437
- len(block.children) if hasattr(block, 'children') else '?',
438
- inner.is_attached,
439
- )
440
- return inner
441
- _sa_logger.warning(
442
- "┃ child fallback → outer=%s children=%s",
443
- type(block).__name__,
444
- len(block.children) if hasattr(block, 'children') else '?',
445
- )
446
- return block
447
-
448
- def _cursor_widget(self) -> Cursor | None:
449
- try:
450
- return self.query_one("#cursor-container Cursor", Cursor)
451
- except Exception:
452
- return None
453
-
454
- def _content_region(self) -> Region | None:
455
- try:
456
- return self.query_one("#content", VerticalGroup).content_region
457
- except Exception:
458
- return None
459
-
460
- def _refresh_block_cursor(self) -> None:
461
- cursor = self._cursor_widget()
462
- if cursor is None:
463
- return
464
- block = self.cursor_block_child
465
- if block is not None:
466
- cursor.visible = True
467
- cursor.follow(block)
468
- _sa_logger.warning(
469
- "┃ follow | block=%s | offset=(%s,%s) | h=%s | visible=%s",
470
- type(block).__name__,
471
- cursor.offset.x, cursor.offset.y,
472
- cursor.styles.height,
473
- cursor.visible,
474
- )
475
- scroll = self._scroll_widget()
476
- if scroll is not None:
477
- scroll.focus()
478
- self.call_after_refresh(
479
- scroll.scroll_to_center, block, immediate=True
480
- )
481
- else:
482
- cursor.visible = False
483
- cursor.follow(None)
484
- self.refresh_bindings()
485
-
486
- def action_cursor_up(self) -> None:
487
- children = self._selectable_children()
488
- _sa_logger.warning(
489
- "▲ cursor_up | offset=%s | num_children=%s | types=%s",
490
- self.cursor_offset,
491
- len(children),
492
- [type(c).__name__ for c in children],
493
- )
494
- if not children:
495
- return
496
- if self.cursor_offset == -1:
497
- self.cursor_offset = len(children) - 1
498
- cursor_block = self.cursor_block
499
- if isinstance(cursor_block, BlockProtocol):
500
- cursor_block.block_cursor_clear()
501
- cursor_block.block_cursor_up()
502
- else:
503
- cursor_block = self.cursor_block
504
- if isinstance(cursor_block, BlockProtocol):
505
- if cursor_block.block_cursor_up() is None:
506
- if self.cursor_offset > 0:
507
- self.cursor_offset -= 1
508
- cursor_block = self.cursor_block
509
- if isinstance(cursor_block, BlockProtocol):
510
- cursor_block.block_cursor_clear()
511
- cursor_block.block_cursor_up()
512
- else:
513
- if self.cursor_offset > 0:
514
- self.cursor_offset -= 1
515
- cursor_block = self.cursor_block
516
- if isinstance(cursor_block, BlockProtocol):
517
- cursor_block.block_cursor_clear()
518
- cursor_block.block_cursor_up()
519
- self._auto_follow = False
520
- self._refresh_block_cursor()
521
-
522
- def action_cursor_down(self) -> None:
523
- children = self._selectable_children()
524
- if not children or self.cursor_offset == -1:
525
- return
526
- cursor_block = self.cursor_block
527
- if isinstance(cursor_block, BlockProtocol):
528
- if cursor_block.block_cursor_down() is None:
529
- if self.cursor_offset < len(children) - 1:
530
- self.cursor_offset += 1
531
- cursor_block = self.cursor_block
532
- if isinstance(cursor_block, BlockProtocol):
533
- cursor_block.block_cursor_clear()
534
- cursor_block.block_cursor_down()
535
- else:
536
- if self.cursor_offset < len(children) - 1:
537
- self.cursor_offset += 1
538
- cursor_block = self.cursor_block
539
- if isinstance(cursor_block, BlockProtocol):
540
- cursor_block.block_cursor_clear()
541
- cursor_block.block_cursor_down()
542
- self._auto_follow = False
543
- self._refresh_block_cursor()
544
-
545
- async def action_select_block(self) -> None:
546
- block = self.cursor_block
547
- if block is None:
548
- return
549
- menu_options: list[MenuItem] = [
550
- MenuItem("[u]C[/]opy to clipboard", "copy_to_clipboard", "c"),
551
- ]
552
- if getattr(block, "ALLOW_MAXIMIZE", False):
553
- menu_options.append(MenuItem("[u]M[/u]aximize", "maximize_block", "m"))
554
- if isinstance(block, MenuProtocol):
555
- menu_options.extend(block.get_block_menu())
556
- if isinstance(block, ExpandProtocol):
557
- if block.is_block_expanded():
558
- menu_options.append(MenuItem("[u]C[/]ollapse", "collapse_block", "x"))
559
- else:
560
- menu_options.append(MenuItem("E[x]pand", "expand_block", "x"))
561
- menu = Menu(block, menu_options)
562
- try:
563
- container = self.query_one("#content", VerticalGroup)
564
- region = container.content_region
565
- menu.styles.offset = Offset(
566
- region.x + 1,
567
- block.virtual_region.y + container.virtual_region.y,
568
- )
569
- except Exception:
570
- pass
571
- await self.mount(menu)
572
- menu.focus()
573
- self._active_menu = menu
574
-
575
- @on(Menu.OptionSelected)
576
- async def on_menu_option_selected(self, event: Menu.OptionSelected) -> None:
577
- event.stop()
578
- event.menu.display = False
579
- if event.action is not None:
580
- await self.run_action(event.action, {"block": event.owner})
581
- self._active_menu = None
582
- self.call_after_refresh(event.menu.remove)
583
-
584
- @on(Menu.Dismissed)
585
- async def on_menu_dismissed(self, event: Menu.Dismissed) -> None:
586
- event.stop()
587
- if event.menu.has_focus:
588
- self.query_one("#scroll", VerticalScroll).focus(scroll_visible=False)
589
- self._active_menu = None
590
- await event.menu.remove()
591
-
592
- def action_copy_to_clipboard(self, block: Widget | None = None) -> None:
593
- if block is None:
594
- block = self.cursor_block
595
- if isinstance(block, MenuProtocol):
596
- text = block.get_block_content("clipboard")
597
- else:
598
- text = None
599
- if text:
600
- self.app.copy_to_clipboard(text)
601
- self.flash("Copied to clipboard")
602
-
603
- def action_maximize_block(self) -> None:
604
- if (block := self.cursor_block) is not None:
605
- self.app.screen.maximize(block, container=False)
606
- block.focus()
607
-
608
- def action_expand_block(self) -> None:
609
- if (block := self.cursor_block) is not None and isinstance(block, ExpandProtocol):
610
- block.expand_block()
611
- self._refresh_block_cursor()
612
-
613
- def action_collapse_block(self) -> None:
614
- if (block := self.cursor_block) is not None and isinstance(block, ExpandProtocol):
615
- block.collapse_block()
616
- self._refresh_block_cursor()
617
-
618
- def action_toggle_expand(self) -> None:
619
- block = self.cursor_block
620
- if block is None:
621
- # No cursor → fall back to "toggle latest completed thought"
622
- try:
623
- container = self.query_one("#content", VerticalGroup)
624
- for child in reversed(container.children):
625
- if isinstance(child, AgentThought) and child._completed:
626
- child.action_toggle()
627
- return
628
- except Exception:
629
- return
630
- return
631
- if isinstance(block, ExpandProtocol):
632
- if block.is_block_expanded():
633
- block.collapse_block()
634
- else:
635
- block.expand_block()
636
- self._refresh_block_cursor()
637
-
638
- # ── Title / Footer ──
639
-
640
- def _update_title(self) -> None:
641
- sa = self.subagent
642
- status_icon = {"running": "🔄", "completed": "✔", "failed": "✗"}.get(sa._status, "?")
643
- self.title = f"{status_icon} Subagent ({sa.agent_type})"
644
- chunks = len("".join(sa._chunks))
645
- tools = len(sa._tool_calls)
646
- parts = [sa._status]
647
- if chunks:
648
- parts.append(f"{chunks}B")
649
- if tools:
650
- parts.append(f"{tools} tool calls")
651
- self.sub_title = " | ".join(parts)
652
-
653
- def _update_footer(self) -> None:
654
- try:
655
- self.query_one("#footer", Static).update(
656
- "[$text-muted]esc[/] 返回 "
657
- "[$text-muted]ctrl+j/k[/] 移动 "
658
- "[$text-muted]enter[/] 菜单 "
659
- "[$text-muted]ctrl+x[/] 折叠 "
660
- "[$text-muted]↑↓[/] 滚动"
661
- )
662
- except Exception:
663
- pass
664
-
665
- # ── Scroll actions ──
666
-
667
- def _scroll_widget(self) -> VerticalScroll | None:
668
- try:
669
- return self.query_one("#scroll", VerticalScroll)
670
- except Exception:
671
- return None
672
-
673
- def action_scroll_up(self) -> None:
674
- self._auto_follow = False
675
- if w := self._scroll_widget():
676
- w.scroll_up()
677
-
678
- def action_scroll_down(self) -> None:
679
- if w := self._scroll_widget():
680
- w.scroll_down()
681
-
682
- def action_scroll_page_up(self) -> None:
683
- self._auto_follow = False
684
- if w := self._scroll_widget():
685
- w.scroll_page_up()
686
-
687
- def action_scroll_page_down(self) -> None:
688
- if w := self._scroll_widget():
689
- w.scroll_page_down()
690
-
691
- def action_scroll_home(self) -> None:
692
- self._auto_follow = False
693
- if w := self._scroll_widget():
694
- w.scroll_home()
695
-
696
- def action_scroll_end(self) -> None:
697
- self._auto_follow = True
698
- if w := self._scroll_widget():
699
- w.scroll_end(animate=True)
700
-
701
- # ── Scroll tracking ──
702
-
703
- def on_scroll(self, event) -> None:
704
- try:
705
- scroll = self.query_one("#scroll", VerticalScroll)
706
- at_end = scroll.scroll_y >= scroll.max_scroll_y - 1
707
- self._auto_follow = at_end
708
- except Exception:
709
- pass