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.
- chrys/__init__.py +16 -0
- chrys/app/__init__.py +3 -0
- chrys/app/acp/__init__.py +3 -0
- chrys/app/acp/bridge.py +664 -0
- chrys/app/acp/content.py +132 -0
- chrys/app/acp/doc/frontend-api.md +425 -0
- chrys/app/acp/history.py +585 -0
- chrys/app/acp/server.py +1796 -0
- chrys/app/acp/session_manager.py +1815 -0
- chrys/app/acp/tool_status.py +45 -0
- chrys/app/cli/__init__.py +3 -0
- chrys/app/cli/acp.py +178 -0
- chrys/app/cli/app.py +165 -0
- chrys/app/cli/approvals.py +101 -0
- chrys/app/cli/headless.py +223 -0
- chrys/app/cli/launch_cwd.py +42 -0
- chrys/app/cli/profiles.py +298 -0
- chrys/app/cli/progress.py +857 -0
- chrys/app/cli/run.py +425 -0
- chrys/app/cli/serve.py +1593 -0
- chrys/app/cli/tool_summary.py +225 -0
- chrys/app/cli/trajectory.py +201 -0
- chrys/app/cli/workflow.py +601 -0
- chrys/app/features/__init__.py +3 -0
- chrys/app/features/buddy/__init__.py +3 -0
- chrys/app/features/buddy/actions.py +68 -0
- chrys/app/features/buddy/animation.py +76 -0
- chrys/app/features/buddy/commands.py +196 -0
- chrys/app/features/buddy/docs/design.md +187 -0
- chrys/app/features/buddy/hatchery.py +80 -0
- chrys/app/features/buddy/lifecycle.py +41 -0
- chrys/app/features/buddy/model.py +265 -0
- chrys/app/features/buddy/pixel_renderer.py +113 -0
- chrys/app/features/buddy/pixel_sprites.py +279 -0
- chrys/app/features/buddy/portrait.py +76 -0
- chrys/app/features/buddy/progression.py +58 -0
- chrys/app/features/buddy/replies.py +191 -0
- chrys/app/features/buddy/sprites/alien.toml +70 -0
- chrys/app/features/buddy/sprites/axolotl.toml +71 -0
- chrys/app/features/buddy/sprites/bat.toml +69 -0
- chrys/app/features/buddy/sprites/bee.toml +69 -0
- chrys/app/features/buddy/sprites/cactus.toml +73 -0
- chrys/app/features/buddy/sprites/capybara.toml +70 -0
- chrys/app/features/buddy/sprites/cat.toml +69 -0
- chrys/app/features/buddy/sprites/crab.toml +70 -0
- chrys/app/features/buddy/sprites/dragon.toml +71 -0
- chrys/app/features/buddy/sprites/duck.toml +69 -0
- chrys/app/features/buddy/sprites/fox.toml +69 -0
- chrys/app/features/buddy/sprites/frog.toml +70 -0
- chrys/app/features/buddy/sprites/ghost.toml +70 -0
- chrys/app/features/buddy/sprites/goose.toml +69 -0
- chrys/app/features/buddy/sprites/jelly.toml +70 -0
- chrys/app/features/buddy/sprites/llama.toml +70 -0
- chrys/app/features/buddy/sprites/mushroom.toml +69 -0
- chrys/app/features/buddy/sprites/octopus.toml +70 -0
- chrys/app/features/buddy/sprites/owl.toml +70 -0
- chrys/app/features/buddy/sprites/panda.toml +71 -0
- chrys/app/features/buddy/sprites/penguin.toml +69 -0
- chrys/app/features/buddy/sprites/rabbit.toml +70 -0
- chrys/app/features/buddy/sprites/robot.toml +72 -0
- chrys/app/features/buddy/sprites/shark.toml +70 -0
- chrys/app/features/buddy/sprites/snail.toml +69 -0
- chrys/app/features/buddy/sprites/snake.toml +69 -0
- chrys/app/features/buddy/sprites/tabby.toml +69 -0
- chrys/app/features/buddy/sprites/turtle.toml +69 -0
- chrys/app/features/buddy/store.py +143 -0
- chrys/app/features/session_title/__init__.py +7 -0
- chrys/app/features/session_title/updater.py +582 -0
- chrys/app/installer.py +651 -0
- chrys/app/parsing.py +17 -0
- chrys/app/tui/__init__.py +3 -0
- chrys/app/tui/app.py +1287 -0
- chrys/app/tui/behaviors/__init__.py +3 -0
- chrys/app/tui/behaviors/click_outside_dismiss.py +90 -0
- chrys/app/tui/behaviors/insert_clipboard.py +73 -0
- chrys/app/tui/behaviors/right_click_copy.py +146 -0
- chrys/app/tui/binding_display.py +139 -0
- chrys/app/tui/buddy_messages.py +17 -0
- chrys/app/tui/buddy_reply.py +86 -0
- chrys/app/tui/chrys.tcss +549 -0
- chrys/app/tui/clipboard.py +109 -0
- chrys/app/tui/copy_messages.py +10 -0
- chrys/app/tui/i18n.py +230 -0
- chrys/app/tui/language.py +58 -0
- chrys/app/tui/notifications/__init__.py +12 -0
- chrys/app/tui/notifications/drivers.py +180 -0
- chrys/app/tui/notifications/service.py +126 -0
- chrys/app/tui/notifications/settings.py +141 -0
- chrys/app/tui/screens/__init__.py +3 -0
- chrys/app/tui/screens/agents/__init__.py +8 -0
- chrys/app/tui/screens/agents/agent_draft_store.py +937 -0
- chrys/app/tui/screens/agents/config.py +2142 -0
- chrys/app/tui/screens/agents/config.tcss +169 -0
- chrys/app/tui/screens/agents/panels/__init__.py +3 -0
- chrys/app/tui/screens/agents/panels/acp.py +1176 -0
- chrys/app/tui/screens/agents/panels/basic.py +497 -0
- chrys/app/tui/screens/agents/panels/compaction.py +231 -0
- chrys/app/tui/screens/agents/panels/config_card.py +218 -0
- chrys/app/tui/screens/agents/panels/instructions.py +91 -0
- chrys/app/tui/screens/agents/panels/markdown_report.py +76 -0
- chrys/app/tui/screens/agents/panels/mcp.py +2262 -0
- chrys/app/tui/screens/agents/panels/memory.py +684 -0
- chrys/app/tui/screens/agents/panels/path_entry.py +227 -0
- chrys/app/tui/screens/agents/panels/skills.py +806 -0
- chrys/app/tui/screens/agents/panels/subagents.py +652 -0
- chrys/app/tui/screens/agents/panels/tools.py +205 -0
- chrys/app/tui/screens/agents/picker.py +103 -0
- chrys/app/tui/screens/agents/skill_paths.py +38 -0
- chrys/app/tui/screens/agents/validation_messages.py +452 -0
- chrys/app/tui/screens/dialogs/__init__.py +35 -0
- chrys/app/tui/screens/dialogs/agent_load.py +834 -0
- chrys/app/tui/screens/dialogs/agent_load.tcss +78 -0
- chrys/app/tui/screens/dialogs/app_mode.py +55 -0
- chrys/app/tui/screens/dialogs/approval/__init__.py +15 -0
- chrys/app/tui/screens/dialogs/approval/approval.tcss +311 -0
- chrys/app/tui/screens/dialogs/approval/bodies/__init__.py +3 -0
- chrys/app/tui/screens/dialogs/approval/bodies/file_edit.py +210 -0
- chrys/app/tui/screens/dialogs/approval/bodies/sub_agent.py +82 -0
- chrys/app/tui/screens/dialogs/approval/body.py +110 -0
- chrys/app/tui/screens/dialogs/approval/dialog.py +565 -0
- chrys/app/tui/screens/dialogs/approval/mode.py +105 -0
- chrys/app/tui/screens/dialogs/ask_user.py +148 -0
- chrys/app/tui/screens/dialogs/ask_user.tcss +62 -0
- chrys/app/tui/screens/dialogs/base.py +84 -0
- chrys/app/tui/screens/dialogs/confirm.py +184 -0
- chrys/app/tui/screens/dialogs/confirm.tcss +46 -0
- chrys/app/tui/screens/dialogs/connection_test.py +183 -0
- chrys/app/tui/screens/dialogs/connection_test.tcss +92 -0
- chrys/app/tui/screens/dialogs/diagram.py +102 -0
- chrys/app/tui/screens/dialogs/diagram.tcss +24 -0
- chrys/app/tui/screens/dialogs/editor.py +378 -0
- chrys/app/tui/screens/dialogs/editor.tcss +132 -0
- chrys/app/tui/screens/dialogs/file_picker.py +582 -0
- chrys/app/tui/screens/dialogs/file_picker.tcss +78 -0
- chrys/app/tui/screens/dialogs/fork_session.py +219 -0
- chrys/app/tui/screens/dialogs/fork_session.tcss +75 -0
- chrys/app/tui/screens/dialogs/image_compression.py +102 -0
- chrys/app/tui/screens/dialogs/image_compression.tcss +28 -0
- chrys/app/tui/screens/dialogs/man_page.py +172 -0
- chrys/app/tui/screens/dialogs/man_page.tcss +39 -0
- chrys/app/tui/screens/dialogs/new_folder.py +277 -0
- chrys/app/tui/screens/dialogs/new_folder.tcss +51 -0
- chrys/app/tui/screens/dialogs/notice.tcss +14 -0
- chrys/app/tui/screens/dialogs/prompt_cache.py +144 -0
- chrys/app/tui/screens/dialogs/prompt_cache.tcss +38 -0
- chrys/app/tui/screens/dialogs/runtime_details.py +371 -0
- chrys/app/tui/screens/dialogs/runtime_details.tcss +49 -0
- chrys/app/tui/screens/dialogs/session_title.py +110 -0
- chrys/app/tui/screens/dialogs/session_title.tcss +43 -0
- chrys/app/tui/screens/dialogs/tool_view.py +207 -0
- chrys/app/tui/screens/dialogs/tool_view.tcss +43 -0
- chrys/app/tui/screens/dialogs/vision_unsupported.py +122 -0
- chrys/app/tui/screens/dialogs/vision_unsupported.tcss +35 -0
- chrys/app/tui/screens/dialogs/workflow_confirm.py +91 -0
- chrys/app/tui/screens/dialogs/workflow_confirm.tcss +17 -0
- chrys/app/tui/screens/dialogs/workflow_input.py +258 -0
- chrys/app/tui/screens/dialogs/workflow_input.tcss +73 -0
- chrys/app/tui/screens/dialogs/workflow_node.py +462 -0
- chrys/app/tui/screens/dialogs/workflow_node.tcss +41 -0
- chrys/app/tui/screens/dialogs/workflow_picker.py +46 -0
- chrys/app/tui/screens/dialogs/workflow_result.py +136 -0
- chrys/app/tui/screens/dialogs/workflow_result.tcss +14 -0
- chrys/app/tui/screens/diff/__init__.py +22 -0
- chrys/app/tui/screens/diff/rollback_modal.py +1381 -0
- chrys/app/tui/screens/diff/rollback_modal.tcss +248 -0
- chrys/app/tui/screens/diff/screen.py +1532 -0
- chrys/app/tui/screens/diff/screen.tcss +104 -0
- chrys/app/tui/screens/guides/__init__.py +7 -0
- chrys/app/tui/screens/guides/_docs/en/guides/configuration/agents.md +178 -0
- chrys/app/tui/screens/guides/_docs/en/guides/configuration/approval.md +117 -0
- chrys/app/tui/screens/guides/_docs/en/guides/configuration/chat-options.md +276 -0
- chrys/app/tui/screens/guides/_docs/en/guides/configuration/compaction.md +42 -0
- chrys/app/tui/screens/guides/_docs/en/guides/configuration/memory.md +48 -0
- chrys/app/tui/screens/guides/_docs/en/guides/configuration/models.md +158 -0
- chrys/app/tui/screens/guides/_docs/en/guides/configuration/settings.md +210 -0
- chrys/app/tui/screens/guides/_docs/en/guides/configuration/themes.md +61 -0
- chrys/app/tui/screens/guides/_docs/en/guides/configuration/tools.md +60 -0
- chrys/app/tui/screens/guides/_docs/en/guides/configuration/web-tools.md +286 -0
- chrys/app/tui/screens/guides/_docs/en/guides/daily-use/sessions.md +77 -0
- chrys/app/tui/screens/guides/_docs/en/guides/daily-use/workspaces.md +51 -0
- chrys/app/tui/screens/guides/_docs/en/guides/extensions/external-acp-agents.md +126 -0
- chrys/app/tui/screens/guides/_docs/en/guides/extensions/hooks.md +167 -0
- chrys/app/tui/screens/guides/_docs/en/guides/extensions/mcp.md +95 -0
- chrys/app/tui/screens/guides/_docs/en/guides/extensions/skills.md +175 -0
- chrys/app/tui/screens/guides/_docs/en/guides/running/icode-acp.md +61 -0
- chrys/app/tui/screens/guides/_docs/en/guides/running/icode-run.md +190 -0
- chrys/app/tui/screens/guides/_docs/en/guides/running/icode-serve.md +239 -0
- chrys/app/tui/screens/guides/_docs/en/guides/running/workflows.md +664 -0
- chrys/app/tui/screens/guides/_docs/en/reference/agent-profile.md +548 -0
- chrys/app/tui/screens/guides/_docs/en/reference/hooks.md +602 -0
- chrys/app/tui/screens/guides/_docs/en/reference/opentelemetry.md +177 -0
- chrys/app/tui/screens/guides/_docs/en/reference/settings.md +245 -0
- chrys/app/tui/screens/guides/_docs/en/reference/themes.md +149 -0
- chrys/app/tui/screens/guides/_docs/en/reference/tool-kinds-and-names.md +58 -0
- chrys/app/tui/screens/guides/_docs/en/reference/tui-slash-commands.md +76 -0
- chrys/app/tui/screens/guides/_docs/en/reference/workflows.md +1006 -0
- chrys/app/tui/screens/guides/_docs/en/start/getting-started.md +170 -0
- chrys/app/tui/screens/guides/_docs/en/start/what-is-icode.md +34 -0
- chrys/app/tui/screens/guides/_docs/index.yaml +100 -0
- chrys/app/tui/screens/guides/_docs/zh-Hans/guides/configuration/agents.md +178 -0
- chrys/app/tui/screens/guides/_docs/zh-Hans/guides/configuration/approval.md +117 -0
- chrys/app/tui/screens/guides/_docs/zh-Hans/guides/configuration/chat-options.md +276 -0
- chrys/app/tui/screens/guides/_docs/zh-Hans/guides/configuration/compaction.md +42 -0
- chrys/app/tui/screens/guides/_docs/zh-Hans/guides/configuration/memory.md +48 -0
- chrys/app/tui/screens/guides/_docs/zh-Hans/guides/configuration/models.md +158 -0
- chrys/app/tui/screens/guides/_docs/zh-Hans/guides/configuration/settings.md +210 -0
- chrys/app/tui/screens/guides/_docs/zh-Hans/guides/configuration/themes.md +61 -0
- chrys/app/tui/screens/guides/_docs/zh-Hans/guides/configuration/tools.md +60 -0
- chrys/app/tui/screens/guides/_docs/zh-Hans/guides/configuration/web-tools.md +286 -0
- chrys/app/tui/screens/guides/_docs/zh-Hans/guides/daily-use/sessions.md +77 -0
- chrys/app/tui/screens/guides/_docs/zh-Hans/guides/daily-use/workspaces.md +51 -0
- chrys/app/tui/screens/guides/_docs/zh-Hans/guides/extensions/external-acp-agents.md +126 -0
- chrys/app/tui/screens/guides/_docs/zh-Hans/guides/extensions/hooks.md +167 -0
- chrys/app/tui/screens/guides/_docs/zh-Hans/guides/extensions/mcp.md +95 -0
- chrys/app/tui/screens/guides/_docs/zh-Hans/guides/extensions/skills.md +175 -0
- chrys/app/tui/screens/guides/_docs/zh-Hans/guides/running/icode-acp.md +61 -0
- chrys/app/tui/screens/guides/_docs/zh-Hans/guides/running/icode-run.md +190 -0
- chrys/app/tui/screens/guides/_docs/zh-Hans/guides/running/icode-serve.md +239 -0
- chrys/app/tui/screens/guides/_docs/zh-Hans/guides/running/workflows.md +664 -0
- chrys/app/tui/screens/guides/_docs/zh-Hans/reference/agent-profile.md +548 -0
- chrys/app/tui/screens/guides/_docs/zh-Hans/reference/hooks.md +602 -0
- chrys/app/tui/screens/guides/_docs/zh-Hans/reference/opentelemetry.md +177 -0
- chrys/app/tui/screens/guides/_docs/zh-Hans/reference/settings.md +245 -0
- chrys/app/tui/screens/guides/_docs/zh-Hans/reference/themes.md +149 -0
- chrys/app/tui/screens/guides/_docs/zh-Hans/reference/tool-kinds-and-names.md +58 -0
- chrys/app/tui/screens/guides/_docs/zh-Hans/reference/tui-slash-commands.md +76 -0
- chrys/app/tui/screens/guides/_docs/zh-Hans/reference/workflows.md +1005 -0
- chrys/app/tui/screens/guides/_docs/zh-Hans/start/getting-started.md +170 -0
- chrys/app/tui/screens/guides/_docs/zh-Hans/start/what-is-icode.md +34 -0
- chrys/app/tui/screens/guides/index.py +215 -0
- chrys/app/tui/screens/guides/reader.py +173 -0
- chrys/app/tui/screens/guides/screen.py +442 -0
- chrys/app/tui/screens/guides/screen.tcss +52 -0
- chrys/app/tui/screens/logs/__init__.py +7 -0
- chrys/app/tui/screens/logs/screen.py +504 -0
- chrys/app/tui/screens/logs/screen.tcss +45 -0
- chrys/app/tui/screens/main/__init__.py +7 -0
- chrys/app/tui/screens/main/action_availability.py +30 -0
- chrys/app/tui/screens/main/buddy_command.py +143 -0
- chrys/app/tui/screens/main/commands.py +1073 -0
- chrys/app/tui/screens/main/config_actions.py +464 -0
- chrys/app/tui/screens/main/copy_actions.py +117 -0
- chrys/app/tui/screens/main/dialog_controllers.py +826 -0
- chrys/app/tui/screens/main/dialog_gateway.py +166 -0
- chrys/app/tui/screens/main/diff_controller.py +478 -0
- chrys/app/tui/screens/main/engine_read_model.py +184 -0
- chrys/app/tui/screens/main/event_handlers.py +2014 -0
- chrys/app/tui/screens/main/input_flow.py +241 -0
- chrys/app/tui/screens/main/live_diff.py +244 -0
- chrys/app/tui/screens/main/main_screen_presenter.py +295 -0
- chrys/app/tui/screens/main/model_indicator.py +217 -0
- chrys/app/tui/screens/main/navigation.py +343 -0
- chrys/app/tui/screens/main/ports.py +571 -0
- chrys/app/tui/screens/main/recent_dirs.py +123 -0
- chrys/app/tui/screens/main/rollback_controller.py +586 -0
- chrys/app/tui/screens/main/runtime_info.py +71 -0
- chrys/app/tui/screens/main/screen.py +2265 -0
- chrys/app/tui/screens/main/screen.tcss +21 -0
- chrys/app/tui/screens/main/session_handlers.py +1127 -0
- chrys/app/tui/screens/main/session_title.py +239 -0
- chrys/app/tui/screens/main/settings_coordinator.py +365 -0
- chrys/app/tui/screens/main/settings_persistence.py +184 -0
- chrys/app/tui/screens/main/shell_mode.py +112 -0
- chrys/app/tui/screens/main/state.py +289 -0
- chrys/app/tui/screens/main/submit_state.py +11 -0
- chrys/app/tui/screens/main/subscriptions.py +177 -0
- chrys/app/tui/screens/main/suggestions.py +982 -0
- chrys/app/tui/screens/main/tool_action_bridge.py +75 -0
- chrys/app/tui/screens/main/view_adapter.py +1567 -0
- chrys/app/tui/screens/main/workflow_browser.py +747 -0
- chrys/app/tui/screens/main/workflow_content.py +248 -0
- chrys/app/tui/screens/main/workflow_controller.py +240 -0
- chrys/app/tui/screens/main/workflow_feedback.py +137 -0
- chrys/app/tui/screens/main/workflow_flow.py +49 -0
- chrys/app/tui/screens/main/workflow_run_control.py +456 -0
- chrys/app/tui/screens/main/workflow_session_view.py +316 -0
- chrys/app/tui/screens/main/workspace_actions.py +272 -0
- chrys/app/tui/screens/main/workspace_branch.py +194 -0
- chrys/app/tui/screens/menus/__init__.py +8 -0
- chrys/app/tui/screens/menus/languages.py +114 -0
- chrys/app/tui/screens/models/__init__.py +7 -0
- chrys/app/tui/screens/models/picker.py +147 -0
- chrys/app/tui/screens/models/screen.py +2043 -0
- chrys/app/tui/screens/models/screen.tcss +255 -0
- chrys/app/tui/screens/sessions/__init__.py +8 -0
- chrys/app/tui/screens/sessions/presenter.py +586 -0
- chrys/app/tui/screens/sessions/screen.py +779 -0
- chrys/app/tui/screens/sessions/screen.tcss +127 -0
- chrys/app/tui/screens/settings/__init__.py +29 -0
- chrys/app/tui/screens/settings/danger.py +26 -0
- chrys/app/tui/screens/settings/dialog.py +281 -0
- chrys/app/tui/screens/settings/layout.py +519 -0
- chrys/app/tui/screens/settings/migrate_dialog.py +253 -0
- chrys/app/tui/screens/settings/panes/__init__.py +3 -0
- chrys/app/tui/screens/settings/panes/notifications.py +248 -0
- chrys/app/tui/screens/settings/panes/sessions.py +148 -0
- chrys/app/tui/screens/settings/ports.py +55 -0
- chrys/app/tui/screens/settings/provenance.py +102 -0
- chrys/app/tui/screens/settings/rows.py +546 -0
- chrys/app/tui/screens/settings/settings.tcss +406 -0
- chrys/app/tui/screens/themes/__init__.py +8 -0
- chrys/app/tui/screens/themes/dialogs.py +330 -0
- chrys/app/tui/screens/themes/editor.py +632 -0
- chrys/app/tui/screens/themes/editor.tcss +268 -0
- chrys/app/tui/screens/themes/messages.py +95 -0
- chrys/app/tui/screens/themes/palette.py +694 -0
- chrys/app/tui/screens/themes/panel.py +113 -0
- chrys/app/tui/screens/themes/picker.py +203 -0
- chrys/app/tui/screens/themes/save.py +191 -0
- chrys/app/tui/support/__init__.py +3 -0
- chrys/app/tui/support/file_manager.py +64 -0
- chrys/app/tui/support/gc_freeze.py +1114 -0
- chrys/app/tui/support/path_shortcuts.py +50 -0
- chrys/app/tui/support/prompt_history.py +298 -0
- chrys/app/tui/support/workspace_mru.py +476 -0
- chrys/app/tui/terminal/__init__.py +6 -0
- chrys/app/tui/terminal/_pty_backend.py +114 -0
- chrys/app/tui/terminal/emulator/__init__.py +24 -0
- chrys/app/tui/terminal/emulator/buffer.py +456 -0
- chrys/app/tui/terminal/emulator/charsets.py +113 -0
- chrys/app/tui/terminal/emulator/core.py +963 -0
- chrys/app/tui/terminal/emulator/input.py +342 -0
- chrys/app/tui/terminal/emulator/parser.py +227 -0
- chrys/app/tui/terminal/emulator/pen.py +158 -0
- chrys/app/tui/terminal/launcher.py +455 -0
- chrys/app/tui/terminal/leaked_reports.py +44 -0
- chrys/app/tui/terminal/panel.py +323 -0
- chrys/app/tui/terminal/pty_process.py +405 -0
- chrys/app/tui/terminal/rendering.py +151 -0
- chrys/app/tui/terminal/shell.py +273 -0
- chrys/app/tui/terminal/shell_integration.py +199 -0
- chrys/app/tui/terminal/title.py +224 -0
- chrys/app/tui/terminal/widget.py +654 -0
- chrys/app/tui/theme.py +422 -0
- chrys/app/tui/theme_loader.py +201 -0
- chrys/app/tui/theme_stylesheet.py +49 -0
- chrys/app/tui/themes/__init__.py +3 -0
- chrys/app/tui/themes/document.py +120 -0
- chrys/app/tui/themes/preview.py +170 -0
- chrys/app/tui/themes/store.py +176 -0
- chrys/app/tui/toasts.py +69 -0
- chrys/app/tui/util/__init__.py +3 -0
- chrys/app/tui/util/context_pressure.py +146 -0
- chrys/app/tui/util/debug_log.py +292 -0
- chrys/app/tui/util/diff_entries.py +64 -0
- chrys/app/tui/util/formatting.py +53 -0
- chrys/app/tui/util/git_branch.py +326 -0
- chrys/app/tui/util/invocation_progress.py +57 -0
- chrys/app/tui/util/logo.py +32 -0
- chrys/app/tui/util/message_gate.py +35 -0
- chrys/app/tui/util/mutation_sources.py +14 -0
- chrys/app/tui/util/picker_text.py +27 -0
- chrys/app/tui/util/removal.py +47 -0
- chrys/app/tui/util/rich_style.py +36 -0
- chrys/app/tui/util/source_text.py +12 -0
- chrys/app/tui/util/static_update.py +88 -0
- chrys/app/tui/util/todo_format.py +51 -0
- chrys/app/tui/util/visibility.py +214 -0
- chrys/app/tui/widgets/__init__.py +60 -0
- chrys/app/tui/widgets/ask_user_controls.py +652 -0
- chrys/app/tui/widgets/ask_user_markdown.py +17 -0
- chrys/app/tui/widgets/ask_user_prompt.py +606 -0
- chrys/app/tui/widgets/buttons.py +52 -0
- chrys/app/tui/widgets/chat/__init__.py +3 -0
- chrys/app/tui/widgets/chat/agent_transcript_surface.py +818 -0
- chrys/app/tui/widgets/chat/chrome.py +296 -0
- chrys/app/tui/widgets/chat/compaction_card.py +353 -0
- chrys/app/tui/widgets/chat/context_fold.py +77 -0
- chrys/app/tui/widgets/chat/file_snapshot.py +91 -0
- chrys/app/tui/widgets/chat/image_preview.py +214 -0
- chrys/app/tui/widgets/chat/live_renderer.py +383 -0
- chrys/app/tui/widgets/chat/messages.py +1039 -0
- chrys/app/tui/widgets/chat/panel.py +1769 -0
- chrys/app/tui/widgets/chat/ports.py +245 -0
- chrys/app/tui/widgets/chat/renderers/__init__.py +7 -0
- chrys/app/tui/widgets/chat/renderers/ask_user.py +747 -0
- chrys/app/tui/widgets/chat/renderers/execute.py +431 -0
- chrys/app/tui/widgets/chat/renderers/file_edit.py +925 -0
- chrys/app/tui/widgets/chat/renderers/hosted_code.py +83 -0
- chrys/app/tui/widgets/chat/renderers/hosted_generic.py +330 -0
- chrys/app/tui/widgets/chat/renderers/hosted_image.py +107 -0
- chrys/app/tui/widgets/chat/renderers/hosted_mcp.py +43 -0
- chrys/app/tui/widgets/chat/renderers/hosted_search.py +167 -0
- chrys/app/tui/widgets/chat/renderers/hosted_shell.py +132 -0
- chrys/app/tui/widgets/chat/renderers/read_file.py +399 -0
- chrys/app/tui/widgets/chat/renderers/search.py +348 -0
- chrys/app/tui/widgets/chat/renderers/skill.py +564 -0
- chrys/app/tui/widgets/chat/renderers/sleep.py +287 -0
- chrys/app/tui/widgets/chat/renderers/sub_agent.py +1385 -0
- chrys/app/tui/widgets/chat/renderers/todo.py +114 -0
- chrys/app/tui/widgets/chat/renderers/web.py +69 -0
- chrys/app/tui/widgets/chat/replay.py +1605 -0
- chrys/app/tui/widgets/chat/replay_mount.py +322 -0
- chrys/app/tui/widgets/chat/scroll_controller.py +579 -0
- chrys/app/tui/widgets/chat/selection_controller.py +435 -0
- chrys/app/tui/widgets/chat/session_json.py +508 -0
- chrys/app/tui/widgets/chat/toc_model.py +156 -0
- chrys/app/tui/widgets/chat/tool_call.py +2478 -0
- chrys/app/tui/widgets/chat/tool_registry.py +753 -0
- chrys/app/tui/widgets/chat/tool_renderers.py +247 -0
- chrys/app/tui/widgets/chat/tool_view_builders.py +260 -0
- chrys/app/tui/widgets/chat/transcript_reader.py +57 -0
- chrys/app/tui/widgets/checkbox.py +24 -0
- chrys/app/tui/widgets/chrome/__init__.py +3 -0
- chrys/app/tui/widgets/chrome/app_header.py +283 -0
- chrys/app/tui/widgets/chrome/commands.py +95 -0
- chrys/app/tui/widgets/chrome/file_index.py +68 -0
- chrys/app/tui/widgets/chrome/file_scanner.py +670 -0
- chrys/app/tui/widgets/chrome/footer.py +284 -0
- chrys/app/tui/widgets/chrome/image_paste.py +351 -0
- chrys/app/tui/widgets/chrome/input_bar.py +1299 -0
- chrys/app/tui/widgets/chrome/status_bar.py +911 -0
- chrys/app/tui/widgets/chrome/suggestion_list.py +652 -0
- chrys/app/tui/widgets/click_affordance.py +24 -0
- chrys/app/tui/widgets/color_picker/__init__.py +254 -0
- chrys/app/tui/widgets/color_picker/controls.py +171 -0
- chrys/app/tui/widgets/color_picker/model.py +89 -0
- chrys/app/tui/widgets/dialog_buttons.py +58 -0
- chrys/app/tui/widgets/dialog_scroll.py +24 -0
- chrys/app/tui/widgets/diff_view/__init__.py +20 -0
- chrys/app/tui/widgets/diff_view/cells.py +59 -0
- chrys/app/tui/widgets/diff_view/code.py +280 -0
- chrys/app/tui/widgets/diff_view/compute.py +286 -0
- chrys/app/tui/widgets/diff_view/gutter.py +161 -0
- chrys/app/tui/widgets/diff_view/inline.py +77 -0
- chrys/app/tui/widgets/diff_view/palette.py +87 -0
- chrys/app/tui/widgets/diff_view/protocols.py +24 -0
- chrys/app/tui/widgets/diff_view/rows.py +138 -0
- chrys/app/tui/widgets/diff_view/unified.py +267 -0
- chrys/app/tui/widgets/diff_view/widget.py +209 -0
- chrys/app/tui/widgets/editor/__init__.py +79 -0
- chrys/app/tui/widgets/editor/coordinates.py +30 -0
- chrys/app/tui/widgets/editor/highlighter.py +139 -0
- chrys/app/tui/widgets/editor/keymaps.py +357 -0
- chrys/app/tui/widgets/editor/types.py +216 -0
- chrys/app/tui/widgets/editor/vim.py +1195 -0
- chrys/app/tui/widgets/editor/widget.py +401 -0
- chrys/app/tui/widgets/file_preview.py +58 -0
- chrys/app/tui/widgets/hatch.py +138 -0
- chrys/app/tui/widgets/input.py +66 -0
- chrys/app/tui/widgets/loading.py +125 -0
- chrys/app/tui/widgets/markdown/__init__.py +25 -0
- chrys/app/tui/widgets/markdown/_utils.py +21 -0
- chrys/app/tui/widgets/markdown/anchors.py +71 -0
- chrys/app/tui/widgets/markdown/blocks.py +115 -0
- chrys/app/tui/widgets/markdown/copyable.py +163 -0
- chrys/app/tui/widgets/markdown/diagram/__init__.py +35 -0
- chrys/app/tui/widgets/markdown/diagram/canvas.py +409 -0
- chrys/app/tui/widgets/markdown/diagram/charts.py +52 -0
- chrys/app/tui/widgets/markdown/diagram/diagnostics.py +101 -0
- chrys/app/tui/widgets/markdown/diagram/geometry.py +46 -0
- chrys/app/tui/widgets/markdown/diagram/layout.py +494 -0
- chrys/app/tui/widgets/markdown/diagram/messages.py +18 -0
- chrys/app/tui/widgets/markdown/diagram/model.py +275 -0
- chrys/app/tui/widgets/markdown/diagram/parser.py +173 -0
- chrys/app/tui/widgets/markdown/diagram/parsers/__init__.py +3 -0
- chrys/app/tui/widgets/markdown/diagram/parsers/charts.py +349 -0
- chrys/app/tui/widgets/markdown/diagram/parsers/common.py +403 -0
- chrys/app/tui/widgets/markdown/diagram/parsers/graphs.py +1072 -0
- chrys/app/tui/widgets/markdown/diagram/parsers/planning.py +317 -0
- chrys/app/tui/widgets/markdown/diagram/parsers/schedule.py +298 -0
- chrys/app/tui/widgets/markdown/diagram/parsers/schemas.py +241 -0
- chrys/app/tui/widgets/markdown/diagram/parsers/structure.py +221 -0
- chrys/app/tui/widgets/markdown/diagram/presentation.py +32 -0
- chrys/app/tui/widgets/markdown/diagram/renderers/__init__.py +3 -0
- chrys/app/tui/widgets/markdown/diagram/renderers/charts.py +275 -0
- chrys/app/tui/widgets/markdown/diagram/renderers/common.py +73 -0
- chrys/app/tui/widgets/markdown/diagram/renderers/planning.py +157 -0
- chrys/app/tui/widgets/markdown/diagram/renderers/schedule.py +202 -0
- chrys/app/tui/widgets/markdown/diagram/renderers/structure.py +77 -0
- chrys/app/tui/widgets/markdown/diagram/renderers/xy.py +385 -0
- chrys/app/tui/widgets/markdown/diagram/router.py +651 -0
- chrys/app/tui/widgets/markdown/diagram/specs/__init__.py +3 -0
- chrys/app/tui/widgets/markdown/diagram/specs/charts.py +94 -0
- chrys/app/tui/widgets/markdown/diagram/specs/planning.py +68 -0
- chrys/app/tui/widgets/markdown/diagram/specs/schedule.py +65 -0
- chrys/app/tui/widgets/markdown/diagram/specs/structure.py +23 -0
- chrys/app/tui/widgets/markdown/diagram/viewer.py +92 -0
- chrys/app/tui/widgets/markdown/links.py +47 -0
- chrys/app/tui/widgets/markdown/math/__init__.py +36 -0
- chrys/app/tui/widgets/markdown/math/layout.py +739 -0
- chrys/app/tui/widgets/markdown/math/markdown.py +291 -0
- chrys/app/tui/widgets/markdown/math/parser.py +325 -0
- chrys/app/tui/widgets/markdown/math/symbols.py +325 -0
- chrys/app/tui/widgets/markdown/navigator.py +80 -0
- chrys/app/tui/widgets/markdown/parser.py +1057 -0
- chrys/app/tui/widgets/markdown/stream.py +73 -0
- chrys/app/tui/widgets/markdown/toc.py +98 -0
- chrys/app/tui/widgets/markdown/viewer.py +146 -0
- chrys/app/tui/widgets/markdown/widget.py +2046 -0
- chrys/app/tui/widgets/marquee.py +101 -0
- chrys/app/tui/widgets/option_menu.py +82 -0
- chrys/app/tui/widgets/page_navigator.py +118 -0
- chrys/app/tui/widgets/select.py +196 -0
- chrys/app/tui/widgets/selection.py +59 -0
- chrys/app/tui/widgets/sidebar/__init__.py +3 -0
- chrys/app/tui/widgets/sidebar/buddy.py +367 -0
- chrys/app/tui/widgets/sidebar/context.py +482 -0
- chrys/app/tui/widgets/sidebar/debug.py +195 -0
- chrys/app/tui/widgets/sidebar/empty_state.py +11 -0
- chrys/app/tui/widgets/sidebar/panel.py +198 -0
- chrys/app/tui/widgets/sidebar/tasks.py +198 -0
- chrys/app/tui/widgets/sidebar/toc.py +166 -0
- chrys/app/tui/widgets/sidebar/toc_types.py +30 -0
- chrys/app/tui/widgets/syntax_theme.py +85 -0
- chrys/app/tui/widgets/text_area.py +258 -0
- chrys/app/tui/widgets/trajectory/__init__.py +8 -0
- chrys/app/tui/widgets/trajectory/chartkit.py +264 -0
- chrys/app/tui/widgets/trajectory/insights.py +1266 -0
- chrys/app/tui/widgets/trajectory/overview.py +1101 -0
- chrys/app/tui/widgets/trajectory/panel.py +983 -0
- chrys/app/tui/widgets/trajectory/presentation.py +311 -0
- chrys/app/tui/widgets/trajectory/session_info.py +124 -0
- chrys/app/tui/widgets/trajectory/text_view.py +124 -0
- chrys/app/tui/widgets/trajectory/timeline.py +380 -0
- chrys/app/tui/widgets/welcome.py +126 -0
- chrys/app/tui/widgets/workflow/__init__.py +5 -0
- chrys/app/tui/widgets/workflow/edges.py +89 -0
- chrys/app/tui/widgets/workflow/graph.py +869 -0
- chrys/app/tui/widgets/workflow/info.py +310 -0
- chrys/app/tui/widgets/workflow/node_view.py +27 -0
- chrys/app/tui/widgets/workflow/output.py +225 -0
- chrys/app/tui/widgets/workflow/panel.py +658 -0
- chrys/app/tui/widgets/workflow/projector.py +324 -0
- chrys/app/tui/widgets/workflow/records.py +69 -0
- chrys/app/tui/widgets/workflow/scrollbar.py +82 -0
- chrys/app/tui/widgets/workflow/selection.py +151 -0
- chrys/app/tui/widgets/workflow/source.py +65 -0
- chrys/app/tui/widgets/workflow/text.py +257 -0
- chrys/app/tui/widgets/workflow/values.py +317 -0
- chrys/foundation/__init__.py +0 -0
- chrys/foundation/branding.py +15 -0
- chrys/foundation/config/__init__.py +7 -0
- chrys/foundation/config/coercion.py +374 -0
- chrys/foundation/config/context.py +34 -0
- chrys/foundation/config/env_file.py +141 -0
- chrys/foundation/config/env_layers.py +370 -0
- chrys/foundation/config/migrations.py +521 -0
- chrys/foundation/config/notification_events.py +22 -0
- chrys/foundation/config/process_settings.py +332 -0
- chrys/foundation/config/runtime_pointer.py +133 -0
- chrys/foundation/config/settings.py +1952 -0
- chrys/foundation/config/settings_store.py +996 -0
- chrys/foundation/config/spec.py +396 -0
- chrys/foundation/config/user_settings.py +140 -0
- chrys/foundation/config/warnings.py +262 -0
- chrys/foundation/config/web_values.py +135 -0
- chrys/foundation/config/yaml_store.py +487 -0
- chrys/foundation/errors/__init__.py +68 -0
- chrys/foundation/errors/_legacy.py +117 -0
- chrys/foundation/errors/_text.py +13 -0
- chrys/foundation/errors/_walk.py +85 -0
- chrys/foundation/errors/classify.py +278 -0
- chrys/foundation/errors/display.py +274 -0
- chrys/foundation/errors/formatting.py +283 -0
- chrys/foundation/errors/kinds.py +67 -0
- chrys/foundation/errors/network.py +497 -0
- chrys/foundation/errors/provider.py +445 -0
- chrys/foundation/errors/route.py +85 -0
- chrys/foundation/events/__init__.py +8 -0
- chrys/foundation/events/bus.py +143 -0
- chrys/foundation/events/types.py +1629 -0
- chrys/foundation/events/workflow.py +38 -0
- chrys/foundation/hosted_tools.py +142 -0
- chrys/foundation/i18n/__init__.py +32 -0
- chrys/foundation/i18n/_catalogs/zh-Hans/LC_MESSAGES/chrys.mo +0 -0
- chrys/foundation/i18n/catalogs.py +42 -0
- chrys/foundation/i18n/formatting.py +202 -0
- chrys/foundation/i18n/locale.py +92 -0
- chrys/foundation/i18n/localizer.py +187 -0
- chrys/foundation/i18n/messages.py +268 -0
- chrys/foundation/io/__init__.py +3 -0
- chrys/foundation/io/result_content.py +237 -0
- chrys/foundation/models/__init__.py +3 -0
- chrys/foundation/models/approval_reuse.py +23 -0
- chrys/foundation/models/ask_user.py +468 -0
- chrys/foundation/models/execution.py +18 -0
- chrys/foundation/models/history_markers.py +115 -0
- chrys/foundation/models/invocations.py +63 -0
- chrys/foundation/models/mutation_scope.py +28 -0
- chrys/foundation/models/session_env.py +87 -0
- chrys/foundation/models/session_surface.py +29 -0
- chrys/foundation/models/todos.py +74 -0
- chrys/foundation/models/turns.py +125 -0
- chrys/foundation/models/workflow_session.py +89 -0
- chrys/foundation/models/workspace.py +59 -0
- chrys/foundation/net/__init__.py +3 -0
- chrys/foundation/net/address_class.py +57 -0
- chrys/foundation/net/route_probe.py +94 -0
- chrys/foundation/net/url.py +107 -0
- chrys/foundation/observability/__init__.py +3 -0
- chrys/foundation/observability/exporters.py +174 -0
- chrys/foundation/observability/gate.py +31 -0
- chrys/foundation/observability/setup.py +497 -0
- chrys/foundation/observability/sink.py +228 -0
- chrys/foundation/patches/__init__.py +19 -0
- chrys/foundation/patches/mdurl_cache.py +59 -0
- chrys/foundation/patches/patcher.py +287 -0
- chrys/foundation/patches/staged_members.py +205 -0
- chrys/foundation/patches/textual_block_border.py +105 -0
- chrys/foundation/patches/textual_button_ansi.py +65 -0
- chrys/foundation/patches/textual_button_ansi_old.txt +68 -0
- chrys/foundation/patches/textual_callback_cache.py +248 -0
- chrys/foundation/patches/textual_callback_dispatch.py +109 -0
- chrys/foundation/patches/textual_compositor_cjk.py +566 -0
- chrys/foundation/patches/textual_dispatch_cache.py +150 -0
- chrys/foundation/patches/textual_ime_cursor_anchor.py +92 -0
- chrys/foundation/patches/textual_kitty_keyboard.py +268 -0
- chrys/foundation/patches/textual_lru_acyclic.py +241 -0
- chrys/foundation/patches/textual_message_pump.py +136 -0
- chrys/foundation/patches/textual_node_diet.py +875 -0
- chrys/foundation/patches/textual_one_shot_timer.py +48 -0
- chrys/foundation/patches/textual_option_list.py +90 -0
- chrys/foundation/patches/textual_precompose.py +89 -0
- chrys/foundation/patches/textual_pruned_tabs.py +69 -0
- chrys/foundation/patches/textual_reflow_reuse.py +1753 -0
- chrys/foundation/patches/textual_removed_node_caches.py +86 -0
- chrys/foundation/patches/textual_removed_screen_callbacks.py +55 -0
- chrys/foundation/patches/textual_selection_extract.py +48 -0
- chrys/foundation/patches/textual_strip_cycles.py +119 -0
- chrys/foundation/patches/textual_tab_selection.py +1611 -0
- chrys/foundation/patches/textual_timer_skip.py +70 -0
- chrys/foundation/patches/textual_utf8_decoder.py +106 -0
- chrys/foundation/patches/textual_win_sleep.py +167 -0
- chrys/foundation/patches/watchdog_fsevents.py +70 -0
- chrys/foundation/patches/watchdog_windows.py +52 -0
- chrys/foundation/platform/__init__.py +556 -0
- chrys/foundation/platform/c_api.py +32 -0
- chrys/foundation/platform/child_reap.py +107 -0
- chrys/foundation/platform/command_line.py +95 -0
- chrys/foundation/platform/files.py +1470 -0
- chrys/foundation/platform/output_capture.py +113 -0
- chrys/foundation/platform/paths.py +193 -0
- chrys/foundation/platform/process.py +1468 -0
- chrys/foundation/platform/pty_output.py +19 -0
- chrys/foundation/platform/runtime_paths.py +281 -0
- chrys/foundation/platform/win_console.py +129 -0
- chrys/foundation/reasoning_origin.py +67 -0
- chrys/foundation/recovery.py +16 -0
- chrys/foundation/retry.py +278 -0
- chrys/foundation/text/__init__.py +3 -0
- chrys/foundation/text/encoding.py +603 -0
- chrys/foundation/text/images.py +304 -0
- chrys/foundation/text/lines.py +24 -0
- chrys/foundation/text/mentions.py +90 -0
- chrys/foundation/text/model_json.py +25 -0
- chrys/foundation/text/reading_order.py +20 -0
- chrys/foundation/text/tokenizer.py +25 -0
- chrys/foundation/text/tool_output.py +287 -0
- chrys/foundation/text/yaml_io.py +62 -0
- chrys/foundation/tool_call_context.py +202 -0
- chrys/foundation/tool_execution_stamp.py +184 -0
- chrys/foundation/tool_invocation_order.py +48 -0
- chrys/foundation/tool_kinds.py +102 -0
- chrys/foundation/tool_result_metadata.py +287 -0
- chrys/foundation/trajectory/__init__.py +10 -0
- chrys/foundation/trajectory/context.py +481 -0
- chrys/foundation/trajectory/envelope.py +571 -0
- chrys/foundation/trajectory/event_types.py +294 -0
- chrys/foundation/trajectory/finalizers.py +46 -0
- chrys/foundation/trajectory/fingerprint.py +62 -0
- chrys/foundation/trajectory/ids.py +155 -0
- chrys/foundation/trajectory/keys.py +99 -0
- chrys/foundation/trajectory/lease.py +173 -0
- chrys/foundation/trajectory/metadata.py +72 -0
- chrys/foundation/trajectory/reader.py +271 -0
- chrys/foundation/trajectory/recovery.py +225 -0
- chrys/foundation/trajectory/revisions.py +152 -0
- chrys/foundation/trajectory/segments.py +225 -0
- chrys/foundation/trajectory/tools.py +117 -0
- chrys/foundation/trajectory/usage.py +151 -0
- chrys/foundation/trajectory/writer.py +972 -0
- chrys/foundation/trajectory_timing.py +97 -0
- chrys/foundation/util/__init__.py +3 -0
- chrys/foundation/util/async_tasks.py +29 -0
- chrys/foundation/util/chrys_headers.py +23 -0
- chrys/foundation/util/env_templates.py +104 -0
- chrys/foundation/util/filenames.py +96 -0
- chrys/foundation/util/header_charset.py +138 -0
- chrys/foundation/util/httpx_helpers.py +12 -0
- chrys/foundation/util/lock.py +236 -0
- chrys/foundation/util/once_close.py +46 -0
- chrys/foundation/util/session_ids.py +29 -0
- chrys/foundation/util/shell_tokens.py +88 -0
- chrys/foundation/util/sub_agent_context.py +38 -0
- chrys/foundation/util/time.py +35 -0
- chrys/foundation/util/unicode_scalars.py +36 -0
- chrys/foundation/vendor/__init__.py +43 -0
- chrys/foundation/vendor/ripgrep/rg-aarch64-apple-darwin +0 -0
- chrys/foundation/vendor/ripgrep/rg-aarch64-pc-windows-msvc.exe +0 -0
- chrys/foundation/vendor/ripgrep/rg-aarch64-unknown-linux-gnu +0 -0
- chrys/foundation/vendor/ripgrep/rg-x86_64-apple-darwin +0 -0
- chrys/foundation/vendor/ripgrep/rg-x86_64-pc-windows-msvc.exe +0 -0
- chrys/foundation/vendor/ripgrep/rg-x86_64-unknown-linux-musl +0 -0
- chrys/kernel/__init__.py +256 -0
- chrys/kernel/_content.py +1866 -0
- chrys/kernel/_loop_recorder.py +631 -0
- chrys/kernel/_null_overlay.py +1026 -0
- chrys/kernel/_result_ceiling.py +216 -0
- chrys/kernel/_serialization.py +431 -0
- chrys/kernel/_tool_arg_errors.py +1629 -0
- chrys/kernel/_tool_execution.py +1172 -0
- chrys/kernel/_tool_expansion.py +26 -0
- chrys/kernel/_types.py +2598 -0
- chrys/kernel/agent.py +994 -0
- chrys/kernel/client.py +1084 -0
- chrys/kernel/compaction.py +1315 -0
- chrys/kernel/exceptions.py +211 -0
- chrys/kernel/exchanges.py +683 -0
- chrys/kernel/identity.py +95 -0
- chrys/kernel/images.py +36 -0
- chrys/kernel/instrumentation.py +1618 -0
- chrys/kernel/loop.py +2308 -0
- chrys/kernel/middleware.py +616 -0
- chrys/kernel/sessions.py +604 -0
- chrys/kernel/tools.py +1061 -0
- chrys/kernel/types.py +126 -0
- chrys/orchestration/__init__.py +3 -0
- chrys/orchestration/engine/__init__.py +3 -0
- chrys/orchestration/engine/assembly.py +236 -0
- chrys/orchestration/engine/build/__init__.py +3 -0
- chrys/orchestration/engine/build/builder.py +1061 -0
- chrys/orchestration/engine/build/construction.py +408 -0
- chrys/orchestration/engine/build/loaded.py +139 -0
- chrys/orchestration/engine/engine.py +789 -0
- chrys/orchestration/engine/execution.py +771 -0
- chrys/orchestration/engine/loader.py +865 -0
- chrys/orchestration/engine/rollback.py +918 -0
- chrys/orchestration/engine/run/__init__.py +3 -0
- chrys/orchestration/engine/run/active_injection.py +419 -0
- chrys/orchestration/engine/run/attachments.py +519 -0
- chrys/orchestration/engine/run/bindings.py +1095 -0
- chrys/orchestration/engine/run/coordinator.py +1062 -0
- chrys/orchestration/engine/run/finalizer.py +417 -0
- chrys/orchestration/engine/run/input_refs.py +60 -0
- chrys/orchestration/engine/run/prompt_content.py +457 -0
- chrys/orchestration/engine/run/resume.py +299 -0
- chrys/orchestration/engine/run/retry.py +948 -0
- chrys/orchestration/engine/run/runner.py +625 -0
- chrys/orchestration/engine/run/runtime_skills.py +146 -0
- chrys/orchestration/engine/run/sub_agent_coordination.py +126 -0
- chrys/orchestration/engine/run/turn_hooks.py +258 -0
- chrys/orchestration/engine/run/turn_state.py +149 -0
- chrys/orchestration/engine/run/working_dir.py +50 -0
- chrys/orchestration/engine/session_lifecycle.py +2013 -0
- chrys/orchestration/engine/state/__init__.py +3 -0
- chrys/orchestration/engine/state/active_session.py +183 -0
- chrys/orchestration/engine/state/controls.py +639 -0
- chrys/orchestration/engine/state/current_agent.py +26 -0
- chrys/orchestration/engine/state/lifecycle_permits.py +395 -0
- chrys/orchestration/engine/state/machine.py +193 -0
- chrys/orchestration/engine/state/session_writer.py +434 -0
- chrys/orchestration/engine/trajectory.py +714 -0
- chrys/orchestration/engine/usage.py +118 -0
- chrys/orchestration/invoker/__init__.py +3 -0
- chrys/orchestration/invoker/acp.py +727 -0
- chrys/orchestration/invoker/acp_protocol.py +1115 -0
- chrys/orchestration/invoker/acp_spec.py +79 -0
- chrys/orchestration/invoker/attempts.py +994 -0
- chrys/orchestration/invoker/child_compaction.py +131 -0
- chrys/orchestration/invoker/child_history.py +99 -0
- chrys/orchestration/invoker/contracts.py +253 -0
- chrys/orchestration/invoker/evidence.py +94 -0
- chrys/orchestration/invoker/kernel.py +343 -0
- chrys/orchestration/invoker/origin.py +79 -0
- chrys/orchestration/invoker/resources.py +343 -0
- chrys/orchestration/invoker/runtime.py +299 -0
- chrys/orchestration/invoker/usage.py +80 -0
- chrys/orchestration/session_hooks.py +117 -0
- chrys/orchestration/session_host.py +1023 -0
- chrys/orchestration/session_resources.py +95 -0
- chrys/orchestration/session_usage.py +219 -0
- chrys/orchestration/startup.py +255 -0
- chrys/orchestration/sub_agents/__init__.py +3 -0
- chrys/orchestration/sub_agents/acp_policy.py +269 -0
- chrys/orchestration/sub_agents/kernel_policy.py +848 -0
- chrys/orchestration/sub_agents/registration.py +44 -0
- chrys/orchestration/sub_agents/shell.py +337 -0
- chrys/orchestration/sub_agents/tools.py +2228 -0
- chrys/orchestration/workflows/__init__.py +3 -0
- chrys/orchestration/workflows/agent_archive.py +156 -0
- chrys/orchestration/workflows/agent_node.py +894 -0
- chrys/orchestration/workflows/agent_node_build.py +687 -0
- chrys/orchestration/workflows/catalog.py +332 -0
- chrys/orchestration/workflows/coordinator.py +771 -0
- chrys/orchestration/workflows/hooks.py +176 -0
- chrys/orchestration/workflows/preview.py +322 -0
- chrys/orchestration/workflows/rollback.py +151 -0
- chrys/orchestration/workflows/runner.py +986 -0
- chrys/orchestration/workflows/session.py +390 -0
- chrys/orchestration/workflows/settings.py +97 -0
- chrys/orchestration/workflows/validation.py +674 -0
- chrys/orchestration/workflows/worker_client.py +1002 -0
- chrys/service/__init__.py +3 -0
- chrys/service/acp_client/__init__.py +65 -0
- chrys/service/acp_client/_transport.py +922 -0
- chrys/service/acp_client/client.py +1311 -0
- chrys/service/acp_client/errors.py +224 -0
- chrys/service/acp_client/protocol.py +220 -0
- chrys/service/acp_client/spawn.py +239 -0
- chrys/service/acp_client/spec.py +100 -0
- chrys/service/agent_middleware/__init__.py +60 -0
- chrys/service/agent_middleware/_metadata_keys.py +52 -0
- chrys/service/agent_middleware/control/__init__.py +3 -0
- chrys/service/agent_middleware/control/approval.py +769 -0
- chrys/service/agent_middleware/control/approval_hooks.py +62 -0
- chrys/service/agent_middleware/control/ask_user.py +207 -0
- chrys/service/agent_middleware/control/interrupt.py +50 -0
- chrys/service/agent_middleware/control/sleep.py +118 -0
- chrys/service/agent_middleware/control/todo.py +117 -0
- chrys/service/agent_middleware/events/__init__.py +3 -0
- chrys/service/agent_middleware/events/hook_dispatch.py +250 -0
- chrys/service/agent_middleware/events/hosted_tools.py +1762 -0
- chrys/service/agent_middleware/events/intermediate_text.py +128 -0
- chrys/service/agent_middleware/events/rejection_metadata.py +50 -0
- chrys/service/agent_middleware/events/result_persistence.py +98 -0
- chrys/service/agent_middleware/events/sub_agent_events.py +951 -0
- chrys/service/agent_middleware/events/tool_error_text.py +22 -0
- chrys/service/agent_middleware/events/tool_events.py +779 -0
- chrys/service/agent_middleware/injection.py +510 -0
- chrys/service/agent_middleware/reminders/__init__.py +91 -0
- chrys/service/agent_middleware/reminders/archive_pointer.py +154 -0
- chrys/service/agent_middleware/reminders/base.py +25 -0
- chrys/service/agent_middleware/reminders/context_usage.py +74 -0
- chrys/service/agent_middleware/reminders/file_change.py +63 -0
- chrys/service/agent_middleware/reminders/mcp.py +39 -0
- chrys/service/agent_middleware/reminders/profile_switch.py +106 -0
- chrys/service/agent_middleware/reminders/runtime_env.py +190 -0
- chrys/service/agent_middleware/reminders/skills.py +44 -0
- chrys/service/agent_middleware/reminders/sub_agents.py +35 -0
- chrys/service/agent_middleware/reminders/todo.py +35 -0
- chrys/service/agent_middleware/reminders/turn_line.py +48 -0
- chrys/service/agent_middleware/response_validation.py +1380 -0
- chrys/service/agent_middleware/system_reminder.py +1107 -0
- chrys/service/agent_middleware/validators.py +396 -0
- chrys/service/analytics/__init__.py +124 -0
- chrys/service/analytics/_actions.py +896 -0
- chrys/service/analytics/_context_evidence.py +357 -0
- chrys/service/analytics/_critical_path.py +179 -0
- chrys/service/analytics/_facts.py +919 -0
- chrys/service/analytics/_insights.py +769 -0
- chrys/service/analytics/_metric_ops.py +83 -0
- chrys/service/analytics/_session_projection.py +460 -0
- chrys/service/analytics/_timeline.py +434 -0
- chrys/service/analytics/_turn_graph.py +1237 -0
- chrys/service/analytics/_turns.py +1377 -0
- chrys/service/analytics/_workflows.py +171 -0
- chrys/service/analytics/aggregation.py +1474 -0
- chrys/service/analytics/classification.py +128 -0
- chrys/service/analytics/export.py +803 -0
- chrys/service/analytics/findings.py +282 -0
- chrys/service/analytics/math.py +79 -0
- chrys/service/analytics/model.py +886 -0
- chrys/service/analytics/reader.py +321 -0
- chrys/service/approval/__init__.py +3 -0
- chrys/service/approval/arbitration.py +102 -0
- chrys/service/approval/command_identity.py +109 -0
- chrys/service/approval/correlation.py +57 -0
- chrys/service/approval/grant_store.py +108 -0
- chrys/service/approval/judge.py +589 -0
- chrys/service/approval/level.py +15 -0
- chrys/service/approval/policy.py +209 -0
- chrys/service/approval/reuse.py +223 -0
- chrys/service/approval/reuse_binding.py +133 -0
- chrys/service/approval/safety_classifier.py +536 -0
- chrys/service/approval/turn_context.py +49 -0
- chrys/service/context/__init__.py +3 -0
- chrys/service/context/compaction/__init__.py +38 -0
- chrys/service/context/compaction/breaker.py +156 -0
- chrys/service/context/compaction/budgets.py +93 -0
- chrys/service/context/compaction/calibration.py +77 -0
- chrys/service/context/compaction/compression.py +690 -0
- chrys/service/context/compaction/current_turn_drop.py +458 -0
- chrys/service/context/compaction/events.py +201 -0
- chrys/service/context/compaction/exclusions.py +261 -0
- chrys/service/context/compaction/groups.py +361 -0
- chrys/service/context/compaction/last_words.py +1996 -0
- chrys/service/context/compaction/last_words_state.py +752 -0
- chrys/service/context/compaction/scoped.py +472 -0
- chrys/service/context/compaction/spill.py +1947 -0
- chrys/service/context/compaction/strategy.py +1116 -0
- chrys/service/context/compaction/summaries.py +319 -0
- chrys/service/context/compaction/turns.py +375 -0
- chrys/service/context/manager.py +174 -0
- chrys/service/context/memory_loader.py +792 -0
- chrys/service/context/middleware/__init__.py +3 -0
- chrys/service/context/middleware/usage.py +332 -0
- chrys/service/context/providers/__init__.py +3 -0
- chrys/service/context/providers/context_management.py +432 -0
- chrys/service/context/providers/history.py +647 -0
- chrys/service/context/providers/memory.py +50 -0
- chrys/service/context/tool_content.py +22 -0
- chrys/service/hooks/__init__.py +37 -0
- chrys/service/hooks/detached_worker.py +118 -0
- chrys/service/hooks/docs/README.md +14 -0
- chrys/service/hooks/docs/authoring.md +684 -0
- chrys/service/hooks/docs/configuration.md +499 -0
- chrys/service/hooks/docs/design.md +359 -0
- chrys/service/hooks/docs/project-hooks.md +348 -0
- chrys/service/hooks/events.py +157 -0
- chrys/service/hooks/loader.py +665 -0
- chrys/service/hooks/manager.py +807 -0
- chrys/service/hooks/matcher.py +111 -0
- chrys/service/hooks/outbox.py +294 -0
- chrys/service/hooks/runner.py +572 -0
- chrys/service/hooks/schema.py +407 -0
- chrys/service/llm/__init__.py +7 -0
- chrys/service/llm/_structured_outputs.py +192 -0
- chrys/service/llm/anthropic_messages/__init__.py +9 -0
- chrys/service/llm/anthropic_messages/client.py +254 -0
- chrys/service/llm/anthropic_messages/decode.py +331 -0
- chrys/service/llm/anthropic_messages/history.py +279 -0
- chrys/service/llm/anthropic_messages/request.py +323 -0
- chrys/service/llm/anthropic_messages/server_tools.py +319 -0
- chrys/service/llm/anthropic_messages/stream.py +297 -0
- chrys/service/llm/anthropic_messages/thinking_binding.py +156 -0
- chrys/service/llm/chat_completions/__init__.py +9 -0
- chrys/service/llm/chat_completions/client.py +369 -0
- chrys/service/llm/chat_completions/decode.py +338 -0
- chrys/service/llm/chat_completions/history.py +657 -0
- chrys/service/llm/chat_completions/reasoning.py +244 -0
- chrys/service/llm/chat_completions/request.py +192 -0
- chrys/service/llm/chat_completions/stream.py +546 -0
- chrys/service/llm/chat_completions/validation.py +308 -0
- chrys/service/llm/clients.py +613 -0
- chrys/service/llm/images.py +65 -0
- chrys/service/llm/mock.py +413 -0
- chrys/service/llm/observer.py +446 -0
- chrys/service/llm/one_shot.py +106 -0
- chrys/service/llm/openai_exceptions.py +93 -0
- chrys/service/llm/openai_responses/__init__.py +10 -0
- chrys/service/llm/openai_responses/client.py +323 -0
- chrys/service/llm/openai_responses/decode.py +432 -0
- chrys/service/llm/openai_responses/history.py +519 -0
- chrys/service/llm/openai_responses/hosted.py +625 -0
- chrys/service/llm/openai_responses/replay.py +629 -0
- chrys/service/llm/openai_responses/request.py +342 -0
- chrys/service/llm/openai_responses/stream.py +847 -0
- chrys/service/llm/openai_timestamps.py +57 -0
- chrys/service/llm/providers.py +107 -0
- chrys/service/llm/proxy_route.py +54 -0
- chrys/service/llm/raw_http_log.py +309 -0
- chrys/service/llm/route_facts.py +63 -0
- chrys/service/llm/route_sessions.py +49 -0
- chrys/service/llm/sdk_anthropic.py +18 -0
- chrys/service/llm/sdk_headers.py +47 -0
- chrys/service/llm/sdk_openai.py +18 -0
- chrys/service/llm/sdk_retry.py +59 -0
- chrys/service/llm/wire_client.py +246 -0
- chrys/service/mcp/__init__.py +3 -0
- chrys/service/mcp/_connection.py +235 -0
- chrys/service/mcp/_http_transport.py +350 -0
- chrys/service/mcp/_progressive.py +459 -0
- chrys/service/mcp/_stdio_transport.py +614 -0
- chrys/service/mcp/_tool_mixins.py +96 -0
- chrys/service/mcp/adapter.py +1031 -0
- chrys/service/mcp/cache.py +476 -0
- chrys/service/mcp/content.py +32 -0
- chrys/service/mcp/errors.py +169 -0
- chrys/service/mcp/owned.py +1330 -0
- chrys/service/mcp/result_limits.py +168 -0
- chrys/service/mcp/thinking_warning.py +95 -0
- chrys/service/mcp/validation.py +74 -0
- chrys/service/mutations/__init__.py +84 -0
- chrys/service/mutations/coordination.py +894 -0
- chrys/service/mutations/detector.py +458 -0
- chrys/service/mutations/git_calibrator.py +397 -0
- chrys/service/mutations/git_state.py +647 -0
- chrys/service/mutations/pipeline.py +779 -0
- chrys/service/mutations/scanner.py +466 -0
- chrys/service/mutations/snapshot_files.py +233 -0
- chrys/service/mutations/store.py +625 -0
- chrys/service/mutations/tool_names.py +15 -0
- chrys/service/mutations/trace.py +246 -0
- chrys/service/mutations/tracker.py +1289 -0
- chrys/service/mutations/types.py +559 -0
- chrys/service/mutations/workspace_changes.py +1583 -0
- chrys/service/profiles/__init__.py +2 -0
- chrys/service/profiles/agents/__init__.py +3 -0
- chrys/service/profiles/agents/builtins/Code.yaml +199 -0
- chrys/service/profiles/agents/builtins/Explore.yaml +62 -0
- chrys/service/profiles/agents/builtins/General.yaml +114 -0
- chrys/service/profiles/agents/builtins/QA.yaml +128 -0
- chrys/service/profiles/agents/loader.py +808 -0
- chrys/service/profiles/agents/registry.py +727 -0
- chrys/service/profiles/agents/schema.py +371 -0
- chrys/service/profiles/agents/serializer.py +196 -0
- chrys/service/profiles/coercion.py +22 -0
- chrys/service/profiles/models/__init__.py +3 -0
- chrys/service/profiles/models/env_bridge.py +157 -0
- chrys/service/profiles/models/loader.py +282 -0
- chrys/service/profiles/models/options.py +438 -0
- chrys/service/profiles/models/registry.py +104 -0
- chrys/service/profiles/models/resolver.py +286 -0
- chrys/service/profiles/models/schema.py +91 -0
- chrys/service/profiles/models/serializer.py +76 -0
- chrys/service/session/__init__.py +3 -0
- chrys/service/session/checkpoint.py +156 -0
- chrys/service/session/history.py +1616 -0
- chrys/service/session/message_metadata.py +151 -0
- chrys/service/session/persistence.py +435 -0
- chrys/service/session/runtime_metadata.py +210 -0
- chrys/service/session/sub_agent_logs.py +1069 -0
- chrys/service/session/sub_agent_transcript.py +654 -0
- chrys/service/skills/__init__.py +3 -0
- chrys/service/skills/adapter.py +408 -0
- chrys/service/skills/constants.py +8 -0
- chrys/service/skills/loader.py +575 -0
- chrys/service/skills/model.py +130 -0
- chrys/service/skills/provider.py +841 -0
- chrys/service/skills/runner.py +390 -0
- chrys/service/state/__init__.py +3 -0
- chrys/service/state/_fork.py +710 -0
- chrys/service/state/_session_files.py +175 -0
- chrys/service/state/_session_meta.py +552 -0
- chrys/service/state/locks.py +154 -0
- chrys/service/state/serializers.py +156 -0
- chrys/service/state/session_catalog.py +361 -0
- chrys/service/state/session_listing.py +84 -0
- chrys/service/state/session_migration.py +446 -0
- chrys/service/state/session_mru.py +315 -0
- chrys/service/state/store.py +2132 -0
- chrys/service/state/workflow.py +158 -0
- chrys/service/text_blocks.py +47 -0
- chrys/service/todos/__init__.py +3 -0
- chrys/service/todos/reminder.py +31 -0
- chrys/service/todos/tracker.py +58 -0
- chrys/service/tools/__init__.py +3 -0
- chrys/service/tools/approval_targets.py +92 -0
- chrys/service/tools/builtins/__init__.py +3 -0
- chrys/service/tools/builtins/ask_user.py +326 -0
- chrys/service/tools/builtins/doc_converter/__init__.py +494 -0
- chrys/service/tools/builtins/doc_converter/artifacts.py +392 -0
- chrys/service/tools/builtins/doc_converter/parsers/__init__.py +3 -0
- chrys/service/tools/builtins/doc_converter/parsers/_table.py +34 -0
- chrys/service/tools/builtins/doc_converter/parsers/base.py +101 -0
- chrys/service/tools/builtins/doc_converter/parsers/docx.py +88 -0
- chrys/service/tools/builtins/doc_converter/parsers/pdf.py +144 -0
- chrys/service/tools/builtins/doc_converter/parsers/pptx.py +103 -0
- chrys/service/tools/builtins/doc_converter/parsers/xls.py +32 -0
- chrys/service/tools/builtins/doc_converter/parsers/xlsx.py +51 -0
- chrys/service/tools/builtins/doc_converter/registry.py +55 -0
- chrys/service/tools/builtins/filesystem.py +1071 -0
- chrys/service/tools/builtins/search.py +1265 -0
- chrys/service/tools/builtins/shell.py +967 -0
- chrys/service/tools/builtins/shell_command_filtering/__init__.py +5 -0
- chrys/service/tools/builtins/shell_command_filtering/policy.py +60 -0
- chrys/service/tools/builtins/shell_command_filtering/presets.py +152 -0
- chrys/service/tools/builtins/shell_command_filtering/readonly/__init__.py +358 -0
- chrys/service/tools/builtins/shell_command_filtering/readonly/commands.py +416 -0
- chrys/service/tools/builtins/shell_command_filtering/readonly/git.py +408 -0
- chrys/service/tools/builtins/shell_command_filtering/readonly/syntax.py +87 -0
- chrys/service/tools/builtins/shell_command_filtering/tokenizer.py +214 -0
- chrys/service/tools/builtins/shell_filter.py +24 -0
- chrys/service/tools/builtins/sleep.py +91 -0
- chrys/service/tools/builtins/todo.py +64 -0
- chrys/service/tools/builtins/web/__init__.py +6 -0
- chrys/service/tools/builtins/web/build.py +268 -0
- chrys/service/tools/builtins/web/config.py +338 -0
- chrys/service/tools/builtins/web/credentials.py +37 -0
- chrys/service/tools/builtins/web/fetch/__init__.py +3 -0
- chrys/service/tools/builtins/web/fetch/cache.py +68 -0
- chrys/service/tools/builtins/web/fetch/convert.py +56 -0
- chrys/service/tools/builtins/web/fetch/tool.py +223 -0
- chrys/service/tools/builtins/web/hosted.py +61 -0
- chrys/service/tools/builtins/web/http.py +330 -0
- chrys/service/tools/builtins/web/progress.py +18 -0
- chrys/service/tools/builtins/web/search/__init__.py +3 -0
- chrys/service/tools/builtins/web/search/exa_mcp.py +146 -0
- chrys/service/tools/builtins/web/search/html.py +152 -0
- chrys/service/tools/builtins/web/search/json_api.py +227 -0
- chrys/service/tools/builtins/web/search/providers.py +77 -0
- chrys/service/tools/builtins/web/search/tool.py +218 -0
- chrys/service/tools/builtins/web/search/types.py +28 -0
- chrys/service/tools/builtins/web/tls_identity.py +66 -0
- chrys/service/tools/kinds.py +115 -0
- chrys/service/tools/names.py +47 -0
- chrys/service/tools/registry.py +242 -0
- chrys/service/tools/result_metadata.py +103 -0
- chrys/service/tools/session_artifacts.py +196 -0
- chrys/service/tools/spill.py +218 -0
- chrys/service/tools/workspace_paths.py +81 -0
- chrys/service/trajectory/__init__.py +11 -0
- chrys/service/trajectory/approvals.py +201 -0
- chrys/service/trajectory/compaction.py +420 -0
- chrys/service/trajectory/fork.py +75 -0
- chrys/service/trajectory/hooks.py +217 -0
- chrys/service/trajectory/items.py +41 -0
- chrys/service/trajectory/preparation.py +374 -0
- chrys/service/trajectory/retries.py +95 -0
- chrys/service/trajectory/revisions.py +129 -0
- chrys/service/trajectory/segmented.py +163 -0
- chrys/service/trajectory/session.py +762 -0
- chrys/service/trajectory/state.py +83 -0
- chrys/service/trajectory/sub_agents.py +169 -0
- chrys/service/trajectory/tombstone.py +262 -0
- chrys/service/trajectory/tools.py +323 -0
- chrys/service/trajectory/validation.py +130 -0
- chrys/service/trajectory/waits.py +161 -0
- chrys/service/trajectory/workflow.py +148 -0
- chrys/service/vision.py +128 -0
- chrys/service/workflows/__init__.py +3 -0
- chrys/service/workflows/admission.py +151 -0
- chrys/service/workflows/artifacts.py +109 -0
- chrys/service/workflows/asks.py +130 -0
- chrys/service/workflows/builtins/__init__.py +12 -0
- chrys/service/workflows/builtins/demo-workflow.manifest.json +635 -0
- chrys/service/workflows/builtins/demo-workflow.py +756 -0
- chrys/service/workflows/discovery.py +554 -0
- chrys/service/workflows/environment.py +284 -0
- chrys/service/workflows/graph.py +430 -0
- chrys/service/workflows/history.py +82 -0
- chrys/service/workflows/interpreter.py +107 -0
- chrys/service/workflows/journal.py +334 -0
- chrys/service/workflows/layout.py +56 -0
- chrys/service/workflows/ledger.py +149 -0
- chrys/service/workflows/model_selection.py +18 -0
- chrys/service/workflows/orphans.py +209 -0
- chrys/service/workflows/outcomes.py +46 -0
- chrys/service/workflows/protocol.py +210 -0
- chrys/service/workflows/records.py +142 -0
- chrys/service/workflows/scheduler.py +770 -0
- chrys/service/workflows/sdk/__init__.py +51 -0
- chrys/service/workflows/sdk/_ask.py +167 -0
- chrys/service/workflows/sdk/_builder.py +781 -0
- chrys/service/workflows/sdk/_values.py +92 -0
- chrys/service/workflows/sdk_artifact.py +74 -0
- chrys/service/workflows/store.py +494 -0
- chrys/service/workflows/transcript.py +102 -0
- chrys/service/workflows/values.py +73 -0
- chrys/service/workflows/worker_host.py +1820 -0
- chrys/workflows.py +38 -0
- icode_tui-0.29.1.dist-info/METADATA +104 -0
- icode_tui-0.29.1.dist-info/RECORD +1138 -0
- icode_tui-0.29.1.dist-info/WHEEL +4 -0
- icode_tui-0.29.1.dist-info/entry_points.txt +2 -0
- icode_tui-0.29.1.dist-info/licenses/LICENSE +202 -0
- icode_tui-0.29.1.dist-info/licenses/NOTICE +1955 -0
|
@@ -0,0 +1,848 @@
|
|
|
1
|
+
# Copyright (c) Huawei Technologies Co., Ltd. 2026. All rights reserved.
|
|
2
|
+
|
|
3
|
+
"""Kernel child recipe, retry history, result and audit policies for the common shell."""
|
|
4
|
+
|
|
5
|
+
from __future__ import annotations
|
|
6
|
+
|
|
7
|
+
import asyncio
|
|
8
|
+
import json
|
|
9
|
+
import logging
|
|
10
|
+
from datetime import UTC, datetime
|
|
11
|
+
from pathlib import Path
|
|
12
|
+
from typing import TYPE_CHECKING, Any, Literal, Protocol, TypeGuard, cast
|
|
13
|
+
|
|
14
|
+
from chrys.foundation.errors import clean_error_message
|
|
15
|
+
from chrys.foundation.errors.display import display_fields
|
|
16
|
+
from chrys.foundation.events.types import (
|
|
17
|
+
InvocationPaused,
|
|
18
|
+
InvocationRetryAttempt,
|
|
19
|
+
InvocationToolCallResult,
|
|
20
|
+
)
|
|
21
|
+
from chrys.foundation.hosted_tools import HostedToolStatus
|
|
22
|
+
from chrys.foundation.platform.files import atomic_write_owner_only_text
|
|
23
|
+
from chrys.foundation.retry import (
|
|
24
|
+
TRANSIENT_RETRY_BACKOFF_SECONDS,
|
|
25
|
+
StreamStall,
|
|
26
|
+
StreamStallExhausted,
|
|
27
|
+
)
|
|
28
|
+
from chrys.foundation.trajectory.context import TrajectoryContext
|
|
29
|
+
from chrys.foundation.trajectory.event_types import RetryMode, RetryReason
|
|
30
|
+
from chrys.foundation.trajectory.ids import new_analytics_id
|
|
31
|
+
from chrys.foundation.trajectory.metadata import ensure_analytics_item_id
|
|
32
|
+
from chrys.kernel import (
|
|
33
|
+
TOOL_RESULT_CONTENT_TYPES,
|
|
34
|
+
AgentResponse,
|
|
35
|
+
LoopRecorder,
|
|
36
|
+
Message,
|
|
37
|
+
)
|
|
38
|
+
from chrys.orchestration.invoker.attempts import (
|
|
39
|
+
AgentRunKwargs,
|
|
40
|
+
AttemptRecipe,
|
|
41
|
+
AttemptRunner,
|
|
42
|
+
AttemptTaskHandle,
|
|
43
|
+
BlockingCallTiming,
|
|
44
|
+
HistoryRollback,
|
|
45
|
+
KeepAndRaise,
|
|
46
|
+
ModelRunTrace,
|
|
47
|
+
RetryBoundaryPolicy,
|
|
48
|
+
has_live_continuation_token,
|
|
49
|
+
)
|
|
50
|
+
from chrys.orchestration.invoker.child_compaction import CompactionRollback
|
|
51
|
+
from chrys.orchestration.invoker.child_history import ChildHistory, service_storage_side
|
|
52
|
+
from chrys.orchestration.invoker.contracts import (
|
|
53
|
+
AbortCause,
|
|
54
|
+
ContinuationTicket,
|
|
55
|
+
Failed,
|
|
56
|
+
FailureDisposition,
|
|
57
|
+
InvocationOutcome,
|
|
58
|
+
Ok,
|
|
59
|
+
RunIntent,
|
|
60
|
+
RunRequest,
|
|
61
|
+
SubAgentFailureReason,
|
|
62
|
+
SubAgentStatus,
|
|
63
|
+
)
|
|
64
|
+
from chrys.orchestration.invoker.kernel import KernelConversation
|
|
65
|
+
from chrys.orchestration.invoker.origin import BoundEmitter
|
|
66
|
+
from chrys.orchestration.invoker.resources import Conversation, PassResources
|
|
67
|
+
from chrys.service.agent_middleware.events.hosted_tools import FinalSegment, adapt_hosted_tool, hosted_replay_status
|
|
68
|
+
from chrys.service.agent_middleware.response_validation import (
|
|
69
|
+
RetryableResponseValidationError,
|
|
70
|
+
)
|
|
71
|
+
from chrys.service.context.compaction.last_words import LastWordsGenerationError
|
|
72
|
+
from chrys.service.session.sub_agent_logs import preview_text
|
|
73
|
+
from chrys.service.tools.result_metadata import record_tool_success, tool_error
|
|
74
|
+
from chrys.service.trajectory.retries import RetryBackoffTrace
|
|
75
|
+
|
|
76
|
+
if TYPE_CHECKING:
|
|
77
|
+
from collections.abc import Callable, Sequence
|
|
78
|
+
|
|
79
|
+
from chrys.foundation.i18n import MessageRef
|
|
80
|
+
from chrys.kernel import Agent, AgentSession
|
|
81
|
+
from chrys.service.agent_middleware.control.sleep import SleepMiddleware
|
|
82
|
+
from chrys.service.agent_middleware.events.sub_agent_events import SubAgentEventMiddleware
|
|
83
|
+
from chrys.service.session.sub_agent_logs import SubAgentLogStats, SubAgentSessionLogWriter
|
|
84
|
+
|
|
85
|
+
from .shell import SubAgentToolShell
|
|
86
|
+
|
|
87
|
+
logger = logging.getLogger(__name__)
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
class HostedBaselineHook(Protocol):
|
|
91
|
+
"""Starts a pass's hosted-work baseline, as ``ResponseValidationMiddleware.begin_pass_hosted_baseline`` does."""
|
|
92
|
+
|
|
93
|
+
def __call__(self, *, resumes_background_response: bool) -> None: ...
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
def _is_string_keyed_dict(value: object) -> TypeGuard[dict[str, Any]]:
|
|
97
|
+
"""Narrow controller-owned kwargs dictionaries with string keys."""
|
|
98
|
+
return isinstance(value, dict)
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
# Retry/backoff knobs mirror TurnBindings's streaming retry budget so the UX
|
|
102
|
+
# feels the same between main-agent and sub-agent failures. The sub-agent
|
|
103
|
+
# retry loop uses the same schedule and cap.
|
|
104
|
+
_DEFAULT_MAX_RETRIES = 5
|
|
105
|
+
_DEFAULT_STREAM_ATTEMPT_TIMEOUT = 300.0
|
|
106
|
+
|
|
107
|
+
# Decisions resolved into the ``pending_decision`` future. Kept as string
|
|
108
|
+
# literals (not an Enum) because futures already pass values by identity —
|
|
109
|
+
# the point here is a readable debug repr.
|
|
110
|
+
_DECISION_RETRY = "retry"
|
|
111
|
+
_DECISION_ABORT = "abort"
|
|
112
|
+
_DECISION_CASCADE = "cascade_abort"
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
def _is_last_words_error(exc: BaseException) -> bool:
|
|
116
|
+
"""Detect :class:`LastWordsGenerationError` directly or on the cause chain."""
|
|
117
|
+
return any(isinstance(e, LastWordsGenerationError) for e in (exc, exc.__cause__) if e is not None)
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
def _service_retry_reason(exc: BaseException) -> str:
|
|
121
|
+
"""Closed trajectory reason for a sub-agent whole-run retry."""
|
|
122
|
+
if isinstance(exc, StreamStall | StreamStallExhausted):
|
|
123
|
+
return RetryReason.STREAM_STALL
|
|
124
|
+
if isinstance(exc, RetryableResponseValidationError):
|
|
125
|
+
return RetryReason.VALIDATION_REJECTED
|
|
126
|
+
return RetryReason.TRANSIENT_ERROR
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
class _CascadeInterruptProbe:
|
|
130
|
+
"""Read the controller latch without transferring cancellation ownership."""
|
|
131
|
+
|
|
132
|
+
def __init__(self, controller: KernelSubAgentPolicy) -> None:
|
|
133
|
+
self._controller = controller
|
|
134
|
+
|
|
135
|
+
@property
|
|
136
|
+
def is_interrupted(self) -> bool:
|
|
137
|
+
return self._controller._shell.cascade_requested
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
class KernelSubAgentPolicy:
|
|
141
|
+
"""Backend-specific policy; decision future, evidence and close binding live in the shell."""
|
|
142
|
+
|
|
143
|
+
def __init__(
|
|
144
|
+
self,
|
|
145
|
+
*,
|
|
146
|
+
shell: SubAgentToolShell,
|
|
147
|
+
conversation: Conversation,
|
|
148
|
+
agent: Agent,
|
|
149
|
+
session: AgentSession,
|
|
150
|
+
loop_recorder: LoopRecorder,
|
|
151
|
+
prompt: str,
|
|
152
|
+
run_kwargs: AgentRunKwargs,
|
|
153
|
+
parent_call_id: str = "",
|
|
154
|
+
parent_event_call_id: str = "",
|
|
155
|
+
sub_agent_log_file: str = "",
|
|
156
|
+
max_retries: int = _DEFAULT_MAX_RETRIES,
|
|
157
|
+
backoff_schedule: tuple[int, ...] = TRANSIENT_RETRY_BACKOFF_SECONDS,
|
|
158
|
+
persist_dir: Path | None = None,
|
|
159
|
+
log_writer: SubAgentSessionLogWriter | None = None,
|
|
160
|
+
log_stats: SubAgentLogStats | None = None,
|
|
161
|
+
terminal_audit_callback: Callable[[], None] | None = None,
|
|
162
|
+
pending_record_finalizer: Callable[[Path | None], None] | None = None,
|
|
163
|
+
tool_event_middleware: SubAgentEventMiddleware | None = None,
|
|
164
|
+
stream: bool = False,
|
|
165
|
+
stream_attempt_timeout: float | None = None,
|
|
166
|
+
sleep_middleware: SleepMiddleware | None = None,
|
|
167
|
+
pass_start_hooks: Sequence[Callable[[], None]] = (),
|
|
168
|
+
hosted_commits_probe: Callable[[], tuple[str, ...]] | None = None,
|
|
169
|
+
begin_hosted_baseline: HostedBaselineHook | None = None,
|
|
170
|
+
trajectory_context: TrajectoryContext | None = None,
|
|
171
|
+
trajectory_boundary_operation_id: str | None = None,
|
|
172
|
+
) -> None:
|
|
173
|
+
self._shell = shell
|
|
174
|
+
invocation_id = shell.invocation_id
|
|
175
|
+
tool_name = shell.tool_name
|
|
176
|
+
agent_name = shell.agent_name
|
|
177
|
+
event_bus = shell.bus
|
|
178
|
+
session_id = shell.origin.session_id or None
|
|
179
|
+
self._invocation_id = invocation_id
|
|
180
|
+
self.origin = shell.origin
|
|
181
|
+
self._emitter = BoundEmitter(event_bus, self.origin)
|
|
182
|
+
self._tool_name = tool_name
|
|
183
|
+
self._agent_name = agent_name
|
|
184
|
+
self._agent = agent
|
|
185
|
+
self._session = session
|
|
186
|
+
self._loop_recorder = loop_recorder
|
|
187
|
+
self._prompt = prompt
|
|
188
|
+
self._run_kwargs: AgentRunKwargs = {**run_kwargs, "session": session}
|
|
189
|
+
self._history = ChildHistory(session, loop_recorder)
|
|
190
|
+
self._service_storage = service_storage_side(agent.client, run_kwargs.get("options"))
|
|
191
|
+
self._compaction = CompactionRollback(run_kwargs.get("compaction_strategy"))
|
|
192
|
+
self._bus = event_bus
|
|
193
|
+
self._session_id = session_id
|
|
194
|
+
# The ``Content.call_id`` of the parent assistant function_call
|
|
195
|
+
# that invoked this sub-agent. Persisted so reload-recovery can
|
|
196
|
+
# pair a paused record back to its dangling function_call by id
|
|
197
|
+
# rather than by name+appearance-order, which mis-matches when
|
|
198
|
+
# the same sub-agent tool is invoked concurrently.
|
|
199
|
+
self._parent_call_id = parent_call_id
|
|
200
|
+
self._parent_event_call_id = parent_event_call_id
|
|
201
|
+
self._sub_agent_log_file = sub_agent_log_file
|
|
202
|
+
self._terminal_audit_persisted = False
|
|
203
|
+
self._max_retries = max_retries
|
|
204
|
+
self._backoff = backoff_schedule
|
|
205
|
+
self._persist_dir = persist_dir
|
|
206
|
+
self._log_writer = log_writer
|
|
207
|
+
self._log_stats = log_stats
|
|
208
|
+
self._terminal_audit_callback = terminal_audit_callback
|
|
209
|
+
self._pending_record_finalizer = pending_record_finalizer
|
|
210
|
+
self._tool_event_middleware = tool_event_middleware
|
|
211
|
+
self._stream = stream
|
|
212
|
+
self._stream_attempt_timeout = (
|
|
213
|
+
stream_attempt_timeout if stream_attempt_timeout is not None else _DEFAULT_STREAM_ATTEMPT_TIMEOUT
|
|
214
|
+
)
|
|
215
|
+
self._sleep_middleware = sleep_middleware
|
|
216
|
+
# The hosted baseline reads this policy's own request options, not the caller's run_kwargs: a
|
|
217
|
+
# whole-run retry replaces them, so only these say whether the pass polls a background response.
|
|
218
|
+
self._begin_hosted_baseline_hook = begin_hosted_baseline
|
|
219
|
+
# Fired at the start of every pass (initial run, or a user Retry
|
|
220
|
+
# decision after a pause). Components carrying state across a pass's
|
|
221
|
+
# whole-run retry attempts — the validation middleware's retry budget —
|
|
222
|
+
# register here so an aborted pass cannot leak state into the next
|
|
223
|
+
# one; mirrors the main executor's run_cycle_start_hooks.
|
|
224
|
+
self._pass_start_hooks = (*pass_start_hooks, self._begin_hosted_baseline)
|
|
225
|
+
# Validation-middleware probe for provider-hosted tool executions the
|
|
226
|
+
# loop recorder cannot see; consulted by the whole-run retry gate.
|
|
227
|
+
self._hosted_commits_probe = hosted_commits_probe
|
|
228
|
+
self._trajectory_context = trajectory_context
|
|
229
|
+
self._trajectory_boundary_operation_id = trajectory_boundary_operation_id
|
|
230
|
+
self._service_retry_trace: RetryBackoffTrace | None = None
|
|
231
|
+
|
|
232
|
+
self._last_error: str = ""
|
|
233
|
+
self._last_error_display: MessageRef | None = None
|
|
234
|
+
self._last_error_hint: MessageRef | None = None
|
|
235
|
+
self._failure_reason: SubAgentFailureReason | None = None
|
|
236
|
+
self._retry_attempts_total: int = 0
|
|
237
|
+
# The answer of the pass that completed the invocation, if any.
|
|
238
|
+
self.final_segment: FinalSegment | None = None
|
|
239
|
+
# The seed prompt is one persisted context item: it keeps a single
|
|
240
|
+
# analytics identity across prompt replays so the trajectory can
|
|
241
|
+
# account for every model request that re-sent it.
|
|
242
|
+
self._seed_item_id = new_analytics_id()
|
|
243
|
+
self._active_run_input: list[Any] = self._seed_input()
|
|
244
|
+
self._next_run_input: list[Any] = self._seed_input()
|
|
245
|
+
self._pass_start_index = 0
|
|
246
|
+
self._attempt_handle = AttemptTaskHandle()
|
|
247
|
+
attempt_recipe = AttemptRecipe(
|
|
248
|
+
stall_exhaustion=KeepAndRaise(),
|
|
249
|
+
stall_error=lambda timeout: StreamStall(f"no streaming updates received for {timeout:g}s"),
|
|
250
|
+
retry_boundary=RetryBoundaryPolicy.OBSERVE,
|
|
251
|
+
blocking_call_timing=BlockingCallTiming.BEFORE_ATTEMPT_TASK,
|
|
252
|
+
before_attempt=self._check_cascade,
|
|
253
|
+
history_state=self._history.state,
|
|
254
|
+
)
|
|
255
|
+
self._rollback = HistoryRollback(
|
|
256
|
+
session,
|
|
257
|
+
history_state=attempt_recipe.history_state,
|
|
258
|
+
snapshot_caller=self._compaction.snapshot,
|
|
259
|
+
restore_caller=self._compaction.restore,
|
|
260
|
+
)
|
|
261
|
+
self._attempts = AttemptRunner(
|
|
262
|
+
agent=agent,
|
|
263
|
+
session=session,
|
|
264
|
+
handle=self._attempt_handle,
|
|
265
|
+
rollback=self._rollback,
|
|
266
|
+
retry_participant=None,
|
|
267
|
+
interrupt=_CascadeInterruptProbe(self),
|
|
268
|
+
# Children have no model.run layer, so context stays None; the notice callback orders RetryBackoffTrace.
|
|
269
|
+
trace=ModelRunTrace(
|
|
270
|
+
interrupted=lambda: self._shell.cascade_requested,
|
|
271
|
+
service_side=lambda: self._service_storage,
|
|
272
|
+
committed=lambda: self._loop_recorder.committed_count > 0,
|
|
273
|
+
),
|
|
274
|
+
stream_observer=None,
|
|
275
|
+
publish_retry=self._publish_service_retry_attempt,
|
|
276
|
+
interruptible_sleep=self._sleep_for_service_retry,
|
|
277
|
+
max_retries=lambda: self.max_retries,
|
|
278
|
+
backoff_schedule=lambda: self.backoff_schedule,
|
|
279
|
+
stream_timeout=lambda: self._stream_attempt_timeout,
|
|
280
|
+
committed_count=lambda: self._loop_recorder.committed_count,
|
|
281
|
+
hosted_commits=lambda: self._hosted_commits_probe() if self._hosted_commits_probe is not None else (),
|
|
282
|
+
recipe=attempt_recipe,
|
|
283
|
+
)
|
|
284
|
+
|
|
285
|
+
self.backend = KernelConversation(
|
|
286
|
+
owner=conversation,
|
|
287
|
+
session=session,
|
|
288
|
+
attempts=self._attempts,
|
|
289
|
+
attempt_handle=self._attempt_handle,
|
|
290
|
+
observer=self,
|
|
291
|
+
run_kwargs=lambda: self._run_kwargs,
|
|
292
|
+
stream=lambda: self._stream,
|
|
293
|
+
service_side=lambda: self._service_storage,
|
|
294
|
+
recorder=loop_recorder,
|
|
295
|
+
hosted_observed=hosted_commits_probe,
|
|
296
|
+
start_hooks=self._pass_start_hooks,
|
|
297
|
+
failure_disposition=FailureDisposition.CALLER_DECISION,
|
|
298
|
+
)
|
|
299
|
+
|
|
300
|
+
async def begin(self, request: RunRequest, resources: PassResources) -> None:
|
|
301
|
+
self._pass_start_index = len(self._history.messages())
|
|
302
|
+
resources.begin()
|
|
303
|
+
self._shell.set_status(SubAgentStatus.RUNNING)
|
|
304
|
+
await self._write_log(status="running")
|
|
305
|
+
self._active_run_input = list(request.messages)
|
|
306
|
+
|
|
307
|
+
async def succeeded(self, response: AgentResponse[Any]) -> None:
|
|
308
|
+
if self._tool_event_middleware is not None:
|
|
309
|
+
await self._tool_event_middleware.reconcile_hosted_response(response.messages)
|
|
310
|
+
|
|
311
|
+
async def failed(self, error: Exception) -> None:
|
|
312
|
+
self._record_failure(error)
|
|
313
|
+
|
|
314
|
+
async def finished(self) -> None:
|
|
315
|
+
# A failed or interrupted pass publishes no outcome, and the buffer
|
|
316
|
+
# spans the invocation: its text must not wait for a later pass.
|
|
317
|
+
if self._tool_event_middleware is not None:
|
|
318
|
+
await self._tool_event_middleware.finish_intermediate_text()
|
|
319
|
+
|
|
320
|
+
def cancelled(self) -> None:
|
|
321
|
+
pass
|
|
322
|
+
|
|
323
|
+
def abort_cause(self) -> AbortCause | None:
|
|
324
|
+
return self._shell.owner_close_cause or (AbortCause.CASCADE if self._shell.cascade_requested else None)
|
|
325
|
+
|
|
326
|
+
async def interrupt(self) -> None:
|
|
327
|
+
await self._shell.cascade_abort()
|
|
328
|
+
|
|
329
|
+
def _record_failure(self, exc: Exception) -> None:
|
|
330
|
+
# The child's own window: its profile may differ from the parent's.
|
|
331
|
+
strategy = self._compaction.strategy
|
|
332
|
+
self._last_error_display, self._last_error_hint = display_fields(
|
|
333
|
+
exc, max_context_tokens=strategy.max_context_tokens if strategy is not None else None
|
|
334
|
+
)
|
|
335
|
+
if isinstance(exc, StreamStallExhausted):
|
|
336
|
+
# Keep the original stall message (chained via __cause__)
|
|
337
|
+
# so the pause banner shows the underlying reason instead
|
|
338
|
+
# of a generic "retries exhausted" placeholder. Falls back
|
|
339
|
+
# to a static label when the chain is empty (e.g. stalls
|
|
340
|
+
# without a stored cause — defensive only).
|
|
341
|
+
cause_msg = clean_error_message(exc) if exc.__cause__ else ""
|
|
342
|
+
self._last_error = (
|
|
343
|
+
f"Stream stalled after {self._max_retries} retries: {cause_msg}"
|
|
344
|
+
if cause_msg
|
|
345
|
+
else f"Stream stalled after {self._max_retries} retries"
|
|
346
|
+
)
|
|
347
|
+
self._failure_reason = SubAgentFailureReason.STREAM_STALL
|
|
348
|
+
logger.warning(
|
|
349
|
+
"Sub-agent '%s' (inv=%s) stalled after %d retries — pausing",
|
|
350
|
+
self._tool_name,
|
|
351
|
+
self._invocation_id,
|
|
352
|
+
self._max_retries,
|
|
353
|
+
)
|
|
354
|
+
|
|
355
|
+
elif isinstance(exc, StreamStall):
|
|
356
|
+
self._last_error = clean_error_message(exc) or "Stream stalled"
|
|
357
|
+
self._failure_reason = SubAgentFailureReason.STREAM_STALL
|
|
358
|
+
logger.warning(
|
|
359
|
+
"Sub-agent '%s' (inv=%s) stalled — pausing: %s",
|
|
360
|
+
self._tool_name,
|
|
361
|
+
self._invocation_id,
|
|
362
|
+
self._last_error,
|
|
363
|
+
)
|
|
364
|
+
|
|
365
|
+
else:
|
|
366
|
+
e = exc
|
|
367
|
+
if _is_last_words_error(e):
|
|
368
|
+
self._failure_reason = SubAgentFailureReason.LAST_WORDS
|
|
369
|
+
else:
|
|
370
|
+
self._failure_reason = SubAgentFailureReason.FRAMEWORK_EXC
|
|
371
|
+
self._last_error = clean_error_message(e)
|
|
372
|
+
logger.warning(
|
|
373
|
+
"Sub-agent '%s' (inv=%s) failed with %s — pausing: %s",
|
|
374
|
+
self._tool_name,
|
|
375
|
+
self._invocation_id,
|
|
376
|
+
self._failure_reason.value,
|
|
377
|
+
self._last_error,
|
|
378
|
+
)
|
|
379
|
+
|
|
380
|
+
@property
|
|
381
|
+
def last_error(self) -> str:
|
|
382
|
+
return self._last_error
|
|
383
|
+
|
|
384
|
+
@property
|
|
385
|
+
def failure_reason(self) -> SubAgentFailureReason | None:
|
|
386
|
+
return self._failure_reason
|
|
387
|
+
|
|
388
|
+
@property
|
|
389
|
+
def max_retries(self) -> int:
|
|
390
|
+
return self._max_retries
|
|
391
|
+
|
|
392
|
+
@property
|
|
393
|
+
def backoff_schedule(self) -> tuple[int, ...]:
|
|
394
|
+
return self._backoff
|
|
395
|
+
|
|
396
|
+
async def _interrupt_active_sleep(self, call_ids: set[str]) -> None:
|
|
397
|
+
"""Let an active inner sleep publish InvocationToolCallResult before cancellation."""
|
|
398
|
+
if not call_ids or self._sleep_middleware is None or self._bus is None:
|
|
399
|
+
return
|
|
400
|
+
pending = set(call_ids)
|
|
401
|
+
loop = asyncio.get_running_loop()
|
|
402
|
+
completed: asyncio.Future[None] = loop.create_future()
|
|
403
|
+
|
|
404
|
+
async def _on_tool_result(event: InvocationToolCallResult) -> None:
|
|
405
|
+
if event.origin.invocation_id != self._invocation_id:
|
|
406
|
+
return
|
|
407
|
+
pending.discard(event.call_id)
|
|
408
|
+
if not pending and not completed.done():
|
|
409
|
+
completed.set_result(None)
|
|
410
|
+
|
|
411
|
+
await self._bus.subscribe(InvocationToolCallResult, _on_tool_result)
|
|
412
|
+
try:
|
|
413
|
+
interrupted = set(self._sleep_middleware.interrupt_active())
|
|
414
|
+
pending.intersection_update(interrupted)
|
|
415
|
+
if not pending:
|
|
416
|
+
return
|
|
417
|
+
# Keep global interrupt responsive: give the inner sleep a
|
|
418
|
+
# small writeback window, then let task cancellation win.
|
|
419
|
+
await asyncio.wait_for(completed, timeout=0.5)
|
|
420
|
+
except TimeoutError:
|
|
421
|
+
return
|
|
422
|
+
finally:
|
|
423
|
+
await self._bus.unsubscribe(InvocationToolCallResult, _on_tool_result)
|
|
424
|
+
|
|
425
|
+
def _check_cascade(self) -> None:
|
|
426
|
+
"""Keep the caller's cancellation check before every agent attempt."""
|
|
427
|
+
if self._shell.cascade_requested:
|
|
428
|
+
raise asyncio.CancelledError
|
|
429
|
+
|
|
430
|
+
async def _reject_hosted_attempt(self, message: str) -> None:
|
|
431
|
+
if self._tool_event_middleware is not None:
|
|
432
|
+
await self._tool_event_middleware.reject_hosted_attempt(message)
|
|
433
|
+
|
|
434
|
+
async def _publish_retry_attempt(
|
|
435
|
+
self,
|
|
436
|
+
message: str,
|
|
437
|
+
attempt: int,
|
|
438
|
+
max_attempts: int,
|
|
439
|
+
delay_seconds: int,
|
|
440
|
+
exc: BaseException,
|
|
441
|
+
*,
|
|
442
|
+
scope: Literal["wire", "run"] = "run",
|
|
443
|
+
) -> None:
|
|
444
|
+
self._retry_attempts_total += 1
|
|
445
|
+
if self._tool_event_middleware is not None and not self._has_live_continuation_token():
|
|
446
|
+
await self._tool_event_middleware.reject_hosted_attempt(message)
|
|
447
|
+
if self._bus is None:
|
|
448
|
+
return
|
|
449
|
+
display_message, display_hint = display_fields(exc, retry_notice=True)
|
|
450
|
+
await self._emitter.publish(
|
|
451
|
+
InvocationRetryAttempt(
|
|
452
|
+
origin=self.origin,
|
|
453
|
+
agent_name=self._agent_name,
|
|
454
|
+
message=message,
|
|
455
|
+
attempt=attempt,
|
|
456
|
+
scope=scope,
|
|
457
|
+
max_attempts=max_attempts,
|
|
458
|
+
delay_seconds=delay_seconds,
|
|
459
|
+
session_id=self._session_id,
|
|
460
|
+
display_message=display_message,
|
|
461
|
+
display_hint=display_hint,
|
|
462
|
+
)
|
|
463
|
+
)
|
|
464
|
+
|
|
465
|
+
async def _publish_service_retry_attempt(
|
|
466
|
+
self,
|
|
467
|
+
message: str,
|
|
468
|
+
attempt: int,
|
|
469
|
+
max_attempts: int,
|
|
470
|
+
delay_seconds: int,
|
|
471
|
+
exc: BaseException,
|
|
472
|
+
) -> None:
|
|
473
|
+
await self._publish_retry_attempt(message, attempt, max_attempts, delay_seconds, exc)
|
|
474
|
+
trace = RetryBackoffTrace.open(
|
|
475
|
+
context=self._trajectory_context,
|
|
476
|
+
parent_operation_id=self._trajectory_boundary_operation_id,
|
|
477
|
+
retry_mode=RetryMode.RUN,
|
|
478
|
+
)
|
|
479
|
+
self._service_retry_trace = trace
|
|
480
|
+
if trace is not None:
|
|
481
|
+
await trace.scheduled(reason_code=_service_retry_reason(exc), delay_seconds=delay_seconds)
|
|
482
|
+
|
|
483
|
+
async def _sleep_for_service_retry(self, seconds: int) -> bool:
|
|
484
|
+
trace, self._service_retry_trace = self._service_retry_trace, None
|
|
485
|
+
try:
|
|
486
|
+
interrupted = await self._interruptible_sleep(seconds)
|
|
487
|
+
except asyncio.CancelledError:
|
|
488
|
+
raise
|
|
489
|
+
if trace is not None and not interrupted:
|
|
490
|
+
await trace.started()
|
|
491
|
+
return interrupted
|
|
492
|
+
|
|
493
|
+
async def publish_wire_retry_attempt(
|
|
494
|
+
self,
|
|
495
|
+
message: str,
|
|
496
|
+
attempt: int,
|
|
497
|
+
max_attempts: int,
|
|
498
|
+
delay_seconds: int,
|
|
499
|
+
exc: BaseException,
|
|
500
|
+
) -> None:
|
|
501
|
+
"""Publish a kernel wire-retry notice through the controller bus."""
|
|
502
|
+
await self._publish_retry_attempt(message, attempt, max_attempts, delay_seconds, exc, scope="wire")
|
|
503
|
+
|
|
504
|
+
async def sleep_for_wire_retry(self, seconds: int) -> bool:
|
|
505
|
+
"""Use the controller's cascade-aware backoff for kernel retries."""
|
|
506
|
+
return await self._interruptible_sleep(seconds)
|
|
507
|
+
|
|
508
|
+
def observe_continuation_token(self, token: Any) -> None:
|
|
509
|
+
"""Mirror the kernel's live continuation token into retry-owned options.
|
|
510
|
+
|
|
511
|
+
A transient failure while polling a stored background response must
|
|
512
|
+
resume that response on the next attempt, not re-issue the original
|
|
513
|
+
create request. Reads ``_run_kwargs`` at call time so a
|
|
514
|
+
handle-stripping restore that replaces the options dict cannot
|
|
515
|
+
orphan the observer.
|
|
516
|
+
"""
|
|
517
|
+
raw_options = self._run_kwargs.get("options")
|
|
518
|
+
options = raw_options if _is_string_keyed_dict(raw_options) else None
|
|
519
|
+
if token is None:
|
|
520
|
+
if options is not None:
|
|
521
|
+
options.pop("continuation_token", None)
|
|
522
|
+
return
|
|
523
|
+
if options is None:
|
|
524
|
+
options = {}
|
|
525
|
+
self._run_kwargs["options"] = options
|
|
526
|
+
options["continuation_token"] = token
|
|
527
|
+
|
|
528
|
+
def _has_live_continuation_token(self) -> bool:
|
|
529
|
+
return has_live_continuation_token(self._run_kwargs)
|
|
530
|
+
|
|
531
|
+
def _begin_hosted_baseline(self) -> None:
|
|
532
|
+
if self._begin_hosted_baseline_hook is not None:
|
|
533
|
+
self._begin_hosted_baseline_hook(resumes_background_response=self._has_live_continuation_token())
|
|
534
|
+
|
|
535
|
+
async def _write_log(
|
|
536
|
+
self,
|
|
537
|
+
*,
|
|
538
|
+
status: str,
|
|
539
|
+
result: str = "",
|
|
540
|
+
failure_reason: str = "",
|
|
541
|
+
last_error: str = "",
|
|
542
|
+
ended: bool = False,
|
|
543
|
+
) -> bool:
|
|
544
|
+
"""Best-effort audit-log update for this invocation.
|
|
545
|
+
|
|
546
|
+
Terminal records (``ended=True``) are the only durable copy of the
|
|
547
|
+
inner history once the controller is removed, so a failed write gets
|
|
548
|
+
one retry and a loud warning instead of the silent debug log. A
|
|
549
|
+
terminal write is also attempted on a writer whose initial write
|
|
550
|
+
failed (``active`` still False) — success there re-creates the log
|
|
551
|
+
file rather than silently discarding the committed inner history.
|
|
552
|
+
"""
|
|
553
|
+
if self._log_writer is None or self._log_writer.path is None:
|
|
554
|
+
return False
|
|
555
|
+
if not ended and not self._log_writer.active:
|
|
556
|
+
return False
|
|
557
|
+
for _attempt in range(2):
|
|
558
|
+
try:
|
|
559
|
+
if await self._log_writer.write(
|
|
560
|
+
status=status,
|
|
561
|
+
state=self._history.state(),
|
|
562
|
+
result=result,
|
|
563
|
+
failure_reason=failure_reason,
|
|
564
|
+
last_error=last_error,
|
|
565
|
+
ended=ended,
|
|
566
|
+
):
|
|
567
|
+
if ended:
|
|
568
|
+
self._terminal_audit_persisted = True
|
|
569
|
+
if self._terminal_audit_callback is not None:
|
|
570
|
+
self._terminal_audit_callback()
|
|
571
|
+
return True
|
|
572
|
+
except Exception:
|
|
573
|
+
logger.debug("sub-agent audit log update failed for invocation %s", self._invocation_id, exc_info=True)
|
|
574
|
+
if not ended:
|
|
575
|
+
return False
|
|
576
|
+
logger.warning(
|
|
577
|
+
"sub-agent audit log terminal write failed for invocation %s; inner history may be incomplete on reload",
|
|
578
|
+
self._invocation_id,
|
|
579
|
+
)
|
|
580
|
+
return False
|
|
581
|
+
|
|
582
|
+
@property
|
|
583
|
+
def terminal_audit_persisted(self) -> bool:
|
|
584
|
+
"""Whether a complete terminal audit record was written successfully."""
|
|
585
|
+
return self._terminal_audit_persisted
|
|
586
|
+
|
|
587
|
+
def _repair_paused_history(self) -> None:
|
|
588
|
+
self._history.repair_after_failure(self._active_run_input, self._pass_start_index)
|
|
589
|
+
|
|
590
|
+
def _prepare_retry_input(self) -> None:
|
|
591
|
+
self._next_run_input = self._history.retry_input(self._seed_input)
|
|
592
|
+
|
|
593
|
+
def _seed_input(self) -> list[Any]:
|
|
594
|
+
"""Build the run input that starts (or restarts) the sub-agent from its prompt.
|
|
595
|
+
|
|
596
|
+
Handing Agent.run a ready ``Message`` instead of the bare string
|
|
597
|
+
lets the analytics item id ride along: Agent.run would
|
|
598
|
+
otherwise mint an anonymous user message that no context revision
|
|
599
|
+
can identify.
|
|
600
|
+
"""
|
|
601
|
+
message = Message("user", [self._prompt])
|
|
602
|
+
ensure_analytics_item_id(message.additional_properties, item_id=self._seed_item_id)
|
|
603
|
+
return [message]
|
|
604
|
+
|
|
605
|
+
async def _interruptible_sleep(self, seconds: int) -> bool:
|
|
606
|
+
"""Sleep in 1-second ticks, returning True if cascade fired."""
|
|
607
|
+
for _ in range(max(0, seconds)):
|
|
608
|
+
if self._shell.cascade_requested:
|
|
609
|
+
return True
|
|
610
|
+
await asyncio.sleep(1)
|
|
611
|
+
return self._shell.cascade_requested
|
|
612
|
+
|
|
613
|
+
def _persist_path(self) -> Path | None:
|
|
614
|
+
if self._persist_dir is None:
|
|
615
|
+
return None
|
|
616
|
+
return self._persist_dir / f"{self._invocation_id}.json"
|
|
617
|
+
|
|
618
|
+
def _serialize_state(self) -> dict[str, Any]:
|
|
619
|
+
"""Snapshot the paused state as a plain JSON-safe dict.
|
|
620
|
+
|
|
621
|
+
We deliberately persist only pause metadata — not the ``Agent``,
|
|
622
|
+
middleware, run_kwargs, or the prompt-level token counts. On
|
|
623
|
+
restore we reconstruct the controller as read-only-abort (see
|
|
624
|
+
:meth:`restore_from_data`); there's no safe way to resume the
|
|
625
|
+
original tool call after the parent process died.
|
|
626
|
+
"""
|
|
627
|
+
now = datetime.now(UTC).isoformat()
|
|
628
|
+
return {
|
|
629
|
+
"schema_version": 1,
|
|
630
|
+
"record_type": "sub_agent_pending",
|
|
631
|
+
"invocation_id": self._invocation_id,
|
|
632
|
+
"tool_name": self._tool_name,
|
|
633
|
+
"agent_name": self._agent_name,
|
|
634
|
+
"prompt_preview": preview_text(self._prompt),
|
|
635
|
+
"session_id": self._session_id or "",
|
|
636
|
+
# ``parent_call_id`` lets the reload-recovery injector pair
|
|
637
|
+
# this record back to its dangling assistant function_call
|
|
638
|
+
# by framework call_id rather than by tool_name + appearance
|
|
639
|
+
# order. The injector treats the field as optional so
|
|
640
|
+
# records from future code paths that don't supply it still
|
|
641
|
+
# flow through the name+order fallback.
|
|
642
|
+
"parent_call_id": self._parent_call_id,
|
|
643
|
+
"parent_provider_call_id": self._parent_call_id,
|
|
644
|
+
"parent_event_call_id": self._parent_event_call_id,
|
|
645
|
+
**({"sub_agent_log_file": self._sub_agent_log_file} if self._sub_agent_log_file else {}),
|
|
646
|
+
"created_at": now,
|
|
647
|
+
"paused_at": now,
|
|
648
|
+
"failure_reason": (self._failure_reason.value if self._failure_reason else ""),
|
|
649
|
+
"last_error": self._last_error,
|
|
650
|
+
"retry_attempts_total": self._retry_attempts_total,
|
|
651
|
+
}
|
|
652
|
+
|
|
653
|
+
def _write_persisted(self) -> None:
|
|
654
|
+
"""Write the paused-state snapshot to disk. Best-effort — IO errors are logged."""
|
|
655
|
+
path = self._persist_path()
|
|
656
|
+
if path is None:
|
|
657
|
+
return
|
|
658
|
+
try:
|
|
659
|
+
atomic_write_owner_only_text(
|
|
660
|
+
path,
|
|
661
|
+
json.dumps(self._serialize_state(), indent=2, allow_nan=False),
|
|
662
|
+
)
|
|
663
|
+
except OSError as e:
|
|
664
|
+
logger.warning("Failed to persist paused sub-agent %s: %s", self._invocation_id, e)
|
|
665
|
+
|
|
666
|
+
def _queue_persisted_cleanup_if_terminal(self) -> None:
|
|
667
|
+
"""Queue the pause record for deletion once parent session save succeeds."""
|
|
668
|
+
if self._shell.status == SubAgentStatus.PAUSED:
|
|
669
|
+
return
|
|
670
|
+
path = self._persist_path()
|
|
671
|
+
if path is None or self._pending_record_finalizer is None:
|
|
672
|
+
return
|
|
673
|
+
self._pending_record_finalizer(path)
|
|
674
|
+
|
|
675
|
+
@staticmethod
|
|
676
|
+
def _final_segment(response: AgentResponse[Any]) -> FinalSegment:
|
|
677
|
+
"""Return the parent result and the transcript's final text for *response*.
|
|
678
|
+
|
|
679
|
+
``FinalSegment`` decides both, as it does for a workflow agent node.
|
|
680
|
+
A hosted image/artifact-only response is still a successful
|
|
681
|
+
structured result, so synthesize a neutral parent result, shown in the
|
|
682
|
+
transcript too, after its rich payload has been published by
|
|
683
|
+
reconciliation.
|
|
684
|
+
"""
|
|
685
|
+
segment = FinalSegment.of(response)
|
|
686
|
+
if segment.result:
|
|
687
|
+
return segment
|
|
688
|
+
|
|
689
|
+
has_images = False
|
|
690
|
+
has_artifacts = False
|
|
691
|
+
for message in response.messages:
|
|
692
|
+
for content in message.contents:
|
|
693
|
+
if content.type not in TOOL_RESULT_CONTENT_TYPES or not content.provider_hosted:
|
|
694
|
+
continue
|
|
695
|
+
view = adapt_hosted_tool(None, content)
|
|
696
|
+
if hosted_replay_status(view, has_result=True) != HostedToolStatus.COMPLETED:
|
|
697
|
+
continue
|
|
698
|
+
has_images = has_images or bool(view.image_contents)
|
|
699
|
+
has_artifacts = has_artifacts or bool(view.artifacts)
|
|
700
|
+
if has_images and has_artifacts:
|
|
701
|
+
note = "Sub-agent returned image and artifact output."
|
|
702
|
+
elif has_images:
|
|
703
|
+
note = "Sub-agent returned image output."
|
|
704
|
+
elif has_artifacts:
|
|
705
|
+
note = "Sub-agent returned artifact output."
|
|
706
|
+
else:
|
|
707
|
+
return segment
|
|
708
|
+
return FinalSegment(note, note)
|
|
709
|
+
|
|
710
|
+
def request(self, ticket: ContinuationTicket | None) -> RunRequest:
|
|
711
|
+
return RunRequest(
|
|
712
|
+
self._next_run_input, RunIntent.RETRY if ticket is not None else RunIntent.FRESH, self.origin, ticket
|
|
713
|
+
)
|
|
714
|
+
|
|
715
|
+
async def project_result(self, outcome: InvocationOutcome) -> str | None:
|
|
716
|
+
try:
|
|
717
|
+
if isinstance(outcome, Failed):
|
|
718
|
+
response = None
|
|
719
|
+
else:
|
|
720
|
+
if not isinstance(outcome, Ok):
|
|
721
|
+
raise TypeError("A completed sub-agent pass must have an Ok or Failed outcome.")
|
|
722
|
+
response = cast(AgentResponse[Any], outcome.backend_payload)
|
|
723
|
+
if response is not None:
|
|
724
|
+
self._shell.set_status(SubAgentStatus.COMPLETED)
|
|
725
|
+
segment = self._final_segment(response)
|
|
726
|
+
text = segment.result
|
|
727
|
+
if not text:
|
|
728
|
+
error_text = tool_error(
|
|
729
|
+
"sub_agent_empty_output",
|
|
730
|
+
f"sub-agent '{self._tool_name}' returned no output",
|
|
731
|
+
details={"tool_name": self._tool_name, "invocation_id": self._invocation_id},
|
|
732
|
+
)
|
|
733
|
+
await self._write_log(
|
|
734
|
+
status="completed",
|
|
735
|
+
result=error_text,
|
|
736
|
+
failure_reason="empty_output",
|
|
737
|
+
last_error=error_text,
|
|
738
|
+
ended=True,
|
|
739
|
+
)
|
|
740
|
+
return error_text
|
|
741
|
+
record_tool_success()
|
|
742
|
+
await self._write_log(status="completed", result=text, ended=True)
|
|
743
|
+
self.final_segment = segment
|
|
744
|
+
return text
|
|
745
|
+
|
|
746
|
+
except asyncio.CancelledError:
|
|
747
|
+
raise
|
|
748
|
+
except Exception as exc:
|
|
749
|
+
self._record_failure(exc)
|
|
750
|
+
|
|
751
|
+
return None
|
|
752
|
+
|
|
753
|
+
async def prepare_pause(self) -> None:
|
|
754
|
+
await self._reject_hosted_attempt(self._last_error or "Sub-agent execution paused")
|
|
755
|
+
self._repair_paused_history()
|
|
756
|
+
|
|
757
|
+
async def record_pause(self) -> None:
|
|
758
|
+
self._write_persisted()
|
|
759
|
+
await self._write_log(
|
|
760
|
+
status="paused",
|
|
761
|
+
failure_reason=self._failure_reason.value if self._failure_reason else "",
|
|
762
|
+
last_error=self._last_error,
|
|
763
|
+
)
|
|
764
|
+
|
|
765
|
+
def pause_event(self) -> InvocationPaused:
|
|
766
|
+
return InvocationPaused(
|
|
767
|
+
origin=self.origin,
|
|
768
|
+
agent_name=self._agent_name,
|
|
769
|
+
tool_name=self._tool_name,
|
|
770
|
+
reason=self._failure_reason.value if self._failure_reason else "",
|
|
771
|
+
last_error=self._last_error,
|
|
772
|
+
last_error_display=self._last_error_display,
|
|
773
|
+
last_error_hint=self._last_error_hint,
|
|
774
|
+
retry_attempts=self._retry_attempts_total,
|
|
775
|
+
session_id=self._session_id,
|
|
776
|
+
)
|
|
777
|
+
|
|
778
|
+
def resolve_late_cascade(self, decision: asyncio.Future[str]) -> None:
|
|
779
|
+
# Preserve the kernel callback window: the operation owner wakes the
|
|
780
|
+
# late future by cancelling its caller after audit convergence.
|
|
781
|
+
pass
|
|
782
|
+
|
|
783
|
+
def check_terminal_race(self) -> None:
|
|
784
|
+
# Kernel keeps its existing writer/return arbitration; ACP rechecks.
|
|
785
|
+
pass
|
|
786
|
+
|
|
787
|
+
def prepare_retry(self) -> None:
|
|
788
|
+
self._prepare_retry_input()
|
|
789
|
+
|
|
790
|
+
async def abort_result(self, *, by_user: bool) -> str:
|
|
791
|
+
reason = self._failure_reason.value if self._failure_reason else ""
|
|
792
|
+
details = {"tool_name": self._tool_name, "invocation_id": self._invocation_id, "failure_reason": reason}
|
|
793
|
+
if by_user:
|
|
794
|
+
status = "aborted"
|
|
795
|
+
text = tool_error(
|
|
796
|
+
"sub_agent_aborted",
|
|
797
|
+
f"sub-agent '{self._tool_name}' aborted by user after failure — {self._last_error}",
|
|
798
|
+
details=details,
|
|
799
|
+
)
|
|
800
|
+
else:
|
|
801
|
+
status = "failed"
|
|
802
|
+
text = tool_error(
|
|
803
|
+
"sub_agent_failed", f"sub-agent '{self._tool_name}' failed — {self._last_error}", details=details
|
|
804
|
+
)
|
|
805
|
+
await self._write_log(
|
|
806
|
+
status=status, result=text, failure_reason=reason, last_error=self._last_error, ended=True
|
|
807
|
+
)
|
|
808
|
+
return text
|
|
809
|
+
|
|
810
|
+
def latch_abort(self, cause: AbortCause) -> None:
|
|
811
|
+
# The backend observer reads the shell latch; no second task owner.
|
|
812
|
+
pass
|
|
813
|
+
|
|
814
|
+
async def cancel_active(self) -> None:
|
|
815
|
+
task = self._attempt_handle.task
|
|
816
|
+
if task is not None and not task.done():
|
|
817
|
+
sleep_call_ids = self._sleep_middleware.active_call_ids if self._sleep_middleware is not None else ()
|
|
818
|
+
if sleep_call_ids:
|
|
819
|
+
await self._interrupt_active_sleep(set(sleep_call_ids))
|
|
820
|
+
if not task.done():
|
|
821
|
+
task.cancel()
|
|
822
|
+
await asyncio.gather(task, return_exceptions=True)
|
|
823
|
+
await self._shell.finalize_cancellation()
|
|
824
|
+
|
|
825
|
+
async def finalize_cancellation(self) -> None:
|
|
826
|
+
if self._tool_event_middleware is not None:
|
|
827
|
+
await self._tool_event_middleware.reject_hosted_attempt("Sub-agent execution interrupted")
|
|
828
|
+
self._repair_paused_history()
|
|
829
|
+
if self._shell.cascade_requested:
|
|
830
|
+
await self._shell.publish_cascade_event()
|
|
831
|
+
else:
|
|
832
|
+
self._shell.set_status(SubAgentStatus.ABORTED)
|
|
833
|
+
await self._write_log(status="cancelled", result="cancelled", last_error="cancelled", ended=True)
|
|
834
|
+
|
|
835
|
+
async def before_cascade_event(self) -> None:
|
|
836
|
+
await self._write_log(
|
|
837
|
+
status="cascade_aborted",
|
|
838
|
+
result="cancelled by parent interrupt",
|
|
839
|
+
failure_reason="cascade_aborted",
|
|
840
|
+
last_error="cancelled by parent interrupt",
|
|
841
|
+
ended=True,
|
|
842
|
+
)
|
|
843
|
+
|
|
844
|
+
async def run_cancelled(self) -> None:
|
|
845
|
+
await self._shell.finalize_cancellation()
|
|
846
|
+
|
|
847
|
+
async def finish_run(self) -> None:
|
|
848
|
+
self._queue_persisted_cleanup_if_terminal()
|