@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,699 +0,0 @@
1
- from __future__ import annotations
2
-
3
- from __future__ import annotations
4
-
5
- import asyncio
6
- import logging
7
- from abc import ABC, abstractmethod
8
- from dataclasses import dataclass, field
9
- from enum import Enum
10
- from typing import Any, AsyncIterator, Callable, Optional
11
-
12
-
13
- @dataclass(frozen=True)
14
- class ChatResponse:
15
- """Structured response from a streaming provider call (Clawd-Code style).
16
-
17
- Unlike ModelResponse (which uses ContentBlock list), ChatResponse provides
18
- a flat structure for the agent loop: content text + structured tool_uses + usage.
19
- """
20
- content: str = ""
21
- tool_uses: list[dict[str, Any]] = field(default_factory=list)
22
- usage: dict[str, int] = field(default_factory=dict)
23
-
24
-
25
- class ContentBlockType(str, Enum):
26
- TEXT = "text"
27
- IMAGE = "image"
28
- THINKING = "thinking"
29
- TOOL_USE = "tool_use"
30
- TOOL_RESULT = "tool_result"
31
- SERVER_TOOL_USE = "server_tool_use"
32
- TOOL_SEARCH_RESULT = "tool_search_tool_result"
33
- CODE_EXECUTION_RESULT = "code_execution_tool_result"
34
-
35
-
36
- @dataclass
37
- class ToolUse:
38
- id: str
39
- name: str
40
- input: dict[str, Any]
41
- caller: str = "agent"
42
-
43
-
44
- @dataclass
45
- class ServerToolUse:
46
- id: str
47
- name: str
48
- input: dict[str, Any]
49
-
50
-
51
- @dataclass
52
- class ToolSearchResult:
53
- tool_use_id: str
54
- content: Any # Can be dict with search results
55
-
56
-
57
- @dataclass
58
- class CodeExecutionResult:
59
- tool_use_id: str
60
- content: Any # Can be dict with execution output
61
-
62
-
63
- @dataclass
64
- class ImageContent:
65
- data: str # base64-encoded image data
66
- mime_type: str = "image/png"
67
-
68
-
69
- @dataclass
70
- class ToolResult:
71
- tool_use_id: str
72
- content: str
73
- is_error: bool = False
74
- content_blocks: list["ContentBlock"] = field(default_factory=list)
75
-
76
-
77
- @dataclass
78
- class ContentBlock:
79
- type: ContentBlockType
80
- text: Optional[str] = None
81
- thinking: Optional[str] = None
82
- image: Optional[ImageContent] = None
83
- tool_use: Optional[ToolUse] = None
84
- tool_result: Optional[ToolResult] = None
85
- server_tool_use: Optional[ServerToolUse] = None
86
- tool_search_result: Optional[ToolSearchResult] = None
87
- code_execution_result: Optional[CodeExecutionResult] = None
88
- cache_control: Optional[str] = None
89
-
90
-
91
- @dataclass
92
- class Message:
93
- role: str # user | assistant | system | tool
94
- content: list[ContentBlock] = field(default_factory=list)
95
- name: Optional[str] = None
96
-
97
- def __init__(self, role: str, content: str | list[ContentBlock] = "", name: Optional[str] = None):
98
- self.role = role
99
- self.name = name
100
- if isinstance(content, str):
101
- if role == "tool" and name:
102
- self.content = [ContentBlock(
103
- type=ContentBlockType.TOOL_RESULT,
104
- tool_result=ToolResult(tool_use_id=name, content=content),
105
- )]
106
- else:
107
- self.content = [ContentBlock(type=ContentBlockType.TEXT, text=content)] if content else []
108
- else:
109
- self.content = content
110
-
111
- def add_text(self, text: str) -> None:
112
- self.content.append(ContentBlock(type=ContentBlockType.TEXT, text=text))
113
-
114
- def add_image(self, data: str, mime_type: str = "image/png") -> None:
115
- self.content.append(ContentBlock(
116
- type=ContentBlockType.IMAGE,
117
- image=ImageContent(data=data, mime_type=mime_type),
118
- ))
119
-
120
- def add_thinking(self, thinking: str) -> None:
121
- self.content.append(ContentBlock(type=ContentBlockType.THINKING, thinking=thinking))
122
-
123
- def add_tool_use(self, tool_use: ToolUse) -> None:
124
- self.content.append(ContentBlock(type=ContentBlockType.TOOL_USE, tool_use=tool_use))
125
-
126
- def add_tool_result(self, tool_result: ToolResult) -> None:
127
- self.content.append(ContentBlock(type=ContentBlockType.TOOL_RESULT, tool_result=tool_result))
128
-
129
- def to_api_content(self) -> str:
130
- """Serialize text/thinking content for API calls.
131
-
132
- For image blocks, includes a placeholder describing the image
133
- so non-vision providers still get context about attached images.
134
- """
135
- parts = []
136
- for cb in self.content:
137
- if cb.type == ContentBlockType.TEXT and cb.text:
138
- parts.append(cb.text)
139
- elif cb.type == ContentBlockType.THINKING and cb.thinking:
140
- parts.append(cb.thinking)
141
- elif cb.type == ContentBlockType.IMAGE and cb.image:
142
- parts.append(f"[Image: {cb.image.mime_type}]")
143
- return "\n".join(parts)
144
-
145
- def to_api_dict(self) -> dict:
146
- """Serialize to OpenAI-compatible message dict (text-only).
147
-
148
- For vision-capable providers, use to_multimodal_dict() to include
149
- image content as content parts.
150
- """
151
- text = self.to_api_content()
152
- msg: dict = {"role": self.role}
153
- msg["content"] = text if text else None
154
-
155
- tool_calls = []
156
- for cb in self.content:
157
- if cb.type == ContentBlockType.TOOL_USE and cb.tool_use:
158
- tc = {
159
- "id": cb.tool_use.id,
160
- "type": "function",
161
- "function": {
162
- "name": cb.tool_use.name,
163
- "arguments": cb.tool_use.input if isinstance(cb.tool_use.input, str) else __import__("json").dumps(cb.tool_use.input),
164
- }
165
- }
166
- tool_calls.append(tc)
167
- if cb.type == ContentBlockType.TOOL_RESULT and cb.tool_result:
168
- msg["role"] = "tool"
169
- msg["tool_call_id"] = cb.tool_result.tool_use_id
170
- msg["content"] = cb.tool_result.content
171
-
172
- if tool_calls:
173
- msg["tool_calls"] = tool_calls
174
-
175
- return msg
176
-
177
- def to_multimodal_dict(self) -> dict:
178
- """Serialize to OpenAI-compatible message dict with image content.
179
-
180
- Returns content as a list of parts (text + image_url) for vision
181
- API calls. Falls back to to_api_dict() when no images are present.
182
- """
183
- has_image = any(cb.type == ContentBlockType.IMAGE and cb.image for cb in self.content)
184
- if not has_image:
185
- return self.to_api_dict()
186
-
187
- content_parts: list[dict] = []
188
- for cb in self.content:
189
- if cb.type == ContentBlockType.TEXT and cb.text:
190
- content_parts.append({"type": "text", "text": cb.text})
191
- elif cb.type == ContentBlockType.IMAGE and cb.image:
192
- content_parts.append({
193
- "type": "image_url",
194
- "image_url": {
195
- "url": f"data:{cb.image.mime_type};base64,{cb.image.data}",
196
- },
197
- })
198
-
199
- msg: dict = self.to_api_dict()
200
- msg["content"] = content_parts
201
- return msg
202
-
203
-
204
- @dataclass
205
- class ModelResponse:
206
- content: list[ContentBlock] = field(default_factory=list)
207
- model: str = ""
208
- usage: dict[str, Any] = field(default_factory=dict)
209
- raw: Any = None
210
-
211
- def __init__(self, content: str | list[ContentBlock | dict] = "", model: str = "", usage: dict[str, Any] = None, raw: Any = None):
212
- self.model = model
213
- self.usage = usage or {}
214
- self.raw = raw
215
- if isinstance(content, str):
216
- self.content = [ContentBlock(type=ContentBlockType.TEXT, text=content)] if content else []
217
- elif isinstance(content, list):
218
- self.content = []
219
- for item in content:
220
- if isinstance(item, ContentBlock):
221
- self.content.append(item)
222
- elif isinstance(item, dict):
223
- cb_type = ContentBlockType(item.get("type", "text"))
224
- if cb_type == ContentBlockType.TEXT:
225
- self.content.append(ContentBlock(type=cb_type, text=item.get("text", "")))
226
- elif cb_type == ContentBlockType.IMAGE:
227
- source = item.get("source", {})
228
- self.content.append(ContentBlock(
229
- type=cb_type,
230
- image=ImageContent(
231
- data=source.get("data", item.get("data", "")),
232
- mime_type=source.get("media_type", item.get("mimeType", "image/png")),
233
- ),
234
- ))
235
- elif cb_type == ContentBlockType.THINKING:
236
- self.content.append(ContentBlock(type=cb_type, thinking=item.get("thinking", "")))
237
- elif cb_type == ContentBlockType.TOOL_USE:
238
- self.content.append(ContentBlock(
239
- type=cb_type,
240
- tool_use=ToolUse(
241
- id=item.get("id", ""),
242
- name=item.get("name", ""),
243
- input=item.get("input", {}),
244
- caller=item.get("caller", "agent"),
245
- )
246
- ))
247
- elif cb_type == ContentBlockType.TOOL_RESULT:
248
- self.content.append(ContentBlock(
249
- type=cb_type,
250
- tool_result=ToolResult(
251
- tool_use_id=item.get("tool_use_id", ""),
252
- content=item.get("content", ""),
253
- is_error=item.get("is_error", False),
254
- )
255
- ))
256
- elif cb_type == ContentBlockType.SERVER_TOOL_USE:
257
- self.content.append(ContentBlock(
258
- type=cb_type,
259
- server_tool_use=ServerToolUse(
260
- id=item.get("id", ""),
261
- name=item.get("name", ""),
262
- input=item.get("input", {}),
263
- )
264
- ))
265
- elif cb_type == ContentBlockType.TOOL_SEARCH_RESULT:
266
- self.content.append(ContentBlock(
267
- type=cb_type,
268
- tool_search_result=ToolSearchResult(
269
- tool_use_id=item.get("tool_use_id", ""),
270
- content=item.get("content", {}),
271
- )
272
- ))
273
- elif cb_type == ContentBlockType.CODE_EXECUTION_RESULT:
274
- self.content.append(ContentBlock(
275
- type=cb_type,
276
- code_execution_result=CodeExecutionResult(
277
- tool_use_id=item.get("tool_use_id", ""),
278
- content=item.get("content", {}),
279
- )
280
- ))
281
- else:
282
- self.content.append(ContentBlock(type=cb_type, text=str(item)))
283
- else:
284
- self.content.append(ContentBlock(type=ContentBlockType.TEXT, text=str(item)))
285
- else:
286
- self.content = []
287
-
288
- def get_text(self) -> str:
289
- return "".join(cb.text or "" for cb in self.content if cb.type == ContentBlockType.TEXT)
290
-
291
- def get_thinking(self) -> Optional[str]:
292
- for cb in self.content:
293
- if cb.type == ContentBlockType.THINKING:
294
- return cb.thinking
295
- return None
296
-
297
-
298
- class Provider(ABC):
299
- name: str = ""
300
-
301
- _prep_logger = logging.getLogger("onecode.provider.prepare")
302
-
303
- @abstractmethod
304
- async def chat(
305
- self, messages: list[Message], model: str, **kwargs
306
- ) -> ModelResponse:
307
- ...
308
-
309
- @abstractmethod
310
- async def chat_stream(
311
- self, messages: list[Message], model: str, **kwargs
312
- ) -> AsyncIterator[str]:
313
- ...
314
- yield ""
315
-
316
- def resolve_api_key(self, key: Optional[str]) -> str:
317
- from onecode.config import resolve_env
318
-
319
- if key and key.startswith("${"):
320
- return resolve_env(key)
321
- return key or ""
322
-
323
- def prepare_messages(self, messages: list["Message"]) -> list[dict]:
324
- """Prepare messages for API call. Handles tool, tool_use, tool_result blocks properly.
325
-
326
- Hardening applied before serialization:
327
- 1. Drop ``tool`` messages with empty content and no ``tool_call_id``
328
- (the OpenAI-compatible API rejects these with HTTP 400).
329
- 2. Coalesce runs of consecutive identical ``user`` content into one
330
- message (some MiniMax gateways reject back-to-back duplicates).
331
- 3. Cap the combined system-prompt length at 32 KiB, keeping the
332
- highest-priority blocks (``AGENT_CONFIG`` → ``REACT_PHASE`` →
333
- newest skills) and dropping older skill bodies first.
334
- 4. Drop ``tool`` messages whose ``tool_call_id`` is not present in
335
- the immediately preceding assistant message's ``tool_calls`` —
336
- the MiniMax gateway returns ``(2013) tool call result does not
337
- follow tool call`` otherwise.
338
- 5. When a tool message is dropped (empty or orphan), also strip
339
- the matching ``tool_call`` entry from the *owning* assistant
340
- message — i.e. the assistant that originally emitted that
341
- ``tool_call.id``. Without this, the request still contains
342
- an ``assistant.tool_calls`` reference with no following
343
- ``tool`` result, which MiniMax rejects with the same (2013)
344
- error (``tool call and result not match`` in the stricter
345
- validator). Tracking is per-id, not per-last-assistant, so
346
- drops that span multiple turns (e.g. an empty result from
347
- turn 1 and a legitimate one from turn 2) are each routed
348
- back to the right assistant.
349
- """
350
- _SYSTEM_CAP_BYTES = 32 * 1024
351
- log = Provider._prep_logger
352
- dropped_empty_tools = 0
353
- dropped_orphan_tools = 0
354
- coalesced_user_msgs = 0
355
-
356
- system_parts: list[tuple[str, str]] = [] # (marker, body)
357
- non_system: list[dict] = []
358
-
359
- for m in messages:
360
- if m.role == "system":
361
- body = m.to_api_content()
362
- marker = ""
363
- if "<!-- AGENT_CONFIG -->" in body:
364
- marker = "AGENT_CONFIG"
365
- elif "<!-- REACT_PHASE -->" in body:
366
- marker = "REACT_PHASE"
367
- elif "<!-- SKILL:" in body:
368
- marker = "SKILL"
369
- elif "<!-- CDH_PROJECT -->" in body:
370
- marker = "CDH_PROJECT"
371
- if body:
372
- system_parts.append((marker, body))
373
- elif m.role == "tool":
374
- api = m.to_api_dict()
375
- has_id = bool(api.get("tool_call_id"))
376
- has_content = bool((api.get("content") or "").strip())
377
- if not has_id or not has_content:
378
- dropped_empty_tools += 1
379
- log.debug(
380
- "prepare_messages: dropped empty tool message (id=%r content_len=%d)",
381
- api.get("tool_call_id"),
382
- len(api.get("content") or ""),
383
- )
384
- continue
385
- non_system.append(api)
386
- else:
387
- non_system.append(m.to_api_dict())
388
-
389
- coalesced: list[dict] = []
390
- for msg in non_system:
391
- if (
392
- msg.get("role") == "user"
393
- and coalesced
394
- and coalesced[-1].get("role") == "user"
395
- and (msg.get("content") or "") == (coalesced[-1].get("content") or "")
396
- and not msg.get("tool_calls")
397
- and not coalesced[-1].get("tool_calls")
398
- ):
399
- coalesced_user_msgs += 1
400
- continue
401
- coalesced.append(msg)
402
- non_system = coalesced
403
-
404
- # First pass: walk messages, drop orphan tool messages, and build
405
- # a per-id map of ``tc_id -> owning assistant index`` so we know
406
- # exactly which assistant emitted each ``tool_call`` entry.
407
- linked: list[dict] = []
408
- last_assistant_tc_ids: set[str] = set()
409
- # Maps tool_call.id -> index in ``linked`` of the assistant that
410
- # currently owns it. Rebuilt whenever a new assistant message
411
- # is appended (matches the same reset semantics as
412
- # ``last_assistant_tc_ids``).
413
- tc_owner: dict[str, int] = {}
414
- for msg in non_system:
415
- if msg.get("role") == "tool":
416
- tcid = msg.get("tool_call_id") or ""
417
- if tcid not in last_assistant_tc_ids:
418
- dropped_orphan_tools += 1
419
- log.debug(
420
- "prepare_messages: dropped orphan tool message "
421
- "(tool_call_id=%r not in preceding assistant.tool_calls)",
422
- tcid,
423
- )
424
- continue
425
- linked.append(msg)
426
- continue
427
- new_index = len(linked)
428
- linked.append(msg)
429
- if msg.get("role") == "assistant":
430
- last_assistant_tc_ids = {
431
- tc.get("id") for tc in (msg.get("tool_calls") or []) if tc.get("id")
432
- }
433
- for tc in msg.get("tool_calls") or []:
434
- tcid = tc.get("id")
435
- if tcid:
436
- tc_owner[tcid] = new_index
437
- else:
438
- last_assistant_tc_ids = set()
439
- non_system = linked
440
-
441
- # Second pass: any tool_call whose matching tool message was
442
- # dropped (empty content caught above, or otherwise missing)
443
- # must be removed from the *owning* assistant message — not just
444
- # the last assistant. We do this in two steps:
445
- # 1. Walk the full list and collect every tool_call_id that
446
- # appears in any tool message — these are the "seen" ids.
447
- # 2. Walk again and, for each assistant message, find any
448
- # tool_call.id that is NOT in the seen set. Those are
449
- # dangling entries that must be stripped.
450
- seen_tool_ids: set[str] = set()
451
- for msg in non_system:
452
- if msg.get("role") == "tool":
453
- tcid = msg.get("tool_call_id") or ""
454
- if tcid:
455
- seen_tool_ids.add(tcid)
456
-
457
- dangling: dict[int, set[str]] = {}
458
- for msg in non_system:
459
- if msg.get("role") != "assistant":
460
- continue
461
- tcs = msg.get("tool_calls") or []
462
- if not tcs:
463
- continue
464
- for tc in tcs:
465
- tcid = tc.get("id") or ""
466
- if tcid and tcid not in seen_tool_ids:
467
- owner_idx = tc_owner.get(tcid)
468
- if owner_idx is not None:
469
- dangling.setdefault(owner_idx, set()).add(tcid)
470
- # Also strip tool_call entries with an empty id — those can
471
- # never be matched to a tool result and would be silently
472
- # dangling. This mirrors the upstream filter in the first-pass
473
- # tool tracking (``if tc.get("id")`` / ``if tcid``).
474
- for msg in non_system:
475
- if msg.get("role") != "assistant":
476
- continue
477
- tcs = msg.get("tool_calls") or []
478
- if not tcs:
479
- continue
480
- kept = [tc for tc in tcs if tc.get("id")]
481
- if len(kept) < len(tcs):
482
- log.debug(
483
- "prepare_messages: stripped %d empty-id tool_call entr%s "
484
- "from assistant message",
485
- len(tcs) - len(kept),
486
- "y" if len(tcs) - len(kept) == 1 else "ies",
487
- )
488
- if kept:
489
- msg["tool_calls"] = kept
490
- else:
491
- msg.pop("tool_calls", None)
492
-
493
- # Apply the cleanup: strip dangling tool_call entries. Empty
494
- # ``tool_calls`` lists are removed entirely.
495
- if dangling:
496
- total_stripped = 0
497
- for idx, ids in dangling.items():
498
- assistant_msg = non_system[idx]
499
- tcs = assistant_msg.get("tool_calls") or []
500
- kept = [tc for tc in tcs if (tc.get("id") or "") not in ids]
501
- stripped = len(tcs) - len(kept)
502
- if stripped:
503
- total_stripped += stripped
504
- log.debug(
505
- "prepare_messages: stripped %d dangling tool_call entr%s "
506
- "from assistant message idx=%d (ids=%r)",
507
- stripped,
508
- "y" if stripped == 1 else "ies",
509
- idx,
510
- sorted(ids),
511
- )
512
- if kept:
513
- assistant_msg["tool_calls"] = kept
514
- else:
515
- assistant_msg.pop("tool_calls", None)
516
- if total_stripped:
517
- log.info(
518
- "prepare_messages(%s): stripped %d dangling tool_call entr%s across %d assistant message(s)",
519
- self.name or "?",
520
- total_stripped,
521
- "y" if total_stripped == 1 else "ies",
522
- len(dangling),
523
- )
524
-
525
- if dropped_empty_tools or dropped_orphan_tools or coalesced_user_msgs:
526
- log.info(
527
- "prepare_messages(%s): dropped empty_tools=%d orphan_tools=%d "
528
- "coalesced_user=%d (input=%d output=%d)",
529
- self.name or "?",
530
- dropped_empty_tools,
531
- dropped_orphan_tools,
532
- coalesced_user_msgs,
533
- len(messages),
534
- len(non_system) + (1 if system_parts else 0),
535
- )
536
-
537
- combined_system = ""
538
- if system_parts:
539
- combined_parts = [body for _, body in system_parts]
540
- combined_system = "\n\n".join(combined_parts)
541
- if len(combined_system.encode("utf-8")) > _SYSTEM_CAP_BYTES:
542
- priority = {"AGENT_CONFIG": 0, "REACT_PHASE": 1, "CDH_PROJECT": 2, "SKILL": 3}
543
- ordered = sorted(
544
- range(len(system_parts)),
545
- key=lambda i: (priority.get(system_parts[i][0], 9), -i),
546
- )
547
- kept_indices: set[int] = set()
548
- running = 0
549
- for idx in ordered:
550
- marker, body = system_parts[idx]
551
- size = len(body.encode("utf-8")) + 2
552
- if marker == "AGENT_CONFIG":
553
- kept_indices.add(idx)
554
- running = max(running, size)
555
- continue
556
- if running + size <= _SYSTEM_CAP_BYTES:
557
- kept_indices.add(idx)
558
- running += size
559
- kept = [body for i, body in enumerate(combined_parts) if i in kept_indices]
560
- if not any("<!-- AGENT_CONFIG -->" in b for b in kept) and system_parts:
561
- kept.insert(0, system_parts[0][1])
562
- combined_system = "\n\n".join(kept).encode("utf-8")[:_SYSTEM_CAP_BYTES].decode("utf-8", errors="ignore")
563
-
564
- if combined_system:
565
- non_system.insert(0, {"role": "system", "content": combined_system})
566
-
567
- return non_system
568
-
569
- def parse_response_tool_calls(self, response_data: dict) -> list[dict]:
570
- """Extract tool calls from a non-streaming API response."""
571
- choice = response_data.get("choices", [{}])[0]
572
- msg = choice.get("message", {})
573
- tool_calls = msg.get("tool_calls", [])
574
- result = []
575
- for tc in tool_calls:
576
- func = tc.get("function", {})
577
- try:
578
- args = __import__("json").loads(func.get("arguments", "{}"))
579
- except Exception:
580
- args = {"raw": func.get("arguments", "")}
581
- if not isinstance(args, dict):
582
- args = {"raw": args}
583
- result.append({
584
- "id": tc.get("id", ""),
585
- "name": func.get("name", ""),
586
- "input": args,
587
- })
588
- return result
589
-
590
- # ── Clawd-Code style structured streaming ──
591
-
592
- def is_anthropic_style(self) -> bool:
593
- """Whether this provider uses Anthropic-style 'system' kwarg."""
594
- return False
595
-
596
- def supports_native_tools(self) -> bool:
597
- """Whether this provider accepts structured tools param in API calls.
598
-
599
- When True, TOOL_DESCRIPTIONS prose in the system prompt is skipped
600
- because the provider's native tool schema (passed via the ``tools``
601
- kwarg to ``chat_stream_response``) provides equivalent information.
602
- """
603
- return True
604
-
605
- async def chat_stream_response(
606
- self,
607
- messages: list[Message],
608
- model: str,
609
- on_text_chunk: Optional[Callable[[str], None]] = None,
610
- on_tool_call_delta: Optional[Callable[[str, str, str], None]] = None,
611
- **kwargs,
612
- ) -> ChatResponse:
613
- """Stream with structured ChatResponse return (Clawd-Code style).
614
-
615
- Default implementation: falls back to chat() for providers that
616
- don't implement structured streaming.
617
- """
618
- logging.getLogger("onecode.models.provider").warning(
619
- "[PROVIDER-STREAM] %s does not override chat_stream_response — "
620
- "falling back to non-streaming chat() (on_text_chunk will NOT fire)",
621
- type(self).__name__,
622
- )
623
- response = await asyncio.wait_for(
624
- self.chat(messages, model=model, **kwargs),
625
- timeout=300,
626
- )
627
- return ChatResponse(
628
- content=response.get_text(),
629
- tool_uses=[
630
- {"id": tu.id, "name": tu.name, "input": tu.input}
631
- for cb in response.content
632
- if cb.type == ContentBlockType.TOOL_USE and cb.tool_use
633
- for tu in [cb.tool_use]
634
- ],
635
- usage=response.usage,
636
- )
637
-
638
- # ── Error classification ────────────────────────────────────────
639
-
640
- @staticmethod
641
- def classify_http_error(
642
- status_code: int,
643
- body: str,
644
- *,
645
- retry_after: Optional[float] = None,
646
- ) -> "ProviderError": # noqa: F821
647
- """Convert an upstream HTTP error into the most specific
648
- :class:`ProviderError` subclass.
649
-
650
- The 4 KiB body cap is applied here too so callers don't have to
651
- remember to truncate before constructing the exception.
652
- """
653
- from onecode.models.errors import (
654
- AuthError,
655
- ContextLengthError,
656
- ProviderError,
657
- RateLimitError,
658
- TransientProviderError,
659
- )
660
- snippet = (body or "").strip()
661
- body_excerpt = snippet[:200] if snippet else ""
662
- if status_code == 429:
663
- return RateLimitError(
664
- "rate limit exceeded", status_code=status_code,
665
- retry_after=retry_after, body=snippet,
666
- )
667
- if status_code in (401, 403):
668
- return AuthError(
669
- "authentication failed", status_code=status_code, body=snippet,
670
- )
671
- if status_code == 400 and "context" in snippet.lower() and "length" in snippet.lower():
672
- return ContextLengthError(
673
- "context length exceeded", status_code=status_code, body=snippet,
674
- )
675
- if 500 <= status_code < 600:
676
- msg = f"upstream {status_code}: {body_excerpt}" if body_excerpt else f"upstream {status_code}"
677
- return TransientProviderError(
678
- msg, status_code=status_code, body=snippet,
679
- )
680
- msg = f"upstream error {status_code}: {body_excerpt}" if body_excerpt else f"upstream error {status_code}"
681
- return ProviderError(
682
- msg, status_code=status_code, body=snippet,
683
- )
684
-
685
-
686
- class ProviderRegistry:
687
- _providers: dict[str, type[Provider]] = {}
688
-
689
- @classmethod
690
- def register(cls, name: str, provider_cls: type[Provider]):
691
- cls._providers[name] = provider_cls
692
-
693
- @classmethod
694
- def get(cls, name: str) -> Optional[type[Provider]]:
695
- return cls._providers.get(name)
696
-
697
- @classmethod
698
- def list(cls) -> list[str]:
699
- return list(cls._providers.keys())