@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,84 +0,0 @@
1
- from __future__ import annotations
2
-
3
- from textual.app import ComposeResult
4
- from textual.binding import Binding
5
- from textual.containers import VerticalScroll
6
- from textual.screen import ModalScreen
7
- from textual.widgets import Static
8
-
9
- from tui.widgets.diff_view import make_diff
10
-
11
-
12
- class DiffScreen(ModalScreen[None]):
13
- """Full-screen view of a file diff.
14
-
15
- Opened when a file is selected from the ModifiedFiles sidebar. Displays
16
- the same DiffView widget that ``Conversation.post_diff`` would have mounted
17
- inline, but as a dedicated modal screen instead of a conversation block.
18
- """
19
-
20
- BINDINGS = [
21
- Binding("escape", "dismiss(None)", "Close", show=False, priority=True),
22
- Binding("q", "dismiss(None)", "Close", show=False, priority=True),
23
- ]
24
-
25
- DEFAULT_CSS = """
26
- DiffScreen {
27
- background: $surface;
28
- }
29
-
30
- #diff-header {
31
- dock: top;
32
- width: 100%;
33
- padding: 1 2;
34
- background: $panel;
35
- color: $text-primary;
36
- text-style: bold;
37
- height: 3;
38
- }
39
-
40
- #diff-header-meta {
41
- color: $text-muted;
42
- text-style: none;
43
- }
44
-
45
- #diff-scroll {
46
- width: 100%;
47
- height: 1fr;
48
- padding: 0 1 0 1;
49
- }
50
-
51
- #diff-scroll > DiffView {
52
- width: 100%;
53
- height: auto;
54
- }
55
- """
56
-
57
- def __init__(
58
- self,
59
- path: str,
60
- before: str | None,
61
- after: str,
62
- *,
63
- name: str | None = None,
64
- id: str | None = None,
65
- classes: str | None = None,
66
- ) -> None:
67
- super().__init__(name=name, id=id, classes=classes)
68
- self._path = path
69
- self._before = before
70
- self._after = after
71
-
72
- def compose(self) -> ComposeResult:
73
- filename = self._path.rsplit("/", 1)[-1] or self._path
74
- meta = "untracked" if self._before is None else "modified"
75
- yield Static(
76
- f"[b]📝 {filename}[/b] [#888888]{meta}[/]",
77
- id="diff-header",
78
- markup=True,
79
- )
80
- with VerticalScroll(id="diff-scroll"):
81
- yield make_diff(self._path, self._path, self._before, self._after)
82
-
83
- def on_mount(self) -> None:
84
- self.title = f"Diff: {self._path}"
@@ -1,553 +0,0 @@
1
- """Log Screen — collapsible per-message view of the JSON-RPC log (F4)."""
2
- from __future__ import annotations
3
-
4
- import json
5
- import re
6
- from pathlib import Path
7
-
8
- from rich.text import Text
9
- from textual import on
10
- from textual.app import ComposeResult
11
- from textual.binding import Binding
12
- from textual.containers import Vertical, VerticalScroll
13
- from textual.message import Message
14
- from textual.reactive import reactive
15
- from textual.screen import ModalScreen
16
- from textual.widgets import Static
17
-
18
- from tui.paths import get_log
19
-
20
-
21
- _TAG_RE = re.compile(r"^\[(client|agent|error)\]\s*(.*)$", re.DOTALL)
22
- _PAGE_SIZE = 50
23
-
24
-
25
- def _find_log_file() -> Path | None:
26
- """Return the most recent message log file, or None if empty."""
27
- log_dir = get_log() / "messages"
28
- if not log_dir.exists():
29
- return None
30
- candidates = [
31
- p for p in log_dir.iterdir()
32
- if p.is_file() and p.suffix == ".jsonl" and not p.name.startswith(".")
33
- ]
34
- if not candidates:
35
- return None
36
- return max(candidates, key=lambda p: p.stat().st_mtime)
37
-
38
-
39
- # ── JSON syntax highlighting (ANSI) ───────────────────────────────
40
-
41
- _ANSI_HIGHLIGHT = re.compile(
42
- r'("(?:[^"\\]|\\.)*")(\s*:)?'
43
- r'|(-?\d+(?:\.\d+)?(?:[eE][+-]?\d+)?)'
44
- r'|\b(true|false|null)\b',
45
- )
46
-
47
-
48
- def _ansi_repl(m: re.Match) -> str:
49
- s, colon, num, lit = m.group(1), m.group(2), m.group(3), m.group(4)
50
- if s is not None:
51
- if colon:
52
- return f"\x1b[36m{s}\x1b[0m{colon}"
53
- return f"\x1b[33m{s}\x1b[0m"
54
- if num is not None:
55
- return f"\x1b[35m{num}\x1b[0m"
56
- if lit is not None:
57
- return f"\x1b[32m{lit}\x1b[0m"
58
- return m.group(0)
59
-
60
-
61
- def _highlight_json(raw: str) -> str:
62
- """Return a pretty-printed JSON string with ANSI color escapes."""
63
- try:
64
- obj = json.loads(raw)
65
- formatted = json.dumps(obj, indent=2, ensure_ascii=False)
66
- except Exception:
67
- return raw
68
- return _ANSI_HIGHLIGHT.sub(_ansi_repl, formatted)
69
-
70
-
71
- def _summarize_message_log(record: dict) -> str:
72
- """Extract a one-line summary of a MessageLog event record."""
73
- event = record.get("event", "")
74
- turn = record.get("turn", "")
75
- turn_str = f" [dim](turn {turn})[/dim]" if turn != "" else ""
76
- if event == "user_input":
77
- text = record.get("text", "")
78
- return f"user_input [dim]\"{text[:60]}{'…' if len(text) > 60 else ''}\"[/dim]{turn_str}"
79
- if event == "agent_output":
80
- text = record.get("text", "")
81
- return f"agent_output [dim]\"{text[:60]}{'…' if len(text) > 60 else ''}\"[/dim]{turn_str}"
82
- if event == "agent_thought":
83
- return f"agent_thought{turn_str}"
84
- if event == "tool_call":
85
- name = record.get("tool_name", "")
86
- return f"tool_call [bold]{name}[/bold]{turn_str}"
87
- if event == "tool_result":
88
- name = record.get("tool_name", "")
89
- status = record.get("status", "success")
90
- return f"tool_result [bold]{name}[/bold] → {status}{turn_str}"
91
- if event == "turn_end":
92
- reason = record.get("stop_reason", "")
93
- return f"turn_end stop={reason}{turn_str}"
94
- if event == "error":
95
- msg = record.get("message", "")
96
- return f"error: {msg[:60]}{turn_str}"
97
- return str(record)[:80]
98
-
99
-
100
- def _summarize(tag: str, raw: str) -> str:
101
- """Extract a one-line summary of a JSON-RPC or MessageLog message."""
102
- try:
103
- obj = json.loads(raw)
104
- except Exception:
105
- return raw[:80]
106
- if not isinstance(obj, dict):
107
- return str(obj)[:80]
108
- # MessageLog event record (event-driven format)
109
- if "event" in obj:
110
- return _summarize_message_log(obj)
111
- # Legacy JSON-RPC wire format
112
- if tag == "agent" and "method" in obj:
113
- method = obj.get("method", "")
114
- params = obj.get("params", {})
115
- if isinstance(params, dict):
116
- update = params.get("update", {})
117
- if isinstance(update, dict):
118
- kind = update.get("sessionUpdate", "")
119
- if kind:
120
- return f"{method} → {kind}"
121
- sid = params.get("sessionId", "")
122
- if method == "session/update" and sid:
123
- return f"{method} [dim]({sid[:8]}…)[/dim]"
124
- return method
125
- if tag == "client":
126
- method = obj.get("method", "")
127
- params = obj.get("params", {})
128
- if isinstance(params, dict):
129
- if method == "session/prompt":
130
- prompt = params.get("prompt", [])
131
- if isinstance(prompt, list) and prompt:
132
- first = prompt[0]
133
- if isinstance(first, dict):
134
- text = first.get("text", "")
135
- return f"{method} [dim]\"{text[:40]}{'…' if len(text) > 40 else ''}\"[/dim]"
136
- return method
137
- if "error" in obj:
138
- err = obj.get("error", {})
139
- return f"error: {err.get('message', '?')}" if isinstance(err, dict) else "error"
140
- return obj.get("method", raw[:60])
141
-
142
-
143
- # ── LogEntry: a single collapsible message ────────────────────────
144
-
145
- class LogEntryClicked(Message):
146
- """Posted when a LogEntry is clicked. Carries the entry reference."""
147
-
148
- def __init__(self, entry: "LogEntry") -> None:
149
- super().__init__()
150
- self.entry = entry
151
-
152
-
153
- class LogEntry(Static):
154
- """One log line: collapsed = summary, expanded = full pretty JSON."""
155
-
156
- DEFAULT_CSS = """
157
- LogEntry {
158
- height: auto;
159
- padding: 0 1;
160
- }
161
- LogEntry > .log-summary {
162
- height: 1;
163
- }
164
- LogEntry > .log-summary:hover {
165
- background: $panel;
166
- }
167
- LogEntry.-selected > .log-summary {
168
- background: $accent;
169
- color: $text;
170
- text-style: bold;
171
- }
172
- LogEntry > .log-body {
173
- height: auto;
174
- padding: 0 0 0 4;
175
- }
176
- LogEntry.-collapsed > .log-body {
177
- display: none;
178
- }
179
- """
180
-
181
- expanded: reactive[bool] = reactive(False)
182
- selected: reactive[bool] = reactive(False)
183
-
184
- def __init__(self, tag: str, raw: str) -> None:
185
- super().__init__()
186
- self.tag = tag
187
- self.raw = raw
188
-
189
- def compose(self) -> ComposeResult:
190
- yield Static(self._summary_text(), classes="log-summary")
191
- yield Static(self._body_text(), classes="log-body", markup=False)
192
-
193
- def on_mount(self) -> None:
194
- self.set_class(not self.expanded, "-collapsed")
195
-
196
- def _summary_text(self) -> Text:
197
- marker = "▼" if self.expanded else "▶"
198
- if self.tag == "client":
199
- style = "bold cyan"
200
- tag_label = "[→]"
201
- elif self.tag == "agent":
202
- style = "bold green"
203
- tag_label = "[←]"
204
- else:
205
- style = "bold red"
206
- tag_label = "[!]"
207
- t = Text()
208
- t.append(f" {marker} ", style="dim")
209
- t.append(tag_label, style=style)
210
- t.append(" ")
211
- # render the summary as markup
212
- from rich.markup import render as render_markup
213
- try:
214
- rendered = render_markup(self._summary_markup())
215
- t.append_text(rendered)
216
- except Exception:
217
- t.append(self._summary_markup())
218
- return t
219
-
220
- def _summary_markup(self) -> str:
221
- return _summarize(self.tag, self.raw)
222
-
223
- def _body_text(self) -> Text:
224
- return Text.from_ansi(_highlight_json(self.raw))
225
-
226
- def watch_expanded(self, expanded: bool) -> None:
227
- self.set_class(not expanded, "-collapsed")
228
- # Refresh the summary to update the ▼ / ▶ marker
229
- try:
230
- self.query_one(".log-summary", Static).update(self._summary_text())
231
- except Exception:
232
- pass
233
-
234
- def on_click(self) -> None:
235
- self.expanded = not self.expanded
236
- # Notify the screen to update its current_index
237
- self.post_message(LogEntryClicked(self))
238
-
239
- def watch_selected(self, selected: bool) -> None:
240
- self.set_class(selected, "-selected")
241
- if selected:
242
- self.scroll_visible()
243
-
244
-
245
- # ── LogScreen ──────────────────────────────────────────────────────
246
-
247
- class LogScreen(ModalScreen[None]):
248
- """Page-based log viewer (F4). Shows all log entries with 50 per page."""
249
-
250
- BINDINGS = [
251
- Binding("escape,f4", "dismiss", "Close"),
252
- # Entry navigation within current page
253
- Binding("down,j", "next_entry", "Next entry"),
254
- Binding("up,k", "prev_entry", "Prev entry"),
255
- # Page navigation (log is newest-first, so PageDown = older entries)
256
- Binding("pagedown,n", "prev_page", "Prev page", show=False),
257
- Binding("pageup,p", "next_page", "Next page", show=False),
258
- Binding("home,g", "first_page", "First page", show=False),
259
- Binding("end,G", "last_page", "Last page", show=False),
260
- # Toggle current
261
- Binding("enter,space,l", "toggle_current", "Toggle", show=False),
262
- Binding("o", "open_current", "Open", show=False),
263
- Binding("O", "expand_all", "Open all"),
264
- Binding("C", "collapse_all", "Close all"),
265
- # Misc
266
- Binding("c", "copy_all", "Copy"),
267
- ]
268
-
269
- DEFAULT_CSS = """
270
- LogScreen {
271
- align: center middle;
272
- }
273
-
274
- LogScreen > Vertical {
275
- width: 95%;
276
- height: 90%;
277
- border: thick $primary;
278
- background: $surface;
279
- }
280
-
281
- LogScreen #log-header {
282
- height: 1;
283
- background: $primary;
284
- color: $text;
285
- padding: 0 1;
286
- }
287
-
288
- LogScreen #log-list {
289
- height: 1fr;
290
- background: $surface;
291
- }
292
- """
293
-
294
- def __init__(self, log_path: Path | None = None) -> None:
295
- super().__init__()
296
- self._log_path = log_path
297
- self._file_pos = 0
298
- self._poll_timer: object = None
299
- self._entries: list[tuple[str, str]] = []
300
- self._current_page: int = 1
301
- self._current_index: int = -1
302
- self._file_was_present: bool = False
303
-
304
- def compose(self) -> ComposeResult:
305
- path = self._log_path or _find_log_file()
306
- self._log_path = path
307
- with Vertical():
308
- yield Static(self._header_text(), id="log-header")
309
- yield VerticalScroll(id="log-list")
310
-
311
- async def on_mount(self) -> None:
312
- self.query_one("#log-list", VerticalScroll).can_focus = False
313
- if self._log_path is None:
314
- self._append_system("No log file yet. Start an agent to begin logging.")
315
- return
316
- if not self._log_path.exists():
317
- self._append_system(
318
- f"⌛ Waiting for log file to be created…\n {self._log_path}"
319
- )
320
- self._poll_timer = self.set_interval(0.2, self._poll_new_lines)
321
- return
322
- await self._begin_tailing()
323
-
324
- # ── Page helpers ───────────────────────────────────────────────
325
-
326
- def _total_pages(self) -> int:
327
- return max(1, (len(self._entries) + _PAGE_SIZE - 1) // _PAGE_SIZE)
328
-
329
- def _page_range(self) -> tuple[int, int]:
330
- start = (self._current_page - 1) * _PAGE_SIZE
331
- end = min(start + _PAGE_SIZE, len(self._entries))
332
- return start, end
333
-
334
- async def _render_page(self) -> None:
335
- scroller = self.query_one("#log-list", VerticalScroll)
336
- await scroller.remove_children()
337
- start, end = self._page_range()
338
- page_entries = self._entries[start:end]
339
- await scroller.mount(*[LogEntry(tag, raw) for tag, raw in page_entries])
340
- self._current_index = 0 if page_entries else -1
341
- self._apply_selection()
342
- self._refresh_header()
343
-
344
- async def _navigate_to_page(self, page: int) -> None:
345
- total = self._total_pages()
346
- self._current_page = max(1, min(page, total))
347
- await self._render_page()
348
-
349
- # ── File loading ───────────────────────────────────────────────
350
-
351
- async def _begin_tailing(self) -> None:
352
- """Read entire log file and start polling."""
353
- assert self._log_path is not None
354
- try:
355
- with self._log_path.open("r", encoding="utf-8", errors="replace") as f:
356
- data = f.read()
357
- self._file_pos = self._log_path.stat().st_size
358
- except OSError as e:
359
- self._append_system(f"Failed to open log: {e}")
360
- return
361
- self._file_was_present = True
362
- self._entries = []
363
- await self._ingest(data)
364
- self._current_page = self._total_pages()
365
- await self._render_page()
366
- if self._poll_timer is None:
367
- self._poll_timer = self.set_interval(0.2, self._poll_new_lines)
368
-
369
- def on_unmount(self) -> None:
370
- if self._poll_timer is not None:
371
- stop = getattr(self._poll_timer, "stop", None)
372
- if callable(stop):
373
- stop()
374
- self._poll_timer = None
375
-
376
- def _header_text(self) -> str:
377
- total = len(self._entries)
378
- pages = self._total_pages()
379
- start, end = self._page_range()
380
- display_start = start + 1 if total > 0 else 0
381
- return (
382
- f"📋 Session log — Page {self._current_page}/{pages} · "
383
- f"Showing {display_start}-{end} of {total} entries │ "
384
- f"↑↓: entry · n/p: page · g/G: first/last · ⏎ toggle · F4/Esc close"
385
- if self._log_path
386
- else "📋 Session log — (no log file found)"
387
- )
388
-
389
- def _refresh_header(self) -> None:
390
- try:
391
- self.query_one("#log-header", Static).update(self._header_text())
392
- except Exception:
393
- pass
394
-
395
- def _apply_selection(self) -> None:
396
- scroller = self.query_one("#log-list", VerticalScroll)
397
- for i, child in enumerate(scroller.children):
398
- if isinstance(child, LogEntry):
399
- child.selected = (i == self._current_index)
400
-
401
- @on(LogEntryClicked)
402
- def on_log_entry_clicked(self, event: LogEntryClicked) -> None:
403
- scroller = self.query_one("#log-list", VerticalScroll)
404
- for i, child in enumerate(scroller.children):
405
- if child is event.entry:
406
- self._current_index = i
407
- self._apply_selection()
408
- return
409
-
410
- def _append_system(self, msg: str) -> None:
411
- scroller = self.query_one("#log-list", VerticalScroll)
412
- scroller.mount(Static(f"[dim]{msg}[/dim]"))
413
-
414
- # ── Polling for new lines ──────────────────────────────────────
415
-
416
- async def _poll_new_lines(self) -> None:
417
- if self._log_path is None:
418
- return
419
- if not self._log_path.exists():
420
- return
421
- if not self._file_was_present:
422
- self._append_system(f"── log file appeared: {self._log_path} ──")
423
- await self._begin_tailing()
424
- return
425
- try:
426
- size = self._log_path.stat().st_size
427
- if size < self._file_pos:
428
- self._file_pos = 0
429
- if size == self._file_pos:
430
- return
431
- with self._log_path.open("r", encoding="utf-8", errors="replace") as f:
432
- f.seek(self._file_pos)
433
- new_text = f.read()
434
- self._file_pos = size
435
- if new_text:
436
- await self._ingest(new_text)
437
- except OSError:
438
- pass
439
-
440
- async def _ingest(self, chunk: str) -> None:
441
- was_on_last_page = (
442
- len(self._entries) == 0
443
- or self._current_page == self._total_pages()
444
- )
445
- for line in chunk.splitlines():
446
- if not line.strip():
447
- continue
448
- try:
449
- record = json.loads(line)
450
- if isinstance(record, dict) and "event" in record:
451
- event = record.get("event", "")
452
- if event in ("user_input",):
453
- tag = "client"
454
- elif event in ("agent_output", "agent_thought", "tool_call", "tool_result", "turn_end"):
455
- tag = "agent"
456
- else:
457
- tag = "error"
458
- self._entries.append((tag, line))
459
- continue
460
- except (json.JSONDecodeError, ValueError):
461
- pass
462
- m = _TAG_RE.match(line)
463
- if m:
464
- self._entries.append((m.group(1), m.group(2)))
465
- else:
466
- self._entries.append(("error", line))
467
- if was_on_last_page:
468
- self._current_page = self._total_pages()
469
- await self._render_page()
470
- else:
471
- self._refresh_header()
472
-
473
- # ── Actions ────────────────────────────────────────────────────
474
-
475
- def _current_entry(self) -> LogEntry | None:
476
- scroller = self.query_one("#log-list", VerticalScroll)
477
- for i, child in enumerate(scroller.children):
478
- if isinstance(child, LogEntry) and i == self._current_index:
479
- return child
480
- return None
481
-
482
- async def action_next_page(self) -> None:
483
- if self._current_page < self._total_pages():
484
- await self._navigate_to_page(self._current_page + 1)
485
-
486
- async def action_prev_page(self) -> None:
487
- if self._current_page > 1:
488
- await self._navigate_to_page(self._current_page - 1)
489
-
490
- async def action_first_page(self) -> None:
491
- await self._navigate_to_page(1)
492
-
493
- async def action_last_page(self) -> None:
494
- await self._navigate_to_page(self._total_pages())
495
-
496
- def action_next_entry(self) -> None:
497
- scroller = self.query_one("#log-list", VerticalScroll)
498
- count = sum(1 for c in scroller.children if isinstance(c, LogEntry))
499
- if count == 0:
500
- return
501
- if self._current_index < 0:
502
- self._current_index = 0
503
- else:
504
- self._current_index = min(count - 1, self._current_index + 1)
505
- self._apply_selection()
506
-
507
- def action_prev_entry(self) -> None:
508
- scroller = self.query_one("#log-list", VerticalScroll)
509
- count = sum(1 for c in scroller.children if isinstance(c, LogEntry))
510
- if count == 0:
511
- return
512
- if self._current_index < 0:
513
- self._current_index = count - 1
514
- else:
515
- self._current_index = max(0, self._current_index - 1)
516
- self._apply_selection()
517
-
518
- def action_toggle_current(self) -> None:
519
- entry = self._current_entry()
520
- if entry is not None:
521
- entry.expanded = not entry.expanded
522
-
523
- def action_open_current(self) -> None:
524
- entry = self._current_entry()
525
- if entry is not None:
526
- entry.expanded = True
527
-
528
- def action_expand_all(self) -> None:
529
- scroller = self.query_one("#log-list", VerticalScroll)
530
- for child in scroller.children:
531
- if isinstance(child, LogEntry):
532
- child.expanded = True
533
-
534
- def action_collapse_all(self) -> None:
535
- scroller = self.query_one("#log-list", VerticalScroll)
536
- for child in scroller.children:
537
- if isinstance(child, LogEntry):
538
- child.expanded = False
539
-
540
- def action_copy_all(self) -> None:
541
- try:
542
- import pyperclip
543
- except ImportError:
544
- self.app.notify("pyperclip not installed", title="Log", severity="warning")
545
- return
546
- if self._log_path is None:
547
- return
548
- try:
549
- text = self._log_path.read_text(errors="replace")
550
- pyperclip.copy(text)
551
- self.app.notify("Log copied to clipboard", title="Log")
552
- except Exception as e:
553
- self.app.notify(f"Copy failed: {e}", title="Log", severity="error")