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,613 @@
|
|
|
1
|
+
# Copyright (c) Huawei Technologies Co., Ltd. 2026. All rights reserved.
|
|
2
|
+
|
|
3
|
+
"""LLM client factory — creates chat clients for supported providers.
|
|
4
|
+
|
|
5
|
+
Takes a ``ModelProfile`` (not ``Settings``) so each call site can pass
|
|
6
|
+
its own profile — main agent, sub-agent, approval judge, last-words
|
|
7
|
+
generator, recall-context call, buddy reply — without sharing global
|
|
8
|
+
env state. All HTTP transport, model id, headers, and credentials are
|
|
9
|
+
read from the profile.
|
|
10
|
+
|
|
11
|
+
Four provider types are supported:
|
|
12
|
+
|
|
13
|
+
- ``anthropic`` — native Anthropic API via Chrys' owned Anthropic wire client.
|
|
14
|
+
- ``openai`` — OpenAI Chat Completions or Responses API via Chrys' owned
|
|
15
|
+
OpenAI wire clients.
|
|
16
|
+
- ``deepseek-openai`` — DeepSeek via its OpenAI-compatible Chat Completions
|
|
17
|
+
or Responses endpoint; reuses the OpenAI HTTP transport and routes through
|
|
18
|
+
the DeepSeek variant of the Chat Completions or Responses client. Named
|
|
19
|
+
``deepseek-openai`` (not
|
|
20
|
+
``deepseek``) to make it explicit that this routes through the
|
|
21
|
+
OpenAI contract; a future native DeepSeek transport could be added
|
|
22
|
+
alongside it under a different id.
|
|
23
|
+
- ``glm-openai`` — GLM (Zhipu AI / z.ai) via its OpenAI-compatible Chat
|
|
24
|
+
Completions endpoint; routes through ``GlmChatCompletionsClient`` so
|
|
25
|
+
``reasoning_content`` is replayed on every multi-turn request per
|
|
26
|
+
z.ai's preserved-thinking contract — see ``chrys.service.llm.chat_completions``.
|
|
27
|
+
|
|
28
|
+
All four providers share the same chrys touch surfaces (request
|
|
29
|
+
reporting and intermediate text, ``function_invocation`` config, default
|
|
30
|
+
headers) so the engine, executor, approval judge, last-words, recall and
|
|
31
|
+
sub-agents behave identically regardless of provider. What differs per
|
|
32
|
+
provider id as plain data (credential and endpoint fallbacks, SDK family,
|
|
33
|
+
API styles) lives in ``chrys.service.llm.providers``.
|
|
34
|
+
"""
|
|
35
|
+
|
|
36
|
+
from __future__ import annotations
|
|
37
|
+
|
|
38
|
+
import logging
|
|
39
|
+
import os
|
|
40
|
+
import sys
|
|
41
|
+
from collections.abc import AsyncIterator, Awaitable, Callable
|
|
42
|
+
from contextlib import asynccontextmanager
|
|
43
|
+
from pathlib import Path
|
|
44
|
+
from typing import TYPE_CHECKING, Any
|
|
45
|
+
|
|
46
|
+
from chrys.foundation.util.chrys_headers import (
|
|
47
|
+
MODEL_ID_HEADER,
|
|
48
|
+
PARENT_SESSION_ID_HEADER,
|
|
49
|
+
SESSION_ID_HEADER,
|
|
50
|
+
X_PARENT_SESSION_ID_HEADER,
|
|
51
|
+
X_SESSION_ID_HEADER,
|
|
52
|
+
)
|
|
53
|
+
from chrys.foundation.util.env_templates import resolve_env_templates
|
|
54
|
+
from chrys.foundation.util.header_charset import (
|
|
55
|
+
api_key_charset_error,
|
|
56
|
+
header_name_charset_error,
|
|
57
|
+
header_value_charset_error,
|
|
58
|
+
model_id_charset_error,
|
|
59
|
+
)
|
|
60
|
+
from chrys.foundation.util.httpx_helpers import BYPASS_PROXY_MOUNTS
|
|
61
|
+
from chrys.foundation.util.once_close import OnceClose
|
|
62
|
+
from chrys.service.llm.providers import PROVIDERS, ProviderSpec
|
|
63
|
+
from chrys.service.profiles.models.options import parse_http_headers
|
|
64
|
+
from chrys.service.profiles.models.schema import ModelProfile
|
|
65
|
+
|
|
66
|
+
if TYPE_CHECKING:
|
|
67
|
+
import httpx
|
|
68
|
+
from anthropic import AsyncAnthropic
|
|
69
|
+
from openai import AsyncOpenAI
|
|
70
|
+
|
|
71
|
+
from chrys.kernel import ToolLoopLayer
|
|
72
|
+
from chrys.service.llm.wire_client import WireClient
|
|
73
|
+
|
|
74
|
+
_log = logging.getLogger(__name__)
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
def _build_user_agent(sdk_user_agent: str | None = None) -> str:
|
|
78
|
+
"""Return Chrys' HTTP user agent with optional provider SDK attribution."""
|
|
79
|
+
from chrys import __version__
|
|
80
|
+
|
|
81
|
+
runtime = sys.version_info
|
|
82
|
+
products = [
|
|
83
|
+
f"Chrys/{__version__}",
|
|
84
|
+
f"Python/{runtime.major}.{runtime.minor}.{runtime.micro}",
|
|
85
|
+
]
|
|
86
|
+
if sdk_user_agent:
|
|
87
|
+
products.append(sdk_user_agent)
|
|
88
|
+
return " ".join(products)
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
def _provider_sdk_user_agent(provider: str) -> str | None:
|
|
92
|
+
"""Return the provider SDK user-agent token Chrys would otherwise replace."""
|
|
93
|
+
spec = PROVIDERS.get(provider)
|
|
94
|
+
if spec is None:
|
|
95
|
+
return None
|
|
96
|
+
if spec.sdk == "anthropic":
|
|
97
|
+
import anthropic
|
|
98
|
+
|
|
99
|
+
return f"AsyncAnthropic/Python {anthropic.__version__}"
|
|
100
|
+
import openai
|
|
101
|
+
|
|
102
|
+
return f"AsyncOpenAI/Python {openai.__version__}"
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
def _build_default_headers(
|
|
106
|
+
session_id: str | None,
|
|
107
|
+
profile: ModelProfile,
|
|
108
|
+
*,
|
|
109
|
+
parent_session_id: str | None = None,
|
|
110
|
+
sdk_user_agent: str | None = None,
|
|
111
|
+
) -> dict[str, str]:
|
|
112
|
+
"""Build default HTTP headers for LLM client requests.
|
|
113
|
+
|
|
114
|
+
Includes chrys platform headers (client name, version, user agent,
|
|
115
|
+
``X-Session-ID``, ``Chrys-Session-Id``, optional parent-session headers,
|
|
116
|
+
and ``Chrys-Model-Id``) merged with the profile's ``http_headers`` (parsed
|
|
117
|
+
from JSON). Profile headers take precedence on key conflicts except for
|
|
118
|
+
Chrys-managed request metadata. The wire clients overwrite the model
|
|
119
|
+
header per request with the final provider ``model`` value.
|
|
120
|
+
"""
|
|
121
|
+
from chrys import __version__
|
|
122
|
+
|
|
123
|
+
headers: dict[str, str] = {
|
|
124
|
+
"User-Agent": _build_user_agent(sdk_user_agent),
|
|
125
|
+
"X-Client-Name": "chrys",
|
|
126
|
+
"X-Client-Version": __version__,
|
|
127
|
+
}
|
|
128
|
+
headers.update(parse_http_headers(profile))
|
|
129
|
+
if session_id:
|
|
130
|
+
headers[X_SESSION_ID_HEADER] = session_id
|
|
131
|
+
headers[SESSION_ID_HEADER] = session_id
|
|
132
|
+
if parent_session_id:
|
|
133
|
+
headers[X_PARENT_SESSION_ID_HEADER] = parent_session_id
|
|
134
|
+
headers[PARENT_SESSION_ID_HEADER] = parent_session_id
|
|
135
|
+
headers[MODEL_ID_HEADER] = profile.model_id
|
|
136
|
+
return headers
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
def _resolve_profile_api_key(profile: ModelProfile) -> str:
|
|
140
|
+
"""Resolve explicit API-key env templates before provider env fallback."""
|
|
141
|
+
return resolve_env_templates(profile.api_key, location=f"model profile {profile.name!r} API Key")
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
def _validate_wire_charset(profile: ModelProfile, *, api_key: str, headers: dict[str, str]) -> None:
|
|
145
|
+
"""Reject profile values that httpx cannot encode into HTTP headers.
|
|
146
|
+
|
|
147
|
+
Runs after ``{{ENV_VAR}}`` templates and the provider env-fallback
|
|
148
|
+
key resolve, so hand-edited YAML, environment credentials, and
|
|
149
|
+
template values are all covered — not only what the profile editor
|
|
150
|
+
validated at save time. Raising here turns what would surface as an
|
|
151
|
+
opaque ``UnicodeEncodeError`` inside the first chat request into a
|
|
152
|
+
configuration error that names the offending field, without echoing
|
|
153
|
+
secret content.
|
|
154
|
+
"""
|
|
155
|
+
problems: list[str] = []
|
|
156
|
+
spec = PROVIDERS.get(profile.provider)
|
|
157
|
+
effective_key = api_key or (os.environ.get(spec.api_key_env, "") if spec is not None else "")
|
|
158
|
+
key_error = api_key_charset_error(effective_key)
|
|
159
|
+
if key_error:
|
|
160
|
+
problems.append(key_error)
|
|
161
|
+
model_error = model_id_charset_error(profile.model_id)
|
|
162
|
+
if model_error:
|
|
163
|
+
problems.append(model_error)
|
|
164
|
+
for name, value in headers.items():
|
|
165
|
+
name_error = header_name_charset_error(name)
|
|
166
|
+
if name_error:
|
|
167
|
+
problems.append(name_error)
|
|
168
|
+
if name == MODEL_ID_HEADER:
|
|
169
|
+
# Mirrors ``profile.model_id`` — already reported above under
|
|
170
|
+
# its own field name.
|
|
171
|
+
continue
|
|
172
|
+
value_error = header_value_charset_error(name, value)
|
|
173
|
+
if value_error:
|
|
174
|
+
problems.append(value_error)
|
|
175
|
+
if problems:
|
|
176
|
+
raise ValueError(
|
|
177
|
+
f"Model profile {profile.name!r} has values that cannot be sent over HTTP: " + " ".join(problems)
|
|
178
|
+
)
|
|
179
|
+
|
|
180
|
+
|
|
181
|
+
def _validate_sdk_wire_charset(profile: ModelProfile, client: Any) -> None:
|
|
182
|
+
"""Reject unsafe static headers added internally by a provider SDK.
|
|
183
|
+
|
|
184
|
+
Both pinned SDKs add environment-derived values after Chrys supplies
|
|
185
|
+
``default_headers``: OpenAI organization/project/custom headers, and
|
|
186
|
+
Anthropic bearer/custom headers. Inspecting the constructed client's
|
|
187
|
+
effective static headers keeps those SDK-owned inputs behind the same
|
|
188
|
+
pre-request charset gate as profile-owned values. Non-string sentinels
|
|
189
|
+
such as OpenAI's ``Omit`` are ignored because the SDK removes them before
|
|
190
|
+
constructing ``httpx.Headers``.
|
|
191
|
+
"""
|
|
192
|
+
effective_headers = dict(client.auth_headers)
|
|
193
|
+
effective_headers.update(client.default_headers)
|
|
194
|
+
|
|
195
|
+
problems: list[str] = []
|
|
196
|
+
for name, value in effective_headers.items():
|
|
197
|
+
if not isinstance(name, str) or not isinstance(value, str):
|
|
198
|
+
continue
|
|
199
|
+
name_error = header_name_charset_error(name)
|
|
200
|
+
if name_error:
|
|
201
|
+
problems.append(name_error)
|
|
202
|
+
value_error = header_value_charset_error(name, value)
|
|
203
|
+
if value_error:
|
|
204
|
+
problems.append(value_error)
|
|
205
|
+
if problems:
|
|
206
|
+
raise ValueError(
|
|
207
|
+
f"Model profile {profile.name!r} has provider SDK headers that cannot be sent over HTTP: "
|
|
208
|
+
+ " ".join(problems)
|
|
209
|
+
)
|
|
210
|
+
|
|
211
|
+
|
|
212
|
+
async def _empty_openai_api_key_provider() -> str:
|
|
213
|
+
"""Return an empty key for unauthenticated OpenAI-compatible endpoints."""
|
|
214
|
+
return ""
|
|
215
|
+
|
|
216
|
+
|
|
217
|
+
def effective_model_base_url(profile: ModelProfile) -> str:
|
|
218
|
+
"""Return the base URL the provider client will use for display/provenance."""
|
|
219
|
+
provider = profile.provider.lower()
|
|
220
|
+
if provider == "mock":
|
|
221
|
+
return profile.base_url
|
|
222
|
+
spec = PROVIDERS.get(provider)
|
|
223
|
+
if spec is None:
|
|
224
|
+
raise _unknown_provider(provider)
|
|
225
|
+
return profile.base_url or os.environ.get(spec.base_url_env, "") or spec.default_base_url
|
|
226
|
+
|
|
227
|
+
|
|
228
|
+
def _build_profile_http_client(
|
|
229
|
+
profile: ModelProfile,
|
|
230
|
+
timeout: Any,
|
|
231
|
+
*,
|
|
232
|
+
raw_http_log_path: Path | None = None,
|
|
233
|
+
session_id: str | None = None,
|
|
234
|
+
transport: httpx.AsyncBaseTransport | None = None,
|
|
235
|
+
) -> httpx.AsyncClient:
|
|
236
|
+
"""Build the profile's ``httpx.AsyncClient``; Chrys, not the SDK, owns every pool.
|
|
237
|
+
|
|
238
|
+
Uses the provider SDK's public ``DefaultAsyncHttpxClient`` so a default
|
|
239
|
+
profile keeps the SDK's own pool limits, redirects and (Anthropic) TCP
|
|
240
|
+
keepalive socket options. When proxy bypass is enabled, explicit ``None``
|
|
241
|
+
mounts override httpx's environment-derived proxy transports while
|
|
242
|
+
leaving ``trust_env=True`` in place for CA bundle env such as
|
|
243
|
+
``SSL_CERT_FILE``.
|
|
244
|
+
|
|
245
|
+
Route hooks come first on both lists, so every request carries its route
|
|
246
|
+
snapshot before any other hook (the raw HTTP log) runs or fails.
|
|
247
|
+
|
|
248
|
+
*transport* replaces the network transport and nothing else; production
|
|
249
|
+
callers never pass it, the client contract tests answer through it.
|
|
250
|
+
"""
|
|
251
|
+
spec = PROVIDERS.get(profile.provider)
|
|
252
|
+
if spec is not None and spec.sdk == "anthropic":
|
|
253
|
+
from anthropic import DefaultAsyncHttpxClient as HTTPClient
|
|
254
|
+
else:
|
|
255
|
+
from openai import DefaultAsyncHttpxClient as HTTPClient
|
|
256
|
+
|
|
257
|
+
from chrys.service.llm.proxy_route import ProxyRouter
|
|
258
|
+
from chrys.service.llm.route_facts import build_route_hooks
|
|
259
|
+
|
|
260
|
+
kwargs: dict[str, Any] = {
|
|
261
|
+
"verify": profile.verify_ssl,
|
|
262
|
+
"timeout": timeout,
|
|
263
|
+
"follow_redirects": True,
|
|
264
|
+
}
|
|
265
|
+
if profile.bypass_proxy:
|
|
266
|
+
kwargs["mounts"] = dict(BYPASS_PROXY_MOUNTS)
|
|
267
|
+
event_hooks = build_route_hooks(ProxyRouter.from_client_config(bypass_proxy=profile.bypass_proxy))
|
|
268
|
+
if raw_http_log_path is not None:
|
|
269
|
+
from chrys.service.llm.raw_http_log import build_raw_http_event_hooks
|
|
270
|
+
|
|
271
|
+
raw_hooks = build_raw_http_event_hooks(
|
|
272
|
+
log_path=raw_http_log_path,
|
|
273
|
+
profile=profile,
|
|
274
|
+
session_id=session_id,
|
|
275
|
+
)
|
|
276
|
+
for event in ("request", "response"):
|
|
277
|
+
event_hooks[event] = [*event_hooks[event], *raw_hooks.get(event, ())]
|
|
278
|
+
kwargs["event_hooks"] = event_hooks
|
|
279
|
+
if transport is not None:
|
|
280
|
+
kwargs["transport"] = transport
|
|
281
|
+
return HTTPClient(**kwargs)
|
|
282
|
+
|
|
283
|
+
|
|
284
|
+
def _build_anthropic_sdk_client(
|
|
285
|
+
*,
|
|
286
|
+
api_key: str,
|
|
287
|
+
base_url: str,
|
|
288
|
+
timeout: Any,
|
|
289
|
+
max_retries: int,
|
|
290
|
+
default_headers: dict[str, str] | None,
|
|
291
|
+
http_client: Any | None = None,
|
|
292
|
+
) -> AsyncAnthropic:
|
|
293
|
+
"""Create a pre-configured ``AsyncAnthropic`` client.
|
|
294
|
+
|
|
295
|
+
``api_key`` and ``base_url`` are passed explicitly when set so the
|
|
296
|
+
profile wins over any process-level env (the SDK falls back to
|
|
297
|
+
``ANTHROPIC_API_KEY`` / ``ANTHROPIC_BASE_URL`` only when the kwargs
|
|
298
|
+
are absent).
|
|
299
|
+
"""
|
|
300
|
+
from chrys.service.llm.sdk_anthropic import RetryGuardedAsyncAnthropic
|
|
301
|
+
|
|
302
|
+
kwargs: dict[str, Any] = {
|
|
303
|
+
"timeout": timeout,
|
|
304
|
+
"max_retries": max_retries,
|
|
305
|
+
"default_headers": default_headers,
|
|
306
|
+
}
|
|
307
|
+
if http_client is not None:
|
|
308
|
+
kwargs["http_client"] = http_client
|
|
309
|
+
if api_key:
|
|
310
|
+
kwargs["api_key"] = api_key
|
|
311
|
+
if base_url:
|
|
312
|
+
kwargs["base_url"] = base_url
|
|
313
|
+
return RetryGuardedAsyncAnthropic(**kwargs)
|
|
314
|
+
|
|
315
|
+
|
|
316
|
+
def _build_openai_sdk_client(
|
|
317
|
+
*,
|
|
318
|
+
api_key: str,
|
|
319
|
+
base_url: str,
|
|
320
|
+
timeout: Any,
|
|
321
|
+
max_retries: int,
|
|
322
|
+
default_headers: dict[str, str] | None,
|
|
323
|
+
http_client: Any | None = None,
|
|
324
|
+
api_key_env: str = "OPENAI_API_KEY",
|
|
325
|
+
base_url_env: str = "OPENAI_BASE_URL",
|
|
326
|
+
default_base_url: str = "",
|
|
327
|
+
) -> AsyncOpenAI:
|
|
328
|
+
"""Create a pre-configured ``AsyncOpenAI`` client.
|
|
329
|
+
|
|
330
|
+
``api_key`` and ``base_url`` come from the profile when set;
|
|
331
|
+
otherwise they fall back to ``api_key_env`` / ``base_url_env`` from
|
|
332
|
+
the environment, finally to ``default_base_url`` for the base URL.
|
|
333
|
+
OpenAI-compatible providers pass their own env names and default
|
|
334
|
+
base URL, so the SDK reads ``OPENAI_API_KEY`` only for OpenAI itself.
|
|
335
|
+
"""
|
|
336
|
+
from chrys.service.llm.sdk_openai import RetryGuardedAsyncOpenAI
|
|
337
|
+
|
|
338
|
+
# Newer OpenAI SDKs require the client to receive an api_key argument
|
|
339
|
+
# unless the provider env var is present. When neither exists, pass an
|
|
340
|
+
# explicit provider that resolves to an empty key. This avoids
|
|
341
|
+
# construction-time credential errors while preserving no-auth behavior
|
|
342
|
+
# for unauthenticated OpenAI-compatible local/gateway endpoints.
|
|
343
|
+
effective_key: str | Callable[[], Awaitable[str]] = (
|
|
344
|
+
api_key or os.environ.get(api_key_env) or _empty_openai_api_key_provider
|
|
345
|
+
)
|
|
346
|
+
effective_base = base_url or os.environ.get(base_url_env) or default_base_url or None
|
|
347
|
+
|
|
348
|
+
kwargs: dict[str, Any] = {
|
|
349
|
+
"api_key": effective_key,
|
|
350
|
+
"timeout": timeout,
|
|
351
|
+
"max_retries": max_retries,
|
|
352
|
+
"default_headers": default_headers,
|
|
353
|
+
}
|
|
354
|
+
if http_client is not None:
|
|
355
|
+
kwargs["http_client"] = http_client
|
|
356
|
+
if effective_base:
|
|
357
|
+
kwargs["base_url"] = effective_base
|
|
358
|
+
return RetryGuardedAsyncOpenAI(**kwargs)
|
|
359
|
+
|
|
360
|
+
|
|
361
|
+
async def create_client(
|
|
362
|
+
profile: ModelProfile,
|
|
363
|
+
on_intermediate_text_async: Callable[[str], Awaitable[None]] | None = None,
|
|
364
|
+
on_intermediate_text_sync: Callable[[str], None] | None = None,
|
|
365
|
+
session_id: str | None = None,
|
|
366
|
+
parent_session_id: str | None = None,
|
|
367
|
+
use_route_session_context: bool = False,
|
|
368
|
+
session_dir: Path | None = None,
|
|
369
|
+
tool_result_ceiling_tokens: int | None = None,
|
|
370
|
+
) -> Any:
|
|
371
|
+
"""Create a chat client stack based on the configured ``ModelProfile``.
|
|
372
|
+
|
|
373
|
+
The factory rolls back its own failures: once the HTTP client exists,
|
|
374
|
+
any later failure (SDK construction, SDK header validation, stack
|
|
375
|
+
assembly, cancellation) closes it before the error propagates. After a
|
|
376
|
+
successful return the caller owns the stack and must register
|
|
377
|
+
``client.aclose`` with its one close owner before its next ``await``.
|
|
378
|
+
|
|
379
|
+
Args:
|
|
380
|
+
profile: The ``ModelProfile`` to bind this client to. Provides
|
|
381
|
+
provider, model id, HTTP transport tuning, headers, and
|
|
382
|
+
credentials.
|
|
383
|
+
on_intermediate_text_async: Async callback for **non-streaming** mode.
|
|
384
|
+
Awaited when the LLM returns text alongside tool calls,
|
|
385
|
+
enabling real-time rendering of intermediate agent messages.
|
|
386
|
+
on_intermediate_text_sync: Sync callback for **streaming** mode.
|
|
387
|
+
Called from a ``result_hook`` after the stream finalizes.
|
|
388
|
+
Must not block — typically stores text in an
|
|
389
|
+
``IntermediateTextBuffer``.
|
|
390
|
+
session_id: Current session ID for the ``X-Session-ID`` and
|
|
391
|
+
``Chrys-Session-Id`` headers.
|
|
392
|
+
parent_session_id: Optional parent session ID for sub-agent LLM
|
|
393
|
+
requests. Sent as ``X-Parent-Session-ID`` and
|
|
394
|
+
``Chrys-Parent-Session-Id``.
|
|
395
|
+
use_route_session_context: Whether the wire client should prefer
|
|
396
|
+
per-invocation route-session ContextVars over its default
|
|
397
|
+
session ids. Intended for shared sub-agent clients.
|
|
398
|
+
session_dir: Optional active session directory. Used by raw HTTP
|
|
399
|
+
logging so tests and custom stores can keep logs beside the
|
|
400
|
+
session artifacts.
|
|
401
|
+
tool_result_ceiling_tokens: Optional kernel backstop for local tool results.
|
|
402
|
+
|
|
403
|
+
Returns:
|
|
404
|
+
A chat client stack compatible with Chrys' kernel runtime; closing it
|
|
405
|
+
(``aclose``) closes the provider SDK client and its HTTP pool.
|
|
406
|
+
"""
|
|
407
|
+
provider = profile.provider
|
|
408
|
+
# Tool-loop knobs for ToolLoopLayer. Intentional headroom on iterations:
|
|
409
|
+
# long autonomous sessions can chain many tool calls.
|
|
410
|
+
stack_kwargs: dict[str, Any] = {
|
|
411
|
+
"on_intermediate_text_async": on_intermediate_text_async,
|
|
412
|
+
"on_intermediate_text_sync": on_intermediate_text_sync,
|
|
413
|
+
"tool_result_ceiling_tokens": tool_result_ceiling_tokens,
|
|
414
|
+
}
|
|
415
|
+
if provider == "mock":
|
|
416
|
+
from chrys.service.llm.mock import MockChatClient
|
|
417
|
+
|
|
418
|
+
return MockChatClient(**stack_kwargs)
|
|
419
|
+
spec = PROVIDERS.get(provider)
|
|
420
|
+
if spec is None:
|
|
421
|
+
raise _unknown_provider(provider)
|
|
422
|
+
|
|
423
|
+
api_key = _resolve_profile_api_key(profile)
|
|
424
|
+
headers = _build_default_headers(
|
|
425
|
+
session_id,
|
|
426
|
+
profile,
|
|
427
|
+
parent_session_id=parent_session_id,
|
|
428
|
+
sdk_user_agent=_provider_sdk_user_agent(provider),
|
|
429
|
+
)
|
|
430
|
+
_validate_wire_charset(profile, api_key=api_key, headers=headers)
|
|
431
|
+
|
|
432
|
+
import httpx
|
|
433
|
+
|
|
434
|
+
timeout = httpx.Timeout(
|
|
435
|
+
connect=profile.http_connect_timeout,
|
|
436
|
+
read=profile.http_read_timeout,
|
|
437
|
+
write=profile.http_read_timeout,
|
|
438
|
+
pool=profile.http_read_timeout,
|
|
439
|
+
)
|
|
440
|
+
from chrys.service.llm.raw_http_log import raw_http_log_path as resolve_raw_http_log_path
|
|
441
|
+
|
|
442
|
+
http_client = _build_profile_http_client(
|
|
443
|
+
profile,
|
|
444
|
+
timeout,
|
|
445
|
+
raw_http_log_path=resolve_raw_http_log_path(session_id, session_dir),
|
|
446
|
+
session_id=session_id,
|
|
447
|
+
)
|
|
448
|
+
close_http_client = OnceClose(http_client.aclose)
|
|
449
|
+
stack_kwargs.update(
|
|
450
|
+
model_id=profile.model_id,
|
|
451
|
+
session_id=session_id,
|
|
452
|
+
parent_session_id=parent_session_id,
|
|
453
|
+
use_route_session_context=use_route_session_context,
|
|
454
|
+
max_iterations=7777,
|
|
455
|
+
max_consecutive_errors=10,
|
|
456
|
+
)
|
|
457
|
+
try:
|
|
458
|
+
return _build_client_stack(
|
|
459
|
+
profile,
|
|
460
|
+
spec,
|
|
461
|
+
api_key=api_key,
|
|
462
|
+
headers=headers,
|
|
463
|
+
timeout=timeout,
|
|
464
|
+
http_client=http_client,
|
|
465
|
+
stack_kwargs=stack_kwargs,
|
|
466
|
+
)
|
|
467
|
+
except BaseException:
|
|
468
|
+
try:
|
|
469
|
+
await close_http_client()
|
|
470
|
+
except Exception:
|
|
471
|
+
_log.warning("Closing the HTTP client of a failed %s client build failed", provider, exc_info=True)
|
|
472
|
+
raise
|
|
473
|
+
|
|
474
|
+
|
|
475
|
+
def _unknown_provider(provider: str) -> ValueError:
|
|
476
|
+
return ValueError(
|
|
477
|
+
f"Unknown provider: {provider!r}. Use 'anthropic', 'openai', 'deepseek-openai', 'glm-openai', or 'mock'."
|
|
478
|
+
)
|
|
479
|
+
|
|
480
|
+
|
|
481
|
+
def _build_client_stack(
|
|
482
|
+
profile: ModelProfile,
|
|
483
|
+
spec: ProviderSpec,
|
|
484
|
+
*,
|
|
485
|
+
api_key: str,
|
|
486
|
+
headers: dict[str, str],
|
|
487
|
+
timeout: Any,
|
|
488
|
+
http_client: httpx.AsyncClient,
|
|
489
|
+
stack_kwargs: dict[str, Any],
|
|
490
|
+
) -> ToolLoopLayer:
|
|
491
|
+
"""Build the provider SDK client over *http_client* and wrap it in the Chrys stack."""
|
|
492
|
+
sdk_kwargs: dict[str, Any] = {
|
|
493
|
+
"api_key": api_key,
|
|
494
|
+
"base_url": profile.base_url,
|
|
495
|
+
"timeout": timeout,
|
|
496
|
+
"max_retries": profile.http_max_retries,
|
|
497
|
+
"default_headers": headers,
|
|
498
|
+
"http_client": http_client,
|
|
499
|
+
}
|
|
500
|
+
sdk_client: AsyncAnthropic | AsyncOpenAI
|
|
501
|
+
if spec.sdk == "anthropic":
|
|
502
|
+
sdk_client = _build_anthropic_sdk_client(**sdk_kwargs)
|
|
503
|
+
else:
|
|
504
|
+
sdk_client = _build_openai_sdk_client(
|
|
505
|
+
**sdk_kwargs,
|
|
506
|
+
api_key_env=spec.api_key_env,
|
|
507
|
+
base_url_env=spec.base_url_env,
|
|
508
|
+
default_base_url="" if spec.native_sdk else spec.default_base_url,
|
|
509
|
+
)
|
|
510
|
+
_validate_sdk_wire_charset(profile, sdk_client)
|
|
511
|
+
client_cls = _wire_client_class(profile.provider, _api_style(profile, spec))
|
|
512
|
+
return _assemble_stack(client_cls, sdk_client, **stack_kwargs)
|
|
513
|
+
|
|
514
|
+
|
|
515
|
+
def _api_style(profile: ModelProfile, spec: ProviderSpec) -> str | None:
|
|
516
|
+
"""The profile's API style, or None for a provider that speaks only one."""
|
|
517
|
+
if spec.api_styles is None:
|
|
518
|
+
return None
|
|
519
|
+
if profile.api_style not in spec.api_styles:
|
|
520
|
+
raise ValueError(
|
|
521
|
+
f"Unknown {spec.label} api_style: {profile.api_style!r}. Use 'chat_completions' or 'responses'."
|
|
522
|
+
)
|
|
523
|
+
return profile.api_style
|
|
524
|
+
|
|
525
|
+
|
|
526
|
+
def _wire_client_class(provider: str, api_style: str | None) -> type[WireClient]:
|
|
527
|
+
"""The wire client class for one provider and API style, imported on demand."""
|
|
528
|
+
match provider, api_style:
|
|
529
|
+
case "anthropic", None:
|
|
530
|
+
from chrys.service.llm.anthropic_messages import AnthropicMessagesClient
|
|
531
|
+
|
|
532
|
+
return AnthropicMessagesClient
|
|
533
|
+
case "openai", "chat_completions":
|
|
534
|
+
from chrys.service.llm.chat_completions import ChatCompletionsClient
|
|
535
|
+
|
|
536
|
+
return ChatCompletionsClient
|
|
537
|
+
case "openai", "responses":
|
|
538
|
+
from chrys.service.llm.openai_responses import ResponsesApiClient
|
|
539
|
+
|
|
540
|
+
return ResponsesApiClient
|
|
541
|
+
case "deepseek-openai", "chat_completions":
|
|
542
|
+
from chrys.service.llm.chat_completions import DeepSeekChatCompletionsClient
|
|
543
|
+
|
|
544
|
+
return DeepSeekChatCompletionsClient
|
|
545
|
+
case "deepseek-openai", "responses":
|
|
546
|
+
from chrys.service.llm.openai_responses import DeepSeekResponsesApiClient
|
|
547
|
+
|
|
548
|
+
return DeepSeekResponsesApiClient
|
|
549
|
+
case "glm-openai", None:
|
|
550
|
+
from chrys.service.llm.chat_completions import GlmChatCompletionsClient
|
|
551
|
+
|
|
552
|
+
return GlmChatCompletionsClient
|
|
553
|
+
case _:
|
|
554
|
+
# A provider with a table entry but no wire client: never build
|
|
555
|
+
# another provider's client for it.
|
|
556
|
+
raise _unknown_provider(provider)
|
|
557
|
+
|
|
558
|
+
|
|
559
|
+
def _assemble_stack(
|
|
560
|
+
client_cls: type[WireClient],
|
|
561
|
+
sdk_client: AsyncAnthropic | AsyncOpenAI,
|
|
562
|
+
*,
|
|
563
|
+
model_id: str,
|
|
564
|
+
session_id: str | None,
|
|
565
|
+
parent_session_id: str | None,
|
|
566
|
+
use_route_session_context: bool,
|
|
567
|
+
on_intermediate_text_async: Callable[[str], Awaitable[None]] | None,
|
|
568
|
+
on_intermediate_text_sync: Callable[[str], None] | None,
|
|
569
|
+
max_iterations: int,
|
|
570
|
+
max_consecutive_errors: int,
|
|
571
|
+
tool_result_ceiling_tokens: int | None,
|
|
572
|
+
) -> ToolLoopLayer:
|
|
573
|
+
"""Wrap the wire client over *sdk_client* in the chrys loop + chat-middleware stack.
|
|
574
|
+
|
|
575
|
+
Every call path — the main agent, judges, last-words, recall and
|
|
576
|
+
compression, sub-agents — gets the same request headers, reporting and
|
|
577
|
+
telemetry, whether or not it asks for intermediate text.
|
|
578
|
+
"""
|
|
579
|
+
from chrys.kernel import ChatMiddlewareLayer, ToolLoopLayer
|
|
580
|
+
from chrys.service.llm.observer import WireCallObserver
|
|
581
|
+
from chrys.service.llm.wire_client import RequestHeaders
|
|
582
|
+
|
|
583
|
+
# Any, not SupportsChatInner: the telemetry layer's get_response names the
|
|
584
|
+
# keywords the middleware layer passes instead of taking **kwargs.
|
|
585
|
+
wire_client: Any = client_cls.from_sdk_client(
|
|
586
|
+
sdk_client,
|
|
587
|
+
model=model_id,
|
|
588
|
+
observer=WireCallObserver(
|
|
589
|
+
on_intermediate_text_async=on_intermediate_text_async,
|
|
590
|
+
on_intermediate_text_sync=on_intermediate_text_sync,
|
|
591
|
+
),
|
|
592
|
+
request_headers=RequestHeaders(
|
|
593
|
+
session_id=session_id,
|
|
594
|
+
parent_session_id=parent_session_id,
|
|
595
|
+
use_route_session_context=use_route_session_context,
|
|
596
|
+
),
|
|
597
|
+
)
|
|
598
|
+
return ToolLoopLayer(
|
|
599
|
+
ChatMiddlewareLayer(wire_client),
|
|
600
|
+
max_iterations=max_iterations,
|
|
601
|
+
max_consecutive_errors=max_consecutive_errors,
|
|
602
|
+
tool_result_ceiling_tokens=tool_result_ceiling_tokens,
|
|
603
|
+
)
|
|
604
|
+
|
|
605
|
+
|
|
606
|
+
@asynccontextmanager
|
|
607
|
+
async def scoped_client(profile: ModelProfile, **kwargs: Any) -> AsyncIterator[Any]:
|
|
608
|
+
"""Create a client stack for one bounded use and close it on every exit."""
|
|
609
|
+
client = await create_client(profile, **kwargs)
|
|
610
|
+
try:
|
|
611
|
+
yield client
|
|
612
|
+
finally:
|
|
613
|
+
await client.aclose()
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
# Copyright (c) Huawei Technologies Co., Ltd. 2026. All rights reserved.
|
|
2
|
+
|
|
3
|
+
"""Images as the model APIs accept them, for every wire protocol's history encoder.
|
|
4
|
+
|
|
5
|
+
An image in a format the APIs don't read (BMP, SVG, HEIC, a mislabelled
|
|
6
|
+
file) goes out as :data:`UNSUPPORTED_IMAGE_TEXT` instead, so one bad image
|
|
7
|
+
doesn't fail every later request of the session. Stored history keeps the
|
|
8
|
+
image as it is.
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
from __future__ import annotations
|
|
12
|
+
|
|
13
|
+
import base64
|
|
14
|
+
import binascii
|
|
15
|
+
from dataclasses import dataclass
|
|
16
|
+
from typing import TYPE_CHECKING, Final
|
|
17
|
+
|
|
18
|
+
from chrys.foundation.text.images import wire_image_media_type
|
|
19
|
+
|
|
20
|
+
if TYPE_CHECKING:
|
|
21
|
+
from chrys.kernel import Content
|
|
22
|
+
|
|
23
|
+
UNSUPPORTED_IMAGE_TEXT: Final = "[Image omitted: unsupported or invalid image data. Use PNG, JPEG, GIF, or WebP.]"
|
|
24
|
+
|
|
25
|
+
# Base64 characters that decode to the 12 bytes every image signature fits in.
|
|
26
|
+
_SIGNATURE_CHARS: Final = 16
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
@dataclass(frozen=True, slots=True)
|
|
30
|
+
class WireImage:
|
|
31
|
+
"""An image as one request sends it."""
|
|
32
|
+
|
|
33
|
+
media_type: str
|
|
34
|
+
uri: str
|
|
35
|
+
"""A data URI naming :attr:`media_type`, or the image's URL."""
|
|
36
|
+
data: str | None
|
|
37
|
+
"""The base64 payload of a data URI; None for a URL."""
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def wire_image(content: Content) -> WireImage | None:
|
|
41
|
+
"""*content*'s image as model APIs accept it; None when they would reject it.
|
|
42
|
+
|
|
43
|
+
The bytes of a data URI decide its type, whatever the content declares;
|
|
44
|
+
only their leading bytes are read, since the payload was encoded or
|
|
45
|
+
checked where it entered. An http(s) URL keeps its declared type when that
|
|
46
|
+
is one the APIs read; the APIs can't fetch any other URL (``file://``).
|
|
47
|
+
"""
|
|
48
|
+
uri = content.uri
|
|
49
|
+
if not isinstance(uri, str):
|
|
50
|
+
return None
|
|
51
|
+
if not uri.startswith("data:"):
|
|
52
|
+
if not uri.lower().startswith(("http://", "https://")):
|
|
53
|
+
return None
|
|
54
|
+
media_type = wire_image_media_type(None, content.media_type)
|
|
55
|
+
return WireImage(media_type, uri, None) if media_type is not None else None
|
|
56
|
+
header, separator, payload = uri.partition(",")
|
|
57
|
+
if not separator or not header.endswith(";base64"):
|
|
58
|
+
return None
|
|
59
|
+
try:
|
|
60
|
+
leading = base64.b64decode(payload[:_SIGNATURE_CHARS], validate=True)
|
|
61
|
+
except binascii.Error, ValueError:
|
|
62
|
+
return None
|
|
63
|
+
if (media_type := wire_image_media_type(leading, content.media_type)) is None:
|
|
64
|
+
return None
|
|
65
|
+
return WireImage(media_type, f"data:{media_type};base64,{payload}", payload)
|