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
chrys/kernel/agent.py
ADDED
|
@@ -0,0 +1,994 @@
|
|
|
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
|
+
"""Agent orchestration over session providers and the model/tool loop.
|
|
6
|
+
|
|
7
|
+
``_AgentCore`` prepares history, instructions and tools, calls the client,
|
|
8
|
+
aggregates an ``AgentResponse``, and runs the session providers before and
|
|
9
|
+
after the run. ``Agent`` adds telemetry and forwards chat/function middleware
|
|
10
|
+
to the client stack::
|
|
11
|
+
|
|
12
|
+
Agent = AgentTelemetryLayer over _AgentCore
|
|
13
|
+
client = ToolLoopLayer(ChatMiddlewareLayer(wire client))
|
|
14
|
+
session/providers = kernel.sessions
|
|
15
|
+
|
|
16
|
+
The MCP adapter supplies flat ``FunctionTool`` lists. Compaction strategy and
|
|
17
|
+
tokenizer are supplied per run. History persistence runs after the complete
|
|
18
|
+
agent response, and both finalizers write ``SessionContext._response``;
|
|
19
|
+
providers observe it through the read-only ``response`` property.
|
|
20
|
+
|
|
21
|
+
``AgentTelemetryLayer`` sets and resets non-streaming ContextVars inside the
|
|
22
|
+
returned coroutine, so it can be driven from another task. Streaming spans
|
|
23
|
+
activate around each pull. Agent spans identify their provider as ``chrys``;
|
|
24
|
+
chat spans identify the model provider.
|
|
25
|
+
|
|
26
|
+
Kernel imports stay within this package, allowed dependencies and foundation.
|
|
27
|
+
"""
|
|
28
|
+
|
|
29
|
+
from __future__ import annotations
|
|
30
|
+
|
|
31
|
+
from collections.abc import Mapping, MutableMapping, Sequence
|
|
32
|
+
from contextlib import AbstractAsyncContextManager, AsyncExitStack
|
|
33
|
+
from copy import deepcopy
|
|
34
|
+
from functools import partial
|
|
35
|
+
from typing import TYPE_CHECKING, Any, ClassVar, Literal, Self, TypedDict, overload
|
|
36
|
+
from uuid import uuid4
|
|
37
|
+
|
|
38
|
+
from ._types import (
|
|
39
|
+
AgentResponse,
|
|
40
|
+
ChatResponseUpdate,
|
|
41
|
+
ResponseStream,
|
|
42
|
+
_build_agent_response_from_chat_response,
|
|
43
|
+
map_chat_to_agent_update,
|
|
44
|
+
normalize_messages,
|
|
45
|
+
)
|
|
46
|
+
from .client import (
|
|
47
|
+
CONVERSATION_HANDLE_KEYS,
|
|
48
|
+
collect_conversation_handles,
|
|
49
|
+
continuation_token_response_id,
|
|
50
|
+
conversation_handle_value,
|
|
51
|
+
resolve_storage_mode_and_handles,
|
|
52
|
+
strip_invalidated_conversation_handles,
|
|
53
|
+
)
|
|
54
|
+
from .exceptions import AgentInvalidResponseException
|
|
55
|
+
from .instrumentation import AgentTelemetryLayer
|
|
56
|
+
from .middleware import split_middleware
|
|
57
|
+
from .sessions import (
|
|
58
|
+
AgentSession,
|
|
59
|
+
HistoryProvider,
|
|
60
|
+
InMemoryHistoryProvider,
|
|
61
|
+
ServiceFallbackHistoryProvider,
|
|
62
|
+
SessionContext,
|
|
63
|
+
is_local_history_conversation_id,
|
|
64
|
+
)
|
|
65
|
+
|
|
66
|
+
# Normalize foreign tools at admission so the run pipeline invokes FunctionTool.
|
|
67
|
+
from .tools import normalize_tools
|
|
68
|
+
|
|
69
|
+
if TYPE_CHECKING:
|
|
70
|
+
from collections.abc import Awaitable, Callable
|
|
71
|
+
|
|
72
|
+
from ._types import (
|
|
73
|
+
AgentResponseUpdate,
|
|
74
|
+
AgentRunInputs,
|
|
75
|
+
ChatResponse,
|
|
76
|
+
Message,
|
|
77
|
+
ToolTypes,
|
|
78
|
+
)
|
|
79
|
+
from .middleware import ChatMiddleware, FunctionMiddleware
|
|
80
|
+
from .sessions import ContextProvider
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
def _get_tool_name(tool: Any) -> str | None:
|
|
84
|
+
"""Return the name of a function-tool declaration or tool-like object."""
|
|
85
|
+
if isinstance(tool, Mapping):
|
|
86
|
+
func = tool.get("function", None)
|
|
87
|
+
if func and isinstance(func, Mapping):
|
|
88
|
+
name = func.get("name")
|
|
89
|
+
return name if isinstance(name, str) else None
|
|
90
|
+
return None
|
|
91
|
+
name = getattr(tool, "name", None)
|
|
92
|
+
return name if isinstance(name, str) else None
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
def _tool_identity(tool: Any) -> Any:
|
|
96
|
+
"""Return the original tool identity shared by clones of a foreign tool."""
|
|
97
|
+
return getattr(tool, "_foreign_invocation_state_source", tool)
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
def _append_unique_tools(
|
|
101
|
+
existing_tools: list[Any],
|
|
102
|
+
new_tools: Sequence[Any],
|
|
103
|
+
*,
|
|
104
|
+
duplicate_error_message: str | None = None,
|
|
105
|
+
) -> list[Any]:
|
|
106
|
+
"""Append tools while preserving the run-pipeline duplicate-name contract.
|
|
107
|
+
|
|
108
|
+
Appends in place and returns the same list. Nameless tools always append;
|
|
109
|
+
the same object (or clones of the same foreign source) seen twice is
|
|
110
|
+
skipped; a *different* object under an existing name raises ``ValueError``.
|
|
111
|
+
"""
|
|
112
|
+
seen_by_name: dict[str, Any] = {}
|
|
113
|
+
for tool_item in existing_tools:
|
|
114
|
+
if tool_name := _get_tool_name(tool_item):
|
|
115
|
+
seen_by_name[tool_name] = tool_item
|
|
116
|
+
|
|
117
|
+
for tool_item in new_tools:
|
|
118
|
+
tool_name = _get_tool_name(tool_item)
|
|
119
|
+
if tool_name is None:
|
|
120
|
+
existing_tools.append(tool_item)
|
|
121
|
+
continue
|
|
122
|
+
|
|
123
|
+
existing_tool = seen_by_name.get(tool_name)
|
|
124
|
+
if existing_tool is None:
|
|
125
|
+
seen_by_name[tool_name] = tool_item
|
|
126
|
+
existing_tools.append(tool_item)
|
|
127
|
+
continue
|
|
128
|
+
|
|
129
|
+
if existing_tool is tool_item or _tool_identity(existing_tool) is _tool_identity(tool_item):
|
|
130
|
+
continue
|
|
131
|
+
|
|
132
|
+
message = duplicate_error_message or "Tool names must be unique."
|
|
133
|
+
raise ValueError(f"Duplicate tool name '{tool_name}'. {message}")
|
|
134
|
+
|
|
135
|
+
return existing_tools
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
def _merge_options(base: dict[str, Any], override: dict[str, Any]) -> dict[str, Any]:
|
|
139
|
+
"""Merge base and override chat options.
|
|
140
|
+
|
|
141
|
+
Returns a new dict; ``None`` override values are skipped, ``tools`` are
|
|
142
|
+
unioned via :func:`_append_unique_tools`, ``logit_bias``/``metadata`` are
|
|
143
|
+
dict-merged, ``instructions`` are newline-concatenated, everything else is
|
|
144
|
+
replaced. ``None`` is treated as "unset" throughout: the merged result is
|
|
145
|
+
stripped of any remaining ``None`` values in a final pass so unset options
|
|
146
|
+
are never forwarded (e.g. an unset ``store`` is left
|
|
147
|
+
for the service to default).
|
|
148
|
+
"""
|
|
149
|
+
result = dict(base)
|
|
150
|
+
|
|
151
|
+
for key, value in override.items():
|
|
152
|
+
if value is None:
|
|
153
|
+
continue
|
|
154
|
+
if key == "tools" and (result.get("tools") or value):
|
|
155
|
+
base_tools = normalize_tools(result.get("tools"))
|
|
156
|
+
override_tools = normalize_tools(value)
|
|
157
|
+
result["tools"] = _append_unique_tools(
|
|
158
|
+
list(base_tools),
|
|
159
|
+
override_tools,
|
|
160
|
+
duplicate_error_message="Tool names must be unique.",
|
|
161
|
+
)
|
|
162
|
+
elif key == "logit_bias" and result.get("logit_bias"):
|
|
163
|
+
result["logit_bias"] = {**result["logit_bias"], **value}
|
|
164
|
+
elif key == "metadata" and result.get("metadata"):
|
|
165
|
+
result["metadata"] = {**result["metadata"], **value}
|
|
166
|
+
elif key == "instructions" and result.get("instructions"):
|
|
167
|
+
result["instructions"] = f"{result['instructions']}\n{value}"
|
|
168
|
+
else:
|
|
169
|
+
result[key] = value
|
|
170
|
+
return {key: value for key, value in result.items() if value is not None}
|
|
171
|
+
|
|
172
|
+
|
|
173
|
+
class _RunContext(TypedDict):
|
|
174
|
+
"""Session, request options and invocation arguments prepared for one run."""
|
|
175
|
+
|
|
176
|
+
session: AgentSession | None
|
|
177
|
+
session_context: SessionContext
|
|
178
|
+
input_messages: Sequence[Message]
|
|
179
|
+
session_messages: Sequence[Message]
|
|
180
|
+
agent_name: str
|
|
181
|
+
chat_options: MutableMapping[str, Any]
|
|
182
|
+
compaction_strategy: Any
|
|
183
|
+
tokenizer: Any
|
|
184
|
+
client_kwargs: Mapping[str, Any]
|
|
185
|
+
function_invocation_kwargs: Mapping[str, Any]
|
|
186
|
+
|
|
187
|
+
|
|
188
|
+
class _AgentCore:
|
|
189
|
+
"""Prepare requests, drive the client, and finalize responses through session providers.
|
|
190
|
+
|
|
191
|
+
The core terminates the cooperative MRO beneath ``AgentTelemetryLayer``.
|
|
192
|
+
Streaming preparation is lazy: ``ResponseStream.from_awaitable`` wraps the
|
|
193
|
+
mapped tool-loop stream, whose transform and result hooks propagate
|
|
194
|
+
conversation state and persist the completed response.
|
|
195
|
+
"""
|
|
196
|
+
|
|
197
|
+
# AgentTelemetryLayer reads this before the core constructor runs, so it
|
|
198
|
+
# must stay a ClassVar. It supplies the agent span's gen_ai.provider.name.
|
|
199
|
+
AGENT_PROVIDER_NAME: ClassVar[str] = "chrys"
|
|
200
|
+
|
|
201
|
+
def __init__(
|
|
202
|
+
self,
|
|
203
|
+
client: Any,
|
|
204
|
+
instructions: str | None = None,
|
|
205
|
+
*,
|
|
206
|
+
id: str | None = None, # Public agent identifier; intentionally shadows the builtin.
|
|
207
|
+
name: str | None = None,
|
|
208
|
+
description: str | None = None,
|
|
209
|
+
tools: ToolTypes | Callable[..., Any] | Sequence[ToolTypes | Callable[..., Any]] | None = None,
|
|
210
|
+
context_providers: Sequence[ContextProvider] | None = None,
|
|
211
|
+
middleware: ChatMiddleware | FunctionMiddleware | Sequence[ChatMiddleware | FunctionMiddleware] | None = None,
|
|
212
|
+
additional_properties: MutableMapping[str, Any] | None = None,
|
|
213
|
+
) -> None:
|
|
214
|
+
"""Initialize agent defaults and provider state around the client stack.
|
|
215
|
+
|
|
216
|
+
Compaction strategy and tokenizer default to ``None`` here; run-level
|
|
217
|
+
values take precedence in ``_prepare_run_context``.
|
|
218
|
+
"""
|
|
219
|
+
# Store middleware as supplied; run() re-reads it on every call so
|
|
220
|
+
# changes between runs take effect. Validating it here rejects an
|
|
221
|
+
# unsupported value at construction rather than on the first run.
|
|
222
|
+
split_middleware(middleware)
|
|
223
|
+
self.id = id if id is not None else str(uuid4())
|
|
224
|
+
self.name = name
|
|
225
|
+
self.description = description
|
|
226
|
+
self.context_providers: list[ContextProvider] = list(context_providers or [])
|
|
227
|
+
self.middleware: ChatMiddleware | FunctionMiddleware | Sequence[ChatMiddleware | FunctionMiddleware] | None = (
|
|
228
|
+
middleware
|
|
229
|
+
)
|
|
230
|
+
self.additional_properties: MutableMapping[str, Any] = additional_properties or {}
|
|
231
|
+
|
|
232
|
+
self.client = client
|
|
233
|
+
self.compaction_strategy: Any = None
|
|
234
|
+
self.tokenizer: Any = None
|
|
235
|
+
|
|
236
|
+
# Normalize flat tools and resolve the model through client delegation.
|
|
237
|
+
# AgentTelemetryLayer also reads this dict when building span attributes.
|
|
238
|
+
initial_tools = _append_unique_tools([], normalize_tools(tools))
|
|
239
|
+
default_options: dict[str, Any] = {
|
|
240
|
+
"instructions": instructions,
|
|
241
|
+
"tool_choice": "auto",
|
|
242
|
+
"tools": initial_tools,
|
|
243
|
+
"model": getattr(client, "model", None),
|
|
244
|
+
}
|
|
245
|
+
self.default_options: dict[str, Any] = {k: v for k, v in default_options.items() if v is not None}
|
|
246
|
+
self._async_exit_stack = AsyncExitStack()
|
|
247
|
+
self._update_agent_name_and_description()
|
|
248
|
+
super().__init__()
|
|
249
|
+
|
|
250
|
+
def _update_agent_name_and_description(self) -> None:
|
|
251
|
+
"""Forward agent identity to clients that expose the optional update hook."""
|
|
252
|
+
update_fn = getattr(self.client, "_update_agent_name_and_description", None)
|
|
253
|
+
if callable(update_fn):
|
|
254
|
+
update_fn(self.name, self.description)
|
|
255
|
+
|
|
256
|
+
async def __aenter__(self) -> Self:
|
|
257
|
+
"""Enter the client context, when supported, and own its cleanup through the exit stack."""
|
|
258
|
+
if isinstance(self.client, AbstractAsyncContextManager):
|
|
259
|
+
await self._async_exit_stack.enter_async_context(self.client)
|
|
260
|
+
return self
|
|
261
|
+
|
|
262
|
+
async def __aexit__(
|
|
263
|
+
self,
|
|
264
|
+
exc_type: type[BaseException] | None,
|
|
265
|
+
exc_val: BaseException | None,
|
|
266
|
+
exc_tb: Any,
|
|
267
|
+
) -> None:
|
|
268
|
+
"""Close client resources registered on the exit stack."""
|
|
269
|
+
await self._async_exit_stack.aclose()
|
|
270
|
+
|
|
271
|
+
def create_session(self, *, session_id: str | None = None) -> AgentSession:
|
|
272
|
+
"""Create a session with a supplied or generated identifier."""
|
|
273
|
+
return AgentSession(session_id=session_id)
|
|
274
|
+
|
|
275
|
+
def get_session(self, service_session_id: str, *, session_id: str | None = None) -> AgentSession:
|
|
276
|
+
"""Create a local session referring to an existing service conversation."""
|
|
277
|
+
return AgentSession(session_id=session_id, service_session_id=service_session_id)
|
|
278
|
+
|
|
279
|
+
def _get_agent_name(self) -> str:
|
|
280
|
+
"""Use UnnamedAgent when no display name is configured."""
|
|
281
|
+
return self.name or "UnnamedAgent"
|
|
282
|
+
|
|
283
|
+
def run(
|
|
284
|
+
self,
|
|
285
|
+
messages: AgentRunInputs | None = None,
|
|
286
|
+
*,
|
|
287
|
+
stream: bool = False,
|
|
288
|
+
session: AgentSession | None = None,
|
|
289
|
+
tools: ToolTypes | Callable[..., Any] | Sequence[ToolTypes | Callable[..., Any]] | None = None,
|
|
290
|
+
options: Mapping[str, Any] | None = None,
|
|
291
|
+
compaction_strategy: Any = None,
|
|
292
|
+
tokenizer: Any = None,
|
|
293
|
+
function_invocation_kwargs: Mapping[str, Any] | None = None,
|
|
294
|
+
client_kwargs: Mapping[str, Any] | None = None,
|
|
295
|
+
) -> Awaitable[AgentResponse[Any]] | ResponseStream[AgentResponseUpdate, AgentResponse[Any]]:
|
|
296
|
+
"""Build a lazy run that prepares context before calling the client.
|
|
297
|
+
|
|
298
|
+
``stream=False`` returns an un-awaited coroutine; ``stream=True`` returns
|
|
299
|
+
``ResponseStream.from_awaitable(...)`` synchronously. Neither mode runs
|
|
300
|
+
providers or calls the client until the result is driven.
|
|
301
|
+
"""
|
|
302
|
+
|
|
303
|
+
async def _prepare() -> _RunContext:
|
|
304
|
+
return await self._prepare_run_context(
|
|
305
|
+
messages=messages,
|
|
306
|
+
session=session,
|
|
307
|
+
tools=tools,
|
|
308
|
+
options=options,
|
|
309
|
+
compaction_strategy=compaction_strategy,
|
|
310
|
+
tokenizer=tokenizer,
|
|
311
|
+
function_invocation_kwargs=function_invocation_kwargs,
|
|
312
|
+
client_kwargs=client_kwargs,
|
|
313
|
+
)
|
|
314
|
+
|
|
315
|
+
if not stream:
|
|
316
|
+
|
|
317
|
+
async def _run_non_streaming() -> AgentResponse[Any]:
|
|
318
|
+
ctx = await _prepare()
|
|
319
|
+
response = await self._call_chat_client(ctx, stream=False)
|
|
320
|
+
return await self._parse_non_streaming_response(ctx, response)
|
|
321
|
+
|
|
322
|
+
return _run_non_streaming()
|
|
323
|
+
|
|
324
|
+
async def _run_streaming() -> ResponseStream[AgentResponseUpdate, AgentResponse[Any]]:
|
|
325
|
+
ctx = await _prepare()
|
|
326
|
+
stream_response = self._call_chat_client(ctx, stream=True)
|
|
327
|
+
return self._parse_streaming_response(ctx, stream_response)
|
|
328
|
+
|
|
329
|
+
return ResponseStream.from_awaitable(_run_streaming())
|
|
330
|
+
|
|
331
|
+
def _call_chat_client(self, context: _RunContext, *, stream: bool) -> Any:
|
|
332
|
+
"""Call the client with the prepared messages, options and invocation arguments."""
|
|
333
|
+
return self.client.get_response(
|
|
334
|
+
messages=context["session_messages"],
|
|
335
|
+
stream=stream,
|
|
336
|
+
options=context["chat_options"],
|
|
337
|
+
compaction_strategy=context["compaction_strategy"],
|
|
338
|
+
tokenizer=context["tokenizer"],
|
|
339
|
+
function_invocation_kwargs=context["function_invocation_kwargs"],
|
|
340
|
+
client_kwargs=context["client_kwargs"],
|
|
341
|
+
)
|
|
342
|
+
|
|
343
|
+
async def _prepare_run_context(
|
|
344
|
+
self,
|
|
345
|
+
*,
|
|
346
|
+
messages: AgentRunInputs | None,
|
|
347
|
+
session: AgentSession | None,
|
|
348
|
+
tools: ToolTypes | Callable[..., Any] | Sequence[ToolTypes | Callable[..., Any]] | None,
|
|
349
|
+
options: Mapping[str, Any] | None,
|
|
350
|
+
compaction_strategy: Any,
|
|
351
|
+
tokenizer: Any,
|
|
352
|
+
function_invocation_kwargs: Mapping[str, Any] | None,
|
|
353
|
+
client_kwargs: Mapping[str, Any] | None,
|
|
354
|
+
) -> _RunContext:
|
|
355
|
+
"""Combine agent defaults, provider contributions and run options into a request."""
|
|
356
|
+
opts = dict(options) if options else {}
|
|
357
|
+
existing_additional_args: dict[str, Any] = opts.pop("additional_function_arguments", None) or {}
|
|
358
|
+
|
|
359
|
+
# Get tools from options or named parameter (named param takes precedence)
|
|
360
|
+
tools_ = tools if tools is not None else opts.pop("tools", None)
|
|
361
|
+
|
|
362
|
+
input_messages = normalize_messages(messages)
|
|
363
|
+
|
|
364
|
+
# Combine agent-level defaults with runtime options up front so the
|
|
365
|
+
# store/conversation_id decisions below read from a single place
|
|
366
|
+
# using _merge_options with the same precedence as the
|
|
367
|
+
# actual client call (runtime wins; unset/None falls back to the agent
|
|
368
|
+
# default).
|
|
369
|
+
effective_options = _merge_options(self.default_options, opts)
|
|
370
|
+
|
|
371
|
+
# `store` in runtime or agent options takes precedence over the
|
|
372
|
+
# client's default storage behavior (the STORES_BY_DEFAULT getattr
|
|
373
|
+
# resolves through the layered clients' __getattr__ delegation). An
|
|
374
|
+
# explicit store=False forces local history injection even when the
|
|
375
|
+
# client stores server-side by default; store=None/unset falls back to
|
|
376
|
+
# STORES_BY_DEFAULT: under the merge's None-strip an explicit None
|
|
377
|
+
# means "unset", not "falsy False".
|
|
378
|
+
try:
|
|
379
|
+
stores_by_default = bool(self.client.STORES_BY_DEFAULT)
|
|
380
|
+
except AttributeError:
|
|
381
|
+
stores_by_default = False
|
|
382
|
+
try:
|
|
383
|
+
force_stateless = bool(self.client.FORCES_STATELESS)
|
|
384
|
+
except AttributeError:
|
|
385
|
+
force_stateless = False
|
|
386
|
+
storage_resolution = resolve_storage_mode_and_handles(
|
|
387
|
+
effective_options,
|
|
388
|
+
stores_by_default=stores_by_default,
|
|
389
|
+
client_kwargs=client_kwargs,
|
|
390
|
+
force_stateless=force_stateless,
|
|
391
|
+
)
|
|
392
|
+
service_stores_history = storage_resolution.service_side
|
|
393
|
+
# One normalized, capability- and invalidation-aware reflection view
|
|
394
|
+
# of the effective request. Forced-stateless clients see the
|
|
395
|
+
# resolver's handle-free copy here so local history remains eligible;
|
|
396
|
+
# the provider wire view is rebuilt later from the original options.
|
|
397
|
+
# handles the tool loop withheld are removed outright, because the
|
|
398
|
+
# service transcript behind them still holds stripped or
|
|
399
|
+
# never-answered calls — re-sending one would combine a poisoned
|
|
400
|
+
# remote transcript with the local fallback replay. The same view
|
|
401
|
+
# feeds the eager-shadow decision here and the history providers
|
|
402
|
+
# below, so no consumer can mistake a withheld handle for a live one.
|
|
403
|
+
reflected_options = storage_resolution.options_without_handles if force_stateless else effective_options
|
|
404
|
+
if session is not None and session.invalidated_service_session_ids:
|
|
405
|
+
reflected_options = strip_invalidated_conversation_handles(
|
|
406
|
+
reflected_options, session.invalidated_service_session_ids
|
|
407
|
+
)
|
|
408
|
+
# Resolve the request-level continuation handles from that view
|
|
409
|
+
# (a live session id still takes precedence below). Every
|
|
410
|
+
# CONVERSATION_HANDLE_KEYS spelling counts, top-level and inside
|
|
411
|
+
# extra_body — each one reaches the wire as service-side
|
|
412
|
+
# continuation state, so any of them means the service owns history.
|
|
413
|
+
request_handles = collect_conversation_handles(reflected_options)
|
|
414
|
+
# Auto-inject local history when no loading HistoryProvider owns it.
|
|
415
|
+
# Non-history and persist-only providers must not suppress prior turns.
|
|
416
|
+
# NOTE: appends permanently to self.context_providers — agent state,
|
|
417
|
+
# not run state.
|
|
418
|
+
if (
|
|
419
|
+
session is not None
|
|
420
|
+
and not any(
|
|
421
|
+
provider.load_messages for provider in self.context_providers if isinstance(provider, HistoryProvider)
|
|
422
|
+
)
|
|
423
|
+
and not request_handles
|
|
424
|
+
):
|
|
425
|
+
if service_stores_history:
|
|
426
|
+
# Service-side storage keeps the transcript only behind the
|
|
427
|
+
# service handle, and the exhaustion tail may have to discard
|
|
428
|
+
# that handle. Shadow every turn locally from the start —
|
|
429
|
+
# waiting until invalidation would permanently lose the turns
|
|
430
|
+
# that succeeded through service storage before it. The
|
|
431
|
+
# handle-gated fallback persists through the ordinary
|
|
432
|
+
# after_run pass but loads only once the handle is gone, so
|
|
433
|
+
# a live service conversation never sees duplicated history.
|
|
434
|
+
self.context_providers.append(ServiceFallbackHistoryProvider())
|
|
435
|
+
elif not session.service_session_id:
|
|
436
|
+
self.context_providers.append(InMemoryHistoryProvider())
|
|
437
|
+
|
|
438
|
+
active_session = session
|
|
439
|
+
if active_session is None and self.context_providers:
|
|
440
|
+
active_session = AgentSession()
|
|
441
|
+
|
|
442
|
+
session_context, chat_options = await self._prepare_session_and_messages(
|
|
443
|
+
session=active_session,
|
|
444
|
+
input_messages=input_messages,
|
|
445
|
+
# Providers reflect on the effective request, not the raw run
|
|
446
|
+
# arguments: agent-default continuation handles must be visible
|
|
447
|
+
# to history-provider load gates exactly like run-level ones,
|
|
448
|
+
# and an invalidated handle must not look live to them — a
|
|
449
|
+
# provider that trusts it would skip local replay while the
|
|
450
|
+
# wire choke point strips the handle, sending the request with
|
|
451
|
+
# neither remote nor local history. Hand over the sanitized
|
|
452
|
+
# merged snapshot.
|
|
453
|
+
options=reflected_options,
|
|
454
|
+
)
|
|
455
|
+
default_additional_args = chat_options.pop("additional_function_arguments", None)
|
|
456
|
+
if isinstance(default_additional_args, Mapping):
|
|
457
|
+
existing_additional_args = {
|
|
458
|
+
**dict(default_additional_args),
|
|
459
|
+
**existing_additional_args,
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
agent_name = self._get_agent_name()
|
|
463
|
+
base_tools = normalize_tools(chat_options.pop("tools", None))
|
|
464
|
+
|
|
465
|
+
# Combine configured, provider and runtime tools under the same
|
|
466
|
+
# duplicate-name rules. All inputs normalize to flat FunctionTools.
|
|
467
|
+
final_tools = list(base_tools)
|
|
468
|
+
_append_unique_tools(final_tools, normalize_tools(tools_))
|
|
469
|
+
|
|
470
|
+
effective_function_invocation_kwargs = (
|
|
471
|
+
dict(function_invocation_kwargs) if function_invocation_kwargs is not None else {}
|
|
472
|
+
)
|
|
473
|
+
additional_function_arguments = {**effective_function_invocation_kwargs, **existing_additional_args}
|
|
474
|
+
|
|
475
|
+
model = opts.pop("model", None)
|
|
476
|
+
|
|
477
|
+
# Build options dict from run() options merged with provided options.
|
|
478
|
+
# ORDER MATTERS for conversation_id: when a session exists, the key is
|
|
479
|
+
# NOT popped from opts above, so an options-level conversation_id
|
|
480
|
+
# overrides the session-derived value via the trailing **opts spread.
|
|
481
|
+
run_opts: dict[str, Any] = {
|
|
482
|
+
"conversation_id": active_session.service_session_id
|
|
483
|
+
if active_session
|
|
484
|
+
else opts.pop("conversation_id", None),
|
|
485
|
+
"allow_multiple_tool_calls": opts.pop("allow_multiple_tool_calls", None),
|
|
486
|
+
"frequency_penalty": opts.pop("frequency_penalty", None),
|
|
487
|
+
"logit_bias": opts.pop("logit_bias", None),
|
|
488
|
+
"max_tokens": opts.pop("max_tokens", None),
|
|
489
|
+
"metadata": opts.pop("metadata", None),
|
|
490
|
+
"presence_penalty": opts.pop("presence_penalty", None),
|
|
491
|
+
"response_format": opts.pop("response_format", None),
|
|
492
|
+
"seed": opts.pop("seed", None),
|
|
493
|
+
"stop": opts.pop("stop", None),
|
|
494
|
+
"store": opts.pop("store", None),
|
|
495
|
+
"temperature": opts.pop("temperature", None),
|
|
496
|
+
"tool_choice": opts.pop("tool_choice", None),
|
|
497
|
+
"tools": final_tools or None,
|
|
498
|
+
"top_p": opts.pop("top_p", None),
|
|
499
|
+
"user": opts.pop("user", None),
|
|
500
|
+
**opts, # Remaining options are provider-specific
|
|
501
|
+
}
|
|
502
|
+
if model is not None:
|
|
503
|
+
run_opts["model"] = model
|
|
504
|
+
# _merge_options strips unset (None) options, so e.g. an unset `store`
|
|
505
|
+
# is not forwarded and the service decides its own default (the
|
|
506
|
+
# explicit pre-filter folded into the merge's final pass).
|
|
507
|
+
co = _merge_options(chat_options, run_opts)
|
|
508
|
+
# Single wire choke point for invalidated handles: run options, agent
|
|
509
|
+
# defaults, and provider chat_options all land in the merged view, so
|
|
510
|
+
# a caller repeating a handle the tool loop withheld is suppressed
|
|
511
|
+
# here regardless of which layer supplied it — under every
|
|
512
|
+
# CONVERSATION_HANDLE_KEYS spelling, top-level or nested in
|
|
513
|
+
# extra_body (provider SDKs merge extra_body over the named
|
|
514
|
+
# parameters, so a nested spelling reaches the wire all the same).
|
|
515
|
+
# Suppression is removal-only: poisoned keys are dropped, never
|
|
516
|
+
# rewritten, except that conversation_id falls back to the session's
|
|
517
|
+
# own live handle when one exists — the fallback provider already
|
|
518
|
+
# skipped its replay on seeing that handle, so bare removal would
|
|
519
|
+
# send neither a handle nor local history.
|
|
520
|
+
if active_session is not None and active_session.invalidated_service_session_ids:
|
|
521
|
+
invalidated = active_session.invalidated_service_session_ids
|
|
522
|
+
for key in CONVERSATION_HANDLE_KEYS:
|
|
523
|
+
handle = conversation_handle_value(co.get(key))
|
|
524
|
+
if handle is None or handle not in invalidated:
|
|
525
|
+
continue
|
|
526
|
+
if key == "conversation_id":
|
|
527
|
+
live_handle = active_session.service_session_id
|
|
528
|
+
if (
|
|
529
|
+
isinstance(live_handle, str)
|
|
530
|
+
and live_handle
|
|
531
|
+
and not is_local_history_conversation_id(live_handle)
|
|
532
|
+
and live_handle not in invalidated
|
|
533
|
+
):
|
|
534
|
+
co[key] = live_handle
|
|
535
|
+
continue
|
|
536
|
+
co.pop(key)
|
|
537
|
+
token_response_id = continuation_token_response_id(co.get("continuation_token"))
|
|
538
|
+
if token_response_id is not None and token_response_id in invalidated:
|
|
539
|
+
# The token would short-circuit the request into retrieving
|
|
540
|
+
# the poisoned response outright — resurfacing the very
|
|
541
|
+
# stripped calls the invalidation withheld, with the request
|
|
542
|
+
# messages ignored. Removal-only: tokens are
|
|
543
|
+
# response-specific, no fall-back applies.
|
|
544
|
+
co.pop("continuation_token")
|
|
545
|
+
extra_body = co.get("extra_body")
|
|
546
|
+
if isinstance(extra_body, Mapping):
|
|
547
|
+
poisoned_keys = [
|
|
548
|
+
key
|
|
549
|
+
for key in CONVERSATION_HANDLE_KEYS
|
|
550
|
+
if (nested := conversation_handle_value(extra_body.get(key))) is not None and nested in invalidated
|
|
551
|
+
]
|
|
552
|
+
if poisoned_keys:
|
|
553
|
+
# Copy-on-write: the mapping may be a caller-owned object
|
|
554
|
+
# shared beyond this run.
|
|
555
|
+
clean_extra_body = dict(extra_body)
|
|
556
|
+
for key in poisoned_keys:
|
|
557
|
+
del clean_extra_body[key]
|
|
558
|
+
co["extra_body"] = clean_extra_body
|
|
559
|
+
|
|
560
|
+
# Build session_messages from session context: context messages + input messages
|
|
561
|
+
session_messages: list[Message] = session_context.get_messages(include_input=True)
|
|
562
|
+
|
|
563
|
+
effective_client_kwargs = dict(client_kwargs) if client_kwargs is not None else {}
|
|
564
|
+
if active_session is not None:
|
|
565
|
+
effective_client_kwargs["session"] = active_session
|
|
566
|
+
# Append provider middleware after existing client middleware.
|
|
567
|
+
# split_middleware rejects unsupported middleware with TypeError.
|
|
568
|
+
provider_middleware = session_context.get_middleware()
|
|
569
|
+
if provider_middleware:
|
|
570
|
+
provider_split = split_middleware(provider_middleware)
|
|
571
|
+
provider_function_chat_middleware: list[Any] = [*provider_split.function, *provider_split.chat]
|
|
572
|
+
if provider_function_chat_middleware:
|
|
573
|
+
existing_middleware = effective_client_kwargs.get("middleware")
|
|
574
|
+
if isinstance(existing_middleware, Sequence) and not isinstance(existing_middleware, (str, bytes)):
|
|
575
|
+
effective_client_kwargs["middleware"] = [
|
|
576
|
+
*existing_middleware,
|
|
577
|
+
*provider_function_chat_middleware,
|
|
578
|
+
]
|
|
579
|
+
elif existing_middleware is not None:
|
|
580
|
+
effective_client_kwargs["middleware"] = [
|
|
581
|
+
existing_middleware,
|
|
582
|
+
*provider_function_chat_middleware,
|
|
583
|
+
]
|
|
584
|
+
else:
|
|
585
|
+
effective_client_kwargs["middleware"] = provider_function_chat_middleware
|
|
586
|
+
|
|
587
|
+
return {
|
|
588
|
+
"session": active_session,
|
|
589
|
+
"session_context": session_context,
|
|
590
|
+
"input_messages": input_messages,
|
|
591
|
+
"session_messages": session_messages,
|
|
592
|
+
"agent_name": agent_name,
|
|
593
|
+
"chat_options": co,
|
|
594
|
+
"compaction_strategy": compaction_strategy or self.compaction_strategy,
|
|
595
|
+
"tokenizer": tokenizer or self.tokenizer,
|
|
596
|
+
"client_kwargs": effective_client_kwargs,
|
|
597
|
+
"function_invocation_kwargs": additional_function_arguments,
|
|
598
|
+
}
|
|
599
|
+
|
|
600
|
+
async def _prepare_session_and_messages(
|
|
601
|
+
self,
|
|
602
|
+
*,
|
|
603
|
+
session: AgentSession | None,
|
|
604
|
+
input_messages: list[Message] | None = None,
|
|
605
|
+
options: dict[str, Any] | None = None,
|
|
606
|
+
) -> tuple[SessionContext, dict[str, Any]]:
|
|
607
|
+
"""Copy agent defaults and collect provider context before the run."""
|
|
608
|
+
# Shallow-copy the tools list, deepcopy every other default.
|
|
609
|
+
chat_options_tools: list[Any] | None = None
|
|
610
|
+
if self.default_options:
|
|
611
|
+
chat_options: dict[str, Any] = {}
|
|
612
|
+
for key, value in self.default_options.items():
|
|
613
|
+
if key == "tools":
|
|
614
|
+
chat_options_tools = list(value) if value else []
|
|
615
|
+
chat_options[key] = chat_options_tools
|
|
616
|
+
else:
|
|
617
|
+
chat_options[key] = deepcopy(value)
|
|
618
|
+
else:
|
|
619
|
+
chat_options = {}
|
|
620
|
+
|
|
621
|
+
provider_session = session
|
|
622
|
+
if provider_session is None and self.context_providers:
|
|
623
|
+
provider_session = AgentSession()
|
|
624
|
+
|
|
625
|
+
session_context = SessionContext(
|
|
626
|
+
session_id=provider_session.session_id if provider_session else None,
|
|
627
|
+
service_session_id=provider_session.service_session_id if provider_session else None,
|
|
628
|
+
input_messages=input_messages or [],
|
|
629
|
+
options=options or {},
|
|
630
|
+
)
|
|
631
|
+
|
|
632
|
+
# Run before_run providers in forward order; HistoryProviders that opt
|
|
633
|
+
# out of message loading are skipped.
|
|
634
|
+
for provider in self.context_providers:
|
|
635
|
+
if isinstance(provider, HistoryProvider) and not provider.load_messages:
|
|
636
|
+
continue
|
|
637
|
+
if provider_session is None:
|
|
638
|
+
raise RuntimeError("Provider session must be available when context providers are configured.")
|
|
639
|
+
await provider.before_run(
|
|
640
|
+
agent=self, # type: ignore[arg-type]
|
|
641
|
+
session=provider_session,
|
|
642
|
+
context=session_context,
|
|
643
|
+
state=provider_session.state.setdefault(provider.source_id, {}),
|
|
644
|
+
)
|
|
645
|
+
|
|
646
|
+
# Merge provider-contributed tools into chat_options.
|
|
647
|
+
if session_context.tools:
|
|
648
|
+
if chat_options_tools is not None:
|
|
649
|
+
chat_options_tools.extend(session_context.tools)
|
|
650
|
+
else:
|
|
651
|
+
chat_options["tools"] = list(session_context.tools)
|
|
652
|
+
|
|
653
|
+
# Merge provider-contributed instructions into chat_options.
|
|
654
|
+
if session_context.instructions:
|
|
655
|
+
combined_instructions = "\n".join(session_context.instructions)
|
|
656
|
+
if "instructions" in chat_options:
|
|
657
|
+
chat_options["instructions"] = f"{chat_options['instructions']}\n{combined_instructions}"
|
|
658
|
+
else:
|
|
659
|
+
chat_options["instructions"] = combined_instructions
|
|
660
|
+
|
|
661
|
+
return session_context, chat_options
|
|
662
|
+
|
|
663
|
+
async def _parse_non_streaming_response(
|
|
664
|
+
self,
|
|
665
|
+
context: _RunContext,
|
|
666
|
+
response: ChatResponse,
|
|
667
|
+
) -> AgentResponse[Any]:
|
|
668
|
+
"""Build the agent response, update conversation state, and run the after-providers pass."""
|
|
669
|
+
if not response:
|
|
670
|
+
raise AgentInvalidResponseException("Chat client did not return a response.")
|
|
671
|
+
|
|
672
|
+
for message in response.messages:
|
|
673
|
+
if message.author_name is None:
|
|
674
|
+
message.author_name = context["agent_name"]
|
|
675
|
+
|
|
676
|
+
session = context["session"]
|
|
677
|
+
if response._chrys_service_state_invalidated:
|
|
678
|
+
# The tool loop withheld this run's continuation handles and
|
|
679
|
+
# already cleared the session's service handle in place; the
|
|
680
|
+
# discarded service transcript was the only history store, so
|
|
681
|
+
# install the local fallback before the after-providers pass
|
|
682
|
+
# persists this run's messages through it.
|
|
683
|
+
self._install_local_history_fallback(session)
|
|
684
|
+
if (
|
|
685
|
+
session
|
|
686
|
+
and response.conversation_id
|
|
687
|
+
and not is_local_history_conversation_id(response.conversation_id)
|
|
688
|
+
and session.service_session_id != response.conversation_id
|
|
689
|
+
):
|
|
690
|
+
session.service_session_id = response.conversation_id
|
|
691
|
+
|
|
692
|
+
agent_response = _build_agent_response_from_chat_response(
|
|
693
|
+
response,
|
|
694
|
+
response_format=context["chat_options"].get("response_format"),
|
|
695
|
+
)
|
|
696
|
+
session_context = context["session_context"]
|
|
697
|
+
# Providers observe the exact object returned to the caller. Response-
|
|
698
|
+
# level fields are shared run results and should be treated as read-only
|
|
699
|
+
# unless a provider intentionally coordinates a mutation.
|
|
700
|
+
session_context._response = agent_response
|
|
701
|
+
await self._run_after_providers(session=session, context=session_context)
|
|
702
|
+
return agent_response
|
|
703
|
+
|
|
704
|
+
def _parse_streaming_response(
|
|
705
|
+
self,
|
|
706
|
+
context: _RunContext,
|
|
707
|
+
stream_response: ResponseStream[ChatResponseUpdate, ChatResponse],
|
|
708
|
+
) -> ResponseStream[AgentResponseUpdate, AgentResponse[Any]]:
|
|
709
|
+
"""Map the tool-loop stream into agent updates and finalize session state.
|
|
710
|
+
|
|
711
|
+
The hook chain keeps streamed updates and the final response consistent:
|
|
712
|
+
``map(...)`` assembles the response, the transform hook propagates the
|
|
713
|
+
conversation id, and the result hook updates history after assembly.
|
|
714
|
+
``run()`` wraps this chain in ``from_awaitable``. Bypassing it can leave
|
|
715
|
+
final state out of sync with the updates already delivered to the caller.
|
|
716
|
+
|
|
717
|
+
The update transform uses ``self.name``, which may be ``None``. The result
|
|
718
|
+
hook backfills missing authors with the non-empty ``_get_agent_name()``;
|
|
719
|
+
both name sources are intentional.
|
|
720
|
+
"""
|
|
721
|
+
|
|
722
|
+
async def _post_hook(response: AgentResponse[Any]) -> None:
|
|
723
|
+
# Update session with conversation_id derived from streaming raw
|
|
724
|
+
# updates. Using response_id here can break function-call
|
|
725
|
+
# continuation for APIs where response IDs are not valid
|
|
726
|
+
# conversation handles.
|
|
727
|
+
conversation_id = self._extract_conversation_id_from_streaming_response(response)
|
|
728
|
+
|
|
729
|
+
for message in response.messages:
|
|
730
|
+
if message.author_name is None:
|
|
731
|
+
message.author_name = context["agent_name"]
|
|
732
|
+
|
|
733
|
+
session = context["session"]
|
|
734
|
+
if response._chrys_service_state_invalidated:
|
|
735
|
+
# The tool loop withheld this run's continuation handles (its
|
|
736
|
+
# exhaustion strip left the service-side transcript holding
|
|
737
|
+
# unanswered calls); the raw updates still carry the stale id
|
|
738
|
+
# and the eager transform already wrote it mid-stream, so
|
|
739
|
+
# clear instead of restoring. Install the local fallback
|
|
740
|
+
# first: the after-providers pass below persists this run's
|
|
741
|
+
# messages through it, so the next run replays them instead
|
|
742
|
+
# of starting from the bare new user message.
|
|
743
|
+
self._install_local_history_fallback(session)
|
|
744
|
+
if session is not None:
|
|
745
|
+
# The raw-scan id recovered above is the withheld handle;
|
|
746
|
+
# record it so a caller-supplied conversation_id repeating
|
|
747
|
+
# it gets suppressed instead of re-sent with the replay.
|
|
748
|
+
for handle in (conversation_id, session.service_session_id):
|
|
749
|
+
if isinstance(handle, str) and handle and not is_local_history_conversation_id(handle):
|
|
750
|
+
session.invalidated_service_session_ids.add(handle)
|
|
751
|
+
session.service_session_id = None
|
|
752
|
+
elif (
|
|
753
|
+
session
|
|
754
|
+
and conversation_id
|
|
755
|
+
and not is_local_history_conversation_id(conversation_id)
|
|
756
|
+
and session.service_session_id != conversation_id
|
|
757
|
+
):
|
|
758
|
+
session.service_session_id = conversation_id
|
|
759
|
+
|
|
760
|
+
session_context = context["session_context"]
|
|
761
|
+
# Agent owns the backing field; providers see the completed
|
|
762
|
+
# response through the read-only SessionContext.response property.
|
|
763
|
+
session_context._response = response
|
|
764
|
+
await self._run_after_providers(session=session, context=session_context)
|
|
765
|
+
|
|
766
|
+
def _propagate_conversation_id(update: AgentResponseUpdate) -> AgentResponseUpdate:
|
|
767
|
+
"""Propagate the conversation id to the session as updates arrive."""
|
|
768
|
+
session = context["session"]
|
|
769
|
+
if session is None:
|
|
770
|
+
return update
|
|
771
|
+
raw = update.raw_representation
|
|
772
|
+
if not isinstance(raw, ChatResponseUpdate):
|
|
773
|
+
return update
|
|
774
|
+
conversation_id = raw.conversation_id
|
|
775
|
+
if (
|
|
776
|
+
isinstance(conversation_id, str)
|
|
777
|
+
and conversation_id
|
|
778
|
+
and not is_local_history_conversation_id(conversation_id)
|
|
779
|
+
# Exhaustion-tail updates defer to the tail's own verdict
|
|
780
|
+
# (post-hook restore or invalidation): mirroring them eagerly
|
|
781
|
+
# would survive a mid-tail abandonment as a stale pointer to a
|
|
782
|
+
# service transcript holding stripped, never-answered calls.
|
|
783
|
+
and not raw.__dict__.get("_chrys_exhaustion_tail_update", False)
|
|
784
|
+
and session.service_session_id != conversation_id
|
|
785
|
+
):
|
|
786
|
+
session.service_session_id = conversation_id
|
|
787
|
+
return update
|
|
788
|
+
|
|
789
|
+
async def _finalizer(updates: Sequence[AgentResponseUpdate]) -> AgentResponse[Any]:
|
|
790
|
+
# Mapped updates span every tool-loop iteration, so copy the
|
|
791
|
+
# inner loop's normalized aggregate and final-call usage instead
|
|
792
|
+
# of re-summing raw cumulative usage snapshots here.
|
|
793
|
+
response = AgentResponse.from_updates(
|
|
794
|
+
updates,
|
|
795
|
+
output_format_type=context["chat_options"].get("response_format"),
|
|
796
|
+
)
|
|
797
|
+
chat_response = await stream_response.get_final_response()
|
|
798
|
+
response.usage_details = chat_response.usage_details
|
|
799
|
+
response.latest_usage_details = chat_response.latest_usage_details
|
|
800
|
+
# The tool loop is the sole reconstruction authority: reuse the
|
|
801
|
+
# tool loop's assembled Message objects instead of the local
|
|
802
|
+
# ``from_updates`` re-merge, which would rebuild multi-fragment
|
|
803
|
+
# function calls as new Content objects and drop kernel-stamped
|
|
804
|
+
# call provenance and folded result metadata. Element identity is
|
|
805
|
+
# preserved; the fresh list container means an after-provider
|
|
806
|
+
# mutating this response's list cannot corrupt the loop's.
|
|
807
|
+
response.messages = list(chat_response.messages)
|
|
808
|
+
if chat_response._chrys_service_state_invalidated:
|
|
809
|
+
# ``AgentResponse.from_updates`` restored ``response_id`` from
|
|
810
|
+
# the mapped updates even though the loop's finalizer withheld
|
|
811
|
+
# it; mirror the invalidation so the post-hook and the caller
|
|
812
|
+
# see no stale continuation handle.
|
|
813
|
+
response.response_id = None
|
|
814
|
+
response._chrys_service_state_invalidated = True
|
|
815
|
+
return response
|
|
816
|
+
|
|
817
|
+
stream = stream_response.map(
|
|
818
|
+
transform=partial(
|
|
819
|
+
map_chat_to_agent_update,
|
|
820
|
+
agent_name=self.name,
|
|
821
|
+
),
|
|
822
|
+
finalizer=_finalizer,
|
|
823
|
+
)
|
|
824
|
+
return stream.with_transform_hook(_propagate_conversation_id).with_result_hook(_post_hook)
|
|
825
|
+
|
|
826
|
+
@staticmethod
|
|
827
|
+
def _extract_conversation_id_from_streaming_response(
|
|
828
|
+
response: AgentResponse[Any],
|
|
829
|
+
) -> str | None:
|
|
830
|
+
"""Read the latest non-empty conversation id from the raw streaming updates."""
|
|
831
|
+
raw = response.raw_representation
|
|
832
|
+
if raw is None:
|
|
833
|
+
return None
|
|
834
|
+
|
|
835
|
+
raw_items: list[Any] = list(raw) if isinstance(raw, list) else [raw]
|
|
836
|
+
for item in reversed(raw_items):
|
|
837
|
+
if isinstance(item, Mapping):
|
|
838
|
+
value = item.get("conversation_id")
|
|
839
|
+
if isinstance(value, str) and value:
|
|
840
|
+
return value
|
|
841
|
+
continue
|
|
842
|
+
|
|
843
|
+
value = getattr(item, "conversation_id", None)
|
|
844
|
+
if isinstance(value, str) and value:
|
|
845
|
+
return value
|
|
846
|
+
|
|
847
|
+
return None
|
|
848
|
+
|
|
849
|
+
def _install_local_history_fallback(self, session: AgentSession | None) -> None:
|
|
850
|
+
"""Give an invalidated service-stored session a local history source.
|
|
851
|
+
|
|
852
|
+
Safety net behind the ``_prepare_run_context`` shadow install: any
|
|
853
|
+
service-stored run normally carries the handle-gated fallback from
|
|
854
|
+
run start, but if an invalidation arrives on a run whose preparation
|
|
855
|
+
did not select it, installing before the after-providers pass still
|
|
856
|
+
lets the standard ``after_run`` persist this run's input/output for
|
|
857
|
+
replay once no live handle exists. Sessions that already have a
|
|
858
|
+
loading HistoryProvider (including a previously installed fallback)
|
|
859
|
+
keep their existing history owner.
|
|
860
|
+
"""
|
|
861
|
+
if session is None:
|
|
862
|
+
return
|
|
863
|
+
if any(provider.load_messages for provider in self.context_providers if isinstance(provider, HistoryProvider)):
|
|
864
|
+
return
|
|
865
|
+
self.context_providers.append(ServiceFallbackHistoryProvider())
|
|
866
|
+
|
|
867
|
+
async def _run_after_providers(
|
|
868
|
+
self,
|
|
869
|
+
*,
|
|
870
|
+
session: AgentSession | None,
|
|
871
|
+
context: SessionContext,
|
|
872
|
+
) -> None:
|
|
873
|
+
"""Run providers in reverse order with their session state and the completed response."""
|
|
874
|
+
provider_session = session
|
|
875
|
+
if provider_session is None and self.context_providers:
|
|
876
|
+
provider_session = AgentSession()
|
|
877
|
+
|
|
878
|
+
for provider in reversed(self.context_providers):
|
|
879
|
+
if provider_session is None:
|
|
880
|
+
raise RuntimeError("Provider session must be available when context providers are configured.")
|
|
881
|
+
await provider.after_run(
|
|
882
|
+
agent=self, # type: ignore[arg-type]
|
|
883
|
+
session=provider_session,
|
|
884
|
+
context=context,
|
|
885
|
+
state=provider_session.state.setdefault(provider.source_id, {}),
|
|
886
|
+
)
|
|
887
|
+
|
|
888
|
+
|
|
889
|
+
class Agent(AgentTelemetryLayer, _AgentCore):
|
|
890
|
+
"""Production agent with telemetry over the orchestration core.
|
|
891
|
+
|
|
892
|
+
Chat and function middleware are split and forwarded to the client stack.
|
|
893
|
+
``AgentTelemetryLayer`` sets and resets non-streaming ContextVars inside
|
|
894
|
+
the returned coroutine, so creation and execution may occur in different
|
|
895
|
+
tasks. Streaming spans activate around each pull and close before their
|
|
896
|
+
ContextVars are reset.
|
|
897
|
+
"""
|
|
898
|
+
|
|
899
|
+
@overload
|
|
900
|
+
def run(
|
|
901
|
+
self,
|
|
902
|
+
messages: AgentRunInputs | None = None,
|
|
903
|
+
*,
|
|
904
|
+
stream: Literal[False] = False,
|
|
905
|
+
session: AgentSession | None = None,
|
|
906
|
+
middleware: ChatMiddleware | FunctionMiddleware | Sequence[ChatMiddleware | FunctionMiddleware] | None = None,
|
|
907
|
+
tools: ToolTypes | Callable[..., Any] | Sequence[ToolTypes | Callable[..., Any]] | None = None,
|
|
908
|
+
options: Mapping[str, Any] | None = None,
|
|
909
|
+
compaction_strategy: Any = None,
|
|
910
|
+
tokenizer: Any = None,
|
|
911
|
+
function_invocation_kwargs: Mapping[str, Any] | None = None,
|
|
912
|
+
client_kwargs: Mapping[str, Any] | None = None,
|
|
913
|
+
) -> Awaitable[AgentResponse[Any]]: ...
|
|
914
|
+
|
|
915
|
+
@overload
|
|
916
|
+
def run(
|
|
917
|
+
self,
|
|
918
|
+
messages: AgentRunInputs | None = None,
|
|
919
|
+
*,
|
|
920
|
+
stream: Literal[True],
|
|
921
|
+
session: AgentSession | None = None,
|
|
922
|
+
middleware: ChatMiddleware | FunctionMiddleware | Sequence[ChatMiddleware | FunctionMiddleware] | None = None,
|
|
923
|
+
tools: ToolTypes | Callable[..., Any] | Sequence[ToolTypes | Callable[..., Any]] | None = None,
|
|
924
|
+
options: Mapping[str, Any] | None = None,
|
|
925
|
+
compaction_strategy: Any = None,
|
|
926
|
+
tokenizer: Any = None,
|
|
927
|
+
function_invocation_kwargs: Mapping[str, Any] | None = None,
|
|
928
|
+
client_kwargs: Mapping[str, Any] | None = None,
|
|
929
|
+
) -> ResponseStream[AgentResponseUpdate, AgentResponse[Any]]: ...
|
|
930
|
+
|
|
931
|
+
@overload
|
|
932
|
+
def run(
|
|
933
|
+
self,
|
|
934
|
+
messages: AgentRunInputs | None = None,
|
|
935
|
+
*,
|
|
936
|
+
stream: bool,
|
|
937
|
+
session: AgentSession | None = None,
|
|
938
|
+
middleware: ChatMiddleware | FunctionMiddleware | Sequence[ChatMiddleware | FunctionMiddleware] | None = None,
|
|
939
|
+
tools: ToolTypes | Callable[..., Any] | Sequence[ToolTypes | Callable[..., Any]] | None = None,
|
|
940
|
+
options: Mapping[str, Any] | None = None,
|
|
941
|
+
compaction_strategy: Any = None,
|
|
942
|
+
tokenizer: Any = None,
|
|
943
|
+
function_invocation_kwargs: Mapping[str, Any] | None = None,
|
|
944
|
+
client_kwargs: Mapping[str, Any] | None = None,
|
|
945
|
+
) -> Awaitable[AgentResponse[Any]] | ResponseStream[AgentResponseUpdate, AgentResponse[Any]]: ...
|
|
946
|
+
|
|
947
|
+
def run(
|
|
948
|
+
self,
|
|
949
|
+
messages: AgentRunInputs | None = None,
|
|
950
|
+
*,
|
|
951
|
+
stream: bool = False,
|
|
952
|
+
session: AgentSession | None = None,
|
|
953
|
+
middleware: ChatMiddleware | FunctionMiddleware | Sequence[ChatMiddleware | FunctionMiddleware] | None = None,
|
|
954
|
+
tools: ToolTypes | Callable[..., Any] | Sequence[ToolTypes | Callable[..., Any]] | None = None,
|
|
955
|
+
options: Mapping[str, Any] | None = None,
|
|
956
|
+
compaction_strategy: Any = None,
|
|
957
|
+
tokenizer: Any = None,
|
|
958
|
+
function_invocation_kwargs: Mapping[str, Any] | None = None,
|
|
959
|
+
client_kwargs: Mapping[str, Any] | None = None,
|
|
960
|
+
) -> Awaitable[AgentResponse[Any]] | ResponseStream[AgentResponseUpdate, AgentResponse[Any]]:
|
|
961
|
+
"""Combine constructor and run middleware, then delegate through telemetry.
|
|
962
|
+
|
|
963
|
+
Re-read ``self.middleware`` on every call so dynamic changes take effect.
|
|
964
|
+
The order is ``[ctor-function, ctor-chat, run-function, run-chat]``; a
|
|
965
|
+
non-empty combination overwrites ``client_kwargs["middleware"]``.
|
|
966
|
+
The ``middleware`` keyword itself must not be forwarded:
|
|
967
|
+
``AgentTelemetryLayer.run`` would pass it to ``_AgentCore.run``, which
|
|
968
|
+
accepts middleware only through ``client_kwargs``.
|
|
969
|
+
"""
|
|
970
|
+
ctor_split = split_middleware(self.middleware)
|
|
971
|
+
run_split = split_middleware(middleware)
|
|
972
|
+
combined_function_chat_middleware: list[Any] = [
|
|
973
|
+
*ctor_split.function,
|
|
974
|
+
*ctor_split.chat,
|
|
975
|
+
*run_split.function,
|
|
976
|
+
*run_split.chat,
|
|
977
|
+
]
|
|
978
|
+
effective_client_kwargs = dict(client_kwargs) if client_kwargs is not None else {}
|
|
979
|
+
if combined_function_chat_middleware:
|
|
980
|
+
effective_client_kwargs["middleware"] = combined_function_chat_middleware
|
|
981
|
+
effective_function_invocation_kwargs = (
|
|
982
|
+
dict(function_invocation_kwargs) if function_invocation_kwargs is not None else {}
|
|
983
|
+
)
|
|
984
|
+
return super().run(
|
|
985
|
+
messages,
|
|
986
|
+
stream=stream,
|
|
987
|
+
session=session,
|
|
988
|
+
tools=tools,
|
|
989
|
+
options=options,
|
|
990
|
+
compaction_strategy=compaction_strategy,
|
|
991
|
+
tokenizer=tokenizer,
|
|
992
|
+
function_invocation_kwargs=effective_function_invocation_kwargs,
|
|
993
|
+
client_kwargs=effective_client_kwargs,
|
|
994
|
+
)
|