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,273 @@
|
|
|
1
|
+
# Copyright (c) Huawei Technologies Co., Ltd. 2026. All rights reserved.
|
|
2
|
+
|
|
3
|
+
"""The shell behind a `Terminal`: starts it, pipes the two together, and ends it."""
|
|
4
|
+
|
|
5
|
+
from __future__ import annotations
|
|
6
|
+
|
|
7
|
+
import asyncio
|
|
8
|
+
import os
|
|
9
|
+
from collections.abc import Callable
|
|
10
|
+
from contextlib import suppress
|
|
11
|
+
from dataclasses import dataclass
|
|
12
|
+
from typing import TYPE_CHECKING, Final
|
|
13
|
+
|
|
14
|
+
from textual import log
|
|
15
|
+
from textual.message import Message
|
|
16
|
+
|
|
17
|
+
from chrys import __version__
|
|
18
|
+
from chrys.app.tui.terminal._pty_backend import IS_WINDOWS
|
|
19
|
+
from chrys.app.tui.terminal.pty_process import PtyProcess, spawn_pty_process
|
|
20
|
+
from chrys.app.tui.terminal.shell_integration import ShellLaunch, prepare_shell_launch
|
|
21
|
+
from chrys.foundation.branding import APP_DISPLAY_NAME
|
|
22
|
+
from chrys.foundation.i18n import MessageRef, msg
|
|
23
|
+
from chrys.foundation.platform.runtime_paths import reorder_path_demoting_runtime
|
|
24
|
+
|
|
25
|
+
if TYPE_CHECKING:
|
|
26
|
+
from chrys.app.tui.terminal.widget import Terminal
|
|
27
|
+
|
|
28
|
+
_CLOSE_TASK_TIMEOUT: Final = 2.0
|
|
29
|
+
_DEFAULT_PTY_SIZE: Final = (80, 24)
|
|
30
|
+
|
|
31
|
+
# How the terminal we run in introduced itself to its programs. The shell is in a different
|
|
32
|
+
# terminal now, and a program that believed these would speak the outer one's private protocols
|
|
33
|
+
# to us. Apple's session variable also makes zsh announce a "restored session" on every start.
|
|
34
|
+
_OUTER_TERMINAL_VARIABLES: Final = (
|
|
35
|
+
"TERM_PROGRAM",
|
|
36
|
+
"TERM_PROGRAM_VERSION",
|
|
37
|
+
"TERM_SESSION_ID",
|
|
38
|
+
"ITERM_SESSION_ID",
|
|
39
|
+
"KITTY_WINDOW_ID",
|
|
40
|
+
"VTE_VERSION",
|
|
41
|
+
"WT_SESSION",
|
|
42
|
+
"WT_PROFILE_ID",
|
|
43
|
+
)
|
|
44
|
+
|
|
45
|
+
_SHELL_FAILED = msg("tui.terminal.shell.failed", fallback="Shell failed: {error}")
|
|
46
|
+
_SHELL_START_FAILED = msg("tui.terminal.shell.start_failed", fallback="Unable to start shell: {error}")
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
@dataclass
|
|
50
|
+
class ShellFinished(Message):
|
|
51
|
+
"""The shell process exited."""
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
def _shell_environment() -> dict[str, str]:
|
|
55
|
+
env = os.environ.copy()
|
|
56
|
+
for name in _OUTER_TERMINAL_VARIABLES:
|
|
57
|
+
env.pop(name, None)
|
|
58
|
+
env.update(
|
|
59
|
+
TERM="xterm-256color",
|
|
60
|
+
COLORTERM="truecolor",
|
|
61
|
+
CLICOLOR="1",
|
|
62
|
+
TERM_PROGRAM=APP_DISPLAY_NAME,
|
|
63
|
+
TERM_PROGRAM_VERSION=__version__,
|
|
64
|
+
# Lets a program, ours included, tell that it runs inside this app.
|
|
65
|
+
CHRYS="1",
|
|
66
|
+
# Output is decoded as UTF-8, which Python on Windows does not write unless told to.
|
|
67
|
+
PYTHONUTF8="1",
|
|
68
|
+
)
|
|
69
|
+
reorder_path_demoting_runtime(env)
|
|
70
|
+
return env
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
class Shell:
|
|
74
|
+
"""One shell process, shown in one `Terminal`."""
|
|
75
|
+
|
|
76
|
+
def __init__(
|
|
77
|
+
self,
|
|
78
|
+
terminal: Terminal,
|
|
79
|
+
working_directory: str,
|
|
80
|
+
shell_command: str = "",
|
|
81
|
+
on_error: Callable[[MessageRef], None] | None = None,
|
|
82
|
+
) -> None:
|
|
83
|
+
self.terminal = terminal
|
|
84
|
+
self.working_directory = working_directory
|
|
85
|
+
self.shell_command = shell_command or ("pwsh" if IS_WINDOWS else os.environ.get("SHELL", "sh"))
|
|
86
|
+
self.on_error = on_error
|
|
87
|
+
self._process: PtyProcess | None = None
|
|
88
|
+
self._launch: ShellLaunch | None = None
|
|
89
|
+
self._task: asyncio.Task[None] | None = None
|
|
90
|
+
self._finished = False
|
|
91
|
+
self._ready = asyncio.Event()
|
|
92
|
+
self._requested_size = _DEFAULT_PTY_SIZE
|
|
93
|
+
self._resize_lock = asyncio.Lock()
|
|
94
|
+
self._input: asyncio.Queue[str] | None = None
|
|
95
|
+
self._input_writer: asyncio.Task[None] | None = None
|
|
96
|
+
|
|
97
|
+
@property
|
|
98
|
+
def is_finished(self) -> bool:
|
|
99
|
+
return self._finished
|
|
100
|
+
|
|
101
|
+
@property
|
|
102
|
+
def pty_size(self) -> tuple[int, int] | None:
|
|
103
|
+
"""The size the shell was last told of; ``None`` while it has been told of none."""
|
|
104
|
+
return None if self._process is None else self._process.size
|
|
105
|
+
|
|
106
|
+
async def wait_for_ready(self) -> None:
|
|
107
|
+
"""Wait until the shell takes input, or has turned out never to."""
|
|
108
|
+
await self._ready.wait()
|
|
109
|
+
|
|
110
|
+
def start(self) -> None:
|
|
111
|
+
if self._task is not None:
|
|
112
|
+
raise RuntimeError("The terminal shell has already been started.")
|
|
113
|
+
self._task = asyncio.create_task(self.run(), name=repr(self))
|
|
114
|
+
|
|
115
|
+
# -- talking to the shell ----------------------------------------------------------------------
|
|
116
|
+
|
|
117
|
+
async def send(self, command: str, width: int, height: int) -> None:
|
|
118
|
+
"""Run ``command`` as if typed at the prompt of a ``width`` by ``height`` terminal."""
|
|
119
|
+
await self._ready.wait()
|
|
120
|
+
if self._process is None:
|
|
121
|
+
return
|
|
122
|
+
# The size first: a prompt drawn for another width smears when the command is echoed.
|
|
123
|
+
await self.resize(width, height)
|
|
124
|
+
await self.write(f"{command}\r")
|
|
125
|
+
|
|
126
|
+
async def interrupt(self) -> None:
|
|
127
|
+
"""Send Ctrl+C."""
|
|
128
|
+
await self.write("\x03")
|
|
129
|
+
|
|
130
|
+
async def write(self, data: str) -> None:
|
|
131
|
+
"""Type ``data`` into the shell at once."""
|
|
132
|
+
if (process := self._process) is not None:
|
|
133
|
+
await process.write(data)
|
|
134
|
+
|
|
135
|
+
async def write_input_queued(self, data: str) -> None:
|
|
136
|
+
"""Type ``data`` into the shell after whatever is already waiting.
|
|
137
|
+
|
|
138
|
+
Keys, pastes and pointer reports come faster than the shell takes them one by one. Queued,
|
|
139
|
+
everything that piled up during a write goes out as the next.
|
|
140
|
+
"""
|
|
141
|
+
if self._process is None or not data:
|
|
142
|
+
return
|
|
143
|
+
if self._input is None:
|
|
144
|
+
self._input = asyncio.Queue()
|
|
145
|
+
self._input.put_nowait(data)
|
|
146
|
+
if self._input_writer is None or self._input_writer.done():
|
|
147
|
+
self._input_writer = asyncio.create_task(self._write_queued_input(self._input))
|
|
148
|
+
|
|
149
|
+
async def _write_queued_input(self, queue: asyncio.Queue[str]) -> None:
|
|
150
|
+
while not self._finished:
|
|
151
|
+
pending = [await queue.get()]
|
|
152
|
+
# One turn of the loop lets the rest of a burst arrive.
|
|
153
|
+
await asyncio.sleep(0)
|
|
154
|
+
with suppress(asyncio.QueueEmpty):
|
|
155
|
+
while True:
|
|
156
|
+
pending.append(queue.get_nowait())
|
|
157
|
+
await self._settle_size()
|
|
158
|
+
await self.write("".join(pending))
|
|
159
|
+
|
|
160
|
+
async def _settle_size(self) -> None:
|
|
161
|
+
"""Have the shell know the terminal's size before input makes it redraw its prompt."""
|
|
162
|
+
while True:
|
|
163
|
+
size = (self.terminal.width, self.terminal.height)
|
|
164
|
+
await self.resize(*size)
|
|
165
|
+
if (self.terminal.width, self.terminal.height) == size:
|
|
166
|
+
return
|
|
167
|
+
|
|
168
|
+
async def resize(self, width: int, height: int) -> None:
|
|
169
|
+
"""Tell the shell its terminal has a new size."""
|
|
170
|
+
async with self._resize_lock:
|
|
171
|
+
size = self._positive_size(width, height)
|
|
172
|
+
if (process := self._process) is not None and process.size != size:
|
|
173
|
+
await process.resize(*size)
|
|
174
|
+
|
|
175
|
+
def _positive_size(self, width: int, height: int) -> tuple[int, int]:
|
|
176
|
+
"""The size to use: a hidden widget measures 0x0, which stands for the last real size."""
|
|
177
|
+
if width > 0 and height > 0:
|
|
178
|
+
self._requested_size = (width, height)
|
|
179
|
+
return self._requested_size
|
|
180
|
+
|
|
181
|
+
# -- life cycle --------------------------------------------------------------------------------
|
|
182
|
+
|
|
183
|
+
def terminate(self) -> None:
|
|
184
|
+
"""End the shell now. `close` also waits for it to be gone."""
|
|
185
|
+
self._stop_input_writer()
|
|
186
|
+
if self._finished:
|
|
187
|
+
return
|
|
188
|
+
if (process := self._process) is not None:
|
|
189
|
+
self._process = None
|
|
190
|
+
process.kill()
|
|
191
|
+
self._mark_finished()
|
|
192
|
+
|
|
193
|
+
async def close(self) -> None:
|
|
194
|
+
self.terminate()
|
|
195
|
+
if (task := self._task) is None:
|
|
196
|
+
return
|
|
197
|
+
try:
|
|
198
|
+
if task is not asyncio.current_task() and not task.done():
|
|
199
|
+
await asyncio.wait_for(task, timeout=_CLOSE_TASK_TIMEOUT)
|
|
200
|
+
except TimeoutError:
|
|
201
|
+
task.cancel()
|
|
202
|
+
with suppress(asyncio.CancelledError):
|
|
203
|
+
await task
|
|
204
|
+
except Exception as error:
|
|
205
|
+
log(f"shell did not close cleanly: {error!r}")
|
|
206
|
+
finally:
|
|
207
|
+
if self._task is task:
|
|
208
|
+
self._task = None
|
|
209
|
+
|
|
210
|
+
async def run(self) -> None:
|
|
211
|
+
"""Start the shell and show its output until it ends."""
|
|
212
|
+
try:
|
|
213
|
+
await self._run()
|
|
214
|
+
except Exception as error:
|
|
215
|
+
log(f"shell failed: {error!r}")
|
|
216
|
+
self._report(_SHELL_FAILED.bind(error=str(error)))
|
|
217
|
+
finally:
|
|
218
|
+
self._stop_input_writer()
|
|
219
|
+
self._mark_finished(announce=True)
|
|
220
|
+
|
|
221
|
+
async def _run(self) -> None:
|
|
222
|
+
if self._finished:
|
|
223
|
+
return
|
|
224
|
+
env = _shell_environment()
|
|
225
|
+
self._launch = launch = prepare_shell_launch(self.shell_command, env)
|
|
226
|
+
columns, lines = self._positive_size(self.terminal.width, self.terminal.height)
|
|
227
|
+
try:
|
|
228
|
+
process = await spawn_pty_process(
|
|
229
|
+
launch.argv, env=env, cwd=self.working_directory, columns=columns, lines=lines
|
|
230
|
+
)
|
|
231
|
+
except Exception as error:
|
|
232
|
+
log(f"unable to start shell: {error!r}")
|
|
233
|
+
self._report(_SHELL_START_FAILED.bind(error=str(error)))
|
|
234
|
+
return
|
|
235
|
+
try:
|
|
236
|
+
if self._finished:
|
|
237
|
+
# Terminated while it was starting.
|
|
238
|
+
process.kill()
|
|
239
|
+
return
|
|
240
|
+
self._process = process
|
|
241
|
+
self.terminal.host_repaints = process.repaints_after_resize
|
|
242
|
+
self.terminal.set_write_to_stdin(self.write_input_queued)
|
|
243
|
+
self._ready.set()
|
|
244
|
+
while output := await process.read():
|
|
245
|
+
try:
|
|
246
|
+
await self.terminal.write(output)
|
|
247
|
+
except Exception as error:
|
|
248
|
+
# One chunk the terminal chokes on must not take the shell down with it.
|
|
249
|
+
log(f"terminal rejected shell output: {error!r}")
|
|
250
|
+
finally:
|
|
251
|
+
self._process = None
|
|
252
|
+
await process.close()
|
|
253
|
+
|
|
254
|
+
def _report(self, error: MessageRef) -> None:
|
|
255
|
+
if self.on_error is not None:
|
|
256
|
+
self.on_error(error)
|
|
257
|
+
|
|
258
|
+
def _stop_input_writer(self) -> None:
|
|
259
|
+
if self._input_writer is not None:
|
|
260
|
+
self._input_writer.cancel()
|
|
261
|
+
self._input_writer = None
|
|
262
|
+
self._input = None
|
|
263
|
+
|
|
264
|
+
def _mark_finished(self, *, announce: bool = False) -> None:
|
|
265
|
+
already_finished = self._finished
|
|
266
|
+
self._finished = True
|
|
267
|
+
# Whoever waits for the shell to be ready should stop: it never will be.
|
|
268
|
+
self._ready.set()
|
|
269
|
+
if self._launch is not None:
|
|
270
|
+
self._launch.clean_up()
|
|
271
|
+
self._launch = None
|
|
272
|
+
if announce and not already_finished:
|
|
273
|
+
self.terminal.post_message(ShellFinished())
|
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
# Copyright (c) Huawei Technologies Co., Ltd. 2026. All rights reserved.
|
|
2
|
+
|
|
3
|
+
"""Getting a shell to report what it is doing.
|
|
4
|
+
|
|
5
|
+
Each supported shell is started with hooks of its own kind that print two private OSC reports,
|
|
6
|
+
which the terminal emulator turns into events: the working directory ahead of every prompt
|
|
7
|
+
(OSC 2025) and the command line about to run (OSC 2026). Payloads travel as base64, so no path or
|
|
8
|
+
command can end the sequence early. The hooks load with the shell's start-up files and echo nothing.
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
from __future__ import annotations
|
|
12
|
+
|
|
13
|
+
import os
|
|
14
|
+
import shlex
|
|
15
|
+
import shutil
|
|
16
|
+
import tempfile
|
|
17
|
+
from dataclasses import dataclass
|
|
18
|
+
from pathlib import Path, PurePath
|
|
19
|
+
|
|
20
|
+
from chrys.app.tui.terminal._pty_backend import IS_WINDOWS
|
|
21
|
+
from chrys.foundation.platform.command_line import split_windows_command_line
|
|
22
|
+
|
|
23
|
+
_POSIX_REPORTS = r"""
|
|
24
|
+
__chrys_b64() { printf "%s" "$1" | base64 | tr -d "\n"; }
|
|
25
|
+
__chrys_report() { printf "\e]%s;b64:%s\e\\" "$1" "$(__chrys_b64 "$2")"; }
|
|
26
|
+
"""
|
|
27
|
+
|
|
28
|
+
# zsh reads its start-up files from ZDOTDIR, so ours stand in for the user's and read those first.
|
|
29
|
+
# The user's .zshenv may itself move ZDOTDIR; whatever it leaves is where their .zshrc is.
|
|
30
|
+
_ZSH_ENV = """\
|
|
31
|
+
__chrys_init_dir="$ZDOTDIR"
|
|
32
|
+
ZDOTDIR={user_zdotdir}
|
|
33
|
+
[[ -f "$ZDOTDIR/.zshenv" ]] && source "$ZDOTDIR/.zshenv"
|
|
34
|
+
__chrys_user_zdotdir="$ZDOTDIR"
|
|
35
|
+
ZDOTDIR="$__chrys_init_dir"
|
|
36
|
+
unset __chrys_init_dir
|
|
37
|
+
"""
|
|
38
|
+
|
|
39
|
+
_ZSH_RC = (
|
|
40
|
+
"""\
|
|
41
|
+
ZDOTDIR="$__chrys_user_zdotdir"
|
|
42
|
+
unset __chrys_user_zdotdir
|
|
43
|
+
[[ -f "$ZDOTDIR/.zshrc" ]] && source "$ZDOTDIR/.zshrc"
|
|
44
|
+
"""
|
|
45
|
+
+ _POSIX_REPORTS
|
|
46
|
+
+ """\
|
|
47
|
+
__chrys_preexec() { __chrys_report 2026 "$1"; }
|
|
48
|
+
__chrys_precmd() { __chrys_report 2025 "$PWD"; }
|
|
49
|
+
precmd_functions+=(__chrys_precmd)
|
|
50
|
+
preexec_functions+=(__chrys_preexec)
|
|
51
|
+
"""
|
|
52
|
+
)
|
|
53
|
+
|
|
54
|
+
# bash has no preexec. Its DEBUG trap fires before every simple command, so the first one after a
|
|
55
|
+
# prompt stands for the command line, whose full text is the history entry it just became. The
|
|
56
|
+
# user's own prompt commands are simple commands too; ours bracket them, so that the trap can tell
|
|
57
|
+
# them from a command line and they still see the exit status of the last one.
|
|
58
|
+
_BASH_RC = (
|
|
59
|
+
"""\
|
|
60
|
+
[[ -f ~/.bashrc ]] && source ~/.bashrc
|
|
61
|
+
"""
|
|
62
|
+
+ _POSIX_REPORTS
|
|
63
|
+
+ """\
|
|
64
|
+
__chrys_at_prompt=false
|
|
65
|
+
__chrys_read_history() {
|
|
66
|
+
local entry pattern='^[[:space:]]*([0-9]+)[* ] (.*)$'
|
|
67
|
+
entry="$(HISTTIMEFORMAT= builtin history 1)"
|
|
68
|
+
if [[ $entry =~ $pattern ]]; then
|
|
69
|
+
__chrys_entry_number="${BASH_REMATCH[1]}" __chrys_entry_text="${BASH_REMATCH[2]}"
|
|
70
|
+
else
|
|
71
|
+
__chrys_entry_number="" __chrys_entry_text=""
|
|
72
|
+
fi
|
|
73
|
+
}
|
|
74
|
+
__chrys_preexec() {
|
|
75
|
+
[[ $BASH_COMMAND == __chrys_prompt_begin ]] && __chrys_at_prompt=false
|
|
76
|
+
[[ $__chrys_at_prompt == true ]] || return
|
|
77
|
+
__chrys_at_prompt=false
|
|
78
|
+
__chrys_read_history
|
|
79
|
+
if [[ $__chrys_entry_number != "$__chrys_prompt_number" || $__chrys_entry_text == "$BASH_COMMAND"* ]]; then
|
|
80
|
+
# A new history entry is the line just entered. So is an old one that begins with the command
|
|
81
|
+
# now starting: the line was a repeat, which the history keeps once.
|
|
82
|
+
__chrys_report 2026 "$__chrys_entry_text"
|
|
83
|
+
else
|
|
84
|
+
# Kept out of the history on purpose, or there is no history. This much of it is certain.
|
|
85
|
+
__chrys_report 2026 "$BASH_COMMAND"
|
|
86
|
+
fi
|
|
87
|
+
}
|
|
88
|
+
__chrys_prompt_begin() { return "$?"; }
|
|
89
|
+
__chrys_precmd() {
|
|
90
|
+
__chrys_report 2025 "$PWD"
|
|
91
|
+
__chrys_read_history
|
|
92
|
+
__chrys_prompt_number="$__chrys_entry_number"
|
|
93
|
+
__chrys_at_prompt=true
|
|
94
|
+
}
|
|
95
|
+
if (( BASH_VERSINFO[0] > 5 || (BASH_VERSINFO[0] == 5 && BASH_VERSINFO[1] >= 1) )); then
|
|
96
|
+
PROMPT_COMMAND=(__chrys_prompt_begin "${PROMPT_COMMAND[@]}" __chrys_precmd)
|
|
97
|
+
else
|
|
98
|
+
__chrys_theirs="${PROMPT_COMMAND%"${PROMPT_COMMAND##*[![:space:];]}"}"
|
|
99
|
+
PROMPT_COMMAND="__chrys_prompt_begin;${__chrys_theirs:+$__chrys_theirs;}__chrys_precmd"
|
|
100
|
+
unset __chrys_theirs
|
|
101
|
+
fi
|
|
102
|
+
trap '__chrys_preexec' DEBUG
|
|
103
|
+
"""
|
|
104
|
+
)
|
|
105
|
+
|
|
106
|
+
_FISH_HOOKS = (
|
|
107
|
+
'function __chrys_report; printf "\\e]%s;b64:%s\\e\\\\" $argv[1] (printf "%s" "$argv[2]" | base64 | tr -d "\\n"); end; '
|
|
108
|
+
'function __chrys_preexec --on-event fish_preexec; __chrys_report 2026 "$argv"; end; '
|
|
109
|
+
"function __chrys_prompt --on-event fish_prompt; __chrys_report 2025 (pwd); end"
|
|
110
|
+
)
|
|
111
|
+
|
|
112
|
+
_POWERSHELL_HOOKS = (
|
|
113
|
+
"function global:__chrys_report($code, $text) {"
|
|
114
|
+
" $e = [char]27; $st = [char]92;"
|
|
115
|
+
" $payload = [Convert]::ToBase64String([Text.Encoding]::UTF8.GetBytes($text));"
|
|
116
|
+
' return "$e]$code;b64:$payload$e$st"'
|
|
117
|
+
"};"
|
|
118
|
+
"function prompt {"
|
|
119
|
+
" Write-Host -NoNewline (__chrys_report 2025 (Get-Location).Path);"
|
|
120
|
+
' return "PS $($executionContext.SessionState.Path.CurrentLocation)> "'
|
|
121
|
+
"};"
|
|
122
|
+
"if (Get-Module PSReadLine) {"
|
|
123
|
+
" Set-PSReadLineOption -AddToHistoryHandler {"
|
|
124
|
+
" param($command)"
|
|
125
|
+
" [Console]::Write((__chrys_report 2026 $command));"
|
|
126
|
+
" return $true"
|
|
127
|
+
" }"
|
|
128
|
+
"}"
|
|
129
|
+
)
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
@dataclass(frozen=True, slots=True)
|
|
133
|
+
class ShellLaunch:
|
|
134
|
+
"""How to start a shell so that it reports to us."""
|
|
135
|
+
|
|
136
|
+
argv: list[str]
|
|
137
|
+
scratch_directory: str | None = None
|
|
138
|
+
"""Holds start-up files written for this shell. The shell reads them once; whoever started it
|
|
139
|
+
removes the directory when the shell is gone."""
|
|
140
|
+
|
|
141
|
+
def clean_up(self) -> None:
|
|
142
|
+
if self.scratch_directory is not None:
|
|
143
|
+
shutil.rmtree(self.scratch_directory, ignore_errors=True)
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
def prepare_shell_launch(command: str, env: dict[str, str]) -> ShellLaunch:
|
|
147
|
+
"""Work out the argv that starts ``command`` with reporting hooks, adjusting ``env`` to match.
|
|
148
|
+
|
|
149
|
+
A shell we have no hooks for starts as it is; it works, and reports nothing.
|
|
150
|
+
"""
|
|
151
|
+
argv = _split_command(command)
|
|
152
|
+
program, arguments = argv[0], argv[1:]
|
|
153
|
+
name = PurePath(program).stem.lower()
|
|
154
|
+
if name.startswith("zsh"):
|
|
155
|
+
return _launch_zsh(argv, env)
|
|
156
|
+
if name.startswith("bash"):
|
|
157
|
+
scratch = _write_scratch("chrys_bash_", {"init.bash": _BASH_RC})
|
|
158
|
+
rcfile = Path(scratch, "init.bash")
|
|
159
|
+
# bash wants its long options ahead of any short ones.
|
|
160
|
+
return ShellLaunch([program, "--rcfile", str(rcfile), *arguments], scratch)
|
|
161
|
+
if name.startswith("fish"):
|
|
162
|
+
return ShellLaunch([*argv, "-C", _FISH_HOOKS])
|
|
163
|
+
if name.startswith(("pwsh", "powershell")):
|
|
164
|
+
return ShellLaunch([*argv, "-NoExit", "-Command", _POWERSHELL_HOOKS])
|
|
165
|
+
return ShellLaunch(argv)
|
|
166
|
+
|
|
167
|
+
|
|
168
|
+
def _split_command(command: str) -> list[str]:
|
|
169
|
+
if os.path.exists(command):
|
|
170
|
+
# A path, spaces and all (C:\Program Files\...), not a command line.
|
|
171
|
+
return [command]
|
|
172
|
+
try:
|
|
173
|
+
argv = split_windows_command_line(command) if IS_WINDOWS else shlex.split(command)
|
|
174
|
+
except ValueError:
|
|
175
|
+
argv = []
|
|
176
|
+
return argv or [command]
|
|
177
|
+
|
|
178
|
+
|
|
179
|
+
def _write_scratch(prefix: str, files: dict[str, str]) -> str:
|
|
180
|
+
"""Write shell startup files, removing their directory if any write fails."""
|
|
181
|
+
scratch = tempfile.mkdtemp(prefix=prefix)
|
|
182
|
+
try:
|
|
183
|
+
for name, content in files.items():
|
|
184
|
+
Path(scratch, name).write_text(content, encoding="utf-8")
|
|
185
|
+
except BaseException:
|
|
186
|
+
shutil.rmtree(scratch, ignore_errors=True)
|
|
187
|
+
raise
|
|
188
|
+
return scratch
|
|
189
|
+
|
|
190
|
+
|
|
191
|
+
def _launch_zsh(argv: list[str], env: dict[str, str]) -> ShellLaunch:
|
|
192
|
+
# The home the shell will see, which is where it would have looked.
|
|
193
|
+
user_zdotdir = env.get("ZDOTDIR") or env.get("HOME") or os.path.expanduser("~")
|
|
194
|
+
scratch = _write_scratch(
|
|
195
|
+
"chrys_zsh_",
|
|
196
|
+
{".zshenv": _ZSH_ENV.format(user_zdotdir=shlex.quote(user_zdotdir)), ".zshrc": _ZSH_RC},
|
|
197
|
+
)
|
|
198
|
+
env["ZDOTDIR"] = scratch
|
|
199
|
+
return ShellLaunch(argv, scratch)
|
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
# Copyright (c) Huawei Technologies Co., Ltd. 2026. All rights reserved.
|
|
2
|
+
|
|
3
|
+
"""Terminal title helpers for native TUI runs."""
|
|
4
|
+
|
|
5
|
+
from __future__ import annotations
|
|
6
|
+
|
|
7
|
+
import contextlib
|
|
8
|
+
import os
|
|
9
|
+
import sys
|
|
10
|
+
import unicodedata
|
|
11
|
+
from collections.abc import Callable
|
|
12
|
+
|
|
13
|
+
BASE_TERMINAL_TITLE = ""
|
|
14
|
+
|
|
15
|
+
_MESSAGE_TITLE_CHARS = 100
|
|
16
|
+
_TEXTUAL_WEB_DRIVER = "textual.drivers.web_driver:WebDriver"
|
|
17
|
+
_TitleWriter = Callable[[str], None]
|
|
18
|
+
_ESC = "\x1b"
|
|
19
|
+
_BEL = "\x07"
|
|
20
|
+
_ST = "\x9c"
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def set_terminal_title(title: str, *, writer: _TitleWriter | None = None) -> None:
|
|
24
|
+
"""Set the terminal window title with OSC 0 and OSC 2."""
|
|
25
|
+
if running_under_textual_web_driver():
|
|
26
|
+
return
|
|
27
|
+
|
|
28
|
+
safe_title = _title_safe_text(title)
|
|
29
|
+
sequence = f"\x1b]0;{safe_title}\x07\x1b]2;{safe_title}\x07"
|
|
30
|
+
with contextlib.suppress(Exception):
|
|
31
|
+
if writer is not None:
|
|
32
|
+
writer(sequence)
|
|
33
|
+
else:
|
|
34
|
+
sys.stderr.write(sequence)
|
|
35
|
+
sys.stderr.flush()
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def set_app_terminal_title_for_cwd(
|
|
39
|
+
app: object,
|
|
40
|
+
cwd: str | os.PathLike[str],
|
|
41
|
+
*,
|
|
42
|
+
indicator: str = "",
|
|
43
|
+
) -> None:
|
|
44
|
+
"""Set the terminal title for a Textual app's active workspace directory."""
|
|
45
|
+
writer = _app_terminal_title_writer(app)
|
|
46
|
+
if writer is None:
|
|
47
|
+
return
|
|
48
|
+
title = terminal_title_for_cwd(cwd)
|
|
49
|
+
if indicator:
|
|
50
|
+
title = f"{indicator} {title}" if title else indicator
|
|
51
|
+
set_terminal_title(title, writer=writer)
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
def set_app_terminal_title_for_current_cwd(app: object) -> None:
|
|
55
|
+
"""Set the terminal title for a Textual app using the current working directory."""
|
|
56
|
+
writer = _app_terminal_title_writer(app)
|
|
57
|
+
if writer is None:
|
|
58
|
+
return
|
|
59
|
+
set_terminal_title_for_current_cwd(writer=writer)
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
def set_app_terminal_title_for_user_message(app: object, text: str) -> None:
|
|
63
|
+
"""Set the terminal title for a Textual app using a user prompt preview."""
|
|
64
|
+
writer = _app_terminal_title_writer(app)
|
|
65
|
+
if writer is None:
|
|
66
|
+
return
|
|
67
|
+
set_terminal_title_for_user_message(text, writer=writer)
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
def set_app_terminal_title_for_session_title(app: object, title: str) -> None:
|
|
71
|
+
"""Set the terminal title for a Textual app using the session display title."""
|
|
72
|
+
writer = _app_terminal_title_writer(app)
|
|
73
|
+
if writer is None:
|
|
74
|
+
return
|
|
75
|
+
set_terminal_title_for_session_title(title, writer=writer)
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
def set_terminal_title_for_cwd(cwd: str | os.PathLike[str], *, writer: _TitleWriter | None = None) -> None:
|
|
79
|
+
"""Set the title to the current directory path."""
|
|
80
|
+
set_terminal_title(terminal_title_for_cwd(cwd), writer=writer)
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
def set_terminal_title_for_current_cwd(*, writer: _TitleWriter | None = None) -> None:
|
|
84
|
+
"""Set the title using ``os.getcwd()``, or the base title if cwd is unavailable."""
|
|
85
|
+
try:
|
|
86
|
+
cwd = os.getcwd()
|
|
87
|
+
except OSError:
|
|
88
|
+
set_terminal_title(BASE_TERMINAL_TITLE, writer=writer)
|
|
89
|
+
return
|
|
90
|
+
set_terminal_title_for_cwd(cwd, writer=writer)
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
def set_terminal_title_for_user_message(text: str, *, writer: _TitleWriter | None = None) -> None:
|
|
94
|
+
"""Set the title to a prompt preview."""
|
|
95
|
+
set_terminal_title(terminal_title_for_user_message(text), writer=writer)
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
def set_terminal_title_for_session_title(title: str, *, writer: _TitleWriter | None = None) -> None:
|
|
99
|
+
"""Set the title to the session title."""
|
|
100
|
+
set_terminal_title(terminal_title_for_session_title(title), writer=writer)
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
def terminal_title_for_cwd(cwd: str | os.PathLike[str]) -> str:
|
|
104
|
+
"""Build the terminal title for a workspace directory."""
|
|
105
|
+
raw_path = os.fspath(cwd)
|
|
106
|
+
if not os.path.isdir(raw_path):
|
|
107
|
+
return BASE_TERMINAL_TITLE
|
|
108
|
+
path = _title_safe_text(raw_path)
|
|
109
|
+
if not path:
|
|
110
|
+
return BASE_TERMINAL_TITLE
|
|
111
|
+
return path
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
def terminal_title_for_user_message(text: str) -> str:
|
|
115
|
+
"""Build the terminal title for a submitted user message."""
|
|
116
|
+
fragment = _message_title_fragment(text)
|
|
117
|
+
return fragment or BASE_TERMINAL_TITLE
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
def terminal_title_for_session_title(title: str) -> str:
|
|
121
|
+
"""Build the terminal title for a session display title."""
|
|
122
|
+
fragment = _message_title_fragment(title)
|
|
123
|
+
return fragment or BASE_TERMINAL_TITLE
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
def _message_title_fragment(text: str) -> str:
|
|
127
|
+
safe_text = _title_safe_text(text)
|
|
128
|
+
return safe_text[:_MESSAGE_TITLE_CHARS]
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
def _title_safe_text(text: str) -> str:
|
|
132
|
+
text = _strip_terminal_sequences(text)
|
|
133
|
+
parts: list[str] = []
|
|
134
|
+
pending_space = False
|
|
135
|
+
for ch in text.strip():
|
|
136
|
+
if ch.isspace():
|
|
137
|
+
pending_space = bool(parts)
|
|
138
|
+
continue
|
|
139
|
+
if unicodedata.category(ch).startswith("C"):
|
|
140
|
+
continue
|
|
141
|
+
if pending_space:
|
|
142
|
+
parts.append(" ")
|
|
143
|
+
pending_space = False
|
|
144
|
+
parts.append(ch)
|
|
145
|
+
return "".join(parts)
|
|
146
|
+
|
|
147
|
+
|
|
148
|
+
def _strip_terminal_sequences(text: str) -> str:
|
|
149
|
+
"""Remove ANSI/OSC-style control sequences before title filtering."""
|
|
150
|
+
result: list[str] = []
|
|
151
|
+
i = 0
|
|
152
|
+
while i < len(text):
|
|
153
|
+
ch = text[i]
|
|
154
|
+
if ch == _ESC:
|
|
155
|
+
i = _skip_esc_sequence(text, i)
|
|
156
|
+
continue
|
|
157
|
+
if ch == "\x9b":
|
|
158
|
+
i = _skip_until_csi_final(text, i + 1)
|
|
159
|
+
continue
|
|
160
|
+
if ch == "\x9d":
|
|
161
|
+
i = _skip_until_string_terminator(text, i + 1)
|
|
162
|
+
continue
|
|
163
|
+
if ch in {"\x90", "\x98", "\x9e", "\x9f"}:
|
|
164
|
+
i = _skip_until_string_terminator(text, i + 1)
|
|
165
|
+
continue
|
|
166
|
+
result.append(ch)
|
|
167
|
+
i += 1
|
|
168
|
+
return "".join(result)
|
|
169
|
+
|
|
170
|
+
|
|
171
|
+
def _skip_esc_sequence(text: str, start: int) -> int:
|
|
172
|
+
next_index = start + 1
|
|
173
|
+
if next_index >= len(text):
|
|
174
|
+
return next_index
|
|
175
|
+
|
|
176
|
+
introducer = text[next_index]
|
|
177
|
+
if introducer == "[":
|
|
178
|
+
return _skip_until_csi_final(text, next_index + 1)
|
|
179
|
+
if introducer == "]":
|
|
180
|
+
return _skip_until_string_terminator(text, next_index + 1)
|
|
181
|
+
if introducer in {"P", "X", "^", "_"}:
|
|
182
|
+
return _skip_until_string_terminator(text, next_index + 1)
|
|
183
|
+
|
|
184
|
+
i = next_index
|
|
185
|
+
while i < len(text) and 0x20 <= ord(text[i]) <= 0x2F:
|
|
186
|
+
i += 1
|
|
187
|
+
if i < len(text) and 0x30 <= ord(text[i]) <= 0x7E:
|
|
188
|
+
return i + 1
|
|
189
|
+
return next_index + 1
|
|
190
|
+
|
|
191
|
+
|
|
192
|
+
def _skip_until_csi_final(text: str, start: int) -> int:
|
|
193
|
+
i = start
|
|
194
|
+
while i < len(text):
|
|
195
|
+
if 0x40 <= ord(text[i]) <= 0x7E:
|
|
196
|
+
return i + 1
|
|
197
|
+
i += 1
|
|
198
|
+
return i
|
|
199
|
+
|
|
200
|
+
|
|
201
|
+
def _skip_until_string_terminator(text: str, start: int) -> int:
|
|
202
|
+
i = start
|
|
203
|
+
while i < len(text):
|
|
204
|
+
if text[i] == _BEL or text[i] == _ST:
|
|
205
|
+
return i + 1
|
|
206
|
+
if text[i] == _ESC and i + 1 < len(text) and text[i + 1] == "\\":
|
|
207
|
+
return i + 2
|
|
208
|
+
i += 1
|
|
209
|
+
return i
|
|
210
|
+
|
|
211
|
+
|
|
212
|
+
def _app_terminal_title_writer(app: object) -> _TitleWriter | None:
|
|
213
|
+
# Textual has no public raw terminal writer; keep the private driver
|
|
214
|
+
# boundary here instead of spreading it through screens.
|
|
215
|
+
driver = getattr(app, "_driver", None)
|
|
216
|
+
write = getattr(driver, "write", None)
|
|
217
|
+
if not callable(write):
|
|
218
|
+
return None
|
|
219
|
+
return write
|
|
220
|
+
|
|
221
|
+
|
|
222
|
+
def running_under_textual_web_driver() -> bool:
|
|
223
|
+
"""Return true when Chrys is hosted by textual-serve."""
|
|
224
|
+
return os.environ.get("TEXTUAL_DRIVER") == _TEXTUAL_WEB_DRIVER
|