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,1005 @@
1
+ # 工作流参考
2
+
3
+ 本页供工作流作者查询 Python API、数据与调度规则、执行环境、交互和运行记录。
4
+
5
+ ## 工作流文件
6
+
7
+ ### 文件定义与校验
8
+
9
+ 工作流通过 `.py` 文件定义。下面是将输入原样返回的最小完整示例:
10
+
11
+ ```python
12
+ from chrys.workflows import WorkflowBuilder, WorkflowValue
13
+
14
+ wf = WorkflowBuilder("Echo")
15
+
16
+
17
+ def echo(value: WorkflowValue) -> WorkflowValue:
18
+ return value
19
+
20
+
21
+ node = wf.python("echo", echo) # 注册节点
22
+ wf.start(node) # 声明唯一的顶层起点
23
+ wf.output(node) # 至少声明一个输出,可以与起点相同
24
+ workflow = wf.build() # 校验并构建,赋给模块顶层的 workflow 变量
25
+ ```
26
+
27
+ 模块顶层必须定义名为 `workflow` 的变量,其值为 `WorkflowBuilder` 实例调用 `build()` 返回的 `Workflow` 对象,如上例的 `workflow = wf.build()`。构建器变量名 `wf` 可以自定,入口变量名 `workflow` 固定。不要将 `workflow` 赋值放在函数内或 `if __name__ == "__main__":` 中。
28
+
29
+ 语法错误、顶层代码执行异常、构建校验失败或缺少有效的 `workflow` 对象都会阻止加载。`build()` 的结构校验规则见[`WorkflowBuilder.build()`](#workflowbuilderbuild)。
30
+
31
+ 运行前可用 [`icode workflow validate`](#icode-workflow-validate) 检查工作流,它会指出每个问题所在的文件和行。
32
+
33
+ ### 文件发现
34
+
35
+ 工作流可以是单个 `.py` 文件,也可以是工作流文件夹:文件夹中有一个与文件夹名完全相同的入口文件,例如 `code-review/code-review.py`。工作流 ID 是文件名去掉 `.py` 后的部分,或工作流文件夹的名称,与 `WorkflowBuilder` 的标题无关。iCode 在以下位置查找工作流:
36
+
37
+ | 位置 | 来源 |
38
+ | --- | --- |
39
+ | 当前工作目录的 `.chrys/workflows/` | `project` |
40
+ | iCode 配置目录下:Windows 为 `%APPDATA%\chrys\workflows\`;Linux、macOS 为 `~/.chrys/workflows/` | `global` |
41
+ | 随 iCode 提供的内置示例 | `builtin` |
42
+
43
+ 多个工作流 ID 相同时,按以下顺序取第一个能读取的:
44
+
45
+ | 优先级 | 工作流 |
46
+ | --- | --- |
47
+ | 1 | 项目工作流文件夹 |
48
+ | 2 | 项目 `.py` 文件 |
49
+ | 3 | 全局工作流文件夹 |
50
+ | 4 | 全局 `.py` 文件 |
51
+ | 5 | 内置工作流 |
52
+
53
+ 项目工作流只从当前工作目录的 `.chrys/workflows/` 发现,不向父目录查找。各位置只发现直接包含的 `.py` 文件和工作流文件夹,忽略以 `.` 或 `_` 开头的名称。没有同名入口文件的文件夹(如 `data/`、`venv/`)不是工作流,会被忽略;工作流文件夹里的子文件夹也不是工作流。内置工作流只有单文件。全局位置保留文件夹名 `sdk` 给 iCode 自用。
54
+
55
+ 用户工作流文件不能是符号链接,需要通过文件所有权检查,源码大小上限为 4 MiB。以下情况的工作流文件夹会被跳过:文件夹本身或其中任何项是符号链接或 Windows 目录联接;其中有普通文件和文件夹以外的项(如命名管道);文件和文件夹总数超过 1000 个、总大小超过 512 MiB,或嵌套超过 16 层。以 `.` 开头的名称(如 `.venv`、`.git`)和 Python 在 `__pycache__` 文件夹中保存的编译副本(如 `helpers.cpython-312.pyc`)不检查,也不计入上限;其他文件都计入,包括二进制文件和数据文件。无法读取的工作流会被跳过并报告原因,改用下一个同 ID 的工作流。
56
+
57
+ ### 工作流文件夹
58
+
59
+ 把工作流放进文件夹,即可拆成多个文件:
60
+
61
+ ```text
62
+ .chrys/workflows/
63
+ code-review/
64
+ code-review.py # 入口文件:与文件夹同名
65
+ steps.py # 用 `from steps import ...` 导入
66
+ prompts/summary.md # 相对 __file__ 读取
67
+ ```
68
+
69
+ - 文件夹位于 `sys.path` 最前,与单文件所在目录相同:`import steps`、`from steps import check` 以及子文件夹中的模块(`from helpers.git import diff`,有无 `__init__.py` 均可)都能使用。相对导入(如 `from .steps import check`)不可用,因为入口文件不属于包。
70
+ - 其他文件相对 `__file__` 读取,例如 `Path(__file__).parent / "prompts" / "summary.md"`。`open("summary.md")` 这类相对路径相对的是工作区,而不是文件夹。
71
+ - 入口文件和文件夹中的其他文件不要与标准库或已安装的模块同名,例如 `json.py`、`pkgutil.py`。Python 可能加载该模块而不是你的文件,也可能用你的文件顶替该模块;工作流用 `multiprocessing` 启动的进程可能无法启动。
72
+ - 不要在其他文件中按名称导入入口文件:这会把入口文件作为另一个模块再执行一次。
73
+ - iCode 把工作流编译出的 Python 文件存放在配置目录下自己的文件夹中,运行工作流不会在你的文件旁生成 `__pycache__` 文件夹,也不会使用其中已有的你的文件的编译副本。工作流启动的 Python 进程同样如此,除非启动时没有沿用工作流的环境变量,或带有 `-E`、`-I`:这些进程照常使用 `__pycache__` 文件夹,包括确认不检查的编译副本。
74
+
75
+ 把 `review.py` 移到 `review/review.py` 会改变工作流的路径,需要重新确认;为旧文件创建的工作流会话无法再运行它,请新建会话。
76
+
77
+ ### 信任确认
78
+
79
+ 首次加载自定义工作流时,需要确认信任:
80
+
81
+ - **TUI**:选择工作流后会弹出“信任工作流”对话框,检查源码及所声明的执行环境后,点击“信任”继续;点击“取消”则不加载。
82
+ - **CLI**:在 `icode workflow run` 命令中添加 `--trust`。例如,在项目根目录运行 `.chrys/workflows/echo.py`:
83
+
84
+ ```shell
85
+ icode workflow run echo --trust --input "Hello"
86
+ ```
87
+
88
+ 确认会被保存,后续运行可省略 `--trust`。工作流源码、构建出的工作流定义,或所选解释器的路径、版本、平台及 iCode 提供的工作流 SDK 等环境信息发生变化后,需要重新确认。单个 `.py` 文件的源码就是该文件,不检查它导入的其他 Python 文件;工作流文件夹的源码是文件夹中除以 `.` 开头的名称和 Python 在 `__pycache__` 文件夹中保存的编译副本以外的所有文件,新增、修改或删除其中任何文件都需要重新确认。该检查不覆盖已安装依赖包的变化。
89
+
90
+ 文件在预览和启动运行时检查,Python 加载时会重新读取。两者之间发生的修改,以及工作流运行中才读取的文件的修改,无法被发现。修改工作流文件夹中的文件后,请重新打开工作流进行预览和确认。
91
+
92
+ 请在确认信任前检查源码。工作流代码可使用当前用户的权限读写文件或启动程序。确认信任后的预览就会执行模块顶层代码,正式运行时还会重新加载,因此顶层的文件写入、网络请求等操作可能在节点启动前发生,并重复执行。应将业务操作放入节点函数,顶层只保留导入、函数定义和工作流构建。
93
+
94
+ ## Python API
95
+
96
+ `chrys.workflows` 提供以下 API:
97
+
98
+ | 名称 | 用途 |
99
+ | --- | --- |
100
+ | `WorkflowBuilder` | 创建顶层节点、连线、循环、起点和输出 |
101
+ | `BuilderScope` | 在循环体内创建节点和连线 |
102
+ | `NodeHandle` | 节点引用,由构建方法返回,`node_id` 为节点名称 |
103
+ | `Workflow` | `build()` 的结果,赋给顶层 `workflow` 变量 |
104
+ | `WorkflowValue` | 节点之间传递的文本与结构化数据 |
105
+ | `SourceValue` | 汇合函数收到的来源与结果 |
106
+ | `NodeContext` | Python 节点的进度报告与人工问答入口 |
107
+ | `Question` | `NodeContext.ask` 的一个问题,可带单选或多选选项 |
108
+ | `Option` | `Question` 的一个选项 |
109
+ | `Answer` | 用户对一个 `Question` 的回答 |
110
+ | `Retry` | 节点重试次数与间隔 |
111
+
112
+ ### `WorkflowBuilder`
113
+
114
+ 创建顶层工作流:
115
+
116
+ ```python
117
+ WorkflowBuilder(title: str, *, description: str | None = None)
118
+ ```
119
+
120
+ `title` 必须是非空字符串,`description` 是可选说明。两者不作为节点输入或智能体指令。
121
+
122
+ `WorkflowBuilder` 继承 `BuilderScope`,可直接调用其 [`python()`](#builderscopepython)、[`agent()`](#builderscopeagent)、[`edge()`](#builderscopeedge)、[`chain()`](#builderscopechain)、[`switch()`](#builderscopeswitch) 和 [`join()`](#builderscopejoin) 方法。
123
+
124
+ #### `WorkflowBuilder.start`
125
+
126
+ ```python
127
+ start(node: NodeHandle) -> None
128
+ ```
129
+
130
+ 声明唯一的顶层起点,只能调用一次。`node` 必须是当前构建器创建的顶层节点引用。
131
+
132
+ #### `WorkflowBuilder.output`
133
+
134
+ ```python
135
+ output(node: NodeHandle) -> None
136
+ ```
137
+
138
+ 指定收集 `node` 的输出结果,作为工作流的输出。`node` 必须是当前构建器创建的顶层节点引用;可以多次调用以收集不同节点的结果,不能重复声明同一个节点。
139
+
140
+ 将节点声明为输出不会终止后续执行;其下游节点和其他可执行分支仍会继续运行,工作流会等待这些路径结束。结果的收集顺序和跳过行为见[输入调度与输出收集](#输入调度与输出收集)。
141
+
142
+ #### `WorkflowBuilder.build`
143
+
144
+ ```python
145
+ build() -> Workflow
146
+ ```
147
+
148
+ 检查并冻结工作流,返回 `Workflow`,只能成功构建一次。
149
+
150
+ 必须用 `start()` 指定一个顶层起点,并用 `output()` 指定至少一个输出节点。所有顶层节点都必须能从顶层起点沿连线到达;每个循环体内的节点也都必须能从该循环体的入口沿连线到达。
151
+
152
+ 同一来源节点到同一目标节点不能重复连线,节点不能连向自身,也不能直接在循环体内外的节点之间连线。连线不能形成循环,例如 `A → B → A`。需要重复执行一组节点时,应使用 `loop()` 定义循环,而不是把下游节点连回上游节点。
153
+
154
+ #### `WorkflowBuilder.loop`
155
+
156
+ 将一组节点封装为循环,重复执行,直到满足结束条件或达到次数上限。返回的 `NodeHandle` 代表整个循环节点,用于连接顶层的上下游节点。
157
+
158
+ ```python
159
+ loop(name, body, until, max_iterations, on_exhausted="continue") -> NodeHandle
160
+ ```
161
+
162
+ | 参数 | 规则 |
163
+ | --- | --- |
164
+ | `name` | 循环节点名称,在整个工作流内唯一;不能为空,不能以 `join:` 开头或包含 `->` |
165
+ | `body` | 构建循环体的函数,签名为 `(scope: BuilderScope) -> tuple[NodeHandle, NodeHandle]`。`scope` 是构建器传入的循环体作用域,用于创建节点和连线;返回 `(entry, exit)`,分别为循环体的入口和出口节点引用 |
166
+ | `until` | 判断是否结束循环的同步函数,签名为 `(value: WorkflowValue) -> bool`。`value` 是本轮出口节点的输出;返回 `True` 表示结束循环,`False` 表示尚未满足结束条件 |
167
+ | `max_iterations` | 最多执行的轮数,必填,至少为 1 的整数 |
168
+ | `on_exhausted` | 达到次数上限但仍未满足结束条件时的处理方式:`"continue"`(默认)或 `"fail"`,见下文 |
169
+
170
+ `body` 和 `until` 各接收一个位置参数;上述 `scope`、`value` 仅为示意名称,可自行命名。
171
+
172
+ **构建循环体**
173
+
174
+ `body` 在调用 `loop()` 时执行一次。返回的入口和出口必须属于该循环体,也可以是同一节点。
175
+
176
+ `body` 通过收到的 [`BuilderScope`](#builderscope) 实例创建节点和连线。循环体内不能再创建循环。
177
+
178
+ **执行与结束规则**
179
+
180
+ 运行时,每轮执行已构建的循环体:
181
+
182
+ 1. 第一轮将循环节点收到的输入传给 `entry`;后续轮次将上一轮 `exit` 的输出传给 `entry`。
183
+ 2. 等待本轮循环体执行结束,取得 `exit` 的输出。如果本轮没有任何分支向出口传递结果(例如通向出口的唯一连线的 `when` 条件为 `False`),出口节点会被跳过,循环报 `loop_no_value` 错误。
184
+ 3. 将出口值传给 `until`。返回 `True` 时结束循环,以该值作为循环节点的输出;返回 `False` 且尚未达到次数上限时,开始下一轮。
185
+
186
+ `until` 在每轮执行后检查,因此循环至少执行一轮。达到 `max_iterations` 且 `until` 仍返回 `False` 时,由 `on_exhausted` 决定结果:
187
+
188
+ | 值 | 行为 |
189
+ | --- | --- |
190
+ | `"continue"` | 结束循环,将最后一轮的出口值作为循环节点的输出,继续执行下游节点 |
191
+ | `"fail"` | 以 `loop_exhausted` 结束工作流运行 |
192
+
193
+ ### `BuilderScope`
194
+
195
+ `BuilderScope` 提供创建节点和连线的实例方法,`WorkflowBuilder` 继承这些方法。在工作流顶层,通过 `WorkflowBuilder` 实例创建节点和连线;在循环体内,通过 `loop()` 的 `body` 回调接收的 `BuilderScope` 实例创建节点和连线,无需自行构造该实例。
196
+
197
+ **节点命名规则**:名称在整个工作流内必须唯一,不能为空,不能以 `join:` 开头或包含 `->`。
198
+
199
+ #### `BuilderScope.python`
200
+
201
+ 定义一个执行 Python 函数的节点。
202
+
203
+ ```python
204
+ python(name, fn, *, timeout=300.0, retry=None) -> NodeHandle
205
+ ```
206
+
207
+ | 参数 | 含义 |
208
+ | --- | --- |
209
+ | `name` | 节点名称 |
210
+ | `fn` | 节点执行的 Python 函数,签名和返回值要求见下文 |
211
+ | `timeout` | 单次尝试的秒数上限,默认 300;有限正数或 `None`,`None` 表示不设截止时间 |
212
+ | `retry` | 重试配置,传入 [`Retry`](#retry) 实例;省略时仅执行一次 |
213
+
214
+ `fn` 支持同步函数和 `async def` 定义的异步函数。
215
+
216
+ `fn` 接收一个或两个位置参数:第一个参数是节点的输入值,类型为 [`WorkflowValue`](#workflowvalue);第二个参数可省略,类型为 [`NodeContext`](#nodecontext),用于报告进度或询问用户。两种签名示例如下:
217
+
218
+ ```python
219
+ def transform(value: WorkflowValue) -> str:
220
+ return value.text.strip()
221
+
222
+
223
+ def report(value: WorkflowValue, ctx: NodeContext) -> WorkflowValue:
224
+ ctx.emit("Preparing result")
225
+ return value
226
+ ```
227
+
228
+ `fn` 的位置参数不能有默认值。`fn` 也不能声明 `*args`、`**kwargs` 或必填的关键字专用参数。
229
+
230
+ `fn` 必须返回字符串或 `WorkflowValue`。返回字符串时,iCode 将其转换为 `WorkflowValue(text=返回的字符串, data=None)`。
231
+
232
+ Python 节点中的相对文件路径以工作流会话的工作目录为基准。
233
+
234
+ #### `BuilderScope.agent`
235
+
236
+ 定义一个执行智能体任务的节点。
237
+
238
+ ```python
239
+ agent(
240
+ name,
241
+ *,
242
+ profile,
243
+ model=None,
244
+ instructions_suffix=None,
245
+ timeout=None,
246
+ retry=None,
247
+ ) -> NodeHandle
248
+ ```
249
+
250
+ | 参数 | 含义 |
251
+ | --- | --- |
252
+ | `name` | 节点名称 |
253
+ | `profile` | 必填,已有智能体配置的 ID、名称或显示名称;建议使用 ID,通过 `icode agents` 查看 |
254
+ | `model` | 可选,传入 iCode 模型配置的 ID 或名称,可通过 `icode models` 查看;省略时按下文的模型选择规则确定 |
255
+ | `instructions_suffix` | 可选字符串,补充当前节点的指令 |
256
+ | `timeout` | 单次尝试的秒数上限,默认不限制;有限正数或 `None` |
257
+ | `retry` | 省略时最多三次尝试,间隔为零;不是所有错误都会自动重试 |
258
+
259
+ ##### 智能体配置匹配
260
+
261
+ `profile` 按以下顺序匹配:
262
+
263
+ 1. ID。
264
+ 2. 名称精确匹配。
265
+ 3. 显示名称精确匹配。
266
+ 4. 名称忽略大小写匹配。
267
+ 5. 显示名称忽略大小写匹配。
268
+
269
+ 某一步匹配到唯一配置即使用该配置;没有匹配时继续下一步;匹配到多个配置时立即报错。所有步骤均未匹配时,也会报错。
270
+
271
+ ##### 模型选择
272
+
273
+ `model` 按以下顺序匹配 iCode 模型配置:
274
+
275
+ 1. ID 精确匹配。
276
+ 2. 名称精确匹配。
277
+ 3. 名称忽略大小写匹配。
278
+
279
+ 某一步匹配到唯一配置即使用该配置;没有匹配时继续下一步;匹配到多个配置时立即报错。所有步骤均未匹配时,也会报错。
280
+
281
+ 普通 iCode 智能体按以下优先级选择模型:
282
+
283
+ 1. `agent()` 的 `model` 参数。
284
+ 2. 智能体配置中绑定的模型。
285
+ 3. 工作流默认模型。TUI 可在“运行设置”中选择;CLI 通过 `icode workflow run <工作流ID> --session <会话ID>` 加载已有工作流会话时,沿用该会话保存的模型选择。未单独选择工作流默认模型时,使用 [iCode 配置的默认模型](settings.md#智能体模型与请求)。
286
+
287
+ `model` 参数指定的模型不存在或不可用时会报错。智能体绑定的模型不存在时,会继续使用工作流默认模型。没有可用模型时,工作流无法启动。
288
+
289
+ ##### 输入与输出
290
+
291
+ 智能体使用上游传入的 `WorkflowValue.text` 作为任务输入,`WorkflowValue.data` 不会自动加入提示。
292
+
293
+ 节点输出为 `WorkflowValue`,`text` 为智能体的回复文本,`data` 为 `None`。普通 iCode 智能体优先使用最终回复文本;最终回复无文本时,将本次执行过程中输出的文本按顺序拼接,作为节点输出,其中可能包含工具调用前后的过程说明。
294
+
295
+ ##### 智能体配置生效范围
296
+
297
+ 普通 iCode 智能体节点对配置项的支持如下(✓ 支持,✗ 不支持),字段格式和配置规则见[智能体配置文件参考](agent-profile.md)。
298
+
299
+ | 配置项 | 是否支持 | 节点中的行为 |
300
+ | --- | :---: | --- |
301
+ | `instructions` | ✓ | 使用配置中的指令,并在末尾追加传给 `agent()` 的 `instructions_suffix` 参数内容 |
302
+ | `model` | ✓ | 参与模型选择 |
303
+ | `tools.builtins` | ✓ | 加载内置工具;CLI 运行不提供“询问用户”工具 |
304
+ | `tools.shell_filter` | ✓ | 应用 Shell 命令过滤配置 |
305
+ | `tools.mcp` | ✓ | 加载 MCP 工具,应用允许工具范围、渐进披露和结果限制 |
306
+ | `approval` | ✓ | 与聊天模式使用相同的[工具审批规则](../guides/configuration/approval.md) |
307
+ | `compaction` | ✓ | 应用上下文压缩配置 |
308
+ | `sub_agents` | ✓ | 注册子智能体工具。子智能体失败时立即结束,并将错误返回给节点的模型,不提供“重试”或“中止”选项 |
309
+ | `skills` | ✓ | 与聊天模式相同,发现并加载 Skill,提供 `load_skill` 工具 |
310
+ | `memory` | ✓ | 加载配置的记忆文件或目录 |
311
+
312
+ 各智能体节点使用独立的上下文。连线只传递节点输出,不会传递完整的对话历史或工具调用记录。
313
+
314
+ ##### 外部 ACP 智能体
315
+
316
+ `profile` 可以直接引用已配置的 ACP 智能体,即使其标记为“仅用作子智能体”,也可作为工作流节点使用。可通过 [TUI 配置外部 ACP 智能体](../guides/extensions/external-acp-agents.md),或[创建包含 `acp` 配置的智能体 YAML 文件](agent-profile.md#acp)。
317
+
318
+ ACP 节点有以下差异:
319
+
320
+ - 省略 `model` 时使用 ACP 配置中的远端模型设置,不使用工作流默认模型。
321
+ - 显式指定 `model` 时,填写 iCode 模型配置的 ID 或名称。iCode 仅使用其中的 `model_id`,通过 ACP 请求切换远端模型;该配置的其他字段不生效。模型未被远端列出,或切换请求因方法不支持、参数无效而被拒绝时,继续使用远端默认模型。
322
+ - `instructions_suffix` 附加到发送给外部智能体的用户提示(user prompt)末尾。
323
+ - 节点输出由外部智能体配置中的“结果”([`acp.result_mode`](agent-profile.md#acp))决定,可选择“最后一个消息片段”或“完整记录”,见[设置结果和超时](../guides/extensions/external-acp-agents.md#设置结果和超时)。
324
+ - 工具执行由外部智能体负责。只有外部智能体通过 ACP 发起权限请求的操作,才会进入 iCode 的审批流程。
325
+
326
+ #### `BuilderScope.edge`
327
+
328
+ 从来源节点连向目标节点,可设置传递结果的条件。
329
+
330
+ ```python
331
+ edge(src: NodeHandle, dst: NodeHandle, *, when=None) -> None
332
+ ```
333
+
334
+ `src` 是来源节点,`dst` 是目标节点。来源节点完成后,沿连线向目标节点传递输出结果。
335
+
336
+ 省略 `when` 时无条件传递;指定 `when` 时,该同步函数接收来源节点输出的 `WorkflowValue`,返回 `True` 时传递,返回 `False` 时不传递。同一个来源节点可以连接多个目标,各条连线的条件独立判断;多个条件成立时,会向对应的多个目标传递结果。
337
+
338
+ 条件函数只能接收一个无默认值的位置参数。建议仅根据输入判断条件,避免修改外部状态。条件计算抛出异常会阻止来源节点正常完成,不会被视为条件不成立。
339
+
340
+ `src` 和 `dst` 必须由调用 `edge()` 的实例创建:通过 `WorkflowBuilder` 调用时,两端必须是该工作流的顶层节点;通过循环体的 `BuilderScope` 调用时,两端必须是该循环体内的节点。
341
+
342
+ #### `BuilderScope.chain`
343
+
344
+ 按顺序连接多个节点。
345
+
346
+ ```python
347
+ chain(*nodes: NodeHandle) -> None
348
+ ```
349
+
350
+ 至少传入两个节点。`chain(a, b, c)` 等价于 `edge(a, b)` 加 `edge(b, c)`。
351
+
352
+ `nodes` 中的所有节点必须由调用 `chain()` 的实例创建。
353
+
354
+ #### `BuilderScope.switch`
355
+
356
+ 根据条件为来源节点选择一个下游分支。
357
+
358
+ ```python
359
+ switch(
360
+ src: NodeHandle,
361
+ cases: Sequence[tuple[Callable[[WorkflowValue], bool], NodeHandle]],
362
+ default: NodeHandle,
363
+ ) -> None
364
+ ```
365
+
366
+ `src` 是来源节点。`cases` 是按顺序排列的序列,每一项必须是 `(条件函数, 目标节点)` 二元组,目标节点为 `NodeHandle`。`default` 是必填的默认目标节点。
367
+
368
+ 按 `cases` 序列中的顺序依次判断条件,遇到第一个返回 `True` 的条件时选择对应分支,不再判断后续条件;全部不满足时选择默认分支。
369
+
370
+ 条件函数必须是同步函数,只能接收一个无默认值的位置参数,接收来源节点输出的 `WorkflowValue` 并返回布尔值。建议仅根据输入判断条件,避免修改外部状态。条件计算抛出异常会阻止来源节点正常完成,不会被视为条件不成立。
371
+
372
+ 同一个来源节点只能定义一个 `switch()`;`switch()` 和 `edge()` 可以同时使用,互不排斥。
373
+
374
+ `src`、`cases` 中的目标节点和 `default` 必须由调用 `switch()` 的实例创建。
375
+
376
+ #### `BuilderScope.join`
377
+
378
+ 汇合多个来源节点的结果,并传给目标节点。
379
+
380
+ ```python
381
+ join(
382
+ sources: Sequence[NodeHandle],
383
+ dst: NodeHandle,
384
+ *,
385
+ combine=None,
386
+ ) -> None
387
+ ```
388
+
389
+ `sources` 是非空的 `NodeHandle` 序列,`dst` 是目标节点的 `NodeHandle`;`join()` 建立名为 `join:<目标名称>` 的汇合节点,再连向 `dst`。`dst` 不能再有其他直接入边。
390
+
391
+ `sources` 中的所有节点和 `dst` 必须由调用 `join()` 的实例创建。
392
+
393
+ 未指定 `combine` 时,使用[默认合并规则](#输入调度与输出收集)。
394
+
395
+ 指定 `combine` 时,该函数必须是同步单参数函数,接收 `list[SourceValue]`,返回字符串或 `WorkflowValue`。列表按 `sources` 的声明顺序排列,而不是完成顺序;被跳过或条件未选中的来源不会出现在列表里。
396
+
397
+ 只要本次至少有一个来源提供输入,就会调用指定的 `combine`,包括只有一个输入的情况。如果没有任何来源提供输入,汇合节点和目标节点都会被跳过,不会调用 `combine`。
398
+
399
+ ### `NodeHandle`
400
+
401
+ ```python
402
+ class NodeHandle:
403
+ node_id: str
404
+ ```
405
+
406
+ 节点引用,用于声明起点、输出和连线。必须使用 `python()`、`agent()` 或 `loop()` 返回的节点引用;直接调用 `NodeHandle("name")` 创建的实例不能用于构建工作流。
407
+
408
+ 唯一的公开属性 `node_id` 为节点名称,不可修改。
409
+
410
+ ### `Workflow`
411
+
412
+ ```python
413
+ class Workflow:
414
+ definition: WorkflowDefinition # 只读属性
415
+ ```
416
+
417
+ `WorkflowBuilder.build()` 返回的已构建工作流。将其赋给工作流文件顶层的 `workflow` 变量,供 iCode 加载和运行。
418
+
419
+ 其 `definition` 属性保存构建后的工作流定义,包括标题、描述、起点、输出节点、节点与连线等信息。该 `WorkflowDefinition` 实例由 `build()` 自动创建,无需手动定义。
420
+
421
+ ### `WorkflowValue`
422
+
423
+ ```python
424
+ class WorkflowValue:
425
+ text: str
426
+ data: dict | list | str | int | float | bool | None = None
427
+ ```
428
+
429
+ 节点之间传递的值。`text` 为文本内容;`data` 为结构化数据,默认是 `None`,仅支持以下 JSON 值:
430
+
431
+ - 字符串(`str`)、整数(`int`)、有限浮点数(`float`)、布尔值(`bool`)和 `None`。
432
+ - 列表(`list`)和键为字符串的字典(`dict`);允许嵌套,但列表元素和字典值也必须符合上述类型要求。
433
+
434
+ 不支持集合(`set`、`frozenset`)、元组(`tuple`)、字节(`bytes`、`bytearray`)等非 JSON 类型,也不支持普通自定义对象、非字符串字典键,以及 `NaN`、正无穷和负无穷。大小限制见[数据与输出限制](#数据与输出限制)。
435
+
436
+ 节点接收的输入由框架传入。Python 节点或 `combine` 返回字符串时,框架会自动将其转换为 `WorkflowValue`;需要返回结构化数据时,可手动创建 `WorkflowValue(text="...", data=...)`,其中 `text` 必填。
437
+
438
+ ### `SourceValue`
439
+
440
+ ```python
441
+ class SourceValue:
442
+ node_id: str
443
+ activation_id: str
444
+ value: WorkflowValue
445
+ ```
446
+
447
+ 汇合函数 `combine` 接收的来源项,由框架创建,无需自行构造。
448
+
449
+ - `node_id`:来源节点的名称。
450
+ - `activation_id`:来源节点在本次工作流运行中的执行标识。循环体节点在不同轮次中具有不同标识。
451
+ - `value`:该次执行产出的 `WorkflowValue`。
452
+
453
+ ### `NodeContext`
454
+
455
+ Python 节点函数可通过第二个位置参数接收 `NodeContext`,用于发送文本消息或询问用户。
456
+
457
+ 每次调用节点函数都会创建新的 `NodeContext` 实例,包括循环中的每一轮和失败后的重试。因此,不应在 `NodeContext` 中保存需要跨调用保留的业务数据;节点之间的数据应通过返回值传递。
458
+
459
+ #### `NodeContext.emit`
460
+
461
+ ```python
462
+ emit(text: str) -> None
463
+ ```
464
+
465
+ 发送任意文本消息,例如进度或提示。TUI 在“输出”页展示消息;CLI 文本模式将消息写入 stderr,`--json` 模式不显示。消息不影响函数返回的节点输出。
466
+
467
+ #### `NodeContext.ask`
468
+
469
+ ```python
470
+ async ask(prompt: str) -> str
471
+ async ask(prompt: Question) -> Answer
472
+ async ask(prompt: list[Question] | tuple[Question, ...]) -> tuple[Answer, ...]
473
+ ```
474
+
475
+ 向用户提问并等待回答。只能在异步节点函数中通过 `await ctx.ask(...)` 调用。返回值取决于传入的参数:
476
+
477
+ - 传入字符串(不能为空):提出一个开放式问题,返回用户输入的文本。
478
+ - 传入 [`Question`](#question):可提供选项供用户单选或多选,返回一个 [`Answer`](#answer)。
479
+ - 传入包含 1 到 5 个问题的列表或元组:在同一个对话框中一并提问,每个问题一个标签页,按问题顺序返回 `Answer` 元组。只有一个元素的列表也返回元组。
480
+
481
+ 传入其他类型的参数会引发 `TypeError`;传入空列表或超过五个问题会引发 `ValueError`。
482
+
483
+ TUI 使用与智能体提问工具相同的对话框显示问题。CLI 不支持交互,调用会以 `ask_unavailable` 失败。
484
+
485
+ 等待回答的时间计入节点超时,`ask()` 不使用智能体提问工具的超时设置。如需一直等待用户回答,可在注册 Python 节点时设置 `timeout=None`,取消该节点的超时限制。
486
+
487
+ [会话目录](../guides/daily-use/sessions.md#查找会话-id-和会话保存位置)下该运行的 `workflows/<run_id>/events.jsonl` 只保存问题和回答的文本摘要(截断至 512 个字符),不保存完整问题。
488
+
489
+ ### `Question`
490
+
491
+ ```python
492
+ Question(
493
+ question: str,
494
+ header: str = "",
495
+ options: list[Option | str] | tuple[Option | str, ...] = (),
496
+ multi_select: bool = False,
497
+ )
498
+ ```
499
+
500
+ `ctx.ask()` 的一个问题。字段名与智能体提问工具一致。
501
+
502
+ - `question`:问题正文,按 Markdown 渲染,不能为空。除消息大小上限外没有长度限制,因此可以把整篇草稿放进问题供用户审阅。
503
+ - `header`:问题标签页上的简短标题,最多 64 个字符。未设置时标签页显示问题序号。只有同时提出多个问题时才显示标签页,因此也才显示标题。
504
+ - `options`:最多 8 个选项。字符串是 `Option(label=...)` 的简写。没有选项时,问题只接受输入的回答。
505
+ - `multi_select`:为 `True` 时用户可以选择多个选项,此时至少需要一个选项。
506
+
507
+ 选项标签会去除首尾空白,并且在同一问题内不能重复。所有字符串都必须是有效的 Unicode,不能包含未配对的代理字符。类型错误引发 `TypeError`,其他违规引发 `ValueError`;两者都在创建 `Question` 或 `Option` 时抛出,因此回溯信息会指向你的代码。
508
+
509
+ 无论问题是否带有选项,用户都可以自行输入回答,或在选择选项时附加备注。
510
+
511
+ ### `Option`
512
+
513
+ ```python
514
+ Option(label: str, description: str = "")
515
+ ```
516
+
517
+ - `label`:用户选择的内容,也是 `Answer.selected` 中返回的值,最多 200 个字符。
518
+ - `description`:显示在标签下方的一行说明,最多 500 个字符。
519
+
520
+ ### `Answer`
521
+
522
+ ```python
523
+ class Answer:
524
+ selected: tuple[str, ...] = ()
525
+ text: str = ""
526
+ answered: bool # 只读属性
527
+ choice: str | None # 只读属性
528
+ ```
529
+
530
+ 用户对一个 `Question` 的回答。
531
+
532
+ - `selected`:回答中与所提供选项标签一致的值,按选项顺序排列。点击选项与输入与标签完全相同(区分大小写)的文本,得到的回答相同。
533
+ - `text`:用户输入的其他内容:与任何标签都不匹配的自定义回答,或随选项一起给出的备注。
534
+ - `answered`:仅当用户跳过该问题时为 `False`。
535
+ - `choice`:唯一选中的标签;未选中任何选项时为 `None`。选中多个时引发 `ValueError`,多选问题请读取 `selected`。
536
+
537
+ 每个回答都是以下三种形式之一:
538
+
539
+ | `selected` | `text` | 含义 |
540
+ | --- | --- | --- |
541
+ | 非空 | 备注,或 `""` | 选择或输入了所提供的选项标签;单选问题最多一个 |
542
+ | `()` | 非空 | 与任何标签都不匹配的自定义回答 |
543
+ | `()` | `""` | 已跳过 |
544
+
545
+ 对话框的行为:
546
+
547
+ - 只有一个单选问题时,点击选项会立即提交,因此备注需要在点击前输入。不点击选项而直接提交时,输入的文本就是完整的回答。
548
+ - 有多个问题时,点击单选问题的选项会跳到下一个未回答的问题或“提交”标签页。多选问题和输入的回答通过“回答并继续”前进(最后一个问题为“回答并检查”)。“提交”标签页列出所有回答,通过“提交回答”发送;仍有问题未回答时按钮为“仍然提交”。一个问题都没有回答时,需要再按一次确认才会提交。
549
+ - 对话框无法用 Esc 关闭。问题会一直等待,直到用户回答,或所属的尝试或运行结束。
550
+
551
+ `Answer` 是本地结果,不能作为节点输出:节点应返回字符串或 `WorkflowValue`。如需把选择结果传给下游,请同时放入 `text`(智能体节点和默认汇合读取)和 `data`(供 Python 节点使用):
552
+
553
+ ```python
554
+ async def pick_areas(value: WorkflowValue, ctx: NodeContext) -> WorkflowValue:
555
+ answer = await ctx.ask(Question("涉及哪些部分?", options=["API", "Storage", "UI"], multi_select=True))
556
+ text = "\n".join(part for part in (", ".join(answer.selected), answer.text) if part)
557
+ return WorkflowValue(text=text, data={"selected": list(answer.selected), "text": answer.text})
558
+ ```
559
+
560
+ ### `Retry`
561
+
562
+ ```python
563
+ Retry(max_attempts: int, backoff: float = 0.0)
564
+ ```
565
+
566
+ `max_attempts` 是包含第一次执行的总尝试次数,至少为 1;`backoff` 是有限、非负的固定秒数间隔。
567
+
568
+ 通过 `python()` 或 `agent()` 的 `retry` 参数设置。是否重试还取决于错误类型,见[超时与重试](#超时与重试)。
569
+
570
+ ## 数据与调度规则
571
+
572
+ ### 数据与输出限制
573
+
574
+ 工作流适合传递任务文本和有限的 JSON 数据。超出下表中的数据限制时会失败,不会自动截断后传给下游。深度、值总数和字符串长度限制适用于 Python 节点及自定义 `combine` 的返回值;返回值无法序列化时也会失败。
575
+
576
+ | 限制对象 | 上限 | 计算范围 |
577
+ | --- | --- | --- |
578
+ | 单次跨进程传输的消息大小 | 16 MiB | 按 UTF-8 编码后的整条消息计算,包括传递的值和框架附加的信息 |
579
+ | `data` 的嵌套深度 | 64 层 | `data` 本身为第 0 层,每进入一层列表元素或字典值,深度加 1 |
580
+ | `data` 中的值的总数 | 200,000 个 | 包括所有嵌套内容;每个列表、字典本身也各计 1 个,字典键名不计入。计数示例见下方 |
581
+ | `text` 或 `data` 中的单个字符串值 | 4,194,304 个字符 | 按字符数计算;整个传输消息仍需满足字节数限制 |
582
+ | 传给自定义 `combine` 的全部来源数据 | 合计 12 MiB | 合并前的所有来源一起计算,包括各自的 `text`、`data` 和来源标识,按 UTF-8 编码后的 JSON 大小计量 |
583
+
584
+ 下面的 `data` 共计 7 个值:
585
+
586
+ ```python
587
+ data = { # 外层字典:1 个
588
+ "names": ["Alice", "Bob"], # 列表本身 + 两个字符串:3 个
589
+ "scores": [90, 80], # 列表本身 + 两个数字:3 个
590
+ }
591
+ ```
592
+
593
+ 键名 `"names"` 和 `"scores"` 不计入。
594
+
595
+ 进度消息和诊断输出另有限制。下表中的“一次尝试”指节点的一次执行,重试时重新计数。
596
+
597
+ | 输出方式 | 每次尝试的限制 | 超限后果 |
598
+ | --- | --- | --- |
599
+ | `ctx.emit()` 发送的消息 | 任意连续 1 秒内最多 200 条;累计最多 10,000 条;消息文本按 UTF-8 编码后累计最多 8 MiB。三项均须满足 | 本次尝试失败 |
600
+ | Python 节点直接写入 `sys.stdout` / `sys.stderr` 的内容(如 `print()` 的输出,不含 `ctx.emit()`) | 两者按 UTF-8 编码后合计保留前 64 KiB | 超出部分截断,不会仅因此导致节点失败,也不影响节点返回值 |
601
+
602
+ CLI 文本模式会将收到的 `ctx.emit()` 消息显示到 stderr,但这些消息仍按 `ctx.emit()` 的独立限额计算,不占用节点的 64 KiB 输出额度。
603
+
604
+ ### 输入调度与输出收集
605
+
606
+ 可以通过多次调用 `wf.edge()`,将多个上游节点连接到同一个节点。节点会等待所有入边都确定是否传递结果,再根据实际收到的结果决定执行或跳过。
607
+
608
+ 除指定了自定义 `combine` 的汇合节点外,各类节点使用以下默认输入合并规则:
609
+
610
+ | 实际收到结果的来源数量 | 处理方式 |
611
+ | --- | --- |
612
+ | 零个 | 节点跳过;仅依赖它的后继也会跳过 |
613
+ | 一个 | 将该来源的 `WorkflowValue` 原样作为节点输入,保留 `data` |
614
+ | 多个 | 按入边声明顺序合并各来源的 `text`,作为节点输入;合并后的 `data=None` |
615
+
616
+ 默认合并多个来源时,文本以来源节点名称作为标题,格式如下:
617
+
618
+ ```text
619
+ ## first_node
620
+ 第一份输出
621
+
622
+ ## second_node
623
+ 第二份输出
624
+ ```
625
+
626
+ 满足执行条件的分支可以并行调度。当前每次运行最多同时执行四个智能体尝试,超出这一上限的智能体节点需等待名额。
627
+
628
+ 工作流按 `output()` 的声明顺序收集输出节点的结果,只收集已完成且有结果的节点。跳过的输出节点不产生空占位,因此工作流可能完成却没有最终输出。
629
+
630
+ ### 超时与重试
631
+
632
+ Python 节点和智能体节点的 `timeout` 限制单次尝试的执行时间,包含等待问答或审批的时间,每次重试重新计时。
633
+
634
+ 同一节点的一批出边条件计算(包括 `switch` 判断)共享 30 秒上限。循环结束条件和自定义 `combine` 则各自每次计算最多允许 30 秒。这些计算均不受节点 `timeout` 设置影响。工作流源码加载与构建合计另有 60 秒上限。
635
+
636
+ 节点失败后,是否自动重试取决于错误类型和节点的 `Retry` 配置:
637
+
638
+ | 情况 | 自动重试条件 |
639
+ | --- | --- |
640
+ | Python 节点的函数异常或执行超时 | 尚未达到 `Retry.max_attempts` |
641
+ | 非 ACP 智能体节点的模型请求遇到临时错误,如连接中断、限流、请求超时 | 先在本次尝试内重试该请求,与聊天模式一致;仍失败时,尚未达到 `Retry.max_attempts` 则重试节点 |
642
+ | 非 ACP 智能体节点的模型请求超出模型的上下文窗口 | 与聊天模式一致:开启上下文压缩时,先在本次尝试内压缩上下文并重新发送一次请求,除非报错给出的上限小于模型配置中的值;仍失败时不自动重试节点 |
643
+ | 非 ACP 智能体节点达到 `timeout` 上限 | 尚未达到 `Retry.max_attempts` |
644
+ | 外部 ACP 智能体节点连接中断、长时间无响应、报错或达到 `timeout` 上限 | 尚未达到 `Retry.max_attempts`。iCode 无法判断外部智能体报告的哪些错误无法恢复,因此都会重试;但智能体无法启动、本次尝试内多次重试连接后仍连不上、配置被拒绝,以及智能体拒绝回答、提前停止或回答为空时不重试 |
645
+ | 重试也无法解决的错误,如额度或套餐已用尽、外部智能体需要登录;以及条件或合并计算失败、返回值无法序列化或超限、运行环境不支持问答等 | 不自动重试 |
646
+
647
+ 若重试可能让模型服务商再次运行它自己那边的工具(如服务商运行的 MCP 服务器或 Shell),则不自动重试节点。服务商运行的搜索和代码执行可以安全重复,不影响重试;iCode 自己的文件、Shell 和 MCP 工具也不影响。
648
+
649
+ 非 ACP 智能体的尝试失败或超时后,重试会接着已有的对话继续执行:已完成的工具调用不会再次执行,节点详情中新一次尝试的对话记录也接着上一次显示。外部 ACP 智能体会以相同输入开启新会话,新一次尝试的对话记录只显示这个会话。若智能体已经完成、之后节点的其他步骤(如出边条件)失败,重试会从输入重新运行智能体。
650
+
651
+ `Retry(max_attempts=1)` 只关闭节点重试:失败的模型请求仍会在本次尝试内重试。
652
+
653
+ TUI 中,节点失败且不再自动重试时(自动重试次数已用尽或不满足自动重试条件),会进入 `awaiting_retry`(等待手动重试)。用户可以查看错误诊断后重试,也可以取消整个运行。手动重试只适用于当前运行中处于这一状态的节点。
654
+
655
+ CLI 不支持手动重试。节点失败且无法继续自动重试时,整个运行结束;即使已有部分输出,整个工作流仍视为失败。
656
+
657
+ 重试 Python 节点会重新执行整个函数,包括函数完成后在出边条件计算时失败的情况。循环节点自身在结束条件或出边条件计算时失败,手动重试只重新计算失败的条件,保留已经完成的循环进度。
658
+
659
+ 重试可能重复文件写入、外部请求等操作,应确保这些操作可安全重复执行。超时或取消不会撤销已经发生的操作,也不保证立即停止正在运行的同步 Python 函数。
660
+
661
+ ## 执行环境
662
+
663
+ 工作流默认使用运行 iCode 的 Python 解释器,也可在工作流文件中指定已有的虚拟环境或 Python 可执行文件,支持 Python 3.9 及以上版本。
664
+
665
+ 下面的例子使用项目根目录下已有的 `.venv`,工作流文件位于项目 `.chrys/workflows/`:
666
+
667
+ ```python
668
+ # /// script
669
+ # [tool.chrys]
670
+ # python = "../../.venv"
671
+ # ///
672
+ ```
673
+
674
+ 保留示例中的 `#` 前缀和 `# ///` 标记,iCode 会读取这段注释中的配置。`[tool.chrys]` 是 iCode 专用配置区,`python` 的相对路径以工作流文件所在目录为基准。工作流文件夹的基准就是文件夹本身:项目根目录下的 `.venv` 写作 `../../../.venv`,文件夹中的写作 `.venv`。
675
+
676
+ `python` 也可直接填写 Python 可执行文件的路径,如 `"/opt/homebrew/bin/python3.12"`。iCode 不会通过 `PATH` 查找命令。使用 uv 创建的环境时,指向其 `.venv`。
677
+
678
+ iCode 启动解释器时会把环境变量 `PYTHONPYCACHEPREFIX` 设为自己存放编译文件的文件夹。用 `-E` 或 `-I` 启动 Python 的包装脚本会忽略该变量,工作流将无法加载。
679
+
680
+ iCode 不会自动安装依赖,请提前在所选环境中安装工作流所需的第三方包。`chrys.workflows` 由 iCode 在运行时提供,无需另外安装。
681
+
682
+ 脚本元数据还支持以下两个顶层字段,写在 `[tool.chrys]` 之前:
683
+
684
+ | 字段 | 规则 |
685
+ | --- | --- |
686
+ | `requires-python` | 可选的 Python 版本约束字符串,例如 `">=3.10,<3.13"`。iCode 检查所选解释器是否满足约束,不满足时拒绝加载;不会自动寻找或安装其他版本。仅支持以逗号分隔、由 `~=`、`==`、`!=`、`<=`、`>=`、`<`、`>` 与纯数字发布版本组成的子句:`.*` 只能与 `==`、`!=` 搭配,`~=` 至少需要两段版本号。其他写法同样会拒绝加载 |
687
+ | `dependencies` | 可选的依赖字符串数组。非空时必须同时指定 `[tool.chrys] python`,否则拒绝加载,即使默认环境已经安装这些包。指定自备解释器后,iCode 不安装这些依赖,也不校验已安装版本是否符合声明 |
688
+
689
+ 例如,以下声明要求使用 Python 3.10 至 3.12 的项目虚拟环境,并由作者预先安装 `requests`:
690
+
691
+ ```python
692
+ # /// script
693
+ # requires-python = ">=3.10,<3.13"
694
+ # dependencies = ["requests"]
695
+ # [tool.chrys]
696
+ # python = "../../.venv"
697
+ # ///
698
+ ```
699
+
700
+ ## 会话、运行与记录
701
+
702
+ 工作流会话独立于聊天会话,用于保存同一工作流在同一工作区中的多次运行。每次启动运行都会生成新的 `run_id`,使用本次提供的输入,不会自动带入历史对话。
703
+
704
+ ### 会话设置
705
+
706
+ TUI 的“启动工作流”对话框提供“运行设置”。工作目录能否更改取决于会话是否已有运行,以及工作流的来源:
707
+
708
+ | 会话与工作流来源 | 工作目录规则 |
709
+ | --- | --- |
710
+ | 尚未运行的新会话,使用内置或全局工作流 | 可以在运行设置中更改工作目录 |
711
+ | 尚未运行的新会话,使用项目工作流 | 固定为发现该工作流的项目目录,即包含 `.chrys/workflows/` 的目录 |
712
+ | 已有运行的会话 | 工作区固定;更换目录或工作流需新建会话 |
713
+
714
+ 包含 iCode 智能体节点时,运行设置还提供默认模型选择。
715
+
716
+ 工作流会话不单独保存审批模式,而是与聊天模式共用 TUI 当前的审批模式,之后重新打开的会话同样如此。CLI 运行始终使用 `bypass`。
717
+
718
+ ### 运行结果与恢复
719
+
720
+ 重新打开会话后,可以查看历史或启动新运行,但不会从上次中断的节点续跑。已取消或中断的运行需要重新开始;当前运行中等待手动重试的节点按[超时与重试](#超时与重试)处理。
721
+
722
+ `icode workflow run --json` 输出的结果对象中,`outcome` 字段表示运行结果。本地记录也保存该字段,位于[会话目录](../guides/daily-use/sessions.md#查找会话-id-和会话保存位置)下 `workflows/<run_id>/events.jsonl` 的运行结束事件中。
723
+
724
+ 进程异常终止、来不及收尾的记录,会在恢复会话时补记 `outcome=orphaned`,在工作流运行界面中显示为“进程退出时未完成”。
725
+
726
+ | 运行结果 `outcome` | 含义 |
727
+ | --- | --- |
728
+ | `completed` | 运行完成 |
729
+ | `node_failed` | 节点失败 |
730
+ | `loop_exhausted` | 循环按 `on_exhausted="fail"` 耗尽次数 |
731
+ | `cancelled` | 运行取消;`reason=deadline_exceeded` 表示运行总超时 |
732
+ | `worker_lost` | 执行工作流的进程丢失 |
733
+ | `storage_failed` | 运行记录无法写入 |
734
+ | `orphaned` | 恢复时发现原进程终止,运行未正常收尾 |
735
+
736
+ 工具调用产生的文件修改按运行归属记录,但任意 Python 代码或外部程序的副作用不应假定都可追踪或撤销。取消、节点重试和再次运行均不自动回滚文件。
737
+
738
+ ### 查看与导出记录
739
+
740
+ TUI 中通过运行页签切换同一会话的运行记录;退出后,切换到工作流模式,再从会话列表重新打开。节点详情保留循环中的不同轮次和重试的不同尝试。查看历史不会执行工作流源码。
741
+
742
+ [会话目录](../guides/daily-use/sessions.md#查找会话-id-和会话保存位置)下的 `workflows/<run_id>/` 保存源码快照、图定义、输入、最终输出、运行事件和节点记录;智能体对话记录也归属于该运行。这些文件用于保留记录,不支持工作流续跑。
743
+
744
+ 运行和节点的用量、耗时可用于检查开销;ACP 用量取决于远端是否报告。需要导出分析时使用:
745
+
746
+ ```shell
747
+ icode trajectory export --session <session-id> --format json --out workflow.json
748
+ icode trajectory export --session <session-id> --format perfetto --out workflow.perfetto.json
749
+ ```
750
+
751
+ 将 `<session-id>` 换成工作流会话 ID。工作流会话的分析导出仅支持 JSON 和 Perfetto 格式。
752
+
753
+ ## 生命周期 Hooks
754
+
755
+ 工作流使用已配置的外部 Hooks,配置文件格式见[Hooks 参考](hooks.md)。一个工作流会话可以包含多次运行。`session_*` 事件表示会话首次投入运行、恢复后开始运行或结束使用;`workflow_run_*` 事件表示每次运行的开始和结束。节点执行不会单独触发下表中的会话事件。
756
+
757
+ 运行须先通过源码、执行环境和智能体配置等启动检查,才会触发会话开始或恢复事件,以及运行开始事件。未通过检查的启动请求不触发这些事件。
758
+
759
+ | 事件 | 触发时机 | 额外字段 |
760
+ | --- | --- | --- |
761
+ | `session_start` | 新建会话首次开始运行时,在 `workflow_run_start` 之前 | 无 |
762
+ | `session_restored` | 从保存记录加载的会话,在本次启动 iCode 后首次开始新运行时,在 `workflow_run_start` 之前 | `restored_session_id`:恢复的会话 ID |
763
+ | `session_end` | 本次启动 iCode 后已开始过运行的会话被删除、iCode 正常关闭或 CLI 运行命令正常结束时 | 无 |
764
+ | `workflow_run_start` | 每次运行通过启动检查后、执行节点前 | `run_id`、`input_text` |
765
+ | `workflow_run_end` | 每次运行完成收尾、确定最终结果后,包括失败和取消 | `run_id`、`outcome`、`reason` |
766
+
767
+ 每次启动 iCode 后,同一会话仅在首次运行时触发 `session_start` 或 `session_restored`;每次被接受的运行各触发一次 `workflow_run_start` 和 `workflow_run_end`,节点重试不会重复触发。进程崩溃或被强制终止时,无法保证触发结束事件。
768
+
769
+ 上述事件均包含 `session_kind: "workflow"`、`workflow_id`、`session_id` 和 `cwd`;`profile` 为空字符串,因为工作流会话不绑定单个智能体。其他通用字段见[Hooks 基础字段](hooks.md#基础字段)。
770
+
771
+ `workflow_run_start` 和 `workflow_run_end` 用于通知和记录。配置为阻塞式钩子时,iCode 会等待钩子结束,但不会采用其返回的操作决定来阻止运行或授予工具权限;`action: block` 会被忽略,钩子失败时的 `on_error: block` 按警告处理。
772
+
773
+ ## 命令行
774
+
775
+ ### `icode workflow list`
776
+
777
+ 按[文件发现](#文件发现)规则列出工作流,不执行工作流代码。自定义工作流的标题取自此前保存的信任确认记录。
778
+
779
+ ```shell
780
+ icode workflow list [--json]
781
+ ```
782
+
783
+ 默认以文本模式显示 `ID`、`Source`、`Title`、`Path`,未知标题显示为 `-`;工作流文件夹的 `Path` 是其入口文件。添加 `--json` 后输出一个对象,其 `workflows` 数组每项包含 `id`、`source`、`layout`(单个 `.py` 文件为 `file`,工作流文件夹为 `package`)、`title`、`path`(入口文件);未知标题为空字符串。两种输出模式下,跳过文件的警告均写入 stderr。使用 `-h` / `--help` 查看帮助。
784
+
785
+ ### `icode workflow validate`
786
+
787
+ 在运行前检查工作流。该命令按运行时的方式加载工作流,像编译器一样指出每个问题所在的文件、行和列。
788
+
789
+ ```shell
790
+ icode workflow validate <path> [--json]
791
+ ```
792
+
793
+ `<path>` 是工作流 `.py` 文件或[工作流文件夹](#工作流文件夹),相对于当前目录,不必位于 iCode 查找工作流的位置。对于文件夹,`code-review`、`code-review/` 和 `code-review/code-review.py` 都检查该文件夹。
794
+
795
+ 校验会执行工作流的模块顶层代码,与在 TUI 中加载时相同,但不运行任何节点,也不调用模型。校验不询问也不记录信任确认,因此工作流是新的或已修改时,之后运行 `icode workflow run` 仍需 `--trust`。
796
+
797
+ 检查按以下顺序进行,在第一个失败的阶段停止:
798
+
799
+ | 阶段 | 检查内容 |
800
+ | --- | --- |
801
+ | `resolve` | 路径指向一个工作流:`.py` 文件,或包含与文件夹同名入口文件的文件夹;不是链接,且名称会被 iCode 加载 |
802
+ | `read` | 每个文件都可读取且未超出大小上限,入口文件为 UTF-8 编码 |
803
+ | `metadata` | `# /// script` 块(如有)有效,见[执行环境](#执行环境) |
804
+ | `environment` | 工作流指定的 Python 解释器存在且能启动 |
805
+ | `load` | 文件夹中每个 `.py` 文件都能编译,顶层代码运行成功,`build()` 成功 |
806
+ | `graph` | 构建出的图有效;结构可疑时给出警告 |
807
+ | `bindings` | 每个智能体节点的智能体配置和模型在本设备上可用 |
808
+
809
+ #### 文本报告
810
+
811
+ 每个问题显示为 `文件:行:列: error: 消息 [代码]`,下方是该行源码并标出位置。`note:` 行说明代码是如何执行到此处的,`help:` 行给出修改建议。加载期间工作流打印的内容显示在 `captured output (load):` 之下。最后一行是结果:
812
+
813
+ ```text
814
+ ./.chrys/workflows/code-review/steps.py:2:10: error: NameError: name 'summarise' is not defined [load_error]
815
+ 2 | PROMPT = summarise("diff")
816
+ | ^~~~~~~~~
817
+ note: imported from ./.chrys/workflows/code-review/code-review.py:3
818
+ captured output (load):
819
+ | loading steps
820
+ FAIL code-review (package): 1 error
821
+ ```
822
+
823
+ 通过校验时只输出一行,例如 `PASS code-review (package) · 1 node · 0 edges`。警告列在其上方,不会导致校验失败。只有工作流使用 Python 3.11 及以上版本时才显示列号。
824
+
825
+ #### JSON 报告
826
+
827
+ 添加 `--json` 后,stdout 输出一个 JSON 对象。所有字段始终存在,未知的值为 `null`。
828
+
829
+ | 字段 | 类型与含义 |
830
+ | --- | --- |
831
+ | `version` | 整数:报告格式版本,当前为 `1` |
832
+ | `status` | 字符串:`pass` 或 `fail` |
833
+ | `target` | 对象:所检查的对象,包括 `path`、`layout`(`file` 或 `package`)、`workflow_id`、`entry`(入口文件)、`package_dir`、`source_digest` 和 `files`(文件数) |
834
+ | `stages` | 对象数组:按顺序列出各阶段的 `name` 和 `status`(`pass`、`fail` 或 `skipped`) |
835
+ | `diagnostics` | 对象数组:发现的问题,结构见下文 |
836
+ | `diagnostics_truncated` | 布尔值:部分加载问题被省略 |
837
+ | `sites_truncated` | 布尔值:工作流节点过多,无法报告每个节点的声明位置,图和绑定问题可能没有行号 |
838
+ | `workflow` | 对象或 `null`:工作流加载成功后,包含 `title`、`node_count`、`edge_count` 和 `outputs`(输出节点 ID) |
839
+ | `output` | 对象:加载期间打印的 `text`,以及是否被截断(`truncated`) |
840
+
841
+ `diagnostics` 中每项包含:
842
+
843
+ | 字段 | 类型与含义 |
844
+ | --- | --- |
845
+ | `severity` | 字符串:`error` 或 `warning` |
846
+ | `code` | 字符串:问题代码,见下表 |
847
+ | `stage` | 字符串:发现问题的阶段 |
848
+ | `message` | 字符串:问题描述 |
849
+ | `file` | 字符串或 `null`:文件的绝对路径 |
850
+ | `line`、`column`、`end_line`、`end_column` | 整数或 `null`:在文件中的位置,从 1 开始 |
851
+ | `node` | 字符串或 `null`:问题涉及的节点 ID,或写作 `source->target` 的边 |
852
+ | `source_line` | 字符串或 `null`:`line` 行的文本 |
853
+ | `notes` | 对象数组,每项包含 `message`、`file`、`line`:代码是如何执行到此处的,由内向外 |
854
+ | `hint` | 字符串或 `null`:修改建议 |
855
+ | `traceback` | 字符串或 `null`:加载失败时的 Python traceback,只保留你自己文件中的帧(不含标准库、已安装的包和 iCode 自身) |
856
+
857
+ | 代码 | 阶段 | 含义 |
858
+ | --- | --- | --- |
859
+ | `path_not_found` | `resolve` | 路径不存在。若有工作流使用该 ID,提示中会给出其路径 |
860
+ | `path_is_link` | `resolve` | 工作流或文件夹的入口文件是链接 |
861
+ | `path_not_workflow` | `resolve` | 路径不指向单个工作流:不是 `.py` 文件或文件夹,是存放工作流的目录(或包含它的项目文件夹、`.chrys` 文件夹)或工作流文件夹中的文件,文件夹的入口文件不是普通文件,或与所在文件夹列出的拼写不同 |
862
+ | `name_ignored` | `resolve` | iCode 从不加载该名称,例如以 `.` 或 `_` 开头的名称 |
863
+ | `name_reserved` | `resolve` | `sdk` 在全局工作流文件夹中是保留名称 |
864
+ | `entry_missing` | `resolve` | 文件夹中没有与其同名的入口文件 |
865
+ | `shadowed`(警告) | `resolve` | 另一个同 ID 的工作流优先被找到,运行时会使用那一个 |
866
+ | `source_too_large`、`package_too_large` | `read` | 入口文件或文件夹超出大小上限 |
867
+ | `source_unreadable`、`package_unreadable` | `read` | 文件无法读取 |
868
+ | `package_link`、`package_unsupported_file` | `read` | 文件夹中有链接,或有普通文件和文件夹以外的项 |
869
+ | `source_not_utf8` | `read` | 入口文件不是 UTF-8 编码 |
870
+ | `metadata_invalid` | `metadata` | `# /// script` 块无效 |
871
+ | `environment_invalid` | `environment` | Python 环境不可用 |
872
+ | `syntax_error` | `load` | `.py` 文件无法编译 |
873
+ | `load_error` | `load` | 顶层代码抛出异常 |
874
+ | `sdk_validation_error` | `load` | `WorkflowBuilder` 拒绝了某个声明或 `build()` |
875
+ | `missing_workflow` | `load` | 没有由 `build()` 构建的模块级 `workflow` |
876
+ | `load_timeout` | `load` | 加载未在时限内完成 |
877
+ | `worker_failed` | `load` | 加载工作流的进程出错 |
878
+ | `manifest_invalid` | `graph` | 构建出的图无效 |
879
+ | `loop_exit_all_conditional`(警告) | `graph` | 循环的出口节点只能经条件边到达,某次迭代可能没有结果值,导致运行失败 |
880
+ | `agent_profile_missing` | `bindings` | 智能体节点指定的智能体配置不可用 |
881
+ | `model_unresolvable` | `bindings` | 智能体节点没有可用的模型 |
882
+ | `internal_error` | 任意 | iCode 自身在所示阶段出错 |
883
+
884
+ #### 退出码
885
+
886
+ | 退出码 | 含义 |
887
+ | --- | --- |
888
+ | `0` | PASS,可能带有警告 |
889
+ | `1` | FAIL |
890
+ | `2` | 参数解析错误 |
891
+ | `130` | CLI 捕获到键盘中断 |
892
+
893
+ ### `icode workflow run`
894
+
895
+ 运行指定工作流,完成后输出结果。
896
+
897
+ #### 参数
898
+
899
+ ```shell
900
+ icode workflow run <workflow-id> [--input TEXT] [-s SESSION] [--trust] [--timeout SECONDS] [--json] [-q]
901
+ ```
902
+
903
+ | 参数 | 默认值与用途 |
904
+ | --- | --- |
905
+ | `<workflow-id>` | 文件名去掉 `.py` 的部分,或工作流文件夹的名称,可由 `icode workflow list` 查询 |
906
+ | `--input TEXT` | 默认空字符串,传给起点的 `WorkflowValue.text`(见[多行输入](#多行输入)) |
907
+ | `-s` / `--session` | 加载已有工作流会话,为该会话绑定的工作流发起新运行;不能续跑旧运行。该会话必须是至少已有一次运行的工作流会话;`<workflow-id>` 必须与会话绑定的工作流一致,否则运行会被拒绝,错误代码为 `spec_changed` |
908
+ | `--trust` | 信任当前自定义源码及环境;内置工作流无需此选项 |
909
+ | `--timeout SECONDS` | 默认无总时限;必须为有限正数,覆盖预览、工作流加载和执行;不包含会话恢复、部分初始化及清理时间,超时后仍等待清理完成 |
910
+ | `--json` | 使用 JSON 输出 |
911
+ | `-q` / `--quiet` | 不在 stderr 显示进度;仍显示警告、错误、加载输出和节点外输出,以及最终输出 |
912
+ | `-h` / `--help` | 查看帮助 |
913
+
914
+ #### 多行输入
915
+
916
+ `--input` 中换行的写法取决于 shell。bash 和 zsh 中使用 `$'...'` 引号,用 `\n` 表示换行:
917
+
918
+ ```shell
919
+ icode workflow run demo-workflow --input $'interactive: false\ndepth: deep\nhow are errors handled?'
920
+ ```
921
+
922
+ PowerShell 中在双引号内用 `` `n `` 表示换行:
923
+
924
+ ```powershell
925
+ icode workflow run demo-workflow --input "interactive: false`ndepth: deep`nhow are errors handled?"
926
+ ```
927
+
928
+ PowerShell 不认识 `$'...'`,会把文本原样作为一行传入,其中的 `\n` 是两个普通字符。
929
+
930
+ #### 文本输出
931
+
932
+ 不加 `--json` 时使用文本模式,将最终输出按声明顺序拼接到 stdout,多份结果之间空一行。进度逐行写入 stderr,每个步骤一行:节点状态、智能体节点的工具调用及其间写下的说明、`ctx.emit()` 进度、循环迭代,以及运行成功时最后的 `✓ Workflow completed` 行。加载输出、节点外输出等运行诊断也写入 stderr。`--quiet` 隐藏进度,但保留警告、错误,以及加载输出和节点外输出。
933
+
934
+ #### JSON 输出
935
+
936
+ JSON 模式不向 stderr 输出节点状态、`ctx.emit()` 进度或循环迭代消息;警告和错误仍写入 stderr。生成运行结果后,向 stdout 输出一个单行 JSON 对象。下表列出该对象的全部顶层字段;`diagnostics` 和 `outputs` 的内部结构分别在后文说明。
937
+
938
+ | 字段 | 类型与含义 |
939
+ | --- | --- |
940
+ | `session_id` | 字符串或 `null`:会话标识;没有可用标识时为 `null` |
941
+ | `run_id` | 字符串:本次运行标识 |
942
+ | `outcome` | 字符串:运行结果,见[运行结果与恢复](#运行结果与恢复) |
943
+ | `reason` | 字符串:结果原因代码,无原因时为空字符串 |
944
+ | `node_id` | 字符串:相关失败节点,无相关节点时为空字符串 |
945
+ | `error` | 字符串:错误说明,无错误时为空字符串 |
946
+ | `duration` | 数值:CLI 统计的耗时秒数,含准备过程 |
947
+ | `diagnostics` | 对象或 `null`:运行诊断;无可用诊断时可为 `null` |
948
+ | `outputs` | 对象数组:最终输出,按输出声明顺序排列;没有结果时为空数组 |
949
+
950
+ `diagnostics` 为对象时,结构如下,不包含节点诊断文件中的输出。示例仅展示该字段的值;为便于阅读添加了换行和注释,实际输出是无注释的单行 JSON。
951
+
952
+ ```jsonc
953
+ {
954
+ "load": {
955
+ // 字符串:加载工作流文件时捕获的输出,例如文件顶层的 print()
956
+ "text": "加载时的输出\n",
957
+ // 布尔值:加载输出是否因超过捕获上限而截断
958
+ "truncated": false
959
+ },
960
+ "native": {
961
+ // 字符串:无法关联到具体节点执行尝试的输出,
962
+ // 例如子进程或原生扩展直接写出的内容;超过捕获上限时只保留末尾部分
963
+ "text": "",
964
+ // 整数:因捕获上限而丢弃的字节数
965
+ "dropped_bytes": 0
966
+ }
967
+ }
968
+ ```
969
+
970
+ 诊断收集或读取失败时,对象中会包含字符串字段 `error`,并可能缺少 `load` 或 `native`。例如读取失败时:
971
+
972
+ ```jsonc
973
+ {
974
+ "error": "诊断读取失败的具体原因"
975
+ }
976
+ ```
977
+
978
+ `outputs` 的每个元素都是一个对象,包含以下字段:
979
+
980
+ | 字段 | 类型与含义 |
981
+ | --- | --- |
982
+ | `node_id` | 字符串:输出节点的 ID |
983
+ | `activation_id` | 字符串:产生该输出的节点激活标识 |
984
+ | `text` | 字符串:节点返回的 `WorkflowValue.text` |
985
+ | `data` | JSON 值:节点返回的 `WorkflowValue.data`,可以是对象、数组、字符串、数值、布尔值或 `null`;内部结构由工作流定义,没有固定字段 |
986
+
987
+ #### 节点诊断
988
+
989
+ 文本和 JSON 模式均会保存节点诊断记录。节点内 `print()` 的输出只写入节点诊断记录,不输出到 CLI 的 stderr,也不包含在结果 JSON 的 `diagnostics` 中。
990
+
991
+ 节点诊断记录位于[会话目录](../guides/daily-use/sessions.md#查找会话-id-和会话保存位置)下的 `workflows/<run_id>/nodes/`,文件名通常为 `<activation_id>.<attempt>.diagnostics.<hash>.json`,分别对应节点激活标识、执行尝试编号,以及记录标识的 8 位哈希(用于在文件名净化后仍保持唯一)。其中 `phases[].stdout.text` 保存捕获的文本,`phases[].stdout.truncated` 表示是否因捕获限制而截断;没有诊断内容时不生成文件。也可在 TUI 节点详情的“输出”页签中查看对应执行尝试的诊断。
992
+
993
+ #### 错误处理与退出码
994
+
995
+ 文本和 JSON 模式使用相同的退出码。运行失败或取消时,文本模式向 stderr 输出错误文本,JSON 模式向 stderr 输出错误 JSON;参数解析错误在两种模式下均以文本形式写入 stderr。
996
+
997
+ 失败或取消且已经生成运行结果时,stdout 仍可能包含输出:文本模式输出已收集的最终结果文本,JSON 模式输出结果对象。若在生成运行结果前失败,例如找不到工作流或尚未确认信任,则不保证产生 stdout 结果。脚本应检查退出码,不能仅凭 stdout 有内容或 JSON 中的 `outputs` 非空判断成功。
998
+
999
+ | 退出码 | 含义 |
1000
+ | --- | --- |
1001
+ | `0` | 完成 |
1002
+ | `1` | 运行失败、被拒绝或普通取消等错误 |
1003
+ | `2` | 参数解析错误 |
1004
+ | `124` | 工作流运行超时 |
1005
+ | `130` | CLI 捕获到键盘中断 |