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,319 @@
|
|
|
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
|
+
"""Compaction summary rendering and summary annotations."""
|
|
6
|
+
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
import logging
|
|
10
|
+
from typing import TYPE_CHECKING, Any
|
|
11
|
+
|
|
12
|
+
from chrys.foundation.trajectory.ids import new_analytics_id
|
|
13
|
+
from chrys.foundation.trajectory.metadata import ensure_analytics_item_id, read_analytics_item_id
|
|
14
|
+
from chrys.kernel import (
|
|
15
|
+
EXCLUDED_KEY,
|
|
16
|
+
GROUP_ANNOTATION_KEY,
|
|
17
|
+
SUMMARIZED_BY_SUMMARY_ID_KEY,
|
|
18
|
+
SUMMARY_OF_GROUP_IDS_KEY,
|
|
19
|
+
SUMMARY_OF_MESSAGE_IDS_KEY,
|
|
20
|
+
TOOL_CALL_CONTENT_TYPES,
|
|
21
|
+
TOOL_RESULT_CONTENT_TYPES,
|
|
22
|
+
Content,
|
|
23
|
+
Message,
|
|
24
|
+
annotate_message_groups,
|
|
25
|
+
annotate_token_counts,
|
|
26
|
+
set_excluded,
|
|
27
|
+
)
|
|
28
|
+
from chrys.kernel.compaction import _has_reasoning
|
|
29
|
+
from chrys.kernel.exchanges import (
|
|
30
|
+
EmptyIdPolicy,
|
|
31
|
+
LiveAccessor,
|
|
32
|
+
NoneIdPolicy,
|
|
33
|
+
PairingPolicy,
|
|
34
|
+
iter_exchanges,
|
|
35
|
+
pair_results,
|
|
36
|
+
)
|
|
37
|
+
|
|
38
|
+
from .events import _REASON_COMPACTION, _REASON_REMOVAL, CachedSummary
|
|
39
|
+
from .groups import _group_start_indices, _tool_call_name, _tool_result_text
|
|
40
|
+
|
|
41
|
+
if TYPE_CHECKING:
|
|
42
|
+
from chrys.kernel import TokenizerProtocol
|
|
43
|
+
|
|
44
|
+
from .exclusions import ExclusionLedger
|
|
45
|
+
|
|
46
|
+
_log = logging.getLogger(__name__)
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def _make_summary_message(
|
|
50
|
+
summary_text: str, summary_id: str, original_ids: list[str], group_id: str, *, item_id: str | None = None
|
|
51
|
+
) -> Message:
|
|
52
|
+
"""Create a compaction summary message."""
|
|
53
|
+
message = Message(
|
|
54
|
+
role="assistant",
|
|
55
|
+
contents=[summary_text],
|
|
56
|
+
message_id=summary_id,
|
|
57
|
+
additional_properties={
|
|
58
|
+
GROUP_ANNOTATION_KEY: {
|
|
59
|
+
SUMMARY_OF_MESSAGE_IDS_KEY: original_ids,
|
|
60
|
+
SUMMARY_OF_GROUP_IDS_KEY: [group_id],
|
|
61
|
+
},
|
|
62
|
+
},
|
|
63
|
+
)
|
|
64
|
+
# The summary replaces the group in every later request, so it needs its
|
|
65
|
+
# analytics identity now — not at the save that ends the turn.
|
|
66
|
+
ensure_analytics_item_id(message.additional_properties, item_id=item_id)
|
|
67
|
+
return message
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
_RESULT_SUMMARY_MAX = 100
|
|
71
|
+
"""Max characters for individual tool result text in compaction summaries."""
|
|
72
|
+
|
|
73
|
+
_ARGS_SUMMARY_MAX = 200
|
|
74
|
+
"""Max characters for tool call arguments in compaction summaries."""
|
|
75
|
+
|
|
76
|
+
_SUMMARY_TOTAL_MAX = 4096
|
|
77
|
+
"""Max characters for the complete tool-call compaction summary."""
|
|
78
|
+
|
|
79
|
+
_SUMMARY_TRUNCATION_MARKER = "... [truncated]"
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
_PAIRING_CONTENT_TYPES = TOOL_CALL_CONTENT_TYPES | TOOL_RESULT_CONTENT_TYPES
|
|
83
|
+
_SUMMARY_REPRESENTABLE_CONTENT_TYPES = frozenset({"text", "text_reasoning", "usage"})
|
|
84
|
+
_SUMMARY_PAIRING_POLICY = PairingPolicy(
|
|
85
|
+
call_types=TOOL_CALL_CONTENT_TYPES,
|
|
86
|
+
include_informational_calls=True,
|
|
87
|
+
result_types=TOOL_RESULT_CONTENT_TYPES,
|
|
88
|
+
none_id=NoneIdPolicy.POSITIONAL,
|
|
89
|
+
empty_id=EmptyIdPolicy.POSITIONAL,
|
|
90
|
+
malformed_id="stringify",
|
|
91
|
+
)
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
def _is_fused_narration(message: Message) -> bool:
|
|
95
|
+
"""Whether the message is a narration member of a fused tool-call group.
|
|
96
|
+
|
|
97
|
+
Exchange fusion absorbs non-call assistant siblings between a call and
|
|
98
|
+
its results into the tool-call group; members carrying no call, result,
|
|
99
|
+
or reasoning content are wire-legal on their own, outside the group's
|
|
100
|
+
projection-atomicity set. Reasoning-bearing members are NOT narration:
|
|
101
|
+
a reasoning item must never outlive its exchange."""
|
|
102
|
+
return (
|
|
103
|
+
message.role == "assistant"
|
|
104
|
+
and not _has_reasoning(message)
|
|
105
|
+
and not any(content.type in _PAIRING_CONTENT_TYPES for content in message.contents)
|
|
106
|
+
)
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
def _narration_survives_summary(message: Message) -> bool:
|
|
110
|
+
"""Whether a narration member must stay on the wire when its group is
|
|
111
|
+
summarized: the text summary cannot represent contents like images, so
|
|
112
|
+
excluding such a member would silently drop them."""
|
|
113
|
+
return _is_fused_narration(message) and any(
|
|
114
|
+
content.type not in _SUMMARY_REPRESENTABLE_CONTENT_TYPES for content in message.contents
|
|
115
|
+
)
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
def _build_summary(group_msgs: list[Message]) -> str | None:
|
|
119
|
+
"""Build a compact summary preserving call args but trimming results."""
|
|
120
|
+
paired_calls: dict[tuple[int, int], Content] = {}
|
|
121
|
+
accessor = LiveAccessor()
|
|
122
|
+
for exchange in iter_exchanges(group_msgs, accessor):
|
|
123
|
+
pairing = pair_results(group_msgs, exchange, accessor, _SUMMARY_PAIRING_POLICY)
|
|
124
|
+
assignments = [assignment for values in pairing.truthy_assignments.values() for assignment in values] + [
|
|
125
|
+
assignment for values in pairing.falsy_assignments.values() for assignment in values
|
|
126
|
+
]
|
|
127
|
+
for call_occurrence, result_occurrence in assignments:
|
|
128
|
+
if result_occurrence is None:
|
|
129
|
+
continue
|
|
130
|
+
paired_calls[(result_occurrence.message_index, result_occurrence.content_index)] = group_msgs[
|
|
131
|
+
call_occurrence.message_index
|
|
132
|
+
].contents[call_occurrence.content_index]
|
|
133
|
+
|
|
134
|
+
# Collect results and absorbed narration with function context, in
|
|
135
|
+
# transcript order \u2014 a fused group may carry assistant text between a
|
|
136
|
+
# call and its results, and excluding the group must not drop that text.
|
|
137
|
+
tool_parts: list[str] = []
|
|
138
|
+
for message_index, msg in enumerate(group_msgs):
|
|
139
|
+
for content_index, content in enumerate(msg.contents):
|
|
140
|
+
if content.type in TOOL_RESULT_CONTENT_TYPES:
|
|
141
|
+
call = paired_calls.get((message_index, content_index))
|
|
142
|
+
result_text = _tool_result_text(content) or "completed"
|
|
143
|
+
if len(result_text) > _RESULT_SUMMARY_MAX:
|
|
144
|
+
result_text = f"{result_text[:_RESULT_SUMMARY_MAX]}... ({len(result_text)} chars)"
|
|
145
|
+
name = _tool_call_name(call) if call is not None else None
|
|
146
|
+
arguments = _summary_call_arguments(call) if call is not None else None
|
|
147
|
+
args_str = _format_summary_arguments(arguments)
|
|
148
|
+
call_str = f"{name}({args_str})" if args_str else name
|
|
149
|
+
tool_parts.append(f"{call_str or 'tool'} \u2192 {result_text}")
|
|
150
|
+
elif msg.role == "assistant" and content.type == "text" and content.text and content.text.strip():
|
|
151
|
+
narration = content.text.strip()
|
|
152
|
+
if len(narration) > _RESULT_SUMMARY_MAX:
|
|
153
|
+
narration = f"{narration[:_RESULT_SUMMARY_MAX]}... ({len(narration)} chars)"
|
|
154
|
+
tool_parts.append(f'assistant: "{narration}"')
|
|
155
|
+
|
|
156
|
+
if not tool_parts:
|
|
157
|
+
return None
|
|
158
|
+
summary_label = "; ".join(tool_parts)
|
|
159
|
+
prefix = "[Tool call: "
|
|
160
|
+
suffix = "]"
|
|
161
|
+
summary_text = f"{prefix}{summary_label}{suffix}"
|
|
162
|
+
if len(summary_text) <= _SUMMARY_TOTAL_MAX:
|
|
163
|
+
return summary_text
|
|
164
|
+
allowed_label_chars = _SUMMARY_TOTAL_MAX - len(prefix) - len(suffix) - len(_SUMMARY_TRUNCATION_MARKER)
|
|
165
|
+
truncated_label = summary_label[:allowed_label_chars].rstrip()
|
|
166
|
+
return f"{prefix}{truncated_label}{_SUMMARY_TRUNCATION_MARKER}{suffix}"
|
|
167
|
+
|
|
168
|
+
|
|
169
|
+
def _summary_call_arguments(content: Content) -> Any:
|
|
170
|
+
"""Return field-aware arguments for every canonical call variant."""
|
|
171
|
+
if content.type == "code_interpreter_tool_call":
|
|
172
|
+
code = "".join(item.text or "" for item in content.inputs or [] if item.type == "text")
|
|
173
|
+
return {"code": code} if code else None
|
|
174
|
+
if content.type == "image_generation_tool_call":
|
|
175
|
+
return {"image_id": content.image_id} if content.image_id else None
|
|
176
|
+
if content.type == "shell_tool_call":
|
|
177
|
+
arguments: dict[str, Any] = {}
|
|
178
|
+
if content.commands is not None:
|
|
179
|
+
arguments["commands"] = content.commands
|
|
180
|
+
if content.timeout_ms is not None:
|
|
181
|
+
arguments["timeout_ms"] = content.timeout_ms
|
|
182
|
+
if content.max_output_length is not None:
|
|
183
|
+
arguments["max_output_length"] = content.max_output_length
|
|
184
|
+
return arguments or None
|
|
185
|
+
return content.arguments
|
|
186
|
+
|
|
187
|
+
|
|
188
|
+
def _format_summary_arguments(arguments: Any) -> str:
|
|
189
|
+
if not arguments:
|
|
190
|
+
return ""
|
|
191
|
+
if isinstance(arguments, dict):
|
|
192
|
+
parts = []
|
|
193
|
+
for key, value in arguments.items():
|
|
194
|
+
value_str = f'"{value}"' if isinstance(value, str) else str(value)
|
|
195
|
+
parts.append(f"{key}={value_str}")
|
|
196
|
+
args_str = ", ".join(parts)
|
|
197
|
+
else:
|
|
198
|
+
args_str = str(arguments)
|
|
199
|
+
if len(args_str) > _ARGS_SUMMARY_MAX:
|
|
200
|
+
return f"{args_str[:_ARGS_SUMMARY_MAX]}..."
|
|
201
|
+
return args_str
|
|
202
|
+
|
|
203
|
+
|
|
204
|
+
def _set_summarized(message: Message, summary_id: str) -> None:
|
|
205
|
+
"""Mark a message as summarized by a given summary ID.
|
|
206
|
+
|
|
207
|
+
Creates a **new** dict for the ``_group`` annotation to avoid mutating
|
|
208
|
+
a dict that may be shared with another Message: shallow-copying
|
|
209
|
+
``additional_properties`` via ``dict()`` retains nested annotation aliases.
|
|
210
|
+
"""
|
|
211
|
+
existing: dict[str, Any] = message.additional_properties.get(GROUP_ANNOTATION_KEY, {})
|
|
212
|
+
annotation = dict(existing) if isinstance(existing, dict) else {}
|
|
213
|
+
annotation[SUMMARIZED_BY_SUMMARY_ID_KEY] = summary_id
|
|
214
|
+
message.additional_properties[GROUP_ANNOTATION_KEY] = annotation
|
|
215
|
+
|
|
216
|
+
|
|
217
|
+
def _compact_group(
|
|
218
|
+
messages: list[Message],
|
|
219
|
+
group_id: str,
|
|
220
|
+
group_msgs: list[Message],
|
|
221
|
+
*,
|
|
222
|
+
ledger: ExclusionLedger,
|
|
223
|
+
tokenizer: TokenizerProtocol,
|
|
224
|
+
) -> list[str] | None:
|
|
225
|
+
"""Compact one tool-call group and update its ledger cache."""
|
|
226
|
+
if (
|
|
227
|
+
not group_msgs
|
|
228
|
+
or group_id in ledger._removed_group_ids
|
|
229
|
+
or any(msg.additional_properties.get(EXCLUDED_KEY, False) for msg in group_msgs)
|
|
230
|
+
):
|
|
231
|
+
return None
|
|
232
|
+
|
|
233
|
+
kept_ids = {id(msg) for msg in group_msgs if _narration_survives_summary(msg)}
|
|
234
|
+
replaced_msgs = [msg for msg in group_msgs if id(msg) not in kept_ids]
|
|
235
|
+
|
|
236
|
+
summary_text = _build_summary(replaced_msgs)
|
|
237
|
+
if summary_text is None:
|
|
238
|
+
return None
|
|
239
|
+
# Group IDs are positional wire-view labels and may be reused next turn.
|
|
240
|
+
# The original-to-summary relationship needs its own occurrence identity.
|
|
241
|
+
item_id = new_analytics_id()
|
|
242
|
+
summary_id = f"tool_summary_{item_id}"
|
|
243
|
+
original_ids = [m.message_id for m in replaced_msgs if m.message_id]
|
|
244
|
+
|
|
245
|
+
tool_names = [
|
|
246
|
+
tool_name for msg in replaced_msgs for content in msg.contents if (tool_name := _tool_call_name(content))
|
|
247
|
+
]
|
|
248
|
+
|
|
249
|
+
# Mark the replaced originals as excluded. Narration members the text
|
|
250
|
+
# summary cannot represent (images and other non-text content) stay on
|
|
251
|
+
# the wire: they are not pairing carriers, so the group still projects
|
|
252
|
+
# atomically without them.
|
|
253
|
+
any_changed = False
|
|
254
|
+
for msg in replaced_msgs:
|
|
255
|
+
_set_summarized(msg, summary_id)
|
|
256
|
+
any_changed = set_excluded(msg, excluded=True, reason=_REASON_COMPACTION) or any_changed
|
|
257
|
+
|
|
258
|
+
if not any_changed:
|
|
259
|
+
return None
|
|
260
|
+
|
|
261
|
+
summary_message = _make_summary_message(summary_text, summary_id, original_ids, group_id, item_id=item_id)
|
|
262
|
+
# Cache the occurrence identity too: message_id may be rewritten each pass.
|
|
263
|
+
ledger._summary_cache[summary_id] = CachedSummary(
|
|
264
|
+
summary_text=summary_text,
|
|
265
|
+
original_ids=original_ids,
|
|
266
|
+
group_id=group_id,
|
|
267
|
+
item_id=item_id,
|
|
268
|
+
message=summary_message,
|
|
269
|
+
)
|
|
270
|
+
|
|
271
|
+
starts = _group_start_indices(messages)
|
|
272
|
+
insertion_index = starts.get(group_id, 0)
|
|
273
|
+
messages.insert(insertion_index, summary_message)
|
|
274
|
+
|
|
275
|
+
annotate_message_groups(messages, from_index=insertion_index, force_reannotate=False)
|
|
276
|
+
annotate_token_counts(messages, tokenizer=tokenizer, from_index=insertion_index)
|
|
277
|
+
|
|
278
|
+
return tool_names
|
|
279
|
+
|
|
280
|
+
|
|
281
|
+
def _remove_group(
|
|
282
|
+
messages: list[Message],
|
|
283
|
+
group_id: str,
|
|
284
|
+
group_msgs: list[Message],
|
|
285
|
+
*,
|
|
286
|
+
ledger: ExclusionLedger,
|
|
287
|
+
) -> list[str] | None:
|
|
288
|
+
"""Remove one tool-call group and update its ledger state."""
|
|
289
|
+
if not group_msgs:
|
|
290
|
+
return None
|
|
291
|
+
|
|
292
|
+
tool_names = [
|
|
293
|
+
tool_name for msg in group_msgs for content in msg.contents if (tool_name := _tool_call_name(content))
|
|
294
|
+
]
|
|
295
|
+
|
|
296
|
+
any_changed = False
|
|
297
|
+
for msg in group_msgs:
|
|
298
|
+
if _is_fused_narration(msg):
|
|
299
|
+
continue
|
|
300
|
+
any_changed = set_excluded(msg, excluded=True, reason=_REASON_REMOVAL) or any_changed
|
|
301
|
+
|
|
302
|
+
summary_ids: set[str] = set()
|
|
303
|
+
for msg in group_msgs:
|
|
304
|
+
annotation = msg.additional_properties.get(GROUP_ANNOTATION_KEY)
|
|
305
|
+
if isinstance(annotation, dict) and isinstance(sid := annotation.get(SUMMARIZED_BY_SUMMARY_ID_KEY), str):
|
|
306
|
+
summary_ids.add(sid)
|
|
307
|
+
for msg in messages:
|
|
308
|
+
item_id = read_analytics_item_id(msg.additional_properties)
|
|
309
|
+
if item_id is not None and f"tool_summary_{item_id}" in summary_ids:
|
|
310
|
+
any_changed = set_excluded(msg, excluded=True, reason=_REASON_REMOVAL) or any_changed
|
|
311
|
+
|
|
312
|
+
if not any_changed:
|
|
313
|
+
return None
|
|
314
|
+
|
|
315
|
+
for summary_id in summary_ids:
|
|
316
|
+
ledger._summary_cache.pop(summary_id, None)
|
|
317
|
+
ledger._removed_group_ids.add(group_id)
|
|
318
|
+
|
|
319
|
+
return tool_names
|
|
@@ -0,0 +1,375 @@
|
|
|
1
|
+
# Copyright (c) Huawei Technologies Co., Ltd. 2026. All rights reserved.
|
|
2
|
+
|
|
3
|
+
"""Turn resolution over live wire messages and provider state."""
|
|
4
|
+
|
|
5
|
+
from __future__ import annotations
|
|
6
|
+
|
|
7
|
+
import logging
|
|
8
|
+
from dataclasses import dataclass
|
|
9
|
+
from typing import Any
|
|
10
|
+
|
|
11
|
+
from chrys.foundation.models.history_markers import HistoryMarkerKind
|
|
12
|
+
from chrys.foundation.models.turns import opens_turn, turn_slices
|
|
13
|
+
from chrys.kernel import EXCLUDED_KEY, Message
|
|
14
|
+
from chrys.service.context.providers.history import TURN_INDEX_KEY
|
|
15
|
+
|
|
16
|
+
_log = logging.getLogger(__name__)
|
|
17
|
+
|
|
18
|
+
# ---------------------------------------------------------------------------
|
|
19
|
+
# Turn resolution (§3.2 of the turn-boundary unification plan)
|
|
20
|
+
# ---------------------------------------------------------------------------
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
@dataclass(frozen=True)
|
|
24
|
+
class TurnSpan:
|
|
25
|
+
"""One resolved turn over the wire list. Snapshot-scoped indices."""
|
|
26
|
+
|
|
27
|
+
start: int
|
|
28
|
+
"""Wire index of the span's first message."""
|
|
29
|
+
|
|
30
|
+
end: int
|
|
31
|
+
"""Wire index one past the span's last message."""
|
|
32
|
+
|
|
33
|
+
absolute_number: int
|
|
34
|
+
"""State-backed absolute turn number (event cosmetics only)."""
|
|
35
|
+
|
|
36
|
+
state_boundary: int | None
|
|
37
|
+
"""Provider-state index of the span's start-boundary message.
|
|
38
|
+
|
|
39
|
+
``None`` when the boundary message is absent from state — for the
|
|
40
|
+
current span that is the Phase 3 clamp's protect-nothing signal: the
|
|
41
|
+
input is stored only after the run, and inputs are stored before
|
|
42
|
+
outputs, so state then holds no current-turn work at all.
|
|
43
|
+
"""
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
@dataclass(frozen=True)
|
|
47
|
+
class ResolvedTurns:
|
|
48
|
+
"""Snapshot-scoped turn resolution over the live wire + provider state.
|
|
49
|
+
|
|
50
|
+
Valid only until the next wire/state mutation: Phase 1 inserts summary
|
|
51
|
+
messages into the wire list and every Phase 3 fold replaces
|
|
52
|
+
``state["messages"]`` outright, shifting all later indices. Re-resolve
|
|
53
|
+
after a mutation; never cache a result across one.
|
|
54
|
+
"""
|
|
55
|
+
|
|
56
|
+
spans: list[TurnSpan]
|
|
57
|
+
"""Real turns, oldest first; the last span is the current turn."""
|
|
58
|
+
|
|
59
|
+
degraded: bool
|
|
60
|
+
"""True when the current marker region holds no real opener and the
|
|
61
|
+
current span was synthesized from the region (§3.2 rule 4)."""
|
|
62
|
+
|
|
63
|
+
synthetic_opener_idx: int | None
|
|
64
|
+
"""Wire index of the first user message inside a degraded region (the
|
|
65
|
+
prompt-visible "opener" is synthetic); ``None`` for an assistant/tool-
|
|
66
|
+
only degraded region, and always ``None`` in strict mode."""
|
|
67
|
+
|
|
68
|
+
region_start: int
|
|
69
|
+
"""Wire index where the current marker region starts."""
|
|
70
|
+
|
|
71
|
+
@property
|
|
72
|
+
def current(self) -> TurnSpan | None:
|
|
73
|
+
"""The current turn's span (the last one), or ``None``."""
|
|
74
|
+
return self.spans[-1] if self.spans else None
|
|
75
|
+
|
|
76
|
+
@property
|
|
77
|
+
def previous(self) -> list[TurnSpan]:
|
|
78
|
+
"""All completed turns' spans, oldest first."""
|
|
79
|
+
return self.spans[:-1]
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
def _state_correspondence(messages: list[Message], state_messages: list[Message]) -> dict[int, int]:
|
|
83
|
+
"""Map wire index → provider-state index.
|
|
84
|
+
|
|
85
|
+
Membership is by identity first, in two tiers. Wrapper identity hits
|
|
86
|
+
when the wire list holds the state objects themselves (legacy callers,
|
|
87
|
+
state-side projections). The kernel wire, however, hands every layer
|
|
88
|
+
per-call message VIEWS — fresh wrapper + fresh contents list — so the
|
|
89
|
+
second tier matches on the tuple of shared content-object ids, which is
|
|
90
|
+
exact to the same degree: content objects live in exactly one message
|
|
91
|
+
(the transcript's no-duplicate invariant), and a view carries the state
|
|
92
|
+
original's objects. Empty-contents messages carry no identity evidence
|
|
93
|
+
and skip the tier. The third tier matches wrappers REBUILT with fresh
|
|
94
|
+
contents but the original's ``additional_properties`` dict — the
|
|
95
|
+
sanctioned write-through channel, kept by the reminder middleware's
|
|
96
|
+
enriched user messages and the LAST_WORDS refresh. Without it a
|
|
97
|
+
stored opener that is also the last user message (a child continuing
|
|
98
|
+
from its own history) drops out of the history segment and the turn
|
|
99
|
+
resolves to nothing. The dict must belong to exactly one state message
|
|
100
|
+
and the roles must agree. The ``message_id`` fallback serves only wire
|
|
101
|
+
messages with no identity hit anywhere in state (streaming finalizers
|
|
102
|
+
rebuild current-turn messages into fresh objects, contents included)
|
|
103
|
+
and is guarded: built EXCLUDING excluded and marker state messages and
|
|
104
|
+
requiring role agreement — a bare id match is not safe because
|
|
105
|
+
response aggregation reuses sequential ids across runs and
|
|
106
|
+
``_dedup_message_ids`` runs only over the wire list, so a pre-marker
|
|
107
|
+
EXCLUDED state message can hold the same id as a visible current-turn
|
|
108
|
+
message. Later state copies win: rebuilt wire objects twin with the
|
|
109
|
+
newest state occurrence of their id.
|
|
110
|
+
"""
|
|
111
|
+
by_identity = {id(m): i for i, m in enumerate(state_messages)}
|
|
112
|
+
by_content_identity: dict[tuple[int, ...], int] = {}
|
|
113
|
+
by_properties_identity: dict[int, int] = {}
|
|
114
|
+
shared_properties: set[int] = set()
|
|
115
|
+
for s, m in enumerate(state_messages):
|
|
116
|
+
if m.contents:
|
|
117
|
+
by_content_identity[tuple(id(c) for c in m.contents)] = s
|
|
118
|
+
properties_key = id(m.additional_properties)
|
|
119
|
+
if properties_key in by_properties_identity:
|
|
120
|
+
shared_properties.add(properties_key)
|
|
121
|
+
by_properties_identity[properties_key] = s
|
|
122
|
+
for properties_key in shared_properties:
|
|
123
|
+
del by_properties_identity[properties_key]
|
|
124
|
+
mapping: dict[int, int] = {}
|
|
125
|
+
unmatched: list[int] = []
|
|
126
|
+
for w, msg in enumerate(messages):
|
|
127
|
+
s = by_identity.get(id(msg))
|
|
128
|
+
if s is None and msg.contents:
|
|
129
|
+
s = by_content_identity.get(tuple(id(c) for c in msg.contents))
|
|
130
|
+
if s is None:
|
|
131
|
+
s = by_properties_identity.get(id(msg.additional_properties))
|
|
132
|
+
if s is not None and state_messages[s].role != msg.role:
|
|
133
|
+
s = None
|
|
134
|
+
if s is None:
|
|
135
|
+
unmatched.append(w)
|
|
136
|
+
else:
|
|
137
|
+
mapping[w] = s
|
|
138
|
+
if not unmatched:
|
|
139
|
+
return mapping
|
|
140
|
+
|
|
141
|
+
fallback: dict[tuple[str, str], int] = {}
|
|
142
|
+
for s, msg in enumerate(state_messages):
|
|
143
|
+
mid = msg.message_id
|
|
144
|
+
if not mid:
|
|
145
|
+
continue
|
|
146
|
+
props = msg.additional_properties
|
|
147
|
+
if props.get(EXCLUDED_KEY, False) or HistoryMarkerKind.KEY in props:
|
|
148
|
+
continue
|
|
149
|
+
fallback[(mid, msg.role)] = s
|
|
150
|
+
engaged = False
|
|
151
|
+
for w in unmatched:
|
|
152
|
+
mid = messages[w].message_id
|
|
153
|
+
if not mid:
|
|
154
|
+
continue
|
|
155
|
+
s = fallback.get((mid, messages[w].role))
|
|
156
|
+
if s is not None:
|
|
157
|
+
mapping[w] = s
|
|
158
|
+
engaged = True
|
|
159
|
+
if engaged:
|
|
160
|
+
_log.debug("turn resolver: message_id fallback engaged for wire-state correspondence")
|
|
161
|
+
return mapping
|
|
162
|
+
|
|
163
|
+
|
|
164
|
+
def _last_healthy_turn_marker(state_messages: list[Message]) -> tuple[int | None, int]:
|
|
165
|
+
"""Return ``(state index, _turn int)`` of the last HEALTHY turn marker.
|
|
166
|
+
|
|
167
|
+
A marker cluster (the contiguous run of ``_chrys_kind`` messages ending
|
|
168
|
+
at a TURN marker) containing ANY ``HistoryMarkerKind.STATUS_MARKERS``
|
|
169
|
+
member does not close a completed turn: a crash-terminated turn is an
|
|
170
|
+
interrupted CURRENT task, not a completed exchange. Walk back to the
|
|
171
|
+
newest turn marker whose cluster carries no status marker. Returns
|
|
172
|
+
``(None, 0)`` when no healthy marker exists; the int is ``0`` when the
|
|
173
|
+
healthy marker carries no usable ``_turn``.
|
|
174
|
+
"""
|
|
175
|
+
i = len(state_messages) - 1
|
|
176
|
+
while i >= 0:
|
|
177
|
+
props = state_messages[i].additional_properties
|
|
178
|
+
if props.get(HistoryMarkerKind.KEY) != HistoryMarkerKind.TURN:
|
|
179
|
+
i -= 1
|
|
180
|
+
continue
|
|
181
|
+
healthy = True
|
|
182
|
+
j = i
|
|
183
|
+
while j >= 0:
|
|
184
|
+
kind = state_messages[j].additional_properties.get(HistoryMarkerKind.KEY)
|
|
185
|
+
if not kind:
|
|
186
|
+
break
|
|
187
|
+
if kind in HistoryMarkerKind.STATUS_MARKERS:
|
|
188
|
+
healthy = False
|
|
189
|
+
j -= 1
|
|
190
|
+
if healthy:
|
|
191
|
+
turn_int = props.get(TURN_INDEX_KEY)
|
|
192
|
+
return i, turn_int if isinstance(turn_int, int) else 0
|
|
193
|
+
i = j
|
|
194
|
+
return None, 0
|
|
195
|
+
|
|
196
|
+
|
|
197
|
+
def _folded_turn_seed(state: dict[str, Any] | None) -> int:
|
|
198
|
+
"""Return the highest turn number preserved only in compressed blocks.
|
|
199
|
+
|
|
200
|
+
Phase 3 / force compression folds up to a marker INCLUSIVE, so folded
|
|
201
|
+
turns' markers no longer live in active state; their numbers survive in
|
|
202
|
+
``compressed_msgs[*].turn_range``. Skips the ``(0, 0)`` no-marker
|
|
203
|
+
sentinel.
|
|
204
|
+
"""
|
|
205
|
+
if state is None:
|
|
206
|
+
return 0
|
|
207
|
+
blocks = state.get("compressed_msgs")
|
|
208
|
+
if not isinstance(blocks, list):
|
|
209
|
+
return 0
|
|
210
|
+
seed = 0
|
|
211
|
+
for block in blocks:
|
|
212
|
+
turn_range = getattr(block, "turn_range", None)
|
|
213
|
+
if turn_range is None and isinstance(block, dict):
|
|
214
|
+
turn_range = block.get("turn_range")
|
|
215
|
+
if not isinstance(turn_range, tuple | list) or len(turn_range) != 2:
|
|
216
|
+
continue
|
|
217
|
+
low, high = turn_range
|
|
218
|
+
if (low, high) == (0, 0) or not isinstance(high, int):
|
|
219
|
+
continue
|
|
220
|
+
seed = max(seed, high)
|
|
221
|
+
return seed
|
|
222
|
+
|
|
223
|
+
|
|
224
|
+
def _resolve_turns(messages: list[Message], state: dict[str, Any] | None) -> ResolvedTurns:
|
|
225
|
+
"""Resolve real turns over the live wire list + provider state (§3.2).
|
|
226
|
+
|
|
227
|
+
Strict when the current marker region holds a real opener; degraded
|
|
228
|
+
(current span = the whole region) when the region is non-empty with no
|
|
229
|
+
opener but holds a user message or follows completed strict turns; the
|
|
230
|
+
empty result only for histories that never held user input. The marker
|
|
231
|
+
boundary comes from the provider state (where markers live) and is
|
|
232
|
+
PROJECTED into the wire list via the identity-first correspondence —
|
|
233
|
+
compaction receives the marker-less wire view, so a wire-side marker
|
|
234
|
+
scan can never see one. EXCLUDED wire messages are invisible to the
|
|
235
|
+
scan: a mid-call fold (Step 0 / P3) excludes a completed turn in place,
|
|
236
|
+
and its opener must not keep opening a turn the state no longer holds.
|
|
237
|
+
"""
|
|
238
|
+
state_messages: list[Message] = []
|
|
239
|
+
if state is not None:
|
|
240
|
+
raw = state.get("messages")
|
|
241
|
+
if isinstance(raw, list):
|
|
242
|
+
state_messages = raw
|
|
243
|
+
|
|
244
|
+
correspondence = _state_correspondence(messages, state_messages) if state_messages else {}
|
|
245
|
+
|
|
246
|
+
# Rule 1a — history segment. Spans are confined to it in both strict
|
|
247
|
+
# and degraded modes: non-history providers can emit user-role messages
|
|
248
|
+
# into the request prefix, and unclipped slicing would let such a prefix
|
|
249
|
+
# message open a "turn", handing provider context to P1/P2 and
|
|
250
|
+
# mis-anchoring P4's prior-turn boundary.
|
|
251
|
+
if correspondence:
|
|
252
|
+
history_start = min(correspondence)
|
|
253
|
+
elif state_messages:
|
|
254
|
+
# State exists but none of it is on the wire (service-side context
|
|
255
|
+
# skips local history): the only session content is the in-flight
|
|
256
|
+
# input tail — anchor at its opener (or first user message for a
|
|
257
|
+
# flagged-only tail) so a provider prefix can never open a turn.
|
|
258
|
+
last_opener = None
|
|
259
|
+
first_user = None
|
|
260
|
+
for i, msg in enumerate(messages):
|
|
261
|
+
if opens_turn(msg):
|
|
262
|
+
last_opener = i
|
|
263
|
+
if first_user is None and msg.role == "user":
|
|
264
|
+
first_user = i
|
|
265
|
+
if last_opener is not None:
|
|
266
|
+
history_start = last_opener
|
|
267
|
+
elif first_user is not None:
|
|
268
|
+
history_start = first_user
|
|
269
|
+
else:
|
|
270
|
+
history_start = len(messages)
|
|
271
|
+
else:
|
|
272
|
+
# No provider state (fresh session or unbound strategy): the whole
|
|
273
|
+
# wire is the segment, matching pre-resolver behavior.
|
|
274
|
+
history_start = 0
|
|
275
|
+
|
|
276
|
+
# Rule 1b — marker region, from the state-side scan projected into the
|
|
277
|
+
# wire: just after the last wire message belonging to the completed-
|
|
278
|
+
# turns set (state messages at/before the last HEALTHY turn marker).
|
|
279
|
+
marker_idx, healthy_turn_int = _last_healthy_turn_marker(state_messages)
|
|
280
|
+
if marker_idx is None:
|
|
281
|
+
region_start = history_start
|
|
282
|
+
else:
|
|
283
|
+
completed_wire = [w for w, s in correspondence.items() if s <= marker_idx]
|
|
284
|
+
region_start = max(completed_wire) + 1 if completed_wire else history_start
|
|
285
|
+
|
|
286
|
+
# Slice over VISIBLE messages only: Step-0 compressions and P3 folds
|
|
287
|
+
# exclude wire messages in place mid-call, and a folded opener must not
|
|
288
|
+
# reopen a turn that no longer exists in provider state (the provider
|
|
289
|
+
# filters excluded messages from the wire before the next request, so
|
|
290
|
+
# mid-call exclusion is the only way one reaches the resolver). Spans
|
|
291
|
+
# keep raw wire indices — each span runs to the next span's start, so
|
|
292
|
+
# interleaved excluded messages stay inside a span and the phases'
|
|
293
|
+
# exclusion-aware group collection sees contiguous ranges.
|
|
294
|
+
segment = messages[history_start:]
|
|
295
|
+
visible_idx = [i for i, m in enumerate(segment) if not m.additional_properties.get(EXCLUDED_KEY, False)]
|
|
296
|
+
visible_slices = turn_slices([segment[i] for i in visible_idx])
|
|
297
|
+
slices: list[tuple[int, int]] = []
|
|
298
|
+
for k, (s, _e) in enumerate(visible_slices):
|
|
299
|
+
start = visible_idx[s] + history_start
|
|
300
|
+
end = visible_idx[visible_slices[k + 1][0]] + history_start if k + 1 < len(visible_slices) else len(messages)
|
|
301
|
+
slices.append((start, end))
|
|
302
|
+
|
|
303
|
+
region = messages[region_start:]
|
|
304
|
+
region_visible = [m for m in region if not m.additional_properties.get(EXCLUDED_KEY, False)]
|
|
305
|
+
degraded = False
|
|
306
|
+
synthetic_opener_idx: int | None = None
|
|
307
|
+
if not region_visible or any(opens_turn(m) for m in region_visible):
|
|
308
|
+
# Rules 2 + 3 — strict: current turn = the last slice.
|
|
309
|
+
final_slices = slices
|
|
310
|
+
elif any(m.role == "user" for m in region_visible) or slices:
|
|
311
|
+
# Rule 4 — degraded: the current span is the whole region (its
|
|
312
|
+
# assistant/tool work precedes any synthetic opener and P4 only
|
|
313
|
+
# collects groups from the span start); previous turns are the
|
|
314
|
+
# strict slices clipped at the region boundary (only the last one
|
|
315
|
+
# can straddle it, and clipping is correct precisely because the
|
|
316
|
+
# boundary cluster is healthy).
|
|
317
|
+
degraded = True
|
|
318
|
+
final_slices = [(s, min(e, region_start)) for s, e in slices if s < region_start]
|
|
319
|
+
final_slices.append((region_start, len(messages)))
|
|
320
|
+
synthetic_opener_idx = next(
|
|
321
|
+
(
|
|
322
|
+
region_start + i
|
|
323
|
+
for i, m in enumerate(region)
|
|
324
|
+
if m.role == "user" and not m.additional_properties.get(EXCLUDED_KEY, False)
|
|
325
|
+
),
|
|
326
|
+
None,
|
|
327
|
+
)
|
|
328
|
+
_log.debug(
|
|
329
|
+
"turn resolver: degraded region at wire index %d (synthetic opener: %s)",
|
|
330
|
+
region_start,
|
|
331
|
+
synthetic_opener_idx,
|
|
332
|
+
)
|
|
333
|
+
else:
|
|
334
|
+
# Rule 5 — no user message anywhere: today's no-op early return.
|
|
335
|
+
return ResolvedTurns(spans=[], degraded=False, synthetic_opener_idx=None, region_start=region_start)
|
|
336
|
+
|
|
337
|
+
# Absolute numbering. Completed spans read the first state turn marker
|
|
338
|
+
# after their opener; the current span is max(last healthy active
|
|
339
|
+
# marker, folded seed) + 1 — NOT turn_counter + 1, which counts an
|
|
340
|
+
# unstripped crash cluster's aborted turn while the resolver refuses to
|
|
341
|
+
# close it. The resolver wins on divergence. The previous-span count
|
|
342
|
+
# keeps enumeration coherent when state carries no numbering at all
|
|
343
|
+
# (unbound strategy) or a healthy marker lost its ``_turn`` int.
|
|
344
|
+
seed = _folded_turn_seed(state)
|
|
345
|
+
current_number = max(healthy_turn_int, seed, len(final_slices) - 1) + 1
|
|
346
|
+
state_turn_markers = [
|
|
347
|
+
(i, m.additional_properties.get(TURN_INDEX_KEY))
|
|
348
|
+
for i, m in enumerate(state_messages)
|
|
349
|
+
if m.additional_properties.get(HistoryMarkerKind.KEY) == HistoryMarkerKind.TURN
|
|
350
|
+
]
|
|
351
|
+
|
|
352
|
+
spans: list[TurnSpan] = []
|
|
353
|
+
last = len(final_slices) - 1
|
|
354
|
+
for k, (start, end) in enumerate(final_slices):
|
|
355
|
+
state_boundary = correspondence.get(start)
|
|
356
|
+
if k == last:
|
|
357
|
+
number = current_number
|
|
358
|
+
else:
|
|
359
|
+
number = None
|
|
360
|
+
if state_boundary is not None:
|
|
361
|
+
for m_idx, turn_int in state_turn_markers:
|
|
362
|
+
if m_idx > state_boundary and isinstance(turn_int, int):
|
|
363
|
+
number = turn_int
|
|
364
|
+
break
|
|
365
|
+
if number is None:
|
|
366
|
+
number = seed + k + 1
|
|
367
|
+
_log.debug("turn resolver: enumerated fallback number %d for span %d", number, k)
|
|
368
|
+
spans.append(TurnSpan(start=start, end=end, absolute_number=number, state_boundary=state_boundary))
|
|
369
|
+
|
|
370
|
+
return ResolvedTurns(
|
|
371
|
+
spans=spans,
|
|
372
|
+
degraded=degraded,
|
|
373
|
+
synthetic_opener_idx=synthetic_opener_idx,
|
|
374
|
+
region_start=region_start,
|
|
375
|
+
)
|