@scemoon/cdh 1.0.3 → 1.0.5

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 (294) 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 +14 -3
  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 +462 -49
  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/tui/__pycache__/about.cpython-314.pyc +0 -0
  182. package/tui/__pycache__/agents.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__/messages.cpython-314.pyc +0 -0
  187. package/tui/__pycache__/path_complete.cpython-314.pyc +0 -0
  188. package/tui/__pycache__/paths.cpython-314.pyc +0 -0
  189. package/tui/__pycache__/session_tracker.cpython-314.pyc +0 -0
  190. package/tui/__pycache__/settings_schema.cpython-314.pyc +0 -0
  191. package/tui/acp/__pycache__/agent.cpython-314.pyc +0 -0
  192. package/tui/acp/__pycache__/api.cpython-314.pyc +0 -0
  193. package/tui/acp/__pycache__/messages.cpython-314.pyc +0 -0
  194. package/tui/acp/__pycache__/prompt.cpython-314.pyc +0 -0
  195. package/tui/acp/__pycache__/protocol.cpython-314.pyc +0 -0
  196. package/tui/acp/agent.py +125 -58
  197. package/tui/acp/api.py +12 -0
  198. package/tui/acp/messages.py +3 -1
  199. package/tui/acp/prompt.py +0 -57
  200. package/tui/acp/protocol.py +6 -0
  201. package/tui/agents.py +8 -7
  202. package/tui/app.py +11 -33
  203. package/tui/data/agents/ampcode.com.toml +1 -0
  204. package/tui/data/agents/augmentcode.com.toml +1 -0
  205. package/tui/data/agents/cdh.cloud-dev-harness.toml +3 -2
  206. package/tui/data/agents/crowai.dev.toml +1 -0
  207. package/tui/data/agents/deepagents.langchain.com +1 -0
  208. package/tui/data/agents/docker.com.toml +1 -0
  209. package/tui/data/agents/goose.ai.toml +1 -0
  210. package/tui/data/agents/inference.huggingface.co.toml +1 -1
  211. package/tui/data/agents/kiro.dev.toml +1 -0
  212. package/tui/data/agents/onecode.dev.toml +22 -0
  213. package/tui/data/agents/openclaw.ai.toml +1 -1
  214. package/tui/data/agents/openhands.dev.toml +1 -0
  215. package/tui/data/agents/stakpak.dev.toml +1 -0
  216. package/tui/data/agents/vibe.mistral.ai.toml +1 -0
  217. package/tui/data/agents/vtcode.dev.toml +1 -0
  218. package/tui/messages.py +2 -0
  219. package/tui/path_complete.py +1 -1
  220. package/tui/paths.py +16 -0
  221. package/tui/screens/__pycache__/component_picker.cpython-314.pyc +0 -0
  222. package/tui/screens/__pycache__/diff_screen.cpython-314.pyc +0 -0
  223. package/tui/screens/__pycache__/log.cpython-314.pyc +0 -0
  224. package/tui/screens/__pycache__/main.cpython-313.pyc +0 -0
  225. package/tui/screens/__pycache__/main.cpython-314.pyc +0 -0
  226. package/tui/screens/__pycache__/permissions.cpython-314.pyc +0 -0
  227. package/tui/screens/__pycache__/projects_app.cpython-314.pyc +0 -0
  228. package/tui/screens/__pycache__/projects_screen.cpython-314.pyc +0 -0
  229. package/tui/screens/__pycache__/sessions.cpython-314.pyc +0 -0
  230. package/tui/screens/__pycache__/store.cpython-314.pyc +0 -0
  231. package/tui/screens/__pycache__/tool_content_screen.cpython-314.pyc +0 -0
  232. package/tui/screens/component_picker.py +35 -15
  233. package/tui/screens/diff_screen.py +84 -0
  234. package/tui/screens/log.py +25 -25
  235. package/tui/screens/main.py +48 -26
  236. package/tui/screens/projects.tcss +5 -1
  237. package/tui/screens/projects_app.py +6 -6
  238. package/tui/screens/projects_screen.py +19 -39
  239. package/tui/screens/sessions.py +3 -5
  240. package/tui/screens/store.py +1 -1
  241. package/tui/session_tracker.py +3 -0
  242. package/tui/settings_schema.py +2 -2
  243. package/tui/visuals/__pycache__/columns.cpython-314.pyc +0 -0
  244. package/tui/visuals/columns.py +1 -2
  245. package/tui/widgets/__pycache__/agent_response.cpython-314.pyc +0 -0
  246. package/tui/widgets/__pycache__/agent_thought.cpython-314.pyc +0 -0
  247. package/tui/widgets/__pycache__/conversation.cpython-314.pyc +0 -0
  248. package/tui/widgets/__pycache__/diff_view.cpython-314.pyc +0 -0
  249. package/tui/widgets/__pycache__/load_more.cpython-314.pyc +0 -0
  250. package/tui/widgets/__pycache__/modified_files.cpython-314.pyc +0 -0
  251. package/tui/widgets/__pycache__/plan.cpython-314.pyc +0 -0
  252. package/tui/widgets/__pycache__/project_grid_select.cpython-314.pyc +0 -0
  253. package/tui/widgets/__pycache__/session_grid_select.cpython-314.pyc +0 -0
  254. package/tui/widgets/__pycache__/shell_result.cpython-314.pyc +0 -0
  255. package/tui/widgets/__pycache__/side_bar.cpython-314.pyc +0 -0
  256. package/tui/widgets/__pycache__/subagent.cpython-314.pyc +0 -0
  257. package/tui/widgets/__pycache__/subagent_screen.cpython-314.pyc +0 -0
  258. package/tui/widgets/__pycache__/terminal.cpython-314.pyc +0 -0
  259. package/tui/widgets/__pycache__/tool_call.cpython-314.pyc +0 -0
  260. package/tui/widgets/agent_response.py +0 -1
  261. package/tui/widgets/agent_thought.py +0 -1
  262. package/tui/widgets/conversation.py +157 -14
  263. package/tui/widgets/diff_view.py +10 -0
  264. package/tui/widgets/load_more.py +24 -0
  265. package/tui/widgets/modified_files.py +173 -105
  266. package/tui/widgets/plan.py +1 -1
  267. package/tui/widgets/project_grid_select.py +9 -2
  268. package/tui/widgets/session_grid_select.py +6 -0
  269. package/tui/widgets/side_bar.py +10 -0
  270. package/tui/widgets/subagent.py +92 -58
  271. package/tui/widgets/subagent_screen.py +638 -115
  272. package/tui/widgets/terminal.py +1 -2
  273. package/tui/widgets/terminal_tool.py +11 -2
  274. package/tui/widgets/tool_call.py +35 -2
  275. package/cdh/__pycache__/__init__.cpython-313.pyc +0 -0
  276. package/cdh/__pycache__/__main__.cpython-314.pyc +0 -0
  277. package/cdh/__pycache__/scaffold.cpython-313.pyc +0 -0
  278. package/onecode/__pycache__/mock_data.cpython-314.pyc +0 -0
  279. package/onecode/agent/__pycache__/cdh_agent_acp.cpython-313.pyc +0 -0
  280. package/onecode/agent/__pycache__/cdh_agent_acp.cpython-314.pyc +0 -0
  281. package/onecode/agent/__pycache__/harness_skill.cpython-314.pyc +0 -0
  282. package/onecode/agent/tools/__pycache__/task_tools.cpython-314.pyc +0 -0
  283. package/onecode/codebase/__pycache__/config.cpython-314.pyc +0 -0
  284. package/onecode/memory/offload.py +0 -114
  285. package/onecode/memory/symbolic.py +0 -164
  286. package/onecode/models/providers/__pycache__/mock_provider.cpython-314.pyc +0 -0
  287. package/onecode/tasks/__pycache__/__init__.cpython-314.pyc +0 -0
  288. package/onecode/tasks/__pycache__/manager.cpython-314.pyc +0 -0
  289. package/onecode/tasks/__pycache__/models.cpython-314.pyc +0 -0
  290. package/tui/__pycache__/cli.cpython-314.pyc +0 -0
  291. package/tui/screens/__pycache__/settings.cpython-314.pyc +0 -0
  292. package/tui/widgets/__pycache__/conversation.cpython-313.pyc +0 -0
  293. package/tui/widgets/__pycache__/terminal.cpython-313.pyc +0 -0
  294. package/tui/widgets/__pycache__/tool_call.cpython-313.pyc +0 -0
@@ -2,6 +2,7 @@ import asyncio
2
2
  from functools import partial
3
3
  from pathlib import Path
4
4
  import random
5
+ import subprocess
5
6
 
6
7
  from textual import on
7
8
  from textual.app import ComposeResult
@@ -27,9 +28,9 @@ from tui.widgets.modified_files import ModifiedFiles
27
28
  from tui.widgets.plan import Plan
28
29
  from tui.widgets.throbber import Throbber
29
30
  from tui.widgets.conversation import Conversation
30
- from tui.widgets.project_directory_tree import ProjectDirectoryTree
31
31
  from tui.widgets.side_bar import SideBar
32
32
  from tui.widgets.session_tabs import SessionsTabs, SessionLabel
33
+ from tui.screens.diff_screen import DiffScreen
33
34
 
34
35
 
35
36
  class ModeProvider(Provider):
@@ -210,33 +211,15 @@ class MainScreen(Screen, can_focus=False):
210
211
  new_dir = event.project_dir
211
212
  sidebar = self.query_one(SideBar)
212
213
  if new_dir is None:
213
- sidebar.remove_panel("project-panel")
214
- self.project_path = None
215
214
  if mf := sidebar.query_one_optional("#modified_files", ModifiedFiles):
216
215
  mf.refresh_files()
217
216
  self._swap_directory_watcher(None)
218
217
  return
219
- if self.project_path == new_dir and sidebar.has_panel("project-panel"):
218
+ if self.project_path == new_dir:
220
219
  if mf := sidebar.query_one_optional("#modified_files", ModifiedFiles):
221
220
  mf.refresh_files()
222
221
  return
223
222
  self.project_path = new_dir
224
- if not sidebar.has_panel("project-panel"):
225
- collapsible = await sidebar.add_panel(
226
- SideBar.Panel(
227
- "Project",
228
- ProjectDirectoryTree(
229
- self.project_path,
230
- id="project_directory_tree",
231
- ),
232
- flex=True,
233
- id="project-panel",
234
- ),
235
- )
236
- tree = collapsible.query_one(ProjectDirectoryTree)
237
- tree.data_bind(path=MainScreen.project_path)
238
- tree.guide_depth = 3
239
-
240
223
  if mf := sidebar.query_one_optional("#modified_files", ModifiedFiles):
241
224
  mf.refresh_files()
242
225
  self._swap_directory_watcher(new_dir)
@@ -247,18 +230,54 @@ class MainScreen(Screen, can_focus=False):
247
230
  except Exception:
248
231
  pass
249
232
 
250
- def _has_project_panel(self) -> bool:
251
- try:
252
- sidebar = self.query_one(SideBar)
253
- except Exception:
254
- return False
255
- return sidebar.has_panel("project-panel")
256
233
 
257
234
  @on(DirectoryTree.FileSelected, "ProjectDirectoryTree")
258
235
  def on_project_directory_tree_selected(self, event: Tree.NodeSelected):
259
236
  if (data := event.node.data) is not None:
260
237
  self.conversation.insert_path_into_prompt(data.path)
261
238
 
239
+ @on(ModifiedFiles.FileSelected)
240
+ async def on_modified_files_file_selected(self, event: ModifiedFiles.FileSelected):
241
+ event.stop()
242
+ filepath = event.filepath
243
+ project_path = self.project_path
244
+ if project_path is None:
245
+ return
246
+
247
+ before, after = self._get_file_diff_content(project_path, filepath)
248
+ if before is None and after is None:
249
+ self.app.notify("No diff available", severity="warning")
250
+ return
251
+ full_path = str(project_path / filepath)
252
+ self.app.push_screen(DiffScreen(full_path, before, after or ""))
253
+
254
+ def _get_file_diff_content(
255
+ self, project_path: Path, filepath: str
256
+ ) -> tuple[str | None, str | None]:
257
+ after: str | None = None
258
+ current_path = project_path / filepath
259
+ try:
260
+ after = current_path.read_text()
261
+ except Exception:
262
+ after = "" if current_path.exists() else None
263
+
264
+ before: str | None = None
265
+ try:
266
+ r = subprocess.run(
267
+ ["git", "-C", str(project_path), "show", f"HEAD:{filepath}"],
268
+ capture_output=True, text=True, timeout=5.0,
269
+ )
270
+ if r.returncode == 0:
271
+ before = r.stdout
272
+ except Exception:
273
+ pass
274
+
275
+ if before == after:
276
+ return None, None
277
+ if before is None and after is None:
278
+ return None, None
279
+ return before, after or ""
280
+
262
281
  @on(acp_messages.Plan)
263
282
  async def on_acp_plan(self, message: acp_messages.Plan):
264
283
  message.stop()
@@ -277,7 +296,10 @@ class MainScreen(Screen, can_focus=False):
277
296
  subtitle=event.subtitle,
278
297
  path=event.path,
279
298
  state=event.state,
299
+ session_pk=event.session_pk,
280
300
  )
301
+ if event.session_pk is not None:
302
+ self.conversation._session_pk = event.session_pk
281
303
  if event.name is not None:
282
304
  self.conversation.update_title()
283
305
 
@@ -28,6 +28,10 @@ ProjectsScreen {
28
28
 
29
29
  #actions Button {
30
30
  margin: 0 1;
31
+ &:focus {
32
+ color: $text;
33
+ background-tint: $primary 20%;
34
+ }
31
35
  }
32
36
 
33
37
 
@@ -68,7 +72,7 @@ ProjectsScreen {
68
72
  width: 1fr;
69
73
  }
70
74
  .path {
71
- color: $text-secondary;
75
+ color: $foreground 70%;
72
76
  text-style: italic;
73
77
  }
74
78
  }
@@ -9,7 +9,7 @@ from textual.reactive import var
9
9
  from textual.widget import Widget
10
10
  from textual.widgets import Button, Label, Static
11
11
 
12
- from onecode.config import CLOUD_DEV_HARNESS_DIR, load_config, save_config
12
+ from onecode.config import load_config, save_config
13
13
  from onecode.agent.cdh_loader import CdhProjectLoader
14
14
  from onecode.config_screen import EditFieldScreen
15
15
 
@@ -162,7 +162,7 @@ class ProjectsApp(App):
162
162
  self._refresh()
163
163
 
164
164
  def _refresh(self) -> None:
165
- projects_dir = CLOUD_DEV_HARNESS_DIR / "projects"
165
+ projects_dir = Path.home() / ".cdh" / "projects"
166
166
  projects_dir.mkdir(parents=True, exist_ok=True)
167
167
  pf_list = sorted(
168
168
  list(projects_dir.glob("*.yaml")) + list(projects_dir.glob("*.json"))
@@ -226,7 +226,7 @@ class ProjectsApp(App):
226
226
  except Exception:
227
227
  ws = Path.cwd().resolve()
228
228
  name = ws.name
229
- projects_dir = CLOUD_DEV_HARNESS_DIR / "projects"
229
+ projects_dir = Path.home() / ".cdh" / "projects"
230
230
  projects_dir.mkdir(parents=True, exist_ok=True)
231
231
  proj_file = projects_dir / f"{name}.yaml"
232
232
  if proj_file.exists():
@@ -273,7 +273,7 @@ class ProjectsApp(App):
273
273
  self.notify(f".cdh already exists at {existing}", severity="warning")
274
274
  return
275
275
  name = target.name
276
- projects_dir = CLOUD_DEV_HARNESS_DIR / "projects"
276
+ projects_dir = Path.home() / ".cdh" / "projects"
277
277
  projects_dir.mkdir(parents=True, exist_ok=True)
278
278
  proj_file = projects_dir / f"{name}.yaml"
279
279
  if proj_file.exists():
@@ -301,7 +301,7 @@ class ProjectsApp(App):
301
301
  self.notify("No project selected", severity="warning")
302
302
  return
303
303
  name = item._name
304
- projects_dir = CLOUD_DEV_HARNESS_DIR / "projects"
304
+ projects_dir = Path.home() / ".cdh" / "projects"
305
305
  for ext in ["yaml", "yml", "json"]:
306
306
  pf = projects_dir / f"{name}.{ext}"
307
307
  if pf.exists():
@@ -332,7 +332,7 @@ class ProjectsApp(App):
332
332
  self.notify("No project selected", severity="warning")
333
333
  return
334
334
  name = item._name
335
- projects_dir = CLOUD_DEV_HARNESS_DIR / "projects"
335
+ projects_dir = Path.home() / ".cdh" / "projects"
336
336
  for ext in ["yaml", "yml", "json"]:
337
337
  pf = projects_dir / f"{name}.{ext}"
338
338
  if pf.exists():
@@ -1,3 +1,4 @@
1
+ from pathlib import Path
1
2
  from time import monotonic
2
3
 
3
4
  from textual.app import ComposeResult
@@ -10,8 +11,6 @@ from textual import containers
10
11
  from textual import on
11
12
 
12
13
 
13
- from onecode.config import CLOUD_DEV_HARNESS_DIR
14
-
15
14
  from tui.app import A2TUIApp
16
15
  from tui.widgets.grid_select import GridSelect
17
16
  from tui.widgets.project_grid_select import ProjectGridSelect
@@ -28,7 +27,7 @@ def _project_db_path(name: str):
28
27
  for *name* across all supported extensions, or ``None`` if the
29
28
  project is not registered yet.
30
29
  """
31
- projects_dir = CLOUD_DEV_HARNESS_DIR / "projects"
30
+ projects_dir = Path.home() / ".cdh" / "projects"
32
31
  for ext in ("yaml", "yml", "json"):
33
32
  pf = projects_dir / f"{name}.{ext}"
34
33
  if pf.exists():
@@ -61,7 +60,11 @@ class ProjectsScreen(ModalScreen[str]):
61
60
 
62
61
  @property
63
62
  def focus_chain(self) -> list[Widget]:
64
- return [self.project_grid_select]
63
+ return [
64
+ self.project_grid_select,
65
+ self.query_one("#new-project", widgets.Button),
66
+ self.query_one("#init-project", widgets.Button),
67
+ ]
65
68
 
66
69
  def action_delete_project(self) -> None:
67
70
  now = monotonic()
@@ -87,7 +90,7 @@ class ProjectsScreen(ModalScreen[str]):
87
90
  project_name = widget.id
88
91
  if project_name is None:
89
92
  return
90
- projects_dir = CLOUD_DEV_HARNESS_DIR / "projects"
93
+ projects_dir = Path.home() / ".cdh" / "projects"
91
94
  deleted = False
92
95
  for ext in ["yaml", "yml", "json"]:
93
96
  pf = projects_dir / f"{project_name}.{ext}"
@@ -96,7 +99,7 @@ class ProjectsScreen(ModalScreen[str]):
96
99
  deleted = True
97
100
  break
98
101
  if not deleted:
99
- self.notify(f"Project file not found", severity="error")
102
+ self.notify("Project file not found", severity="error")
100
103
  return
101
104
  widget.remove()
102
105
  self.notify(f"Deleted project: {project_name}")
@@ -139,7 +142,7 @@ class ProjectsScreen(ModalScreen[str]):
139
142
  lambda picked: self._on_new_project_components(target, picked),
140
143
  )
141
144
 
142
- def _on_new_project_components(
145
+ async def _on_new_project_components(
143
146
  self,
144
147
  target: "Path",
145
148
  picked: list[str] | None,
@@ -149,9 +152,9 @@ class ProjectsScreen(ModalScreen[str]):
149
152
  return
150
153
  if not picked:
151
154
  return
152
- self._do_new_project(target, picked)
155
+ await self._do_new_project(target, picked)
153
156
 
154
- def _do_new_project(
157
+ async def _do_new_project(
155
158
  self,
156
159
  target: "Path",
157
160
  components: list[str],
@@ -173,15 +176,14 @@ class ProjectsScreen(ModalScreen[str]):
173
176
  severity="error",
174
177
  )
175
178
  return
176
- projects_dir = CLOUD_DEV_HARNESS_DIR / "projects"
179
+ projects_dir = Path.home() / ".cdh" / "projects"
177
180
  projects_dir.mkdir(parents=True, exist_ok=True)
178
181
  proj_file = projects_dir / f"{name}.yaml"
179
182
  CdhProjectLoader.init_project(target, name)
180
183
  import yaml
181
184
  proj_data = {"name": name, "path": str(target), "description": ""}
182
185
  proj_file.write_text(yaml.dump(proj_data))
183
- widget = ProjectSummary(name, str(target), id=name)
184
- self.project_grid_select.mount(widget)
186
+ await self.project_grid_select.reload()
185
187
  self.project_grid_select.highlighted = len(self.project_grid_select.children) - 1
186
188
  self.notify(
187
189
  f"Created project '{name}' at {target} "
@@ -198,7 +200,7 @@ class ProjectsScreen(ModalScreen[str]):
198
200
  self._on_init_path,
199
201
  )
200
202
 
201
- def _on_init_path(self, path_str: str | None) -> None:
203
+ async def _on_init_path(self, path_str: str | None) -> None:
202
204
  from pathlib import Path
203
205
  from onecode.agent.cdh_loader import CdhProjectLoader
204
206
 
@@ -222,30 +224,9 @@ class ProjectsScreen(ModalScreen[str]):
222
224
  severity="warning",
223
225
  )
224
226
  return
225
- self.app.push_screen(
226
- ComponentPickerScreen(
227
- title="Init .cdh — Select Components",
228
- subtitle=(
229
- f"Directory: {target}\n"
230
- "Pick the components already present in this directory. "
231
- "Empty selection is allowed (no apps/ created)."
232
- ),
233
- allow_empty=True,
234
- ),
235
- lambda picked: self._on_init_components(target, picked),
236
- )
237
-
238
- def _on_init_components(
239
- self,
240
- target: "Path",
241
- picked: list[str] | None,
242
- ) -> None:
243
- if picked is None:
244
- self.notify("Init cancelled", severity="warning")
245
- return
246
- self._do_init_project(target, picked)
227
+ await self._do_init_project(target, [])
247
228
 
248
- def _do_init_project(
229
+ async def _do_init_project(
249
230
  self,
250
231
  target: "Path",
251
232
  components: list[str],
@@ -273,13 +254,12 @@ class ProjectsScreen(ModalScreen[str]):
273
254
  self.notify(str(e), severity="error")
274
255
  CdhProjectLoader.init_project(target, name)
275
256
  import yaml
276
- projects_dir = CLOUD_DEV_HARNESS_DIR / "projects"
257
+ projects_dir = Path.home() / ".cdh" / "projects"
277
258
  projects_dir.mkdir(parents=True, exist_ok=True)
278
259
  proj_file = projects_dir / f"{name}.yaml"
279
260
  proj_data = {"name": name, "path": str(target), "description": ""}
280
261
  proj_file.write_text(yaml.dump(proj_data))
281
- widget = ProjectSummary(name, str(target), id=name)
282
- self.project_grid_select.mount(widget)
262
+ await self.project_grid_select.reload()
283
263
  self.project_grid_select.highlighted = len(self.project_grid_select.children) - 1
284
264
  suffix = (
285
265
  f" (components: {', '.join(components)})"
@@ -12,10 +12,9 @@ from textual import containers
12
12
  from textual import on
13
13
 
14
14
 
15
- from onecode.config import CLOUD_DEV_HARNESS_DIR
16
-
17
15
  from tui.app import A2TUIApp
18
16
  from tui.db import DB
17
+ from tui.paths import get_sessions
19
18
  from tui.widgets.grid_select import GridSelect
20
19
  from tui.widgets.session_grid_select import (
21
20
  SessionGridSelect,
@@ -92,7 +91,7 @@ class SessionsScreen(ModalScreen[str]):
92
91
  await db.session_delete(session_pk)
93
92
 
94
93
  if agent_session_id:
95
- session_file = CLOUD_DEV_HARNESS_DIR / "sessions" / f"{agent_session_id}.json"
94
+ session_file = get_sessions() / f"{agent_session_id}.json"
96
95
  if session_file.exists():
97
96
  session_file.unlink()
98
97
 
@@ -145,9 +144,8 @@ class SessionsScreen(ModalScreen[str]):
145
144
  self.run_worker(self._load_historical_sessions())
146
145
 
147
146
  async def _on_screen_resume(self, event: ScreenResume) -> None:
147
+ await self._load_historical_sessions()
148
148
  current_mode = self.app.screen_stack[0].id
149
- for instructions in self.query(".instructions"):
150
- instructions.display = not self.session_grid_select.children
151
149
  if current_mode is not None:
152
150
  self.session_grid_select.update_current(current_mode)
153
151
 
@@ -421,7 +421,7 @@ class StoreScreen(Screen):
421
421
  async def on_mount(self) -> None:
422
422
  self.app.settings_changed_signal.subscribe(self, self.setting_updated)
423
423
  if not self.app.settings.get("launcher.agents", str).strip():
424
- self.app.settings.set("launcher.agents", "cdh.cloud-dev-harness")
424
+ self.app.settings.set("launcher.agents", "onecode.dev")
425
425
  await self.app.save_settings()
426
426
  try:
427
427
  self._agents = await read_agents()
@@ -77,6 +77,7 @@ class SessionTracker:
77
77
  subtitle: str | None = None,
78
78
  path: str | None = None,
79
79
  state: SessionState | None = None,
80
+ session_pk: int | None = None,
80
81
  ) -> SessionDetails:
81
82
  session_details = self.sessions[mode_name]
82
83
  if title is not None:
@@ -87,6 +88,8 @@ class SessionTracker:
87
88
  session_details.path = path
88
89
  if state is not None:
89
90
  session_details.state = state
91
+ if session_pk is not None:
92
+ session_details.session_pk = session_pk
90
93
  self.signal.publish((mode_name, session_details))
91
94
  return session_details
92
95
 
@@ -261,7 +261,7 @@ SCHEMA: list[SchemaDict] = [
261
261
  "title": "Tool content max height",
262
262
  "help": "Max height of expanded tool content as a percentage of viewport height (0 = no limit).",
263
263
  "type": "integer",
264
- "default": 60,
264
+ "default": 30,
265
265
  "validate": [{"type": "minimum", "value": 0}, {"type": "maximum", "value": 100}],
266
266
  },
267
267
  ],
@@ -363,7 +363,7 @@ SCHEMA: list[SchemaDict] = [
363
363
  "key": "agents",
364
364
  "title": "Agents to show in the launcher",
365
365
  "type": "text",
366
- "default": "cdh.cloud-dev-harness",
366
+ "default": "onecode.dev",
367
367
  }
368
368
  ],
369
369
  },
@@ -1,6 +1,6 @@
1
1
  from __future__ import annotations
2
2
 
3
- from typing import Iterable, Iterator, Literal
3
+ from typing import Iterator, Literal
4
4
  from fractions import Fraction
5
5
 
6
6
  import rich.repr
@@ -16,7 +16,6 @@ from textual.style import Style
16
16
  from tui._loop import loop_last
17
17
 
18
18
 
19
- from textual._profile import timer
20
19
 
21
20
 
22
21
  @rich.repr.auto
@@ -1,6 +1,5 @@
1
1
  from textual.reactive import var
2
2
  from textual.widget import Widget
3
- from textual.widgets import Markdown
4
3
  from textual.widgets.markdown import MarkdownStream
5
4
 
6
5
  from tui.conversation_markdown import ConversationMarkdown
@@ -9,7 +9,6 @@ from textual.reactive import reactive
9
9
  from textual.widgets import Markdown, Static
10
10
  from textual.widgets.markdown import MarkdownStream
11
11
 
12
- from tui.protocol import ExpandProtocol
13
12
 
14
13
 
15
14
  class AgentThought(Vertical, can_focus=True):