@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
@@ -0,0 +1,39 @@
1
+ from __future__ import annotations
2
+
3
+ import re
4
+ from typing import Any
5
+
6
+
7
+ _PATH_RE = re.compile(r'\$path')
8
+ _ARG_RE = re.compile(r'\$(\d+)')
9
+ _ARGS_RE = re.compile(r'\$ARGUMENTS')
10
+
11
+
12
+ def substitute_arguments(content: str, arguments: list[str] | None = None) -> str:
13
+ """Substitute positional arguments in skill content.
14
+
15
+ Supports:
16
+ $path -> first argument
17
+ $0, $1, $2 -> positional arguments
18
+ $ARGUMENTS -> all arguments joined by space
19
+ """
20
+ args = arguments or []
21
+ text = content
22
+
23
+ # $path -> first argument
24
+ if args:
25
+ text = _PATH_RE.sub(args[0], text)
26
+ else:
27
+ text = _PATH_RE.sub("", text)
28
+
29
+ # $0, $1, $2...
30
+ def _replace_arg(m: re.Match) -> str:
31
+ idx = int(m.group(1))
32
+ return args[idx] if idx < len(args) else ""
33
+
34
+ text = _ARG_RE.sub(_replace_arg, text)
35
+
36
+ # $ARGUMENTS -> all joined
37
+ text = _ARGS_RE.sub(" ".join(args), text)
38
+
39
+ return text
@@ -0,0 +1,56 @@
1
+ from __future__ import annotations
2
+
3
+ from pathlib import Path
4
+ from typing import Optional
5
+
6
+ import yaml
7
+
8
+
9
+ SKILL_TEMPLATE = """---
10
+ name: {name}
11
+ description: {description}
12
+ enabled: true
13
+ ---
14
+
15
+ # {name} Skill
16
+
17
+ ## Description
18
+ {description}
19
+
20
+ ## Usage
21
+ When the user asks about {name}, follow these instructions:
22
+
23
+ ## Guidelines
24
+ - Follow the project conventions
25
+ - Use appropriate tools
26
+ """
27
+
28
+
29
+ def create_skill_scaffold(
30
+ skills_dir: Path,
31
+ name: str,
32
+ description: str = "",
33
+ ) -> Optional[str]:
34
+ """Create a new skill directory with SKILL.md and skill.yaml.
35
+
36
+ Returns error message or None on success.
37
+ """
38
+ skill_path = skills_dir / name
39
+ if skill_path.exists():
40
+ return f"Skill '{name}' already exists at {skill_path}"
41
+
42
+ skill_path.mkdir(parents=True, exist_ok=True)
43
+
44
+ skill_md = skill_path / "SKILL.md"
45
+ skill_md.write_text(
46
+ SKILL_TEMPLATE.format(name=name, description=description or f"A skill for {name}"),
47
+ encoding="utf-8",
48
+ )
49
+
50
+ skill_yaml = skill_path / "skill.yaml"
51
+ skill_yaml.write_text(
52
+ yaml.dump({"name": name, "description": description, "enabled": True}, default_flow_style=False),
53
+ encoding="utf-8",
54
+ )
55
+
56
+ return None
@@ -0,0 +1,33 @@
1
+ from __future__ import annotations
2
+
3
+ import re
4
+ from typing import Any
5
+
6
+ import yaml
7
+
8
+
9
+ _FRONTMATTER_RE = re.compile(
10
+ r'^---\s*\n(.*?)\n---\s*\n?',
11
+ re.DOTALL,
12
+ )
13
+
14
+
15
+ def parse_frontmatter(text: str) -> tuple[dict[str, Any], str]:
16
+ """Parse YAML frontmatter from markdown text.
17
+
18
+ Returns (frontmatter_dict, body_text). If no frontmatter,
19
+ frontmatter_dict is empty and body_text is the full text.
20
+ """
21
+ match = _FRONTMATTER_RE.match(text)
22
+ if not match:
23
+ return {}, text
24
+
25
+ yaml_block = match.group(1)
26
+ body = text[match.end():]
27
+
28
+ try:
29
+ frontmatter = yaml.safe_load(yaml_block) or {}
30
+ except yaml.YAMLError:
31
+ frontmatter = {}
32
+
33
+ return frontmatter, body
@@ -0,0 +1,157 @@
1
+ from __future__ import annotations
2
+
3
+ import re
4
+ from pathlib import Path
5
+ from typing import Optional
6
+
7
+ import yaml
8
+
9
+ from onecode.skills.frontmatter import parse_frontmatter
10
+ from onecode.skills.model import Skill
11
+
12
+ from onecode.config import CLOUD_DEV_HARNESS_DIR
13
+
14
+
15
+ USER_SKILLS_DIR = CLOUD_DEV_HARNESS_DIR / "skills"
16
+
17
+
18
+ SKILL_LOCATIONS = [
19
+ ("user", USER_SKILLS_DIR),
20
+ (".opencode", ".opencode/skills"),
21
+ (".claude", ".claude/skills"),
22
+ (".agents", ".agents/skills"),
23
+ ]
24
+
25
+
26
+ class SkillLoader:
27
+ def __init__(self, workspace_root: Path | None = None):
28
+ self._workspace_root = workspace_root or Path.cwd()
29
+ self._cache: dict[str, Skill] | None = None
30
+
31
+ def _get_search_dirs(self) -> list[tuple[str, Path]]:
32
+ dirs = []
33
+ if USER_SKILLS_DIR.exists():
34
+ dirs.append(("user", USER_SKILLS_DIR))
35
+
36
+ # Built-in skills packaged with onecode
37
+ builtin_dir = Path(__file__).resolve().parent.parent / "builtin_skills"
38
+ if builtin_dir.exists():
39
+ dirs.append(("builtin", builtin_dir))
40
+
41
+ # Project root-level directories containing SKILL.md
42
+ try:
43
+ for d in sorted(self._workspace_root.iterdir()):
44
+ if d.is_dir() and (d / "SKILL.md").exists():
45
+ dirs.append(("project", self._workspace_root))
46
+ break
47
+ except Exception:
48
+ pass
49
+
50
+ search_paths = [
51
+ (".opencode", ".claude", ".agents"),
52
+ ]
53
+ for group in search_paths:
54
+ for name in group:
55
+ pattern = f"{name}/skills"
56
+ for parent in self._walk_up_parents():
57
+ candidate = parent / pattern
58
+ if candidate.exists():
59
+ dirs.append((f"{name}/skills", candidate))
60
+ break
61
+
62
+ return dirs
63
+
64
+ def _walk_up_parents(self):
65
+ current = self._workspace_root.resolve()
66
+ yield current
67
+ try:
68
+ git_root = next(
69
+ (p for p in current.parents if (p / ".git").exists() or (p / ".hg").exists()),
70
+ None,
71
+ )
72
+ if git_root:
73
+ yield git_root
74
+ except StopIteration:
75
+ pass
76
+ yield Path.home()
77
+
78
+ def _discover(self) -> dict[str, Skill]:
79
+ if self._cache is not None:
80
+ return self._cache
81
+
82
+ skills: dict[str, Skill] = {}
83
+ seen_names: set[str] = set()
84
+
85
+ for source, skills_dir in self._get_search_dirs():
86
+ if not skills_dir.exists():
87
+ continue
88
+ try:
89
+ for d in sorted(skills_dir.iterdir()):
90
+ if not d.is_dir():
91
+ continue
92
+ skill_md = d / "SKILL.md"
93
+ if not skill_md.exists():
94
+ continue
95
+
96
+ content = skill_md.read_text(encoding="utf-8")
97
+ cfg = {}
98
+ skill_yaml = d / "skill.yaml"
99
+ if skill_yaml.exists():
100
+ try:
101
+ cfg = yaml.safe_load(skill_yaml.read_text(encoding="utf-8")) or {}
102
+ except Exception:
103
+ cfg = {}
104
+
105
+ frontmatter, body = parse_frontmatter(content)
106
+
107
+ raw_name = frontmatter.get("name") or cfg.get("name") or d.name
108
+ name = raw_name.lower()
109
+
110
+ valid, err = Skill.validate_name(name)
111
+ if not valid:
112
+ continue
113
+
114
+ desc = frontmatter.get("description") or cfg.get("description", "")
115
+
116
+ skill = Skill(
117
+ name=name,
118
+ description=desc,
119
+ path=d,
120
+ enabled=frontmatter.get("enabled", cfg.get("enabled", True)),
121
+ allowed_tools=frontmatter.get("allowed_tools") or cfg.get("allowed_tools", []),
122
+ arguments=frontmatter.get("arguments") or cfg.get("arguments", []),
123
+ triggers=frontmatter.get("triggers") or cfg.get("triggers", []),
124
+ phases=frontmatter.get("phases") or cfg.get("phases", []),
125
+ content=body if body else content,
126
+ license=frontmatter.get("license") or cfg.get("license", ""),
127
+ compatibility=frontmatter.get("compatibility") or cfg.get("compatibility", ""),
128
+ metadata=frontmatter.get("metadata") or cfg.get("metadata", {}),
129
+ )
130
+
131
+ if name not in seen_names:
132
+ skills[name] = skill
133
+ seen_names.add(name)
134
+
135
+ except Exception:
136
+ continue
137
+
138
+ self._cache = skills
139
+ return skills
140
+
141
+ def get_all(self) -> dict[str, Skill]:
142
+ return self._discover()
143
+
144
+ def get(self, name: str) -> Optional[Skill]:
145
+ return self._discover().get(name.lower())
146
+
147
+ def get_enabled(self) -> list[Skill]:
148
+ return [s for s in self._discover().values() if s.enabled]
149
+
150
+ def get_by_source(self, source_prefix: str) -> list[Skill]:
151
+ return [
152
+ s for s in self._discover().values()
153
+ if s.path and str(s.path).startswith(source_prefix)
154
+ ]
155
+
156
+ def invalidate_cache(self) -> None:
157
+ self._cache = None
@@ -0,0 +1,75 @@
1
+ from __future__ import annotations
2
+
3
+ from pathlib import Path
4
+ from typing import Optional
5
+
6
+ import yaml
7
+
8
+ from onecode.config import CLOUD_DEV_HARNESS_DIR
9
+
10
+
11
+ class SkillManager:
12
+ def __init__(self):
13
+ self.skills_dir = CLOUD_DEV_HARNESS_DIR / "skills"
14
+ self.skills_dir.mkdir(parents=True, exist_ok=True)
15
+ self._skills: dict[str, dict] = {}
16
+
17
+ def install(self, path: Path) -> Optional[str]:
18
+ skill_yaml = path / "skill.yaml"
19
+ if not skill_yaml.exists():
20
+ return "skill.yaml not found"
21
+ data = yaml.safe_load(skill_yaml.read_text())
22
+ name = data.get("name", path.name)
23
+ target = self.skills_dir / name
24
+ target.mkdir(parents=True, exist_ok=True)
25
+ for src in path.iterdir():
26
+ (target / src.name).write_bytes(src.read_bytes())
27
+ self._skills[name] = data
28
+ return None
29
+
30
+ def list(self) -> list[dict]:
31
+ result = []
32
+ for d in self.skills_dir.iterdir():
33
+ if d.is_dir():
34
+ config_path = d / "skill.yaml"
35
+ if config_path.exists():
36
+ data = yaml.safe_load(config_path.read_text()) or {}
37
+ data["name"] = data.get("name", d.name)
38
+ data["enabled"] = data.get("enabled", True)
39
+ result.append(data)
40
+ return result
41
+
42
+ def enable(self, name: str, enabled: bool = True):
43
+ config_path = self.skills_dir / name / "skill.yaml"
44
+ if config_path.exists():
45
+ data = yaml.safe_load(config_path.read_text()) or {}
46
+ data["enabled"] = enabled
47
+ config_path.write_text(yaml.dump(data, default_flow_style=False))
48
+
49
+ def remove(self, name: str) -> Optional[str]:
50
+ """Remove a skill by name.
51
+
52
+ Returns error message or None on success.
53
+ """
54
+ skill_path = self.skills_dir / name
55
+ if not skill_path.exists():
56
+ return f"Skill '{name}' not found"
57
+ if not skill_path.is_dir():
58
+ return f"'{name}' is not a skill directory"
59
+ import shutil
60
+ shutil.rmtree(skill_path)
61
+ self._skills.pop(name, None)
62
+ return None
63
+
64
+ def get(self, name: str) -> Optional[dict]:
65
+ """Get a skill by name."""
66
+ if name in self._skills:
67
+ return self._skills[name]
68
+ skill_path = self.skills_dir / name / "skill.yaml"
69
+ if skill_path.exists():
70
+ data = yaml.safe_load(skill_path.read_text()) or {}
71
+ data["name"] = data.get("name", name)
72
+ data["enabled"] = data.get("enabled", True)
73
+ self._skills[name] = data
74
+ return data
75
+ return None
@@ -0,0 +1,43 @@
1
+ from __future__ import annotations
2
+
3
+ import re
4
+ from dataclasses import dataclass, field
5
+ from pathlib import Path
6
+ from typing import Any
7
+
8
+
9
+ SKILL_NAME_RE = re.compile(r"^[a-z0-9]+(-[a-z0-9]+)*$")
10
+
11
+
12
+ @dataclass
13
+ class Skill:
14
+ name: str
15
+ description: str = ""
16
+ path: Path | None = None
17
+ enabled: bool = True
18
+ allowed_tools: list[str] = field(default_factory=list)
19
+ arguments: list[dict[str, Any]] = field(default_factory=list)
20
+ triggers: list[str] = field(default_factory=list)
21
+ phases: list[str] = field(default_factory=list)
22
+ content: str = ""
23
+ license: str = ""
24
+ compatibility: str = ""
25
+ metadata: dict[str, str] = field(default_factory=dict)
26
+
27
+ @classmethod
28
+ def validate_name(cls, name: str) -> tuple[bool, str]:
29
+ if not name:
30
+ return False, "name is required"
31
+ if len(name) < 1 or len(name) > 64:
32
+ return False, "name must be 1-64 characters"
33
+ if not SKILL_NAME_RE.match(name):
34
+ return False, "name must be lowercase alphanumeric with single hyphens, cannot start/end with hyphen or have consecutive hyphens"
35
+ return True, ""
36
+
37
+ @classmethod
38
+ def validate_description(cls, desc: str) -> tuple[bool, str]:
39
+ if not desc:
40
+ return False, "description is required"
41
+ if len(desc) > 1024:
42
+ return False, "description must be 1-1024 characters"
43
+ return True, ""
File without changes
@@ -0,0 +1,64 @@
1
+ from __future__ import annotations
2
+
3
+ import json
4
+ import uuid
5
+ from datetime import datetime, timezone
6
+ from pathlib import Path
7
+ from typing import Optional
8
+
9
+ from sqlalchemy import Column, String, Text, DateTime, JSON, create_engine
10
+ from sqlalchemy.orm import declarative_base, sessionmaker
11
+
12
+ from onecode.config import CLOUD_DEV_HARNESS_DIR
13
+
14
+ Base = declarative_base()
15
+
16
+
17
+ class ActivityRecord(Base):
18
+ __tablename__ = "activities"
19
+
20
+ id = Column(String(36), primary_key=True, default=lambda: str(uuid.uuid4()))
21
+ event_type = Column(String(50), nullable=False)
22
+ project = Column(String(255), default="")
23
+ session = Column(String(36), default="")
24
+ details = Column(JSON, default=dict)
25
+ created_at = Column(DateTime, default=lambda: datetime.now(timezone.utc))
26
+
27
+
28
+ class ActivityRecorder:
29
+ def __init__(self, db_path: Optional[Path] = None):
30
+ if db_path is None:
31
+ db_path = CLOUD_DEV_HARNESS_DIR / "sessions" / "cdh.db"
32
+ db_path.parent.mkdir(parents=True, exist_ok=True)
33
+ self.engine = create_engine(f"sqlite:///{db_path}")
34
+ Base.metadata.create_all(self.engine)
35
+ self.Session = sessionmaker(bind=self.engine)
36
+
37
+ def record(self, event_type: str, project: str = "", session: str = "", details: Optional[dict] = None) -> str:
38
+ with self.Session() as s:
39
+ record = ActivityRecord(
40
+ event_type=event_type,
41
+ project=project,
42
+ session=session,
43
+ details=details or {},
44
+ )
45
+ s.add(record)
46
+ s.commit()
47
+ s.refresh(record)
48
+ return record.id
49
+
50
+ def list_activities(self, project: str = "", limit: int = 50) -> list[ActivityRecord]:
51
+ with self.Session() as s:
52
+ q = s.query(ActivityRecord).order_by(ActivityRecord.created_at.desc())
53
+ if project:
54
+ q = q.filter_by(project=project)
55
+ return q.limit(limit).all()
56
+
57
+ def list_by_session(self, session_id: str) -> list[ActivityRecord]:
58
+ with self.Session() as s:
59
+ return (
60
+ s.query(ActivityRecord)
61
+ .filter_by(session=session_id)
62
+ .order_by(ActivityRecord.created_at.desc())
63
+ .all()
64
+ )
@@ -0,0 +1,54 @@
1
+ from __future__ import annotations
2
+
3
+ from pathlib import Path
4
+ from typing import Optional
5
+
6
+ import yaml
7
+
8
+
9
+ class ProjectConfig:
10
+ def __init__(self, root: Path):
11
+ self.root = root
12
+ self.config_path = root / "cdh.project.yaml"
13
+ self._data: dict = {}
14
+ if self.config_path.exists():
15
+ self._data = yaml.safe_load(self.config_path.read_text()) or {}
16
+
17
+ def save(self):
18
+ self.config_path.write_text(yaml.dump(self._data, default_flow_style=False))
19
+
20
+ def get(self, key: str, default=None):
21
+ return self._data.get(key, default)
22
+
23
+ def set(self, key: str, value):
24
+ self._data[key] = value
25
+
26
+ @staticmethod
27
+ def create(name: str, path: Optional[Path] = None) -> ProjectConfig:
28
+ if path is None:
29
+ path = Path.cwd() / name
30
+ path.mkdir(parents=True, exist_ok=True)
31
+ config = ProjectConfig(path)
32
+ config._data = {"name": name, "version": "0.1.0"}
33
+ config.save()
34
+ return config
35
+
36
+ def tree(self, depth: int = 3) -> str:
37
+ lines = []
38
+ self._render_tree(self.root, "", depth, lines)
39
+ return "\n".join(lines)
40
+
41
+ def _render_tree(self, path: Path, prefix: str, depth: int, lines: list):
42
+ if depth < 0:
43
+ return
44
+ entries = sorted(
45
+ [e for e in path.iterdir() if not e.name.startswith(".") and e.name != "__pycache__"],
46
+ key=lambda e: (not e.is_dir(), e.name),
47
+ )
48
+ for i, entry in enumerate(entries):
49
+ is_last = i == len(entries) - 1
50
+ connector = "└── " if is_last else "├── "
51
+ lines.append(f"{prefix}{connector}{entry.name}{'/' if entry.is_dir() else ''}")
52
+ if entry.is_dir():
53
+ ext = " " if is_last else "│ "
54
+ self._render_tree(entry, prefix + ext, depth - 1, lines)
@@ -0,0 +1,113 @@
1
+ from __future__ import annotations
2
+
3
+ import json
4
+ import uuid
5
+ from datetime import datetime, timezone
6
+ from pathlib import Path
7
+ from typing import Optional
8
+
9
+ from sqlalchemy import (
10
+ Column,
11
+ String,
12
+ Text,
13
+ DateTime,
14
+ JSON,
15
+ create_engine,
16
+ )
17
+ from sqlalchemy.orm import declarative_base, Session as SASession, sessionmaker
18
+
19
+ from onecode.config import CLOUD_DEV_HARNESS_DIR
20
+
21
+ Base = declarative_base()
22
+
23
+
24
+ class SessionRecord(Base):
25
+ __tablename__ = "sessions"
26
+
27
+ id = Column(String(36), primary_key=True, default=lambda: str(uuid.uuid4()))
28
+ name = Column(String(255), default="Untitled")
29
+ mode = Column(String(50), default="build")
30
+ project = Column(String(255), default="")
31
+ model = Column(String(255), default="")
32
+ provider = Column(String(255), default="")
33
+ messages = Column(JSON, default=list)
34
+ lifecycle_state = Column(JSON, default=dict)
35
+ created_at = Column(DateTime, default=lambda: datetime.now(timezone.utc))
36
+ updated_at = Column(
37
+ DateTime,
38
+ default=lambda: datetime.now(timezone.utc),
39
+ onupdate=lambda: datetime.now(timezone.utc),
40
+ )
41
+
42
+
43
+ class SessionStore:
44
+ def __init__(self, db_path: Optional[Path] = None):
45
+ if db_path is None:
46
+ db_path = CLOUD_DEV_HARNESS_DIR / "sessions" / "cdh.db"
47
+ db_path.parent.mkdir(parents=True, exist_ok=True)
48
+ self.engine = create_engine(f"sqlite:///{db_path}")
49
+ Base.metadata.create_all(self.engine)
50
+ self.Session = sessionmaker(bind=self.engine)
51
+
52
+ def create(self, name: str = "Untitled", mode: str = "build", project: str = "") -> SessionRecord:
53
+ with self.Session() as session:
54
+ record = SessionRecord(name=name, mode=mode, project=project)
55
+ session.add(record)
56
+ session.commit()
57
+ session.refresh(record)
58
+ return record
59
+
60
+ def list_all(self) -> list[SessionRecord]:
61
+ with self.Session() as session:
62
+ return session.query(SessionRecord).order_by(SessionRecord.updated_at.desc()).all()
63
+
64
+ def list_by_project(self, project: str) -> list[SessionRecord]:
65
+ with self.Session() as session:
66
+ return (
67
+ session.query(SessionRecord)
68
+ .filter_by(project=project)
69
+ .order_by(SessionRecord.updated_at.desc())
70
+ .all()
71
+ )
72
+
73
+ def load(self, session_id: str) -> Optional[SessionRecord]:
74
+ with self.Session() as session:
75
+ return session.query(SessionRecord).filter_by(id=session_id).first()
76
+
77
+ def update(self, record: SessionRecord):
78
+ with self.Session() as s:
79
+ s.merge(record)
80
+ s.commit()
81
+
82
+ def delete(self, session_id: str):
83
+ with self.Session() as s:
84
+ record = s.query(SessionRecord).filter_by(id=session_id).first()
85
+ if record:
86
+ s.delete(record)
87
+ s.commit()
88
+
89
+ def rename(self, session_id: str, new_name: str):
90
+ with self.Session() as s:
91
+ record = s.query(SessionRecord).filter_by(id=session_id).first()
92
+ if record:
93
+ record.name = new_name
94
+ s.commit()
95
+
96
+ def export_json(self, session_id: str) -> Optional[str]:
97
+ record = self.load(session_id)
98
+ if not record:
99
+ return None
100
+ return json.dumps(
101
+ {
102
+ "id": record.id,
103
+ "name": record.name,
104
+ "mode": record.mode,
105
+ "project": record.project,
106
+ "model": record.model,
107
+ "messages": record.messages,
108
+ "created_at": record.created_at.isoformat() if record.created_at else None,
109
+ "updated_at": record.updated_at.isoformat() if record.updated_at else None,
110
+ },
111
+ indent=2,
112
+ ensure_ascii=False,
113
+ )
@@ -0,0 +1,26 @@
1
+ from onecode.tasks.models import (
2
+ TaskStatus,
3
+ TodoStatus,
4
+ TodoItem,
5
+ TaskChecklistState,
6
+ TaskGateRecord,
7
+ TaskToolCallSummary,
8
+ TaskTimelineEntry,
9
+ TaskRecord,
10
+ )
11
+ from onecode.tasks.manager import TaskManager, TaskExecutor, ExecutionTask, TaskExecutionResult
12
+
13
+ __all__ = [
14
+ "TaskStatus",
15
+ "TodoStatus",
16
+ "TodoItem",
17
+ "TaskChecklistState",
18
+ "TaskGateRecord",
19
+ "TaskToolCallSummary",
20
+ "TaskTimelineEntry",
21
+ "TaskRecord",
22
+ "TaskManager",
23
+ "TaskExecutor",
24
+ "ExecutionTask",
25
+ "TaskExecutionResult",
26
+ ]