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,664 @@
1
+ # 创建和运行工作流
2
+
3
+ 工作流(workflow)将任务拆分为多个节点,并通过边定义执行顺序和数据流向。Python 节点用于确定性处理,智能体节点用于需要模型理解和生成的任务;分支、汇合和循环用于组织更复杂的执行流程。
4
+
5
+ 本教程首先通过内置示例介绍工作流的终端用户界面(Terminal User Interface,TUI)和基本操作,再通过六个可独立运行的 Python 示例介绍如何编写工作流。完整参数说明和运行规则见[工作流参考](../../reference/workflows.md)。
6
+
7
+ ## 在 TUI 中运行内置工作流
8
+
9
+ 先[配置可用模型](../../start/getting-started.md#3-配置模型),并准备一个本地项目目录。接下来运行的内置示例会让智能体读取该目录中的文件,生成项目介绍,并产生模型调用费用。
10
+
11
+ ### 选择工作流
12
+
13
+ 在终端中进入所选项目目录,运行 `icode` 打开 TUI。在输入框输入 `/workflow`,打开工作流选择器,选择来源为内置的 `demo-workflow`。
14
+
15
+ 也可以点击左上角的“应用模式:聊天”,选择“工作流”切换模式,然后再点击“新建会话”并选择工作流。
16
+
17
+ ### 了解工作流界面
18
+
19
+ 选择示例后,可以通过以下页签了解工作流:
20
+
21
+ - **工作流**:展示执行图,包括节点、连接关系和执行状态。执行图超出面板时,可以按住鼠标拖动来移动视图。运行后,点击图中的节点可以查看该节点的输入、输出,下方的子页签可切换“Markdown”(默认)、“纯文本”(未经排版的原文)、“数据”(结构化数据按字段展示)和“进度消息”(节点运行时报告的进度),只显示有内容的页签;智能体节点还提供“对话记录”,用于查看模型回复和工具调用。
22
+ - **信息**:展示工作流名称、描述、脚本位置、执行环境和节点配置,包括智能体及模型。
23
+ - **源代码**:工作流通过 Python 代码定义,此处显示对应的源代码。“工作流”和“源代码”页均为只读;如需修改工作流,需要编辑对应的 Python 源代码文件。
24
+ - **输入**:启动后按 Markdown 格式展示本次运行提交的输入内容。点击“复制”可复制提交时的原始内容。
25
+ - **输出**:随运行更新节点状态和进度日志,并展示最终输出。
26
+
27
+ ### 运行并观察工作流
28
+
29
+ 工作流中的智能体沿用聊天模式的工具审批方式。运行前可通过右上角的“审批模式:…”调整审批模式,运行中按提示处理审批请求。
30
+
31
+ 1. 在“工作流”页点击“▶ 开始”,打开“启动工作流”对话框。在其中的“运行设置”区域确认工作目录和默认模型。
32
+ 2. 按需填写希望了解的项目内容,例如 `介绍这个项目的入口和主要模块,用中文回答`;也可以留空,使用示例的默认任务。点击对话框中的“▶ 开始”启动。
33
+
34
+ 启动后,示例会询问阅读深度。可以选择 `deep`,体验多个智能体并行分析;希望减少调用量时可选择 `quick`,由一个智能体快速阅读。
35
+
36
+ 运行期间,可以观察执行图中哪些节点正在运行、已经完成或被跳过。如需停止工作流,点击“■ 取消”并确认。
37
+
38
+ 如果节点因错误进入“等待重试”状态,点击该节点查看错误详情,排查后点击“重试”;也可以关闭节点详情并取消整个运行。手动重试只适用于当前运行中等待重试的节点,不能用来重跑已完成节点或恢复已结束的运行。重试可能重复执行文件写入或外部请求,已发生的修改不会自动撤销。
39
+
40
+ 生成项目介绍后,示例会把草稿放在问题中,请求审阅。回答 `ok` 接受,或填写具体修改意见。示例最多进行两轮撰写,最终输出项目介绍;`deep` 路径还会输出后续阅读建议。
41
+
42
+ 运行结束并产生结果后,点击“■ 取消”右侧的“结果”查看最终输出。工作流有多个输出时,每个输出单独一个页签,页签名为对应的输出节点名称。“输出”页仍保留完整记录,包括节点状态和进度日志。再次点击“▶ 开始”,可填写新的输入并重新运行。
43
+
44
+ 同一工作流会话可以保存多次运行。在“工作流”“信息”等页签上方,点击“运行 1”“运行 2”等运行页签,可切换查看各次记录。退出并重新打开 iCode 后,先通过左上角的应用模式选择器切换到“工作流”。按 `F1` 或点击界面底部的 `f1 会话`,在会话列表中选择工作流会话,可查看历史输入、输出和节点记录。
45
+
46
+ ## 创建第一个工作流
47
+
48
+ 接下来介绍如何编写自己的工作流。先在项目目录下创建 `.chrys/workflows/` 目录(如果尚不存在),后续工作流文件都保存在这个目录下。
49
+
50
+ 新建 `.chrys/workflows/greeting.py`:
51
+
52
+ ```python
53
+ from chrys.workflows import WorkflowBuilder, WorkflowValue
54
+
55
+ wf = WorkflowBuilder(
56
+ "greeting",
57
+ description="Greet the person named in the input."
58
+ )
59
+
60
+
61
+ def greet(value: WorkflowValue) -> str:
62
+ text = value.text
63
+ name = text.strip() or "friend"
64
+ return f"Hello, {name}!"
65
+
66
+
67
+ hello = wf.python("hello", greet)
68
+ wf.start(hello)
69
+ wf.output(hello)
70
+ workflow = wf.build()
71
+ ```
72
+
73
+ `WorkflowBuilder` 的第一个参数设置工作流标题,可选参数 `description` 描述其用途。标题和描述用于展示工作流信息,不会作为节点输入或智能体指令。
74
+
75
+ 节点是工作流中的执行步骤。`greet()` 定义本例的处理逻辑:接收 `WorkflowValue`,通过 `value.text` 读取输入,返回问候语。`wf.python("hello", greet)` 将该函数注册为名为 `hello` 的 Python 节点。注册时传入函数本身,不加调用括号。
76
+
77
+ `wf.start(hello)` 指定起点节点,`wf.output(hello)` 指定工作流的输出节点。本例中,`hello` 同时作为起点和输出节点,执行路径如下:
78
+
79
+ ```text
80
+ 输入 → hello 节点 → 工作流输出
81
+ ```
82
+
83
+ 最后,`wf.build()` 检查并生成工作流。**文件必须将生成的对象赋给模块顶层的 `workflow` 变量,供 iCode 加载。**
84
+
85
+ 保存文件后无需重启 iCode。点击“新建会话”,打开工作流选择器,选择 `greeting`。
86
+
87
+ 自定义文件首次加载或发生变化时,TUI 会要求检查源码并确认信任:工作流是可执行 Python,加载时就可能执行文件顶层代码。
88
+
89
+ 确认信任后,点击“▶ 开始”,输入 `Alex` 后运行,最终应得到 `Hello, Alex!`;不填输入则得到 `Hello, friend!`。
90
+
91
+ ## 使用其他 Python 环境
92
+
93
+ 默认使用运行 iCode 的 Python 解释器。工作流需要第三方库时,可以通过文件内的脚本元数据指定自备 Python 解释器或虚拟环境;依赖需自行安装,iCode 不会自动安装。配置方式见[工作流参考:执行环境](../../reference/workflows.md#执行环境)。本教程的 Python 示例仅使用标准库,无需额外准备环境。
94
+
95
+ ## 传递数据与询问用户
96
+
97
+ ### 在两个节点之间传递数据
98
+
99
+ 新建 `.chrys/workflows/fruit_list.py`:
100
+
101
+ ```python
102
+ from chrys.workflows import NodeContext, WorkflowBuilder, WorkflowValue
103
+
104
+ wf = WorkflowBuilder("Fruit list")
105
+
106
+
107
+ def parse_items(value: WorkflowValue) -> WorkflowValue:
108
+ text = value.text
109
+ items = [item.strip() for item in text.split(",") if item.strip()]
110
+ return WorkflowValue(text=", ".join(items), data={"items": items})
111
+
112
+
113
+ def describe(value: WorkflowValue, ctx: NodeContext) -> str:
114
+ items = value.data["items"]
115
+ ctx.emit(f"Received {len(items)} items; preparing the list")
116
+ return f"{len(items)} items: {value.text}"
117
+
118
+
119
+ parse = wf.python("parse", parse_items)
120
+ report = wf.python("report", describe)
121
+ wf.start(parse)
122
+ wf.chain(parse, report)
123
+ wf.output(report)
124
+ workflow = wf.build()
125
+ ```
126
+
127
+ 本例中,`parse` 节点将输入整理为水果列表,`report` 节点根据列表生成说明。工作流的执行路径如下:
128
+
129
+ ```text
130
+ 输入 → parse 节点 → report 节点 → 工作流输出
131
+ ```
132
+
133
+ `wf.chain(parse, report)` 连接两个节点,将 `parse` 的返回值作为 `report` 的输入。`chain()` 是连续调用 `edge()` 的简写:连接这两个节点时,等价于 `wf.edge(parse, report)`;连接更多节点时,`wf.chain(a, b, c)` 等价于依次调用 `wf.edge(a, b)` 和 `wf.edge(b, c)`。
134
+
135
+ 节点之间通过 `WorkflowValue` 传递数据。它的 `text` 字段存放文本,`data` 字段可选,存放可用 JSON 表示的结构化数据,默认为 `None`。本例中,`parse_items()` 用 `text` 保存逗号分隔的水果名称,用 `data` 保存包含水果列表的字典;`describe()` 通过 `value.data["items"]` 读取列表,计算水果数量。
136
+
137
+ 节点通过 `return` 返回处理结果,返回值决定向下游传递的内容:
138
+
139
+ - 返回字符串时,iCode 将字符串放入 `WorkflowValue.text`,并将 `data` 设为 `None`。本例中的 `describe()` 只需要输出说明,因此返回字符串。
140
+ - 返回 `WorkflowValue` 时,可以同时传递文本和结构化数据,如本例中的 `parse_items()`。
141
+
142
+ Python 节点函数可以接收一个或两个参数:`parse_items(value)` 接收 `WorkflowValue`;`describe(value, ctx)` 除了接收 `WorkflowValue`,还通过第二个参数接收执行上下文 `NodeContext`。`NodeContext` 提供与当前节点执行相关的操作。本例通过 `ctx.emit()` 向 TUI 报告当前节点的进度。
143
+
144
+ 在 TUI 选择 `fruit_list`,输入 `apple, banana, pear` 并运行。运行完成后,在“输出”页查看工作流的最终输出,结果显示在输出节点名称下方:
145
+
146
+ ```text
147
+ report
148
+ 3 items: apple, banana, pear
149
+ ```
150
+
151
+ ### 在执行中等待用户回答
152
+
153
+ 除了接收上游节点的数据,节点还可以在执行过程中向用户提问,并根据回答继续处理。
154
+
155
+ 分别替换 `describe()` 函数和 `report = ...` 注册语句,保留中间的 `parse = ...` 及其他代码:
156
+
157
+ ```python
158
+ async def describe(value: WorkflowValue, ctx: NodeContext) -> str:
159
+ title = await ctx.ask("请为这份水果清单起一个标题。")
160
+ items = value.data["items"]
161
+ return f"{title}: {len(items)} items: {value.text}"
162
+
163
+
164
+ # 等待用户回答时不设置节点截止时间。
165
+ report = wf.python("report", describe, timeout=None)
166
+ ```
167
+
168
+ 保存修改后,在 TUI 中重新打开该工作流,预览更新后的源码并确认信任,然后启动。运行输入仍填 `apple, banana, pear`。问答窗口出现时输入 `Shopping List`,最终输出应为 `Shopping List: 3 items: apple, banana, pear`。
169
+
170
+ `ctx.ask()` 向用户提问,等待回答后返回字符串。调用时需要使用 `await`,因此节点函数应使用 `async def` 定义。包含用户问答的工作流需在 TUI 中运行,不支持通过无人值守的 CLI 运行。
171
+
172
+ 问题还可以提供选项,一个对话框也可以同时提出多个问题。此时传入 `Question` 对象而不是字符串。先在文件顶部的 `from chrys.workflows import ...` 一行中加入 `Question`,再次替换 `describe()`:
173
+
174
+ ```python
175
+ async def describe(value: WorkflowValue, ctx: NodeContext) -> str:
176
+ title, extras = await ctx.ask(
177
+ [
178
+ Question("请为这份水果清单起一个标题。", header="标题"),
179
+ Question("清单上还要加什么?", header="追加", options=["milk", "bread", "eggs"], multi_select=True),
180
+ ]
181
+ )
182
+ items = value.data["items"] + list(extras.selected)
183
+ return f"{title.text}: {len(items)} items: {', '.join(items)}"
184
+ ```
185
+
186
+ 传入问题列表时,按顺序为每个问题返回一个 `Answer`:`selected` 是用户选中的选项标签,`text` 是用户输入的内容。使用相同的输入运行。对话框为每个问题显示一个标签页:在“标题”页输入 `Shopping List` 并点击“回答并继续”,在“追加”页勾选 `milk` 和 `eggs` 并点击“回答并检查”,最后点击“提交回答”。输出应为 `Shopping List: 5 items: apple, banana, pear, milk, eggs`。
187
+
188
+ 单选问题、回答包含的内容以及如何把选择结果传给下游,请参阅[工作流参考:`NodeContext.ask`](../../reference/workflows.md#nodecontextask)。
189
+
190
+ ## 定义智能体节点
191
+
192
+ ### 使用 iCode 智能体
193
+
194
+ 新建 `.chrys/workflows/learning_plan.py`:
195
+
196
+ ```python
197
+ from chrys.workflows import WorkflowBuilder, WorkflowValue
198
+
199
+ wf = WorkflowBuilder("Learning plan")
200
+
201
+
202
+ def make_prompt(value: WorkflowValue) -> str:
203
+ text = value.text
204
+ topic = text.strip() or "Python basics"
205
+ return (
206
+ f"Create a three-step learning plan for a beginner studying {topic}. "
207
+ "Use one sentence per step. Answer in English using only this input. Do not call tools."
208
+ )
209
+
210
+
211
+ prepare = wf.python("prepare", make_prompt)
212
+ plan = wf.agent("plan", profile="QA")
213
+ wf.start(prepare)
214
+ wf.chain(prepare, plan)
215
+ wf.output(plan)
216
+ workflow = wf.build()
217
+ ```
218
+
219
+ 本例中,`prepare` 节点组织提示词,`plan` 节点调用 QA 智能体生成学习计划。工作流的执行路径如下:
220
+
221
+ ```text
222
+ 输入 → prepare(Python)→ plan(智能体)→ 工作流输出
223
+ ```
224
+
225
+ `wf.agent()` 用于定义智能体节点。在 `wf.agent("plan", profile="QA")` 中,`"plan"` 是节点名称,`profile="QA"` 选择智能体配置。使用以下命令查看可用配置:
226
+
227
+ ```shell
228
+ icode agents
229
+ icode models
230
+ ```
231
+
232
+ `profile` 填写 `icode agents` 输出中的 `Name`,可选参数 `model` 填写 `icode models` 输出中的 `Name`。需要为该节点指定模型时,替换注册语句,并将 `My model` 换成实际的模型配置名称:
233
+
234
+ ```python
235
+ plan = wf.agent("plan", profile="QA", model="My model")
236
+ ```
237
+
238
+ `model` 为该节点指定模型,优先于智能体绑定的模型配置。省略时,优先使用智能体绑定的模型配置,否则使用工作流默认模型。
239
+
240
+ 智能体节点只读取上游节点传递的 `WorkflowValue.text` 作为用户消息,不会读取 `data`。如果模型需要使用 `data` 中的信息,应在上游 Python 节点中将相关内容整理到 `text` 中。智能体生成的回答保存在返回的 `WorkflowValue.text` 中,传给下游节点。
241
+
242
+ 在 TUI 中新建会话,选择 `learning_plan` 工作流,输入 `Python file handling` 并运行。可打开 `plan` 节点的“对话记录”查看生成过程。运行完成后,“输出”页会显示一份三步学习计划,具体措辞由模型决定。
243
+
244
+ #### 补充节点指令
245
+
246
+ 需要为节点补充固定职责或输出要求时,可以使用 `instructions_suffix`。例如,替换 `plan` 的注册语句,让学习计划适合没有编程经验的读者:
247
+
248
+ ```python
249
+ plan = wf.agent(
250
+ "plan",
251
+ profile="QA",
252
+ instructions_suffix="Assume the learner has no programming experience. Explain unfamiliar terms briefly.",
253
+ )
254
+ ```
255
+
256
+ 对普通 iCode 智能体,`instructions_suffix` 追加在配置原有的 `instructions` 后,作为系统提示词的一部分;上游传入的 `text` 仍作为用户消息。
257
+
258
+ ### 使用 ACP 智能体
259
+
260
+ 已经[配置外部智能体客户端协议(Agent Client Protocol,ACP)智能体](../extensions/external-acp-agents.md#创建配置并测试连接)时,可用其配置名称替换 `QA`:
261
+
262
+ ```python
263
+ plan = wf.agent("plan", profile="My ACP agent")
264
+ ```
265
+
266
+ 将 `My ACP agent` 替换为 `icode agents` 中已有的 ACP 配置名称,并确保该配置指定的外部程序可以启动。
267
+
268
+ ACP 节点默认使用外部智能体配置中的模型,不使用工作流默认模型。
269
+
270
+ ACP 节点也可以设置 `instructions_suffix`,但它会追加到发送给远端的用户提示末尾,不修改远端智能体的系统提示词。
271
+
272
+ ## 设置超时与重试
273
+
274
+ Python 节点和智能体节点都可以设置超时和重试:`timeout` 限制节点每次执行的时间,`retry` 设置包含首次执行在内的最多尝试次数及重试间隔。
275
+
276
+ | 节点 | 默认单次超时 | 默认最多尝试次数(含首次) |
277
+ | --- | --- | --- |
278
+ | Python | 300 秒 | 1 次,不自动重试 |
279
+ | 智能体 | 不限制 | 3 次 |
280
+
281
+ 例如,为前面的学习计划节点设置超时和重试。在 `learning_plan.py` 顶部补充 `Retry` 导入,并替换 `plan` 的注册语句:
282
+
283
+ ```python
284
+ from chrys.workflows import Retry
285
+
286
+ plan = wf.agent(
287
+ "plan",
288
+ profile="QA",
289
+ timeout=120,
290
+ retry=Retry(max_attempts=3, backoff=2),
291
+ )
292
+ ```
293
+
294
+ 这里每次执行最多 120 秒,包含首次执行在内最多尝试三次,重试间隔为两秒。Python 节点也可以在 `wf.python(...)` 中使用相同的 `timeout` 和 `retry` 参数。
295
+
296
+ 设置 `timeout=None` 表示不限制执行时间。等待人工回答或工具审批也会计时,因此前面的问答示例使用了 `timeout=None`。
297
+
298
+ 重试可能重复调用模型、写入文件,或重复外部 ACP 智能体的工具调用。非 ACP 智能体的尝试失败或超时后,重试会接着已有的对话继续执行,已完成的工具调用不会再次执行。已经发生的操作不会自动撤销。并非所有错误都会自动重试,具体规则见[工作流参考:超时与重试](../../reference/workflows.md#超时与重试)。
299
+
300
+ ## 定义条件分支
301
+
302
+ ### 使用 switch() 选择一条分支
303
+
304
+ 新建 `.chrys/workflows/route_text.py`:
305
+
306
+ ```python
307
+ from chrys.workflows import WorkflowBuilder, WorkflowValue
308
+
309
+ wf = WorkflowBuilder("Route by length")
310
+
311
+
312
+ def normalize(value: WorkflowValue) -> str:
313
+ text = value.text
314
+ return text.strip()
315
+
316
+
317
+ def is_short(value: WorkflowValue) -> bool:
318
+ return len(value.text) <= 10
319
+
320
+
321
+ def is_medium(value: WorkflowValue) -> bool:
322
+ return len(value.text) <= 20
323
+
324
+
325
+ def short_reply(value: WorkflowValue) -> str:
326
+ text = value.text
327
+ return f"Short text: {text}"
328
+
329
+
330
+ def medium_reply(value: WorkflowValue) -> str:
331
+ text = value.text
332
+ return f"Medium text: {text}"
333
+
334
+
335
+ def long_reply(value: WorkflowValue) -> str:
336
+ text = value.text
337
+ return f"Long text: {len(text)} characters"
338
+
339
+
340
+ check = wf.python("check", normalize)
341
+ short = wf.python("short", short_reply)
342
+ medium = wf.python("medium", medium_reply)
343
+ long = wf.python("long", long_reply)
344
+ wf.start(check)
345
+ wf.switch(
346
+ check,
347
+ cases=[(is_short, short), (is_medium, medium)],
348
+ default=long,
349
+ )
350
+ wf.output(short)
351
+ wf.output(medium)
352
+ wf.output(long)
353
+ workflow = wf.build()
354
+ ```
355
+
356
+ 本例中,`check` 节点先去除输入两端的空白,再根据文本长度选择分支。工作流的执行路径如下:
357
+
358
+ ```text
359
+ ┌─ 长度 ≤ 10 → short → 输出
360
+ 输入 → check ──┼─ 10 < 长度 ≤ 20 → medium → 输出
361
+ └─ 长度 > 20 → long → 输出
362
+ ```
363
+
364
+ `wf.switch(check, cases=[...], default=long)` 为 `check` 节点的输出选择一条分支。`cases` 中的每一项由条件函数和目标节点组成,例如 `(is_short, short)`。`switch()` 按声明顺序选择第一个条件函数返回 `True` 的目标;均不满足时选择 `default` 指定的节点。
365
+
366
+ 条件函数接收来源节点输出的 `WorkflowValue`,返回布尔值。本例中的 `is_short()` 和 `is_medium()` 通过 `value.text` 判断文本长度,依次检查,均不满足时进入 `long`。长度不超过 10 的文本同时满足两个条件,但只会进入先声明的 `short` 分支。因此,`medium` 分支实际处理长度大于 10 且不超过 20 的文本。
367
+
368
+ 三个分支节点均通过 `wf.output()` 声明为工作流的输出节点。每次运行只选择一条分支,最终结果只包含该分支的输出,跳过的分支不会产生空结果。
369
+
370
+ 在 TUI 中新建会话,选择 `route_text` 工作流。分别使用以下输入运行,观察执行图中选中的路径与跳过的节点,并在“输出”页查看最终输出:
371
+
372
+ | 输入 | 最终输出 |
373
+ | --- | --- |
374
+ | `hello` | `Short text: hello` |
375
+ | `hello workflow` | `Medium text: hello workflow` |
376
+ | `hello workflow tutorial` | `Long text: 23 characters` |
377
+
378
+ ### 使用 edge() 条件边执行多个分支
379
+
380
+ `wf.edge(来源节点, 目标节点, when=条件函数)` 连接两个节点。`when` 指定的条件函数接收来源节点输出的 `WorkflowValue`,返回 `True` 时,将来源节点的输出传递给目标节点;省略 `when` 时无条件传递。
381
+
382
+ 各条条件边独立判断,可以选中多条路径。将本例中的 `wf.switch(...)` 调用替换为:
383
+
384
+ ```python
385
+ wf.edge(check, short, when=is_short)
386
+ wf.edge(check, medium, when=is_medium)
387
+ wf.edge(check, long, when=lambda value: len(value.text) > 20)
388
+ ```
389
+
390
+ 保存修改后,在 TUI 中重新打开该工作流,预览更新后的源码并确认信任,然后输入 `hello` 并运行。输入同时满足 `is_short` 和 `is_medium`,因此两个节点都会执行。“输出”页会分别显示节点名称及其结果:
391
+
392
+ ```text
393
+ short
394
+ Short text: hello
395
+
396
+ medium
397
+ Medium text: hello
398
+ ```
399
+
400
+ ## 并行处理并汇总结果
401
+
402
+ 新建 `.chrys/workflows/text_stats.py`:
403
+
404
+ ```python
405
+ from chrys.workflows import SourceValue, WorkflowBuilder, WorkflowValue
406
+
407
+ wf = WorkflowBuilder("Text statistics")
408
+
409
+
410
+ def normalize(value: WorkflowValue) -> str:
411
+ text = value.text
412
+ return text.strip()
413
+
414
+
415
+ def count_chars(value: WorkflowValue) -> WorkflowValue:
416
+ text = value.text
417
+ return WorkflowValue(text=str(len(text)), data={"chars": len(text)})
418
+
419
+
420
+ def count_words(value: WorkflowValue) -> WorkflowValue:
421
+ text = value.text
422
+ count = len(text.split())
423
+ return WorkflowValue(text=str(count), data={"words": count})
424
+
425
+
426
+ def combine_stats(sources: list[SourceValue]) -> str:
427
+ by_node = {source.node_id: source.value.data for source in sources}
428
+ return f"Characters: {by_node['chars']['chars']}; words: {by_node['words']['words']}"
429
+
430
+
431
+ def format_report(value: WorkflowValue) -> str:
432
+ text = value.text
433
+ return f"Done. {text}"
434
+
435
+
436
+ prepare = wf.python("prepare", normalize)
437
+ chars = wf.python("chars", count_chars)
438
+ words = wf.python("words", count_words)
439
+ report = wf.python("report", format_report)
440
+ wf.start(prepare)
441
+ wf.edge(prepare, chars)
442
+ wf.edge(prepare, words)
443
+ wf.join([chars, words], report, combine=combine_stats)
444
+ wf.output(report)
445
+ workflow = wf.build()
446
+ ```
447
+
448
+ 执行路径如下:
449
+
450
+ ```text
451
+ ┌→ chars ─┐
452
+ 输入 → prepare ───┤ ├→ join:report → report → 输出
453
+ └→ words ─┘
454
+ ```
455
+
456
+ `chars` 和 `words` 都在 `prepare` 完成后具备运行条件,彼此无需等待。`wf.join([chars, words], report, combine=combine_stats)` 建立汇合节点,等待两个分支完成,再调用 `combine` 参数指定的合并函数 `combine_stats()`,将其返回值作为 `report` 节点的输入。
457
+
458
+ 合并函数接收 `SourceValue` 列表,通过 `source.node_id` 识别来源,通过 `source.value` 读取结果。本例按来源名称取出字符数和单词数。
459
+
460
+ 合并函数可以返回字符串或 `WorkflowValue`,需要继续传递结构化数据时使用后者。
461
+
462
+ 在 TUI 中新建会话,选择 `text_stats` 工作流,输入 `hello workflow` 并运行,“输出”页应显示:
463
+
464
+ ```text
465
+ report
466
+ Done. Characters: 14; words: 2
467
+ ```
468
+
469
+ 需要合并多份文本时,可以省略 `combine`,将原来的 `wf.join(...)` 调用替换为:
470
+
471
+ ```python
472
+ wf.join([chars, words], report)
473
+ ```
474
+
475
+ 本例的两个来源都会产生结果,默认合并按 `[chars, words]` 的声明顺序拼接各来源的 `WorkflowValue.text`,不保留 `data`,顺序与分支完成先后无关。如果将汇合用于条件分支,被跳过的来源不会参与合并;只有一个有效来源时,会原样传递其 `WorkflowValue`,包括 `data`。
476
+
477
+ 保存修改后,在 TUI 中重新打开该工作流,预览更新后的源码并确认信任,再输入 `hello workflow` 并运行。“输出”页会显示:
478
+
479
+ ```text
480
+ report
481
+ Done. ## chars
482
+ 14
483
+
484
+ ## words
485
+ 2
486
+ ```
487
+
488
+ 其中,`Done.` 由 `format_report()` 添加。默认合并适合将多份智能体分析交给下游总结,无需自行编写合并函数。
489
+
490
+ ## 循环执行直到满足条件
491
+
492
+ 新建 `.chrys/workflows/count_up.py`:
493
+
494
+ ```python
495
+ from chrys.workflows import (
496
+ BuilderScope,
497
+ NodeContext,
498
+ NodeHandle,
499
+ WorkflowBuilder,
500
+ WorkflowValue,
501
+ )
502
+
503
+ wf = WorkflowBuilder("Count up to three")
504
+
505
+
506
+ def increment(value: WorkflowValue) -> str:
507
+ text = value.text
508
+ return str(int(text) + 1)
509
+
510
+
511
+ def report_value(value: WorkflowValue, ctx: NodeContext) -> WorkflowValue:
512
+ ctx.emit(f"Current value: {value.text}")
513
+ return value
514
+
515
+
516
+ def reached_target(value: WorkflowValue) -> bool:
517
+ return int(value.text) >= 3
518
+
519
+
520
+ def make_body(scope: BuilderScope) -> tuple[NodeHandle, NodeHandle]:
521
+ increment_node = scope.python("increment", increment)
522
+ report_node = scope.python("report", report_value)
523
+ scope.chain(increment_node, report_node)
524
+ return increment_node, report_node
525
+
526
+
527
+ count = wf.loop(
528
+ "count",
529
+ body=make_body,
530
+ until=reached_target,
531
+ max_iterations=5,
532
+ on_exhausted="fail",
533
+ )
534
+ wf.start(count)
535
+ wf.output(count)
536
+ workflow = wf.build()
537
+ ```
538
+
539
+ `wf.loop()` 创建循环节点,本例使用的参数含义如下:
540
+
541
+ | 参数 | 含义 |
542
+ | --- | --- |
543
+ | `"count"` | 循环节点的名称 |
544
+ | `body=make_body` | 构建循环体的函数,声明内部节点及连线,返回入口和出口节点引用 |
545
+ | `until=reached_target` | 结束条件函数,接收本轮出口的 `WorkflowValue`;返回 `True` 时结束循环,返回 `False` 且未达到轮数上限时继续下一轮 |
546
+ | `max_iterations=5` | 最多执行五轮 |
547
+ | `on_exhausted="fail"` | 达到轮数上限仍未满足条件时,`"fail"` 使工作流失败;`"continue"` 则以最后一轮出口的结果作为循环输出,继续执行后续工作流 |
548
+
549
+ `make_body()` 在构建工作流时执行,通过 `scope` 创建并连接循环体内的节点。返回值 `(increment_node, report_node)` 按顺序指定入口和出口:
550
+
551
+ - **入口节点 `increment`**:接收每轮输入,并将数字加一。
552
+ - **出口节点 `report`**:发送进度消息并返回本轮结果,供结束条件判断使用。
553
+
554
+ 本例的循环节点作为工作流起点,因此第一轮入口节点接收工作流输入。每轮出口节点的结果交给 `until` 指定的 `reached_target()` 判断:数字达到 3 时,结果成为循环节点的输出;否则,在未达到轮数上限时传给下一轮入口节点。
555
+
556
+ 在 TUI 中新建会话,选择 `count_up` 工作流,输入 `0` 并运行。三轮结果依次为 `1`、`2`、`3`,最终输出为 `3`。可打开循环体节点,查看不同轮次的输入、输出和进度消息。再输入 `-10` 运行,观察达到五轮上限后工作流失败的结果。
557
+
558
+ ## 把工作流拆成多个文件
559
+
560
+ 工作流变大后,可以把它移进同名文件夹,拆成多个 Python 文件和资源文件。新建 `.chrys/workflows/greeting_kit/`,放入两个文件。入口文件必须与文件夹同名,即 `greeting_kit.py`:
561
+
562
+ ```python
563
+ from pathlib import Path
564
+
565
+ from chrys.workflows import WorkflowBuilder, WorkflowValue
566
+ from phrases import greet
567
+
568
+ wf = WorkflowBuilder("greeting kit")
569
+ TEMPLATE = (Path(__file__).parent / "template.txt").read_text(encoding="utf-8")
570
+
571
+
572
+ def hello(value: WorkflowValue) -> str:
573
+ return greet(TEMPLATE, value.text.strip() or "friend")
574
+
575
+
576
+ node = wf.python("hello", hello)
577
+ wf.start(node)
578
+ wf.output(node)
579
+ workflow = wf.build()
580
+ ```
581
+
582
+ 同一文件夹中的 `phrases.py`:
583
+
584
+ ```python
585
+ def greet(template: str, name: str) -> str:
586
+ return template.format(name=name)
587
+ ```
588
+
589
+ 再在文件夹中放一个 `template.txt`,内容为 `Hello, {name}!`。
590
+
591
+ 在 TUI 中选择 `greeting_kit`,确认信任后输入 `Alex` 运行,结果为 `Hello, Alex!`。
592
+
593
+ - 按模块名导入文件夹中的其他文件,如 `from phrases import greet`。相对导入(如 `from .phrases import greet`)不可用。
594
+ - 资源文件相对 `__file__` 读取。`open("template.txt")` 这类相对路径相对的是工作区,而不是文件夹。
595
+ - 信任确认覆盖文件夹中除以 `.` 开头的名称(如 `.venv`、`.git`)和 Python 在 `__pycache__` 文件夹中保存的编译副本以外的所有文件。修改其中任何文件后,请重新打开工作流进行预览和确认。
596
+ - 在工作流选择器中删除工作流文件夹时,只删除其入口文件,其他文件保留。
597
+
598
+ 完整规则见[工作流参考:工作流文件夹](../../reference/workflows.md#工作流文件夹)。
599
+
600
+ ## 从命令行运行
601
+
602
+ CLI 适合无需人工交互的工作流:不支持 `ctx.ask()` 用户问答,工具审批模式固定为 `bypass`,即跳过工具审批。
603
+
604
+ ### 列举和运行工作流
605
+
606
+ 在项目目录执行以下命令,列举可用的工作流:
607
+
608
+ ```shell
609
+ icode workflow list
610
+ ```
611
+
612
+ 要检查正在编写的工作流,将其文件或文件夹传给 `icode workflow validate`。它会输出 `PASS`,或列出每个问题所在的文件和行,见 [`icode workflow validate`](../../reference/workflows.md#icode-workflow-validate):
613
+
614
+ ```shell
615
+ icode workflow validate .chrys/workflows/greeting.py
616
+ ```
617
+
618
+ 使用列表中的工作流 ID 运行工作流。将以下命令中的 `WORKFLOW_ID` 替换为实际的 ID:
619
+
620
+ ```shell
621
+ icode workflow run WORKFLOW_ID --input "输入文本" --trust
622
+ ```
623
+
624
+ `--input` 设置起点节点收到的 `WorkflowValue.text`,省略时为空字符串。初始输入的 `data` 为 `None`,不能通过 CLI 参数直接设置;即使传入 JSON 字符串,也仍是文本,需要工作流自行解析。
625
+
626
+ 输入跨多行时,bash 和 zsh 可用 `$'...'` 引号,以 `\n` 表示换行;PowerShell 中改在双引号内用 `` `n ``,例如 `` --input "第一行`n第二行" ``。见[多行输入](../../reference/workflows.md#多行输入)。
627
+
628
+ 新建或修改工作流文件后,`--trust` 用于确认信任当前源码及运行环境,与在 TUI 中点击“信任”的作用相同。已确认的内容未变化时可以省略;具体检查范围和加载时的行为见[信任确认](../../reference/workflows.md#信任确认)。
629
+
630
+ 要在 TUI 中查看从命令行启动的运行,打开“工作流会话”窗口并勾选“CLI”。
631
+
632
+ ### 保存文本结果
633
+
634
+ 默认输出各输出节点的 `text`,多份结果之间以空行分隔。最终结果写入 stdout(标准输出)。工作流运行期间,进度写入 stderr(标准错误),包括各节点的状态、智能体节点的操作(工具调用及其间写下的说明),以及 `ctx.emit()` 发送的消息。例如:
635
+
636
+ ```text
637
+ • Starting workflow review…
638
+ Workflow Code review (review) · run 0b337219bb2e · session 890c8ee93562
639
+ ▸ [plan] running
640
+ [plan] → read src/app.py
641
+ [plan] ✓ 0.1s
642
+ ✓ [plan] completed · 4.2s
643
+ ▸ [report] running
644
+ ✓ [report] completed · 2.0s
645
+ ✓ Workflow completed · 6.5s
646
+ ```
647
+
648
+ 在终端中,结果里的控制字符会显示为 `�`。可以通过 `>` 将最终结果原样保存到文件,进度仍显示在终端中:
649
+
650
+ ```shell
651
+ icode workflow run WORKFLOW_ID --input "输入文本" > result.txt
652
+ ```
653
+
654
+ 如只需查看警告、错误和最终结果,可添加 `-q` 或 `--quiet`。
655
+
656
+ ### 获取 JSON 结果
657
+
658
+ 添加 `--json` 后,CLI 不显示节点状态和进度消息,而是在运行结束后向 stdout 输出 JSON 格式的运行结果,包括运行状态、输出节点名称,以及各结果的 `text` 和 `data`:
659
+
660
+ ```shell
661
+ icode workflow run WORKFLOW_ID --input "输入文本" --json
662
+ ```
663
+
664
+ 完整 JSON 字段和退出码见[工作流参考](../../reference/workflows.md#命令行)。