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,647 @@
|
|
|
1
|
+
# Copyright (c) Huawei Technologies Co., Ltd. 2026. All rights reserved.
|
|
2
|
+
|
|
3
|
+
"""CompressibleHistoryProvider — History provider with marker-based context compression.
|
|
4
|
+
|
|
5
|
+
Supports automatic turn markers, stacking context compression, and
|
|
6
|
+
recall via sub-agent queries on compressed blocks.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from __future__ import annotations
|
|
10
|
+
|
|
11
|
+
import copy
|
|
12
|
+
import uuid
|
|
13
|
+
from dataclasses import dataclass, field
|
|
14
|
+
from typing import TYPE_CHECKING, Any
|
|
15
|
+
|
|
16
|
+
from chrys.foundation.models.history_markers import HistoryMarkerKind
|
|
17
|
+
from chrys.foundation.models.turns import is_continuation_message
|
|
18
|
+
from chrys.foundation.trajectory.metadata import ensure_analytics_item_id
|
|
19
|
+
from chrys.foundation.util.time import utc_iso
|
|
20
|
+
from chrys.kernel import EXCLUDED_KEY as _EXCLUDED_KEY
|
|
21
|
+
from chrys.kernel import (
|
|
22
|
+
TOOL_CALL_CONTENT_TYPES,
|
|
23
|
+
AgentSession,
|
|
24
|
+
HistoryProvider,
|
|
25
|
+
Message,
|
|
26
|
+
SessionContext,
|
|
27
|
+
collect_conversation_handles,
|
|
28
|
+
strip_invalidated_conversation_handles,
|
|
29
|
+
)
|
|
30
|
+
from chrys.service.context.middleware.usage import contains_provider_hosted_content, resolve_hosted_context_input_tokens
|
|
31
|
+
from chrys.service.context.tool_content import tool_call_name
|
|
32
|
+
from chrys.service.session.message_metadata import (
|
|
33
|
+
LAST_ASSISTANT_CREATED_AT_STATE_KEY,
|
|
34
|
+
MESSAGE_CREATED_AT_KEY,
|
|
35
|
+
should_stamp_message_created_at,
|
|
36
|
+
stamp_message_created_at,
|
|
37
|
+
try_normalize_created_at,
|
|
38
|
+
)
|
|
39
|
+
|
|
40
|
+
if TYPE_CHECKING:
|
|
41
|
+
from collections.abc import Collection, Mapping, Sequence
|
|
42
|
+
|
|
43
|
+
from chrys.service.context.compaction import UnifiedContextStrategy
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
@dataclass
|
|
47
|
+
class CompressedBlock:
|
|
48
|
+
"""A block of original messages that were compressed into a summary.
|
|
49
|
+
|
|
50
|
+
Attributes:
|
|
51
|
+
compressed_context_id: Unique identifier for this block (e.g., ``ctx_a1b2c3d4``).
|
|
52
|
+
messages: Deep copy of the original messages that were compressed.
|
|
53
|
+
summary_text: The summary that replaced them in the active history.
|
|
54
|
+
marker_id: The marker_id up to which compression occurred.
|
|
55
|
+
turn_range: ``(from_turn, to_turn)`` inclusive turn indices.
|
|
56
|
+
created_at: ISO timestamp of when compression occurred.
|
|
57
|
+
"""
|
|
58
|
+
|
|
59
|
+
compressed_context_id: str
|
|
60
|
+
messages: list[Message] = field(default_factory=list)
|
|
61
|
+
summary_text: str = ""
|
|
62
|
+
marker_id: str = ""
|
|
63
|
+
turn_range: tuple[int, int] = (0, 0)
|
|
64
|
+
created_at: str = ""
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
# ---------------------------------------------------------------------------
|
|
68
|
+
# Sentinel keys for identifying special messages in history
|
|
69
|
+
# ---------------------------------------------------------------------------
|
|
70
|
+
_TURN_ID_KEY = "_turn_id"
|
|
71
|
+
TURN_INDEX_KEY = "_turn"
|
|
72
|
+
_TURN_KEY = TURN_INDEX_KEY
|
|
73
|
+
_BLOCK_ID_KEY = "_block_id"
|
|
74
|
+
PRE_OUTPUT_HISTORY_LEN_STATE_KEY = "_chrys_pre_output_history_len"
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
def _is_turn_marker(msg: Message) -> bool:
|
|
78
|
+
"""Return True if the message is a turn marker."""
|
|
79
|
+
return msg.additional_properties.get(HistoryMarkerKind.KEY) == HistoryMarkerKind.TURN
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
def _is_compressed_summary(msg: Message) -> bool:
|
|
83
|
+
"""Return True if the message is a compressed summary."""
|
|
84
|
+
return msg.additional_properties.get(HistoryMarkerKind.KEY) == HistoryMarkerKind.SUMMARY
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
def _uses_service_side_context(
|
|
88
|
+
context: SessionContext,
|
|
89
|
+
default_options: Mapping[str, Any] | None = None,
|
|
90
|
+
invalidated_handles: Collection[str] | None = None,
|
|
91
|
+
) -> bool:
|
|
92
|
+
"""Return True when the current run should continue server-side history."""
|
|
93
|
+
options = dict(default_options or {})
|
|
94
|
+
options.update(context.options)
|
|
95
|
+
if invalidated_handles:
|
|
96
|
+
# ``context.options`` arrives already sanitized by the Agent, but
|
|
97
|
+
# sanitization REMOVES keys, and an absent key cannot override a
|
|
98
|
+
# configured default through the merge above — an invalidated
|
|
99
|
+
# default handle would read as live here while the wire choke point
|
|
100
|
+
# strips it, leaving the request with neither remote nor local
|
|
101
|
+
# history. Strip the merged view so the defaults obey the same
|
|
102
|
+
# invalidation verdicts as the request options.
|
|
103
|
+
options = strip_invalidated_conversation_handles(options, invalidated_handles)
|
|
104
|
+
# Normalized handle view: every continuation spelling counts — plain
|
|
105
|
+
# strings, mapping ``{"id": ...}`` forms, extra_body copies, and
|
|
106
|
+
# continuation tokens — since each reaches the wire as service-side
|
|
107
|
+
# continuation state; a handle that survives the strip above is live.
|
|
108
|
+
if collect_conversation_handles(options):
|
|
109
|
+
return True
|
|
110
|
+
if options.get("store") is False:
|
|
111
|
+
return False
|
|
112
|
+
return bool(context.service_session_id)
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
def _refresh_pre_output_history_len_from_anchors(state: dict[str, Any], anchors: list[Message]) -> None:
|
|
116
|
+
"""Refresh the current-turn floor after post-output history rewrites."""
|
|
117
|
+
if not anchors:
|
|
118
|
+
return
|
|
119
|
+
messages = state.get("messages")
|
|
120
|
+
if not isinstance(messages, list):
|
|
121
|
+
return
|
|
122
|
+
anchor_ids = {id(anchor) for anchor in anchors}
|
|
123
|
+
for index, message in enumerate(messages):
|
|
124
|
+
if id(message) in anchor_ids:
|
|
125
|
+
state[PRE_OUTPUT_HISTORY_LEN_STATE_KEY] = index
|
|
126
|
+
return
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
def _compress_state(
|
|
130
|
+
state: dict[str, Any],
|
|
131
|
+
marker_id: str,
|
|
132
|
+
summary_text: str,
|
|
133
|
+
compressed_context_id: str | None = None,
|
|
134
|
+
) -> tuple[str, list[Message]]:
|
|
135
|
+
"""Core compression: deep-copy fold range, create CompressedBlock, replace state messages.
|
|
136
|
+
|
|
137
|
+
Returns ``(compressed_context_id, fold_range)`` where *fold_range* is the
|
|
138
|
+
list of **original** Message objects that were in the fold range before
|
|
139
|
+
the list replacement. Callers that need tool-loop visibility can set
|
|
140
|
+
``_excluded`` flags on these shared objects.
|
|
141
|
+
|
|
142
|
+
Raises:
|
|
143
|
+
ValueError: If the marker is not found or invalid.
|
|
144
|
+
"""
|
|
145
|
+
messages: list[Message] = state.get("messages", [])
|
|
146
|
+
if not messages:
|
|
147
|
+
raise ValueError("Nothing to compress — history is empty.")
|
|
148
|
+
|
|
149
|
+
# Find the target marker
|
|
150
|
+
marker_idx: int | None = None
|
|
151
|
+
for i, msg in enumerate(messages):
|
|
152
|
+
if msg.additional_properties.get(_TURN_ID_KEY) == marker_id:
|
|
153
|
+
marker_idx = i
|
|
154
|
+
break
|
|
155
|
+
|
|
156
|
+
if marker_idx is None:
|
|
157
|
+
raise ValueError(f"Marker '{marker_id}' not found in history.")
|
|
158
|
+
|
|
159
|
+
# Find fold_start: first message after the last compressed summary
|
|
160
|
+
fold_start = 0
|
|
161
|
+
for i, msg in enumerate(messages):
|
|
162
|
+
if _is_compressed_summary(msg):
|
|
163
|
+
fold_start = i + 1
|
|
164
|
+
|
|
165
|
+
if fold_start > marker_idx:
|
|
166
|
+
raise ValueError(f"Marker '{marker_id}' is already within or before an existing compressed block.")
|
|
167
|
+
|
|
168
|
+
# Determine turn range from markers in the fold range
|
|
169
|
+
turn_indices = []
|
|
170
|
+
for msg in messages[fold_start : marker_idx + 1]:
|
|
171
|
+
ti = msg.additional_properties.get(_TURN_KEY)
|
|
172
|
+
if ti is not None:
|
|
173
|
+
turn_indices.append(ti)
|
|
174
|
+
turn_range = (min(turn_indices), max(turn_indices)) if turn_indices else (0, 0)
|
|
175
|
+
|
|
176
|
+
# Deep-copy the fold range (originals preserved in block)
|
|
177
|
+
fold_range = messages[fold_start : marker_idx + 1]
|
|
178
|
+
for message in fold_range:
|
|
179
|
+
ensure_analytics_item_id(message.additional_properties)
|
|
180
|
+
replaced = copy.deepcopy(fold_range)
|
|
181
|
+
|
|
182
|
+
# Create compressed block
|
|
183
|
+
if compressed_context_id is None:
|
|
184
|
+
compressed_context_id = f"ctx_{uuid.uuid4().hex[:8]}"
|
|
185
|
+
block = CompressedBlock(
|
|
186
|
+
compressed_context_id=compressed_context_id,
|
|
187
|
+
messages=replaced,
|
|
188
|
+
summary_text=summary_text,
|
|
189
|
+
marker_id=marker_id,
|
|
190
|
+
turn_range=turn_range,
|
|
191
|
+
created_at=utc_iso(),
|
|
192
|
+
)
|
|
193
|
+
|
|
194
|
+
compressed: list[CompressedBlock] = state.setdefault("compressed_msgs", [])
|
|
195
|
+
compressed.append(block)
|
|
196
|
+
|
|
197
|
+
# Create summary message
|
|
198
|
+
summary_msg = Message(
|
|
199
|
+
"assistant",
|
|
200
|
+
[f"[Compressed context: {compressed_context_id}]\nSummary: {summary_text}"],
|
|
201
|
+
)
|
|
202
|
+
summary_msg.additional_properties[HistoryMarkerKind.KEY] = HistoryMarkerKind.SUMMARY
|
|
203
|
+
summary_msg.additional_properties[_BLOCK_ID_KEY] = compressed_context_id
|
|
204
|
+
# It stands in for the whole folded range from the next request on, so it
|
|
205
|
+
# is stamped where it is minted rather than at the turn-ending save.
|
|
206
|
+
ensure_analytics_item_id(summary_msg.additional_properties)
|
|
207
|
+
|
|
208
|
+
# Replace state["messages"] with the clean list
|
|
209
|
+
state["messages"] = [
|
|
210
|
+
*messages[:fold_start],
|
|
211
|
+
summary_msg,
|
|
212
|
+
*messages[marker_idx + 1 :],
|
|
213
|
+
]
|
|
214
|
+
|
|
215
|
+
return compressed_context_id, fold_range
|
|
216
|
+
|
|
217
|
+
|
|
218
|
+
def _compress_state_validate(state: dict[str, Any], marker_id: str) -> int:
|
|
219
|
+
"""Validate that *marker_id* can be compressed, return fold range length.
|
|
220
|
+
|
|
221
|
+
Used by :meth:`UnifiedContextStrategy.queue_compression` for early
|
|
222
|
+
validation before the deferred execution in ``__call__``.
|
|
223
|
+
|
|
224
|
+
Raises:
|
|
225
|
+
ValueError: If the marker is not found or invalid.
|
|
226
|
+
"""
|
|
227
|
+
messages: list[Message] = state.get("messages", [])
|
|
228
|
+
if not messages:
|
|
229
|
+
raise ValueError("Nothing to compress — history is empty.")
|
|
230
|
+
|
|
231
|
+
marker_idx: int | None = None
|
|
232
|
+
for i, msg in enumerate(messages):
|
|
233
|
+
if msg.additional_properties.get(_TURN_ID_KEY) == marker_id:
|
|
234
|
+
marker_idx = i
|
|
235
|
+
break
|
|
236
|
+
if marker_idx is None:
|
|
237
|
+
raise ValueError(f"Marker '{marker_id}' not found in history.")
|
|
238
|
+
|
|
239
|
+
fold_start = 0
|
|
240
|
+
for i, msg in enumerate(messages):
|
|
241
|
+
if _is_compressed_summary(msg):
|
|
242
|
+
fold_start = i + 1
|
|
243
|
+
if fold_start > marker_idx:
|
|
244
|
+
raise ValueError(f"Marker '{marker_id}' is already within or before an existing compressed block.")
|
|
245
|
+
|
|
246
|
+
return marker_idx + 1 - fold_start
|
|
247
|
+
|
|
248
|
+
|
|
249
|
+
class CompressibleHistoryProvider(HistoryProvider):
|
|
250
|
+
"""In-memory history provider with marker-based context compression.
|
|
251
|
+
|
|
252
|
+
All state lives in ``session.state`` under the provider's ``source_id`` key
|
|
253
|
+
(passed by Agent as ``state`` in before/after_run).
|
|
254
|
+
|
|
255
|
+
State layout::
|
|
256
|
+
|
|
257
|
+
state["messages"] -> list[Message] (active message history)
|
|
258
|
+
state["compressed_msgs"] -> list[CompressedBlock] (stack of compressed blocks)
|
|
259
|
+
state["turn_counter"] -> int (monotonic turn counter)
|
|
260
|
+
|
|
261
|
+
The kernel ``SessionContext.extend_messages`` appends state messages
|
|
262
|
+
as-is (no copy), so ``_excluded`` flags set by intra-run compaction land
|
|
263
|
+
directly on stored history and persist across ``agent.run()`` calls.
|
|
264
|
+
The ``after_run`` anchor pass remains for the one path aliasing cannot
|
|
265
|
+
cover: streaming finalizers rebuild current-turn response messages from
|
|
266
|
+
updates, so their flags must be re-anchored onto the stored objects.
|
|
267
|
+
"""
|
|
268
|
+
|
|
269
|
+
DEFAULT_SOURCE_ID = "chrys_history"
|
|
270
|
+
|
|
271
|
+
def __init__(
|
|
272
|
+
self,
|
|
273
|
+
source_id: str | None = None,
|
|
274
|
+
compaction_strategy: UnifiedContextStrategy | None = None,
|
|
275
|
+
max_context_tokens: int = 0,
|
|
276
|
+
force_compress_pct: float = 0.70,
|
|
277
|
+
skip_local_history_for_service_context: bool = False,
|
|
278
|
+
service_context_default_options: Mapping[str, Any] | None = None,
|
|
279
|
+
use_local_context_estimate_for_hosted_usage: bool = False,
|
|
280
|
+
):
|
|
281
|
+
super().__init__(
|
|
282
|
+
source_id=source_id or self.DEFAULT_SOURCE_ID,
|
|
283
|
+
load_messages=True,
|
|
284
|
+
store_inputs=True,
|
|
285
|
+
store_outputs=True,
|
|
286
|
+
)
|
|
287
|
+
self._compaction_strategy: UnifiedContextStrategy | None = compaction_strategy
|
|
288
|
+
self._max_context_tokens = max_context_tokens
|
|
289
|
+
self._force_compress_pct = force_compress_pct
|
|
290
|
+
self._skip_local_history_for_service_context = skip_local_history_for_service_context
|
|
291
|
+
self._service_context_default_options = dict(service_context_default_options or {})
|
|
292
|
+
self._use_local_context_estimate_for_hosted_usage = use_local_context_estimate_for_hosted_usage
|
|
293
|
+
|
|
294
|
+
# ---- HistoryProvider abstract methods ----
|
|
295
|
+
|
|
296
|
+
async def get_messages(
|
|
297
|
+
self, session_id: str | None, *, state: dict[str, Any] | None = None, **kwargs: Any
|
|
298
|
+
) -> list[Message]:
|
|
299
|
+
if state is None:
|
|
300
|
+
return []
|
|
301
|
+
messages = state.get("messages", [])
|
|
302
|
+
# Filter out turn markers (structural metadata), excluded messages
|
|
303
|
+
# (compacted tool-call groups whose summaries replace them), and
|
|
304
|
+
# crash-leftover synthetic ``continue`` nudges — a state-RESIDENT
|
|
305
|
+
# flagged nudge is by construction a leftover (a live nudge travels
|
|
306
|
+
# as the run's input prefix and reaches state only after the run,
|
|
307
|
+
# where post-run cleanup removes it) and must not be re-sent to the
|
|
308
|
+
# model on every subsequent run. Injections are NOT filtered: they
|
|
309
|
+
# are real user input.
|
|
310
|
+
# Compressed summaries ARE kept because the LLM needs to see them.
|
|
311
|
+
return [
|
|
312
|
+
m
|
|
313
|
+
for m in messages
|
|
314
|
+
if not _is_turn_marker(m)
|
|
315
|
+
and not m.additional_properties.get(_EXCLUDED_KEY, False)
|
|
316
|
+
and not is_continuation_message(m)
|
|
317
|
+
]
|
|
318
|
+
|
|
319
|
+
async def save_messages(
|
|
320
|
+
self,
|
|
321
|
+
session_id: str | None,
|
|
322
|
+
messages: Sequence[Message],
|
|
323
|
+
*,
|
|
324
|
+
state: dict[str, Any] | None = None,
|
|
325
|
+
**kwargs: Any,
|
|
326
|
+
) -> None:
|
|
327
|
+
if state is None:
|
|
328
|
+
return
|
|
329
|
+
existing = state.get("messages", [])
|
|
330
|
+
state["messages"] = [*existing, *messages]
|
|
331
|
+
|
|
332
|
+
# ---- Lifecycle hooks ----
|
|
333
|
+
|
|
334
|
+
async def before_run(
|
|
335
|
+
self,
|
|
336
|
+
*,
|
|
337
|
+
agent: Any,
|
|
338
|
+
session: AgentSession,
|
|
339
|
+
context: SessionContext,
|
|
340
|
+
state: dict[str, Any],
|
|
341
|
+
) -> None:
|
|
342
|
+
"""Load history and expose message count."""
|
|
343
|
+
if not self._skip_local_history_for_service_context or not _uses_service_side_context(
|
|
344
|
+
context,
|
|
345
|
+
self._service_context_default_options,
|
|
346
|
+
session.invalidated_service_session_ids,
|
|
347
|
+
):
|
|
348
|
+
await super().before_run(agent=agent, session=session, context=context, state=state)
|
|
349
|
+
session.state["_chrys_history_len"] = len(state.get("messages", []))
|
|
350
|
+
session.state.pop(LAST_ASSISTANT_CREATED_AT_STATE_KEY, None)
|
|
351
|
+
# Bind strategy to state so it can process compressions and list markers.
|
|
352
|
+
if self._compaction_strategy is not None:
|
|
353
|
+
self._compaction_strategy.bind_state(state)
|
|
354
|
+
|
|
355
|
+
async def after_run(
|
|
356
|
+
self,
|
|
357
|
+
*,
|
|
358
|
+
agent: Any,
|
|
359
|
+
session: AgentSession,
|
|
360
|
+
context: SessionContext,
|
|
361
|
+
state: dict[str, Any],
|
|
362
|
+
) -> None:
|
|
363
|
+
"""Store outputs and persist compaction flags on the stored state messages.
|
|
364
|
+
|
|
365
|
+
History messages reach the wire un-copied (kernel
|
|
366
|
+
``SessionContext.extend_messages``), so their intra-run ``_excluded``
|
|
367
|
+
flags are already on the stored objects. Current-turn response
|
|
368
|
+
messages are the exception: streaming finalizers rebuild them from
|
|
369
|
+
updates before they are stored, dropping flags set on the loop-level
|
|
370
|
+
objects.
|
|
371
|
+
|
|
372
|
+
Instead of re-running the full compaction algorithm on state messages
|
|
373
|
+
(which would see all messages as non-excluded and potentially compact
|
|
374
|
+
far more aggressively than the tool loop did), we:
|
|
375
|
+
|
|
376
|
+
1. Flush any pending compressions that weren't processed during the
|
|
377
|
+
tool loop (edge case: ``compress_context`` called right before the
|
|
378
|
+
run ended).
|
|
379
|
+
2. Propagate tool-loop exclusion flags onto the stored messages via
|
|
380
|
+
anchors — identity hits are no-ops for the aliased history
|
|
381
|
+
messages; structural fallbacks re-anchor the streaming-rebuilt
|
|
382
|
+
current-turn messages.
|
|
383
|
+
|
|
384
|
+
For Responses service-side sessions, this remains local bookkeeping
|
|
385
|
+
only; compaction does not rewrite the provider's server-side context.
|
|
386
|
+
"""
|
|
387
|
+
await super().after_run(agent=agent, session=session, context=context, state=state)
|
|
388
|
+
current_turn_anchors = list(context.input_messages)
|
|
389
|
+
if context.response is not None:
|
|
390
|
+
current_turn_anchors.extend(context.response.messages)
|
|
391
|
+
messages = state.get("messages", [])
|
|
392
|
+
if isinstance(messages, list):
|
|
393
|
+
pre_output_len = state.get(PRE_OUTPUT_HISTORY_LEN_STATE_KEY)
|
|
394
|
+
start_idx = pre_output_len if isinstance(pre_output_len, int) else session.state.get("_chrys_history_len")
|
|
395
|
+
if not isinstance(start_idx, int):
|
|
396
|
+
start_idx = len(messages)
|
|
397
|
+
elif start_idx < 0:
|
|
398
|
+
start_idx = 0
|
|
399
|
+
elif start_idx > len(messages):
|
|
400
|
+
start_idx = len(messages)
|
|
401
|
+
timestamp = utc_iso()
|
|
402
|
+
last_assistant_timestamp: str | None = None
|
|
403
|
+
for message in messages[start_idx:]:
|
|
404
|
+
if not should_stamp_message_created_at(message) or message.role != "assistant":
|
|
405
|
+
continue
|
|
406
|
+
stamp_message_created_at(message, timestamp)
|
|
407
|
+
created_at = message.additional_properties.get(MESSAGE_CREATED_AT_KEY)
|
|
408
|
+
normalized = try_normalize_created_at(created_at)
|
|
409
|
+
if normalized is not None:
|
|
410
|
+
last_assistant_timestamp = normalized
|
|
411
|
+
if last_assistant_timestamp is not None:
|
|
412
|
+
session.state[LAST_ASSISTANT_CREATED_AT_STATE_KEY] = last_assistant_timestamp
|
|
413
|
+
else:
|
|
414
|
+
messages = []
|
|
415
|
+
state_rewritten_after_output = False
|
|
416
|
+
if self._compaction_strategy is not None and messages:
|
|
417
|
+
state_rewritten_after_output = await self._compaction_strategy.flush_pending_compressions()
|
|
418
|
+
# Flushing can replace the list. Persist into the owned list, then
|
|
419
|
+
# refresh the current-turn floor if Phase 1 inserted summaries.
|
|
420
|
+
messages = state.get("messages", [])
|
|
421
|
+
previous_length = len(messages)
|
|
422
|
+
self._compaction_strategy.persist_exclusions_to_state(messages)
|
|
423
|
+
state_rewritten_after_output |= len(messages) != previous_length
|
|
424
|
+
|
|
425
|
+
# Force-compress: if context usage still exceeds force_compress_pct
|
|
426
|
+
# after compaction, auto-compress the oldest uncompressed turn.
|
|
427
|
+
state_rewritten_after_output = (
|
|
428
|
+
await self._check_force_compress(state, context, session.invalidated_service_session_ids)
|
|
429
|
+
or state_rewritten_after_output
|
|
430
|
+
)
|
|
431
|
+
if state_rewritten_after_output:
|
|
432
|
+
_refresh_pre_output_history_len_from_anchors(state, current_turn_anchors)
|
|
433
|
+
|
|
434
|
+
async def _check_force_compress(
|
|
435
|
+
self,
|
|
436
|
+
state: dict[str, Any],
|
|
437
|
+
context: SessionContext,
|
|
438
|
+
invalidated_handles: Collection[str] | None = None,
|
|
439
|
+
) -> bool:
|
|
440
|
+
"""Auto-compress the oldest turn if context usage exceeds force_compress_pct.
|
|
441
|
+
|
|
442
|
+
Delegates to the strategy's ``force_compress`` if available, falling
|
|
443
|
+
back to the static ``compress()`` for strategy-less providers.
|
|
444
|
+
"""
|
|
445
|
+
if self._max_context_tokens <= 0 or self._force_compress_pct >= 1.0:
|
|
446
|
+
return False
|
|
447
|
+
service_options = dict(self._service_context_default_options)
|
|
448
|
+
service_options.update(context.options)
|
|
449
|
+
if self._skip_local_history_for_service_context and (
|
|
450
|
+
service_options.get("store") is True
|
|
451
|
+
or _uses_service_side_context(context, self._service_context_default_options, invalidated_handles)
|
|
452
|
+
):
|
|
453
|
+
# Rewriting local history cannot shrink a provider-owned
|
|
454
|
+
# continuation and would only create a misleading compression.
|
|
455
|
+
return False
|
|
456
|
+
|
|
457
|
+
# ``usage_details`` is the billable aggregate across every model call
|
|
458
|
+
# in a tool loop. Force-compression needs the final call's input size,
|
|
459
|
+
# which represents the actual context occupancy.
|
|
460
|
+
if not context.response or not context.response.latest_usage_details:
|
|
461
|
+
return False
|
|
462
|
+
if (
|
|
463
|
+
self._use_local_context_estimate_for_hosted_usage
|
|
464
|
+
and self._compaction_strategy is not None
|
|
465
|
+
and contains_provider_hosted_content(context.response.messages)
|
|
466
|
+
):
|
|
467
|
+
input_tokens = resolve_hosted_context_input_tokens(
|
|
468
|
+
context.response.latest_usage_details,
|
|
469
|
+
local_estimate=self._compaction_strategy.estimated_context_input_tokens,
|
|
470
|
+
)
|
|
471
|
+
else:
|
|
472
|
+
input_tokens = context.response.latest_usage_details.get("input_token_count") or 0
|
|
473
|
+
if input_tokens <= 0:
|
|
474
|
+
return False
|
|
475
|
+
|
|
476
|
+
pct = input_tokens / self._max_context_tokens
|
|
477
|
+
if pct <= self._force_compress_pct:
|
|
478
|
+
return False
|
|
479
|
+
|
|
480
|
+
# Find the oldest available fold marker
|
|
481
|
+
info = self.list_compressed(state)
|
|
482
|
+
markers = info.get("markers", [])
|
|
483
|
+
if not markers:
|
|
484
|
+
return False
|
|
485
|
+
|
|
486
|
+
marker_id = markers[0]["marker_id"]
|
|
487
|
+
summary = _auto_summary(state, markers[0].get("position", 0))
|
|
488
|
+
|
|
489
|
+
if self._compaction_strategy is not None:
|
|
490
|
+
compressed_context_id = await self._compaction_strategy.force_compress(
|
|
491
|
+
marker_id,
|
|
492
|
+
summary,
|
|
493
|
+
source="auto",
|
|
494
|
+
usage_pct=pct,
|
|
495
|
+
tokens_before=input_tokens,
|
|
496
|
+
)
|
|
497
|
+
return compressed_context_id is not None
|
|
498
|
+
try:
|
|
499
|
+
self.compress(state, marker_id, summary)
|
|
500
|
+
except ValueError:
|
|
501
|
+
return False
|
|
502
|
+
return True
|
|
503
|
+
|
|
504
|
+
# ---- Marker operations (static, operate on session state) ----
|
|
505
|
+
|
|
506
|
+
@staticmethod
|
|
507
|
+
def insert_marker(state: dict[str, Any], turn_index: int) -> str:
|
|
508
|
+
"""Insert a turn marker at the end of message history.
|
|
509
|
+
|
|
510
|
+
Args:
|
|
511
|
+
state: The provider-scoped state dict (``session.state[source_id]``).
|
|
512
|
+
turn_index: Sequential turn number.
|
|
513
|
+
|
|
514
|
+
Returns:
|
|
515
|
+
The ``marker_id`` for this marker.
|
|
516
|
+
"""
|
|
517
|
+
marker_id = f"turn_{turn_index}"
|
|
518
|
+
msg = Message("assistant", [""])
|
|
519
|
+
msg.additional_properties[HistoryMarkerKind.KEY] = HistoryMarkerKind.TURN
|
|
520
|
+
msg.additional_properties[_TURN_ID_KEY] = marker_id
|
|
521
|
+
msg.additional_properties[_TURN_KEY] = turn_index
|
|
522
|
+
ensure_analytics_item_id(msg.additional_properties)
|
|
523
|
+
|
|
524
|
+
messages: list[Message] = state.setdefault("messages", [])
|
|
525
|
+
messages.append(msg)
|
|
526
|
+
state["turn_counter"] = turn_index
|
|
527
|
+
|
|
528
|
+
return marker_id
|
|
529
|
+
|
|
530
|
+
# ---- Compression operations (static) ----
|
|
531
|
+
|
|
532
|
+
@staticmethod
|
|
533
|
+
def compress(
|
|
534
|
+
state: dict[str, Any],
|
|
535
|
+
marker_id: str,
|
|
536
|
+
summary_text: str,
|
|
537
|
+
) -> str:
|
|
538
|
+
"""Compress messages from the last summary up to (inclusive) the target marker.
|
|
539
|
+
|
|
540
|
+
Thin wrapper around :func:`_compress_state`. Use the unified
|
|
541
|
+
strategy's ``queue_compression`` / ``force_compress`` for
|
|
542
|
+
tool-loop-aware compression.
|
|
543
|
+
|
|
544
|
+
Returns:
|
|
545
|
+
The ``compressed_context_id`` for the new block.
|
|
546
|
+
|
|
547
|
+
Raises:
|
|
548
|
+
ValueError: If the marker_id is not found or invalid.
|
|
549
|
+
"""
|
|
550
|
+
ctx_id, _fold_range = _compress_state(state, marker_id, summary_text)
|
|
551
|
+
return ctx_id
|
|
552
|
+
|
|
553
|
+
@staticmethod
|
|
554
|
+
def list_compressed(state: dict[str, Any]) -> dict[str, Any]:
|
|
555
|
+
"""Return metadata about all compressed blocks and available fold markers.
|
|
556
|
+
|
|
557
|
+
Returns:
|
|
558
|
+
Dict with ``"blocks"`` (compressed block metadata) and
|
|
559
|
+
``"markers"`` (available fold point markers).
|
|
560
|
+
"""
|
|
561
|
+
# Compressed blocks
|
|
562
|
+
compressed: list[CompressedBlock] = state.get("compressed_msgs", [])
|
|
563
|
+
blocks = [
|
|
564
|
+
{
|
|
565
|
+
"compressed_context_id": b.compressed_context_id,
|
|
566
|
+
"summary": b.summary_text,
|
|
567
|
+
"marker_id": b.marker_id,
|
|
568
|
+
"turn_range": b.turn_range,
|
|
569
|
+
"num_messages": len(b.messages),
|
|
570
|
+
"created_at": b.created_at,
|
|
571
|
+
}
|
|
572
|
+
for b in compressed
|
|
573
|
+
]
|
|
574
|
+
|
|
575
|
+
# Available fold markers (markers that are after the last summary)
|
|
576
|
+
messages: list[Message] = state.get("messages", [])
|
|
577
|
+
last_summary_idx = -1
|
|
578
|
+
for i, msg in enumerate(messages):
|
|
579
|
+
if _is_compressed_summary(msg):
|
|
580
|
+
last_summary_idx = i
|
|
581
|
+
|
|
582
|
+
markers = []
|
|
583
|
+
for i, msg in enumerate(messages):
|
|
584
|
+
if i <= last_summary_idx:
|
|
585
|
+
continue
|
|
586
|
+
if _is_turn_marker(msg):
|
|
587
|
+
markers.append(
|
|
588
|
+
{
|
|
589
|
+
"marker_id": msg.additional_properties.get(_TURN_ID_KEY, ""),
|
|
590
|
+
"turn_index": msg.additional_properties.get(_TURN_KEY, 0),
|
|
591
|
+
"position": i,
|
|
592
|
+
}
|
|
593
|
+
)
|
|
594
|
+
|
|
595
|
+
return {"blocks": blocks, "markers": markers}
|
|
596
|
+
|
|
597
|
+
|
|
598
|
+
# ---------------------------------------------------------------------------
|
|
599
|
+
# Auto-summary for force-compress
|
|
600
|
+
# ---------------------------------------------------------------------------
|
|
601
|
+
|
|
602
|
+
_AUTO_SUMMARY_USER_MAX = 100
|
|
603
|
+
"""Max characters for user message text in auto-generated summaries."""
|
|
604
|
+
|
|
605
|
+
|
|
606
|
+
def _auto_summary(state: dict[str, Any], marker_position: int) -> str:
|
|
607
|
+
"""Generate a summary from messages up to marker_position for auto-compression.
|
|
608
|
+
|
|
609
|
+
Extracts user message snippets and tool names from the fold range.
|
|
610
|
+
"""
|
|
611
|
+
messages: list[Message] = state.get("messages", [])
|
|
612
|
+
|
|
613
|
+
# Find fold_start (after last compressed summary)
|
|
614
|
+
fold_start = 0
|
|
615
|
+
for i, msg in enumerate(messages):
|
|
616
|
+
if _is_compressed_summary(msg):
|
|
617
|
+
fold_start = i + 1
|
|
618
|
+
|
|
619
|
+
fold_range = messages[fold_start : marker_position + 1]
|
|
620
|
+
if not fold_range:
|
|
621
|
+
return "Earlier conversation"
|
|
622
|
+
|
|
623
|
+
user_snippets: list[str] = []
|
|
624
|
+
tool_names: set[str] = set()
|
|
625
|
+
|
|
626
|
+
for msg in fold_range:
|
|
627
|
+
# Skip synthetic ``continue`` nudges so a fold summary never opens
|
|
628
|
+
# with "User: continue"; injections are real user input and stay.
|
|
629
|
+
if msg.role == "user" and not is_continuation_message(msg):
|
|
630
|
+
text = msg.text or ""
|
|
631
|
+
if text:
|
|
632
|
+
if len(text) > _AUTO_SUMMARY_USER_MAX:
|
|
633
|
+
text = text[:_AUTO_SUMMARY_USER_MAX] + "..."
|
|
634
|
+
user_snippets.append(text)
|
|
635
|
+
for c in msg.contents:
|
|
636
|
+
if c.type in TOOL_CALL_CONTENT_TYPES and (name := tool_call_name(c)):
|
|
637
|
+
tool_names.add(name)
|
|
638
|
+
|
|
639
|
+
parts: list[str] = []
|
|
640
|
+
if user_snippets:
|
|
641
|
+
parts.append(f"User: {user_snippets[0]}")
|
|
642
|
+
if len(user_snippets) > 1:
|
|
643
|
+
parts.append(f"(+{len(user_snippets) - 1} more messages)")
|
|
644
|
+
if tool_names:
|
|
645
|
+
parts.append(f"Tools: {', '.join(sorted(tool_names))}")
|
|
646
|
+
|
|
647
|
+
return "; ".join(parts) if parts else "Earlier conversation"
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# Copyright (c) Huawei Technologies Co., Ltd. 2026. All rights reserved.
|
|
2
|
+
|
|
3
|
+
"""MemoryProvider — injects auto-loaded reference content into the system prompt.
|
|
4
|
+
|
|
5
|
+
Companion to :mod:`chrys.service.context.memory_loader`. Receives the already-rendered
|
|
6
|
+
markdown block at construction time and re-injects it via
|
|
7
|
+
``context.extend_instructions`` on every LLM call.
|
|
8
|
+
|
|
9
|
+
Sub-agents bypass this provider by simply not passing ``memory_text`` to
|
|
10
|
+
their own :class:`chrys.service.context.manager.ContextManager`, so memory
|
|
11
|
+
does not duplicate into concurrent sub-agent contexts.
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
from __future__ import annotations
|
|
15
|
+
|
|
16
|
+
from typing import TYPE_CHECKING, Any
|
|
17
|
+
|
|
18
|
+
from chrys.kernel import AgentSession, ContextProvider, SessionContext
|
|
19
|
+
|
|
20
|
+
if TYPE_CHECKING:
|
|
21
|
+
pass
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
class MemoryProvider(ContextProvider):
|
|
25
|
+
"""Injects pre-loaded reference content into the agent's system prompt.
|
|
26
|
+
|
|
27
|
+
The provider is a thin pass-through: text is rendered once by
|
|
28
|
+
:func:`chrys.service.context.memory_loader.load_memory_content` at agent build
|
|
29
|
+
time and re-emitted on every ``before_run``. Soft-restart (profile or
|
|
30
|
+
workspace switch) rebuilds the agent and instantiates a fresh provider,
|
|
31
|
+
which re-reads files — so on-disk edits are picked up automatically
|
|
32
|
+
after the next build.
|
|
33
|
+
"""
|
|
34
|
+
|
|
35
|
+
DEFAULT_SOURCE_ID = "chrys_memory"
|
|
36
|
+
|
|
37
|
+
def __init__(self, rendered_text: str, source_id: str = DEFAULT_SOURCE_ID) -> None:
|
|
38
|
+
super().__init__(source_id)
|
|
39
|
+
self._instructions = rendered_text
|
|
40
|
+
|
|
41
|
+
async def before_run(
|
|
42
|
+
self,
|
|
43
|
+
*,
|
|
44
|
+
agent: Any,
|
|
45
|
+
session: AgentSession,
|
|
46
|
+
context: SessionContext,
|
|
47
|
+
state: dict[str, Any],
|
|
48
|
+
) -> None:
|
|
49
|
+
if self._instructions:
|
|
50
|
+
context.extend_instructions(self.source_id, self._instructions)
|