@scemoon/cdh 1.0.0

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 (528) hide show
  1. package/ai-dlc-skill/SKILL.md +75 -0
  2. package/ai-dlc-skill/agents/deliver-agent.md +24 -0
  3. package/ai-dlc-skill/agents/master.md +44 -0
  4. package/ai-dlc-skill/agents/plan-agent.md +23 -0
  5. package/ai-dlc-skill/agents/understand-agent.md +23 -0
  6. package/ai-dlc-skill/agents/verify-agent.md +27 -0
  7. package/ai-dlc-skill/architecture/project-structure.md +78 -0
  8. package/ai-dlc-skill/brownfield/README.md +30 -0
  9. package/ai-dlc-skill/brownfield/generate-context.sh +64 -0
  10. package/ai-dlc-skill/brownfield/scripts/deps.sh +27 -0
  11. package/ai-dlc-skill/brownfield/scripts/discover.sh +34 -0
  12. package/ai-dlc-skill/brownfield/scripts/extract-api.sh +45 -0
  13. package/ai-dlc-skill/components/backend.md +34 -0
  14. package/ai-dlc-skill/components/desktop.md +30 -0
  15. package/ai-dlc-skill/components/mya.md +29 -0
  16. package/ai-dlc-skill/components/native.md +30 -0
  17. package/ai-dlc-skill/components/tta.md +29 -0
  18. package/ai-dlc-skill/components/web.md +31 -0
  19. package/ai-dlc-skill/components/wxa.md +29 -0
  20. package/ai-dlc-skill/contracts/README.md +25 -0
  21. package/ai-dlc-skill/core/adaptive-flow.md +36 -0
  22. package/ai-dlc-skill/core/security.md +29 -0
  23. package/ai-dlc-skill/cross-tool/cline/export.sh +31 -0
  24. package/ai-dlc-skill/cross-tool/copilot/export.sh +47 -0
  25. package/ai-dlc-skill/cross-tool/cursor/export.sh +32 -0
  26. package/ai-dlc-skill/cross-tool/export.sh +22 -0
  27. package/ai-dlc-skill/cross-tool/onecode/config.yaml.tpl +17 -0
  28. package/ai-dlc-skill/cross-tool/onecode/export-skills.sh +31 -0
  29. package/ai-dlc-skill/cross-tool/onecode/export.sh +48 -0
  30. package/ai-dlc-skill/phases/deliver/entry.md +26 -0
  31. package/ai-dlc-skill/phases/deliver/lifecycle.md +185 -0
  32. package/ai-dlc-skill/phases/deliver/prompt.md +40 -0
  33. package/ai-dlc-skill/phases/deliver/rules.md +61 -0
  34. package/ai-dlc-skill/phases/plan/entry.md +25 -0
  35. package/ai-dlc-skill/phases/plan/lifecycle.md +204 -0
  36. package/ai-dlc-skill/phases/plan/prompt.md +38 -0
  37. package/ai-dlc-skill/phases/plan/rules.md +25 -0
  38. package/ai-dlc-skill/phases/understand/entry.md +26 -0
  39. package/ai-dlc-skill/phases/understand/lifecycle.md +184 -0
  40. package/ai-dlc-skill/phases/understand/prompt.md +41 -0
  41. package/ai-dlc-skill/phases/understand/rules.md +37 -0
  42. package/ai-dlc-skill/phases/verify/entry.md +26 -0
  43. package/ai-dlc-skill/phases/verify/lifecycle.md +192 -0
  44. package/ai-dlc-skill/phases/verify/prompt.md +43 -0
  45. package/ai-dlc-skill/phases/verify/rules.md +73 -0
  46. package/ai-dlc-skill/practices/bdd.md +91 -0
  47. package/ai-dlc-skill/practices/sdd.md +84 -0
  48. package/ai-dlc-skill/practices/tdd.md +95 -0
  49. package/ai-dlc-skill/providers/README.md +114 -0
  50. package/ai-dlc-skill/providers/aliyun/deployment.yaml +66 -0
  51. package/ai-dlc-skill/providers/aliyun/preview.yaml +84 -0
  52. package/ai-dlc-skill/providers/aliyun/provider.yaml +160 -0
  53. package/ai-dlc-skill/providers/tcb/deployment.yaml +69 -0
  54. package/ai-dlc-skill/providers/tcb/preview.yaml +83 -0
  55. package/ai-dlc-skill/providers/tcb/provider.yaml +172 -0
  56. package/ai-dlc-skill/requirements.md +140 -0
  57. package/ai-dlc-skill/skill.yaml +147 -0
  58. package/ai-dlc-skill/templates/integration/CHANGELOG.md +41 -0
  59. package/ai-dlc-skill/templates/integration/asyncapi.yaml +43 -0
  60. package/ai-dlc-skill/templates/integration/contract-diff.md +63 -0
  61. package/ai-dlc-skill/templates/integration/contract-spec.md +49 -0
  62. package/ai-dlc-skill/templates/integration/openapi.yaml +18 -0
  63. package/ai-dlc-skill/templates/integration/runtime-contract.yaml +36 -0
  64. package/ai-dlc-skill/templates/plan/design.md +49 -0
  65. package/ai-dlc-skill/templates/plan/task-list.md +32 -0
  66. package/ai-dlc-skill/templates/project/README.md +127 -0
  67. package/ai-dlc-skill/templates/project/template.md +119 -0
  68. package/ai-dlc-skill/templates/understand/feature.feature +23 -0
  69. package/ai-dlc-skill/templates/understand/intent.md +29 -0
  70. package/ai-dlc-skill/templates/understand/spec-delta.md +47 -0
  71. package/ai-dlc-skill/templates/verify/test-unit.py +27 -0
  72. package/ai-dlc-skill/walkthrough/collect.sh +50 -0
  73. package/ai-dlc-skill/walkthrough/template.md +54 -0
  74. package/ai-dlc-skill/workflows/ai-dlc.yaml +110 -0
  75. package/ai-dlc-skill/workflows/deployment.yaml +199 -0
  76. package/cdh/__init__.py +0 -0
  77. package/cdh/__main__.py +4 -0
  78. package/cdh/__pycache__/__init__.cpython-313.pyc +0 -0
  79. package/cdh/__pycache__/__init__.cpython-314.pyc +0 -0
  80. package/cdh/__pycache__/cli.cpython-314.pyc +0 -0
  81. package/cdh/__pycache__/scaffold.cpython-313.pyc +0 -0
  82. package/cdh/__pycache__/scaffold.cpython-314.pyc +0 -0
  83. package/cdh/cli.py +361 -0
  84. package/cdh/scaffold.py +312 -0
  85. package/cli.js +2 -0
  86. package/onecode/__init__.py +1 -0
  87. package/onecode/__main__.py +4 -0
  88. package/onecode/__pycache__/__init__.cpython-314.pyc +0 -0
  89. package/onecode/__pycache__/cli.cpython-314.pyc +0 -0
  90. package/onecode/__pycache__/commands.cpython-314.pyc +0 -0
  91. package/onecode/__pycache__/config.cpython-314.pyc +0 -0
  92. package/onecode/__pycache__/config_screen.cpython-314.pyc +0 -0
  93. package/onecode/__pycache__/mock_data.cpython-314.pyc +0 -0
  94. package/onecode/agent/__init__.py +0 -0
  95. package/onecode/agent/__pycache__/__init__.cpython-314.pyc +0 -0
  96. package/onecode/agent/__pycache__/cdh_agent_acp.cpython-313.pyc +0 -0
  97. package/onecode/agent/__pycache__/cdh_agent_acp.cpython-314.pyc +0 -0
  98. package/onecode/agent/__pycache__/cdh_loader.cpython-314.pyc +0 -0
  99. package/onecode/agent/__pycache__/context.cpython-314.pyc +0 -0
  100. package/onecode/agent/__pycache__/engine.cpython-314.pyc +0 -0
  101. package/onecode/agent/__pycache__/harness_skill.cpython-314.pyc +0 -0
  102. package/onecode/agent/__pycache__/hooks.cpython-314.pyc +0 -0
  103. package/onecode/agent/__pycache__/onecode_agent_acp.cpython-314.pyc +0 -0
  104. package/onecode/agent/__pycache__/permissions.cpython-314.pyc +0 -0
  105. package/onecode/agent/__pycache__/permissions_store.cpython-314.pyc +0 -0
  106. package/onecode/agent/__pycache__/session.cpython-314.pyc +0 -0
  107. package/onecode/agent/agents/__init__.py +29 -0
  108. package/onecode/agent/agents/__pycache__/__init__.cpython-314.pyc +0 -0
  109. package/onecode/agent/agents/__pycache__/types.cpython-314.pyc +0 -0
  110. package/onecode/agent/agents/types.py +662 -0
  111. package/onecode/agent/attachments.py +113 -0
  112. package/onecode/agent/cdh_loader.py +262 -0
  113. package/onecode/agent/context.py +338 -0
  114. package/onecode/agent/engine.py +1894 -0
  115. package/onecode/agent/hooks.py +86 -0
  116. package/onecode/agent/onecode_agent_acp.py +2203 -0
  117. package/onecode/agent/permissions.py +151 -0
  118. package/onecode/agent/permissions_store.py +62 -0
  119. package/onecode/agent/session.py +186 -0
  120. package/onecode/agent/snapshot.py +145 -0
  121. package/onecode/agent/tools/__init__.py +17 -0
  122. package/onecode/agent/tools/__pycache__/__init__.cpython-314.pyc +0 -0
  123. package/onecode/agent/tools/__pycache__/agent_tools.cpython-314.pyc +0 -0
  124. package/onecode/agent/tools/__pycache__/apply_patch_tool.cpython-314.pyc +0 -0
  125. package/onecode/agent/tools/__pycache__/bash_tool.cpython-314.pyc +0 -0
  126. package/onecode/agent/tools/__pycache__/communication_tools.cpython-314.pyc +0 -0
  127. package/onecode/agent/tools/__pycache__/config_tool.cpython-314.pyc +0 -0
  128. package/onecode/agent/tools/__pycache__/cron_tools.cpython-314.pyc +0 -0
  129. package/onecode/agent/tools/__pycache__/errors.cpython-314.pyc +0 -0
  130. package/onecode/agent/tools/__pycache__/file_ops.cpython-314.pyc +0 -0
  131. package/onecode/agent/tools/__pycache__/file_tools.cpython-314.pyc +0 -0
  132. package/onecode/agent/tools/__pycache__/git_tools.cpython-314.pyc +0 -0
  133. package/onecode/agent/tools/__pycache__/lsp_tools.cpython-314.pyc +0 -0
  134. package/onecode/agent/tools/__pycache__/mcp_tools.cpython-314.pyc +0 -0
  135. package/onecode/agent/tools/__pycache__/permission_handler.cpython-314.pyc +0 -0
  136. package/onecode/agent/tools/__pycache__/permissions.cpython-314.pyc +0 -0
  137. package/onecode/agent/tools/__pycache__/protocol.cpython-314.pyc +0 -0
  138. package/onecode/agent/tools/__pycache__/registry.cpython-314.pyc +0 -0
  139. package/onecode/agent/tools/__pycache__/sandbox.cpython-314.pyc +0 -0
  140. package/onecode/agent/tools/__pycache__/schema_validation.cpython-314.pyc +0 -0
  141. package/onecode/agent/tools/__pycache__/skill_tools.cpython-314.pyc +0 -0
  142. package/onecode/agent/tools/__pycache__/task_tools.cpython-314.pyc +0 -0
  143. package/onecode/agent/tools/__pycache__/web_tools.cpython-314.pyc +0 -0
  144. package/onecode/agent/tools/agent_tools.py +134 -0
  145. package/onecode/agent/tools/apply_patch_tool.py +144 -0
  146. package/onecode/agent/tools/bash_tool.py +91 -0
  147. package/onecode/agent/tools/communication_tools.py +149 -0
  148. package/onecode/agent/tools/config_tool.py +130 -0
  149. package/onecode/agent/tools/cron_tools.py +179 -0
  150. package/onecode/agent/tools/errors.py +17 -0
  151. package/onecode/agent/tools/file_ops.py +187 -0
  152. package/onecode/agent/tools/file_tools.py +226 -0
  153. package/onecode/agent/tools/git_tools.py +88 -0
  154. package/onecode/agent/tools/lsp_tools.py +404 -0
  155. package/onecode/agent/tools/mcp_tools.py +129 -0
  156. package/onecode/agent/tools/permission_handler.py +46 -0
  157. package/onecode/agent/tools/permissions.py +77 -0
  158. package/onecode/agent/tools/protocol.py +20 -0
  159. package/onecode/agent/tools/registry.py +134 -0
  160. package/onecode/agent/tools/sandbox.py +264 -0
  161. package/onecode/agent/tools/schema_validation.py +100 -0
  162. package/onecode/agent/tools/skill_tools.py +52 -0
  163. package/onecode/agent/tools/task_tools.py +249 -0
  164. package/onecode/agent/tools/web_tools.py +170 -0
  165. package/onecode/builtin_skills/git/SKILL.md +64 -0
  166. package/onecode/builtin_skills/git/skill.yaml +7 -0
  167. package/onecode/builtin_skills/shell/SKILL.md +58 -0
  168. package/onecode/builtin_skills/shell/skill.yaml +8 -0
  169. package/onecode/cli.py +755 -0
  170. package/onecode/cloud/__init__.py +0 -0
  171. package/onecode/cloud/base.py +20 -0
  172. package/onecode/codebase/__init__.py +69 -0
  173. package/onecode/codebase/__pycache__/__init__.cpython-314.pyc +0 -0
  174. package/onecode/codebase/__pycache__/chunker.cpython-314.pyc +0 -0
  175. package/onecode/codebase/__pycache__/config.cpython-314.pyc +0 -0
  176. package/onecode/codebase/__pycache__/indexer.cpython-314.pyc +0 -0
  177. package/onecode/codebase/__pycache__/retriever.cpython-314.pyc +0 -0
  178. package/onecode/codebase/__pycache__/storage.cpython-314.pyc +0 -0
  179. package/onecode/codebase/__pycache__/tools.cpython-314.pyc +0 -0
  180. package/onecode/codebase/chunker.py +130 -0
  181. package/onecode/codebase/indexer.py +136 -0
  182. package/onecode/codebase/retriever.py +192 -0
  183. package/onecode/codebase/storage.py +130 -0
  184. package/onecode/codebase/tools.py +59 -0
  185. package/onecode/commands.py +276 -0
  186. package/onecode/config.py +285 -0
  187. package/onecode/config_screen.py +594 -0
  188. package/onecode/cron/__init__.py +3 -0
  189. package/onecode/lsp/__init__.py +3 -0
  190. package/onecode/mcp/__init__.py +4 -0
  191. package/onecode/mcp/__pycache__/__init__.cpython-314.pyc +0 -0
  192. package/onecode/mcp/__pycache__/client.cpython-314.pyc +0 -0
  193. package/onecode/mcp/__pycache__/manager.cpython-314.pyc +0 -0
  194. package/onecode/mcp/client.py +193 -0
  195. package/onecode/mcp/manager.py +191 -0
  196. package/onecode/memory/__init__.py +95 -0
  197. package/onecode/memory/__pycache__/__init__.cpython-314.pyc +0 -0
  198. package/onecode/memory/__pycache__/backend.cpython-314.pyc +0 -0
  199. package/onecode/memory/__pycache__/offload.cpython-314.pyc +0 -0
  200. package/onecode/memory/__pycache__/pyramid.cpython-314.pyc +0 -0
  201. package/onecode/memory/__pycache__/recall.cpython-314.pyc +0 -0
  202. package/onecode/memory/__pycache__/symbolic.cpython-314.pyc +0 -0
  203. package/onecode/memory/backend.py +185 -0
  204. package/onecode/memory/offload.py +114 -0
  205. package/onecode/memory/pyramid.py +202 -0
  206. package/onecode/memory/recall.py +168 -0
  207. package/onecode/memory/symbolic.py +164 -0
  208. package/onecode/models/__init__.py +4 -0
  209. package/onecode/models/__pycache__/__init__.cpython-314.pyc +0 -0
  210. package/onecode/models/__pycache__/errors.cpython-314.pyc +0 -0
  211. package/onecode/models/__pycache__/messages.cpython-314.pyc +0 -0
  212. package/onecode/models/__pycache__/provider.cpython-314.pyc +0 -0
  213. package/onecode/models/__pycache__/registry.cpython-314.pyc +0 -0
  214. package/onecode/models/errors.py +94 -0
  215. package/onecode/models/messages.py +662 -0
  216. package/onecode/models/provider.py +450 -0
  217. package/onecode/models/providers/__init__.py +17 -0
  218. package/onecode/models/providers/__pycache__/__init__.cpython-314.pyc +0 -0
  219. package/onecode/models/providers/__pycache__/anthropic_provider.cpython-314.pyc +0 -0
  220. package/onecode/models/providers/__pycache__/deepseek_provider.cpython-314.pyc +0 -0
  221. package/onecode/models/providers/__pycache__/glm_provider.cpython-314.pyc +0 -0
  222. package/onecode/models/providers/__pycache__/minimax_provider.cpython-314.pyc +0 -0
  223. package/onecode/models/providers/__pycache__/minimaxi_provider.cpython-314.pyc +0 -0
  224. package/onecode/models/providers/__pycache__/mock_provider.cpython-314.pyc +0 -0
  225. package/onecode/models/providers/__pycache__/ollama_provider.cpython-314.pyc +0 -0
  226. package/onecode/models/providers/__pycache__/openai_provider.cpython-314.pyc +0 -0
  227. package/onecode/models/providers/anthropic_provider.py +224 -0
  228. package/onecode/models/providers/deepseek_provider.py +210 -0
  229. package/onecode/models/providers/glm_provider.py +154 -0
  230. package/onecode/models/providers/minimax_provider.py +154 -0
  231. package/onecode/models/providers/minimaxi_provider.py +363 -0
  232. package/onecode/models/providers/ollama_provider.py +96 -0
  233. package/onecode/models/providers/openai_provider.py +233 -0
  234. package/onecode/models/registry.py +212 -0
  235. package/onecode/server/__init__.py +3 -0
  236. package/onecode/server/app.py +224 -0
  237. package/onecode/skills/__init__.py +11 -0
  238. package/onecode/skills/__pycache__/__init__.cpython-314.pyc +0 -0
  239. package/onecode/skills/__pycache__/argument_substitution.cpython-314.pyc +0 -0
  240. package/onecode/skills/__pycache__/create.cpython-314.pyc +0 -0
  241. package/onecode/skills/__pycache__/frontmatter.cpython-314.pyc +0 -0
  242. package/onecode/skills/__pycache__/loader.cpython-314.pyc +0 -0
  243. package/onecode/skills/__pycache__/manager.cpython-314.pyc +0 -0
  244. package/onecode/skills/__pycache__/model.cpython-314.pyc +0 -0
  245. package/onecode/skills/argument_substitution.py +39 -0
  246. package/onecode/skills/create.py +56 -0
  247. package/onecode/skills/frontmatter.py +33 -0
  248. package/onecode/skills/loader.py +157 -0
  249. package/onecode/skills/manager.py +75 -0
  250. package/onecode/skills/model.py +43 -0
  251. package/onecode/storage/__init__.py +0 -0
  252. package/onecode/storage/activity.py +64 -0
  253. package/onecode/storage/project.py +54 -0
  254. package/onecode/storage/session.py +113 -0
  255. package/onecode/tasks/__init__.py +26 -0
  256. package/onecode/tasks/manager.py +219 -0
  257. package/onecode/tasks/models.py +240 -0
  258. package/onecode/trace/__init__.py +0 -0
  259. package/onecode/trace/tracer.py +174 -0
  260. package/onecode/utils/__init__.py +0 -0
  261. package/onecode/utils/helpers.py +20 -0
  262. package/onecode-cli.js +2 -0
  263. package/package.json +32 -0
  264. package/pyproject.toml +60 -0
  265. package/run.js +86 -0
  266. package/tui/__init__.py +46 -0
  267. package/tui/__main__.py +4 -0
  268. package/tui/__pycache__/__init__.cpython-314.pyc +0 -0
  269. package/tui/__pycache__/_loop.cpython-314.pyc +0 -0
  270. package/tui/__pycache__/_path_fuzzy_search.cpython-314.pyc +0 -0
  271. package/tui/__pycache__/_path_match.cpython-314.pyc +0 -0
  272. package/tui/__pycache__/agent.cpython-314.pyc +0 -0
  273. package/tui/__pycache__/agent_schema.cpython-314.pyc +0 -0
  274. package/tui/__pycache__/agents.cpython-314.pyc +0 -0
  275. package/tui/__pycache__/answer.cpython-314.pyc +0 -0
  276. package/tui/__pycache__/app.cpython-314.pyc +0 -0
  277. package/tui/__pycache__/atomic.cpython-314.pyc +0 -0
  278. package/tui/__pycache__/complete.cpython-314.pyc +0 -0
  279. package/tui/__pycache__/constants.cpython-314.pyc +0 -0
  280. package/tui/__pycache__/conversation_markdown.cpython-314.pyc +0 -0
  281. package/tui/__pycache__/danger.cpython-314.pyc +0 -0
  282. package/tui/__pycache__/db.cpython-314.pyc +0 -0
  283. package/tui/__pycache__/dec.cpython-314.pyc +0 -0
  284. package/tui/__pycache__/directory.cpython-314.pyc +0 -0
  285. package/tui/__pycache__/directory_suggester.cpython-314.pyc +0 -0
  286. package/tui/__pycache__/directory_watcher.cpython-314.pyc +0 -0
  287. package/tui/__pycache__/format_path.cpython-314.pyc +0 -0
  288. package/tui/__pycache__/fuzzy.cpython-314.pyc +0 -0
  289. package/tui/__pycache__/fuzzy_index.cpython-314.pyc +0 -0
  290. package/tui/__pycache__/history.cpython-314.pyc +0 -0
  291. package/tui/__pycache__/jsonrpc.cpython-314.pyc +0 -0
  292. package/tui/__pycache__/menus.cpython-314.pyc +0 -0
  293. package/tui/__pycache__/message_log.cpython-314.pyc +0 -0
  294. package/tui/__pycache__/messages.cpython-314.pyc +0 -0
  295. package/tui/__pycache__/path_complete.cpython-314.pyc +0 -0
  296. package/tui/__pycache__/path_filter.cpython-314.pyc +0 -0
  297. package/tui/__pycache__/paths.cpython-314.pyc +0 -0
  298. package/tui/__pycache__/pill.cpython-314.pyc +0 -0
  299. package/tui/__pycache__/platform_commands.cpython-314.pyc +0 -0
  300. package/tui/__pycache__/protocol.cpython-314.pyc +0 -0
  301. package/tui/__pycache__/session_tracker.cpython-314.pyc +0 -0
  302. package/tui/__pycache__/settings.cpython-314.pyc +0 -0
  303. package/tui/__pycache__/settings_schema.cpython-314.pyc +0 -0
  304. package/tui/__pycache__/shell.cpython-314.pyc +0 -0
  305. package/tui/__pycache__/shell_read.cpython-314.pyc +0 -0
  306. package/tui/__pycache__/slash_command.cpython-314.pyc +0 -0
  307. package/tui/__pycache__/version.cpython-314.pyc +0 -0
  308. package/tui/_loop.py +86 -0
  309. package/tui/_path_fuzzy_search.py +48 -0
  310. package/tui/_path_match.py +141 -0
  311. package/tui/about.py +95 -0
  312. package/tui/acp/__pycache__/agent.cpython-314.pyc +0 -0
  313. package/tui/acp/__pycache__/api.cpython-314.pyc +0 -0
  314. package/tui/acp/__pycache__/encode_tool_call_id.cpython-314.pyc +0 -0
  315. package/tui/acp/__pycache__/messages.cpython-314.pyc +0 -0
  316. package/tui/acp/__pycache__/prompt.cpython-314.pyc +0 -0
  317. package/tui/acp/__pycache__/protocol.cpython-314.pyc +0 -0
  318. package/tui/acp/agent.py +886 -0
  319. package/tui/acp/api.py +55 -0
  320. package/tui/acp/encode_tool_call_id.py +12 -0
  321. package/tui/acp/messages.py +190 -0
  322. package/tui/acp/prompt.py +110 -0
  323. package/tui/acp/protocol.py +462 -0
  324. package/tui/agent.py +70 -0
  325. package/tui/agent_schema.py +76 -0
  326. package/tui/agents.py +45 -0
  327. package/tui/ansi/__init__.py +1 -0
  328. package/tui/ansi/__pycache__/__init__.cpython-314.pyc +0 -0
  329. package/tui/ansi/__pycache__/_ansi.cpython-314.pyc +0 -0
  330. package/tui/ansi/__pycache__/_ansi_colors.cpython-314.pyc +0 -0
  331. package/tui/ansi/__pycache__/_control_codes.cpython-314.pyc +0 -0
  332. package/tui/ansi/__pycache__/_keys.cpython-314.pyc +0 -0
  333. package/tui/ansi/__pycache__/_sgr_styles.cpython-314.pyc +0 -0
  334. package/tui/ansi/__pycache__/_stream_parser.cpython-314.pyc +0 -0
  335. package/tui/ansi/_ansi.py +1689 -0
  336. package/tui/ansi/_ansi_colors.py +264 -0
  337. package/tui/ansi/_control_codes.py +37 -0
  338. package/tui/ansi/_keys.py +251 -0
  339. package/tui/ansi/_sgr_styles.py +64 -0
  340. package/tui/ansi/_stream_parser.py +418 -0
  341. package/tui/answer.py +12 -0
  342. package/tui/app.py +1236 -0
  343. package/tui/atomic.py +37 -0
  344. package/tui/cli.py +313 -0
  345. package/tui/code_analyze.py +27 -0
  346. package/tui/complete.py +38 -0
  347. package/tui/constants.py +61 -0
  348. package/tui/conversation_markdown.py +30 -0
  349. package/tui/danger.py +372 -0
  350. package/tui/data/agents/ampcode.com.toml +51 -0
  351. package/tui/data/agents/augmentcode.com.toml +40 -0
  352. package/tui/data/agents/cdh.cloud-dev-harness.toml +22 -0
  353. package/tui/data/agents/claude.com.toml +41 -0
  354. package/tui/data/agents/copilot.github.com.toml +29 -0
  355. package/tui/data/agents/crowai.dev.toml +35 -0
  356. package/tui/data/agents/cursor.com.toml +38 -0
  357. package/tui/data/agents/deepagents.langchain.com +33 -0
  358. package/tui/data/agents/docker.com.toml +59 -0
  359. package/tui/data/agents/geminicli.com.toml +28 -0
  360. package/tui/data/agents/goose.ai.toml +51 -0
  361. package/tui/data/agents/inference.huggingface.co.toml +41 -0
  362. package/tui/data/agents/kimi.com.toml +35 -0
  363. package/tui/data/agents/kiro.dev.toml +42 -0
  364. package/tui/data/agents/openai.com.toml +53 -0
  365. package/tui/data/agents/openclaw.ai.toml +37 -0
  366. package/tui/data/agents/opencode.ai.toml +39 -0
  367. package/tui/data/agents/openhands.dev.toml +45 -0
  368. package/tui/data/agents/stakpak.dev.toml +61 -0
  369. package/tui/data/agents/vibe.mistral.ai.toml +30 -0
  370. package/tui/data/agents/vtcode.dev.toml +62 -0
  371. package/tui/data/images/frog.png +0 -0
  372. package/tui/data/sounds/question.wav +0 -0
  373. package/tui/data/sounds/turn-over.wav +0 -0
  374. package/tui/db.py +190 -0
  375. package/tui/dec.py +332 -0
  376. package/tui/directory.py +234 -0
  377. package/tui/directory_suggester.py +93 -0
  378. package/tui/directory_watcher.py +197 -0
  379. package/tui/format_path.py +25 -0
  380. package/tui/fuzzy.py +140 -0
  381. package/tui/fuzzy_index.py +275 -0
  382. package/tui/gist.py +33 -0
  383. package/tui/history.py +138 -0
  384. package/tui/jsonrpc.py +578 -0
  385. package/tui/menus.py +14 -0
  386. package/tui/message_log.py +69 -0
  387. package/tui/messages.py +139 -0
  388. package/tui/option_content.py +51 -0
  389. package/tui/os.py +0 -0
  390. package/tui/path_complete.py +217 -0
  391. package/tui/path_filter.py +124 -0
  392. package/tui/paths.py +71 -0
  393. package/tui/pill.py +23 -0
  394. package/tui/platform_commands.py +52 -0
  395. package/tui/prompt/__pycache__/extract.cpython-314.pyc +0 -0
  396. package/tui/prompt/__pycache__/resource.cpython-314.pyc +0 -0
  397. package/tui/prompt/extract.py +19 -0
  398. package/tui/prompt/resource.py +68 -0
  399. package/tui/protocol.py +28 -0
  400. package/tui/screens/__init__.py +0 -0
  401. package/tui/screens/__pycache__/__init__.cpython-314.pyc +0 -0
  402. package/tui/screens/__pycache__/log.cpython-314.pyc +0 -0
  403. package/tui/screens/__pycache__/main.cpython-314.pyc +0 -0
  404. package/tui/screens/__pycache__/projects_screen.cpython-314.pyc +0 -0
  405. package/tui/screens/__pycache__/sessions.cpython-314.pyc +0 -0
  406. package/tui/screens/__pycache__/settings.cpython-314.pyc +0 -0
  407. package/tui/screens/__pycache__/store.cpython-314.pyc +0 -0
  408. package/tui/screens/action_modal.py +94 -0
  409. package/tui/screens/agent_modal.py +175 -0
  410. package/tui/screens/command_edit_modal.py +74 -0
  411. package/tui/screens/log.py +553 -0
  412. package/tui/screens/main.py +411 -0
  413. package/tui/screens/main.tcss +655 -0
  414. package/tui/screens/permissions.py +404 -0
  415. package/tui/screens/permissions.tcss +72 -0
  416. package/tui/screens/projects.tcss +66 -0
  417. package/tui/screens/projects_app.py +319 -0
  418. package/tui/screens/projects_screen.py +142 -0
  419. package/tui/screens/session_resume_modal.py +172 -0
  420. package/tui/screens/session_resume_modal.tcss +35 -0
  421. package/tui/screens/sessions.py +166 -0
  422. package/tui/screens/sessions.tcss +119 -0
  423. package/tui/screens/settings.py +254 -0
  424. package/tui/screens/settings.tcss +101 -0
  425. package/tui/screens/store.py +500 -0
  426. package/tui/screens/store.tcss +274 -0
  427. package/tui/screens/tool_content_screen.py +59 -0
  428. package/tui/session_tracker.py +120 -0
  429. package/tui/settings.py +353 -0
  430. package/tui/settings_schema.py +431 -0
  431. package/tui/shell.py +304 -0
  432. package/tui/shell_read.py +42 -0
  433. package/tui/slash_command.py +34 -0
  434. package/tui/tui.tcss +246 -0
  435. package/tui/twitter.py +38 -0
  436. package/tui/version.py +80 -0
  437. package/tui/visuals/__init__.py +0 -0
  438. package/tui/visuals/__pycache__/__init__.cpython-314.pyc +0 -0
  439. package/tui/visuals/__pycache__/columns.cpython-314.pyc +0 -0
  440. package/tui/visuals/columns.py +273 -0
  441. package/tui/widgets/__init__.py +0 -0
  442. package/tui/widgets/__pycache__/__init__.cpython-314.pyc +0 -0
  443. package/tui/widgets/__pycache__/acp_content.cpython-314.pyc +0 -0
  444. package/tui/widgets/__pycache__/agent_response.cpython-314.pyc +0 -0
  445. package/tui/widgets/__pycache__/agent_thought.cpython-314.pyc +0 -0
  446. package/tui/widgets/__pycache__/ask_user.cpython-314.pyc +0 -0
  447. package/tui/widgets/__pycache__/condensed_path.cpython-314.pyc +0 -0
  448. package/tui/widgets/__pycache__/context_stats.cpython-314.pyc +0 -0
  449. package/tui/widgets/__pycache__/conversation.cpython-313.pyc +0 -0
  450. package/tui/widgets/__pycache__/conversation.cpython-314.pyc +0 -0
  451. package/tui/widgets/__pycache__/diff_view.cpython-314.pyc +0 -0
  452. package/tui/widgets/__pycache__/directory_input.cpython-314.pyc +0 -0
  453. package/tui/widgets/__pycache__/flash.cpython-314.pyc +0 -0
  454. package/tui/widgets/__pycache__/future_text.cpython-314.pyc +0 -0
  455. package/tui/widgets/__pycache__/grid_select.cpython-314.pyc +0 -0
  456. package/tui/widgets/__pycache__/highlighted_textarea.cpython-314.pyc +0 -0
  457. package/tui/widgets/__pycache__/mandelbrot.cpython-314.pyc +0 -0
  458. package/tui/widgets/__pycache__/markdown_note.cpython-314.pyc +0 -0
  459. package/tui/widgets/__pycache__/menu.cpython-314.pyc +0 -0
  460. package/tui/widgets/__pycache__/modified_files.cpython-314.pyc +0 -0
  461. package/tui/widgets/__pycache__/non_selectable_label.cpython-314.pyc +0 -0
  462. package/tui/widgets/__pycache__/note.cpython-314.pyc +0 -0
  463. package/tui/widgets/__pycache__/path_search.cpython-314.pyc +0 -0
  464. package/tui/widgets/__pycache__/plan.cpython-314.pyc +0 -0
  465. package/tui/widgets/__pycache__/project_directory_tree.cpython-314.pyc +0 -0
  466. package/tui/widgets/__pycache__/project_grid_select.cpython-314.pyc +0 -0
  467. package/tui/widgets/__pycache__/project_summary.cpython-314.pyc +0 -0
  468. package/tui/widgets/__pycache__/prompt.cpython-314.pyc +0 -0
  469. package/tui/widgets/__pycache__/question.cpython-314.pyc +0 -0
  470. package/tui/widgets/__pycache__/session_grid_select.cpython-314.pyc +0 -0
  471. package/tui/widgets/__pycache__/session_summary.cpython-314.pyc +0 -0
  472. package/tui/widgets/__pycache__/session_tabs.cpython-314.pyc +0 -0
  473. package/tui/widgets/__pycache__/shell_result.cpython-314.pyc +0 -0
  474. package/tui/widgets/__pycache__/shell_terminal.cpython-314.pyc +0 -0
  475. package/tui/widgets/__pycache__/side_bar.cpython-314.pyc +0 -0
  476. package/tui/widgets/__pycache__/slash_complete.cpython-314.pyc +0 -0
  477. package/tui/widgets/__pycache__/strike_text.cpython-314.pyc +0 -0
  478. package/tui/widgets/__pycache__/subagent.cpython-314.pyc +0 -0
  479. package/tui/widgets/__pycache__/terminal.cpython-313.pyc +0 -0
  480. package/tui/widgets/__pycache__/terminal.cpython-314.pyc +0 -0
  481. package/tui/widgets/__pycache__/throbber.cpython-314.pyc +0 -0
  482. package/tui/widgets/__pycache__/tool_call.cpython-313.pyc +0 -0
  483. package/tui/widgets/__pycache__/tool_call.cpython-314.pyc +0 -0
  484. package/tui/widgets/__pycache__/user_input.cpython-314.pyc +0 -0
  485. package/tui/widgets/acp_content.py +70 -0
  486. package/tui/widgets/agent_response.py +77 -0
  487. package/tui/widgets/agent_thought.py +168 -0
  488. package/tui/widgets/ask_user.py +264 -0
  489. package/tui/widgets/command_pane.py +223 -0
  490. package/tui/widgets/condensed_path.py +115 -0
  491. package/tui/widgets/context_stats.py +66 -0
  492. package/tui/widgets/conversation.py +2441 -0
  493. package/tui/widgets/danger_warning.py +65 -0
  494. package/tui/widgets/diff_view.py +59 -0
  495. package/tui/widgets/directory_input.py +8 -0
  496. package/tui/widgets/flash.py +81 -0
  497. package/tui/widgets/future_text.py +126 -0
  498. package/tui/widgets/grid_select.py +234 -0
  499. package/tui/widgets/highlighted_textarea.py +180 -0
  500. package/tui/widgets/mandelbrot.py +294 -0
  501. package/tui/widgets/markdown_note.py +13 -0
  502. package/tui/widgets/menu.py +147 -0
  503. package/tui/widgets/modified_files.py +106 -0
  504. package/tui/widgets/non_selectable_label.py +5 -0
  505. package/tui/widgets/note.py +18 -0
  506. package/tui/widgets/path_search.py +492 -0
  507. package/tui/widgets/plan.py +263 -0
  508. package/tui/widgets/project_directory_tree.py +90 -0
  509. package/tui/widgets/project_grid_select.py +35 -0
  510. package/tui/widgets/project_summary.py +33 -0
  511. package/tui/widgets/prompt.py +795 -0
  512. package/tui/widgets/question.py +360 -0
  513. package/tui/widgets/session_grid_select.py +224 -0
  514. package/tui/widgets/session_summary.py +115 -0
  515. package/tui/widgets/session_tabs.py +188 -0
  516. package/tui/widgets/shell_result.py +35 -0
  517. package/tui/widgets/shell_terminal.py +40 -0
  518. package/tui/widgets/side_bar.py +114 -0
  519. package/tui/widgets/slash_complete.py +235 -0
  520. package/tui/widgets/strike_text.py +70 -0
  521. package/tui/widgets/subagent.py +87 -0
  522. package/tui/widgets/terminal.py +577 -0
  523. package/tui/widgets/terminal_tool.py +351 -0
  524. package/tui/widgets/throbber.py +100 -0
  525. package/tui/widgets/tool_call.py +368 -0
  526. package/tui/widgets/user_input.py +23 -0
  527. package/tui/widgets/version.py +5 -0
  528. package/tui/widgets/welcome.py +31 -0
package/onecode/cli.py ADDED
@@ -0,0 +1,755 @@
1
+ import click
2
+ import logging
3
+ from logging.handlers import TimedRotatingFileHandler
4
+ from pathlib import Path
5
+ from typing import Optional
6
+
7
+ from onecode.config import ensure_dirs, load_config, save_config
8
+
9
+ LOG_DIR = Path.home() / ".onecode" / "logs"
10
+ LOG_FILE = LOG_DIR / "cdh.log"
11
+ LOG_BACKUP_COUNT = 7 # keep 7 days of history
12
+
13
+ _VALID_LOG_LEVELS = {"DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"}
14
+
15
+
16
+ def setup_logging(log_level: str = "INFO") -> logging.Logger:
17
+ """Configure root logging to write to a daily-rotated ``cdh.log`` file.
18
+
19
+ The active log is always ``~/.onecode/logs/cdh.log``; at midnight it is
20
+ rolled to ``cdh.log.YYYY-MM-DD`` and a fresh file is started. Up to
21
+ :data:`LOG_BACKUP_COUNT` days of history are retained.
22
+
23
+ Returns the root logger so callers can attach additional handlers (e.g.
24
+ a console handler) without re-running ``basicConfig``.
25
+ """
26
+ LOG_DIR.mkdir(parents=True, exist_ok=True)
27
+ level = log_level.upper()
28
+ if level not in _VALID_LOG_LEVELS:
29
+ level = "INFO"
30
+ numeric_level = getattr(logging, level)
31
+
32
+ handler = TimedRotatingFileHandler(
33
+ LOG_FILE,
34
+ when="midnight",
35
+ interval=1,
36
+ backupCount=LOG_BACKUP_COUNT,
37
+ encoding="utf-8",
38
+ utc=False,
39
+ )
40
+ handler.suffix = "%Y-%m-%d"
41
+ handler.setFormatter(
42
+ logging.Formatter("%(asctime)s [%(name)s] %(levelname)s: %(message)s")
43
+ )
44
+
45
+ root = logging.getLogger()
46
+ root.setLevel(numeric_level)
47
+ # Avoid stacking handlers if setup_logging() is called twice (e.g. by
48
+ # tests importing both the CLI and a sub-process entry point).
49
+ for h in list(root.handlers):
50
+ if isinstance(h, TimedRotatingFileHandler) and getattr(h, "baseFilename", "") == str(LOG_FILE):
51
+ root.removeHandler(h)
52
+ root.addHandler(handler)
53
+
54
+ # Silence chatty third-party loggers; keep the rest at the requested level.
55
+ logging.getLogger("httpx").setLevel(logging.WARNING)
56
+ logging.getLogger("httpcore").setLevel(logging.WARNING)
57
+ # Engine / provider / adapter loggers — leave at the requested level
58
+ # (do NOT cap the entire ``onecode`` namespace at WARNING any more, that
59
+ # was the bug which kept ``cdh.log`` empty).
60
+ return root
61
+
62
+
63
+ @click.group()
64
+ @click.option(
65
+ "--log-level",
66
+ type=click.Choice(sorted(_VALID_LOG_LEVELS), case_sensitive=False),
67
+ default="INFO",
68
+ show_default=True,
69
+ envvar="CDH_LOG_LEVEL",
70
+ help="Root logger verbosity. Defaults to INFO; daily-rotated to ~/.onecode/logs/cdh.log.",
71
+ )
72
+ def cli(log_level: str):
73
+ """CDH Agent CLI - Cloud Dev Harness Agent commands."""
74
+ setup_logging(log_level)
75
+
76
+
77
+ @cli.group(invoke_without_command=True)
78
+ def config():
79
+ """Manage CDH configuration (mode, model, provider, cloud, skill, mcp)."""
80
+ pass
81
+
82
+
83
+ # --- config mode sub-command ---
84
+
85
+ @config.group("mode")
86
+ def config_mode():
87
+ """Manage default agent mode (build, plan, solo)."""
88
+ pass
89
+
90
+
91
+ @config_mode.command("get")
92
+ def config_mode_get():
93
+ """Show current mode."""
94
+ cfg = load_config()
95
+ click.echo(f"mode = {cfg.default_mode} (build | plan | solo)")
96
+
97
+
98
+ @config_mode.command("set")
99
+ @click.argument("value", default="build")
100
+ def config_mode_set(value):
101
+ """Set default agent mode."""
102
+ cfg = load_config()
103
+ cfg.default_mode = value
104
+ save_config(cfg)
105
+ click.echo(f"mode = {value}")
106
+
107
+
108
+ # --- config model sub-command ---
109
+
110
+ @config.group("model")
111
+ def config_model():
112
+ """Manage default LLM model."""
113
+ pass
114
+
115
+
116
+ @config_model.command("get")
117
+ def config_model_get():
118
+ """Show current model."""
119
+ cfg = load_config()
120
+ click.echo(f"model = {cfg.default_model}")
121
+
122
+
123
+ @config_model.command("set")
124
+ @click.argument("value")
125
+ def config_model_set(value):
126
+ """Set default LLM model."""
127
+ cfg = load_config()
128
+ cfg.default_model = value
129
+ save_config(cfg)
130
+ click.echo(f"model = {value}")
131
+
132
+
133
+ # --- config provider sub-command ---
134
+
135
+ @config.group("provider")
136
+ def config_provider():
137
+ """Manage default LLM provider."""
138
+ pass
139
+
140
+
141
+ @config_provider.command("get")
142
+ def config_provider_get():
143
+ """Show current provider."""
144
+ cfg = load_config()
145
+ click.echo(f"provider = {cfg.default_provider}")
146
+
147
+
148
+ @config_provider.command("set")
149
+ @click.argument("value")
150
+ def config_provider_set(value):
151
+ """Set default LLM provider."""
152
+ cfg = load_config()
153
+ cfg.default_provider = value
154
+ save_config(cfg)
155
+ click.echo(f"provider = {value}")
156
+
157
+
158
+ # --- config log-level sub-command ---
159
+
160
+ @config.group("log-level")
161
+ def config_log_level():
162
+ """Manage log level."""
163
+ pass
164
+
165
+
166
+ @config_log_level.command("get")
167
+ def config_log_level_get():
168
+ """Show current log level."""
169
+ cfg = load_config()
170
+ click.echo(f"log-level = {cfg.log_level} (debug | info | warn | error)")
171
+
172
+
173
+ @config_log_level.command("set")
174
+ @click.argument("value", default="info")
175
+ def config_log_level_set(value):
176
+ """Set log level."""
177
+ cfg = load_config()
178
+ cfg.log_level = value
179
+ save_config(cfg)
180
+ click.echo(f"log-level = {value}")
181
+
182
+
183
+ # --- config list ---
184
+
185
+ @config.command("list")
186
+ def config_list():
187
+ """Show full YAML configuration."""
188
+ cfg = load_config()
189
+ import yaml
190
+ from onecode.config import _dataclass_to_dict
191
+ click.echo(yaml.dump(_dataclass_to_dict(cfg), default_flow_style=False))
192
+
193
+
194
+ @cli.group(invoke_without_command=True)
195
+ def skill():
196
+ """Manage CDH skills (list, add, remove).
197
+
198
+ \b
199
+ Skills are instruction sets that extend the agent's capabilities.
200
+ Use `cdh skill list` to see available skills.
201
+ """
202
+ pass
203
+
204
+
205
+ @skill.command("list")
206
+ def skill_list():
207
+ """List all skills."""
208
+ from onecode.skills.loader import SkillLoader
209
+
210
+ loader = SkillLoader()
211
+ skills = loader.get_all()
212
+
213
+ if not skills:
214
+ click.echo("No skills found.")
215
+ return
216
+
217
+ click.echo("Skills:")
218
+ for s in skills.values():
219
+ status = "[enabled]" if s.enabled else "[disabled]"
220
+ click.echo(f" {status} {s.name}")
221
+ if s.description:
222
+ click.echo(f" {s.description}")
223
+ click.echo(f"\nTotal: {len(skills)} skill(s)")
224
+
225
+
226
+ @skill.command("add")
227
+ @click.argument("path", type=click.Path(exists=True, file_okay=True, dir_okay=True, path_type=Path))
228
+ def skill_add(path):
229
+ """Install a skill from a local path.
230
+
231
+ \b
232
+ The path should contain a skill.yaml and SKILL.md file.
233
+
234
+ \b
235
+ Example:
236
+ cdh skill add /path/to/my-skill
237
+ """
238
+ from onecode.skills.manager import SkillManager
239
+
240
+ skill_path = Path(path)
241
+ if skill_path.is_file():
242
+ skill_path = skill_path.parent
243
+
244
+ mgr = SkillManager()
245
+ err = mgr.install(skill_path)
246
+ if err:
247
+ click.echo(f"Error: {err}")
248
+ else:
249
+ click.echo(f"Skill installed from {skill_path}")
250
+
251
+
252
+ @skill.command("remove")
253
+ @click.argument("name")
254
+ def skill_remove(name):
255
+ """Remove an installed skill by name."""
256
+ from onecode.skills.manager import SkillManager
257
+
258
+ mgr = SkillManager()
259
+ err = mgr.remove(name)
260
+ if err:
261
+ click.echo(f"Error: {err}")
262
+ else:
263
+ click.echo(f"Skill '{name}' removed.")
264
+
265
+
266
+ @skill.command("enable")
267
+ @click.argument("name")
268
+ def skill_enable(name):
269
+ """Enable a skill by name."""
270
+ _toggle_skill(name, enabled=True)
271
+
272
+
273
+ @skill.command("disable")
274
+ @click.argument("name")
275
+ def skill_disable(name):
276
+ """Disable a skill by name."""
277
+ _toggle_skill(name, enabled=False)
278
+
279
+
280
+ def _toggle_skill(name: str, enabled: bool):
281
+ import yaml
282
+ from onecode.skills.loader import SkillLoader
283
+
284
+ loader = SkillLoader()
285
+ skill = loader.get(name)
286
+ if not skill or not skill.path:
287
+ click.echo(f"Skill '{name}' not found.")
288
+ return
289
+
290
+ skill_yaml = skill.path / "skill.yaml"
291
+ if not skill_yaml.exists():
292
+ click.echo(f"No skill.yaml found at {skill.path}")
293
+ return
294
+
295
+ data = yaml.safe_load(skill_yaml.read_text()) or {}
296
+ data["enabled"] = enabled
297
+ skill_yaml.write_text(yaml.dump(data, default_flow_style=False))
298
+ loader.invalidate_cache()
299
+ status = "enabled" if enabled else "disabled"
300
+ click.echo(f"Skill '{name}' {status}.")
301
+
302
+
303
+ @config.group("skill")
304
+ def config_skill():
305
+ """Manage CDH skills (alias for cdh skill)."""
306
+ pass
307
+
308
+
309
+ @config_skill.command("list")
310
+ def config_skill_list():
311
+ """List all skills."""
312
+ from onecode.skills.loader import SkillLoader
313
+
314
+ loader = SkillLoader()
315
+ skills = loader.get_all()
316
+
317
+ if not skills:
318
+ click.echo("No skills found.")
319
+ return
320
+
321
+ click.echo("Skills:")
322
+ for s in skills.values():
323
+ status = "[enabled]" if s.enabled else "[disabled]"
324
+ click.echo(f" {status} {s.name}")
325
+ if s.description:
326
+ click.echo(f" {s.description}")
327
+ click.echo(f"\nTotal: {len(skills)} skill(s)")
328
+
329
+
330
+ @config_skill.command("add")
331
+ @click.argument("path", type=click.Path(exists=True, file_okay=True, dir_okay=True, path_type=Path))
332
+ def config_skill_add(path):
333
+ """Install a skill from a local path."""
334
+ from onecode.skills.manager import SkillManager
335
+
336
+ skill_path = Path(path)
337
+ if skill_path.is_file():
338
+ skill_path = skill_path.parent
339
+
340
+ mgr = SkillManager()
341
+ err = mgr.install(skill_path)
342
+ if err:
343
+ click.echo(f"Error: {err}")
344
+ else:
345
+ click.echo(f"Skill installed from {skill_path}")
346
+
347
+
348
+ @config_skill.command("remove")
349
+ @click.argument("name")
350
+ def config_skill_remove(name):
351
+ """Remove an installed skill by name."""
352
+ from onecode.skills.manager import SkillManager
353
+
354
+ mgr = SkillManager()
355
+ err = mgr.remove(name)
356
+ if err:
357
+ click.echo(f"Error: {err}")
358
+ else:
359
+ click.echo(f"Skill '{name}' removed.")
360
+
361
+
362
+ @config_skill.command("enable")
363
+ @click.argument("name")
364
+ def config_skill_enable(name):
365
+ """Enable a skill by name."""
366
+ _toggle_skill(name, enabled=True)
367
+
368
+
369
+ @config_skill.command("disable")
370
+ @click.argument("name")
371
+ def config_skill_disable(name):
372
+ """Disable a skill by name."""
373
+ _toggle_skill(name, enabled=False)
374
+
375
+
376
+ @cli.group(invoke_without_command=True)
377
+ def mcp():
378
+ """Manage MCP (Model Context Protocol) servers.
379
+
380
+ \b
381
+ MCP servers expose tools and resources to the agent.
382
+ Use `cdh mcp list` to see configured servers.
383
+ """
384
+ pass
385
+
386
+
387
+ @mcp.command("list")
388
+ def mcp_list():
389
+ """List all configured MCP servers."""
390
+ from onecode.mcp.manager import MCPManager
391
+
392
+ mgr = MCPManager()
393
+ servers = mgr.list()
394
+
395
+ if not servers:
396
+ click.echo("No MCP servers configured. Use `cdh mcp add <name> <url>` to add one.")
397
+ return
398
+
399
+ click.echo("Configured MCP servers:")
400
+ for s in servers:
401
+ name = s.get("name", "unknown")
402
+ transport = s.get("transport", "sse")
403
+ enabled = s.get("enabled", True)
404
+ status = "[enabled]" if enabled else "[disabled]"
405
+ if transport == "sse":
406
+ url = s.get("url", "")
407
+ click.echo(f" {status} {name} (SSE)")
408
+ if url:
409
+ click.echo(f" URL: {url}")
410
+ else:
411
+ cmd = s.get("command", "")
412
+ args = " ".join(s.get("args", []))
413
+ click.echo(f" {status} {name} (stdio)")
414
+ if cmd:
415
+ click.echo(f" Command: {cmd} {args}")
416
+ click.echo(f"\nTotal: {len(servers)} server(s)")
417
+
418
+
419
+ @mcp.command("add")
420
+ @click.argument("name")
421
+ @click.argument("url")
422
+ @click.option("--type", "transport", default="sse", help="Transport type: sse or stdio")
423
+ @click.option("--command", help="Command for stdio transport")
424
+ @click.option("--args", help="Arguments for stdio transport (comma-separated)")
425
+ def mcp_add(name, url, transport, command, args):
426
+ """Add an MCP server configuration.
427
+
428
+ \b
429
+ For SSE transport (default):
430
+ cdh mcp add my-server https://example.com/mcp
431
+
432
+ \b
433
+ For stdio transport:
434
+ cdh mcp add my-server --type stdio --command npx --args "server-name"
435
+ """
436
+ from onecode.mcp.manager import MCPManager
437
+
438
+ mgr = MCPManager()
439
+ if mgr.get(name):
440
+ click.echo(f"Error: MCP server '{name}' already exists")
441
+ return
442
+
443
+ if transport == "stdio":
444
+ if not command:
445
+ click.echo("Error: --command required for stdio transport")
446
+ return
447
+ cmd_args = [a.strip() for a in args.split(",")] if args else []
448
+ mgr.add_stdio(name, command, cmd_args)
449
+ click.echo(f"MCP server '{name}' added (stdio)")
450
+ else:
451
+ mgr.add(name, url, transport="sse")
452
+ click.echo(f"MCP server '{name}' added (SSE) at {url}")
453
+
454
+
455
+ @mcp.command("remove")
456
+ @click.argument("name")
457
+ def mcp_remove(name):
458
+ """Remove an MCP server configuration."""
459
+ from onecode.mcp.manager import MCPManager
460
+
461
+ mgr = MCPManager()
462
+ err = mgr.remove(name)
463
+ if err:
464
+ click.echo(f"Error: MCP server '{name}' not found")
465
+ else:
466
+ click.echo(f"MCP server '{name}' removed.")
467
+
468
+
469
+ @mcp.command("enable")
470
+ @click.argument("name")
471
+ def mcp_enable(name):
472
+ """Enable an MCP server."""
473
+ from onecode.mcp.manager import MCPManager
474
+
475
+ mgr = MCPManager()
476
+ err = mgr.enable(name, True)
477
+ if err:
478
+ click.echo(f"Error: {err}")
479
+ else:
480
+ click.echo(f"MCP server '{name}' enabled.")
481
+
482
+
483
+ @mcp.command("disable")
484
+ @click.argument("name")
485
+ def mcp_disable(name):
486
+ """Disable an MCP server."""
487
+ from onecode.mcp.manager import MCPManager
488
+
489
+ mgr = MCPManager()
490
+ err = mgr.enable(name, False)
491
+ if err:
492
+ click.echo(f"Error: {err}")
493
+ else:
494
+ click.echo(f"MCP server '{name}' disabled.")
495
+
496
+
497
+ @config.group("mcp")
498
+ def config_mcp():
499
+ """Manage MCP servers (alias for cdh mcp)."""
500
+ pass
501
+
502
+
503
+ @config_mcp.command("list")
504
+ def config_mcp_list():
505
+ """List all configured MCP servers."""
506
+ from onecode.mcp.manager import MCPManager
507
+
508
+ mgr = MCPManager()
509
+ servers = mgr.list()
510
+
511
+ if not servers:
512
+ click.echo("No MCP servers configured. Use `cdh mcp add <name> <url>` to add one.")
513
+ return
514
+
515
+ click.echo("Configured MCP servers:")
516
+ for s in servers:
517
+ name = s.get("name", "unknown")
518
+ transport = s.get("transport", "sse")
519
+ enabled = s.get("enabled", True)
520
+ status = "[enabled]" if enabled else "[disabled]"
521
+ if transport == "sse":
522
+ url = s.get("url", "")
523
+ click.echo(f" {status} {name} (SSE)")
524
+ if url:
525
+ click.echo(f" URL: {url}")
526
+ else:
527
+ cmd = s.get("command", "")
528
+ args = " ".join(s.get("args", []))
529
+ click.echo(f" {status} {name} (stdio)")
530
+ if cmd:
531
+ click.echo(f" Command: {cmd} {args}")
532
+ click.echo(f"\nTotal: {len(servers)} server(s)")
533
+
534
+
535
+ @config_mcp.command("add")
536
+ @click.argument("name")
537
+ @click.argument("url")
538
+ @click.option("--type", "transport", default="sse", help="Transport type: sse or stdio")
539
+ @click.option("--command", help="Command for stdio transport")
540
+ @click.option("--args", help="Arguments for stdio transport (comma-separated)")
541
+ def config_mcp_add(name, url, transport, command, args):
542
+ """Add an MCP server configuration."""
543
+ from onecode.mcp.manager import MCPManager
544
+
545
+ mgr = MCPManager()
546
+ if mgr.get(name):
547
+ click.echo(f"Error: MCP server '{name}' already exists")
548
+ return
549
+
550
+ if transport == "stdio":
551
+ if not command:
552
+ click.echo("Error: --command required for stdio transport")
553
+ return
554
+ cmd_args = [a.strip() for a in args.split(",")] if args else []
555
+ mgr.add_stdio(name, command, cmd_args)
556
+ click.echo(f"MCP server '{name}' added (stdio)")
557
+ else:
558
+ mgr.add(name, url, transport="sse")
559
+ click.echo(f"MCP server '{name}' added (SSE) at {url}")
560
+
561
+
562
+ @config_mcp.command("remove")
563
+ @click.argument("name")
564
+ def config_mcp_remove(name):
565
+ """Remove an MCP server configuration."""
566
+ from onecode.mcp.manager import MCPManager
567
+
568
+ mgr = MCPManager()
569
+ err = mgr.remove(name)
570
+ if err:
571
+ click.echo(f"Error: MCP server '{name}' not found")
572
+ else:
573
+ click.echo(f"MCP server '{name}' removed.")
574
+
575
+
576
+ @config_mcp.command("enable")
577
+ @click.argument("name")
578
+ def config_mcp_enable(name):
579
+ """Enable an MCP server."""
580
+ from onecode.mcp.manager import MCPManager
581
+
582
+ mgr = MCPManager()
583
+ err = mgr.enable(name, True)
584
+ if err:
585
+ click.echo(f"Error: {err}")
586
+ else:
587
+ click.echo(f"MCP server '{name}' enabled.")
588
+
589
+
590
+ @config_mcp.command("disable")
591
+ @click.argument("name")
592
+ def config_mcp_disable(name):
593
+ """Disable an MCP server."""
594
+ from onecode.mcp.manager import MCPManager
595
+
596
+ mgr = MCPManager()
597
+ err = mgr.enable(name, False)
598
+ if err:
599
+ click.echo(f"Error: {err}")
600
+ else:
601
+ click.echo(f"MCP server '{name}' disabled.")
602
+
603
+
604
+ @cli.group(invoke_without_command=True)
605
+ def codebase():
606
+ """Manage codebase index and search.
607
+
608
+ \b
609
+ The codebase index enables semantic and keyword search over project files.
610
+ Use `cdh codebase index` to build or update the index, then the agent
611
+ can automatically retrieve relevant code when answering questions.
612
+ """
613
+ pass
614
+
615
+
616
+ @codebase.command("index")
617
+ @click.option("--force", is_flag=True, help="Rebuild index from scratch")
618
+ @click.option("--path", default=".", help="Project directory", show_default=True)
619
+ def codebase_index(force: bool, path: str):
620
+ """Index project files for codebase search."""
621
+ import asyncio
622
+ from onecode.codebase import CodebaseEngine, CodebaseConfig
623
+
624
+ project_dir = Path(path).resolve()
625
+ if not project_dir.is_dir():
626
+ click.echo(f"Error: {path} is not a valid directory")
627
+ return
628
+
629
+ cfg = load_config()
630
+ engine = CodebaseEngine(project_dir, cfg.codebase)
631
+ result = asyncio.run(engine.ensure_indexed(force=force))
632
+
633
+ total = result.total_files if hasattr(result, 'total_files') else 0
634
+ click.echo(
635
+ f"Indexed {project_dir.name}: "
636
+ f"{result.indexed_files} files, "
637
+ f"{result.total_chunks} chunks"
638
+ f"{' (forced rebuild)' if force else ''}"
639
+ )
640
+ if result.failed_files:
641
+ click.echo(f" Failed: {result.failed_files}")
642
+ for err in result.errors[:5]:
643
+ click.echo(f" {err}")
644
+
645
+
646
+ @codebase.command("status")
647
+ @click.option("--path", default=".", help="Project directory", show_default=True)
648
+ def codebase_status(path: str):
649
+ """Show codebase index status."""
650
+ from onecode.codebase import CodebaseStorage
651
+
652
+ project_dir = Path(path).resolve()
653
+ if not project_dir.is_dir():
654
+ click.echo(f"Error: {path} is not a valid directory")
655
+ return
656
+
657
+ storage = CodebaseStorage(project_dir)
658
+ chunk_count = storage.chunk_count()
659
+ file_count = storage.file_count()
660
+
661
+ click.echo(f"Codebase index for {project_dir.name}:")
662
+ click.echo(f" Files: {file_count}")
663
+ click.echo(f" Chunks: {chunk_count}")
664
+ if chunk_count == 0:
665
+ click.echo(" (not indexed yet — run `cdh codebase index`)")
666
+
667
+
668
+ @codebase.command("search")
669
+ @click.argument("query")
670
+ @click.option("--top-k", default=5, help="Number of results", show_default=True)
671
+ @click.option("--path", default=".", help="Project directory", show_default=True)
672
+ def codebase_search(query: str, top_k: int, path: str):
673
+ """Search indexed codebase."""
674
+ import asyncio
675
+ from onecode.codebase import CodebaseEngine
676
+
677
+ project_dir = Path(path).resolve()
678
+ if not project_dir.is_dir():
679
+ click.echo(f"Error: {path} is not a valid directory")
680
+ return
681
+
682
+ cfg = load_config()
683
+ engine = CodebaseEngine(project_dir, cfg.codebase)
684
+ chunks = asyncio.run(engine.retrieve(query, top_k=top_k))
685
+
686
+ if not chunks:
687
+ click.echo("No results found.")
688
+ return
689
+
690
+ click.echo(f"Top {len(chunks)} results for: {query}\n")
691
+ for i, c in enumerate(chunks, 1):
692
+ click.echo(f"[{i}] {c.file_path}:{c.start_line}-{c.end_line}")
693
+ click.echo("```")
694
+ click.echo(c.content[:300])
695
+ if len(c.content) > 300:
696
+ click.echo("...")
697
+ click.echo("```")
698
+ click.echo()
699
+
700
+
701
+ @codebase.command("reindex")
702
+ @click.option("--path", default=".", help="Project directory", show_default=True)
703
+ def codebase_reindex(path: str):
704
+ """Force rebuild the codebase index (alias for index --force)."""
705
+ import asyncio
706
+ from onecode.codebase import CodebaseEngine
707
+
708
+ project_dir = Path(path).resolve()
709
+ if not project_dir.is_dir():
710
+ click.echo(f"Error: {path} is not a valid directory")
711
+ return
712
+
713
+ cfg = load_config()
714
+ engine = CodebaseEngine(project_dir, cfg.codebase)
715
+ result = asyncio.run(engine.ensure_indexed(force=True))
716
+
717
+ click.echo(
718
+ f"Reindexed {project_dir.name}: "
719
+ f"{result.indexed_files} files, "
720
+ f"{result.total_chunks} chunks"
721
+ )
722
+
723
+
724
+ @cli.command()
725
+ @click.argument("command", required=False)
726
+ @click.option("--list", "list_commands", is_flag=True, help="List all available commands")
727
+ def help_cmd(command, list_commands):
728
+ """Show help for commands."""
729
+ if list_commands:
730
+ click.echo("Available commands:")
731
+ for name, cmd in cli.commands.items():
732
+ click.echo(f" {name:15} {cmd.help or ''}")
733
+ elif command:
734
+ cmd = cli.commands.get(command)
735
+ if cmd:
736
+ click.echo(cmd.get_help(click.Context(cmd)))
737
+ else:
738
+ click.echo(f"Unknown command: {command}")
739
+ else:
740
+ click.echo(cli.get_help(click.Context(cli)))
741
+
742
+
743
+ @cli.command()
744
+ def version():
745
+ """Show version info."""
746
+ from onecode import __version__
747
+ click.echo(f"onecode {__version__}")
748
+
749
+
750
+ def main():
751
+ cli()
752
+
753
+
754
+ if __name__ == "__main__":
755
+ main()