iCode-TUI 0.29.1__py3-none-any.whl

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 (1138) hide show
  1. chrys/__init__.py +16 -0
  2. chrys/app/__init__.py +3 -0
  3. chrys/app/acp/__init__.py +3 -0
  4. chrys/app/acp/bridge.py +664 -0
  5. chrys/app/acp/content.py +132 -0
  6. chrys/app/acp/doc/frontend-api.md +425 -0
  7. chrys/app/acp/history.py +585 -0
  8. chrys/app/acp/server.py +1796 -0
  9. chrys/app/acp/session_manager.py +1815 -0
  10. chrys/app/acp/tool_status.py +45 -0
  11. chrys/app/cli/__init__.py +3 -0
  12. chrys/app/cli/acp.py +178 -0
  13. chrys/app/cli/app.py +165 -0
  14. chrys/app/cli/approvals.py +101 -0
  15. chrys/app/cli/headless.py +223 -0
  16. chrys/app/cli/launch_cwd.py +42 -0
  17. chrys/app/cli/profiles.py +298 -0
  18. chrys/app/cli/progress.py +857 -0
  19. chrys/app/cli/run.py +425 -0
  20. chrys/app/cli/serve.py +1593 -0
  21. chrys/app/cli/tool_summary.py +225 -0
  22. chrys/app/cli/trajectory.py +201 -0
  23. chrys/app/cli/workflow.py +601 -0
  24. chrys/app/features/__init__.py +3 -0
  25. chrys/app/features/buddy/__init__.py +3 -0
  26. chrys/app/features/buddy/actions.py +68 -0
  27. chrys/app/features/buddy/animation.py +76 -0
  28. chrys/app/features/buddy/commands.py +196 -0
  29. chrys/app/features/buddy/docs/design.md +187 -0
  30. chrys/app/features/buddy/hatchery.py +80 -0
  31. chrys/app/features/buddy/lifecycle.py +41 -0
  32. chrys/app/features/buddy/model.py +265 -0
  33. chrys/app/features/buddy/pixel_renderer.py +113 -0
  34. chrys/app/features/buddy/pixel_sprites.py +279 -0
  35. chrys/app/features/buddy/portrait.py +76 -0
  36. chrys/app/features/buddy/progression.py +58 -0
  37. chrys/app/features/buddy/replies.py +191 -0
  38. chrys/app/features/buddy/sprites/alien.toml +70 -0
  39. chrys/app/features/buddy/sprites/axolotl.toml +71 -0
  40. chrys/app/features/buddy/sprites/bat.toml +69 -0
  41. chrys/app/features/buddy/sprites/bee.toml +69 -0
  42. chrys/app/features/buddy/sprites/cactus.toml +73 -0
  43. chrys/app/features/buddy/sprites/capybara.toml +70 -0
  44. chrys/app/features/buddy/sprites/cat.toml +69 -0
  45. chrys/app/features/buddy/sprites/crab.toml +70 -0
  46. chrys/app/features/buddy/sprites/dragon.toml +71 -0
  47. chrys/app/features/buddy/sprites/duck.toml +69 -0
  48. chrys/app/features/buddy/sprites/fox.toml +69 -0
  49. chrys/app/features/buddy/sprites/frog.toml +70 -0
  50. chrys/app/features/buddy/sprites/ghost.toml +70 -0
  51. chrys/app/features/buddy/sprites/goose.toml +69 -0
  52. chrys/app/features/buddy/sprites/jelly.toml +70 -0
  53. chrys/app/features/buddy/sprites/llama.toml +70 -0
  54. chrys/app/features/buddy/sprites/mushroom.toml +69 -0
  55. chrys/app/features/buddy/sprites/octopus.toml +70 -0
  56. chrys/app/features/buddy/sprites/owl.toml +70 -0
  57. chrys/app/features/buddy/sprites/panda.toml +71 -0
  58. chrys/app/features/buddy/sprites/penguin.toml +69 -0
  59. chrys/app/features/buddy/sprites/rabbit.toml +70 -0
  60. chrys/app/features/buddy/sprites/robot.toml +72 -0
  61. chrys/app/features/buddy/sprites/shark.toml +70 -0
  62. chrys/app/features/buddy/sprites/snail.toml +69 -0
  63. chrys/app/features/buddy/sprites/snake.toml +69 -0
  64. chrys/app/features/buddy/sprites/tabby.toml +69 -0
  65. chrys/app/features/buddy/sprites/turtle.toml +69 -0
  66. chrys/app/features/buddy/store.py +143 -0
  67. chrys/app/features/session_title/__init__.py +7 -0
  68. chrys/app/features/session_title/updater.py +582 -0
  69. chrys/app/installer.py +651 -0
  70. chrys/app/parsing.py +17 -0
  71. chrys/app/tui/__init__.py +3 -0
  72. chrys/app/tui/app.py +1287 -0
  73. chrys/app/tui/behaviors/__init__.py +3 -0
  74. chrys/app/tui/behaviors/click_outside_dismiss.py +90 -0
  75. chrys/app/tui/behaviors/insert_clipboard.py +73 -0
  76. chrys/app/tui/behaviors/right_click_copy.py +146 -0
  77. chrys/app/tui/binding_display.py +139 -0
  78. chrys/app/tui/buddy_messages.py +17 -0
  79. chrys/app/tui/buddy_reply.py +86 -0
  80. chrys/app/tui/chrys.tcss +549 -0
  81. chrys/app/tui/clipboard.py +109 -0
  82. chrys/app/tui/copy_messages.py +10 -0
  83. chrys/app/tui/i18n.py +230 -0
  84. chrys/app/tui/language.py +58 -0
  85. chrys/app/tui/notifications/__init__.py +12 -0
  86. chrys/app/tui/notifications/drivers.py +180 -0
  87. chrys/app/tui/notifications/service.py +126 -0
  88. chrys/app/tui/notifications/settings.py +141 -0
  89. chrys/app/tui/screens/__init__.py +3 -0
  90. chrys/app/tui/screens/agents/__init__.py +8 -0
  91. chrys/app/tui/screens/agents/agent_draft_store.py +937 -0
  92. chrys/app/tui/screens/agents/config.py +2142 -0
  93. chrys/app/tui/screens/agents/config.tcss +169 -0
  94. chrys/app/tui/screens/agents/panels/__init__.py +3 -0
  95. chrys/app/tui/screens/agents/panels/acp.py +1176 -0
  96. chrys/app/tui/screens/agents/panels/basic.py +497 -0
  97. chrys/app/tui/screens/agents/panels/compaction.py +231 -0
  98. chrys/app/tui/screens/agents/panels/config_card.py +218 -0
  99. chrys/app/tui/screens/agents/panels/instructions.py +91 -0
  100. chrys/app/tui/screens/agents/panels/markdown_report.py +76 -0
  101. chrys/app/tui/screens/agents/panels/mcp.py +2262 -0
  102. chrys/app/tui/screens/agents/panels/memory.py +684 -0
  103. chrys/app/tui/screens/agents/panels/path_entry.py +227 -0
  104. chrys/app/tui/screens/agents/panels/skills.py +806 -0
  105. chrys/app/tui/screens/agents/panels/subagents.py +652 -0
  106. chrys/app/tui/screens/agents/panels/tools.py +205 -0
  107. chrys/app/tui/screens/agents/picker.py +103 -0
  108. chrys/app/tui/screens/agents/skill_paths.py +38 -0
  109. chrys/app/tui/screens/agents/validation_messages.py +452 -0
  110. chrys/app/tui/screens/dialogs/__init__.py +35 -0
  111. chrys/app/tui/screens/dialogs/agent_load.py +834 -0
  112. chrys/app/tui/screens/dialogs/agent_load.tcss +78 -0
  113. chrys/app/tui/screens/dialogs/app_mode.py +55 -0
  114. chrys/app/tui/screens/dialogs/approval/__init__.py +15 -0
  115. chrys/app/tui/screens/dialogs/approval/approval.tcss +311 -0
  116. chrys/app/tui/screens/dialogs/approval/bodies/__init__.py +3 -0
  117. chrys/app/tui/screens/dialogs/approval/bodies/file_edit.py +210 -0
  118. chrys/app/tui/screens/dialogs/approval/bodies/sub_agent.py +82 -0
  119. chrys/app/tui/screens/dialogs/approval/body.py +110 -0
  120. chrys/app/tui/screens/dialogs/approval/dialog.py +565 -0
  121. chrys/app/tui/screens/dialogs/approval/mode.py +105 -0
  122. chrys/app/tui/screens/dialogs/ask_user.py +148 -0
  123. chrys/app/tui/screens/dialogs/ask_user.tcss +62 -0
  124. chrys/app/tui/screens/dialogs/base.py +84 -0
  125. chrys/app/tui/screens/dialogs/confirm.py +184 -0
  126. chrys/app/tui/screens/dialogs/confirm.tcss +46 -0
  127. chrys/app/tui/screens/dialogs/connection_test.py +183 -0
  128. chrys/app/tui/screens/dialogs/connection_test.tcss +92 -0
  129. chrys/app/tui/screens/dialogs/diagram.py +102 -0
  130. chrys/app/tui/screens/dialogs/diagram.tcss +24 -0
  131. chrys/app/tui/screens/dialogs/editor.py +378 -0
  132. chrys/app/tui/screens/dialogs/editor.tcss +132 -0
  133. chrys/app/tui/screens/dialogs/file_picker.py +582 -0
  134. chrys/app/tui/screens/dialogs/file_picker.tcss +78 -0
  135. chrys/app/tui/screens/dialogs/fork_session.py +219 -0
  136. chrys/app/tui/screens/dialogs/fork_session.tcss +75 -0
  137. chrys/app/tui/screens/dialogs/image_compression.py +102 -0
  138. chrys/app/tui/screens/dialogs/image_compression.tcss +28 -0
  139. chrys/app/tui/screens/dialogs/man_page.py +172 -0
  140. chrys/app/tui/screens/dialogs/man_page.tcss +39 -0
  141. chrys/app/tui/screens/dialogs/new_folder.py +277 -0
  142. chrys/app/tui/screens/dialogs/new_folder.tcss +51 -0
  143. chrys/app/tui/screens/dialogs/notice.tcss +14 -0
  144. chrys/app/tui/screens/dialogs/prompt_cache.py +144 -0
  145. chrys/app/tui/screens/dialogs/prompt_cache.tcss +38 -0
  146. chrys/app/tui/screens/dialogs/runtime_details.py +371 -0
  147. chrys/app/tui/screens/dialogs/runtime_details.tcss +49 -0
  148. chrys/app/tui/screens/dialogs/session_title.py +110 -0
  149. chrys/app/tui/screens/dialogs/session_title.tcss +43 -0
  150. chrys/app/tui/screens/dialogs/tool_view.py +207 -0
  151. chrys/app/tui/screens/dialogs/tool_view.tcss +43 -0
  152. chrys/app/tui/screens/dialogs/vision_unsupported.py +122 -0
  153. chrys/app/tui/screens/dialogs/vision_unsupported.tcss +35 -0
  154. chrys/app/tui/screens/dialogs/workflow_confirm.py +91 -0
  155. chrys/app/tui/screens/dialogs/workflow_confirm.tcss +17 -0
  156. chrys/app/tui/screens/dialogs/workflow_input.py +258 -0
  157. chrys/app/tui/screens/dialogs/workflow_input.tcss +73 -0
  158. chrys/app/tui/screens/dialogs/workflow_node.py +462 -0
  159. chrys/app/tui/screens/dialogs/workflow_node.tcss +41 -0
  160. chrys/app/tui/screens/dialogs/workflow_picker.py +46 -0
  161. chrys/app/tui/screens/dialogs/workflow_result.py +136 -0
  162. chrys/app/tui/screens/dialogs/workflow_result.tcss +14 -0
  163. chrys/app/tui/screens/diff/__init__.py +22 -0
  164. chrys/app/tui/screens/diff/rollback_modal.py +1381 -0
  165. chrys/app/tui/screens/diff/rollback_modal.tcss +248 -0
  166. chrys/app/tui/screens/diff/screen.py +1532 -0
  167. chrys/app/tui/screens/diff/screen.tcss +104 -0
  168. chrys/app/tui/screens/guides/__init__.py +7 -0
  169. chrys/app/tui/screens/guides/_docs/en/guides/configuration/agents.md +178 -0
  170. chrys/app/tui/screens/guides/_docs/en/guides/configuration/approval.md +117 -0
  171. chrys/app/tui/screens/guides/_docs/en/guides/configuration/chat-options.md +276 -0
  172. chrys/app/tui/screens/guides/_docs/en/guides/configuration/compaction.md +42 -0
  173. chrys/app/tui/screens/guides/_docs/en/guides/configuration/memory.md +48 -0
  174. chrys/app/tui/screens/guides/_docs/en/guides/configuration/models.md +158 -0
  175. chrys/app/tui/screens/guides/_docs/en/guides/configuration/settings.md +210 -0
  176. chrys/app/tui/screens/guides/_docs/en/guides/configuration/themes.md +61 -0
  177. chrys/app/tui/screens/guides/_docs/en/guides/configuration/tools.md +60 -0
  178. chrys/app/tui/screens/guides/_docs/en/guides/configuration/web-tools.md +286 -0
  179. chrys/app/tui/screens/guides/_docs/en/guides/daily-use/sessions.md +77 -0
  180. chrys/app/tui/screens/guides/_docs/en/guides/daily-use/workspaces.md +51 -0
  181. chrys/app/tui/screens/guides/_docs/en/guides/extensions/external-acp-agents.md +126 -0
  182. chrys/app/tui/screens/guides/_docs/en/guides/extensions/hooks.md +167 -0
  183. chrys/app/tui/screens/guides/_docs/en/guides/extensions/mcp.md +95 -0
  184. chrys/app/tui/screens/guides/_docs/en/guides/extensions/skills.md +175 -0
  185. chrys/app/tui/screens/guides/_docs/en/guides/running/icode-acp.md +61 -0
  186. chrys/app/tui/screens/guides/_docs/en/guides/running/icode-run.md +190 -0
  187. chrys/app/tui/screens/guides/_docs/en/guides/running/icode-serve.md +239 -0
  188. chrys/app/tui/screens/guides/_docs/en/guides/running/workflows.md +664 -0
  189. chrys/app/tui/screens/guides/_docs/en/reference/agent-profile.md +548 -0
  190. chrys/app/tui/screens/guides/_docs/en/reference/hooks.md +602 -0
  191. chrys/app/tui/screens/guides/_docs/en/reference/opentelemetry.md +177 -0
  192. chrys/app/tui/screens/guides/_docs/en/reference/settings.md +245 -0
  193. chrys/app/tui/screens/guides/_docs/en/reference/themes.md +149 -0
  194. chrys/app/tui/screens/guides/_docs/en/reference/tool-kinds-and-names.md +58 -0
  195. chrys/app/tui/screens/guides/_docs/en/reference/tui-slash-commands.md +76 -0
  196. chrys/app/tui/screens/guides/_docs/en/reference/workflows.md +1006 -0
  197. chrys/app/tui/screens/guides/_docs/en/start/getting-started.md +170 -0
  198. chrys/app/tui/screens/guides/_docs/en/start/what-is-icode.md +34 -0
  199. chrys/app/tui/screens/guides/_docs/index.yaml +100 -0
  200. chrys/app/tui/screens/guides/_docs/zh-Hans/guides/configuration/agents.md +178 -0
  201. chrys/app/tui/screens/guides/_docs/zh-Hans/guides/configuration/approval.md +117 -0
  202. chrys/app/tui/screens/guides/_docs/zh-Hans/guides/configuration/chat-options.md +276 -0
  203. chrys/app/tui/screens/guides/_docs/zh-Hans/guides/configuration/compaction.md +42 -0
  204. chrys/app/tui/screens/guides/_docs/zh-Hans/guides/configuration/memory.md +48 -0
  205. chrys/app/tui/screens/guides/_docs/zh-Hans/guides/configuration/models.md +158 -0
  206. chrys/app/tui/screens/guides/_docs/zh-Hans/guides/configuration/settings.md +210 -0
  207. chrys/app/tui/screens/guides/_docs/zh-Hans/guides/configuration/themes.md +61 -0
  208. chrys/app/tui/screens/guides/_docs/zh-Hans/guides/configuration/tools.md +60 -0
  209. chrys/app/tui/screens/guides/_docs/zh-Hans/guides/configuration/web-tools.md +286 -0
  210. chrys/app/tui/screens/guides/_docs/zh-Hans/guides/daily-use/sessions.md +77 -0
  211. chrys/app/tui/screens/guides/_docs/zh-Hans/guides/daily-use/workspaces.md +51 -0
  212. chrys/app/tui/screens/guides/_docs/zh-Hans/guides/extensions/external-acp-agents.md +126 -0
  213. chrys/app/tui/screens/guides/_docs/zh-Hans/guides/extensions/hooks.md +167 -0
  214. chrys/app/tui/screens/guides/_docs/zh-Hans/guides/extensions/mcp.md +95 -0
  215. chrys/app/tui/screens/guides/_docs/zh-Hans/guides/extensions/skills.md +175 -0
  216. chrys/app/tui/screens/guides/_docs/zh-Hans/guides/running/icode-acp.md +61 -0
  217. chrys/app/tui/screens/guides/_docs/zh-Hans/guides/running/icode-run.md +190 -0
  218. chrys/app/tui/screens/guides/_docs/zh-Hans/guides/running/icode-serve.md +239 -0
  219. chrys/app/tui/screens/guides/_docs/zh-Hans/guides/running/workflows.md +664 -0
  220. chrys/app/tui/screens/guides/_docs/zh-Hans/reference/agent-profile.md +548 -0
  221. chrys/app/tui/screens/guides/_docs/zh-Hans/reference/hooks.md +602 -0
  222. chrys/app/tui/screens/guides/_docs/zh-Hans/reference/opentelemetry.md +177 -0
  223. chrys/app/tui/screens/guides/_docs/zh-Hans/reference/settings.md +245 -0
  224. chrys/app/tui/screens/guides/_docs/zh-Hans/reference/themes.md +149 -0
  225. chrys/app/tui/screens/guides/_docs/zh-Hans/reference/tool-kinds-and-names.md +58 -0
  226. chrys/app/tui/screens/guides/_docs/zh-Hans/reference/tui-slash-commands.md +76 -0
  227. chrys/app/tui/screens/guides/_docs/zh-Hans/reference/workflows.md +1005 -0
  228. chrys/app/tui/screens/guides/_docs/zh-Hans/start/getting-started.md +170 -0
  229. chrys/app/tui/screens/guides/_docs/zh-Hans/start/what-is-icode.md +34 -0
  230. chrys/app/tui/screens/guides/index.py +215 -0
  231. chrys/app/tui/screens/guides/reader.py +173 -0
  232. chrys/app/tui/screens/guides/screen.py +442 -0
  233. chrys/app/tui/screens/guides/screen.tcss +52 -0
  234. chrys/app/tui/screens/logs/__init__.py +7 -0
  235. chrys/app/tui/screens/logs/screen.py +504 -0
  236. chrys/app/tui/screens/logs/screen.tcss +45 -0
  237. chrys/app/tui/screens/main/__init__.py +7 -0
  238. chrys/app/tui/screens/main/action_availability.py +30 -0
  239. chrys/app/tui/screens/main/buddy_command.py +143 -0
  240. chrys/app/tui/screens/main/commands.py +1073 -0
  241. chrys/app/tui/screens/main/config_actions.py +464 -0
  242. chrys/app/tui/screens/main/copy_actions.py +117 -0
  243. chrys/app/tui/screens/main/dialog_controllers.py +826 -0
  244. chrys/app/tui/screens/main/dialog_gateway.py +166 -0
  245. chrys/app/tui/screens/main/diff_controller.py +478 -0
  246. chrys/app/tui/screens/main/engine_read_model.py +184 -0
  247. chrys/app/tui/screens/main/event_handlers.py +2014 -0
  248. chrys/app/tui/screens/main/input_flow.py +241 -0
  249. chrys/app/tui/screens/main/live_diff.py +244 -0
  250. chrys/app/tui/screens/main/main_screen_presenter.py +295 -0
  251. chrys/app/tui/screens/main/model_indicator.py +217 -0
  252. chrys/app/tui/screens/main/navigation.py +343 -0
  253. chrys/app/tui/screens/main/ports.py +571 -0
  254. chrys/app/tui/screens/main/recent_dirs.py +123 -0
  255. chrys/app/tui/screens/main/rollback_controller.py +586 -0
  256. chrys/app/tui/screens/main/runtime_info.py +71 -0
  257. chrys/app/tui/screens/main/screen.py +2265 -0
  258. chrys/app/tui/screens/main/screen.tcss +21 -0
  259. chrys/app/tui/screens/main/session_handlers.py +1127 -0
  260. chrys/app/tui/screens/main/session_title.py +239 -0
  261. chrys/app/tui/screens/main/settings_coordinator.py +365 -0
  262. chrys/app/tui/screens/main/settings_persistence.py +184 -0
  263. chrys/app/tui/screens/main/shell_mode.py +112 -0
  264. chrys/app/tui/screens/main/state.py +289 -0
  265. chrys/app/tui/screens/main/submit_state.py +11 -0
  266. chrys/app/tui/screens/main/subscriptions.py +177 -0
  267. chrys/app/tui/screens/main/suggestions.py +982 -0
  268. chrys/app/tui/screens/main/tool_action_bridge.py +75 -0
  269. chrys/app/tui/screens/main/view_adapter.py +1567 -0
  270. chrys/app/tui/screens/main/workflow_browser.py +747 -0
  271. chrys/app/tui/screens/main/workflow_content.py +248 -0
  272. chrys/app/tui/screens/main/workflow_controller.py +240 -0
  273. chrys/app/tui/screens/main/workflow_feedback.py +137 -0
  274. chrys/app/tui/screens/main/workflow_flow.py +49 -0
  275. chrys/app/tui/screens/main/workflow_run_control.py +456 -0
  276. chrys/app/tui/screens/main/workflow_session_view.py +316 -0
  277. chrys/app/tui/screens/main/workspace_actions.py +272 -0
  278. chrys/app/tui/screens/main/workspace_branch.py +194 -0
  279. chrys/app/tui/screens/menus/__init__.py +8 -0
  280. chrys/app/tui/screens/menus/languages.py +114 -0
  281. chrys/app/tui/screens/models/__init__.py +7 -0
  282. chrys/app/tui/screens/models/picker.py +147 -0
  283. chrys/app/tui/screens/models/screen.py +2043 -0
  284. chrys/app/tui/screens/models/screen.tcss +255 -0
  285. chrys/app/tui/screens/sessions/__init__.py +8 -0
  286. chrys/app/tui/screens/sessions/presenter.py +586 -0
  287. chrys/app/tui/screens/sessions/screen.py +779 -0
  288. chrys/app/tui/screens/sessions/screen.tcss +127 -0
  289. chrys/app/tui/screens/settings/__init__.py +29 -0
  290. chrys/app/tui/screens/settings/danger.py +26 -0
  291. chrys/app/tui/screens/settings/dialog.py +281 -0
  292. chrys/app/tui/screens/settings/layout.py +519 -0
  293. chrys/app/tui/screens/settings/migrate_dialog.py +253 -0
  294. chrys/app/tui/screens/settings/panes/__init__.py +3 -0
  295. chrys/app/tui/screens/settings/panes/notifications.py +248 -0
  296. chrys/app/tui/screens/settings/panes/sessions.py +148 -0
  297. chrys/app/tui/screens/settings/ports.py +55 -0
  298. chrys/app/tui/screens/settings/provenance.py +102 -0
  299. chrys/app/tui/screens/settings/rows.py +546 -0
  300. chrys/app/tui/screens/settings/settings.tcss +406 -0
  301. chrys/app/tui/screens/themes/__init__.py +8 -0
  302. chrys/app/tui/screens/themes/dialogs.py +330 -0
  303. chrys/app/tui/screens/themes/editor.py +632 -0
  304. chrys/app/tui/screens/themes/editor.tcss +268 -0
  305. chrys/app/tui/screens/themes/messages.py +95 -0
  306. chrys/app/tui/screens/themes/palette.py +694 -0
  307. chrys/app/tui/screens/themes/panel.py +113 -0
  308. chrys/app/tui/screens/themes/picker.py +203 -0
  309. chrys/app/tui/screens/themes/save.py +191 -0
  310. chrys/app/tui/support/__init__.py +3 -0
  311. chrys/app/tui/support/file_manager.py +64 -0
  312. chrys/app/tui/support/gc_freeze.py +1114 -0
  313. chrys/app/tui/support/path_shortcuts.py +50 -0
  314. chrys/app/tui/support/prompt_history.py +298 -0
  315. chrys/app/tui/support/workspace_mru.py +476 -0
  316. chrys/app/tui/terminal/__init__.py +6 -0
  317. chrys/app/tui/terminal/_pty_backend.py +114 -0
  318. chrys/app/tui/terminal/emulator/__init__.py +24 -0
  319. chrys/app/tui/terminal/emulator/buffer.py +456 -0
  320. chrys/app/tui/terminal/emulator/charsets.py +113 -0
  321. chrys/app/tui/terminal/emulator/core.py +963 -0
  322. chrys/app/tui/terminal/emulator/input.py +342 -0
  323. chrys/app/tui/terminal/emulator/parser.py +227 -0
  324. chrys/app/tui/terminal/emulator/pen.py +158 -0
  325. chrys/app/tui/terminal/launcher.py +455 -0
  326. chrys/app/tui/terminal/leaked_reports.py +44 -0
  327. chrys/app/tui/terminal/panel.py +323 -0
  328. chrys/app/tui/terminal/pty_process.py +405 -0
  329. chrys/app/tui/terminal/rendering.py +151 -0
  330. chrys/app/tui/terminal/shell.py +273 -0
  331. chrys/app/tui/terminal/shell_integration.py +199 -0
  332. chrys/app/tui/terminal/title.py +224 -0
  333. chrys/app/tui/terminal/widget.py +654 -0
  334. chrys/app/tui/theme.py +422 -0
  335. chrys/app/tui/theme_loader.py +201 -0
  336. chrys/app/tui/theme_stylesheet.py +49 -0
  337. chrys/app/tui/themes/__init__.py +3 -0
  338. chrys/app/tui/themes/document.py +120 -0
  339. chrys/app/tui/themes/preview.py +170 -0
  340. chrys/app/tui/themes/store.py +176 -0
  341. chrys/app/tui/toasts.py +69 -0
  342. chrys/app/tui/util/__init__.py +3 -0
  343. chrys/app/tui/util/context_pressure.py +146 -0
  344. chrys/app/tui/util/debug_log.py +292 -0
  345. chrys/app/tui/util/diff_entries.py +64 -0
  346. chrys/app/tui/util/formatting.py +53 -0
  347. chrys/app/tui/util/git_branch.py +326 -0
  348. chrys/app/tui/util/invocation_progress.py +57 -0
  349. chrys/app/tui/util/logo.py +32 -0
  350. chrys/app/tui/util/message_gate.py +35 -0
  351. chrys/app/tui/util/mutation_sources.py +14 -0
  352. chrys/app/tui/util/picker_text.py +27 -0
  353. chrys/app/tui/util/removal.py +47 -0
  354. chrys/app/tui/util/rich_style.py +36 -0
  355. chrys/app/tui/util/source_text.py +12 -0
  356. chrys/app/tui/util/static_update.py +88 -0
  357. chrys/app/tui/util/todo_format.py +51 -0
  358. chrys/app/tui/util/visibility.py +214 -0
  359. chrys/app/tui/widgets/__init__.py +60 -0
  360. chrys/app/tui/widgets/ask_user_controls.py +652 -0
  361. chrys/app/tui/widgets/ask_user_markdown.py +17 -0
  362. chrys/app/tui/widgets/ask_user_prompt.py +606 -0
  363. chrys/app/tui/widgets/buttons.py +52 -0
  364. chrys/app/tui/widgets/chat/__init__.py +3 -0
  365. chrys/app/tui/widgets/chat/agent_transcript_surface.py +818 -0
  366. chrys/app/tui/widgets/chat/chrome.py +296 -0
  367. chrys/app/tui/widgets/chat/compaction_card.py +353 -0
  368. chrys/app/tui/widgets/chat/context_fold.py +77 -0
  369. chrys/app/tui/widgets/chat/file_snapshot.py +91 -0
  370. chrys/app/tui/widgets/chat/image_preview.py +214 -0
  371. chrys/app/tui/widgets/chat/live_renderer.py +383 -0
  372. chrys/app/tui/widgets/chat/messages.py +1039 -0
  373. chrys/app/tui/widgets/chat/panel.py +1769 -0
  374. chrys/app/tui/widgets/chat/ports.py +245 -0
  375. chrys/app/tui/widgets/chat/renderers/__init__.py +7 -0
  376. chrys/app/tui/widgets/chat/renderers/ask_user.py +747 -0
  377. chrys/app/tui/widgets/chat/renderers/execute.py +431 -0
  378. chrys/app/tui/widgets/chat/renderers/file_edit.py +925 -0
  379. chrys/app/tui/widgets/chat/renderers/hosted_code.py +83 -0
  380. chrys/app/tui/widgets/chat/renderers/hosted_generic.py +330 -0
  381. chrys/app/tui/widgets/chat/renderers/hosted_image.py +107 -0
  382. chrys/app/tui/widgets/chat/renderers/hosted_mcp.py +43 -0
  383. chrys/app/tui/widgets/chat/renderers/hosted_search.py +167 -0
  384. chrys/app/tui/widgets/chat/renderers/hosted_shell.py +132 -0
  385. chrys/app/tui/widgets/chat/renderers/read_file.py +399 -0
  386. chrys/app/tui/widgets/chat/renderers/search.py +348 -0
  387. chrys/app/tui/widgets/chat/renderers/skill.py +564 -0
  388. chrys/app/tui/widgets/chat/renderers/sleep.py +287 -0
  389. chrys/app/tui/widgets/chat/renderers/sub_agent.py +1385 -0
  390. chrys/app/tui/widgets/chat/renderers/todo.py +114 -0
  391. chrys/app/tui/widgets/chat/renderers/web.py +69 -0
  392. chrys/app/tui/widgets/chat/replay.py +1605 -0
  393. chrys/app/tui/widgets/chat/replay_mount.py +322 -0
  394. chrys/app/tui/widgets/chat/scroll_controller.py +579 -0
  395. chrys/app/tui/widgets/chat/selection_controller.py +435 -0
  396. chrys/app/tui/widgets/chat/session_json.py +508 -0
  397. chrys/app/tui/widgets/chat/toc_model.py +156 -0
  398. chrys/app/tui/widgets/chat/tool_call.py +2478 -0
  399. chrys/app/tui/widgets/chat/tool_registry.py +753 -0
  400. chrys/app/tui/widgets/chat/tool_renderers.py +247 -0
  401. chrys/app/tui/widgets/chat/tool_view_builders.py +260 -0
  402. chrys/app/tui/widgets/chat/transcript_reader.py +57 -0
  403. chrys/app/tui/widgets/checkbox.py +24 -0
  404. chrys/app/tui/widgets/chrome/__init__.py +3 -0
  405. chrys/app/tui/widgets/chrome/app_header.py +283 -0
  406. chrys/app/tui/widgets/chrome/commands.py +95 -0
  407. chrys/app/tui/widgets/chrome/file_index.py +68 -0
  408. chrys/app/tui/widgets/chrome/file_scanner.py +670 -0
  409. chrys/app/tui/widgets/chrome/footer.py +284 -0
  410. chrys/app/tui/widgets/chrome/image_paste.py +351 -0
  411. chrys/app/tui/widgets/chrome/input_bar.py +1299 -0
  412. chrys/app/tui/widgets/chrome/status_bar.py +911 -0
  413. chrys/app/tui/widgets/chrome/suggestion_list.py +652 -0
  414. chrys/app/tui/widgets/click_affordance.py +24 -0
  415. chrys/app/tui/widgets/color_picker/__init__.py +254 -0
  416. chrys/app/tui/widgets/color_picker/controls.py +171 -0
  417. chrys/app/tui/widgets/color_picker/model.py +89 -0
  418. chrys/app/tui/widgets/dialog_buttons.py +58 -0
  419. chrys/app/tui/widgets/dialog_scroll.py +24 -0
  420. chrys/app/tui/widgets/diff_view/__init__.py +20 -0
  421. chrys/app/tui/widgets/diff_view/cells.py +59 -0
  422. chrys/app/tui/widgets/diff_view/code.py +280 -0
  423. chrys/app/tui/widgets/diff_view/compute.py +286 -0
  424. chrys/app/tui/widgets/diff_view/gutter.py +161 -0
  425. chrys/app/tui/widgets/diff_view/inline.py +77 -0
  426. chrys/app/tui/widgets/diff_view/palette.py +87 -0
  427. chrys/app/tui/widgets/diff_view/protocols.py +24 -0
  428. chrys/app/tui/widgets/diff_view/rows.py +138 -0
  429. chrys/app/tui/widgets/diff_view/unified.py +267 -0
  430. chrys/app/tui/widgets/diff_view/widget.py +209 -0
  431. chrys/app/tui/widgets/editor/__init__.py +79 -0
  432. chrys/app/tui/widgets/editor/coordinates.py +30 -0
  433. chrys/app/tui/widgets/editor/highlighter.py +139 -0
  434. chrys/app/tui/widgets/editor/keymaps.py +357 -0
  435. chrys/app/tui/widgets/editor/types.py +216 -0
  436. chrys/app/tui/widgets/editor/vim.py +1195 -0
  437. chrys/app/tui/widgets/editor/widget.py +401 -0
  438. chrys/app/tui/widgets/file_preview.py +58 -0
  439. chrys/app/tui/widgets/hatch.py +138 -0
  440. chrys/app/tui/widgets/input.py +66 -0
  441. chrys/app/tui/widgets/loading.py +125 -0
  442. chrys/app/tui/widgets/markdown/__init__.py +25 -0
  443. chrys/app/tui/widgets/markdown/_utils.py +21 -0
  444. chrys/app/tui/widgets/markdown/anchors.py +71 -0
  445. chrys/app/tui/widgets/markdown/blocks.py +115 -0
  446. chrys/app/tui/widgets/markdown/copyable.py +163 -0
  447. chrys/app/tui/widgets/markdown/diagram/__init__.py +35 -0
  448. chrys/app/tui/widgets/markdown/diagram/canvas.py +409 -0
  449. chrys/app/tui/widgets/markdown/diagram/charts.py +52 -0
  450. chrys/app/tui/widgets/markdown/diagram/diagnostics.py +101 -0
  451. chrys/app/tui/widgets/markdown/diagram/geometry.py +46 -0
  452. chrys/app/tui/widgets/markdown/diagram/layout.py +494 -0
  453. chrys/app/tui/widgets/markdown/diagram/messages.py +18 -0
  454. chrys/app/tui/widgets/markdown/diagram/model.py +275 -0
  455. chrys/app/tui/widgets/markdown/diagram/parser.py +173 -0
  456. chrys/app/tui/widgets/markdown/diagram/parsers/__init__.py +3 -0
  457. chrys/app/tui/widgets/markdown/diagram/parsers/charts.py +349 -0
  458. chrys/app/tui/widgets/markdown/diagram/parsers/common.py +403 -0
  459. chrys/app/tui/widgets/markdown/diagram/parsers/graphs.py +1072 -0
  460. chrys/app/tui/widgets/markdown/diagram/parsers/planning.py +317 -0
  461. chrys/app/tui/widgets/markdown/diagram/parsers/schedule.py +298 -0
  462. chrys/app/tui/widgets/markdown/diagram/parsers/schemas.py +241 -0
  463. chrys/app/tui/widgets/markdown/diagram/parsers/structure.py +221 -0
  464. chrys/app/tui/widgets/markdown/diagram/presentation.py +32 -0
  465. chrys/app/tui/widgets/markdown/diagram/renderers/__init__.py +3 -0
  466. chrys/app/tui/widgets/markdown/diagram/renderers/charts.py +275 -0
  467. chrys/app/tui/widgets/markdown/diagram/renderers/common.py +73 -0
  468. chrys/app/tui/widgets/markdown/diagram/renderers/planning.py +157 -0
  469. chrys/app/tui/widgets/markdown/diagram/renderers/schedule.py +202 -0
  470. chrys/app/tui/widgets/markdown/diagram/renderers/structure.py +77 -0
  471. chrys/app/tui/widgets/markdown/diagram/renderers/xy.py +385 -0
  472. chrys/app/tui/widgets/markdown/diagram/router.py +651 -0
  473. chrys/app/tui/widgets/markdown/diagram/specs/__init__.py +3 -0
  474. chrys/app/tui/widgets/markdown/diagram/specs/charts.py +94 -0
  475. chrys/app/tui/widgets/markdown/diagram/specs/planning.py +68 -0
  476. chrys/app/tui/widgets/markdown/diagram/specs/schedule.py +65 -0
  477. chrys/app/tui/widgets/markdown/diagram/specs/structure.py +23 -0
  478. chrys/app/tui/widgets/markdown/diagram/viewer.py +92 -0
  479. chrys/app/tui/widgets/markdown/links.py +47 -0
  480. chrys/app/tui/widgets/markdown/math/__init__.py +36 -0
  481. chrys/app/tui/widgets/markdown/math/layout.py +739 -0
  482. chrys/app/tui/widgets/markdown/math/markdown.py +291 -0
  483. chrys/app/tui/widgets/markdown/math/parser.py +325 -0
  484. chrys/app/tui/widgets/markdown/math/symbols.py +325 -0
  485. chrys/app/tui/widgets/markdown/navigator.py +80 -0
  486. chrys/app/tui/widgets/markdown/parser.py +1057 -0
  487. chrys/app/tui/widgets/markdown/stream.py +73 -0
  488. chrys/app/tui/widgets/markdown/toc.py +98 -0
  489. chrys/app/tui/widgets/markdown/viewer.py +146 -0
  490. chrys/app/tui/widgets/markdown/widget.py +2046 -0
  491. chrys/app/tui/widgets/marquee.py +101 -0
  492. chrys/app/tui/widgets/option_menu.py +82 -0
  493. chrys/app/tui/widgets/page_navigator.py +118 -0
  494. chrys/app/tui/widgets/select.py +196 -0
  495. chrys/app/tui/widgets/selection.py +59 -0
  496. chrys/app/tui/widgets/sidebar/__init__.py +3 -0
  497. chrys/app/tui/widgets/sidebar/buddy.py +367 -0
  498. chrys/app/tui/widgets/sidebar/context.py +482 -0
  499. chrys/app/tui/widgets/sidebar/debug.py +195 -0
  500. chrys/app/tui/widgets/sidebar/empty_state.py +11 -0
  501. chrys/app/tui/widgets/sidebar/panel.py +198 -0
  502. chrys/app/tui/widgets/sidebar/tasks.py +198 -0
  503. chrys/app/tui/widgets/sidebar/toc.py +166 -0
  504. chrys/app/tui/widgets/sidebar/toc_types.py +30 -0
  505. chrys/app/tui/widgets/syntax_theme.py +85 -0
  506. chrys/app/tui/widgets/text_area.py +258 -0
  507. chrys/app/tui/widgets/trajectory/__init__.py +8 -0
  508. chrys/app/tui/widgets/trajectory/chartkit.py +264 -0
  509. chrys/app/tui/widgets/trajectory/insights.py +1266 -0
  510. chrys/app/tui/widgets/trajectory/overview.py +1101 -0
  511. chrys/app/tui/widgets/trajectory/panel.py +983 -0
  512. chrys/app/tui/widgets/trajectory/presentation.py +311 -0
  513. chrys/app/tui/widgets/trajectory/session_info.py +124 -0
  514. chrys/app/tui/widgets/trajectory/text_view.py +124 -0
  515. chrys/app/tui/widgets/trajectory/timeline.py +380 -0
  516. chrys/app/tui/widgets/welcome.py +126 -0
  517. chrys/app/tui/widgets/workflow/__init__.py +5 -0
  518. chrys/app/tui/widgets/workflow/edges.py +89 -0
  519. chrys/app/tui/widgets/workflow/graph.py +869 -0
  520. chrys/app/tui/widgets/workflow/info.py +310 -0
  521. chrys/app/tui/widgets/workflow/node_view.py +27 -0
  522. chrys/app/tui/widgets/workflow/output.py +225 -0
  523. chrys/app/tui/widgets/workflow/panel.py +658 -0
  524. chrys/app/tui/widgets/workflow/projector.py +324 -0
  525. chrys/app/tui/widgets/workflow/records.py +69 -0
  526. chrys/app/tui/widgets/workflow/scrollbar.py +82 -0
  527. chrys/app/tui/widgets/workflow/selection.py +151 -0
  528. chrys/app/tui/widgets/workflow/source.py +65 -0
  529. chrys/app/tui/widgets/workflow/text.py +257 -0
  530. chrys/app/tui/widgets/workflow/values.py +317 -0
  531. chrys/foundation/__init__.py +0 -0
  532. chrys/foundation/branding.py +15 -0
  533. chrys/foundation/config/__init__.py +7 -0
  534. chrys/foundation/config/coercion.py +374 -0
  535. chrys/foundation/config/context.py +34 -0
  536. chrys/foundation/config/env_file.py +141 -0
  537. chrys/foundation/config/env_layers.py +370 -0
  538. chrys/foundation/config/migrations.py +521 -0
  539. chrys/foundation/config/notification_events.py +22 -0
  540. chrys/foundation/config/process_settings.py +332 -0
  541. chrys/foundation/config/runtime_pointer.py +133 -0
  542. chrys/foundation/config/settings.py +1952 -0
  543. chrys/foundation/config/settings_store.py +996 -0
  544. chrys/foundation/config/spec.py +396 -0
  545. chrys/foundation/config/user_settings.py +140 -0
  546. chrys/foundation/config/warnings.py +262 -0
  547. chrys/foundation/config/web_values.py +135 -0
  548. chrys/foundation/config/yaml_store.py +487 -0
  549. chrys/foundation/errors/__init__.py +68 -0
  550. chrys/foundation/errors/_legacy.py +117 -0
  551. chrys/foundation/errors/_text.py +13 -0
  552. chrys/foundation/errors/_walk.py +85 -0
  553. chrys/foundation/errors/classify.py +278 -0
  554. chrys/foundation/errors/display.py +274 -0
  555. chrys/foundation/errors/formatting.py +283 -0
  556. chrys/foundation/errors/kinds.py +67 -0
  557. chrys/foundation/errors/network.py +497 -0
  558. chrys/foundation/errors/provider.py +445 -0
  559. chrys/foundation/errors/route.py +85 -0
  560. chrys/foundation/events/__init__.py +8 -0
  561. chrys/foundation/events/bus.py +143 -0
  562. chrys/foundation/events/types.py +1629 -0
  563. chrys/foundation/events/workflow.py +38 -0
  564. chrys/foundation/hosted_tools.py +142 -0
  565. chrys/foundation/i18n/__init__.py +32 -0
  566. chrys/foundation/i18n/_catalogs/zh-Hans/LC_MESSAGES/chrys.mo +0 -0
  567. chrys/foundation/i18n/catalogs.py +42 -0
  568. chrys/foundation/i18n/formatting.py +202 -0
  569. chrys/foundation/i18n/locale.py +92 -0
  570. chrys/foundation/i18n/localizer.py +187 -0
  571. chrys/foundation/i18n/messages.py +268 -0
  572. chrys/foundation/io/__init__.py +3 -0
  573. chrys/foundation/io/result_content.py +237 -0
  574. chrys/foundation/models/__init__.py +3 -0
  575. chrys/foundation/models/approval_reuse.py +23 -0
  576. chrys/foundation/models/ask_user.py +468 -0
  577. chrys/foundation/models/execution.py +18 -0
  578. chrys/foundation/models/history_markers.py +115 -0
  579. chrys/foundation/models/invocations.py +63 -0
  580. chrys/foundation/models/mutation_scope.py +28 -0
  581. chrys/foundation/models/session_env.py +87 -0
  582. chrys/foundation/models/session_surface.py +29 -0
  583. chrys/foundation/models/todos.py +74 -0
  584. chrys/foundation/models/turns.py +125 -0
  585. chrys/foundation/models/workflow_session.py +89 -0
  586. chrys/foundation/models/workspace.py +59 -0
  587. chrys/foundation/net/__init__.py +3 -0
  588. chrys/foundation/net/address_class.py +57 -0
  589. chrys/foundation/net/route_probe.py +94 -0
  590. chrys/foundation/net/url.py +107 -0
  591. chrys/foundation/observability/__init__.py +3 -0
  592. chrys/foundation/observability/exporters.py +174 -0
  593. chrys/foundation/observability/gate.py +31 -0
  594. chrys/foundation/observability/setup.py +497 -0
  595. chrys/foundation/observability/sink.py +228 -0
  596. chrys/foundation/patches/__init__.py +19 -0
  597. chrys/foundation/patches/mdurl_cache.py +59 -0
  598. chrys/foundation/patches/patcher.py +287 -0
  599. chrys/foundation/patches/staged_members.py +205 -0
  600. chrys/foundation/patches/textual_block_border.py +105 -0
  601. chrys/foundation/patches/textual_button_ansi.py +65 -0
  602. chrys/foundation/patches/textual_button_ansi_old.txt +68 -0
  603. chrys/foundation/patches/textual_callback_cache.py +248 -0
  604. chrys/foundation/patches/textual_callback_dispatch.py +109 -0
  605. chrys/foundation/patches/textual_compositor_cjk.py +566 -0
  606. chrys/foundation/patches/textual_dispatch_cache.py +150 -0
  607. chrys/foundation/patches/textual_ime_cursor_anchor.py +92 -0
  608. chrys/foundation/patches/textual_kitty_keyboard.py +268 -0
  609. chrys/foundation/patches/textual_lru_acyclic.py +241 -0
  610. chrys/foundation/patches/textual_message_pump.py +136 -0
  611. chrys/foundation/patches/textual_node_diet.py +875 -0
  612. chrys/foundation/patches/textual_one_shot_timer.py +48 -0
  613. chrys/foundation/patches/textual_option_list.py +90 -0
  614. chrys/foundation/patches/textual_precompose.py +89 -0
  615. chrys/foundation/patches/textual_pruned_tabs.py +69 -0
  616. chrys/foundation/patches/textual_reflow_reuse.py +1753 -0
  617. chrys/foundation/patches/textual_removed_node_caches.py +86 -0
  618. chrys/foundation/patches/textual_removed_screen_callbacks.py +55 -0
  619. chrys/foundation/patches/textual_selection_extract.py +48 -0
  620. chrys/foundation/patches/textual_strip_cycles.py +119 -0
  621. chrys/foundation/patches/textual_tab_selection.py +1611 -0
  622. chrys/foundation/patches/textual_timer_skip.py +70 -0
  623. chrys/foundation/patches/textual_utf8_decoder.py +106 -0
  624. chrys/foundation/patches/textual_win_sleep.py +167 -0
  625. chrys/foundation/patches/watchdog_fsevents.py +70 -0
  626. chrys/foundation/patches/watchdog_windows.py +52 -0
  627. chrys/foundation/platform/__init__.py +556 -0
  628. chrys/foundation/platform/c_api.py +32 -0
  629. chrys/foundation/platform/child_reap.py +107 -0
  630. chrys/foundation/platform/command_line.py +95 -0
  631. chrys/foundation/platform/files.py +1470 -0
  632. chrys/foundation/platform/output_capture.py +113 -0
  633. chrys/foundation/platform/paths.py +193 -0
  634. chrys/foundation/platform/process.py +1468 -0
  635. chrys/foundation/platform/pty_output.py +19 -0
  636. chrys/foundation/platform/runtime_paths.py +281 -0
  637. chrys/foundation/platform/win_console.py +129 -0
  638. chrys/foundation/reasoning_origin.py +67 -0
  639. chrys/foundation/recovery.py +16 -0
  640. chrys/foundation/retry.py +278 -0
  641. chrys/foundation/text/__init__.py +3 -0
  642. chrys/foundation/text/encoding.py +603 -0
  643. chrys/foundation/text/images.py +304 -0
  644. chrys/foundation/text/lines.py +24 -0
  645. chrys/foundation/text/mentions.py +90 -0
  646. chrys/foundation/text/model_json.py +25 -0
  647. chrys/foundation/text/reading_order.py +20 -0
  648. chrys/foundation/text/tokenizer.py +25 -0
  649. chrys/foundation/text/tool_output.py +287 -0
  650. chrys/foundation/text/yaml_io.py +62 -0
  651. chrys/foundation/tool_call_context.py +202 -0
  652. chrys/foundation/tool_execution_stamp.py +184 -0
  653. chrys/foundation/tool_invocation_order.py +48 -0
  654. chrys/foundation/tool_kinds.py +102 -0
  655. chrys/foundation/tool_result_metadata.py +287 -0
  656. chrys/foundation/trajectory/__init__.py +10 -0
  657. chrys/foundation/trajectory/context.py +481 -0
  658. chrys/foundation/trajectory/envelope.py +571 -0
  659. chrys/foundation/trajectory/event_types.py +294 -0
  660. chrys/foundation/trajectory/finalizers.py +46 -0
  661. chrys/foundation/trajectory/fingerprint.py +62 -0
  662. chrys/foundation/trajectory/ids.py +155 -0
  663. chrys/foundation/trajectory/keys.py +99 -0
  664. chrys/foundation/trajectory/lease.py +173 -0
  665. chrys/foundation/trajectory/metadata.py +72 -0
  666. chrys/foundation/trajectory/reader.py +271 -0
  667. chrys/foundation/trajectory/recovery.py +225 -0
  668. chrys/foundation/trajectory/revisions.py +152 -0
  669. chrys/foundation/trajectory/segments.py +225 -0
  670. chrys/foundation/trajectory/tools.py +117 -0
  671. chrys/foundation/trajectory/usage.py +151 -0
  672. chrys/foundation/trajectory/writer.py +972 -0
  673. chrys/foundation/trajectory_timing.py +97 -0
  674. chrys/foundation/util/__init__.py +3 -0
  675. chrys/foundation/util/async_tasks.py +29 -0
  676. chrys/foundation/util/chrys_headers.py +23 -0
  677. chrys/foundation/util/env_templates.py +104 -0
  678. chrys/foundation/util/filenames.py +96 -0
  679. chrys/foundation/util/header_charset.py +138 -0
  680. chrys/foundation/util/httpx_helpers.py +12 -0
  681. chrys/foundation/util/lock.py +236 -0
  682. chrys/foundation/util/once_close.py +46 -0
  683. chrys/foundation/util/session_ids.py +29 -0
  684. chrys/foundation/util/shell_tokens.py +88 -0
  685. chrys/foundation/util/sub_agent_context.py +38 -0
  686. chrys/foundation/util/time.py +35 -0
  687. chrys/foundation/util/unicode_scalars.py +36 -0
  688. chrys/foundation/vendor/__init__.py +43 -0
  689. chrys/foundation/vendor/ripgrep/rg-aarch64-apple-darwin +0 -0
  690. chrys/foundation/vendor/ripgrep/rg-aarch64-pc-windows-msvc.exe +0 -0
  691. chrys/foundation/vendor/ripgrep/rg-aarch64-unknown-linux-gnu +0 -0
  692. chrys/foundation/vendor/ripgrep/rg-x86_64-apple-darwin +0 -0
  693. chrys/foundation/vendor/ripgrep/rg-x86_64-pc-windows-msvc.exe +0 -0
  694. chrys/foundation/vendor/ripgrep/rg-x86_64-unknown-linux-musl +0 -0
  695. chrys/kernel/__init__.py +256 -0
  696. chrys/kernel/_content.py +1866 -0
  697. chrys/kernel/_loop_recorder.py +631 -0
  698. chrys/kernel/_null_overlay.py +1026 -0
  699. chrys/kernel/_result_ceiling.py +216 -0
  700. chrys/kernel/_serialization.py +431 -0
  701. chrys/kernel/_tool_arg_errors.py +1629 -0
  702. chrys/kernel/_tool_execution.py +1172 -0
  703. chrys/kernel/_tool_expansion.py +26 -0
  704. chrys/kernel/_types.py +2598 -0
  705. chrys/kernel/agent.py +994 -0
  706. chrys/kernel/client.py +1084 -0
  707. chrys/kernel/compaction.py +1315 -0
  708. chrys/kernel/exceptions.py +211 -0
  709. chrys/kernel/exchanges.py +683 -0
  710. chrys/kernel/identity.py +95 -0
  711. chrys/kernel/images.py +36 -0
  712. chrys/kernel/instrumentation.py +1618 -0
  713. chrys/kernel/loop.py +2308 -0
  714. chrys/kernel/middleware.py +616 -0
  715. chrys/kernel/sessions.py +604 -0
  716. chrys/kernel/tools.py +1061 -0
  717. chrys/kernel/types.py +126 -0
  718. chrys/orchestration/__init__.py +3 -0
  719. chrys/orchestration/engine/__init__.py +3 -0
  720. chrys/orchestration/engine/assembly.py +236 -0
  721. chrys/orchestration/engine/build/__init__.py +3 -0
  722. chrys/orchestration/engine/build/builder.py +1061 -0
  723. chrys/orchestration/engine/build/construction.py +408 -0
  724. chrys/orchestration/engine/build/loaded.py +139 -0
  725. chrys/orchestration/engine/engine.py +789 -0
  726. chrys/orchestration/engine/execution.py +771 -0
  727. chrys/orchestration/engine/loader.py +865 -0
  728. chrys/orchestration/engine/rollback.py +918 -0
  729. chrys/orchestration/engine/run/__init__.py +3 -0
  730. chrys/orchestration/engine/run/active_injection.py +419 -0
  731. chrys/orchestration/engine/run/attachments.py +519 -0
  732. chrys/orchestration/engine/run/bindings.py +1095 -0
  733. chrys/orchestration/engine/run/coordinator.py +1062 -0
  734. chrys/orchestration/engine/run/finalizer.py +417 -0
  735. chrys/orchestration/engine/run/input_refs.py +60 -0
  736. chrys/orchestration/engine/run/prompt_content.py +457 -0
  737. chrys/orchestration/engine/run/resume.py +299 -0
  738. chrys/orchestration/engine/run/retry.py +948 -0
  739. chrys/orchestration/engine/run/runner.py +625 -0
  740. chrys/orchestration/engine/run/runtime_skills.py +146 -0
  741. chrys/orchestration/engine/run/sub_agent_coordination.py +126 -0
  742. chrys/orchestration/engine/run/turn_hooks.py +258 -0
  743. chrys/orchestration/engine/run/turn_state.py +149 -0
  744. chrys/orchestration/engine/run/working_dir.py +50 -0
  745. chrys/orchestration/engine/session_lifecycle.py +2013 -0
  746. chrys/orchestration/engine/state/__init__.py +3 -0
  747. chrys/orchestration/engine/state/active_session.py +183 -0
  748. chrys/orchestration/engine/state/controls.py +639 -0
  749. chrys/orchestration/engine/state/current_agent.py +26 -0
  750. chrys/orchestration/engine/state/lifecycle_permits.py +395 -0
  751. chrys/orchestration/engine/state/machine.py +193 -0
  752. chrys/orchestration/engine/state/session_writer.py +434 -0
  753. chrys/orchestration/engine/trajectory.py +714 -0
  754. chrys/orchestration/engine/usage.py +118 -0
  755. chrys/orchestration/invoker/__init__.py +3 -0
  756. chrys/orchestration/invoker/acp.py +727 -0
  757. chrys/orchestration/invoker/acp_protocol.py +1115 -0
  758. chrys/orchestration/invoker/acp_spec.py +79 -0
  759. chrys/orchestration/invoker/attempts.py +994 -0
  760. chrys/orchestration/invoker/child_compaction.py +131 -0
  761. chrys/orchestration/invoker/child_history.py +99 -0
  762. chrys/orchestration/invoker/contracts.py +253 -0
  763. chrys/orchestration/invoker/evidence.py +94 -0
  764. chrys/orchestration/invoker/kernel.py +343 -0
  765. chrys/orchestration/invoker/origin.py +79 -0
  766. chrys/orchestration/invoker/resources.py +343 -0
  767. chrys/orchestration/invoker/runtime.py +299 -0
  768. chrys/orchestration/invoker/usage.py +80 -0
  769. chrys/orchestration/session_hooks.py +117 -0
  770. chrys/orchestration/session_host.py +1023 -0
  771. chrys/orchestration/session_resources.py +95 -0
  772. chrys/orchestration/session_usage.py +219 -0
  773. chrys/orchestration/startup.py +255 -0
  774. chrys/orchestration/sub_agents/__init__.py +3 -0
  775. chrys/orchestration/sub_agents/acp_policy.py +269 -0
  776. chrys/orchestration/sub_agents/kernel_policy.py +848 -0
  777. chrys/orchestration/sub_agents/registration.py +44 -0
  778. chrys/orchestration/sub_agents/shell.py +337 -0
  779. chrys/orchestration/sub_agents/tools.py +2228 -0
  780. chrys/orchestration/workflows/__init__.py +3 -0
  781. chrys/orchestration/workflows/agent_archive.py +156 -0
  782. chrys/orchestration/workflows/agent_node.py +894 -0
  783. chrys/orchestration/workflows/agent_node_build.py +687 -0
  784. chrys/orchestration/workflows/catalog.py +332 -0
  785. chrys/orchestration/workflows/coordinator.py +771 -0
  786. chrys/orchestration/workflows/hooks.py +176 -0
  787. chrys/orchestration/workflows/preview.py +322 -0
  788. chrys/orchestration/workflows/rollback.py +151 -0
  789. chrys/orchestration/workflows/runner.py +986 -0
  790. chrys/orchestration/workflows/session.py +390 -0
  791. chrys/orchestration/workflows/settings.py +97 -0
  792. chrys/orchestration/workflows/validation.py +674 -0
  793. chrys/orchestration/workflows/worker_client.py +1002 -0
  794. chrys/service/__init__.py +3 -0
  795. chrys/service/acp_client/__init__.py +65 -0
  796. chrys/service/acp_client/_transport.py +922 -0
  797. chrys/service/acp_client/client.py +1311 -0
  798. chrys/service/acp_client/errors.py +224 -0
  799. chrys/service/acp_client/protocol.py +220 -0
  800. chrys/service/acp_client/spawn.py +239 -0
  801. chrys/service/acp_client/spec.py +100 -0
  802. chrys/service/agent_middleware/__init__.py +60 -0
  803. chrys/service/agent_middleware/_metadata_keys.py +52 -0
  804. chrys/service/agent_middleware/control/__init__.py +3 -0
  805. chrys/service/agent_middleware/control/approval.py +769 -0
  806. chrys/service/agent_middleware/control/approval_hooks.py +62 -0
  807. chrys/service/agent_middleware/control/ask_user.py +207 -0
  808. chrys/service/agent_middleware/control/interrupt.py +50 -0
  809. chrys/service/agent_middleware/control/sleep.py +118 -0
  810. chrys/service/agent_middleware/control/todo.py +117 -0
  811. chrys/service/agent_middleware/events/__init__.py +3 -0
  812. chrys/service/agent_middleware/events/hook_dispatch.py +250 -0
  813. chrys/service/agent_middleware/events/hosted_tools.py +1762 -0
  814. chrys/service/agent_middleware/events/intermediate_text.py +128 -0
  815. chrys/service/agent_middleware/events/rejection_metadata.py +50 -0
  816. chrys/service/agent_middleware/events/result_persistence.py +98 -0
  817. chrys/service/agent_middleware/events/sub_agent_events.py +951 -0
  818. chrys/service/agent_middleware/events/tool_error_text.py +22 -0
  819. chrys/service/agent_middleware/events/tool_events.py +779 -0
  820. chrys/service/agent_middleware/injection.py +510 -0
  821. chrys/service/agent_middleware/reminders/__init__.py +91 -0
  822. chrys/service/agent_middleware/reminders/archive_pointer.py +154 -0
  823. chrys/service/agent_middleware/reminders/base.py +25 -0
  824. chrys/service/agent_middleware/reminders/context_usage.py +74 -0
  825. chrys/service/agent_middleware/reminders/file_change.py +63 -0
  826. chrys/service/agent_middleware/reminders/mcp.py +39 -0
  827. chrys/service/agent_middleware/reminders/profile_switch.py +106 -0
  828. chrys/service/agent_middleware/reminders/runtime_env.py +190 -0
  829. chrys/service/agent_middleware/reminders/skills.py +44 -0
  830. chrys/service/agent_middleware/reminders/sub_agents.py +35 -0
  831. chrys/service/agent_middleware/reminders/todo.py +35 -0
  832. chrys/service/agent_middleware/reminders/turn_line.py +48 -0
  833. chrys/service/agent_middleware/response_validation.py +1380 -0
  834. chrys/service/agent_middleware/system_reminder.py +1107 -0
  835. chrys/service/agent_middleware/validators.py +396 -0
  836. chrys/service/analytics/__init__.py +124 -0
  837. chrys/service/analytics/_actions.py +896 -0
  838. chrys/service/analytics/_context_evidence.py +357 -0
  839. chrys/service/analytics/_critical_path.py +179 -0
  840. chrys/service/analytics/_facts.py +919 -0
  841. chrys/service/analytics/_insights.py +769 -0
  842. chrys/service/analytics/_metric_ops.py +83 -0
  843. chrys/service/analytics/_session_projection.py +460 -0
  844. chrys/service/analytics/_timeline.py +434 -0
  845. chrys/service/analytics/_turn_graph.py +1237 -0
  846. chrys/service/analytics/_turns.py +1377 -0
  847. chrys/service/analytics/_workflows.py +171 -0
  848. chrys/service/analytics/aggregation.py +1474 -0
  849. chrys/service/analytics/classification.py +128 -0
  850. chrys/service/analytics/export.py +803 -0
  851. chrys/service/analytics/findings.py +282 -0
  852. chrys/service/analytics/math.py +79 -0
  853. chrys/service/analytics/model.py +886 -0
  854. chrys/service/analytics/reader.py +321 -0
  855. chrys/service/approval/__init__.py +3 -0
  856. chrys/service/approval/arbitration.py +102 -0
  857. chrys/service/approval/command_identity.py +109 -0
  858. chrys/service/approval/correlation.py +57 -0
  859. chrys/service/approval/grant_store.py +108 -0
  860. chrys/service/approval/judge.py +589 -0
  861. chrys/service/approval/level.py +15 -0
  862. chrys/service/approval/policy.py +209 -0
  863. chrys/service/approval/reuse.py +223 -0
  864. chrys/service/approval/reuse_binding.py +133 -0
  865. chrys/service/approval/safety_classifier.py +536 -0
  866. chrys/service/approval/turn_context.py +49 -0
  867. chrys/service/context/__init__.py +3 -0
  868. chrys/service/context/compaction/__init__.py +38 -0
  869. chrys/service/context/compaction/breaker.py +156 -0
  870. chrys/service/context/compaction/budgets.py +93 -0
  871. chrys/service/context/compaction/calibration.py +77 -0
  872. chrys/service/context/compaction/compression.py +690 -0
  873. chrys/service/context/compaction/current_turn_drop.py +458 -0
  874. chrys/service/context/compaction/events.py +201 -0
  875. chrys/service/context/compaction/exclusions.py +261 -0
  876. chrys/service/context/compaction/groups.py +361 -0
  877. chrys/service/context/compaction/last_words.py +1996 -0
  878. chrys/service/context/compaction/last_words_state.py +752 -0
  879. chrys/service/context/compaction/scoped.py +472 -0
  880. chrys/service/context/compaction/spill.py +1947 -0
  881. chrys/service/context/compaction/strategy.py +1116 -0
  882. chrys/service/context/compaction/summaries.py +319 -0
  883. chrys/service/context/compaction/turns.py +375 -0
  884. chrys/service/context/manager.py +174 -0
  885. chrys/service/context/memory_loader.py +792 -0
  886. chrys/service/context/middleware/__init__.py +3 -0
  887. chrys/service/context/middleware/usage.py +332 -0
  888. chrys/service/context/providers/__init__.py +3 -0
  889. chrys/service/context/providers/context_management.py +432 -0
  890. chrys/service/context/providers/history.py +647 -0
  891. chrys/service/context/providers/memory.py +50 -0
  892. chrys/service/context/tool_content.py +22 -0
  893. chrys/service/hooks/__init__.py +37 -0
  894. chrys/service/hooks/detached_worker.py +118 -0
  895. chrys/service/hooks/docs/README.md +14 -0
  896. chrys/service/hooks/docs/authoring.md +684 -0
  897. chrys/service/hooks/docs/configuration.md +499 -0
  898. chrys/service/hooks/docs/design.md +359 -0
  899. chrys/service/hooks/docs/project-hooks.md +348 -0
  900. chrys/service/hooks/events.py +157 -0
  901. chrys/service/hooks/loader.py +665 -0
  902. chrys/service/hooks/manager.py +807 -0
  903. chrys/service/hooks/matcher.py +111 -0
  904. chrys/service/hooks/outbox.py +294 -0
  905. chrys/service/hooks/runner.py +572 -0
  906. chrys/service/hooks/schema.py +407 -0
  907. chrys/service/llm/__init__.py +7 -0
  908. chrys/service/llm/_structured_outputs.py +192 -0
  909. chrys/service/llm/anthropic_messages/__init__.py +9 -0
  910. chrys/service/llm/anthropic_messages/client.py +254 -0
  911. chrys/service/llm/anthropic_messages/decode.py +331 -0
  912. chrys/service/llm/anthropic_messages/history.py +279 -0
  913. chrys/service/llm/anthropic_messages/request.py +323 -0
  914. chrys/service/llm/anthropic_messages/server_tools.py +319 -0
  915. chrys/service/llm/anthropic_messages/stream.py +297 -0
  916. chrys/service/llm/anthropic_messages/thinking_binding.py +156 -0
  917. chrys/service/llm/chat_completions/__init__.py +9 -0
  918. chrys/service/llm/chat_completions/client.py +369 -0
  919. chrys/service/llm/chat_completions/decode.py +338 -0
  920. chrys/service/llm/chat_completions/history.py +657 -0
  921. chrys/service/llm/chat_completions/reasoning.py +244 -0
  922. chrys/service/llm/chat_completions/request.py +192 -0
  923. chrys/service/llm/chat_completions/stream.py +546 -0
  924. chrys/service/llm/chat_completions/validation.py +308 -0
  925. chrys/service/llm/clients.py +613 -0
  926. chrys/service/llm/images.py +65 -0
  927. chrys/service/llm/mock.py +413 -0
  928. chrys/service/llm/observer.py +446 -0
  929. chrys/service/llm/one_shot.py +106 -0
  930. chrys/service/llm/openai_exceptions.py +93 -0
  931. chrys/service/llm/openai_responses/__init__.py +10 -0
  932. chrys/service/llm/openai_responses/client.py +323 -0
  933. chrys/service/llm/openai_responses/decode.py +432 -0
  934. chrys/service/llm/openai_responses/history.py +519 -0
  935. chrys/service/llm/openai_responses/hosted.py +625 -0
  936. chrys/service/llm/openai_responses/replay.py +629 -0
  937. chrys/service/llm/openai_responses/request.py +342 -0
  938. chrys/service/llm/openai_responses/stream.py +847 -0
  939. chrys/service/llm/openai_timestamps.py +57 -0
  940. chrys/service/llm/providers.py +107 -0
  941. chrys/service/llm/proxy_route.py +54 -0
  942. chrys/service/llm/raw_http_log.py +309 -0
  943. chrys/service/llm/route_facts.py +63 -0
  944. chrys/service/llm/route_sessions.py +49 -0
  945. chrys/service/llm/sdk_anthropic.py +18 -0
  946. chrys/service/llm/sdk_headers.py +47 -0
  947. chrys/service/llm/sdk_openai.py +18 -0
  948. chrys/service/llm/sdk_retry.py +59 -0
  949. chrys/service/llm/wire_client.py +246 -0
  950. chrys/service/mcp/__init__.py +3 -0
  951. chrys/service/mcp/_connection.py +235 -0
  952. chrys/service/mcp/_http_transport.py +350 -0
  953. chrys/service/mcp/_progressive.py +459 -0
  954. chrys/service/mcp/_stdio_transport.py +614 -0
  955. chrys/service/mcp/_tool_mixins.py +96 -0
  956. chrys/service/mcp/adapter.py +1031 -0
  957. chrys/service/mcp/cache.py +476 -0
  958. chrys/service/mcp/content.py +32 -0
  959. chrys/service/mcp/errors.py +169 -0
  960. chrys/service/mcp/owned.py +1330 -0
  961. chrys/service/mcp/result_limits.py +168 -0
  962. chrys/service/mcp/thinking_warning.py +95 -0
  963. chrys/service/mcp/validation.py +74 -0
  964. chrys/service/mutations/__init__.py +84 -0
  965. chrys/service/mutations/coordination.py +894 -0
  966. chrys/service/mutations/detector.py +458 -0
  967. chrys/service/mutations/git_calibrator.py +397 -0
  968. chrys/service/mutations/git_state.py +647 -0
  969. chrys/service/mutations/pipeline.py +779 -0
  970. chrys/service/mutations/scanner.py +466 -0
  971. chrys/service/mutations/snapshot_files.py +233 -0
  972. chrys/service/mutations/store.py +625 -0
  973. chrys/service/mutations/tool_names.py +15 -0
  974. chrys/service/mutations/trace.py +246 -0
  975. chrys/service/mutations/tracker.py +1289 -0
  976. chrys/service/mutations/types.py +559 -0
  977. chrys/service/mutations/workspace_changes.py +1583 -0
  978. chrys/service/profiles/__init__.py +2 -0
  979. chrys/service/profiles/agents/__init__.py +3 -0
  980. chrys/service/profiles/agents/builtins/Code.yaml +199 -0
  981. chrys/service/profiles/agents/builtins/Explore.yaml +62 -0
  982. chrys/service/profiles/agents/builtins/General.yaml +114 -0
  983. chrys/service/profiles/agents/builtins/QA.yaml +128 -0
  984. chrys/service/profiles/agents/loader.py +808 -0
  985. chrys/service/profiles/agents/registry.py +727 -0
  986. chrys/service/profiles/agents/schema.py +371 -0
  987. chrys/service/profiles/agents/serializer.py +196 -0
  988. chrys/service/profiles/coercion.py +22 -0
  989. chrys/service/profiles/models/__init__.py +3 -0
  990. chrys/service/profiles/models/env_bridge.py +157 -0
  991. chrys/service/profiles/models/loader.py +282 -0
  992. chrys/service/profiles/models/options.py +438 -0
  993. chrys/service/profiles/models/registry.py +104 -0
  994. chrys/service/profiles/models/resolver.py +286 -0
  995. chrys/service/profiles/models/schema.py +91 -0
  996. chrys/service/profiles/models/serializer.py +76 -0
  997. chrys/service/session/__init__.py +3 -0
  998. chrys/service/session/checkpoint.py +156 -0
  999. chrys/service/session/history.py +1616 -0
  1000. chrys/service/session/message_metadata.py +151 -0
  1001. chrys/service/session/persistence.py +435 -0
  1002. chrys/service/session/runtime_metadata.py +210 -0
  1003. chrys/service/session/sub_agent_logs.py +1069 -0
  1004. chrys/service/session/sub_agent_transcript.py +654 -0
  1005. chrys/service/skills/__init__.py +3 -0
  1006. chrys/service/skills/adapter.py +408 -0
  1007. chrys/service/skills/constants.py +8 -0
  1008. chrys/service/skills/loader.py +575 -0
  1009. chrys/service/skills/model.py +130 -0
  1010. chrys/service/skills/provider.py +841 -0
  1011. chrys/service/skills/runner.py +390 -0
  1012. chrys/service/state/__init__.py +3 -0
  1013. chrys/service/state/_fork.py +710 -0
  1014. chrys/service/state/_session_files.py +175 -0
  1015. chrys/service/state/_session_meta.py +552 -0
  1016. chrys/service/state/locks.py +154 -0
  1017. chrys/service/state/serializers.py +156 -0
  1018. chrys/service/state/session_catalog.py +361 -0
  1019. chrys/service/state/session_listing.py +84 -0
  1020. chrys/service/state/session_migration.py +446 -0
  1021. chrys/service/state/session_mru.py +315 -0
  1022. chrys/service/state/store.py +2132 -0
  1023. chrys/service/state/workflow.py +158 -0
  1024. chrys/service/text_blocks.py +47 -0
  1025. chrys/service/todos/__init__.py +3 -0
  1026. chrys/service/todos/reminder.py +31 -0
  1027. chrys/service/todos/tracker.py +58 -0
  1028. chrys/service/tools/__init__.py +3 -0
  1029. chrys/service/tools/approval_targets.py +92 -0
  1030. chrys/service/tools/builtins/__init__.py +3 -0
  1031. chrys/service/tools/builtins/ask_user.py +326 -0
  1032. chrys/service/tools/builtins/doc_converter/__init__.py +494 -0
  1033. chrys/service/tools/builtins/doc_converter/artifacts.py +392 -0
  1034. chrys/service/tools/builtins/doc_converter/parsers/__init__.py +3 -0
  1035. chrys/service/tools/builtins/doc_converter/parsers/_table.py +34 -0
  1036. chrys/service/tools/builtins/doc_converter/parsers/base.py +101 -0
  1037. chrys/service/tools/builtins/doc_converter/parsers/docx.py +88 -0
  1038. chrys/service/tools/builtins/doc_converter/parsers/pdf.py +144 -0
  1039. chrys/service/tools/builtins/doc_converter/parsers/pptx.py +103 -0
  1040. chrys/service/tools/builtins/doc_converter/parsers/xls.py +32 -0
  1041. chrys/service/tools/builtins/doc_converter/parsers/xlsx.py +51 -0
  1042. chrys/service/tools/builtins/doc_converter/registry.py +55 -0
  1043. chrys/service/tools/builtins/filesystem.py +1071 -0
  1044. chrys/service/tools/builtins/search.py +1265 -0
  1045. chrys/service/tools/builtins/shell.py +967 -0
  1046. chrys/service/tools/builtins/shell_command_filtering/__init__.py +5 -0
  1047. chrys/service/tools/builtins/shell_command_filtering/policy.py +60 -0
  1048. chrys/service/tools/builtins/shell_command_filtering/presets.py +152 -0
  1049. chrys/service/tools/builtins/shell_command_filtering/readonly/__init__.py +358 -0
  1050. chrys/service/tools/builtins/shell_command_filtering/readonly/commands.py +416 -0
  1051. chrys/service/tools/builtins/shell_command_filtering/readonly/git.py +408 -0
  1052. chrys/service/tools/builtins/shell_command_filtering/readonly/syntax.py +87 -0
  1053. chrys/service/tools/builtins/shell_command_filtering/tokenizer.py +214 -0
  1054. chrys/service/tools/builtins/shell_filter.py +24 -0
  1055. chrys/service/tools/builtins/sleep.py +91 -0
  1056. chrys/service/tools/builtins/todo.py +64 -0
  1057. chrys/service/tools/builtins/web/__init__.py +6 -0
  1058. chrys/service/tools/builtins/web/build.py +268 -0
  1059. chrys/service/tools/builtins/web/config.py +338 -0
  1060. chrys/service/tools/builtins/web/credentials.py +37 -0
  1061. chrys/service/tools/builtins/web/fetch/__init__.py +3 -0
  1062. chrys/service/tools/builtins/web/fetch/cache.py +68 -0
  1063. chrys/service/tools/builtins/web/fetch/convert.py +56 -0
  1064. chrys/service/tools/builtins/web/fetch/tool.py +223 -0
  1065. chrys/service/tools/builtins/web/hosted.py +61 -0
  1066. chrys/service/tools/builtins/web/http.py +330 -0
  1067. chrys/service/tools/builtins/web/progress.py +18 -0
  1068. chrys/service/tools/builtins/web/search/__init__.py +3 -0
  1069. chrys/service/tools/builtins/web/search/exa_mcp.py +146 -0
  1070. chrys/service/tools/builtins/web/search/html.py +152 -0
  1071. chrys/service/tools/builtins/web/search/json_api.py +227 -0
  1072. chrys/service/tools/builtins/web/search/providers.py +77 -0
  1073. chrys/service/tools/builtins/web/search/tool.py +218 -0
  1074. chrys/service/tools/builtins/web/search/types.py +28 -0
  1075. chrys/service/tools/builtins/web/tls_identity.py +66 -0
  1076. chrys/service/tools/kinds.py +115 -0
  1077. chrys/service/tools/names.py +47 -0
  1078. chrys/service/tools/registry.py +242 -0
  1079. chrys/service/tools/result_metadata.py +103 -0
  1080. chrys/service/tools/session_artifacts.py +196 -0
  1081. chrys/service/tools/spill.py +218 -0
  1082. chrys/service/tools/workspace_paths.py +81 -0
  1083. chrys/service/trajectory/__init__.py +11 -0
  1084. chrys/service/trajectory/approvals.py +201 -0
  1085. chrys/service/trajectory/compaction.py +420 -0
  1086. chrys/service/trajectory/fork.py +75 -0
  1087. chrys/service/trajectory/hooks.py +217 -0
  1088. chrys/service/trajectory/items.py +41 -0
  1089. chrys/service/trajectory/preparation.py +374 -0
  1090. chrys/service/trajectory/retries.py +95 -0
  1091. chrys/service/trajectory/revisions.py +129 -0
  1092. chrys/service/trajectory/segmented.py +163 -0
  1093. chrys/service/trajectory/session.py +762 -0
  1094. chrys/service/trajectory/state.py +83 -0
  1095. chrys/service/trajectory/sub_agents.py +169 -0
  1096. chrys/service/trajectory/tombstone.py +262 -0
  1097. chrys/service/trajectory/tools.py +323 -0
  1098. chrys/service/trajectory/validation.py +130 -0
  1099. chrys/service/trajectory/waits.py +161 -0
  1100. chrys/service/trajectory/workflow.py +148 -0
  1101. chrys/service/vision.py +128 -0
  1102. chrys/service/workflows/__init__.py +3 -0
  1103. chrys/service/workflows/admission.py +151 -0
  1104. chrys/service/workflows/artifacts.py +109 -0
  1105. chrys/service/workflows/asks.py +130 -0
  1106. chrys/service/workflows/builtins/__init__.py +12 -0
  1107. chrys/service/workflows/builtins/demo-workflow.manifest.json +635 -0
  1108. chrys/service/workflows/builtins/demo-workflow.py +756 -0
  1109. chrys/service/workflows/discovery.py +554 -0
  1110. chrys/service/workflows/environment.py +284 -0
  1111. chrys/service/workflows/graph.py +430 -0
  1112. chrys/service/workflows/history.py +82 -0
  1113. chrys/service/workflows/interpreter.py +107 -0
  1114. chrys/service/workflows/journal.py +334 -0
  1115. chrys/service/workflows/layout.py +56 -0
  1116. chrys/service/workflows/ledger.py +149 -0
  1117. chrys/service/workflows/model_selection.py +18 -0
  1118. chrys/service/workflows/orphans.py +209 -0
  1119. chrys/service/workflows/outcomes.py +46 -0
  1120. chrys/service/workflows/protocol.py +210 -0
  1121. chrys/service/workflows/records.py +142 -0
  1122. chrys/service/workflows/scheduler.py +770 -0
  1123. chrys/service/workflows/sdk/__init__.py +51 -0
  1124. chrys/service/workflows/sdk/_ask.py +167 -0
  1125. chrys/service/workflows/sdk/_builder.py +781 -0
  1126. chrys/service/workflows/sdk/_values.py +92 -0
  1127. chrys/service/workflows/sdk_artifact.py +74 -0
  1128. chrys/service/workflows/store.py +494 -0
  1129. chrys/service/workflows/transcript.py +102 -0
  1130. chrys/service/workflows/values.py +73 -0
  1131. chrys/service/workflows/worker_host.py +1820 -0
  1132. chrys/workflows.py +38 -0
  1133. icode_tui-0.29.1.dist-info/METADATA +104 -0
  1134. icode_tui-0.29.1.dist-info/RECORD +1138 -0
  1135. icode_tui-0.29.1.dist-info/WHEEL +4 -0
  1136. icode_tui-0.29.1.dist-info/entry_points.txt +2 -0
  1137. icode_tui-0.29.1.dist-info/licenses/LICENSE +202 -0
  1138. icode_tui-0.29.1.dist-info/licenses/NOTICE +1955 -0
@@ -0,0 +1,1629 @@
1
+ # Copyright (c) Huawei Technologies Co., Ltd. 2026. All rights reserved.
2
+
3
+ """Event type definitions for frontend ↔ backend communication."""
4
+
5
+ from __future__ import annotations
6
+
7
+ from dataclasses import FrozenInstanceError, dataclass, field
8
+ from datetime import UTC, datetime
9
+ from typing import TYPE_CHECKING, Any, ClassVar, Literal
10
+ from uuid import uuid4
11
+
12
+ from chrys.foundation.i18n import MessageRef
13
+ from chrys.foundation.models.approval_reuse import ApprovalReuseOffer, ReuseChoice
14
+ from chrys.foundation.models.ask_user import AskUserAnswer, AskUserQuestion
15
+ from chrys.foundation.models.execution import ExecutionSnapshot
16
+ from chrys.foundation.models.invocations import InvocationOrigin
17
+ from chrys.foundation.models.todos import TodoItem
18
+ from chrys.foundation.models.workflow_session import (
19
+ WorkflowModelSelection,
20
+ WorkflowPins,
21
+ WorkflowSessionSelection,
22
+ WorkflowTarget,
23
+ )
24
+
25
+ if TYPE_CHECKING:
26
+ # Typing-only import: avoids a runtime dependency from foundation events
27
+ # into service mutations while still letting
28
+ # :class:`RollbackResult.restore_results` advertise
29
+ # the real dataclass it carries. ``from __future__ import annotations``
30
+ # (top of file) keeps all annotations as strings, so this import never
31
+ # executes at runtime.
32
+ from chrys.service.mutations.types import RestoreResult
33
+
34
+ AGENT_LOAD_PHASE_MODEL = "model"
35
+ AGENT_LOAD_PHASE_RUNTIME = "runtime"
36
+ AGENT_LOAD_PHASE_SESSION = "session"
37
+ AGENT_LOAD_PHASE_TOOLS = "tools"
38
+ AGENT_LOAD_PHASE_SUB_AGENTS = "sub_agents"
39
+ AGENT_LOAD_PHASE_MCP = "mcp"
40
+ AGENT_LOAD_PHASE_SKILLS = "skills"
41
+ AGENT_LOAD_PHASE_AGENT = "agent"
42
+
43
+ AGENT_LOAD_STATUS_RUNNING = "running"
44
+ AGENT_LOAD_STATUS_DONE = "done"
45
+ AGENT_LOAD_STATUS_FAILED = "failed"
46
+ AGENT_LOAD_STATUS_SKIPPED = "skipped"
47
+
48
+ # ---------------------------------------------------------------------------
49
+ # Base
50
+ # ---------------------------------------------------------------------------
51
+
52
+
53
+ @dataclass
54
+ class Event:
55
+ """Base class for all events."""
56
+
57
+ event_id: str = field(default_factory=lambda: uuid4().hex[:12])
58
+ timestamp: datetime = field(default_factory=lambda: datetime.now(tz=UTC))
59
+ session_id: str | None = None
60
+
61
+
62
+ @dataclass(kw_only=True)
63
+ class ExecutionChanged(Event):
64
+ """The execution owner changed, including admission and final lease release."""
65
+
66
+ snapshot: ExecutionSnapshot
67
+
68
+
69
+ @dataclass(kw_only=True)
70
+ class InvocationEvent(Event):
71
+ """An execution or presentation fact with an explicit logical owner.
72
+
73
+ The immutable origin is the routing authority. The event envelope retains
74
+ the bus timestamp and session fields used by existing frontend consumers.
75
+ """
76
+
77
+ origin: InvocationOrigin
78
+ _sealed: ClassVar[bool] = False
79
+
80
+ def __post_init__(self) -> None:
81
+ if not isinstance(self.origin, InvocationOrigin):
82
+ raise ValueError("Cannot route an invocation event without a live origin")
83
+ if self.session_id and self.session_id != self.origin.session_id:
84
+ raise ValueError("Event session does not match its invocation origin")
85
+ object.__setattr__(self, "_sealed", True)
86
+
87
+ def __setattr__(self, name: str, value: object) -> None:
88
+ # User action envelopes are mutable; execution facts seal only after
89
+ # their dataclass initializer has populated every inherited field.
90
+ if self._sealed:
91
+ raise FrozenInstanceError(f"cannot assign to field {name!r}")
92
+ object.__setattr__(self, name, value)
93
+
94
+ def __delattr__(self, name: str) -> None:
95
+ raise FrozenInstanceError(f"cannot delete field {name!r}")
96
+
97
+
98
+ # ---------------------------------------------------------------------------
99
+ # Frontend → Backend (user actions)
100
+ # ---------------------------------------------------------------------------
101
+
102
+
103
+ @dataclass
104
+ class UserMessage(Event):
105
+ """User sends a message to the agent."""
106
+
107
+ text: str = ""
108
+ # Filled by the backend after prompt hooks, image validation, and image
109
+ # compression succeed. TUI rendering uses this to preview exactly the
110
+ # multimodal content accepted for the model call.
111
+ prepared_contents: list[Any] | None = field(default=None, repr=False, compare=False)
112
+ # Set by frontends that submit while a run is active so the resulting
113
+ # mid-run injection can be correlated and cancelled (``UserInjectCancel``)
114
+ # before the model sees it. ``None`` for ordinary fresh-turn submits.
115
+ injection_id: str | None = None
116
+
117
+
118
+ @dataclass
119
+ class UserInterrupt(Event):
120
+ """User interrupts the current agent execution."""
121
+
122
+
123
+ @dataclass
124
+ class UserRetry(Event):
125
+ """User retries the last failed/interrupted run from current state.
126
+
127
+ When ``text`` is non-empty, it is used as a mid-turn continuation prompt
128
+ and persisted as real user input inside the current turn. An empty retry
129
+ continues from completed history or replays the prior user opener.
130
+ """
131
+
132
+ text: str = ""
133
+
134
+
135
+ @dataclass
136
+ class UserInject(Event):
137
+ """User injects a prompt while agent is executing (inserted before next model call)."""
138
+
139
+ text: str = ""
140
+ injection_id: str | None = None
141
+ """Frontend-assigned id correlating this injection with cancel/result events."""
142
+
143
+
144
+ @dataclass
145
+ class UserInjectCancel(Event):
146
+ """User cancels a queued mid-run injection before the model sees it.
147
+
148
+ Effective only while the injection identified by ``injection_id`` is
149
+ still pending (queued or in admission); once consumed, the cancel is a
150
+ no-op and a ``consumed=True`` :class:`UserInjectResult` follows.
151
+ """
152
+
153
+ injection_id: str = ""
154
+
155
+
156
+ @dataclass
157
+ class UserRollback(Event):
158
+ """User requests Chat rollback to keep the first ``target_turn`` turns.
159
+
160
+ This command restores conversation/Agent state. Workflow file rollback
161
+ uses Run identities and must never be routed through this Chat command.
162
+
163
+ ``target_turn = 0`` means "roll back to the empty pre-session
164
+ state" — all conversation history is discarded and (optionally)
165
+ every file mutation is reverted. ``target_turn = N >= 1`` means
166
+ "keep turns 1..N and discard everything after"; any file
167
+ mutations introduced by the discarded turns are (optionally)
168
+ reverted.
169
+ """
170
+
171
+ target_turn: int = 0
172
+ """Number of turns to keep (0 = session start, N = keep turns 1..N)."""
173
+
174
+ relative_turns: int | None = None
175
+ """When set, discard this many latest turns under the backend transition fence.
176
+
177
+ This is the authoritative selector for relative commands such as
178
+ ``/rollback 1``; ``target_turn`` is ignored in that case. Deferring the
179
+ calculation prevents a frontend from publishing a stale absolute target
180
+ when another turn finalizes while the request is being admitted.
181
+ """
182
+
183
+ expected_current_turn: int | None = None
184
+ """Picker projection turn that must still be current when rollback is fenced.
185
+
186
+ Direct commands leave this unset because relative targets are resolved under
187
+ the backend fence and absolute targets are explicit. Picker confirmations
188
+ set it so file selections projected from an older conversation cannot be
189
+ applied after another turn completes while the modal remains open.
190
+ """
191
+
192
+ expected_conversation_revision: int | None = None
193
+ """Fresh/retry lifecycle revision that must still match the picker projection.
194
+
195
+ Unlike ``expected_current_turn``, this advances for a retry or continuation
196
+ that changes history and mutation planning without opening a fresh turn.
197
+ """
198
+
199
+ expected_build_generation: int | None = None
200
+ """Runtime build generation that produced the picker preview.
201
+
202
+ Workspace and settings rebuilds may replace mutation coordination without
203
+ advancing the conversation. Picker confirmations set this so concrete file
204
+ selections cannot be applied against a different runtime build.
205
+ """
206
+
207
+ expected_workspace_cwd: str | None = None
208
+ """Normalized primary workspace cwd that produced the picker preview."""
209
+
210
+ revert_changes: bool = False
211
+ """When True, also restore file-system changes from the discarded turns."""
212
+
213
+ selected_paths: list[str] | None = None
214
+ """Paths to include when ``revert_changes`` is True.
215
+
216
+ Either ``None`` ("revert every path in the plan") or a non-empty
217
+ list restricting the revert to those paths. The rollback modal
218
+ sends a concrete list when the user leaves files checked, and
219
+ ``None`` when ``revert_changes`` is False. ``[]`` is not a supported
220
+ input — the modal collapses the "no files checked" case into
221
+ ``revert_changes=False, selected_paths=None``; any empty list arriving
222
+ from a server-side caller is treated as ``None`` by the engine.
223
+ Ignored when ``revert_changes`` is False.
224
+ """
225
+
226
+
227
+ @dataclass
228
+ class ApprovalResponse(Event):
229
+ """User responds to an approval request."""
230
+
231
+ request_id: str = ""
232
+ approved: bool = False
233
+ reason: str = ""
234
+ modified_args: dict[str, Any] | None = None
235
+ remember_choice: ReuseChoice = ""
236
+
237
+
238
+ @dataclass
239
+ class ApprovalCancelled(Event):
240
+ """A pending approval request was abandoned by its backend owner."""
241
+
242
+ request_id: str = ""
243
+
244
+
245
+ @dataclass
246
+ class ApprovalAutoFulfillBlocked(Event):
247
+ """Frontend tells the backend not to auto-fulfil an approved judge verdict."""
248
+
249
+ request_id: str = ""
250
+
251
+
252
+ @dataclass
253
+ class AskUserResponse(Event):
254
+ """User responds to an ask_user question."""
255
+
256
+ request_id: str = ""
257
+ answers: tuple[AskUserAnswer, ...] | None = None
258
+ cancelled: bool = False
259
+
260
+
261
+ @dataclass
262
+ class SleepSkip(Event):
263
+ """User skips a running sleep tool call."""
264
+
265
+ call_id: str = ""
266
+
267
+
268
+ @dataclass
269
+ class AgentProfileSwitch(Event):
270
+ """User switches to a different agent profile."""
271
+
272
+ profile_name: str = ""
273
+
274
+
275
+ @dataclass
276
+ class WorkspaceChange(Event):
277
+ """User requests a workspace/cwd change."""
278
+
279
+ primary_cwd: str = ""
280
+
281
+
282
+ @dataclass
283
+ class ConfigUpdate(Event):
284
+ """User updates a configuration value."""
285
+
286
+ key: str = ""
287
+ value: Any = None
288
+
289
+
290
+ @dataclass
291
+ class SettingsReload(Event):
292
+ """User updated .env settings — engine should reload Settings and rebuild agent."""
293
+
294
+
295
+ @dataclass
296
+ class SetApprovalMode(Event):
297
+ """User changes the approval mode (manual/auto/bypass).
298
+
299
+ The engine updates ``ApprovalMiddleware`` and echoes ``ApprovalModeUpdated``
300
+ so the TUI can refresh the badge from the authoritative backend state.
301
+ ``persist`` controls whether the mode is also written as the global default;
302
+ ACP standard session-mode changes are session-scoped and set this false.
303
+ """
304
+
305
+ mode: str = "" # "manual" | "auto" | "bypass"
306
+ persist: bool = True
307
+
308
+
309
+ @dataclass
310
+ class SetModelProfile(Event):
311
+ """User switches the active model profile for this session only.
312
+
313
+ The engine swaps ``settings.model_profile`` in-memory and soft-restarts the
314
+ agent — no global ``.env`` write — so each session can run a different model
315
+ without colliding on process-wide environment state. The engine echoes
316
+ ``ModelProfileSwitched`` once the rebuild completes.
317
+ """
318
+
319
+ profile_id: str = ""
320
+
321
+
322
+ # ---------------------------------------------------------------------------
323
+ # Backend → Frontend (system events)
324
+ # ---------------------------------------------------------------------------
325
+
326
+
327
+ @dataclass
328
+ class AgentThinking(Event):
329
+ """Agent is thinking (optional thinking content)."""
330
+
331
+ text: str | None = None
332
+
333
+
334
+ @dataclass(frozen=True)
335
+ class ProvisionalPresentation:
336
+ """Identity of one retractable text segment from a response attempt."""
337
+
338
+ attempt_id: str
339
+ segment_id: str
340
+
341
+
342
+ @dataclass
343
+ class InvocationStarted(InvocationEvent):
344
+ """A sub-agent invocation has started — binds invocation_id to parent call_id.
345
+
346
+ Emitted by ``SubAgentTools._invoke`` immediately after generating the
347
+ ``invocation_id``, before the first LLM call. Carries both the parent
348
+ tool call's ``call_id`` (generated by :class:`ToolEventMiddleware`) and
349
+ the new ``invocation_id`` so the TUI can deterministically link the
350
+ sub-agent widget that was mounted for the parent call to the sub-agent
351
+ runtime, without relying on first-inner-tool-call arrival order.
352
+
353
+ This matters when multiple sub-agents run in parallel: if one stalls
354
+ in a retry backoff while its sibling's inner tool calls start arriving,
355
+ a FIFO linker would assign the wrong widget and route retry banners /
356
+ progress updates to the wrong card.
357
+
358
+ ``sub_agent_log_file`` is the writer's immutable safe basename, not a
359
+ claim that the audit is complete. Frontends may retain it from this first
360
+ event and accept the file only after its envelope reaches a terminal
361
+ status; this keeps audit discovery independent of controller creation.
362
+
363
+ ``opening_prompt`` carries the actual user text for standalone invocations
364
+ whose input is not already visible in a parent tool card.
365
+ """
366
+
367
+ agent_name: str = ""
368
+ tool_name: str = ""
369
+ parent_call_id: str = ""
370
+ sub_agent_log_file: str = ""
371
+ opening_prompt: str = ""
372
+
373
+
374
+ @dataclass
375
+ class InvocationMessage(InvocationEvent):
376
+ """Assistant output owned by an invocation; consumers choose its projection."""
377
+
378
+ agent_name: str = ""
379
+ text: str = ""
380
+ is_final: bool = True
381
+ is_intermediate: bool = False
382
+ structured_output_completed: bool = False
383
+ presentation: ProvisionalPresentation | None = None
384
+
385
+
386
+ @dataclass
387
+ class InvocationPresentationAttemptAccepted(InvocationEvent):
388
+ """Commit provisional sub-agent transcript segments from one attempt."""
389
+
390
+ agent_name: str = ""
391
+ attempt_id: str = ""
392
+ segment_ids: tuple[str, ...] = ()
393
+
394
+
395
+ @dataclass
396
+ class InvocationPresentationAttemptRejected(InvocationEvent):
397
+ """Retract provisional sub-agent transcript segments from one attempt."""
398
+
399
+ agent_name: str = ""
400
+ attempt_id: str = ""
401
+
402
+
403
+ @dataclass
404
+ class InvocationToolCallStart(InvocationEvent):
405
+ """A tool call started inside a sub-agent."""
406
+
407
+ agent_name: str = ""
408
+ tool_name: str = ""
409
+ tool_kind: str = ""
410
+ args: dict[str, Any] = field(default_factory=dict)
411
+ call_id: str = ""
412
+ provider_hosted: bool = False
413
+ hosted_family: str = ""
414
+ provider: str = ""
415
+ provider_item_type: str = ""
416
+ provider_call_id: str = ""
417
+ provider_status: str = ""
418
+
419
+
420
+ @dataclass
421
+ class InvocationToolCallArgsUpdated(InvocationEvent):
422
+ """A sub-agent tool call's arguments changed after its start event."""
423
+
424
+ agent_name: str = ""
425
+ tool_name: str = ""
426
+ tool_kind: str = ""
427
+ call_id: str = ""
428
+ args: dict[str, Any] = field(default_factory=dict)
429
+ provider_hosted: bool = False
430
+ hosted_family: str = ""
431
+ provider: str = ""
432
+ provider_item_type: str = ""
433
+ provider_call_id: str = ""
434
+ provider_status: str = ""
435
+
436
+
437
+ @dataclass
438
+ class InvocationToolCallStatusUpdated(InvocationEvent):
439
+ """A sub-agent tool call's structured lifecycle status changed."""
440
+
441
+ agent_name: str = ""
442
+ tool_name: str = ""
443
+ call_id: str = ""
444
+ status: str = ""
445
+ provider_status: str = ""
446
+ provider_hosted: bool = False
447
+ hosted_family: str = ""
448
+ provider: str = ""
449
+ metadata: dict[str, Any] = field(default_factory=dict)
450
+
451
+
452
+ @dataclass
453
+ class InvocationToolCallProgress(InvocationEvent):
454
+ """Incremental text or structured progress from a sub-agent tool call."""
455
+
456
+ agent_name: str = ""
457
+ tool_name: str = ""
458
+ call_id: str = ""
459
+ lines: list[str] = field(default_factory=list)
460
+ image_contents: list[Any] = field(default_factory=list, repr=False, compare=False)
461
+ snapshot_metadata: dict[str, Any] = field(default_factory=dict)
462
+ provider_hosted: bool = False
463
+ hosted_family: str = ""
464
+ provider: str = ""
465
+ provider_item_type: str = ""
466
+ provider_call_id: str = ""
467
+ provider_status: str = ""
468
+
469
+
470
+ @dataclass
471
+ class InvocationToolCallResult(InvocationEvent):
472
+ """A tool call completed inside a sub-agent."""
473
+
474
+ agent_name: str = ""
475
+ tool_name: str = ""
476
+ call_id: str = ""
477
+ result: str = ""
478
+ image_contents: list[Any] = field(default_factory=list, repr=False, compare=False)
479
+ duration_ms: int = 0
480
+ metadata: dict[str, Any] = field(default_factory=dict)
481
+ artifacts: list[dict[str, Any]] = field(default_factory=list)
482
+ provider_hosted: bool = False
483
+ hosted_family: str = ""
484
+ provider: str = ""
485
+ provider_item_type: str = ""
486
+ provider_call_id: str = ""
487
+ provider_status: str = ""
488
+
489
+
490
+ @dataclass
491
+ class InvocationProgress(InvocationEvent):
492
+ """Cumulative progress update from a sub-agent invocation."""
493
+
494
+ agent_name: str = ""
495
+ tool_call_count: int = 0
496
+ """Completed inner tool calls for this invocation."""
497
+
498
+ total_tokens: int = 0
499
+ """Current context-window tokens reported by the most recent sub-agent LLM call."""
500
+
501
+ total_usage_tokens: int = 0
502
+ """Cumulative tokens consumed by this sub-agent invocation across LLM calls."""
503
+
504
+ usage_unreported_attempts: int = 0
505
+ """ACP attempts whose terminal response did not report spend."""
506
+
507
+
508
+ @dataclass
509
+ class InvocationCompactionStarted(InvocationEvent):
510
+ """Phase-4 LAST_WORDS compaction began inside a sub-agent invocation.
511
+
512
+ Mirrors :class:`CompactionStarted` with ``invocation_id`` as the
513
+ routing key so the TUI can show a live compaction line on the
514
+ owning sub-agent card.
515
+ """
516
+
517
+ agent_name: str = ""
518
+ compaction_id: str = ""
519
+ phase: str = "phase4"
520
+
521
+
522
+ @dataclass
523
+ class InvocationCompactionFinished(InvocationEvent):
524
+ """Phase-4 LAST_WORDS compaction finished inside a sub-agent invocation.
525
+
526
+ ``outcome`` matches :class:`CompactionFinished`. The note text is
527
+ deliberately omitted — sub-agent cards only flip the status line — but
528
+ ``format_violation`` preserves an accepted structured-note violation for
529
+ observers, and ``failure_reason`` carries the safety-limit cause of a
530
+ failed outcome (see :class:`CompactionFinished`).
531
+ """
532
+
533
+ agent_name: str = ""
534
+ compaction_id: str = ""
535
+ phase: str = "phase4"
536
+ outcome: str = ""
537
+ duration_ms: int = 0
538
+ format_violation: str = ""
539
+ failure_reason: str = ""
540
+
541
+
542
+ @dataclass
543
+ class InvocationCompactionCommitted(InvocationEvent):
544
+ """A Phase-4 compaction round was durably applied inside a sub-agent.
545
+
546
+ Follows the finished(``outcome="ok"``) signal for the same
547
+ ``compaction_id`` once the strategy has committed the round — spill
548
+ written (or checkpointed), note set, messages excluded. A finished-ok
549
+ round whose spill write failed never produces this event, so observers
550
+ that count real compactions (the sub-agent card's "Compactions: N"
551
+ subtitle) count this instead of finished-ok.
552
+ """
553
+
554
+ agent_name: str = ""
555
+ compaction_id: str = ""
556
+ phase: str = "phase4"
557
+
558
+
559
+ # --- Sub-agent lifecycle (pause / retry / abort) ---------------------------
560
+ #
561
+ # These events scope retry and abort to a single sub-agent invocation so
562
+ # that, when multiple sub-agents run concurrently, a retry click on one
563
+ # paused card does not disturb healthy siblings. Every event carries
564
+ # ``invocation_id`` as its routing key.
565
+
566
+
567
+ @dataclass
568
+ class InvocationRetryAttempt(InvocationEvent):
569
+ """Executor is retrying a transient error (published before each retry sleep).
570
+
571
+ Also announces the one resend after a context overflow, which compacts first.
572
+ """
573
+
574
+ agent_name: str = ""
575
+ message: str = ""
576
+ """Pre-rendered English retained byte-for-byte for compatibility consumers."""
577
+ attempt: int = 0
578
+ """1-based attempt number (the retry about to happen)."""
579
+ max_attempts: int = 0
580
+ delay_seconds: int = 0
581
+ scope: Literal["wire", "run", "compaction", "connection"] = "run"
582
+ """The owning retry lane: wire, whole run, connection, or compaction. Frontends render compaction retries
583
+ inside the live compaction card instead of a transcript-level error banner."""
584
+ display_message: MessageRef | None = None
585
+ """Locale-neutral display reference when this retry has migrated prose."""
586
+ display_hint: MessageRef | None = None
587
+ """Shown after ``display_message`` (e.g. "seems offline"); never without it."""
588
+ detail: str = ""
589
+ """Raw untranslated diagnostic component separated from a fixed wrapper."""
590
+
591
+
592
+ @dataclass
593
+ class InvocationPaused(InvocationEvent):
594
+ """A sub-agent exhausted auto-retry (or hit a non-retryable error) and is
595
+ waiting for the user to decide via Retry or Abort.
596
+
597
+ The parent's ``_invoke()`` is still awaiting — the parent tool call
598
+ will only resolve once the user picks a decision (or a global
599
+ interrupt fires).
600
+ """
601
+
602
+ agent_name: str = ""
603
+ tool_name: str = ""
604
+ reason: str = ""
605
+ """One of ``stream_stall``, ``last_words``, ``framework_exc``, ``acp_transport``."""
606
+ last_error: str = ""
607
+ last_error_display: MessageRef | None = None
608
+ """What ``last_error`` means to the user; the raw text still follows it."""
609
+ last_error_hint: MessageRef | None = None
610
+ retry_attempts: int = 0
611
+ diagnostic_path: str | None = None
612
+ """UI-only diagnostic file path; never interpolate into model-visible errors."""
613
+
614
+
615
+ @dataclass
616
+ class InvocationRetryRequested(Event):
617
+ """User clicked Retry on a paused sub-agent card (frontend → backend)."""
618
+
619
+ invocation_id: str = ""
620
+
621
+
622
+ @dataclass
623
+ class InvocationAbortRequested(Event):
624
+ """User clicked Abort on a paused sub-agent card (frontend → backend).
625
+
626
+ The controller resolves the pending decision to ``"abort"``; the tool
627
+ call returns an ``Error:`` string so the parent agent sees a normal
628
+ tool-failure result and can decide what to do next.
629
+ """
630
+
631
+ invocation_id: str = ""
632
+
633
+
634
+ @dataclass
635
+ class InvocationResumed(InvocationEvent):
636
+ """The controller restarted the sub-agent after a user Retry (backend → frontend)."""
637
+
638
+ agent_name: str = ""
639
+
640
+
641
+ @dataclass
642
+ class InvocationCascadeAborted(InvocationEvent):
643
+ """A global :class:`UserInterrupt` tore down this paused/running sub-agent.
644
+
645
+ Distinct from :class:`InvocationPaused` with an abort action: here the
646
+ user stopped the whole engine, not just this one sub-agent.
647
+ """
648
+
649
+ agent_name: str = ""
650
+
651
+
652
+ @dataclass
653
+ class InvocationAborted(InvocationEvent):
654
+ """A failed sub-agent ended without a retry (backend → frontend).
655
+
656
+ Emitted by the controller after resolving its ``pending_decision``
657
+ with the user's Abort — or at once, where the caller's surface shows
658
+ no card that could pause — right before the tool call returns an
659
+ ``Error:`` string to the parent. Distinct from
660
+ :class:`InvocationCascadeAborted` — this one is scoped to a single
661
+ invocation, the parent run keeps going. The engine listens for this
662
+ event to decrement its paused-invocation set and drive the FSM out
663
+ of ``AWAITING_SUB_AGENTS``.
664
+ """
665
+
666
+ agent_name: str = ""
667
+ last_error: str = ""
668
+
669
+
670
+ @dataclass
671
+ class ApprovalRequest(Event):
672
+ """Engine requests user approval for a tool call."""
673
+
674
+ request_id: str = ""
675
+ call_id: str = ""
676
+ caller_name: str = ""
677
+ tool_name: str = ""
678
+ tool_kind: str = ""
679
+ presentation_kind: str = ""
680
+ """Display-only kind hint for bridged remote (ACP) requests.
681
+
682
+ Drives the approval dialog's human header ("Run command", …). Never
683
+ consulted by approval policy or the judge — ``tool_kind`` stays ``""``
684
+ for bridged requests precisely so kind-scoped rules cannot match them.
685
+ """
686
+ args: dict[str, Any] = field(default_factory=dict)
687
+ intent_summary: str = ""
688
+ user_message: str = ""
689
+ workspace_roots: list[str] = field(default_factory=list)
690
+ workspace_cwd: str = ""
691
+ reuse_offer: ApprovalReuseOffer | None = None
692
+ judging: bool = False
693
+ """True when an LLM reviewer is concurrently evaluating this request.
694
+
695
+ An ``ApprovalReviewed`` follows unless the wait ends first. A frontend may
696
+ hold the request out of sight until then and ask the user only when the
697
+ verdict flags it (the ACP server always does; the TUI does by default), or
698
+ show it at once with an "Evaluating" spinner.
699
+ """
700
+
701
+
702
+ @dataclass
703
+ class ApprovalReviewed(Event):
704
+ """Automated reviewer has finished evaluating a pending ``ApprovalRequest``.
705
+
706
+ Published only for AUTO-mode requests. An approved outcome normally
707
+ causes the backend to auto-fulfil the approval after the TUI receives this
708
+ event, unless the frontend publishes ``ApprovalAutoFulfillBlocked`` because
709
+ a user decision is already in flight. A flagged outcome carries the
710
+ concern so the user can decide.
711
+ """
712
+
713
+ request_id: str = ""
714
+ approved: bool = False
715
+ reason: str = ""
716
+
717
+
718
+ @dataclass
719
+ class ApprovalModeUpdated(Event):
720
+ """Backend confirms the current approval mode (after a ``SetApprovalMode``
721
+ or after session start). The TUI uses this as the authoritative source
722
+ for the header badge.
723
+ """
724
+
725
+ mode: str = "" # "manual" | "auto" | "bypass"
726
+
727
+
728
+ @dataclass
729
+ class QuestionToUser(Event):
730
+ """Agent asks the user a question."""
731
+
732
+ questions: tuple[AskUserQuestion, ...] = ()
733
+ request_id: str = ""
734
+ call_id: str = ""
735
+ caller_name: str = ""
736
+
737
+
738
+ @dataclass
739
+ class AskUserTimedOut(Event):
740
+ """An ask_user question expired before the user responded."""
741
+
742
+ request_id: str = ""
743
+
744
+
745
+ @dataclass
746
+ class ToolCompacted(Event):
747
+ """Intra-turn tool compaction compressed old tool-call groups."""
748
+
749
+ compacted_groups: int = 0
750
+ """Number of tool-call groups that were compacted."""
751
+
752
+ phase: str = ""
753
+ """Which phase: ``"phase1"`` to ``"phase4"`` (see compaction module docstring)."""
754
+
755
+ turn_numbers: list[int] = field(default_factory=list)
756
+ """1-based turn numbers affected (phase 1 only)."""
757
+
758
+ compacted_tool_names: list[str] = field(default_factory=list)
759
+ """Tool names from compacted groups (for debugging)."""
760
+
761
+ tokens_before: int = 0
762
+ """Estimated token count before compaction."""
763
+
764
+ tokens_after: int = 0
765
+ """Estimated token count after compaction."""
766
+
767
+ last_words_generated: bool = False
768
+ """Phase 4 only: True when a LAST_WORDS progress note was produced/updated."""
769
+
770
+
771
+ @dataclass
772
+ class CompactionStarted(Event):
773
+ """Phase-4 LAST_WORDS compaction began on the main agent.
774
+
775
+ Published immediately before the summarization LLM call so frontends
776
+ can surface a live "Compacting conversation…" indicator during the
777
+ otherwise-silent wait (seconds to minutes with retry backoff).
778
+ ``compaction_id`` correlates with :class:`CompactionFinished`.
779
+ """
780
+
781
+ compaction_id: str = ""
782
+ phase: str = "phase4"
783
+
784
+
785
+ @dataclass
786
+ class CompactionFinished(Event):
787
+ """Phase-4 LAST_WORDS compaction finished on the main agent.
788
+
789
+ ``outcome`` is ``"ok"`` (note generated), ``"failed"`` (generation
790
+ exhausted its retry budget), or ``"canceled"`` (the run was
791
+ interrupted mid-generation). ``last_words`` carries the generated
792
+ note on success so frontends can render it without re-reading backend
793
+ state. ``format_violation`` records a structured-note violation accepted
794
+ when the bounded corrective retry process stops. ``failure_reason`` is
795
+ a short human-readable cause set on failed outcomes caused by a known
796
+ safety limit (per-turn round limit, side-call spend budget); frontends
797
+ show it on the failure card in place of the duration.
798
+ """
799
+
800
+ compaction_id: str = ""
801
+ phase: str = "phase4"
802
+ outcome: str = ""
803
+ duration_ms: int = 0
804
+ last_words: str = ""
805
+ format_violation: str = ""
806
+ failure_reason: str = ""
807
+
808
+
809
+ @dataclass
810
+ class InvocationContextPressure(InvocationEvent):
811
+ """Phase 4 disabled after its attempt/progress/spend breaker tripped."""
812
+
813
+ reason: str = ""
814
+ attempts: int = 0
815
+ side_call_tokens: int = 0
816
+ side_call_token_budget: int = 0
817
+ source: str = "main"
818
+
819
+
820
+ @dataclass
821
+ class ContextCompressed(Event):
822
+ """Context was compressed (folded) at a turn marker."""
823
+
824
+ compressed_context_id: str = ""
825
+ summary: str = ""
826
+ freed_messages: int = 0
827
+ turn_range: tuple[int, int] = (0, 0)
828
+ source: str = "agent"
829
+ """What initiated: ``"agent"`` (LLM) or ``"auto"`` (platform)."""
830
+
831
+
832
+ @dataclass
833
+ class UsageUpdate(Event):
834
+ """Token usage update."""
835
+
836
+ agent_profile: str = ""
837
+ """Agent profile that produced this usage update."""
838
+
839
+ usage_source_id: str = ""
840
+ """Stable source id for the agent run that produced this update.
841
+
842
+ Main-agent usage uses the session id; sub-agent usage uses the sub-agent
843
+ invocation id. Profile names are display metadata and are not unique
844
+ enough to distinguish main-agent and sub-agent windows.
845
+ """
846
+
847
+ input_tokens: int = 0
848
+ output_tokens: int = 0
849
+ total_tokens: int = 0
850
+ pct: float = 0.0
851
+ max_context_tokens: int = 0
852
+ total_session_tokens: int = 0
853
+ """Cumulative tokens consumed across all LLM calls in this session."""
854
+
855
+ total_session_input_tokens: int = 0
856
+ """Cumulative input tokens consumed across all LLM calls in this session."""
857
+
858
+ total_session_output_tokens: int = 0
859
+ """Cumulative output tokens consumed across all LLM calls in this session."""
860
+
861
+ cache_hit_tokens: int | None = None
862
+ """Cache-read tokens reported by the provider for the last LLM call, or
863
+ ``None`` if no provider in this session has reported a cache field."""
864
+
865
+ total_session_cache_hit_tokens: int | None = None
866
+ """Cumulative cache-read tokens across the session, or ``None`` until the
867
+ first cache-aware response."""
868
+
869
+ local_tokens: int = 0
870
+ """Local tokenizer estimate of included conversation tokens (excludes system prompt/tools)."""
871
+
872
+ calibration_ratio: float = 1.0
873
+ """Ratio between API token count and local estimate (> 1.0 = API sees more due to overhead)."""
874
+
875
+ system_overhead_tokens: int = 0
876
+ """Estimated fixed overhead (system prompt + tool definitions), not counted in local_tokens."""
877
+
878
+
879
+ @dataclass
880
+ class StateChanged(Event):
881
+ """A session state value changed."""
882
+
883
+ key: str = ""
884
+ value: Any = None
885
+
886
+
887
+ @dataclass
888
+ class TodoListUpdated(Event):
889
+ """The session todo list was replaced (full-list payload, not a diff)."""
890
+
891
+ items: list[TodoItem] = field(default_factory=list)
892
+ source: str = "main"
893
+ """Origin of the update; future: sub-agent name / ``"user"``."""
894
+
895
+
896
+ @dataclass
897
+ class UserInjectResult(Event):
898
+ """Reports whether a mid-run user message was delivered to the model.
899
+
900
+ consumed=True: The message was injected before the next model call.
901
+ The TUI should display it in the chat at this point.
902
+ consumed=False: agent.run() ended before the message could be injected.
903
+ The TUI should keep the text in the input bar for re-use.
904
+
905
+ ``created_at`` is the original user-message timestamp, not this result
906
+ event's publish timestamp.
907
+ """
908
+
909
+ text: str = ""
910
+ consumed: bool = False
911
+ created_at: datetime | str | None = None
912
+ injection_id: str | None = None
913
+ """Id of the originating injection when it carried one; frontends use it
914
+ to ignore results for injections they already cancelled or replaced."""
915
+
916
+
917
+ @dataclass
918
+ class Error(Event):
919
+ """An error occurred."""
920
+
921
+ code: str = ""
922
+ message: str = ""
923
+ """Pre-rendered English retained byte-for-byte for compatibility consumers."""
924
+ recoverable: bool = True
925
+ display_message: MessageRef | None = None
926
+ display_hint: MessageRef | None = None
927
+ """Shown after ``display_message``; never without it."""
928
+
929
+
930
+ @dataclass
931
+ class Warning(Event):
932
+ """A non-fatal warning that should be surfaced to the user without disrupting workflow."""
933
+
934
+ request_id: str = ""
935
+ """Workflow admission diagnostics route before a run has been accepted."""
936
+ code: str = ""
937
+ message: str = ""
938
+ """Pre-rendered English retained byte-for-byte for compatibility consumers."""
939
+ display_message: MessageRef | None = None
940
+
941
+
942
+ @dataclass
943
+ class RuntimeModelDetails:
944
+ """Non-sensitive details about the active model profile."""
945
+
946
+ profile_id: str = ""
947
+ name: str = ""
948
+ provider: str = ""
949
+ api_style: str = ""
950
+ model_id: str = ""
951
+ max_context_tokens: int = 0
952
+ base_url: str = ""
953
+ stream: bool = False
954
+ vision: bool = False
955
+ selection_source: Literal["override", "agent", "inherited", "active", "default"] = "active"
956
+
957
+
958
+ @dataclass
959
+ class RuntimeSkillDetails:
960
+ """Non-sensitive details about one loaded runtime skill."""
961
+
962
+ name: str = ""
963
+ description: str = ""
964
+ source: str = ""
965
+
966
+
967
+ @dataclass
968
+ class RuntimeHookDetails:
969
+ """Non-sensitive details about one configured runtime hook."""
970
+
971
+ id: str = ""
972
+ event: str = ""
973
+ execution_mode: str = ""
974
+ enabled: bool = True
975
+ description: str = ""
976
+
977
+
978
+ @dataclass
979
+ class RuntimeHookSourceDetails:
980
+ """One project or global source contributing runtime hooks."""
981
+
982
+ scope: Literal["project", "global"] = "global"
983
+ source_path: str = ""
984
+ hooks: list[RuntimeHookDetails] = field(default_factory=list)
985
+
986
+
987
+ @dataclass
988
+ class AgentRuntimeDetails:
989
+ """Grouped runtime metadata for the TUI details dialog."""
990
+
991
+ model: RuntimeModelDetails = field(default_factory=RuntimeModelDetails)
992
+ builtin_tools: dict[str, list[str]] = field(default_factory=dict)
993
+ web_search_providers: dict[str, str] = field(default_factory=dict)
994
+ sub_agent_tools: list[str] = field(default_factory=list)
995
+ mcp_tools: dict[str, list[str]] = field(default_factory=dict)
996
+ mcp_failures: dict[str, str] = field(default_factory=dict)
997
+ skill_sources: dict[str, list[str]] = field(default_factory=dict)
998
+ skill_details: list[RuntimeSkillDetails] = field(default_factory=list)
999
+ hook_sources: list[RuntimeHookSourceDetails] = field(default_factory=list)
1000
+ memory_sources: dict[str, list[str]] = field(default_factory=dict)
1001
+
1002
+
1003
+ @dataclass
1004
+ class AgentLoadStarted(Event):
1005
+ """Agent infrastructure loading has started."""
1006
+
1007
+ operation: str = ""
1008
+ from_profile: str = ""
1009
+ to_profile: str = ""
1010
+ from_display_name: str = ""
1011
+ to_display_name: str = ""
1012
+
1013
+
1014
+ @dataclass
1015
+ class AgentLoadProgress(Event):
1016
+ """Incremental progress while building agent tools/context."""
1017
+
1018
+ phase: str = ""
1019
+ message: str = ""
1020
+ """Pre-rendered English retained byte-for-byte for compatibility consumers."""
1021
+ server_name: str = ""
1022
+ """MCP server identifier retained for compatibility."""
1023
+ current: int = 0
1024
+ total: int = 0
1025
+ failed: int = 0
1026
+ status: str = ""
1027
+ """Closed progress status from the ``AGENT_LOAD_STATUS_*`` vocabulary."""
1028
+ subject: str = ""
1029
+ """Generic per-item identifier, such as an MCP server or sub-agent profile."""
1030
+ detail: str = ""
1031
+ """Raw untranslated dynamic reason associated with this progress update."""
1032
+
1033
+
1034
+ @dataclass
1035
+ class AgentLoadFinished(Event):
1036
+ """Agent infrastructure loading has finished successfully."""
1037
+
1038
+ operation: str = ""
1039
+ agent_profile: str = ""
1040
+ display_name: str = ""
1041
+
1042
+
1043
+ @dataclass
1044
+ class AgentLoadFailed(Event):
1045
+ """Agent infrastructure loading failed before the session became usable."""
1046
+
1047
+ operation: str = ""
1048
+ agent_profile: str = ""
1049
+ display_name: str = ""
1050
+ message: str = ""
1051
+ """Pre-rendered English retained byte-for-byte for compatibility consumers."""
1052
+ display_message: MessageRef | None = None
1053
+ """Locale-neutral display reference for future migrated failure producers."""
1054
+ display_hint: MessageRef | None = None
1055
+ """Shown after ``display_message``; never without it."""
1056
+
1057
+
1058
+ @dataclass
1059
+ class ImageAttachmentCompressionStarted(Event):
1060
+ """Image attachment compression has started before a user turn is sent."""
1061
+
1062
+ image_count: int = 0
1063
+
1064
+
1065
+ @dataclass
1066
+ class ImageAttachmentCompressionFinished(Event):
1067
+ """Image attachment compression has finished before a user turn is sent."""
1068
+
1069
+ image_count: int = 0
1070
+
1071
+
1072
+ @dataclass
1073
+ class SessionReady(Event):
1074
+ """Session is initialized and ready."""
1075
+
1076
+ agent_profile: str = ""
1077
+ display_name: str = ""
1078
+ model_profile_id: str = ""
1079
+ max_context_tokens: int = 0
1080
+ tool_names: list[str] = field(default_factory=list)
1081
+ tool_kinds: dict[str, str] = field(default_factory=dict)
1082
+ skill_names: list[str] = field(default_factory=list)
1083
+ sub_agent_tool_names: list[str] = field(default_factory=list)
1084
+ memory_files: list[str] = field(default_factory=list)
1085
+ runtime_details: AgentRuntimeDetails = field(default_factory=AgentRuntimeDetails)
1086
+ primary_cwd: str = ""
1087
+ # All workspace roots (may include the primary cwd) so consumers such as
1088
+ # the workspace MRU can record secondary roots without an engine query.
1089
+ working_dirs: list[str] = field(default_factory=list)
1090
+
1091
+
1092
+ @dataclass
1093
+ class AgentRuntimeUpdated(Event):
1094
+ """Agent runtime metadata changed without a full agent rebuild.
1095
+
1096
+ ``model_profile_id`` and ``max_context_tokens`` are intentionally
1097
+ denormalized from ``runtime_details.model`` for active model and context
1098
+ window tracking. ``runtime_details`` carries the complete confirmed
1099
+ metadata consumed by runtime confirmation paths.
1100
+ """
1101
+
1102
+ model_profile_id: str = ""
1103
+ max_context_tokens: int = 0
1104
+ tool_names: list[str] = field(default_factory=list)
1105
+ skill_names: list[str] = field(default_factory=list)
1106
+ memory_files: list[str] = field(default_factory=list)
1107
+ runtime_details: AgentRuntimeDetails = field(default_factory=AgentRuntimeDetails)
1108
+
1109
+
1110
+ # ---------------------------------------------------------------------------
1111
+ # Workspace & history events
1112
+ # ---------------------------------------------------------------------------
1113
+
1114
+
1115
+ @dataclass
1116
+ class SessionNew(Event):
1117
+ """User requests to start a new session (preserving the current one)."""
1118
+
1119
+
1120
+ @dataclass
1121
+ class SessionRestore(Event):
1122
+ """User requests to restore a saved session."""
1123
+
1124
+ session_id: str = ""
1125
+ primary_cwd: str = ""
1126
+ profile_name: str = ""
1127
+ # Rollback restores have already swapped session.json and must ignore/delete
1128
+ # any live crash-recovery sidecar from the pre-rollback state.
1129
+ ignore_recovery: bool = False
1130
+ apply_saved_model: bool = False
1131
+ # Request-time additional working directories (paths), excluding the primary cwd.
1132
+ # ``None`` means the caller did not specify roots — keep the saved workspace. A
1133
+ # list (possibly empty) is authoritative and replaces the saved additional roots,
1134
+ # so ACP clients can narrow, swap, or clear scope on load.
1135
+ working_dirs: list[str] | None = None
1136
+
1137
+
1138
+ @dataclass
1139
+ class SessionDelete(Event):
1140
+ """User requests to delete a saved session."""
1141
+
1142
+ session_id: str = ""
1143
+
1144
+
1145
+ @dataclass
1146
+ class SessionClear(Event):
1147
+ """User requests to delete the ACTIVE session and start a fresh one.
1148
+
1149
+ One fenced backend transition: prompt admission is closed for the whole
1150
+ operation, the deletion is acknowledged by ``SessionDeleted`` before the
1151
+ fresh session starts, and a failed deletion keeps the current session
1152
+ intact and reports ``Error(code="session_clear_failed")`` — the fresh
1153
+ session is never started in that case. ``session_id`` must be the
1154
+ engine's active session.
1155
+ """
1156
+
1157
+ session_id: str = ""
1158
+
1159
+
1160
+ @dataclass
1161
+ class SessionRestored(Event):
1162
+ """A session has been successfully restored (backend → frontend)."""
1163
+
1164
+ session_id: str = ""
1165
+ agent_profile: str = ""
1166
+ display_name: str = ""
1167
+ # Profile shown by the oldest restored messages. This avoids a frontend
1168
+ # scan of every saved session merely to recover one history field.
1169
+ initial_agent_profile: str = ""
1170
+ message_count: int = 0
1171
+ cwd_warning: str = ""
1172
+ primary_cwd: str = ""
1173
+ recovered_from_sidecar: bool = False
1174
+ # Restored workspace roots (may include the primary cwd) so consumers
1175
+ # such as the workspace MRU can record secondary roots without an
1176
+ # engine query.
1177
+ working_dirs: list[str] = field(default_factory=list)
1178
+
1179
+
1180
+ @dataclass
1181
+ class SessionSaved(Event):
1182
+ """A session has been auto-saved (backend → frontend, triggers history refresh)."""
1183
+
1184
+ session_id: str = ""
1185
+
1186
+
1187
+ @dataclass
1188
+ class SessionTitleUpdated(Event):
1189
+ """A session's title overlay changed (backend → frontend).
1190
+
1191
+ Published after a title patch lands in ``session.json``: either the
1192
+ user saved/cleared a custom title (``custom=True``, ``title`` may be
1193
+ empty to fall back to automatic titles) or the post-turn summarizer
1194
+ persisted a fresh auto-generated title (``custom=False``).
1195
+
1196
+ ``display_title`` carries the post-update resolved title (custom >
1197
+ generated > first-message fallback) so protocol consumers that show a
1198
+ single title string (e.g. the ACP bridge) don't clear it while a
1199
+ fallback still exists; ``title`` stays the raw patched value for
1200
+ consumers that track the overlay fields themselves.
1201
+ """
1202
+
1203
+ title: str = ""
1204
+ custom: bool = False
1205
+ display_title: str = ""
1206
+
1207
+
1208
+ @dataclass
1209
+ class SessionFork(Event):
1210
+ """User requests to fork the current session."""
1211
+
1212
+ session_id: str = ""
1213
+
1214
+
1215
+ @dataclass
1216
+ class SessionForked(Event):
1217
+ """A session has been forked (backend → frontend)."""
1218
+
1219
+ session_id: str = ""
1220
+ parent_session_id: str = ""
1221
+ new_session_id: str = ""
1222
+
1223
+
1224
+ @dataclass
1225
+ class RollbackResult(Event):
1226
+ """Rollback completed (backend → frontend).
1227
+
1228
+ The TUI should clear its chat view and either replay the restored
1229
+ history (for ``target_turn >= 1``) or show the welcome state
1230
+ (for ``target_turn == 0``). Frontends may seed their input composer
1231
+ from ``rolled_back_user_text`` after the rollback UI refresh.
1232
+ """
1233
+
1234
+ session_id: str = ""
1235
+ target_turn: int = 0
1236
+ """Number of turns kept after the rollback (0 = session start)."""
1237
+
1238
+ rolled_back_user_text: str = ""
1239
+ """First user prompt from the discarded turn range, if available."""
1240
+
1241
+ files_reverted: int = 0
1242
+ """Count of files that were actually changed on disk by the revert
1243
+ (sum of ``r.changed`` across :attr:`restore_results`). Zero means
1244
+ either no revert was requested or every target was already at the
1245
+ expected content. Use ``bool(restore_results)`` to distinguish
1246
+ "revert was attempted" from "revert was skipped"."""
1247
+
1248
+ restore_results: list[RestoreResult] = field(default_factory=list)
1249
+ """Per-file :class:`chrys.service.mutations.types.RestoreResult`
1250
+ entries — one per path the rollback plan targeted. The import is
1251
+ ``TYPE_CHECKING``-only so the events module stays runtime-free of
1252
+ a core dependency (see header); consumers import ``RestoreResult``
1253
+ directly and use ``r.changed``/``r.ok`` for per-path counts and
1254
+ ``r.reason`` for failure text. The list is never heterogeneous —
1255
+ ``MutationTracker.rollback`` is the sole producer."""
1256
+
1257
+ exclusions: list[tuple[str, str]] = field(default_factory=list)
1258
+ """``(path, reason)`` pairs for files the rollback plan dropped —
1259
+ primitive shapes only (``reason`` is a
1260
+ ``RollbackExclusionReason.value`` string like ``"unrestorable"`` /
1261
+ ``"move_poisoned"``); the enum lives in the service layer, which
1262
+ foundation must not import. Populated from the pre-built
1263
+ ``RollbackPlan`` — the engine builds the plan before executing
1264
+ because the rolled-back turns (and with them the exclusions) are
1265
+ unreconstructable afterwards. Empty when no file revert was
1266
+ requested."""
1267
+
1268
+ warnings: list[str] = field(default_factory=list)
1269
+ """Advisory, repo-level notice strings attached to the rollback
1270
+ plan (e.g. another chrys session has an active command in this
1271
+ tree). Per-path hazards are exclusions, never warnings."""
1272
+
1273
+
1274
+ @dataclass
1275
+ class SessionDeleted(Event):
1276
+ """A session has been deleted (backend → frontend)."""
1277
+
1278
+ session_id: str = ""
1279
+
1280
+
1281
+ @dataclass
1282
+ class ProfileSwitched(Event):
1283
+ """A profile switch has completed with history preserved (backend → frontend)."""
1284
+
1285
+ from_profile: str = ""
1286
+ to_profile: str = ""
1287
+ from_display_name: str = ""
1288
+ to_display_name: str = ""
1289
+ message_count: int = 0
1290
+ model_profile_id: str = ""
1291
+ max_context_tokens: int = 0
1292
+ tool_names: list[str] = field(default_factory=list)
1293
+ skill_names: list[str] = field(default_factory=list)
1294
+ sub_agent_tool_names: list[str] = field(default_factory=list)
1295
+ memory_files: list[str] = field(default_factory=list)
1296
+ runtime_details: AgentRuntimeDetails = field(default_factory=AgentRuntimeDetails)
1297
+
1298
+
1299
+ @dataclass
1300
+ class ModelProfileSwitched(Event):
1301
+ """A model profile switch has completed for this session (backend → frontend)."""
1302
+
1303
+ model_profile_id: str = ""
1304
+ max_context_tokens: int = 0
1305
+ runtime_details: AgentRuntimeDetails = field(default_factory=AgentRuntimeDetails)
1306
+
1307
+
1308
+ @dataclass
1309
+ class WorkspaceUpdated(Event):
1310
+ """Session workspace has been updated mid-session (backend → frontend)."""
1311
+
1312
+ primary_cwd: str = ""
1313
+ working_dirs: list[str] = field(default_factory=list)
1314
+ reference_files: list[str] = field(default_factory=list)
1315
+
1316
+
1317
+ @dataclass
1318
+ class SettingsReloaded(Event):
1319
+ """A settings reload (env + registries) has completed (backend → frontend).
1320
+
1321
+ Echoed once the agent has been rebuilt so a caller awaiting the reload can
1322
+ distinguish success from an ``AgentLoadFailed`` rebuild failure.
1323
+ """
1324
+
1325
+ runtime_details: AgentRuntimeDetails = field(default_factory=AgentRuntimeDetails)
1326
+
1327
+
1328
+ # ---------------------------------------------------------------------------
1329
+ # Workflow mode
1330
+ # ---------------------------------------------------------------------------
1331
+ #
1332
+ # Lifecycle events (``WorkflowRunStarted`` … ``WorkflowRunFinished``) carry
1333
+ # ``seq``, the run store's record sequence: they are published only after the
1334
+ # record is written, in sequence order, so a live consumer applies exactly what
1335
+ # a replay of ``events.jsonl`` would. The one exception is the
1336
+ # ``outcome="storage_failed"`` terminal, which is out of band (``seq=None``) and
1337
+ # reports how far the written prefix reaches (``last_written_seq``). Node events
1338
+ # carry the activation identity ``run_id + node_id + activation_id + attempt``;
1339
+ # ``attempt=0`` is the sentinel for pending/skipped states and run notices.
1340
+ # ``WorkflowRunAccepted`` / ``WorkflowRunRejected`` are control-plane replies
1341
+ # to a ``WorkflowRunRequest``: never stored, no ``seq``, exactly one per
1342
+ # ``request_id``.
1343
+
1344
+ WORKFLOW_NOTICE_DATA_DROPPED = "data_dropped_at_agent_boundary"
1345
+ WORKFLOW_OUTPUT_EMIT = "emit"
1346
+ """``WorkflowNodeOutput.kind`` of a process fragment published by ``ctx.emit``."""
1347
+ WORKFLOW_OUTPUT_FINAL = "final"
1348
+ """``WorkflowNodeOutput.kind`` of an activation's final value."""
1349
+
1350
+
1351
+ @dataclass
1352
+ class WorkflowPreviewProgress(Event):
1353
+ """Progress of an explicit preview load, correlated to its requesting view."""
1354
+
1355
+ request_id: str = ""
1356
+ workflow_id: str = ""
1357
+ stage: Literal["definition", "environment", "graph", "ready"] = "definition"
1358
+ title: str = ""
1359
+ node_count: int = 0
1360
+
1361
+
1362
+ @dataclass(kw_only=True)
1363
+ class WorkflowRunRequest(Event):
1364
+ """User asks to run a discovered workflow (frontend → backend).
1365
+
1366
+ ``target`` fixes the workflow and workspace before admission. A draft creates
1367
+ a session; a selection restores its durable session and verifies the binding.
1368
+ ``timeout`` above zero is the run-level deadline in seconds: when it passes the run
1369
+ is cancelled with ``reason="deadline_exceeded"``.
1370
+ """
1371
+
1372
+ target: WorkflowTarget
1373
+ session_id: str | None = field(default=None, init=False)
1374
+ pins: WorkflowPins | None = None
1375
+ input_text: str = ""
1376
+ request_id: str = ""
1377
+ timeout: float = 0.0
1378
+
1379
+ def __post_init__(self) -> None:
1380
+ self.session_id = self.target.session_id if isinstance(self.target, WorkflowSessionSelection) else None
1381
+
1382
+
1383
+ @dataclass(kw_only=True)
1384
+ class WorkflowModelChangeRequest(Event):
1385
+ """Change one idle Workflow session's default model without changing global or Chat settings."""
1386
+
1387
+ session_id: str
1388
+ profile_id: str
1389
+ request_id: str
1390
+
1391
+
1392
+ @dataclass(kw_only=True)
1393
+ class WorkflowModelChangeResult(Event):
1394
+ """Acknowledge a model change only after the session checkpoint has been saved."""
1395
+
1396
+ request_id: str
1397
+ selection: WorkflowSessionSelection | None = None
1398
+ error: str = ""
1399
+
1400
+
1401
+ @dataclass(kw_only=True)
1402
+ class WorkflowRollbackRequest(Event):
1403
+ """Preview, or apply a confirmed file-only rollback before a stable Run ID.
1404
+
1405
+ An empty token previews. Commit repeats the returned token; the owner checks
1406
+ the ledger and the current safe file plan again under the session lock.
1407
+ Run records are never deleted or converted into retryable executions.
1408
+ """
1409
+
1410
+ session_id: str
1411
+ run_id: str
1412
+ request_id: str
1413
+ token: str = ""
1414
+
1415
+
1416
+ @dataclass(kw_only=True)
1417
+ class WorkflowRollbackResult(Event):
1418
+ request_id: str
1419
+ run_id: str
1420
+ token: str = ""
1421
+ paths: tuple[str, ...] = ()
1422
+ exclusions: tuple[tuple[str, str], ...] = ()
1423
+ warnings: tuple[str, ...] = ()
1424
+ applied: bool = False
1425
+ changed: int = 0
1426
+ error: str = ""
1427
+
1428
+
1429
+ @dataclass
1430
+ class WorkflowCancelRequest(Event):
1431
+ """User cancels the running workflow (frontend → backend)."""
1432
+
1433
+ run_id: str = ""
1434
+
1435
+
1436
+ @dataclass
1437
+ class WorkflowNodeAnswer(Event):
1438
+ """User answers a node's ``ctx.ask`` (frontend → backend): one answer per question, in order."""
1439
+
1440
+ run_id: str = ""
1441
+ node_id: str = ""
1442
+ activation_id: str = ""
1443
+ request_id: str = ""
1444
+ answers: tuple[AskUserAnswer, ...] = ()
1445
+
1446
+
1447
+ @dataclass
1448
+ class WorkflowNodeRetryRequest(Event):
1449
+ """User retries an activation that is awaiting retry (frontend → backend).
1450
+
1451
+ ``request_id`` and ``expected_failed_attempt`` make the request idempotent:
1452
+ a second delivery, or a replay after a later failure, starts no attempt.
1453
+ """
1454
+
1455
+ run_id: str = ""
1456
+ node_id: str = ""
1457
+ activation_id: str = ""
1458
+ request_id: str = ""
1459
+ expected_failed_attempt: int = 0
1460
+
1461
+
1462
+ @dataclass(kw_only=True)
1463
+ class WorkflowRunAccepted(Event):
1464
+ """The run request was admitted and bound to ``run_id`` (backend → frontend)."""
1465
+
1466
+ request_id: str = ""
1467
+ run_id: str = ""
1468
+ selection: WorkflowSessionSelection
1469
+ session_id: str | None = field(default=None, init=False)
1470
+
1471
+ def __post_init__(self) -> None:
1472
+ self.session_id = self.selection.session_id
1473
+
1474
+
1475
+ @dataclass
1476
+ class WorkflowRunRejected(Event):
1477
+ """The run request was refused deterministically (backend → frontend).
1478
+
1479
+ ``error`` is the structured reason code; ``message`` is for display.
1480
+ """
1481
+
1482
+ request_id: str = ""
1483
+ error: str = ""
1484
+ message: str = ""
1485
+
1486
+
1487
+ @dataclass
1488
+ class WorkflowRunStarted(Event):
1489
+ """A run began; carries the manifest and the per-agent-node resolution snapshot."""
1490
+
1491
+ seq: int = 0
1492
+ input_text: str = ""
1493
+ run_id: str = ""
1494
+ workflow_id: str = ""
1495
+ source_kind: str = ""
1496
+ canonical_path: str = ""
1497
+ title: str = ""
1498
+ spec_digest: str = ""
1499
+ manifest: dict[str, Any] = field(default_factory=dict)
1500
+ resolved_nodes: list[dict[str, Any]] = field(default_factory=list)
1501
+ model: WorkflowModelSelection | None = None
1502
+
1503
+
1504
+ @dataclass
1505
+ class WorkflowNodeStateChanged(Event):
1506
+ """An activation changed state.
1507
+
1508
+ ``invocation_id`` binds an agent activation to its ``Invocation*`` events
1509
+ ahead of time: the runner allocates the origin before publishing ``running``.
1510
+ """
1511
+
1512
+ seq: int = 0
1513
+ run_id: str = ""
1514
+ node_id: str = ""
1515
+ activation_id: str = ""
1516
+ attempt: int = 0
1517
+ state: str = ""
1518
+ iteration: int = 0
1519
+ failure_phase: str = ""
1520
+ invocation_id: str = ""
1521
+ error: str = ""
1522
+ error_class: str = ""
1523
+
1524
+
1525
+ @dataclass
1526
+ class WorkflowNodeOutput(Event):
1527
+ """A process fragment (``kind="emit"``) or the activation's final value (``kind="final"``).
1528
+
1529
+ ``ordinal`` is scoped to ``(activation_id, attempt)`` and restarts at 1 per
1530
+ attempt. ``summary_text`` is a bounded display summary; the full value is
1531
+ in the run store.
1532
+ """
1533
+
1534
+ seq: int = 0
1535
+ run_id: str = ""
1536
+ node_id: str = ""
1537
+ activation_id: str = ""
1538
+ attempt: int = 0
1539
+ kind: str = ""
1540
+ ordinal: int = 0
1541
+ summary_text: str = ""
1542
+
1543
+
1544
+ @dataclass
1545
+ class WorkflowNodeAskUser(Event):
1546
+ """A python node is waiting on ``ctx.ask``; answer with ``WorkflowNodeAnswer``.
1547
+
1548
+ Live events carry the full questions; a replayed one carries the stored
1549
+ summary as a single open question.
1550
+ """
1551
+
1552
+ seq: int = 0
1553
+ run_id: str = ""
1554
+ node_id: str = ""
1555
+ activation_id: str = ""
1556
+ attempt: int = 0
1557
+ request_id: str = ""
1558
+ questions: tuple[AskUserQuestion, ...] = ()
1559
+
1560
+
1561
+ @dataclass
1562
+ class WorkflowNodeAnswered(Event):
1563
+ """An accepted answer, journaled before the waiting attempt resumes; ``answer`` is its summary."""
1564
+
1565
+ seq: int = 0
1566
+ run_id: str = ""
1567
+ node_id: str = ""
1568
+ activation_id: str = ""
1569
+ attempt: int = 0
1570
+ request_id: str = ""
1571
+ answer: str = ""
1572
+
1573
+
1574
+ @dataclass
1575
+ class WorkflowLoopIteration(Event):
1576
+ """A loop's ``until`` verdict for one iteration (``continue`` / ``exit`` / ``exhausted``)."""
1577
+
1578
+ seq: int = 0
1579
+ run_id: str = ""
1580
+ loop_id: str = ""
1581
+ activation_id: str = ""
1582
+ attempt: int = 0
1583
+ iteration: int = 0
1584
+ verdict: str = ""
1585
+
1586
+
1587
+ @dataclass
1588
+ class WorkflowRunNotice(Event):
1589
+ """A once-per-run advisory; the node identity is the first activation that hit it."""
1590
+
1591
+ seq: int = 0
1592
+ run_id: str = ""
1593
+ node_id: str = ""
1594
+ activation_id: str = ""
1595
+ attempt: int = 0
1596
+ code: str = ""
1597
+ message: str = ""
1598
+
1599
+
1600
+ @dataclass
1601
+ class WorkflowOutputSummary:
1602
+ """One declared output of a finished run; the full value is in the run store."""
1603
+
1604
+ node_id: str = ""
1605
+ activation_id: str = ""
1606
+ summary_text: str = ""
1607
+ attempt: int = 0
1608
+
1609
+
1610
+ @dataclass
1611
+ class WorkflowRunFinished(Event):
1612
+ """The run reached a terminal outcome.
1613
+
1614
+ ``outputs`` follows the workflow's ``output()`` declaration order and omits
1615
+ skipped outputs. ``node_id``/``error`` name the failing activation for
1616
+ ``node_failed``/``loop_exhausted``. ``reason`` refines the outcome
1617
+ (``deadline_exceeded`` for a run-level timeout cancellation).
1618
+ """
1619
+
1620
+ seq: int | None = None
1621
+ run_id: str = ""
1622
+ outcome: str = ""
1623
+ outputs: list[WorkflowOutputSummary] = field(default_factory=list)
1624
+ duration: float = 0.0 # seconds
1625
+ node_id: str = ""
1626
+ error: str = ""
1627
+ reason: str = ""
1628
+ last_written_seq: int = 0
1629
+ degraded: bool = False