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,657 @@
|
|
|
1
|
+
# Copyright (c) Microsoft. All rights reserved.
|
|
2
|
+
# Copyright (c) Huawei Technologies Co., Ltd. 2026. All rights reserved.
|
|
3
|
+
# Contains code adapted from Microsoft Agent Framework (MIT License; see NOTICE).
|
|
4
|
+
|
|
5
|
+
"""Chat history encoded as Chat Completions messages.
|
|
6
|
+
|
|
7
|
+
One kernel message can become several wire messages: a tool result is a
|
|
8
|
+
``tool`` record of its own, and the images tool results return follow them
|
|
9
|
+
in one user message. History written by another provider's hosted tools is
|
|
10
|
+
first reduced to text this wire can carry.
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
from __future__ import annotations
|
|
14
|
+
|
|
15
|
+
import json
|
|
16
|
+
import logging
|
|
17
|
+
import re
|
|
18
|
+
from collections.abc import Mapping, Sequence
|
|
19
|
+
from typing import TYPE_CHECKING, Any, cast
|
|
20
|
+
|
|
21
|
+
from chrys.foundation.text.model_json import model_json
|
|
22
|
+
from chrys.kernel import TOOL_CALL_CONTENT_TYPES, Content, Message, is_image_content
|
|
23
|
+
from chrys.service.agent_middleware.events.hosted_tools import cross_provider_hosted_degradations
|
|
24
|
+
from chrys.service.llm.images import UNSUPPORTED_IMAGE_TEXT, WireImage, wire_image
|
|
25
|
+
from chrys.service.text_blocks import join_text_blocks, reconstruct_text_blocks, text_block_id
|
|
26
|
+
|
|
27
|
+
from .reasoning import (
|
|
28
|
+
REASONING_FIELDS,
|
|
29
|
+
contribution,
|
|
30
|
+
fold,
|
|
31
|
+
pad_reasoning_content,
|
|
32
|
+
replayable_fields,
|
|
33
|
+
replays_reasoning,
|
|
34
|
+
stored_reasoning,
|
|
35
|
+
)
|
|
36
|
+
|
|
37
|
+
if TYPE_CHECKING:
|
|
38
|
+
from chrys.foundation.reasoning_origin import ReasoningOrigin
|
|
39
|
+
|
|
40
|
+
from .client import ChatCompletionsVariant
|
|
41
|
+
|
|
42
|
+
logger = logging.getLogger(__name__)
|
|
43
|
+
|
|
44
|
+
# Request-local keys: the images a tool result returned, waiting for the user
|
|
45
|
+
# message after the results, and the marker on a hosted-history summary.
|
|
46
|
+
_PENDING_IMAGES = "_chrys_pending_image_parts"
|
|
47
|
+
_HOSTED_SUMMARY = "_chrys_hosted_context_summary"
|
|
48
|
+
|
|
49
|
+
# OpenAI checks ``name`` against ``^[^\s<|\\/>]+$`` with at most 64 characters.
|
|
50
|
+
# CJK and hyphens pass, so only the characters the rule forbids are removed.
|
|
51
|
+
_FORBIDDEN_NAME_CHARS = re.compile(r"[\s<|\\/>]+")
|
|
52
|
+
|
|
53
|
+
_AUDIO_FORMATS = ("wav", "mp3")
|
|
54
|
+
|
|
55
|
+
# What the model reads in place of media this wire has no part for.
|
|
56
|
+
_UNSUPPORTED_MEDIA_TEXT = "[{media_type} content omitted: the Chat Completions API does not accept it.]"
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
def sanitize_author_name(name: str | None) -> str | None:
|
|
60
|
+
"""The author name as a valid ``name`` field; ``None`` when nothing valid is left.
|
|
61
|
+
|
|
62
|
+
Callers then omit the field instead of sending ``""``.
|
|
63
|
+
"""
|
|
64
|
+
if not name:
|
|
65
|
+
return None
|
|
66
|
+
return _FORBIDDEN_NAME_CHARS.sub("", name)[:64] or None
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
def encode_messages(
|
|
70
|
+
messages: Sequence[Message],
|
|
71
|
+
*,
|
|
72
|
+
variant: ChatCompletionsVariant,
|
|
73
|
+
request_has_tools: bool = False,
|
|
74
|
+
origin: ReasoningOrigin | None = None,
|
|
75
|
+
) -> list[dict[str, Any]]:
|
|
76
|
+
"""The request's ``messages``, sent to the endpoint *origin*.
|
|
77
|
+
|
|
78
|
+
Each kernel message is encoded and canonicalized on its own, so the
|
|
79
|
+
fragments of different messages never merge.
|
|
80
|
+
"""
|
|
81
|
+
messages = degrade_hosted_history(messages)
|
|
82
|
+
replay = replays_reasoning(messages, variant=variant, request_has_tools=request_has_tools)
|
|
83
|
+
wire = [
|
|
84
|
+
part
|
|
85
|
+
for message in messages
|
|
86
|
+
for part in canonicalize_tool_call_messages(
|
|
87
|
+
encode_message(message, variant=variant, replay_reasoning=replay, origin=origin)
|
|
88
|
+
)
|
|
89
|
+
]
|
|
90
|
+
if replay and variant.reasoning_with_tools:
|
|
91
|
+
pad_reasoning_content(wire)
|
|
92
|
+
return insert_image_messages(wire)
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
def encode_message(
|
|
96
|
+
message: Message,
|
|
97
|
+
*,
|
|
98
|
+
variant: ChatCompletionsVariant,
|
|
99
|
+
replay_reasoning: bool = True,
|
|
100
|
+
origin: ReasoningOrigin | None = None,
|
|
101
|
+
) -> list[dict[str, Any]]:
|
|
102
|
+
"""The wire messages for one kernel message, before canonicalization, sent to the endpoint *origin*."""
|
|
103
|
+
if message.role in ("system", "developer"):
|
|
104
|
+
# A plain string: some compatible endpoints reject a list for these
|
|
105
|
+
# roles. Reasoning never replays on them.
|
|
106
|
+
texts = [content.text for content in message.contents if content.type == "text" and content.text]
|
|
107
|
+
if not texts:
|
|
108
|
+
return []
|
|
109
|
+
instruction: dict[str, Any] = {"role": message.role, "content": "\n".join(texts)}
|
|
110
|
+
if name := sanitize_author_name(message.author_name):
|
|
111
|
+
instruction["name"] = name
|
|
112
|
+
return [instruction]
|
|
113
|
+
if replay_reasoning and message.role == "assistant" and replayable_fields(message, origin=origin):
|
|
114
|
+
return encode_reasoning_message(message, origin=origin)
|
|
115
|
+
if variant.strict_messages:
|
|
116
|
+
return _strict_messages(message)
|
|
117
|
+
return _standard_messages(message, replay_reasoning=replay_reasoning, origin=origin)
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
def _standard_messages(
|
|
121
|
+
message: Message, *, replay_reasoning: bool, origin: ReasoningOrigin | None
|
|
122
|
+
) -> list[dict[str, Any]]:
|
|
123
|
+
"""One wire message per content; calls in a row share one message.
|
|
124
|
+
|
|
125
|
+
Replayed reasoning rides the next message with content or calls, and the
|
|
126
|
+
copy kept in the message properties rides every one.
|
|
127
|
+
"""
|
|
128
|
+
stored = stored_reasoning(message, origin=origin) if replay_reasoning else {}
|
|
129
|
+
wire: list[dict[str, Any]] = []
|
|
130
|
+
pending: dict[str, Any] = {}
|
|
131
|
+
for content in message.contents:
|
|
132
|
+
if content.type == "text_reasoning":
|
|
133
|
+
if replay_reasoning and (found := contribution(content, origin=origin)) is not None:
|
|
134
|
+
fold(pending, *found)
|
|
135
|
+
continue
|
|
136
|
+
if content.type == "function_call" and wire and "tool_calls" in wire[-1]:
|
|
137
|
+
wire[-1]["tool_calls"].append(encode_content(content))
|
|
138
|
+
continue
|
|
139
|
+
fragment: dict[str, Any] = {"role": message.role}
|
|
140
|
+
if message.role != "tool" and (name := sanitize_author_name(message.author_name)):
|
|
141
|
+
fragment["name"] = name
|
|
142
|
+
fragment.update(stored)
|
|
143
|
+
if content.type == "function_result":
|
|
144
|
+
fragment.update(_result_fields(content))
|
|
145
|
+
wire.append(fragment)
|
|
146
|
+
continue
|
|
147
|
+
if content.type == "function_call":
|
|
148
|
+
fragment["tool_calls"] = [encode_content(content)]
|
|
149
|
+
else:
|
|
150
|
+
fragment["content"] = [encode_content(content)]
|
|
151
|
+
fragment.update(pending)
|
|
152
|
+
pending = {}
|
|
153
|
+
wire.append(fragment)
|
|
154
|
+
if pending:
|
|
155
|
+
if wire:
|
|
156
|
+
wire[-1].update(pending)
|
|
157
|
+
elif message.role == "assistant":
|
|
158
|
+
wire.append(_reasoning_carrier(message, pending))
|
|
159
|
+
_flatten_text_parts(wire)
|
|
160
|
+
return wire
|
|
161
|
+
|
|
162
|
+
|
|
163
|
+
def _strict_messages(message: Message) -> list[dict[str, Any]]:
|
|
164
|
+
"""DeepSeek's layout: a message's fragments merge as far as their roles allow.
|
|
165
|
+
|
|
166
|
+
Calls join the assistant message before them and other parts the
|
|
167
|
+
previous message of the same role, and an assistant message with calls
|
|
168
|
+
always has a ``content``. No reasoning rides here: a message whose
|
|
169
|
+
reasoning replays is encoded by :func:`encode_reasoning_message`.
|
|
170
|
+
"""
|
|
171
|
+
wire: list[dict[str, Any]] = []
|
|
172
|
+
for content in message.contents:
|
|
173
|
+
if content.type == "text_reasoning":
|
|
174
|
+
continue
|
|
175
|
+
last = wire[-1] if wire else None
|
|
176
|
+
open_last = last is not None and "tool_call_id" not in last and last.get("role") == message.role
|
|
177
|
+
fragment: dict[str, Any] = {"role": message.role}
|
|
178
|
+
if message.role != "tool" and (name := sanitize_author_name(message.author_name)):
|
|
179
|
+
fragment["name"] = name
|
|
180
|
+
if content.type == "function_result":
|
|
181
|
+
fragment.update(_result_fields(content))
|
|
182
|
+
elif content.type == "function_call":
|
|
183
|
+
call = encode_content(content)
|
|
184
|
+
if last is not None and "tool_calls" in last:
|
|
185
|
+
last["tool_calls"].append(call)
|
|
186
|
+
continue
|
|
187
|
+
if last is not None and open_last and message.role == "assistant":
|
|
188
|
+
last["tool_calls"] = [call]
|
|
189
|
+
continue
|
|
190
|
+
fragment["tool_calls"] = [call]
|
|
191
|
+
_default_call_content(fragment)
|
|
192
|
+
elif last is not None and open_last and message.role != "tool":
|
|
193
|
+
parts = last.setdefault("content", [])
|
|
194
|
+
if not isinstance(parts, list):
|
|
195
|
+
parts = [Content.from_text(text=str(parts)).to_dict(exclude_none=True)]
|
|
196
|
+
last["content"] = parts
|
|
197
|
+
cast("list[dict[str, Any]]", parts).append(encode_content(content))
|
|
198
|
+
continue
|
|
199
|
+
else:
|
|
200
|
+
fragment["content"] = [encode_content(content)]
|
|
201
|
+
wire.append(fragment)
|
|
202
|
+
_flatten_text_parts(wire)
|
|
203
|
+
return wire
|
|
204
|
+
|
|
205
|
+
|
|
206
|
+
def encode_reasoning_message(message: Message, *, origin: ReasoningOrigin | None = None) -> list[dict[str, Any]]:
|
|
207
|
+
"""An assistant message whose reasoning replays to the endpoint *origin*, as runs around its tool results.
|
|
208
|
+
|
|
209
|
+
The text and calls between two results form one run and go out as one
|
|
210
|
+
wire message, so text and its calls never reach the wire split. Its
|
|
211
|
+
content stays a string: assistant content lists admit only text and
|
|
212
|
+
refusal parts, and GLM documents a string. Other parts go out on their
|
|
213
|
+
own ahead of their run's message; results stay ``tool`` records in
|
|
214
|
+
source order, each right after the message with its call. Within a run,
|
|
215
|
+
calls start a new text segment for text-block reconstruction and a
|
|
216
|
+
hosted-history summary takes a segment of its own; reasoning splits
|
|
217
|
+
none.
|
|
218
|
+
|
|
219
|
+
A run's reasoning rides the run's message, next to the calls it led to,
|
|
220
|
+
and never moves back across a result. A run of reasoning alone waits past
|
|
221
|
+
the results that follow it (a message among them would separate calls
|
|
222
|
+
from their results) and joins the next run, or ends the message as an
|
|
223
|
+
empty carrier. Reasoning kept only in the message properties is placed
|
|
224
|
+
once, for the whole message.
|
|
225
|
+
"""
|
|
226
|
+
wire: list[dict[str, Any]] = []
|
|
227
|
+
segments: list[list[tuple[str, str | None]]] = []
|
|
228
|
+
calls: list[dict[str, Any]] = []
|
|
229
|
+
reasoning: dict[str, Any] = {}
|
|
230
|
+
supplied: set[str] = set()
|
|
231
|
+
|
|
232
|
+
def end_segment() -> None:
|
|
233
|
+
if segments and segments[-1]:
|
|
234
|
+
segments.append([])
|
|
235
|
+
|
|
236
|
+
def end_run(*, keep_reasoning_alone: bool = False) -> None:
|
|
237
|
+
if not (segments or calls or (keep_reasoning_alone and reasoning)):
|
|
238
|
+
return
|
|
239
|
+
run = _role_and_name(message)
|
|
240
|
+
run["content"] = join_text_blocks(block for segment in segments for block in reconstruct_text_blocks(segment))
|
|
241
|
+
run.update(reasoning)
|
|
242
|
+
if calls:
|
|
243
|
+
run["tool_calls"] = list(calls)
|
|
244
|
+
wire.append(run)
|
|
245
|
+
segments.clear()
|
|
246
|
+
calls.clear()
|
|
247
|
+
reasoning.clear()
|
|
248
|
+
|
|
249
|
+
for content in message.contents:
|
|
250
|
+
kind = content.type
|
|
251
|
+
if kind == "text_reasoning":
|
|
252
|
+
if (found := contribution(content, origin=origin)) is not None:
|
|
253
|
+
fold(reasoning, *found)
|
|
254
|
+
supplied.add(found[0])
|
|
255
|
+
elif kind == "function_call":
|
|
256
|
+
calls.append(encode_content(content))
|
|
257
|
+
end_segment()
|
|
258
|
+
elif kind == "text":
|
|
259
|
+
if content.text is None:
|
|
260
|
+
continue
|
|
261
|
+
summary = content.additional_properties.get(_HOSTED_SUMMARY) is True
|
|
262
|
+
if summary:
|
|
263
|
+
end_segment()
|
|
264
|
+
if not segments:
|
|
265
|
+
segments.append([])
|
|
266
|
+
segments[-1].append((content.text, text_block_id(content.additional_properties)))
|
|
267
|
+
if summary:
|
|
268
|
+
end_segment()
|
|
269
|
+
elif kind == "function_result":
|
|
270
|
+
# Reasoning alone stays pending past the results.
|
|
271
|
+
end_run()
|
|
272
|
+
wire.append({"role": "tool", **_result_fields(content)})
|
|
273
|
+
else:
|
|
274
|
+
if kind in TOOL_CALL_CONTENT_TYPES:
|
|
275
|
+
end_segment()
|
|
276
|
+
standalone = _role_and_name(message)
|
|
277
|
+
standalone["content"] = [encode_content(content)]
|
|
278
|
+
wire.append(standalone)
|
|
279
|
+
end_run(keep_reasoning_alone=True)
|
|
280
|
+
_attach_reasoning(wire, message, stored_reasoning(message, skip=supplied, origin=origin))
|
|
281
|
+
return wire
|
|
282
|
+
|
|
283
|
+
|
|
284
|
+
def _attach_reasoning(wire: list[dict[str, Any]], message: Message, fields: dict[str, Any]) -> None:
|
|
285
|
+
"""Put reasoning on one wire message of an assistant message.
|
|
286
|
+
|
|
287
|
+
It rides the last message with ``tool_calls`` (DeepSeek and GLM document
|
|
288
|
+
reasoning on the calls message), else the last text message of the same
|
|
289
|
+
role that is not a result (never a multimodal list), else a new empty
|
|
290
|
+
message.
|
|
291
|
+
"""
|
|
292
|
+
if not fields:
|
|
293
|
+
return
|
|
294
|
+
carrier = next((candidate for candidate in reversed(wire) if "tool_calls" in candidate), None)
|
|
295
|
+
if carrier is None:
|
|
296
|
+
carrier = next((candidate for candidate in reversed(wire) if _text_message(candidate, message.role)), None)
|
|
297
|
+
if carrier is None:
|
|
298
|
+
wire.append(_reasoning_carrier(message, fields))
|
|
299
|
+
else:
|
|
300
|
+
carrier.update(fields)
|
|
301
|
+
|
|
302
|
+
|
|
303
|
+
def _text_message(candidate: dict[str, Any], role: str) -> bool:
|
|
304
|
+
"""Whether *candidate* is a non-result message of *role* whose content is text."""
|
|
305
|
+
if candidate.get("role") != role or "tool_call_id" in candidate:
|
|
306
|
+
return False
|
|
307
|
+
content = candidate.get("content")
|
|
308
|
+
return isinstance(content, str) or _text_parts_only(content)
|
|
309
|
+
|
|
310
|
+
|
|
311
|
+
def _reasoning_carrier(message: Message, fields: Mapping[str, Any]) -> dict[str, Any]:
|
|
312
|
+
"""An empty assistant message for reasoning nothing else can carry."""
|
|
313
|
+
carrier: dict[str, Any] = {"role": message.role, "content": "", **fields}
|
|
314
|
+
if name := sanitize_author_name(message.author_name):
|
|
315
|
+
carrier["name"] = name
|
|
316
|
+
return carrier
|
|
317
|
+
|
|
318
|
+
|
|
319
|
+
def _role_and_name(message: Message) -> dict[str, Any]:
|
|
320
|
+
head: dict[str, Any] = {"role": message.role}
|
|
321
|
+
if name := sanitize_author_name(message.author_name):
|
|
322
|
+
head["name"] = name
|
|
323
|
+
return head
|
|
324
|
+
|
|
325
|
+
|
|
326
|
+
def _result_fields(content: Content) -> dict[str, Any]:
|
|
327
|
+
text, images = lower_function_result(content)
|
|
328
|
+
fields: dict[str, Any] = {"tool_call_id": content.call_id, "content": text}
|
|
329
|
+
if images:
|
|
330
|
+
fields[_PENDING_IMAGES] = images
|
|
331
|
+
return fields
|
|
332
|
+
|
|
333
|
+
|
|
334
|
+
def _text_parts_only(value: Any) -> bool:
|
|
335
|
+
"""Whether *value* is a content list holding text parts alone (an empty list too)."""
|
|
336
|
+
return isinstance(value, list) and all(
|
|
337
|
+
isinstance(part, Mapping) and cast("Mapping[str, Any]", part).get("type") == "text"
|
|
338
|
+
for part in cast("list[object]", value)
|
|
339
|
+
)
|
|
340
|
+
|
|
341
|
+
|
|
342
|
+
def _flatten_text_parts(wire: list[dict[str, Any]]) -> None:
|
|
343
|
+
"""Join content lists of text parts alone into one string.
|
|
344
|
+
|
|
345
|
+
Some endpoints (Foundry Local) require a string for text-only messages;
|
|
346
|
+
a list with any other part stays multimodal.
|
|
347
|
+
"""
|
|
348
|
+
for message in wire:
|
|
349
|
+
parts = message.get("content")
|
|
350
|
+
if _text_parts_only(parts):
|
|
351
|
+
message["content"] = "\n".join(
|
|
352
|
+
text if isinstance(text := part.get("text", ""), str) else ""
|
|
353
|
+
for part in cast("list[Mapping[str, Any]]", parts)
|
|
354
|
+
)
|
|
355
|
+
|
|
356
|
+
|
|
357
|
+
# --- contents ---------------------------------------------------------------
|
|
358
|
+
|
|
359
|
+
|
|
360
|
+
def encode_content(content: Content) -> dict[str, Any]:
|
|
361
|
+
"""One content as a wire content part, tool call or result."""
|
|
362
|
+
match content.type:
|
|
363
|
+
case "function_call":
|
|
364
|
+
arguments = model_json(content.arguments) if isinstance(content.arguments, Mapping) else content.arguments
|
|
365
|
+
return {
|
|
366
|
+
"id": content.call_id,
|
|
367
|
+
"type": "function",
|
|
368
|
+
"function": {"name": content.name, "arguments": arguments},
|
|
369
|
+
}
|
|
370
|
+
case "function_result":
|
|
371
|
+
return {"tool_call_id": content.call_id, "content": "" if content.result is None else content.result}
|
|
372
|
+
case "text" if _HOSTED_SUMMARY in content.additional_properties:
|
|
373
|
+
return _unmarked_summary(content)
|
|
374
|
+
case "data" | "uri":
|
|
375
|
+
return _media_part(content)
|
|
376
|
+
case _:
|
|
377
|
+
return content.to_dict(exclude_none=True)
|
|
378
|
+
|
|
379
|
+
|
|
380
|
+
def image_part(content: Content) -> dict[str, Any]:
|
|
381
|
+
"""An ``image_url`` part, or a text part saying the image was left out when the API can't read it."""
|
|
382
|
+
if (image := wire_image(content)) is None:
|
|
383
|
+
return {"type": "text", "text": UNSUPPORTED_IMAGE_TEXT}
|
|
384
|
+
return _image_url_part(image, content)
|
|
385
|
+
|
|
386
|
+
|
|
387
|
+
def _image_url_part(image: WireImage, content: Content) -> dict[str, Any]:
|
|
388
|
+
"""An ``image_url`` part, with the content's ``detail`` when it sets one."""
|
|
389
|
+
image_url: dict[str, Any] = {"url": image.uri}
|
|
390
|
+
if isinstance(detail := content.additional_properties.get("detail"), str):
|
|
391
|
+
image_url["detail"] = detail
|
|
392
|
+
return {"type": "image_url", "image_url": image_url}
|
|
393
|
+
|
|
394
|
+
|
|
395
|
+
def _media_part(content: Content) -> dict[str, Any]:
|
|
396
|
+
if content.has_top_level_media_type("image"):
|
|
397
|
+
return image_part(content)
|
|
398
|
+
if content.has_top_level_media_type("audio"):
|
|
399
|
+
media_type = content.media_type or ""
|
|
400
|
+
audio_format = next((name for name in _AUDIO_FORMATS if name in media_type), None)
|
|
401
|
+
if audio_format is not None and content.uri is not None and content.uri.startswith("data:"):
|
|
402
|
+
# Only the base64 payload; ``input_audio`` takes no link.
|
|
403
|
+
data = content.uri.split(",", 1)[-1]
|
|
404
|
+
return {"type": "input_audio", "input_audio": {"data": data, "format": audio_format}}
|
|
405
|
+
elif (
|
|
406
|
+
content.has_top_level_media_type("application") and content.uri is not None and content.uri.startswith("data:")
|
|
407
|
+
):
|
|
408
|
+
# Every application type goes out as a file.
|
|
409
|
+
file: dict[str, Any] = {"file_data": content.uri}
|
|
410
|
+
if filename := content.additional_properties.get("filename"):
|
|
411
|
+
file["filename"] = filename
|
|
412
|
+
return {"type": "file", "file": file}
|
|
413
|
+
media_type = content.media_type or "Media"
|
|
414
|
+
# Debug only: history is encoded again for every request.
|
|
415
|
+
logger.debug("Chat Completions has no content part for %s; a placeholder text goes out instead.", media_type)
|
|
416
|
+
return {"type": "text", "text": _UNSUPPORTED_MEDIA_TEXT.format(media_type=media_type)}
|
|
417
|
+
|
|
418
|
+
|
|
419
|
+
def _unmarked_summary(content: Content) -> dict[str, Any]:
|
|
420
|
+
"""A summary's text part without the request-local marker; history keeps it.
|
|
421
|
+
|
|
422
|
+
Text parts of a multimodal message carry their properties to the wire.
|
|
423
|
+
"""
|
|
424
|
+
part = content.to_dict(exclude_none=True)
|
|
425
|
+
properties = dict(part["additional_properties"])
|
|
426
|
+
del properties[_HOSTED_SUMMARY]
|
|
427
|
+
if properties:
|
|
428
|
+
part["additional_properties"] = properties
|
|
429
|
+
else:
|
|
430
|
+
del part["additional_properties"]
|
|
431
|
+
return part
|
|
432
|
+
|
|
433
|
+
|
|
434
|
+
def lower_function_result(content: Content) -> tuple[str, list[dict[str, Any]]]:
|
|
435
|
+
"""A tool result's text, and the image parts the user message after the results carries.
|
|
436
|
+
|
|
437
|
+
A ``tool`` record takes text only. Each image follows a label naming its
|
|
438
|
+
call and item; other rich items are dropped with a warning.
|
|
439
|
+
"""
|
|
440
|
+
if not content.items:
|
|
441
|
+
return ("" if content.result is None else content.result), []
|
|
442
|
+
texts: list[str] = []
|
|
443
|
+
images: list[dict[str, Any]] = []
|
|
444
|
+
dropped = False
|
|
445
|
+
for position, item in enumerate(content.items, start=1):
|
|
446
|
+
if item.type == "text":
|
|
447
|
+
texts.append(item.text or "")
|
|
448
|
+
elif item.type in ("data", "uri"):
|
|
449
|
+
if is_image_content(item) and isinstance(item.uri, str):
|
|
450
|
+
if (image := wire_image(item)) is None:
|
|
451
|
+
texts.append(UNSUPPORTED_IMAGE_TEXT)
|
|
452
|
+
continue
|
|
453
|
+
images.append({"type": "text", "text": f"Image from tool call {content.call_id}, item {position}:"})
|
|
454
|
+
images.append(_image_url_part(image, item))
|
|
455
|
+
else:
|
|
456
|
+
dropped = True
|
|
457
|
+
if dropped:
|
|
458
|
+
logger.warning(
|
|
459
|
+
"Chat Completions tool results carry only text and images; other rich items are left out "
|
|
460
|
+
"(the Responses API client sends them)."
|
|
461
|
+
)
|
|
462
|
+
if images:
|
|
463
|
+
texts.append("(see following user message for image)")
|
|
464
|
+
return "\n".join(texts), images
|
|
465
|
+
|
|
466
|
+
|
|
467
|
+
def insert_image_messages(wire: list[dict[str, Any]]) -> list[dict[str, Any]]:
|
|
468
|
+
"""Move the images of tool results into one user message after each block of results."""
|
|
469
|
+
arranged: list[dict[str, Any]] = []
|
|
470
|
+
images: list[dict[str, Any]] = []
|
|
471
|
+
for message in wire:
|
|
472
|
+
parts = message.pop(_PENDING_IMAGES, None)
|
|
473
|
+
if message.get("role") == "tool":
|
|
474
|
+
if isinstance(parts, list):
|
|
475
|
+
images.extend(cast("list[dict[str, Any]]", parts))
|
|
476
|
+
elif images:
|
|
477
|
+
arranged.append({"role": "user", "content": images})
|
|
478
|
+
images = []
|
|
479
|
+
arranged.append(message)
|
|
480
|
+
if images:
|
|
481
|
+
arranged.append({"role": "user", "content": images})
|
|
482
|
+
return arranged
|
|
483
|
+
|
|
484
|
+
|
|
485
|
+
def degrade_hosted_history(messages: Sequence[Message]) -> Sequence[Message]:
|
|
486
|
+
"""History with every hosted tool content reduced to text.
|
|
487
|
+
|
|
488
|
+
This wire has no hosted item types: a hosted content would arrive as an
|
|
489
|
+
unknown part and an informational hosted call as a ``tool_calls`` entry
|
|
490
|
+
no result answers, and strict endpoints reject both. No Chat Completions
|
|
491
|
+
dialect hosts tools, so every hosted content is foreign here. A summary
|
|
492
|
+
becomes text marked request-local; encoding removes the marker.
|
|
493
|
+
"""
|
|
494
|
+
summaries = cross_provider_hosted_degradations(messages, target_provider="")
|
|
495
|
+
if not summaries:
|
|
496
|
+
return messages
|
|
497
|
+
return [
|
|
498
|
+
_degraded(message, summaries) if any(id(content) in summaries for content in message.contents) else message
|
|
499
|
+
for message in messages
|
|
500
|
+
]
|
|
501
|
+
|
|
502
|
+
|
|
503
|
+
def _degraded(message: Message, summaries: Mapping[int, str | None]) -> Message:
|
|
504
|
+
contents: list[Content] = []
|
|
505
|
+
for content in message.contents:
|
|
506
|
+
if id(content) not in summaries:
|
|
507
|
+
contents.append(content)
|
|
508
|
+
elif summary := summaries[id(content)]:
|
|
509
|
+
contents.append(Content.from_text(text=summary, additional_properties={_HOSTED_SUMMARY: True}))
|
|
510
|
+
return Message(
|
|
511
|
+
message.role,
|
|
512
|
+
contents,
|
|
513
|
+
author_name=message.author_name,
|
|
514
|
+
message_id=message.message_id,
|
|
515
|
+
additional_properties=message.additional_properties,
|
|
516
|
+
raw_representation=message.raw_representation,
|
|
517
|
+
)
|
|
518
|
+
|
|
519
|
+
|
|
520
|
+
# --- canonical tool-call layout ----------------------------------------------
|
|
521
|
+
|
|
522
|
+
|
|
523
|
+
def canonicalize_tool_call_messages(wire: list[dict[str, Any]]) -> list[dict[str, Any]]:
|
|
524
|
+
"""Repair the wire messages of ONE kernel message around its tool calls.
|
|
525
|
+
|
|
526
|
+
The encoder can split an assistant message with text and calls into a
|
|
527
|
+
text message and a calls message; strict servers (vLLM) reject the pair,
|
|
528
|
+
and the rejected history would stay in the session. Adjacent assistant
|
|
529
|
+
fragments merge, one that cannot merge moves ahead of the calls message
|
|
530
|
+
so results still follow their calls, and call arguments that are not a
|
|
531
|
+
JSON object become ``"{}"``. Running per kernel message keeps turns from
|
|
532
|
+
merging.
|
|
533
|
+
"""
|
|
534
|
+
canonical: list[dict[str, Any]] = []
|
|
535
|
+
for original in wire:
|
|
536
|
+
message = dict(original)
|
|
537
|
+
_repair_call_arguments(message)
|
|
538
|
+
_default_call_content(message)
|
|
539
|
+
previous = canonical[-1] if canonical else None
|
|
540
|
+
if previous is not None and _mergeable(previous, message):
|
|
541
|
+
_merge_into(previous, message)
|
|
542
|
+
_default_call_content(previous)
|
|
543
|
+
elif previous is not None and _goes_before_calls(previous, message):
|
|
544
|
+
canonical.insert(len(canonical) - 1, message)
|
|
545
|
+
else:
|
|
546
|
+
canonical.append(message)
|
|
547
|
+
return canonical
|
|
548
|
+
|
|
549
|
+
|
|
550
|
+
def _repair_call_arguments(message: dict[str, Any]) -> None:
|
|
551
|
+
"""Replace call arguments that are not a JSON object string with ``"{}"``.
|
|
552
|
+
|
|
553
|
+
Some endpoints validate historical arguments: a call the model cut off at
|
|
554
|
+
``"{"`` got an error result, but resending it would fail the request.
|
|
555
|
+
"""
|
|
556
|
+
calls = message.get("tool_calls")
|
|
557
|
+
if message.get("role") != "assistant" or not isinstance(calls, list):
|
|
558
|
+
return
|
|
559
|
+
originals = cast("list[Any]", calls)
|
|
560
|
+
repaired = [_repaired_call(call) for call in originals]
|
|
561
|
+
if any(new is not old for new, old in zip(repaired, originals, strict=True)):
|
|
562
|
+
message["tool_calls"] = repaired
|
|
563
|
+
|
|
564
|
+
|
|
565
|
+
def _repaired_call(call: Any) -> Any:
|
|
566
|
+
if not isinstance(call, dict):
|
|
567
|
+
return call
|
|
568
|
+
function = cast("dict[str, Any]", call).get("function")
|
|
569
|
+
if not isinstance(function, dict):
|
|
570
|
+
return call
|
|
571
|
+
arguments = cast("dict[str, Any]", function).get("arguments")
|
|
572
|
+
valid = _json_object_arguments(arguments)
|
|
573
|
+
if valid == arguments:
|
|
574
|
+
return call
|
|
575
|
+
return {**cast("dict[str, Any]", call), "function": {**cast("dict[str, Any]", function), "arguments": valid}}
|
|
576
|
+
|
|
577
|
+
|
|
578
|
+
def _json_object_arguments(arguments: Any) -> str:
|
|
579
|
+
"""The arguments as a JSON object string; ``"{}"`` for anything else."""
|
|
580
|
+
if isinstance(arguments, Mapping):
|
|
581
|
+
try:
|
|
582
|
+
return model_json(arguments)
|
|
583
|
+
except TypeError, ValueError:
|
|
584
|
+
return "{}"
|
|
585
|
+
if isinstance(arguments, str):
|
|
586
|
+
try:
|
|
587
|
+
decoded = json.loads(arguments)
|
|
588
|
+
except json.JSONDecodeError:
|
|
589
|
+
return "{}"
|
|
590
|
+
if isinstance(decoded, dict):
|
|
591
|
+
return arguments
|
|
592
|
+
return "{}"
|
|
593
|
+
|
|
594
|
+
|
|
595
|
+
def _default_call_content(message: dict[str, Any]) -> None:
|
|
596
|
+
"""Give an assistant message with calls an explicit empty ``content``."""
|
|
597
|
+
if message.get("role") == "assistant" and "tool_calls" in message and "content" not in message:
|
|
598
|
+
message["content"] = ""
|
|
599
|
+
|
|
600
|
+
|
|
601
|
+
def _is_empty(value: Any) -> bool:
|
|
602
|
+
return value in (None, "", [])
|
|
603
|
+
|
|
604
|
+
|
|
605
|
+
def _mergeable(previous: dict[str, Any], current: dict[str, Any]) -> bool:
|
|
606
|
+
"""Whether two adjacent fragments are one assistant message the encoder split."""
|
|
607
|
+
if previous.get("role") != "assistant" or current.get("role") != "assistant":
|
|
608
|
+
return False
|
|
609
|
+
if "tool_call_id" in previous or "tool_call_id" in current:
|
|
610
|
+
return False
|
|
611
|
+
# A message with reasoning was assembled whole, its reasoning next to its
|
|
612
|
+
# calls; merging would duplicate or move it, or take in parts its shape
|
|
613
|
+
# rejects.
|
|
614
|
+
if any(name in previous or name in current for name in REASONING_FIELDS):
|
|
615
|
+
return False
|
|
616
|
+
# Non-empty string and list contents cannot combine without losing one.
|
|
617
|
+
# Empty content combines with either, so a calls-only fragment still
|
|
618
|
+
# merges with a multimodal one.
|
|
619
|
+
first, second = previous.get("content"), current.get("content")
|
|
620
|
+
if not _is_empty(first) and not _is_empty(second) and isinstance(first, str) != isinstance(second, str):
|
|
621
|
+
return False
|
|
622
|
+
return "tool_calls" in previous or "tool_calls" in current
|
|
623
|
+
|
|
624
|
+
|
|
625
|
+
def _goes_before_calls(previous: dict[str, Any], current: dict[str, Any]) -> bool:
|
|
626
|
+
"""Whether a fragment that could not merge belongs ahead of the calls message before it.
|
|
627
|
+
|
|
628
|
+
Results must directly follow the message with their calls, so a
|
|
629
|
+
content-only assistant fragment left over (a string and list clash)
|
|
630
|
+
moves in front of it, the layout the reasoning encoder also produces.
|
|
631
|
+
"""
|
|
632
|
+
return (
|
|
633
|
+
previous.get("role") == "assistant"
|
|
634
|
+
and "tool_calls" in previous
|
|
635
|
+
and "tool_call_id" not in previous
|
|
636
|
+
and current.get("role") == "assistant"
|
|
637
|
+
and "tool_calls" not in current
|
|
638
|
+
and "tool_call_id" not in current
|
|
639
|
+
)
|
|
640
|
+
|
|
641
|
+
|
|
642
|
+
def _merge_into(target: dict[str, Any], source: dict[str, Any]) -> None:
|
|
643
|
+
"""Fold a later assistant fragment into the one before it."""
|
|
644
|
+
if calls := source.get("tool_calls"):
|
|
645
|
+
target.setdefault("tool_calls", []).extend(calls)
|
|
646
|
+
added = source.get("content")
|
|
647
|
+
if not _is_empty(added):
|
|
648
|
+
present = target.get("content")
|
|
649
|
+
if _is_empty(present):
|
|
650
|
+
target["content"] = added
|
|
651
|
+
elif isinstance(present, str) and isinstance(added, str):
|
|
652
|
+
target["content"] = present + added
|
|
653
|
+
elif isinstance(present, list) and isinstance(added, list):
|
|
654
|
+
target["content"] = [*cast("list[Any]", present), *cast("list[Any]", added)]
|
|
655
|
+
for key, value in source.items():
|
|
656
|
+
if key not in ("role", "content", "tool_calls") and _is_empty(target.get(key)):
|
|
657
|
+
target[key] = value
|