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,120 @@
|
|
|
1
|
+
# Copyright (c) Huawei Technologies Co., Ltd. 2026. All rights reserved.
|
|
2
|
+
|
|
3
|
+
"""Theme drafts and field-scoped, one-shot edit transactions."""
|
|
4
|
+
|
|
5
|
+
from __future__ import annotations
|
|
6
|
+
|
|
7
|
+
from dataclasses import dataclass, replace
|
|
8
|
+
from uuid import UUID, uuid4
|
|
9
|
+
|
|
10
|
+
from textual.theme import Theme
|
|
11
|
+
|
|
12
|
+
SURFACES = ("background", "surface", "panel", "boost")
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def copy_theme(theme: Theme, *, name: str | None = None) -> Theme:
|
|
16
|
+
"""Textual Theme is mutable; its variables must never be shared with drafts."""
|
|
17
|
+
return replace(theme, name=theme.name if name is None else name, variables=dict(theme.variables))
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
@dataclass(frozen=True)
|
|
21
|
+
class EditToken:
|
|
22
|
+
document: UUID
|
|
23
|
+
field: str
|
|
24
|
+
transaction: UUID
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
@dataclass
|
|
28
|
+
class EditTransaction:
|
|
29
|
+
token: EditToken
|
|
30
|
+
candidate: Theme
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
class ThemeDocument:
|
|
34
|
+
"""Opening baseline, saved baseline and history are separate concepts."""
|
|
35
|
+
|
|
36
|
+
def __init__(self, theme: Theme, *, is_new: bool = False) -> None:
|
|
37
|
+
self.is_new = is_new
|
|
38
|
+
self.id = uuid4()
|
|
39
|
+
self.original = copy_theme(theme)
|
|
40
|
+
self.saved = copy_theme(theme)
|
|
41
|
+
self.draft = copy_theme(theme)
|
|
42
|
+
self.undo_stack: list[Theme] = []
|
|
43
|
+
self.redo_stack: list[Theme] = []
|
|
44
|
+
self.transaction: EditTransaction | None = None
|
|
45
|
+
|
|
46
|
+
@property
|
|
47
|
+
def changed(self) -> bool:
|
|
48
|
+
return self.draft != self.original
|
|
49
|
+
|
|
50
|
+
@property
|
|
51
|
+
def unsaved(self) -> bool:
|
|
52
|
+
return self.is_new or self.draft != self.saved
|
|
53
|
+
|
|
54
|
+
def begin(self, field: str) -> EditToken:
|
|
55
|
+
self.cancel()
|
|
56
|
+
token = EditToken(self.id, field, uuid4())
|
|
57
|
+
self.transaction = EditTransaction(token, copy_theme(self.draft))
|
|
58
|
+
return token
|
|
59
|
+
|
|
60
|
+
def owns(self, token: EditToken) -> bool:
|
|
61
|
+
return self.transaction is not None and self.transaction.token == token
|
|
62
|
+
|
|
63
|
+
def require_transaction(self) -> EditTransaction:
|
|
64
|
+
if self.transaction is None:
|
|
65
|
+
raise RuntimeError("The theme document has no active edit transaction.")
|
|
66
|
+
return self.transaction
|
|
67
|
+
|
|
68
|
+
def stage(self, token: EditToken, value: str | None) -> Theme | None:
|
|
69
|
+
if not self.owns(token):
|
|
70
|
+
return None
|
|
71
|
+
candidate = copy_theme(self.draft)
|
|
72
|
+
kind, name = token.field.split(":", 1)
|
|
73
|
+
if kind == "color":
|
|
74
|
+
setattr(candidate, name, value)
|
|
75
|
+
elif kind == "var":
|
|
76
|
+
if value is None:
|
|
77
|
+
candidate.variables.pop(name, None)
|
|
78
|
+
else:
|
|
79
|
+
candidate.variables[name] = value
|
|
80
|
+
else:
|
|
81
|
+
raise ValueError(f"Unknown theme field: {token.field}")
|
|
82
|
+
self.transaction = EditTransaction(token, candidate)
|
|
83
|
+
return candidate
|
|
84
|
+
|
|
85
|
+
def commit(self, token: EditToken) -> bool:
|
|
86
|
+
if not self.owns(token):
|
|
87
|
+
return False
|
|
88
|
+
candidate = self.require_transaction().candidate
|
|
89
|
+
self.transaction = None
|
|
90
|
+
return self.replace(candidate)
|
|
91
|
+
|
|
92
|
+
def cancel(self) -> None:
|
|
93
|
+
self.transaction = None
|
|
94
|
+
|
|
95
|
+
def replace(self, candidate: Theme) -> bool:
|
|
96
|
+
self.cancel()
|
|
97
|
+
if candidate == self.draft:
|
|
98
|
+
return False
|
|
99
|
+
self.undo_stack.append(copy_theme(self.draft))
|
|
100
|
+
del self.undo_stack[:-100]
|
|
101
|
+
self.redo_stack.clear()
|
|
102
|
+
self.draft = copy_theme(candidate)
|
|
103
|
+
return True
|
|
104
|
+
|
|
105
|
+
def undo(self) -> None:
|
|
106
|
+
self.cancel()
|
|
107
|
+
if self.undo_stack:
|
|
108
|
+
self.redo_stack.append(self.draft)
|
|
109
|
+
self.draft = self.undo_stack.pop()
|
|
110
|
+
|
|
111
|
+
def redo(self) -> None:
|
|
112
|
+
self.cancel()
|
|
113
|
+
if self.redo_stack:
|
|
114
|
+
self.undo_stack.append(self.draft)
|
|
115
|
+
self.draft = self.redo_stack.pop()
|
|
116
|
+
|
|
117
|
+
def mark_saved(self) -> None:
|
|
118
|
+
"""A future writer calls this only after a successful atomic write."""
|
|
119
|
+
self.is_new = False
|
|
120
|
+
self.saved = copy_theme(self.draft)
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
# Copyright (c) Huawei Technologies Co., Ltd. 2026. All rights reserved.
|
|
2
|
+
|
|
3
|
+
"""Validate candidate themes without touching the running application's styles.
|
|
4
|
+
|
|
5
|
+
The adapter targets the project's pinned Textual 8.2.7. Private CSS invalidation
|
|
6
|
+
and source metadata live here; widgets only submit whole Theme snapshots. The
|
|
7
|
+
application suppresses preference writes while an editor preview is active.
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
from __future__ import annotations
|
|
11
|
+
|
|
12
|
+
from typing import TYPE_CHECKING
|
|
13
|
+
|
|
14
|
+
from textual.color import Color
|
|
15
|
+
from textual.css.stylesheet import Stylesheet, StylesheetError, StylesheetParseError
|
|
16
|
+
from textual.css.tokenizer import TokenError
|
|
17
|
+
from textual.theme import Theme
|
|
18
|
+
|
|
19
|
+
from chrys.app.tui.i18n import render_str
|
|
20
|
+
from chrys.app.tui.theme import with_tui_css_variables
|
|
21
|
+
from chrys.foundation.i18n import Localizer, msg
|
|
22
|
+
|
|
23
|
+
from .document import SURFACES, copy_theme
|
|
24
|
+
|
|
25
|
+
if TYPE_CHECKING:
|
|
26
|
+
from chrys.app.tui.app import ChrysApp
|
|
27
|
+
|
|
28
|
+
_INVALID_CSS = msg("tui.theme_editor.invalid_css", fallback="Invalid CSS value{field}: {value}")
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def theme_variables(theme: Theme, defaults: dict[str, str]) -> dict[str, str]:
|
|
32
|
+
variables = with_tui_css_variables(theme, {**defaults, **theme.to_color_system().generate(), **theme.variables})
|
|
33
|
+
return variables
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def css_error(error: Exception, localizer: Localizer | None = None) -> str:
|
|
37
|
+
if isinstance(error, StylesheetParseError):
|
|
38
|
+
# Textual's HelpText summaries embed Rich markup alongside raw user
|
|
39
|
+
# values. Build a plain diagnostic from tokens instead of interpreting
|
|
40
|
+
# that mixed string or exposing its formatting tags in a Label.
|
|
41
|
+
messages = []
|
|
42
|
+
localizer = localizer or Localizer("en")
|
|
43
|
+
for rule in error.errors.rules:
|
|
44
|
+
for token, _message in rule.errors:
|
|
45
|
+
reference = token.referenced_by
|
|
46
|
+
variable = f" (${reference.name})" if reference is not None else ""
|
|
47
|
+
messages.append(render_str(localizer, _INVALID_CSS.bind(field=variable, value=repr(token.value))))
|
|
48
|
+
return "; ".join(dict.fromkeys(messages))[:700]
|
|
49
|
+
return str(error)[:700] or type(error).__name__
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def validate_theme(theme: Theme, defaults: dict[str, str], live: Stylesheet) -> dict[str, str]:
|
|
53
|
+
"""Check only styles already in memory, without touching the live sheet.
|
|
54
|
+
|
|
55
|
+
New screen/widget styles are checked by ThemeStylesheet when loaded; the
|
|
56
|
+
preview's recovery hook keeps the previous valid theme if they reject it.
|
|
57
|
+
Never scan or parse application/library source files to open the editor.
|
|
58
|
+
"""
|
|
59
|
+
for name in SURFACES:
|
|
60
|
+
value = getattr(theme, name)
|
|
61
|
+
if value is not None and Color.parse(value).a != 1:
|
|
62
|
+
# TextArea's Rich fallback may consume Theme.surface directly,
|
|
63
|
+
# outside CSS parsing. Keep the editor's existing opaque-surface policy.
|
|
64
|
+
raise ValueError(f"{name} requires an opaque color")
|
|
65
|
+
variables = theme_variables(theme, defaults)
|
|
66
|
+
probe = Stylesheet(variables=variables)
|
|
67
|
+
probe.source.update(live.source)
|
|
68
|
+
probe.parse()
|
|
69
|
+
return variables
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
class ThemePreview:
|
|
73
|
+
"""Last-valid publication with bounded history for newly discovered CSS."""
|
|
74
|
+
|
|
75
|
+
def __init__(self, app: ChrysApp) -> None:
|
|
76
|
+
self.app = app
|
|
77
|
+
# Opening the editor adopts the already displayed theme. Revalidating
|
|
78
|
+
# and republishing it would parse all loaded CSS and restyle the entire
|
|
79
|
+
# transcript before the panel can paint, despite no theme change.
|
|
80
|
+
self.current: Theme | None = copy_theme(app.current_theme)
|
|
81
|
+
self.variables: dict[str, str] | None = app.get_css_variables().copy()
|
|
82
|
+
self.history: list[Theme] = []
|
|
83
|
+
self.baseline: Theme | None = copy_theme(app.current_theme)
|
|
84
|
+
self._error: Exception | None = None
|
|
85
|
+
self._error_field = ""
|
|
86
|
+
self.field = ""
|
|
87
|
+
|
|
88
|
+
@property
|
|
89
|
+
def error(self) -> str:
|
|
90
|
+
"""Render retained diagnostics in the active language without revalidating."""
|
|
91
|
+
if self._error is None:
|
|
92
|
+
return ""
|
|
93
|
+
diagnostic = css_error(self._error, self.app.locale_controller.localizer)
|
|
94
|
+
return f"{self._error_field}: {diagnostic}" if self._error_field else diagnostic
|
|
95
|
+
|
|
96
|
+
def checkpoint(self) -> None:
|
|
97
|
+
"""Retain the pre-gesture theme even after a long stream of drag updates."""
|
|
98
|
+
if self.current is not None:
|
|
99
|
+
self.baseline = copy_theme(self.current)
|
|
100
|
+
|
|
101
|
+
def check(self, theme: Theme, field: str = "") -> dict[str, str] | None:
|
|
102
|
+
try:
|
|
103
|
+
result = validate_theme(theme, self.app.get_theme_variable_defaults(), self.app.stylesheet)
|
|
104
|
+
except (StylesheetError, TokenError, ValueError, TypeError, AttributeError) as error:
|
|
105
|
+
self._error = error
|
|
106
|
+
self._error_field = field
|
|
107
|
+
return None
|
|
108
|
+
self._error = None
|
|
109
|
+
return result
|
|
110
|
+
|
|
111
|
+
def show(self, theme: Theme, field: str = "") -> bool:
|
|
112
|
+
if theme == self.current:
|
|
113
|
+
self._error = None
|
|
114
|
+
return True
|
|
115
|
+
variables = self.check(theme, field)
|
|
116
|
+
if variables is None:
|
|
117
|
+
return False
|
|
118
|
+
if field != self.field:
|
|
119
|
+
self.checkpoint()
|
|
120
|
+
if self.current is not None:
|
|
121
|
+
self.history.append(copy_theme(self.current))
|
|
122
|
+
del self.history[:-20]
|
|
123
|
+
self.field = field
|
|
124
|
+
self.current = copy_theme(theme)
|
|
125
|
+
self.variables = variables
|
|
126
|
+
self._refresh()
|
|
127
|
+
return True
|
|
128
|
+
|
|
129
|
+
def _refresh(self) -> None:
|
|
130
|
+
theme = self.current
|
|
131
|
+
if theme is None:
|
|
132
|
+
raise RuntimeError("Refreshing the theme preview requires a current theme.")
|
|
133
|
+
app = self.app
|
|
134
|
+
classes = {name: False for name in app.classes if name.startswith("-theme-")}
|
|
135
|
+
classes.update(
|
|
136
|
+
{
|
|
137
|
+
f"-theme-{theme.name}": True,
|
|
138
|
+
"-dark-mode": theme.dark,
|
|
139
|
+
"-light-mode": not theme.dark,
|
|
140
|
+
}
|
|
141
|
+
)
|
|
142
|
+
app.update_classes(classes, update=False)
|
|
143
|
+
app._refresh_truecolor_filter(app.ansi_theme)
|
|
144
|
+
app._invalidate_css()
|
|
145
|
+
app.refresh_css(animate=False)
|
|
146
|
+
app.theme_changed_signal.publish(theme)
|
|
147
|
+
|
|
148
|
+
def recover(self, stylesheet: Stylesheet, error: Exception) -> bool:
|
|
149
|
+
"""A lazily introduced style rejects the candidate, without theme switching.
|
|
150
|
+
|
|
151
|
+
Ordinary application syntax errors still propagate: none of the previous
|
|
152
|
+
themes can make them valid. Never delegate an editing failure to Chrys's
|
|
153
|
+
production fallback-to-chrys behavior.
|
|
154
|
+
"""
|
|
155
|
+
candidates = [*reversed(self.history)]
|
|
156
|
+
if self.baseline is not None:
|
|
157
|
+
candidates.append(self.baseline)
|
|
158
|
+
for previous in candidates:
|
|
159
|
+
try:
|
|
160
|
+
variables = validate_theme(previous, self.app.get_theme_variable_defaults(), stylesheet)
|
|
161
|
+
except StylesheetError, TokenError, ValueError, TypeError, AttributeError:
|
|
162
|
+
continue
|
|
163
|
+
self._error = error
|
|
164
|
+
self._error_field = self.field
|
|
165
|
+
self.current = copy_theme(previous)
|
|
166
|
+
self.variables = variables
|
|
167
|
+
stylesheet.set_variables(variables)
|
|
168
|
+
self.app.call_next(self._refresh)
|
|
169
|
+
return True
|
|
170
|
+
return False
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
# Copyright (c) Huawei Technologies Co., Ltd. 2026. All rights reserved.
|
|
2
|
+
|
|
3
|
+
"""Validated user-theme files with atomic writes and optimistic conflict checks."""
|
|
4
|
+
|
|
5
|
+
from __future__ import annotations
|
|
6
|
+
|
|
7
|
+
import hashlib
|
|
8
|
+
from dataclasses import dataclass, fields
|
|
9
|
+
from pathlib import Path
|
|
10
|
+
|
|
11
|
+
import yaml
|
|
12
|
+
from textual.theme import Theme
|
|
13
|
+
|
|
14
|
+
from chrys.app.tui.theme_loader import (
|
|
15
|
+
_theme_from_data,
|
|
16
|
+
default_theme_directory,
|
|
17
|
+
theme_is_read_only,
|
|
18
|
+
theme_name_is_valid,
|
|
19
|
+
)
|
|
20
|
+
from chrys.foundation.i18n import MessageRef, msg
|
|
21
|
+
from chrys.foundation.platform.files import atomic_write_text
|
|
22
|
+
from chrys.foundation.util.lock import FileLock
|
|
23
|
+
|
|
24
|
+
_INVALID_NAME = msg(
|
|
25
|
+
"tui.theme_store.invalid_name", fallback="Use a short name with letters, digits, dots, dashes or underscores."
|
|
26
|
+
)
|
|
27
|
+
_READ_ONLY = msg("tui.theme_store.read_only", fallback="Built-in themes are read-only. Choose a new name.")
|
|
28
|
+
_EXISTS = msg("tui.theme_store.exists", fallback="A theme with this name already exists. Choose another name.")
|
|
29
|
+
_CONFLICT = msg(
|
|
30
|
+
"tui.theme_store.conflict", fallback="This theme changed on disk. Close the editor and reopen it before saving."
|
|
31
|
+
)
|
|
32
|
+
_IO_ERROR = msg("tui.theme_store.io_error", fallback="Could not save the theme: {reason}")
|
|
33
|
+
_LOAD_ERROR = msg("tui.theme_store.load_error", fallback="Could not open the theme: {reason}")
|
|
34
|
+
_DELETE_ERROR = msg("tui.theme_store.delete_error", fallback="Could not delete the theme: {reason}")
|
|
35
|
+
_DELETE_CONFLICT = msg(
|
|
36
|
+
"tui.theme_store.delete_conflict",
|
|
37
|
+
fallback="This theme changed on disk. Close the editor and reopen it before deleting.",
|
|
38
|
+
)
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
class ThemeStoreError(Exception):
|
|
42
|
+
"""A storage failure with a localizable display message."""
|
|
43
|
+
|
|
44
|
+
def __init__(self, display: MessageRef) -> None:
|
|
45
|
+
super().__init__(display)
|
|
46
|
+
self.display = display
|
|
47
|
+
|
|
48
|
+
@property
|
|
49
|
+
def retryable(self) -> bool:
|
|
50
|
+
"""A save IO failure may be retried without changing the document."""
|
|
51
|
+
return self.display.definition == _IO_ERROR
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
@dataclass(frozen=True)
|
|
55
|
+
class ThemeFileRevision:
|
|
56
|
+
path: Path
|
|
57
|
+
digest: str
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
def theme_data(theme: Theme) -> dict[str, object]:
|
|
61
|
+
"""Persist declared values, preserving expressions and omitted color fields."""
|
|
62
|
+
return {
|
|
63
|
+
field.name: dict(theme.variables) if field.name == "variables" else getattr(theme, field.name)
|
|
64
|
+
for field in fields(Theme)
|
|
65
|
+
if field.name != "name" and getattr(theme, field.name) is not None
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
class UserThemeStore:
|
|
70
|
+
def __init__(self, directory: Path | None = None) -> None:
|
|
71
|
+
self.directory = directory if directory is not None else default_theme_directory()
|
|
72
|
+
|
|
73
|
+
def _matches(self, name: str) -> list[Path]:
|
|
74
|
+
if not self.directory.is_dir():
|
|
75
|
+
return []
|
|
76
|
+
return sorted(
|
|
77
|
+
path
|
|
78
|
+
for path in self.directory.iterdir()
|
|
79
|
+
if path.suffix.lower() in {".yaml", ".yml"} and path.stem.casefold() == name.casefold()
|
|
80
|
+
)
|
|
81
|
+
|
|
82
|
+
def validate_name(self, name: str, revision: ThemeFileRevision | None = None) -> None:
|
|
83
|
+
# Names are filenames on every supported platform, including Windows.
|
|
84
|
+
device = name.split(".", 1)[0].upper()
|
|
85
|
+
if (
|
|
86
|
+
not theme_name_is_valid(name)
|
|
87
|
+
or len(name) > 100
|
|
88
|
+
or name.endswith(".")
|
|
89
|
+
or device
|
|
90
|
+
in {"CON", "PRN", "AUX", "NUL", *(f"COM{i}" for i in range(1, 10)), *(f"LPT{i}" for i in range(1, 10))}
|
|
91
|
+
):
|
|
92
|
+
raise ThemeStoreError(_INVALID_NAME.bind())
|
|
93
|
+
if theme_is_read_only(name):
|
|
94
|
+
raise ThemeStoreError(_READ_ONLY.bind())
|
|
95
|
+
try:
|
|
96
|
+
matches = self._matches(name)
|
|
97
|
+
except OSError as error:
|
|
98
|
+
raise ThemeStoreError(_IO_ERROR.bind(reason=str(error))) from error
|
|
99
|
+
if revision is not None:
|
|
100
|
+
if name != revision.path.stem or matches != [revision.path] or revision.path.is_symlink():
|
|
101
|
+
raise ThemeStoreError(_CONFLICT.bind())
|
|
102
|
+
elif matches:
|
|
103
|
+
raise ThemeStoreError(_EXISTS.bind())
|
|
104
|
+
|
|
105
|
+
def suggest_name(self, base: str) -> str:
|
|
106
|
+
stem = base[:85].rstrip(".") or "my-theme"
|
|
107
|
+
for index in range(1, 10000):
|
|
108
|
+
name = f"{stem}-{index}"
|
|
109
|
+
try:
|
|
110
|
+
self.validate_name(name)
|
|
111
|
+
except ThemeStoreError as error:
|
|
112
|
+
if error.display.definition == _EXISTS:
|
|
113
|
+
continue
|
|
114
|
+
raise
|
|
115
|
+
return name
|
|
116
|
+
raise ThemeStoreError(_EXISTS.bind())
|
|
117
|
+
|
|
118
|
+
def load(self, name: str) -> tuple[Theme, ThemeFileRevision]:
|
|
119
|
+
if theme_is_read_only(name):
|
|
120
|
+
raise ThemeStoreError(_READ_ONLY.bind())
|
|
121
|
+
try:
|
|
122
|
+
paths = self._matches(name)
|
|
123
|
+
if len(paths) != 1 or paths[0].is_symlink() or paths[0].stem != name:
|
|
124
|
+
raise ThemeStoreError(_CONFLICT.bind())
|
|
125
|
+
path = paths[0]
|
|
126
|
+
payload = path.read_bytes()
|
|
127
|
+
data = yaml.safe_load(payload)
|
|
128
|
+
if not isinstance(data, dict):
|
|
129
|
+
raise ValueError("Theme must contain a mapping")
|
|
130
|
+
theme = _theme_from_data(name, data, path)
|
|
131
|
+
return theme, ThemeFileRevision(path, hashlib.sha256(payload).hexdigest())
|
|
132
|
+
except ThemeStoreError:
|
|
133
|
+
raise
|
|
134
|
+
except Exception as error:
|
|
135
|
+
raise ThemeStoreError(_LOAD_ERROR.bind(reason=str(error))) from error
|
|
136
|
+
|
|
137
|
+
def save(self, theme: Theme, revision: ThemeFileRevision | None) -> ThemeFileRevision:
|
|
138
|
+
"""Call off the UI thread, after complete CSS preview validation."""
|
|
139
|
+
try:
|
|
140
|
+
self.directory.mkdir(parents=True, exist_ok=True)
|
|
141
|
+
with FileLock(self.directory / ".themes.lock", timeout=3):
|
|
142
|
+
self.validate_name(theme.name, revision)
|
|
143
|
+
path = revision.path if revision is not None else self.directory / f"{theme.name}.yaml"
|
|
144
|
+
if revision is not None and hashlib.sha256(path.read_bytes()).hexdigest() != revision.digest:
|
|
145
|
+
raise ThemeStoreError(_CONFLICT.bind())
|
|
146
|
+
data = theme_data(theme)
|
|
147
|
+
_theme_from_data(theme.name, data, path)
|
|
148
|
+
payload = yaml.safe_dump(data, sort_keys=False, allow_unicode=True)
|
|
149
|
+
written = atomic_write_text(path, payload)
|
|
150
|
+
return ThemeFileRevision(path, hashlib.sha256(written).hexdigest())
|
|
151
|
+
except ThemeStoreError:
|
|
152
|
+
raise
|
|
153
|
+
except Exception as error:
|
|
154
|
+
raise ThemeStoreError(_IO_ERROR.bind(reason=str(error))) from error
|
|
155
|
+
|
|
156
|
+
def delete(self, name: str, revision: ThemeFileRevision) -> None:
|
|
157
|
+
"""Remove only the user file the editor opened, under the save lock."""
|
|
158
|
+
if theme_is_read_only(name):
|
|
159
|
+
raise ThemeStoreError(_READ_ONLY.bind())
|
|
160
|
+
try:
|
|
161
|
+
with FileLock(self.directory / ".themes.lock", timeout=3):
|
|
162
|
+
if (
|
|
163
|
+
not theme_name_is_valid(name)
|
|
164
|
+
or revision.path.stem != name
|
|
165
|
+
or self._matches(name) != [revision.path]
|
|
166
|
+
or revision.path.is_symlink()
|
|
167
|
+
or hashlib.sha256(revision.path.read_bytes()).hexdigest() != revision.digest
|
|
168
|
+
):
|
|
169
|
+
raise ThemeStoreError(_DELETE_CONFLICT.bind())
|
|
170
|
+
revision.path.unlink()
|
|
171
|
+
except ThemeStoreError:
|
|
172
|
+
raise
|
|
173
|
+
except FileNotFoundError as error:
|
|
174
|
+
raise ThemeStoreError(_DELETE_CONFLICT.bind()) from error
|
|
175
|
+
except Exception as error:
|
|
176
|
+
raise ThemeStoreError(_DELETE_ERROR.bind(reason=str(error))) from error
|
chrys/app/tui/toasts.py
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
# Copyright (c) Huawei Technologies Co., Ltd. 2026. All rights reserved.
|
|
2
|
+
|
|
3
|
+
"""Toasts under the header, the newest on top.
|
|
4
|
+
|
|
5
|
+
Textual appends each new toast under the older ones and scrolls its rack to
|
|
6
|
+
the end, which stacks a bottom-docked rack upward from the newest toast.
|
|
7
|
+
Chrys docks the rack under the header instead (``chrys.tcss``), so the stack
|
|
8
|
+
grows downward: new toasts mount ahead of the older ones and the rack keeps
|
|
9
|
+
its start in view.
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
from __future__ import annotations
|
|
13
|
+
|
|
14
|
+
from typing import TYPE_CHECKING
|
|
15
|
+
|
|
16
|
+
from textual.app import ScreenStackError
|
|
17
|
+
from textual.css.query import NoMatches
|
|
18
|
+
from textual.widgets._toast import Toast, ToastHolder, ToastRack
|
|
19
|
+
|
|
20
|
+
if TYPE_CHECKING:
|
|
21
|
+
from textual.app import App
|
|
22
|
+
from textual.notifications import Notification, Notifications
|
|
23
|
+
|
|
24
|
+
TEXTUAL_TOAST_RACK_FORK_VERSION = "8.2.7"
|
|
25
|
+
"""The Textual release whose private ``App._refresh_notifications`` and ``ToastRack.show`` this mirrors."""
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def refresh_newest_first(app: App[object]) -> None:
|
|
29
|
+
"""``App._refresh_notifications`` showing the current screen's rack newest first."""
|
|
30
|
+
try:
|
|
31
|
+
screen = app.screen
|
|
32
|
+
except ScreenStackError:
|
|
33
|
+
return
|
|
34
|
+
try:
|
|
35
|
+
rack = screen.get_child_by_type(ToastRack)
|
|
36
|
+
except NoMatches:
|
|
37
|
+
return
|
|
38
|
+
app.call_later(show_newest_first, rack, app._notifications)
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def show_newest_first(rack: ToastRack, notifications: Notifications) -> None:
|
|
42
|
+
"""``ToastRack.show`` with the newest toast on top.
|
|
43
|
+
|
|
44
|
+
The only intentional delta from Textual's version: new toasts mount ahead
|
|
45
|
+
of the toasts already racked, and the rack scrolls to its start.
|
|
46
|
+
"""
|
|
47
|
+
rack.display = bool(notifications)
|
|
48
|
+
for toast in rack.query(Toast):
|
|
49
|
+
if toast._notification not in notifications:
|
|
50
|
+
toast.remove()
|
|
51
|
+
|
|
52
|
+
new_toasts: list[Notification] = []
|
|
53
|
+
for notification in notifications:
|
|
54
|
+
try:
|
|
55
|
+
rack.get_child_by_id(rack._toast_id(notification))
|
|
56
|
+
except NoMatches:
|
|
57
|
+
if not notification.has_expired:
|
|
58
|
+
new_toasts.append(notification)
|
|
59
|
+
|
|
60
|
+
if new_toasts:
|
|
61
|
+
# Notifications iterate oldest first; the newest goes in first so it lands on top.
|
|
62
|
+
rack.mount_all(
|
|
63
|
+
[
|
|
64
|
+
ToastHolder(Toast(notification), id=rack._toast_id(notification))
|
|
65
|
+
for notification in reversed(new_toasts)
|
|
66
|
+
],
|
|
67
|
+
before=0,
|
|
68
|
+
)
|
|
69
|
+
rack.call_later(rack.scroll_home, animate=False, force=True)
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
# Copyright (c) Huawei Technologies Co., Ltd. 2026. All rights reserved.
|
|
2
|
+
|
|
3
|
+
"""Shared context-pressure explanations for chat and nested agent transcripts."""
|
|
4
|
+
|
|
5
|
+
from __future__ import annotations
|
|
6
|
+
|
|
7
|
+
from chrys.foundation.i18n import MessageDef, MessageRef, msg
|
|
8
|
+
|
|
9
|
+
_CONTEXT_PRESSURE_CONVERSATION = msg(
|
|
10
|
+
"tui.context_pressure.conversation.generic",
|
|
11
|
+
fallback="Conversation context compaction stopped because {reason}. The active task may exceed its model window.",
|
|
12
|
+
)
|
|
13
|
+
_CONTEXT_PRESSURE_SUB_AGENT = msg(
|
|
14
|
+
"tui.context_pressure.sub_agent.generic",
|
|
15
|
+
fallback="Sub-agent context compaction stopped because {reason}. The active task may exceed its model window.",
|
|
16
|
+
)
|
|
17
|
+
_CONTEXT_PRESSURE_CONVERSATION_INTERNAL_LIMIT = msg(
|
|
18
|
+
"tui.context_pressure.conversation.internal_limit",
|
|
19
|
+
fallback=(
|
|
20
|
+
"Conversation context compaction stopped because an internal safety limit was reached. "
|
|
21
|
+
"The active task may exceed its model window."
|
|
22
|
+
),
|
|
23
|
+
)
|
|
24
|
+
_CONTEXT_PRESSURE_SUB_AGENT_INTERNAL_LIMIT = msg(
|
|
25
|
+
"tui.context_pressure.sub_agent.internal_limit",
|
|
26
|
+
fallback=(
|
|
27
|
+
"Sub-agent context compaction stopped because an internal safety limit was reached. "
|
|
28
|
+
"The active task may exceed its model window."
|
|
29
|
+
),
|
|
30
|
+
)
|
|
31
|
+
_CONTEXT_PRESSURE_CONVERSATION_DISABLED = msg(
|
|
32
|
+
"tui.context_pressure.conversation.disabled",
|
|
33
|
+
fallback=(
|
|
34
|
+
"Conversation context compaction stopped because the compaction breaker was already disabled. "
|
|
35
|
+
"The active task may exceed its model window."
|
|
36
|
+
),
|
|
37
|
+
)
|
|
38
|
+
_CONTEXT_PRESSURE_SUB_AGENT_DISABLED = msg(
|
|
39
|
+
"tui.context_pressure.sub_agent.disabled",
|
|
40
|
+
fallback=(
|
|
41
|
+
"Sub-agent context compaction stopped because the compaction breaker was already disabled. "
|
|
42
|
+
"The active task may exceed its model window."
|
|
43
|
+
),
|
|
44
|
+
)
|
|
45
|
+
_CONTEXT_PRESSURE_CONVERSATION_GENERATION_FAILURE = msg(
|
|
46
|
+
"tui.context_pressure.conversation.generation_failure",
|
|
47
|
+
fallback=(
|
|
48
|
+
"Conversation context compaction stopped because progress-note generation failed repeatedly. "
|
|
49
|
+
"The active task may exceed its model window."
|
|
50
|
+
),
|
|
51
|
+
)
|
|
52
|
+
_CONTEXT_PRESSURE_SUB_AGENT_GENERATION_FAILURE = msg(
|
|
53
|
+
"tui.context_pressure.sub_agent.generation_failure",
|
|
54
|
+
fallback=(
|
|
55
|
+
"Sub-agent context compaction stopped because progress-note generation failed repeatedly. "
|
|
56
|
+
"The active task may exceed its model window."
|
|
57
|
+
),
|
|
58
|
+
)
|
|
59
|
+
_CONTEXT_PRESSURE_CONVERSATION_NO_PROGRESS = msg(
|
|
60
|
+
"tui.context_pressure.conversation.no_progress",
|
|
61
|
+
fallback=(
|
|
62
|
+
"Conversation context compaction stopped because repeated compaction attempts made insufficient progress. "
|
|
63
|
+
"The active task may exceed its model window."
|
|
64
|
+
),
|
|
65
|
+
)
|
|
66
|
+
_CONTEXT_PRESSURE_SUB_AGENT_NO_PROGRESS = msg(
|
|
67
|
+
"tui.context_pressure.sub_agent.no_progress",
|
|
68
|
+
fallback=(
|
|
69
|
+
"Sub-agent context compaction stopped because repeated compaction attempts made insufficient progress. "
|
|
70
|
+
"The active task may exceed its model window."
|
|
71
|
+
),
|
|
72
|
+
)
|
|
73
|
+
_CONTEXT_PRESSURE_CONVERSATION_ROUND_LIMIT = msg(
|
|
74
|
+
"tui.context_pressure.conversation.round_limit",
|
|
75
|
+
fallback=(
|
|
76
|
+
"Conversation context compaction stopped because the compaction attempt limit was reached. "
|
|
77
|
+
"The active task may exceed its model window."
|
|
78
|
+
),
|
|
79
|
+
)
|
|
80
|
+
_CONTEXT_PRESSURE_SUB_AGENT_ROUND_LIMIT = msg(
|
|
81
|
+
"tui.context_pressure.sub_agent.round_limit",
|
|
82
|
+
fallback=(
|
|
83
|
+
"Sub-agent context compaction stopped because the compaction attempt limit was reached. "
|
|
84
|
+
"The active task may exceed its model window."
|
|
85
|
+
),
|
|
86
|
+
)
|
|
87
|
+
_CONTEXT_PRESSURE_CONVERSATION_SIDE_CALL_BUDGET = msg(
|
|
88
|
+
"tui.context_pressure.conversation.side_call_budget",
|
|
89
|
+
fallback=(
|
|
90
|
+
"Conversation context compaction stopped because the progress-note token budget was exhausted. "
|
|
91
|
+
"The active task may exceed its model window."
|
|
92
|
+
),
|
|
93
|
+
)
|
|
94
|
+
_CONTEXT_PRESSURE_SUB_AGENT_SIDE_CALL_BUDGET = msg(
|
|
95
|
+
"tui.context_pressure.sub_agent.side_call_budget",
|
|
96
|
+
fallback=(
|
|
97
|
+
"Sub-agent context compaction stopped because the progress-note token budget was exhausted. "
|
|
98
|
+
"The active task may exceed its model window."
|
|
99
|
+
),
|
|
100
|
+
)
|
|
101
|
+
_CONTEXT_PRESSURE_CONVERSATION_SPILL_ABORT = msg(
|
|
102
|
+
"tui.context_pressure.conversation.spill_abort",
|
|
103
|
+
fallback=(
|
|
104
|
+
"Conversation context compaction stopped because dropped-call storage could not be durably checkpointed. "
|
|
105
|
+
"The active task may exceed its model window."
|
|
106
|
+
),
|
|
107
|
+
)
|
|
108
|
+
_CONTEXT_PRESSURE_SUB_AGENT_SPILL_ABORT = msg(
|
|
109
|
+
"tui.context_pressure.sub_agent.spill_abort",
|
|
110
|
+
fallback=(
|
|
111
|
+
"Sub-agent context compaction stopped because dropped-call storage could not be durably checkpointed. "
|
|
112
|
+
"The active task may exceed its model window."
|
|
113
|
+
),
|
|
114
|
+
)
|
|
115
|
+
|
|
116
|
+
_CONTEXT_PRESSURE_MESSAGES: dict[tuple[str, str], MessageDef] = {
|
|
117
|
+
("main", "disabled"): _CONTEXT_PRESSURE_CONVERSATION_DISABLED,
|
|
118
|
+
("sub_agent", "disabled"): _CONTEXT_PRESSURE_SUB_AGENT_DISABLED,
|
|
119
|
+
("main", "generation_failure"): _CONTEXT_PRESSURE_CONVERSATION_GENERATION_FAILURE,
|
|
120
|
+
("sub_agent", "generation_failure"): _CONTEXT_PRESSURE_SUB_AGENT_GENERATION_FAILURE,
|
|
121
|
+
("main", "no_progress"): _CONTEXT_PRESSURE_CONVERSATION_NO_PROGRESS,
|
|
122
|
+
("sub_agent", "no_progress"): _CONTEXT_PRESSURE_SUB_AGENT_NO_PROGRESS,
|
|
123
|
+
("main", "round_limit"): _CONTEXT_PRESSURE_CONVERSATION_ROUND_LIMIT,
|
|
124
|
+
("sub_agent", "round_limit"): _CONTEXT_PRESSURE_SUB_AGENT_ROUND_LIMIT,
|
|
125
|
+
("main", "side_call_budget"): _CONTEXT_PRESSURE_CONVERSATION_SIDE_CALL_BUDGET,
|
|
126
|
+
("sub_agent", "side_call_budget"): _CONTEXT_PRESSURE_SUB_AGENT_SIDE_CALL_BUDGET,
|
|
127
|
+
("main", "spill_abort"): _CONTEXT_PRESSURE_CONVERSATION_SPILL_ABORT,
|
|
128
|
+
("sub_agent", "spill_abort"): _CONTEXT_PRESSURE_SUB_AGENT_SPILL_ABORT,
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
def context_pressure_message(reason: str, *, source: str = "main") -> MessageRef:
|
|
133
|
+
"""Keep the reason-specific warning identical across transcript surfaces."""
|
|
134
|
+
source = "sub_agent" if source == "sub_agent" else "main"
|
|
135
|
+
definition = _CONTEXT_PRESSURE_MESSAGES.get((source, reason))
|
|
136
|
+
if definition is not None:
|
|
137
|
+
return definition.bind()
|
|
138
|
+
if reason:
|
|
139
|
+
definition = _CONTEXT_PRESSURE_SUB_AGENT if source == "sub_agent" else _CONTEXT_PRESSURE_CONVERSATION
|
|
140
|
+
return definition.bind(reason=reason.replace("_", " "))
|
|
141
|
+
definition = (
|
|
142
|
+
_CONTEXT_PRESSURE_SUB_AGENT_INTERNAL_LIMIT
|
|
143
|
+
if source == "sub_agent"
|
|
144
|
+
else _CONTEXT_PRESSURE_CONVERSATION_INTERNAL_LIMIT
|
|
145
|
+
)
|
|
146
|
+
return definition.bind()
|