@scemoon/cdh 1.0.6 → 1.0.8

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 (551) hide show
  1. package/package.json +2 -2
  2. package/run.js +2 -1
  3. package/ai-dlc-skill/SKILL.md +0 -77
  4. package/ai-dlc-skill/agents/deliver-agent.md +0 -24
  5. package/ai-dlc-skill/agents/master.md +0 -50
  6. package/ai-dlc-skill/agents/plan-agent.md +0 -23
  7. package/ai-dlc-skill/agents/understand-agent.md +0 -23
  8. package/ai-dlc-skill/agents/verify-agent.md +0 -27
  9. package/ai-dlc-skill/architecture/project-structure.md +0 -78
  10. package/ai-dlc-skill/brownfield/README.md +0 -30
  11. package/ai-dlc-skill/brownfield/generate-context.sh +0 -64
  12. package/ai-dlc-skill/brownfield/scripts/deps.sh +0 -27
  13. package/ai-dlc-skill/brownfield/scripts/discover.sh +0 -34
  14. package/ai-dlc-skill/brownfield/scripts/extract-api.sh +0 -45
  15. package/ai-dlc-skill/components/backend.md +0 -34
  16. package/ai-dlc-skill/components/desktop.md +0 -30
  17. package/ai-dlc-skill/components/mya.md +0 -29
  18. package/ai-dlc-skill/components/native.md +0 -30
  19. package/ai-dlc-skill/components/tta.md +0 -29
  20. package/ai-dlc-skill/components/web.md +0 -31
  21. package/ai-dlc-skill/components/wxa.md +0 -29
  22. package/ai-dlc-skill/contracts/README.md +0 -25
  23. package/ai-dlc-skill/core/adaptive-flow.md +0 -36
  24. package/ai-dlc-skill/core/security.md +0 -29
  25. package/ai-dlc-skill/cross-tool/cline/export.sh +0 -31
  26. package/ai-dlc-skill/cross-tool/copilot/export.sh +0 -47
  27. package/ai-dlc-skill/cross-tool/cursor/export.sh +0 -32
  28. package/ai-dlc-skill/cross-tool/export.sh +0 -22
  29. package/ai-dlc-skill/cross-tool/onecode/config.yaml.tpl +0 -17
  30. package/ai-dlc-skill/cross-tool/onecode/export-skills.sh +0 -35
  31. package/ai-dlc-skill/cross-tool/onecode/export.sh +0 -54
  32. package/ai-dlc-skill/phases/deliver/entry.md +0 -26
  33. package/ai-dlc-skill/phases/deliver/lifecycle.md +0 -185
  34. package/ai-dlc-skill/phases/deliver/prompt.md +0 -40
  35. package/ai-dlc-skill/phases/deliver/rules.md +0 -61
  36. package/ai-dlc-skill/phases/plan/entry.md +0 -25
  37. package/ai-dlc-skill/phases/plan/lifecycle.md +0 -204
  38. package/ai-dlc-skill/phases/plan/prompt.md +0 -38
  39. package/ai-dlc-skill/phases/plan/rules.md +0 -25
  40. package/ai-dlc-skill/phases/understand/entry.md +0 -26
  41. package/ai-dlc-skill/phases/understand/lifecycle.md +0 -184
  42. package/ai-dlc-skill/phases/understand/prompt.md +0 -41
  43. package/ai-dlc-skill/phases/understand/rules.md +0 -37
  44. package/ai-dlc-skill/phases/verify/entry.md +0 -26
  45. package/ai-dlc-skill/phases/verify/lifecycle.md +0 -192
  46. package/ai-dlc-skill/phases/verify/prompt.md +0 -43
  47. package/ai-dlc-skill/phases/verify/rules.md +0 -73
  48. package/ai-dlc-skill/practices/bdd.md +0 -91
  49. package/ai-dlc-skill/practices/sdd.md +0 -84
  50. package/ai-dlc-skill/practices/tdd.md +0 -95
  51. package/ai-dlc-skill/providers/README.md +0 -114
  52. package/ai-dlc-skill/providers/aliyun/deployment.yaml +0 -66
  53. package/ai-dlc-skill/providers/aliyun/preview.yaml +0 -84
  54. package/ai-dlc-skill/providers/aliyun/provider.yaml +0 -160
  55. package/ai-dlc-skill/providers/tcb/deployment.yaml +0 -69
  56. package/ai-dlc-skill/providers/tcb/preview.yaml +0 -83
  57. package/ai-dlc-skill/providers/tcb/provider.yaml +0 -172
  58. package/ai-dlc-skill/requirements.md +0 -140
  59. package/ai-dlc-skill/skill.yaml +0 -147
  60. package/ai-dlc-skill/templates/integration/CHANGELOG.md +0 -41
  61. package/ai-dlc-skill/templates/integration/asyncapi.yaml +0 -43
  62. package/ai-dlc-skill/templates/integration/contract-diff.md +0 -63
  63. package/ai-dlc-skill/templates/integration/contract-spec.md +0 -49
  64. package/ai-dlc-skill/templates/integration/openapi.yaml +0 -18
  65. package/ai-dlc-skill/templates/integration/runtime-contract.yaml +0 -36
  66. package/ai-dlc-skill/templates/plan/design.md +0 -49
  67. package/ai-dlc-skill/templates/plan/task-list.md +0 -32
  68. package/ai-dlc-skill/templates/project/README.md +0 -126
  69. package/ai-dlc-skill/templates/project/template.md +0 -119
  70. package/ai-dlc-skill/templates/understand/feature.feature +0 -23
  71. package/ai-dlc-skill/templates/understand/intent.md +0 -29
  72. package/ai-dlc-skill/templates/understand/spec-delta.md +0 -47
  73. package/ai-dlc-skill/templates/verify/test-unit.py +0 -27
  74. package/ai-dlc-skill/walkthrough/collect.sh +0 -50
  75. package/ai-dlc-skill/walkthrough/template.md +0 -54
  76. package/ai-dlc-skill/workflows/ai-dlc.yaml +0 -110
  77. package/ai-dlc-skill/workflows/deployment.yaml +0 -199
  78. package/cdh/__init__.py +0 -0
  79. package/cdh/__main__.py +0 -4
  80. package/cdh/__pycache__/__init__.cpython-314.pyc +0 -0
  81. package/cdh/__pycache__/cdh_mcp_injector.cpython-314.pyc +0 -0
  82. package/cdh/__pycache__/cdh_mcp_loader.cpython-314.pyc +0 -0
  83. package/cdh/__pycache__/cdh_mcp_manager.cpython-314.pyc +0 -0
  84. package/cdh/__pycache__/cdh_session_aggregator.cpython-314.pyc +0 -0
  85. package/cdh/__pycache__/cdh_skill_loader.cpython-314.pyc +0 -0
  86. package/cdh/__pycache__/cdh_skill_manager.cpython-314.pyc +0 -0
  87. package/cdh/__pycache__/cli.cpython-313.pyc +0 -0
  88. package/cdh/__pycache__/cli.cpython-314.pyc +0 -0
  89. package/cdh/__pycache__/scaffold.cpython-314.pyc +0 -0
  90. package/cdh/cdh_mcp_injector.py +0 -115
  91. package/cdh/cdh_mcp_loader.py +0 -67
  92. package/cdh/cdh_mcp_manager.py +0 -73
  93. package/cdh/cdh_session_aggregator.py +0 -258
  94. package/cdh/cdh_skill_manager.py +0 -105
  95. package/cdh/cli.py +0 -807
  96. package/cdh/scaffold.py +0 -728
  97. package/onecode/__init__.py +0 -1
  98. package/onecode/__main__.py +0 -4
  99. package/onecode/__pycache__/__init__.cpython-314.pyc +0 -0
  100. package/onecode/__pycache__/cli.cpython-314.pyc +0 -0
  101. package/onecode/__pycache__/commands.cpython-314.pyc +0 -0
  102. package/onecode/__pycache__/config.cpython-314.pyc +0 -0
  103. package/onecode/__pycache__/config_screen.cpython-314.pyc +0 -0
  104. package/onecode/__pycache__/migrate.cpython-314.pyc +0 -0
  105. package/onecode/agent/__init__.py +0 -0
  106. package/onecode/agent/__pycache__/__init__.cpython-314.pyc +0 -0
  107. package/onecode/agent/__pycache__/cdh_loader.cpython-314.pyc +0 -0
  108. package/onecode/agent/__pycache__/context.cpython-314.pyc +0 -0
  109. package/onecode/agent/__pycache__/engine.cpython-314.pyc +0 -0
  110. package/onecode/agent/__pycache__/hooks.cpython-314.pyc +0 -0
  111. package/onecode/agent/__pycache__/onecode_agent_acp.cpython-314.pyc +0 -0
  112. package/onecode/agent/__pycache__/permissions.cpython-314.pyc +0 -0
  113. package/onecode/agent/__pycache__/permissions_store.cpython-314.pyc +0 -0
  114. package/onecode/agent/__pycache__/project_doc.cpython-314.pyc +0 -0
  115. package/onecode/agent/__pycache__/session.cpython-314.pyc +0 -0
  116. package/onecode/agent/agents/__init__.py +0 -29
  117. package/onecode/agent/agents/__pycache__/__init__.cpython-314.pyc +0 -0
  118. package/onecode/agent/agents/__pycache__/types.cpython-314.pyc +0 -0
  119. package/onecode/agent/agents/types.py +0 -589
  120. package/onecode/agent/attachments.py +0 -112
  121. package/onecode/agent/cdh_loader.py +0 -267
  122. package/onecode/agent/context.py +0 -343
  123. package/onecode/agent/engine.py +0 -2700
  124. package/onecode/agent/hooks.py +0 -86
  125. package/onecode/agent/onecode_agent_acp.py +0 -2743
  126. package/onecode/agent/onecode_agent_acp.py.bak +0 -2447
  127. package/onecode/agent/permissions.py +0 -150
  128. package/onecode/agent/permissions_store.py +0 -62
  129. package/onecode/agent/project_doc.py +0 -19
  130. package/onecode/agent/session.py +0 -195
  131. package/onecode/agent/snapshot.py +0 -144
  132. package/onecode/agent/tools/__init__.py +0 -17
  133. package/onecode/agent/tools/__pycache__/__init__.cpython-314.pyc +0 -0
  134. package/onecode/agent/tools/__pycache__/agent_tools.cpython-314.pyc +0 -0
  135. package/onecode/agent/tools/__pycache__/apply_patch_tool.cpython-314.pyc +0 -0
  136. package/onecode/agent/tools/__pycache__/bash_tool.cpython-314.pyc +0 -0
  137. package/onecode/agent/tools/__pycache__/communication_tools.cpython-314.pyc +0 -0
  138. package/onecode/agent/tools/__pycache__/config_tool.cpython-314.pyc +0 -0
  139. package/onecode/agent/tools/__pycache__/cron_tools.cpython-314.pyc +0 -0
  140. package/onecode/agent/tools/__pycache__/errors.cpython-314.pyc +0 -0
  141. package/onecode/agent/tools/__pycache__/file_ops.cpython-314.pyc +0 -0
  142. package/onecode/agent/tools/__pycache__/file_tools.cpython-314.pyc +0 -0
  143. package/onecode/agent/tools/__pycache__/git_tools.cpython-314.pyc +0 -0
  144. package/onecode/agent/tools/__pycache__/lsp_tools.cpython-314.pyc +0 -0
  145. package/onecode/agent/tools/__pycache__/mcp_tools.cpython-314.pyc +0 -0
  146. package/onecode/agent/tools/__pycache__/permission_handler.cpython-314.pyc +0 -0
  147. package/onecode/agent/tools/__pycache__/permissions.cpython-314.pyc +0 -0
  148. package/onecode/agent/tools/__pycache__/protocol.cpython-314.pyc +0 -0
  149. package/onecode/agent/tools/__pycache__/registry.cpython-314.pyc +0 -0
  150. package/onecode/agent/tools/__pycache__/sandbox.cpython-314.pyc +0 -0
  151. package/onecode/agent/tools/__pycache__/schema_validation.cpython-314.pyc +0 -0
  152. package/onecode/agent/tools/__pycache__/skill_tools.cpython-314.pyc +0 -0
  153. package/onecode/agent/tools/__pycache__/todo_tools.cpython-314.pyc +0 -0
  154. package/onecode/agent/tools/__pycache__/web_tools.cpython-314.pyc +0 -0
  155. package/onecode/agent/tools/agent_tools.py +0 -132
  156. package/onecode/agent/tools/apply_patch_tool.py +0 -138
  157. package/onecode/agent/tools/bash_tool.py +0 -111
  158. package/onecode/agent/tools/communication_tools.py +0 -148
  159. package/onecode/agent/tools/config_tool.py +0 -130
  160. package/onecode/agent/tools/cron_tools.py +0 -178
  161. package/onecode/agent/tools/errors.py +0 -17
  162. package/onecode/agent/tools/file_ops.py +0 -221
  163. package/onecode/agent/tools/file_tools.py +0 -225
  164. package/onecode/agent/tools/git_tools.py +0 -88
  165. package/onecode/agent/tools/lsp_tools.py +0 -404
  166. package/onecode/agent/tools/mcp_tools.py +0 -127
  167. package/onecode/agent/tools/permission_handler.py +0 -46
  168. package/onecode/agent/tools/permissions.py +0 -77
  169. package/onecode/agent/tools/protocol.py +0 -20
  170. package/onecode/agent/tools/registry.py +0 -201
  171. package/onecode/agent/tools/sandbox.py +0 -358
  172. package/onecode/agent/tools/schema_validation.py +0 -100
  173. package/onecode/agent/tools/skill_tools.py +0 -52
  174. package/onecode/agent/tools/todo_tools.py +0 -207
  175. package/onecode/agent/tools/web_tools.py +0 -169
  176. package/onecode/builtin_skills/agent-browser/SKILL.md +0 -212
  177. package/onecode/builtin_skills/agent-browser/skill.yaml +0 -8
  178. package/onecode/builtin_skills/git/SKILL.md +0 -64
  179. package/onecode/builtin_skills/git/skill.yaml +0 -7
  180. package/onecode/builtin_skills/shell/SKILL.md +0 -58
  181. package/onecode/builtin_skills/shell/skill.yaml +0 -8
  182. package/onecode/builtin_skills/skill-creator/SKILL.md +0 -106
  183. package/onecode/builtin_skills/skill-creator/skill.yaml +0 -8
  184. package/onecode/cli.py +0 -935
  185. package/onecode/cloud/__init__.py +0 -0
  186. package/onecode/cloud/base.py +0 -20
  187. package/onecode/codebase/__init__.py +0 -69
  188. package/onecode/codebase/__pycache__/__init__.cpython-314.pyc +0 -0
  189. package/onecode/codebase/__pycache__/chunker.cpython-314.pyc +0 -0
  190. package/onecode/codebase/__pycache__/indexer.cpython-314.pyc +0 -0
  191. package/onecode/codebase/__pycache__/retriever.cpython-314.pyc +0 -0
  192. package/onecode/codebase/__pycache__/storage.cpython-314.pyc +0 -0
  193. package/onecode/codebase/__pycache__/tools.cpython-314.pyc +0 -0
  194. package/onecode/codebase/chunker.py +0 -125
  195. package/onecode/codebase/indexer.py +0 -149
  196. package/onecode/codebase/retriever.py +0 -203
  197. package/onecode/codebase/storage.py +0 -131
  198. package/onecode/codebase/tools.py +0 -59
  199. package/onecode/commands.py +0 -596
  200. package/onecode/config.py +0 -314
  201. package/onecode/config_screen.py +0 -600
  202. package/onecode/cron/__init__.py +0 -3
  203. package/onecode/lsp/__init__.py +0 -3
  204. package/onecode/mcp/__init__.py +0 -4
  205. package/onecode/mcp/__pycache__/__init__.cpython-314.pyc +0 -0
  206. package/onecode/mcp/__pycache__/client.cpython-314.pyc +0 -0
  207. package/onecode/mcp/__pycache__/manager.cpython-314.pyc +0 -0
  208. package/onecode/mcp/client.py +0 -193
  209. package/onecode/mcp/manager.py +0 -190
  210. package/onecode/memory/__init__.py +0 -49
  211. package/onecode/memory/__pycache__/__init__.cpython-314.pyc +0 -0
  212. package/onecode/memory/__pycache__/backend.cpython-314.pyc +0 -0
  213. package/onecode/memory/__pycache__/offload.cpython-314.pyc +0 -0
  214. package/onecode/memory/__pycache__/pyramid.cpython-314.pyc +0 -0
  215. package/onecode/memory/__pycache__/recall.cpython-314.pyc +0 -0
  216. package/onecode/memory/__pycache__/symbolic.cpython-314.pyc +0 -0
  217. package/onecode/memory/backend.py +0 -159
  218. package/onecode/memory/pyramid.py +0 -133
  219. package/onecode/memory/recall.py +0 -203
  220. package/onecode/migrate.py +0 -122
  221. package/onecode/models/__init__.py +0 -4
  222. package/onecode/models/__pycache__/__init__.cpython-314.pyc +0 -0
  223. package/onecode/models/__pycache__/errors.cpython-314.pyc +0 -0
  224. package/onecode/models/__pycache__/messages.cpython-314.pyc +0 -0
  225. package/onecode/models/__pycache__/provider.cpython-314.pyc +0 -0
  226. package/onecode/models/__pycache__/registry.cpython-314.pyc +0 -0
  227. package/onecode/models/errors.py +0 -104
  228. package/onecode/models/messages.py +0 -739
  229. package/onecode/models/provider.py +0 -699
  230. package/onecode/models/providers/__init__.py +0 -17
  231. package/onecode/models/providers/__pycache__/__init__.cpython-314.pyc +0 -0
  232. package/onecode/models/providers/__pycache__/anthropic_provider.cpython-314.pyc +0 -0
  233. package/onecode/models/providers/__pycache__/deepseek_provider.cpython-314.pyc +0 -0
  234. package/onecode/models/providers/__pycache__/glm_provider.cpython-314.pyc +0 -0
  235. package/onecode/models/providers/__pycache__/minimax_provider.cpython-314.pyc +0 -0
  236. package/onecode/models/providers/__pycache__/minimaxi_provider.cpython-314.pyc +0 -0
  237. package/onecode/models/providers/__pycache__/ollama_provider.cpython-314.pyc +0 -0
  238. package/onecode/models/providers/__pycache__/openai_provider.cpython-314.pyc +0 -0
  239. package/onecode/models/providers/anthropic_provider.py +0 -273
  240. package/onecode/models/providers/deepseek_provider.py +0 -212
  241. package/onecode/models/providers/glm_provider.py +0 -195
  242. package/onecode/models/providers/minimax_provider.py +0 -158
  243. package/onecode/models/providers/minimaxi_provider.py +0 -417
  244. package/onecode/models/providers/ollama_provider.py +0 -100
  245. package/onecode/models/providers/openai_provider.py +0 -237
  246. package/onecode/models/registry.py +0 -212
  247. package/onecode/server/__init__.py +0 -3
  248. package/onecode/server/app.py +0 -224
  249. package/onecode/skills/__init__.py +0 -11
  250. package/onecode/skills/__pycache__/__init__.cpython-314.pyc +0 -0
  251. package/onecode/skills/__pycache__/argument_substitution.cpython-314.pyc +0 -0
  252. package/onecode/skills/__pycache__/bootstrap.cpython-314.pyc +0 -0
  253. package/onecode/skills/__pycache__/create.cpython-314.pyc +0 -0
  254. package/onecode/skills/__pycache__/frontmatter.cpython-314.pyc +0 -0
  255. package/onecode/skills/__pycache__/loader.cpython-314.pyc +0 -0
  256. package/onecode/skills/__pycache__/manager.cpython-314.pyc +0 -0
  257. package/onecode/skills/__pycache__/model.cpython-314.pyc +0 -0
  258. package/onecode/skills/argument_substitution.py +0 -38
  259. package/onecode/skills/bootstrap.py +0 -124
  260. package/onecode/skills/create.py +0 -56
  261. package/onecode/skills/frontmatter.py +0 -33
  262. package/onecode/skills/loader.py +0 -139
  263. package/onecode/skills/manager.py +0 -75
  264. package/onecode/skills/model.py +0 -43
  265. package/onecode/storage/__init__.py +0 -0
  266. package/onecode/storage/activity.py +0 -63
  267. package/onecode/storage/project.py +0 -54
  268. package/onecode/storage/session.py +0 -112
  269. package/onecode/tasks/__init__.py +0 -26
  270. package/onecode/tasks/manager.py +0 -232
  271. package/onecode/tasks/models.py +0 -240
  272. package/onecode/trace/__init__.py +0 -0
  273. package/onecode/trace/tracer.py +0 -173
  274. package/onecode/utils/__init__.py +0 -0
  275. package/onecode/utils/helpers.py +0 -20
  276. package/pyproject.toml +0 -74
  277. package/tui/__init__.py +0 -46
  278. package/tui/__main__.py +0 -4
  279. package/tui/__pycache__/__init__.cpython-314.pyc +0 -0
  280. package/tui/__pycache__/_loop.cpython-314.pyc +0 -0
  281. package/tui/__pycache__/_path_fuzzy_search.cpython-314.pyc +0 -0
  282. package/tui/__pycache__/_path_match.cpython-314.pyc +0 -0
  283. package/tui/__pycache__/about.cpython-314.pyc +0 -0
  284. package/tui/__pycache__/agent.cpython-314.pyc +0 -0
  285. package/tui/__pycache__/agent_schema.cpython-314.pyc +0 -0
  286. package/tui/__pycache__/agents.cpython-314.pyc +0 -0
  287. package/tui/__pycache__/answer.cpython-314.pyc +0 -0
  288. package/tui/__pycache__/app.cpython-313.pyc +0 -0
  289. package/tui/__pycache__/app.cpython-314.pyc +0 -0
  290. package/tui/__pycache__/atomic.cpython-314.pyc +0 -0
  291. package/tui/__pycache__/complete.cpython-314.pyc +0 -0
  292. package/tui/__pycache__/constants.cpython-314.pyc +0 -0
  293. package/tui/__pycache__/conversation_markdown.cpython-314.pyc +0 -0
  294. package/tui/__pycache__/danger.cpython-314.pyc +0 -0
  295. package/tui/__pycache__/db.cpython-314.pyc +0 -0
  296. package/tui/__pycache__/dec.cpython-314.pyc +0 -0
  297. package/tui/__pycache__/directory.cpython-314.pyc +0 -0
  298. package/tui/__pycache__/directory_suggester.cpython-314.pyc +0 -0
  299. package/tui/__pycache__/directory_watcher.cpython-314.pyc +0 -0
  300. package/tui/__pycache__/format_path.cpython-314.pyc +0 -0
  301. package/tui/__pycache__/fuzzy.cpython-314.pyc +0 -0
  302. package/tui/__pycache__/fuzzy_index.cpython-314.pyc +0 -0
  303. package/tui/__pycache__/history.cpython-314.pyc +0 -0
  304. package/tui/__pycache__/jsonrpc.cpython-314.pyc +0 -0
  305. package/tui/__pycache__/menus.cpython-314.pyc +0 -0
  306. package/tui/__pycache__/message_log.cpython-314.pyc +0 -0
  307. package/tui/__pycache__/messages.cpython-314.pyc +0 -0
  308. package/tui/__pycache__/path_complete.cpython-314.pyc +0 -0
  309. package/tui/__pycache__/path_filter.cpython-314.pyc +0 -0
  310. package/tui/__pycache__/paths.cpython-314.pyc +0 -0
  311. package/tui/__pycache__/pill.cpython-314.pyc +0 -0
  312. package/tui/__pycache__/platform_commands.cpython-314.pyc +0 -0
  313. package/tui/__pycache__/protocol.cpython-314.pyc +0 -0
  314. package/tui/__pycache__/session_tracker.cpython-314.pyc +0 -0
  315. package/tui/__pycache__/settings.cpython-314.pyc +0 -0
  316. package/tui/__pycache__/settings_schema.cpython-314.pyc +0 -0
  317. package/tui/__pycache__/shell.cpython-314.pyc +0 -0
  318. package/tui/__pycache__/shell_read.cpython-314.pyc +0 -0
  319. package/tui/__pycache__/slash_command.cpython-314.pyc +0 -0
  320. package/tui/__pycache__/version.cpython-314.pyc +0 -0
  321. package/tui/_loop.py +0 -86
  322. package/tui/_path_fuzzy_search.py +0 -48
  323. package/tui/_path_match.py +0 -141
  324. package/tui/about.py +0 -95
  325. package/tui/acp/__pycache__/agent.cpython-314.pyc +0 -0
  326. package/tui/acp/__pycache__/api.cpython-314.pyc +0 -0
  327. package/tui/acp/__pycache__/encode_tool_call_id.cpython-314.pyc +0 -0
  328. package/tui/acp/__pycache__/messages.cpython-314.pyc +0 -0
  329. package/tui/acp/__pycache__/prompt.cpython-314.pyc +0 -0
  330. package/tui/acp/__pycache__/protocol.cpython-314.pyc +0 -0
  331. package/tui/acp/agent.py +0 -1002
  332. package/tui/acp/api.py +0 -73
  333. package/tui/acp/encode_tool_call_id.py +0 -12
  334. package/tui/acp/messages.py +0 -203
  335. package/tui/acp/prompt.py +0 -53
  336. package/tui/acp/protocol.py +0 -499
  337. package/tui/agent.py +0 -70
  338. package/tui/agent_schema.py +0 -76
  339. package/tui/agents.py +0 -46
  340. package/tui/ansi/__init__.py +0 -1
  341. package/tui/ansi/__pycache__/__init__.cpython-314.pyc +0 -0
  342. package/tui/ansi/__pycache__/_ansi.cpython-314.pyc +0 -0
  343. package/tui/ansi/__pycache__/_ansi_colors.cpython-314.pyc +0 -0
  344. package/tui/ansi/__pycache__/_control_codes.cpython-314.pyc +0 -0
  345. package/tui/ansi/__pycache__/_keys.cpython-314.pyc +0 -0
  346. package/tui/ansi/__pycache__/_sgr_styles.cpython-314.pyc +0 -0
  347. package/tui/ansi/__pycache__/_stream_parser.cpython-314.pyc +0 -0
  348. package/tui/ansi/_ansi.py +0 -1689
  349. package/tui/ansi/_ansi_colors.py +0 -264
  350. package/tui/ansi/_control_codes.py +0 -37
  351. package/tui/ansi/_keys.py +0 -251
  352. package/tui/ansi/_sgr_styles.py +0 -64
  353. package/tui/ansi/_stream_parser.py +0 -418
  354. package/tui/answer.py +0 -12
  355. package/tui/app.py +0 -1266
  356. package/tui/atomic.py +0 -37
  357. package/tui/cli.py +0 -313
  358. package/tui/code_analyze.py +0 -27
  359. package/tui/complete.py +0 -38
  360. package/tui/constants.py +0 -61
  361. package/tui/conversation_markdown.py +0 -30
  362. package/tui/danger.py +0 -372
  363. package/tui/data/agents/ampcode.com.toml +0 -52
  364. package/tui/data/agents/augmentcode.com.toml +0 -41
  365. package/tui/data/agents/cdh.cloud-dev-harness.toml +0 -23
  366. package/tui/data/agents/claude.com.toml +0 -41
  367. package/tui/data/agents/copilot.github.com.toml +0 -29
  368. package/tui/data/agents/crowai.dev.toml +0 -36
  369. package/tui/data/agents/cursor.com.toml +0 -38
  370. package/tui/data/agents/deepagents.langchain.com +0 -34
  371. package/tui/data/agents/docker.com.toml +0 -60
  372. package/tui/data/agents/geminicli.com.toml +0 -28
  373. package/tui/data/agents/goose.ai.toml +0 -52
  374. package/tui/data/agents/inference.huggingface.co.toml +0 -41
  375. package/tui/data/agents/kimi.com.toml +0 -35
  376. package/tui/data/agents/kiro.dev.toml +0 -43
  377. package/tui/data/agents/onecode.dev.toml +0 -22
  378. package/tui/data/agents/openai.com.toml +0 -53
  379. package/tui/data/agents/openclaw.ai.toml +0 -37
  380. package/tui/data/agents/opencode.ai.toml +0 -39
  381. package/tui/data/agents/openhands.dev.toml +0 -46
  382. package/tui/data/agents/stakpak.dev.toml +0 -62
  383. package/tui/data/agents/vibe.mistral.ai.toml +0 -31
  384. package/tui/data/agents/vtcode.dev.toml +0 -63
  385. package/tui/data/images/frog.png +0 -0
  386. package/tui/data/sounds/question.wav +0 -0
  387. package/tui/data/sounds/turn-over.wav +0 -0
  388. package/tui/db.py +0 -213
  389. package/tui/dec.py +0 -332
  390. package/tui/directory.py +0 -234
  391. package/tui/directory_suggester.py +0 -93
  392. package/tui/directory_watcher.py +0 -231
  393. package/tui/format_path.py +0 -25
  394. package/tui/fuzzy.py +0 -140
  395. package/tui/fuzzy_index.py +0 -275
  396. package/tui/gist.py +0 -33
  397. package/tui/history.py +0 -138
  398. package/tui/jsonrpc.py +0 -578
  399. package/tui/menus.py +0 -14
  400. package/tui/message_log.py +0 -69
  401. package/tui/messages.py +0 -144
  402. package/tui/option_content.py +0 -51
  403. package/tui/os.py +0 -0
  404. package/tui/path_complete.py +0 -217
  405. package/tui/path_filter.py +0 -124
  406. package/tui/paths.py +0 -87
  407. package/tui/pill.py +0 -23
  408. package/tui/platform_commands.py +0 -52
  409. package/tui/prompt/__pycache__/extract.cpython-314.pyc +0 -0
  410. package/tui/prompt/__pycache__/resource.cpython-314.pyc +0 -0
  411. package/tui/prompt/extract.py +0 -19
  412. package/tui/prompt/resource.py +0 -68
  413. package/tui/protocol.py +0 -28
  414. package/tui/screens/__init__.py +0 -0
  415. package/tui/screens/__pycache__/__init__.cpython-314.pyc +0 -0
  416. package/tui/screens/__pycache__/agent_modal.cpython-314.pyc +0 -0
  417. package/tui/screens/__pycache__/component_picker.cpython-314.pyc +0 -0
  418. package/tui/screens/__pycache__/diff_screen.cpython-314.pyc +0 -0
  419. package/tui/screens/__pycache__/log.cpython-314.pyc +0 -0
  420. package/tui/screens/__pycache__/main.cpython-313.pyc +0 -0
  421. package/tui/screens/__pycache__/main.cpython-314.pyc +0 -0
  422. package/tui/screens/__pycache__/permissions.cpython-314.pyc +0 -0
  423. package/tui/screens/__pycache__/projects_app.cpython-314.pyc +0 -0
  424. package/tui/screens/__pycache__/projects_screen.cpython-314.pyc +0 -0
  425. package/tui/screens/__pycache__/sessions.cpython-314.pyc +0 -0
  426. package/tui/screens/__pycache__/store.cpython-314.pyc +0 -0
  427. package/tui/screens/__pycache__/tool_content_screen.cpython-314.pyc +0 -0
  428. package/tui/screens/action_modal.py +0 -94
  429. package/tui/screens/agent_modal.py +0 -175
  430. package/tui/screens/command_edit_modal.py +0 -74
  431. package/tui/screens/component_picker.py +0 -168
  432. package/tui/screens/diff_screen.py +0 -84
  433. package/tui/screens/log.py +0 -553
  434. package/tui/screens/main.py +0 -385
  435. package/tui/screens/main.tcss +0 -655
  436. package/tui/screens/permissions.py +0 -404
  437. package/tui/screens/permissions.tcss +0 -72
  438. package/tui/screens/projects.tcss +0 -80
  439. package/tui/screens/projects_app.py +0 -347
  440. package/tui/screens/projects_screen.py +0 -284
  441. package/tui/screens/session_resume_modal.py +0 -172
  442. package/tui/screens/session_resume_modal.tcss +0 -35
  443. package/tui/screens/sessions.py +0 -164
  444. package/tui/screens/sessions.tcss +0 -119
  445. package/tui/screens/settings.py +0 -254
  446. package/tui/screens/settings.tcss +0 -101
  447. package/tui/screens/store.py +0 -500
  448. package/tui/screens/store.tcss +0 -274
  449. package/tui/screens/tool_content_screen.py +0 -59
  450. package/tui/session_tracker.py +0 -123
  451. package/tui/settings.py +0 -353
  452. package/tui/settings_schema.py +0 -431
  453. package/tui/shell.py +0 -304
  454. package/tui/shell_read.py +0 -42
  455. package/tui/slash_command.py +0 -34
  456. package/tui/tui.tcss +0 -246
  457. package/tui/twitter.py +0 -38
  458. package/tui/version.py +0 -80
  459. package/tui/visuals/__init__.py +0 -0
  460. package/tui/visuals/__pycache__/__init__.cpython-314.pyc +0 -0
  461. package/tui/visuals/__pycache__/columns.cpython-314.pyc +0 -0
  462. package/tui/visuals/columns.py +0 -272
  463. package/tui/widgets/__init__.py +0 -0
  464. package/tui/widgets/__pycache__/__init__.cpython-314.pyc +0 -0
  465. package/tui/widgets/__pycache__/acp_content.cpython-314.pyc +0 -0
  466. package/tui/widgets/__pycache__/agent_response.cpython-314.pyc +0 -0
  467. package/tui/widgets/__pycache__/agent_thought.cpython-314.pyc +0 -0
  468. package/tui/widgets/__pycache__/ask_user.cpython-314.pyc +0 -0
  469. package/tui/widgets/__pycache__/condensed_path.cpython-314.pyc +0 -0
  470. package/tui/widgets/__pycache__/context_stats.cpython-314.pyc +0 -0
  471. package/tui/widgets/__pycache__/conversation.cpython-314.pyc +0 -0
  472. package/tui/widgets/__pycache__/diff_view.cpython-314.pyc +0 -0
  473. package/tui/widgets/__pycache__/directory_input.cpython-314.pyc +0 -0
  474. package/tui/widgets/__pycache__/flash.cpython-314.pyc +0 -0
  475. package/tui/widgets/__pycache__/future_text.cpython-314.pyc +0 -0
  476. package/tui/widgets/__pycache__/grid_select.cpython-314.pyc +0 -0
  477. package/tui/widgets/__pycache__/highlighted_textarea.cpython-314.pyc +0 -0
  478. package/tui/widgets/__pycache__/load_more.cpython-314.pyc +0 -0
  479. package/tui/widgets/__pycache__/mandelbrot.cpython-314.pyc +0 -0
  480. package/tui/widgets/__pycache__/markdown_note.cpython-314.pyc +0 -0
  481. package/tui/widgets/__pycache__/menu.cpython-314.pyc +0 -0
  482. package/tui/widgets/__pycache__/modified_files.cpython-314.pyc +0 -0
  483. package/tui/widgets/__pycache__/non_selectable_label.cpython-314.pyc +0 -0
  484. package/tui/widgets/__pycache__/note.cpython-314.pyc +0 -0
  485. package/tui/widgets/__pycache__/path_search.cpython-314.pyc +0 -0
  486. package/tui/widgets/__pycache__/plan.cpython-314.pyc +0 -0
  487. package/tui/widgets/__pycache__/project_directory_tree.cpython-314.pyc +0 -0
  488. package/tui/widgets/__pycache__/project_grid_select.cpython-314.pyc +0 -0
  489. package/tui/widgets/__pycache__/project_summary.cpython-314.pyc +0 -0
  490. package/tui/widgets/__pycache__/prompt.cpython-314.pyc +0 -0
  491. package/tui/widgets/__pycache__/question.cpython-314.pyc +0 -0
  492. package/tui/widgets/__pycache__/session_grid_select.cpython-314.pyc +0 -0
  493. package/tui/widgets/__pycache__/session_summary.cpython-314.pyc +0 -0
  494. package/tui/widgets/__pycache__/session_tabs.cpython-314.pyc +0 -0
  495. package/tui/widgets/__pycache__/shell_result.cpython-314.pyc +0 -0
  496. package/tui/widgets/__pycache__/shell_terminal.cpython-314.pyc +0 -0
  497. package/tui/widgets/__pycache__/side_bar.cpython-314.pyc +0 -0
  498. package/tui/widgets/__pycache__/slash_complete.cpython-314.pyc +0 -0
  499. package/tui/widgets/__pycache__/strike_text.cpython-314.pyc +0 -0
  500. package/tui/widgets/__pycache__/subagent.cpython-314.pyc +0 -0
  501. package/tui/widgets/__pycache__/subagent_screen.cpython-314.pyc +0 -0
  502. package/tui/widgets/__pycache__/terminal.cpython-314.pyc +0 -0
  503. package/tui/widgets/__pycache__/throbber.cpython-314.pyc +0 -0
  504. package/tui/widgets/__pycache__/tool_call.cpython-314.pyc +0 -0
  505. package/tui/widgets/__pycache__/user_input.cpython-314.pyc +0 -0
  506. package/tui/widgets/acp_content.py +0 -70
  507. package/tui/widgets/agent_response.py +0 -76
  508. package/tui/widgets/agent_thought.py +0 -167
  509. package/tui/widgets/ask_user.py +0 -264
  510. package/tui/widgets/command_pane.py +0 -223
  511. package/tui/widgets/condensed_path.py +0 -115
  512. package/tui/widgets/context_stats.py +0 -66
  513. package/tui/widgets/conversation.py +0 -2641
  514. package/tui/widgets/danger_warning.py +0 -65
  515. package/tui/widgets/diff_view.py +0 -69
  516. package/tui/widgets/directory_input.py +0 -8
  517. package/tui/widgets/flash.py +0 -81
  518. package/tui/widgets/future_text.py +0 -126
  519. package/tui/widgets/grid_select.py +0 -234
  520. package/tui/widgets/highlighted_textarea.py +0 -180
  521. package/tui/widgets/load_more.py +0 -24
  522. package/tui/widgets/mandelbrot.py +0 -294
  523. package/tui/widgets/markdown_note.py +0 -13
  524. package/tui/widgets/menu.py +0 -147
  525. package/tui/widgets/modified_files.py +0 -306
  526. package/tui/widgets/non_selectable_label.py +0 -5
  527. package/tui/widgets/note.py +0 -18
  528. package/tui/widgets/path_search.py +0 -492
  529. package/tui/widgets/plan.py +0 -285
  530. package/tui/widgets/project_directory_tree.py +0 -102
  531. package/tui/widgets/project_grid_select.py +0 -64
  532. package/tui/widgets/project_summary.py +0 -33
  533. package/tui/widgets/prompt.py +0 -795
  534. package/tui/widgets/question.py +0 -360
  535. package/tui/widgets/session_grid_select.py +0 -230
  536. package/tui/widgets/session_summary.py +0 -115
  537. package/tui/widgets/session_tabs.py +0 -188
  538. package/tui/widgets/shell_result.py +0 -35
  539. package/tui/widgets/shell_terminal.py +0 -40
  540. package/tui/widgets/side_bar.py +0 -124
  541. package/tui/widgets/slash_complete.py +0 -235
  542. package/tui/widgets/strike_text.py +0 -70
  543. package/tui/widgets/subagent.py +0 -287
  544. package/tui/widgets/subagent_screen.py +0 -709
  545. package/tui/widgets/terminal.py +0 -576
  546. package/tui/widgets/terminal_tool.py +0 -360
  547. package/tui/widgets/throbber.py +0 -100
  548. package/tui/widgets/tool_call.py +0 -398
  549. package/tui/widgets/user_input.py +0 -23
  550. package/tui/widgets/version.py +0 -5
  551. 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())