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,865 @@
|
|
|
1
|
+
# Copyright (c) Huawei Technologies Co., Ltd. 2026. All rights reserved.
|
|
2
|
+
|
|
3
|
+
"""Engine-internal companion module for ``AgentEngine`` build and restart orchestration."""
|
|
4
|
+
|
|
5
|
+
from __future__ import annotations
|
|
6
|
+
|
|
7
|
+
import asyncio
|
|
8
|
+
import contextlib
|
|
9
|
+
import copy
|
|
10
|
+
import logging
|
|
11
|
+
from collections.abc import Callable
|
|
12
|
+
from datetime import UTC, datetime
|
|
13
|
+
from typing import TYPE_CHECKING
|
|
14
|
+
|
|
15
|
+
from chrys.foundation.branding import APP_DISPLAY_NAME
|
|
16
|
+
from chrys.foundation.errors import clean_error_message
|
|
17
|
+
from chrys.foundation.errors.display import display_fields
|
|
18
|
+
from chrys.foundation.events.types import (
|
|
19
|
+
AgentLoadFailed,
|
|
20
|
+
AgentLoadFinished,
|
|
21
|
+
AgentLoadProgress,
|
|
22
|
+
AgentLoadStarted,
|
|
23
|
+
ApprovalModeUpdated,
|
|
24
|
+
ProfileSwitched,
|
|
25
|
+
SessionReady,
|
|
26
|
+
Warning,
|
|
27
|
+
WorkspaceUpdated,
|
|
28
|
+
)
|
|
29
|
+
from chrys.foundation.i18n import msg
|
|
30
|
+
from chrys.foundation.models.workspace import Workspace
|
|
31
|
+
from chrys.foundation.platform import safe_getcwd
|
|
32
|
+
from chrys.foundation.trajectory.event_types import ProfileKind
|
|
33
|
+
from chrys.orchestration.engine.build import construction
|
|
34
|
+
from chrys.orchestration.engine.build.construction import BuildAgentFn, StagedBuild
|
|
35
|
+
from chrys.orchestration.engine.build.loaded import AgentManifest, CompletedBuild, ReplacedBuild
|
|
36
|
+
from chrys.orchestration.engine.state.machine import Trigger
|
|
37
|
+
from chrys.orchestration.engine.trajectory import TrajectoryRecorder
|
|
38
|
+
from chrys.orchestration.invoker.resources import PreparedAgent
|
|
39
|
+
from chrys.orchestration.session_hooks import SessionHookFactory
|
|
40
|
+
from chrys.service.agent_middleware.reminders.archive_pointer import CATALOG_POINTER_RECORD_COUNT_STATE_KEY
|
|
41
|
+
from chrys.service.mcp.cache import MCPConnectionCache
|
|
42
|
+
from chrys.service.mutations.workspace_changes import WorkspaceChangeTracker
|
|
43
|
+
from chrys.service.profiles.models.schema import API_STYLE_RESPONSES
|
|
44
|
+
from chrys.service.session.runtime_metadata import SessionRuntimeMetadata
|
|
45
|
+
from chrys.service.trajectory.session import SessionStartInfo
|
|
46
|
+
|
|
47
|
+
if TYPE_CHECKING:
|
|
48
|
+
from chrys.foundation.config.settings_store import LoadedSettings, SettingsHandle
|
|
49
|
+
from chrys.foundation.events.bus import EventBus
|
|
50
|
+
from chrys.foundation.events.types import RuntimeSkillDetails
|
|
51
|
+
from chrys.orchestration.engine.run.turn_hooks import TurnHookDispatcher
|
|
52
|
+
from chrys.orchestration.engine.run.turn_state import TurnRuntimeState
|
|
53
|
+
from chrys.orchestration.engine.state.active_session import ActiveSession
|
|
54
|
+
from chrys.orchestration.engine.state.current_agent import CurrentAgent
|
|
55
|
+
from chrys.orchestration.engine.state.lifecycle_permits import LifecyclePermits
|
|
56
|
+
from chrys.orchestration.engine.state.machine import EngineStateMachine
|
|
57
|
+
from chrys.orchestration.engine.state.session_writer import RecoveryCheckpoints
|
|
58
|
+
from chrys.orchestration.engine.usage import UsagePublisher
|
|
59
|
+
from chrys.service.approval.turn_context import TurnContextHolder
|
|
60
|
+
from chrys.service.hooks.manager import HookManager
|
|
61
|
+
from chrys.service.profiles.agents.registry import AgentProfileRegistry
|
|
62
|
+
from chrys.service.profiles.agents.schema import AgentProfile, MCPServerConfig
|
|
63
|
+
from chrys.service.profiles.models.registry import ModelProfileRegistry
|
|
64
|
+
from chrys.service.profiles.models.schema import ModelProfile
|
|
65
|
+
from chrys.service.session.history import SessionHistoryManager
|
|
66
|
+
from chrys.service.session.persistence import SessionPersistence
|
|
67
|
+
from chrys.service.trajectory.session import SessionTrajectory
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
logger = logging.getLogger(__name__)
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
_CONSTRUCTION_SERVICE_SESSION_INCOMPATIBLE = msg(
|
|
74
|
+
"construction.service_session_incompatible",
|
|
75
|
+
fallback=(
|
|
76
|
+
"The previous OpenAI Responses service session is not compatible with the active agent profile, workspace, "
|
|
77
|
+
"model profile, service endpoint, or storage is disabled. {app_name} will continue from local history only."
|
|
78
|
+
),
|
|
79
|
+
)
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
def _is_openai_responses_profile(profile: ModelProfile | None) -> bool:
|
|
83
|
+
"""Return True for profiles that use OpenAI Responses transport."""
|
|
84
|
+
return profile is not None and profile.provider == "openai" and profile.api_style == API_STYLE_RESPONSES
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
def _responses_service_session_profiles_match(
|
|
88
|
+
old_profile: ModelProfile | None, new_profile: ModelProfile | None
|
|
89
|
+
) -> bool:
|
|
90
|
+
"""Return True when two profiles can safely share a Responses service session id."""
|
|
91
|
+
return (
|
|
92
|
+
_is_openai_responses_profile(old_profile)
|
|
93
|
+
and _is_openai_responses_profile(new_profile)
|
|
94
|
+
and old_profile is not None
|
|
95
|
+
and new_profile is not None
|
|
96
|
+
and old_profile.model_id == new_profile.model_id
|
|
97
|
+
)
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
def _workspace_signature(workspace: Workspace | None) -> tuple[str, tuple[str, ...]]:
|
|
101
|
+
"""Return the session-relevant workspace identity for service-session reuse."""
|
|
102
|
+
if workspace is None:
|
|
103
|
+
return ("", ())
|
|
104
|
+
return (workspace.primary_cwd, tuple(working_dir.path for working_dir in workspace.working_dirs))
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
def _workspace_primary_cwd(workspace: Workspace | None) -> str:
|
|
108
|
+
"""Return the workspace primary cwd used for project-scoped config."""
|
|
109
|
+
return workspace.primary_cwd if workspace is not None else ""
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
def _can_reuse_responses_service_session(
|
|
113
|
+
*,
|
|
114
|
+
old_agent_profile_fingerprint: str,
|
|
115
|
+
new_agent_profile_fingerprint: str,
|
|
116
|
+
old_model_profile_fingerprint: str,
|
|
117
|
+
new_model_profile_fingerprint: str,
|
|
118
|
+
old_model_profile: ModelProfile | None,
|
|
119
|
+
new_model_profile: ModelProfile | None,
|
|
120
|
+
old_model_base_url: str,
|
|
121
|
+
new_model_base_url: str,
|
|
122
|
+
old_workspace: Workspace | None,
|
|
123
|
+
new_workspace: Workspace | None,
|
|
124
|
+
old_storage_enabled: bool,
|
|
125
|
+
new_storage_enabled: bool,
|
|
126
|
+
) -> bool:
|
|
127
|
+
"""Return True when a Responses service session can safely survive a rebuild."""
|
|
128
|
+
return bool(
|
|
129
|
+
_responses_service_session_profiles_match(old_model_profile, new_model_profile)
|
|
130
|
+
and old_agent_profile_fingerprint
|
|
131
|
+
and old_agent_profile_fingerprint == new_agent_profile_fingerprint
|
|
132
|
+
and old_model_profile_fingerprint
|
|
133
|
+
and old_model_profile_fingerprint == new_model_profile_fingerprint
|
|
134
|
+
and old_model_base_url
|
|
135
|
+
and old_model_base_url == new_model_base_url
|
|
136
|
+
and _workspace_signature(old_workspace) == _workspace_signature(new_workspace)
|
|
137
|
+
and old_storage_enabled
|
|
138
|
+
and new_storage_enabled
|
|
139
|
+
)
|
|
140
|
+
|
|
141
|
+
|
|
142
|
+
async def _close_replaced_hook_manager(manager: HookManager | None) -> None:
|
|
143
|
+
"""Close a hook manager that no longer belongs to the live executor."""
|
|
144
|
+
if manager is None:
|
|
145
|
+
return
|
|
146
|
+
try:
|
|
147
|
+
await manager.drain_session()
|
|
148
|
+
except Exception:
|
|
149
|
+
logger.exception("Error draining replaced hook manager")
|
|
150
|
+
|
|
151
|
+
|
|
152
|
+
def _preserved_history_state(raw: dict | None) -> dict | None:
|
|
153
|
+
"""Deep copy of the predecessor's history state, installed as the successor's live history.
|
|
154
|
+
|
|
155
|
+
The copy owns every layer (messages, contents lists, content objects) so the
|
|
156
|
+
successor's registries and anchors can never alias the predecessor's live
|
|
157
|
+
objects. Falsy/empty history returns ``None`` — no carryover to preserve.
|
|
158
|
+
"""
|
|
159
|
+
return copy.deepcopy(raw) if raw else None
|
|
160
|
+
|
|
161
|
+
|
|
162
|
+
class AgentLoader:
|
|
163
|
+
"""Construct candidates, install their values, and release displaced build resources."""
|
|
164
|
+
|
|
165
|
+
def __init__(
|
|
166
|
+
self,
|
|
167
|
+
*,
|
|
168
|
+
bus: EventBus,
|
|
169
|
+
persistence: SessionPersistence,
|
|
170
|
+
agent_registry: AgentProfileRegistry | None,
|
|
171
|
+
model_registry: ModelProfileRegistry | None,
|
|
172
|
+
settings_handle: SettingsHandle,
|
|
173
|
+
session: ActiveSession,
|
|
174
|
+
current: CurrentAgent,
|
|
175
|
+
permits: LifecyclePermits,
|
|
176
|
+
checkpoints: RecoveryCheckpoints,
|
|
177
|
+
usage_publisher: UsagePublisher,
|
|
178
|
+
hooks: TurnHookDispatcher,
|
|
179
|
+
history: SessionHistoryManager,
|
|
180
|
+
turn_state: TurnRuntimeState,
|
|
181
|
+
workspace_change_tracker: WorkspaceChangeTracker,
|
|
182
|
+
trajectory_recorder: TrajectoryRecorder,
|
|
183
|
+
fsm: EngineStateMachine,
|
|
184
|
+
turn_context: TurnContextHolder,
|
|
185
|
+
mcp_cache: MCPConnectionCache,
|
|
186
|
+
mcp_overlay: list[MCPServerConfig] | None,
|
|
187
|
+
allow_user_interaction: bool,
|
|
188
|
+
build_agent_fn: BuildAgentFn,
|
|
189
|
+
register_current_engine: Callable[[], None],
|
|
190
|
+
) -> None:
|
|
191
|
+
self._bus = bus
|
|
192
|
+
self._persistence = persistence
|
|
193
|
+
self._agent_registry = agent_registry
|
|
194
|
+
self._model_registry = model_registry
|
|
195
|
+
self._settings_handle = settings_handle
|
|
196
|
+
self._session = session
|
|
197
|
+
self._current = current
|
|
198
|
+
self._permits = permits
|
|
199
|
+
self._checkpoints = checkpoints
|
|
200
|
+
self._usage_publisher = usage_publisher
|
|
201
|
+
self._hooks = hooks
|
|
202
|
+
self._history = history
|
|
203
|
+
self._turn_state = turn_state
|
|
204
|
+
self._workspace_change_tracker = workspace_change_tracker
|
|
205
|
+
self._trajectory_recorder = trajectory_recorder
|
|
206
|
+
self._fsm = fsm
|
|
207
|
+
self._mcp_cache = mcp_cache
|
|
208
|
+
self._turn_context = turn_context
|
|
209
|
+
self._injection_notify_tasks: set[asyncio.Task[None]] = set()
|
|
210
|
+
self._mcp_overlay = list(mcp_overlay or [])
|
|
211
|
+
self._allow_user_interaction = allow_user_interaction
|
|
212
|
+
self._build_agent_fn = build_agent_fn
|
|
213
|
+
self._register_current_engine = register_current_engine
|
|
214
|
+
|
|
215
|
+
def stage(
|
|
216
|
+
self,
|
|
217
|
+
*,
|
|
218
|
+
loaded: LoadedSettings,
|
|
219
|
+
agent_profile: AgentProfile,
|
|
220
|
+
workspace: Workspace | None,
|
|
221
|
+
hook_manager: HookManager | None,
|
|
222
|
+
) -> StagedBuild:
|
|
223
|
+
"""Assemble the settings, workspace, and coordinator candidate."""
|
|
224
|
+
return construction.stage_build(
|
|
225
|
+
session=self._session,
|
|
226
|
+
persistence=self._persistence,
|
|
227
|
+
loaded=loaded,
|
|
228
|
+
agent_profile=agent_profile,
|
|
229
|
+
workspace=workspace,
|
|
230
|
+
hook_manager=hook_manager,
|
|
231
|
+
)
|
|
232
|
+
|
|
233
|
+
async def stage_hook_manager(
|
|
234
|
+
self,
|
|
235
|
+
*,
|
|
236
|
+
operation: str,
|
|
237
|
+
staged_loaded: LoadedSettings | None,
|
|
238
|
+
workspace: Workspace | None,
|
|
239
|
+
) -> HookManager | None:
|
|
240
|
+
"""Construct the hook candidate when the caller's replacement decision requires it."""
|
|
241
|
+
old_hook_manager = self._session.hook_manager
|
|
242
|
+
hook_manager = old_hook_manager
|
|
243
|
+
if old_hook_manager is None or operation == "workspace_change":
|
|
244
|
+
# Project hooks are primary-cwd scoped, so the candidate is built for
|
|
245
|
+
# the root the staged workspace would install, not the live one.
|
|
246
|
+
build_settings = (staged_loaded if staged_loaded is not None else self._settings_handle.loaded).settings
|
|
247
|
+
hook_manager = await self.build_hook_manager(
|
|
248
|
+
project_root=_workspace_primary_cwd(workspace),
|
|
249
|
+
project_hooks_enabled=build_settings.project_hooks_enabled,
|
|
250
|
+
)
|
|
251
|
+
return hook_manager
|
|
252
|
+
|
|
253
|
+
async def build(
|
|
254
|
+
self, profile: AgentProfile, staged: StagedBuild, *, preserved_history: dict | None = None
|
|
255
|
+
) -> CompletedBuild:
|
|
256
|
+
"""Construct a complete candidate without installing it."""
|
|
257
|
+
return await construction.build_agent(
|
|
258
|
+
self._profile_with_mcp_overlay(profile),
|
|
259
|
+
staged=staged,
|
|
260
|
+
preserved_history=preserved_history,
|
|
261
|
+
build_agent_fn=self._build_agent_fn,
|
|
262
|
+
session=self._session,
|
|
263
|
+
settings_handle=self._settings_handle,
|
|
264
|
+
persistence=self._persistence,
|
|
265
|
+
bus=self._bus,
|
|
266
|
+
agent_registry=self._agent_registry,
|
|
267
|
+
model_registry=self._model_registry,
|
|
268
|
+
workspace_change_tracker=self._workspace_change_tracker,
|
|
269
|
+
turn_state=self._turn_state,
|
|
270
|
+
turn_context=self._turn_context,
|
|
271
|
+
mcp_cache=self._mcp_cache,
|
|
272
|
+
allow_user_interaction=self._allow_user_interaction,
|
|
273
|
+
checkpoints=self._checkpoints,
|
|
274
|
+
usage_publisher=self._usage_publisher,
|
|
275
|
+
fire_pre_compact=self._hooks.fire_pre_compact,
|
|
276
|
+
publish_load_progress=self.publish_load_progress,
|
|
277
|
+
hold_injection_notification=self.hold_injection_notification,
|
|
278
|
+
)
|
|
279
|
+
|
|
280
|
+
def _workspace_cwd(self) -> str:
|
|
281
|
+
"""Return the engine workspace cwd, falling back only for legacy unstarted engines."""
|
|
282
|
+
if self._session.workspace is not None:
|
|
283
|
+
return self._session.workspace.primary_cwd
|
|
284
|
+
return safe_getcwd()
|
|
285
|
+
|
|
286
|
+
def _workspace_working_dirs(self) -> list[str]:
|
|
287
|
+
"""Return all workspace root paths for event payloads."""
|
|
288
|
+
if self._session.workspace is None:
|
|
289
|
+
return []
|
|
290
|
+
return [working_dir.path for working_dir in self._session.workspace.working_dirs]
|
|
291
|
+
|
|
292
|
+
def trajectory_session_start_info(self) -> SessionStartInfo:
|
|
293
|
+
"""Resolved lazily, at the recorder's first event — after the build set the fingerprints."""
|
|
294
|
+
return SessionStartInfo(
|
|
295
|
+
primary_cwd=_workspace_primary_cwd(self._session.workspace),
|
|
296
|
+
agent_profile_fingerprint=self._current.manifest.agent_profile_fingerprint,
|
|
297
|
+
model_profile_fingerprint=self._current.manifest.model_profile_fingerprint,
|
|
298
|
+
)
|
|
299
|
+
|
|
300
|
+
async def build_hook_manager(
|
|
301
|
+
self, *, project_root: str, project_hooks_enabled: bool, session_id: str | None = None
|
|
302
|
+
) -> HookManager | None:
|
|
303
|
+
return await SessionHookFactory(self._bus)(
|
|
304
|
+
project_root=project_root,
|
|
305
|
+
project_hooks_enabled=project_hooks_enabled,
|
|
306
|
+
session_id=session_id or self._session.session_id,
|
|
307
|
+
)
|
|
308
|
+
|
|
309
|
+
def start_outbox_recovery(self) -> None:
|
|
310
|
+
"""Start durable outbox recovery for the current hook manager if needed."""
|
|
311
|
+
if self._session.hook_manager is None or self._session.outbox_recovery_task is not None:
|
|
312
|
+
return
|
|
313
|
+
# Background-recover the outbox only after the session guard is held.
|
|
314
|
+
# That prevents a failed/conflicting startup from spawning work, and
|
|
315
|
+
# shutdown explicitly observes/cancels this task before draining hooks.
|
|
316
|
+
self._session.outbox_recovery_task = asyncio.create_task(self._session.hook_manager.recover_outbox())
|
|
317
|
+
|
|
318
|
+
async def cancel_outbox_recovery(self) -> None:
|
|
319
|
+
"""Observe or cancel the active outbox recovery task before replacing managers."""
|
|
320
|
+
task = self._session.outbox_recovery_task
|
|
321
|
+
if task is None:
|
|
322
|
+
return
|
|
323
|
+
if task.done():
|
|
324
|
+
try:
|
|
325
|
+
task.result()
|
|
326
|
+
except asyncio.CancelledError:
|
|
327
|
+
pass
|
|
328
|
+
except Exception:
|
|
329
|
+
logger.exception("Outbox recovery task failed")
|
|
330
|
+
else:
|
|
331
|
+
task.cancel()
|
|
332
|
+
with contextlib.suppress(asyncio.CancelledError):
|
|
333
|
+
await task
|
|
334
|
+
self._session.outbox_recovery_task = None
|
|
335
|
+
|
|
336
|
+
async def commit_hook_manager_replacement(
|
|
337
|
+
self,
|
|
338
|
+
old_hook_manager: HookManager | None,
|
|
339
|
+
) -> None:
|
|
340
|
+
"""Retire the old hook manager after a replacement executor is installed."""
|
|
341
|
+
await self.cancel_outbox_recovery()
|
|
342
|
+
await _close_replaced_hook_manager(old_hook_manager)
|
|
343
|
+
self.start_outbox_recovery()
|
|
344
|
+
|
|
345
|
+
async def settle_staged_hook_manager(
|
|
346
|
+
self,
|
|
347
|
+
*,
|
|
348
|
+
old: HookManager | None,
|
|
349
|
+
staged: HookManager | None,
|
|
350
|
+
) -> None:
|
|
351
|
+
"""After a failed build, retire whichever hook manager lost.
|
|
352
|
+
|
|
353
|
+
Pre-commit failure: the staged candidate never went live — drain it and
|
|
354
|
+
leave the old manager, its outbox and its recovery task untouched.
|
|
355
|
+
Post-commit failure: the candidate is installed and the build it belongs
|
|
356
|
+
to is what the engine keeps, so retire the old manager exactly as the
|
|
357
|
+
success path would have.
|
|
358
|
+
"""
|
|
359
|
+
if staged is old:
|
|
360
|
+
return
|
|
361
|
+
if self._session.hook_manager is staged:
|
|
362
|
+
await self.commit_hook_manager_replacement(old)
|
|
363
|
+
else:
|
|
364
|
+
await _close_replaced_hook_manager(staged)
|
|
365
|
+
|
|
366
|
+
async def load(
|
|
367
|
+
self,
|
|
368
|
+
profile: AgentProfile,
|
|
369
|
+
*,
|
|
370
|
+
operation: str = "startup",
|
|
371
|
+
staged_loaded: LoadedSettings | None = None,
|
|
372
|
+
workspace: Workspace | None,
|
|
373
|
+
hook_manager: HookManager | None,
|
|
374
|
+
trajectory: SessionTrajectory,
|
|
375
|
+
old_hook_manager: HookManager | None,
|
|
376
|
+
) -> None:
|
|
377
|
+
"""Build and install the agent from a profile.
|
|
378
|
+
|
|
379
|
+
``staged_loaded`` is a settings candidate the build should be configured
|
|
380
|
+
from instead of the live handle — a settings reload or workspace change
|
|
381
|
+
retrying after a failed first build passes the re-derived load here, and
|
|
382
|
+
it goes live only when the build commits. ``workspace`` is the same thing
|
|
383
|
+
for the workspace: a no-executor workspace change passes the new root here
|
|
384
|
+
rather than mutating the live one, so a failed build keeps the workspace
|
|
385
|
+
the live settings and hooks still describe.
|
|
386
|
+
"""
|
|
387
|
+
self._permits.begin_agent_load()
|
|
388
|
+
try:
|
|
389
|
+
await self._bus.publish(
|
|
390
|
+
AgentLoadStarted(
|
|
391
|
+
operation=operation,
|
|
392
|
+
to_profile=profile.name,
|
|
393
|
+
to_display_name=profile.display_name or profile.name,
|
|
394
|
+
session_id=self._session.session_id,
|
|
395
|
+
),
|
|
396
|
+
)
|
|
397
|
+
|
|
398
|
+
staged = self.stage(
|
|
399
|
+
loaded=staged_loaded if staged_loaded is not None else self._settings_handle.loaded,
|
|
400
|
+
agent_profile=profile,
|
|
401
|
+
workspace=workspace,
|
|
402
|
+
hook_manager=hook_manager,
|
|
403
|
+
)
|
|
404
|
+
completed = await self.build(profile, staged)
|
|
405
|
+
replaced = self.install(completed)
|
|
406
|
+
await self.release(replaced)
|
|
407
|
+
self._fsm.try_transition(Trigger.START)
|
|
408
|
+
self._register_current_engine()
|
|
409
|
+
except Exception as exc:
|
|
410
|
+
await self.settle_staged_hook_manager(old=old_hook_manager, staged=hook_manager)
|
|
411
|
+
self._permits.finish_agent_load()
|
|
412
|
+
await self.publish_load_failed(operation=operation, profile=profile, exc=exc)
|
|
413
|
+
raise
|
|
414
|
+
except BaseException:
|
|
415
|
+
await self.settle_staged_hook_manager(old=old_hook_manager, staged=hook_manager)
|
|
416
|
+
self._permits.finish_agent_load()
|
|
417
|
+
raise
|
|
418
|
+
|
|
419
|
+
# The build committed, so the profiles this session opened with are the
|
|
420
|
+
# ones it keeps: pin them before a switch can rewrite what the recorder
|
|
421
|
+
# reads at its first event.
|
|
422
|
+
trajectory.pin_session_start_info()
|
|
423
|
+
|
|
424
|
+
if hook_manager is not old_hook_manager:
|
|
425
|
+
await self.commit_hook_manager_replacement(old_hook_manager)
|
|
426
|
+
else:
|
|
427
|
+
self.start_outbox_recovery()
|
|
428
|
+
|
|
429
|
+
self._permits.finish_agent_load()
|
|
430
|
+
await self._bus.publish(
|
|
431
|
+
AgentLoadFinished(
|
|
432
|
+
operation=operation,
|
|
433
|
+
agent_profile=profile.name,
|
|
434
|
+
display_name=profile.display_name or profile.name,
|
|
435
|
+
session_id=self._session.session_id,
|
|
436
|
+
),
|
|
437
|
+
)
|
|
438
|
+
|
|
439
|
+
sub_agent_tool_names = (
|
|
440
|
+
self._current.loaded.sub_agent_tools.tool_names()
|
|
441
|
+
if self._current.loaded is not None and self._current.loaded.sub_agent_tools
|
|
442
|
+
else []
|
|
443
|
+
)
|
|
444
|
+
await self._bus.publish(
|
|
445
|
+
SessionReady(
|
|
446
|
+
agent_profile=profile.name,
|
|
447
|
+
display_name=profile.display_name,
|
|
448
|
+
model_profile_id=self._current.manifest.active_profile.id
|
|
449
|
+
if self._current.manifest.active_profile
|
|
450
|
+
else "",
|
|
451
|
+
max_context_tokens=self._current.manifest.active_profile.max_context_tokens
|
|
452
|
+
if self._current.manifest.active_profile
|
|
453
|
+
else 0,
|
|
454
|
+
session_id=self._session.session_id,
|
|
455
|
+
tool_names=list(self._current.manifest.tool_names),
|
|
456
|
+
tool_kinds=dict(self._current.manifest.tool_kinds),
|
|
457
|
+
skill_names=list(self._current.manifest.skill_names),
|
|
458
|
+
sub_agent_tool_names=sub_agent_tool_names,
|
|
459
|
+
memory_files=list(self._current.manifest.memory_files),
|
|
460
|
+
runtime_details=copy.deepcopy(self._current.manifest.runtime_details),
|
|
461
|
+
primary_cwd=self._workspace_cwd(),
|
|
462
|
+
working_dirs=self._workspace_working_dirs(),
|
|
463
|
+
),
|
|
464
|
+
)
|
|
465
|
+
await self._bus.publish(
|
|
466
|
+
ApprovalModeUpdated(mode=self._session.approval_mode.value, session_id=self._session.session_id)
|
|
467
|
+
)
|
|
468
|
+
|
|
469
|
+
# Fire ``session_start`` hooks after the engine is fully ready and
|
|
470
|
+
# the UI has its ``SessionReady`` event. Hooks are observers here:
|
|
471
|
+
# they cannot deny startup or mutate engine state, although a
|
|
472
|
+
# blocking hook still runs inline at this post-ready boundary.
|
|
473
|
+
# Profile-switch/rebuild operations skip this so users don't see a
|
|
474
|
+
# hook fire every time the same session reloads infrastructure.
|
|
475
|
+
if self._session.hook_manager is not None and operation in {"startup", "new_session", "reset"}:
|
|
476
|
+
from chrys.service.hooks.events import HookEvent
|
|
477
|
+
|
|
478
|
+
await self._session.hook_manager.fire(
|
|
479
|
+
HookEvent.SESSION_START,
|
|
480
|
+
{"session_id": self._session.session_id, "profile": profile.name, "cwd": self._workspace_cwd()},
|
|
481
|
+
scope="session",
|
|
482
|
+
)
|
|
483
|
+
|
|
484
|
+
async def publish_load_progress(
|
|
485
|
+
self,
|
|
486
|
+
*,
|
|
487
|
+
phase: str,
|
|
488
|
+
message: str,
|
|
489
|
+
server_name: str = "",
|
|
490
|
+
current: int = 0,
|
|
491
|
+
total: int = 0,
|
|
492
|
+
failed: int = 0,
|
|
493
|
+
status: str = "",
|
|
494
|
+
subject: str = "",
|
|
495
|
+
detail: str = "",
|
|
496
|
+
) -> None:
|
|
497
|
+
"""Publish an agent load progress event."""
|
|
498
|
+
await self._bus.publish(
|
|
499
|
+
AgentLoadProgress(
|
|
500
|
+
phase=phase,
|
|
501
|
+
message=message,
|
|
502
|
+
server_name=server_name,
|
|
503
|
+
current=current,
|
|
504
|
+
total=total,
|
|
505
|
+
failed=failed,
|
|
506
|
+
status=status,
|
|
507
|
+
subject=subject,
|
|
508
|
+
detail=detail,
|
|
509
|
+
session_id=self._session.session_id,
|
|
510
|
+
),
|
|
511
|
+
)
|
|
512
|
+
|
|
513
|
+
async def publish_load_failed(
|
|
514
|
+
self,
|
|
515
|
+
*,
|
|
516
|
+
operation: str,
|
|
517
|
+
profile: AgentProfile,
|
|
518
|
+
exc: Exception,
|
|
519
|
+
) -> None:
|
|
520
|
+
"""Publish an agent load failure event."""
|
|
521
|
+
display_message, display_hint = display_fields(exc)
|
|
522
|
+
await self._bus.publish(
|
|
523
|
+
AgentLoadFailed(
|
|
524
|
+
operation=operation,
|
|
525
|
+
agent_profile=profile.name,
|
|
526
|
+
display_name=profile.display_name or profile.name,
|
|
527
|
+
message=clean_error_message(exc),
|
|
528
|
+
session_id=self._session.session_id,
|
|
529
|
+
display_message=display_message,
|
|
530
|
+
display_hint=display_hint,
|
|
531
|
+
),
|
|
532
|
+
)
|
|
533
|
+
|
|
534
|
+
async def reload(
|
|
535
|
+
self,
|
|
536
|
+
new_profile: AgentProfile,
|
|
537
|
+
workspace: Workspace | None = None,
|
|
538
|
+
*,
|
|
539
|
+
operation: str = "switch",
|
|
540
|
+
staged_loaded: LoadedSettings | None = None,
|
|
541
|
+
) -> None:
|
|
542
|
+
"""Restart the agent with a new profile/workspace while preserving history.
|
|
543
|
+
|
|
544
|
+
``staged_loaded`` is a settings candidate the build should be configured
|
|
545
|
+
from instead of the live handle — a settings reload or workspace change
|
|
546
|
+
passes the re-derived load here, and it goes live only when the build
|
|
547
|
+
commits. A pre-commit failure therefore leaves the settings the previous
|
|
548
|
+
executor was built from untouched; a post-commit failure keeps the new
|
|
549
|
+
ones, because they are what the installed executor runs with.
|
|
550
|
+
"""
|
|
551
|
+
old_profile_name = self._session.agent_profile.name if self._session.agent_profile else ""
|
|
552
|
+
old_display_name = self._session.agent_profile.display_name if self._session.agent_profile else ""
|
|
553
|
+
old_model_profile = self._current.manifest.active_profile
|
|
554
|
+
old_model_base_url = self._current.manifest.runtime_details.model.base_url
|
|
555
|
+
old_agent_profile_fingerprint = self._current.manifest.agent_profile_fingerprint
|
|
556
|
+
old_model_profile_fingerprint = self._current.manifest.model_profile_fingerprint
|
|
557
|
+
old_service_session_id = (
|
|
558
|
+
self._current.loaded.bindings.backend.service_session_id if self._current.loaded is not None else ""
|
|
559
|
+
)
|
|
560
|
+
old_service_session_storage_enabled = (
|
|
561
|
+
self._current.loaded.bindings.backend.service_session_storage_enabled
|
|
562
|
+
if self._current.loaded is not None
|
|
563
|
+
else False
|
|
564
|
+
)
|
|
565
|
+
old_workspace = self._session.workspace
|
|
566
|
+
old_hook_manager = self._session.hook_manager
|
|
567
|
+
staged_hook_manager = old_hook_manager
|
|
568
|
+
new_loaded = staged_loaded if staged_loaded is not None else self._settings_handle.loaded
|
|
569
|
+
# Project hooks are primary-cwd scoped and gated by ``project.hooks_enabled``:
|
|
570
|
+
# a new primary cwd or a flipped gate rebuilds the manager for the root
|
|
571
|
+
# the build is about to install (the live one when the workspace stays).
|
|
572
|
+
reload_hook_manager = (
|
|
573
|
+
workspace is not None and _workspace_primary_cwd(old_workspace) != _workspace_primary_cwd(workspace)
|
|
574
|
+
) or new_loaded.settings.project_hooks_enabled != self._settings_handle.loaded.settings.project_hooks_enabled
|
|
575
|
+
hook_manager_root = _workspace_primary_cwd(workspace if workspace is not None else old_workspace)
|
|
576
|
+
hook_manager_replacement_committed = False
|
|
577
|
+
|
|
578
|
+
preserved_state: dict | None = None
|
|
579
|
+
self._permits.begin_agent_load()
|
|
580
|
+
try:
|
|
581
|
+
await self._bus.publish(
|
|
582
|
+
AgentLoadStarted(
|
|
583
|
+
operation=operation,
|
|
584
|
+
from_profile=old_profile_name,
|
|
585
|
+
to_profile=new_profile.name,
|
|
586
|
+
from_display_name=old_display_name or old_profile_name,
|
|
587
|
+
to_display_name=new_profile.display_name or new_profile.name,
|
|
588
|
+
session_id=self._session.session_id,
|
|
589
|
+
),
|
|
590
|
+
)
|
|
591
|
+
|
|
592
|
+
if self._current.loaded is not None:
|
|
593
|
+
raw = self._current.loaded.bindings.backend.history_state
|
|
594
|
+
preserved_state = _preserved_history_state(raw)
|
|
595
|
+
if self._current.loaded is not None:
|
|
596
|
+
catalog_pointer_record_count = (
|
|
597
|
+
self._current.loaded.reminder_middleware.sources.archive_pointer.record_count_state()
|
|
598
|
+
)
|
|
599
|
+
if catalog_pointer_record_count is not None:
|
|
600
|
+
preserved_state = preserved_state or {}
|
|
601
|
+
preserved_state[CATALOG_POINTER_RECORD_COUNT_STATE_KEY] = catalog_pointer_record_count
|
|
602
|
+
|
|
603
|
+
old_pending_switch = (
|
|
604
|
+
self._current.loaded.reminder_middleware.sources.profile_switch.snapshot_pending_switch()
|
|
605
|
+
if self._current.loaded is not None
|
|
606
|
+
else None
|
|
607
|
+
)
|
|
608
|
+
is_consecutive = old_pending_switch is not None
|
|
609
|
+
|
|
610
|
+
if preserved_state is not None and new_profile.name != old_profile_name:
|
|
611
|
+
switches = preserved_state.setdefault("agent_profile_switches", [])
|
|
612
|
+
new_label = new_profile.display_name or new_profile.name
|
|
613
|
+
if is_consecutive and switches:
|
|
614
|
+
switches[-1]["to"] = new_profile.name
|
|
615
|
+
switches[-1]["to_display"] = new_label
|
|
616
|
+
switches[-1]["timestamp"] = datetime.now(UTC).isoformat()
|
|
617
|
+
if switches[-1]["from"] == new_profile.name:
|
|
618
|
+
switches.pop()
|
|
619
|
+
else:
|
|
620
|
+
switches.append(
|
|
621
|
+
{
|
|
622
|
+
"from": old_profile_name,
|
|
623
|
+
"to": new_profile.name,
|
|
624
|
+
"from_display": old_display_name or old_profile_name,
|
|
625
|
+
"to_display": new_label,
|
|
626
|
+
"at_message_index": len(preserved_state.get("messages", [])),
|
|
627
|
+
"timestamp": datetime.now(UTC).isoformat(),
|
|
628
|
+
},
|
|
629
|
+
)
|
|
630
|
+
|
|
631
|
+
if reload_hook_manager:
|
|
632
|
+
staged_hook_manager = await self.build_hook_manager(
|
|
633
|
+
project_root=hook_manager_root,
|
|
634
|
+
project_hooks_enabled=new_loaded.settings.project_hooks_enabled,
|
|
635
|
+
)
|
|
636
|
+
|
|
637
|
+
staged = self.stage(
|
|
638
|
+
loaded=staged_loaded if staged_loaded is not None else self._settings_handle.loaded,
|
|
639
|
+
agent_profile=new_profile,
|
|
640
|
+
workspace=workspace if workspace is not None else old_workspace,
|
|
641
|
+
hook_manager=staged_hook_manager,
|
|
642
|
+
)
|
|
643
|
+
# The commit inside ``_build_agent`` records ``new_profile`` with the
|
|
644
|
+
# executor it configured — and installs ``preserved_state`` into that
|
|
645
|
+
# executor in the same synchronous block. Doing either here, after the
|
|
646
|
+
# awaited post-commit steps, would let a cancellation strand the new
|
|
647
|
+
# executor under the old profile's name or publish it with an empty
|
|
648
|
+
# history for the next save to persist.
|
|
649
|
+
completed = await self.build(new_profile, staged, preserved_history=preserved_state)
|
|
650
|
+
replaced = self.install(completed)
|
|
651
|
+
await self.release(replaced)
|
|
652
|
+
if staged_hook_manager is not old_hook_manager:
|
|
653
|
+
await self.commit_hook_manager_replacement(old_hook_manager)
|
|
654
|
+
hook_manager_replacement_committed = True
|
|
655
|
+
if old_service_session_id and self._current.loaded is not None:
|
|
656
|
+
if _can_reuse_responses_service_session(
|
|
657
|
+
old_agent_profile_fingerprint=old_agent_profile_fingerprint,
|
|
658
|
+
new_agent_profile_fingerprint=self._current.manifest.agent_profile_fingerprint,
|
|
659
|
+
old_model_profile_fingerprint=old_model_profile_fingerprint,
|
|
660
|
+
new_model_profile_fingerprint=self._current.manifest.model_profile_fingerprint,
|
|
661
|
+
old_model_profile=old_model_profile,
|
|
662
|
+
new_model_profile=self._current.manifest.active_profile,
|
|
663
|
+
old_model_base_url=old_model_base_url,
|
|
664
|
+
new_model_base_url=self._current.manifest.runtime_details.model.base_url,
|
|
665
|
+
old_workspace=old_workspace,
|
|
666
|
+
new_workspace=self._session.workspace,
|
|
667
|
+
old_storage_enabled=old_service_session_storage_enabled,
|
|
668
|
+
new_storage_enabled=self._current.loaded.bindings.backend.service_session_storage_enabled,
|
|
669
|
+
):
|
|
670
|
+
self._current.loaded.bindings.backend.service_session_id = old_service_session_id
|
|
671
|
+
else:
|
|
672
|
+
self._current.loaded.bindings.backend.service_session_id = ""
|
|
673
|
+
await self._bus.publish(
|
|
674
|
+
Warning(
|
|
675
|
+
code="service_session_incompatible",
|
|
676
|
+
message=(
|
|
677
|
+
"The previous OpenAI Responses service session is not compatible with "
|
|
678
|
+
"the active agent profile, workspace, model profile, service endpoint, "
|
|
679
|
+
"or storage is disabled. "
|
|
680
|
+
f"{APP_DISPLAY_NAME} will continue from local history only."
|
|
681
|
+
),
|
|
682
|
+
display_message=_CONSTRUCTION_SERVICE_SESSION_INCOMPATIBLE.bind(
|
|
683
|
+
app_name=APP_DISPLAY_NAME,
|
|
684
|
+
),
|
|
685
|
+
session_id=self._session.session_id,
|
|
686
|
+
)
|
|
687
|
+
)
|
|
688
|
+
if new_profile.name != old_profile_name and self._current.loaded is not None:
|
|
689
|
+
new_label = new_profile.display_name or new_profile.name
|
|
690
|
+
set_profile_switch = self._current.loaded.reminder_middleware.sources.profile_switch.set_profile_switch
|
|
691
|
+
if is_consecutive and old_pending_switch is not None:
|
|
692
|
+
if old_pending_switch["from"] != new_label:
|
|
693
|
+
set_profile_switch(old_pending_switch["from"], new_label)
|
|
694
|
+
else:
|
|
695
|
+
old_label = old_display_name or old_profile_name
|
|
696
|
+
set_profile_switch(old_label, new_label)
|
|
697
|
+
|
|
698
|
+
if preserved_state is not None:
|
|
699
|
+
last_usage = preserved_state.get("last_usage")
|
|
700
|
+
if isinstance(last_usage, dict):
|
|
701
|
+
preserved_meta = SessionRuntimeMetadata.from_state_dict(preserved_state)
|
|
702
|
+
self._session.runtime_meta.last_usage_details = preserved_meta.last_usage_details
|
|
703
|
+
# Route through the ordered chain so a sub-agent UsageUpdate
|
|
704
|
+
# still queued from the prior build can't overtake this
|
|
705
|
+
# post-restart snapshot.
|
|
706
|
+
self._usage_publisher.enqueue_usage_event(self._usage_publisher.make_usage_event())
|
|
707
|
+
except Exception as exc:
|
|
708
|
+
# Nothing was staged onto the engine, so there is nothing to roll
|
|
709
|
+
# back: a pre-commit failure left every live field untouched, and a
|
|
710
|
+
# post-commit failure keeps the committed build. Only the losing
|
|
711
|
+
# hook manager still needs retiring.
|
|
712
|
+
if not hook_manager_replacement_committed:
|
|
713
|
+
await self.settle_staged_hook_manager(old=old_hook_manager, staged=staged_hook_manager)
|
|
714
|
+
self._permits.finish_agent_load()
|
|
715
|
+
await self.publish_load_failed(operation=operation, profile=new_profile, exc=exc)
|
|
716
|
+
raise
|
|
717
|
+
except BaseException:
|
|
718
|
+
if not hook_manager_replacement_committed:
|
|
719
|
+
await self.settle_staged_hook_manager(old=old_hook_manager, staged=staged_hook_manager)
|
|
720
|
+
self._permits.finish_agent_load()
|
|
721
|
+
raise
|
|
722
|
+
|
|
723
|
+
message_count = len(preserved_state.get("messages", [])) if preserved_state else 0
|
|
724
|
+
switched_sub_agent_names = (
|
|
725
|
+
self._current.loaded.sub_agent_tools.tool_names()
|
|
726
|
+
if self._current.loaded is not None and self._current.loaded.sub_agent_tools
|
|
727
|
+
else []
|
|
728
|
+
)
|
|
729
|
+
self._permits.finish_agent_load()
|
|
730
|
+
await self._bus.publish(
|
|
731
|
+
AgentLoadFinished(
|
|
732
|
+
operation=operation,
|
|
733
|
+
agent_profile=new_profile.name,
|
|
734
|
+
display_name=new_profile.display_name or new_profile.name,
|
|
735
|
+
session_id=self._session.session_id,
|
|
736
|
+
),
|
|
737
|
+
)
|
|
738
|
+
await self._bus.publish(
|
|
739
|
+
ProfileSwitched(
|
|
740
|
+
from_profile=old_profile_name,
|
|
741
|
+
to_profile=new_profile.name,
|
|
742
|
+
from_display_name=old_display_name or old_profile_name,
|
|
743
|
+
to_display_name=new_profile.display_name or new_profile.name,
|
|
744
|
+
message_count=message_count,
|
|
745
|
+
model_profile_id=self._current.manifest.active_profile.id
|
|
746
|
+
if self._current.manifest.active_profile
|
|
747
|
+
else "",
|
|
748
|
+
max_context_tokens=self._current.manifest.active_profile.max_context_tokens
|
|
749
|
+
if self._current.manifest.active_profile
|
|
750
|
+
else 0,
|
|
751
|
+
session_id=self._session.session_id,
|
|
752
|
+
tool_names=list(self._current.manifest.tool_names),
|
|
753
|
+
skill_names=list(self._current.manifest.skill_names),
|
|
754
|
+
sub_agent_tool_names=switched_sub_agent_names,
|
|
755
|
+
memory_files=list(self._current.manifest.memory_files),
|
|
756
|
+
runtime_details=copy.deepcopy(self._current.manifest.runtime_details),
|
|
757
|
+
),
|
|
758
|
+
)
|
|
759
|
+
await self._trajectory_recorder.profile_switched(
|
|
760
|
+
kind=ProfileKind.AGENT,
|
|
761
|
+
from_fingerprint=old_agent_profile_fingerprint,
|
|
762
|
+
to_fingerprint=self._current.manifest.agent_profile_fingerprint,
|
|
763
|
+
)
|
|
764
|
+
await self._trajectory_recorder.profile_switched(
|
|
765
|
+
kind=ProfileKind.MODEL,
|
|
766
|
+
from_fingerprint=old_model_profile_fingerprint,
|
|
767
|
+
to_fingerprint=self._current.manifest.model_profile_fingerprint,
|
|
768
|
+
)
|
|
769
|
+
if workspace is not None:
|
|
770
|
+
await self._bus.publish(
|
|
771
|
+
WorkspaceUpdated(
|
|
772
|
+
primary_cwd=workspace.primary_cwd,
|
|
773
|
+
working_dirs=[d.path for d in workspace.working_dirs],
|
|
774
|
+
reference_files=workspace.reference_files,
|
|
775
|
+
session_id=self._session.session_id,
|
|
776
|
+
),
|
|
777
|
+
)
|
|
778
|
+
|
|
779
|
+
def install(self, completed: CompletedBuild) -> ReplacedBuild:
|
|
780
|
+
"""Install the completed candidate before releasing the previous owner."""
|
|
781
|
+
old_loaded = self._current.loaded
|
|
782
|
+
old_coordinator = self._session.mutation_coordinator
|
|
783
|
+
staged = completed.staged
|
|
784
|
+
# The commit: everything the build was configured from goes live in one
|
|
785
|
+
# synchronous block together with the executor it produced — no await
|
|
786
|
+
# between the first assignment and the last, so a concurrent reader sees
|
|
787
|
+
# the old build entirely or the new one entirely, never a mixture.
|
|
788
|
+
self._settings_handle.install_prepared(completed.settings)
|
|
789
|
+
self._session.install_build(
|
|
790
|
+
staged, mutation_tracker=completed.mutation_tracker, todo_tracker=completed.todo_tracker
|
|
791
|
+
)
|
|
792
|
+
self._current.loaded = completed.loaded
|
|
793
|
+
self._current.manifest = completed.manifest
|
|
794
|
+
self._history.bind(completed.loaded.bindings.backend.history_state)
|
|
795
|
+
self._workspace_change_tracker.apply_retarget(completed.workspace_retarget)
|
|
796
|
+
self._permits.advance_build_generation()
|
|
797
|
+
return ReplacedBuild(
|
|
798
|
+
loaded=old_loaded,
|
|
799
|
+
coordinator=old_coordinator if old_coordinator is not staged.mutation_coordinator else None,
|
|
800
|
+
)
|
|
801
|
+
|
|
802
|
+
async def release(self, replaced: ReplacedBuild) -> None:
|
|
803
|
+
old_prepared = replaced.loaded.prepared if replaced.loaded is not None else None
|
|
804
|
+
old_coordinator = replaced.coordinator
|
|
805
|
+
cancelled: asyncio.CancelledError | None = None
|
|
806
|
+
if old_coordinator is not None:
|
|
807
|
+
# Settings turned coordination off (or the session re-targeted): the
|
|
808
|
+
# replaced registry file is stamped closed only now that the build is
|
|
809
|
+
# committed, so peers keep warning about us until we truly stop.
|
|
810
|
+
try:
|
|
811
|
+
await construction._close_coordinator(old_coordinator, reason="replaced")
|
|
812
|
+
except asyncio.CancelledError as exc:
|
|
813
|
+
cancelled = exc
|
|
814
|
+
try:
|
|
815
|
+
await self._cleanup_replaced_build_resources(old_prepared)
|
|
816
|
+
except asyncio.CancelledError as exc:
|
|
817
|
+
cancelled = exc
|
|
818
|
+
if cancelled is not None:
|
|
819
|
+
raise cancelled
|
|
820
|
+
|
|
821
|
+
def apply_skill_refresh(
|
|
822
|
+
self, *, skill_names: list[str], skill_sources: dict[str, list[str]], skill_details: list[RuntimeSkillDetails]
|
|
823
|
+
) -> AgentManifest:
|
|
824
|
+
"""Install a new manifest containing the refreshed skill catalog."""
|
|
825
|
+
manifest = self._current.manifest.with_skill_refresh(
|
|
826
|
+
skill_names=skill_names, skill_sources=skill_sources, skill_details=skill_details
|
|
827
|
+
)
|
|
828
|
+
self._current.manifest = manifest
|
|
829
|
+
return manifest
|
|
830
|
+
|
|
831
|
+
def hold_injection_notification(self, task: asyncio.Task[None]) -> None:
|
|
832
|
+
"""Hold the latest detached injection delivery task."""
|
|
833
|
+
self._injection_notify_tasks.add(task)
|
|
834
|
+
task.add_done_callback(self._injection_notify_tasks.discard)
|
|
835
|
+
|
|
836
|
+
def _profile_with_mcp_overlay(self, profile: AgentProfile) -> AgentProfile:
|
|
837
|
+
"""Return a per-session profile copy with ephemeral MCP servers appended."""
|
|
838
|
+
if not self._mcp_overlay:
|
|
839
|
+
return profile
|
|
840
|
+
effective = copy.deepcopy(profile)
|
|
841
|
+
effective.tools.mcp.extend(copy.deepcopy(self._mcp_overlay))
|
|
842
|
+
return effective
|
|
843
|
+
|
|
844
|
+
async def _cleanup_replaced_build_resources(self, old_prepared: PreparedAgent | None) -> None:
|
|
845
|
+
"""Drain the displaced owner; borrowed engine fields have no close authority.
|
|
846
|
+
|
|
847
|
+
Prepared keeps its cleanup task reachable and completes every release even
|
|
848
|
+
if this post-install waiter is cancelled repeatedly.
|
|
849
|
+
"""
|
|
850
|
+
if old_prepared is not None and old_prepared is not (
|
|
851
|
+
self._current.loaded.prepared if self._current.loaded is not None else None
|
|
852
|
+
):
|
|
853
|
+
await old_prepared.aclose()
|
|
854
|
+
|
|
855
|
+
async def release_current(self) -> None:
|
|
856
|
+
"""Close the installed owner and then clear the live resource slot."""
|
|
857
|
+
loaded = self._current.loaded
|
|
858
|
+
if loaded is not None:
|
|
859
|
+
await loaded.aclose()
|
|
860
|
+
self._current.loaded = None
|
|
861
|
+
|
|
862
|
+
async def close(self) -> None:
|
|
863
|
+
"""Close and replace the engine-level MCP connection cache."""
|
|
864
|
+
await self._mcp_cache.close_all()
|
|
865
|
+
self._mcp_cache = MCPConnectionCache()
|