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,76 @@
|
|
|
1
|
+
# Copyright (c) Huawei Technologies Co., Ltd. 2026. All rights reserved.
|
|
2
|
+
|
|
3
|
+
"""Timing for the three pixel poses, independent of artwork and terminal rendering."""
|
|
4
|
+
|
|
5
|
+
from __future__ import annotations
|
|
6
|
+
|
|
7
|
+
from dataclasses import dataclass
|
|
8
|
+
|
|
9
|
+
from chrys.app.features.buddy.model import Species
|
|
10
|
+
|
|
11
|
+
IDLE_FRAME_COUNT = 3
|
|
12
|
+
FRAME_COUNT = IDLE_FRAME_COUNT * 2
|
|
13
|
+
# Eyelids keep their own time. The period shares no factor with any temperament's, so a blink lands on a
|
|
14
|
+
# different moment of the rhythm each time instead of becoming part of it.
|
|
15
|
+
_BLINK_EVERY_TICKS = 13
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
@dataclass(frozen=True)
|
|
19
|
+
class _Temperament:
|
|
20
|
+
"""How a species idles: it rests, then stretches through its two other poses, holding each one."""
|
|
21
|
+
|
|
22
|
+
rest_ticks: int
|
|
23
|
+
hold_ticks: int
|
|
24
|
+
|
|
25
|
+
def pose(self, tick: int) -> int:
|
|
26
|
+
"""The idle pose at *tick*: 0 while resting, then 1 and 2 for *hold_ticks* each."""
|
|
27
|
+
into_stretch = tick % (self.rest_ticks + 2 * self.hold_ticks) - self.rest_ticks
|
|
28
|
+
return 0 if into_stretch < 0 else 1 + into_stretch // self.hold_ticks
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
_DARTING = _Temperament(rest_ticks=2, hold_ticks=1)
|
|
32
|
+
_LIVELY = _Temperament(rest_ticks=5, hold_ticks=1)
|
|
33
|
+
_EASY = _Temperament(rest_ticks=8, hold_ticks=2)
|
|
34
|
+
_SLOW = _Temperament(rest_ticks=14, hold_ticks=3)
|
|
35
|
+
|
|
36
|
+
# How restless each species is. The rhythm comes from the temperament, never from a per-species cue list.
|
|
37
|
+
_TEMPERAMENTS: dict[Species, _Temperament] = {
|
|
38
|
+
Species.ALIEN: _LIVELY,
|
|
39
|
+
Species.AXOLOTL: _EASY,
|
|
40
|
+
Species.BAT: _LIVELY,
|
|
41
|
+
Species.BEE: _DARTING,
|
|
42
|
+
Species.CACTUS: _SLOW,
|
|
43
|
+
Species.CAPYBARA: _SLOW,
|
|
44
|
+
Species.CAT: _EASY,
|
|
45
|
+
Species.CRAB: _LIVELY,
|
|
46
|
+
Species.DRAGON: _LIVELY,
|
|
47
|
+
Species.DUCK: _EASY,
|
|
48
|
+
Species.FOX: _LIVELY,
|
|
49
|
+
Species.FROG: _LIVELY,
|
|
50
|
+
Species.GHOST: _EASY,
|
|
51
|
+
Species.GOOSE: _EASY,
|
|
52
|
+
Species.JELLY: _EASY,
|
|
53
|
+
Species.LLAMA: _EASY,
|
|
54
|
+
Species.MUSHROOM: _SLOW,
|
|
55
|
+
Species.OCTOPUS: _LIVELY,
|
|
56
|
+
Species.OWL: _EASY,
|
|
57
|
+
Species.PANDA: _SLOW,
|
|
58
|
+
Species.PENGUIN: _EASY,
|
|
59
|
+
Species.RABBIT: _LIVELY,
|
|
60
|
+
Species.ROBOT: _LIVELY,
|
|
61
|
+
Species.SHARK: _DARTING,
|
|
62
|
+
Species.SNAIL: _SLOW,
|
|
63
|
+
Species.SNAKE: _DARTING,
|
|
64
|
+
Species.TABBY: _EASY,
|
|
65
|
+
Species.TURTLE: _SLOW,
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
def get_idle_frame(species: Species, tick: int) -> tuple[int, bool]:
|
|
70
|
+
"""Choose an idle pixel pose and eyelid state for the current tick."""
|
|
71
|
+
return _TEMPERAMENTS[species].pose(tick), tick % _BLINK_EVERY_TICKS == _BLINK_EVERY_TICKS - 1
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
def get_pet_frame(tick: int) -> int:
|
|
75
|
+
"""Cycle the three intact petting poses at the caller's faster cadence."""
|
|
76
|
+
return IDLE_FRAME_COUNT + tick % IDLE_FRAME_COUNT
|
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
# Copyright (c) Huawei Technologies Co., Ltd. 2026. All rights reserved.
|
|
2
|
+
|
|
3
|
+
"""The ``/buddy`` command: what each subcommand does and what it answers.
|
|
4
|
+
|
|
5
|
+
Everything here answers at once. The TUI can wait for a model, so it answers ``/buddy pet``
|
|
6
|
+
itself, after :func:`pet_refusal`, and never asks for it here. Asked here anyway, petting is
|
|
7
|
+
counted and gets a stock line.
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
from __future__ import annotations
|
|
11
|
+
|
|
12
|
+
import logging
|
|
13
|
+
from typing import TYPE_CHECKING, Literal
|
|
14
|
+
|
|
15
|
+
from rich.cells import cell_len
|
|
16
|
+
|
|
17
|
+
from chrys.app.features.buddy import actions
|
|
18
|
+
from chrys.app.features.buddy.model import TRAIT_MAX, Trait, clean_name
|
|
19
|
+
from chrys.app.features.buddy.replies import stock_reply
|
|
20
|
+
from chrys.foundation.i18n import DisplayBlock, MessageRef, msg
|
|
21
|
+
from chrys.foundation.i18n.formatting import format_message
|
|
22
|
+
|
|
23
|
+
if TYPE_CHECKING:
|
|
24
|
+
from collections.abc import Callable
|
|
25
|
+
|
|
26
|
+
from chrys.app.features.buddy.model import Buddy
|
|
27
|
+
|
|
28
|
+
logger = logging.getLogger(__name__)
|
|
29
|
+
|
|
30
|
+
_GAUGE_CELLS = 10
|
|
31
|
+
|
|
32
|
+
type Severity = Literal["information", "warning"]
|
|
33
|
+
type CommandAnswer = tuple[MessageRef | str, Severity]
|
|
34
|
+
# The card is text put together here, so the persona line inside it is rendered here, by the caller's renderer.
|
|
35
|
+
type Render = Callable[[MessageRef], str]
|
|
36
|
+
|
|
37
|
+
_NO_BUDDY_TO_PET = msg(
|
|
38
|
+
"tui.buddy.no_buddy_to_pet",
|
|
39
|
+
fallback="There is nobody to pet yet. Hatch a buddy with /buddy hatch.",
|
|
40
|
+
)
|
|
41
|
+
_BUDDY_MUTED = msg(
|
|
42
|
+
"tui.buddy.muted",
|
|
43
|
+
fallback="{name} is muted and stays quiet. Use /buddy mute to hear from it again.",
|
|
44
|
+
)
|
|
45
|
+
_INTRO_NO_BUDDY = msg(
|
|
46
|
+
"tui.buddy.intro_no_buddy",
|
|
47
|
+
fallback="🥚 There is an egg here, and nobody knows what is in it.\n\n/buddy hatch finds out.",
|
|
48
|
+
multiline=True,
|
|
49
|
+
)
|
|
50
|
+
_INTRO_WITH_BUDDY = msg(
|
|
51
|
+
"tui.buddy.intro_with_buddy",
|
|
52
|
+
fallback="🐾 {name} is keeping you company.\n\n/buddy info shows how it is doing, /buddy pet gives it a pat.",
|
|
53
|
+
multiline=True,
|
|
54
|
+
)
|
|
55
|
+
_NOT_HATCHED = msg("tui.buddy.not_hatched", fallback="No buddy has hatched yet. Start with /buddy hatch.")
|
|
56
|
+
_HATCH_ALREADY = msg("tui.buddy.hatch_already", fallback="{name} is already here, and one buddy is all you get.")
|
|
57
|
+
_HATCH_SUCCESS = msg(
|
|
58
|
+
"tui.buddy.hatch_success",
|
|
59
|
+
fallback="🐣 Out of the egg:\n\n{info}\n\nFrom now on it lives in the sidebar, on the Buddy tab.",
|
|
60
|
+
multiline=True,
|
|
61
|
+
)
|
|
62
|
+
_MUTE_ON = msg("tui.buddy.mute_on", fallback="Your buddy will keep quiet from now on. It is still around.")
|
|
63
|
+
_MUTE_OFF = msg("tui.buddy.mute_off", fallback="Your buddy can speak up again.")
|
|
64
|
+
_NAME_EMPTY = msg("tui.buddy.name_empty", fallback="Give the new name too, for example /buddy name Mochi")
|
|
65
|
+
_NAME_SUCCESS = msg("tui.buddy.name_success", fallback="Your buddy answers to {name} now.")
|
|
66
|
+
_SAVE_FAILED = msg(
|
|
67
|
+
"tui.buddy.save_failed",
|
|
68
|
+
fallback="The buddy save file could not be updated, so nothing has changed. Try again in a moment.",
|
|
69
|
+
)
|
|
70
|
+
_UNKNOWN_COMMAND = msg(
|
|
71
|
+
"tui.buddy.unknown",
|
|
72
|
+
fallback='/buddy does not know "{arg}".\n\nIt knows: hatch, info, pet, mute, name <new name>',
|
|
73
|
+
multiline=True,
|
|
74
|
+
)
|
|
75
|
+
# The card's labels. Species and rarity stay as they are spelled everywhere else.
|
|
76
|
+
_CARD_SHINY = msg("tui.buddy.card.shiny", fallback="shiny")
|
|
77
|
+
_CARD_LEVEL = msg("tui.buddy.card.level", fallback="level")
|
|
78
|
+
_CARD_FULLY_GROWN = msg("tui.buddy.card.fully_grown", fallback="{level} · fully grown")
|
|
79
|
+
_CARD_PROGRESS = msg("tui.buddy.card.progress", fallback="{level} · {xp}/{needed} XP")
|
|
80
|
+
_CARD_TRAIT_FOCUS = msg("tui.buddy.card.trait.focus", fallback="focus")
|
|
81
|
+
_CARD_TRAIT_CURIOSITY = msg("tui.buddy.card.trait.curiosity", fallback="curiosity")
|
|
82
|
+
_CARD_TRAIT_GRIT = msg("tui.buddy.card.trait.grit", fallback="grit")
|
|
83
|
+
_CARD_TRAIT_CHARM = msg("tui.buddy.card.trait.charm", fallback="charm")
|
|
84
|
+
_CARD_SINCE = msg("tui.buddy.card.since", fallback="{hatched} · {turns} turns · {pets} pets")
|
|
85
|
+
_CARD_EVOLUTION = msg("tui.buddy.card.evolution", fallback="evolution {stage}")
|
|
86
|
+
_CARD_TRAITS = {
|
|
87
|
+
Trait.FOCUS: _CARD_TRAIT_FOCUS,
|
|
88
|
+
Trait.CURIOSITY: _CARD_TRAIT_CURIOSITY,
|
|
89
|
+
Trait.GRIT: _CARD_TRAIT_GRIT,
|
|
90
|
+
Trait.CHARM: _CARD_TRAIT_CHARM,
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
def split_command(arg: str | None) -> tuple[str, str]:
|
|
95
|
+
"""``/buddy <arg>`` as a lower-case subcommand and whatever follows it. Any whitespace separates the two."""
|
|
96
|
+
verb, rest, *_ = [*(arg or "").split(None, 1), "", ""]
|
|
97
|
+
return verb.lower(), rest
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
def pet_refusal(buddy: Buddy | None) -> CommandAnswer | None:
|
|
101
|
+
"""Why *buddy* cannot be petted through the command right now, or None when it can."""
|
|
102
|
+
if buddy is None:
|
|
103
|
+
return _NO_BUDDY_TO_PET.bind(), "warning"
|
|
104
|
+
if buddy.muted:
|
|
105
|
+
return _BUDDY_MUTED.bind(name=buddy.display_name), "warning"
|
|
106
|
+
return None
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
def handle_buddy_command(arg: str | None, *, render: Render = format_message) -> CommandAnswer:
|
|
110
|
+
"""Carry out ``/buddy <arg>`` and say what happened. *render* puts the info card in the user's language."""
|
|
111
|
+
try:
|
|
112
|
+
return _carry_out(arg, render)
|
|
113
|
+
except OSError: # a read-only or full config directory, or another instance wedged on the save file
|
|
114
|
+
logger.warning("Buddy save file could not be updated", exc_info=True)
|
|
115
|
+
return _SAVE_FAILED.bind(), "warning"
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
def _carry_out(arg: str | None, render: Render) -> CommandAnswer:
|
|
119
|
+
buddy = actions.current_buddy()
|
|
120
|
+
verb, rest = split_command(arg)
|
|
121
|
+
|
|
122
|
+
if not verb:
|
|
123
|
+
if buddy is None:
|
|
124
|
+
return _INTRO_NO_BUDDY.bind(), "information"
|
|
125
|
+
return _INTRO_WITH_BUDDY.bind(name=buddy.display_name), "information"
|
|
126
|
+
if verb == "hatch":
|
|
127
|
+
if buddy is not None:
|
|
128
|
+
return _HATCH_ALREADY.bind(name=buddy.display_name), "warning"
|
|
129
|
+
return _HATCH_SUCCESS.bind(info=DisplayBlock(buddy_card(actions.hatch(), render=render))), "information"
|
|
130
|
+
if verb == "pet":
|
|
131
|
+
refusal = pet_refusal(buddy)
|
|
132
|
+
if refusal is not None:
|
|
133
|
+
return refusal
|
|
134
|
+
if buddy is None:
|
|
135
|
+
raise RuntimeError("Petting requires an existing buddy.")
|
|
136
|
+
actions.record_pet()
|
|
137
|
+
return stock_reply(buddy), "information"
|
|
138
|
+
if verb not in {"info", "mute", "name"}:
|
|
139
|
+
return _UNKNOWN_COMMAND.bind(arg=arg or ""), "warning"
|
|
140
|
+
if buddy is None:
|
|
141
|
+
return _NOT_HATCHED.bind(), "warning"
|
|
142
|
+
if verb == "info":
|
|
143
|
+
return buddy_card(buddy, render=render), "information"
|
|
144
|
+
if verb == "mute":
|
|
145
|
+
actions.set_muted(not buddy.muted)
|
|
146
|
+
return (_MUTE_OFF if buddy.muted else _MUTE_ON).bind(), "information"
|
|
147
|
+
name = clean_name(rest)
|
|
148
|
+
if not name:
|
|
149
|
+
return _NAME_EMPTY.bind(), "warning"
|
|
150
|
+
actions.rename(name)
|
|
151
|
+
return _NAME_SUCCESS.bind(name=name), "information"
|
|
152
|
+
|
|
153
|
+
|
|
154
|
+
def buddy_card(buddy: Buddy, *, render: Render = format_message) -> str:
|
|
155
|
+
"""*buddy* at a glance: who it is, how far it has come, what it is like, and since when."""
|
|
156
|
+
progress, record = buddy.progress, buddy.record
|
|
157
|
+
who = [buddy.display_name, buddy.species.value, buddy.rarity.value]
|
|
158
|
+
if buddy.shiny:
|
|
159
|
+
who.append(render(_CARD_SHINY.bind()))
|
|
160
|
+
if progress.maxed:
|
|
161
|
+
climb = f"{_gauge(1, 1)} {render(_CARD_FULLY_GROWN.bind(level=buddy.level))}"
|
|
162
|
+
else:
|
|
163
|
+
into, needed = progress.xp_into_level, progress.xp_for_level
|
|
164
|
+
climb = f"{_gauge(into, needed)} {render(_CARD_PROGRESS.bind(level=buddy.level, xp=into, needed=needed))}"
|
|
165
|
+
level_label = render(_CARD_LEVEL.bind())
|
|
166
|
+
trait_labels = {trait: render(_CARD_TRAITS[trait].bind()) for trait in Trait}
|
|
167
|
+
label_width = max(cell_len(label) for label in (level_label, *trait_labels.values()))
|
|
168
|
+
traits = buddy.traits
|
|
169
|
+
since = render(
|
|
170
|
+
_CARD_SINCE.bind(hatched=f"{record.hatched_at.astimezone():%Y-%m-%d}", turns=record.turns, pets=record.pets)
|
|
171
|
+
)
|
|
172
|
+
if buddy.evolved:
|
|
173
|
+
since += f" · {render(_CARD_EVOLUTION.bind(stage=progress.stage))}"
|
|
174
|
+
return "\n".join(
|
|
175
|
+
[
|
|
176
|
+
f"🐾 {' · '.join(who)}",
|
|
177
|
+
f"{_padded(level_label, label_width)} {climb}",
|
|
178
|
+
*(
|
|
179
|
+
f"{_padded(trait_labels[trait], label_width)} {_gauge(traits[trait], TRAIT_MAX)} {traits[trait]}"
|
|
180
|
+
for trait in Trait
|
|
181
|
+
),
|
|
182
|
+
f"“{render(buddy.persona)}”",
|
|
183
|
+
since,
|
|
184
|
+
]
|
|
185
|
+
)
|
|
186
|
+
|
|
187
|
+
|
|
188
|
+
def _padded(label: str, width: int) -> str:
|
|
189
|
+
# Padded by cells, not characters: a CJK label is two cells wide per character.
|
|
190
|
+
return label + " " * (width - cell_len(label))
|
|
191
|
+
|
|
192
|
+
|
|
193
|
+
def _gauge(value: int, full: int) -> str:
|
|
194
|
+
# Rounded down: a gauge is full only when what it measures is.
|
|
195
|
+
filled = _GAUGE_CELLS * value // full
|
|
196
|
+
return "▰" * filled + "▱" * (_GAUGE_CELLS - filled)
|
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
# Buddy
|
|
2
|
+
|
|
3
|
+
A buddy is a small pet that lives in the sidebar, grows as the user works, and
|
|
4
|
+
answers in one line when it is petted. The package is split by concern:
|
|
5
|
+
|
|
6
|
+
| Module | Owns |
|
|
7
|
+
| --- | --- |
|
|
8
|
+
| `model.py` | `BuddyRecord` (what is saved) and `Buddy` (the record plus everything derived from it) |
|
|
9
|
+
| `hatchery.py` | The random draw that makes a new record |
|
|
10
|
+
| `progression.py` | Experience, levels and evolution stages |
|
|
11
|
+
| `store.py` | The save file: locking, atomic writes, the signed envelope |
|
|
12
|
+
| `actions.py` | The changes a user can cause: hatch, rename, mute, pet, finish a turn |
|
|
13
|
+
| `commands.py` | `/buddy` subcommands and the info card |
|
|
14
|
+
| `replies.py` | The one-line answer to a pet, from a model or a stock line |
|
|
15
|
+
| `lifecycle.py` | The hook every frontend calls, on its event loop, after a successful turn |
|
|
16
|
+
| `sprites/*.toml`, `pixel_sprites.py`, `pixel_renderer.py`, `animation.py`, `portrait.py` | Artwork and its rendering |
|
|
17
|
+
|
|
18
|
+
The TUI adds `app/tui/buddy_reply.py::PetReplyFlow`, which the sidebar panel and
|
|
19
|
+
`/buddy pet` share: a thinking toast now, the answer when it arrives, and one
|
|
20
|
+
reply in flight per process.
|
|
21
|
+
|
|
22
|
+
## Hatching
|
|
23
|
+
|
|
24
|
+
Hatching is a plain random draw (`random.SystemRandom` in production, any
|
|
25
|
+
`random.Random` in tests) and the whole result is saved. Nothing about a buddy
|
|
26
|
+
is derived from the machine or the user, so a buddy moves with its save file.
|
|
27
|
+
|
|
28
|
+
The draw picks a rarity tier (`RARITY_ODDS`), a species that hatches in that
|
|
29
|
+
tier, a 1-in-40 shiny flag, four traits (focus, curiosity, grit and charm) and
|
|
30
|
+
a name. Each tier has a trait point budget (`TRAIT_POINTS`) that is shared out
|
|
31
|
+
unevenly, so every buddy leans some way. The strongest trait at hatch time
|
|
32
|
+
decides the persona line. It is a message like any other display text: the
|
|
33
|
+
info card and the sidebar show it in the user's language, and the reply
|
|
34
|
+
prompt, which is English throughout, is given the English line.
|
|
35
|
+
|
|
36
|
+
`SPECIES_RARITY` sorts the species by how far from the back garden one would
|
|
37
|
+
have to go to meet them: N lives outside the window (bee, cat, duck, snail),
|
|
38
|
+
R takes a trip (fox, owl, penguin, shark), SR takes luck (axolotl, capybara,
|
|
39
|
+
panda), and SSR is not from around here at all (alien, dragon, ghost, robot).
|
|
40
|
+
|
|
41
|
+
## Progression
|
|
42
|
+
|
|
43
|
+
A finished turn is worth 10 XP and a pet 2 XP. Only the first `5 × (turns + 1)`
|
|
44
|
+
pets of a buddy's life count, so the pets a turn pays for are worth exactly as
|
|
45
|
+
much as the turn itself: petting can at best double what working earns, and
|
|
46
|
+
without work it stops paying after the first five. The allowance is cumulative:
|
|
47
|
+
pets not given after one turn may be given after a later one.
|
|
48
|
+
|
|
49
|
+
A stage is 99 level-ups. A level costs `10 × (10 + level // 10 + 2 × stage)`
|
|
50
|
+
XP, which makes the first stage about 1,440 turns and each later stage about
|
|
51
|
+
200 turns longer. Finishing a stage below the top rarity tier evolves the buddy
|
|
52
|
+
one tier and restarts it at level 1; the top tier ends at level 100. Levels and
|
|
53
|
+
stages are never stored. `progress()` derives them from the turn and pet
|
|
54
|
+
counters, so changing the curve re-levels every buddy consistently.
|
|
55
|
+
|
|
56
|
+
Traits grow by one point per ten levels and ten per evolution, capped at 100.
|
|
57
|
+
A top-tier buddy that has evolved or reached the final level turns shiny.
|
|
58
|
+
|
|
59
|
+
## Save file
|
|
60
|
+
|
|
61
|
+
`<config dir>/extras/buddy/buddy.json`, shared by every running instance:
|
|
62
|
+
|
|
63
|
+
```json
|
|
64
|
+
{"v": 2, "buddy": {"species": "...", "rarity": "...", "...": "..."}, "sig": "<HMAC-SHA256>"}
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
Changes are read-modify-write under a lock file and land through an atomic
|
|
68
|
+
replace, so readers take no lock. `buddy.json.bak` is a second copy that a
|
|
69
|
+
reader falls back to. The signature uses a constant key: it catches damage and
|
|
70
|
+
casual hand edits, and is not a secret. A file that does not verify, or that is
|
|
71
|
+
not version 2, reads as "no buddy yet". Files written before version 2 are not
|
|
72
|
+
migrated; those users hatch again.
|
|
73
|
+
|
|
74
|
+
`BuddyRecord.from_json` accepts exactly what `to_json` writes and coerces
|
|
75
|
+
nothing. Reading never raises. A change raises `OSError` when the file cannot
|
|
76
|
+
be written (`TimeoutError` when another instance holds the lock for ten
|
|
77
|
+
seconds): `/buddy` answers that with a warning, petting goes ahead uncounted,
|
|
78
|
+
and the after-turn hook logs it. A muted buddy keeps its information toasts to
|
|
79
|
+
itself, never a warning: a command that did not work is always reported. Until
|
|
80
|
+
a buddy has hatched, no change touches the disk at all, so users who never
|
|
81
|
+
hatch one pay nothing per turn.
|
|
82
|
+
|
|
83
|
+
Waiting for the lock is never the event loop's job, since every frontend runs
|
|
84
|
+
its turns, its input and its rendering there. The sidebar counts a pet on a
|
|
85
|
+
widget worker, which its unmount cancels; `/buddy` commands run on a thread,
|
|
86
|
+
one after another in the order they were given, and answer when they are done;
|
|
87
|
+
and the after-turn hook hands the credit to the loop's default executor, which
|
|
88
|
+
the loop's runner joins at exit, so a headless run still lands its last turn.
|
|
89
|
+
A change whose task was cancelled still lands: a thread cannot be stopped, and
|
|
90
|
+
the file is the truth either way. Reads take no lock and stay on the loop. A
|
|
91
|
+
`/buddy pet` has two ends, the count and the answer, which finish in either
|
|
92
|
+
order, and each one refreshes the panel in place when it does.
|
|
93
|
+
|
|
94
|
+
# Pixel portraits
|
|
95
|
+
|
|
96
|
+
All 28 species use a **20 × 16 RGBA canvas**, rendered as 20 terminal columns
|
|
97
|
+
and eight rows of TrueColor half blocks (`▀`).
|
|
98
|
+
|
|
99
|
+
## Artwork
|
|
100
|
+
|
|
101
|
+
Artwork is data: each species has one `sprites/<species>.toml` file holding its
|
|
102
|
+
`[palette]` (index → `[r, g, b, a]`) and three distinct poses as `[[frames]]`
|
|
103
|
+
tables. Each pose's `rows` are 16 strings of 20 palette-index digits, which are
|
|
104
|
+
not characters displayed to the user. `pixel_sprites.py` loads a file on first
|
|
105
|
+
use and rejects one whose size or indices don't fit. Palette roles are `0` for
|
|
106
|
+
transparency, `3` for the body shadow, and `4` for pupils; other colors belong
|
|
107
|
+
to that species' design.
|
|
108
|
+
|
|
109
|
+
Keep the silhouette recognizable at native size. Features that distinguish
|
|
110
|
+
similar animals include:
|
|
111
|
+
|
|
112
|
+
| Species | Defining features |
|
|
113
|
+
| --- | --- |
|
|
114
|
+
| Duck / goose | Flat orange bill; goose has a long neck |
|
|
115
|
+
| Cat / tabby / fox | Pointed ears; tabby is rounder and wider; fox has a pale muzzle and large tail |
|
|
116
|
+
| Rabbit | Long pink inner ears, dark pupils, cream muzzle, rounded haunches and paws, small round tail |
|
|
117
|
+
| Owl / penguin | Owl's facial discs and ear tufts; penguin's pale belly and orange feet |
|
|
118
|
+
| Turtle / snail | Turtle's domed shell and low legs; snail's spiral shell and eye stalks |
|
|
119
|
+
| Octopus / axolotl | Tentacles; external gills and four small limbs |
|
|
120
|
+
| Dragon / bat | Dragon's horns, belly and long tail; bat's broad wings |
|
|
121
|
+
| Panda / capybara / llama | Dark eye patches; broad blunt muzzle; tall neck |
|
|
122
|
+
| Shark / snake / frog | Dorsal fin and teeth; long coiled body; raised eyes and spread feet |
|
|
123
|
+
| Bee / crab | Striped abdomen and wings; paired claws and spread legs |
|
|
124
|
+
| Ghost / jelly / alien | Wavy hem; soft low body; large dome and dark eyes |
|
|
125
|
+
| Cactus / mushroom / robot | Branched stem and pot; spotted cap and stalk; metal panels, LED eyes and antenna |
|
|
126
|
+
|
|
127
|
+
Pupils retain their authored contrast color. Blinking changes only vertically
|
|
128
|
+
stacked pupil pixels: upper pixels use the body shadow, while the bottom stays
|
|
129
|
+
visible as a closed-eye line. Every built-in pose includes vertically stacked
|
|
130
|
+
pupils so blinking visibly changes its expression. Isolated pupil pixels stay
|
|
131
|
+
intact. Other features that happen to share an eye's RGB color must remain unchanged.
|
|
132
|
+
|
|
133
|
+
## Animation and portrait layout
|
|
134
|
+
|
|
135
|
+
`animation.py` owns timing for idle poses 0–2 and petting poses 3–5. Idling is
|
|
136
|
+
a rule, not a list of cues: each species has a temperament (darting, lively,
|
|
137
|
+
easy or slow), and a temperament is how long the animal rests and how long it
|
|
138
|
+
holds a pose. It rests, stretches through pose 1 and then pose 2 for the same
|
|
139
|
+
time each, and rests again, so every temperament has a period of its own.
|
|
140
|
+
Eyelids keep their own time: one blink every 13 ticks whatever the pose, a
|
|
141
|
+
period that shares no factor with any temperament's, so blinks never settle
|
|
142
|
+
into the rhythm. Petting cycles all three poses faster. Its first pose hops up
|
|
143
|
+
one pixel only when the top row is empty, preserving ears, horns and antennae.
|
|
144
|
+
No particles or decorations overwrite the animal.
|
|
145
|
+
|
|
146
|
+
`portrait.py` adds separate rarity-colored corners and a compact nameplate.
|
|
147
|
+
Shiny animates only the badge. The portrait occupies 11 terminal rows at every
|
|
148
|
+
width. Below 20 columns the complete pixel canvas is scaled with nearest-neighbor
|
|
149
|
+
sampling and vertically padded, including custom PNG artwork. Built-in pupil
|
|
150
|
+
pixels are retained at their scaled positions so single-column eyes stay visible. Corners are
|
|
151
|
+
omitted below 22 columns so they do not crowd the animal.
|
|
152
|
+
|
|
153
|
+
The sidebar repaints frames without invalidating layout, uses cached geometry,
|
|
154
|
+
and skips offscreen portraits. The shiny badge runs on its own 10 Hz timer.
|
|
155
|
+
|
|
156
|
+
The save file changes behind the panel's back: every finished turn credits it,
|
|
157
|
+
and so does every other running instance. The panel reads it again when it
|
|
158
|
+
comes into view and every few seconds while it stays there, and rewrites a
|
|
159
|
+
label only when its text has changed, because each label update lays the whole
|
|
160
|
+
screen out again.
|
|
161
|
+
|
|
162
|
+
## Custom artwork
|
|
163
|
+
|
|
164
|
+
Place PNG overrides at `~/.chrys/extras/buddy/assets/<species>_<frame>.png`, with
|
|
165
|
+
frame indices 0–5. Images are normalized to 20 × 16 with nearest-neighbor
|
|
166
|
+
sampling. Custom pixels are kept as supplied, including their eye design.
|
|
167
|
+
File revisions invalidate a bounded image cache; missing or unreadable files
|
|
168
|
+
fall back to built-in artwork and are retried on subsequent renders.
|
|
169
|
+
|
|
170
|
+
When upgrading from 16 × 10, existing custom PNGs are stretched to the new
|
|
171
|
+
20 × 16 canvas. Their aspect ratio therefore changes; redraw or export them
|
|
172
|
+
at 20 × 16 to control their proportions. Two species were renamed: overrides
|
|
173
|
+
called `blob_<frame>.png` or `chonk_<frame>.png` are no longer looked up and
|
|
174
|
+
need renaming to `jelly_<frame>.png` and `tabby_<frame>.png`.
|
|
175
|
+
|
|
176
|
+
## Preview and verification
|
|
177
|
+
|
|
178
|
+
Run `uv run python playground/buddy.py` to inspect all species. Space pauses;
|
|
179
|
+
`n`/`p` step ticks; `x` toggles petting; `s` toggles shiny; `t` cycles rarity;
|
|
180
|
+
`b` forces blinking; `r` resets; `q` quits.
|
|
181
|
+
|
|
182
|
+
Tests cover native dimensions and palettes, intact petting poses, pupil
|
|
183
|
+
contrast, animation timing, narrow pixel rendering, PNG cache invalidation and
|
|
184
|
+
mounted sidebar repaint behavior, plus the hatch draw, the progression curve,
|
|
185
|
+
the save file envelope and its concurrency, commands and replies.
|
|
186
|
+
`tests/app/tui/behaviors/test_buddy_sidebar_flow.py` drives `/buddy` through the
|
|
187
|
+
real command controller, view adapter and sidebar.
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
# Copyright (c) Huawei Technologies Co., Ltd. 2026. All rights reserved.
|
|
2
|
+
|
|
3
|
+
"""Hatching: one random draw, saved whole. Nothing about a buddy is derived from who the user is."""
|
|
4
|
+
|
|
5
|
+
from __future__ import annotations
|
|
6
|
+
|
|
7
|
+
from datetime import UTC, datetime
|
|
8
|
+
from typing import TYPE_CHECKING
|
|
9
|
+
|
|
10
|
+
from chrys.app.features.buddy.model import BuddyRecord, Rarity, Species, Trait
|
|
11
|
+
|
|
12
|
+
if TYPE_CHECKING:
|
|
13
|
+
from random import Random
|
|
14
|
+
|
|
15
|
+
RARITY_ODDS: dict[Rarity, int] = {Rarity.N: 55, Rarity.R: 30, Rarity.SR: 12, Rarity.SSR: 3}
|
|
16
|
+
|
|
17
|
+
SHINY_ODDS = 1 / 40
|
|
18
|
+
|
|
19
|
+
# The tier each species hatches in, by how far from the back garden you would have to go to meet one:
|
|
20
|
+
# N lives outside the window, R takes a trip, SR takes luck, SSR is not from around here at all.
|
|
21
|
+
# Evolution moves a buddy up; it never changes species.
|
|
22
|
+
SPECIES_RARITY: dict[Species, Rarity] = {
|
|
23
|
+
Species.ALIEN: Rarity.SSR,
|
|
24
|
+
Species.AXOLOTL: Rarity.SR,
|
|
25
|
+
Species.BAT: Rarity.R,
|
|
26
|
+
Species.BEE: Rarity.N,
|
|
27
|
+
Species.CACTUS: Rarity.R,
|
|
28
|
+
Species.CAPYBARA: Rarity.SR,
|
|
29
|
+
Species.CAT: Rarity.N,
|
|
30
|
+
Species.CRAB: Rarity.R,
|
|
31
|
+
Species.DRAGON: Rarity.SSR,
|
|
32
|
+
Species.DUCK: Rarity.N,
|
|
33
|
+
Species.FOX: Rarity.R,
|
|
34
|
+
Species.FROG: Rarity.N,
|
|
35
|
+
Species.GHOST: Rarity.SSR,
|
|
36
|
+
Species.GOOSE: Rarity.N,
|
|
37
|
+
Species.JELLY: Rarity.SR,
|
|
38
|
+
Species.LLAMA: Rarity.R,
|
|
39
|
+
Species.MUSHROOM: Rarity.N,
|
|
40
|
+
Species.OCTOPUS: Rarity.SR,
|
|
41
|
+
Species.OWL: Rarity.R,
|
|
42
|
+
Species.PANDA: Rarity.SR,
|
|
43
|
+
Species.PENGUIN: Rarity.R,
|
|
44
|
+
Species.RABBIT: Rarity.N,
|
|
45
|
+
Species.ROBOT: Rarity.SSR,
|
|
46
|
+
Species.SHARK: Rarity.R,
|
|
47
|
+
Species.SNAIL: Rarity.N,
|
|
48
|
+
Species.SNAKE: Rarity.N,
|
|
49
|
+
Species.TABBY: Rarity.N,
|
|
50
|
+
Species.TURTLE: Rarity.N,
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
# Trait points a hatchling of each tier has to share out. The largest possible share is half
|
|
54
|
+
# the budget (see _share_out), so no budget here can push a trait past its maximum.
|
|
55
|
+
TRAIT_POINTS: dict[Rarity, int] = {Rarity.N: 120, Rarity.R: 150, Rarity.SR: 180, Rarity.SSR: 200}
|
|
56
|
+
|
|
57
|
+
NAMES = ("Byte", "Dot", "Miso", "Mochi", "Nori", "Pico", "Pixel", "Sprout", "Tofu", "Widget")
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
def hatchling(rng: Random, *, now: datetime | None = None) -> BuddyRecord:
|
|
61
|
+
"""Draw a new buddy from *rng*."""
|
|
62
|
+
rarity = rng.choices(list(RARITY_ODDS), weights=list(RARITY_ODDS.values()))[0]
|
|
63
|
+
return BuddyRecord(
|
|
64
|
+
species=rng.choice([species for species, home in SPECIES_RARITY.items() if home is rarity]),
|
|
65
|
+
rarity=rarity,
|
|
66
|
+
shiny=rng.random() < SHINY_ODDS,
|
|
67
|
+
traits=_share_out(rng, TRAIT_POINTS[rarity]),
|
|
68
|
+
name=rng.choice(NAMES),
|
|
69
|
+
hatched_at=now if now is not None else datetime.now(UTC),
|
|
70
|
+
)
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
def _share_out(rng: Random, points: int) -> dict[Trait, int]:
|
|
74
|
+
"""Split *points* between the traits unevenly, so every buddy leans some way.
|
|
75
|
+
|
|
76
|
+
An appetite is at most three times another, which bounds a share between a tenth and a half of *points*.
|
|
77
|
+
"""
|
|
78
|
+
appetites = {trait: rng.uniform(0.5, 1.5) for trait in Trait}
|
|
79
|
+
unit = points / sum(appetites.values())
|
|
80
|
+
return {trait: round(appetite * unit) for trait, appetite in appetites.items()}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# Copyright (c) Huawei Technologies Co., Ltd. 2026. All rights reserved.
|
|
2
|
+
|
|
3
|
+
"""Buddy lifecycle callbacks for application entrypoints."""
|
|
4
|
+
|
|
5
|
+
from __future__ import annotations
|
|
6
|
+
|
|
7
|
+
import asyncio
|
|
8
|
+
import logging
|
|
9
|
+
from typing import TYPE_CHECKING
|
|
10
|
+
|
|
11
|
+
from chrys.app.features.buddy.actions import record_turn
|
|
12
|
+
|
|
13
|
+
if TYPE_CHECKING:
|
|
14
|
+
from chrys.app.features.buddy.model import Buddy
|
|
15
|
+
|
|
16
|
+
logger = logging.getLogger(__name__)
|
|
17
|
+
|
|
18
|
+
_FAILED = "Failed to credit the buddy with a turn"
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def on_successful_turn() -> None:
|
|
22
|
+
"""Credit the buddy with a finished turn. A buddy must never be why a turn fails, or why it waits.
|
|
23
|
+
|
|
24
|
+
Every frontend finishes its turns on the event loop, and crediting waits for the save file's
|
|
25
|
+
lock, which another instance may hold for seconds. So the write goes to the loop's default
|
|
26
|
+
executor, which the loop's runner joins at exit, and the turn goes on at once.
|
|
27
|
+
"""
|
|
28
|
+
try:
|
|
29
|
+
credit = asyncio.get_running_loop().run_in_executor(None, record_turn)
|
|
30
|
+
except Exception:
|
|
31
|
+
logger.debug(_FAILED, exc_info=True)
|
|
32
|
+
return
|
|
33
|
+
credit.add_done_callback(_log_a_failure)
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def _log_a_failure(credit: asyncio.Future[Buddy | None]) -> None:
|
|
37
|
+
if credit.cancelled():
|
|
38
|
+
return
|
|
39
|
+
failure = credit.exception()
|
|
40
|
+
if failure is not None:
|
|
41
|
+
logger.debug(_FAILED, exc_info=failure)
|