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,445 @@
|
|
|
1
|
+
# Copyright (c) Huawei Technologies Co., Ltd. 2026. All rights reserved.
|
|
2
|
+
|
|
3
|
+
"""Provider signals: what the model service itself said about a failure.
|
|
4
|
+
|
|
5
|
+
A signal is read from ONE explicit node — the first SDK-shaped exception in
|
|
6
|
+
walk order — so its status, code, type and message never combine evidence
|
|
7
|
+
from different nodes. An SDK-shaped node is a :class:`ProviderResponseError`,
|
|
8
|
+
a node with an integer ``status_code``, or a node with both a ``body`` and a
|
|
9
|
+
``code`` attribute (the bare ``openai.APIError`` an in-band stream error
|
|
10
|
+
raises). ``code`` alone doesn't count: ``SystemExit.code`` would match.
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
from __future__ import annotations
|
|
14
|
+
|
|
15
|
+
import json
|
|
16
|
+
import math
|
|
17
|
+
import re
|
|
18
|
+
from collections.abc import Iterable, Mapping
|
|
19
|
+
from dataclasses import dataclass
|
|
20
|
+
from typing import Any
|
|
21
|
+
|
|
22
|
+
from ._text import _clean_exception_text
|
|
23
|
+
from .kinds import ErrorKind
|
|
24
|
+
|
|
25
|
+
# Account quota or billing exhaustion: retrying the same request cannot
|
|
26
|
+
# succeed until the account changes. Broad types such as
|
|
27
|
+
# ``invalid_request_error`` are deliberately absent.
|
|
28
|
+
NON_RETRYABLE_PROVIDER_ERROR_CODES = frozenset(
|
|
29
|
+
{
|
|
30
|
+
"insufficient_quota",
|
|
31
|
+
"billing_hard_limit_reached",
|
|
32
|
+
"exceeded_current_quota_error",
|
|
33
|
+
"usage_not_included",
|
|
34
|
+
}
|
|
35
|
+
)
|
|
36
|
+
# Zhipu GLM's balance-exhausted code; it means quota only on a 429.
|
|
37
|
+
_GLM_QUOTA_CODE = "1113"
|
|
38
|
+
_PAYMENT_REQUIRED = 402
|
|
39
|
+
|
|
40
|
+
_PROVIDER_CODE_KINDS: Mapping[str, ErrorKind] = {
|
|
41
|
+
"rate_limit_exceeded": ErrorKind.RATE_LIMITED,
|
|
42
|
+
"rate_limit_error": ErrorKind.RATE_LIMITED,
|
|
43
|
+
"overloaded_error": ErrorKind.OVERLOADED,
|
|
44
|
+
"server_is_overloaded": ErrorKind.OVERLOADED,
|
|
45
|
+
"slow_down": ErrorKind.OVERLOADED,
|
|
46
|
+
"api_error": ErrorKind.SERVER_ERROR,
|
|
47
|
+
"server_error": ErrorKind.SERVER_ERROR,
|
|
48
|
+
"request_too_large": ErrorKind.PAYLOAD_TOO_LARGE,
|
|
49
|
+
"authentication_error": ErrorKind.AUTH_FAILED,
|
|
50
|
+
"permission_error": ErrorKind.AUTH_FAILED,
|
|
51
|
+
"invalid_request_error": ErrorKind.REQUEST_REJECTED,
|
|
52
|
+
"not_found_error": ErrorKind.REQUEST_REJECTED,
|
|
53
|
+
"content_filter": ErrorKind.CONTENT_FILTERED,
|
|
54
|
+
"billing_error": ErrorKind.QUOTA_EXHAUSTED,
|
|
55
|
+
"stream_truncated": ErrorKind.STREAM_TRUNCATED,
|
|
56
|
+
}
|
|
57
|
+
# Codes only a response's own failure reports (``ProviderResponseError``, or
|
|
58
|
+
# an error event inside its stream): an HTTP error that carries one keeps the
|
|
59
|
+
# kind its status gives it.
|
|
60
|
+
_IN_BAND_CODE_KINDS: Mapping[str, ErrorKind] = {
|
|
61
|
+
**_PROVIDER_CODE_KINDS,
|
|
62
|
+
# Finish reasons a Chat Completions service (GLM, DeepSeek) ends a
|
|
63
|
+
# completion with when it failed to finish it.
|
|
64
|
+
"network_error": ErrorKind.STREAM_TRUNCATED,
|
|
65
|
+
"insufficient_system_resource": ErrorKind.OVERLOADED,
|
|
66
|
+
# Codes a failed Responses API response reports.
|
|
67
|
+
"invalid_prompt": ErrorKind.REQUEST_REJECTED,
|
|
68
|
+
"cyber_policy": ErrorKind.CONTENT_FILTERED,
|
|
69
|
+
"misalignment_policy_violation": ErrorKind.CONTENT_FILTERED,
|
|
70
|
+
"image_content_policy_violation": ErrorKind.CONTENT_FILTERED,
|
|
71
|
+
**dict.fromkeys(
|
|
72
|
+
(
|
|
73
|
+
"invalid_image",
|
|
74
|
+
"invalid_image_format",
|
|
75
|
+
"invalid_base64_image",
|
|
76
|
+
"invalid_image_url",
|
|
77
|
+
"image_too_large",
|
|
78
|
+
"image_too_small",
|
|
79
|
+
"image_parse_error",
|
|
80
|
+
"invalid_image_mode",
|
|
81
|
+
"image_file_too_large",
|
|
82
|
+
"unsupported_image_media_type",
|
|
83
|
+
"empty_image_file",
|
|
84
|
+
"failed_to_download_image",
|
|
85
|
+
"image_file_not_found",
|
|
86
|
+
),
|
|
87
|
+
ErrorKind.REQUEST_REJECTED,
|
|
88
|
+
),
|
|
89
|
+
}
|
|
90
|
+
# Kinds of a failure a response reported in-band that the same request meets
|
|
91
|
+
# again when sent anew.
|
|
92
|
+
_FINAL_IN_BAND_KINDS = frozenset(
|
|
93
|
+
{
|
|
94
|
+
ErrorKind.QUOTA_EXHAUSTED,
|
|
95
|
+
ErrorKind.CONTEXT_OVERFLOW,
|
|
96
|
+
ErrorKind.PAYLOAD_TOO_LARGE,
|
|
97
|
+
ErrorKind.AUTH_FAILED,
|
|
98
|
+
ErrorKind.REQUEST_REJECTED,
|
|
99
|
+
ErrorKind.CONTENT_FILTERED,
|
|
100
|
+
}
|
|
101
|
+
)
|
|
102
|
+
|
|
103
|
+
_CONTEXT_OVERFLOW_CODES = frozenset({"context_length_exceeded", "model_context_window_exceeded"})
|
|
104
|
+
# Only phrasings that name the context window or the model's token limit.
|
|
105
|
+
_CONTEXT_OVERFLOW_PATTERNS = tuple(
|
|
106
|
+
re.compile(pattern, re.IGNORECASE)
|
|
107
|
+
for pattern in (
|
|
108
|
+
r"context_length_exceeded",
|
|
109
|
+
r"context window", # OpenAI "exceeds the context window", MiniMax
|
|
110
|
+
r"maximum context length", # OpenAI, DeepSeek, OpenRouter
|
|
111
|
+
r"prompt is too long", # Anthropic
|
|
112
|
+
r"input is too long", # Amazon Bedrock
|
|
113
|
+
r"too many tokens",
|
|
114
|
+
r"input token count.*exceeds the maximum", # Google Gemini
|
|
115
|
+
r"maximum prompt length is \d+", # xAI
|
|
116
|
+
r"reduce the length of the messages", # Groq
|
|
117
|
+
r"exceeds the available context size", # llama.cpp
|
|
118
|
+
r"greater than the context length", # LM Studio
|
|
119
|
+
r"exceeded model token limit", # Kimi
|
|
120
|
+
)
|
|
121
|
+
)
|
|
122
|
+
# The window limit, in tokens, that an overflow phrasing above names: a
|
|
123
|
+
# plain decimal, optionally with thousands commas; never a "128k" shorthand.
|
|
124
|
+
_LIMIT = r"(\d{1,3}(?:,\d{3})+|\d+)(?!\w|[.,]\d)"
|
|
125
|
+
_CONTEXT_LIMIT_PATTERNS = tuple(
|
|
126
|
+
re.compile(pattern.replace("{limit}", _LIMIT), re.IGNORECASE)
|
|
127
|
+
for pattern in (
|
|
128
|
+
r"maximum context length is {limit} tokens", # OpenAI, vLLM, DeepSeek, OpenRouter
|
|
129
|
+
r"prompt is too long: [\d,]+ tokens > {limit} maximum", # Anthropic
|
|
130
|
+
r"maximum number of tokens allowed \({limit}\)", # Google Gemini
|
|
131
|
+
r"maximum prompt length is {limit}", # xAI
|
|
132
|
+
r"available context size \({limit} tokens\)", # llama.cpp
|
|
133
|
+
r"n_ctx: {limit}", # LM Studio
|
|
134
|
+
r"exceeded model token limit: {limit}", # Kimi
|
|
135
|
+
)
|
|
136
|
+
)
|
|
137
|
+
# Throttling that happens to mention tokens ("Too many tokens, please wait",
|
|
138
|
+
# "too many tokens per minute", a daily token quota) is a rate limit, not an
|
|
139
|
+
# oversized request. Without a provider signal the text is the only
|
|
140
|
+
# evidence, so any rate-window wording vetoes it.
|
|
141
|
+
_NON_OVERFLOW_PHRASES = (
|
|
142
|
+
"throttl",
|
|
143
|
+
"rate limit",
|
|
144
|
+
"rate_limit",
|
|
145
|
+
"too many requests",
|
|
146
|
+
"please wait",
|
|
147
|
+
"per sec",
|
|
148
|
+
"per min",
|
|
149
|
+
"per hour",
|
|
150
|
+
"per day",
|
|
151
|
+
"quota",
|
|
152
|
+
)
|
|
153
|
+
# 429 is throttling. 413 / ``request_too_large`` is an oversized payload (an
|
|
154
|
+
# image, an attachment), which compaction cannot fix. Every 5xx is vetoed too
|
|
155
|
+
# (:func:`_is_server_error`): the server failed, and overflow wording there may
|
|
156
|
+
# name a temporary limit, so it stays a retry.
|
|
157
|
+
_NON_OVERFLOW_STATUS_CODES = frozenset({413, 429})
|
|
158
|
+
_NON_OVERFLOW_CODES = frozenset({"request_too_large"})
|
|
159
|
+
|
|
160
|
+
# Error types an Anthropic stream reports after its 200 that a retry of the
|
|
161
|
+
# same request cannot fix; every other type (overloaded, api, rate limit,
|
|
162
|
+
# timeout, unknown) is transient.
|
|
163
|
+
_NON_RETRYABLE_STREAM_ERROR_TYPES = frozenset(
|
|
164
|
+
{
|
|
165
|
+
"invalid_request_error",
|
|
166
|
+
"authentication_error",
|
|
167
|
+
"permission_error",
|
|
168
|
+
"not_found_error",
|
|
169
|
+
"request_too_large",
|
|
170
|
+
"billing_error",
|
|
171
|
+
}
|
|
172
|
+
)
|
|
173
|
+
|
|
174
|
+
|
|
175
|
+
def _code_kind(code: str) -> ErrorKind:
|
|
176
|
+
if code in _CONTEXT_OVERFLOW_CODES:
|
|
177
|
+
return ErrorKind.CONTEXT_OVERFLOW
|
|
178
|
+
if code in NON_RETRYABLE_PROVIDER_ERROR_CODES:
|
|
179
|
+
return ErrorKind.QUOTA_EXHAUSTED
|
|
180
|
+
return _IN_BAND_CODE_KINDS.get(code, ErrorKind.UNKNOWN)
|
|
181
|
+
|
|
182
|
+
|
|
183
|
+
def in_band_failure_retryable(code: str) -> bool:
|
|
184
|
+
"""Whether a request whose response failed with *code* may succeed when sent again.
|
|
185
|
+
|
|
186
|
+
Adapters raising :class:`ProviderResponseError` for a failure the
|
|
187
|
+
response itself reported decide its retry by this, and the classifier
|
|
188
|
+
applies it to an error an SDK raised from inside a stream; an unknown
|
|
189
|
+
code may pass.
|
|
190
|
+
"""
|
|
191
|
+
return _code_kind(code) not in _FINAL_IN_BAND_KINDS
|
|
192
|
+
|
|
193
|
+
|
|
194
|
+
class ContinuationVerdictError(Exception):
|
|
195
|
+
"""A failure that states whether it judged the response terminal.
|
|
196
|
+
|
|
197
|
+
True means a live continuation token now names a completed, immutable
|
|
198
|
+
response: a retry must issue a fresh request, never re-poll it. Raisers
|
|
199
|
+
in higher tiers subclass this so the classifier reads a typed field.
|
|
200
|
+
"""
|
|
201
|
+
|
|
202
|
+
invalidates_continuation_token: bool = False
|
|
203
|
+
|
|
204
|
+
|
|
205
|
+
class ProviderResponseError(ContinuationVerdictError):
|
|
206
|
+
"""A provider failure an adapter found in a response the SDK accepted.
|
|
207
|
+
|
|
208
|
+
Adapters raise it for failures the SDK does not raise itself — a stream
|
|
209
|
+
that ended without its terminal event, an error-typed finish reason — and
|
|
210
|
+
state the retry decision explicitly.
|
|
211
|
+
|
|
212
|
+
``observed_contents`` holds what the failed response showed that the
|
|
213
|
+
adapter never yielded, such as provider-hosted tool work: the retry gates
|
|
214
|
+
count it as executed. It is opaque here; the layer that reads it knows
|
|
215
|
+
its type. ``usage_details`` holds the token usage the failed response
|
|
216
|
+
reported, so the tokens it consumed are still counted.
|
|
217
|
+
"""
|
|
218
|
+
|
|
219
|
+
def __init__(
|
|
220
|
+
self,
|
|
221
|
+
code: str,
|
|
222
|
+
provider_message: str,
|
|
223
|
+
*,
|
|
224
|
+
retryable: bool,
|
|
225
|
+
retry_after: float | None = None,
|
|
226
|
+
invalidates_continuation_token: bool = False,
|
|
227
|
+
kind: ErrorKind | None = None,
|
|
228
|
+
observed_contents: tuple[object, ...] = (),
|
|
229
|
+
usage_details: Mapping[str, Any] | None = None,
|
|
230
|
+
) -> None:
|
|
231
|
+
super().__init__(f"{code}: {provider_message}")
|
|
232
|
+
self.code = code
|
|
233
|
+
self.provider_message = provider_message
|
|
234
|
+
self.retryable = retryable
|
|
235
|
+
self.retry_after = retry_after
|
|
236
|
+
self.invalidates_continuation_token = invalidates_continuation_token
|
|
237
|
+
self.kind = kind if kind is not None else _code_kind(code)
|
|
238
|
+
self.observed_contents = observed_contents
|
|
239
|
+
self.usage_details = usage_details
|
|
240
|
+
|
|
241
|
+
|
|
242
|
+
@dataclass(frozen=True, slots=True)
|
|
243
|
+
class ProviderSignal:
|
|
244
|
+
"""The provider's own statement about a failure, read from one node."""
|
|
245
|
+
|
|
246
|
+
# Every field below was read from this one exception.
|
|
247
|
+
source: BaseException
|
|
248
|
+
# None for a bare ``APIError`` raised from an in-band stream event.
|
|
249
|
+
status_code: int | None
|
|
250
|
+
code: str | None
|
|
251
|
+
# ``body.error.type`` or the node's ``.type``.
|
|
252
|
+
error_type: str | None
|
|
253
|
+
message: str | None
|
|
254
|
+
# Seconds from the response's ``retry-after`` header.
|
|
255
|
+
retry_after: float | None
|
|
256
|
+
# Set only by :class:`ProviderResponseError`.
|
|
257
|
+
explicit_retryable: bool | None = None
|
|
258
|
+
|
|
259
|
+
|
|
260
|
+
def _text(value: object) -> str | None:
|
|
261
|
+
if isinstance(value, bool):
|
|
262
|
+
return None
|
|
263
|
+
if isinstance(value, int):
|
|
264
|
+
return str(value)
|
|
265
|
+
return value if isinstance(value, str) and value else None
|
|
266
|
+
|
|
267
|
+
|
|
268
|
+
def _error_object(body: object) -> Mapping[str, Any]:
|
|
269
|
+
"""Return the error object of a provider body (a dict or its JSON text)."""
|
|
270
|
+
if isinstance(body, str | bytes):
|
|
271
|
+
try:
|
|
272
|
+
body = json.loads(body)
|
|
273
|
+
except ValueError:
|
|
274
|
+
return {}
|
|
275
|
+
if not isinstance(body, Mapping):
|
|
276
|
+
return {}
|
|
277
|
+
error = body.get("error")
|
|
278
|
+
return error if isinstance(error, Mapping) else body
|
|
279
|
+
|
|
280
|
+
|
|
281
|
+
def _retry_after(node: BaseException) -> float | None:
|
|
282
|
+
response = getattr(node, "response", None)
|
|
283
|
+
headers = getattr(response, "headers", None)
|
|
284
|
+
if not isinstance(headers, Mapping):
|
|
285
|
+
return None
|
|
286
|
+
raw = headers.get("retry-after")
|
|
287
|
+
try:
|
|
288
|
+
seconds = float(raw) if isinstance(raw, str) else None
|
|
289
|
+
except ValueError:
|
|
290
|
+
return None
|
|
291
|
+
return seconds if seconds is not None and math.isfinite(seconds) and seconds >= 0 else None
|
|
292
|
+
|
|
293
|
+
|
|
294
|
+
def _status(node: BaseException) -> int | None:
|
|
295
|
+
status = getattr(node, "status_code", None)
|
|
296
|
+
return status if isinstance(status, int) and not isinstance(status, bool) else None
|
|
297
|
+
|
|
298
|
+
|
|
299
|
+
def provider_signal(explicit: Iterable[BaseException]) -> ProviderSignal | None:
|
|
300
|
+
"""Return the signal of the first SDK-shaped node in *explicit*, if any."""
|
|
301
|
+
for node in explicit:
|
|
302
|
+
if isinstance(node, ProviderResponseError):
|
|
303
|
+
return ProviderSignal(
|
|
304
|
+
source=node,
|
|
305
|
+
status_code=None,
|
|
306
|
+
code=node.code,
|
|
307
|
+
error_type=None,
|
|
308
|
+
message=node.provider_message,
|
|
309
|
+
retry_after=node.retry_after,
|
|
310
|
+
explicit_retryable=node.retryable,
|
|
311
|
+
)
|
|
312
|
+
status = _status(node)
|
|
313
|
+
body = getattr(node, "body", None)
|
|
314
|
+
if status is None and (body is None or not hasattr(node, "code")):
|
|
315
|
+
continue
|
|
316
|
+
error = _error_object(body)
|
|
317
|
+
return ProviderSignal(
|
|
318
|
+
source=node,
|
|
319
|
+
status_code=status,
|
|
320
|
+
code=_text(getattr(node, "code", None)) or _text(error.get("code")),
|
|
321
|
+
error_type=_text(getattr(node, "type", None)) or _text(error.get("type")),
|
|
322
|
+
message=_text(error.get("message")) or _text(getattr(node, "message", None)),
|
|
323
|
+
retry_after=_retry_after(node),
|
|
324
|
+
)
|
|
325
|
+
return None
|
|
326
|
+
|
|
327
|
+
|
|
328
|
+
def _is_server_error(status: int | None) -> bool:
|
|
329
|
+
return status is not None and 500 <= status < 600
|
|
330
|
+
|
|
331
|
+
|
|
332
|
+
def status_kind(status: int) -> ErrorKind:
|
|
333
|
+
"""Map an HTTP error status to its coarse kind."""
|
|
334
|
+
if status == 429:
|
|
335
|
+
return ErrorKind.RATE_LIMITED
|
|
336
|
+
if status in (401, 403):
|
|
337
|
+
return ErrorKind.AUTH_FAILED
|
|
338
|
+
if status == 413:
|
|
339
|
+
return ErrorKind.PAYLOAD_TOO_LARGE
|
|
340
|
+
if status == _PAYMENT_REQUIRED:
|
|
341
|
+
return ErrorKind.QUOTA_EXHAUSTED
|
|
342
|
+
if status == 529:
|
|
343
|
+
return ErrorKind.OVERLOADED
|
|
344
|
+
if _is_server_error(status):
|
|
345
|
+
return ErrorKind.SERVER_ERROR
|
|
346
|
+
if 400 <= status < 500:
|
|
347
|
+
return ErrorKind.REQUEST_REJECTED
|
|
348
|
+
return ErrorKind.UNKNOWN
|
|
349
|
+
|
|
350
|
+
|
|
351
|
+
def _is_quota(signal: ProviderSignal) -> bool:
|
|
352
|
+
if signal.code in NON_RETRYABLE_PROVIDER_ERROR_CODES or signal.error_type in NON_RETRYABLE_PROVIDER_ERROR_CODES:
|
|
353
|
+
return True
|
|
354
|
+
if signal.code == _GLM_QUOTA_CODE and signal.status_code == 429:
|
|
355
|
+
return True
|
|
356
|
+
return signal.status_code == _PAYMENT_REQUIRED
|
|
357
|
+
|
|
358
|
+
|
|
359
|
+
def signal_kind(signal: ProviderSignal) -> tuple[ErrorKind, str]:
|
|
360
|
+
"""Return the kind *signal* names and the evidence for it."""
|
|
361
|
+
source = signal.source
|
|
362
|
+
if isinstance(source, ProviderResponseError):
|
|
363
|
+
return source.kind, f"provider {source.code}"
|
|
364
|
+
evidence = f"{type(source).__name__} http {signal.status_code}"
|
|
365
|
+
if _is_quota(signal):
|
|
366
|
+
return ErrorKind.QUOTA_EXHAUSTED, f"{evidence} {signal.code or signal.error_type or ''}".rstrip()
|
|
367
|
+
# An error a stream reports in-band, with no status of its own, is how
|
|
368
|
+
# that response failed: the codes only a response reports name it too.
|
|
369
|
+
codes = _IN_BAND_CODE_KINDS if signal.status_code is None else _PROVIDER_CODE_KINDS
|
|
370
|
+
if signal.code is not None and (kind := codes.get(signal.code)) is not None:
|
|
371
|
+
return kind, f"{evidence} {signal.code}"
|
|
372
|
+
# An error status outranks the error type, which can be broad
|
|
373
|
+
# (OpenAI answers a bad key with 401 ``invalid_request_error``); the type
|
|
374
|
+
# decides only for errors reported without one, e.g. inside a 2xx stream.
|
|
375
|
+
if signal.status_code is not None and (kind := status_kind(signal.status_code)) is not ErrorKind.UNKNOWN:
|
|
376
|
+
return kind, evidence
|
|
377
|
+
if signal.error_type is not None and (kind := codes.get(signal.error_type)) is not None:
|
|
378
|
+
return kind, f"{evidence} {signal.error_type}"
|
|
379
|
+
return ErrorKind.UNKNOWN, evidence
|
|
380
|
+
|
|
381
|
+
|
|
382
|
+
def _names_overflow(texts: Iterable[str]) -> bool:
|
|
383
|
+
texts = [text.casefold() for text in texts if text]
|
|
384
|
+
if any(phrase in text for text in texts for phrase in _NON_OVERFLOW_PHRASES):
|
|
385
|
+
return False
|
|
386
|
+
return any(pattern.search(text) for text in texts for pattern in _CONTEXT_OVERFLOW_PATTERNS)
|
|
387
|
+
|
|
388
|
+
|
|
389
|
+
def names_context_overflow(signal: ProviderSignal | None, unstructured_texts: Iterable[str]) -> bool:
|
|
390
|
+
"""Return whether explicit evidence says the request overflowed the context window.
|
|
391
|
+
|
|
392
|
+
With a provider signal only its own status, code and text count. Without
|
|
393
|
+
one (a plain exception carrying the provider's text), *unstructured_texts*
|
|
394
|
+
— the explicit nodes' texts, minus nodes Chrys's own policies raised — are
|
|
395
|
+
read instead.
|
|
396
|
+
"""
|
|
397
|
+
if signal is None:
|
|
398
|
+
return _names_overflow(unstructured_texts)
|
|
399
|
+
source = signal.source
|
|
400
|
+
if isinstance(source, ProviderResponseError):
|
|
401
|
+
return source.kind is ErrorKind.CONTEXT_OVERFLOW
|
|
402
|
+
status = signal.status_code
|
|
403
|
+
if status in _NON_OVERFLOW_STATUS_CODES or _is_server_error(status) or signal.code in _NON_OVERFLOW_CODES:
|
|
404
|
+
return False
|
|
405
|
+
if signal.code in _CONTEXT_OVERFLOW_CODES:
|
|
406
|
+
return True
|
|
407
|
+
return _names_overflow((signal.message or "", _clean_exception_text(source)))
|
|
408
|
+
|
|
409
|
+
|
|
410
|
+
def named_context_limit(texts: Iterable[str]) -> int | None:
|
|
411
|
+
"""Return the one positive window limit, in tokens, that an overflow's *texts* name; None for none or several."""
|
|
412
|
+
limits = {
|
|
413
|
+
int(match.group(1).replace(",", ""))
|
|
414
|
+
for text in texts
|
|
415
|
+
for pattern in _CONTEXT_LIMIT_PATTERNS
|
|
416
|
+
for match in pattern.finditer(text)
|
|
417
|
+
}
|
|
418
|
+
limits.discard(0)
|
|
419
|
+
return limits.pop() if len(limits) == 1 else None
|
|
420
|
+
|
|
421
|
+
|
|
422
|
+
def names_server_error_overflow(signal: ProviderSignal) -> bool:
|
|
423
|
+
"""Return whether a 5xx names the context window, which :func:`names_context_overflow` vetoes.
|
|
424
|
+
|
|
425
|
+
The veto stands for retry policy: a 5xx may name a temporary limit ("maximum
|
|
426
|
+
context length is temporarily reduced"). A gateway may also wrap a real
|
|
427
|
+
overflow in one, though. Rate-window wording still vetoes it, and a
|
|
428
|
+
:class:`ProviderResponseError` names its own kind.
|
|
429
|
+
"""
|
|
430
|
+
if not _is_server_error(signal.status_code) or isinstance(signal.source, ProviderResponseError):
|
|
431
|
+
return False
|
|
432
|
+
if signal.code in _NON_OVERFLOW_CODES:
|
|
433
|
+
return False
|
|
434
|
+
if signal.code in _CONTEXT_OVERFLOW_CODES:
|
|
435
|
+
return True
|
|
436
|
+
return _names_overflow((signal.message or "", _clean_exception_text(signal.source)))
|
|
437
|
+
|
|
438
|
+
|
|
439
|
+
def stream_error_retryable(signal: ProviderSignal) -> bool:
|
|
440
|
+
"""Retry decision for an error a stream reported after its 2xx response."""
|
|
441
|
+
return signal.error_type not in _NON_RETRYABLE_STREAM_ERROR_TYPES
|
|
442
|
+
|
|
443
|
+
|
|
444
|
+
def is_2xx(status: int | None) -> bool:
|
|
445
|
+
return status is not None and 200 <= status < 300
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
# Copyright (c) Huawei Technologies Co., Ltd. 2026. All rights reserved.
|
|
2
|
+
|
|
3
|
+
"""Route facts: where a request was going, and through which first hop.
|
|
4
|
+
|
|
5
|
+
The LLM HTTP client stamps a :class:`RouteFacts` snapshot on every request it
|
|
6
|
+
sends (``request.extensions[ROUTE_EXTENSION_KEY]``), redirects and SDK retries
|
|
7
|
+
included. The classifier reads it back from the failed request carried on the
|
|
8
|
+
exception chain, so a verdict about a failure never depends on process-global
|
|
9
|
+
state read at classification time.
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
from __future__ import annotations
|
|
13
|
+
|
|
14
|
+
import contextlib
|
|
15
|
+
from collections.abc import Iterable, Mapping
|
|
16
|
+
from dataclasses import dataclass
|
|
17
|
+
from urllib.parse import urlsplit
|
|
18
|
+
|
|
19
|
+
from chrys.foundation.net.url import hostname
|
|
20
|
+
|
|
21
|
+
from ._walk import request_of
|
|
22
|
+
|
|
23
|
+
ROUTE_EXTENSION_KEY = "chrys.route"
|
|
24
|
+
|
|
25
|
+
_DEFAULT_PORTS = {"http": 80, "https": 443, "socks5": 1080, "socks5h": 1080}
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
@dataclass(frozen=True, slots=True)
|
|
29
|
+
class Origin:
|
|
30
|
+
"""A scheme/host/port identity; the host is lowercase, IPv6 without brackets."""
|
|
31
|
+
|
|
32
|
+
scheme: str
|
|
33
|
+
host: str
|
|
34
|
+
port: int
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
@dataclass(frozen=True, slots=True)
|
|
38
|
+
class RouteFacts:
|
|
39
|
+
"""One request's route, as its client resolved it when the request left."""
|
|
40
|
+
|
|
41
|
+
target: Origin
|
|
42
|
+
# The proxy this client used for ``target``, credentials stripped.
|
|
43
|
+
proxy: Origin | None
|
|
44
|
+
# Whether this process had EVER received a response through the same
|
|
45
|
+
# first hop before this request was sent — never proof it is reachable now.
|
|
46
|
+
first_hop_reached: bool
|
|
47
|
+
|
|
48
|
+
@property
|
|
49
|
+
def first_hop(self) -> Origin:
|
|
50
|
+
return self.proxy or self.target
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
def origin_of(url: object) -> Origin | None:
|
|
54
|
+
"""Return the origin of *url* (a string or an ``httpx.URL``), or None when it has none."""
|
|
55
|
+
try:
|
|
56
|
+
parts = urlsplit(str(url))
|
|
57
|
+
port = parts.port
|
|
58
|
+
except ValueError:
|
|
59
|
+
return None
|
|
60
|
+
scheme = parts.scheme.lower()
|
|
61
|
+
host = parts.hostname
|
|
62
|
+
if not scheme or not host:
|
|
63
|
+
return None
|
|
64
|
+
port = port if port is not None else _DEFAULT_PORTS.get(scheme)
|
|
65
|
+
if port is None:
|
|
66
|
+
return None
|
|
67
|
+
with contextlib.suppress(ValueError):
|
|
68
|
+
host = hostname(host)
|
|
69
|
+
return Origin(scheme, host, port)
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
def route_of(explicit: Iterable[BaseException]) -> RouteFacts | None:
|
|
73
|
+
"""Return the route snapshot of the deepest explicit node whose request carries one.
|
|
74
|
+
|
|
75
|
+
After a redirect the inner transport error holds the redirected request,
|
|
76
|
+
so the deepest snapshot names the target that actually failed.
|
|
77
|
+
"""
|
|
78
|
+
found: RouteFacts | None = None
|
|
79
|
+
for node in explicit:
|
|
80
|
+
request = request_of(node)
|
|
81
|
+
extensions = getattr(request, "extensions", None) if request is not None else None
|
|
82
|
+
facts = extensions.get(ROUTE_EXTENSION_KEY) if isinstance(extensions, Mapping) else None
|
|
83
|
+
if isinstance(facts, RouteFacts):
|
|
84
|
+
found = facts
|
|
85
|
+
return found
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
# Copyright (c) Huawei Technologies Co., Ltd. 2026. All rights reserved.
|
|
2
|
+
|
|
3
|
+
"""Event-driven communication system between frontend and backend."""
|
|
4
|
+
|
|
5
|
+
from chrys.foundation.events.bus import EventBus
|
|
6
|
+
from chrys.foundation.events.types import Event
|
|
7
|
+
|
|
8
|
+
__all__ = ["Event", "EventBus"]
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
# Copyright (c) Huawei Technologies Co., Ltd. 2026. All rights reserved.
|
|
2
|
+
|
|
3
|
+
"""EventBus — async pub/sub event dispatcher."""
|
|
4
|
+
|
|
5
|
+
from __future__ import annotations
|
|
6
|
+
|
|
7
|
+
import asyncio
|
|
8
|
+
import logging
|
|
9
|
+
from collections import defaultdict
|
|
10
|
+
from typing import TYPE_CHECKING, TypeVar
|
|
11
|
+
|
|
12
|
+
from chrys.foundation.events.types import Event
|
|
13
|
+
|
|
14
|
+
if TYPE_CHECKING:
|
|
15
|
+
from collections.abc import AsyncIterator, Awaitable, Callable
|
|
16
|
+
|
|
17
|
+
E = TypeVar("E", bound=Event)
|
|
18
|
+
logger = logging.getLogger(__name__)
|
|
19
|
+
|
|
20
|
+
# Stream queues are intentionally unbounded so a slow consumer never causes event
|
|
21
|
+
# loss: dropping here would silently truncate streamed LLM output on the
|
|
22
|
+
# headless/ACP path (see ``session_host._HEADLESS_RUN_EVENT_TYPES``, which carries
|
|
23
|
+
# ``InvocationMessage``/``AgentThinking``). This threshold only drives a one-shot
|
|
24
|
+
# diagnostic warning so a badly-lagging consumer is observable in the wild —
|
|
25
|
+
# delivery semantics never change (events are retained, never dropped).
|
|
26
|
+
_STREAM_QUEUE_HIGH_WATER = 10_000
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
class EventBus:
|
|
30
|
+
"""In-process async event bus.
|
|
31
|
+
|
|
32
|
+
Supports both callback-based subscriptions and async iteration (streaming).
|
|
33
|
+
Designed as the sole communication channel between frontend and backend.
|
|
34
|
+
|
|
35
|
+
Two delivery mechanisms with deliberately different backpressure:
|
|
36
|
+
|
|
37
|
+
* ``subscribe()`` callbacks are awaited inline by :meth:`publish`, so a slow
|
|
38
|
+
handler backpressures the publisher. Never lossy. Downstream ordering
|
|
39
|
+
contract: the TUI's tool-card routing relies on this — a tool's
|
|
40
|
+
InvocationToolCallStart handler chain completes before the tool executes, so a
|
|
41
|
+
call's result can never overtake its own start (see
|
|
42
|
+
``app.tui.widgets.chat.tool_registry``). Making publish fire-and-forget
|
|
43
|
+
would silently re-open mid-mount routing races there.
|
|
44
|
+
* ``stream()`` iterators receive events through an **unbounded** per-consumer
|
|
45
|
+
queue (:class:`_EventStream`). :meth:`publish` enqueues without awaiting, so
|
|
46
|
+
it never blocks on a slow consumer, and the queue is unbounded so it never
|
|
47
|
+
drops. A stalled consumer therefore grows memory (bounded in practice by a
|
|
48
|
+
single turn's events — the stream is opened and torn down per turn) rather
|
|
49
|
+
than losing events.
|
|
50
|
+
"""
|
|
51
|
+
|
|
52
|
+
def __init__(self) -> None:
|
|
53
|
+
self._handlers: dict[type[Event], list[Callable[..., Awaitable[None]]]] = defaultdict(list)
|
|
54
|
+
self._streams: list[_EventStream] = []
|
|
55
|
+
|
|
56
|
+
async def publish(self, event: Event, *, raise_handler_errors: bool = False) -> None:
|
|
57
|
+
"""Publish an event to all subscribers."""
|
|
58
|
+
event_type = type(event)
|
|
59
|
+
failures: list[Exception] = []
|
|
60
|
+
for handler in list(self._handlers.get(event_type, [])):
|
|
61
|
+
try:
|
|
62
|
+
await handler(event)
|
|
63
|
+
except Exception as exc:
|
|
64
|
+
failures.append(exc)
|
|
65
|
+
logger.exception("EventBus handler failed for %s", event_type.__name__)
|
|
66
|
+
for stream in list(self._streams):
|
|
67
|
+
stream._deliver(event)
|
|
68
|
+
if raise_handler_errors and failures:
|
|
69
|
+
if len(failures) == 1:
|
|
70
|
+
raise failures[0]
|
|
71
|
+
raise ExceptionGroup(f"EventBus handlers failed for {event_type.__name__}", failures)
|
|
72
|
+
|
|
73
|
+
async def subscribe(self, event_type: type[E], handler: Callable[[E], Awaitable[None]]) -> None:
|
|
74
|
+
"""Register a callback handler for a specific event type."""
|
|
75
|
+
self._handlers[event_type].append(handler) # type: ignore[arg-type]
|
|
76
|
+
|
|
77
|
+
async def unsubscribe(self, event_type: type[E], handler: Callable[..., Awaitable[None]]) -> None:
|
|
78
|
+
"""Remove a previously registered handler."""
|
|
79
|
+
handlers = self._handlers.get(event_type, [])
|
|
80
|
+
if handler in handlers:
|
|
81
|
+
handlers.remove(handler)
|
|
82
|
+
|
|
83
|
+
def stream(self, *event_types: type[Event]) -> _EventStream:
|
|
84
|
+
"""Create an async iterator that yields events of the given types.
|
|
85
|
+
|
|
86
|
+
Usage::
|
|
87
|
+
|
|
88
|
+
async for event in bus.stream(InvocationMessage, InvocationToolCallStart):
|
|
89
|
+
...
|
|
90
|
+
"""
|
|
91
|
+
return _EventStream(self, event_types)
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
class _EventStream:
|
|
95
|
+
"""Async iterator adapter for EventBus streaming.
|
|
96
|
+
|
|
97
|
+
Backed by an unbounded queue: events are retained, never dropped, so a slow
|
|
98
|
+
consumer cannot truncate streamed output (notably LLM text on the
|
|
99
|
+
headless/ACP path). See the module-level ``_STREAM_QUEUE_HIGH_WATER`` note.
|
|
100
|
+
"""
|
|
101
|
+
|
|
102
|
+
def __init__(self, bus: EventBus, event_types: tuple[type[Event], ...]) -> None:
|
|
103
|
+
self._bus = bus
|
|
104
|
+
self._event_types = event_types
|
|
105
|
+
self._queue: asyncio.Queue[Event] = asyncio.Queue() # unbounded — lossless by design
|
|
106
|
+
self._warned_high_water = False
|
|
107
|
+
|
|
108
|
+
def _deliver(self, event: Event) -> None:
|
|
109
|
+
"""Enqueue an event this stream subscribed to — never drops.
|
|
110
|
+
|
|
111
|
+
Events are filtered here (producer side) so the unbounded queue only ever
|
|
112
|
+
retains events the stream actually asked for: a narrow ``stream(X)`` never
|
|
113
|
+
accumulates unrelated traffic, and the high-water backlog counts only
|
|
114
|
+
matching events. The queue is unbounded, so ``put_nowait`` cannot raise
|
|
115
|
+
``QueueFull``; we emit a single high-water warning if the matching backlog
|
|
116
|
+
grows large, so a stalled consumer is observable without discarding an
|
|
117
|
+
event. An empty ``_event_types`` means "subscribe to all".
|
|
118
|
+
"""
|
|
119
|
+
if self._event_types and not isinstance(event, self._event_types):
|
|
120
|
+
return
|
|
121
|
+
self._queue.put_nowait(event)
|
|
122
|
+
if not self._warned_high_water and self._queue.qsize() >= _STREAM_QUEUE_HIGH_WATER:
|
|
123
|
+
self._warned_high_water = True
|
|
124
|
+
logger.warning(
|
|
125
|
+
"EventBus stream backlog exceeded %d events; consumer is falling behind "
|
|
126
|
+
"(events are retained, not dropped)",
|
|
127
|
+
_STREAM_QUEUE_HIGH_WATER,
|
|
128
|
+
)
|
|
129
|
+
|
|
130
|
+
async def __aenter__(self) -> _EventStream:
|
|
131
|
+
self._bus._streams.append(self)
|
|
132
|
+
return self
|
|
133
|
+
|
|
134
|
+
async def __aexit__(self, *exc: object) -> None:
|
|
135
|
+
self._bus._streams.remove(self)
|
|
136
|
+
|
|
137
|
+
def __aiter__(self) -> AsyncIterator[Event]:
|
|
138
|
+
return self
|
|
139
|
+
|
|
140
|
+
async def __anext__(self) -> Event:
|
|
141
|
+
# Filtering happens producer-side in ``_deliver``; everything queued here
|
|
142
|
+
# already matches ``_event_types``.
|
|
143
|
+
return await self._queue.get()
|