iCode-TUI 0.29.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- chrys/__init__.py +16 -0
- chrys/app/__init__.py +3 -0
- chrys/app/acp/__init__.py +3 -0
- chrys/app/acp/bridge.py +664 -0
- chrys/app/acp/content.py +132 -0
- chrys/app/acp/doc/frontend-api.md +425 -0
- chrys/app/acp/history.py +585 -0
- chrys/app/acp/server.py +1796 -0
- chrys/app/acp/session_manager.py +1815 -0
- chrys/app/acp/tool_status.py +45 -0
- chrys/app/cli/__init__.py +3 -0
- chrys/app/cli/acp.py +178 -0
- chrys/app/cli/app.py +165 -0
- chrys/app/cli/approvals.py +101 -0
- chrys/app/cli/headless.py +223 -0
- chrys/app/cli/launch_cwd.py +42 -0
- chrys/app/cli/profiles.py +298 -0
- chrys/app/cli/progress.py +857 -0
- chrys/app/cli/run.py +425 -0
- chrys/app/cli/serve.py +1593 -0
- chrys/app/cli/tool_summary.py +225 -0
- chrys/app/cli/trajectory.py +201 -0
- chrys/app/cli/workflow.py +601 -0
- chrys/app/features/__init__.py +3 -0
- chrys/app/features/buddy/__init__.py +3 -0
- chrys/app/features/buddy/actions.py +68 -0
- chrys/app/features/buddy/animation.py +76 -0
- chrys/app/features/buddy/commands.py +196 -0
- chrys/app/features/buddy/docs/design.md +187 -0
- chrys/app/features/buddy/hatchery.py +80 -0
- chrys/app/features/buddy/lifecycle.py +41 -0
- chrys/app/features/buddy/model.py +265 -0
- chrys/app/features/buddy/pixel_renderer.py +113 -0
- chrys/app/features/buddy/pixel_sprites.py +279 -0
- chrys/app/features/buddy/portrait.py +76 -0
- chrys/app/features/buddy/progression.py +58 -0
- chrys/app/features/buddy/replies.py +191 -0
- chrys/app/features/buddy/sprites/alien.toml +70 -0
- chrys/app/features/buddy/sprites/axolotl.toml +71 -0
- chrys/app/features/buddy/sprites/bat.toml +69 -0
- chrys/app/features/buddy/sprites/bee.toml +69 -0
- chrys/app/features/buddy/sprites/cactus.toml +73 -0
- chrys/app/features/buddy/sprites/capybara.toml +70 -0
- chrys/app/features/buddy/sprites/cat.toml +69 -0
- chrys/app/features/buddy/sprites/crab.toml +70 -0
- chrys/app/features/buddy/sprites/dragon.toml +71 -0
- chrys/app/features/buddy/sprites/duck.toml +69 -0
- chrys/app/features/buddy/sprites/fox.toml +69 -0
- chrys/app/features/buddy/sprites/frog.toml +70 -0
- chrys/app/features/buddy/sprites/ghost.toml +70 -0
- chrys/app/features/buddy/sprites/goose.toml +69 -0
- chrys/app/features/buddy/sprites/jelly.toml +70 -0
- chrys/app/features/buddy/sprites/llama.toml +70 -0
- chrys/app/features/buddy/sprites/mushroom.toml +69 -0
- chrys/app/features/buddy/sprites/octopus.toml +70 -0
- chrys/app/features/buddy/sprites/owl.toml +70 -0
- chrys/app/features/buddy/sprites/panda.toml +71 -0
- chrys/app/features/buddy/sprites/penguin.toml +69 -0
- chrys/app/features/buddy/sprites/rabbit.toml +70 -0
- chrys/app/features/buddy/sprites/robot.toml +72 -0
- chrys/app/features/buddy/sprites/shark.toml +70 -0
- chrys/app/features/buddy/sprites/snail.toml +69 -0
- chrys/app/features/buddy/sprites/snake.toml +69 -0
- chrys/app/features/buddy/sprites/tabby.toml +69 -0
- chrys/app/features/buddy/sprites/turtle.toml +69 -0
- chrys/app/features/buddy/store.py +143 -0
- chrys/app/features/session_title/__init__.py +7 -0
- chrys/app/features/session_title/updater.py +582 -0
- chrys/app/installer.py +651 -0
- chrys/app/parsing.py +17 -0
- chrys/app/tui/__init__.py +3 -0
- chrys/app/tui/app.py +1287 -0
- chrys/app/tui/behaviors/__init__.py +3 -0
- chrys/app/tui/behaviors/click_outside_dismiss.py +90 -0
- chrys/app/tui/behaviors/insert_clipboard.py +73 -0
- chrys/app/tui/behaviors/right_click_copy.py +146 -0
- chrys/app/tui/binding_display.py +139 -0
- chrys/app/tui/buddy_messages.py +17 -0
- chrys/app/tui/buddy_reply.py +86 -0
- chrys/app/tui/chrys.tcss +549 -0
- chrys/app/tui/clipboard.py +109 -0
- chrys/app/tui/copy_messages.py +10 -0
- chrys/app/tui/i18n.py +230 -0
- chrys/app/tui/language.py +58 -0
- chrys/app/tui/notifications/__init__.py +12 -0
- chrys/app/tui/notifications/drivers.py +180 -0
- chrys/app/tui/notifications/service.py +126 -0
- chrys/app/tui/notifications/settings.py +141 -0
- chrys/app/tui/screens/__init__.py +3 -0
- chrys/app/tui/screens/agents/__init__.py +8 -0
- chrys/app/tui/screens/agents/agent_draft_store.py +937 -0
- chrys/app/tui/screens/agents/config.py +2142 -0
- chrys/app/tui/screens/agents/config.tcss +169 -0
- chrys/app/tui/screens/agents/panels/__init__.py +3 -0
- chrys/app/tui/screens/agents/panels/acp.py +1176 -0
- chrys/app/tui/screens/agents/panels/basic.py +497 -0
- chrys/app/tui/screens/agents/panels/compaction.py +231 -0
- chrys/app/tui/screens/agents/panels/config_card.py +218 -0
- chrys/app/tui/screens/agents/panels/instructions.py +91 -0
- chrys/app/tui/screens/agents/panels/markdown_report.py +76 -0
- chrys/app/tui/screens/agents/panels/mcp.py +2262 -0
- chrys/app/tui/screens/agents/panels/memory.py +684 -0
- chrys/app/tui/screens/agents/panels/path_entry.py +227 -0
- chrys/app/tui/screens/agents/panels/skills.py +806 -0
- chrys/app/tui/screens/agents/panels/subagents.py +652 -0
- chrys/app/tui/screens/agents/panels/tools.py +205 -0
- chrys/app/tui/screens/agents/picker.py +103 -0
- chrys/app/tui/screens/agents/skill_paths.py +38 -0
- chrys/app/tui/screens/agents/validation_messages.py +452 -0
- chrys/app/tui/screens/dialogs/__init__.py +35 -0
- chrys/app/tui/screens/dialogs/agent_load.py +834 -0
- chrys/app/tui/screens/dialogs/agent_load.tcss +78 -0
- chrys/app/tui/screens/dialogs/app_mode.py +55 -0
- chrys/app/tui/screens/dialogs/approval/__init__.py +15 -0
- chrys/app/tui/screens/dialogs/approval/approval.tcss +311 -0
- chrys/app/tui/screens/dialogs/approval/bodies/__init__.py +3 -0
- chrys/app/tui/screens/dialogs/approval/bodies/file_edit.py +210 -0
- chrys/app/tui/screens/dialogs/approval/bodies/sub_agent.py +82 -0
- chrys/app/tui/screens/dialogs/approval/body.py +110 -0
- chrys/app/tui/screens/dialogs/approval/dialog.py +565 -0
- chrys/app/tui/screens/dialogs/approval/mode.py +105 -0
- chrys/app/tui/screens/dialogs/ask_user.py +148 -0
- chrys/app/tui/screens/dialogs/ask_user.tcss +62 -0
- chrys/app/tui/screens/dialogs/base.py +84 -0
- chrys/app/tui/screens/dialogs/confirm.py +184 -0
- chrys/app/tui/screens/dialogs/confirm.tcss +46 -0
- chrys/app/tui/screens/dialogs/connection_test.py +183 -0
- chrys/app/tui/screens/dialogs/connection_test.tcss +92 -0
- chrys/app/tui/screens/dialogs/diagram.py +102 -0
- chrys/app/tui/screens/dialogs/diagram.tcss +24 -0
- chrys/app/tui/screens/dialogs/editor.py +378 -0
- chrys/app/tui/screens/dialogs/editor.tcss +132 -0
- chrys/app/tui/screens/dialogs/file_picker.py +582 -0
- chrys/app/tui/screens/dialogs/file_picker.tcss +78 -0
- chrys/app/tui/screens/dialogs/fork_session.py +219 -0
- chrys/app/tui/screens/dialogs/fork_session.tcss +75 -0
- chrys/app/tui/screens/dialogs/image_compression.py +102 -0
- chrys/app/tui/screens/dialogs/image_compression.tcss +28 -0
- chrys/app/tui/screens/dialogs/man_page.py +172 -0
- chrys/app/tui/screens/dialogs/man_page.tcss +39 -0
- chrys/app/tui/screens/dialogs/new_folder.py +277 -0
- chrys/app/tui/screens/dialogs/new_folder.tcss +51 -0
- chrys/app/tui/screens/dialogs/notice.tcss +14 -0
- chrys/app/tui/screens/dialogs/prompt_cache.py +144 -0
- chrys/app/tui/screens/dialogs/prompt_cache.tcss +38 -0
- chrys/app/tui/screens/dialogs/runtime_details.py +371 -0
- chrys/app/tui/screens/dialogs/runtime_details.tcss +49 -0
- chrys/app/tui/screens/dialogs/session_title.py +110 -0
- chrys/app/tui/screens/dialogs/session_title.tcss +43 -0
- chrys/app/tui/screens/dialogs/tool_view.py +207 -0
- chrys/app/tui/screens/dialogs/tool_view.tcss +43 -0
- chrys/app/tui/screens/dialogs/vision_unsupported.py +122 -0
- chrys/app/tui/screens/dialogs/vision_unsupported.tcss +35 -0
- chrys/app/tui/screens/dialogs/workflow_confirm.py +91 -0
- chrys/app/tui/screens/dialogs/workflow_confirm.tcss +17 -0
- chrys/app/tui/screens/dialogs/workflow_input.py +258 -0
- chrys/app/tui/screens/dialogs/workflow_input.tcss +73 -0
- chrys/app/tui/screens/dialogs/workflow_node.py +462 -0
- chrys/app/tui/screens/dialogs/workflow_node.tcss +41 -0
- chrys/app/tui/screens/dialogs/workflow_picker.py +46 -0
- chrys/app/tui/screens/dialogs/workflow_result.py +136 -0
- chrys/app/tui/screens/dialogs/workflow_result.tcss +14 -0
- chrys/app/tui/screens/diff/__init__.py +22 -0
- chrys/app/tui/screens/diff/rollback_modal.py +1381 -0
- chrys/app/tui/screens/diff/rollback_modal.tcss +248 -0
- chrys/app/tui/screens/diff/screen.py +1532 -0
- chrys/app/tui/screens/diff/screen.tcss +104 -0
- chrys/app/tui/screens/guides/__init__.py +7 -0
- chrys/app/tui/screens/guides/_docs/en/guides/configuration/agents.md +178 -0
- chrys/app/tui/screens/guides/_docs/en/guides/configuration/approval.md +117 -0
- chrys/app/tui/screens/guides/_docs/en/guides/configuration/chat-options.md +276 -0
- chrys/app/tui/screens/guides/_docs/en/guides/configuration/compaction.md +42 -0
- chrys/app/tui/screens/guides/_docs/en/guides/configuration/memory.md +48 -0
- chrys/app/tui/screens/guides/_docs/en/guides/configuration/models.md +158 -0
- chrys/app/tui/screens/guides/_docs/en/guides/configuration/settings.md +210 -0
- chrys/app/tui/screens/guides/_docs/en/guides/configuration/themes.md +61 -0
- chrys/app/tui/screens/guides/_docs/en/guides/configuration/tools.md +60 -0
- chrys/app/tui/screens/guides/_docs/en/guides/configuration/web-tools.md +286 -0
- chrys/app/tui/screens/guides/_docs/en/guides/daily-use/sessions.md +77 -0
- chrys/app/tui/screens/guides/_docs/en/guides/daily-use/workspaces.md +51 -0
- chrys/app/tui/screens/guides/_docs/en/guides/extensions/external-acp-agents.md +126 -0
- chrys/app/tui/screens/guides/_docs/en/guides/extensions/hooks.md +167 -0
- chrys/app/tui/screens/guides/_docs/en/guides/extensions/mcp.md +95 -0
- chrys/app/tui/screens/guides/_docs/en/guides/extensions/skills.md +175 -0
- chrys/app/tui/screens/guides/_docs/en/guides/running/icode-acp.md +61 -0
- chrys/app/tui/screens/guides/_docs/en/guides/running/icode-run.md +190 -0
- chrys/app/tui/screens/guides/_docs/en/guides/running/icode-serve.md +239 -0
- chrys/app/tui/screens/guides/_docs/en/guides/running/workflows.md +664 -0
- chrys/app/tui/screens/guides/_docs/en/reference/agent-profile.md +548 -0
- chrys/app/tui/screens/guides/_docs/en/reference/hooks.md +602 -0
- chrys/app/tui/screens/guides/_docs/en/reference/opentelemetry.md +177 -0
- chrys/app/tui/screens/guides/_docs/en/reference/settings.md +245 -0
- chrys/app/tui/screens/guides/_docs/en/reference/themes.md +149 -0
- chrys/app/tui/screens/guides/_docs/en/reference/tool-kinds-and-names.md +58 -0
- chrys/app/tui/screens/guides/_docs/en/reference/tui-slash-commands.md +76 -0
- chrys/app/tui/screens/guides/_docs/en/reference/workflows.md +1006 -0
- chrys/app/tui/screens/guides/_docs/en/start/getting-started.md +170 -0
- chrys/app/tui/screens/guides/_docs/en/start/what-is-icode.md +34 -0
- chrys/app/tui/screens/guides/_docs/index.yaml +100 -0
- chrys/app/tui/screens/guides/_docs/zh-Hans/guides/configuration/agents.md +178 -0
- chrys/app/tui/screens/guides/_docs/zh-Hans/guides/configuration/approval.md +117 -0
- chrys/app/tui/screens/guides/_docs/zh-Hans/guides/configuration/chat-options.md +276 -0
- chrys/app/tui/screens/guides/_docs/zh-Hans/guides/configuration/compaction.md +42 -0
- chrys/app/tui/screens/guides/_docs/zh-Hans/guides/configuration/memory.md +48 -0
- chrys/app/tui/screens/guides/_docs/zh-Hans/guides/configuration/models.md +158 -0
- chrys/app/tui/screens/guides/_docs/zh-Hans/guides/configuration/settings.md +210 -0
- chrys/app/tui/screens/guides/_docs/zh-Hans/guides/configuration/themes.md +61 -0
- chrys/app/tui/screens/guides/_docs/zh-Hans/guides/configuration/tools.md +60 -0
- chrys/app/tui/screens/guides/_docs/zh-Hans/guides/configuration/web-tools.md +286 -0
- chrys/app/tui/screens/guides/_docs/zh-Hans/guides/daily-use/sessions.md +77 -0
- chrys/app/tui/screens/guides/_docs/zh-Hans/guides/daily-use/workspaces.md +51 -0
- chrys/app/tui/screens/guides/_docs/zh-Hans/guides/extensions/external-acp-agents.md +126 -0
- chrys/app/tui/screens/guides/_docs/zh-Hans/guides/extensions/hooks.md +167 -0
- chrys/app/tui/screens/guides/_docs/zh-Hans/guides/extensions/mcp.md +95 -0
- chrys/app/tui/screens/guides/_docs/zh-Hans/guides/extensions/skills.md +175 -0
- chrys/app/tui/screens/guides/_docs/zh-Hans/guides/running/icode-acp.md +61 -0
- chrys/app/tui/screens/guides/_docs/zh-Hans/guides/running/icode-run.md +190 -0
- chrys/app/tui/screens/guides/_docs/zh-Hans/guides/running/icode-serve.md +239 -0
- chrys/app/tui/screens/guides/_docs/zh-Hans/guides/running/workflows.md +664 -0
- chrys/app/tui/screens/guides/_docs/zh-Hans/reference/agent-profile.md +548 -0
- chrys/app/tui/screens/guides/_docs/zh-Hans/reference/hooks.md +602 -0
- chrys/app/tui/screens/guides/_docs/zh-Hans/reference/opentelemetry.md +177 -0
- chrys/app/tui/screens/guides/_docs/zh-Hans/reference/settings.md +245 -0
- chrys/app/tui/screens/guides/_docs/zh-Hans/reference/themes.md +149 -0
- chrys/app/tui/screens/guides/_docs/zh-Hans/reference/tool-kinds-and-names.md +58 -0
- chrys/app/tui/screens/guides/_docs/zh-Hans/reference/tui-slash-commands.md +76 -0
- chrys/app/tui/screens/guides/_docs/zh-Hans/reference/workflows.md +1005 -0
- chrys/app/tui/screens/guides/_docs/zh-Hans/start/getting-started.md +170 -0
- chrys/app/tui/screens/guides/_docs/zh-Hans/start/what-is-icode.md +34 -0
- chrys/app/tui/screens/guides/index.py +215 -0
- chrys/app/tui/screens/guides/reader.py +173 -0
- chrys/app/tui/screens/guides/screen.py +442 -0
- chrys/app/tui/screens/guides/screen.tcss +52 -0
- chrys/app/tui/screens/logs/__init__.py +7 -0
- chrys/app/tui/screens/logs/screen.py +504 -0
- chrys/app/tui/screens/logs/screen.tcss +45 -0
- chrys/app/tui/screens/main/__init__.py +7 -0
- chrys/app/tui/screens/main/action_availability.py +30 -0
- chrys/app/tui/screens/main/buddy_command.py +143 -0
- chrys/app/tui/screens/main/commands.py +1073 -0
- chrys/app/tui/screens/main/config_actions.py +464 -0
- chrys/app/tui/screens/main/copy_actions.py +117 -0
- chrys/app/tui/screens/main/dialog_controllers.py +826 -0
- chrys/app/tui/screens/main/dialog_gateway.py +166 -0
- chrys/app/tui/screens/main/diff_controller.py +478 -0
- chrys/app/tui/screens/main/engine_read_model.py +184 -0
- chrys/app/tui/screens/main/event_handlers.py +2014 -0
- chrys/app/tui/screens/main/input_flow.py +241 -0
- chrys/app/tui/screens/main/live_diff.py +244 -0
- chrys/app/tui/screens/main/main_screen_presenter.py +295 -0
- chrys/app/tui/screens/main/model_indicator.py +217 -0
- chrys/app/tui/screens/main/navigation.py +343 -0
- chrys/app/tui/screens/main/ports.py +571 -0
- chrys/app/tui/screens/main/recent_dirs.py +123 -0
- chrys/app/tui/screens/main/rollback_controller.py +586 -0
- chrys/app/tui/screens/main/runtime_info.py +71 -0
- chrys/app/tui/screens/main/screen.py +2265 -0
- chrys/app/tui/screens/main/screen.tcss +21 -0
- chrys/app/tui/screens/main/session_handlers.py +1127 -0
- chrys/app/tui/screens/main/session_title.py +239 -0
- chrys/app/tui/screens/main/settings_coordinator.py +365 -0
- chrys/app/tui/screens/main/settings_persistence.py +184 -0
- chrys/app/tui/screens/main/shell_mode.py +112 -0
- chrys/app/tui/screens/main/state.py +289 -0
- chrys/app/tui/screens/main/submit_state.py +11 -0
- chrys/app/tui/screens/main/subscriptions.py +177 -0
- chrys/app/tui/screens/main/suggestions.py +982 -0
- chrys/app/tui/screens/main/tool_action_bridge.py +75 -0
- chrys/app/tui/screens/main/view_adapter.py +1567 -0
- chrys/app/tui/screens/main/workflow_browser.py +747 -0
- chrys/app/tui/screens/main/workflow_content.py +248 -0
- chrys/app/tui/screens/main/workflow_controller.py +240 -0
- chrys/app/tui/screens/main/workflow_feedback.py +137 -0
- chrys/app/tui/screens/main/workflow_flow.py +49 -0
- chrys/app/tui/screens/main/workflow_run_control.py +456 -0
- chrys/app/tui/screens/main/workflow_session_view.py +316 -0
- chrys/app/tui/screens/main/workspace_actions.py +272 -0
- chrys/app/tui/screens/main/workspace_branch.py +194 -0
- chrys/app/tui/screens/menus/__init__.py +8 -0
- chrys/app/tui/screens/menus/languages.py +114 -0
- chrys/app/tui/screens/models/__init__.py +7 -0
- chrys/app/tui/screens/models/picker.py +147 -0
- chrys/app/tui/screens/models/screen.py +2043 -0
- chrys/app/tui/screens/models/screen.tcss +255 -0
- chrys/app/tui/screens/sessions/__init__.py +8 -0
- chrys/app/tui/screens/sessions/presenter.py +586 -0
- chrys/app/tui/screens/sessions/screen.py +779 -0
- chrys/app/tui/screens/sessions/screen.tcss +127 -0
- chrys/app/tui/screens/settings/__init__.py +29 -0
- chrys/app/tui/screens/settings/danger.py +26 -0
- chrys/app/tui/screens/settings/dialog.py +281 -0
- chrys/app/tui/screens/settings/layout.py +519 -0
- chrys/app/tui/screens/settings/migrate_dialog.py +253 -0
- chrys/app/tui/screens/settings/panes/__init__.py +3 -0
- chrys/app/tui/screens/settings/panes/notifications.py +248 -0
- chrys/app/tui/screens/settings/panes/sessions.py +148 -0
- chrys/app/tui/screens/settings/ports.py +55 -0
- chrys/app/tui/screens/settings/provenance.py +102 -0
- chrys/app/tui/screens/settings/rows.py +546 -0
- chrys/app/tui/screens/settings/settings.tcss +406 -0
- chrys/app/tui/screens/themes/__init__.py +8 -0
- chrys/app/tui/screens/themes/dialogs.py +330 -0
- chrys/app/tui/screens/themes/editor.py +632 -0
- chrys/app/tui/screens/themes/editor.tcss +268 -0
- chrys/app/tui/screens/themes/messages.py +95 -0
- chrys/app/tui/screens/themes/palette.py +694 -0
- chrys/app/tui/screens/themes/panel.py +113 -0
- chrys/app/tui/screens/themes/picker.py +203 -0
- chrys/app/tui/screens/themes/save.py +191 -0
- chrys/app/tui/support/__init__.py +3 -0
- chrys/app/tui/support/file_manager.py +64 -0
- chrys/app/tui/support/gc_freeze.py +1114 -0
- chrys/app/tui/support/path_shortcuts.py +50 -0
- chrys/app/tui/support/prompt_history.py +298 -0
- chrys/app/tui/support/workspace_mru.py +476 -0
- chrys/app/tui/terminal/__init__.py +6 -0
- chrys/app/tui/terminal/_pty_backend.py +114 -0
- chrys/app/tui/terminal/emulator/__init__.py +24 -0
- chrys/app/tui/terminal/emulator/buffer.py +456 -0
- chrys/app/tui/terminal/emulator/charsets.py +113 -0
- chrys/app/tui/terminal/emulator/core.py +963 -0
- chrys/app/tui/terminal/emulator/input.py +342 -0
- chrys/app/tui/terminal/emulator/parser.py +227 -0
- chrys/app/tui/terminal/emulator/pen.py +158 -0
- chrys/app/tui/terminal/launcher.py +455 -0
- chrys/app/tui/terminal/leaked_reports.py +44 -0
- chrys/app/tui/terminal/panel.py +323 -0
- chrys/app/tui/terminal/pty_process.py +405 -0
- chrys/app/tui/terminal/rendering.py +151 -0
- chrys/app/tui/terminal/shell.py +273 -0
- chrys/app/tui/terminal/shell_integration.py +199 -0
- chrys/app/tui/terminal/title.py +224 -0
- chrys/app/tui/terminal/widget.py +654 -0
- chrys/app/tui/theme.py +422 -0
- chrys/app/tui/theme_loader.py +201 -0
- chrys/app/tui/theme_stylesheet.py +49 -0
- chrys/app/tui/themes/__init__.py +3 -0
- chrys/app/tui/themes/document.py +120 -0
- chrys/app/tui/themes/preview.py +170 -0
- chrys/app/tui/themes/store.py +176 -0
- chrys/app/tui/toasts.py +69 -0
- chrys/app/tui/util/__init__.py +3 -0
- chrys/app/tui/util/context_pressure.py +146 -0
- chrys/app/tui/util/debug_log.py +292 -0
- chrys/app/tui/util/diff_entries.py +64 -0
- chrys/app/tui/util/formatting.py +53 -0
- chrys/app/tui/util/git_branch.py +326 -0
- chrys/app/tui/util/invocation_progress.py +57 -0
- chrys/app/tui/util/logo.py +32 -0
- chrys/app/tui/util/message_gate.py +35 -0
- chrys/app/tui/util/mutation_sources.py +14 -0
- chrys/app/tui/util/picker_text.py +27 -0
- chrys/app/tui/util/removal.py +47 -0
- chrys/app/tui/util/rich_style.py +36 -0
- chrys/app/tui/util/source_text.py +12 -0
- chrys/app/tui/util/static_update.py +88 -0
- chrys/app/tui/util/todo_format.py +51 -0
- chrys/app/tui/util/visibility.py +214 -0
- chrys/app/tui/widgets/__init__.py +60 -0
- chrys/app/tui/widgets/ask_user_controls.py +652 -0
- chrys/app/tui/widgets/ask_user_markdown.py +17 -0
- chrys/app/tui/widgets/ask_user_prompt.py +606 -0
- chrys/app/tui/widgets/buttons.py +52 -0
- chrys/app/tui/widgets/chat/__init__.py +3 -0
- chrys/app/tui/widgets/chat/agent_transcript_surface.py +818 -0
- chrys/app/tui/widgets/chat/chrome.py +296 -0
- chrys/app/tui/widgets/chat/compaction_card.py +353 -0
- chrys/app/tui/widgets/chat/context_fold.py +77 -0
- chrys/app/tui/widgets/chat/file_snapshot.py +91 -0
- chrys/app/tui/widgets/chat/image_preview.py +214 -0
- chrys/app/tui/widgets/chat/live_renderer.py +383 -0
- chrys/app/tui/widgets/chat/messages.py +1039 -0
- chrys/app/tui/widgets/chat/panel.py +1769 -0
- chrys/app/tui/widgets/chat/ports.py +245 -0
- chrys/app/tui/widgets/chat/renderers/__init__.py +7 -0
- chrys/app/tui/widgets/chat/renderers/ask_user.py +747 -0
- chrys/app/tui/widgets/chat/renderers/execute.py +431 -0
- chrys/app/tui/widgets/chat/renderers/file_edit.py +925 -0
- chrys/app/tui/widgets/chat/renderers/hosted_code.py +83 -0
- chrys/app/tui/widgets/chat/renderers/hosted_generic.py +330 -0
- chrys/app/tui/widgets/chat/renderers/hosted_image.py +107 -0
- chrys/app/tui/widgets/chat/renderers/hosted_mcp.py +43 -0
- chrys/app/tui/widgets/chat/renderers/hosted_search.py +167 -0
- chrys/app/tui/widgets/chat/renderers/hosted_shell.py +132 -0
- chrys/app/tui/widgets/chat/renderers/read_file.py +399 -0
- chrys/app/tui/widgets/chat/renderers/search.py +348 -0
- chrys/app/tui/widgets/chat/renderers/skill.py +564 -0
- chrys/app/tui/widgets/chat/renderers/sleep.py +287 -0
- chrys/app/tui/widgets/chat/renderers/sub_agent.py +1385 -0
- chrys/app/tui/widgets/chat/renderers/todo.py +114 -0
- chrys/app/tui/widgets/chat/renderers/web.py +69 -0
- chrys/app/tui/widgets/chat/replay.py +1605 -0
- chrys/app/tui/widgets/chat/replay_mount.py +322 -0
- chrys/app/tui/widgets/chat/scroll_controller.py +579 -0
- chrys/app/tui/widgets/chat/selection_controller.py +435 -0
- chrys/app/tui/widgets/chat/session_json.py +508 -0
- chrys/app/tui/widgets/chat/toc_model.py +156 -0
- chrys/app/tui/widgets/chat/tool_call.py +2478 -0
- chrys/app/tui/widgets/chat/tool_registry.py +753 -0
- chrys/app/tui/widgets/chat/tool_renderers.py +247 -0
- chrys/app/tui/widgets/chat/tool_view_builders.py +260 -0
- chrys/app/tui/widgets/chat/transcript_reader.py +57 -0
- chrys/app/tui/widgets/checkbox.py +24 -0
- chrys/app/tui/widgets/chrome/__init__.py +3 -0
- chrys/app/tui/widgets/chrome/app_header.py +283 -0
- chrys/app/tui/widgets/chrome/commands.py +95 -0
- chrys/app/tui/widgets/chrome/file_index.py +68 -0
- chrys/app/tui/widgets/chrome/file_scanner.py +670 -0
- chrys/app/tui/widgets/chrome/footer.py +284 -0
- chrys/app/tui/widgets/chrome/image_paste.py +351 -0
- chrys/app/tui/widgets/chrome/input_bar.py +1299 -0
- chrys/app/tui/widgets/chrome/status_bar.py +911 -0
- chrys/app/tui/widgets/chrome/suggestion_list.py +652 -0
- chrys/app/tui/widgets/click_affordance.py +24 -0
- chrys/app/tui/widgets/color_picker/__init__.py +254 -0
- chrys/app/tui/widgets/color_picker/controls.py +171 -0
- chrys/app/tui/widgets/color_picker/model.py +89 -0
- chrys/app/tui/widgets/dialog_buttons.py +58 -0
- chrys/app/tui/widgets/dialog_scroll.py +24 -0
- chrys/app/tui/widgets/diff_view/__init__.py +20 -0
- chrys/app/tui/widgets/diff_view/cells.py +59 -0
- chrys/app/tui/widgets/diff_view/code.py +280 -0
- chrys/app/tui/widgets/diff_view/compute.py +286 -0
- chrys/app/tui/widgets/diff_view/gutter.py +161 -0
- chrys/app/tui/widgets/diff_view/inline.py +77 -0
- chrys/app/tui/widgets/diff_view/palette.py +87 -0
- chrys/app/tui/widgets/diff_view/protocols.py +24 -0
- chrys/app/tui/widgets/diff_view/rows.py +138 -0
- chrys/app/tui/widgets/diff_view/unified.py +267 -0
- chrys/app/tui/widgets/diff_view/widget.py +209 -0
- chrys/app/tui/widgets/editor/__init__.py +79 -0
- chrys/app/tui/widgets/editor/coordinates.py +30 -0
- chrys/app/tui/widgets/editor/highlighter.py +139 -0
- chrys/app/tui/widgets/editor/keymaps.py +357 -0
- chrys/app/tui/widgets/editor/types.py +216 -0
- chrys/app/tui/widgets/editor/vim.py +1195 -0
- chrys/app/tui/widgets/editor/widget.py +401 -0
- chrys/app/tui/widgets/file_preview.py +58 -0
- chrys/app/tui/widgets/hatch.py +138 -0
- chrys/app/tui/widgets/input.py +66 -0
- chrys/app/tui/widgets/loading.py +125 -0
- chrys/app/tui/widgets/markdown/__init__.py +25 -0
- chrys/app/tui/widgets/markdown/_utils.py +21 -0
- chrys/app/tui/widgets/markdown/anchors.py +71 -0
- chrys/app/tui/widgets/markdown/blocks.py +115 -0
- chrys/app/tui/widgets/markdown/copyable.py +163 -0
- chrys/app/tui/widgets/markdown/diagram/__init__.py +35 -0
- chrys/app/tui/widgets/markdown/diagram/canvas.py +409 -0
- chrys/app/tui/widgets/markdown/diagram/charts.py +52 -0
- chrys/app/tui/widgets/markdown/diagram/diagnostics.py +101 -0
- chrys/app/tui/widgets/markdown/diagram/geometry.py +46 -0
- chrys/app/tui/widgets/markdown/diagram/layout.py +494 -0
- chrys/app/tui/widgets/markdown/diagram/messages.py +18 -0
- chrys/app/tui/widgets/markdown/diagram/model.py +275 -0
- chrys/app/tui/widgets/markdown/diagram/parser.py +173 -0
- chrys/app/tui/widgets/markdown/diagram/parsers/__init__.py +3 -0
- chrys/app/tui/widgets/markdown/diagram/parsers/charts.py +349 -0
- chrys/app/tui/widgets/markdown/diagram/parsers/common.py +403 -0
- chrys/app/tui/widgets/markdown/diagram/parsers/graphs.py +1072 -0
- chrys/app/tui/widgets/markdown/diagram/parsers/planning.py +317 -0
- chrys/app/tui/widgets/markdown/diagram/parsers/schedule.py +298 -0
- chrys/app/tui/widgets/markdown/diagram/parsers/schemas.py +241 -0
- chrys/app/tui/widgets/markdown/diagram/parsers/structure.py +221 -0
- chrys/app/tui/widgets/markdown/diagram/presentation.py +32 -0
- chrys/app/tui/widgets/markdown/diagram/renderers/__init__.py +3 -0
- chrys/app/tui/widgets/markdown/diagram/renderers/charts.py +275 -0
- chrys/app/tui/widgets/markdown/diagram/renderers/common.py +73 -0
- chrys/app/tui/widgets/markdown/diagram/renderers/planning.py +157 -0
- chrys/app/tui/widgets/markdown/diagram/renderers/schedule.py +202 -0
- chrys/app/tui/widgets/markdown/diagram/renderers/structure.py +77 -0
- chrys/app/tui/widgets/markdown/diagram/renderers/xy.py +385 -0
- chrys/app/tui/widgets/markdown/diagram/router.py +651 -0
- chrys/app/tui/widgets/markdown/diagram/specs/__init__.py +3 -0
- chrys/app/tui/widgets/markdown/diagram/specs/charts.py +94 -0
- chrys/app/tui/widgets/markdown/diagram/specs/planning.py +68 -0
- chrys/app/tui/widgets/markdown/diagram/specs/schedule.py +65 -0
- chrys/app/tui/widgets/markdown/diagram/specs/structure.py +23 -0
- chrys/app/tui/widgets/markdown/diagram/viewer.py +92 -0
- chrys/app/tui/widgets/markdown/links.py +47 -0
- chrys/app/tui/widgets/markdown/math/__init__.py +36 -0
- chrys/app/tui/widgets/markdown/math/layout.py +739 -0
- chrys/app/tui/widgets/markdown/math/markdown.py +291 -0
- chrys/app/tui/widgets/markdown/math/parser.py +325 -0
- chrys/app/tui/widgets/markdown/math/symbols.py +325 -0
- chrys/app/tui/widgets/markdown/navigator.py +80 -0
- chrys/app/tui/widgets/markdown/parser.py +1057 -0
- chrys/app/tui/widgets/markdown/stream.py +73 -0
- chrys/app/tui/widgets/markdown/toc.py +98 -0
- chrys/app/tui/widgets/markdown/viewer.py +146 -0
- chrys/app/tui/widgets/markdown/widget.py +2046 -0
- chrys/app/tui/widgets/marquee.py +101 -0
- chrys/app/tui/widgets/option_menu.py +82 -0
- chrys/app/tui/widgets/page_navigator.py +118 -0
- chrys/app/tui/widgets/select.py +196 -0
- chrys/app/tui/widgets/selection.py +59 -0
- chrys/app/tui/widgets/sidebar/__init__.py +3 -0
- chrys/app/tui/widgets/sidebar/buddy.py +367 -0
- chrys/app/tui/widgets/sidebar/context.py +482 -0
- chrys/app/tui/widgets/sidebar/debug.py +195 -0
- chrys/app/tui/widgets/sidebar/empty_state.py +11 -0
- chrys/app/tui/widgets/sidebar/panel.py +198 -0
- chrys/app/tui/widgets/sidebar/tasks.py +198 -0
- chrys/app/tui/widgets/sidebar/toc.py +166 -0
- chrys/app/tui/widgets/sidebar/toc_types.py +30 -0
- chrys/app/tui/widgets/syntax_theme.py +85 -0
- chrys/app/tui/widgets/text_area.py +258 -0
- chrys/app/tui/widgets/trajectory/__init__.py +8 -0
- chrys/app/tui/widgets/trajectory/chartkit.py +264 -0
- chrys/app/tui/widgets/trajectory/insights.py +1266 -0
- chrys/app/tui/widgets/trajectory/overview.py +1101 -0
- chrys/app/tui/widgets/trajectory/panel.py +983 -0
- chrys/app/tui/widgets/trajectory/presentation.py +311 -0
- chrys/app/tui/widgets/trajectory/session_info.py +124 -0
- chrys/app/tui/widgets/trajectory/text_view.py +124 -0
- chrys/app/tui/widgets/trajectory/timeline.py +380 -0
- chrys/app/tui/widgets/welcome.py +126 -0
- chrys/app/tui/widgets/workflow/__init__.py +5 -0
- chrys/app/tui/widgets/workflow/edges.py +89 -0
- chrys/app/tui/widgets/workflow/graph.py +869 -0
- chrys/app/tui/widgets/workflow/info.py +310 -0
- chrys/app/tui/widgets/workflow/node_view.py +27 -0
- chrys/app/tui/widgets/workflow/output.py +225 -0
- chrys/app/tui/widgets/workflow/panel.py +658 -0
- chrys/app/tui/widgets/workflow/projector.py +324 -0
- chrys/app/tui/widgets/workflow/records.py +69 -0
- chrys/app/tui/widgets/workflow/scrollbar.py +82 -0
- chrys/app/tui/widgets/workflow/selection.py +151 -0
- chrys/app/tui/widgets/workflow/source.py +65 -0
- chrys/app/tui/widgets/workflow/text.py +257 -0
- chrys/app/tui/widgets/workflow/values.py +317 -0
- chrys/foundation/__init__.py +0 -0
- chrys/foundation/branding.py +15 -0
- chrys/foundation/config/__init__.py +7 -0
- chrys/foundation/config/coercion.py +374 -0
- chrys/foundation/config/context.py +34 -0
- chrys/foundation/config/env_file.py +141 -0
- chrys/foundation/config/env_layers.py +370 -0
- chrys/foundation/config/migrations.py +521 -0
- chrys/foundation/config/notification_events.py +22 -0
- chrys/foundation/config/process_settings.py +332 -0
- chrys/foundation/config/runtime_pointer.py +133 -0
- chrys/foundation/config/settings.py +1952 -0
- chrys/foundation/config/settings_store.py +996 -0
- chrys/foundation/config/spec.py +396 -0
- chrys/foundation/config/user_settings.py +140 -0
- chrys/foundation/config/warnings.py +262 -0
- chrys/foundation/config/web_values.py +135 -0
- chrys/foundation/config/yaml_store.py +487 -0
- chrys/foundation/errors/__init__.py +68 -0
- chrys/foundation/errors/_legacy.py +117 -0
- chrys/foundation/errors/_text.py +13 -0
- chrys/foundation/errors/_walk.py +85 -0
- chrys/foundation/errors/classify.py +278 -0
- chrys/foundation/errors/display.py +274 -0
- chrys/foundation/errors/formatting.py +283 -0
- chrys/foundation/errors/kinds.py +67 -0
- chrys/foundation/errors/network.py +497 -0
- chrys/foundation/errors/provider.py +445 -0
- chrys/foundation/errors/route.py +85 -0
- chrys/foundation/events/__init__.py +8 -0
- chrys/foundation/events/bus.py +143 -0
- chrys/foundation/events/types.py +1629 -0
- chrys/foundation/events/workflow.py +38 -0
- chrys/foundation/hosted_tools.py +142 -0
- chrys/foundation/i18n/__init__.py +32 -0
- chrys/foundation/i18n/_catalogs/zh-Hans/LC_MESSAGES/chrys.mo +0 -0
- chrys/foundation/i18n/catalogs.py +42 -0
- chrys/foundation/i18n/formatting.py +202 -0
- chrys/foundation/i18n/locale.py +92 -0
- chrys/foundation/i18n/localizer.py +187 -0
- chrys/foundation/i18n/messages.py +268 -0
- chrys/foundation/io/__init__.py +3 -0
- chrys/foundation/io/result_content.py +237 -0
- chrys/foundation/models/__init__.py +3 -0
- chrys/foundation/models/approval_reuse.py +23 -0
- chrys/foundation/models/ask_user.py +468 -0
- chrys/foundation/models/execution.py +18 -0
- chrys/foundation/models/history_markers.py +115 -0
- chrys/foundation/models/invocations.py +63 -0
- chrys/foundation/models/mutation_scope.py +28 -0
- chrys/foundation/models/session_env.py +87 -0
- chrys/foundation/models/session_surface.py +29 -0
- chrys/foundation/models/todos.py +74 -0
- chrys/foundation/models/turns.py +125 -0
- chrys/foundation/models/workflow_session.py +89 -0
- chrys/foundation/models/workspace.py +59 -0
- chrys/foundation/net/__init__.py +3 -0
- chrys/foundation/net/address_class.py +57 -0
- chrys/foundation/net/route_probe.py +94 -0
- chrys/foundation/net/url.py +107 -0
- chrys/foundation/observability/__init__.py +3 -0
- chrys/foundation/observability/exporters.py +174 -0
- chrys/foundation/observability/gate.py +31 -0
- chrys/foundation/observability/setup.py +497 -0
- chrys/foundation/observability/sink.py +228 -0
- chrys/foundation/patches/__init__.py +19 -0
- chrys/foundation/patches/mdurl_cache.py +59 -0
- chrys/foundation/patches/patcher.py +287 -0
- chrys/foundation/patches/staged_members.py +205 -0
- chrys/foundation/patches/textual_block_border.py +105 -0
- chrys/foundation/patches/textual_button_ansi.py +65 -0
- chrys/foundation/patches/textual_button_ansi_old.txt +68 -0
- chrys/foundation/patches/textual_callback_cache.py +248 -0
- chrys/foundation/patches/textual_callback_dispatch.py +109 -0
- chrys/foundation/patches/textual_compositor_cjk.py +566 -0
- chrys/foundation/patches/textual_dispatch_cache.py +150 -0
- chrys/foundation/patches/textual_ime_cursor_anchor.py +92 -0
- chrys/foundation/patches/textual_kitty_keyboard.py +268 -0
- chrys/foundation/patches/textual_lru_acyclic.py +241 -0
- chrys/foundation/patches/textual_message_pump.py +136 -0
- chrys/foundation/patches/textual_node_diet.py +875 -0
- chrys/foundation/patches/textual_one_shot_timer.py +48 -0
- chrys/foundation/patches/textual_option_list.py +90 -0
- chrys/foundation/patches/textual_precompose.py +89 -0
- chrys/foundation/patches/textual_pruned_tabs.py +69 -0
- chrys/foundation/patches/textual_reflow_reuse.py +1753 -0
- chrys/foundation/patches/textual_removed_node_caches.py +86 -0
- chrys/foundation/patches/textual_removed_screen_callbacks.py +55 -0
- chrys/foundation/patches/textual_selection_extract.py +48 -0
- chrys/foundation/patches/textual_strip_cycles.py +119 -0
- chrys/foundation/patches/textual_tab_selection.py +1611 -0
- chrys/foundation/patches/textual_timer_skip.py +70 -0
- chrys/foundation/patches/textual_utf8_decoder.py +106 -0
- chrys/foundation/patches/textual_win_sleep.py +167 -0
- chrys/foundation/patches/watchdog_fsevents.py +70 -0
- chrys/foundation/patches/watchdog_windows.py +52 -0
- chrys/foundation/platform/__init__.py +556 -0
- chrys/foundation/platform/c_api.py +32 -0
- chrys/foundation/platform/child_reap.py +107 -0
- chrys/foundation/platform/command_line.py +95 -0
- chrys/foundation/platform/files.py +1470 -0
- chrys/foundation/platform/output_capture.py +113 -0
- chrys/foundation/platform/paths.py +193 -0
- chrys/foundation/platform/process.py +1468 -0
- chrys/foundation/platform/pty_output.py +19 -0
- chrys/foundation/platform/runtime_paths.py +281 -0
- chrys/foundation/platform/win_console.py +129 -0
- chrys/foundation/reasoning_origin.py +67 -0
- chrys/foundation/recovery.py +16 -0
- chrys/foundation/retry.py +278 -0
- chrys/foundation/text/__init__.py +3 -0
- chrys/foundation/text/encoding.py +603 -0
- chrys/foundation/text/images.py +304 -0
- chrys/foundation/text/lines.py +24 -0
- chrys/foundation/text/mentions.py +90 -0
- chrys/foundation/text/model_json.py +25 -0
- chrys/foundation/text/reading_order.py +20 -0
- chrys/foundation/text/tokenizer.py +25 -0
- chrys/foundation/text/tool_output.py +287 -0
- chrys/foundation/text/yaml_io.py +62 -0
- chrys/foundation/tool_call_context.py +202 -0
- chrys/foundation/tool_execution_stamp.py +184 -0
- chrys/foundation/tool_invocation_order.py +48 -0
- chrys/foundation/tool_kinds.py +102 -0
- chrys/foundation/tool_result_metadata.py +287 -0
- chrys/foundation/trajectory/__init__.py +10 -0
- chrys/foundation/trajectory/context.py +481 -0
- chrys/foundation/trajectory/envelope.py +571 -0
- chrys/foundation/trajectory/event_types.py +294 -0
- chrys/foundation/trajectory/finalizers.py +46 -0
- chrys/foundation/trajectory/fingerprint.py +62 -0
- chrys/foundation/trajectory/ids.py +155 -0
- chrys/foundation/trajectory/keys.py +99 -0
- chrys/foundation/trajectory/lease.py +173 -0
- chrys/foundation/trajectory/metadata.py +72 -0
- chrys/foundation/trajectory/reader.py +271 -0
- chrys/foundation/trajectory/recovery.py +225 -0
- chrys/foundation/trajectory/revisions.py +152 -0
- chrys/foundation/trajectory/segments.py +225 -0
- chrys/foundation/trajectory/tools.py +117 -0
- chrys/foundation/trajectory/usage.py +151 -0
- chrys/foundation/trajectory/writer.py +972 -0
- chrys/foundation/trajectory_timing.py +97 -0
- chrys/foundation/util/__init__.py +3 -0
- chrys/foundation/util/async_tasks.py +29 -0
- chrys/foundation/util/chrys_headers.py +23 -0
- chrys/foundation/util/env_templates.py +104 -0
- chrys/foundation/util/filenames.py +96 -0
- chrys/foundation/util/header_charset.py +138 -0
- chrys/foundation/util/httpx_helpers.py +12 -0
- chrys/foundation/util/lock.py +236 -0
- chrys/foundation/util/once_close.py +46 -0
- chrys/foundation/util/session_ids.py +29 -0
- chrys/foundation/util/shell_tokens.py +88 -0
- chrys/foundation/util/sub_agent_context.py +38 -0
- chrys/foundation/util/time.py +35 -0
- chrys/foundation/util/unicode_scalars.py +36 -0
- chrys/foundation/vendor/__init__.py +43 -0
- chrys/foundation/vendor/ripgrep/rg-aarch64-apple-darwin +0 -0
- chrys/foundation/vendor/ripgrep/rg-aarch64-pc-windows-msvc.exe +0 -0
- chrys/foundation/vendor/ripgrep/rg-aarch64-unknown-linux-gnu +0 -0
- chrys/foundation/vendor/ripgrep/rg-x86_64-apple-darwin +0 -0
- chrys/foundation/vendor/ripgrep/rg-x86_64-pc-windows-msvc.exe +0 -0
- chrys/foundation/vendor/ripgrep/rg-x86_64-unknown-linux-musl +0 -0
- chrys/kernel/__init__.py +256 -0
- chrys/kernel/_content.py +1866 -0
- chrys/kernel/_loop_recorder.py +631 -0
- chrys/kernel/_null_overlay.py +1026 -0
- chrys/kernel/_result_ceiling.py +216 -0
- chrys/kernel/_serialization.py +431 -0
- chrys/kernel/_tool_arg_errors.py +1629 -0
- chrys/kernel/_tool_execution.py +1172 -0
- chrys/kernel/_tool_expansion.py +26 -0
- chrys/kernel/_types.py +2598 -0
- chrys/kernel/agent.py +994 -0
- chrys/kernel/client.py +1084 -0
- chrys/kernel/compaction.py +1315 -0
- chrys/kernel/exceptions.py +211 -0
- chrys/kernel/exchanges.py +683 -0
- chrys/kernel/identity.py +95 -0
- chrys/kernel/images.py +36 -0
- chrys/kernel/instrumentation.py +1618 -0
- chrys/kernel/loop.py +2308 -0
- chrys/kernel/middleware.py +616 -0
- chrys/kernel/sessions.py +604 -0
- chrys/kernel/tools.py +1061 -0
- chrys/kernel/types.py +126 -0
- chrys/orchestration/__init__.py +3 -0
- chrys/orchestration/engine/__init__.py +3 -0
- chrys/orchestration/engine/assembly.py +236 -0
- chrys/orchestration/engine/build/__init__.py +3 -0
- chrys/orchestration/engine/build/builder.py +1061 -0
- chrys/orchestration/engine/build/construction.py +408 -0
- chrys/orchestration/engine/build/loaded.py +139 -0
- chrys/orchestration/engine/engine.py +789 -0
- chrys/orchestration/engine/execution.py +771 -0
- chrys/orchestration/engine/loader.py +865 -0
- chrys/orchestration/engine/rollback.py +918 -0
- chrys/orchestration/engine/run/__init__.py +3 -0
- chrys/orchestration/engine/run/active_injection.py +419 -0
- chrys/orchestration/engine/run/attachments.py +519 -0
- chrys/orchestration/engine/run/bindings.py +1095 -0
- chrys/orchestration/engine/run/coordinator.py +1062 -0
- chrys/orchestration/engine/run/finalizer.py +417 -0
- chrys/orchestration/engine/run/input_refs.py +60 -0
- chrys/orchestration/engine/run/prompt_content.py +457 -0
- chrys/orchestration/engine/run/resume.py +299 -0
- chrys/orchestration/engine/run/retry.py +948 -0
- chrys/orchestration/engine/run/runner.py +625 -0
- chrys/orchestration/engine/run/runtime_skills.py +146 -0
- chrys/orchestration/engine/run/sub_agent_coordination.py +126 -0
- chrys/orchestration/engine/run/turn_hooks.py +258 -0
- chrys/orchestration/engine/run/turn_state.py +149 -0
- chrys/orchestration/engine/run/working_dir.py +50 -0
- chrys/orchestration/engine/session_lifecycle.py +2013 -0
- chrys/orchestration/engine/state/__init__.py +3 -0
- chrys/orchestration/engine/state/active_session.py +183 -0
- chrys/orchestration/engine/state/controls.py +639 -0
- chrys/orchestration/engine/state/current_agent.py +26 -0
- chrys/orchestration/engine/state/lifecycle_permits.py +395 -0
- chrys/orchestration/engine/state/machine.py +193 -0
- chrys/orchestration/engine/state/session_writer.py +434 -0
- chrys/orchestration/engine/trajectory.py +714 -0
- chrys/orchestration/engine/usage.py +118 -0
- chrys/orchestration/invoker/__init__.py +3 -0
- chrys/orchestration/invoker/acp.py +727 -0
- chrys/orchestration/invoker/acp_protocol.py +1115 -0
- chrys/orchestration/invoker/acp_spec.py +79 -0
- chrys/orchestration/invoker/attempts.py +994 -0
- chrys/orchestration/invoker/child_compaction.py +131 -0
- chrys/orchestration/invoker/child_history.py +99 -0
- chrys/orchestration/invoker/contracts.py +253 -0
- chrys/orchestration/invoker/evidence.py +94 -0
- chrys/orchestration/invoker/kernel.py +343 -0
- chrys/orchestration/invoker/origin.py +79 -0
- chrys/orchestration/invoker/resources.py +343 -0
- chrys/orchestration/invoker/runtime.py +299 -0
- chrys/orchestration/invoker/usage.py +80 -0
- chrys/orchestration/session_hooks.py +117 -0
- chrys/orchestration/session_host.py +1023 -0
- chrys/orchestration/session_resources.py +95 -0
- chrys/orchestration/session_usage.py +219 -0
- chrys/orchestration/startup.py +255 -0
- chrys/orchestration/sub_agents/__init__.py +3 -0
- chrys/orchestration/sub_agents/acp_policy.py +269 -0
- chrys/orchestration/sub_agents/kernel_policy.py +848 -0
- chrys/orchestration/sub_agents/registration.py +44 -0
- chrys/orchestration/sub_agents/shell.py +337 -0
- chrys/orchestration/sub_agents/tools.py +2228 -0
- chrys/orchestration/workflows/__init__.py +3 -0
- chrys/orchestration/workflows/agent_archive.py +156 -0
- chrys/orchestration/workflows/agent_node.py +894 -0
- chrys/orchestration/workflows/agent_node_build.py +687 -0
- chrys/orchestration/workflows/catalog.py +332 -0
- chrys/orchestration/workflows/coordinator.py +771 -0
- chrys/orchestration/workflows/hooks.py +176 -0
- chrys/orchestration/workflows/preview.py +322 -0
- chrys/orchestration/workflows/rollback.py +151 -0
- chrys/orchestration/workflows/runner.py +986 -0
- chrys/orchestration/workflows/session.py +390 -0
- chrys/orchestration/workflows/settings.py +97 -0
- chrys/orchestration/workflows/validation.py +674 -0
- chrys/orchestration/workflows/worker_client.py +1002 -0
- chrys/service/__init__.py +3 -0
- chrys/service/acp_client/__init__.py +65 -0
- chrys/service/acp_client/_transport.py +922 -0
- chrys/service/acp_client/client.py +1311 -0
- chrys/service/acp_client/errors.py +224 -0
- chrys/service/acp_client/protocol.py +220 -0
- chrys/service/acp_client/spawn.py +239 -0
- chrys/service/acp_client/spec.py +100 -0
- chrys/service/agent_middleware/__init__.py +60 -0
- chrys/service/agent_middleware/_metadata_keys.py +52 -0
- chrys/service/agent_middleware/control/__init__.py +3 -0
- chrys/service/agent_middleware/control/approval.py +769 -0
- chrys/service/agent_middleware/control/approval_hooks.py +62 -0
- chrys/service/agent_middleware/control/ask_user.py +207 -0
- chrys/service/agent_middleware/control/interrupt.py +50 -0
- chrys/service/agent_middleware/control/sleep.py +118 -0
- chrys/service/agent_middleware/control/todo.py +117 -0
- chrys/service/agent_middleware/events/__init__.py +3 -0
- chrys/service/agent_middleware/events/hook_dispatch.py +250 -0
- chrys/service/agent_middleware/events/hosted_tools.py +1762 -0
- chrys/service/agent_middleware/events/intermediate_text.py +128 -0
- chrys/service/agent_middleware/events/rejection_metadata.py +50 -0
- chrys/service/agent_middleware/events/result_persistence.py +98 -0
- chrys/service/agent_middleware/events/sub_agent_events.py +951 -0
- chrys/service/agent_middleware/events/tool_error_text.py +22 -0
- chrys/service/agent_middleware/events/tool_events.py +779 -0
- chrys/service/agent_middleware/injection.py +510 -0
- chrys/service/agent_middleware/reminders/__init__.py +91 -0
- chrys/service/agent_middleware/reminders/archive_pointer.py +154 -0
- chrys/service/agent_middleware/reminders/base.py +25 -0
- chrys/service/agent_middleware/reminders/context_usage.py +74 -0
- chrys/service/agent_middleware/reminders/file_change.py +63 -0
- chrys/service/agent_middleware/reminders/mcp.py +39 -0
- chrys/service/agent_middleware/reminders/profile_switch.py +106 -0
- chrys/service/agent_middleware/reminders/runtime_env.py +190 -0
- chrys/service/agent_middleware/reminders/skills.py +44 -0
- chrys/service/agent_middleware/reminders/sub_agents.py +35 -0
- chrys/service/agent_middleware/reminders/todo.py +35 -0
- chrys/service/agent_middleware/reminders/turn_line.py +48 -0
- chrys/service/agent_middleware/response_validation.py +1380 -0
- chrys/service/agent_middleware/system_reminder.py +1107 -0
- chrys/service/agent_middleware/validators.py +396 -0
- chrys/service/analytics/__init__.py +124 -0
- chrys/service/analytics/_actions.py +896 -0
- chrys/service/analytics/_context_evidence.py +357 -0
- chrys/service/analytics/_critical_path.py +179 -0
- chrys/service/analytics/_facts.py +919 -0
- chrys/service/analytics/_insights.py +769 -0
- chrys/service/analytics/_metric_ops.py +83 -0
- chrys/service/analytics/_session_projection.py +460 -0
- chrys/service/analytics/_timeline.py +434 -0
- chrys/service/analytics/_turn_graph.py +1237 -0
- chrys/service/analytics/_turns.py +1377 -0
- chrys/service/analytics/_workflows.py +171 -0
- chrys/service/analytics/aggregation.py +1474 -0
- chrys/service/analytics/classification.py +128 -0
- chrys/service/analytics/export.py +803 -0
- chrys/service/analytics/findings.py +282 -0
- chrys/service/analytics/math.py +79 -0
- chrys/service/analytics/model.py +886 -0
- chrys/service/analytics/reader.py +321 -0
- chrys/service/approval/__init__.py +3 -0
- chrys/service/approval/arbitration.py +102 -0
- chrys/service/approval/command_identity.py +109 -0
- chrys/service/approval/correlation.py +57 -0
- chrys/service/approval/grant_store.py +108 -0
- chrys/service/approval/judge.py +589 -0
- chrys/service/approval/level.py +15 -0
- chrys/service/approval/policy.py +209 -0
- chrys/service/approval/reuse.py +223 -0
- chrys/service/approval/reuse_binding.py +133 -0
- chrys/service/approval/safety_classifier.py +536 -0
- chrys/service/approval/turn_context.py +49 -0
- chrys/service/context/__init__.py +3 -0
- chrys/service/context/compaction/__init__.py +38 -0
- chrys/service/context/compaction/breaker.py +156 -0
- chrys/service/context/compaction/budgets.py +93 -0
- chrys/service/context/compaction/calibration.py +77 -0
- chrys/service/context/compaction/compression.py +690 -0
- chrys/service/context/compaction/current_turn_drop.py +458 -0
- chrys/service/context/compaction/events.py +201 -0
- chrys/service/context/compaction/exclusions.py +261 -0
- chrys/service/context/compaction/groups.py +361 -0
- chrys/service/context/compaction/last_words.py +1996 -0
- chrys/service/context/compaction/last_words_state.py +752 -0
- chrys/service/context/compaction/scoped.py +472 -0
- chrys/service/context/compaction/spill.py +1947 -0
- chrys/service/context/compaction/strategy.py +1116 -0
- chrys/service/context/compaction/summaries.py +319 -0
- chrys/service/context/compaction/turns.py +375 -0
- chrys/service/context/manager.py +174 -0
- chrys/service/context/memory_loader.py +792 -0
- chrys/service/context/middleware/__init__.py +3 -0
- chrys/service/context/middleware/usage.py +332 -0
- chrys/service/context/providers/__init__.py +3 -0
- chrys/service/context/providers/context_management.py +432 -0
- chrys/service/context/providers/history.py +647 -0
- chrys/service/context/providers/memory.py +50 -0
- chrys/service/context/tool_content.py +22 -0
- chrys/service/hooks/__init__.py +37 -0
- chrys/service/hooks/detached_worker.py +118 -0
- chrys/service/hooks/docs/README.md +14 -0
- chrys/service/hooks/docs/authoring.md +684 -0
- chrys/service/hooks/docs/configuration.md +499 -0
- chrys/service/hooks/docs/design.md +359 -0
- chrys/service/hooks/docs/project-hooks.md +348 -0
- chrys/service/hooks/events.py +157 -0
- chrys/service/hooks/loader.py +665 -0
- chrys/service/hooks/manager.py +807 -0
- chrys/service/hooks/matcher.py +111 -0
- chrys/service/hooks/outbox.py +294 -0
- chrys/service/hooks/runner.py +572 -0
- chrys/service/hooks/schema.py +407 -0
- chrys/service/llm/__init__.py +7 -0
- chrys/service/llm/_structured_outputs.py +192 -0
- chrys/service/llm/anthropic_messages/__init__.py +9 -0
- chrys/service/llm/anthropic_messages/client.py +254 -0
- chrys/service/llm/anthropic_messages/decode.py +331 -0
- chrys/service/llm/anthropic_messages/history.py +279 -0
- chrys/service/llm/anthropic_messages/request.py +323 -0
- chrys/service/llm/anthropic_messages/server_tools.py +319 -0
- chrys/service/llm/anthropic_messages/stream.py +297 -0
- chrys/service/llm/anthropic_messages/thinking_binding.py +156 -0
- chrys/service/llm/chat_completions/__init__.py +9 -0
- chrys/service/llm/chat_completions/client.py +369 -0
- chrys/service/llm/chat_completions/decode.py +338 -0
- chrys/service/llm/chat_completions/history.py +657 -0
- chrys/service/llm/chat_completions/reasoning.py +244 -0
- chrys/service/llm/chat_completions/request.py +192 -0
- chrys/service/llm/chat_completions/stream.py +546 -0
- chrys/service/llm/chat_completions/validation.py +308 -0
- chrys/service/llm/clients.py +613 -0
- chrys/service/llm/images.py +65 -0
- chrys/service/llm/mock.py +413 -0
- chrys/service/llm/observer.py +446 -0
- chrys/service/llm/one_shot.py +106 -0
- chrys/service/llm/openai_exceptions.py +93 -0
- chrys/service/llm/openai_responses/__init__.py +10 -0
- chrys/service/llm/openai_responses/client.py +323 -0
- chrys/service/llm/openai_responses/decode.py +432 -0
- chrys/service/llm/openai_responses/history.py +519 -0
- chrys/service/llm/openai_responses/hosted.py +625 -0
- chrys/service/llm/openai_responses/replay.py +629 -0
- chrys/service/llm/openai_responses/request.py +342 -0
- chrys/service/llm/openai_responses/stream.py +847 -0
- chrys/service/llm/openai_timestamps.py +57 -0
- chrys/service/llm/providers.py +107 -0
- chrys/service/llm/proxy_route.py +54 -0
- chrys/service/llm/raw_http_log.py +309 -0
- chrys/service/llm/route_facts.py +63 -0
- chrys/service/llm/route_sessions.py +49 -0
- chrys/service/llm/sdk_anthropic.py +18 -0
- chrys/service/llm/sdk_headers.py +47 -0
- chrys/service/llm/sdk_openai.py +18 -0
- chrys/service/llm/sdk_retry.py +59 -0
- chrys/service/llm/wire_client.py +246 -0
- chrys/service/mcp/__init__.py +3 -0
- chrys/service/mcp/_connection.py +235 -0
- chrys/service/mcp/_http_transport.py +350 -0
- chrys/service/mcp/_progressive.py +459 -0
- chrys/service/mcp/_stdio_transport.py +614 -0
- chrys/service/mcp/_tool_mixins.py +96 -0
- chrys/service/mcp/adapter.py +1031 -0
- chrys/service/mcp/cache.py +476 -0
- chrys/service/mcp/content.py +32 -0
- chrys/service/mcp/errors.py +169 -0
- chrys/service/mcp/owned.py +1330 -0
- chrys/service/mcp/result_limits.py +168 -0
- chrys/service/mcp/thinking_warning.py +95 -0
- chrys/service/mcp/validation.py +74 -0
- chrys/service/mutations/__init__.py +84 -0
- chrys/service/mutations/coordination.py +894 -0
- chrys/service/mutations/detector.py +458 -0
- chrys/service/mutations/git_calibrator.py +397 -0
- chrys/service/mutations/git_state.py +647 -0
- chrys/service/mutations/pipeline.py +779 -0
- chrys/service/mutations/scanner.py +466 -0
- chrys/service/mutations/snapshot_files.py +233 -0
- chrys/service/mutations/store.py +625 -0
- chrys/service/mutations/tool_names.py +15 -0
- chrys/service/mutations/trace.py +246 -0
- chrys/service/mutations/tracker.py +1289 -0
- chrys/service/mutations/types.py +559 -0
- chrys/service/mutations/workspace_changes.py +1583 -0
- chrys/service/profiles/__init__.py +2 -0
- chrys/service/profiles/agents/__init__.py +3 -0
- chrys/service/profiles/agents/builtins/Code.yaml +199 -0
- chrys/service/profiles/agents/builtins/Explore.yaml +62 -0
- chrys/service/profiles/agents/builtins/General.yaml +114 -0
- chrys/service/profiles/agents/builtins/QA.yaml +128 -0
- chrys/service/profiles/agents/loader.py +808 -0
- chrys/service/profiles/agents/registry.py +727 -0
- chrys/service/profiles/agents/schema.py +371 -0
- chrys/service/profiles/agents/serializer.py +196 -0
- chrys/service/profiles/coercion.py +22 -0
- chrys/service/profiles/models/__init__.py +3 -0
- chrys/service/profiles/models/env_bridge.py +157 -0
- chrys/service/profiles/models/loader.py +282 -0
- chrys/service/profiles/models/options.py +438 -0
- chrys/service/profiles/models/registry.py +104 -0
- chrys/service/profiles/models/resolver.py +286 -0
- chrys/service/profiles/models/schema.py +91 -0
- chrys/service/profiles/models/serializer.py +76 -0
- chrys/service/session/__init__.py +3 -0
- chrys/service/session/checkpoint.py +156 -0
- chrys/service/session/history.py +1616 -0
- chrys/service/session/message_metadata.py +151 -0
- chrys/service/session/persistence.py +435 -0
- chrys/service/session/runtime_metadata.py +210 -0
- chrys/service/session/sub_agent_logs.py +1069 -0
- chrys/service/session/sub_agent_transcript.py +654 -0
- chrys/service/skills/__init__.py +3 -0
- chrys/service/skills/adapter.py +408 -0
- chrys/service/skills/constants.py +8 -0
- chrys/service/skills/loader.py +575 -0
- chrys/service/skills/model.py +130 -0
- chrys/service/skills/provider.py +841 -0
- chrys/service/skills/runner.py +390 -0
- chrys/service/state/__init__.py +3 -0
- chrys/service/state/_fork.py +710 -0
- chrys/service/state/_session_files.py +175 -0
- chrys/service/state/_session_meta.py +552 -0
- chrys/service/state/locks.py +154 -0
- chrys/service/state/serializers.py +156 -0
- chrys/service/state/session_catalog.py +361 -0
- chrys/service/state/session_listing.py +84 -0
- chrys/service/state/session_migration.py +446 -0
- chrys/service/state/session_mru.py +315 -0
- chrys/service/state/store.py +2132 -0
- chrys/service/state/workflow.py +158 -0
- chrys/service/text_blocks.py +47 -0
- chrys/service/todos/__init__.py +3 -0
- chrys/service/todos/reminder.py +31 -0
- chrys/service/todos/tracker.py +58 -0
- chrys/service/tools/__init__.py +3 -0
- chrys/service/tools/approval_targets.py +92 -0
- chrys/service/tools/builtins/__init__.py +3 -0
- chrys/service/tools/builtins/ask_user.py +326 -0
- chrys/service/tools/builtins/doc_converter/__init__.py +494 -0
- chrys/service/tools/builtins/doc_converter/artifacts.py +392 -0
- chrys/service/tools/builtins/doc_converter/parsers/__init__.py +3 -0
- chrys/service/tools/builtins/doc_converter/parsers/_table.py +34 -0
- chrys/service/tools/builtins/doc_converter/parsers/base.py +101 -0
- chrys/service/tools/builtins/doc_converter/parsers/docx.py +88 -0
- chrys/service/tools/builtins/doc_converter/parsers/pdf.py +144 -0
- chrys/service/tools/builtins/doc_converter/parsers/pptx.py +103 -0
- chrys/service/tools/builtins/doc_converter/parsers/xls.py +32 -0
- chrys/service/tools/builtins/doc_converter/parsers/xlsx.py +51 -0
- chrys/service/tools/builtins/doc_converter/registry.py +55 -0
- chrys/service/tools/builtins/filesystem.py +1071 -0
- chrys/service/tools/builtins/search.py +1265 -0
- chrys/service/tools/builtins/shell.py +967 -0
- chrys/service/tools/builtins/shell_command_filtering/__init__.py +5 -0
- chrys/service/tools/builtins/shell_command_filtering/policy.py +60 -0
- chrys/service/tools/builtins/shell_command_filtering/presets.py +152 -0
- chrys/service/tools/builtins/shell_command_filtering/readonly/__init__.py +358 -0
- chrys/service/tools/builtins/shell_command_filtering/readonly/commands.py +416 -0
- chrys/service/tools/builtins/shell_command_filtering/readonly/git.py +408 -0
- chrys/service/tools/builtins/shell_command_filtering/readonly/syntax.py +87 -0
- chrys/service/tools/builtins/shell_command_filtering/tokenizer.py +214 -0
- chrys/service/tools/builtins/shell_filter.py +24 -0
- chrys/service/tools/builtins/sleep.py +91 -0
- chrys/service/tools/builtins/todo.py +64 -0
- chrys/service/tools/builtins/web/__init__.py +6 -0
- chrys/service/tools/builtins/web/build.py +268 -0
- chrys/service/tools/builtins/web/config.py +338 -0
- chrys/service/tools/builtins/web/credentials.py +37 -0
- chrys/service/tools/builtins/web/fetch/__init__.py +3 -0
- chrys/service/tools/builtins/web/fetch/cache.py +68 -0
- chrys/service/tools/builtins/web/fetch/convert.py +56 -0
- chrys/service/tools/builtins/web/fetch/tool.py +223 -0
- chrys/service/tools/builtins/web/hosted.py +61 -0
- chrys/service/tools/builtins/web/http.py +330 -0
- chrys/service/tools/builtins/web/progress.py +18 -0
- chrys/service/tools/builtins/web/search/__init__.py +3 -0
- chrys/service/tools/builtins/web/search/exa_mcp.py +146 -0
- chrys/service/tools/builtins/web/search/html.py +152 -0
- chrys/service/tools/builtins/web/search/json_api.py +227 -0
- chrys/service/tools/builtins/web/search/providers.py +77 -0
- chrys/service/tools/builtins/web/search/tool.py +218 -0
- chrys/service/tools/builtins/web/search/types.py +28 -0
- chrys/service/tools/builtins/web/tls_identity.py +66 -0
- chrys/service/tools/kinds.py +115 -0
- chrys/service/tools/names.py +47 -0
- chrys/service/tools/registry.py +242 -0
- chrys/service/tools/result_metadata.py +103 -0
- chrys/service/tools/session_artifacts.py +196 -0
- chrys/service/tools/spill.py +218 -0
- chrys/service/tools/workspace_paths.py +81 -0
- chrys/service/trajectory/__init__.py +11 -0
- chrys/service/trajectory/approvals.py +201 -0
- chrys/service/trajectory/compaction.py +420 -0
- chrys/service/trajectory/fork.py +75 -0
- chrys/service/trajectory/hooks.py +217 -0
- chrys/service/trajectory/items.py +41 -0
- chrys/service/trajectory/preparation.py +374 -0
- chrys/service/trajectory/retries.py +95 -0
- chrys/service/trajectory/revisions.py +129 -0
- chrys/service/trajectory/segmented.py +163 -0
- chrys/service/trajectory/session.py +762 -0
- chrys/service/trajectory/state.py +83 -0
- chrys/service/trajectory/sub_agents.py +169 -0
- chrys/service/trajectory/tombstone.py +262 -0
- chrys/service/trajectory/tools.py +323 -0
- chrys/service/trajectory/validation.py +130 -0
- chrys/service/trajectory/waits.py +161 -0
- chrys/service/trajectory/workflow.py +148 -0
- chrys/service/vision.py +128 -0
- chrys/service/workflows/__init__.py +3 -0
- chrys/service/workflows/admission.py +151 -0
- chrys/service/workflows/artifacts.py +109 -0
- chrys/service/workflows/asks.py +130 -0
- chrys/service/workflows/builtins/__init__.py +12 -0
- chrys/service/workflows/builtins/demo-workflow.manifest.json +635 -0
- chrys/service/workflows/builtins/demo-workflow.py +756 -0
- chrys/service/workflows/discovery.py +554 -0
- chrys/service/workflows/environment.py +284 -0
- chrys/service/workflows/graph.py +430 -0
- chrys/service/workflows/history.py +82 -0
- chrys/service/workflows/interpreter.py +107 -0
- chrys/service/workflows/journal.py +334 -0
- chrys/service/workflows/layout.py +56 -0
- chrys/service/workflows/ledger.py +149 -0
- chrys/service/workflows/model_selection.py +18 -0
- chrys/service/workflows/orphans.py +209 -0
- chrys/service/workflows/outcomes.py +46 -0
- chrys/service/workflows/protocol.py +210 -0
- chrys/service/workflows/records.py +142 -0
- chrys/service/workflows/scheduler.py +770 -0
- chrys/service/workflows/sdk/__init__.py +51 -0
- chrys/service/workflows/sdk/_ask.py +167 -0
- chrys/service/workflows/sdk/_builder.py +781 -0
- chrys/service/workflows/sdk/_values.py +92 -0
- chrys/service/workflows/sdk_artifact.py +74 -0
- chrys/service/workflows/store.py +494 -0
- chrys/service/workflows/transcript.py +102 -0
- chrys/service/workflows/values.py +73 -0
- chrys/service/workflows/worker_host.py +1820 -0
- chrys/workflows.py +38 -0
- icode_tui-0.29.1.dist-info/METADATA +104 -0
- icode_tui-0.29.1.dist-info/RECORD +1138 -0
- icode_tui-0.29.1.dist-info/WHEEL +4 -0
- icode_tui-0.29.1.dist-info/entry_points.txt +2 -0
- icode_tui-0.29.1.dist-info/licenses/LICENSE +202 -0
- icode_tui-0.29.1.dist-info/licenses/NOTICE +1955 -0
|
@@ -0,0 +1,951 @@
|
|
|
1
|
+
# Copyright (c) Huawei Technologies Co., Ltd. 2026. All rights reserved.
|
|
2
|
+
|
|
3
|
+
"""Sub-agent event middleware — publishes InvocationToolCallStart/InvocationToolCallResult events."""
|
|
4
|
+
|
|
5
|
+
from __future__ import annotations
|
|
6
|
+
|
|
7
|
+
import asyncio
|
|
8
|
+
import contextlib
|
|
9
|
+
import time
|
|
10
|
+
from datetime import UTC, datetime
|
|
11
|
+
from typing import TYPE_CHECKING, Any
|
|
12
|
+
from uuid import uuid4
|
|
13
|
+
|
|
14
|
+
from chrys.foundation.events.types import (
|
|
15
|
+
InvocationMessage,
|
|
16
|
+
InvocationPresentationAttemptAccepted,
|
|
17
|
+
InvocationPresentationAttemptRejected,
|
|
18
|
+
InvocationProgress,
|
|
19
|
+
InvocationToolCallArgsUpdated,
|
|
20
|
+
InvocationToolCallProgress,
|
|
21
|
+
InvocationToolCallResult,
|
|
22
|
+
InvocationToolCallStart,
|
|
23
|
+
InvocationToolCallStatusUpdated,
|
|
24
|
+
ProvisionalPresentation,
|
|
25
|
+
)
|
|
26
|
+
from chrys.foundation.hosted_tools import HOSTED_TOOL_DEFAULT_KIND_BY_FAMILY, HostedToolStatus
|
|
27
|
+
from chrys.foundation.io.result_content import extract_result_images, extract_result_text
|
|
28
|
+
from chrys.foundation.platform.paths import resolve_workspace_path
|
|
29
|
+
from chrys.foundation.tool_call_context import resolve_tool_call_context
|
|
30
|
+
from chrys.foundation.tool_execution_stamp import write_execution_stamp
|
|
31
|
+
from chrys.foundation.tool_kinds import KIND_SHELL, KIND_SUB_AGENT, get_tool_kind
|
|
32
|
+
from chrys.foundation.tool_result_metadata import (
|
|
33
|
+
TOOL_ERROR_KIND_METADATA_KEY,
|
|
34
|
+
TOOL_ERRORED_METADATA_KEY,
|
|
35
|
+
tool_payload_observation,
|
|
36
|
+
tool_result_metadata_failure_state,
|
|
37
|
+
)
|
|
38
|
+
from chrys.foundation.trajectory.context import bind_tool_operation, reset_tool_operation
|
|
39
|
+
from chrys.foundation.trajectory.event_types import ToolOutcome
|
|
40
|
+
from chrys.foundation.trajectory_timing import build_trajectory_timing, stamp_trajectory_timing
|
|
41
|
+
from chrys.foundation.util.sub_agent_context import (
|
|
42
|
+
SUB_AGENT_RESULT_COMMIT_CALLBACK_KEY,
|
|
43
|
+
SUB_AGENT_TRANSCRIPT_FINAL_TEXT_METADATA_KEY,
|
|
44
|
+
SubAgentParentResultMetadata,
|
|
45
|
+
sub_agent_parent_call_id,
|
|
46
|
+
sub_agent_parent_result_metadata,
|
|
47
|
+
)
|
|
48
|
+
from chrys.kernel._result_ceiling import preview_result_ceiling
|
|
49
|
+
from chrys.kernel.middleware import FunctionMiddleware
|
|
50
|
+
from chrys.service.agent_middleware._metadata_keys import (
|
|
51
|
+
_APPROVAL_REJECTED_KEY,
|
|
52
|
+
_SHORT_ID_LEN,
|
|
53
|
+
_SLEEP_INTERRUPTED_KEY,
|
|
54
|
+
_SLEEP_SKIPPED_KEY,
|
|
55
|
+
)
|
|
56
|
+
from chrys.service.agent_middleware.events.hook_dispatch import (
|
|
57
|
+
append_extra_context_to_result,
|
|
58
|
+
apply_before_tool_hooks,
|
|
59
|
+
final_tool_args,
|
|
60
|
+
fire_after_tool_hooks,
|
|
61
|
+
get_call_id,
|
|
62
|
+
get_provider_call_id,
|
|
63
|
+
get_tool_invocation_order,
|
|
64
|
+
is_mutable_tool_args,
|
|
65
|
+
set_call_id,
|
|
66
|
+
set_tool_invocation_order,
|
|
67
|
+
)
|
|
68
|
+
from chrys.service.agent_middleware.events.hosted_tools import (
|
|
69
|
+
FinalTextOp,
|
|
70
|
+
HostedPresentationBridge,
|
|
71
|
+
HostedToolArgsOp,
|
|
72
|
+
HostedToolProgressOp,
|
|
73
|
+
HostedToolResultOp,
|
|
74
|
+
HostedToolStartOp,
|
|
75
|
+
HostedToolStatusOp,
|
|
76
|
+
IntermediateTextOp,
|
|
77
|
+
PresentationAttemptAcceptedOp,
|
|
78
|
+
PresentationAttemptRejectedOp,
|
|
79
|
+
PresentationSinkOperation,
|
|
80
|
+
next_hosted_run_generation,
|
|
81
|
+
)
|
|
82
|
+
from chrys.service.agent_middleware.events.intermediate_text import IntermediateTextBuffer
|
|
83
|
+
from chrys.service.agent_middleware.events.rejection_metadata import rejection_result_metadata, rejection_source
|
|
84
|
+
from chrys.service.agent_middleware.events.result_persistence import (
|
|
85
|
+
RESULT_SLEEP_INTERRUPTED_METADATA_KEY,
|
|
86
|
+
RESULT_SLEEP_SKIPPED_METADATA_KEY,
|
|
87
|
+
RESULT_SUB_AGENT_AUDIT_COMPLETE_METADATA_KEY,
|
|
88
|
+
RESULT_SUB_AGENT_INVOCATION_ID_METADATA_KEY,
|
|
89
|
+
RESULT_SUB_AGENT_LOG_FILE_METADATA_KEY,
|
|
90
|
+
write_result_carriage,
|
|
91
|
+
)
|
|
92
|
+
from chrys.service.agent_middleware.events.tool_error_text import tool_card_error_text
|
|
93
|
+
from chrys.service.mutations.pipeline import (
|
|
94
|
+
abort_mutation_tracking,
|
|
95
|
+
finalize_mutation_tracking,
|
|
96
|
+
prepare_mutation_tracking,
|
|
97
|
+
)
|
|
98
|
+
from chrys.service.mutations.tool_names import _FILE_TOOLS, _IMPLICIT_WRITE_TOOLS
|
|
99
|
+
from chrys.service.tools.result_metadata import tool_result_metadata
|
|
100
|
+
from chrys.service.trajectory.preparation import (
|
|
101
|
+
PreparationOutcome,
|
|
102
|
+
PreparationScope,
|
|
103
|
+
PreparationTrace,
|
|
104
|
+
preparation_lock,
|
|
105
|
+
)
|
|
106
|
+
from chrys.service.trajectory.tools import ToolOperationTrace, tool_operation_id, tool_outcome
|
|
107
|
+
|
|
108
|
+
if TYPE_CHECKING:
|
|
109
|
+
from collections.abc import Awaitable, Callable, Sequence
|
|
110
|
+
|
|
111
|
+
from chrys.foundation.events.bus import EventBus
|
|
112
|
+
from chrys.foundation.models.invocations import InvocationOrigin
|
|
113
|
+
from chrys.kernel import Message
|
|
114
|
+
from chrys.kernel.middleware import FunctionInvocationContext
|
|
115
|
+
from chrys.service.hooks.manager import HookManager
|
|
116
|
+
from chrys.service.mutations.coordination import MutationCoordinator
|
|
117
|
+
from chrys.service.mutations.tracker import MutationTracker
|
|
118
|
+
from chrys.service.session.sub_agent_logs import SubAgentLogStats
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
class SubAgentStatsMiddleware(FunctionMiddleware):
|
|
122
|
+
"""Record sub-agent inner tool completions without publishing events."""
|
|
123
|
+
|
|
124
|
+
def __init__(self, stats: SubAgentLogStats) -> None:
|
|
125
|
+
self._stats = stats
|
|
126
|
+
|
|
127
|
+
async def process(
|
|
128
|
+
self,
|
|
129
|
+
context: FunctionInvocationContext,
|
|
130
|
+
call_next: Callable[[], Awaitable[None]],
|
|
131
|
+
) -> None:
|
|
132
|
+
cancelled = False
|
|
133
|
+
try:
|
|
134
|
+
await call_next()
|
|
135
|
+
except asyncio.CancelledError:
|
|
136
|
+
cancelled = True
|
|
137
|
+
raise
|
|
138
|
+
finally:
|
|
139
|
+
if not cancelled:
|
|
140
|
+
self._stats.record_tool_call()
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
class SubAgentEventMiddleware(FunctionMiddleware):
|
|
144
|
+
"""Publishes InvocationToolCallStart/InvocationToolCallResult events for sub-agent tool invocations.
|
|
145
|
+
|
|
146
|
+
Lightweight variant of ToolEventMiddleware for sub-agents. Created fresh per ``_invoke()``
|
|
147
|
+
call with a unique ``invocation_id``, then passed as per-run middleware to
|
|
148
|
+
``agent.run()``.
|
|
149
|
+
|
|
150
|
+
A per-invocation ``IntermediateTextBuffer`` preserves the same ordering as
|
|
151
|
+
the main agent: pending assistant text is delivered before the first tool
|
|
152
|
+
start in its batch. Sub-agent transcripts do not persist batch IDs.
|
|
153
|
+
|
|
154
|
+
Tracks cumulative tool call count and publishes ``InvocationProgress``
|
|
155
|
+
after each tool result so the TUI can display live stats.
|
|
156
|
+
|
|
157
|
+
When a ``mutation_tracker`` is provided, records file mutations (write_file,
|
|
158
|
+
edit_file) and shell command changes so that ``/diff`` picks up sub-agent
|
|
159
|
+
modifications.
|
|
160
|
+
"""
|
|
161
|
+
|
|
162
|
+
def __init__(
|
|
163
|
+
self,
|
|
164
|
+
event_bus: EventBus,
|
|
165
|
+
agent_name: str,
|
|
166
|
+
invocation_id: str,
|
|
167
|
+
mutation_tracker: MutationTracker | None = None,
|
|
168
|
+
hook_manager: HookManager | None = None,
|
|
169
|
+
profile_name: str = "",
|
|
170
|
+
session_id: str | None = None,
|
|
171
|
+
workspace_cwd: str = "",
|
|
172
|
+
serialize_implicit_windows: bool = False,
|
|
173
|
+
stats: SubAgentLogStats | None = None,
|
|
174
|
+
mutation_coordinator: MutationCoordinator | None = None,
|
|
175
|
+
tool_result_ceiling_tokens: int | None = None,
|
|
176
|
+
intermediate_buffer: IntermediateTextBuffer | None = None,
|
|
177
|
+
*,
|
|
178
|
+
origin: InvocationOrigin,
|
|
179
|
+
) -> None:
|
|
180
|
+
self._bus = event_bus
|
|
181
|
+
self._origin = origin
|
|
182
|
+
self._agent_name = agent_name
|
|
183
|
+
self._invocation_id = invocation_id
|
|
184
|
+
self._mutation_tracker = mutation_tracker
|
|
185
|
+
self._mutation_coordinator = mutation_coordinator
|
|
186
|
+
self._hook_manager = hook_manager
|
|
187
|
+
self._profile_name = profile_name
|
|
188
|
+
self._session_id = session_id
|
|
189
|
+
self._workspace_cwd = workspace_cwd
|
|
190
|
+
self._serialize_implicit_windows = serialize_implicit_windows
|
|
191
|
+
self._stats = stats
|
|
192
|
+
self._tool_result_ceiling_tokens = tool_result_ceiling_tokens
|
|
193
|
+
self._intermediate_buffer = intermediate_buffer
|
|
194
|
+
self._tool_call_count = 0
|
|
195
|
+
self._tool_invocation_order = 0
|
|
196
|
+
self._total_tokens = 0
|
|
197
|
+
self._total_usage_tokens = 0
|
|
198
|
+
self._progress_tasks: set[asyncio.Task[None]] = set()
|
|
199
|
+
self._progress_publish_tail: asyncio.Task[None] | None = None
|
|
200
|
+
self._hosted_run_generation = 0
|
|
201
|
+
self._hosted_bridge: HostedPresentationBridge | None = None
|
|
202
|
+
|
|
203
|
+
def bind_origin(self, origin: InvocationOrigin) -> None:
|
|
204
|
+
"""Bind the next pass; each tool call and hosted bridge keeps the origin it started under."""
|
|
205
|
+
self._origin = origin
|
|
206
|
+
|
|
207
|
+
def begin_hosted_pass(self) -> HostedPresentationBridge:
|
|
208
|
+
"""Create the presentation bridge owned by the next controller pass."""
|
|
209
|
+
self._hosted_run_generation = next_hosted_run_generation()
|
|
210
|
+
origin = self._origin
|
|
211
|
+
self._hosted_bridge = HostedPresentationBridge(
|
|
212
|
+
lambda operation: self._publish_hosted_operation(operation, origin),
|
|
213
|
+
run_generation=self._hosted_run_generation,
|
|
214
|
+
before_response=self.release_intermediate_text,
|
|
215
|
+
)
|
|
216
|
+
return self._hosted_bridge
|
|
217
|
+
|
|
218
|
+
async def reconcile_hosted_response(self, messages: Sequence[Message]) -> None:
|
|
219
|
+
"""Reconcile the accepted full-pass transcript through the current bridge.
|
|
220
|
+
|
|
221
|
+
The controller calls this once after the pass completes, so no more
|
|
222
|
+
tool starts can arrive: barriers for calls that never entered the
|
|
223
|
+
tool pipeline (unknown tool, pre-pipeline argument rejection) must
|
|
224
|
+
be released here or the hosted events behind them stay buffered
|
|
225
|
+
forever. The text such a call streamed is released first, so it
|
|
226
|
+
precedes what the reconcile publishes.
|
|
227
|
+
"""
|
|
228
|
+
await self.release_intermediate_text()
|
|
229
|
+
if self._hosted_bridge is not None:
|
|
230
|
+
await self._hosted_bridge.reconcile_accepted(messages, final=True)
|
|
231
|
+
|
|
232
|
+
async def release_intermediate_text(self) -> None:
|
|
233
|
+
"""Publish intermediate text that no tool start has released yet.
|
|
234
|
+
|
|
235
|
+
A call that never enters the tool pipeline (unknown tool, pre-pipeline
|
|
236
|
+
argument rejection) starts no tool, so the text streamed with it stays
|
|
237
|
+
buffered until the next response starts or the pass ends.
|
|
238
|
+
"""
|
|
239
|
+
await self._release_intermediate_text(None)
|
|
240
|
+
|
|
241
|
+
async def finish_intermediate_text(self) -> None:
|
|
242
|
+
"""Release what is still buffered as the pass ends; see ``IntermediateTextBuffer.finish``."""
|
|
243
|
+
if self._intermediate_buffer is not None:
|
|
244
|
+
await self._intermediate_buffer.finish(self._publish_intermediate_text)
|
|
245
|
+
|
|
246
|
+
async def _release_intermediate_text(self, preamble: PreparationTrace | None) -> None:
|
|
247
|
+
if self._intermediate_buffer is not None:
|
|
248
|
+
await self._intermediate_buffer.release(self._publish_intermediate_text, preamble)
|
|
249
|
+
|
|
250
|
+
async def _publish_intermediate_text(self, text: str) -> None:
|
|
251
|
+
await self._bus.publish(
|
|
252
|
+
InvocationMessage(
|
|
253
|
+
is_final=False,
|
|
254
|
+
is_intermediate=True,
|
|
255
|
+
origin=self._origin,
|
|
256
|
+
agent_name=self._agent_name,
|
|
257
|
+
text=text,
|
|
258
|
+
session_id=self._session_id,
|
|
259
|
+
)
|
|
260
|
+
)
|
|
261
|
+
|
|
262
|
+
async def reject_hosted_attempt(
|
|
263
|
+
self,
|
|
264
|
+
reason: str,
|
|
265
|
+
*,
|
|
266
|
+
status: str = HostedToolStatus.INTERRUPTED,
|
|
267
|
+
) -> None:
|
|
268
|
+
"""Terminalize running hosted cards at a controller boundary."""
|
|
269
|
+
if self._hosted_bridge is not None:
|
|
270
|
+
await self._hosted_bridge.attempt_rejected(reason, status=status)
|
|
271
|
+
|
|
272
|
+
@staticmethod
|
|
273
|
+
def _artifact_descriptors(operation: HostedToolResultOp) -> list[dict[str, Any]]:
|
|
274
|
+
descriptors: list[dict[str, Any]] = []
|
|
275
|
+
for artifact in operation.view.artifacts:
|
|
276
|
+
# "path" must stay a real URI: consumers turn it into links, and a
|
|
277
|
+
# bare hosted filename (OpenAI hosted_file) is not addressable.
|
|
278
|
+
descriptor: dict[str, Any] = {
|
|
279
|
+
"id": artifact.file_id or artifact.vector_store_id or artifact.id or "",
|
|
280
|
+
"name": artifact.name or "",
|
|
281
|
+
"path": artifact.uri or "",
|
|
282
|
+
"mime": artifact.media_type or "",
|
|
283
|
+
}
|
|
284
|
+
size = artifact.additional_properties.get("size")
|
|
285
|
+
if isinstance(size, int) and not isinstance(size, bool):
|
|
286
|
+
descriptor["size"] = size
|
|
287
|
+
descriptors.append({key: value for key, value in descriptor.items() if value != ""})
|
|
288
|
+
return descriptors
|
|
289
|
+
|
|
290
|
+
async def _publish_hosted_operation(self, operation: PresentationSinkOperation, origin: InvocationOrigin) -> None:
|
|
291
|
+
"""Map one hosted presentation operation to sub-agent events."""
|
|
292
|
+
if isinstance(operation, IntermediateTextOp):
|
|
293
|
+
presentation = None
|
|
294
|
+
if operation.provisional:
|
|
295
|
+
segment_id = operation.segment_ids[0] if operation.segment_ids else ""
|
|
296
|
+
presentation = ProvisionalPresentation(operation.attempt_id, segment_id)
|
|
297
|
+
await self._bus.publish(
|
|
298
|
+
InvocationMessage(
|
|
299
|
+
is_final=False,
|
|
300
|
+
is_intermediate=True,
|
|
301
|
+
origin=origin,
|
|
302
|
+
agent_name=self._agent_name,
|
|
303
|
+
text=operation.text,
|
|
304
|
+
presentation=presentation,
|
|
305
|
+
session_id=self._session_id,
|
|
306
|
+
)
|
|
307
|
+
)
|
|
308
|
+
return
|
|
309
|
+
if isinstance(operation, PresentationAttemptAcceptedOp):
|
|
310
|
+
await self._bus.publish(
|
|
311
|
+
InvocationPresentationAttemptAccepted(
|
|
312
|
+
origin=origin,
|
|
313
|
+
agent_name=self._agent_name,
|
|
314
|
+
attempt_id=operation.attempt_id,
|
|
315
|
+
segment_ids=tuple(
|
|
316
|
+
segment_id for segment in operation.segments for segment_id in segment.segment_ids
|
|
317
|
+
),
|
|
318
|
+
session_id=self._session_id,
|
|
319
|
+
)
|
|
320
|
+
)
|
|
321
|
+
return
|
|
322
|
+
if isinstance(operation, PresentationAttemptRejectedOp):
|
|
323
|
+
await self._bus.publish(
|
|
324
|
+
InvocationPresentationAttemptRejected(
|
|
325
|
+
origin=origin,
|
|
326
|
+
agent_name=self._agent_name,
|
|
327
|
+
attempt_id=operation.attempt_id,
|
|
328
|
+
session_id=self._session_id,
|
|
329
|
+
)
|
|
330
|
+
)
|
|
331
|
+
return
|
|
332
|
+
if isinstance(operation, FinalTextOp):
|
|
333
|
+
return
|
|
334
|
+
view = operation.view
|
|
335
|
+
common: dict[str, Any] = {
|
|
336
|
+
"agent_name": self._agent_name,
|
|
337
|
+
"tool_name": view.tool_name,
|
|
338
|
+
"call_id": operation.presentation_id,
|
|
339
|
+
"provider_hosted": True,
|
|
340
|
+
"hosted_family": view.family,
|
|
341
|
+
"provider": view.provider,
|
|
342
|
+
"session_id": self._session_id,
|
|
343
|
+
}
|
|
344
|
+
if isinstance(operation, HostedToolStartOp):
|
|
345
|
+
await self._bus.publish(
|
|
346
|
+
InvocationToolCallStart(
|
|
347
|
+
origin=origin,
|
|
348
|
+
**common,
|
|
349
|
+
tool_kind=HOSTED_TOOL_DEFAULT_KIND_BY_FAMILY.get(view.family, ""),
|
|
350
|
+
args=view.arguments,
|
|
351
|
+
provider_item_type=view.provider_item_type,
|
|
352
|
+
provider_call_id=view.provider_call_id,
|
|
353
|
+
provider_status=view.provider_status,
|
|
354
|
+
)
|
|
355
|
+
)
|
|
356
|
+
elif isinstance(operation, HostedToolArgsOp):
|
|
357
|
+
await self._bus.publish(
|
|
358
|
+
InvocationToolCallArgsUpdated(
|
|
359
|
+
origin=origin,
|
|
360
|
+
**common,
|
|
361
|
+
tool_kind=HOSTED_TOOL_DEFAULT_KIND_BY_FAMILY.get(view.family, ""),
|
|
362
|
+
args=view.arguments,
|
|
363
|
+
provider_item_type=view.provider_item_type,
|
|
364
|
+
provider_call_id=view.provider_call_id,
|
|
365
|
+
provider_status=view.provider_status,
|
|
366
|
+
)
|
|
367
|
+
)
|
|
368
|
+
elif isinstance(operation, HostedToolProgressOp):
|
|
369
|
+
await self._bus.publish(
|
|
370
|
+
InvocationToolCallProgress(
|
|
371
|
+
origin=origin,
|
|
372
|
+
**common,
|
|
373
|
+
lines=view.result_text.splitlines(),
|
|
374
|
+
image_contents=view.image_contents,
|
|
375
|
+
snapshot_metadata=view.metadata,
|
|
376
|
+
provider_item_type=view.provider_item_type,
|
|
377
|
+
provider_call_id=view.provider_call_id,
|
|
378
|
+
provider_status=view.provider_status,
|
|
379
|
+
)
|
|
380
|
+
)
|
|
381
|
+
elif isinstance(operation, HostedToolStatusOp):
|
|
382
|
+
metadata = dict(view.metadata)
|
|
383
|
+
if view.result_text:
|
|
384
|
+
metadata["result_text"] = view.result_text
|
|
385
|
+
if view.provider_item_type:
|
|
386
|
+
metadata["provider_item_type"] = view.provider_item_type
|
|
387
|
+
if view.provider_call_id:
|
|
388
|
+
metadata["provider_call_id"] = view.provider_call_id
|
|
389
|
+
await self._bus.publish(
|
|
390
|
+
InvocationToolCallStatusUpdated(
|
|
391
|
+
origin=origin,
|
|
392
|
+
**common,
|
|
393
|
+
status=view.status,
|
|
394
|
+
provider_status=view.provider_status,
|
|
395
|
+
metadata=metadata,
|
|
396
|
+
)
|
|
397
|
+
)
|
|
398
|
+
elif isinstance(operation, HostedToolResultOp):
|
|
399
|
+
await self._bus.publish(
|
|
400
|
+
InvocationToolCallResult(
|
|
401
|
+
origin=origin,
|
|
402
|
+
**common,
|
|
403
|
+
result=view.result_text,
|
|
404
|
+
image_contents=view.image_contents,
|
|
405
|
+
metadata=view.metadata,
|
|
406
|
+
artifacts=self._artifact_descriptors(operation),
|
|
407
|
+
provider_item_type=view.provider_item_type,
|
|
408
|
+
provider_call_id=view.provider_call_id,
|
|
409
|
+
provider_status=view.provider_status,
|
|
410
|
+
)
|
|
411
|
+
)
|
|
412
|
+
|
|
413
|
+
def record_usage(self, total_tokens: int, total_usage_tokens: int) -> None:
|
|
414
|
+
"""Record sub-agent usage and publish progress from the usage callback."""
|
|
415
|
+
if self._stats is not None:
|
|
416
|
+
self._stats.record_usage(total_tokens, total_usage_tokens)
|
|
417
|
+
self._total_tokens = total_tokens
|
|
418
|
+
self._total_usage_tokens = total_usage_tokens
|
|
419
|
+
# ``record_usage`` is sync (called from ``UsageTrackingMiddleware.
|
|
420
|
+
# _fire_callback``). Skip the publish when there's no running loop —
|
|
421
|
+
# callers driving this from a non-async context (test fixture, future
|
|
422
|
+
# threadpool result hook) should not crash; the cumulative state has
|
|
423
|
+
# already been recorded on ``self``.
|
|
424
|
+
try:
|
|
425
|
+
asyncio.get_running_loop()
|
|
426
|
+
except RuntimeError:
|
|
427
|
+
return
|
|
428
|
+
self._schedule_progress_publish()
|
|
429
|
+
|
|
430
|
+
def _schedule_progress_publish(self) -> None:
|
|
431
|
+
"""Schedule a InvocationProgress publish chained behind the previous one.
|
|
432
|
+
|
|
433
|
+
Chaining matches the parent ``_track_usage_publish`` pattern in
|
|
434
|
+
``chrys.service.usage`` — without it, two close-together publishes can be
|
|
435
|
+
delivered out of order under a slow subscriber, regressing the displayed
|
|
436
|
+
token/tool-call counters. Tasks read ``self._*`` live, so a stale
|
|
437
|
+
``tool_call_count`` snapshot can never undo a fresher one.
|
|
438
|
+
"""
|
|
439
|
+
previous = self._progress_publish_tail
|
|
440
|
+
|
|
441
|
+
async def _publish_after_previous() -> None:
|
|
442
|
+
if previous is not None:
|
|
443
|
+
await asyncio.gather(previous, return_exceptions=True)
|
|
444
|
+
await self._publish_progress()
|
|
445
|
+
|
|
446
|
+
task = asyncio.create_task(_publish_after_previous())
|
|
447
|
+
self._progress_publish_tail = task
|
|
448
|
+
self._progress_tasks.add(task)
|
|
449
|
+
task.add_done_callback(self._progress_tasks.discard)
|
|
450
|
+
task.add_done_callback(self._maybe_clear_tail)
|
|
451
|
+
task.add_done_callback(_observe_task_exception)
|
|
452
|
+
|
|
453
|
+
def _maybe_clear_tail(self, task: asyncio.Task[None]) -> None:
|
|
454
|
+
if self._progress_publish_tail is task:
|
|
455
|
+
self._progress_publish_tail = None
|
|
456
|
+
|
|
457
|
+
async def flush_progress(self) -> None:
|
|
458
|
+
"""Wait for any usage-triggered progress publishes to finish.
|
|
459
|
+
|
|
460
|
+
Loops until no tasks remain — a ``record_usage`` that fires while the
|
|
461
|
+
gather is suspended (e.g. a late streaming finalization) adds a task
|
|
462
|
+
to ``_progress_tasks`` that a single snapshot would miss.
|
|
463
|
+
"""
|
|
464
|
+
while self._progress_tasks:
|
|
465
|
+
tasks = tuple(self._progress_tasks)
|
|
466
|
+
await asyncio.gather(*tasks, return_exceptions=True)
|
|
467
|
+
self._progress_tasks.difference_update(tasks)
|
|
468
|
+
|
|
469
|
+
async def _publish_progress(self) -> None:
|
|
470
|
+
await self._bus.publish(
|
|
471
|
+
InvocationProgress(
|
|
472
|
+
origin=self._origin,
|
|
473
|
+
agent_name=self._agent_name,
|
|
474
|
+
tool_call_count=self._tool_call_count,
|
|
475
|
+
total_tokens=self._total_tokens,
|
|
476
|
+
total_usage_tokens=self._total_usage_tokens,
|
|
477
|
+
session_id=self._session_id,
|
|
478
|
+
)
|
|
479
|
+
)
|
|
480
|
+
|
|
481
|
+
async def process(
|
|
482
|
+
self,
|
|
483
|
+
context: FunctionInvocationContext,
|
|
484
|
+
call_next: Callable[[], Awaitable[None]],
|
|
485
|
+
) -> None:
|
|
486
|
+
# Bound before the first await, for the reason spelled out in
|
|
487
|
+
# ``ToolEventMiddleware.process``: the kernel hands the operation over
|
|
488
|
+
# at dispatch, and everything below can be cancelled before the start
|
|
489
|
+
# marker is written.
|
|
490
|
+
trajectory = ToolOperationTrace.open(context.metadata if isinstance(context.metadata, dict) else {})
|
|
491
|
+
preamble = (
|
|
492
|
+
PreparationTrace.open(
|
|
493
|
+
scope=PreparationScope.TOOL_PREAMBLE,
|
|
494
|
+
phase="tool_dispatch",
|
|
495
|
+
parent_operation_id=trajectory.context.innermost_model_operation_id,
|
|
496
|
+
target_operation_id=trajectory.operation_id,
|
|
497
|
+
context=trajectory.context,
|
|
498
|
+
)
|
|
499
|
+
if trajectory is not None
|
|
500
|
+
else None
|
|
501
|
+
)
|
|
502
|
+
origin = self._origin
|
|
503
|
+
try:
|
|
504
|
+
if preamble is not None:
|
|
505
|
+
await preamble.started()
|
|
506
|
+
await self._process(context, call_next, trajectory, preamble, origin)
|
|
507
|
+
except Exception:
|
|
508
|
+
if preamble is not None:
|
|
509
|
+
preamble.finished_soon(outcome=PreparationOutcome.FAILED)
|
|
510
|
+
self._abandon_operation(context, trajectory, preamble, ToolOutcome.ERRORED)
|
|
511
|
+
raise
|
|
512
|
+
except BaseException:
|
|
513
|
+
if preamble is not None:
|
|
514
|
+
preamble.finished_soon(outcome=PreparationOutcome.INTERRUPTED)
|
|
515
|
+
self._abandon_operation(context, trajectory, preamble, ToolOutcome.INTERRUPTED)
|
|
516
|
+
raise
|
|
517
|
+
|
|
518
|
+
def _abandon_operation(
|
|
519
|
+
self,
|
|
520
|
+
context: FunctionInvocationContext,
|
|
521
|
+
trajectory: ToolOperationTrace | None,
|
|
522
|
+
preamble: PreparationTrace | None,
|
|
523
|
+
outcome: str,
|
|
524
|
+
) -> None:
|
|
525
|
+
"""Close an operation that never reached its own start marker (a no-op once it has)."""
|
|
526
|
+
if trajectory is None:
|
|
527
|
+
return
|
|
528
|
+
metadata = context.metadata if isinstance(context.metadata, dict) else {}
|
|
529
|
+
args = context.arguments if is_mutable_tool_args(context.arguments) else {}
|
|
530
|
+
trajectory.abandoned_soon(
|
|
531
|
+
tool_name=context.function.name,
|
|
532
|
+
tool_kind=get_tool_kind(context.function) or "",
|
|
533
|
+
batch_index=None,
|
|
534
|
+
invocation_order=get_tool_invocation_order(context),
|
|
535
|
+
arguments=args,
|
|
536
|
+
invocation_metadata=metadata,
|
|
537
|
+
tool_context=resolve_tool_call_context(context.function, args) or None,
|
|
538
|
+
outcome=outcome,
|
|
539
|
+
preamble_operation_id=(
|
|
540
|
+
preamble.operation_id if preamble is not None and preamble.start_committed else None
|
|
541
|
+
),
|
|
542
|
+
)
|
|
543
|
+
|
|
544
|
+
async def _process(
|
|
545
|
+
self,
|
|
546
|
+
context: FunctionInvocationContext,
|
|
547
|
+
call_next: Callable[[], Awaitable[None]],
|
|
548
|
+
trajectory: ToolOperationTrace | None,
|
|
549
|
+
preamble: PreparationTrace | None,
|
|
550
|
+
origin: InvocationOrigin,
|
|
551
|
+
) -> None:
|
|
552
|
+
tool_order = get_tool_invocation_order(context)
|
|
553
|
+
if tool_order is None:
|
|
554
|
+
tool_order = self._tool_invocation_order
|
|
555
|
+
self._tool_invocation_order = max(self._tool_invocation_order, tool_order + 1)
|
|
556
|
+
set_tool_invocation_order(context, tool_order)
|
|
557
|
+
|
|
558
|
+
await self._release_intermediate_text(preamble)
|
|
559
|
+
|
|
560
|
+
provider_call_id = get_provider_call_id(context)
|
|
561
|
+
call_id = get_call_id(context) or uuid4().hex[:_SHORT_ID_LEN]
|
|
562
|
+
tool_name = context.function.name
|
|
563
|
+
args = context.arguments if is_mutable_tool_args(context.arguments) else {}
|
|
564
|
+
# Stash the Chrys call_id in metadata so downstream middleware
|
|
565
|
+
# references the same id as the published
|
|
566
|
+
# InvocationToolCallStart/InvocationToolCallResult events.
|
|
567
|
+
set_call_id(context, call_id)
|
|
568
|
+
|
|
569
|
+
tool_kind = get_tool_kind(context.function) or ""
|
|
570
|
+
blocked = await apply_before_tool_hooks(
|
|
571
|
+
manager=self._hook_manager,
|
|
572
|
+
context=context,
|
|
573
|
+
session_id=self._session_id,
|
|
574
|
+
profile_name=self._profile_name,
|
|
575
|
+
tool_name=tool_name,
|
|
576
|
+
kind=tool_kind,
|
|
577
|
+
call_id=call_id,
|
|
578
|
+
args=args,
|
|
579
|
+
workspace_cwd=self._workspace_cwd,
|
|
580
|
+
target_operation_id=trajectory.operation_id if trajectory is not None else None,
|
|
581
|
+
)
|
|
582
|
+
args = context.arguments if is_mutable_tool_args(context.arguments) else {}
|
|
583
|
+
|
|
584
|
+
async def _blocked_call_next() -> None:
|
|
585
|
+
return None
|
|
586
|
+
|
|
587
|
+
# Serialize concurrent mutations to the same file (same rationale
|
|
588
|
+
# as ToolEventMiddleware — framework uses asyncio.gather()).
|
|
589
|
+
file_lock_path = _file_lock_path(tool_name, args, self._workspace_cwd)
|
|
590
|
+
implicit_window = _uses_implicit_window(tool_name, tool_kind)
|
|
591
|
+
if blocked:
|
|
592
|
+
await self._process_tool_call(
|
|
593
|
+
context, _blocked_call_next, call_id, provider_call_id, tool_name, args, trajectory, preamble, origin
|
|
594
|
+
)
|
|
595
|
+
elif self._serialize_implicit_windows and implicit_window and self._mutation_tracker is not None:
|
|
596
|
+
async with preparation_lock(self._mutation_tracker.get_implicit_window_lock(), preamble):
|
|
597
|
+
await self._process_tool_call(
|
|
598
|
+
context, call_next, call_id, provider_call_id, tool_name, args, trajectory, preamble, origin
|
|
599
|
+
)
|
|
600
|
+
elif file_lock_path and self._mutation_tracker is not None:
|
|
601
|
+
async with preparation_lock(self._mutation_tracker.get_file_lock(file_lock_path), preamble):
|
|
602
|
+
await self._process_tool_call(
|
|
603
|
+
context, call_next, call_id, provider_call_id, tool_name, args, trajectory, preamble, origin
|
|
604
|
+
)
|
|
605
|
+
else:
|
|
606
|
+
await self._process_tool_call(
|
|
607
|
+
context, call_next, call_id, provider_call_id, tool_name, args, trajectory, preamble, origin
|
|
608
|
+
)
|
|
609
|
+
|
|
610
|
+
async def _process_tool_call(
|
|
611
|
+
self,
|
|
612
|
+
context: FunctionInvocationContext,
|
|
613
|
+
call_next: Callable[[], Awaitable[None]],
|
|
614
|
+
call_id: str,
|
|
615
|
+
provider_call_id: str,
|
|
616
|
+
tool_name: str,
|
|
617
|
+
args: dict,
|
|
618
|
+
trajectory: ToolOperationTrace | None,
|
|
619
|
+
preamble: PreparationTrace | None,
|
|
620
|
+
origin: InvocationOrigin,
|
|
621
|
+
) -> None:
|
|
622
|
+
"""Core tool-call processing for sub-agents."""
|
|
623
|
+
tool_kind = get_tool_kind(context.function) or ""
|
|
624
|
+
is_shell = tool_kind == KIND_SHELL
|
|
625
|
+
is_sub_agent = tool_kind == KIND_SUB_AGENT
|
|
626
|
+
|
|
627
|
+
# Pre-execution mutation tracking
|
|
628
|
+
_meta = context.metadata if isinstance(context.metadata, dict) else {}
|
|
629
|
+
pre_rejected = bool(_meta.get(_APPROVAL_REJECTED_KEY))
|
|
630
|
+
mut_ctx = None
|
|
631
|
+
if not pre_rejected:
|
|
632
|
+
mut_ctx = await prepare_mutation_tracking(
|
|
633
|
+
self._mutation_tracker,
|
|
634
|
+
tool_name,
|
|
635
|
+
args,
|
|
636
|
+
call_id,
|
|
637
|
+
is_shell,
|
|
638
|
+
workspace_cwd=self._workspace_cwd,
|
|
639
|
+
coordinator=self._mutation_coordinator,
|
|
640
|
+
)
|
|
641
|
+
|
|
642
|
+
await self._bus.publish(
|
|
643
|
+
InvocationToolCallStart(
|
|
644
|
+
origin=origin,
|
|
645
|
+
agent_name=self._agent_name,
|
|
646
|
+
tool_name=tool_name,
|
|
647
|
+
tool_kind=tool_kind,
|
|
648
|
+
args=args,
|
|
649
|
+
call_id=call_id,
|
|
650
|
+
session_id=self._session_id,
|
|
651
|
+
)
|
|
652
|
+
)
|
|
653
|
+
if self._hosted_bridge is not None:
|
|
654
|
+
await self._hosted_bridge.local_call_start_published(provider_call_id)
|
|
655
|
+
|
|
656
|
+
# A delegation from this invocation (a workflow node's, or a nested sub-agent's) binds its
|
|
657
|
+
# child to this call the same way ToolEventMiddleware binds a chat turn's: the child reads
|
|
658
|
+
# the parent call ids from these ContextVars and writes its invocation id back for the result.
|
|
659
|
+
sub_agent_token = None
|
|
660
|
+
sub_agent_metadata_token = None
|
|
661
|
+
sub_agent_metadata: SubAgentParentResultMetadata | None = None
|
|
662
|
+
if is_sub_agent:
|
|
663
|
+
raw_commit = _meta.get(SUB_AGENT_RESULT_COMMIT_CALLBACK_KEY)
|
|
664
|
+
sub_agent_token = sub_agent_parent_call_id.set(call_id)
|
|
665
|
+
sub_agent_metadata = SubAgentParentResultMetadata(
|
|
666
|
+
parent_provider_call_id=provider_call_id,
|
|
667
|
+
parent_event_call_id=call_id,
|
|
668
|
+
commit_interrupted_result=raw_commit if callable(raw_commit) else None,
|
|
669
|
+
)
|
|
670
|
+
sub_agent_metadata_token = sub_agent_parent_result_metadata.set(sub_agent_metadata)
|
|
671
|
+
|
|
672
|
+
started_at = datetime.now(UTC)
|
|
673
|
+
start = time.monotonic()
|
|
674
|
+
error_text = ""
|
|
675
|
+
errored = False
|
|
676
|
+
raised_error_kind: str | None = None
|
|
677
|
+
cancelled = False
|
|
678
|
+
shell_metadata_token = None
|
|
679
|
+
shell_metadata: dict[str, object] | None = None
|
|
680
|
+
generic_metadata: dict[str, object] = {}
|
|
681
|
+
generic_metadata_token = tool_result_metadata.set(generic_metadata)
|
|
682
|
+
payload_observation: dict[str, object] = {}
|
|
683
|
+
payload_observation_token = tool_payload_observation.set(payload_observation)
|
|
684
|
+
if is_shell:
|
|
685
|
+
from chrys.service.tools.builtins.shell import shell_result_metadata
|
|
686
|
+
|
|
687
|
+
shell_metadata = {}
|
|
688
|
+
shell_metadata_token = shell_result_metadata.set(shell_metadata)
|
|
689
|
+
tool_operation_token = bind_tool_operation(
|
|
690
|
+
trajectory.operation_id if trajectory is not None else tool_operation_id(_meta)
|
|
691
|
+
)
|
|
692
|
+
try:
|
|
693
|
+
if preamble is not None:
|
|
694
|
+
await preamble.finished(outcome=PreparationOutcome.HANDOFF)
|
|
695
|
+
# Inside the block that closes the operation: the start marker
|
|
696
|
+
# awaits its write ack, and an interrupt landing there would
|
|
697
|
+
# otherwise leave the operation open forever. Nothing between the
|
|
698
|
+
# trace and here awaits, so the marker still precedes the call.
|
|
699
|
+
if trajectory is not None:
|
|
700
|
+
await trajectory.started(
|
|
701
|
+
tool_name=tool_name,
|
|
702
|
+
tool_kind=tool_kind,
|
|
703
|
+
batch_index=None,
|
|
704
|
+
invocation_order=get_tool_invocation_order(context),
|
|
705
|
+
arguments=args,
|
|
706
|
+
invocation_metadata=_meta,
|
|
707
|
+
# Resolved again after the call for the persisted carriage;
|
|
708
|
+
# here it describes the call as dispatched, alongside the
|
|
709
|
+
# argument fingerprint of those same arguments.
|
|
710
|
+
tool_context=resolve_tool_call_context(context.function, args) or None,
|
|
711
|
+
preamble_operation_id=(
|
|
712
|
+
preamble.operation_id if preamble is not None and preamble.start_committed else None
|
|
713
|
+
),
|
|
714
|
+
)
|
|
715
|
+
await call_next()
|
|
716
|
+
except Exception as exc:
|
|
717
|
+
errored = True
|
|
718
|
+
raised_error_kind = type(exc).__name__
|
|
719
|
+
error_text = tool_card_error_text(exc)
|
|
720
|
+
raise
|
|
721
|
+
except BaseException:
|
|
722
|
+
cancelled = True
|
|
723
|
+
raise
|
|
724
|
+
finally:
|
|
725
|
+
reset_tool_operation(tool_operation_token)
|
|
726
|
+
if shell_metadata_token is not None:
|
|
727
|
+
from chrys.service.tools.builtins.shell import shell_result_metadata
|
|
728
|
+
|
|
729
|
+
shell_result_metadata.reset(shell_metadata_token)
|
|
730
|
+
tool_result_metadata.reset(generic_metadata_token)
|
|
731
|
+
tool_payload_observation.reset(payload_observation_token)
|
|
732
|
+
if sub_agent_token is not None:
|
|
733
|
+
sub_agent_parent_call_id.reset(sub_agent_token)
|
|
734
|
+
if sub_agent_metadata_token is not None:
|
|
735
|
+
sub_agent_parent_result_metadata.reset(sub_agent_metadata_token)
|
|
736
|
+
|
|
737
|
+
if not isinstance(context.metadata, dict):
|
|
738
|
+
context.metadata = {}
|
|
739
|
+
rejected = bool(context.metadata.get(_APPROVAL_REJECTED_KEY, False))
|
|
740
|
+
finished_at = datetime.now(UTC)
|
|
741
|
+
elapsed_ms = int((time.monotonic() - start) * 1000)
|
|
742
|
+
# A rejected delegation reports no duration to the UI — it never
|
|
743
|
+
# ran — but the operation was open for the whole approval wait.
|
|
744
|
+
duration_ms = 0 if rejected else elapsed_ms
|
|
745
|
+
stamp_trajectory_timing(
|
|
746
|
+
context.metadata,
|
|
747
|
+
build_trajectory_timing(
|
|
748
|
+
started_at=finished_at if rejected else started_at,
|
|
749
|
+
finished_at=finished_at,
|
|
750
|
+
duration_ms=duration_ms,
|
|
751
|
+
),
|
|
752
|
+
overwrite=True,
|
|
753
|
+
)
|
|
754
|
+
|
|
755
|
+
if cancelled and trajectory is not None:
|
|
756
|
+
# Unwinding from CancelledError: close without awaiting the ack.
|
|
757
|
+
trajectory.finished_soon(outcome=ToolOutcome.INTERRUPTED, duration_ms=elapsed_ms)
|
|
758
|
+
if cancelled and mut_ctx is not None:
|
|
759
|
+
# Cancelled tasks raise CancelledError at their next await,
|
|
760
|
+
# so the async finalize below is unreachable — release the
|
|
761
|
+
# trace wrapper and close the coordination window
|
|
762
|
+
# synchronously or the registry advertises a live command
|
|
763
|
+
# to peers until shutdown. The command may have written
|
|
764
|
+
# before the interrupt, so implicit detection is truncated.
|
|
765
|
+
abort_mutation_tracking(mut_ctx, self._mutation_coordinator, tracker=self._mutation_tracker)
|
|
766
|
+
if not cancelled:
|
|
767
|
+
try:
|
|
768
|
+
result_text = error_text or extract_result_text(context.result)
|
|
769
|
+
_meta = context.metadata
|
|
770
|
+
# Refresh to the final (approval-modified) args — everything
|
|
771
|
+
# below (after-tool hooks, persisted provenance) must see the
|
|
772
|
+
# arguments the tool actually ran with, same as the main
|
|
773
|
+
# ToolEventMiddleware.
|
|
774
|
+
args = final_tool_args(context, args)
|
|
775
|
+
if rejected and mut_ctx is not None:
|
|
776
|
+
# Rejected at approval, post-prepare: finalize is
|
|
777
|
+
# deliberately skipped (the tool never executed), so
|
|
778
|
+
# release the trace wrapper and close the observation
|
|
779
|
+
# window here.
|
|
780
|
+
abort_mutation_tracking(mut_ctx, self._mutation_coordinator)
|
|
781
|
+
if self._stats is not None:
|
|
782
|
+
self._stats.record_tool_call()
|
|
783
|
+
self._tool_call_count += 1
|
|
784
|
+
|
|
785
|
+
# Post-execution mutation tracking (skip for rejected tools)
|
|
786
|
+
metadata: dict[str, Any] = {}
|
|
787
|
+
metadata.update(generic_metadata)
|
|
788
|
+
if shell_metadata:
|
|
789
|
+
metadata.update(shell_metadata)
|
|
790
|
+
if not rejected and mut_ctx is not None:
|
|
791
|
+
# Authorship gate for coordination claims: structured
|
|
792
|
+
# "Error: ..." results (tool_error / record_tool_failure)
|
|
793
|
+
# mean the write may not have happened — the observed
|
|
794
|
+
# delta could be a peer racing our window. ``errored``
|
|
795
|
+
# only covers raised exceptions; the metadata failure
|
|
796
|
+
# state covers the no-raise failure paths.
|
|
797
|
+
tool_failed = errored or tool_result_metadata_failure_state(metadata) is True
|
|
798
|
+
try:
|
|
799
|
+
mut_result = await finalize_mutation_tracking(
|
|
800
|
+
self._mutation_tracker,
|
|
801
|
+
mut_ctx,
|
|
802
|
+
call_id,
|
|
803
|
+
coordinator=self._mutation_coordinator,
|
|
804
|
+
tool_errored=tool_failed,
|
|
805
|
+
)
|
|
806
|
+
except BaseException:
|
|
807
|
+
# An interrupt landing DURING finalize (git
|
|
808
|
+
# calibration, scans, and trace parsing are executor
|
|
809
|
+
# hops) bypasses both the cancel-path abort above
|
|
810
|
+
# (``cancelled`` only covers call_next) and
|
|
811
|
+
# finalize's own release — clean up synchronously.
|
|
812
|
+
# Idempotent after a partial finalize. The command
|
|
813
|
+
# ran; its aborted detection is truncated.
|
|
814
|
+
abort_mutation_tracking(mut_ctx, self._mutation_coordinator, tracker=self._mutation_tracker)
|
|
815
|
+
raise
|
|
816
|
+
if mut_result.file_snapshot is not None:
|
|
817
|
+
metadata["file_snapshot"] = mut_result.file_snapshot
|
|
818
|
+
if mut_result.file_operation is not None:
|
|
819
|
+
metadata["file_mutation_op"] = mut_result.file_operation
|
|
820
|
+
if mut_result.file_bytes_changed is not None:
|
|
821
|
+
metadata["file_bytes_changed"] = mut_result.file_bytes_changed
|
|
822
|
+
if mut_result.file_hashes is not None:
|
|
823
|
+
metadata["file_mutation_hashes"] = mut_result.file_hashes
|
|
824
|
+
if mut_result.shell_snapshots:
|
|
825
|
+
metadata["shell_file_snapshots"] = mut_result.shell_snapshots
|
|
826
|
+
if rejected:
|
|
827
|
+
metadata.update(rejection_result_metadata(_meta))
|
|
828
|
+
if isinstance(_meta, dict) and _meta.get(_SLEEP_SKIPPED_KEY, False):
|
|
829
|
+
metadata[RESULT_SLEEP_SKIPPED_METADATA_KEY] = True
|
|
830
|
+
if isinstance(_meta, dict) and _meta.get(_SLEEP_INTERRUPTED_KEY, False):
|
|
831
|
+
metadata[RESULT_SLEEP_INTERRUPTED_METADATA_KEY] = True
|
|
832
|
+
if sub_agent_metadata is not None:
|
|
833
|
+
if sub_agent_metadata.sub_agent_invocation_id:
|
|
834
|
+
metadata[RESULT_SUB_AGENT_INVOCATION_ID_METADATA_KEY] = (
|
|
835
|
+
sub_agent_metadata.sub_agent_invocation_id
|
|
836
|
+
)
|
|
837
|
+
if sub_agent_metadata.sub_agent_log_file:
|
|
838
|
+
metadata[RESULT_SUB_AGENT_LOG_FILE_METADATA_KEY] = sub_agent_metadata.sub_agent_log_file
|
|
839
|
+
if sub_agent_metadata.sub_agent_audit_complete:
|
|
840
|
+
metadata[RESULT_SUB_AGENT_AUDIT_COMPLETE_METADATA_KEY] = True
|
|
841
|
+
if sub_agent_metadata.transcript_final_text is not None:
|
|
842
|
+
metadata[SUB_AGENT_TRANSCRIPT_FINAL_TEXT_METADATA_KEY] = (
|
|
843
|
+
sub_agent_metadata.transcript_final_text
|
|
844
|
+
)
|
|
845
|
+
if errored:
|
|
846
|
+
metadata[TOOL_ERRORED_METADATA_KEY] = True
|
|
847
|
+
structured_failed = tool_result_metadata_failure_state(metadata) is True
|
|
848
|
+
source = rejection_source(_meta) if rejected else ""
|
|
849
|
+
# Same carriage as ToolEventMiddleware: the kernel folds the
|
|
850
|
+
# carried metadata/provenance onto the right Contents at
|
|
851
|
+
# construction — no post-run positional re-association.
|
|
852
|
+
tool_context = resolve_tool_call_context(context.function, args)
|
|
853
|
+
write_result_carriage(context, metadata=metadata, tool_context=tool_context or None)
|
|
854
|
+
|
|
855
|
+
hook_decision = await fire_after_tool_hooks(
|
|
856
|
+
manager=self._hook_manager,
|
|
857
|
+
session_id=self._session_id,
|
|
858
|
+
profile_name=self._profile_name,
|
|
859
|
+
tool_name=tool_name,
|
|
860
|
+
kind=tool_kind,
|
|
861
|
+
call_id=call_id,
|
|
862
|
+
args=args,
|
|
863
|
+
result_text=result_text,
|
|
864
|
+
duration_ms=duration_ms,
|
|
865
|
+
errored=errored,
|
|
866
|
+
failed=structured_failed,
|
|
867
|
+
approval_rejected=rejected,
|
|
868
|
+
rejection_source=source,
|
|
869
|
+
workspace_cwd=self._workspace_cwd,
|
|
870
|
+
target_operation_id=trajectory.operation_id if trajectory is not None else None,
|
|
871
|
+
)
|
|
872
|
+
context.result, result_text = append_extra_context_to_result(
|
|
873
|
+
context.result,
|
|
874
|
+
result_text,
|
|
875
|
+
hook_decision.extra_context,
|
|
876
|
+
)
|
|
877
|
+
structured_error_kind = metadata.get(TOOL_ERROR_KIND_METADATA_KEY)
|
|
878
|
+
if not isinstance(context.metadata, dict):
|
|
879
|
+
context.metadata = {}
|
|
880
|
+
write_execution_stamp(
|
|
881
|
+
context.metadata,
|
|
882
|
+
context.arguments,
|
|
883
|
+
outcome="error" if errored or structured_failed else "ok",
|
|
884
|
+
error_kind=(
|
|
885
|
+
raised_error_kind
|
|
886
|
+
or (structured_error_kind if isinstance(structured_error_kind, str) else None)
|
|
887
|
+
),
|
|
888
|
+
)
|
|
889
|
+
result_images = extract_result_images(context.result)
|
|
890
|
+
await self._bus.publish(
|
|
891
|
+
InvocationToolCallResult(
|
|
892
|
+
origin=origin,
|
|
893
|
+
agent_name=self._agent_name,
|
|
894
|
+
tool_name=tool_name,
|
|
895
|
+
call_id=call_id,
|
|
896
|
+
result=result_text,
|
|
897
|
+
image_contents=result_images,
|
|
898
|
+
duration_ms=duration_ms,
|
|
899
|
+
metadata=metadata,
|
|
900
|
+
session_id=self._session_id,
|
|
901
|
+
)
|
|
902
|
+
)
|
|
903
|
+
if trajectory is not None:
|
|
904
|
+
# Bounded the way the kernel will bound it — see the
|
|
905
|
+
# same call in ``tool_events``.
|
|
906
|
+
await trajectory.payload_observed(
|
|
907
|
+
result_text=preview_result_ceiling(
|
|
908
|
+
result_text,
|
|
909
|
+
self._tool_result_ceiling_tokens,
|
|
910
|
+
observation=payload_observation,
|
|
911
|
+
),
|
|
912
|
+
image_count=len(result_images),
|
|
913
|
+
observation=payload_observation,
|
|
914
|
+
)
|
|
915
|
+
await trajectory.finished(
|
|
916
|
+
outcome=tool_outcome(
|
|
917
|
+
cancelled=False, rejected=rejected, errored=errored, result_metadata=metadata
|
|
918
|
+
),
|
|
919
|
+
duration_ms=elapsed_ms,
|
|
920
|
+
result_metadata=metadata,
|
|
921
|
+
error_kind=raised_error_kind,
|
|
922
|
+
)
|
|
923
|
+
await self._publish_progress()
|
|
924
|
+
except BaseException:
|
|
925
|
+
# Interrupted while closing out a call that already ran:
|
|
926
|
+
# the operation is open, and only this path can close it.
|
|
927
|
+
if trajectory is not None:
|
|
928
|
+
trajectory.finished_soon(outcome=ToolOutcome.INTERRUPTED, duration_ms=elapsed_ms)
|
|
929
|
+
raise
|
|
930
|
+
|
|
931
|
+
|
|
932
|
+
def _file_lock_path(tool_name: str, args: dict[str, Any], workspace_cwd: str = "") -> str:
|
|
933
|
+
"""Return a file path for write/edit serialization, or empty when absent."""
|
|
934
|
+
if tool_name not in _FILE_TOOLS:
|
|
935
|
+
return ""
|
|
936
|
+
path = args.get("path")
|
|
937
|
+
if not isinstance(path, str) or not path:
|
|
938
|
+
return ""
|
|
939
|
+
return resolve_workspace_path(path, base_cwd=workspace_cwd or None)
|
|
940
|
+
|
|
941
|
+
|
|
942
|
+
def _uses_implicit_window(tool_name: str, tool_kind: str) -> bool:
|
|
943
|
+
"""Return whether a tool needs serialized implicit mutation observation."""
|
|
944
|
+
return tool_kind == KIND_SHELL or tool_name in _IMPLICIT_WRITE_TOOLS
|
|
945
|
+
|
|
946
|
+
|
|
947
|
+
def _observe_task_exception(task: asyncio.Task[None]) -> None:
|
|
948
|
+
if task.cancelled():
|
|
949
|
+
return
|
|
950
|
+
with contextlib.suppress(Exception):
|
|
951
|
+
task.exception()
|