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,948 @@
|
|
|
1
|
+
# Copyright (c) Huawei Technologies Co., Ltd. 2026. All rights reserved.
|
|
2
|
+
|
|
3
|
+
"""Retry admission and pending-retry dispatch for main-agent turns."""
|
|
4
|
+
|
|
5
|
+
from __future__ import annotations
|
|
6
|
+
|
|
7
|
+
import asyncio
|
|
8
|
+
from collections.abc import Awaitable, Callable
|
|
9
|
+
from dataclasses import dataclass
|
|
10
|
+
from datetime import datetime
|
|
11
|
+
from typing import TYPE_CHECKING, Protocol
|
|
12
|
+
|
|
13
|
+
from chrys.foundation.events.types import Error, UserRetry, Warning
|
|
14
|
+
from chrys.foundation.i18n import msg
|
|
15
|
+
from chrys.foundation.models.history_markers import HistoryMarkerKind
|
|
16
|
+
from chrys.foundation.models.turns import current_turn_start, is_continuation_message
|
|
17
|
+
from chrys.orchestration.engine.execution import (
|
|
18
|
+
CurrentRunInjectionWindow,
|
|
19
|
+
CurrentRunScope,
|
|
20
|
+
PreAdmissionPreparationEntry,
|
|
21
|
+
PreAdmissionPreparationTracker,
|
|
22
|
+
PromptAdmissionScope,
|
|
23
|
+
)
|
|
24
|
+
from chrys.orchestration.engine.run.active_injection import ActiveTurnInjector
|
|
25
|
+
from chrys.orchestration.engine.run.input_refs import format_skill_reference_reminder, parse_skill_reference
|
|
26
|
+
from chrys.orchestration.engine.run.prompt_content import PromptContentPreparer
|
|
27
|
+
from chrys.orchestration.engine.run.runtime_skills import (
|
|
28
|
+
CommittedSkillRefresh,
|
|
29
|
+
RuntimeSkillRefresher,
|
|
30
|
+
StagedRuntimeSkillRefresh,
|
|
31
|
+
)
|
|
32
|
+
from chrys.orchestration.engine.run.turn_hooks import PromptSubmitGate
|
|
33
|
+
from chrys.orchestration.engine.run.turn_state import ActiveInjectionTarget
|
|
34
|
+
from chrys.orchestration.engine.run.working_dir import publish_working_dir_missing, refuse_while_working_dir_missing
|
|
35
|
+
from chrys.orchestration.engine.state.machine import EngineState, Trigger
|
|
36
|
+
from chrys.service.hooks.schema import HookDecision
|
|
37
|
+
from chrys.service.trajectory.preparation import (
|
|
38
|
+
PreparationOutcome,
|
|
39
|
+
PreparationScope,
|
|
40
|
+
PreparationTrace,
|
|
41
|
+
input_admission_wait,
|
|
42
|
+
)
|
|
43
|
+
|
|
44
|
+
if TYPE_CHECKING:
|
|
45
|
+
from chrys.foundation.events.bus import EventBus
|
|
46
|
+
from chrys.foundation.events.types import RuntimeSkillDetails
|
|
47
|
+
from chrys.orchestration.engine.run.bindings import TurnBindings
|
|
48
|
+
from chrys.orchestration.engine.run.turn_state import TurnRuntimeState
|
|
49
|
+
from chrys.orchestration.engine.state.active_session import ActiveSession
|
|
50
|
+
from chrys.orchestration.engine.state.current_agent import CurrentAgent
|
|
51
|
+
from chrys.orchestration.engine.state.lifecycle_permits import LifecyclePermits
|
|
52
|
+
from chrys.orchestration.engine.state.machine import EngineStateMachine
|
|
53
|
+
from chrys.orchestration.engine.trajectory import TrajectoryRecorder
|
|
54
|
+
from chrys.orchestration.invoker.kernel import KernelConversation
|
|
55
|
+
from chrys.service.agent_middleware.system_reminder import (
|
|
56
|
+
CurrentRunReminderScope,
|
|
57
|
+
CurrentRunReminderTarget,
|
|
58
|
+
SystemReminderMiddleware,
|
|
59
|
+
)
|
|
60
|
+
from chrys.service.session.history import SessionHistoryManager
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
_RETRY_MISSING_USER_ANCHOR = msg(
|
|
64
|
+
"retry.missing_user_anchor",
|
|
65
|
+
fallback="Cannot retry without a real user message in history.",
|
|
66
|
+
)
|
|
67
|
+
_RETRY_SUB_AGENT_PAUSED = msg(
|
|
68
|
+
"retry.sub_agent_paused",
|
|
69
|
+
fallback="Resolve paused sub-agent(s) first (Retry/Abort on the card) before retrying the main run.",
|
|
70
|
+
)
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
@dataclass(frozen=True)
|
|
74
|
+
class _CurrentRunSideEffectTarget:
|
|
75
|
+
"""Captured current-run owner for non-injection retry-note side effects."""
|
|
76
|
+
|
|
77
|
+
session_id: str | None
|
|
78
|
+
session_generation: int
|
|
79
|
+
build_generation: int
|
|
80
|
+
current_run_scope: CurrentRunScope
|
|
81
|
+
bindings: TurnBindings
|
|
82
|
+
conversation: KernelConversation
|
|
83
|
+
reminder_middleware: SystemReminderMiddleware
|
|
84
|
+
reminder_target: CurrentRunReminderTarget
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
@dataclass(frozen=True)
|
|
88
|
+
class _RetryNoteOwner:
|
|
89
|
+
"""Session/build/current-run owner captured before retry-note hook awaits."""
|
|
90
|
+
|
|
91
|
+
session_id: str | None
|
|
92
|
+
session_generation: int
|
|
93
|
+
build_generation: int
|
|
94
|
+
current_run_scope: CurrentRunScope | None
|
|
95
|
+
bindings: TurnBindings
|
|
96
|
+
conversation: KernelConversation
|
|
97
|
+
reminder_middleware: SystemReminderMiddleware | None
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
@dataclass(frozen=True)
|
|
101
|
+
class _PreparedRetryNoteSideEffects:
|
|
102
|
+
"""Retry-note reminders and staged skill refresh ready for a concrete run scope."""
|
|
103
|
+
|
|
104
|
+
reminders: list[str]
|
|
105
|
+
staged: StagedRuntimeSkillRefresh | None
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
class RetryPassRunner(Protocol):
|
|
109
|
+
"""Execute an admitted retry and save its terminal state."""
|
|
110
|
+
|
|
111
|
+
async def __call__(
|
|
112
|
+
self,
|
|
113
|
+
additional_text: str = "",
|
|
114
|
+
created_at: datetime | str | None = None,
|
|
115
|
+
*,
|
|
116
|
+
run_scope: CurrentRunScope | None = None,
|
|
117
|
+
injection_window: CurrentRunInjectionWindow | None = None,
|
|
118
|
+
admission_preparation: PreparationTrace | None = None,
|
|
119
|
+
) -> None: ...
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
class RetryCoordinator:
|
|
123
|
+
"""Own retry admission, pending retry state, and retry task creation."""
|
|
124
|
+
|
|
125
|
+
def __init__(
|
|
126
|
+
self,
|
|
127
|
+
*,
|
|
128
|
+
turn_state: TurnRuntimeState,
|
|
129
|
+
current: CurrentAgent,
|
|
130
|
+
permits: LifecyclePermits,
|
|
131
|
+
session: ActiveSession,
|
|
132
|
+
fsm: EngineStateMachine,
|
|
133
|
+
history: SessionHistoryManager,
|
|
134
|
+
bus: EventBus,
|
|
135
|
+
trajectory_recorder: TrajectoryRecorder,
|
|
136
|
+
gate: PromptSubmitGate,
|
|
137
|
+
injector: ActiveTurnInjector,
|
|
138
|
+
content: PromptContentPreparer,
|
|
139
|
+
skills: RuntimeSkillRefresher,
|
|
140
|
+
retry_and_save: RetryPassRunner,
|
|
141
|
+
) -> None:
|
|
142
|
+
self._turn_state = turn_state
|
|
143
|
+
self._current = current
|
|
144
|
+
self._permits = permits
|
|
145
|
+
self._session = session
|
|
146
|
+
self._fsm = fsm
|
|
147
|
+
self._history = history
|
|
148
|
+
self._bus = bus
|
|
149
|
+
self._trajectory_recorder = trajectory_recorder
|
|
150
|
+
self._gate = gate
|
|
151
|
+
self._injector = injector
|
|
152
|
+
self._content = content
|
|
153
|
+
self._skills = skills
|
|
154
|
+
self._retry_and_save = retry_and_save
|
|
155
|
+
self._preparation_handed_off = False
|
|
156
|
+
|
|
157
|
+
def _open_pre_turn_preparation(self) -> PreparationTrace | None:
|
|
158
|
+
"""Open a session-root preparation scope before retry admission awaits."""
|
|
159
|
+
context = self._trajectory_recorder.context()
|
|
160
|
+
if context is not None:
|
|
161
|
+
context = context.with_turn(None).with_run(None)
|
|
162
|
+
return PreparationTrace.open(
|
|
163
|
+
scope=PreparationScope.PRE_TURN,
|
|
164
|
+
phase="input_admission",
|
|
165
|
+
context=context,
|
|
166
|
+
)
|
|
167
|
+
|
|
168
|
+
async def _start_pre_admission_preparation(self, tracker: PreAdmissionPreparationTracker) -> None:
|
|
169
|
+
"""Start and register a retry preparation against the current session."""
|
|
170
|
+
preparation = self._open_pre_turn_preparation()
|
|
171
|
+
if preparation is None:
|
|
172
|
+
tracker.current = None
|
|
173
|
+
return
|
|
174
|
+
entry = PreAdmissionPreparationEntry(preparation=preparation)
|
|
175
|
+
tracker.current = entry
|
|
176
|
+
await preparation.started()
|
|
177
|
+
self._turn_state.lease.register_pre_admission_preparation(entry)
|
|
178
|
+
|
|
179
|
+
async def _wait_for_pre_admission_gate(
|
|
180
|
+
self,
|
|
181
|
+
wait_for_gate: Callable[[], Awaitable[object]],
|
|
182
|
+
tracker: PreAdmissionPreparationTracker,
|
|
183
|
+
) -> None:
|
|
184
|
+
"""Wait at one gate and rebind a preparation swept by a session boundary."""
|
|
185
|
+
entry = tracker.current
|
|
186
|
+
preparation = tracker.preparation
|
|
187
|
+
await input_admission_wait(wait_for_gate, preparation, entry)
|
|
188
|
+
if preparation is None or not preparation.finished_state:
|
|
189
|
+
return
|
|
190
|
+
self._turn_state.lease.deregister_pre_admission_preparation(entry)
|
|
191
|
+
await self._start_pre_admission_preparation(tracker)
|
|
192
|
+
|
|
193
|
+
@staticmethod
|
|
194
|
+
async def _finish_preparation(preparation: PreparationTrace | None, outcome: str) -> None:
|
|
195
|
+
if preparation is not None:
|
|
196
|
+
await preparation.finished(outcome=outcome)
|
|
197
|
+
|
|
198
|
+
async def handle_user_retry(self, event: UserRetry) -> None:
|
|
199
|
+
"""Handle retry requests and route them to immediate or pending execution."""
|
|
200
|
+
if await self._turn_state.lease.refuse_while_workflow_active(self._bus, self._session.session_id):
|
|
201
|
+
return
|
|
202
|
+
preparation_tracker = PreAdmissionPreparationTracker()
|
|
203
|
+
try:
|
|
204
|
+
await self._start_pre_admission_preparation(preparation_tracker)
|
|
205
|
+
await self._handle_user_retry(event, preparation_tracker=preparation_tracker)
|
|
206
|
+
except asyncio.CancelledError:
|
|
207
|
+
preparation = preparation_tracker.preparation
|
|
208
|
+
if preparation is not None:
|
|
209
|
+
preparation.finished_soon(outcome=PreparationOutcome.CANCELLED)
|
|
210
|
+
raise
|
|
211
|
+
except BaseException:
|
|
212
|
+
preparation = preparation_tracker.preparation
|
|
213
|
+
if preparation is not None:
|
|
214
|
+
preparation.finished_soon(outcome=PreparationOutcome.PREPARATION_FAILED)
|
|
215
|
+
raise
|
|
216
|
+
finally:
|
|
217
|
+
self._turn_state.lease.deregister_pre_admission_preparation(preparation_tracker.current)
|
|
218
|
+
preparation = preparation_tracker.preparation
|
|
219
|
+
pending_owns_preparation = self._turn_state.lease.pending_retry.preparation_trace is preparation
|
|
220
|
+
if (
|
|
221
|
+
preparation is not None
|
|
222
|
+
and not self._preparation_handed_off
|
|
223
|
+
and not pending_owns_preparation
|
|
224
|
+
and not preparation.finished_state
|
|
225
|
+
):
|
|
226
|
+
await preparation.finished(outcome=PreparationOutcome.PREPARATION_FAILED)
|
|
227
|
+
|
|
228
|
+
async def _handle_user_retry(
|
|
229
|
+
self,
|
|
230
|
+
event: UserRetry,
|
|
231
|
+
*,
|
|
232
|
+
preparation_tracker: PreAdmissionPreparationTracker,
|
|
233
|
+
) -> None:
|
|
234
|
+
"""Execute one retry admission under its pre-turn preparation scope."""
|
|
235
|
+
admission: PromptAdmissionScope | None = None
|
|
236
|
+
admission_released = False
|
|
237
|
+
while True:
|
|
238
|
+
await self._wait_for_pre_admission_gate(self._permits.wait_for_agent_load_idle, preparation_tracker)
|
|
239
|
+
preparation = preparation_tracker.preparation
|
|
240
|
+
if self._current.loaded is None:
|
|
241
|
+
if self._turn_state.lease.prompt_admission_closed:
|
|
242
|
+
await self._wait_for_pre_admission_gate(
|
|
243
|
+
self._turn_state.lease.wait_for_prompt_admission_open,
|
|
244
|
+
preparation_tracker,
|
|
245
|
+
)
|
|
246
|
+
continue
|
|
247
|
+
await self._finish_preparation(preparation, PreparationOutcome.NOT_READY)
|
|
248
|
+
return
|
|
249
|
+
if self._turn_state.lease.prompt_admission_closed:
|
|
250
|
+
await self._wait_for_pre_admission_gate(
|
|
251
|
+
self._turn_state.lease.wait_for_prompt_admission_open,
|
|
252
|
+
preparation_tracker,
|
|
253
|
+
)
|
|
254
|
+
continue
|
|
255
|
+
if self._turn_state.lease.has_active_admission_kind("fresh"):
|
|
256
|
+
await self._wait_for_pre_admission_gate(
|
|
257
|
+
self._turn_state.lease.wait_for_active_admissions_idle,
|
|
258
|
+
preparation_tracker,
|
|
259
|
+
)
|
|
260
|
+
continue
|
|
261
|
+
if await refuse_while_working_dir_missing(self._bus, self._session):
|
|
262
|
+
await self._finish_preparation(preparation, PreparationOutcome.REJECTED)
|
|
263
|
+
return
|
|
264
|
+
# A workflow run may have taken the lease while this retry was preparing.
|
|
265
|
+
if await self._turn_state.lease.refuse_while_workflow_active(self._bus, self._session.session_id):
|
|
266
|
+
await self._finish_preparation(preparation, PreparationOutcome.REJECTED)
|
|
267
|
+
return
|
|
268
|
+
if not self._has_real_user_anchor():
|
|
269
|
+
await self._bus.publish(
|
|
270
|
+
Error(
|
|
271
|
+
code="retry_missing_user_anchor",
|
|
272
|
+
message="Cannot retry without a real user message in history.",
|
|
273
|
+
display_message=_RETRY_MISSING_USER_ANCHOR.bind(),
|
|
274
|
+
recoverable=True,
|
|
275
|
+
session_id=self._session.session_id,
|
|
276
|
+
)
|
|
277
|
+
)
|
|
278
|
+
await self._finish_preparation(preparation, PreparationOutcome.REJECTED)
|
|
279
|
+
return
|
|
280
|
+
admission = self._turn_state.lease.reserve_prompt_admission(
|
|
281
|
+
kind="retry",
|
|
282
|
+
session_generation=self._permits.session_generation,
|
|
283
|
+
build_generation=self._permits.build_generation,
|
|
284
|
+
preparation_trace=preparation,
|
|
285
|
+
)
|
|
286
|
+
if admission is None:
|
|
287
|
+
await self._wait_for_pre_admission_gate(
|
|
288
|
+
self._turn_state.lease.wait_for_prompt_admission_open,
|
|
289
|
+
preparation_tracker,
|
|
290
|
+
)
|
|
291
|
+
continue
|
|
292
|
+
self._turn_state.lease.deregister_pre_admission_preparation(preparation_tracker.current)
|
|
293
|
+
break
|
|
294
|
+
|
|
295
|
+
try:
|
|
296
|
+
if self._fsm.is_awaiting_sub_agents():
|
|
297
|
+
await self._bus.publish(
|
|
298
|
+
Warning(
|
|
299
|
+
code="sub_agent_paused",
|
|
300
|
+
message=(
|
|
301
|
+
"Resolve paused sub-agent(s) first (Retry/Abort on the card) before retrying the main run."
|
|
302
|
+
),
|
|
303
|
+
display_message=_RETRY_SUB_AGENT_PAUSED.bind(),
|
|
304
|
+
session_id=self._session.session_id,
|
|
305
|
+
)
|
|
306
|
+
)
|
|
307
|
+
await self._finish_preparation(preparation, PreparationOutcome.CONFLICT)
|
|
308
|
+
return
|
|
309
|
+
decision: HookDecision | None = None
|
|
310
|
+
retry_note_owner = self._capture_retry_note_owner() if event.text else None
|
|
311
|
+
active_retry_target = (
|
|
312
|
+
self._capture_retry_note_active_target()
|
|
313
|
+
if event.text and self._current.loaded is not None and self._current.loaded.bindings.state.running
|
|
314
|
+
else None
|
|
315
|
+
)
|
|
316
|
+
pending_retry_installed = False
|
|
317
|
+
|
|
318
|
+
def _install_pending_retry_before_commit() -> None:
|
|
319
|
+
nonlocal admission_released, pending_retry_installed
|
|
320
|
+
if active_retry_target is None:
|
|
321
|
+
return
|
|
322
|
+
if (
|
|
323
|
+
self._turn_state.lease.run_task is not active_retry_target.run_task
|
|
324
|
+
or active_retry_target.run_task.done()
|
|
325
|
+
):
|
|
326
|
+
return
|
|
327
|
+
if not self._pending_retry_request_still_accepted():
|
|
328
|
+
return
|
|
329
|
+
if not self._admission_owner_is_current(admission):
|
|
330
|
+
return
|
|
331
|
+
self._turn_state.lease.upsert_pending_retry_from_admission(admission, event.text, event.timestamp)
|
|
332
|
+
self._preparation_handed_off = True
|
|
333
|
+
self._turn_state.lease.release_prompt_admission(admission)
|
|
334
|
+
admission_released = True
|
|
335
|
+
transition = self._fsm.try_transition(Trigger.RETRY_REQUESTED)
|
|
336
|
+
pending_retry_installed = transition is not None or self._fsm.state == EngineState.PENDING_RETRY
|
|
337
|
+
|
|
338
|
+
if event.text:
|
|
339
|
+
decision = await self._gate.evaluate(
|
|
340
|
+
event.text,
|
|
341
|
+
injected=True,
|
|
342
|
+
target_operation_id=preparation.committed_operation_id if preparation is not None else None,
|
|
343
|
+
trajectory_context=preparation.context if preparation is not None else None,
|
|
344
|
+
)
|
|
345
|
+
if not self._admission_owner_is_current(admission) or self._retry_note_owner_stale_after_hook(
|
|
346
|
+
retry_note_owner, active_retry_target
|
|
347
|
+
):
|
|
348
|
+
await self._finish_preparation(preparation, PreparationOutcome.OWNER_CHANGED)
|
|
349
|
+
self._clear_pending_retry_for_admission_or_unowned(admission)
|
|
350
|
+
return
|
|
351
|
+
retry_note_session_id = retry_note_owner.session_id if retry_note_owner is not None else None
|
|
352
|
+
if await self._gate.handle_decision(
|
|
353
|
+
decision,
|
|
354
|
+
injected=True,
|
|
355
|
+
session_id=retry_note_session_id,
|
|
356
|
+
):
|
|
357
|
+
await self._finish_preparation(preparation, PreparationOutcome.REJECTED)
|
|
358
|
+
self._clear_pending_retry_for_admission_or_unowned(admission)
|
|
359
|
+
return
|
|
360
|
+
if await self._reject_retry_images(event.text, session_id=retry_note_session_id):
|
|
361
|
+
await self._finish_preparation(preparation, PreparationOutcome.IMAGE_REJECTED)
|
|
362
|
+
self._clear_pending_retry_for_admission_or_unowned(admission)
|
|
363
|
+
return
|
|
364
|
+
if not self._admission_owner_is_current(admission):
|
|
365
|
+
await self._finish_preparation(preparation, PreparationOutcome.OWNER_CHANGED)
|
|
366
|
+
return
|
|
367
|
+
if await self._reject_text_only_active_history():
|
|
368
|
+
await self._finish_preparation(preparation, PreparationOutcome.IMAGE_REJECTED)
|
|
369
|
+
self._clear_pending_retry_for_admission_or_unowned(admission)
|
|
370
|
+
return
|
|
371
|
+
deferred_retry_note: _PreparedRetryNoteSideEffects | None = None
|
|
372
|
+
if event.text:
|
|
373
|
+
accepted, deferred_retry_note = await self._commit_retry_note_side_effects(
|
|
374
|
+
event.text,
|
|
375
|
+
decision,
|
|
376
|
+
retry_note_owner,
|
|
377
|
+
active_retry_target,
|
|
378
|
+
before_commit=_install_pending_retry_before_commit,
|
|
379
|
+
)
|
|
380
|
+
if not accepted:
|
|
381
|
+
await self._finish_preparation(preparation, PreparationOutcome.PREPARATION_FAILED)
|
|
382
|
+
self._clear_pending_retry_for_admission_or_unowned(admission)
|
|
383
|
+
return
|
|
384
|
+
if pending_retry_installed:
|
|
385
|
+
return
|
|
386
|
+
if (
|
|
387
|
+
self._current.loaded is not None
|
|
388
|
+
and not self._current.loaded.bindings.state.running
|
|
389
|
+
and self._turn_state.lease.run_task is None
|
|
390
|
+
and not self._immediate_retry_start_may_be_valid()
|
|
391
|
+
):
|
|
392
|
+
await self._finish_preparation(preparation, PreparationOutcome.CONFLICT)
|
|
393
|
+
return
|
|
394
|
+
if self._current.loaded is not None and self._current.loaded.bindings.state.running:
|
|
395
|
+
if self._admission_owner_is_current(admission) and self._pending_retry_request_still_accepted():
|
|
396
|
+
self._turn_state.lease.upsert_pending_retry_from_admission(admission, event.text, event.timestamp)
|
|
397
|
+
self._preparation_handed_off = True
|
|
398
|
+
self._turn_state.lease.release_prompt_admission(admission)
|
|
399
|
+
admission_released = True
|
|
400
|
+
self._fsm.try_transition(Trigger.RETRY_REQUESTED)
|
|
401
|
+
else:
|
|
402
|
+
outcome = (
|
|
403
|
+
PreparationOutcome.CONFLICT
|
|
404
|
+
if self._admission_owner_is_current(admission)
|
|
405
|
+
else PreparationOutcome.OWNER_CHANGED
|
|
406
|
+
)
|
|
407
|
+
await self._finish_preparation(preparation, outcome)
|
|
408
|
+
self._clear_pending_retry_for_admission_or_unowned(admission)
|
|
409
|
+
return
|
|
410
|
+
wait_entry = PreAdmissionPreparationEntry(preparation=preparation) if preparation is not None else None
|
|
411
|
+
if wait_entry is not None:
|
|
412
|
+
self._turn_state.lease.register_pre_admission_preparation(wait_entry)
|
|
413
|
+
try:
|
|
414
|
+
await input_admission_wait(self._wait_for_existing_run_task, preparation, wait_entry)
|
|
415
|
+
finally:
|
|
416
|
+
self._turn_state.lease.deregister_pre_admission_preparation(wait_entry)
|
|
417
|
+
if not self._admission_owner_is_current(admission):
|
|
418
|
+
await self._finish_preparation(preparation, PreparationOutcome.OWNER_CHANGED)
|
|
419
|
+
return
|
|
420
|
+
if self._turn_state.lease.run_task is not None and not self._turn_state.lease.run_task.done():
|
|
421
|
+
await self._finish_preparation(preparation, PreparationOutcome.CONFLICT)
|
|
422
|
+
return
|
|
423
|
+
# The run this retry waited for can end because its directory was deleted.
|
|
424
|
+
if await refuse_while_working_dir_missing(self._bus, self._session):
|
|
425
|
+
await self._finish_preparation(preparation, PreparationOutcome.REJECTED)
|
|
426
|
+
return
|
|
427
|
+
if not self._claim_immediate_retry_start():
|
|
428
|
+
await self._finish_preparation(preparation, PreparationOutcome.CONFLICT)
|
|
429
|
+
return
|
|
430
|
+
if self._current.loaded is None:
|
|
431
|
+
self._turn_state.lease.release_prompt_admission(admission)
|
|
432
|
+
admission_released = True
|
|
433
|
+
self._history.remove_trailing_markers()
|
|
434
|
+
self._turn_state.lease.run_task = asyncio.create_task(
|
|
435
|
+
self._retry_and_save(
|
|
436
|
+
event.text,
|
|
437
|
+
created_at=event.timestamp,
|
|
438
|
+
admission_preparation=preparation,
|
|
439
|
+
)
|
|
440
|
+
)
|
|
441
|
+
self._preparation_handed_off = True
|
|
442
|
+
return
|
|
443
|
+
|
|
444
|
+
self._history.remove_trailing_markers()
|
|
445
|
+
promotion = self._turn_state.lease.promote_retry_admission(
|
|
446
|
+
admission,
|
|
447
|
+
reminder_scope=self._retry_reminder_scope_for_admission(admission),
|
|
448
|
+
make_task=lambda scope, window: asyncio.create_task(
|
|
449
|
+
self._retry_and_save(
|
|
450
|
+
event.text,
|
|
451
|
+
created_at=event.timestamp,
|
|
452
|
+
run_scope=scope,
|
|
453
|
+
injection_window=window,
|
|
454
|
+
admission_preparation=preparation,
|
|
455
|
+
)
|
|
456
|
+
),
|
|
457
|
+
text=event.text,
|
|
458
|
+
created_at=event.timestamp,
|
|
459
|
+
)
|
|
460
|
+
if promotion.outcome == "task":
|
|
461
|
+
admission_released = True
|
|
462
|
+
self._preparation_handed_off = True
|
|
463
|
+
if deferred_retry_note is not None:
|
|
464
|
+
scope = self._turn_state.lease.current_run_scope
|
|
465
|
+
if scope is None or scope.owner_admission_id != admission.admission_id:
|
|
466
|
+
self._discard_promoted_retry_task(promotion.task, scope)
|
|
467
|
+
await self._finish_preparation(preparation, PreparationOutcome.OWNER_CHANGED)
|
|
468
|
+
self._clear_pending_retry_for_admission_or_unowned(admission)
|
|
469
|
+
return
|
|
470
|
+
if not await self._commit_deferred_retry_note_side_effects(deferred_retry_note, scope):
|
|
471
|
+
self._discard_promoted_retry_task(promotion.task, scope)
|
|
472
|
+
await self._finish_preparation(preparation, PreparationOutcome.PREPARATION_FAILED)
|
|
473
|
+
self._clear_pending_retry_for_admission_or_unowned(admission)
|
|
474
|
+
else:
|
|
475
|
+
await self._finish_preparation(
|
|
476
|
+
preparation,
|
|
477
|
+
PreparationOutcome.OWNER_CHANGED if promotion.outcome == "stale" else PreparationOutcome.CONFLICT,
|
|
478
|
+
)
|
|
479
|
+
finally:
|
|
480
|
+
if admission is not None and not admission_released:
|
|
481
|
+
self._turn_state.lease.release_prompt_admission(admission)
|
|
482
|
+
|
|
483
|
+
def start_pending_retry_if_due(self) -> str | None:
|
|
484
|
+
"""Start a queued retry when post-run state allows retry dispatch.
|
|
485
|
+
|
|
486
|
+
Return the working directory only when a due retry was dropped because
|
|
487
|
+
that directory is gone, else None. The finished pass left the FSM
|
|
488
|
+
RUNNING for that retry, so the caller settles it to the pass's own
|
|
489
|
+
terminal state and then reports the drop
|
|
490
|
+
(:meth:`report_retry_dropped_for_missing_cwd`).
|
|
491
|
+
"""
|
|
492
|
+
if self._session.shutting_down:
|
|
493
|
+
self._turn_state.lease.clear_pending_retry(outcome=PreparationOutcome.DROPPED)
|
|
494
|
+
return None
|
|
495
|
+
if self._fsm.state != EngineState.RUNNING:
|
|
496
|
+
self._turn_state.lease.clear_pending_retry(outcome=PreparationOutcome.DROPPED)
|
|
497
|
+
return None
|
|
498
|
+
if self._turn_state.lease.pending_retry.dispatch_disabled:
|
|
499
|
+
self._turn_state.lease.clear_pending_retry(outcome=PreparationOutcome.DROPPED)
|
|
500
|
+
return None
|
|
501
|
+
pending = self._turn_state.lease.pending_retry
|
|
502
|
+
scope = self._turn_state.lease.current_run_scope
|
|
503
|
+
if pending.owner_admission_id is None:
|
|
504
|
+
self._turn_state.lease.clear_pending_retry(outcome=PreparationOutcome.DROPPED)
|
|
505
|
+
return None
|
|
506
|
+
if pending.session_generation != self._permits.session_generation:
|
|
507
|
+
self._turn_state.lease.clear_pending_retry(outcome=PreparationOutcome.DROPPED)
|
|
508
|
+
return None
|
|
509
|
+
if pending.run_generation == 0:
|
|
510
|
+
if scope is not None:
|
|
511
|
+
self._turn_state.lease.clear_pending_retry(outcome=PreparationOutcome.DROPPED)
|
|
512
|
+
return None
|
|
513
|
+
elif scope is None or pending.run_generation != scope.run_generation:
|
|
514
|
+
self._turn_state.lease.clear_pending_retry(outcome=PreparationOutcome.DROPPED)
|
|
515
|
+
return None
|
|
516
|
+
if self._turn_state.lease.pending_retry_dispatch_disabled_for_session_generation == pending.session_generation:
|
|
517
|
+
self._turn_state.lease.clear_pending_retry(outcome=PreparationOutcome.DROPPED)
|
|
518
|
+
return None
|
|
519
|
+
workspace = self._session.workspace
|
|
520
|
+
if workspace is not None and (missing := workspace.missing_primary()) is not None:
|
|
521
|
+
self._turn_state.lease.clear_pending_retry(outcome=PreparationOutcome.DROPPED)
|
|
522
|
+
return missing
|
|
523
|
+
self._history.remove_trailing_markers()
|
|
524
|
+
text = pending.text
|
|
525
|
+
created_at = pending.created_at
|
|
526
|
+
dispatched = self._turn_state.lease.clear_pending_retry(outcome=PreparationOutcome.RETRY_TURN)
|
|
527
|
+
self._turn_state.lease.run_task = self._create_retry_run_task(
|
|
528
|
+
text,
|
|
529
|
+
created_at=created_at,
|
|
530
|
+
admission_preparation=dispatched.preparation_trace,
|
|
531
|
+
)
|
|
532
|
+
return None
|
|
533
|
+
|
|
534
|
+
async def report_retry_dropped_for_missing_cwd(self, path: str) -> None:
|
|
535
|
+
"""Tell frontends a queued retry will not run because *path* is gone.
|
|
536
|
+
|
|
537
|
+
A frontend shows an accepted retry as running until a run ends it; no
|
|
538
|
+
run will, so this error does.
|
|
539
|
+
"""
|
|
540
|
+
await publish_working_dir_missing(self._bus, self._session.session_id, path)
|
|
541
|
+
|
|
542
|
+
async def _wait_for_existing_run_task(self) -> None:
|
|
543
|
+
"""Wait for current run-task cleanup, if any."""
|
|
544
|
+
task = self._turn_state.lease.run_task
|
|
545
|
+
if task is not None and not task.done():
|
|
546
|
+
await task
|
|
547
|
+
|
|
548
|
+
def _reuse_or_create_retry_scope(self) -> CurrentRunScope | None:
|
|
549
|
+
"""Return a retry scope, preserving the current logical scope when valid."""
|
|
550
|
+
scope = self._turn_state.lease.current_run_scope
|
|
551
|
+
if (
|
|
552
|
+
scope is not None
|
|
553
|
+
and scope.session_generation == self._permits.session_generation
|
|
554
|
+
and scope.build_generation == self._permits.build_generation
|
|
555
|
+
):
|
|
556
|
+
return scope
|
|
557
|
+
return None
|
|
558
|
+
|
|
559
|
+
def _reuse_or_create_retry_scope_and_window(self) -> tuple[CurrentRunScope, CurrentRunInjectionWindow] | None:
|
|
560
|
+
"""Open a retry injection window, preserving the current logical scope when valid."""
|
|
561
|
+
scope = self._reuse_or_create_retry_scope()
|
|
562
|
+
if scope is not None:
|
|
563
|
+
return scope, self._turn_state.lease.open_injection_admission(scope)
|
|
564
|
+
return None
|
|
565
|
+
|
|
566
|
+
def _create_retry_run_task(
|
|
567
|
+
self,
|
|
568
|
+
text: str,
|
|
569
|
+
*,
|
|
570
|
+
created_at: datetime | str | None,
|
|
571
|
+
admission_preparation: PreparationTrace | None = None,
|
|
572
|
+
) -> asyncio.Task[None]:
|
|
573
|
+
"""Create a retry task, preserving the validated current retry scope."""
|
|
574
|
+
scope_window = self._reuse_or_create_retry_scope_and_window()
|
|
575
|
+
if scope_window is None:
|
|
576
|
+
return asyncio.create_task(
|
|
577
|
+
self._retry_and_save(
|
|
578
|
+
text,
|
|
579
|
+
created_at=created_at,
|
|
580
|
+
admission_preparation=admission_preparation,
|
|
581
|
+
)
|
|
582
|
+
)
|
|
583
|
+
scope, window = scope_window
|
|
584
|
+
return asyncio.create_task(
|
|
585
|
+
self._retry_and_save(
|
|
586
|
+
text,
|
|
587
|
+
created_at=created_at,
|
|
588
|
+
run_scope=scope,
|
|
589
|
+
injection_window=window,
|
|
590
|
+
admission_preparation=admission_preparation,
|
|
591
|
+
)
|
|
592
|
+
)
|
|
593
|
+
|
|
594
|
+
def _discard_promoted_retry_task(
|
|
595
|
+
self,
|
|
596
|
+
task: asyncio.Task[None] | None,
|
|
597
|
+
scope: CurrentRunScope | None,
|
|
598
|
+
) -> None:
|
|
599
|
+
"""Cancel a just-promoted retry task when its deferred admission side effects fail."""
|
|
600
|
+
if task is not None and not task.done():
|
|
601
|
+
task.cancel()
|
|
602
|
+
if self._turn_state.lease.run_task is task:
|
|
603
|
+
self._turn_state.lease.run_task = None
|
|
604
|
+
if scope is not None:
|
|
605
|
+
self._turn_state.lease.clear_current_run_scope(scope)
|
|
606
|
+
if self._current.loaded is not None:
|
|
607
|
+
self._current.loaded.reminder_middleware.expire_current_run_scope(scope.reminder_scope)
|
|
608
|
+
self._fsm.try_transition(Trigger.RUN_FAILED)
|
|
609
|
+
|
|
610
|
+
def _admission_owner_is_current(self, admission: PromptAdmissionScope) -> bool:
|
|
611
|
+
"""Return whether *admission* still belongs to the live session/build owner."""
|
|
612
|
+
return (
|
|
613
|
+
self._permits.session_generation == admission.session_generation
|
|
614
|
+
and self._permits.build_generation == admission.build_generation
|
|
615
|
+
)
|
|
616
|
+
|
|
617
|
+
def _has_real_user_anchor(self) -> bool:
|
|
618
|
+
"""Return whether the marker-ignoring current logical turn has user input."""
|
|
619
|
+
current_input = self._turn_state.current_input
|
|
620
|
+
if current_input.kind != "continuation" and (current_input.text or current_input.contents):
|
|
621
|
+
# Fresh input may not have landed in provider history yet, but it
|
|
622
|
+
# is the same real anchor crash recovery would synthesize.
|
|
623
|
+
return True
|
|
624
|
+
messages = self._history.messages
|
|
625
|
+
logical_end = len(messages)
|
|
626
|
+
while logical_end:
|
|
627
|
+
kind = messages[logical_end - 1].additional_properties.get(HistoryMarkerKind.KEY)
|
|
628
|
+
if kind not in HistoryMarkerKind.SESSION_COUNT_EXCLUDED:
|
|
629
|
+
break
|
|
630
|
+
logical_end -= 1
|
|
631
|
+
logical_messages = messages[:logical_end]
|
|
632
|
+
start = current_turn_start(logical_messages)
|
|
633
|
+
return any(
|
|
634
|
+
message.role == "user" and not is_continuation_message(message) for message in logical_messages[start:]
|
|
635
|
+
)
|
|
636
|
+
|
|
637
|
+
def _immediate_retry_start_may_be_valid(self) -> bool:
|
|
638
|
+
"""Return whether current state may be valid for an immediate retry after cleanup."""
|
|
639
|
+
if self._session.shutting_down:
|
|
640
|
+
return False
|
|
641
|
+
if self._fsm.state in (EngineState.INTERRUPTED, EngineState.FAILED):
|
|
642
|
+
return True
|
|
643
|
+
return (
|
|
644
|
+
self._fsm.state is EngineState.RUNNING
|
|
645
|
+
and self._turn_state.lease.run_task is not None
|
|
646
|
+
and self._turn_state.lease.run_task.done()
|
|
647
|
+
and self._current.loaded is not None
|
|
648
|
+
and not self._current.loaded.bindings.state.running
|
|
649
|
+
)
|
|
650
|
+
|
|
651
|
+
def _claim_immediate_retry_start(self) -> bool:
|
|
652
|
+
"""Validate and transition the FSM for an immediate retry before task install."""
|
|
653
|
+
if self._session.shutting_down:
|
|
654
|
+
return False
|
|
655
|
+
if self._fsm.state in (EngineState.INTERRUPTED, EngineState.FAILED):
|
|
656
|
+
self._fsm.try_transition(Trigger.RETRY_STARTED)
|
|
657
|
+
return self._fsm.state is EngineState.RUNNING
|
|
658
|
+
return (
|
|
659
|
+
self._fsm.state is EngineState.RUNNING
|
|
660
|
+
and self._turn_state.lease.run_task is not None
|
|
661
|
+
and self._turn_state.lease.run_task.done()
|
|
662
|
+
and self._current.loaded is not None
|
|
663
|
+
and not self._current.loaded.bindings.state.running
|
|
664
|
+
)
|
|
665
|
+
|
|
666
|
+
def _retry_request_still_accepted(self) -> bool:
|
|
667
|
+
"""Return whether retry-note side effects may still be committed."""
|
|
668
|
+
return not self._session.shutting_down and self._fsm.state in (
|
|
669
|
+
EngineState.RUNNING,
|
|
670
|
+
EngineState.PENDING_RETRY,
|
|
671
|
+
EngineState.INTERRUPTED,
|
|
672
|
+
EngineState.FAILED,
|
|
673
|
+
)
|
|
674
|
+
|
|
675
|
+
def _pending_retry_request_still_accepted(self) -> bool:
|
|
676
|
+
"""Return whether a retry request may be queued for the active executor."""
|
|
677
|
+
return not self._session.shutting_down and self._fsm.state is EngineState.RUNNING
|
|
678
|
+
|
|
679
|
+
def _clear_pending_retry_for_admission_or_unowned(self, admission: PromptAdmissionScope) -> None:
|
|
680
|
+
"""Clear retry state only when it is unowned or belongs to *admission*."""
|
|
681
|
+
pending = self._turn_state.lease.pending_retry
|
|
682
|
+
if pending.owner_admission_id is None or pending.updated_by_admission_id == admission.admission_id:
|
|
683
|
+
self._turn_state.lease.clear_pending_retry(outcome=PreparationOutcome.DROPPED)
|
|
684
|
+
|
|
685
|
+
def _retry_reminder_scope_for_admission(self, admission: PromptAdmissionScope) -> CurrentRunReminderScope:
|
|
686
|
+
"""Return the existing logical retry reminder scope, or allocate a new one."""
|
|
687
|
+
current_scope = self._turn_state.lease.current_run_scope
|
|
688
|
+
if (
|
|
689
|
+
current_scope is not None
|
|
690
|
+
and current_scope.session_generation == admission.session_generation
|
|
691
|
+
and current_scope.build_generation == admission.build_generation
|
|
692
|
+
):
|
|
693
|
+
return current_scope.reminder_scope
|
|
694
|
+
reminder_middleware = self._current.loaded.reminder_middleware if self._current.loaded is not None else None
|
|
695
|
+
if reminder_middleware is None:
|
|
696
|
+
raise RuntimeError("Cannot promote retry without reminder middleware")
|
|
697
|
+
return reminder_middleware.create_current_run_scope()
|
|
698
|
+
|
|
699
|
+
def _capture_retry_note_active_target(self) -> ActiveInjectionTarget | None:
|
|
700
|
+
"""Capture the active current-run owner used by retry-note side effects."""
|
|
701
|
+
return self._injector.capture_target(route="fsm_active")
|
|
702
|
+
|
|
703
|
+
def _retry_note_active_target_owner_invalid(self, target: ActiveInjectionTarget) -> bool:
|
|
704
|
+
"""Return whether a captured retry-note owner changed beyond executor completion."""
|
|
705
|
+
return self._injector.target_owner_invalid(target)
|
|
706
|
+
|
|
707
|
+
def _capture_retry_note_owner(self) -> _RetryNoteOwner | None:
|
|
708
|
+
"""Capture the retry-note owner before awaited prompt-submit hooks run."""
|
|
709
|
+
executor = self._current.loaded.bindings if self._current.loaded is not None else None
|
|
710
|
+
if executor is None:
|
|
711
|
+
return None
|
|
712
|
+
return _RetryNoteOwner(
|
|
713
|
+
session_id=self._session.session_id,
|
|
714
|
+
session_generation=self._permits.session_generation,
|
|
715
|
+
build_generation=self._permits.build_generation,
|
|
716
|
+
current_run_scope=self._turn_state.lease.current_run_scope,
|
|
717
|
+
bindings=executor,
|
|
718
|
+
conversation=executor.backend,
|
|
719
|
+
reminder_middleware=self._current.loaded.reminder_middleware if self._current.loaded is not None else None,
|
|
720
|
+
)
|
|
721
|
+
|
|
722
|
+
def _retry_note_owner_invalid(self, owner: _RetryNoteOwner) -> bool:
|
|
723
|
+
"""Return whether the pre-hook retry-note owner changed."""
|
|
724
|
+
return (
|
|
725
|
+
self._session.session_id != owner.session_id
|
|
726
|
+
or self._permits.session_generation != owner.session_generation
|
|
727
|
+
or self._permits.build_generation != owner.build_generation
|
|
728
|
+
or (self._current.loaded is None or self._current.loaded.bindings.backend is not owner.conversation)
|
|
729
|
+
or self._current.loaded.reminder_middleware is not owner.reminder_middleware
|
|
730
|
+
)
|
|
731
|
+
|
|
732
|
+
def _retry_note_owner_scope_conflicted(self, owner: _RetryNoteOwner) -> bool:
|
|
733
|
+
"""Return whether a different live current-run scope replaced the pre-hook owner."""
|
|
734
|
+
current_scope = self._turn_state.lease.current_run_scope
|
|
735
|
+
return current_scope is not None and current_scope != owner.current_run_scope
|
|
736
|
+
|
|
737
|
+
def _capture_current_run_side_effect_target(self, scope: CurrentRunScope) -> _CurrentRunSideEffectTarget | None:
|
|
738
|
+
"""Capture a current-run reminder target for scoped retry-note side effects."""
|
|
739
|
+
executor = self._current.loaded.bindings if self._current.loaded is not None else None
|
|
740
|
+
reminder_middleware = self._current.loaded.reminder_middleware if self._current.loaded is not None else None
|
|
741
|
+
if executor is None or reminder_middleware is None:
|
|
742
|
+
return None
|
|
743
|
+
if (
|
|
744
|
+
scope.session_generation != self._permits.session_generation
|
|
745
|
+
or scope.build_generation != self._permits.build_generation
|
|
746
|
+
):
|
|
747
|
+
return None
|
|
748
|
+
if self._turn_state.lease.current_run_scope != scope:
|
|
749
|
+
return None
|
|
750
|
+
reminder_target = reminder_middleware.capture_current_run_target(scope.reminder_scope)
|
|
751
|
+
if reminder_target is None:
|
|
752
|
+
return None
|
|
753
|
+
return _CurrentRunSideEffectTarget(
|
|
754
|
+
session_id=self._session.session_id,
|
|
755
|
+
session_generation=self._permits.session_generation,
|
|
756
|
+
build_generation=self._permits.build_generation,
|
|
757
|
+
current_run_scope=scope,
|
|
758
|
+
bindings=executor,
|
|
759
|
+
conversation=executor.backend,
|
|
760
|
+
reminder_middleware=reminder_middleware,
|
|
761
|
+
reminder_target=reminder_target,
|
|
762
|
+
)
|
|
763
|
+
|
|
764
|
+
def _current_run_side_effect_target_is_current(self, target: _CurrentRunSideEffectTarget) -> bool:
|
|
765
|
+
"""Return whether a scoped retry-note side-effect owner remains current."""
|
|
766
|
+
return (
|
|
767
|
+
self._session.session_id == target.session_id
|
|
768
|
+
and self._permits.session_generation == target.session_generation
|
|
769
|
+
and self._permits.build_generation == target.build_generation
|
|
770
|
+
and self._turn_state.lease.current_run_scope == target.current_run_scope
|
|
771
|
+
and self._current.loaded is not None
|
|
772
|
+
and self._current.loaded.bindings.backend is target.conversation
|
|
773
|
+
and self._current.loaded.reminder_middleware is target.reminder_middleware
|
|
774
|
+
)
|
|
775
|
+
|
|
776
|
+
def _retry_note_owner_stale_after_hook(
|
|
777
|
+
self,
|
|
778
|
+
owner: _RetryNoteOwner | None,
|
|
779
|
+
active_retry_target: ActiveInjectionTarget | None,
|
|
780
|
+
) -> bool:
|
|
781
|
+
"""Return whether a retry note owner became stale while hooks awaited."""
|
|
782
|
+
if owner is None or self._retry_note_owner_invalid(owner) or self._retry_note_owner_scope_conflicted(owner):
|
|
783
|
+
return True
|
|
784
|
+
return active_retry_target is not None and self._retry_note_active_target_owner_invalid(active_retry_target)
|
|
785
|
+
|
|
786
|
+
async def _commit_retry_note_side_effects(
|
|
787
|
+
self,
|
|
788
|
+
text: str,
|
|
789
|
+
decision: HookDecision | None,
|
|
790
|
+
owner: _RetryNoteOwner | None,
|
|
791
|
+
active_retry_target: ActiveInjectionTarget | None,
|
|
792
|
+
*,
|
|
793
|
+
before_commit: Callable[[], None] | None = None,
|
|
794
|
+
) -> tuple[bool, _PreparedRetryNoteSideEffects | None]:
|
|
795
|
+
"""Commit retry-note side effects, or defer them until retry promotion creates a scope."""
|
|
796
|
+
if not text:
|
|
797
|
+
return True, None
|
|
798
|
+
if not self._retry_request_still_accepted():
|
|
799
|
+
return False, None
|
|
800
|
+
if owner is None or self._retry_note_owner_invalid(owner) or self._retry_note_owner_scope_conflicted(owner):
|
|
801
|
+
return False, None
|
|
802
|
+
|
|
803
|
+
staged = await self._stage_runtime_skills()
|
|
804
|
+
if (
|
|
805
|
+
not self._retry_request_still_accepted()
|
|
806
|
+
or self._retry_note_owner_invalid(owner)
|
|
807
|
+
or self._retry_note_owner_scope_conflicted(owner)
|
|
808
|
+
):
|
|
809
|
+
return False, None
|
|
810
|
+
|
|
811
|
+
side_effects = self._prepare_retry_note_side_effects(text, decision, staged)
|
|
812
|
+
|
|
813
|
+
target: _CurrentRunSideEffectTarget | None = None
|
|
814
|
+
if active_retry_target is not None:
|
|
815
|
+
if self._retry_note_active_target_owner_invalid(active_retry_target):
|
|
816
|
+
return False, None
|
|
817
|
+
current_scope = self._turn_state.lease.current_run_scope
|
|
818
|
+
if current_scope == active_retry_target.current_run_scope:
|
|
819
|
+
target = _CurrentRunSideEffectTarget(
|
|
820
|
+
session_id=active_retry_target.session_id,
|
|
821
|
+
session_generation=active_retry_target.session_generation,
|
|
822
|
+
build_generation=active_retry_target.build_generation,
|
|
823
|
+
current_run_scope=active_retry_target.current_run_scope,
|
|
824
|
+
bindings=active_retry_target.bindings,
|
|
825
|
+
conversation=active_retry_target.conversation,
|
|
826
|
+
reminder_middleware=active_retry_target.reminder_middleware,
|
|
827
|
+
reminder_target=active_retry_target.reminder_target,
|
|
828
|
+
)
|
|
829
|
+
elif current_scope is not None:
|
|
830
|
+
return False, None
|
|
831
|
+
|
|
832
|
+
if target is None:
|
|
833
|
+
scope = self._reuse_or_create_retry_scope()
|
|
834
|
+
if scope is None:
|
|
835
|
+
return True, side_effects
|
|
836
|
+
target = self._capture_current_run_side_effect_target(scope)
|
|
837
|
+
if target is None:
|
|
838
|
+
return False, None
|
|
839
|
+
|
|
840
|
+
if not await self._commit_retry_note_side_effects_to_target(
|
|
841
|
+
side_effects,
|
|
842
|
+
target,
|
|
843
|
+
before_commit=before_commit,
|
|
844
|
+
):
|
|
845
|
+
return False, None
|
|
846
|
+
return True, None
|
|
847
|
+
|
|
848
|
+
def _prepare_retry_note_side_effects(
|
|
849
|
+
self,
|
|
850
|
+
text: str,
|
|
851
|
+
decision: HookDecision | None,
|
|
852
|
+
staged: StagedRuntimeSkillRefresh | None,
|
|
853
|
+
) -> _PreparedRetryNoteSideEffects:
|
|
854
|
+
"""Build retry-note side effects after hooks and skill refresh have settled."""
|
|
855
|
+
reminders = PromptSubmitGate.reminder_texts(decision)
|
|
856
|
+
skill_reference = self._skill_reference_reminder(
|
|
857
|
+
text,
|
|
858
|
+
skill_details=staged.skill_details if staged is not None else None,
|
|
859
|
+
)
|
|
860
|
+
if skill_reference is not None:
|
|
861
|
+
reminders.append(skill_reference)
|
|
862
|
+
return _PreparedRetryNoteSideEffects(reminders=reminders, staged=staged)
|
|
863
|
+
|
|
864
|
+
async def _commit_retry_note_side_effects_to_target(
|
|
865
|
+
self,
|
|
866
|
+
side_effects: _PreparedRetryNoteSideEffects,
|
|
867
|
+
target: _CurrentRunSideEffectTarget,
|
|
868
|
+
*,
|
|
869
|
+
before_commit: Callable[[], None] | None = None,
|
|
870
|
+
) -> bool:
|
|
871
|
+
"""Commit prepared retry-note side effects to a captured current-run target."""
|
|
872
|
+
if not self._retry_request_still_accepted() or not self._current_run_side_effect_target_is_current(target):
|
|
873
|
+
return False
|
|
874
|
+
if not target.reminder_middleware.is_current_run_target_valid(target.reminder_target):
|
|
875
|
+
return False
|
|
876
|
+
|
|
877
|
+
staged = side_effects.staged
|
|
878
|
+
if staged is not None and not target.reminder_middleware.set_skill_catalog_for_current_run(
|
|
879
|
+
target.reminder_target,
|
|
880
|
+
staged.skill_catalog,
|
|
881
|
+
):
|
|
882
|
+
return False
|
|
883
|
+
if not target.reminder_middleware.queue_hook_reminders_for_current_run(
|
|
884
|
+
target.reminder_target,
|
|
885
|
+
side_effects.reminders,
|
|
886
|
+
):
|
|
887
|
+
return False
|
|
888
|
+
if before_commit is not None:
|
|
889
|
+
before_commit()
|
|
890
|
+
if not self._retry_request_still_accepted() or not self._current_run_side_effect_target_is_current(target):
|
|
891
|
+
return False
|
|
892
|
+
if not target.reminder_middleware.is_current_run_target_valid(target.reminder_target):
|
|
893
|
+
return False
|
|
894
|
+
|
|
895
|
+
committed = self._commit_staged_runtime_skills(staged)
|
|
896
|
+
await self._publish_staged_runtime_skill_refresh(
|
|
897
|
+
committed,
|
|
898
|
+
session_id=target.session_id,
|
|
899
|
+
)
|
|
900
|
+
return True
|
|
901
|
+
|
|
902
|
+
async def _commit_deferred_retry_note_side_effects(
|
|
903
|
+
self,
|
|
904
|
+
side_effects: _PreparedRetryNoteSideEffects,
|
|
905
|
+
scope: CurrentRunScope,
|
|
906
|
+
) -> bool:
|
|
907
|
+
"""Commit deferred retry-note side effects after retry admission owns a real scope."""
|
|
908
|
+
target = self._capture_current_run_side_effect_target(scope)
|
|
909
|
+
if target is None:
|
|
910
|
+
return False
|
|
911
|
+
return await self._commit_retry_note_side_effects_to_target(side_effects, target)
|
|
912
|
+
|
|
913
|
+
async def _reject_retry_images(self, text: str, *, session_id: str | None = None) -> bool:
|
|
914
|
+
"""Publish a non-fatal rejection for retry notes containing image mentions."""
|
|
915
|
+
return await self._content.reject_retry_images(text, session_id=session_id)
|
|
916
|
+
|
|
917
|
+
async def _reject_text_only_active_history(self) -> bool:
|
|
918
|
+
"""Publish a text-only model rejection when active history contains image content."""
|
|
919
|
+
return await self._content.reject_text_only_active_history()
|
|
920
|
+
|
|
921
|
+
async def _stage_runtime_skills(self) -> StagedRuntimeSkillRefresh | None:
|
|
922
|
+
"""Discover runtime skills without mutating live provider or host runtime state."""
|
|
923
|
+
return await self._skills.stage_refresh()
|
|
924
|
+
|
|
925
|
+
def _commit_staged_runtime_skills(self, staged: StagedRuntimeSkillRefresh | None) -> CommittedSkillRefresh | None:
|
|
926
|
+
"""Commit a staged runtime skill refresh synchronously to the captured owner."""
|
|
927
|
+
return self._skills.commit_staged_refresh(staged)
|
|
928
|
+
|
|
929
|
+
async def _publish_staged_runtime_skill_refresh(
|
|
930
|
+
self,
|
|
931
|
+
committed: CommittedSkillRefresh | None,
|
|
932
|
+
*,
|
|
933
|
+
session_id: str | None,
|
|
934
|
+
) -> None:
|
|
935
|
+
"""Publish warning/runtime update events for a committed staged refresh."""
|
|
936
|
+
await self._skills.publish_committed_refresh(committed, session_id=session_id)
|
|
937
|
+
|
|
938
|
+
def _skill_reference_reminder(
|
|
939
|
+
self,
|
|
940
|
+
text: str,
|
|
941
|
+
*,
|
|
942
|
+
skill_details: list[RuntimeSkillDetails] | None = None,
|
|
943
|
+
) -> str | None:
|
|
944
|
+
"""Return the skill-reference reminder for *text*, if it names a loaded skill."""
|
|
945
|
+
reference = parse_skill_reference(text, skill_details or self._current.manifest.runtime_details.skill_details)
|
|
946
|
+
if reference is None:
|
|
947
|
+
return None
|
|
948
|
+
return format_skill_reference_reminder(reference)
|