@scemoon/cdh 1.0.6 → 1.0.7

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 (550) hide show
  1. package/package.json +2 -2
  2. package/ai-dlc-skill/SKILL.md +0 -77
  3. package/ai-dlc-skill/agents/deliver-agent.md +0 -24
  4. package/ai-dlc-skill/agents/master.md +0 -50
  5. package/ai-dlc-skill/agents/plan-agent.md +0 -23
  6. package/ai-dlc-skill/agents/understand-agent.md +0 -23
  7. package/ai-dlc-skill/agents/verify-agent.md +0 -27
  8. package/ai-dlc-skill/architecture/project-structure.md +0 -78
  9. package/ai-dlc-skill/brownfield/README.md +0 -30
  10. package/ai-dlc-skill/brownfield/generate-context.sh +0 -64
  11. package/ai-dlc-skill/brownfield/scripts/deps.sh +0 -27
  12. package/ai-dlc-skill/brownfield/scripts/discover.sh +0 -34
  13. package/ai-dlc-skill/brownfield/scripts/extract-api.sh +0 -45
  14. package/ai-dlc-skill/components/backend.md +0 -34
  15. package/ai-dlc-skill/components/desktop.md +0 -30
  16. package/ai-dlc-skill/components/mya.md +0 -29
  17. package/ai-dlc-skill/components/native.md +0 -30
  18. package/ai-dlc-skill/components/tta.md +0 -29
  19. package/ai-dlc-skill/components/web.md +0 -31
  20. package/ai-dlc-skill/components/wxa.md +0 -29
  21. package/ai-dlc-skill/contracts/README.md +0 -25
  22. package/ai-dlc-skill/core/adaptive-flow.md +0 -36
  23. package/ai-dlc-skill/core/security.md +0 -29
  24. package/ai-dlc-skill/cross-tool/cline/export.sh +0 -31
  25. package/ai-dlc-skill/cross-tool/copilot/export.sh +0 -47
  26. package/ai-dlc-skill/cross-tool/cursor/export.sh +0 -32
  27. package/ai-dlc-skill/cross-tool/export.sh +0 -22
  28. package/ai-dlc-skill/cross-tool/onecode/config.yaml.tpl +0 -17
  29. package/ai-dlc-skill/cross-tool/onecode/export-skills.sh +0 -35
  30. package/ai-dlc-skill/cross-tool/onecode/export.sh +0 -54
  31. package/ai-dlc-skill/phases/deliver/entry.md +0 -26
  32. package/ai-dlc-skill/phases/deliver/lifecycle.md +0 -185
  33. package/ai-dlc-skill/phases/deliver/prompt.md +0 -40
  34. package/ai-dlc-skill/phases/deliver/rules.md +0 -61
  35. package/ai-dlc-skill/phases/plan/entry.md +0 -25
  36. package/ai-dlc-skill/phases/plan/lifecycle.md +0 -204
  37. package/ai-dlc-skill/phases/plan/prompt.md +0 -38
  38. package/ai-dlc-skill/phases/plan/rules.md +0 -25
  39. package/ai-dlc-skill/phases/understand/entry.md +0 -26
  40. package/ai-dlc-skill/phases/understand/lifecycle.md +0 -184
  41. package/ai-dlc-skill/phases/understand/prompt.md +0 -41
  42. package/ai-dlc-skill/phases/understand/rules.md +0 -37
  43. package/ai-dlc-skill/phases/verify/entry.md +0 -26
  44. package/ai-dlc-skill/phases/verify/lifecycle.md +0 -192
  45. package/ai-dlc-skill/phases/verify/prompt.md +0 -43
  46. package/ai-dlc-skill/phases/verify/rules.md +0 -73
  47. package/ai-dlc-skill/practices/bdd.md +0 -91
  48. package/ai-dlc-skill/practices/sdd.md +0 -84
  49. package/ai-dlc-skill/practices/tdd.md +0 -95
  50. package/ai-dlc-skill/providers/README.md +0 -114
  51. package/ai-dlc-skill/providers/aliyun/deployment.yaml +0 -66
  52. package/ai-dlc-skill/providers/aliyun/preview.yaml +0 -84
  53. package/ai-dlc-skill/providers/aliyun/provider.yaml +0 -160
  54. package/ai-dlc-skill/providers/tcb/deployment.yaml +0 -69
  55. package/ai-dlc-skill/providers/tcb/preview.yaml +0 -83
  56. package/ai-dlc-skill/providers/tcb/provider.yaml +0 -172
  57. package/ai-dlc-skill/requirements.md +0 -140
  58. package/ai-dlc-skill/skill.yaml +0 -147
  59. package/ai-dlc-skill/templates/integration/CHANGELOG.md +0 -41
  60. package/ai-dlc-skill/templates/integration/asyncapi.yaml +0 -43
  61. package/ai-dlc-skill/templates/integration/contract-diff.md +0 -63
  62. package/ai-dlc-skill/templates/integration/contract-spec.md +0 -49
  63. package/ai-dlc-skill/templates/integration/openapi.yaml +0 -18
  64. package/ai-dlc-skill/templates/integration/runtime-contract.yaml +0 -36
  65. package/ai-dlc-skill/templates/plan/design.md +0 -49
  66. package/ai-dlc-skill/templates/plan/task-list.md +0 -32
  67. package/ai-dlc-skill/templates/project/README.md +0 -126
  68. package/ai-dlc-skill/templates/project/template.md +0 -119
  69. package/ai-dlc-skill/templates/understand/feature.feature +0 -23
  70. package/ai-dlc-skill/templates/understand/intent.md +0 -29
  71. package/ai-dlc-skill/templates/understand/spec-delta.md +0 -47
  72. package/ai-dlc-skill/templates/verify/test-unit.py +0 -27
  73. package/ai-dlc-skill/walkthrough/collect.sh +0 -50
  74. package/ai-dlc-skill/walkthrough/template.md +0 -54
  75. package/ai-dlc-skill/workflows/ai-dlc.yaml +0 -110
  76. package/ai-dlc-skill/workflows/deployment.yaml +0 -199
  77. package/cdh/__init__.py +0 -0
  78. package/cdh/__main__.py +0 -4
  79. package/cdh/__pycache__/__init__.cpython-314.pyc +0 -0
  80. package/cdh/__pycache__/cdh_mcp_injector.cpython-314.pyc +0 -0
  81. package/cdh/__pycache__/cdh_mcp_loader.cpython-314.pyc +0 -0
  82. package/cdh/__pycache__/cdh_mcp_manager.cpython-314.pyc +0 -0
  83. package/cdh/__pycache__/cdh_session_aggregator.cpython-314.pyc +0 -0
  84. package/cdh/__pycache__/cdh_skill_loader.cpython-314.pyc +0 -0
  85. package/cdh/__pycache__/cdh_skill_manager.cpython-314.pyc +0 -0
  86. package/cdh/__pycache__/cli.cpython-313.pyc +0 -0
  87. package/cdh/__pycache__/cli.cpython-314.pyc +0 -0
  88. package/cdh/__pycache__/scaffold.cpython-314.pyc +0 -0
  89. package/cdh/cdh_mcp_injector.py +0 -115
  90. package/cdh/cdh_mcp_loader.py +0 -67
  91. package/cdh/cdh_mcp_manager.py +0 -73
  92. package/cdh/cdh_session_aggregator.py +0 -258
  93. package/cdh/cdh_skill_manager.py +0 -105
  94. package/cdh/cli.py +0 -807
  95. package/cdh/scaffold.py +0 -728
  96. package/onecode/__init__.py +0 -1
  97. package/onecode/__main__.py +0 -4
  98. package/onecode/__pycache__/__init__.cpython-314.pyc +0 -0
  99. package/onecode/__pycache__/cli.cpython-314.pyc +0 -0
  100. package/onecode/__pycache__/commands.cpython-314.pyc +0 -0
  101. package/onecode/__pycache__/config.cpython-314.pyc +0 -0
  102. package/onecode/__pycache__/config_screen.cpython-314.pyc +0 -0
  103. package/onecode/__pycache__/migrate.cpython-314.pyc +0 -0
  104. package/onecode/agent/__init__.py +0 -0
  105. package/onecode/agent/__pycache__/__init__.cpython-314.pyc +0 -0
  106. package/onecode/agent/__pycache__/cdh_loader.cpython-314.pyc +0 -0
  107. package/onecode/agent/__pycache__/context.cpython-314.pyc +0 -0
  108. package/onecode/agent/__pycache__/engine.cpython-314.pyc +0 -0
  109. package/onecode/agent/__pycache__/hooks.cpython-314.pyc +0 -0
  110. package/onecode/agent/__pycache__/onecode_agent_acp.cpython-314.pyc +0 -0
  111. package/onecode/agent/__pycache__/permissions.cpython-314.pyc +0 -0
  112. package/onecode/agent/__pycache__/permissions_store.cpython-314.pyc +0 -0
  113. package/onecode/agent/__pycache__/project_doc.cpython-314.pyc +0 -0
  114. package/onecode/agent/__pycache__/session.cpython-314.pyc +0 -0
  115. package/onecode/agent/agents/__init__.py +0 -29
  116. package/onecode/agent/agents/__pycache__/__init__.cpython-314.pyc +0 -0
  117. package/onecode/agent/agents/__pycache__/types.cpython-314.pyc +0 -0
  118. package/onecode/agent/agents/types.py +0 -589
  119. package/onecode/agent/attachments.py +0 -112
  120. package/onecode/agent/cdh_loader.py +0 -267
  121. package/onecode/agent/context.py +0 -343
  122. package/onecode/agent/engine.py +0 -2700
  123. package/onecode/agent/hooks.py +0 -86
  124. package/onecode/agent/onecode_agent_acp.py +0 -2743
  125. package/onecode/agent/onecode_agent_acp.py.bak +0 -2447
  126. package/onecode/agent/permissions.py +0 -150
  127. package/onecode/agent/permissions_store.py +0 -62
  128. package/onecode/agent/project_doc.py +0 -19
  129. package/onecode/agent/session.py +0 -195
  130. package/onecode/agent/snapshot.py +0 -144
  131. package/onecode/agent/tools/__init__.py +0 -17
  132. package/onecode/agent/tools/__pycache__/__init__.cpython-314.pyc +0 -0
  133. package/onecode/agent/tools/__pycache__/agent_tools.cpython-314.pyc +0 -0
  134. package/onecode/agent/tools/__pycache__/apply_patch_tool.cpython-314.pyc +0 -0
  135. package/onecode/agent/tools/__pycache__/bash_tool.cpython-314.pyc +0 -0
  136. package/onecode/agent/tools/__pycache__/communication_tools.cpython-314.pyc +0 -0
  137. package/onecode/agent/tools/__pycache__/config_tool.cpython-314.pyc +0 -0
  138. package/onecode/agent/tools/__pycache__/cron_tools.cpython-314.pyc +0 -0
  139. package/onecode/agent/tools/__pycache__/errors.cpython-314.pyc +0 -0
  140. package/onecode/agent/tools/__pycache__/file_ops.cpython-314.pyc +0 -0
  141. package/onecode/agent/tools/__pycache__/file_tools.cpython-314.pyc +0 -0
  142. package/onecode/agent/tools/__pycache__/git_tools.cpython-314.pyc +0 -0
  143. package/onecode/agent/tools/__pycache__/lsp_tools.cpython-314.pyc +0 -0
  144. package/onecode/agent/tools/__pycache__/mcp_tools.cpython-314.pyc +0 -0
  145. package/onecode/agent/tools/__pycache__/permission_handler.cpython-314.pyc +0 -0
  146. package/onecode/agent/tools/__pycache__/permissions.cpython-314.pyc +0 -0
  147. package/onecode/agent/tools/__pycache__/protocol.cpython-314.pyc +0 -0
  148. package/onecode/agent/tools/__pycache__/registry.cpython-314.pyc +0 -0
  149. package/onecode/agent/tools/__pycache__/sandbox.cpython-314.pyc +0 -0
  150. package/onecode/agent/tools/__pycache__/schema_validation.cpython-314.pyc +0 -0
  151. package/onecode/agent/tools/__pycache__/skill_tools.cpython-314.pyc +0 -0
  152. package/onecode/agent/tools/__pycache__/todo_tools.cpython-314.pyc +0 -0
  153. package/onecode/agent/tools/__pycache__/web_tools.cpython-314.pyc +0 -0
  154. package/onecode/agent/tools/agent_tools.py +0 -132
  155. package/onecode/agent/tools/apply_patch_tool.py +0 -138
  156. package/onecode/agent/tools/bash_tool.py +0 -111
  157. package/onecode/agent/tools/communication_tools.py +0 -148
  158. package/onecode/agent/tools/config_tool.py +0 -130
  159. package/onecode/agent/tools/cron_tools.py +0 -178
  160. package/onecode/agent/tools/errors.py +0 -17
  161. package/onecode/agent/tools/file_ops.py +0 -221
  162. package/onecode/agent/tools/file_tools.py +0 -225
  163. package/onecode/agent/tools/git_tools.py +0 -88
  164. package/onecode/agent/tools/lsp_tools.py +0 -404
  165. package/onecode/agent/tools/mcp_tools.py +0 -127
  166. package/onecode/agent/tools/permission_handler.py +0 -46
  167. package/onecode/agent/tools/permissions.py +0 -77
  168. package/onecode/agent/tools/protocol.py +0 -20
  169. package/onecode/agent/tools/registry.py +0 -201
  170. package/onecode/agent/tools/sandbox.py +0 -358
  171. package/onecode/agent/tools/schema_validation.py +0 -100
  172. package/onecode/agent/tools/skill_tools.py +0 -52
  173. package/onecode/agent/tools/todo_tools.py +0 -207
  174. package/onecode/agent/tools/web_tools.py +0 -169
  175. package/onecode/builtin_skills/agent-browser/SKILL.md +0 -212
  176. package/onecode/builtin_skills/agent-browser/skill.yaml +0 -8
  177. package/onecode/builtin_skills/git/SKILL.md +0 -64
  178. package/onecode/builtin_skills/git/skill.yaml +0 -7
  179. package/onecode/builtin_skills/shell/SKILL.md +0 -58
  180. package/onecode/builtin_skills/shell/skill.yaml +0 -8
  181. package/onecode/builtin_skills/skill-creator/SKILL.md +0 -106
  182. package/onecode/builtin_skills/skill-creator/skill.yaml +0 -8
  183. package/onecode/cli.py +0 -935
  184. package/onecode/cloud/__init__.py +0 -0
  185. package/onecode/cloud/base.py +0 -20
  186. package/onecode/codebase/__init__.py +0 -69
  187. package/onecode/codebase/__pycache__/__init__.cpython-314.pyc +0 -0
  188. package/onecode/codebase/__pycache__/chunker.cpython-314.pyc +0 -0
  189. package/onecode/codebase/__pycache__/indexer.cpython-314.pyc +0 -0
  190. package/onecode/codebase/__pycache__/retriever.cpython-314.pyc +0 -0
  191. package/onecode/codebase/__pycache__/storage.cpython-314.pyc +0 -0
  192. package/onecode/codebase/__pycache__/tools.cpython-314.pyc +0 -0
  193. package/onecode/codebase/chunker.py +0 -125
  194. package/onecode/codebase/indexer.py +0 -149
  195. package/onecode/codebase/retriever.py +0 -203
  196. package/onecode/codebase/storage.py +0 -131
  197. package/onecode/codebase/tools.py +0 -59
  198. package/onecode/commands.py +0 -596
  199. package/onecode/config.py +0 -314
  200. package/onecode/config_screen.py +0 -600
  201. package/onecode/cron/__init__.py +0 -3
  202. package/onecode/lsp/__init__.py +0 -3
  203. package/onecode/mcp/__init__.py +0 -4
  204. package/onecode/mcp/__pycache__/__init__.cpython-314.pyc +0 -0
  205. package/onecode/mcp/__pycache__/client.cpython-314.pyc +0 -0
  206. package/onecode/mcp/__pycache__/manager.cpython-314.pyc +0 -0
  207. package/onecode/mcp/client.py +0 -193
  208. package/onecode/mcp/manager.py +0 -190
  209. package/onecode/memory/__init__.py +0 -49
  210. package/onecode/memory/__pycache__/__init__.cpython-314.pyc +0 -0
  211. package/onecode/memory/__pycache__/backend.cpython-314.pyc +0 -0
  212. package/onecode/memory/__pycache__/offload.cpython-314.pyc +0 -0
  213. package/onecode/memory/__pycache__/pyramid.cpython-314.pyc +0 -0
  214. package/onecode/memory/__pycache__/recall.cpython-314.pyc +0 -0
  215. package/onecode/memory/__pycache__/symbolic.cpython-314.pyc +0 -0
  216. package/onecode/memory/backend.py +0 -159
  217. package/onecode/memory/pyramid.py +0 -133
  218. package/onecode/memory/recall.py +0 -203
  219. package/onecode/migrate.py +0 -122
  220. package/onecode/models/__init__.py +0 -4
  221. package/onecode/models/__pycache__/__init__.cpython-314.pyc +0 -0
  222. package/onecode/models/__pycache__/errors.cpython-314.pyc +0 -0
  223. package/onecode/models/__pycache__/messages.cpython-314.pyc +0 -0
  224. package/onecode/models/__pycache__/provider.cpython-314.pyc +0 -0
  225. package/onecode/models/__pycache__/registry.cpython-314.pyc +0 -0
  226. package/onecode/models/errors.py +0 -104
  227. package/onecode/models/messages.py +0 -739
  228. package/onecode/models/provider.py +0 -699
  229. package/onecode/models/providers/__init__.py +0 -17
  230. package/onecode/models/providers/__pycache__/__init__.cpython-314.pyc +0 -0
  231. package/onecode/models/providers/__pycache__/anthropic_provider.cpython-314.pyc +0 -0
  232. package/onecode/models/providers/__pycache__/deepseek_provider.cpython-314.pyc +0 -0
  233. package/onecode/models/providers/__pycache__/glm_provider.cpython-314.pyc +0 -0
  234. package/onecode/models/providers/__pycache__/minimax_provider.cpython-314.pyc +0 -0
  235. package/onecode/models/providers/__pycache__/minimaxi_provider.cpython-314.pyc +0 -0
  236. package/onecode/models/providers/__pycache__/ollama_provider.cpython-314.pyc +0 -0
  237. package/onecode/models/providers/__pycache__/openai_provider.cpython-314.pyc +0 -0
  238. package/onecode/models/providers/anthropic_provider.py +0 -273
  239. package/onecode/models/providers/deepseek_provider.py +0 -212
  240. package/onecode/models/providers/glm_provider.py +0 -195
  241. package/onecode/models/providers/minimax_provider.py +0 -158
  242. package/onecode/models/providers/minimaxi_provider.py +0 -417
  243. package/onecode/models/providers/ollama_provider.py +0 -100
  244. package/onecode/models/providers/openai_provider.py +0 -237
  245. package/onecode/models/registry.py +0 -212
  246. package/onecode/server/__init__.py +0 -3
  247. package/onecode/server/app.py +0 -224
  248. package/onecode/skills/__init__.py +0 -11
  249. package/onecode/skills/__pycache__/__init__.cpython-314.pyc +0 -0
  250. package/onecode/skills/__pycache__/argument_substitution.cpython-314.pyc +0 -0
  251. package/onecode/skills/__pycache__/bootstrap.cpython-314.pyc +0 -0
  252. package/onecode/skills/__pycache__/create.cpython-314.pyc +0 -0
  253. package/onecode/skills/__pycache__/frontmatter.cpython-314.pyc +0 -0
  254. package/onecode/skills/__pycache__/loader.cpython-314.pyc +0 -0
  255. package/onecode/skills/__pycache__/manager.cpython-314.pyc +0 -0
  256. package/onecode/skills/__pycache__/model.cpython-314.pyc +0 -0
  257. package/onecode/skills/argument_substitution.py +0 -38
  258. package/onecode/skills/bootstrap.py +0 -124
  259. package/onecode/skills/create.py +0 -56
  260. package/onecode/skills/frontmatter.py +0 -33
  261. package/onecode/skills/loader.py +0 -139
  262. package/onecode/skills/manager.py +0 -75
  263. package/onecode/skills/model.py +0 -43
  264. package/onecode/storage/__init__.py +0 -0
  265. package/onecode/storage/activity.py +0 -63
  266. package/onecode/storage/project.py +0 -54
  267. package/onecode/storage/session.py +0 -112
  268. package/onecode/tasks/__init__.py +0 -26
  269. package/onecode/tasks/manager.py +0 -232
  270. package/onecode/tasks/models.py +0 -240
  271. package/onecode/trace/__init__.py +0 -0
  272. package/onecode/trace/tracer.py +0 -173
  273. package/onecode/utils/__init__.py +0 -0
  274. package/onecode/utils/helpers.py +0 -20
  275. package/pyproject.toml +0 -74
  276. package/tui/__init__.py +0 -46
  277. package/tui/__main__.py +0 -4
  278. package/tui/__pycache__/__init__.cpython-314.pyc +0 -0
  279. package/tui/__pycache__/_loop.cpython-314.pyc +0 -0
  280. package/tui/__pycache__/_path_fuzzy_search.cpython-314.pyc +0 -0
  281. package/tui/__pycache__/_path_match.cpython-314.pyc +0 -0
  282. package/tui/__pycache__/about.cpython-314.pyc +0 -0
  283. package/tui/__pycache__/agent.cpython-314.pyc +0 -0
  284. package/tui/__pycache__/agent_schema.cpython-314.pyc +0 -0
  285. package/tui/__pycache__/agents.cpython-314.pyc +0 -0
  286. package/tui/__pycache__/answer.cpython-314.pyc +0 -0
  287. package/tui/__pycache__/app.cpython-313.pyc +0 -0
  288. package/tui/__pycache__/app.cpython-314.pyc +0 -0
  289. package/tui/__pycache__/atomic.cpython-314.pyc +0 -0
  290. package/tui/__pycache__/complete.cpython-314.pyc +0 -0
  291. package/tui/__pycache__/constants.cpython-314.pyc +0 -0
  292. package/tui/__pycache__/conversation_markdown.cpython-314.pyc +0 -0
  293. package/tui/__pycache__/danger.cpython-314.pyc +0 -0
  294. package/tui/__pycache__/db.cpython-314.pyc +0 -0
  295. package/tui/__pycache__/dec.cpython-314.pyc +0 -0
  296. package/tui/__pycache__/directory.cpython-314.pyc +0 -0
  297. package/tui/__pycache__/directory_suggester.cpython-314.pyc +0 -0
  298. package/tui/__pycache__/directory_watcher.cpython-314.pyc +0 -0
  299. package/tui/__pycache__/format_path.cpython-314.pyc +0 -0
  300. package/tui/__pycache__/fuzzy.cpython-314.pyc +0 -0
  301. package/tui/__pycache__/fuzzy_index.cpython-314.pyc +0 -0
  302. package/tui/__pycache__/history.cpython-314.pyc +0 -0
  303. package/tui/__pycache__/jsonrpc.cpython-314.pyc +0 -0
  304. package/tui/__pycache__/menus.cpython-314.pyc +0 -0
  305. package/tui/__pycache__/message_log.cpython-314.pyc +0 -0
  306. package/tui/__pycache__/messages.cpython-314.pyc +0 -0
  307. package/tui/__pycache__/path_complete.cpython-314.pyc +0 -0
  308. package/tui/__pycache__/path_filter.cpython-314.pyc +0 -0
  309. package/tui/__pycache__/paths.cpython-314.pyc +0 -0
  310. package/tui/__pycache__/pill.cpython-314.pyc +0 -0
  311. package/tui/__pycache__/platform_commands.cpython-314.pyc +0 -0
  312. package/tui/__pycache__/protocol.cpython-314.pyc +0 -0
  313. package/tui/__pycache__/session_tracker.cpython-314.pyc +0 -0
  314. package/tui/__pycache__/settings.cpython-314.pyc +0 -0
  315. package/tui/__pycache__/settings_schema.cpython-314.pyc +0 -0
  316. package/tui/__pycache__/shell.cpython-314.pyc +0 -0
  317. package/tui/__pycache__/shell_read.cpython-314.pyc +0 -0
  318. package/tui/__pycache__/slash_command.cpython-314.pyc +0 -0
  319. package/tui/__pycache__/version.cpython-314.pyc +0 -0
  320. package/tui/_loop.py +0 -86
  321. package/tui/_path_fuzzy_search.py +0 -48
  322. package/tui/_path_match.py +0 -141
  323. package/tui/about.py +0 -95
  324. package/tui/acp/__pycache__/agent.cpython-314.pyc +0 -0
  325. package/tui/acp/__pycache__/api.cpython-314.pyc +0 -0
  326. package/tui/acp/__pycache__/encode_tool_call_id.cpython-314.pyc +0 -0
  327. package/tui/acp/__pycache__/messages.cpython-314.pyc +0 -0
  328. package/tui/acp/__pycache__/prompt.cpython-314.pyc +0 -0
  329. package/tui/acp/__pycache__/protocol.cpython-314.pyc +0 -0
  330. package/tui/acp/agent.py +0 -1002
  331. package/tui/acp/api.py +0 -73
  332. package/tui/acp/encode_tool_call_id.py +0 -12
  333. package/tui/acp/messages.py +0 -203
  334. package/tui/acp/prompt.py +0 -53
  335. package/tui/acp/protocol.py +0 -499
  336. package/tui/agent.py +0 -70
  337. package/tui/agent_schema.py +0 -76
  338. package/tui/agents.py +0 -46
  339. package/tui/ansi/__init__.py +0 -1
  340. package/tui/ansi/__pycache__/__init__.cpython-314.pyc +0 -0
  341. package/tui/ansi/__pycache__/_ansi.cpython-314.pyc +0 -0
  342. package/tui/ansi/__pycache__/_ansi_colors.cpython-314.pyc +0 -0
  343. package/tui/ansi/__pycache__/_control_codes.cpython-314.pyc +0 -0
  344. package/tui/ansi/__pycache__/_keys.cpython-314.pyc +0 -0
  345. package/tui/ansi/__pycache__/_sgr_styles.cpython-314.pyc +0 -0
  346. package/tui/ansi/__pycache__/_stream_parser.cpython-314.pyc +0 -0
  347. package/tui/ansi/_ansi.py +0 -1689
  348. package/tui/ansi/_ansi_colors.py +0 -264
  349. package/tui/ansi/_control_codes.py +0 -37
  350. package/tui/ansi/_keys.py +0 -251
  351. package/tui/ansi/_sgr_styles.py +0 -64
  352. package/tui/ansi/_stream_parser.py +0 -418
  353. package/tui/answer.py +0 -12
  354. package/tui/app.py +0 -1266
  355. package/tui/atomic.py +0 -37
  356. package/tui/cli.py +0 -313
  357. package/tui/code_analyze.py +0 -27
  358. package/tui/complete.py +0 -38
  359. package/tui/constants.py +0 -61
  360. package/tui/conversation_markdown.py +0 -30
  361. package/tui/danger.py +0 -372
  362. package/tui/data/agents/ampcode.com.toml +0 -52
  363. package/tui/data/agents/augmentcode.com.toml +0 -41
  364. package/tui/data/agents/cdh.cloud-dev-harness.toml +0 -23
  365. package/tui/data/agents/claude.com.toml +0 -41
  366. package/tui/data/agents/copilot.github.com.toml +0 -29
  367. package/tui/data/agents/crowai.dev.toml +0 -36
  368. package/tui/data/agents/cursor.com.toml +0 -38
  369. package/tui/data/agents/deepagents.langchain.com +0 -34
  370. package/tui/data/agents/docker.com.toml +0 -60
  371. package/tui/data/agents/geminicli.com.toml +0 -28
  372. package/tui/data/agents/goose.ai.toml +0 -52
  373. package/tui/data/agents/inference.huggingface.co.toml +0 -41
  374. package/tui/data/agents/kimi.com.toml +0 -35
  375. package/tui/data/agents/kiro.dev.toml +0 -43
  376. package/tui/data/agents/onecode.dev.toml +0 -22
  377. package/tui/data/agents/openai.com.toml +0 -53
  378. package/tui/data/agents/openclaw.ai.toml +0 -37
  379. package/tui/data/agents/opencode.ai.toml +0 -39
  380. package/tui/data/agents/openhands.dev.toml +0 -46
  381. package/tui/data/agents/stakpak.dev.toml +0 -62
  382. package/tui/data/agents/vibe.mistral.ai.toml +0 -31
  383. package/tui/data/agents/vtcode.dev.toml +0 -63
  384. package/tui/data/images/frog.png +0 -0
  385. package/tui/data/sounds/question.wav +0 -0
  386. package/tui/data/sounds/turn-over.wav +0 -0
  387. package/tui/db.py +0 -213
  388. package/tui/dec.py +0 -332
  389. package/tui/directory.py +0 -234
  390. package/tui/directory_suggester.py +0 -93
  391. package/tui/directory_watcher.py +0 -231
  392. package/tui/format_path.py +0 -25
  393. package/tui/fuzzy.py +0 -140
  394. package/tui/fuzzy_index.py +0 -275
  395. package/tui/gist.py +0 -33
  396. package/tui/history.py +0 -138
  397. package/tui/jsonrpc.py +0 -578
  398. package/tui/menus.py +0 -14
  399. package/tui/message_log.py +0 -69
  400. package/tui/messages.py +0 -144
  401. package/tui/option_content.py +0 -51
  402. package/tui/os.py +0 -0
  403. package/tui/path_complete.py +0 -217
  404. package/tui/path_filter.py +0 -124
  405. package/tui/paths.py +0 -87
  406. package/tui/pill.py +0 -23
  407. package/tui/platform_commands.py +0 -52
  408. package/tui/prompt/__pycache__/extract.cpython-314.pyc +0 -0
  409. package/tui/prompt/__pycache__/resource.cpython-314.pyc +0 -0
  410. package/tui/prompt/extract.py +0 -19
  411. package/tui/prompt/resource.py +0 -68
  412. package/tui/protocol.py +0 -28
  413. package/tui/screens/__init__.py +0 -0
  414. package/tui/screens/__pycache__/__init__.cpython-314.pyc +0 -0
  415. package/tui/screens/__pycache__/agent_modal.cpython-314.pyc +0 -0
  416. package/tui/screens/__pycache__/component_picker.cpython-314.pyc +0 -0
  417. package/tui/screens/__pycache__/diff_screen.cpython-314.pyc +0 -0
  418. package/tui/screens/__pycache__/log.cpython-314.pyc +0 -0
  419. package/tui/screens/__pycache__/main.cpython-313.pyc +0 -0
  420. package/tui/screens/__pycache__/main.cpython-314.pyc +0 -0
  421. package/tui/screens/__pycache__/permissions.cpython-314.pyc +0 -0
  422. package/tui/screens/__pycache__/projects_app.cpython-314.pyc +0 -0
  423. package/tui/screens/__pycache__/projects_screen.cpython-314.pyc +0 -0
  424. package/tui/screens/__pycache__/sessions.cpython-314.pyc +0 -0
  425. package/tui/screens/__pycache__/store.cpython-314.pyc +0 -0
  426. package/tui/screens/__pycache__/tool_content_screen.cpython-314.pyc +0 -0
  427. package/tui/screens/action_modal.py +0 -94
  428. package/tui/screens/agent_modal.py +0 -175
  429. package/tui/screens/command_edit_modal.py +0 -74
  430. package/tui/screens/component_picker.py +0 -168
  431. package/tui/screens/diff_screen.py +0 -84
  432. package/tui/screens/log.py +0 -553
  433. package/tui/screens/main.py +0 -385
  434. package/tui/screens/main.tcss +0 -655
  435. package/tui/screens/permissions.py +0 -404
  436. package/tui/screens/permissions.tcss +0 -72
  437. package/tui/screens/projects.tcss +0 -80
  438. package/tui/screens/projects_app.py +0 -347
  439. package/tui/screens/projects_screen.py +0 -284
  440. package/tui/screens/session_resume_modal.py +0 -172
  441. package/tui/screens/session_resume_modal.tcss +0 -35
  442. package/tui/screens/sessions.py +0 -164
  443. package/tui/screens/sessions.tcss +0 -119
  444. package/tui/screens/settings.py +0 -254
  445. package/tui/screens/settings.tcss +0 -101
  446. package/tui/screens/store.py +0 -500
  447. package/tui/screens/store.tcss +0 -274
  448. package/tui/screens/tool_content_screen.py +0 -59
  449. package/tui/session_tracker.py +0 -123
  450. package/tui/settings.py +0 -353
  451. package/tui/settings_schema.py +0 -431
  452. package/tui/shell.py +0 -304
  453. package/tui/shell_read.py +0 -42
  454. package/tui/slash_command.py +0 -34
  455. package/tui/tui.tcss +0 -246
  456. package/tui/twitter.py +0 -38
  457. package/tui/version.py +0 -80
  458. package/tui/visuals/__init__.py +0 -0
  459. package/tui/visuals/__pycache__/__init__.cpython-314.pyc +0 -0
  460. package/tui/visuals/__pycache__/columns.cpython-314.pyc +0 -0
  461. package/tui/visuals/columns.py +0 -272
  462. package/tui/widgets/__init__.py +0 -0
  463. package/tui/widgets/__pycache__/__init__.cpython-314.pyc +0 -0
  464. package/tui/widgets/__pycache__/acp_content.cpython-314.pyc +0 -0
  465. package/tui/widgets/__pycache__/agent_response.cpython-314.pyc +0 -0
  466. package/tui/widgets/__pycache__/agent_thought.cpython-314.pyc +0 -0
  467. package/tui/widgets/__pycache__/ask_user.cpython-314.pyc +0 -0
  468. package/tui/widgets/__pycache__/condensed_path.cpython-314.pyc +0 -0
  469. package/tui/widgets/__pycache__/context_stats.cpython-314.pyc +0 -0
  470. package/tui/widgets/__pycache__/conversation.cpython-314.pyc +0 -0
  471. package/tui/widgets/__pycache__/diff_view.cpython-314.pyc +0 -0
  472. package/tui/widgets/__pycache__/directory_input.cpython-314.pyc +0 -0
  473. package/tui/widgets/__pycache__/flash.cpython-314.pyc +0 -0
  474. package/tui/widgets/__pycache__/future_text.cpython-314.pyc +0 -0
  475. package/tui/widgets/__pycache__/grid_select.cpython-314.pyc +0 -0
  476. package/tui/widgets/__pycache__/highlighted_textarea.cpython-314.pyc +0 -0
  477. package/tui/widgets/__pycache__/load_more.cpython-314.pyc +0 -0
  478. package/tui/widgets/__pycache__/mandelbrot.cpython-314.pyc +0 -0
  479. package/tui/widgets/__pycache__/markdown_note.cpython-314.pyc +0 -0
  480. package/tui/widgets/__pycache__/menu.cpython-314.pyc +0 -0
  481. package/tui/widgets/__pycache__/modified_files.cpython-314.pyc +0 -0
  482. package/tui/widgets/__pycache__/non_selectable_label.cpython-314.pyc +0 -0
  483. package/tui/widgets/__pycache__/note.cpython-314.pyc +0 -0
  484. package/tui/widgets/__pycache__/path_search.cpython-314.pyc +0 -0
  485. package/tui/widgets/__pycache__/plan.cpython-314.pyc +0 -0
  486. package/tui/widgets/__pycache__/project_directory_tree.cpython-314.pyc +0 -0
  487. package/tui/widgets/__pycache__/project_grid_select.cpython-314.pyc +0 -0
  488. package/tui/widgets/__pycache__/project_summary.cpython-314.pyc +0 -0
  489. package/tui/widgets/__pycache__/prompt.cpython-314.pyc +0 -0
  490. package/tui/widgets/__pycache__/question.cpython-314.pyc +0 -0
  491. package/tui/widgets/__pycache__/session_grid_select.cpython-314.pyc +0 -0
  492. package/tui/widgets/__pycache__/session_summary.cpython-314.pyc +0 -0
  493. package/tui/widgets/__pycache__/session_tabs.cpython-314.pyc +0 -0
  494. package/tui/widgets/__pycache__/shell_result.cpython-314.pyc +0 -0
  495. package/tui/widgets/__pycache__/shell_terminal.cpython-314.pyc +0 -0
  496. package/tui/widgets/__pycache__/side_bar.cpython-314.pyc +0 -0
  497. package/tui/widgets/__pycache__/slash_complete.cpython-314.pyc +0 -0
  498. package/tui/widgets/__pycache__/strike_text.cpython-314.pyc +0 -0
  499. package/tui/widgets/__pycache__/subagent.cpython-314.pyc +0 -0
  500. package/tui/widgets/__pycache__/subagent_screen.cpython-314.pyc +0 -0
  501. package/tui/widgets/__pycache__/terminal.cpython-314.pyc +0 -0
  502. package/tui/widgets/__pycache__/throbber.cpython-314.pyc +0 -0
  503. package/tui/widgets/__pycache__/tool_call.cpython-314.pyc +0 -0
  504. package/tui/widgets/__pycache__/user_input.cpython-314.pyc +0 -0
  505. package/tui/widgets/acp_content.py +0 -70
  506. package/tui/widgets/agent_response.py +0 -76
  507. package/tui/widgets/agent_thought.py +0 -167
  508. package/tui/widgets/ask_user.py +0 -264
  509. package/tui/widgets/command_pane.py +0 -223
  510. package/tui/widgets/condensed_path.py +0 -115
  511. package/tui/widgets/context_stats.py +0 -66
  512. package/tui/widgets/conversation.py +0 -2641
  513. package/tui/widgets/danger_warning.py +0 -65
  514. package/tui/widgets/diff_view.py +0 -69
  515. package/tui/widgets/directory_input.py +0 -8
  516. package/tui/widgets/flash.py +0 -81
  517. package/tui/widgets/future_text.py +0 -126
  518. package/tui/widgets/grid_select.py +0 -234
  519. package/tui/widgets/highlighted_textarea.py +0 -180
  520. package/tui/widgets/load_more.py +0 -24
  521. package/tui/widgets/mandelbrot.py +0 -294
  522. package/tui/widgets/markdown_note.py +0 -13
  523. package/tui/widgets/menu.py +0 -147
  524. package/tui/widgets/modified_files.py +0 -306
  525. package/tui/widgets/non_selectable_label.py +0 -5
  526. package/tui/widgets/note.py +0 -18
  527. package/tui/widgets/path_search.py +0 -492
  528. package/tui/widgets/plan.py +0 -285
  529. package/tui/widgets/project_directory_tree.py +0 -102
  530. package/tui/widgets/project_grid_select.py +0 -64
  531. package/tui/widgets/project_summary.py +0 -33
  532. package/tui/widgets/prompt.py +0 -795
  533. package/tui/widgets/question.py +0 -360
  534. package/tui/widgets/session_grid_select.py +0 -230
  535. package/tui/widgets/session_summary.py +0 -115
  536. package/tui/widgets/session_tabs.py +0 -188
  537. package/tui/widgets/shell_result.py +0 -35
  538. package/tui/widgets/shell_terminal.py +0 -40
  539. package/tui/widgets/side_bar.py +0 -124
  540. package/tui/widgets/slash_complete.py +0 -235
  541. package/tui/widgets/strike_text.py +0 -70
  542. package/tui/widgets/subagent.py +0 -287
  543. package/tui/widgets/subagent_screen.py +0 -709
  544. package/tui/widgets/terminal.py +0 -576
  545. package/tui/widgets/terminal_tool.py +0 -360
  546. package/tui/widgets/throbber.py +0 -100
  547. package/tui/widgets/tool_call.py +0 -398
  548. package/tui/widgets/user_input.py +0 -23
  549. package/tui/widgets/version.py +0 -5
  550. package/tui/widgets/welcome.py +0 -31
@@ -1,77 +0,0 @@
1
- from __future__ import annotations
2
-
3
- from dataclasses import dataclass, field
4
- from enum import Enum
5
- from pathlib import Path
6
- from typing import Optional
7
-
8
- from onecode.agent.tools.errors import ToolPermissionError
9
-
10
-
11
- class PermissionResult(str, Enum):
12
- ALLOW = "allow"
13
- DENY = "deny"
14
- ASK = "ask"
15
-
16
-
17
- def _resolve_path(p: str | Path) -> Path:
18
- return Path(p).expanduser().resolve()
19
-
20
-
21
- def _is_within(child: Path, parent: Path) -> bool:
22
- try:
23
- child.relative_to(parent)
24
- return True
25
- except ValueError:
26
- return False
27
-
28
-
29
- @dataclass
30
- class ToolPermissionContext:
31
- deny_names: frozenset[str] = field(default_factory=frozenset)
32
- deny_prefixes: tuple[str, ...] = ()
33
- workspace_root: Optional[Path] = None
34
- additional_working_directories: tuple[Path, ...] = ()
35
-
36
- @classmethod
37
- def from_iterables(
38
- cls,
39
- deny_names: list[str] | None = None,
40
- deny_prefixes: list[str] | None = None,
41
- *,
42
- workspace_root: str | Path | None = None,
43
- additional_working_directories: list[str | Path] | None = None,
44
- ) -> ToolPermissionContext:
45
- return cls(
46
- deny_names=frozenset(name.lower() for name in (deny_names or [])),
47
- deny_prefixes=tuple(prefix.lower() for prefix in (deny_prefixes or [])),
48
- workspace_root=_resolve_path(workspace_root) if workspace_root else None,
49
- additional_working_directories=tuple(
50
- _resolve_path(p) for p in (additional_working_directories or [])
51
- ),
52
- )
53
-
54
- def blocks_tool(self, tool_name: str) -> bool:
55
- lowered = tool_name.lower()
56
- return lowered in self.deny_names or any(
57
- lowered.startswith(prefix) for prefix in self.deny_prefixes
58
- )
59
-
60
- def allowed_roots(self) -> tuple[Path, ...]:
61
- roots: list[Path] = []
62
- if self.workspace_root is not None:
63
- roots.append(self.workspace_root)
64
- roots.extend(self.additional_working_directories)
65
- return tuple(roots)
66
-
67
- def ensure_path_allowed(self, path: str | Path) -> Path:
68
- resolved = _resolve_path(path)
69
- roots = self.allowed_roots()
70
- if not roots:
71
- return resolved
72
- if any(_is_within(resolved, root) for root in roots):
73
- return resolved
74
- roots_str = ", ".join(str(r) for r in roots)
75
- raise ToolPermissionError(
76
- f"path is outside allowed working directories: {resolved} (allowed: {roots_str})"
77
- )
@@ -1,20 +0,0 @@
1
- from __future__ import annotations
2
-
3
- from dataclasses import dataclass
4
- from typing import Any, Literal, Optional
5
-
6
-
7
- @dataclass(frozen=True)
8
- class ToolCall:
9
- name: str
10
- input: dict[str, Any]
11
- tool_use_id: Optional[str] = None
12
-
13
-
14
- @dataclass(frozen=True)
15
- class ToolResult:
16
- name: str
17
- output: Any
18
- is_error: bool = False
19
- tool_use_id: Optional[str] = None
20
- content_type: Literal["text", "json"] = "json"
@@ -1,201 +0,0 @@
1
- from __future__ import annotations
2
-
3
- from abc import ABC, abstractmethod
4
- from dataclasses import dataclass
5
- from typing import Any, Callable, Iterable, Mapping
6
-
7
- from onecode.agent.tools.errors import ToolInputError, ToolPermissionError
8
- from onecode.agent.tools.protocol import ToolCall, ToolResult
9
- from onecode.agent.tools.schema_validation import validate_json_schema
10
-
11
-
12
- @dataclass(frozen=True)
13
- class ToolSpec:
14
- name: str
15
- description: str
16
- input_schema: Mapping[str, Any]
17
- aliases: tuple[str, ...] = ()
18
- is_read_only: bool = False
19
- is_destructive: bool = False
20
- max_result_size_chars: int = 20_000
21
-
22
-
23
- class Tool(ABC):
24
- @abstractmethod
25
- def spec(self) -> ToolSpec: ...
26
-
27
- @abstractmethod
28
- def run(self, tool_input: dict[str, Any]) -> ToolResult: ...
29
-
30
- async def run_async(
31
- self, tool_input: dict[str, Any],
32
- cancel_check: Callable[[], bool] | None = None,
33
- ) -> ToolResult:
34
- return self.run(tool_input)
35
-
36
-
37
- class ToolRegistry:
38
- def __init__(
39
- self,
40
- tools: Iterable[Tool] | None = None,
41
- ) -> None:
42
- self._tools: list[Tool] = []
43
- self._by_name: dict[str, Tool] = {}
44
- if tools:
45
- for tool in tools:
46
- self.register(tool)
47
-
48
- def register(self, tool: Tool) -> None:
49
- spec = tool.spec()
50
- key = spec.name.lower()
51
- if key in self._by_name:
52
- raise ValueError(f"duplicate tool name: {spec.name}")
53
- self._tools.append(tool)
54
- self._by_name[key] = tool
55
- for alias in spec.aliases:
56
- alias_key = alias.lower()
57
- if alias_key in self._by_name:
58
- raise ValueError(f"duplicate tool alias: {alias}")
59
- self._by_name[alias_key] = tool
60
-
61
- def list_specs(self) -> list[ToolSpec]:
62
- return [tool.spec() for tool in self._tools]
63
-
64
- def get(self, name: str) -> Tool | None:
65
- return self._by_name.get(name.lower())
66
-
67
- def make_openai_schemas(self) -> list[dict]:
68
- schemas = []
69
- for spec in self.list_specs():
70
- schemas.append({
71
- "type": "function",
72
- "function": {
73
- "name": spec.name,
74
- "description": spec.description,
75
- "parameters": dict(spec.input_schema),
76
- },
77
- })
78
- return schemas
79
-
80
- async def dispatch_async(
81
- self,
82
- call: ToolCall,
83
- cancel_check: Callable[[], bool] | None = None,
84
- ) -> ToolResult:
85
- tool = self.get(call.name)
86
- if tool is None:
87
- return ToolResult(
88
- name=call.name,
89
- output={"error": f"unknown tool: {call.name}"},
90
- is_error=True,
91
- tool_use_id=call.tool_use_id,
92
- )
93
- try:
94
- spec = tool.spec()
95
- validate_json_schema(call.input, spec.input_schema, tool_name=call.name)
96
- result = await tool.run_async(call.input, cancel_check=cancel_check)
97
- max_chars = spec.max_result_size_chars
98
- if max_chars > 0 and isinstance(result.output, str) and len(result.output) > max_chars:
99
- result = ToolResult(
100
- name=result.name,
101
- output=result.output[:max_chars]
102
- + f"\n\n[Output truncated to {max_chars} characters]",
103
- is_error=result.is_error,
104
- tool_use_id=result.tool_use_id or call.tool_use_id,
105
- content_type=result.content_type,
106
- )
107
- if result.tool_use_id is None:
108
- return ToolResult(
109
- name=result.name,
110
- output=result.output,
111
- is_error=result.is_error,
112
- tool_use_id=call.tool_use_id,
113
- content_type=result.content_type,
114
- )
115
- return result
116
- except ToolInputError as e:
117
- return ToolResult(
118
- name=call.name,
119
- output={"error": str(e)},
120
- is_error=True,
121
- tool_use_id=call.tool_use_id,
122
- )
123
- except ToolPermissionError as e:
124
- return ToolResult(
125
- name=call.name,
126
- output={"error": str(e)},
127
- is_error=True,
128
- tool_use_id=call.tool_use_id,
129
- )
130
- except Exception as e:
131
- return ToolResult(
132
- name=call.name,
133
- output={"error": str(e)},
134
- is_error=True,
135
- tool_use_id=call.tool_use_id,
136
- )
137
-
138
- def dispatch(
139
- self,
140
- call: ToolCall,
141
- ) -> ToolResult:
142
- tool = self.get(call.name)
143
- if tool is None:
144
- return ToolResult(
145
- name=call.name,
146
- output={"error": f"unknown tool: {call.name}"},
147
- is_error=True,
148
- tool_use_id=call.tool_use_id,
149
- )
150
- try:
151
- spec = tool.spec()
152
-
153
- # Schema validation
154
- validate_json_schema(call.input, spec.input_schema, tool_name=call.name)
155
-
156
- # Execute
157
- result = tool.run(call.input)
158
-
159
- # Enforce max result size — truncate oversized output so the
160
- # context window is not flooded by a single tool result.
161
- max_chars = spec.max_result_size_chars
162
- if max_chars > 0 and isinstance(result.output, str) and len(result.output) > max_chars:
163
- result = ToolResult(
164
- name=result.name,
165
- output=result.output[:max_chars]
166
- + f"\n\n[Output truncated to {max_chars} characters]",
167
- is_error=result.is_error,
168
- tool_use_id=result.tool_use_id or call.tool_use_id,
169
- content_type=result.content_type,
170
- )
171
-
172
- if result.tool_use_id is None:
173
- return ToolResult(
174
- name=result.name,
175
- output=result.output,
176
- is_error=result.is_error,
177
- tool_use_id=call.tool_use_id,
178
- content_type=result.content_type,
179
- )
180
- return result
181
- except ToolInputError as e:
182
- return ToolResult(
183
- name=call.name,
184
- output={"error": str(e)},
185
- is_error=True,
186
- tool_use_id=call.tool_use_id,
187
- )
188
- except ToolPermissionError as e:
189
- return ToolResult(
190
- name=call.name,
191
- output={"error": str(e)},
192
- is_error=True,
193
- tool_use_id=call.tool_use_id,
194
- )
195
- except Exception as e:
196
- return ToolResult(
197
- name=call.name,
198
- output={"error": str(e)},
199
- is_error=True,
200
- tool_use_id=call.tool_use_id,
201
- )
@@ -1,358 +0,0 @@
1
- from __future__ import annotations
2
-
3
- import asyncio
4
- import enum
5
- import os
6
- import resource
7
- import subprocess
8
- from dataclasses import dataclass, field
9
- from pathlib import Path
10
- from typing import Callable, Optional
11
-
12
-
13
- class SandboxMode(enum.Enum):
14
- NONE = "none"
15
- BUBBLEWRAP = "bwrap"
16
- DOCKER = "docker"
17
-
18
-
19
- @dataclass
20
- class ResourceLimits:
21
- cpu_time: int = 30
22
- memory_mb: int = 512
23
- max_procs: int = 10
24
- max_open_files: int = 100
25
- max_pseudo_terminals: int = 0
26
-
27
-
28
- @dataclass
29
- class SandboxConfig:
30
- workspace_root: Path
31
- mode: SandboxMode = SandboxMode.NONE
32
- resource_limits: ResourceLimits = field(default_factory=ResourceLimits)
33
- read_only_bindings: tuple[str, ...] = ("/usr", "/bin", "/lib", "/lib64", "/opt", "/tmp")
34
- network_enabled: bool = False
35
- env_whitelist: tuple[str, ...] = ("PATH", "HOME", "USER", "TERM", "LANG", "LC_*")
36
-
37
-
38
- class SandboxError(Exception):
39
- pass
40
-
41
-
42
- class Sandbox:
43
- def __init__(self, config: SandboxConfig):
44
- self.config = config
45
- self._bwrap_available: Optional[bool] = None
46
-
47
- def _check_bwrap_available(self) -> bool:
48
- if self._bwrap_available is not None:
49
- return self._bwrap_available
50
- try:
51
- subprocess.run(["bwrap", "--version"], capture_output=True, check=True)
52
- self._bwrap_available = True
53
- except (subprocess.CalledProcessError, FileNotFoundError):
54
- self._bwrap_available = False
55
- return self._bwrap_available
56
-
57
- def _build_bwrap_cmd(self, cmd: str) -> list[str]:
58
- ws = str(self.config.workspace_root.resolve())
59
-
60
- bwrap_args = ["bwrap"]
61
-
62
- bwrap_args.extend(["--dev", "/dev"])
63
- bwrap_args.extend(["--proc", "/proc"])
64
-
65
- bwrap_args.extend(["--bind", ws, "/workspace"])
66
-
67
- for ro_path in self.config.read_only_bindings:
68
- p = Path(ro_path)
69
- if p.exists():
70
- bwrap_args.extend(["--ro-bind", str(p), str(p)])
71
-
72
- bwrap_args.extend(["--tmpfs", "/tmp"])
73
- bwrap_args.extend(["--tmpfs", "/var/tmp"])
74
-
75
- if not self.config.network_enabled:
76
- bwrap_args.append("--unshare-net")
77
-
78
- bwrap_args.extend(["--uid", str(os.getuid())])
79
- bwrap_args.extend(["--gid", str(os.getgid())])
80
-
81
- bwrap_args.extend(["--setenv", "HOME", "/workspace"])
82
- bwrap_args.extend(["--setenv", "PATH", "/usr/local/sbin:/usr/local/bin:/usr/bin:/bin"])
83
-
84
- bwrap_args.extend(["--chdir", "/workspace"])
85
-
86
- bwrap_args.extend(["--", "sh", "-c", cmd])
87
-
88
- return bwrap_args
89
-
90
- def _set_resource_limits(self) -> None:
91
- """Deprecated: applied rlimits to the parent process which broke
92
- ``subprocess.run``. Kept as a no-op for backward compatibility —
93
- use :meth:`_exec_direct` (which now applies the limits in a
94
- ``preexec_fn``) instead.
95
- """
96
- return
97
-
98
- def exec(self, cmd: str, timeout: int = 60) -> dict:
99
- """Public entry point — dispatches to the right backend for the mode."""
100
- mode = self.config.mode
101
-
102
- if mode == SandboxMode.NONE:
103
- return self._exec_direct(cmd, timeout)
104
- if mode == SandboxMode.BUBBLEWRAP:
105
- if self._check_bwrap_available():
106
- return self._exec_bwrap(cmd, timeout)
107
- return self._exec_direct(cmd, timeout)
108
- if mode == SandboxMode.DOCKER:
109
- return self._exec_docker(cmd, timeout)
110
- return self._exec_direct(cmd, timeout)
111
-
112
- async def exec_async(
113
- self, cmd: str, timeout: int = 60,
114
- cancel_check: Callable[[], bool] | None = None,
115
- ) -> dict:
116
- """Async public entry point — supports cancellation mid-execution."""
117
- mode = self.config.mode
118
-
119
- if mode == SandboxMode.NONE:
120
- return await self._exec_direct_async(cmd, timeout, cancel_check)
121
- if mode == SandboxMode.BUBBLEWRAP:
122
- if self._check_bwrap_available():
123
- return await self._exec_bwrap_async(cmd, timeout, cancel_check)
124
- return await self._exec_direct_async(cmd, timeout, cancel_check)
125
- if mode == SandboxMode.DOCKER:
126
- # Docker exec is async-adaptable via docker-py, but keep sync for now
127
- return self._exec_docker(cmd, timeout)
128
- return await self._exec_direct_async(cmd, timeout, cancel_check)
129
-
130
- def _exec_direct(self, cmd: str, timeout: int) -> dict:
131
- # Apply resource limits in the *child* process only — calling
132
- # ``setrlimit`` on the parent (this Python interpreter) shrinks
133
- # its own address space, which then fails with ``EAGAIN`` on the
134
- # very next ``fork``/``execve`` that ``subprocess.run`` performs.
135
- limits = self.config.resource_limits
136
-
137
- def _preexec_apply_rlimits() -> None: # pragma: no cover (runs in child)
138
- try:
139
- resource.setrlimit(
140
- resource.RLIMIT_CPU, (limits.cpu_time, limits.cpu_time + 5)
141
- )
142
- except (ValueError, OSError, resource.error):
143
- pass
144
- try:
145
- mem_bytes = limits.memory_mb * 1024 * 1024
146
- resource.setrlimit(
147
- resource.RLIMIT_AS, (mem_bytes, mem_bytes)
148
- )
149
- except (ValueError, OSError, resource.error):
150
- pass
151
- try:
152
- result = subprocess.run(
153
- cmd,
154
- shell=True,
155
- capture_output=True,
156
- text=True,
157
- cwd=str(self.config.workspace_root),
158
- timeout=timeout,
159
- preexec_fn=_preexec_apply_rlimits,
160
- )
161
- return {
162
- "success": result.returncode == 0,
163
- "stdout": result.stdout,
164
- "stderr": result.stderr,
165
- "returncode": result.returncode,
166
- "sandbox": "none",
167
- }
168
- except subprocess.TimeoutExpired:
169
- return {"success": False, "error": "Command timed out", "sandbox": "none"}
170
- except Exception as e:
171
- return {"success": False, "error": str(e), "sandbox": "none"}
172
-
173
- async def _exec_direct_async(
174
- self, cmd: str, timeout: int,
175
- cancel_check: Callable[[], bool] | None = None,
176
- ) -> dict:
177
- limits = self.config.resource_limits
178
-
179
- def _preexec_apply_rlimits() -> None:
180
- try:
181
- resource.setrlimit(
182
- resource.RLIMIT_CPU, (limits.cpu_time, limits.cpu_time + 5)
183
- )
184
- except (ValueError, OSError, resource.error):
185
- pass
186
- try:
187
- mem_bytes = limits.memory_mb * 1024 * 1024
188
- resource.setrlimit(
189
- resource.RLIMIT_AS, (mem_bytes, mem_bytes)
190
- )
191
- except (ValueError, OSError, resource.error):
192
- pass
193
- process = await asyncio.create_subprocess_shell(
194
- cmd,
195
- stdout=asyncio.subprocess.PIPE,
196
- stderr=asyncio.subprocess.PIPE,
197
- cwd=str(self.config.workspace_root),
198
- preexec_fn=_preexec_apply_rlimits,
199
- )
200
- try:
201
- if cancel_check is not None and cancel_check():
202
- process.terminate()
203
- await process.wait()
204
- return {"success": False, "error": "Cancelled", "sandbox": "none"}
205
- stdout, stderr = await asyncio.wait_for(
206
- process.communicate(), timeout=timeout,
207
- )
208
- stdout = stdout.decode("utf-8", errors="replace") if isinstance(stdout, bytes) else stdout
209
- stderr = stderr.decode("utf-8", errors="replace") if isinstance(stderr, bytes) else stderr
210
- return {
211
- "success": process.returncode == 0,
212
- "stdout": stdout,
213
- "stderr": stderr,
214
- "returncode": process.returncode,
215
- "sandbox": "none",
216
- }
217
- except asyncio.TimeoutError:
218
- process.terminate()
219
- await process.wait()
220
- return {"success": False, "error": "Command timed out", "sandbox": "none"}
221
- except Exception as e:
222
- process.terminate()
223
- await process.wait()
224
- return {"success": False, "error": str(e), "sandbox": "none"}
225
-
226
- async def _exec_bwrap_async(
227
- self, cmd: str, timeout: int,
228
- cancel_check: Callable[[], bool] | None = None,
229
- ) -> dict:
230
- bwrap_cmd = self._build_bwrap_cmd(cmd)
231
- process = await asyncio.create_subprocess_exec(
232
- *bwrap_cmd,
233
- stdout=asyncio.subprocess.PIPE,
234
- stderr=asyncio.subprocess.PIPE,
235
- cwd=str(self.config.workspace_root),
236
- )
237
- try:
238
- if cancel_check is not None and cancel_check():
239
- process.terminate()
240
- await process.wait()
241
- return {"success": False, "error": "Cancelled", "sandbox": "bwrap"}
242
- stdout, stderr = await asyncio.wait_for(
243
- process.communicate(), timeout=timeout,
244
- )
245
- stdout = stdout.decode("utf-8", errors="replace") if isinstance(stdout, bytes) else stdout
246
- stderr = stderr.decode("utf-8", errors="replace") if isinstance(stderr, bytes) else stderr
247
- return {
248
- "success": process.returncode == 0,
249
- "stdout": stdout,
250
- "stderr": stderr,
251
- "returncode": process.returncode,
252
- "sandbox": "bwrap",
253
- }
254
- except asyncio.TimeoutError:
255
- process.terminate()
256
- await process.wait()
257
- return {"success": False, "error": "Command timed out", "sandbox": "bwrap"}
258
- except Exception as e:
259
- process.terminate()
260
- await process.wait()
261
- return {"success": False, "error": str(e), "sandbox": "bwrap"}
262
-
263
- def _exec_bwrap(self, cmd: str, timeout: int) -> dict:
264
- bwrap_cmd = self._build_bwrap_cmd(cmd)
265
-
266
- try:
267
- result = subprocess.run(
268
- bwrap_cmd,
269
- capture_output=True,
270
- text=True,
271
- cwd=str(self.config.workspace_root),
272
- timeout=timeout,
273
- )
274
- return {
275
- "success": result.returncode == 0,
276
- "stdout": result.stdout,
277
- "stderr": result.stderr,
278
- "returncode": result.returncode,
279
- "sandbox": "bwrap",
280
- }
281
- except subprocess.TimeoutExpired:
282
- return {"success": False, "error": "Command timed out", "sandbox": "bwrap"}
283
- except FileNotFoundError:
284
- return {"success": False, "error": "bwrap not installed", "sandbox": "bwrap"}
285
- except Exception as e:
286
- return {"success": False, "error": str(e), "sandbox": "bwrap"}
287
-
288
- def _exec_docker(self, cmd: str, timeout: int) -> dict:
289
- import docker
290
-
291
- ws = str(self.config.workspace_root.resolve())
292
-
293
- docker_cmd = [
294
- "sh", "-c",
295
- f"cd /workspace && {cmd}"
296
- ]
297
-
298
- try:
299
- client = docker.from_env()
300
- container = client.containers.run(
301
- "alpine:latest",
302
- docker_cmd,
303
- detach=True,
304
- mem_limit=f"{self.config.resource_limits.memory_mb}m",
305
- cpu_period=100000,
306
- cpu_quota=self.config.resource_limits.cpu_time * 1000,
307
- network_mode="none" if not self.config.network_enabled else "bridge",
308
- volumes={ws: {"bind": "/workspace", "mode": "rw"}},
309
- working_dir="/workspace",
310
- user=f"{os.getuid()}:{os.getgid()}",
311
- remove=True,
312
- )
313
- result = container.wait(timeout=timeout)
314
- logs = container.logs().decode("utf-8", errors="replace")
315
- return {
316
- "success": result["StatusCode"] == 0,
317
- "stdout": logs,
318
- "stderr": "",
319
- "returncode": result["StatusCode"],
320
- "sandbox": "docker",
321
- }
322
- except docker.errors.DockerException:
323
- return {"success": False, "error": "Docker not available", "sandbox": "docker"}
324
- except docker.errors.TimeoutError:
325
- return {"success": False, "error": "Container timed out", "sandbox": "docker"}
326
- except Exception as e:
327
- return {"success": False, "error": str(e), "sandbox": "docker"}
328
-
329
-
330
- def create_sandbox(
331
- workspace_root: Path,
332
- mode: str = "auto",
333
- **kwargs,
334
- ) -> Sandbox:
335
- if mode == "auto":
336
- sandbox_mode = SandboxMode.NONE
337
- if Path("/usr/bin/bwrap").exists():
338
- sandbox_mode = SandboxMode.BUBBLEWRAP
339
- elif Path("/var/run/docker.sock").exists():
340
- try:
341
- subprocess.run(["docker", "info"], capture_output=True, check=True)
342
- sandbox_mode = SandboxMode.DOCKER
343
- except (subprocess.CalledProcessError, FileNotFoundError):
344
- pass
345
- elif mode == "bwrap":
346
- sandbox_mode = SandboxMode.BUBBLEWRAP
347
- elif mode == "docker":
348
- sandbox_mode = SandboxMode.DOCKER
349
- else:
350
- sandbox_mode = SandboxMode.NONE
351
-
352
- config = SandboxConfig(
353
- workspace_root=workspace_root,
354
- mode=sandbox_mode,
355
- resource_limits=ResourceLimits(**kwargs) if kwargs else ResourceLimits(),
356
- )
357
-
358
- return Sandbox(config)