@scemoon/cdh 1.0.5 → 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 (551) hide show
  1. package/package.json +2 -2
  2. package/run.js +68 -14
  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 -758
  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,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")