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,521 @@
|
|
|
1
|
+
# Copyright (c) Huawei Technologies Co., Ltd. 2026. All rights reserved.
|
|
2
|
+
|
|
3
|
+
"""Component migrations into the user settings document.
|
|
4
|
+
|
|
5
|
+
Importing an external legacy format is tracked in the ``migrations:`` ledger,
|
|
6
|
+
never inferred from the document's existence: a crash between "wrote the YAML"
|
|
7
|
+
and "cleaned the old source" must retry the cleanup on the next start, and a
|
|
8
|
+
user who pre-created ``settings.yaml`` by hand has not thereby migrated
|
|
9
|
+
anything. Each component entry is either a completion timestamp or
|
|
10
|
+
``{pending_cleanup: true}``.
|
|
11
|
+
|
|
12
|
+
Every migration is strictly three-phase, holding at most one configuration
|
|
13
|
+
lock at any moment:
|
|
14
|
+
|
|
15
|
+
- **A** (settings lock): read the old source, coerce, merge and commit with
|
|
16
|
+
``pending_cleanup: true``.
|
|
17
|
+
- **B** (the old source's own lock, never the settings lock): retire the old
|
|
18
|
+
source. Nesting ``.env.lock`` inside the settings lock is a deadlock waiting
|
|
19
|
+
for its second process, so cross-file consistency comes from the resumable
|
|
20
|
+
ledger, not from lock nesting.
|
|
21
|
+
- **C** (settings lock again): replace ``pending_cleanup`` with the
|
|
22
|
+
completion timestamp. A crash before C reruns B, which is idempotent.
|
|
23
|
+
|
|
24
|
+
Which side wins the merge depends on the ledger, and the two answers are not
|
|
25
|
+
in tension:
|
|
26
|
+
|
|
27
|
+
- While the component is **unfinished** — no entry, or ``pending_cleanup`` —
|
|
28
|
+
the document wins. A rerun after a crash between phases must not roll a
|
|
29
|
+
later panel edit back to the old file.
|
|
30
|
+
- Once it is **complete**, an old source that is active again became active
|
|
31
|
+
*after* we finished, and the only thing that writes these formats now is a
|
|
32
|
+
downgraded install that cannot see the document. That makes it the newer
|
|
33
|
+
intent: it wins, and the component reopens to retire it again. Importing it
|
|
34
|
+
under the document-wins rule instead would delete the newer value and keep
|
|
35
|
+
the stale one, and skipping it would leave a legacy layer outranking every
|
|
36
|
+
panel write for good — the exact "I changed it and nothing happened" these
|
|
37
|
+
migrations exist to end.
|
|
38
|
+
|
|
39
|
+
Phase B never retires a source it cannot prove is the one phase A read, and
|
|
40
|
+
never on a read that did not succeed. The two are separate guarantees:
|
|
41
|
+
|
|
42
|
+
- *Same bytes.* The retirement is gated on a fingerprint taken before the
|
|
43
|
+
parse and rechecked under the source's own lock. A source that moved in
|
|
44
|
+
between digests as its older self, so the recheck fails and the component
|
|
45
|
+
stays pending for the next start to fold in and retry.
|
|
46
|
+
- *A real read.* Cleanup removes the whole key space, not the keys that were
|
|
47
|
+
found, so "this source holds nothing of ours" and "this source could not be
|
|
48
|
+
read" must not arrive here as the same empty mapping. An unreadable source
|
|
49
|
+
aborts the migration before anything is written or deleted.
|
|
50
|
+
|
|
51
|
+
:func:`migrate_renamed_theme` is not an import and needs none of this: it
|
|
52
|
+
rewrites one value inside the document, in one phase under the one lock.
|
|
53
|
+
"""
|
|
54
|
+
|
|
55
|
+
from __future__ import annotations
|
|
56
|
+
|
|
57
|
+
import logging
|
|
58
|
+
from dataclasses import dataclass
|
|
59
|
+
from datetime import UTC, datetime
|
|
60
|
+
from pathlib import Path
|
|
61
|
+
from typing import Any
|
|
62
|
+
|
|
63
|
+
from chrys.foundation.config.coercion import Coerced, CoerceStatus
|
|
64
|
+
from chrys.foundation.config.env_file import config_env_path, update_env_file
|
|
65
|
+
from chrys.foundation.config.env_layers import (
|
|
66
|
+
canonical_env_name,
|
|
67
|
+
dotenv_disabled,
|
|
68
|
+
process_env_snapshot,
|
|
69
|
+
read_dotenv_snapshot,
|
|
70
|
+
)
|
|
71
|
+
from chrys.foundation.config.notification_events import NotificationEvent
|
|
72
|
+
from chrys.foundation.config.settings import RENAMED_THEMES, Settings
|
|
73
|
+
from chrys.foundation.config.settings_store import SettingsWarning
|
|
74
|
+
from chrys.foundation.config.spec import SettingOrigin, SettingSpec, Source, kind_accepts, specs_by_field
|
|
75
|
+
from chrys.foundation.config.user_settings import apply_settings_patch, flatten_user_doc, user_settings_path
|
|
76
|
+
from chrys.foundation.config.yaml_store import (
|
|
77
|
+
LOCK_TIMEOUT_SECONDS,
|
|
78
|
+
backup_path_for,
|
|
79
|
+
lock_path_for,
|
|
80
|
+
read_yaml_doc,
|
|
81
|
+
read_yaml_document,
|
|
82
|
+
update_yaml_doc,
|
|
83
|
+
)
|
|
84
|
+
from chrys.foundation.platform.files import file_fingerprint
|
|
85
|
+
from chrys.foundation.util.lock import FileLock
|
|
86
|
+
|
|
87
|
+
logger = logging.getLogger(__name__)
|
|
88
|
+
|
|
89
|
+
DOTENV_COMPONENT = "dotenv_v0"
|
|
90
|
+
NOTIFICATIONS_COMPONENT = "notifications_v0"
|
|
91
|
+
|
|
92
|
+
_DEFERRED_CLEANUP = "Legacy %s changed while it was being migrated; %s stays pending for the next start: %s"
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
class _AlreadyComplete(Exception):
|
|
96
|
+
"""Raised inside the mutator so the document is not rewritten per boot."""
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
@dataclass(frozen=True, slots=True)
|
|
100
|
+
class MigrationResult:
|
|
101
|
+
"""What one migration run moved, and what it had to leave behind."""
|
|
102
|
+
|
|
103
|
+
migrated: dict[str, Any]
|
|
104
|
+
warnings: tuple[SettingsWarning, ...]
|
|
105
|
+
performed: bool
|
|
106
|
+
"""``False`` when the ledger said the work was already done."""
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
def migrate_dotenv_v0() -> MigrationResult:
|
|
110
|
+
"""Move the chrys keys out of ``~/.chrys/.env`` into ``settings.yaml``.
|
|
111
|
+
|
|
112
|
+
Left in place, a legacy ``CHRYS_THEME`` line keeps loading as the
|
|
113
|
+
``USER_ENV`` layer and silently outranks every panel write — "I changed it
|
|
114
|
+
and nothing happened". So the values move to the document and the lines
|
|
115
|
+
go, in the three phases described in the module docstring.
|
|
116
|
+
|
|
117
|
+
Reading is two-step because the two ends speak different grammars (the
|
|
118
|
+
alias's ``env_coerce`` first, then the key's own ``coerce`` on the
|
|
119
|
+
canonical result): ``CHRYS_HISTORY_DISABLE=1`` means *disable*, and a
|
|
120
|
+
one-step read through the positive-polarity key coercer would migrate it
|
|
121
|
+
as ``history.prompt.enabled: true`` — flipping the user's setting in the
|
|
122
|
+
act of preserving it. The second step keeps migration from being the one
|
|
123
|
+
channel that can write a value into the YAML no panel could.
|
|
124
|
+
|
|
125
|
+
Values interpolate against the bootstrap snapshot, exactly as the
|
|
126
|
+
``USER_ENV`` layer would have resolved them: migration writes what the
|
|
127
|
+
loader would have loaded.
|
|
128
|
+
"""
|
|
129
|
+
if dotenv_disabled():
|
|
130
|
+
# The opt-out has to reach this too, and not only because the values
|
|
131
|
+
# would be unreadable: phase B *deletes* the lines it migrated, so
|
|
132
|
+
# running with the file disabled would empty a file the user told us
|
|
133
|
+
# not to read and move its values somewhere the opt-out cannot reach.
|
|
134
|
+
# Nothing is marked complete, so a later ordinary launch migrates.
|
|
135
|
+
return MigrationResult(migrated={}, warnings=(), performed=False)
|
|
136
|
+
|
|
137
|
+
env_path = config_env_path()
|
|
138
|
+
snapshot = process_env_snapshot()
|
|
139
|
+
base = snapshot.values if snapshot is not None else {}
|
|
140
|
+
specs = specs_by_field(Settings)
|
|
141
|
+
aliases = {canonical_env_name(entry.env): entry for entry in specs.values() if entry.env is not None}
|
|
142
|
+
known_keys = frozenset(entry.key for entry in specs.values())
|
|
143
|
+
|
|
144
|
+
# Read before the settings lock is taken, and unconditionally — ahead of
|
|
145
|
+
# the ledger — because a completed component can only notice that its
|
|
146
|
+
# source came back by looking. The parsed values and the digest come from
|
|
147
|
+
# one snapshot: cleanup deletes every alias regardless of what was found,
|
|
148
|
+
# so "nothing to import" and "could not read it" must not look alike.
|
|
149
|
+
snapshot = read_dotenv_snapshot(env_path, base=base)
|
|
150
|
+
if snapshot is None:
|
|
151
|
+
# The file is there and unreadable. Nothing is imported, nothing is
|
|
152
|
+
# deleted, and the ledger is untouched, so the next start tries again.
|
|
153
|
+
return MigrationResult(migrated={}, warnings=(), performed=False)
|
|
154
|
+
fingerprint = snapshot.fingerprint
|
|
155
|
+
candidates: dict[str, tuple[SettingSpec, str]] = {}
|
|
156
|
+
for env_name, value in snapshot.values.items():
|
|
157
|
+
spec_entry = aliases.get(canonical_env_name(env_name))
|
|
158
|
+
if spec_entry is not None:
|
|
159
|
+
# Later spellings win a fold collision, same as the loader.
|
|
160
|
+
candidates[spec_entry.key] = (spec_entry, value)
|
|
161
|
+
|
|
162
|
+
# Whether a line said anything is the coercer's call, not the string's:
|
|
163
|
+
# for most keys an empty assignment is silence, but ``CHRYS_HISTORY_DISABLE=``
|
|
164
|
+
# reads as "not 1" and imports as *enabled*. Both the completion guard and
|
|
165
|
+
# phase B's retirement must hear a line exactly the way fold-in does, or a
|
|
166
|
+
# speaking-empty line migrates yet survives — and, sitting in the higher
|
|
167
|
+
# USER_ENV layer, shadows the very document it was folded into.
|
|
168
|
+
speaking = frozenset(
|
|
169
|
+
key
|
|
170
|
+
for key, (spec_entry, value) in candidates.items()
|
|
171
|
+
if (spec_entry.env_coerce or spec_entry.coerce)(value).status is not CoerceStatus.MISSING
|
|
172
|
+
)
|
|
173
|
+
|
|
174
|
+
migrated: dict[str, Any] = {}
|
|
175
|
+
warnings: list[SettingsWarning] = []
|
|
176
|
+
origin = SettingOrigin(layer=Source.USER_ENV, path=env_path)
|
|
177
|
+
|
|
178
|
+
def fold_in(doc: dict[str, Any]) -> dict[str, Any]:
|
|
179
|
+
entry = _ledger_entry(doc, DOTENV_COMPONENT)
|
|
180
|
+
completed = entry is not None and not _pending_cleanup(entry)
|
|
181
|
+
if completed and not speaking:
|
|
182
|
+
# Presence is not reappearance here: ``.env`` outlives the
|
|
183
|
+
# migration on purpose, still carrying the SDK variables — and the
|
|
184
|
+
# lines phase B deliberately left behind, which say nothing and so
|
|
185
|
+
# are not somebody writing here again either.
|
|
186
|
+
raise _AlreadyComplete
|
|
187
|
+
document_wins = not completed and _document_is_newer(entry, fingerprint)
|
|
188
|
+
migrated.clear()
|
|
189
|
+
warnings.clear()
|
|
190
|
+
|
|
191
|
+
existing, _ = flatten_user_doc(doc, known_keys)
|
|
192
|
+
for key, (spec_entry, value) in candidates.items():
|
|
193
|
+
if key in existing and document_wins:
|
|
194
|
+
# A rerun after a crash between phases must not roll a later
|
|
195
|
+
# panel edit back to the old file. Once the source has moved
|
|
196
|
+
# since we imported from it — or the component has completed —
|
|
197
|
+
# the reverse holds; see the module docstring.
|
|
198
|
+
#
|
|
199
|
+
# Logged because phase B then deletes the line: without this the
|
|
200
|
+
# legacy value and every trace of it having existed disappear in
|
|
201
|
+
# the same run, and the only remaining evidence of the disagreement
|
|
202
|
+
# is a document that quietly does not say what the file said. The
|
|
203
|
+
# value itself stays out of the log — the key names the setting
|
|
204
|
+
# well enough to explain the outcome.
|
|
205
|
+
logger.info(
|
|
206
|
+
"Settings document already sets %s; dropping the legacy %s in %s",
|
|
207
|
+
key,
|
|
208
|
+
spec_entry.env or key,
|
|
209
|
+
env_path,
|
|
210
|
+
)
|
|
211
|
+
continue
|
|
212
|
+
first = (spec_entry.env_coerce or spec_entry.coerce)(value)
|
|
213
|
+
if first.status is CoerceStatus.MISSING:
|
|
214
|
+
continue
|
|
215
|
+
if first.status is CoerceStatus.INVALID:
|
|
216
|
+
warnings.append(SettingsWarning(key=key, origin=origin, outcome=first))
|
|
217
|
+
continue
|
|
218
|
+
if first.status is CoerceStatus.CLAMPED:
|
|
219
|
+
warnings.append(SettingsWarning(key=key, origin=origin, outcome=first))
|
|
220
|
+
second = spec_entry.coerce(first.value)
|
|
221
|
+
if second.status is CoerceStatus.MISSING and kind_accepts(spec_entry.kind, first.value):
|
|
222
|
+
# The first step already produced the field's own canonical
|
|
223
|
+
# value, and a coercer reads a canonical "unset" — ``None`` for
|
|
224
|
+
# an ``OPTIONAL_INT`` — as "say nothing" rather than as the
|
|
225
|
+
# value it is. Re-coercing it would drop the very setting being
|
|
226
|
+
# migrated: ``CHRYS_ASK_USER_TIMEOUT_SECONDS=0`` means *no
|
|
227
|
+
# timeout*, and the second read turns that into silence while
|
|
228
|
+
# phase B deletes the line that said it.
|
|
229
|
+
second = Coerced(status=CoerceStatus.VALID, value=first.value)
|
|
230
|
+
if second.status is not CoerceStatus.VALID:
|
|
231
|
+
warnings.append(SettingsWarning(key=key, origin=origin, outcome=second))
|
|
232
|
+
continue
|
|
233
|
+
migrated[key] = second.value
|
|
234
|
+
|
|
235
|
+
apply_settings_patch(doc, migrated)
|
|
236
|
+
_set_ledger(doc, DOTENV_COMPONENT, _pending(fingerprint))
|
|
237
|
+
return doc
|
|
238
|
+
|
|
239
|
+
try:
|
|
240
|
+
update_yaml_doc(user_settings_path(), fold_in)
|
|
241
|
+
except _AlreadyComplete:
|
|
242
|
+
return MigrationResult(migrated={}, warnings=(), performed=False)
|
|
243
|
+
|
|
244
|
+
result = MigrationResult(migrated=dict(migrated), warnings=tuple(warnings), performed=True)
|
|
245
|
+
|
|
246
|
+
# Phase B. The existence check keeps a fresh install from growing an empty
|
|
247
|
+
# ``.env``. Everything else — a file that raced in, changed, or stopped
|
|
248
|
+
# being readable since phase A — fails the fingerprint inside the file's
|
|
249
|
+
# own lock, and the component stays pending so the next start folds in
|
|
250
|
+
# what changed before retiring anything.
|
|
251
|
+
#
|
|
252
|
+
# Only the lines this read actually heard a value on are removed. A line
|
|
253
|
+
# that resolved to nothing was imported from nowhere, so deleting it would
|
|
254
|
+
# be the one thing this migration must never do — destroy the only
|
|
255
|
+
# remaining record of a setting. That is not hypothetical: cross-file
|
|
256
|
+
# ``${VAR}`` references no longer resolve, and such a line reads as empty
|
|
257
|
+
# here while still being the user's writing.
|
|
258
|
+
retired = sorted(
|
|
259
|
+
canonical_env_name(spec_entry.env)
|
|
260
|
+
for key, (spec_entry, _) in candidates.items()
|
|
261
|
+
if key in speaking and spec_entry.env is not None
|
|
262
|
+
)
|
|
263
|
+
if env_path.is_file() and retired:
|
|
264
|
+
removed = fingerprint is not None and update_env_file(
|
|
265
|
+
{},
|
|
266
|
+
remove_keys=retired,
|
|
267
|
+
expect_fingerprint=fingerprint,
|
|
268
|
+
)
|
|
269
|
+
if not removed:
|
|
270
|
+
logger.warning(_DEFERRED_CLEANUP, "dotenv", DOTENV_COMPONENT, env_path)
|
|
271
|
+
return result
|
|
272
|
+
|
|
273
|
+
update_yaml_doc(user_settings_path(), _mark_complete(DOTENV_COMPONENT))
|
|
274
|
+
return result
|
|
275
|
+
|
|
276
|
+
|
|
277
|
+
_LEGACY_NOTIFICATION_FIELDS: dict[str, str] = {
|
|
278
|
+
"enabled": "notifications.enabled",
|
|
279
|
+
"desktop": "notifications.delivery.desktop",
|
|
280
|
+
"sound": "notifications.delivery.sound",
|
|
281
|
+
"suppress_when_focused": "notifications.suppress_when_focused",
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
|
|
285
|
+
def _all_notification_keys() -> tuple[str, ...]:
|
|
286
|
+
"""Every settings key the retired ``notifications.yaml`` could speak for."""
|
|
287
|
+
return (
|
|
288
|
+
*_LEGACY_NOTIFICATION_FIELDS.values(),
|
|
289
|
+
*(f"notifications.events.{event.value}" for event in NotificationEvent),
|
|
290
|
+
)
|
|
291
|
+
|
|
292
|
+
|
|
293
|
+
def _legacy_notifications_path() -> Path:
|
|
294
|
+
from chrys.foundation.platform import get_platform
|
|
295
|
+
|
|
296
|
+
return get_platform().config_dir / "notifications.yaml"
|
|
297
|
+
|
|
298
|
+
|
|
299
|
+
def migrate_notifications_v0() -> MigrationResult:
|
|
300
|
+
"""Fold ``notifications.yaml`` into the ``notifications.*`` settings keys.
|
|
301
|
+
|
|
302
|
+
The legacy loader's reading was ``bool(value)`` per present field with
|
|
303
|
+
missing fields defaulting on, and that is reproduced here so migration
|
|
304
|
+
writes what the old reader would have read. Every written value is a
|
|
305
|
+
canonical bool, so nothing enters the document that a panel could not
|
|
306
|
+
write. Unknown event names and stray fields are dropped, as they always
|
|
307
|
+
were; ``schema_version`` belongs to the retired format.
|
|
308
|
+
"""
|
|
309
|
+
legacy_path = _legacy_notifications_path()
|
|
310
|
+
# Read under the legacy file's own lock *before* taking the settings lock:
|
|
311
|
+
# migrations hold at most one configuration lock at any moment. Once the
|
|
312
|
+
# component completes, the rename below makes this a cheap miss per boot.
|
|
313
|
+
# The fingerprint comes out of the same call rather than from a digest
|
|
314
|
+
# taken beside it: this read repairs a corrupt primary from its backup, so
|
|
315
|
+
# a digest taken before it describes a file that no longer exists and one
|
|
316
|
+
# taken after it races the read it is supposed to describe.
|
|
317
|
+
read = read_yaml_document(legacy_path)
|
|
318
|
+
legacy_doc, fingerprint = read.doc, read.fingerprint
|
|
319
|
+
|
|
320
|
+
candidates: dict[str, bool] = {}
|
|
321
|
+
if legacy_doc is not None:
|
|
322
|
+
for field_name, key in _LEGACY_NOTIFICATION_FIELDS.items():
|
|
323
|
+
if field_name in legacy_doc:
|
|
324
|
+
candidates[key] = bool(legacy_doc[field_name])
|
|
325
|
+
events = legacy_doc.get("events")
|
|
326
|
+
if isinstance(events, dict):
|
|
327
|
+
for raw_name, value in events.items():
|
|
328
|
+
try:
|
|
329
|
+
event = NotificationEvent(str(raw_name))
|
|
330
|
+
except ValueError:
|
|
331
|
+
continue
|
|
332
|
+
candidates[f"notifications.events.{event.value}"] = bool(value)
|
|
333
|
+
# What the old reader would have reported for the whole feature, which is
|
|
334
|
+
# not the same list: it defaulted every absent field to on, so this format
|
|
335
|
+
# has no way to say "unset" and a partial file still describes a complete
|
|
336
|
+
# state. That only matters once the component has completed and the file
|
|
337
|
+
# came back — then the file *is* the newer state and has to replace the
|
|
338
|
+
# document wholesale, or a field the returning writer never mentioned keeps
|
|
339
|
+
# a value the user's old build is not showing them. Before completion the
|
|
340
|
+
# sparse list is the right one: filling in defaults there would overwrite
|
|
341
|
+
# panel edits with "on" for every field the legacy file happens to omit.
|
|
342
|
+
# (``.env`` needs no such distinction — absent keys there really are unset,
|
|
343
|
+
# and fall through to the layers below.)
|
|
344
|
+
complete_state = dict.fromkeys(_all_notification_keys(), True) | candidates
|
|
345
|
+
|
|
346
|
+
known_keys = frozenset(entry.key for entry in specs_by_field(Settings).values())
|
|
347
|
+
migrated: dict[str, Any] = {}
|
|
348
|
+
|
|
349
|
+
def fold_in(doc: dict[str, Any]) -> dict[str, Any]:
|
|
350
|
+
entry = _ledger_entry(doc, NOTIFICATIONS_COMPONENT)
|
|
351
|
+
completed = entry is not None and not _pending_cleanup(entry)
|
|
352
|
+
if completed and legacy_doc is None:
|
|
353
|
+
# Presence *is* reappearance here, unlike ``.env``: this file has
|
|
354
|
+
# no role left once the component completes, because completing it
|
|
355
|
+
# renamed the file away. Anything back at this path was written by
|
|
356
|
+
# something that does not know the document exists.
|
|
357
|
+
raise _AlreadyComplete
|
|
358
|
+
document_wins = not completed and _document_is_newer(entry, fingerprint)
|
|
359
|
+
migrated.clear()
|
|
360
|
+
existing, _ = flatten_user_doc(doc, known_keys)
|
|
361
|
+
for key, value in (complete_state if completed else candidates).items():
|
|
362
|
+
if key in existing and document_wins:
|
|
363
|
+
# The document's value is newer: a rerun after a crash between
|
|
364
|
+
# phases must not roll a later panel edit back to the old file.
|
|
365
|
+
# Past completion the reverse holds — see the module docstring.
|
|
366
|
+
# Logged for the same reason as its dotenv twin: phase B retires
|
|
367
|
+
# the file, so this is the last moment the disagreement exists.
|
|
368
|
+
logger.info(
|
|
369
|
+
"Settings document already sets %s; dropping the legacy value in %s",
|
|
370
|
+
key,
|
|
371
|
+
legacy_path,
|
|
372
|
+
)
|
|
373
|
+
continue
|
|
374
|
+
migrated[key] = value
|
|
375
|
+
apply_settings_patch(doc, migrated)
|
|
376
|
+
_set_ledger(doc, NOTIFICATIONS_COMPONENT, _pending(fingerprint))
|
|
377
|
+
return doc
|
|
378
|
+
|
|
379
|
+
try:
|
|
380
|
+
update_yaml_doc(user_settings_path(), fold_in)
|
|
381
|
+
except _AlreadyComplete:
|
|
382
|
+
return MigrationResult(migrated={}, warnings=(), performed=False)
|
|
383
|
+
|
|
384
|
+
result = MigrationResult(migrated=dict(migrated), warnings=(), performed=True)
|
|
385
|
+
|
|
386
|
+
# Phase B: the old document is renamed, never deleted — kept for rollback
|
|
387
|
+
# and debugging. Its backup is renamed first; left behind, a crashed rerun
|
|
388
|
+
# would restore the primary from it and resurrect the file just retired —
|
|
389
|
+
# which is why the backup is retired even when the primary is already gone.
|
|
390
|
+
# Under the file's own lock and the same fingerprint gate the dotenv
|
|
391
|
+
# cleanup uses: renaming a file that changed since phase A read it carries
|
|
392
|
+
# away preferences nobody imported. They would still be recoverable from
|
|
393
|
+
# the ``.migrated`` name, which is the only reason this is not the P1 the
|
|
394
|
+
# dotenv deletion would be.
|
|
395
|
+
backup = backup_path_for(legacy_path)
|
|
396
|
+
if legacy_path.is_file() or backup.is_file():
|
|
397
|
+
with FileLock(lock_path_for(legacy_path), timeout=LOCK_TIMEOUT_SECONDS):
|
|
398
|
+
current = file_fingerprint(legacy_path)
|
|
399
|
+
# A file that is present but cannot be digested has no identity to
|
|
400
|
+
# compare against, and ``None == None`` would pass for proof that
|
|
401
|
+
# it is unchanged — retiring bytes nobody managed to read. A file
|
|
402
|
+
# that reads but does not *parse* still digests, so that case
|
|
403
|
+
# retires as it should rather than deferring forever.
|
|
404
|
+
unreadable = current is None and legacy_path.is_file()
|
|
405
|
+
if current != fingerprint or unreadable:
|
|
406
|
+
logger.warning(_DEFERRED_CLEANUP, "notifications", NOTIFICATIONS_COMPONENT, legacy_path)
|
|
407
|
+
return result
|
|
408
|
+
if backup.is_file():
|
|
409
|
+
backup.replace(backup.with_name(backup.name + ".migrated"))
|
|
410
|
+
if legacy_path.is_file():
|
|
411
|
+
legacy_path.replace(legacy_path.with_name(legacy_path.name + ".migrated"))
|
|
412
|
+
|
|
413
|
+
update_yaml_doc(user_settings_path(), _mark_complete(NOTIFICATIONS_COMPONENT))
|
|
414
|
+
return result
|
|
415
|
+
|
|
416
|
+
|
|
417
|
+
def migrate_renamed_theme() -> MigrationResult:
|
|
418
|
+
"""Rewrite a saved ``ui.theme`` that names a built-in theme by a name it no longer has.
|
|
419
|
+
|
|
420
|
+
Nothing draws wrong without this — the loader follows :data:`RENAMED_THEMES`
|
|
421
|
+
at every layer. It is here so the document says what the panel shows, and
|
|
422
|
+
still names a theme for a build that has dropped the redirect.
|
|
423
|
+
|
|
424
|
+
There is no ledger entry, because the rewrite is its own record: once the
|
|
425
|
+
old name is gone there is nothing left to do, and a downgraded install that
|
|
426
|
+
writes it back is simply renamed again. Looking before locking keeps the
|
|
427
|
+
ordinary start — nothing to rename — from needing a writable config
|
|
428
|
+
directory, which a read does not.
|
|
429
|
+
"""
|
|
430
|
+
path = user_settings_path()
|
|
431
|
+
key = specs_by_field(Settings)["theme"].key
|
|
432
|
+
done = MigrationResult(migrated={}, warnings=(), performed=False)
|
|
433
|
+
if _renamed_theme(read_yaml_doc(path), key) is None:
|
|
434
|
+
return done
|
|
435
|
+
|
|
436
|
+
migrated: dict[str, Any] = {}
|
|
437
|
+
|
|
438
|
+
def rename(doc: dict[str, Any]) -> dict[str, Any]:
|
|
439
|
+
successor = _renamed_theme(doc, key)
|
|
440
|
+
if successor is None:
|
|
441
|
+
# Another process got here between the look and the lock.
|
|
442
|
+
raise _AlreadyComplete
|
|
443
|
+
migrated[key] = successor
|
|
444
|
+
return apply_settings_patch(doc, migrated)
|
|
445
|
+
|
|
446
|
+
try:
|
|
447
|
+
update_yaml_doc(path, rename)
|
|
448
|
+
except _AlreadyComplete:
|
|
449
|
+
return done
|
|
450
|
+
return MigrationResult(migrated=dict(migrated), warnings=(), performed=True)
|
|
451
|
+
|
|
452
|
+
|
|
453
|
+
def _renamed_theme(doc: dict[str, Any] | None, key: str) -> str | None:
|
|
454
|
+
"""The name the document's theme goes by now, when it is saved under a retired one."""
|
|
455
|
+
if doc is None:
|
|
456
|
+
return None
|
|
457
|
+
saved = flatten_user_doc(doc, frozenset({key}))[0].get(key)
|
|
458
|
+
return RENAMED_THEMES.get(saved.strip()) if isinstance(saved, str) else None
|
|
459
|
+
|
|
460
|
+
|
|
461
|
+
def _mark_complete(component: str) -> Any:
|
|
462
|
+
def mutate(doc: dict[str, Any]) -> dict[str, Any]:
|
|
463
|
+
_set_ledger(doc, component, datetime.now(UTC).strftime("%Y-%m-%dT%H:%M:%SZ"))
|
|
464
|
+
return doc
|
|
465
|
+
|
|
466
|
+
return mutate
|
|
467
|
+
|
|
468
|
+
|
|
469
|
+
def _pending(fingerprint: str | None) -> dict[str, Any]:
|
|
470
|
+
"""The ledger entry for an import whose cleanup has not run yet.
|
|
471
|
+
|
|
472
|
+
It carries the digest the values were imported from, because "the document
|
|
473
|
+
is newer than the source" is only true while the source has not moved
|
|
474
|
+
since; without recording it, the two reasons a component can be pending
|
|
475
|
+
are indistinguishable. See :func:`_document_is_newer`.
|
|
476
|
+
"""
|
|
477
|
+
entry: dict[str, Any] = {"pending_cleanup": True}
|
|
478
|
+
if fingerprint is not None:
|
|
479
|
+
entry["source_fingerprint"] = fingerprint
|
|
480
|
+
return entry
|
|
481
|
+
|
|
482
|
+
|
|
483
|
+
def _document_is_newer(entry: Any, fingerprint: str | None) -> bool:
|
|
484
|
+
"""Whether the document outranks the legacy source where both hold a key.
|
|
485
|
+
|
|
486
|
+
True for a component that has never run — the document may be something
|
|
487
|
+
the user wrote by hand — and while the source still digests to what the
|
|
488
|
+
pending import read, which is the crash-between-phases case: a rerun there
|
|
489
|
+
must not roll a later panel edit back to the old file.
|
|
490
|
+
|
|
491
|
+
False once the source has changed since that import, which is exactly what
|
|
492
|
+
a *deferred* cleanup means: phase B refused because somebody wrote there
|
|
493
|
+
afterwards. Treating the document as newer then is how the value that
|
|
494
|
+
caused the deferral gets skipped on the rerun and deleted by the cleanup
|
|
495
|
+
that follows it — imported nowhere, gone for good.
|
|
496
|
+
|
|
497
|
+
A pending entry with no digest recorded reads as "unchanged". Only a build
|
|
498
|
+
that predates this could write one, and the crash-rerun reading is the one
|
|
499
|
+
that cannot lose data.
|
|
500
|
+
"""
|
|
501
|
+
if not isinstance(entry, dict):
|
|
502
|
+
return True
|
|
503
|
+
recorded = entry.get("source_fingerprint")
|
|
504
|
+
return not isinstance(recorded, str) or recorded == fingerprint
|
|
505
|
+
|
|
506
|
+
|
|
507
|
+
def _set_ledger(doc: dict[str, Any], component: str, value: Any) -> None:
|
|
508
|
+
ledger = doc.get("migrations")
|
|
509
|
+
if not isinstance(ledger, dict):
|
|
510
|
+
ledger = {}
|
|
511
|
+
doc["migrations"] = ledger
|
|
512
|
+
ledger[component] = value
|
|
513
|
+
|
|
514
|
+
|
|
515
|
+
def _ledger_entry(doc: dict[str, Any], component: str) -> Any:
|
|
516
|
+
ledger = doc.get("migrations")
|
|
517
|
+
return ledger.get(component) if isinstance(ledger, dict) else None
|
|
518
|
+
|
|
519
|
+
|
|
520
|
+
def _pending_cleanup(entry: Any) -> bool:
|
|
521
|
+
return isinstance(entry, dict) and bool(entry.get("pending_cleanup"))
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# Copyright (c) Huawei Technologies Co., Ltd. 2026. All rights reserved.
|
|
2
|
+
|
|
3
|
+
"""Notification event identity, shared by settings and the TUI delivery layer.
|
|
4
|
+
|
|
5
|
+
Pure data on purpose: the persisted ``notifications.events.*`` settings keys
|
|
6
|
+
and the app-layer delivery service must agree on one set of event names, and
|
|
7
|
+
foundation cannot import the app layer, so the enum lives here. Labels,
|
|
8
|
+
descriptions, and delivery behaviour stay in ``chrys.app.tui.notifications``.
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
from __future__ import annotations
|
|
12
|
+
|
|
13
|
+
from enum import StrEnum
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class NotificationEvent(StrEnum):
|
|
17
|
+
"""User-visible notification reasons."""
|
|
18
|
+
|
|
19
|
+
APPROVAL_REQUIRED = "approval_required"
|
|
20
|
+
ASK_USER = "ask_user"
|
|
21
|
+
TURN_COMPLETE = "turn_complete"
|
|
22
|
+
TURN_ERROR = "turn_error"
|