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,629 @@
|
|
|
1
|
+
# Copyright (c) Huawei Technologies Co., Ltd. 2026. All rights reserved.
|
|
2
|
+
|
|
3
|
+
"""Replaying reasoning from local history.
|
|
4
|
+
|
|
5
|
+
Under local storage the request carries reasoning items the client rebuilds
|
|
6
|
+
from history, and the API accepts one only next to the calls it led to. So
|
|
7
|
+
history is cut into positional groups (:func:`partition_groups`): a call
|
|
8
|
+
message with the reasoning around it and the outputs that answer it, or a
|
|
9
|
+
message standing alone. :func:`plan_groups` rebuilds each group's reasoning
|
|
10
|
+
items and degrades a group that cannot replay them safely, encrypted
|
|
11
|
+
reasoning another endpoint issued included: it then goes out without
|
|
12
|
+
reasoning or hosted MCP calls, its function calls without item ids.
|
|
13
|
+
:func:`encode_input` encodes history with those plans.
|
|
14
|
+
"""
|
|
15
|
+
|
|
16
|
+
from __future__ import annotations
|
|
17
|
+
|
|
18
|
+
import logging
|
|
19
|
+
from collections import Counter
|
|
20
|
+
from collections.abc import Mapping, Sequence
|
|
21
|
+
from dataclasses import dataclass, field
|
|
22
|
+
from itertools import groupby
|
|
23
|
+
from typing import TYPE_CHECKING, Any
|
|
24
|
+
|
|
25
|
+
from chrys.foundation.reasoning_origin import replays_to
|
|
26
|
+
from chrys.kernel.compaction import (
|
|
27
|
+
GROUP_ANNOTATION_KEY,
|
|
28
|
+
GROUP_HAS_REASONING_KEY,
|
|
29
|
+
GROUP_KIND_KEY,
|
|
30
|
+
group_annotation_signature,
|
|
31
|
+
)
|
|
32
|
+
from chrys.kernel.exchanges import (
|
|
33
|
+
TOOL_CALL_CONTENT_TYPES,
|
|
34
|
+
TOOL_RESULT_CONTENT_TYPES,
|
|
35
|
+
EmptyIdPolicy,
|
|
36
|
+
LiveAccessor,
|
|
37
|
+
NoneIdPolicy,
|
|
38
|
+
PairingPolicy,
|
|
39
|
+
iter_exchanges,
|
|
40
|
+
namespaced_pairing_key,
|
|
41
|
+
pair_results,
|
|
42
|
+
)
|
|
43
|
+
from chrys.service.llm.chat_completions.reasoning import (
|
|
44
|
+
REASONING_CONTENT_FIELD,
|
|
45
|
+
REASONING_DETAILS_FIELD,
|
|
46
|
+
REASONING_FIELD,
|
|
47
|
+
REASONING_FORMAT_KEY,
|
|
48
|
+
)
|
|
49
|
+
|
|
50
|
+
from .history import (
|
|
51
|
+
OPENAI_SHELL_OUTPUT_TYPE_KEY,
|
|
52
|
+
OPENAI_SHELL_OUTPUT_TYPE_LOCAL_SHELL_CALL,
|
|
53
|
+
OPENAI_SHELL_OUTPUT_TYPE_SHELL_CALL,
|
|
54
|
+
answer_apply_patch_calls,
|
|
55
|
+
encode_content,
|
|
56
|
+
encode_message,
|
|
57
|
+
hosted_degradations,
|
|
58
|
+
marked_reasoning_text,
|
|
59
|
+
)
|
|
60
|
+
from .hosted import coalesce_pending_results
|
|
61
|
+
|
|
62
|
+
if TYPE_CHECKING:
|
|
63
|
+
from chrys.foundation.reasoning_origin import ReasoningOrigin
|
|
64
|
+
from chrys.kernel import Content, Message
|
|
65
|
+
from chrys.kernel.exchanges import PairingKey
|
|
66
|
+
|
|
67
|
+
from .client import ResponsesVariant
|
|
68
|
+
|
|
69
|
+
logger = logging.getLogger(__name__)
|
|
70
|
+
|
|
71
|
+
_TOOL_TYPES = TOOL_CALL_CONTENT_TYPES | TOOL_RESULT_CONTENT_TYPES
|
|
72
|
+
_SHELL_OUTPUT_MARKERS = frozenset({OPENAI_SHELL_OUTPUT_TYPE_SHELL_CALL, OPENAI_SHELL_OUTPUT_TYPE_LOCAL_SHELL_CALL})
|
|
73
|
+
# Reasoning captured from Chat Completions; it never replays as an item.
|
|
74
|
+
_CHAT_COMPLETIONS_FORMATS = (REASONING_CONTENT_FIELD, REASONING_DETAILS_FIELD, REASONING_FIELD)
|
|
75
|
+
_LIVE = LiveAccessor()
|
|
76
|
+
_PAIRING = PairingPolicy(
|
|
77
|
+
call_types=TOOL_CALL_CONTENT_TYPES,
|
|
78
|
+
include_informational_calls=True,
|
|
79
|
+
result_types=TOOL_RESULT_CONTENT_TYPES,
|
|
80
|
+
none_id=NoneIdPolicy.POSITIONAL,
|
|
81
|
+
empty_id=EmptyIdPolicy.POSITIONAL,
|
|
82
|
+
malformed_id="stringify",
|
|
83
|
+
)
|
|
84
|
+
|
|
85
|
+
type _Signature = tuple[str, str, int, bool]
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
@dataclass(slots=True, frozen=True)
|
|
89
|
+
class ReplayGroup:
|
|
90
|
+
"""Messages that replay, or degrade, together."""
|
|
91
|
+
|
|
92
|
+
position: int
|
|
93
|
+
messages: tuple[Message, ...]
|
|
94
|
+
annotated_reasoning_tool_call: bool
|
|
95
|
+
# The exchange the group belongs to; None when it has none or several.
|
|
96
|
+
exchange_ordinal: int | None
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
@dataclass(slots=True)
|
|
100
|
+
class ReplayPlan:
|
|
101
|
+
"""How one group is encoded; contents are named by identity."""
|
|
102
|
+
|
|
103
|
+
group: ReplayGroup
|
|
104
|
+
# Rebuilt items keyed by the first content of their occurrence.
|
|
105
|
+
reasoning_items: dict[int, dict[str, Any]] = field(default_factory=dict)
|
|
106
|
+
dropped: set[int] = field(default_factory=set)
|
|
107
|
+
calls_without_id: set[int] = field(default_factory=set)
|
|
108
|
+
reasoning_ids: list[str] = field(default_factory=list)
|
|
109
|
+
call_ids: list[str] = field(default_factory=list)
|
|
110
|
+
# Top-level item ids the group sends; ids must not repeat in a request.
|
|
111
|
+
wire_ids: list[str] = field(default_factory=list)
|
|
112
|
+
mcp_wire_ids: list[str] = field(default_factory=list)
|
|
113
|
+
mcp_result_ids: list[str] = field(default_factory=list)
|
|
114
|
+
degraded: bool = False
|
|
115
|
+
# Degraded only because another endpoint issued some of the reasoning:
|
|
116
|
+
# expected after a switch, not a fault.
|
|
117
|
+
foreign_reasoning: bool = False
|
|
118
|
+
|
|
119
|
+
def degrade(self) -> None:
|
|
120
|
+
"""Switch the group to the form that always replays."""
|
|
121
|
+
self.degraded = True
|
|
122
|
+
self.reasoning_items.clear()
|
|
123
|
+
for message in self.group.messages:
|
|
124
|
+
for content in message.contents:
|
|
125
|
+
key = id(content)
|
|
126
|
+
if content.type in {"text_reasoning", "mcp_server_tool_call"}:
|
|
127
|
+
self.dropped.add(key)
|
|
128
|
+
elif content.type == "function_call" and key not in self.dropped:
|
|
129
|
+
self.calls_without_id.add(key)
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
def encode_input(
|
|
133
|
+
messages: Sequence[Message],
|
|
134
|
+
*,
|
|
135
|
+
service_side: bool,
|
|
136
|
+
variant: ResponsesVariant,
|
|
137
|
+
origin: ReasoningOrigin | None = None,
|
|
138
|
+
) -> list[dict[str, Any]]:
|
|
139
|
+
"""Encode history as input items for the endpoint *origin*.
|
|
140
|
+
|
|
141
|
+
Pending hosted results join their calls within one exchange only: call
|
|
142
|
+
ids may repeat in a later one.
|
|
143
|
+
"""
|
|
144
|
+
groups = partition_groups(messages)
|
|
145
|
+
provider = variant.hosted_provider
|
|
146
|
+
degradations = hosted_degradations(messages, provider=provider, service_side=service_side)
|
|
147
|
+
plans = (
|
|
148
|
+
[ReplayPlan(group) for group in groups] if service_side else plan_groups(groups, variant=variant, origin=origin)
|
|
149
|
+
)
|
|
150
|
+
items: list[dict[str, Any]] = []
|
|
151
|
+
for _, batch in groupby(plans, key=_batch_key):
|
|
152
|
+
batch_items = [
|
|
153
|
+
item
|
|
154
|
+
for plan in batch
|
|
155
|
+
for message in plan.group.messages
|
|
156
|
+
for item in encode_message(
|
|
157
|
+
message,
|
|
158
|
+
provider=provider,
|
|
159
|
+
service_side=service_side,
|
|
160
|
+
reasoning_items=plan.reasoning_items,
|
|
161
|
+
dropped=plan.dropped,
|
|
162
|
+
calls_without_id=plan.calls_without_id,
|
|
163
|
+
degradations=degradations,
|
|
164
|
+
)
|
|
165
|
+
]
|
|
166
|
+
items.extend(answer_apply_patch_calls(coalesce_pending_results(batch_items)))
|
|
167
|
+
return items
|
|
168
|
+
|
|
169
|
+
|
|
170
|
+
def _batch_key(plan: ReplayPlan) -> tuple[str, int]:
|
|
171
|
+
ordinal = plan.group.exchange_ordinal
|
|
172
|
+
return ("alone", plan.group.position) if ordinal is None else ("exchange", ordinal)
|
|
173
|
+
|
|
174
|
+
|
|
175
|
+
@dataclass(slots=True)
|
|
176
|
+
class _Run:
|
|
177
|
+
"""The group being cut: its annotation signature and its exchange."""
|
|
178
|
+
|
|
179
|
+
signature: _Signature | None
|
|
180
|
+
call_keys: set[PairingKey] = field(default_factory=set)
|
|
181
|
+
owner: int | None = None
|
|
182
|
+
|
|
183
|
+
def admits(self, signature: _Signature | None) -> bool:
|
|
184
|
+
"""Compaction annotations only split groups: a message whose
|
|
185
|
+
signature conflicts with the group's stays out."""
|
|
186
|
+
if self.signature is None:
|
|
187
|
+
self.signature = signature
|
|
188
|
+
return True
|
|
189
|
+
return signature is None or signature == self.signature
|
|
190
|
+
|
|
191
|
+
def admits_result(self, message: Message, signature: _Signature | None) -> bool:
|
|
192
|
+
"""An assistant message answering only this group's calls joins
|
|
193
|
+
whatever its signature (the annotator gives it a span of its own);
|
|
194
|
+
results for calls made elsewhere follow the signature rule, so a
|
|
195
|
+
stray orphan cannot join and degrade a valid group."""
|
|
196
|
+
if message.role == "assistant":
|
|
197
|
+
keys = _pairing_keys(message, TOOL_RESULT_CONTENT_TYPES)
|
|
198
|
+
if keys and keys <= self.call_keys:
|
|
199
|
+
return True
|
|
200
|
+
return self.admits(signature)
|
|
201
|
+
|
|
202
|
+
|
|
203
|
+
def partition_groups(messages: Sequence[Message]) -> list[ReplayGroup]:
|
|
204
|
+
"""Cut history into replay groups.
|
|
205
|
+
|
|
206
|
+
The exchange grammar decides which outputs answer which calls: a group
|
|
207
|
+
takes only outputs its own exchange owns, and a history marker always
|
|
208
|
+
stands alone. Within an exchange every call message opens its own group.
|
|
209
|
+
A group without a call message has no exchange; its orphan outputs join
|
|
210
|
+
structurally and degrade with it. Annotations only split, so histories
|
|
211
|
+
without them cut the same either way.
|
|
212
|
+
"""
|
|
213
|
+
signatures = [group_annotation_signature(message) for message in messages]
|
|
214
|
+
call_owner: dict[int, int] = {}
|
|
215
|
+
output_owner: dict[int, int] = {}
|
|
216
|
+
for ordinal, exchange in enumerate(iter_exchanges(messages, _LIVE)):
|
|
217
|
+
call_owner.update(dict.fromkeys(exchange.response_indices, ordinal))
|
|
218
|
+
output_owner.update(dict.fromkeys(exchange.output_indices, ordinal))
|
|
219
|
+
total = len(messages)
|
|
220
|
+
|
|
221
|
+
def skip_reasoning(index: int, run: _Run) -> int:
|
|
222
|
+
while index < total and _is_reasoning_only(messages[index]) and run.admits(signatures[index]):
|
|
223
|
+
index += 1
|
|
224
|
+
return index
|
|
225
|
+
|
|
226
|
+
def open_exchange(index: int, run: _Run) -> int:
|
|
227
|
+
run.call_keys |= _pairing_keys(messages[index], TOOL_CALL_CONTENT_TYPES)
|
|
228
|
+
run.owner = call_owner.get(index)
|
|
229
|
+
return skip_reasoning(index + 1, run)
|
|
230
|
+
|
|
231
|
+
def owned_output(index: int, owner: int | None) -> bool:
|
|
232
|
+
if owner is not None:
|
|
233
|
+
return output_owner.get(index) == owner
|
|
234
|
+
return _is_output_message(messages[index]) and not _LIVE.has_marker(messages[index])
|
|
235
|
+
|
|
236
|
+
groups: list[ReplayGroup] = []
|
|
237
|
+
start = 0
|
|
238
|
+
while start < total:
|
|
239
|
+
first = messages[start]
|
|
240
|
+
run = _Run(signatures[start])
|
|
241
|
+
end = start + 1
|
|
242
|
+
if _LIVE.has_marker(first):
|
|
243
|
+
pass
|
|
244
|
+
elif _is_call_message(first) or _is_reasoning_only(first):
|
|
245
|
+
if _is_call_message(first):
|
|
246
|
+
end = open_exchange(start, run)
|
|
247
|
+
else:
|
|
248
|
+
end = skip_reasoning(end, run)
|
|
249
|
+
if end < total and _is_call_message(messages[end]) and run.admits(signatures[end]):
|
|
250
|
+
end = open_exchange(end, run)
|
|
251
|
+
while end < total and owned_output(end, run.owner) and run.admits_result(messages[end], signatures[end]):
|
|
252
|
+
end += 1
|
|
253
|
+
elif _is_output_message(first):
|
|
254
|
+
while (
|
|
255
|
+
end < total
|
|
256
|
+
and _is_output_message(messages[end])
|
|
257
|
+
and not _LIVE.has_marker(messages[end])
|
|
258
|
+
and run.admits_result(messages[end], signatures[end])
|
|
259
|
+
):
|
|
260
|
+
end += 1
|
|
261
|
+
members = tuple(messages[start:end])
|
|
262
|
+
exchanges = {
|
|
263
|
+
owner
|
|
264
|
+
for index in range(start, end)
|
|
265
|
+
if (owner := call_owner.get(index, output_owner.get(index))) is not None
|
|
266
|
+
}
|
|
267
|
+
groups.append(
|
|
268
|
+
ReplayGroup(
|
|
269
|
+
position=len(groups),
|
|
270
|
+
messages=members,
|
|
271
|
+
annotated_reasoning_tool_call=any(map(_annotated_reasoning_tool_call, members)),
|
|
272
|
+
# A group spans at most one exchange; malformed history that
|
|
273
|
+
# breaks this fails closed instead of coalescing across them.
|
|
274
|
+
exchange_ordinal=next(iter(exchanges)) if len(exchanges) == 1 else None,
|
|
275
|
+
)
|
|
276
|
+
)
|
|
277
|
+
start = end
|
|
278
|
+
return groups
|
|
279
|
+
|
|
280
|
+
|
|
281
|
+
def _is_reasoning_only(message: Message) -> bool:
|
|
282
|
+
return (
|
|
283
|
+
message.role == "assistant"
|
|
284
|
+
and bool(message.contents)
|
|
285
|
+
and all(content.type == "text_reasoning" for content in message.contents)
|
|
286
|
+
)
|
|
287
|
+
|
|
288
|
+
|
|
289
|
+
def _is_call_message(message: Message) -> bool:
|
|
290
|
+
return message.role == "assistant" and any(content.type in TOOL_CALL_CONTENT_TYPES for content in message.contents)
|
|
291
|
+
|
|
292
|
+
|
|
293
|
+
def _is_output_message(message: Message) -> bool:
|
|
294
|
+
"""A message that only answers calls made before it."""
|
|
295
|
+
if message.role == "tool":
|
|
296
|
+
return True
|
|
297
|
+
return (
|
|
298
|
+
message.role == "assistant"
|
|
299
|
+
and not _is_call_message(message)
|
|
300
|
+
and any(content.type in TOOL_RESULT_CONTENT_TYPES for content in message.contents)
|
|
301
|
+
)
|
|
302
|
+
|
|
303
|
+
|
|
304
|
+
def _annotated_reasoning_tool_call(message: Message) -> bool:
|
|
305
|
+
annotation = message.additional_properties.get(GROUP_ANNOTATION_KEY)
|
|
306
|
+
return (
|
|
307
|
+
isinstance(annotation, Mapping)
|
|
308
|
+
and annotation.get(GROUP_KIND_KEY) == "tool_call"
|
|
309
|
+
and annotation.get(GROUP_HAS_REASONING_KEY) is True
|
|
310
|
+
)
|
|
311
|
+
|
|
312
|
+
|
|
313
|
+
def _pairing_keys(message: Message, types: frozenset[str]) -> set[PairingKey]:
|
|
314
|
+
return {
|
|
315
|
+
key
|
|
316
|
+
for content in message.contents
|
|
317
|
+
if content.type in types and (key := namespaced_pairing_key(content.type, _LIVE.raw_id(content))) is not None
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
|
|
321
|
+
def plan_groups(
|
|
322
|
+
groups: Sequence[ReplayGroup], *, variant: ResponsesVariant, origin: ReasoningOrigin | None = None
|
|
323
|
+
) -> list[ReplayPlan]:
|
|
324
|
+
"""Plan every group of a request to the endpoint *origin* that replays local history."""
|
|
325
|
+
result_owners = _result_owners(groups)
|
|
326
|
+
plans = [_plan_group(group, result_owners, variant=variant, origin=origin) for group in groups]
|
|
327
|
+
_degrade_reused_ids(plans)
|
|
328
|
+
# A result whose call was degraded cannot replay without it. Results
|
|
329
|
+
# without an owner stay until coalescing drops them: their position
|
|
330
|
+
# still splits the message runs around them.
|
|
331
|
+
degraded_positions = {plan.group.position for plan in plans if plan.degraded}
|
|
332
|
+
for plan in plans:
|
|
333
|
+
for message in plan.group.messages:
|
|
334
|
+
for content in message.contents:
|
|
335
|
+
if content.type == "mcp_server_tool_result" and result_owners.get(id(content)) in degraded_positions:
|
|
336
|
+
plan.dropped.add(id(content))
|
|
337
|
+
degraded = [plan for plan in plans if plan.degraded]
|
|
338
|
+
if faulty := [plan for plan in degraded if not plan.foreign_reasoning]:
|
|
339
|
+
logger.warning(
|
|
340
|
+
"Degraded stateless reasoning replay: groups=%s reasoning_ids=%s call_ids=%s",
|
|
341
|
+
[plan.group.position for plan in faulty],
|
|
342
|
+
list(dict.fromkeys(name for plan in faulty for name in plan.reasoning_ids)),
|
|
343
|
+
list(dict.fromkeys(name for plan in faulty for name in plan.call_ids)),
|
|
344
|
+
)
|
|
345
|
+
if foreign := [plan for plan in degraded if plan.foreign_reasoning]:
|
|
346
|
+
logger.debug("Left out reasoning another endpoint issued: groups=%s", [plan.group.position for plan in foreign])
|
|
347
|
+
return plans
|
|
348
|
+
|
|
349
|
+
|
|
350
|
+
def _plan_group(
|
|
351
|
+
group: ReplayGroup,
|
|
352
|
+
result_owners: Mapping[int, int],
|
|
353
|
+
*,
|
|
354
|
+
variant: ResponsesVariant,
|
|
355
|
+
origin: ReasoningOrigin | None,
|
|
356
|
+
) -> ReplayPlan:
|
|
357
|
+
occurrences = _reasoning_occurrences(group)
|
|
358
|
+
reasoning_items, replayable, only_foreign = _rebuilt_reasoning(
|
|
359
|
+
occurrences, encrypted=variant.encrypted_reasoning, origin=origin
|
|
360
|
+
)
|
|
361
|
+
plan = ReplayPlan(group, reasoning_items)
|
|
362
|
+
plan.reasoning_ids = [occurrence[0].id or "<missing>" for occurrence in occurrences]
|
|
363
|
+
tools = [
|
|
364
|
+
(message, content) for message in group.messages for content in message.contents if content.type in _TOOL_TYPES
|
|
365
|
+
]
|
|
366
|
+
plan.call_ids = [
|
|
367
|
+
name for _, content in tools if isinstance(name := content.call_id or content.image_id, str) and name
|
|
368
|
+
]
|
|
369
|
+
|
|
370
|
+
invalid = bool(occurrences) and not replayable
|
|
371
|
+
faulty = invalid and not only_foreign
|
|
372
|
+
if group.annotated_reasoning_tool_call and tools and not occurrences:
|
|
373
|
+
# Compaction saw reasoning here that history no longer has.
|
|
374
|
+
faulty = True
|
|
375
|
+
plan.reasoning_ids.append("<missing>")
|
|
376
|
+
if group.annotated_reasoning_tool_call and occurrences and not tools:
|
|
377
|
+
faulty = True
|
|
378
|
+
|
|
379
|
+
def encode(message: Message, content: Content) -> dict[str, Any]:
|
|
380
|
+
return encode_content(
|
|
381
|
+
message.role,
|
|
382
|
+
content,
|
|
383
|
+
provider=variant.hosted_provider,
|
|
384
|
+
replays_local_storage="_attribution" in message.additional_properties,
|
|
385
|
+
)
|
|
386
|
+
|
|
387
|
+
unsafe: set[int] = set()
|
|
388
|
+
if occurrences or group.annotated_reasoning_tool_call:
|
|
389
|
+
# Reasoning replays only with calls the API pairs with it again.
|
|
390
|
+
for message, content in tools:
|
|
391
|
+
shell_output = (
|
|
392
|
+
content.type in {"function_call", "function_result"}
|
|
393
|
+
and content.additional_properties.get(OPENAI_SHELL_OUTPUT_TYPE_KEY) in _SHELL_OUTPUT_MARKERS
|
|
394
|
+
)
|
|
395
|
+
informational = content.type == "function_call" and content.informational_only
|
|
396
|
+
encoded = encode(message, content)
|
|
397
|
+
if shell_output or informational or not encoded:
|
|
398
|
+
unsafe.add(id(content))
|
|
399
|
+
elif content.type == "function_call" and (wire_id := _item_id(encoded)):
|
|
400
|
+
plan.wire_ids.append(wire_id)
|
|
401
|
+
calls = {
|
|
402
|
+
content_type: {
|
|
403
|
+
content.call_id
|
|
404
|
+
for _, content in tools
|
|
405
|
+
if content.type == content_type and id(content) not in unsafe and content.call_id
|
|
406
|
+
}
|
|
407
|
+
for content_type in ("function_call", "mcp_server_tool_call")
|
|
408
|
+
}
|
|
409
|
+
for _, content in tools:
|
|
410
|
+
if content.type not in {"function_result", "mcp_server_tool_result"}:
|
|
411
|
+
continue
|
|
412
|
+
owner = result_owners.get(id(content))
|
|
413
|
+
if owner is not None and owner != group.position:
|
|
414
|
+
# Carried by this group, but the exchange paired it with a
|
|
415
|
+
# sibling group's call.
|
|
416
|
+
continue
|
|
417
|
+
call_type = "function_call" if content.type == "function_result" else "mcp_server_tool_call"
|
|
418
|
+
if owner is None or not content.call_id or content.call_id not in calls[call_type]:
|
|
419
|
+
unsafe.add(id(content))
|
|
420
|
+
else:
|
|
421
|
+
for message, content in tools:
|
|
422
|
+
if content.type == "function_call" and content.call_id and (wire_id := _item_id(encode(message, content))):
|
|
423
|
+
plan.wire_ids.append(wire_id)
|
|
424
|
+
|
|
425
|
+
plan.wire_ids.extend(item["id"] for item in reasoning_items.values() if _item_id(item))
|
|
426
|
+
plan.mcp_wire_ids = [
|
|
427
|
+
content.call_id for _, content in tools if content.type == "mcp_server_tool_call" and content.call_id
|
|
428
|
+
]
|
|
429
|
+
plan.mcp_result_ids = [
|
|
430
|
+
content.call_id for _, content in tools if content.type == "mcp_server_tool_result" and content.call_id
|
|
431
|
+
]
|
|
432
|
+
plan.wire_ids.extend(plan.mcp_wire_ids)
|
|
433
|
+
if invalid or faulty or unsafe:
|
|
434
|
+
plan.dropped.update(unsafe)
|
|
435
|
+
plan.degrade()
|
|
436
|
+
plan.foreign_reasoning = not (faulty or unsafe)
|
|
437
|
+
return plan
|
|
438
|
+
|
|
439
|
+
|
|
440
|
+
def _item_id(item: Mapping[str, Any] | None) -> str | None:
|
|
441
|
+
item_id = item.get("id") if item else None
|
|
442
|
+
return item_id if isinstance(item_id, str) and item_id else None
|
|
443
|
+
|
|
444
|
+
|
|
445
|
+
def _degrade_reused_ids(plans: Sequence[ReplayPlan]) -> None:
|
|
446
|
+
"""Degrade a reasoning or MCP group whose item ids repeat.
|
|
447
|
+
|
|
448
|
+
Groups with function calls only never degrade here: their ids are
|
|
449
|
+
reserved against every other group wherever they sit. Repeated MCP ids
|
|
450
|
+
whose every call is answered inside the group are separate calls that
|
|
451
|
+
coalesce in order; any other repeat, inside the group or with an
|
|
452
|
+
earlier one, degrades.
|
|
453
|
+
"""
|
|
454
|
+
seen: set[str] = set()
|
|
455
|
+
reserved: set[str] = set()
|
|
456
|
+
candidates: list[ReplayPlan] = []
|
|
457
|
+
for plan in plans:
|
|
458
|
+
if plan.degraded:
|
|
459
|
+
continue
|
|
460
|
+
sends_mcp_calls = any(
|
|
461
|
+
content.type == "mcp_server_tool_call" and content.call_id
|
|
462
|
+
for message in plan.group.messages
|
|
463
|
+
for content in message.contents
|
|
464
|
+
)
|
|
465
|
+
if plan.reasoning_items or sends_mcp_calls:
|
|
466
|
+
candidates.append(plan)
|
|
467
|
+
else:
|
|
468
|
+
reserved.update(plan.wire_ids)
|
|
469
|
+
for plan in candidates:
|
|
470
|
+
mcp_calls = Counter(plan.mcp_wire_ids)
|
|
471
|
+
mcp_results = Counter(plan.mcp_result_ids)
|
|
472
|
+
repeats = any(
|
|
473
|
+
count > 1 and not (mcp_calls[wire_id] == count and mcp_results[wire_id] == count)
|
|
474
|
+
for wire_id, count in Counter(plan.wire_ids).items()
|
|
475
|
+
)
|
|
476
|
+
if repeats or any(wire_id in seen or wire_id in reserved for wire_id in plan.wire_ids):
|
|
477
|
+
plan.degrade()
|
|
478
|
+
else:
|
|
479
|
+
seen.update(plan.wire_ids)
|
|
480
|
+
|
|
481
|
+
|
|
482
|
+
def _result_owners(groups: Sequence[ReplayGroup]) -> dict[int, int]:
|
|
483
|
+
"""The group whose call each paired result answers, by result identity.
|
|
484
|
+
|
|
485
|
+
``pair_results`` decides which occurrence answers which call, even with
|
|
486
|
+
repeated ids, so a result carried by one group can belong to a sibling.
|
|
487
|
+
A result object paired into two groups gets no owner.
|
|
488
|
+
"""
|
|
489
|
+
messages = [message for group in groups for message in group.messages]
|
|
490
|
+
positions = [group.position for group in groups for _ in group.messages]
|
|
491
|
+
owners: dict[int, int] = {}
|
|
492
|
+
ambiguous: set[int] = set()
|
|
493
|
+
for exchange in iter_exchanges(messages, _LIVE):
|
|
494
|
+
pairing = pair_results(messages, exchange, _LIVE, _PAIRING)
|
|
495
|
+
for assignments in (*pairing.truthy_assignments.values(), *pairing.falsy_assignments.values()):
|
|
496
|
+
for call, result in assignments:
|
|
497
|
+
if result is None:
|
|
498
|
+
continue
|
|
499
|
+
key = id(messages[result.message_index].contents[result.content_index])
|
|
500
|
+
if key in ambiguous:
|
|
501
|
+
continue
|
|
502
|
+
owner = positions[call.message_index]
|
|
503
|
+
if owners.setdefault(key, owner) != owner:
|
|
504
|
+
del owners[key]
|
|
505
|
+
ambiguous.add(key)
|
|
506
|
+
return owners
|
|
507
|
+
|
|
508
|
+
|
|
509
|
+
def _reasoning_occurrences(group: ReplayGroup) -> list[list[Content]]:
|
|
510
|
+
"""Runs of reasoning contents, one per provider reasoning item.
|
|
511
|
+
|
|
512
|
+
A run ends at any other content or where the reasoning id changes; a
|
|
513
|
+
content object repeated within a run counts once.
|
|
514
|
+
"""
|
|
515
|
+
occurrences: list[list[Content]] = []
|
|
516
|
+
current: list[Content] = []
|
|
517
|
+
for message in group.messages:
|
|
518
|
+
for content in message.contents:
|
|
519
|
+
if content.type != "text_reasoning":
|
|
520
|
+
if current:
|
|
521
|
+
occurrences.append(current)
|
|
522
|
+
current = []
|
|
523
|
+
continue
|
|
524
|
+
if current and current[-1].id != content.id:
|
|
525
|
+
occurrences.append(current)
|
|
526
|
+
current = []
|
|
527
|
+
if not any(existing is content for existing in current):
|
|
528
|
+
current.append(content)
|
|
529
|
+
if current:
|
|
530
|
+
occurrences.append(current)
|
|
531
|
+
return occurrences
|
|
532
|
+
|
|
533
|
+
|
|
534
|
+
def _rebuilt_reasoning(
|
|
535
|
+
occurrences: Sequence[Sequence[Content]], *, encrypted: bool, origin: ReasoningOrigin | None
|
|
536
|
+
) -> tuple[dict[int, dict[str, Any]], bool, bool]:
|
|
537
|
+
"""Rebuild each occurrence's reasoning item.
|
|
538
|
+
|
|
539
|
+
Returns the items, whether every occurrence replays, and whether the
|
|
540
|
+
ones that do not are all ones another endpoint issued (False when every
|
|
541
|
+
one replays).
|
|
542
|
+
|
|
543
|
+
OpenAI replays the encrypted payload; an occurrence without one, or with
|
|
544
|
+
one an endpoint other than *origin* issued, cannot replay. Plaintext
|
|
545
|
+
dialects replay the reasoning text; an occurrence captured from Chat
|
|
546
|
+
Completions is left out without degrading the group.
|
|
547
|
+
"""
|
|
548
|
+
if encrypted:
|
|
549
|
+
foreign = {
|
|
550
|
+
id(contents[0])
|
|
551
|
+
for contents in occurrences
|
|
552
|
+
if not all(replays_to(content.additional_properties, origin) for content in contents)
|
|
553
|
+
}
|
|
554
|
+
items = {
|
|
555
|
+
id(contents[0]): item
|
|
556
|
+
for contents in occurrences
|
|
557
|
+
if id(contents[0]) not in foreign and (item := _encrypted_item(contents)) is not None
|
|
558
|
+
}
|
|
559
|
+
return items, len(items) == len(occurrences), bool(foreign) and len(items) + len(foreign) == len(occurrences)
|
|
560
|
+
items = {id(contents[0]): item for contents in occurrences if (item := _plaintext_item(contents)) is not None}
|
|
561
|
+
return items, all(map(_plaintext_replayable, occurrences)), False
|
|
562
|
+
|
|
563
|
+
|
|
564
|
+
def _encrypted_item(contents: Sequence[Content]) -> dict[str, Any] | None:
|
|
565
|
+
reasoning_id = contents[0].id
|
|
566
|
+
# Every streamed sibling carries the item's first payload; only the last
|
|
567
|
+
# one carries the final payload, so the last one present wins.
|
|
568
|
+
payload = next(
|
|
569
|
+
(
|
|
570
|
+
found
|
|
571
|
+
for content in reversed(contents)
|
|
572
|
+
if (found := content.protected_data or content.additional_properties.get("encrypted_content"))
|
|
573
|
+
),
|
|
574
|
+
None,
|
|
575
|
+
)
|
|
576
|
+
if not reasoning_id or not payload:
|
|
577
|
+
return None
|
|
578
|
+
item: dict[str, Any] = {"type": "reasoning", "id": reasoning_id, "summary": [], "encrypted_content": payload}
|
|
579
|
+
texts: list[dict[str, str]] = []
|
|
580
|
+
for content in contents:
|
|
581
|
+
properties = content.additional_properties
|
|
582
|
+
if status := properties.get("status"):
|
|
583
|
+
item["status"] = status
|
|
584
|
+
if properties.get("reasoning_text"):
|
|
585
|
+
if text := marked_reasoning_text(content):
|
|
586
|
+
texts.append({"type": "reasoning_text", "text": text})
|
|
587
|
+
elif content.text:
|
|
588
|
+
item["summary"].append({"type": "summary_text", "text": content.text})
|
|
589
|
+
if texts:
|
|
590
|
+
item["content"] = texts
|
|
591
|
+
return item
|
|
592
|
+
|
|
593
|
+
|
|
594
|
+
def _plaintext_item(contents: Sequence[Content]) -> dict[str, Any] | None:
|
|
595
|
+
if not _plaintext_replayable(contents) or _chat_completions_formats(contents):
|
|
596
|
+
return None
|
|
597
|
+
status: Any = None
|
|
598
|
+
texts: list[dict[str, str]] = []
|
|
599
|
+
for content in contents:
|
|
600
|
+
if (value := content.additional_properties.get("status")) is not None:
|
|
601
|
+
status = value
|
|
602
|
+
if text := marked_reasoning_text(content):
|
|
603
|
+
texts.append({"type": "reasoning_text", "text": text})
|
|
604
|
+
if not texts:
|
|
605
|
+
return None
|
|
606
|
+
item: dict[str, Any] = {"type": "reasoning", "content": texts}
|
|
607
|
+
if contents[0].id:
|
|
608
|
+
item["id"] = contents[0].id
|
|
609
|
+
if status is not None:
|
|
610
|
+
item["status"] = status
|
|
611
|
+
return item
|
|
612
|
+
|
|
613
|
+
|
|
614
|
+
def _plaintext_replayable(contents: Sequence[Content]) -> bool:
|
|
615
|
+
if formats := _chat_completions_formats(contents):
|
|
616
|
+
return all(name in _CHAT_COMPLETIONS_FORMATS for name in formats)
|
|
617
|
+
# An encrypted payload without its item id is broken history.
|
|
618
|
+
payload = any(
|
|
619
|
+
content.protected_data or content.additional_properties.get("encrypted_content") for content in contents
|
|
620
|
+
)
|
|
621
|
+
return not (payload and not contents[0].id)
|
|
622
|
+
|
|
623
|
+
|
|
624
|
+
def _chat_completions_formats(contents: Sequence[Content]) -> list[Any]:
|
|
625
|
+
return [
|
|
626
|
+
content.additional_properties[REASONING_FORMAT_KEY]
|
|
627
|
+
for content in contents
|
|
628
|
+
if REASONING_FORMAT_KEY in content.additional_properties
|
|
629
|
+
]
|