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,556 @@
|
|
|
1
|
+
# Copyright (c) Huawei Technologies Co., Ltd. 2026. All rights reserved.
|
|
2
|
+
|
|
3
|
+
"""Cross-platform detection — OS, architecture, shell, paths.
|
|
4
|
+
|
|
5
|
+
Provides a cached ``get_platform()`` singleton that any module can import
|
|
6
|
+
for lightweight platform checks without needing ``SessionEnvironment``.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from __future__ import annotations
|
|
10
|
+
|
|
11
|
+
import ctypes
|
|
12
|
+
import functools
|
|
13
|
+
import os
|
|
14
|
+
import platform
|
|
15
|
+
import shutil
|
|
16
|
+
from ctypes import wintypes
|
|
17
|
+
from dataclasses import dataclass
|
|
18
|
+
from pathlib import Path
|
|
19
|
+
from typing import Any, cast
|
|
20
|
+
|
|
21
|
+
from chrys.foundation.platform.c_api import declare_functions
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
@dataclass(frozen=True)
|
|
25
|
+
class ShellInfo:
|
|
26
|
+
"""Detected shell information."""
|
|
27
|
+
|
|
28
|
+
name: str # e.g. "bash", "zsh", "pwsh", "powershell", "cmd"
|
|
29
|
+
path: str # e.g. "/bin/bash", "C:\\Windows\\System32\\cmd.exe"
|
|
30
|
+
args: list[str] # e.g. ["-c"] for bash, ["-Command"] for pwsh/powershell
|
|
31
|
+
version: str = "" # e.g. "7.5.0", "5.1.22621.4391"
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
@dataclass(frozen=True)
|
|
35
|
+
class PlatformInfo:
|
|
36
|
+
"""Detected platform information."""
|
|
37
|
+
|
|
38
|
+
os_name: str # "windows", "macos", "linux"
|
|
39
|
+
os_version: str # marketing version: "15.4.1" (macOS), "11" (Win), "22.04" (Ubuntu)
|
|
40
|
+
arch: str # "arm64", "amd64", "x86", or raw machine string
|
|
41
|
+
shell: ShellInfo
|
|
42
|
+
config_dir: Path # ~/.chrys or %APPDATA%/chrys
|
|
43
|
+
data_dir: Path # same as config_dir for now
|
|
44
|
+
extra_shells: tuple[ShellInfo, ...] = () # additional shells (e.g. Git Bash on Windows)
|
|
45
|
+
|
|
46
|
+
# --- OS convenience properties ---
|
|
47
|
+
|
|
48
|
+
@property
|
|
49
|
+
def is_windows(self) -> bool:
|
|
50
|
+
return self.os_name == "windows"
|
|
51
|
+
|
|
52
|
+
@property
|
|
53
|
+
def is_macos(self) -> bool:
|
|
54
|
+
return self.os_name == "macos"
|
|
55
|
+
|
|
56
|
+
@property
|
|
57
|
+
def is_linux(self) -> bool:
|
|
58
|
+
return self.os_name == "linux"
|
|
59
|
+
|
|
60
|
+
@property
|
|
61
|
+
def os_display(self) -> str:
|
|
62
|
+
"""Human-friendly OS name (``"macOS"`` / ``"Windows"`` / ``"Linux"``)."""
|
|
63
|
+
return {"macos": "macOS", "windows": "Windows", "linux": "Linux"}.get(self.os_name, self.os_name.title())
|
|
64
|
+
|
|
65
|
+
@property
|
|
66
|
+
def display_label(self) -> str:
|
|
67
|
+
"""Short ``"macOS-arm64"``-style label for headers and status UIs."""
|
|
68
|
+
return f"{self.os_display}-{self.arch}" if self.arch else self.os_display
|
|
69
|
+
|
|
70
|
+
# --- Architecture convenience properties ---
|
|
71
|
+
|
|
72
|
+
@property
|
|
73
|
+
def is_arm64(self) -> bool:
|
|
74
|
+
return self.arch == "arm64"
|
|
75
|
+
|
|
76
|
+
@property
|
|
77
|
+
def is_amd64(self) -> bool:
|
|
78
|
+
return self.arch == "amd64"
|
|
79
|
+
|
|
80
|
+
@property
|
|
81
|
+
def is_x86(self) -> bool:
|
|
82
|
+
return self.arch == "x86"
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
def _detect_arch() -> str:
|
|
86
|
+
"""Detect CPU architecture, normalized to common names."""
|
|
87
|
+
machine = platform.machine().lower()
|
|
88
|
+
if machine in ("aarch64", "arm64"):
|
|
89
|
+
return "arm64"
|
|
90
|
+
if machine in ("x86_64", "amd64"):
|
|
91
|
+
return "amd64"
|
|
92
|
+
if machine in ("i386", "i686", "x86"):
|
|
93
|
+
return "x86"
|
|
94
|
+
return machine # fallback to raw value
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
def _detect_os_version(system: str) -> str:
|
|
98
|
+
"""Detect the user-facing OS version (marketing version, not kernel release).
|
|
99
|
+
|
|
100
|
+
On macOS, ``platform.release()`` returns the Darwin kernel release
|
|
101
|
+
(e.g. ``"25.4.0"``) — not the macOS version users recognize. This
|
|
102
|
+
helper picks the right per-OS source for a human-meaningful version
|
|
103
|
+
string and falls back to ``platform.release()`` if the preferred
|
|
104
|
+
source is unavailable.
|
|
105
|
+
|
|
106
|
+
Args:
|
|
107
|
+
system: Lowercased ``platform.system()`` value
|
|
108
|
+
(``"darwin"`` / ``"windows"`` / ``"linux"``).
|
|
109
|
+
"""
|
|
110
|
+
try:
|
|
111
|
+
if system == "darwin":
|
|
112
|
+
return platform.mac_ver()[0] or platform.release()
|
|
113
|
+
if system == "windows":
|
|
114
|
+
win = platform.win32_ver()
|
|
115
|
+
return win[1] or win[0] or platform.release()
|
|
116
|
+
if system == "linux":
|
|
117
|
+
try:
|
|
118
|
+
info = platform.freedesktop_os_release()
|
|
119
|
+
except OSError, AttributeError:
|
|
120
|
+
return platform.release()
|
|
121
|
+
return info.get("VERSION_ID") or info.get("VERSION", "") or platform.release()
|
|
122
|
+
except Exception:
|
|
123
|
+
pass
|
|
124
|
+
return platform.release()
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
def detect_platform() -> PlatformInfo:
|
|
128
|
+
"""Detect the current platform and return unified info."""
|
|
129
|
+
system = platform.system().lower()
|
|
130
|
+
arch = _detect_arch()
|
|
131
|
+
os_version = _detect_os_version(system)
|
|
132
|
+
|
|
133
|
+
extra_shells: tuple[ShellInfo, ...] = ()
|
|
134
|
+
|
|
135
|
+
if system == "windows":
|
|
136
|
+
from concurrent.futures import ThreadPoolExecutor
|
|
137
|
+
|
|
138
|
+
os_name = "windows"
|
|
139
|
+
config_dir = Path(os.environ.get("APPDATA", Path.home() / "AppData" / "Roaming")) / "chrys"
|
|
140
|
+
# Detect default shell and Git Bash in parallel
|
|
141
|
+
with ThreadPoolExecutor(max_workers=2) as pool:
|
|
142
|
+
shell_future = pool.submit(_detect_windows_shell)
|
|
143
|
+
git_bash_future = pool.submit(_detect_git_bash)
|
|
144
|
+
shell = shell_future.result()
|
|
145
|
+
git_bash = git_bash_future.result()
|
|
146
|
+
if git_bash is not None:
|
|
147
|
+
extra_shells = (git_bash,)
|
|
148
|
+
elif system == "darwin":
|
|
149
|
+
os_name = "macos"
|
|
150
|
+
shell = _detect_unix_shell()
|
|
151
|
+
config_dir = Path.home() / ".chrys"
|
|
152
|
+
else:
|
|
153
|
+
os_name = "linux"
|
|
154
|
+
shell = _detect_unix_shell()
|
|
155
|
+
config_dir = Path.home() / ".chrys"
|
|
156
|
+
|
|
157
|
+
return PlatformInfo(
|
|
158
|
+
os_name=os_name,
|
|
159
|
+
arch=arch,
|
|
160
|
+
shell=shell,
|
|
161
|
+
config_dir=config_dir,
|
|
162
|
+
data_dir=config_dir,
|
|
163
|
+
extra_shells=extra_shells,
|
|
164
|
+
os_version=os_version,
|
|
165
|
+
)
|
|
166
|
+
|
|
167
|
+
|
|
168
|
+
@functools.cache
|
|
169
|
+
def get_platform() -> PlatformInfo:
|
|
170
|
+
"""Cached platform singleton — safe to call from any module."""
|
|
171
|
+
return detect_platform()
|
|
172
|
+
|
|
173
|
+
|
|
174
|
+
def safe_getcwd() -> str:
|
|
175
|
+
"""Return the current working directory, falling back to ``~`` if it no longer exists."""
|
|
176
|
+
try:
|
|
177
|
+
return os.getcwd()
|
|
178
|
+
except OSError:
|
|
179
|
+
return os.path.expanduser("~")
|
|
180
|
+
|
|
181
|
+
|
|
182
|
+
CF_UNICODETEXT = 13
|
|
183
|
+
GMEM_MOVEABLE = 0x0002
|
|
184
|
+
|
|
185
|
+
|
|
186
|
+
@dataclass(frozen=True)
|
|
187
|
+
class _Win32ClipboardAPI:
|
|
188
|
+
"""Typed handles for the lazily loaded Win32 clipboard libraries."""
|
|
189
|
+
|
|
190
|
+
user32: ctypes.CDLL
|
|
191
|
+
kernel32: ctypes.CDLL
|
|
192
|
+
|
|
193
|
+
|
|
194
|
+
@functools.lru_cache(maxsize=1)
|
|
195
|
+
def _win32_clipboard_api() -> _Win32ClipboardAPI:
|
|
196
|
+
"""Load user32/kernel32 once and pin argtypes/restype for clipboard calls.
|
|
197
|
+
|
|
198
|
+
Cached so the per-call overhead is one dict lookup. Lazily constructed so
|
|
199
|
+
non-Windows platforms never touch ``ctypes.WinDLL``.
|
|
200
|
+
"""
|
|
201
|
+
windows_ctypes = cast(Any, ctypes)
|
|
202
|
+
user32 = windows_ctypes.WinDLL("user32", use_last_error=True)
|
|
203
|
+
kernel32 = windows_ctypes.WinDLL("kernel32", use_last_error=True)
|
|
204
|
+
declare_functions(
|
|
205
|
+
user32,
|
|
206
|
+
{
|
|
207
|
+
"OpenClipboard": (wintypes.BOOL, [wintypes.HWND]),
|
|
208
|
+
"CloseClipboard": (wintypes.BOOL, []),
|
|
209
|
+
"EmptyClipboard": (wintypes.BOOL, []),
|
|
210
|
+
"IsClipboardFormatAvailable": (wintypes.BOOL, [wintypes.UINT]),
|
|
211
|
+
"GetClipboardData": (wintypes.HANDLE, [wintypes.UINT]),
|
|
212
|
+
"SetClipboardData": (wintypes.HANDLE, [wintypes.UINT, wintypes.HANDLE]),
|
|
213
|
+
},
|
|
214
|
+
)
|
|
215
|
+
declare_functions(
|
|
216
|
+
kernel32,
|
|
217
|
+
{
|
|
218
|
+
"GlobalAlloc": (wintypes.HGLOBAL, [wintypes.UINT, ctypes.c_size_t]),
|
|
219
|
+
"GlobalLock": (wintypes.LPVOID, [wintypes.HGLOBAL]),
|
|
220
|
+
"GlobalUnlock": (wintypes.BOOL, [wintypes.HGLOBAL]),
|
|
221
|
+
"GlobalFree": (wintypes.HGLOBAL, [wintypes.HGLOBAL]),
|
|
222
|
+
},
|
|
223
|
+
)
|
|
224
|
+
return _Win32ClipboardAPI(user32=user32, kernel32=kernel32)
|
|
225
|
+
|
|
226
|
+
|
|
227
|
+
def _win32_error() -> OSError:
|
|
228
|
+
"""Build an OSError from the Win32 thread-local error state."""
|
|
229
|
+
windows_ctypes = cast(Any, ctypes)
|
|
230
|
+
return windows_ctypes.WinError(windows_ctypes.get_last_error())
|
|
231
|
+
|
|
232
|
+
|
|
233
|
+
def _open_clipboard_with_retry(api: _Win32ClipboardAPI, attempts: int = 5, delay: float = 0.01) -> None:
|
|
234
|
+
"""Acquire the clipboard. Retries on transient ERROR_ACCESS_DENIED."""
|
|
235
|
+
import time
|
|
236
|
+
|
|
237
|
+
for i in range(attempts):
|
|
238
|
+
if api.user32.OpenClipboard(None):
|
|
239
|
+
return
|
|
240
|
+
if i == attempts - 1:
|
|
241
|
+
raise _win32_error()
|
|
242
|
+
time.sleep(delay)
|
|
243
|
+
|
|
244
|
+
|
|
245
|
+
def _clipboard_copy_windows(text: str) -> None:
|
|
246
|
+
# Direct Win32 SetClipboardData(CF_UNICODETEXT, ...) — no subprocess, no
|
|
247
|
+
# codepage ambiguity, no UTF-16 BOM leaking into the clipboard payload
|
|
248
|
+
# (which is what ``clip.exe`` does, leaving a U+FEFF on every paste).
|
|
249
|
+
api = _win32_clipboard_api()
|
|
250
|
+
user32, kernel32 = api.user32, api.kernel32
|
|
251
|
+
|
|
252
|
+
data = text.encode("utf-16-le") + b"\x00\x00" # CF_UNICODETEXT requires NUL-terminated UTF-16-LE
|
|
253
|
+
h = kernel32.GlobalAlloc(GMEM_MOVEABLE, len(data))
|
|
254
|
+
if not h:
|
|
255
|
+
raise _win32_error()
|
|
256
|
+
try:
|
|
257
|
+
ptr = kernel32.GlobalLock(h)
|
|
258
|
+
if not ptr:
|
|
259
|
+
raise _win32_error()
|
|
260
|
+
ctypes.memmove(ptr, data, len(data))
|
|
261
|
+
kernel32.GlobalUnlock(h)
|
|
262
|
+
|
|
263
|
+
_open_clipboard_with_retry(api)
|
|
264
|
+
try:
|
|
265
|
+
user32.EmptyClipboard()
|
|
266
|
+
if not user32.SetClipboardData(CF_UNICODETEXT, h):
|
|
267
|
+
raise _win32_error()
|
|
268
|
+
h = None # ownership transferred to the clipboard
|
|
269
|
+
finally:
|
|
270
|
+
user32.CloseClipboard()
|
|
271
|
+
finally:
|
|
272
|
+
if h:
|
|
273
|
+
kernel32.GlobalFree(h)
|
|
274
|
+
|
|
275
|
+
|
|
276
|
+
def clipboard_copy(text: str) -> None:
|
|
277
|
+
"""Copy text to system clipboard (cross-platform)."""
|
|
278
|
+
import contextlib
|
|
279
|
+
import subprocess
|
|
280
|
+
|
|
281
|
+
with contextlib.suppress(subprocess.SubprocessError, FileNotFoundError, OSError):
|
|
282
|
+
info = get_platform()
|
|
283
|
+
if info.is_macos:
|
|
284
|
+
subprocess.run(["pbcopy"], input=text.encode(), check=True, timeout=2)
|
|
285
|
+
elif info.is_windows:
|
|
286
|
+
_clipboard_copy_windows(text)
|
|
287
|
+
else:
|
|
288
|
+
for cmd in (["xclip", "-selection", "clipboard"], ["xsel", "--clipboard", "--input"]):
|
|
289
|
+
try:
|
|
290
|
+
subprocess.run(cmd, input=text.encode(), check=True, timeout=2)
|
|
291
|
+
return
|
|
292
|
+
except FileNotFoundError:
|
|
293
|
+
continue
|
|
294
|
+
|
|
295
|
+
|
|
296
|
+
def _clipboard_paste_windows() -> str:
|
|
297
|
+
# Direct Win32 GetClipboardData(CF_UNICODETEXT). Mirrors
|
|
298
|
+
# ``_clipboard_copy_windows`` and avoids PowerShell's trailing-newline
|
|
299
|
+
# quirk and codepage-dependent stdout decoding.
|
|
300
|
+
api = _win32_clipboard_api()
|
|
301
|
+
user32, kernel32 = api.user32, api.kernel32
|
|
302
|
+
|
|
303
|
+
if not user32.IsClipboardFormatAvailable(CF_UNICODETEXT):
|
|
304
|
+
return ""
|
|
305
|
+
|
|
306
|
+
_open_clipboard_with_retry(api)
|
|
307
|
+
try:
|
|
308
|
+
h = user32.GetClipboardData(CF_UNICODETEXT)
|
|
309
|
+
if not h:
|
|
310
|
+
return ""
|
|
311
|
+
ptr = kernel32.GlobalLock(h)
|
|
312
|
+
if not ptr:
|
|
313
|
+
return ""
|
|
314
|
+
try:
|
|
315
|
+
# CF_UNICODETEXT is NUL-terminated UTF-16-LE; wstring_at follows the NUL.
|
|
316
|
+
return ctypes.wstring_at(ptr)
|
|
317
|
+
finally:
|
|
318
|
+
kernel32.GlobalUnlock(h)
|
|
319
|
+
# Don't GlobalFree — the handle is owned by the clipboard, not us.
|
|
320
|
+
finally:
|
|
321
|
+
user32.CloseClipboard()
|
|
322
|
+
|
|
323
|
+
|
|
324
|
+
def clipboard_paste() -> str:
|
|
325
|
+
"""Read text from system clipboard (cross-platform)."""
|
|
326
|
+
import subprocess
|
|
327
|
+
|
|
328
|
+
from chrys.foundation.platform.process import decode_subprocess_output
|
|
329
|
+
|
|
330
|
+
try:
|
|
331
|
+
info = get_platform()
|
|
332
|
+
if info.is_macos:
|
|
333
|
+
r = subprocess.run(["pbpaste"], stdin=subprocess.DEVNULL, capture_output=True, check=True, timeout=2)
|
|
334
|
+
return decode_subprocess_output(r.stdout)
|
|
335
|
+
if info.is_windows:
|
|
336
|
+
return _clipboard_paste_windows()
|
|
337
|
+
for cmd in (["xclip", "-selection", "clipboard", "-o"], ["xsel", "--clipboard", "--output"]):
|
|
338
|
+
try:
|
|
339
|
+
r = subprocess.run(cmd, stdin=subprocess.DEVNULL, capture_output=True, check=True, timeout=2)
|
|
340
|
+
return decode_subprocess_output(r.stdout)
|
|
341
|
+
except FileNotFoundError:
|
|
342
|
+
continue
|
|
343
|
+
except subprocess.SubprocessError, FileNotFoundError, OSError:
|
|
344
|
+
pass
|
|
345
|
+
return ""
|
|
346
|
+
|
|
347
|
+
|
|
348
|
+
def _get_shell_version(shell_path: str, name: str) -> str:
|
|
349
|
+
"""Try to get the shell version string. Returns empty string on failure."""
|
|
350
|
+
import contextlib
|
|
351
|
+
import subprocess
|
|
352
|
+
|
|
353
|
+
from chrys.foundation.platform.process import windows_hidden_subprocess_kwargs
|
|
354
|
+
|
|
355
|
+
win_kwargs = windows_hidden_subprocess_kwargs()
|
|
356
|
+
|
|
357
|
+
with contextlib.suppress(subprocess.SubprocessError, FileNotFoundError, OSError):
|
|
358
|
+
if name in ("pwsh", "powershell"):
|
|
359
|
+
r = subprocess.run(
|
|
360
|
+
[shell_path, "-NoProfile", "-Command", "$PSVersionTable.PSVersion.ToString()"],
|
|
361
|
+
# Startup probe: the process stdin (the ACP protocol pipe
|
|
362
|
+
# under ACP, before its reader even starts) must not reach
|
|
363
|
+
# the child.
|
|
364
|
+
stdin=subprocess.DEVNULL,
|
|
365
|
+
capture_output=True,
|
|
366
|
+
text=True,
|
|
367
|
+
encoding="utf-8",
|
|
368
|
+
errors="replace",
|
|
369
|
+
timeout=3,
|
|
370
|
+
**win_kwargs,
|
|
371
|
+
)
|
|
372
|
+
if r.returncode == 0:
|
|
373
|
+
return r.stdout.strip()
|
|
374
|
+
elif name != "cmd":
|
|
375
|
+
r = subprocess.run(
|
|
376
|
+
[shell_path, "--version"],
|
|
377
|
+
stdin=subprocess.DEVNULL,
|
|
378
|
+
capture_output=True,
|
|
379
|
+
text=True,
|
|
380
|
+
encoding="utf-8",
|
|
381
|
+
errors="replace",
|
|
382
|
+
timeout=3,
|
|
383
|
+
**win_kwargs,
|
|
384
|
+
)
|
|
385
|
+
if r.returncode == 0:
|
|
386
|
+
# Extract version from output like "bash 5.2.37" or "zsh 5.9"
|
|
387
|
+
for token in r.stdout.strip().split():
|
|
388
|
+
if token[0:1].isdigit():
|
|
389
|
+
return token
|
|
390
|
+
return ""
|
|
391
|
+
|
|
392
|
+
|
|
393
|
+
def _is_executable_file(path: str) -> bool:
|
|
394
|
+
"""Return whether *path* points to an executable regular file."""
|
|
395
|
+
return os.path.isfile(path) and os.access(path, os.X_OK)
|
|
396
|
+
|
|
397
|
+
|
|
398
|
+
def _detect_unix_shell() -> ShellInfo:
|
|
399
|
+
"""Detect the default shell on macOS/Linux.
|
|
400
|
+
|
|
401
|
+
Prefers ``$SHELL`` if it points to an executable binary, then probes common
|
|
402
|
+
shell names via ``shutil.which()`` so we work on distros where shells live
|
|
403
|
+
in non-standard locations (NixOS, Alpine, etc.). If ``$SHELL`` is stale and
|
|
404
|
+
``PATH`` is sparse, also try common absolute locations before falling back
|
|
405
|
+
to ``/bin/sh``.
|
|
406
|
+
"""
|
|
407
|
+
shell_env = os.environ.get("SHELL")
|
|
408
|
+
if shell_env and _is_executable_file(shell_env):
|
|
409
|
+
shell_path = shell_env
|
|
410
|
+
else:
|
|
411
|
+
resolved = None
|
|
412
|
+
shell_names: list[str] = []
|
|
413
|
+
if shell_env:
|
|
414
|
+
shell_names.append(Path(shell_env).name)
|
|
415
|
+
shell_names.extend(name for name in ("bash", "sh", "zsh", "dash", "ash") if name not in shell_names)
|
|
416
|
+
for candidate in shell_names:
|
|
417
|
+
resolved = shutil.which(candidate)
|
|
418
|
+
if resolved and _is_executable_file(resolved):
|
|
419
|
+
break
|
|
420
|
+
resolved = None
|
|
421
|
+
if resolved:
|
|
422
|
+
shell_path = resolved
|
|
423
|
+
else:
|
|
424
|
+
shell_dirs = ("/bin", "/usr/bin", "/usr/local/bin")
|
|
425
|
+
candidate_names: list[str] = []
|
|
426
|
+
if shell_env:
|
|
427
|
+
candidate_names.append(Path(shell_env).name)
|
|
428
|
+
candidate_names.extend(name for name in ("bash", "zsh", "sh", "dash", "ash") if name not in candidate_names)
|
|
429
|
+
absolute_candidates = [f"{directory}/{name}" for name in candidate_names for directory in shell_dirs]
|
|
430
|
+
shell_path = next(
|
|
431
|
+
(candidate for candidate in absolute_candidates if _is_executable_file(candidate)), "/bin/sh"
|
|
432
|
+
)
|
|
433
|
+
name = Path(shell_path).name
|
|
434
|
+
version = _get_shell_version(shell_path, name)
|
|
435
|
+
return ShellInfo(name=name, path=shell_path, args=["-c"], version=version)
|
|
436
|
+
|
|
437
|
+
|
|
438
|
+
def windows_program_files_dirs() -> tuple[str, ...]:
|
|
439
|
+
"""Return candidate Program Files directories on Windows.
|
|
440
|
+
|
|
441
|
+
Uses the ``PROGRAMFILES`` / ``PROGRAMFILES(X86)`` environment variables
|
|
442
|
+
(set by Windows itself and honouring the actual system install drive).
|
|
443
|
+
If they are missing — e.g. in stripped-down environments — synthesises
|
|
444
|
+
them from ``SystemDrive`` (e.g. ``D:``) rather than assuming ``C:``.
|
|
445
|
+
"""
|
|
446
|
+
# ``os.environ`` is case-insensitive on Windows, so the canonical
|
|
447
|
+
# uppercase names work regardless of the actual env var casing.
|
|
448
|
+
dirs: list[str] = []
|
|
449
|
+
seen: set[str] = set()
|
|
450
|
+
system_drive = os.environ.get("SYSTEMDRIVE", "")
|
|
451
|
+
candidates = (
|
|
452
|
+
os.environ.get("PROGRAMFILES"),
|
|
453
|
+
os.environ.get("PROGRAMFILES(X86)"),
|
|
454
|
+
os.environ.get("PROGRAMW6432"),
|
|
455
|
+
f"{system_drive}\\Program Files" if system_drive else None,
|
|
456
|
+
f"{system_drive}\\Program Files (x86)" if system_drive else None,
|
|
457
|
+
)
|
|
458
|
+
for path in candidates:
|
|
459
|
+
if path and path not in seen:
|
|
460
|
+
seen.add(path)
|
|
461
|
+
dirs.append(path)
|
|
462
|
+
return tuple(dirs)
|
|
463
|
+
|
|
464
|
+
|
|
465
|
+
def _detect_git_bash() -> ShellInfo | None:
|
|
466
|
+
"""Detect Git Bash on Windows.
|
|
467
|
+
|
|
468
|
+
Searches common Git for Windows install paths and PATH. WSL bash is
|
|
469
|
+
excluded by checking that the resolved path contains "Git".
|
|
470
|
+
"""
|
|
471
|
+
import contextlib
|
|
472
|
+
import subprocess
|
|
473
|
+
from concurrent.futures import ThreadPoolExecutor
|
|
474
|
+
|
|
475
|
+
candidates: list[str] = []
|
|
476
|
+
|
|
477
|
+
# Known Git for Windows install paths
|
|
478
|
+
for base in windows_program_files_dirs():
|
|
479
|
+
path = os.path.join(base, "Git", "bin", "bash.exe")
|
|
480
|
+
if os.path.isfile(path):
|
|
481
|
+
candidates.append(path)
|
|
482
|
+
|
|
483
|
+
# Check PATH — only accept if path looks like Git Bash (not WSL)
|
|
484
|
+
which_bash = shutil.which("bash")
|
|
485
|
+
if which_bash and "git" in which_bash.lower():
|
|
486
|
+
candidates.append(which_bash)
|
|
487
|
+
|
|
488
|
+
if not candidates:
|
|
489
|
+
return None
|
|
490
|
+
|
|
491
|
+
bash_path = candidates[0]
|
|
492
|
+
|
|
493
|
+
# Try to get git version from the same installation
|
|
494
|
+
git_path = os.path.join(os.path.dirname(bash_path), "git.exe")
|
|
495
|
+
has_git = os.path.isfile(git_path)
|
|
496
|
+
|
|
497
|
+
def _get_git_version() -> str:
|
|
498
|
+
if not has_git:
|
|
499
|
+
return ""
|
|
500
|
+
from chrys.foundation.platform.process import windows_hidden_subprocess_kwargs
|
|
501
|
+
|
|
502
|
+
with contextlib.suppress(subprocess.SubprocessError, FileNotFoundError, OSError):
|
|
503
|
+
r = subprocess.run(
|
|
504
|
+
[git_path, "--version"],
|
|
505
|
+
# Startup probe: never hand the child the process stdin —
|
|
506
|
+
# under ACP that is the protocol pipe, and this runs before
|
|
507
|
+
# its reader starts.
|
|
508
|
+
stdin=subprocess.DEVNULL,
|
|
509
|
+
capture_output=True,
|
|
510
|
+
text=True,
|
|
511
|
+
encoding="utf-8",
|
|
512
|
+
errors="replace",
|
|
513
|
+
timeout=3,
|
|
514
|
+
**windows_hidden_subprocess_kwargs(),
|
|
515
|
+
)
|
|
516
|
+
if r.returncode == 0:
|
|
517
|
+
return r.stdout.strip()
|
|
518
|
+
return ""
|
|
519
|
+
|
|
520
|
+
# Run bash --version and git --version in parallel
|
|
521
|
+
with ThreadPoolExecutor(max_workers=2) as pool:
|
|
522
|
+
bash_ver_future = pool.submit(_get_shell_version, bash_path, "bash")
|
|
523
|
+
git_ver_future = pool.submit(_get_git_version)
|
|
524
|
+
bash_version = bash_ver_future.result()
|
|
525
|
+
git_version = git_ver_future.result()
|
|
526
|
+
|
|
527
|
+
version = f"{bash_version} ({git_version})" if bash_version and git_version else bash_version or git_version
|
|
528
|
+
return ShellInfo(name="git_bash", path=bash_path, args=["-c"], version=version)
|
|
529
|
+
|
|
530
|
+
|
|
531
|
+
def _detect_windows_shell() -> ShellInfo:
|
|
532
|
+
"""Detect the default shell on Windows.
|
|
533
|
+
|
|
534
|
+
Preference order:
|
|
535
|
+
1. ``pwsh`` (PowerShell 7+ / cross-platform) — newest, best UX
|
|
536
|
+
2. ``powershell`` (Windows PowerShell 5.1, ships with Windows)
|
|
537
|
+
3. ``cmd`` (fallback)
|
|
538
|
+
"""
|
|
539
|
+
# PowerShell 7+ (cross-platform, installed separately)
|
|
540
|
+
pwsh = shutil.which("pwsh")
|
|
541
|
+
if pwsh:
|
|
542
|
+
version = _get_shell_version(pwsh, "pwsh")
|
|
543
|
+
return ShellInfo(name="pwsh", path=pwsh, args=["-NoProfile", "-Command"], version=version)
|
|
544
|
+
# Windows PowerShell 5.1 (built-in, always at this path on modern Windows)
|
|
545
|
+
ps5 = shutil.which("powershell")
|
|
546
|
+
if ps5:
|
|
547
|
+
version = _get_shell_version(ps5, "powershell")
|
|
548
|
+
return ShellInfo(name="powershell", path=ps5, args=["-NoProfile", "-Command"], version=version)
|
|
549
|
+
# Fallback to cmd. Prefer COMSPEC; fall back to SystemRoot (Windows
|
|
550
|
+
# always sets this to the actual install path, e.g. ``D:\Windows``)
|
|
551
|
+
# before assuming the drive letter.
|
|
552
|
+
cmd = os.environ.get("COMSPEC")
|
|
553
|
+
if not cmd:
|
|
554
|
+
system_root = os.environ.get("SYSTEMROOT", r"C:\Windows")
|
|
555
|
+
cmd = os.path.join(system_root, "System32", "cmd.exe")
|
|
556
|
+
return ShellInfo(name="cmd", path=cmd, args=["/c"])
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# Copyright (c) Huawei Technologies Co., Ltd. 2026. All rights reserved.
|
|
2
|
+
|
|
3
|
+
"""Table-driven ctypes declarations for the native APIs this package loads.
|
|
4
|
+
|
|
5
|
+
ctypes passes a Python ``int`` argument of an undeclared export as a C
|
|
6
|
+
``int`` and reads its result as one, so 64-bit handles and pointers are
|
|
7
|
+
rejected or truncated. Each loader therefore lists its exports as
|
|
8
|
+
``{name: (restype, [argtypes])}``, in C prototype order, and structures list
|
|
9
|
+
their members in runs of one type, as a C declaration does, so one line
|
|
10
|
+
describes one export and a layout reads like its header.
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
from __future__ import annotations
|
|
14
|
+
|
|
15
|
+
from collections.abc import Mapping, Sequence
|
|
16
|
+
from typing import Any
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def declare_functions(library: Any, signatures: Mapping[str, tuple[Any, Sequence[Any]]]) -> None:
|
|
20
|
+
"""Pin the result and argument types of each named export of ``library``.
|
|
21
|
+
|
|
22
|
+
Each signature is ``(restype, argtypes)``; a ``None`` restype is ``void``.
|
|
23
|
+
"""
|
|
24
|
+
for name, (restype, argtypes) in signatures.items():
|
|
25
|
+
function = getattr(library, name)
|
|
26
|
+
function.restype = restype
|
|
27
|
+
function.argtypes = list(argtypes)
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def struct_fields(*runs: tuple[Any, str]) -> list[tuple[str, Any]]:
|
|
31
|
+
"""Expand ``(ctype, "name name …")`` runs into a ``_fields_`` list, in order."""
|
|
32
|
+
return [(name, ctype) for ctype, names in runs for name in names.split()]
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
# Copyright (c) Huawei Technologies Co., Ltd. 2026. All rights reserved.
|
|
2
|
+
|
|
3
|
+
"""Keep a job-control stopped child from wedging the asyncio event loop on macOS.
|
|
4
|
+
|
|
5
|
+
CPython 3.14.7 moved subprocess reaping onto the event loop thread: a per-child
|
|
6
|
+
waiter thread parks in ``waitid(P_PID, pid, WEXITED | WNOWAIT)`` and, once that
|
|
7
|
+
returns, schedules ``_reap_and_notify`` — a blocking ``waitpid(pid, 0)`` — on the
|
|
8
|
+
loop, so the reap and the returncode notification are atomic with respect to it.
|
|
9
|
+
|
|
10
|
+
Darwin returns from that ``waitid`` when the child merely *stops*: the result
|
|
11
|
+
carries ``si_code == CLD_STOPPED``, which upstream discards. The loop thread
|
|
12
|
+
then blocks in ``waitpid(pid, 0)``, which cannot return until the child exits,
|
|
13
|
+
and a stopped child does not exit on its own. The whole event loop is wedged —
|
|
14
|
+
including :func:`chrys.foundation.platform.process.wait_for_subprocess`, whose
|
|
15
|
+
stopped-process detection exists to kill exactly this child. A shell command
|
|
16
|
+
that stops (``kill -STOP $$``, or a program running its own job control) would
|
|
17
|
+
otherwise hang the entire TUI, not just the tool call.
|
|
18
|
+
|
|
19
|
+
Check the reported state in the waiter thread and schedule reaping only after
|
|
20
|
+
an exit. Keep upstream's atomic loop-thread reap and notification: reaping in
|
|
21
|
+
the waiter would free the PID while ``Process.send_signal()`` still considers
|
|
22
|
+
it live, allowing cancellation to signal an unrelated process that reused it.
|
|
23
|
+
"""
|
|
24
|
+
|
|
25
|
+
from __future__ import annotations
|
|
26
|
+
|
|
27
|
+
import logging
|
|
28
|
+
import os
|
|
29
|
+
import sys
|
|
30
|
+
import time
|
|
31
|
+
from typing import TYPE_CHECKING, Any, cast
|
|
32
|
+
|
|
33
|
+
if TYPE_CHECKING:
|
|
34
|
+
import asyncio
|
|
35
|
+
from collections.abc import Callable
|
|
36
|
+
|
|
37
|
+
logger = logging.getLogger(__name__)
|
|
38
|
+
|
|
39
|
+
_STOPPED_CHILD_POLL_INTERVAL = 0.05
|
|
40
|
+
|
|
41
|
+
_REQUIRED_ATTRIBUTES = ("_do_waitpid", "_reap", "_reap_and_notify")
|
|
42
|
+
"""Shape of the upstream implementation this shim replaces a method on.
|
|
43
|
+
|
|
44
|
+
``_reap_and_notify`` is the atomic loop-thread reap the shim must preserve: an
|
|
45
|
+
implementation without it does not hand a blocking ``waitpid`` to the loop and
|
|
46
|
+
must be left alone. ``_threads`` is deliberately absent — it is set in
|
|
47
|
+
``__init__``, so it is not visible on the class.
|
|
48
|
+
"""
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
def _do_waitpid_until_exit(
|
|
52
|
+
self: Any,
|
|
53
|
+
loop: asyncio.AbstractEventLoop,
|
|
54
|
+
expected_pid: int,
|
|
55
|
+
callback: Callable[..., object],
|
|
56
|
+
args: tuple[object, ...],
|
|
57
|
+
) -> None:
|
|
58
|
+
"""Leave the PID reserved until the loop can reap and notify atomically."""
|
|
59
|
+
# ``waitid`` and its constants are POSIX-only, and this runs on Darwin alone.
|
|
60
|
+
posix_os = cast(Any, os)
|
|
61
|
+
exited = (posix_os.CLD_EXITED, posix_os.CLD_KILLED, posix_os.CLD_DUMPED)
|
|
62
|
+
try:
|
|
63
|
+
try:
|
|
64
|
+
while True:
|
|
65
|
+
result = posix_os.waitid(posix_os.P_PID, expected_pid, posix_os.WEXITED | posix_os.WNOWAIT)
|
|
66
|
+
if result is not None and result.si_code in exited:
|
|
67
|
+
break
|
|
68
|
+
# Darwin can repeatedly report the same unconsumed stopped
|
|
69
|
+
# state. Back off in this child-owned waiter thread, never on
|
|
70
|
+
# the loop that detects and terminates stopped processes.
|
|
71
|
+
time.sleep(_STOPPED_CHILD_POLL_INTERVAL)
|
|
72
|
+
except ChildProcessError:
|
|
73
|
+
# Preserve upstream's handling of a child reaped elsewhere.
|
|
74
|
+
pass
|
|
75
|
+
if not loop.is_closed():
|
|
76
|
+
try:
|
|
77
|
+
loop.call_soon_threadsafe(self._reap_and_notify, loop, expected_pid, callback, args)
|
|
78
|
+
return
|
|
79
|
+
except RuntimeError:
|
|
80
|
+
# The loop closed between the check and the scheduling call.
|
|
81
|
+
pass
|
|
82
|
+
pid, _ = self._reap(loop, expected_pid)
|
|
83
|
+
logger.warning("Loop %r that handles pid %r is closed", loop, pid)
|
|
84
|
+
finally:
|
|
85
|
+
self._threads.pop(expected_pid, None)
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
def install_stopped_child_reap_fix() -> bool:
|
|
89
|
+
"""Apply the shim on affected platforms; report whether it was applied.
|
|
90
|
+
|
|
91
|
+
Idempotent, and a no-op wherever the upstream implementation does not have
|
|
92
|
+
the shape described in the module docstring — including every non-Darwin
|
|
93
|
+
platform and any CPython that reaps off the event loop thread already.
|
|
94
|
+
"""
|
|
95
|
+
if sys.platform != "darwin":
|
|
96
|
+
return False
|
|
97
|
+
|
|
98
|
+
from asyncio import unix_events
|
|
99
|
+
|
|
100
|
+
watcher = getattr(unix_events, "_ThreadedChildWatcher", None)
|
|
101
|
+
if watcher is None or not all(hasattr(watcher, name) for name in _REQUIRED_ATTRIBUTES):
|
|
102
|
+
return False
|
|
103
|
+
if watcher._do_waitpid is _do_waitpid_until_exit:
|
|
104
|
+
return False
|
|
105
|
+
|
|
106
|
+
watcher._do_waitpid = _do_waitpid_until_exit
|
|
107
|
+
return True
|