@scemoon/cdh 1.0.4 → 1.0.6

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 (269) hide show
  1. package/ai-dlc-skill/SKILL.md +4 -2
  2. package/ai-dlc-skill/agents/master.md +6 -0
  3. package/ai-dlc-skill/agents/plan-agent.md +2 -2
  4. package/ai-dlc-skill/agents/understand-agent.md +4 -4
  5. package/ai-dlc-skill/agents/verify-agent.md +1 -1
  6. package/ai-dlc-skill/architecture/project-structure.md +10 -10
  7. package/ai-dlc-skill/brownfield/README.md +2 -2
  8. package/ai-dlc-skill/brownfield/generate-context.sh +3 -3
  9. package/ai-dlc-skill/brownfield/scripts/extract-api.sh +5 -5
  10. package/ai-dlc-skill/components/backend.md +1 -1
  11. package/ai-dlc-skill/components/web.md +2 -2
  12. package/ai-dlc-skill/contracts/README.md +3 -3
  13. package/ai-dlc-skill/cross-tool/cline/export.sh +1 -1
  14. package/ai-dlc-skill/cross-tool/copilot/export.sh +1 -1
  15. package/ai-dlc-skill/cross-tool/onecode/export-skills.sh +7 -3
  16. package/ai-dlc-skill/cross-tool/onecode/export.sh +14 -8
  17. package/ai-dlc-skill/phases/deliver/lifecycle.md +6 -6
  18. package/ai-dlc-skill/phases/deliver/prompt.md +2 -2
  19. package/ai-dlc-skill/phases/deliver/rules.md +1 -1
  20. package/ai-dlc-skill/phases/plan/lifecycle.md +11 -11
  21. package/ai-dlc-skill/phases/plan/prompt.md +6 -6
  22. package/ai-dlc-skill/phases/plan/rules.md +1 -1
  23. package/ai-dlc-skill/phases/understand/entry.md +1 -1
  24. package/ai-dlc-skill/phases/understand/lifecycle.md +7 -7
  25. package/ai-dlc-skill/phases/understand/prompt.md +8 -8
  26. package/ai-dlc-skill/phases/understand/rules.md +5 -5
  27. package/ai-dlc-skill/phases/verify/lifecycle.md +24 -24
  28. package/ai-dlc-skill/phases/verify/prompt.md +8 -8
  29. package/ai-dlc-skill/phases/verify/rules.md +9 -9
  30. package/ai-dlc-skill/providers/README.md +2 -2
  31. package/ai-dlc-skill/providers/aliyun/preview.yaml +2 -2
  32. package/ai-dlc-skill/providers/tcb/preview.yaml +2 -2
  33. package/ai-dlc-skill/requirements.md +7 -7
  34. package/ai-dlc-skill/skill.yaml +4 -4
  35. package/ai-dlc-skill/templates/integration/CHANGELOG.md +2 -2
  36. package/ai-dlc-skill/templates/integration/contract-diff.md +7 -7
  37. package/ai-dlc-skill/templates/integration/contract-spec.md +7 -7
  38. package/ai-dlc-skill/templates/integration/runtime-contract.yaml +1 -1
  39. package/ai-dlc-skill/templates/project/README.md +18 -19
  40. package/ai-dlc-skill/templates/project/template.md +21 -21
  41. package/ai-dlc-skill/walkthrough/collect.sh +1 -1
  42. package/ai-dlc-skill/walkthrough/template.md +2 -2
  43. package/ai-dlc-skill/workflows/ai-dlc.yaml +12 -12
  44. package/ai-dlc-skill/workflows/deployment.yaml +4 -4
  45. package/cdh/__pycache__/cdh_mcp_injector.cpython-314.pyc +0 -0
  46. package/cdh/__pycache__/cdh_mcp_loader.cpython-314.pyc +0 -0
  47. package/cdh/__pycache__/cdh_mcp_manager.cpython-314.pyc +0 -0
  48. package/cdh/__pycache__/cdh_session_aggregator.cpython-314.pyc +0 -0
  49. package/cdh/__pycache__/cdh_skill_loader.cpython-314.pyc +0 -0
  50. package/cdh/__pycache__/cdh_skill_manager.cpython-314.pyc +0 -0
  51. package/cdh/__pycache__/cli.cpython-313.pyc +0 -0
  52. package/cdh/__pycache__/cli.cpython-314.pyc +0 -0
  53. package/cdh/__pycache__/scaffold.cpython-314.pyc +0 -0
  54. package/cdh/cdh_mcp_injector.py +115 -0
  55. package/cdh/cdh_mcp_loader.py +67 -0
  56. package/cdh/cdh_mcp_manager.py +73 -0
  57. package/cdh/cdh_session_aggregator.py +258 -0
  58. package/cdh/cdh_skill_manager.py +105 -0
  59. package/cdh/cli.py +64 -4
  60. package/cdh/scaffold.py +192 -41
  61. package/onecode/__init__.py +1 -1
  62. package/onecode/__pycache__/cli.cpython-314.pyc +0 -0
  63. package/onecode/__pycache__/commands.cpython-314.pyc +0 -0
  64. package/onecode/__pycache__/config.cpython-314.pyc +0 -0
  65. package/onecode/__pycache__/config_screen.cpython-314.pyc +0 -0
  66. package/onecode/__pycache__/migrate.cpython-314.pyc +0 -0
  67. package/onecode/agent/__pycache__/cdh_loader.cpython-314.pyc +0 -0
  68. package/onecode/agent/__pycache__/context.cpython-314.pyc +0 -0
  69. package/onecode/agent/__pycache__/engine.cpython-314.pyc +0 -0
  70. package/onecode/agent/__pycache__/hooks.cpython-314.pyc +0 -0
  71. package/onecode/agent/__pycache__/onecode_agent_acp.cpython-314.pyc +0 -0
  72. package/onecode/agent/__pycache__/permissions.cpython-314.pyc +0 -0
  73. package/onecode/agent/__pycache__/project_doc.cpython-314.pyc +0 -0
  74. package/onecode/agent/__pycache__/session.cpython-314.pyc +0 -0
  75. package/onecode/agent/agents/__pycache__/types.cpython-314.pyc +0 -0
  76. package/onecode/agent/agents/types.py +47 -164
  77. package/onecode/agent/attachments.py +0 -1
  78. package/onecode/agent/cdh_loader.py +17 -25
  79. package/onecode/agent/context.py +8 -3
  80. package/onecode/agent/engine.py +835 -220
  81. package/onecode/agent/hooks.py +1 -1
  82. package/onecode/agent/onecode_agent_acp.py +460 -47
  83. package/onecode/agent/onecode_agent_acp.py.bak +2447 -0
  84. package/onecode/agent/permissions.py +0 -1
  85. package/onecode/agent/project_doc.py +19 -0
  86. package/onecode/agent/session.py +17 -3
  87. package/onecode/agent/snapshot.py +3 -4
  88. package/onecode/agent/tools/__pycache__/agent_tools.cpython-314.pyc +0 -0
  89. package/onecode/agent/tools/__pycache__/apply_patch_tool.cpython-314.pyc +0 -0
  90. package/onecode/agent/tools/__pycache__/bash_tool.cpython-314.pyc +0 -0
  91. package/onecode/agent/tools/__pycache__/communication_tools.cpython-314.pyc +0 -0
  92. package/onecode/agent/tools/__pycache__/config_tool.cpython-314.pyc +0 -0
  93. package/onecode/agent/tools/__pycache__/cron_tools.cpython-314.pyc +0 -0
  94. package/onecode/agent/tools/__pycache__/file_ops.cpython-314.pyc +0 -0
  95. package/onecode/agent/tools/__pycache__/file_tools.cpython-314.pyc +0 -0
  96. package/onecode/agent/tools/__pycache__/git_tools.cpython-314.pyc +0 -0
  97. package/onecode/agent/tools/__pycache__/lsp_tools.cpython-314.pyc +0 -0
  98. package/onecode/agent/tools/__pycache__/mcp_tools.cpython-314.pyc +0 -0
  99. package/onecode/agent/tools/__pycache__/permission_handler.cpython-314.pyc +0 -0
  100. package/onecode/agent/tools/__pycache__/protocol.cpython-314.pyc +0 -0
  101. package/onecode/agent/tools/__pycache__/registry.cpython-314.pyc +0 -0
  102. package/onecode/agent/tools/__pycache__/sandbox.cpython-314.pyc +0 -0
  103. package/onecode/agent/tools/__pycache__/skill_tools.cpython-314.pyc +0 -0
  104. package/onecode/agent/tools/__pycache__/todo_tools.cpython-314.pyc +0 -0
  105. package/onecode/agent/tools/__pycache__/web_tools.cpython-314.pyc +0 -0
  106. package/onecode/agent/tools/agent_tools.py +4 -6
  107. package/onecode/agent/tools/apply_patch_tool.py +2 -8
  108. package/onecode/agent/tools/bash_tool.py +32 -12
  109. package/onecode/agent/tools/communication_tools.py +4 -5
  110. package/onecode/agent/tools/config_tool.py +3 -3
  111. package/onecode/agent/tools/cron_tools.py +4 -5
  112. package/onecode/agent/tools/file_ops.py +37 -3
  113. package/onecode/agent/tools/file_tools.py +10 -11
  114. package/onecode/agent/tools/git_tools.py +2 -2
  115. package/onecode/agent/tools/lsp_tools.py +2 -2
  116. package/onecode/agent/tools/mcp_tools.py +3 -5
  117. package/onecode/agent/tools/permission_handler.py +1 -1
  118. package/onecode/agent/tools/protocol.py +1 -1
  119. package/onecode/agent/tools/registry.py +69 -2
  120. package/onecode/agent/tools/sandbox.py +110 -16
  121. package/onecode/agent/tools/skill_tools.py +2 -2
  122. package/onecode/agent/tools/todo_tools.py +38 -19
  123. package/onecode/agent/tools/web_tools.py +6 -7
  124. package/onecode/builtin_skills/agent-browser/SKILL.md +212 -0
  125. package/onecode/builtin_skills/agent-browser/skill.yaml +8 -0
  126. package/onecode/builtin_skills/skill-creator/SKILL.md +106 -0
  127. package/onecode/builtin_skills/skill-creator/skill.yaml +8 -0
  128. package/onecode/cli.py +186 -6
  129. package/onecode/codebase/__pycache__/chunker.cpython-314.pyc +0 -0
  130. package/onecode/codebase/__pycache__/indexer.cpython-314.pyc +0 -0
  131. package/onecode/codebase/__pycache__/retriever.cpython-314.pyc +0 -0
  132. package/onecode/codebase/__pycache__/storage.cpython-314.pyc +0 -0
  133. package/onecode/codebase/chunker.py +0 -5
  134. package/onecode/codebase/indexer.py +14 -1
  135. package/onecode/codebase/retriever.py +13 -2
  136. package/onecode/codebase/storage.py +5 -4
  137. package/onecode/commands.py +81 -6
  138. package/onecode/config.py +41 -12
  139. package/onecode/config_screen.py +7 -3
  140. package/onecode/mcp/__pycache__/manager.cpython-314.pyc +0 -0
  141. package/onecode/mcp/manager.py +2 -3
  142. package/onecode/memory/__init__.py +7 -53
  143. package/onecode/memory/__pycache__/__init__.cpython-314.pyc +0 -0
  144. package/onecode/memory/__pycache__/backend.cpython-314.pyc +0 -0
  145. package/onecode/memory/__pycache__/offload.cpython-314.pyc +0 -0
  146. package/onecode/memory/__pycache__/pyramid.cpython-314.pyc +0 -0
  147. package/onecode/memory/__pycache__/recall.cpython-314.pyc +0 -0
  148. package/onecode/memory/backend.py +13 -39
  149. package/onecode/memory/pyramid.py +2 -71
  150. package/onecode/memory/recall.py +38 -3
  151. package/onecode/migrate.py +122 -0
  152. package/onecode/models/__pycache__/messages.cpython-314.pyc +0 -0
  153. package/onecode/models/__pycache__/provider.cpython-314.pyc +0 -0
  154. package/onecode/models/messages.py +58 -0
  155. package/onecode/models/provider.py +20 -2
  156. package/onecode/models/providers/__pycache__/anthropic_provider.cpython-314.pyc +0 -0
  157. package/onecode/models/providers/__pycache__/glm_provider.cpython-314.pyc +0 -0
  158. package/onecode/models/providers/__pycache__/minimax_provider.cpython-314.pyc +0 -0
  159. package/onecode/models/providers/__pycache__/minimaxi_provider.cpython-314.pyc +0 -0
  160. package/onecode/models/providers/__pycache__/ollama_provider.cpython-314.pyc +0 -0
  161. package/onecode/models/providers/anthropic_provider.py +59 -12
  162. package/onecode/models/providers/glm_provider.py +40 -0
  163. package/onecode/models/providers/minimax_provider.py +3 -0
  164. package/onecode/models/providers/minimaxi_provider.py +3 -0
  165. package/onecode/models/providers/ollama_provider.py +3 -0
  166. package/onecode/server/app.py +1 -1
  167. package/onecode/skills/__pycache__/argument_substitution.cpython-314.pyc +0 -0
  168. package/onecode/skills/__pycache__/bootstrap.cpython-314.pyc +0 -0
  169. package/onecode/skills/__pycache__/loader.cpython-314.pyc +0 -0
  170. package/onecode/skills/__pycache__/manager.cpython-314.pyc +0 -0
  171. package/onecode/skills/argument_substitution.py +0 -1
  172. package/onecode/skills/bootstrap.py +124 -0
  173. package/onecode/skills/loader.py +35 -53
  174. package/onecode/skills/manager.py +2 -2
  175. package/onecode/storage/activity.py +3 -4
  176. package/onecode/storage/session.py +3 -4
  177. package/onecode/tasks/manager.py +23 -10
  178. package/onecode/trace/tracer.py +2 -3
  179. package/package.json +1 -1
  180. package/pyproject.toml +5 -1
  181. package/run.js +68 -14
  182. package/tui/__pycache__/about.cpython-314.pyc +0 -0
  183. package/tui/__pycache__/app.cpython-313.pyc +0 -0
  184. package/tui/__pycache__/app.cpython-314.pyc +0 -0
  185. package/tui/__pycache__/danger.cpython-314.pyc +0 -0
  186. package/tui/__pycache__/directory_suggester.cpython-314.pyc +0 -0
  187. package/tui/__pycache__/messages.cpython-314.pyc +0 -0
  188. package/tui/__pycache__/path_complete.cpython-314.pyc +0 -0
  189. package/tui/__pycache__/paths.cpython-314.pyc +0 -0
  190. package/tui/__pycache__/session_tracker.cpython-314.pyc +0 -0
  191. package/tui/__pycache__/settings_schema.cpython-314.pyc +0 -0
  192. package/tui/acp/__pycache__/agent.cpython-314.pyc +0 -0
  193. package/tui/acp/__pycache__/api.cpython-314.pyc +0 -0
  194. package/tui/acp/__pycache__/messages.cpython-314.pyc +0 -0
  195. package/tui/acp/__pycache__/prompt.cpython-314.pyc +0 -0
  196. package/tui/acp/__pycache__/protocol.cpython-314.pyc +0 -0
  197. package/tui/acp/agent.py +125 -58
  198. package/tui/acp/api.py +12 -0
  199. package/tui/acp/messages.py +3 -1
  200. package/tui/acp/prompt.py +0 -57
  201. package/tui/acp/protocol.py +6 -0
  202. package/tui/app.py +11 -33
  203. package/tui/messages.py +2 -0
  204. package/tui/path_complete.py +1 -1
  205. package/tui/paths.py +16 -0
  206. package/tui/screens/__pycache__/agent_modal.cpython-314.pyc +0 -0
  207. package/tui/screens/__pycache__/component_picker.cpython-314.pyc +0 -0
  208. package/tui/screens/__pycache__/diff_screen.cpython-314.pyc +0 -0
  209. package/tui/screens/__pycache__/log.cpython-314.pyc +0 -0
  210. package/tui/screens/__pycache__/main.cpython-313.pyc +0 -0
  211. package/tui/screens/__pycache__/main.cpython-314.pyc +0 -0
  212. package/tui/screens/__pycache__/permissions.cpython-314.pyc +0 -0
  213. package/tui/screens/__pycache__/projects_app.cpython-314.pyc +0 -0
  214. package/tui/screens/__pycache__/projects_screen.cpython-314.pyc +0 -0
  215. package/tui/screens/__pycache__/sessions.cpython-314.pyc +0 -0
  216. package/tui/screens/__pycache__/store.cpython-314.pyc +0 -0
  217. package/tui/screens/__pycache__/tool_content_screen.cpython-314.pyc +0 -0
  218. package/tui/screens/component_picker.py +35 -15
  219. package/tui/screens/diff_screen.py +84 -0
  220. package/tui/screens/log.py +25 -25
  221. package/tui/screens/main.py +48 -26
  222. package/tui/screens/projects.tcss +5 -1
  223. package/tui/screens/projects_app.py +6 -6
  224. package/tui/screens/projects_screen.py +19 -39
  225. package/tui/screens/sessions.py +3 -5
  226. package/tui/session_tracker.py +3 -0
  227. package/tui/settings_schema.py +1 -1
  228. package/tui/visuals/__pycache__/columns.cpython-314.pyc +0 -0
  229. package/tui/visuals/columns.py +1 -2
  230. package/tui/widgets/__pycache__/acp_content.cpython-314.pyc +0 -0
  231. package/tui/widgets/__pycache__/agent_response.cpython-314.pyc +0 -0
  232. package/tui/widgets/__pycache__/agent_thought.cpython-314.pyc +0 -0
  233. package/tui/widgets/__pycache__/conversation.cpython-314.pyc +0 -0
  234. package/tui/widgets/__pycache__/diff_view.cpython-314.pyc +0 -0
  235. package/tui/widgets/__pycache__/directory_input.cpython-314.pyc +0 -0
  236. package/tui/widgets/__pycache__/future_text.cpython-314.pyc +0 -0
  237. package/tui/widgets/__pycache__/grid_select.cpython-314.pyc +0 -0
  238. package/tui/widgets/__pycache__/load_more.cpython-314.pyc +0 -0
  239. package/tui/widgets/__pycache__/mandelbrot.cpython-314.pyc +0 -0
  240. package/tui/widgets/__pycache__/markdown_note.cpython-314.pyc +0 -0
  241. package/tui/widgets/__pycache__/modified_files.cpython-314.pyc +0 -0
  242. package/tui/widgets/__pycache__/plan.cpython-314.pyc +0 -0
  243. package/tui/widgets/__pycache__/project_grid_select.cpython-314.pyc +0 -0
  244. package/tui/widgets/__pycache__/project_summary.cpython-314.pyc +0 -0
  245. package/tui/widgets/__pycache__/session_grid_select.cpython-314.pyc +0 -0
  246. package/tui/widgets/__pycache__/session_summary.cpython-314.pyc +0 -0
  247. package/tui/widgets/__pycache__/shell_result.cpython-314.pyc +0 -0
  248. package/tui/widgets/__pycache__/side_bar.cpython-314.pyc +0 -0
  249. package/tui/widgets/__pycache__/subagent.cpython-314.pyc +0 -0
  250. package/tui/widgets/__pycache__/subagent_screen.cpython-314.pyc +0 -0
  251. package/tui/widgets/__pycache__/terminal.cpython-314.pyc +0 -0
  252. package/tui/widgets/__pycache__/tool_call.cpython-314.pyc +0 -0
  253. package/tui/widgets/agent_response.py +0 -1
  254. package/tui/widgets/agent_thought.py +0 -1
  255. package/tui/widgets/conversation.py +157 -14
  256. package/tui/widgets/diff_view.py +10 -0
  257. package/tui/widgets/load_more.py +24 -0
  258. package/tui/widgets/modified_files.py +86 -12
  259. package/tui/widgets/plan.py +1 -1
  260. package/tui/widgets/project_grid_select.py +9 -2
  261. package/tui/widgets/session_grid_select.py +6 -0
  262. package/tui/widgets/side_bar.py +10 -0
  263. package/tui/widgets/subagent.py +92 -58
  264. package/tui/widgets/subagent_screen.py +638 -115
  265. package/tui/widgets/terminal.py +1 -2
  266. package/tui/widgets/terminal_tool.py +11 -2
  267. package/tui/widgets/tool_call.py +35 -2
  268. package/onecode/memory/offload.py +0 -114
  269. package/onecode/memory/symbolic.py +0 -164
@@ -1,15 +1,16 @@
1
1
  from __future__ import annotations
2
2
 
3
- from typing import ClassVar
3
+ import logging
4
+ from collections.abc import Callable, Coroutine
5
+ from typing import Any
4
6
 
5
- from textual import containers
7
+ from textual import containers, events
6
8
  from textual.app import ComposeResult
7
- from textual.binding import Binding, BindingType
8
9
  from textual.content import Content
9
10
  from textual.reactive import var
10
11
  from textual.widgets import Static
11
12
 
12
- from tui.protocol import ExpandProtocol
13
+ _sa_logger = logging.getLogger("tui.widgets.subagent")
13
14
 
14
15
 
15
16
  class SubAgentHeader(Static):
@@ -23,11 +24,9 @@ class SubAgentHeader(Static):
23
24
 
24
25
 
25
26
  class SubAgent(containers.VerticalGroup, can_focus=True):
26
- """Sub-agent compact view — animated header + latest line with ctrl+x hint.
27
+ """Sub-agent view — header + dynamically updated latest line.
27
28
 
28
- During streaming: header shows a spinner + latest line updates live.
29
- After completion: header shows static marker.
30
- Ctrl+X to open full-screen SubAgentScreen with full structured output.
29
+ Ctrl+N opens the full-screen SubAgentScreen.
31
30
  """
32
31
 
33
32
  DEFAULT_CLASSES = "block"
@@ -35,60 +34,46 @@ class SubAgent(containers.VerticalGroup, can_focus=True):
35
34
  HELP = """
36
35
  ## Sub-agent
37
36
 
38
- - **ctrl+x** Open full-screen output
39
- - **up/down** Scroll (if content overflows)
37
+ - **ctrl+n / click** Open full-screen output
40
38
  """
41
39
 
42
- BINDINGS: ClassVar[list[BindingType]] = [
43
- Binding("ctrl+x", "toggle", "Full screen", show=False, priority=True),
44
- ]
45
-
46
- ALLOW_MAXIMIZE = True
47
-
48
40
  DEFAULT_CSS = """
49
41
  SubAgent {
50
42
  height: auto;
51
43
  width: 1fr;
52
44
  min-height: 2;
53
- padding: 0 1;
54
- border-left: thick $secondary;
55
- background: $surface-darken-1;
45
+ border-left: tall $secondary;
56
46
 
57
47
  SubAgentHeader {
58
48
  color: $text-secondary;
59
49
  text-style: bold;
50
+ padding: 0 1;
51
+ }
52
+
53
+ #subagent-latest {
54
+ padding: 0 0 0 2;
60
55
  }
61
56
 
62
57
  &.-status-running {
63
- border-left: thick $warning;
64
- background: $boost;
58
+ border-left: tall $warning;
65
59
  SubAgentHeader {
66
60
  color: $warning;
67
61
  text-style: bold italic;
68
62
  }
69
- #subagent-latest {
70
- color: $text;
71
- }
72
63
  }
73
64
 
74
65
  &.-status-completed {
75
- border-left: thick $success;
66
+ border-left: tall $success;
76
67
  SubAgentHeader {
77
68
  color: $success;
78
69
  }
79
- #subagent-latest {
80
- color: $text-muted;
81
- }
82
70
  }
83
71
 
84
72
  &.-status-failed {
85
- border-left: thick $error;
73
+ border-left: tall $error;
86
74
  SubAgentHeader {
87
75
  color: $error;
88
76
  }
89
- #subagent-latest {
90
- color: $error;
91
- }
92
77
  }
93
78
  }
94
79
  """
@@ -115,10 +100,20 @@ class SubAgent(containers.VerticalGroup, can_focus=True):
115
100
  self._error = ""
116
101
  self._mounted = False
117
102
  self._spin_timer = None
103
+ # Single handler set by SubAgentScreen for real-time event delivery
104
+ self._screen_handler: Callable[[str, Any], Coroutine[Any, Any, None]] | None = None
105
+ # Tool calls invoked *inside* this subagent (tracked for SubAgentScreen)
106
+ self._tool_calls: dict = {}
107
+ self._tool_order: list[str] = []
108
+ # Ordered event queue for chronological rendering (used by SubAgentScreen)
109
+ self._events: list = []
110
+ # Diagnostics counters (for log correlation)
111
+ self._chunk_count_log: int = 0
112
+ self._byte_count_log: int = 0
118
113
 
119
114
  def compose(self) -> ComposeResult:
120
115
  self.set_class(True, f"-status-{self._status}")
121
- yield SubAgentHeader(self._header_text(), id="subagent-header")
116
+ yield SubAgentHeader(self._header_text(), id="subagent-header", markup=False)
122
117
  yield Static(self._latest_content, id="subagent-latest")
123
118
 
124
119
  def on_mount(self) -> None:
@@ -147,6 +142,8 @@ class SubAgent(containers.VerticalGroup, can_focus=True):
147
142
  if _new != "running":
148
143
  self._stop_spinner()
149
144
 
145
+ # ── Refresh helpers ──
146
+
150
147
  def _refresh(self) -> None:
151
148
  if not self._mounted:
152
149
  return
@@ -155,7 +152,6 @@ class SubAgent(containers.VerticalGroup, can_focus=True):
155
152
  if self._status != "running":
156
153
  self.set_class(False, "-status-running")
157
154
  self.query_one("#subagent-header", SubAgentHeader).update(self._header_text())
158
- self.query_one("#subagent-latest", Static).update(self._latest_content)
159
155
  except Exception:
160
156
  pass
161
157
 
@@ -167,25 +163,40 @@ class SubAgent(containers.VerticalGroup, can_focus=True):
167
163
  except Exception:
168
164
  pass
169
165
 
170
- def _header_text(self) -> str:
171
- label = self.agent_type
172
- status_tag = self._status_label()
166
+ # ── Header content (aligned with ToolCall style) ──
167
+
168
+ def _header_text(self) -> Content:
169
+ parts = [
170
+ Content.from_markup(f"🧠 Subagent ({self.agent_type})"),
171
+ ]
172
+ if self.prompt:
173
+ p = self.prompt.replace("\n", " ").strip()
174
+ if len(p) > 55:
175
+ p = p[:55] + "…"
176
+ parts.append(Content.from_markup(f" [$text-muted]{p}[/]"))
173
177
  if self._status == "running":
174
178
  spin = self.SPINNER_FRAMES[self.spinner_frame]
175
- return f"{spin} @ {label} [{status_tag}]"
179
+ parts.append(Content.from_markup(f" [$text-warning]{spin}"))
176
180
  elif self._status == "completed":
177
- return f" @ {label} [{status_tag}]"
181
+ parts.append(Content.from_markup(" [$success]"))
178
182
  elif self._status == "failed":
179
- return f"✗ @ {label} [{status_tag}]"
180
- return f"@ {label} [{status_tag}]"
183
+ from tui.pill import pill
184
+ tag = f": {self._error[:40]}" if self._error else ""
185
+ parts.append(Content.assemble(" ", pill(f"failed{tag}", "$error-muted", "$error")))
186
+ return Content.assemble(*parts)
187
+
188
+ # ── Preview line (shown when collapsed) ──
181
189
 
182
190
  @property
183
191
  def _latest_content(self) -> Content:
184
192
  text = (self.latest_line or "").strip()
185
- hint = Content.from_markup(" [$text-muted]ctrl+x 展开查看")
186
193
  if text:
187
- return Content.assemble(text, hint)
188
- return Content.from_markup("[$text-muted]⏳ 等待输出… ctrl+x 展开查看")
194
+ return Content.assemble(
195
+ Content(text),
196
+ Content(" "),
197
+ Content.from_markup("[$text-muted]ctrl+n / 点击打开全屏[/]"),
198
+ )
199
+ return Content.from_markup("[$text-muted]⏳ 等待输出… (ctrl+n / 点击打开全屏)[/]")
189
200
 
190
201
  def _status_label(self) -> str:
191
202
  if self._status == "running":
@@ -206,15 +217,45 @@ class SubAgent(containers.VerticalGroup, can_focus=True):
206
217
  return line
207
218
  return ""
208
219
 
220
+ # ── Streaming updates ──
221
+
209
222
  def append_chunk(self, text: str) -> None:
210
223
  self._chunks.append(text)
224
+ self._events.append(("text", text))
225
+ self._chunk_count_log += 1
226
+ self._byte_count_log += len(text or "")
211
227
  self.latest_line = self._update_latest_line()
212
228
  self._refresh_latest()
229
+ if self._screen_handler is not None:
230
+ self.run_worker(self._screen_handler("text", text), exit_on_error=False)
213
231
 
214
232
  def append_thinking(self, text: str) -> None:
215
233
  self._thinking_chunks.append(text)
234
+ self._events.append(("thinking", text))
235
+ if self._screen_handler is not None:
236
+ self.run_worker(self._screen_handler("thinking", text), exit_on_error=False)
237
+
238
+ async def add_or_update_tool_call(self, tool_id: str, tool_call) -> None:
239
+ """Track a tool call so the full-screen SubAgentScreen can display it."""
240
+ self._tool_calls[tool_id] = tool_call
241
+ if tool_id not in self._tool_order:
242
+ self._tool_order.append(tool_id)
243
+ self._events.append(("tool", (tool_id, tool_call)))
244
+ # Show the current tool name as the inline preview line.
245
+ title = tool_call.get("title", "") if isinstance(tool_call, dict) else ""
246
+ if title:
247
+ self.latest_line = title
248
+ self._refresh_latest()
249
+ if self._screen_handler is not None:
250
+ self.run_worker(self._screen_handler("tool", (tool_id, tool_call)), exit_on_error=False)
216
251
 
217
252
  def complete(self, status: str = "completed", error: str = "") -> None:
253
+ _sa_logger.debug(
254
+ "[WIDGET-SUBagent] complete id=%s status=%s err=%r chunks=%d bytes=%d "
255
+ "was_completed=%s",
256
+ self.id, status, (error or "")[:80], self._chunk_count_log,
257
+ self._byte_count_log, self._completed,
258
+ )
218
259
  if self._completed:
219
260
  return
220
261
  self._completed = True
@@ -226,6 +267,8 @@ class SubAgent(containers.VerticalGroup, can_focus=True):
226
267
  self.latest_line = self._update_latest_line()
227
268
  self._stop_spinner()
228
269
  self._refresh()
270
+ if self._screen_handler is not None:
271
+ self.run_worker(self._screen_handler("complete", {"status": status, "error": error}), exit_on_error=False)
229
272
 
230
273
  def _refresh_latest(self) -> None:
231
274
  if not self._mounted:
@@ -235,19 +278,10 @@ class SubAgent(containers.VerticalGroup, can_focus=True):
235
278
  except Exception:
236
279
  pass
237
280
 
238
- def can_expand(self) -> bool:
239
- return True
240
-
241
- def expand_block(self) -> None:
242
- self.action_toggle()
243
-
244
- def collapse_block(self) -> None:
245
- pass
246
-
247
- def is_block_expanded(self) -> bool:
248
- return False
281
+ def on_click(self, _event: events.Click) -> None:
282
+ self.action_fullscreen()
249
283
 
250
- def action_toggle(self) -> None:
251
- """Ctrl+X: open full-screen view (works even while running)."""
284
+ def action_fullscreen(self) -> None:
285
+ """Ctrl+N / click: open full-screen view (works even while running)."""
252
286
  from tui.widgets.subagent_screen import SubAgentScreen
253
- self.app.push_screen(SubAgentScreen(self))
287
+ self.app.push_screen(SubAgentScreen(self))