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,631 @@
|
|
|
1
|
+
# Copyright (c) Huawei Technologies Co., Ltd. 2026. All rights reserved.
|
|
2
|
+
|
|
3
|
+
"""Interrupt-recovery journal for the model/tool loop.
|
|
4
|
+
|
|
5
|
+
``LoopRecorder`` keeps what a run has done so far, so an interrupted turn can
|
|
6
|
+
be saved and resumed: the pre-call message snapshots, the service-side loop
|
|
7
|
+
messages, and an ordinal-slot journal of every landed call batch. Tool
|
|
8
|
+
execution fills a slot only through the ``_ResultCommit`` handle the loop
|
|
9
|
+
stages for it.
|
|
10
|
+
|
|
11
|
+
``_message_snapshot`` is the loop's wrapper-copy primitive for landed
|
|
12
|
+
messages: it copies the Message wrapper and shares its Content objects.
|
|
13
|
+
"""
|
|
14
|
+
|
|
15
|
+
from __future__ import annotations
|
|
16
|
+
|
|
17
|
+
import asyncio
|
|
18
|
+
import hashlib
|
|
19
|
+
import logging
|
|
20
|
+
from collections.abc import Mapping, Sequence
|
|
21
|
+
from copy import copy
|
|
22
|
+
from dataclasses import dataclass
|
|
23
|
+
from typing import TYPE_CHECKING, Any
|
|
24
|
+
|
|
25
|
+
from chrys.foundation.recovery import RecoveryPersistOutcome
|
|
26
|
+
from chrys.foundation.tool_invocation_order import read_tool_invocation_order
|
|
27
|
+
from chrys.foundation.tool_result_metadata import (
|
|
28
|
+
TOOL_FAILED_METADATA_KEY,
|
|
29
|
+
TOOL_INTERRUPTED_METADATA_KEY,
|
|
30
|
+
TOOL_POST_PROCESSING_INTERRUPTED_METADATA_KEY,
|
|
31
|
+
TOOL_RESULT_METADATA_KEY,
|
|
32
|
+
)
|
|
33
|
+
from chrys.foundation.trajectory.metadata import ANALYTICS_ITEM_ID_KEY
|
|
34
|
+
from chrys.foundation.trajectory_timing import TRAJECTORY_TIMING_KEY
|
|
35
|
+
|
|
36
|
+
from ._content import Content
|
|
37
|
+
from ._tool_execution import _is_actionable_function_call, _result_additional_properties, _tool_trajectory_timing
|
|
38
|
+
from ._types import ChatResponse, Message
|
|
39
|
+
|
|
40
|
+
if TYPE_CHECKING:
|
|
41
|
+
from collections.abc import Awaitable, Callable, Coroutine
|
|
42
|
+
|
|
43
|
+
from .middleware import FunctionInvocationContext
|
|
44
|
+
|
|
45
|
+
# Log lines keep the loop's logger name: log configuration and tests filter on it.
|
|
46
|
+
logger = logging.getLogger("chrys.kernel.loop")
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def _contains_identity(messages: list[Message], target: Message) -> bool:
|
|
50
|
+
return any(message is target for message in messages)
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
def _has_function_call(message: Message) -> bool:
|
|
54
|
+
return any(_is_actionable_function_call(content) for content in message.contents)
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
def _message_snapshot(message: Message, contents: list[Content]) -> Message:
|
|
58
|
+
"""Loop-owned shallow copy of a message wrapper holding *contents*.
|
|
59
|
+
|
|
60
|
+
The wrapper and its two containers (``contents`` list,
|
|
61
|
+
``additional_properties`` dict) are copied; the Content objects are NOT —
|
|
62
|
+
their identity is the echo memo's currency and must stay shared. Landing
|
|
63
|
+
retains these snapshots instead of client-minted wrappers
|
|
64
|
+
(``_land_response_contents``); the request direction of wrapper aliasing
|
|
65
|
+
is covered by ``_wire_message_view``.
|
|
66
|
+
"""
|
|
67
|
+
snapshot = copy(message)
|
|
68
|
+
snapshot.contents = contents
|
|
69
|
+
snapshot.additional_properties = dict(message.additional_properties)
|
|
70
|
+
# Echo-strip provenance is assembly-local. A mixed echo+fresh message is
|
|
71
|
+
# retained, but its snapshot must not carry the marker into later calls.
|
|
72
|
+
snapshot._chrys_echo_content_stripped = False
|
|
73
|
+
return snapshot
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
@dataclass(slots=True)
|
|
77
|
+
class _PendingExchangeSlot:
|
|
78
|
+
ordinal: int
|
|
79
|
+
function_call: Content
|
|
80
|
+
call_id: str | None
|
|
81
|
+
result: Content | None = None
|
|
82
|
+
fill_kind: str = ""
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
@dataclass(slots=True)
|
|
86
|
+
class _PendingExchange:
|
|
87
|
+
response_messages: tuple[Message, ...]
|
|
88
|
+
slots: tuple[_PendingExchangeSlot, ...]
|
|
89
|
+
result_carrier_item_id: str
|
|
90
|
+
projection_messages: tuple[Message, ...] | None = None
|
|
91
|
+
|
|
92
|
+
@property
|
|
93
|
+
def answered_count(self) -> int:
|
|
94
|
+
return sum(slot.result is not None for slot in self.slots)
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
@dataclass(frozen=True, slots=True)
|
|
98
|
+
class _SealedExchange:
|
|
99
|
+
messages: tuple[Message, ...]
|
|
100
|
+
answered_count: int
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
class _ResultCommit:
|
|
104
|
+
"""Synchronous, invocation-bound writer for one pending exchange slot."""
|
|
105
|
+
|
|
106
|
+
def __init__(self, recorder: LoopRecorder, exchange: _PendingExchange, slot: _PendingExchangeSlot) -> None:
|
|
107
|
+
self._recorder = recorder
|
|
108
|
+
self._exchange = exchange
|
|
109
|
+
self._slot = slot
|
|
110
|
+
|
|
111
|
+
@property
|
|
112
|
+
def has_raw_result(self) -> bool:
|
|
113
|
+
return self._slot.fill_kind == "raw"
|
|
114
|
+
|
|
115
|
+
def commit_raw(self, result: Content) -> None:
|
|
116
|
+
self._recorder._fill_slot(self._exchange, self._slot, result, fill_kind="raw")
|
|
117
|
+
|
|
118
|
+
def commit_final(self, result: Content) -> None:
|
|
119
|
+
self._recorder._fill_slot(self._exchange, self._slot, result, fill_kind="final", upgrade_raw=True)
|
|
120
|
+
|
|
121
|
+
def commit_interrupted(
|
|
122
|
+
self,
|
|
123
|
+
function_call: Content,
|
|
124
|
+
invocation_context: FunctionInvocationContext | None,
|
|
125
|
+
metadata: Mapping[str, Any] | None = None,
|
|
126
|
+
) -> None:
|
|
127
|
+
self._recorder._interrupt_slot(
|
|
128
|
+
self._exchange,
|
|
129
|
+
self._slot,
|
|
130
|
+
function_call,
|
|
131
|
+
invocation_context,
|
|
132
|
+
metadata,
|
|
133
|
+
)
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
@dataclass(frozen=True, slots=True)
|
|
137
|
+
class LoopRecorderSnapshot:
|
|
138
|
+
"""Retry snapshot of non-journal :class:`LoopRecorder` capture state."""
|
|
139
|
+
|
|
140
|
+
initial_count: int | None
|
|
141
|
+
captured: tuple[Message, ...] | None
|
|
142
|
+
service_loop_messages: tuple[Message, ...]
|
|
143
|
+
last_checkpoint_key: tuple[int, str] | None
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
class LoopRecorder:
|
|
147
|
+
"""Records tool-loop messages for interrupt recovery.
|
|
148
|
+
|
|
149
|
+
Successor to the chat-middleware-based loop-capture middleware: the loop
|
|
150
|
+
feeds it directly (:meth:`record_pre_call` before each wire call,
|
|
151
|
+
:meth:`record_response` after each parsed response) instead of observing
|
|
152
|
+
the per-call middleware pipeline. The consumer surface
|
|
153
|
+
(:attr:`loop_messages`, :meth:`reset`, :attr:`on_checkpoint`) and the
|
|
154
|
+
capture semantics are unchanged.
|
|
155
|
+
|
|
156
|
+
On early termination (e.g. hard-cancel ``CancelledError``) only the last
|
|
157
|
+
iteration's messages appear in the run result — previous iterations live
|
|
158
|
+
only in the loop's growing ``prepped_messages`` list. The pre-call
|
|
159
|
+
snapshot preserves them so the engine can merge completed iterations into
|
|
160
|
+
session state.
|
|
161
|
+
|
|
162
|
+
``message_hasher`` turns the newest captured message into a stable payload
|
|
163
|
+
string for checkpoint suppression (chrys injects a ``serialize_message``
|
|
164
|
+
JSON wrapper; the kernel cannot import chrys). Defaults to ``repr``.
|
|
165
|
+
|
|
166
|
+
**Reset contract**: :meth:`reset` must be called before each fresh run.
|
|
167
|
+
|
|
168
|
+
**Delivery**: per-run via ``client_kwargs["loop_recorder"]`` — parallel
|
|
169
|
+
sub-agent invocations share one client stack, so the recorder must never
|
|
170
|
+
be attached to the layer itself.
|
|
171
|
+
"""
|
|
172
|
+
|
|
173
|
+
def __init__(
|
|
174
|
+
self,
|
|
175
|
+
*,
|
|
176
|
+
capture_service_loop_messages: bool = False,
|
|
177
|
+
on_checkpoint: Callable[[], Coroutine[Any, Any, None]] | None = None,
|
|
178
|
+
on_pre_wire_barrier: Callable[[], Awaitable[RecoveryPersistOutcome]] | None = None,
|
|
179
|
+
on_result_checkpoint: Callable[[], Coroutine[Any, Any, None]] | None = None,
|
|
180
|
+
message_hasher: Callable[[Message], str] | None = None,
|
|
181
|
+
) -> None:
|
|
182
|
+
self._capture_service_loop_messages = capture_service_loop_messages
|
|
183
|
+
self._on_result_checkpoint = on_result_checkpoint if on_result_checkpoint is not None else on_checkpoint
|
|
184
|
+
self._on_pre_wire_barrier = on_pre_wire_barrier
|
|
185
|
+
self._message_hasher: Callable[[Message], str] = message_hasher if message_hasher is not None else repr
|
|
186
|
+
self._initial_count: int | None = None
|
|
187
|
+
self._captured: list[Message] | None = None
|
|
188
|
+
self._service_loop_messages: list[Message] = []
|
|
189
|
+
self._last_checkpoint_key: tuple[int, str] | None = None
|
|
190
|
+
self._sealed_exchanges: list[_SealedExchange] = []
|
|
191
|
+
self._pending_exchange: _PendingExchange | None = None
|
|
192
|
+
self._landed_response: tuple[Message, ...] | None = None
|
|
193
|
+
self._committed_count = 0
|
|
194
|
+
self._barrier_degraded = False
|
|
195
|
+
self._barrier_unconfigured = False
|
|
196
|
+
self._barrier_warned = False
|
|
197
|
+
|
|
198
|
+
def reset(self) -> None:
|
|
199
|
+
"""Clear captured state for a new run."""
|
|
200
|
+
self._initial_count = None
|
|
201
|
+
self._captured = None
|
|
202
|
+
self._service_loop_messages = []
|
|
203
|
+
self._last_checkpoint_key = None
|
|
204
|
+
self._sealed_exchanges = []
|
|
205
|
+
self._pending_exchange = None
|
|
206
|
+
self._landed_response = None
|
|
207
|
+
self._committed_count = 0
|
|
208
|
+
self._barrier_degraded = False
|
|
209
|
+
self._barrier_warned = False
|
|
210
|
+
|
|
211
|
+
def snapshot(self) -> LoopRecorderSnapshot:
|
|
212
|
+
"""Capture recorder state for an outer provider retry."""
|
|
213
|
+
return LoopRecorderSnapshot(
|
|
214
|
+
initial_count=self._initial_count,
|
|
215
|
+
captured=None if self._captured is None else tuple(self._captured),
|
|
216
|
+
service_loop_messages=tuple(self._service_loop_messages),
|
|
217
|
+
last_checkpoint_key=self._last_checkpoint_key,
|
|
218
|
+
)
|
|
219
|
+
|
|
220
|
+
def restore(self, snapshot: LoopRecorderSnapshot) -> None:
|
|
221
|
+
"""Restore capture state while preserving every answered journal slot."""
|
|
222
|
+
self._initial_count = snapshot.initial_count
|
|
223
|
+
self._captured = None if snapshot.captured is None else list(snapshot.captured)
|
|
224
|
+
self._service_loop_messages = list(snapshot.service_loop_messages)
|
|
225
|
+
self._last_checkpoint_key = snapshot.last_checkpoint_key
|
|
226
|
+
# The retried attempt sends its request again.
|
|
227
|
+
self._landed_response = None
|
|
228
|
+
pending = self._pending_exchange
|
|
229
|
+
if pending is not None and not any(slot.fill_kind in ("raw", "final") for slot in pending.slots):
|
|
230
|
+
self._pending_exchange = None
|
|
231
|
+
|
|
232
|
+
@property
|
|
233
|
+
def on_checkpoint(self) -> Callable[[], Coroutine[Any, Any, None]] | None:
|
|
234
|
+
"""Compatibility alias for the best-effort checkpoint callback."""
|
|
235
|
+
return self._on_result_checkpoint
|
|
236
|
+
|
|
237
|
+
@on_checkpoint.setter
|
|
238
|
+
def on_checkpoint(self, callback: Callable[[], Coroutine[Any, Any, None]] | None) -> None:
|
|
239
|
+
self._on_result_checkpoint = callback
|
|
240
|
+
|
|
241
|
+
@property
|
|
242
|
+
def on_pre_wire_barrier(self) -> Callable[[], Awaitable[RecoveryPersistOutcome]] | None:
|
|
243
|
+
"""Strict recovery barrier invoked before a post-commit provider call."""
|
|
244
|
+
return self._on_pre_wire_barrier
|
|
245
|
+
|
|
246
|
+
@on_pre_wire_barrier.setter
|
|
247
|
+
def on_pre_wire_barrier(
|
|
248
|
+
self,
|
|
249
|
+
callback: Callable[[], Awaitable[RecoveryPersistOutcome]] | None,
|
|
250
|
+
) -> None:
|
|
251
|
+
self._on_pre_wire_barrier = callback
|
|
252
|
+
self._barrier_unconfigured = False
|
|
253
|
+
|
|
254
|
+
@property
|
|
255
|
+
def on_result_checkpoint(self) -> Callable[[], Coroutine[Any, Any, None]] | None:
|
|
256
|
+
"""Best-effort checkpoint callback kicked after slot fills and snapshots."""
|
|
257
|
+
return self._on_result_checkpoint
|
|
258
|
+
|
|
259
|
+
@on_result_checkpoint.setter
|
|
260
|
+
def on_result_checkpoint(self, callback: Callable[[], Coroutine[Any, Any, None]] | None) -> None:
|
|
261
|
+
self._on_result_checkpoint = callback
|
|
262
|
+
|
|
263
|
+
@property
|
|
264
|
+
def committed_count(self) -> int:
|
|
265
|
+
"""Number of answered ordinal slots in the current outer pass."""
|
|
266
|
+
return self._committed_count
|
|
267
|
+
|
|
268
|
+
@property
|
|
269
|
+
def initial_count(self) -> int | None:
|
|
270
|
+
"""Message count of the first wire call, or ``None`` before any call."""
|
|
271
|
+
return self._initial_count
|
|
272
|
+
|
|
273
|
+
@property
|
|
274
|
+
def captured_count(self) -> int | None:
|
|
275
|
+
"""Size of the newest pre-call snapshot, or ``None`` before any call."""
|
|
276
|
+
return None if self._captured is None else len(self._captured)
|
|
277
|
+
|
|
278
|
+
@property
|
|
279
|
+
def landed_response(self) -> tuple[Message, ...] | None:
|
|
280
|
+
"""The newest request's response messages as the loop landed them; ``None`` while it is in flight.
|
|
281
|
+
|
|
282
|
+
Their Content objects are the ones history keeps, so they tell that request's own exchange apart
|
|
283
|
+
from earlier ones reusing its call ids.
|
|
284
|
+
"""
|
|
285
|
+
return self._landed_response
|
|
286
|
+
|
|
287
|
+
@property
|
|
288
|
+
def loop_messages(self) -> list[Message] | None:
|
|
289
|
+
"""Messages from completed tool loop iterations, or ``None``.
|
|
290
|
+
|
|
291
|
+
Returns the assistant + tool messages that the tool loop accumulated
|
|
292
|
+
from **previous** iterations. Returns ``None`` if no multi-iteration
|
|
293
|
+
loop occurred (single iteration or no tool calls).
|
|
294
|
+
"""
|
|
295
|
+
captured_delta: list[Message] = []
|
|
296
|
+
if self._captured is not None and self._initial_count is not None and len(self._captured) > self._initial_count:
|
|
297
|
+
captured_delta = self._captured[self._initial_count :]
|
|
298
|
+
|
|
299
|
+
base_messages = self._service_loop_messages or captured_delta
|
|
300
|
+
journal: list[tuple[set[int], tuple[Message, ...]]] = [
|
|
301
|
+
(
|
|
302
|
+
{id(content) for message in exchange.messages for content in message.contents},
|
|
303
|
+
exchange.messages,
|
|
304
|
+
)
|
|
305
|
+
for exchange in self._sealed_exchanges
|
|
306
|
+
]
|
|
307
|
+
if self._pending_exchange is not None and self._pending_exchange.answered_count:
|
|
308
|
+
pending_projection = tuple(self._project_pending_exchange(self._pending_exchange))
|
|
309
|
+
pending_owned = {
|
|
310
|
+
id(content) for message in self._pending_exchange.response_messages for content in message.contents
|
|
311
|
+
}
|
|
312
|
+
pending_owned.update(id(slot.result) for slot in self._pending_exchange.slots if slot.result is not None)
|
|
313
|
+
journal.append((pending_owned, pending_projection))
|
|
314
|
+
|
|
315
|
+
candidates: list[Message] = []
|
|
316
|
+
inserted: set[int] = set()
|
|
317
|
+
all_owned = set().union(*(owned for owned, _projection in journal)) if journal else set()
|
|
318
|
+
for message in base_messages:
|
|
319
|
+
message_ids = {id(content) for content in message.contents}
|
|
320
|
+
for index, (owned, projection) in enumerate(journal):
|
|
321
|
+
if index not in inserted and message_ids.intersection(owned):
|
|
322
|
+
candidates.extend(projection)
|
|
323
|
+
inserted.add(index)
|
|
324
|
+
remaining = [content for content in message.contents if id(content) not in all_owned]
|
|
325
|
+
if remaining:
|
|
326
|
+
candidates.append(
|
|
327
|
+
message if len(remaining) == len(message.contents) else _message_snapshot(message, remaining)
|
|
328
|
+
)
|
|
329
|
+
for index, (_owned, projection) in enumerate(journal):
|
|
330
|
+
if index not in inserted:
|
|
331
|
+
candidates.extend(projection)
|
|
332
|
+
deduped = self._dedupe_projected_messages(candidates)
|
|
333
|
+
return deduped or None
|
|
334
|
+
|
|
335
|
+
async def record_pre_call(self, messages: list[Message]) -> None:
|
|
336
|
+
"""Snapshot the prepped message list before a wire call."""
|
|
337
|
+
self._landed_response = None
|
|
338
|
+
if self._initial_count is None:
|
|
339
|
+
self._initial_count = len(messages)
|
|
340
|
+
prev_len = len(self._captured) if self._captured else 0
|
|
341
|
+
# Copy to avoid aliasing mutations of the loop's growing list.
|
|
342
|
+
self._captured = list(messages)
|
|
343
|
+
# Responses store=true service-side continuations replace the growing
|
|
344
|
+
# local prepped list with compact assistant/tool payloads. Preserve
|
|
345
|
+
# those too so pause-time recovery can replay locally after dropping
|
|
346
|
+
# the service id. The mode is configured by chrys from the model
|
|
347
|
+
# profile/options; ``ChatResponse.conversation_id`` alone is provider
|
|
348
|
+
# metadata and is not a reliable discriminator.
|
|
349
|
+
if self._capture_service_loop_messages and self._service_loop_messages:
|
|
350
|
+
for msg in messages:
|
|
351
|
+
if not _contains_identity(self._service_loop_messages, msg) and msg.role in ("assistant", "tool"):
|
|
352
|
+
self._service_loop_messages.append(msg)
|
|
353
|
+
logger.debug(
|
|
354
|
+
"LoopRecorder: initial=%d prev=%d now=%d delta=%d",
|
|
355
|
+
self._initial_count,
|
|
356
|
+
prev_len,
|
|
357
|
+
len(self._captured),
|
|
358
|
+
len(self._captured) - self._initial_count,
|
|
359
|
+
)
|
|
360
|
+
barrier_persisted = await self._run_pre_wire_barrier()
|
|
361
|
+
if self._on_result_checkpoint is None:
|
|
362
|
+
return
|
|
363
|
+
# A persisted barrier already made this pre-call state durable; the
|
|
364
|
+
# best-effort checkpoint would only build and write it again. Suppression
|
|
365
|
+
# still runs first: it records this prefix as checkpointed, so a retry of
|
|
366
|
+
# the same request stays suppressed after a later barrier failure.
|
|
367
|
+
if self._should_suppress_checkpoint() or barrier_persisted:
|
|
368
|
+
return
|
|
369
|
+
await self._on_result_checkpoint()
|
|
370
|
+
|
|
371
|
+
def record_response(self, response: ChatResponse) -> None:
|
|
372
|
+
"""Record assistant function-call messages from a parsed response.
|
|
373
|
+
|
|
374
|
+
The loop owns the parsed ``ChatResponse`` for both stream modes, so the
|
|
375
|
+
stream ``result_hook`` side channel of the middleware era is gone.
|
|
376
|
+
"""
|
|
377
|
+
self._landed_response = tuple(response.messages)
|
|
378
|
+
if not self._capture_service_loop_messages:
|
|
379
|
+
return
|
|
380
|
+
for msg in response.messages:
|
|
381
|
+
if not _contains_identity(self._service_loop_messages, msg) and _has_function_call(msg):
|
|
382
|
+
self._service_loop_messages.append(msg)
|
|
383
|
+
|
|
384
|
+
def stage_exchange(
|
|
385
|
+
self,
|
|
386
|
+
response_messages: Sequence[Message],
|
|
387
|
+
function_calls: Sequence[Content],
|
|
388
|
+
*,
|
|
389
|
+
result_carrier_item_id: str,
|
|
390
|
+
) -> tuple[_ResultCommit, ...]:
|
|
391
|
+
"""Reserve ordinal slots for one landed call batch."""
|
|
392
|
+
slots: list[_PendingExchangeSlot] = []
|
|
393
|
+
for function_call in function_calls:
|
|
394
|
+
ordinal = read_tool_invocation_order(function_call.additional_properties)
|
|
395
|
+
if ordinal is None:
|
|
396
|
+
raise ValueError("Landed function call is missing its invocation ordinal.")
|
|
397
|
+
slots.append(
|
|
398
|
+
_PendingExchangeSlot(
|
|
399
|
+
ordinal=ordinal,
|
|
400
|
+
function_call=function_call,
|
|
401
|
+
call_id=function_call.call_id,
|
|
402
|
+
)
|
|
403
|
+
)
|
|
404
|
+
exchange = _PendingExchange(
|
|
405
|
+
response_messages=tuple(response_messages),
|
|
406
|
+
slots=tuple(slots),
|
|
407
|
+
result_carrier_item_id=result_carrier_item_id,
|
|
408
|
+
)
|
|
409
|
+
self._pending_exchange = exchange
|
|
410
|
+
return tuple(_ResultCommit(self, exchange, slot) for slot in exchange.slots)
|
|
411
|
+
|
|
412
|
+
def seal_exchange(self, result_message: Message) -> None:
|
|
413
|
+
"""Replace provisional results with their canonical carrier message."""
|
|
414
|
+
exchange = self._pending_exchange
|
|
415
|
+
if exchange is None:
|
|
416
|
+
return
|
|
417
|
+
result_identities = {id(content) for content in result_message.contents}
|
|
418
|
+
if any(slot.result is not None and id(slot.result) not in result_identities for slot in exchange.slots):
|
|
419
|
+
return
|
|
420
|
+
self._sealed_exchanges.append(
|
|
421
|
+
_SealedExchange(
|
|
422
|
+
messages=(*exchange.response_messages, result_message),
|
|
423
|
+
answered_count=exchange.answered_count,
|
|
424
|
+
)
|
|
425
|
+
)
|
|
426
|
+
self._pending_exchange = None
|
|
427
|
+
|
|
428
|
+
def _fill_slot(
|
|
429
|
+
self,
|
|
430
|
+
exchange: _PendingExchange,
|
|
431
|
+
slot: _PendingExchangeSlot,
|
|
432
|
+
result: Content,
|
|
433
|
+
*,
|
|
434
|
+
fill_kind: str,
|
|
435
|
+
upgrade_raw: bool = False,
|
|
436
|
+
) -> None:
|
|
437
|
+
if exchange is not self._pending_exchange:
|
|
438
|
+
return
|
|
439
|
+
if slot.result is None:
|
|
440
|
+
slot.result = result
|
|
441
|
+
slot.fill_kind = fill_kind
|
|
442
|
+
exchange.projection_messages = None
|
|
443
|
+
# Interrupted fills mark cancellation before the side-effect
|
|
444
|
+
# boundary was observed: they persist through finalization but are
|
|
445
|
+
# not commits, so a zero-commit retry whose own stream teardown
|
|
446
|
+
# cancelled in-flight tools may still re-dispatch them.
|
|
447
|
+
if fill_kind != "interrupted":
|
|
448
|
+
self._committed_count += 1
|
|
449
|
+
self._kick_result_checkpoint()
|
|
450
|
+
return
|
|
451
|
+
if upgrade_raw and slot.fill_kind == "raw":
|
|
452
|
+
slot.result = result
|
|
453
|
+
slot.fill_kind = fill_kind
|
|
454
|
+
exchange.projection_messages = None
|
|
455
|
+
self._kick_result_checkpoint()
|
|
456
|
+
|
|
457
|
+
def _interrupt_slot(
|
|
458
|
+
self,
|
|
459
|
+
exchange: _PendingExchange,
|
|
460
|
+
slot: _PendingExchangeSlot,
|
|
461
|
+
function_call: Content,
|
|
462
|
+
invocation_context: FunctionInvocationContext | None,
|
|
463
|
+
metadata: Mapping[str, Any] | None,
|
|
464
|
+
) -> None:
|
|
465
|
+
result_metadata = dict(metadata or {})
|
|
466
|
+
result_metadata[TOOL_INTERRUPTED_METADATA_KEY] = True
|
|
467
|
+
if slot.fill_kind == "interrupted" and slot.result is not None:
|
|
468
|
+
# Terminal audit persistence can finish after the early
|
|
469
|
+
# interruption fill, including after the exchange was sealed.
|
|
470
|
+
# The slot retains the canonical result object, so merge the late
|
|
471
|
+
# replay references in place and checkpoint the upgraded history.
|
|
472
|
+
existing = slot.result.additional_properties.get(TOOL_RESULT_METADATA_KEY)
|
|
473
|
+
existing_metadata = dict(existing) if isinstance(existing, Mapping) else {}
|
|
474
|
+
slot.result.additional_properties[TOOL_RESULT_METADATA_KEY] = {
|
|
475
|
+
**existing_metadata,
|
|
476
|
+
**result_metadata,
|
|
477
|
+
}
|
|
478
|
+
if invocation_context is not None:
|
|
479
|
+
timing = _tool_trajectory_timing(function_call, invocation_context)
|
|
480
|
+
slot.result.additional_properties[TRAJECTORY_TIMING_KEY] = timing
|
|
481
|
+
self._kick_result_checkpoint()
|
|
482
|
+
return
|
|
483
|
+
if exchange is not self._pending_exchange:
|
|
484
|
+
return
|
|
485
|
+
if slot.fill_kind == "raw" and slot.result is not None:
|
|
486
|
+
result_metadata[TOOL_POST_PROCESSING_INTERRUPTED_METADATA_KEY] = True
|
|
487
|
+
existing = slot.result.additional_properties.get(TOOL_RESULT_METADATA_KEY)
|
|
488
|
+
if isinstance(existing, Mapping):
|
|
489
|
+
result_metadata = {**existing, **result_metadata}
|
|
490
|
+
slot.result.additional_properties[TOOL_RESULT_METADATA_KEY] = result_metadata
|
|
491
|
+
timing = _tool_trajectory_timing(function_call, invocation_context)
|
|
492
|
+
slot.result.additional_properties[TRAJECTORY_TIMING_KEY] = timing
|
|
493
|
+
self._kick_result_checkpoint()
|
|
494
|
+
return
|
|
495
|
+
if slot.result is not None:
|
|
496
|
+
# Final results are immutable; raw and interrupted fills took
|
|
497
|
+
# their dedicated merge paths above.
|
|
498
|
+
return
|
|
499
|
+
result_metadata[TOOL_FAILED_METADATA_KEY] = True
|
|
500
|
+
additional = _result_additional_properties(function_call, invocation_context)
|
|
501
|
+
additional[TOOL_RESULT_METADATA_KEY] = result_metadata
|
|
502
|
+
result = Content.from_function_result(
|
|
503
|
+
call_id=function_call.call_id, # type: ignore[arg-type]
|
|
504
|
+
result=(
|
|
505
|
+
"Error: Tool execution was interrupted. The operation may have completed; "
|
|
506
|
+
"inspect current state before retrying."
|
|
507
|
+
),
|
|
508
|
+
additional_properties=additional,
|
|
509
|
+
)
|
|
510
|
+
self._fill_slot(exchange, slot, result, fill_kind="interrupted")
|
|
511
|
+
|
|
512
|
+
async def _run_pre_wire_barrier(self) -> bool:
|
|
513
|
+
"""Strictly persist committed tool work; True only when the barrier reports it persisted."""
|
|
514
|
+
if self._committed_count == 0 or self._barrier_degraded or self._barrier_unconfigured:
|
|
515
|
+
return False
|
|
516
|
+
callback = self._on_pre_wire_barrier
|
|
517
|
+
if callback is None:
|
|
518
|
+
self._barrier_unconfigured = True
|
|
519
|
+
return False
|
|
520
|
+
for _attempt in range(2):
|
|
521
|
+
try:
|
|
522
|
+
outcome = await callback()
|
|
523
|
+
except Exception:
|
|
524
|
+
outcome = RecoveryPersistOutcome.FAILED
|
|
525
|
+
if outcome is RecoveryPersistOutcome.PERSISTED:
|
|
526
|
+
return True
|
|
527
|
+
if outcome is RecoveryPersistOutcome.UNCONFIGURED:
|
|
528
|
+
self._barrier_unconfigured = True
|
|
529
|
+
return False
|
|
530
|
+
self._barrier_degraded = True
|
|
531
|
+
if not self._barrier_warned:
|
|
532
|
+
self._barrier_warned = True
|
|
533
|
+
logger.error(
|
|
534
|
+
"Recovery sidecar persistence failed twice after committed tool work; "
|
|
535
|
+
"continuing with the in-memory journal."
|
|
536
|
+
)
|
|
537
|
+
return False
|
|
538
|
+
|
|
539
|
+
def _kick_result_checkpoint(self) -> None:
|
|
540
|
+
callback = self._on_result_checkpoint
|
|
541
|
+
if callback is None:
|
|
542
|
+
return
|
|
543
|
+
task = asyncio.get_running_loop().create_task(callback())
|
|
544
|
+
task.add_done_callback(self._observe_checkpoint_task)
|
|
545
|
+
|
|
546
|
+
@staticmethod
|
|
547
|
+
def _observe_checkpoint_task(task: asyncio.Task[None]) -> None:
|
|
548
|
+
if task.cancelled():
|
|
549
|
+
return
|
|
550
|
+
try:
|
|
551
|
+
exception = task.exception()
|
|
552
|
+
except Exception:
|
|
553
|
+
logger.debug("LoopRecorder result checkpoint failed", exc_info=True)
|
|
554
|
+
return
|
|
555
|
+
if exception is not None:
|
|
556
|
+
logger.debug(
|
|
557
|
+
"LoopRecorder result checkpoint failed",
|
|
558
|
+
exc_info=(type(exception), exception, exception.__traceback__),
|
|
559
|
+
)
|
|
560
|
+
|
|
561
|
+
@staticmethod
|
|
562
|
+
def _project_pending_exchange(exchange: _PendingExchange) -> list[Message]:
|
|
563
|
+
if exchange.projection_messages is not None:
|
|
564
|
+
return list(exchange.projection_messages)
|
|
565
|
+
answered_calls = {id(slot.function_call) for slot in exchange.slots if slot.result is not None}
|
|
566
|
+
staged_calls = {id(slot.function_call) for slot in exchange.slots}
|
|
567
|
+
projected: list[Message] = []
|
|
568
|
+
for message in exchange.response_messages:
|
|
569
|
+
message_staged_calls = [content for content in message.contents if id(content) in staged_calls]
|
|
570
|
+
if not message_staged_calls:
|
|
571
|
+
projected.append(message)
|
|
572
|
+
continue
|
|
573
|
+
answered_in_message = [content for content in message_staged_calls if id(content) in answered_calls]
|
|
574
|
+
informational = any(
|
|
575
|
+
content.type == "function_call" and content.informational_only for content in message.contents
|
|
576
|
+
)
|
|
577
|
+
if not answered_in_message and not informational:
|
|
578
|
+
continue
|
|
579
|
+
contents = [
|
|
580
|
+
content
|
|
581
|
+
for content in message.contents
|
|
582
|
+
if id(content) not in staged_calls or id(content) in answered_calls
|
|
583
|
+
]
|
|
584
|
+
projected.append(_message_snapshot(message, contents))
|
|
585
|
+
results = [slot.result for slot in exchange.slots if slot.result is not None]
|
|
586
|
+
if results:
|
|
587
|
+
carrier = Message(role="tool", contents=results)
|
|
588
|
+
carrier.additional_properties[ANALYTICS_ITEM_ID_KEY] = exchange.result_carrier_item_id
|
|
589
|
+
projected.append(carrier)
|
|
590
|
+
exchange.projection_messages = tuple(projected)
|
|
591
|
+
return projected
|
|
592
|
+
|
|
593
|
+
@staticmethod
|
|
594
|
+
def _dedupe_projected_messages(messages: Sequence[Message]) -> list[Message]:
|
|
595
|
+
seen_contents: set[int] = set()
|
|
596
|
+
projected: list[Message] = []
|
|
597
|
+
for message in messages:
|
|
598
|
+
contents = [content for content in message.contents if id(content) not in seen_contents]
|
|
599
|
+
if not contents:
|
|
600
|
+
continue
|
|
601
|
+
seen_contents.update(id(content) for content in contents)
|
|
602
|
+
projected.append(
|
|
603
|
+
message if len(contents) == len(message.contents) else _message_snapshot(message, contents)
|
|
604
|
+
)
|
|
605
|
+
return projected
|
|
606
|
+
|
|
607
|
+
def _checkpoint_messages(self) -> list[Message]:
|
|
608
|
+
"""Return the effective message prefix used for checkpoint suppression."""
|
|
609
|
+
if self._capture_service_loop_messages and self._service_loop_messages:
|
|
610
|
+
return self._service_loop_messages
|
|
611
|
+
return self._captured or []
|
|
612
|
+
|
|
613
|
+
def _should_suppress_checkpoint(self) -> bool:
|
|
614
|
+
"""Return True when the captured prefix has not changed since the last checkpoint."""
|
|
615
|
+
messages = self._checkpoint_messages()
|
|
616
|
+
key = (len(messages), self._hash_last_message(messages))
|
|
617
|
+
if key == self._last_checkpoint_key:
|
|
618
|
+
return True
|
|
619
|
+
self._last_checkpoint_key = key
|
|
620
|
+
return False
|
|
621
|
+
|
|
622
|
+
def _hash_last_message(self, messages: list[Message]) -> str:
|
|
623
|
+
if not messages:
|
|
624
|
+
return ""
|
|
625
|
+
try:
|
|
626
|
+
payload = self._message_hasher(messages[-1])
|
|
627
|
+
except Exception:
|
|
628
|
+
payload = repr(messages[-1])
|
|
629
|
+
# Hashing is identity-bearing: surrogatepass keeps the operation total
|
|
630
|
+
# without aliasing a lone surrogate to the literal escape that spells it.
|
|
631
|
+
return hashlib.sha256(payload.encode("utf-8", errors="surrogatepass")).hexdigest()
|