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,1061 @@
|
|
|
1
|
+
# Copyright (c) Huawei Technologies Co., Ltd. 2026. All rights reserved.
|
|
2
|
+
|
|
3
|
+
"""AgentBuilder — constructs Agent + TurnBindings from an AgentProfile.
|
|
4
|
+
|
|
5
|
+
Extracts the infrastructure-wiring logic from ``AgentEngine._build_agent``
|
|
6
|
+
into a reusable function. The engine provides callbacks (for intermediate
|
|
7
|
+
text, usage, injection) that close over engine state; this module handles
|
|
8
|
+
everything else: compaction strategy, context management, tool loading,
|
|
9
|
+
sub-agent registration, skills, middleware chain, and Agent/TurnBindings creation.
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
from __future__ import annotations
|
|
13
|
+
|
|
14
|
+
import logging
|
|
15
|
+
from collections.abc import Awaitable, Callable, Mapping
|
|
16
|
+
from dataclasses import asdict, dataclass
|
|
17
|
+
from functools import partial
|
|
18
|
+
from pathlib import Path
|
|
19
|
+
from typing import TYPE_CHECKING, Any, Literal, Protocol
|
|
20
|
+
|
|
21
|
+
from chrys.foundation.config.settings import Settings
|
|
22
|
+
from chrys.foundation.events.types import (
|
|
23
|
+
AGENT_LOAD_PHASE_AGENT,
|
|
24
|
+
AGENT_LOAD_PHASE_MCP,
|
|
25
|
+
AGENT_LOAD_PHASE_MODEL,
|
|
26
|
+
AGENT_LOAD_PHASE_RUNTIME,
|
|
27
|
+
AGENT_LOAD_PHASE_SKILLS,
|
|
28
|
+
AGENT_LOAD_PHASE_SUB_AGENTS,
|
|
29
|
+
AGENT_LOAD_PHASE_TOOLS,
|
|
30
|
+
AGENT_LOAD_STATUS_DONE,
|
|
31
|
+
AGENT_LOAD_STATUS_FAILED,
|
|
32
|
+
AGENT_LOAD_STATUS_RUNNING,
|
|
33
|
+
AGENT_LOAD_STATUS_SKIPPED,
|
|
34
|
+
AgentRuntimeDetails,
|
|
35
|
+
CompactionFinished,
|
|
36
|
+
CompactionStarted,
|
|
37
|
+
InvocationContextPressure,
|
|
38
|
+
InvocationMessage,
|
|
39
|
+
InvocationRetryAttempt,
|
|
40
|
+
RuntimeHookDetails,
|
|
41
|
+
RuntimeHookSourceDetails,
|
|
42
|
+
RuntimeModelDetails,
|
|
43
|
+
Warning,
|
|
44
|
+
)
|
|
45
|
+
from chrys.foundation.i18n import DisplayBlock, msg
|
|
46
|
+
from chrys.foundation.models.session_env import SessionEnvironment
|
|
47
|
+
from chrys.foundation.platform.files import surrogate_safe_text
|
|
48
|
+
from chrys.foundation.retry import RetryAttemptInfo
|
|
49
|
+
from chrys.foundation.tool_kinds import KIND_ASK_USER, KIND_FILESYSTEM_READ, KIND_SHELL, get_tool_kind
|
|
50
|
+
from chrys.kernel import Agent, LoopRecorder
|
|
51
|
+
from chrys.orchestration.engine.run.bindings import TurnBindings
|
|
52
|
+
from chrys.orchestration.invoker.origin import InvocationPublishers
|
|
53
|
+
from chrys.orchestration.invoker.resources import Conversation, PreparedAgent, rollback_resources
|
|
54
|
+
from chrys.orchestration.invoker.runtime import (
|
|
55
|
+
ApprovalInputs,
|
|
56
|
+
AskUserInputs,
|
|
57
|
+
ContextInputs,
|
|
58
|
+
LastWordsInputs,
|
|
59
|
+
MainRecipe,
|
|
60
|
+
ReminderInputs,
|
|
61
|
+
SharedRuntime,
|
|
62
|
+
create_approval,
|
|
63
|
+
create_ask_user,
|
|
64
|
+
create_context,
|
|
65
|
+
create_runtime,
|
|
66
|
+
create_validation,
|
|
67
|
+
)
|
|
68
|
+
from chrys.orchestration.sub_agents.registration import (
|
|
69
|
+
acp_sub_agent_depth,
|
|
70
|
+
sub_agent_registration_state,
|
|
71
|
+
sub_agent_skip_reason,
|
|
72
|
+
)
|
|
73
|
+
from chrys.service.agent_middleware import (
|
|
74
|
+
IntermediateTextBuffer,
|
|
75
|
+
TodoMiddleware,
|
|
76
|
+
)
|
|
77
|
+
from chrys.service.agent_middleware.injection import InjectionMiddleware
|
|
78
|
+
from chrys.service.agent_middleware.system_reminder import SystemReminderMiddleware
|
|
79
|
+
from chrys.service.approval.policy import ApprovalMode, ApprovalPolicy
|
|
80
|
+
from chrys.service.approval.reuse_binding import ApprovalReuseBinding
|
|
81
|
+
from chrys.service.context.compaction.last_words_state import DropRoundBreakerState, LastWordsState
|
|
82
|
+
from chrys.service.context.compaction.spill import COMPACTIONS_DIR_NAME
|
|
83
|
+
from chrys.service.context.memory_loader import load_memory_content, memory_truncated_warning
|
|
84
|
+
from chrys.service.llm.clients import create_client, effective_model_base_url
|
|
85
|
+
from chrys.service.llm.route_sessions import derive_llm_route_session_id
|
|
86
|
+
from chrys.service.profiles.models.options import (
|
|
87
|
+
effective_chat_options,
|
|
88
|
+
protected_chat_option_keys_warning_structured,
|
|
89
|
+
uses_responses_compact_continuation,
|
|
90
|
+
)
|
|
91
|
+
from chrys.service.profiles.models.resolver import resolve_selection_for_agent
|
|
92
|
+
from chrys.service.profiles.models.schema import API_STYLE_CHAT_COMPLETIONS, API_STYLE_RESPONSES
|
|
93
|
+
from chrys.service.session.persistence import agent_profile_context_fingerprint, model_profile_context_fingerprint
|
|
94
|
+
from chrys.service.state.serializers import serialized_message_payload
|
|
95
|
+
from chrys.service.todos.reminder import format_todo_reminder
|
|
96
|
+
from chrys.service.tools.names import chrys_reserved_tool_names
|
|
97
|
+
|
|
98
|
+
if TYPE_CHECKING:
|
|
99
|
+
from chrys.foundation.events.bus import EventBus
|
|
100
|
+
from chrys.foundation.models.workspace import Workspace
|
|
101
|
+
from chrys.orchestration.sub_agents.tools import SubAgentTools
|
|
102
|
+
from chrys.service.approval.judge import ApprovalJudge
|
|
103
|
+
from chrys.service.approval.turn_context import TurnContextHolder
|
|
104
|
+
from chrys.service.context.compaction import CompactionInfo, CompressInfo, PreCompactInfo
|
|
105
|
+
from chrys.service.context.compaction.last_words import CompactionStatus
|
|
106
|
+
from chrys.service.context.compaction.spill import SpillQuota
|
|
107
|
+
from chrys.service.hooks.manager import HookManager
|
|
108
|
+
from chrys.service.hooks.schema import HooksFile
|
|
109
|
+
from chrys.service.mcp.adapter import MCPAdapter
|
|
110
|
+
from chrys.service.mcp.cache import MCPConnectionCache
|
|
111
|
+
from chrys.service.mutations.coordination import MutationCoordinator
|
|
112
|
+
from chrys.service.mutations.tracker import MutationTracker
|
|
113
|
+
from chrys.service.profiles.agents.registry import AgentProfileRegistry
|
|
114
|
+
from chrys.service.profiles.agents.schema import AgentProfile
|
|
115
|
+
from chrys.service.profiles.models.registry import ModelProfileRegistry
|
|
116
|
+
from chrys.service.profiles.models.schema import ModelProfile
|
|
117
|
+
from chrys.service.skills.provider import ChrysSkillsProvider
|
|
118
|
+
from chrys.service.todos.tracker import TodoTracker
|
|
119
|
+
|
|
120
|
+
logger = logging.getLogger(__name__)
|
|
121
|
+
|
|
122
|
+
_RETRY_LAST_WORDS_COMPACTION = msg(
|
|
123
|
+
"retry.last_words_compaction",
|
|
124
|
+
fallback="LAST_WORDS compaction: {reason}",
|
|
125
|
+
multiline=True,
|
|
126
|
+
)
|
|
127
|
+
_RETRY_INVALID_RESPONSE = msg(
|
|
128
|
+
"retry.invalid_response",
|
|
129
|
+
fallback="Invalid response: {reason}",
|
|
130
|
+
multiline=True,
|
|
131
|
+
)
|
|
132
|
+
_BUILDER_PROTECTED_CHAT_OPTIONS_STRIPPED = msg(
|
|
133
|
+
"builder.protected_chat_options_stripped",
|
|
134
|
+
fallback=(
|
|
135
|
+
"Protected chat option key(s) were stripped: {keys}. "
|
|
136
|
+
"These keys can no longer be configured in profile YAML because they bypass context admission. "
|
|
137
|
+
"Reusable prompts and profile-pinned continuation IDs are unavailable there; store: true only enables "
|
|
138
|
+
"automatically managed Responses continuation."
|
|
139
|
+
),
|
|
140
|
+
)
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
def _render_todo_reminder(tracker: TodoTracker | None) -> str | None:
|
|
144
|
+
"""Todo reminder provider body — reads the sync lock-free tracker snapshot."""
|
|
145
|
+
if tracker is None:
|
|
146
|
+
return None
|
|
147
|
+
return format_todo_reminder(tracker.snapshot())
|
|
148
|
+
|
|
149
|
+
|
|
150
|
+
def _runtime_api_style(provider: str, api_style: str) -> str:
|
|
151
|
+
"""Return the API style users should see for the active model transport."""
|
|
152
|
+
if provider in ("openai", "deepseek-openai"):
|
|
153
|
+
return api_style
|
|
154
|
+
if provider == "glm-openai":
|
|
155
|
+
return API_STYLE_CHAT_COMPLETIONS
|
|
156
|
+
return ""
|
|
157
|
+
|
|
158
|
+
|
|
159
|
+
def _runtime_hook_source_details(
|
|
160
|
+
scope: Literal["project", "global"],
|
|
161
|
+
file: HooksFile,
|
|
162
|
+
) -> RuntimeHookSourceDetails:
|
|
163
|
+
"""Build the non-sensitive runtime view for one hook config source."""
|
|
164
|
+
return RuntimeHookSourceDetails(
|
|
165
|
+
scope=scope,
|
|
166
|
+
source_path=surrogate_safe_text(file.source),
|
|
167
|
+
hooks=[
|
|
168
|
+
RuntimeHookDetails(
|
|
169
|
+
id=hook.id,
|
|
170
|
+
event=str(hook.event),
|
|
171
|
+
execution_mode=hook.execution.mode,
|
|
172
|
+
enabled=hook.enabled,
|
|
173
|
+
description=hook.description,
|
|
174
|
+
)
|
|
175
|
+
for hook in file.hooks
|
|
176
|
+
],
|
|
177
|
+
)
|
|
178
|
+
|
|
179
|
+
|
|
180
|
+
def _runtime_hook_sources(hook_manager: HookManager | None) -> list[RuntimeHookSourceDetails]:
|
|
181
|
+
"""Snapshot the live project/global hook manager without executable configuration."""
|
|
182
|
+
if hook_manager is None:
|
|
183
|
+
return []
|
|
184
|
+
sources: list[RuntimeHookSourceDetails] = []
|
|
185
|
+
project = hook_manager.file.project
|
|
186
|
+
if project is not None:
|
|
187
|
+
sources.append(_runtime_hook_source_details("project", project))
|
|
188
|
+
global_ = hook_manager.file.global_
|
|
189
|
+
if global_ is not None:
|
|
190
|
+
sources.append(_runtime_hook_source_details("global", global_))
|
|
191
|
+
return sources
|
|
192
|
+
|
|
193
|
+
|
|
194
|
+
class LoadProgressCallback(Protocol):
|
|
195
|
+
"""Typed callback used by the engine to surface build progress."""
|
|
196
|
+
|
|
197
|
+
def __call__(
|
|
198
|
+
self,
|
|
199
|
+
*,
|
|
200
|
+
phase: str,
|
|
201
|
+
message: str,
|
|
202
|
+
server_name: str = "",
|
|
203
|
+
current: int = 0,
|
|
204
|
+
total: int = 0,
|
|
205
|
+
failed: int = 0,
|
|
206
|
+
status: str = "",
|
|
207
|
+
subject: str = "",
|
|
208
|
+
detail: str = "",
|
|
209
|
+
) -> Awaitable[None]: ...
|
|
210
|
+
|
|
211
|
+
|
|
212
|
+
@dataclass
|
|
213
|
+
class AgentBuildResult:
|
|
214
|
+
"""Everything produced by ``build_agent``."""
|
|
215
|
+
|
|
216
|
+
prepared: PreparedAgent
|
|
217
|
+
conversation: Conversation
|
|
218
|
+
agent: Agent
|
|
219
|
+
bindings: TurnBindings
|
|
220
|
+
runtime: SessionEnvironment
|
|
221
|
+
loop_recorder: LoopRecorder
|
|
222
|
+
reminder_middleware: SystemReminderMiddleware
|
|
223
|
+
last_words: LastWordsState
|
|
224
|
+
sub_agent_tools: SubAgentTools | None
|
|
225
|
+
mcp_adapter: MCPAdapter | None
|
|
226
|
+
skills_provider: ChrysSkillsProvider | None
|
|
227
|
+
tool_names: list[str]
|
|
228
|
+
tool_kinds: dict[str, str]
|
|
229
|
+
skill_names: list[str]
|
|
230
|
+
memory_files: list[str]
|
|
231
|
+
agent_profile_fingerprint: str
|
|
232
|
+
model_profile_fingerprint: str
|
|
233
|
+
runtime_details: AgentRuntimeDetails
|
|
234
|
+
compaction_strategy: Any
|
|
235
|
+
active_profile: ModelProfile
|
|
236
|
+
|
|
237
|
+
|
|
238
|
+
async def build_agent(
|
|
239
|
+
# -- required -----------------------------------------------------
|
|
240
|
+
profile: AgentProfile,
|
|
241
|
+
settings: Settings,
|
|
242
|
+
workspace: Workspace | None,
|
|
243
|
+
session_id: str | None,
|
|
244
|
+
bus: EventBus,
|
|
245
|
+
agent_registry: AgentProfileRegistry | None,
|
|
246
|
+
injection: InjectionMiddleware,
|
|
247
|
+
intermediate_buffer: IntermediateTextBuffer,
|
|
248
|
+
on_intermediate_async: Callable[[str], Awaitable[None]],
|
|
249
|
+
on_intermediate_sync: Callable[[str], None],
|
|
250
|
+
on_usage: Callable[..., None],
|
|
251
|
+
*,
|
|
252
|
+
# -- optional -----------------------------------------------------
|
|
253
|
+
model_registry: ModelProfileRegistry | None = None,
|
|
254
|
+
on_sub_agent_usage: Callable[..., None] | None = None,
|
|
255
|
+
on_side_call_usage: Callable[[Mapping[str, Any]], None] | None = None,
|
|
256
|
+
commit_intermediate_text: Callable[[str, int], None] | None = None,
|
|
257
|
+
drain_parent_usage_publishes: Callable[[], Awaitable[None]] | None = None,
|
|
258
|
+
on_compaction: Callable[[CompactionInfo], Awaitable[None]] | None = None,
|
|
259
|
+
on_pre_compact: Callable[[PreCompactInfo], Awaitable[None]] | None = None,
|
|
260
|
+
on_compress: Callable[[CompressInfo], Awaitable[None]] | None = None,
|
|
261
|
+
on_load_progress: LoadProgressCallback | None = None,
|
|
262
|
+
mutation_tracker: MutationTracker | None = None,
|
|
263
|
+
mutation_coordinator: MutationCoordinator | None = None,
|
|
264
|
+
todo_tracker: TodoTracker | None = None,
|
|
265
|
+
file_change_provider: Callable[[], str | None] | None = None,
|
|
266
|
+
approval_mode: ApprovalMode = ApprovalMode.MANUAL,
|
|
267
|
+
approval_judge: ApprovalJudge | None = None,
|
|
268
|
+
session_dir: Path | None = None,
|
|
269
|
+
mcp_cache: MCPConnectionCache | None = None,
|
|
270
|
+
hook_manager: HookManager | None = None,
|
|
271
|
+
spill_quota: SpillQuota | None = None,
|
|
272
|
+
persist_recovery_now: Callable[[], Awaitable[bool]] | None = None,
|
|
273
|
+
turn_context: TurnContextHolder | None = None,
|
|
274
|
+
allow_user_interaction: bool = True,
|
|
275
|
+
) -> AgentBuildResult:
|
|
276
|
+
"""Build an ``Agent``, ``TurnBindings``, and all supporting infrastructure.
|
|
277
|
+
|
|
278
|
+
Parameters
|
|
279
|
+
----------
|
|
280
|
+
profile:
|
|
281
|
+
The agent profile to build from. Explicit main-agent model overrides
|
|
282
|
+
in ``settings`` win first; otherwise the profile's ``model.profile_id``
|
|
283
|
+
(if set and registered) overrides the session-active profile.
|
|
284
|
+
settings:
|
|
285
|
+
Application settings — provides the session-active model profile
|
|
286
|
+
id via ``settings.model_profile``.
|
|
287
|
+
model_registry:
|
|
288
|
+
Registry used to resolve the main agent's ``profile_id``
|
|
289
|
+
override and per-sub-agent overrides. ``None`` → everything
|
|
290
|
+
falls back to the hardcoded default profile.
|
|
291
|
+
workspace:
|
|
292
|
+
Current workspace (used for ``SessionEnvironment``).
|
|
293
|
+
session_id:
|
|
294
|
+
Current session ID (passed to ``TurnBindings``).
|
|
295
|
+
bus:
|
|
296
|
+
Event bus (passed to ``TurnBindings``).
|
|
297
|
+
agent_registry:
|
|
298
|
+
Profile registry (used for sub-agent resolution).
|
|
299
|
+
injection:
|
|
300
|
+
Pre-configured ``InjectionMiddleware`` (engine owns the callbacks).
|
|
301
|
+
intermediate_buffer:
|
|
302
|
+
Pre-configured ``IntermediateTextBuffer``.
|
|
303
|
+
on_intermediate_async:
|
|
304
|
+
Async callback for intermediate text (non-streaming path).
|
|
305
|
+
on_intermediate_sync:
|
|
306
|
+
Sync callback for intermediate text (streaming path).
|
|
307
|
+
commit_intermediate_text:
|
|
308
|
+
Accepted-only persistence callback for a pre-reserved provisional batch.
|
|
309
|
+
on_usage:
|
|
310
|
+
Callback for context usage updates.
|
|
311
|
+
on_side_call_usage:
|
|
312
|
+
Callback receiving raw provider ``usage_details`` from Phase-4
|
|
313
|
+
LAST_WORDS side calls (main agent and sub-agents) so their spend
|
|
314
|
+
joins the session totals.
|
|
315
|
+
on_compaction:
|
|
316
|
+
Callback for intra-turn tool compaction events.
|
|
317
|
+
|
|
318
|
+
Returns
|
|
319
|
+
-------
|
|
320
|
+
AgentBuildResult
|
|
321
|
+
All constructed components needed by the engine.
|
|
322
|
+
"""
|
|
323
|
+
|
|
324
|
+
prepared = PreparedAgent()
|
|
325
|
+
|
|
326
|
+
async def _acquire(conversation: Conversation) -> AgentBuildResult:
|
|
327
|
+
nonlocal turn_context
|
|
328
|
+
|
|
329
|
+
async def _progress(
|
|
330
|
+
phase: str,
|
|
331
|
+
message: str,
|
|
332
|
+
*,
|
|
333
|
+
server_name: str = "",
|
|
334
|
+
current: int = 0,
|
|
335
|
+
total: int = 0,
|
|
336
|
+
failed: int = 0,
|
|
337
|
+
status: str = "",
|
|
338
|
+
subject: str = "",
|
|
339
|
+
detail: str = "",
|
|
340
|
+
) -> None:
|
|
341
|
+
if on_load_progress is not None:
|
|
342
|
+
await on_load_progress(
|
|
343
|
+
phase=phase,
|
|
344
|
+
message=message,
|
|
345
|
+
server_name=server_name,
|
|
346
|
+
current=current,
|
|
347
|
+
total=total,
|
|
348
|
+
failed=failed,
|
|
349
|
+
status=status,
|
|
350
|
+
subject=subject,
|
|
351
|
+
detail=detail,
|
|
352
|
+
)
|
|
353
|
+
|
|
354
|
+
if profile.acp is not None:
|
|
355
|
+
raise ValueError(f"ACP profile {profile.name!r} is sub-agent-only and cannot be launched as the main agent")
|
|
356
|
+
|
|
357
|
+
transient_retries = settings.effective_max_transient_retries()
|
|
358
|
+
|
|
359
|
+
if turn_context is None:
|
|
360
|
+
from chrys.service.approval.turn_context import TurnContextHolder
|
|
361
|
+
|
|
362
|
+
turn_context = TurnContextHolder()
|
|
363
|
+
|
|
364
|
+
await _progress(AGENT_LOAD_PHASE_MODEL, "Resolving model profile", status=AGENT_LOAD_STATUS_RUNNING)
|
|
365
|
+
|
|
366
|
+
# Resolve the main agent's ModelProfile: profile override → active.
|
|
367
|
+
# Missing ids fall back silently to active (no throw).
|
|
368
|
+
model_selection = resolve_selection_for_agent(model_registry, settings, profile)
|
|
369
|
+
active_profile = model_selection.profile
|
|
370
|
+
|
|
371
|
+
# Capture the session environment for this agent build.
|
|
372
|
+
await _progress(AGENT_LOAD_PHASE_RUNTIME, "Capturing workspace context", status=AGENT_LOAD_STATUS_RUNNING)
|
|
373
|
+
runtime = SessionEnvironment.capture(workspace=workspace)
|
|
374
|
+
serialize_implicit_windows = not settings.parallel_implicit_tools
|
|
375
|
+
|
|
376
|
+
# Auto-loaded memory (files + folders configured on the profile). Read
|
|
377
|
+
# once per build; subsequent edits to source files are picked up by the
|
|
378
|
+
# next build (e.g. profile-save soft-restart). Sub-agents skip this by
|
|
379
|
+
# not passing ``memory_text`` on their own ContextManager.
|
|
380
|
+
memory_content = load_memory_content(
|
|
381
|
+
profile.memory,
|
|
382
|
+
workspace_cwd=workspace.primary_cwd if workspace else None,
|
|
383
|
+
)
|
|
384
|
+
acp_depth = acp_sub_agent_depth()
|
|
385
|
+
effective_sub_agents: list[dict[str, Any]] = []
|
|
386
|
+
for ref in profile.sub_agents.agents:
|
|
387
|
+
resolved = agent_registry.get(ref.profile) if agent_registry is not None else None
|
|
388
|
+
effective_sub_agents.append(
|
|
389
|
+
{
|
|
390
|
+
"reference": asdict(ref),
|
|
391
|
+
"resolved_profile": asdict(resolved) if resolved is not None else None,
|
|
392
|
+
"state": sub_agent_registration_state(resolved, acp_depth=acp_depth),
|
|
393
|
+
}
|
|
394
|
+
)
|
|
395
|
+
agent_profile_fingerprint = agent_profile_context_fingerprint(
|
|
396
|
+
profile,
|
|
397
|
+
memory_text=memory_content.text,
|
|
398
|
+
effective_sub_agents=effective_sub_agents,
|
|
399
|
+
allow_user_interaction=allow_user_interaction,
|
|
400
|
+
)
|
|
401
|
+
|
|
402
|
+
# Resolve session-scoped log directories from a single session_dir source.
|
|
403
|
+
# If the caller didn't pass session_dir (e.g. engine with no state_store)
|
|
404
|
+
# but a session_id exists, fall back to the active sessions directory — this
|
|
405
|
+
# preserves on-disk logging for real runs. Tests with ``tmp_path`` stores
|
|
406
|
+
# always pass session_dir, so their logs stay in the temp dir.
|
|
407
|
+
effective_session_dir = session_dir
|
|
408
|
+
if effective_session_dir is None and session_id:
|
|
409
|
+
from chrys.foundation.config.settings import resolve_sessions_dir
|
|
410
|
+
from chrys.foundation.util.session_ids import session_short_id
|
|
411
|
+
|
|
412
|
+
effective_session_dir = resolve_sessions_dir() / session_short_id(session_id)
|
|
413
|
+
approval_log_dir = effective_session_dir / "approvals" if effective_session_dir else None
|
|
414
|
+
last_words_log_dir = effective_session_dir / "compactions" / "debug" if effective_session_dir else None
|
|
415
|
+
|
|
416
|
+
# Parse chat options early — needed by context history mode, executor, and sub-agents.
|
|
417
|
+
chat_options = effective_chat_options(active_profile)
|
|
418
|
+
if protected_options_warning := protected_chat_option_keys_warning_structured(active_profile):
|
|
419
|
+
await bus.publish(
|
|
420
|
+
Warning(
|
|
421
|
+
code="protected_chat_options_stripped",
|
|
422
|
+
message=protected_options_warning.message,
|
|
423
|
+
display_message=_BUILDER_PROTECTED_CHAT_OPTIONS_STRIPPED.bind(
|
|
424
|
+
keys=", ".join(protected_options_warning.keys)
|
|
425
|
+
),
|
|
426
|
+
session_id=session_id,
|
|
427
|
+
)
|
|
428
|
+
)
|
|
429
|
+
model_profile_fingerprint = model_profile_context_fingerprint(active_profile, chat_options=chat_options)
|
|
430
|
+
uses_responses_service_history = (
|
|
431
|
+
active_profile.provider == "openai" and active_profile.api_style == API_STYLE_RESPONSES
|
|
432
|
+
)
|
|
433
|
+
capture_service_loop_messages = uses_responses_compact_continuation(active_profile, chat_options)
|
|
434
|
+
context_recall_session_id = derive_llm_route_session_id(
|
|
435
|
+
session_id,
|
|
436
|
+
route_kind="context-recall",
|
|
437
|
+
model_profile=active_profile,
|
|
438
|
+
)
|
|
439
|
+
last_words_session_id = derive_llm_route_session_id(
|
|
440
|
+
session_id,
|
|
441
|
+
route_kind="last-words",
|
|
442
|
+
route_parts=(profile.name,),
|
|
443
|
+
model_profile=active_profile,
|
|
444
|
+
)
|
|
445
|
+
|
|
446
|
+
def _publish_context_pressure(
|
|
447
|
+
reason: str,
|
|
448
|
+
breaker: DropRoundBreakerState,
|
|
449
|
+
budget: int,
|
|
450
|
+
) -> Awaitable[None]:
|
|
451
|
+
emitter = invocation_publishers.capture()
|
|
452
|
+
return emitter.publish(
|
|
453
|
+
InvocationContextPressure(
|
|
454
|
+
origin=emitter.origin,
|
|
455
|
+
reason=reason,
|
|
456
|
+
attempts=breaker.attempts,
|
|
457
|
+
side_call_tokens=breaker.side_call_tokens,
|
|
458
|
+
side_call_token_budget=budget,
|
|
459
|
+
session_id=session_id,
|
|
460
|
+
)
|
|
461
|
+
)
|
|
462
|
+
|
|
463
|
+
# Context management (providers + middleware + compaction from profile config)
|
|
464
|
+
context_inputs = ContextInputs(
|
|
465
|
+
profile=active_profile,
|
|
466
|
+
on_usage=on_usage,
|
|
467
|
+
on_compaction=on_compaction,
|
|
468
|
+
on_pre_compact=on_pre_compact,
|
|
469
|
+
on_compress=on_compress,
|
|
470
|
+
on_context_pressure=_publish_context_pressure,
|
|
471
|
+
spill_quota=spill_quota,
|
|
472
|
+
debug_log_dir=last_words_log_dir,
|
|
473
|
+
compaction_config=profile.compaction,
|
|
474
|
+
memory_text=memory_content.text,
|
|
475
|
+
warn_threshold_pct=settings.warn_threshold_pct,
|
|
476
|
+
session_id=context_recall_session_id,
|
|
477
|
+
parent_session_id=session_id,
|
|
478
|
+
session_dir=effective_session_dir,
|
|
479
|
+
skip_local_history_for_service_context=uses_responses_service_history,
|
|
480
|
+
service_context_default_options=chat_options,
|
|
481
|
+
)
|
|
482
|
+
|
|
483
|
+
ctx = create_context(context_inputs)
|
|
484
|
+
|
|
485
|
+
# Create LLM client with intermediate text callbacks. ``session_dir`` is
|
|
486
|
+
# only used by opt-in raw HTTP logging; normal transport construction stays
|
|
487
|
+
# unchanged.
|
|
488
|
+
invocation_publishers = InvocationPublishers(bus)
|
|
489
|
+
|
|
490
|
+
async def _publish_intermediate(text: str) -> None:
|
|
491
|
+
emitter = invocation_publishers.capture()
|
|
492
|
+
await on_intermediate_async(text)
|
|
493
|
+
await emitter.publish(
|
|
494
|
+
InvocationMessage(
|
|
495
|
+
origin=emitter.origin,
|
|
496
|
+
text=text,
|
|
497
|
+
is_final=False,
|
|
498
|
+
is_intermediate=True,
|
|
499
|
+
session_id=session_id,
|
|
500
|
+
)
|
|
501
|
+
)
|
|
502
|
+
|
|
503
|
+
client = await create_client(
|
|
504
|
+
active_profile,
|
|
505
|
+
on_intermediate_text_async=_publish_intermediate,
|
|
506
|
+
on_intermediate_text_sync=on_intermediate_sync,
|
|
507
|
+
session_id=session_id,
|
|
508
|
+
session_dir=effective_session_dir,
|
|
509
|
+
tool_result_ceiling_tokens=settings.tool_result_ceiling_tokens,
|
|
510
|
+
)
|
|
511
|
+
await prepared.own_or_release(client.aclose)
|
|
512
|
+
|
|
513
|
+
# Build tools from profile's builtin categories
|
|
514
|
+
from chrys.service.tools.builtins.web.build import assemble_web_tools
|
|
515
|
+
from chrys.service.tools.registry import ToolRegistry
|
|
516
|
+
|
|
517
|
+
await _progress(AGENT_LOAD_PHASE_TOOLS, "Loading built-in tools", status=AGENT_LOAD_STATUS_RUNNING)
|
|
518
|
+
tool_registry = ToolRegistry(vision_enabled=active_profile.vision)
|
|
519
|
+
builtin_categories = profile.tools.builtins or []
|
|
520
|
+
web_tools = assemble_web_tools(
|
|
521
|
+
builtin_categories,
|
|
522
|
+
settings,
|
|
523
|
+
profile.tools.web_search,
|
|
524
|
+
profile.tools.web_fetch,
|
|
525
|
+
chat_options=chat_options,
|
|
526
|
+
agent=profile.name,
|
|
527
|
+
model_profile_id=active_profile.id,
|
|
528
|
+
session_id=session_id,
|
|
529
|
+
)
|
|
530
|
+
tool_registry.load_builtins(
|
|
531
|
+
builtin_categories,
|
|
532
|
+
runtime=runtime,
|
|
533
|
+
settings=settings,
|
|
534
|
+
shell_filter_config=profile.tools.shell_filter,
|
|
535
|
+
session_id=session_id,
|
|
536
|
+
session_dir=effective_session_dir,
|
|
537
|
+
web=web_tools,
|
|
538
|
+
)
|
|
539
|
+
# Published once the web tools are decided, like the skill and memory warnings
|
|
540
|
+
# further on; a later step can still fail the whole build.
|
|
541
|
+
for warning in web_tools.warnings:
|
|
542
|
+
await bus.publish(warning)
|
|
543
|
+
from chrys.service.vision import filter_image_tools
|
|
544
|
+
|
|
545
|
+
tools = filter_image_tools(tool_registry.get_all(), vision_enabled=active_profile.vision)
|
|
546
|
+
if not allow_user_interaction:
|
|
547
|
+
tools = [tool for tool in tools if get_tool_kind(tool) != KIND_ASK_USER]
|
|
548
|
+
builtin_tools: dict[str, list[str]] = {}
|
|
549
|
+
for category in dict.fromkeys(builtin_categories):
|
|
550
|
+
names = [
|
|
551
|
+
tool.name
|
|
552
|
+
for tool in filter_image_tools(
|
|
553
|
+
tool_registry.get_by_category(category), vision_enabled=active_profile.vision
|
|
554
|
+
)
|
|
555
|
+
if allow_user_interaction or get_tool_kind(tool) != KIND_ASK_USER
|
|
556
|
+
]
|
|
557
|
+
if names:
|
|
558
|
+
builtin_tools[category] = names
|
|
559
|
+
builtin_tool_count = len(tools)
|
|
560
|
+
await _progress(
|
|
561
|
+
AGENT_LOAD_PHASE_TOOLS,
|
|
562
|
+
"Built-in tools loaded",
|
|
563
|
+
current=builtin_tool_count,
|
|
564
|
+
total=builtin_tool_count,
|
|
565
|
+
status=AGENT_LOAD_STATUS_DONE,
|
|
566
|
+
)
|
|
567
|
+
|
|
568
|
+
# Collect workspace roots for file-write auto-approval (needed by both
|
|
569
|
+
# the main agent's ApprovalMiddleware and each sub-agent's fresh one).
|
|
570
|
+
workspace_roots: list[str] = []
|
|
571
|
+
if workspace:
|
|
572
|
+
workspace_roots.append(workspace.primary_cwd)
|
|
573
|
+
workspace_roots.extend(wd.path for wd in workspace.working_dirs)
|
|
574
|
+
|
|
575
|
+
# Build sub-agent tools at the composition root. The displaced owner
|
|
576
|
+
# stays live until construction atomically installs this result.
|
|
577
|
+
sub_agent_tools: SubAgentTools | None = None
|
|
578
|
+
sub_agent_tool_names: list[str] = []
|
|
579
|
+
from chrys.service.skills.adapter import create_skills_provider
|
|
580
|
+
|
|
581
|
+
if profile.sub_agents.agents and agent_registry:
|
|
582
|
+
sub_agent_total = len(profile.sub_agents.agents)
|
|
583
|
+
await _progress(
|
|
584
|
+
AGENT_LOAD_PHASE_SUB_AGENTS,
|
|
585
|
+
"Loading sub-agent tools",
|
|
586
|
+
current=0,
|
|
587
|
+
total=sub_agent_total,
|
|
588
|
+
status=AGENT_LOAD_STATUS_RUNNING,
|
|
589
|
+
)
|
|
590
|
+
from chrys.orchestration.sub_agents.tools import SubAgentTools
|
|
591
|
+
|
|
592
|
+
sub_agent_tools = SubAgentTools(
|
|
593
|
+
max_total_concurrency=profile.sub_agents.max_total_concurrency,
|
|
594
|
+
event_bus=bus,
|
|
595
|
+
session_id=session_id,
|
|
596
|
+
session_dir=effective_session_dir,
|
|
597
|
+
on_sub_agent_usage=on_sub_agent_usage,
|
|
598
|
+
on_side_call_usage=on_side_call_usage,
|
|
599
|
+
drain_parent_usage_publishes=drain_parent_usage_publishes,
|
|
600
|
+
parent_approval=profile.approval,
|
|
601
|
+
mutation_tracker=mutation_tracker,
|
|
602
|
+
mutation_coordinator=mutation_coordinator,
|
|
603
|
+
approval_mode=approval_mode,
|
|
604
|
+
approval_judge=approval_judge,
|
|
605
|
+
workspace_roots=workspace_roots,
|
|
606
|
+
approval_log_dir=approval_log_dir,
|
|
607
|
+
mcp_cache=mcp_cache,
|
|
608
|
+
hook_manager=hook_manager,
|
|
609
|
+
workspace_cwd=runtime.cwd,
|
|
610
|
+
serialize_implicit_windows=serialize_implicit_windows,
|
|
611
|
+
spill_quota=spill_quota,
|
|
612
|
+
ask_user_timeout_seconds=settings.ask_user_timeout_seconds,
|
|
613
|
+
turn_context=turn_context,
|
|
614
|
+
max_transient_retries=transient_retries,
|
|
615
|
+
tool_result_ceiling_tokens=settings.tool_result_ceiling_tokens,
|
|
616
|
+
allow_user_interaction=allow_user_interaction,
|
|
617
|
+
# A headless run shows no card to pause on, so a failed child ends with its error.
|
|
618
|
+
human_failure_decisions=allow_user_interaction,
|
|
619
|
+
)
|
|
620
|
+
prepared.own(sub_agent_tools.cleanup)
|
|
621
|
+
for index, ref in enumerate(profile.sub_agents.agents, start=1):
|
|
622
|
+
await _progress(
|
|
623
|
+
AGENT_LOAD_PHASE_SUB_AGENTS,
|
|
624
|
+
f"Loading sub-agent {ref.profile}",
|
|
625
|
+
server_name=ref.profile,
|
|
626
|
+
current=index - 1,
|
|
627
|
+
total=sub_agent_total,
|
|
628
|
+
status=AGENT_LOAD_STATUS_RUNNING,
|
|
629
|
+
subject=ref.profile,
|
|
630
|
+
)
|
|
631
|
+
sub_profile = agent_registry.get(ref.profile)
|
|
632
|
+
if sub_profile is None:
|
|
633
|
+
logger.warning("Sub-agent profile not found: %s", ref.profile)
|
|
634
|
+
await _progress(
|
|
635
|
+
AGENT_LOAD_PHASE_SUB_AGENTS,
|
|
636
|
+
f"Skipped sub-agent {ref.profile}",
|
|
637
|
+
server_name=ref.profile,
|
|
638
|
+
current=index,
|
|
639
|
+
total=sub_agent_total,
|
|
640
|
+
status=AGENT_LOAD_STATUS_SKIPPED,
|
|
641
|
+
subject=ref.profile,
|
|
642
|
+
)
|
|
643
|
+
continue
|
|
644
|
+
registration_state = effective_sub_agents[index - 1]["state"]
|
|
645
|
+
if registration_state in {"empty_command", "depth_limit"}:
|
|
646
|
+
reason = sub_agent_skip_reason(registration_state, acp_depth=acp_depth)
|
|
647
|
+
logger.warning("Skipping sub-agent profile %s: %s", ref.profile, reason)
|
|
648
|
+
await _progress(
|
|
649
|
+
AGENT_LOAD_PHASE_SUB_AGENTS,
|
|
650
|
+
f"Skipped sub-agent {ref.profile}: {reason}",
|
|
651
|
+
server_name=ref.profile,
|
|
652
|
+
current=index,
|
|
653
|
+
total=sub_agent_total,
|
|
654
|
+
status=AGENT_LOAD_STATUS_SKIPPED,
|
|
655
|
+
subject=ref.profile,
|
|
656
|
+
detail=reason,
|
|
657
|
+
)
|
|
658
|
+
continue
|
|
659
|
+
if sub_profile.acp is not None:
|
|
660
|
+
await sub_agent_tools.register_acp(ref, sub_profile, runtime)
|
|
661
|
+
else:
|
|
662
|
+
await sub_agent_tools.register(
|
|
663
|
+
ref,
|
|
664
|
+
sub_profile,
|
|
665
|
+
runtime,
|
|
666
|
+
settings=settings,
|
|
667
|
+
fallback_profile=active_profile,
|
|
668
|
+
model_registry=model_registry,
|
|
669
|
+
)
|
|
670
|
+
await _progress(
|
|
671
|
+
AGENT_LOAD_PHASE_SUB_AGENTS,
|
|
672
|
+
f"Loaded sub-agent {ref.profile}",
|
|
673
|
+
server_name=ref.profile,
|
|
674
|
+
current=index,
|
|
675
|
+
total=sub_agent_total,
|
|
676
|
+
status=AGENT_LOAD_STATUS_DONE,
|
|
677
|
+
subject=ref.profile,
|
|
678
|
+
)
|
|
679
|
+
sub_agent_tool_instances = sub_agent_tools.get_tools()
|
|
680
|
+
sub_agent_tool_names = [tool.name for tool in sub_agent_tool_instances]
|
|
681
|
+
tools.extend(sub_agent_tool_instances)
|
|
682
|
+
|
|
683
|
+
# Build MCP tools; the new Prepared owns this acquisition.
|
|
684
|
+
mcp_adapter: MCPAdapter | None = None
|
|
685
|
+
mcp_tools_by_server: dict[str, list[str]] = {}
|
|
686
|
+
if profile.tools.mcp:
|
|
687
|
+
from chrys.service.mcp.adapter import MCPAdapter
|
|
688
|
+
from chrys.service.mcp.thinking_warning import warn_if_tool_loading_unbinds_thinking
|
|
689
|
+
|
|
690
|
+
reserved_tool_names = chrys_reserved_tool_names()
|
|
691
|
+
reserved_tool_names.update(tool.name for tool in tools)
|
|
692
|
+
# A provider-hosted web tool owns its name too, so a clashing MCP tool fails
|
|
693
|
+
# the build with the guidance to rename or exclude it.
|
|
694
|
+
reserved_tool_names.update(web_tools.hosted)
|
|
695
|
+
mcp_adapter = MCPAdapter(
|
|
696
|
+
bus=bus,
|
|
697
|
+
session_id=session_id,
|
|
698
|
+
cache=mcp_cache,
|
|
699
|
+
stdio_cwd=runtime.cwd,
|
|
700
|
+
session_dir=effective_session_dir,
|
|
701
|
+
reserved_tool_names=reserved_tool_names,
|
|
702
|
+
)
|
|
703
|
+
prepared.own(mcp_adapter.disconnect_all)
|
|
704
|
+
enabled_mcp = [config for config in profile.tools.mcp if config.enabled]
|
|
705
|
+
if enabled_mcp:
|
|
706
|
+
await _progress(
|
|
707
|
+
AGENT_LOAD_PHASE_MCP,
|
|
708
|
+
"Connecting MCP servers",
|
|
709
|
+
total=len(enabled_mcp),
|
|
710
|
+
status=AGENT_LOAD_STATUS_RUNNING,
|
|
711
|
+
)
|
|
712
|
+
|
|
713
|
+
async def _mcp_progress(config: Any, state: str, current: int, total: int, failed: int) -> None:
|
|
714
|
+
action = {
|
|
715
|
+
"starting": "Connecting",
|
|
716
|
+
"connected": "Connected",
|
|
717
|
+
"failed": "Failed",
|
|
718
|
+
}.get(state, "Loading")
|
|
719
|
+
status = {
|
|
720
|
+
"starting": AGENT_LOAD_STATUS_RUNNING,
|
|
721
|
+
"connected": AGENT_LOAD_STATUS_DONE,
|
|
722
|
+
"failed": AGENT_LOAD_STATUS_FAILED,
|
|
723
|
+
}.get(state, AGENT_LOAD_STATUS_RUNNING)
|
|
724
|
+
await _progress(
|
|
725
|
+
AGENT_LOAD_PHASE_MCP,
|
|
726
|
+
f"{action} MCP server {config.name}",
|
|
727
|
+
server_name=config.name,
|
|
728
|
+
current=current,
|
|
729
|
+
total=total,
|
|
730
|
+
failed=failed,
|
|
731
|
+
status=status,
|
|
732
|
+
subject=config.name,
|
|
733
|
+
)
|
|
734
|
+
|
|
735
|
+
mcp_tools = await mcp_adapter.connect_all(profile.tools.mcp, progress=_mcp_progress)
|
|
736
|
+
mcp_tools_by_server = mcp_adapter.tool_names_by_server
|
|
737
|
+
tools.extend(mcp_tools)
|
|
738
|
+
warn_if_tool_loading_unbinds_thinking(profile, active_profile, chat_options, mcp_tools_by_server)
|
|
739
|
+
|
|
740
|
+
# Build skills provider (if configured)
|
|
741
|
+
await _progress(AGENT_LOAD_PHASE_SKILLS, "Loading skills", status=AGENT_LOAD_STATUS_RUNNING)
|
|
742
|
+
context_providers = []
|
|
743
|
+
progressive_resume_provider = mcp_adapter.create_resume_provider() if mcp_adapter is not None else None
|
|
744
|
+
|
|
745
|
+
skills_provider, skill_warnings = await create_skills_provider(
|
|
746
|
+
profile.skills,
|
|
747
|
+
runtime=runtime,
|
|
748
|
+
session_dir=effective_session_dir,
|
|
749
|
+
project_skills_enabled=settings.project_skills_enabled,
|
|
750
|
+
)
|
|
751
|
+
if skills_provider is not None:
|
|
752
|
+
context_providers.append(skills_provider)
|
|
753
|
+
if progressive_resume_provider is not None:
|
|
754
|
+
# Run after history and skills so restored calls can be inspected
|
|
755
|
+
# and newly advertised always-load tools can detect every visible
|
|
756
|
+
# name before contributing to this invocation.
|
|
757
|
+
context_providers.append(progressive_resume_provider)
|
|
758
|
+
for warn in skill_warnings:
|
|
759
|
+
await bus.publish(Warning(code=warn.code, message=warn.message, session_id=session_id))
|
|
760
|
+
skill_names = skills_provider.skill_names() if skills_provider else []
|
|
761
|
+
skill_sources = skills_provider.skill_sources() if skills_provider else {}
|
|
762
|
+
skill_details = skills_provider.skill_details() if skills_provider else []
|
|
763
|
+
await _progress(
|
|
764
|
+
AGENT_LOAD_PHASE_SKILLS,
|
|
765
|
+
"Skills loaded",
|
|
766
|
+
current=len(skill_names),
|
|
767
|
+
total=len(skill_names),
|
|
768
|
+
status=AGENT_LOAD_STATUS_DONE,
|
|
769
|
+
)
|
|
770
|
+
|
|
771
|
+
if memory_content.truncated:
|
|
772
|
+
await bus.publish(memory_truncated_warning(memory_content, session_id=session_id))
|
|
773
|
+
|
|
774
|
+
# Capture tool/skill names
|
|
775
|
+
await _progress(AGENT_LOAD_PHASE_AGENT, "Finalizing agent", status=AGENT_LOAD_STATUS_RUNNING)
|
|
776
|
+
tool_names = [t.name for t in tools]
|
|
777
|
+
tool_kinds = {t.name: k for t in tools if (k := get_tool_kind(t))}
|
|
778
|
+
context_tool_names = ctx.context_mgmt_provider.tool_names if ctx.context_mgmt_provider is not None else []
|
|
779
|
+
skill_tool_names = skills_provider.tool_names if skills_provider is not None else []
|
|
780
|
+
mcp_failures = {name: str(err) for name, err in (mcp_adapter.failures if mcp_adapter else {}).items()}
|
|
781
|
+
runtime_details = AgentRuntimeDetails(
|
|
782
|
+
model=RuntimeModelDetails(
|
|
783
|
+
profile_id=active_profile.id,
|
|
784
|
+
name=active_profile.name,
|
|
785
|
+
provider=active_profile.provider,
|
|
786
|
+
api_style=_runtime_api_style(active_profile.provider, active_profile.api_style),
|
|
787
|
+
model_id=active_profile.model_id,
|
|
788
|
+
max_context_tokens=active_profile.max_context_tokens,
|
|
789
|
+
base_url=effective_model_base_url(active_profile),
|
|
790
|
+
stream=active_profile.stream,
|
|
791
|
+
vision=active_profile.vision,
|
|
792
|
+
selection_source=model_selection.source,
|
|
793
|
+
),
|
|
794
|
+
builtin_tools=builtin_tools,
|
|
795
|
+
web_search_providers=web_tools.provider_origins(),
|
|
796
|
+
sub_agent_tools=sub_agent_tool_names,
|
|
797
|
+
mcp_tools=mcp_tools_by_server,
|
|
798
|
+
mcp_failures=mcp_failures,
|
|
799
|
+
skill_sources=skill_sources,
|
|
800
|
+
skill_details=skill_details,
|
|
801
|
+
hook_sources=_runtime_hook_sources(hook_manager),
|
|
802
|
+
memory_sources=memory_content.loaded_files_by_source,
|
|
803
|
+
)
|
|
804
|
+
|
|
805
|
+
# Loop-message recorder for interrupt recovery — fed per run by the
|
|
806
|
+
# chrys ToolLoopLayer via client_kwargs (TurnBindings._build_run_kwargs).
|
|
807
|
+
loop_recorder = LoopRecorder(
|
|
808
|
+
capture_service_loop_messages=capture_service_loop_messages,
|
|
809
|
+
message_hasher=serialized_message_payload,
|
|
810
|
+
)
|
|
811
|
+
|
|
812
|
+
# Todo wiring gates on the profile category; the tracker's own
|
|
813
|
+
# lifecycle (create/hydrate/save) is profile-independent and engine-owned.
|
|
814
|
+
todo_enabled = "todo" in builtin_categories and todo_tracker is not None
|
|
815
|
+
|
|
816
|
+
# System reminder middleware (ChatMiddleware) — enriches the user
|
|
817
|
+
# message with <system-reminder> tags before each LLM call.
|
|
818
|
+
# Placed last so it runs closest to the LLM.
|
|
819
|
+
reminder_inputs = ReminderInputs(
|
|
820
|
+
runtime=runtime,
|
|
821
|
+
max_context_tokens=active_profile.max_context_tokens,
|
|
822
|
+
warn_threshold_pct=settings.warn_threshold_pct,
|
|
823
|
+
sub_agent_names=[t.name for t in sub_agent_tools.get_tools()] if sub_agent_tools else None,
|
|
824
|
+
shell_tool_enabled=KIND_SHELL in tool_kinds.values(),
|
|
825
|
+
tool_names=[*tool_names, *context_tool_names, *skill_tool_names],
|
|
826
|
+
session_root=effective_session_dir,
|
|
827
|
+
file_read_available=KIND_FILESYSTEM_READ in tool_kinds.values(),
|
|
828
|
+
spill_quota=spill_quota,
|
|
829
|
+
skill_catalog_provider=skills_provider.render_catalog_reminder if skills_provider else None,
|
|
830
|
+
todo_state_provider=partial(_render_todo_reminder, todo_tracker) if todo_enabled else None,
|
|
831
|
+
mcp_instructions_provider=mcp_adapter.render_instructions_reminder if mcp_adapter is not None else None,
|
|
832
|
+
file_change_provider=file_change_provider,
|
|
833
|
+
)
|
|
834
|
+
|
|
835
|
+
# Wire up Phase 4 LAST_WORDS generator for the main agent. Sub-agents
|
|
836
|
+
# do the same wiring in ``SubAgentTools.register`` using their own
|
|
837
|
+
# profile.compaction and their own SystemReminderMiddleware. The
|
|
838
|
+
# log dir is derived from ``session_dir`` (computed above), so tests
|
|
839
|
+
# using ``tmp_path`` stores keep all log output in the temp dir.
|
|
840
|
+
|
|
841
|
+
async def _publish_last_words_retry(info: RetryAttemptInfo) -> None:
|
|
842
|
+
emitter = invocation_publishers.capture()
|
|
843
|
+
await emitter.publish(
|
|
844
|
+
InvocationRetryAttempt(
|
|
845
|
+
origin=emitter.origin,
|
|
846
|
+
message=f"LAST_WORDS compaction: {info.reason}",
|
|
847
|
+
attempt=info.attempt,
|
|
848
|
+
max_attempts=info.max_attempts,
|
|
849
|
+
delay_seconds=int(info.delay_seconds),
|
|
850
|
+
scope="compaction",
|
|
851
|
+
session_id=session_id,
|
|
852
|
+
display_message=_RETRY_LAST_WORDS_COMPACTION.bind(reason=DisplayBlock(info.reason)),
|
|
853
|
+
detail=info.reason,
|
|
854
|
+
)
|
|
855
|
+
)
|
|
856
|
+
|
|
857
|
+
async def _publish_compaction_status(status: CompactionStatus) -> None:
|
|
858
|
+
if status.stage == "started":
|
|
859
|
+
await bus.publish(CompactionStarted(compaction_id=status.compaction_id, session_id=session_id))
|
|
860
|
+
return
|
|
861
|
+
if status.stage == "committed":
|
|
862
|
+
# The main agent has a dedicated post-commit signal already
|
|
863
|
+
# (``on_compaction`` → ToolCompacted); mapping this to
|
|
864
|
+
# CompactionFinished would publish a bogus second finish.
|
|
865
|
+
return
|
|
866
|
+
await bus.publish(
|
|
867
|
+
CompactionFinished(
|
|
868
|
+
compaction_id=status.compaction_id,
|
|
869
|
+
outcome=status.outcome,
|
|
870
|
+
duration_ms=status.duration_ms,
|
|
871
|
+
last_words=status.last_words,
|
|
872
|
+
format_violation=status.format_violation,
|
|
873
|
+
failure_reason=status.failure_reason,
|
|
874
|
+
session_id=session_id,
|
|
875
|
+
)
|
|
876
|
+
)
|
|
877
|
+
|
|
878
|
+
last_words_inputs = LastWordsInputs(
|
|
879
|
+
profile=active_profile,
|
|
880
|
+
template=profile.compaction.last_words_template,
|
|
881
|
+
max_output_tokens=profile.compaction.last_words_max_output_tokens,
|
|
882
|
+
log_dir=last_words_log_dir,
|
|
883
|
+
session_id=last_words_session_id,
|
|
884
|
+
parent_session_id=session_id,
|
|
885
|
+
session_dir=effective_session_dir,
|
|
886
|
+
max_transient_retries=transient_retries,
|
|
887
|
+
publish_retry=_publish_last_words_retry,
|
|
888
|
+
publish_status=_publish_compaction_status,
|
|
889
|
+
report_usage=on_side_call_usage,
|
|
890
|
+
)
|
|
891
|
+
|
|
892
|
+
# Response-validation middleware — placed innermost (closest to
|
|
893
|
+
# ``_inner_get_response``) so its retries on structurally invalid
|
|
894
|
+
# responses do not double-fire outer middleware (usage, system
|
|
895
|
+
# reminder, loop capture). On exhausted retries the response is
|
|
896
|
+
# returned with ``function_call`` contents stripped (so the tool
|
|
897
|
+
# loop exits cleanly) and structurally-empty assistant messages
|
|
898
|
+
# dropped from both ``response.messages`` and ``updates`` (so the
|
|
899
|
+
# streaming rebuild + persistence stay clean). Empty-assistant
|
|
900
|
+
# scrub also runs on the valid path to catch ``[empty, valid]``
|
|
901
|
+
# multi-message shapes that pass validation but would otherwise
|
|
902
|
+
# land a stray ``content: []`` message in ``session.json``.
|
|
903
|
+
# ``publish_retry`` surfaces client-mode validation retries on the
|
|
904
|
+
# bus; service-side failures raise to the executor's whole-run
|
|
905
|
+
# retry, which publishes its own ``RetryAttempt``.
|
|
906
|
+
async def _publish_validation_retry(info: RetryAttemptInfo) -> None:
|
|
907
|
+
emitter = invocation_publishers.capture()
|
|
908
|
+
await emitter.publish(
|
|
909
|
+
InvocationRetryAttempt(
|
|
910
|
+
scope="wire",
|
|
911
|
+
origin=emitter.origin,
|
|
912
|
+
message=f"Invalid response: {info.reason}",
|
|
913
|
+
attempt=info.attempt,
|
|
914
|
+
max_attempts=info.max_attempts,
|
|
915
|
+
delay_seconds=int(info.delay_seconds),
|
|
916
|
+
session_id=session_id,
|
|
917
|
+
display_message=_RETRY_INVALID_RESPONSE.bind(reason=DisplayBlock(info.reason)),
|
|
918
|
+
detail=info.reason,
|
|
919
|
+
)
|
|
920
|
+
)
|
|
921
|
+
|
|
922
|
+
recipe = MainRecipe(
|
|
923
|
+
context=context_inputs,
|
|
924
|
+
reminder=reminder_inputs,
|
|
925
|
+
last_words=last_words_inputs,
|
|
926
|
+
injection=InjectionMiddleware,
|
|
927
|
+
validation=lambda owner: create_validation(owner, publish_retry=_publish_validation_retry),
|
|
928
|
+
persist_recovery=persist_recovery_now,
|
|
929
|
+
)
|
|
930
|
+
web_tools.check_names(tools)
|
|
931
|
+
|
|
932
|
+
assembled = create_runtime(
|
|
933
|
+
conversation,
|
|
934
|
+
SharedRuntime(
|
|
935
|
+
client=client,
|
|
936
|
+
name="Chrys",
|
|
937
|
+
instructions=profile.instructions,
|
|
938
|
+
tools=tools,
|
|
939
|
+
providers=context_providers,
|
|
940
|
+
vision=active_profile.vision,
|
|
941
|
+
),
|
|
942
|
+
recipe,
|
|
943
|
+
context=ctx,
|
|
944
|
+
injection=injection,
|
|
945
|
+
)
|
|
946
|
+
validation_middleware = assembled.validation
|
|
947
|
+
if validation_middleware is None:
|
|
948
|
+
raise RuntimeError("The main agent assembly requires response validation middleware.")
|
|
949
|
+
agent = assembled.agent
|
|
950
|
+
reminder_middleware = assembled.reminder
|
|
951
|
+
last_words = assembled.last_words
|
|
952
|
+
await agent.__aenter__()
|
|
953
|
+
# Register agent cleanup BEFORE anything below can fail — an un-exited
|
|
954
|
+
# Agent leaks its transport/session.
|
|
955
|
+
await prepared.own_or_release(partial(agent.__aexit__, None, None, None))
|
|
956
|
+
|
|
957
|
+
# Create executor
|
|
958
|
+
session = agent.create_session()
|
|
959
|
+
approval_policy = ApprovalPolicy(profile.approval, tools=tools)
|
|
960
|
+
|
|
961
|
+
approval_middleware = await create_approval(
|
|
962
|
+
conversation,
|
|
963
|
+
ApprovalInputs(
|
|
964
|
+
reuse=ApprovalReuseBinding(runtime, tools, session_id=session_id)
|
|
965
|
+
if session_id or runtime.session_id
|
|
966
|
+
else None,
|
|
967
|
+
approval_policy=approval_policy,
|
|
968
|
+
event_bus=bus,
|
|
969
|
+
session_id=session_id,
|
|
970
|
+
tool_kinds=tool_kinds,
|
|
971
|
+
caller_name=profile.display_name or profile.name,
|
|
972
|
+
workspace_roots=workspace_roots,
|
|
973
|
+
approval_mode=approval_mode,
|
|
974
|
+
approval_judge=approval_judge,
|
|
975
|
+
approval_log_dir=approval_log_dir,
|
|
976
|
+
workspace_cwd=runtime.cwd,
|
|
977
|
+
dev_mode=settings.dev_mode,
|
|
978
|
+
hook_manager=hook_manager,
|
|
979
|
+
profile_name=profile.name,
|
|
980
|
+
session_archive_read_roots=(
|
|
981
|
+
[effective_session_dir / COMPACTIONS_DIR_NAME] if effective_session_dir else None
|
|
982
|
+
),
|
|
983
|
+
turn_context=turn_context,
|
|
984
|
+
),
|
|
985
|
+
)
|
|
986
|
+
ask_user_middleware = create_ask_user(
|
|
987
|
+
conversation,
|
|
988
|
+
AskUserInputs(
|
|
989
|
+
event_bus=bus,
|
|
990
|
+
session_id=session_id,
|
|
991
|
+
caller_name=profile.display_name or profile.name,
|
|
992
|
+
timeout_seconds=settings.ask_user_timeout_seconds,
|
|
993
|
+
),
|
|
994
|
+
)
|
|
995
|
+
extra_function_middleware: list[Any] = []
|
|
996
|
+
if todo_enabled and todo_tracker is not None:
|
|
997
|
+
extra_function_middleware.append(TodoMiddleware(bus, todo_tracker, session_id))
|
|
998
|
+
executor = TurnBindings(
|
|
999
|
+
conversation=conversation,
|
|
1000
|
+
agent=agent,
|
|
1001
|
+
session=session,
|
|
1002
|
+
event_bus=bus,
|
|
1003
|
+
approval_middleware=approval_middleware,
|
|
1004
|
+
ask_user_middleware=ask_user_middleware,
|
|
1005
|
+
injection_middleware=injection,
|
|
1006
|
+
loop_recorder=loop_recorder,
|
|
1007
|
+
session_id=session_id,
|
|
1008
|
+
compaction_strategy=ctx.compaction_strategy,
|
|
1009
|
+
stream=active_profile.stream,
|
|
1010
|
+
intermediate_buffer=intermediate_buffer,
|
|
1011
|
+
chat_options=chat_options,
|
|
1012
|
+
mutation_tracker=mutation_tracker,
|
|
1013
|
+
mutation_coordinator=mutation_coordinator,
|
|
1014
|
+
stream_attempt_timeout=active_profile.http_read_timeout,
|
|
1015
|
+
max_transient_retries=transient_retries,
|
|
1016
|
+
hook_manager=hook_manager,
|
|
1017
|
+
profile_name=profile.name,
|
|
1018
|
+
workspace_cwd=runtime.cwd,
|
|
1019
|
+
serialize_implicit_windows=serialize_implicit_windows,
|
|
1020
|
+
extra_function_middleware=extra_function_middleware,
|
|
1021
|
+
run_cycle_start_hooks=(
|
|
1022
|
+
web_tools.begin_pass,
|
|
1023
|
+
validation_middleware.reset_service_retry_state,
|
|
1024
|
+
),
|
|
1025
|
+
hosted_commits_probe=validation_middleware.hosted_commits_observed,
|
|
1026
|
+
hosted_commits_in_flight_probe=validation_middleware.hosted_commits_in_flight,
|
|
1027
|
+
response_validation_middleware=validation_middleware,
|
|
1028
|
+
publish_intermediate_text=_publish_intermediate,
|
|
1029
|
+
invocation_publishers=invocation_publishers,
|
|
1030
|
+
commit_intermediate_text=commit_intermediate_text,
|
|
1031
|
+
tool_result_ceiling_tokens=settings.tool_result_ceiling_tokens,
|
|
1032
|
+
)
|
|
1033
|
+
|
|
1034
|
+
return AgentBuildResult(
|
|
1035
|
+
prepared=prepared,
|
|
1036
|
+
conversation=conversation,
|
|
1037
|
+
agent=agent,
|
|
1038
|
+
bindings=executor,
|
|
1039
|
+
runtime=runtime,
|
|
1040
|
+
loop_recorder=loop_recorder,
|
|
1041
|
+
reminder_middleware=reminder_middleware,
|
|
1042
|
+
last_words=last_words,
|
|
1043
|
+
sub_agent_tools=sub_agent_tools,
|
|
1044
|
+
mcp_adapter=mcp_adapter,
|
|
1045
|
+
skills_provider=skills_provider,
|
|
1046
|
+
tool_names=tool_names,
|
|
1047
|
+
tool_kinds=tool_kinds,
|
|
1048
|
+
skill_names=skill_names,
|
|
1049
|
+
memory_files=memory_content.loaded_files,
|
|
1050
|
+
agent_profile_fingerprint=agent_profile_fingerprint,
|
|
1051
|
+
model_profile_fingerprint=model_profile_fingerprint,
|
|
1052
|
+
runtime_details=runtime_details,
|
|
1053
|
+
compaction_strategy=ctx.compaction_strategy,
|
|
1054
|
+
active_profile=active_profile,
|
|
1055
|
+
)
|
|
1056
|
+
|
|
1057
|
+
try:
|
|
1058
|
+
return await prepared.open(_acquire)
|
|
1059
|
+
except BaseException:
|
|
1060
|
+
await rollback_resources(prepared)
|
|
1061
|
+
raise
|