@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,151 @@
1
+ from __future__ import annotations
2
+
3
+ import fnmatch
4
+ import re
5
+ from dataclasses import dataclass, field
6
+ from enum import Enum
7
+ from pathlib import Path
8
+ from typing import Optional
9
+
10
+
11
+ class PermissionResult(Enum):
12
+ ALLOW = "allow"
13
+ DENY = "deny"
14
+ ASK = "ask"
15
+
16
+
17
+ @dataclass
18
+ class PathRule:
19
+ pattern: str
20
+ permission: PermissionResult = PermissionResult.ALLOW
21
+
22
+ def matches(self, path: str) -> bool:
23
+ return (
24
+ fnmatch.fnmatch(path, self.pattern) or
25
+ fnmatch.fnmatch(Path(path).name, self.pattern) or
26
+ fnmatch.fnmatch(Path(path).stem, self.pattern)
27
+ )
28
+
29
+
30
+ @dataclass
31
+ class CommandRule:
32
+ pattern: str
33
+ permission: PermissionResult = PermissionResult.ALLOW
34
+
35
+ def matches(self, cmd: str) -> bool:
36
+ normalized = cmd.strip()
37
+ if fnmatch.fnmatch(normalized, self.pattern):
38
+ return True
39
+ parts = normalized.split()
40
+ if parts:
41
+ cmd_base = parts[0]
42
+ args = " ".join(parts[1:]) if len(parts) > 1 else ""
43
+ if args and fnmatch.fnmatch(f"{cmd_base} {args}", self.pattern):
44
+ return True
45
+ if fnmatch.fnmatch(cmd_base, self.pattern):
46
+ return True
47
+ return False
48
+
49
+
50
+ @dataclass
51
+ class PermissionSet:
52
+ path_rules: list[PathRule] = field(default_factory=list)
53
+ command_rules: list[CommandRule] = field(default_factory=list)
54
+ default_path_permission: PermissionResult = PermissionResult.ALLOW
55
+ default_command_permission: PermissionResult = PermissionResult.ALLOW
56
+
57
+ def check_path(self, path: str) -> PermissionResult:
58
+ matched = self.default_path_permission
59
+ for rule in self.path_rules:
60
+ if rule.matches(path):
61
+ matched = rule.permission
62
+ return matched
63
+
64
+ def check_command(self, cmd: str) -> PermissionResult:
65
+ matched = self.default_command_permission
66
+ for rule in self.command_rules:
67
+ if rule.matches(cmd):
68
+ matched = rule.permission
69
+ return matched
70
+
71
+ def allow_path(self, pattern: str) -> None:
72
+ self.path_rules.append(PathRule(pattern, PermissionResult.ALLOW))
73
+
74
+ def deny_path(self, pattern: str) -> None:
75
+ self.path_rules.append(PathRule(pattern, PermissionResult.DENY))
76
+
77
+ def ask_path(self, pattern: str) -> None:
78
+ self.path_rules.append(PathRule(pattern, PermissionResult.ASK))
79
+
80
+ def allow_command(self, pattern: str) -> None:
81
+ self.command_rules.append(CommandRule(pattern, PermissionResult.ALLOW))
82
+
83
+ def deny_command(self, pattern: str) -> None:
84
+ self.command_rules.append(CommandRule(pattern, PermissionResult.DENY))
85
+
86
+ def ask_command(self, pattern: str) -> None:
87
+ self.command_rules.append(CommandRule(pattern, PermissionResult.ASK))
88
+
89
+ @classmethod
90
+ def from_config(cls, config: dict) -> "PermissionSet":
91
+ ps = cls()
92
+ perm_map = {"allow": PermissionResult.ALLOW, "ask": PermissionResult.ASK, "deny": PermissionResult.DENY}
93
+
94
+ if "path" in config:
95
+ for pattern, action in config["path"].items():
96
+ if action in perm_map:
97
+ getattr(ps, f"{action}_path")(pattern)
98
+
99
+ if "command" in config:
100
+ for pattern, action in config["command"].items():
101
+ if action in perm_map:
102
+ getattr(ps, f"{action}_command")(pattern)
103
+
104
+ if "default" in config:
105
+ default = config["default"]
106
+ if "path" in default and default["path"] in perm_map:
107
+ ps.default_path_permission = perm_map[default["path"]]
108
+ if "command" in default and default["command"] in perm_map:
109
+ ps.default_command_permission = perm_map[default["command"]]
110
+
111
+ return ps
112
+
113
+
114
+ class PermissionChecker:
115
+ def __init__(self, permission_set: Optional[PermissionSet] = None):
116
+ self.permission_set = permission_set or PermissionSet()
117
+
118
+ def check_file_read(self, path: str) -> PermissionResult:
119
+ return self.permission_set.check_path(path)
120
+
121
+ def check_file_write(self, path: str) -> PermissionResult:
122
+ return self.permission_set.check_path(path)
123
+
124
+ def check_command(self, cmd: str) -> PermissionResult:
125
+ return self.permission_set.check_command(cmd)
126
+
127
+ def is_allowed(self, permission: PermissionResult) -> bool:
128
+ return permission == PermissionResult.ALLOW
129
+
130
+ def is_denied(self, permission: PermissionResult) -> bool:
131
+ return permission == PermissionResult.DENY
132
+
133
+ def requires_approval(self, permission: PermissionResult) -> bool:
134
+ return permission == PermissionResult.ASK
135
+
136
+
137
+ def create_safe_permission_set() -> PermissionSet:
138
+ ps = PermissionSet()
139
+ ps.deny_path("**/.env")
140
+ ps.deny_path("**/secrets/**")
141
+ ps.deny_path("**/credentials/**")
142
+ ps.deny_command("rm -rf /")
143
+ ps.deny_command("rm -rf /*")
144
+ ps.deny_command("dd if=*")
145
+ ps.deny_command("mkfs.*")
146
+ ps.deny_command(":(){:|:&};:")
147
+ ps.ask_command("sudo *")
148
+ ps.ask_command("chmod 777 *")
149
+ ps.ask_command("curl *")
150
+ ps.ask_command("wget *")
151
+ return ps
@@ -0,0 +1,62 @@
1
+ from __future__ import annotations
2
+
3
+ from typing import Optional
4
+
5
+ from onecode.agent.agents.types import AgentPermission
6
+
7
+
8
+ class PermissionStore:
9
+ """Persists user-defined allow_always / reject_always overrides across
10
+ ``set_agent()`` calls so permissions survive mode switches.
11
+
12
+ Usage::
13
+
14
+ store = PermissionStore()
15
+ store.set_override("bash", AgentPermission.ALLOW) # user said "Allow always"
16
+ store.set_override("edit", AgentPermission.DENY) # user said "Reject always"
17
+ ...
18
+ store.apply_to(current_agent) # re-apply after set_agent
19
+ """
20
+
21
+ def __init__(self) -> None:
22
+ # perm_key → AgentPermission (e.g. "bash" → AgentPermission.ALLOW)
23
+ self._overrides: dict[str, AgentPermission] = {}
24
+
25
+ def set_override(self, perm_key: str, perm: AgentPermission) -> None:
26
+ """Record a user override for the given permission key."""
27
+ self._overrides[perm_key] = perm
28
+
29
+ def get_override(self, perm_key: str) -> Optional[AgentPermission]:
30
+ return self._overrides.get(perm_key)
31
+
32
+ def clear_override(self, perm_key: str) -> None:
33
+ self._overrides.pop(perm_key, None)
34
+
35
+ def clear_all(self) -> None:
36
+ self._overrides.clear()
37
+
38
+ def apply_to(self, agent) -> None:
39
+ """Apply all recorded overrides to an AgentConfig instance.
40
+
41
+ Call this after ``set_agent()`` to restore the user's choices.
42
+ """
43
+ for perm_key, perm in self._overrides.items():
44
+ attr_name = f"permission_{perm_key}"
45
+ if hasattr(agent, attr_name):
46
+ setattr(agent, attr_name, perm)
47
+
48
+ def to_dict(self) -> dict[str, str]:
49
+ return {k: v.value for k, v in self._overrides.items()}
50
+
51
+ @classmethod
52
+ def from_dict(cls, d: dict[str, str]) -> PermissionStore:
53
+ store = cls()
54
+ for k, v in d.items():
55
+ try:
56
+ store._overrides[k] = AgentPermission(v)
57
+ except ValueError:
58
+ pass
59
+ return store
60
+
61
+ def snapshot(self) -> dict[str, AgentPermission]:
62
+ return dict(self._overrides)
@@ -0,0 +1,186 @@
1
+ from __future__ import annotations
2
+
3
+ import json
4
+ import logging
5
+ import uuid
6
+ from datetime import datetime, timezone
7
+ from dataclasses import dataclass, field
8
+ from pathlib import Path
9
+ from typing import Optional
10
+
11
+ logger = logging.getLogger("onecode.session")
12
+
13
+
14
+ @dataclass
15
+ class SessionData:
16
+ id: str = field(default_factory=lambda: str(uuid.uuid4()))
17
+ name: str = "Untitled"
18
+ mode: str = "build"
19
+ project: str = ""
20
+ model: str = ""
21
+ provider: str = ""
22
+ messages: list[dict] = field(default_factory=list)
23
+ lifecycle_state: dict = field(default_factory=dict)
24
+ created_at: Optional[str] = None
25
+ updated_at: Optional[str] = None
26
+ tasks: list[dict] = field(default_factory=list)
27
+ todos: list[dict] = field(default_factory=list)
28
+
29
+ def to_dict(self) -> dict:
30
+ return {
31
+ "id": self.id,
32
+ "name": self.name,
33
+ "mode": self.mode,
34
+ "project": self.project,
35
+ "model": self.model,
36
+ "provider": self.provider,
37
+ "messages": self.messages,
38
+ "lifecycle_state": self.lifecycle_state,
39
+ "created_at": self.created_at,
40
+ "updated_at": self.updated_at,
41
+ "tasks": self.tasks,
42
+ "todos": self.todos,
43
+ }
44
+
45
+ @classmethod
46
+ def from_dict(cls, data: dict) -> SessionData:
47
+ return cls(
48
+ id=data.get("id", str(uuid.uuid4())),
49
+ name=data.get("name", "Untitled"),
50
+ mode=data.get("mode", "build"),
51
+ project=data.get("project", ""),
52
+ model=data.get("model", ""),
53
+ provider=data.get("provider", ""),
54
+ messages=data.get("messages", []),
55
+ lifecycle_state=data.get("lifecycle_state", {}),
56
+ created_at=data.get("created_at"),
57
+ updated_at=data.get("updated_at"),
58
+ tasks=data.get("tasks", []),
59
+ todos=data.get("todos", []),
60
+ )
61
+
62
+
63
+ class AgentSession:
64
+ def __init__(self, session_id: Optional[str] = None, storage_path: Optional[Path] = None):
65
+ self.storage_path = storage_path or self._default_storage_path()
66
+ self._data: SessionData = SessionData()
67
+ if session_id:
68
+ self._data.id = session_id
69
+ self.load()
70
+
71
+ def _default_storage_path(self) -> Path:
72
+ from onecode.config import CLOUD_DEV_HARNESS_DIR
73
+ return CLOUD_DEV_HARNESS_DIR / "sessions"
74
+
75
+ @property
76
+ def id(self) -> str:
77
+ return self._data.id
78
+
79
+ @property
80
+ def name(self) -> str:
81
+ return self._data.name
82
+
83
+ @name.setter
84
+ def name(self, value: str) -> None:
85
+ self._data.name = value
86
+
87
+ @property
88
+ def messages(self) -> list[dict]:
89
+ return self._data.messages
90
+
91
+ @messages.setter
92
+ def messages(self, value: list[dict]) -> None:
93
+ self._data.messages = value
94
+
95
+ @property
96
+ def lifecycle_state(self) -> dict:
97
+ return self._data.lifecycle_state
98
+
99
+ @property
100
+ def tasks(self) -> list[dict]:
101
+ return self._data.tasks
102
+
103
+ @tasks.setter
104
+ def tasks(self, value: list[dict]) -> None:
105
+ self._data.tasks = value
106
+
107
+ @property
108
+ def todos(self) -> list[dict]:
109
+ return self._data.todos
110
+
111
+ @todos.setter
112
+ def todos(self, value: list[dict]) -> None:
113
+ self._data.todos = value
114
+
115
+ def add_message(self, role: str, content: str) -> None:
116
+ self._data.messages.append({"role": role, "content": content})
117
+ self._touch()
118
+
119
+ def compact_messages(self, summary: str) -> None:
120
+ if len(self._data.messages) <= 2:
121
+ return
122
+ system_msgs = [m for m in self._data.messages if m.get("role") == "system"]
123
+ other_msgs = [m for m in self._data.messages if m.get("role") != "system"]
124
+ self._data.messages = system_msgs + [
125
+ {"role": "system", "content": f"[Previous context summarized]\n{summary}"}
126
+ ]
127
+ self._touch()
128
+
129
+ def update_state(self, key: str, value: any) -> None:
130
+ self._data.lifecycle_state[key] = value
131
+ self._touch()
132
+
133
+ def get_state(self, key: str, default: any = None) -> any:
134
+ return self._data.lifecycle_state.get(key, default)
135
+
136
+ def save(self) -> None:
137
+ self.storage_path.mkdir(parents=True, exist_ok=True)
138
+ file_path = self.storage_path / f"{self._data.id}.json"
139
+ self._data.updated_at = datetime.now(timezone.utc).isoformat()
140
+ file_path.write_text(json.dumps(self._data.to_dict(), indent=2, ensure_ascii=False), encoding="utf-8")
141
+
142
+ def load(self) -> bool:
143
+ file_path = self.storage_path / f"{self._data.id}.json"
144
+ if not file_path.exists():
145
+ return False
146
+ try:
147
+ data = json.loads(file_path.read_text(encoding="utf-8"))
148
+ self._data = SessionData.from_dict(data)
149
+ return True
150
+ except Exception as e:
151
+ logger.warning("Failed to load session %s: %s", self._data.id, e)
152
+ return False
153
+
154
+ def delete(self) -> None:
155
+ file_path = self.storage_path / f"{self._data.id}.json"
156
+ if file_path.exists():
157
+ file_path.unlink()
158
+
159
+ def _touch(self) -> None:
160
+ self._data.updated_at = datetime.now(timezone.utc).isoformat()
161
+
162
+ @classmethod
163
+ def list_sessions(cls, storage_path: Optional[Path] = None) -> list[SessionData]:
164
+ path = storage_path or cls()._default_storage_path()
165
+ if not path.exists():
166
+ return []
167
+ sessions = []
168
+ for f in path.glob("*.json"):
169
+ try:
170
+ data = json.loads(f.read_text(encoding="utf-8"))
171
+ sessions.append(SessionData.from_dict(data))
172
+ except Exception:
173
+ continue
174
+ return sorted(sessions, key=lambda s: s.updated_at or "", reverse=True)
175
+
176
+ @classmethod
177
+ def delete_by_id(cls, session_id: str, storage_path: Optional[Path] = None) -> bool:
178
+ path = storage_path or cls()._default_storage_path()
179
+ file_path = path / f"{session_id}.json"
180
+ if file_path.exists():
181
+ file_path.unlink()
182
+ return True
183
+ return False
184
+
185
+ def to_dict(self) -> dict:
186
+ return self._data.to_dict()
@@ -0,0 +1,145 @@
1
+ from __future__ import annotations
2
+
3
+ import fnmatch
4
+ import json
5
+ import os
6
+ import shutil
7
+ import tarfile
8
+ import tempfile
9
+ import uuid
10
+ from dataclasses import dataclass, field
11
+ from datetime import datetime, timezone
12
+ from pathlib import Path
13
+ from typing import Optional
14
+
15
+
16
+ @dataclass
17
+ class SnapshotInfo:
18
+ id: str
19
+ name: str
20
+ timestamp: str
21
+ description: str
22
+ size_bytes: int
23
+ file_count: int
24
+
25
+
26
+ class SnapshotManager:
27
+ def __init__(self, base_path: Optional[Path] = None):
28
+ from onecode.config import CLOUD_DEV_HARNESS_DIR
29
+ self.base_path = base_path or (CLOUD_DEV_HARNESS_DIR / "snapshots")
30
+ self.base_path.mkdir(parents=True, exist_ok=True)
31
+
32
+ def create(
33
+ self,
34
+ workspace: Path,
35
+ name: str,
36
+ description: str = "",
37
+ exclude_patterns: Optional[list[str]] = None,
38
+ ) -> SnapshotInfo:
39
+ snapshot_id = str(uuid.uuid4())[:8]
40
+ snapshot_dir = self.base_path / snapshot_id
41
+ snapshot_dir.mkdir(parents=True, exist_ok=True)
42
+
43
+ tar_path = snapshot_dir / "snapshot.tar.gz"
44
+ manifest_path = snapshot_dir / "manifest.json"
45
+
46
+ exclude_patterns = exclude_patterns or [
47
+ ".git",
48
+ "node_modules",
49
+ "__pycache__",
50
+ "*.pyc",
51
+ ".pytest_cache",
52
+ ".venv",
53
+ "venv",
54
+ ".env",
55
+ "*.egg-info",
56
+ ".cdh",
57
+ "snapshots",
58
+ ]
59
+
60
+ file_count = 0
61
+ with tarfile.open(str(tar_path), "w:gz") as tar:
62
+ for root, dirs, files in os.walk(workspace):
63
+ dirs[:] = [d for d in dirs if not self._should_exclude(d, exclude_patterns)]
64
+
65
+ for file in files:
66
+ file_path = Path(root) / file
67
+ if not self._should_exclude(file_path.name, exclude_patterns):
68
+ try:
69
+ tar.add(str(file_path), arcname=str(file_path.relative_to(workspace)))
70
+ file_count += 1
71
+ except Exception:
72
+ pass
73
+
74
+ size_bytes = tar_path.stat().st_size
75
+
76
+ manifest = {
77
+ "id": snapshot_id,
78
+ "name": name,
79
+ "description": description,
80
+ "timestamp": datetime.now(timezone.utc).isoformat(),
81
+ "workspace": str(workspace),
82
+ "file_count": file_count,
83
+ "size_bytes": size_bytes,
84
+ }
85
+ manifest_path.write_text(json.dumps(manifest, indent=2), encoding="utf-8")
86
+
87
+ return SnapshotInfo(
88
+ id=snapshot_id,
89
+ name=name,
90
+ timestamp=manifest["timestamp"],
91
+ description=description,
92
+ size_bytes=size_bytes,
93
+ file_count=file_count,
94
+ )
95
+
96
+ def restore(self, snapshot_id: str, target_dir: Path) -> bool:
97
+ snapshot_dir = self.base_path / snapshot_id
98
+ if not snapshot_dir.exists():
99
+ return False
100
+
101
+ tar_path = snapshot_dir / "snapshot.tar.gz"
102
+ if not tar_path.exists():
103
+ return False
104
+
105
+ target_dir.mkdir(parents=True, exist_ok=True)
106
+
107
+ with tarfile.open(str(tar_path), "r:gz") as tar:
108
+ tar.extractall(target_dir)
109
+
110
+ return True
111
+
112
+ def list(self) -> list[SnapshotInfo]:
113
+ snapshots = []
114
+ for snapshot_dir in self.base_path.iterdir():
115
+ if not snapshot_dir.is_dir():
116
+ continue
117
+ manifest_path = snapshot_dir / "manifest.json"
118
+ if not manifest_path.exists():
119
+ continue
120
+ try:
121
+ manifest = json.loads(manifest_path.read_text(encoding="utf-8"))
122
+ snapshots.append(SnapshotInfo(
123
+ id=manifest["id"],
124
+ name=manifest["name"],
125
+ timestamp=manifest["timestamp"],
126
+ description=manifest.get("description", ""),
127
+ size_bytes=manifest.get("size_bytes", 0),
128
+ file_count=manifest.get("file_count", 0),
129
+ ))
130
+ except Exception:
131
+ continue
132
+ return sorted(snapshots, key=lambda s: s.timestamp, reverse=True)
133
+
134
+ def delete(self, snapshot_id: str) -> bool:
135
+ snapshot_dir = self.base_path / snapshot_id
136
+ if snapshot_dir.exists():
137
+ shutil.rmtree(snapshot_dir)
138
+ return True
139
+ return False
140
+
141
+ def _should_exclude(self, name: str, patterns: list[str]) -> bool:
142
+ for pattern in patterns:
143
+ if fnmatch.fnmatch(name, pattern):
144
+ return True
145
+ return False
@@ -0,0 +1,17 @@
1
+ from onecode.agent.tools.file_ops import FileOps, ShellTool, ToolFactory
2
+ from onecode.agent.tools.protocol import ToolCall, ToolResult
3
+ from onecode.agent.tools.errors import ToolError, ToolInputError, ToolPermissionError, ToolExecutionError
4
+ from onecode.agent.tools.registry import Tool, ToolRegistry, ToolSpec
5
+ from onecode.agent.tools.permissions import ToolPermissionContext, PermissionResult
6
+ from onecode.agent.tools.permission_handler import InteractivePermissionHandler, PermissionDecision, PermissionHandler
7
+ from onecode.agent.tools.schema_validation import validate_json_schema
8
+
9
+ __all__ = [
10
+ "FileOps", "ShellTool", "ToolFactory",
11
+ "ToolCall", "ToolResult",
12
+ "ToolError", "ToolInputError", "ToolPermissionError", "ToolExecutionError",
13
+ "Tool", "ToolRegistry", "ToolSpec",
14
+ "ToolPermissionContext", "PermissionResult",
15
+ "InteractivePermissionHandler", "PermissionDecision", "PermissionHandler",
16
+ "validate_json_schema",
17
+ ]