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,92 @@
|
|
|
1
|
+
# Copyright (c) Huawei Technologies Co., Ltd. 2026. All rights reserved.
|
|
2
|
+
|
|
3
|
+
"""Data envelope and node context of the workflow SDK (pure stdlib, Python 3.9)."""
|
|
4
|
+
|
|
5
|
+
from __future__ import annotations
|
|
6
|
+
|
|
7
|
+
from collections.abc import Awaitable, Callable, Sequence
|
|
8
|
+
from dataclasses import dataclass
|
|
9
|
+
from typing import Any, Optional, Union, overload
|
|
10
|
+
|
|
11
|
+
from ._ask import Answer, Question, answer_from_wire, questions_to_wire
|
|
12
|
+
|
|
13
|
+
# Strict recursive JSON. ``typing.Union`` is the one sanctioned exception to
|
|
14
|
+
# the modern-syntax rule: a runtime ``X | Y`` alias does not exist on 3.9.
|
|
15
|
+
JsonValue = Union[dict[str, "JsonValue"], list["JsonValue"], str, int, float, bool, None]
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
@dataclass(frozen=True)
|
|
19
|
+
class WorkflowValue:
|
|
20
|
+
"""The single envelope routed between nodes.
|
|
21
|
+
|
|
22
|
+
``text`` is what prompts, the TUI and logs consume; ``data`` is an optional
|
|
23
|
+
structured payload for program consumers. Serializability is checked at
|
|
24
|
+
the process boundary, not here, so the envelope stays a plain value.
|
|
25
|
+
"""
|
|
26
|
+
|
|
27
|
+
text: str
|
|
28
|
+
data: Optional[JsonValue] = None
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
@dataclass(frozen=True)
|
|
32
|
+
class SourceValue:
|
|
33
|
+
"""One resolved input of a fan-in node, in declared source order."""
|
|
34
|
+
|
|
35
|
+
node_id: str
|
|
36
|
+
activation_id: str
|
|
37
|
+
value: WorkflowValue
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
class NodeContext:
|
|
41
|
+
"""Per-activation context handed to ``fn(value, ctx)`` node bodies.
|
|
42
|
+
|
|
43
|
+
The worker host constructs it with the two callbacks wired to the wire
|
|
44
|
+
protocol; user code only calls :meth:`emit` and awaits :meth:`ask`.
|
|
45
|
+
"""
|
|
46
|
+
|
|
47
|
+
def __init__(
|
|
48
|
+
self,
|
|
49
|
+
*,
|
|
50
|
+
emit: Callable[[str], None],
|
|
51
|
+
ask: Callable[[list[dict[str, Any]]], Awaitable[list[dict[str, Any]]]],
|
|
52
|
+
) -> None:
|
|
53
|
+
self._emit = emit
|
|
54
|
+
self._ask = ask
|
|
55
|
+
|
|
56
|
+
def emit(self, text: str) -> None:
|
|
57
|
+
"""Publish a piece of process output for this activation."""
|
|
58
|
+
if not isinstance(text, str):
|
|
59
|
+
raise TypeError("ctx.emit() expects a str.")
|
|
60
|
+
self._emit(text)
|
|
61
|
+
|
|
62
|
+
@overload
|
|
63
|
+
async def ask(self, prompt: str) -> str: ...
|
|
64
|
+
|
|
65
|
+
@overload
|
|
66
|
+
async def ask(self, prompt: Question) -> Answer: ...
|
|
67
|
+
|
|
68
|
+
@overload
|
|
69
|
+
async def ask(self, prompt: Sequence[Question]) -> tuple[Answer, ...]: ...
|
|
70
|
+
|
|
71
|
+
async def ask(self, prompt: Union[str, Question, Sequence[Question]]) -> Union[str, Answer, tuple[Answer, ...]]:
|
|
72
|
+
"""Ask the person driving the run; only usable from an ``async def`` body.
|
|
73
|
+
|
|
74
|
+
A ``str`` asks one open question and returns the typed text. A
|
|
75
|
+
:class:`Question` returns one :class:`Answer`. A list or tuple of 1-5
|
|
76
|
+
questions shows them in one dialog and returns a tuple of answers in
|
|
77
|
+
the same order.
|
|
78
|
+
"""
|
|
79
|
+
if isinstance(prompt, str):
|
|
80
|
+
if not prompt.strip():
|
|
81
|
+
raise ValueError("ctx.ask() prompt must not be blank.")
|
|
82
|
+
answers = await self._ask_questions((Question(prompt),))
|
|
83
|
+
return answers[0].text
|
|
84
|
+
if isinstance(prompt, Question):
|
|
85
|
+
return (await self._ask_questions((prompt,)))[0]
|
|
86
|
+
if isinstance(prompt, (list, tuple)):
|
|
87
|
+
return await self._ask_questions(tuple(prompt))
|
|
88
|
+
raise TypeError("ctx.ask() expects a str, a Question, or a list or tuple of Questions.")
|
|
89
|
+
|
|
90
|
+
async def _ask_questions(self, questions: tuple[Question, ...]) -> tuple[Answer, ...]:
|
|
91
|
+
wire = questions_to_wire(questions)
|
|
92
|
+
return tuple(answer_from_wire(answer) for answer in await self._ask(wire))
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
# Copyright (c) Huawei Technologies Co., Ltd. 2026. All rights reserved.
|
|
2
|
+
|
|
3
|
+
"""The SDK artifact injected into a worker: a regular ``chrys`` package holding ``chrys.workflows``.
|
|
4
|
+
|
|
5
|
+
The SDK's single source is ``chrys.service.workflows.sdk``. A worker cannot
|
|
6
|
+
import that path (it runs in the user's interpreter, without chrys), so the
|
|
7
|
+
main process materializes a copy laid out as ``chrys/__init__.py`` +
|
|
8
|
+
``chrys/workflows/{__init__,_builder,_values}.py`` and the host prepends that
|
|
9
|
+
directory to ``sys.path``. The top-level ``__init__.py`` makes it a regular
|
|
10
|
+
package: a regular package on ``sys.path`` wins over any namespace portion or
|
|
11
|
+
later regular package, so a stale ``chrys`` in the user's environment cannot
|
|
12
|
+
capture the import. The host still verifies the import origin.
|
|
13
|
+
"""
|
|
14
|
+
|
|
15
|
+
from __future__ import annotations
|
|
16
|
+
|
|
17
|
+
import hashlib
|
|
18
|
+
import tempfile
|
|
19
|
+
from dataclasses import dataclass
|
|
20
|
+
from pathlib import Path
|
|
21
|
+
|
|
22
|
+
from chrys.foundation.platform.files import atomic_write_owner_only_bytes
|
|
23
|
+
from chrys.service.workflows import sdk as _sdk_package
|
|
24
|
+
|
|
25
|
+
SDK_SOURCE_DIR = Path(_sdk_package.__file__).resolve().parent
|
|
26
|
+
SDK_MODULES = ("__init__.py", "_ask.py", "_builder.py", "_values.py")
|
|
27
|
+
|
|
28
|
+
_PACKAGE_INIT = b'"""Injected by chrys: only ``chrys.workflows`` is supported inside a workflow worker."""\n'
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
@dataclass(frozen=True, slots=True)
|
|
32
|
+
class SdkArtifact:
|
|
33
|
+
"""A materialized artifact directory and the digest of the bytes it holds."""
|
|
34
|
+
|
|
35
|
+
path: Path
|
|
36
|
+
digest: str
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def sdk_artifact_digest() -> str:
|
|
40
|
+
"""SHA-256 over the artifact's relative paths and bytes, independent of where it is written."""
|
|
41
|
+
return _digest(_artifact_files())
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def _digest(files: list[tuple[str, bytes]]) -> str:
|
|
45
|
+
digest = hashlib.sha256()
|
|
46
|
+
for relative, payload in files:
|
|
47
|
+
digest.update(relative.encode("utf-8") + b"\0" + payload + b"\0")
|
|
48
|
+
return digest.hexdigest()
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
def materialize_sdk_artifact(root: Path) -> SdkArtifact:
|
|
52
|
+
"""Publish a complete, immutable artifact under its full content digest."""
|
|
53
|
+
files = _artifact_files()
|
|
54
|
+
digest = _digest(files)
|
|
55
|
+
root.mkdir(parents=True, exist_ok=True)
|
|
56
|
+
destination = root / digest
|
|
57
|
+
if not (destination / ".complete").is_file():
|
|
58
|
+
with tempfile.TemporaryDirectory(prefix=".sdk-", dir=root) as staging:
|
|
59
|
+
directory = Path(staging)
|
|
60
|
+
for relative, payload in files:
|
|
61
|
+
atomic_write_owner_only_bytes(directory / relative, payload)
|
|
62
|
+
atomic_write_owner_only_bytes(directory / ".complete", digest.encode("ascii"))
|
|
63
|
+
try:
|
|
64
|
+
directory.rename(destination)
|
|
65
|
+
except OSError:
|
|
66
|
+
if not (destination / ".complete").is_file():
|
|
67
|
+
raise
|
|
68
|
+
return SdkArtifact(path=destination, digest=digest)
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
def _artifact_files() -> list[tuple[str, bytes]]:
|
|
72
|
+
files = [("chrys/__init__.py", _PACKAGE_INIT)]
|
|
73
|
+
files.extend((f"chrys/workflows/{name}", (SDK_SOURCE_DIR / name).read_bytes()) for name in SDK_MODULES)
|
|
74
|
+
return files
|
|
@@ -0,0 +1,494 @@
|
|
|
1
|
+
# Copyright (c) Huawei Technologies Co., Ltd. 2026. All rights reserved.
|
|
2
|
+
|
|
3
|
+
"""One run's write-once listing header, immutable specification and log-owned terminal.
|
|
4
|
+
|
|
5
|
+
Large values, diagnostics and output identities live outside the bounded lifecycle
|
|
6
|
+
log. Payload identities use node/activation/request keys because trajectory envelopes
|
|
7
|
+
reserve *_id keys for analytics identities.
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
from __future__ import annotations
|
|
11
|
+
|
|
12
|
+
import asyncio
|
|
13
|
+
import errno
|
|
14
|
+
import hashlib
|
|
15
|
+
import json
|
|
16
|
+
import logging
|
|
17
|
+
import os
|
|
18
|
+
from collections.abc import Callable, Mapping, Sequence
|
|
19
|
+
from dataclasses import asdict, dataclass
|
|
20
|
+
from enum import StrEnum
|
|
21
|
+
from pathlib import Path
|
|
22
|
+
from typing import Any, Final
|
|
23
|
+
|
|
24
|
+
from chrys.foundation.models.workflow_session import WorkflowModelSelection
|
|
25
|
+
from chrys.foundation.platform.files import (
|
|
26
|
+
atomic_write_basename_budget,
|
|
27
|
+
atomic_write_owner_only_bytes,
|
|
28
|
+
read_owner_verified_bounded,
|
|
29
|
+
secure_open_owner_only_append,
|
|
30
|
+
)
|
|
31
|
+
from chrys.foundation.trajectory.envelope import EventDraft
|
|
32
|
+
from chrys.foundation.trajectory.event_types import KNOWN_EVENT_TYPES, RuntimeFinishReason
|
|
33
|
+
from chrys.foundation.trajectory.ids import new_analytics_id
|
|
34
|
+
from chrys.foundation.trajectory.keys import ensure_owner_only_directory
|
|
35
|
+
from chrys.foundation.trajectory.reader import TrajectoryReadResult, read_trajectory
|
|
36
|
+
from chrys.foundation.trajectory.writer import (
|
|
37
|
+
DEFAULT_WRITE_ACK_TIMEOUT_SECONDS,
|
|
38
|
+
EmitResult,
|
|
39
|
+
FdWriteBackend,
|
|
40
|
+
TrajectoryWriter,
|
|
41
|
+
WriteBackend,
|
|
42
|
+
)
|
|
43
|
+
from chrys.foundation.util.filenames import bounded_safe_stem
|
|
44
|
+
from chrys.service.workflows.graph import KIND_JOIN, KIND_PYTHON
|
|
45
|
+
from chrys.service.workflows.layout import (
|
|
46
|
+
EVENTS_FILE,
|
|
47
|
+
HEADER_FILE,
|
|
48
|
+
INPUT_FILE,
|
|
49
|
+
NODES_DIR,
|
|
50
|
+
OUTPUT_INDEX_FILE,
|
|
51
|
+
RUN_OUTPUT_FILE,
|
|
52
|
+
SOURCE_FILE,
|
|
53
|
+
SPEC_FILE,
|
|
54
|
+
)
|
|
55
|
+
from chrys.service.workflows.protocol import LIMITS
|
|
56
|
+
|
|
57
|
+
logger = logging.getLogger(__name__)
|
|
58
|
+
|
|
59
|
+
NODE_RECORD_INPUT: Final = "input"
|
|
60
|
+
NODE_RECORD_OUTPUT: Final = "output"
|
|
61
|
+
NODE_RECORD_DIAGNOSTICS: Final = "diagnostics"
|
|
62
|
+
NODE_RECORD_SESSION: Final = "session"
|
|
63
|
+
NODE_RECORD_USAGE: Final = "usage"
|
|
64
|
+
MAX_HEADER_BYTES: Final = 64 * 1024
|
|
65
|
+
INPUT_EXCERPT_CHARS: Final = 2000
|
|
66
|
+
MAX_SPEC_BYTES: Final = 16 * 1024 * 1024
|
|
67
|
+
MAX_INPUT_BYTES: Final = 16 * 1024 * 1024
|
|
68
|
+
# Serialized ceilings include JSON wrappers and worst-case control-character escaping.
|
|
69
|
+
MAX_PYTHON_VALUE_BYTES: Final = 6 * LIMITS.max_frame_bytes + 4096
|
|
70
|
+
MAX_JOIN_VALUE_BYTES: Final = 6 * LIMITS.max_join_retained_bytes + 4096
|
|
71
|
+
MAX_AGENT_VALUE_BYTES: Final = 128 * 1024 * 1024
|
|
72
|
+
MAX_EMITS_BYTES: Final = 6 * LIMITS.max_emit_bytes_per_attempt + 128 * LIMITS.max_emits_per_attempt
|
|
73
|
+
MAX_OUTPUT_INDEX_BYTES: Final = 16 * 1024 * 1024
|
|
74
|
+
MAX_RUN_OUTPUT_BYTES: Final = 1024 * 1024
|
|
75
|
+
MAX_DIAGNOSTICS_BYTES: Final = 1024 * 1024
|
|
76
|
+
RUN_RECORD_WRITE_ACK_TIMEOUT_SECONDS: Final = DEFAULT_WRITE_ACK_TIMEOUT_SECONDS
|
|
77
|
+
"""Bound on one run-record write, read when a store opens without its own.
|
|
78
|
+
|
|
79
|
+
Unlike the session trajectory, whose writer degrades and the turn goes on, a run
|
|
80
|
+
record that misses its ack fails the run as storage-failed: the record is the
|
|
81
|
+
run's source of truth. A host whose disk stalls for longer under fsync pressure
|
|
82
|
+
(a loaded test runner) widens this one name instead of every ``open`` call.
|
|
83
|
+
"""
|
|
84
|
+
"""Room for the worker's bounded stdout and traceback, including JSON escaping."""
|
|
85
|
+
NODE_RECORD_EMITS: Final = "emits"
|
|
86
|
+
"""The per-attempt log of ``ctx.emit`` texts in full, one JSON line ``{ordinal, text}`` each."""
|
|
87
|
+
DATA_DROPPED_KEY: Final = "data_dropped_at_agent_boundary"
|
|
88
|
+
"""Set on an agent activation's input record when its value carried ``data`` the agent boundary drops."""
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
class RunRecord(StrEnum):
|
|
92
|
+
"""Event types the run log carries."""
|
|
93
|
+
|
|
94
|
+
RUN_STARTED = "workflow.log.run.started"
|
|
95
|
+
NODE_STATE = "workflow.log.node.state"
|
|
96
|
+
NODE_OUTPUT = "workflow.log.node.output"
|
|
97
|
+
NODE_ASK = "workflow.log.node.ask"
|
|
98
|
+
NODE_ANSWER = "workflow.log.node.answer"
|
|
99
|
+
LOOP_ITERATION = "workflow.log.loop.iteration"
|
|
100
|
+
RUN_NOTICE = "workflow.log.run.notice"
|
|
101
|
+
RETRY_KEY = "workflow.log.retry.key"
|
|
102
|
+
RUN_FINISHED = "workflow.log.run.finished"
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
WORKFLOW_EVENT_TYPES: Final = frozenset(RunRecord)
|
|
106
|
+
|
|
107
|
+
RUN_KNOWN_EVENT_TYPES: Final = KNOWN_EVENT_TYPES | WORKFLOW_EVENT_TYPES
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
class WorkflowStorageFailed(RuntimeError):
|
|
111
|
+
"""The run record can no longer be trusted; the run must stop."""
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
@dataclass(frozen=True, slots=True)
|
|
115
|
+
class RunHeader:
|
|
116
|
+
"""Small, immutable listing metadata in ``run.json``."""
|
|
117
|
+
|
|
118
|
+
run_id: str
|
|
119
|
+
session_id: str
|
|
120
|
+
workflow_id: str
|
|
121
|
+
source_kind: str
|
|
122
|
+
canonical_path: str
|
|
123
|
+
title: str
|
|
124
|
+
input_excerpt: str
|
|
125
|
+
entry_digest: str
|
|
126
|
+
manifest_digest: str
|
|
127
|
+
schema_version: int
|
|
128
|
+
spec_digest: str
|
|
129
|
+
started_at: str = ""
|
|
130
|
+
mode: str = ""
|
|
131
|
+
model: WorkflowModelSelection | None = None
|
|
132
|
+
|
|
133
|
+
def to_dict(self) -> dict[str, Any]:
|
|
134
|
+
return {
|
|
135
|
+
"run_id": self.run_id,
|
|
136
|
+
"session_id": self.session_id,
|
|
137
|
+
"workflow_id": self.workflow_id,
|
|
138
|
+
"source_kind": self.source_kind,
|
|
139
|
+
"canonical_path": self.canonical_path,
|
|
140
|
+
"title": self.title,
|
|
141
|
+
"input_excerpt": self.input_excerpt[:INPUT_EXCERPT_CHARS],
|
|
142
|
+
"entry_digest": self.entry_digest,
|
|
143
|
+
"manifest_digest": self.manifest_digest,
|
|
144
|
+
"schema_version": self.schema_version,
|
|
145
|
+
"spec_digest": self.spec_digest,
|
|
146
|
+
"started_at": self.started_at,
|
|
147
|
+
"mode": self.mode,
|
|
148
|
+
"model": asdict(self.model) if self.model is not None else None,
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
|
|
152
|
+
@dataclass(frozen=True, slots=True)
|
|
153
|
+
class RunSpec:
|
|
154
|
+
"""The immutable definition and resolution snapshot loaded only for replay or details."""
|
|
155
|
+
|
|
156
|
+
manifest: Mapping[str, Any]
|
|
157
|
+
environment: Mapping[str, Any]
|
|
158
|
+
resolved_nodes: Sequence[Mapping[str, Any]] = ()
|
|
159
|
+
|
|
160
|
+
def to_dict(self) -> dict[str, Any]:
|
|
161
|
+
return {
|
|
162
|
+
"manifest": dict(self.manifest),
|
|
163
|
+
"environment": dict(self.environment),
|
|
164
|
+
"resolved_nodes": [dict(node) for node in self.resolved_nodes],
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
|
|
168
|
+
BackendFactory = Callable[[int], WriteBackend]
|
|
169
|
+
|
|
170
|
+
|
|
171
|
+
@dataclass(frozen=True, slots=True)
|
|
172
|
+
class RunTerminal:
|
|
173
|
+
"""The validated terminal facts owned exclusively by the lifecycle log."""
|
|
174
|
+
|
|
175
|
+
outcome: str
|
|
176
|
+
last_seq: int
|
|
177
|
+
reason: str = ""
|
|
178
|
+
finished_at: str = ""
|
|
179
|
+
|
|
180
|
+
|
|
181
|
+
class WorkflowRunStore:
|
|
182
|
+
"""Writer side of one run directory; open with :meth:`open`."""
|
|
183
|
+
|
|
184
|
+
def __init__(
|
|
185
|
+
self, run_dir: Path, header: RunHeader, spec: RunSpec, input_text: str, writer: TrajectoryWriter
|
|
186
|
+
) -> None:
|
|
187
|
+
self._run_dir = run_dir
|
|
188
|
+
self._header = header
|
|
189
|
+
self.spec = spec
|
|
190
|
+
self.input_text = input_text
|
|
191
|
+
self._writer = writer
|
|
192
|
+
self._last_written = 0
|
|
193
|
+
self._closing: asyncio.Task[bool] | None = None
|
|
194
|
+
|
|
195
|
+
@classmethod
|
|
196
|
+
def open(
|
|
197
|
+
cls,
|
|
198
|
+
run_dir: Path,
|
|
199
|
+
*,
|
|
200
|
+
header: RunHeader,
|
|
201
|
+
spec: RunSpec,
|
|
202
|
+
input_text: str,
|
|
203
|
+
source: bytes,
|
|
204
|
+
backend_factory: BackendFactory | None = None,
|
|
205
|
+
write_ack_timeout: float | None = None,
|
|
206
|
+
) -> WorkflowRunStore:
|
|
207
|
+
"""Create the directory (owner-only), write header and source, and start the log writer.
|
|
208
|
+
|
|
209
|
+
``write_ack_timeout`` defaults to :data:`RUN_RECORD_WRITE_ACK_TIMEOUT_SECONDS` as it stands when the store opens.
|
|
210
|
+
"""
|
|
211
|
+
try:
|
|
212
|
+
ensure_owner_only_directory(run_dir)
|
|
213
|
+
ensure_owner_only_directory(run_dir / NODES_DIR)
|
|
214
|
+
atomic_write_owner_only_bytes(run_dir / SOURCE_FILE, source)
|
|
215
|
+
_write_bounded_json(run_dir / SPEC_FILE, spec.to_dict(), MAX_SPEC_BYTES)
|
|
216
|
+
encoded_input = input_text.encode("utf-8", errors="surrogatepass")
|
|
217
|
+
if len(encoded_input) > MAX_INPUT_BYTES:
|
|
218
|
+
raise ValueError("Workflow input exceeds the size limit.")
|
|
219
|
+
atomic_write_owner_only_bytes(run_dir / INPUT_FILE, encoded_input)
|
|
220
|
+
_write_bounded_json(run_dir / HEADER_FILE, header.to_dict(), MAX_HEADER_BYTES)
|
|
221
|
+
handle = secure_open_owner_only_append(run_dir / EVENTS_FILE)
|
|
222
|
+
except (OSError, ValueError, TypeError) as exc:
|
|
223
|
+
raise WorkflowStorageFailed(f"Cannot create the run record under {run_dir}: {exc}") from exc
|
|
224
|
+
make_backend: BackendFactory = backend_factory or FdWriteBackend
|
|
225
|
+
writer = TrajectoryWriter(
|
|
226
|
+
backend=make_backend(handle.fd),
|
|
227
|
+
session_id=header.session_id,
|
|
228
|
+
runtime_id=header.run_id,
|
|
229
|
+
coverage_id=new_analytics_id(),
|
|
230
|
+
branch_id=new_analytics_id(),
|
|
231
|
+
write_ack_timeout=RUN_RECORD_WRITE_ACK_TIMEOUT_SECONDS if write_ack_timeout is None else write_ack_timeout,
|
|
232
|
+
thread_name=f"chrys-workflow-run-{header.run_id[:8]}",
|
|
233
|
+
)
|
|
234
|
+
writer.start()
|
|
235
|
+
return cls(run_dir, header, spec, input_text, writer)
|
|
236
|
+
|
|
237
|
+
@property
|
|
238
|
+
def run_dir(self) -> Path:
|
|
239
|
+
return self._run_dir
|
|
240
|
+
|
|
241
|
+
@property
|
|
242
|
+
def header(self) -> RunHeader:
|
|
243
|
+
return self._header
|
|
244
|
+
|
|
245
|
+
@property
|
|
246
|
+
def last_written_seq(self) -> int:
|
|
247
|
+
return self._last_written
|
|
248
|
+
|
|
249
|
+
async def append(self, event_type: str, payload: Mapping[str, Any], *, durable: bool = False) -> int:
|
|
250
|
+
"""Append one lifecycle record; returns its sequence once it is in the file.
|
|
251
|
+
|
|
252
|
+
``durable`` follows the record with a checkpoint and fsync. Anything
|
|
253
|
+
but WRITTEN raises :class:`WorkflowStorageFailed`.
|
|
254
|
+
"""
|
|
255
|
+
if event_type not in WORKFLOW_EVENT_TYPES:
|
|
256
|
+
raise ValueError(f"{event_type!r} is not a workflow event type.")
|
|
257
|
+
if self._closing is not None:
|
|
258
|
+
raise WorkflowStorageFailed("the run record is closed.")
|
|
259
|
+
submitted = self._writer.submit(EventDraft(event_type=event_type, payload=payload))
|
|
260
|
+
outcome = await self._writer.wait(submitted)
|
|
261
|
+
result = submitted.result
|
|
262
|
+
if outcome is not EmitResult.WRITTEN or isinstance(result, EmitResult):
|
|
263
|
+
raise WorkflowStorageFailed(self._failure(f"{event_type} was not written"))
|
|
264
|
+
self._last_written = result.sequence
|
|
265
|
+
if durable and await self._writer.checkpoint() is not EmitResult.WRITTEN:
|
|
266
|
+
raise WorkflowStorageFailed(self._failure(f"{event_type} could not be made durable"))
|
|
267
|
+
return result.sequence
|
|
268
|
+
|
|
269
|
+
def write_node_value(self, activation_id: str, attempt: int, kind: str, payload: Mapping[str, Any]) -> Path:
|
|
270
|
+
"""Persist a full value under ``nodes/``; returns the file written."""
|
|
271
|
+
path = node_value_path(self._run_dir, activation_id, attempt, kind)
|
|
272
|
+
try:
|
|
273
|
+
atomic_write_owner_only_bytes(path, _json_bytes(dict(payload)), create_parents=False)
|
|
274
|
+
except (OSError, TypeError, ValueError) as exc:
|
|
275
|
+
raise WorkflowStorageFailed(f"Cannot write {path.name}: {exc}") from exc
|
|
276
|
+
return path
|
|
277
|
+
|
|
278
|
+
def append_node_emit(self, activation_id: str, attempt: int, ordinal: int, text: str) -> None:
|
|
279
|
+
"""Append one ``ctx.emit`` in full to the attempt's emit log under ``nodes/``."""
|
|
280
|
+
path = node_emits_path(self._run_dir, activation_id, attempt)
|
|
281
|
+
try:
|
|
282
|
+
line = json.dumps({"ordinal": ordinal, "text": text}, ensure_ascii=False, sort_keys=True)
|
|
283
|
+
payload = (line + "\n").encode("utf-8", errors="backslashreplace")
|
|
284
|
+
handle = secure_open_owner_only_append(path)
|
|
285
|
+
try:
|
|
286
|
+
while payload:
|
|
287
|
+
payload = payload[os.write(handle.fd, payload) :]
|
|
288
|
+
finally:
|
|
289
|
+
os.close(handle.fd)
|
|
290
|
+
except (OSError, TypeError, ValueError) as exc:
|
|
291
|
+
raise WorkflowStorageFailed(f"Cannot append to {path.name}: {exc}") from exc
|
|
292
|
+
|
|
293
|
+
def write_node_diagnostics(
|
|
294
|
+
self,
|
|
295
|
+
activation_id: str,
|
|
296
|
+
attempt: int,
|
|
297
|
+
*,
|
|
298
|
+
phase: str,
|
|
299
|
+
iteration: int,
|
|
300
|
+
stdout: str = "",
|
|
301
|
+
truncated: bool = False,
|
|
302
|
+
traceback: str = "",
|
|
303
|
+
) -> None:
|
|
304
|
+
"""Retain diagnostics by phase and iteration; these best-effort records never decide the outcome."""
|
|
305
|
+
if not stdout and not truncated and not traceback:
|
|
306
|
+
return
|
|
307
|
+
try:
|
|
308
|
+
record = read_node_diagnostics(self._run_dir, activation_id, attempt) or {"phases": []}
|
|
309
|
+
phases = record.get("phases")
|
|
310
|
+
if not isinstance(phases, list):
|
|
311
|
+
raise ValueError("diagnostics phases must be a list")
|
|
312
|
+
diagnostics = {
|
|
313
|
+
"phase": phase,
|
|
314
|
+
"iteration": iteration,
|
|
315
|
+
"stdout": {"text": stdout, "truncated": truncated},
|
|
316
|
+
"traceback": traceback,
|
|
317
|
+
}
|
|
318
|
+
phases.append(diagnostics)
|
|
319
|
+
if len(_json_bytes(record)) > MAX_DIAGNOSTICS_BYTES:
|
|
320
|
+
raise ValueError("diagnostics exceed the record size limit")
|
|
321
|
+
self.write_node_value(activation_id, attempt, NODE_RECORD_DIAGNOSTICS, record)
|
|
322
|
+
except OSError, ValueError, TypeError, WorkflowStorageFailed:
|
|
323
|
+
logger.warning(
|
|
324
|
+
"workflow diagnostics for %s attempt %s could not be written", activation_id, attempt, exc_info=True
|
|
325
|
+
)
|
|
326
|
+
|
|
327
|
+
async def finish(self, outcome: str, payload: Mapping[str, Any]) -> int:
|
|
328
|
+
"""Commit the only authoritative terminal; the header is never rewritten."""
|
|
329
|
+
return await self.append(RunRecord.RUN_FINISHED, {"outcome": outcome, **payload}, durable=True)
|
|
330
|
+
|
|
331
|
+
async def write_outputs(self, outputs: Sequence[Mapping[str, Any]]) -> None:
|
|
332
|
+
await self.offload(self.write_output_index, outputs)
|
|
333
|
+
|
|
334
|
+
async def offload(self, write: Callable[..., Any], *args: Any, **kwargs: Any) -> None:
|
|
335
|
+
"""Drain the thread before propagating cancellation or allowing terminal/close."""
|
|
336
|
+
task = asyncio.create_task(asyncio.to_thread(write, *args, **kwargs))
|
|
337
|
+
cancelled = None
|
|
338
|
+
while not task.done():
|
|
339
|
+
try:
|
|
340
|
+
await asyncio.shield(task)
|
|
341
|
+
except asyncio.CancelledError as exc:
|
|
342
|
+
cancelled = exc
|
|
343
|
+
task.result()
|
|
344
|
+
if cancelled is not None:
|
|
345
|
+
raise cancelled
|
|
346
|
+
|
|
347
|
+
def write_output_index(self, outputs: Sequence[Mapping[str, Any]]) -> None:
|
|
348
|
+
"""Commit exact declared output identities before the terminal that references them."""
|
|
349
|
+
try:
|
|
350
|
+
_write_bounded_json(self._run_dir / OUTPUT_INDEX_FILE, {"outputs": list(outputs)}, MAX_OUTPUT_INDEX_BYTES)
|
|
351
|
+
except (OSError, TypeError, ValueError) as exc:
|
|
352
|
+
raise WorkflowStorageFailed(f"Cannot write output index: {exc}") from exc
|
|
353
|
+
|
|
354
|
+
def write_run_output(self, payload: Mapping[str, Any]) -> None:
|
|
355
|
+
"""Best-effort bounded load/native diagnostics, outside the terminal record."""
|
|
356
|
+
_write_bounded_json(self._run_dir / RUN_OUTPUT_FILE, payload, MAX_RUN_OUTPUT_BYTES)
|
|
357
|
+
|
|
358
|
+
async def close(self) -> bool:
|
|
359
|
+
"""Close the log (runtime markers + fsync); idempotent. False when the runtime stays unclosed."""
|
|
360
|
+
if self._closing is None: # one close; every caller, concurrent or late, gets its verdict
|
|
361
|
+
self._closing = asyncio.create_task(
|
|
362
|
+
self._writer.close(reason=RuntimeFinishReason.GRACEFUL_SHUTDOWN), name="chrys.workflow.store.close"
|
|
363
|
+
)
|
|
364
|
+
return await asyncio.shield(self._closing) # a cancelled waiter must not take the close down with it
|
|
365
|
+
|
|
366
|
+
def _failure(self, what: str) -> str:
|
|
367
|
+
reason = self._writer.snapshot().degraded_reason
|
|
368
|
+
return f"{what} ({reason})" if reason else what
|
|
369
|
+
|
|
370
|
+
|
|
371
|
+
def node_value_path(run_dir: Path, activation_id: str, attempt: int, kind: str) -> Path:
|
|
372
|
+
"""The ``nodes/`` file for one (activation, attempt, kind); the same function names it for reads."""
|
|
373
|
+
return _node_file(run_dir, activation_id, attempt, kind, ".json")
|
|
374
|
+
|
|
375
|
+
|
|
376
|
+
def node_emits_path(run_dir: Path, activation_id: str, attempt: int) -> Path:
|
|
377
|
+
"""The ``nodes/`` emit log of one attempt (see :data:`NODE_RECORD_EMITS`)."""
|
|
378
|
+
return _node_file(run_dir, activation_id, attempt, NODE_RECORD_EMITS, ".jsonl")
|
|
379
|
+
|
|
380
|
+
|
|
381
|
+
def _node_file(run_dir: Path, activation_id: str, attempt: int, kind: str, suffix: str) -> Path:
|
|
382
|
+
identity = f"{activation_id}.{attempt}.{kind}"
|
|
383
|
+
# Sanitising can fold distinct ids together (``a:b`` / ``a_b``, case-insensitive
|
|
384
|
+
# filesystems): a digest of the raw identity keeps every file distinct.
|
|
385
|
+
digest = hashlib.sha256(identity.encode("utf-8", "surrogatepass")).hexdigest()[:8]
|
|
386
|
+
stem = bounded_safe_stem(f"{identity}.{digest}", suffix=suffix, max_filename_bytes=atomic_write_basename_budget())
|
|
387
|
+
return run_dir / NODES_DIR / f"{stem}{suffix}"
|
|
388
|
+
|
|
389
|
+
|
|
390
|
+
def read_node_value(
|
|
391
|
+
run_dir: Path, activation_id: str, attempt: int, kind: str, *, node_kind: str = ""
|
|
392
|
+
) -> dict[str, Any] | None:
|
|
393
|
+
"""The stored record for one (activation, attempt, kind), or ``None`` when it was never written."""
|
|
394
|
+
path = node_value_path(run_dir, activation_id, attempt, kind)
|
|
395
|
+
return _optional_json(path, node_record_limit(kind, node_kind=node_kind))
|
|
396
|
+
|
|
397
|
+
|
|
398
|
+
def read_node_emits(run_dir: Path, activation_id: str, attempt: int) -> list[tuple[int, str]]:
|
|
399
|
+
"""Every ``(ordinal, text)`` the attempt emitted, in log order; a torn tail ends the readable prefix."""
|
|
400
|
+
try:
|
|
401
|
+
raw = read_owner_verified_bounded(node_emits_path(run_dir, activation_id, attempt), max_bytes=MAX_EMITS_BYTES)
|
|
402
|
+
except OSError as exc:
|
|
403
|
+
if exc.errno in (errno.ENOENT, errno.ENOTDIR):
|
|
404
|
+
return []
|
|
405
|
+
raise
|
|
406
|
+
emits: list[tuple[int, str]] = []
|
|
407
|
+
for line in raw.split(b"\n"):
|
|
408
|
+
if not line:
|
|
409
|
+
continue
|
|
410
|
+
try:
|
|
411
|
+
record = json.loads(line)
|
|
412
|
+
except ValueError:
|
|
413
|
+
break
|
|
414
|
+
if not isinstance(record, dict):
|
|
415
|
+
break
|
|
416
|
+
ordinal, text = record.get("ordinal"), record.get("text")
|
|
417
|
+
if not isinstance(ordinal, int) or not isinstance(text, str):
|
|
418
|
+
break
|
|
419
|
+
emits.append((ordinal, text))
|
|
420
|
+
return emits
|
|
421
|
+
|
|
422
|
+
|
|
423
|
+
def read_node_diagnostics(run_dir: Path, activation_id: str, attempt: int) -> dict[str, Any] | None:
|
|
424
|
+
"""Captured stdout (text and truncation flag) and traceback, when the attempt produced them."""
|
|
425
|
+
path = node_value_path(run_dir, activation_id, attempt, NODE_RECORD_DIAGNOSTICS)
|
|
426
|
+
return _optional_json(path, MAX_DIAGNOSTICS_BYTES)
|
|
427
|
+
|
|
428
|
+
|
|
429
|
+
def read_run_events(run_dir: Path) -> TrajectoryReadResult:
|
|
430
|
+
"""Decode ``events.jsonl`` with workflow event types counted as known."""
|
|
431
|
+
return read_trajectory(run_dir / EVENTS_FILE, known_event_types=RUN_KNOWN_EVENT_TYPES)
|
|
432
|
+
|
|
433
|
+
|
|
434
|
+
def read_run_header(run_dir: Path) -> dict[str, Any]:
|
|
435
|
+
return read_json_object(run_dir / HEADER_FILE, MAX_HEADER_BYTES)
|
|
436
|
+
|
|
437
|
+
|
|
438
|
+
def read_run_spec(run_dir: Path) -> dict[str, Any]:
|
|
439
|
+
return read_json_object(run_dir / SPEC_FILE, MAX_SPEC_BYTES)
|
|
440
|
+
|
|
441
|
+
|
|
442
|
+
def read_run_input(run_dir: Path) -> str:
|
|
443
|
+
return read_owner_verified_bounded(run_dir / INPUT_FILE, max_bytes=MAX_INPUT_BYTES).decode("utf-8", "surrogatepass")
|
|
444
|
+
|
|
445
|
+
|
|
446
|
+
def read_run_output(run_dir: Path) -> dict[str, Any] | None:
|
|
447
|
+
return _optional_json(run_dir / RUN_OUTPUT_FILE, MAX_RUN_OUTPUT_BYTES)
|
|
448
|
+
|
|
449
|
+
|
|
450
|
+
def node_record_limit(kind: str, *, node_kind: str = "") -> int:
|
|
451
|
+
"""Record-kind limits admit joins and agent text independently of worker frame ceilings."""
|
|
452
|
+
if kind == NODE_RECORD_DIAGNOSTICS:
|
|
453
|
+
return MAX_DIAGNOSTICS_BYTES
|
|
454
|
+
if kind == NODE_RECORD_USAGE:
|
|
455
|
+
return 4096
|
|
456
|
+
if kind in {NODE_RECORD_INPUT, NODE_RECORD_OUTPUT}:
|
|
457
|
+
if node_kind == KIND_PYTHON:
|
|
458
|
+
return MAX_PYTHON_VALUE_BYTES
|
|
459
|
+
if node_kind == KIND_JOIN:
|
|
460
|
+
return MAX_JOIN_VALUE_BYTES
|
|
461
|
+
return MAX_AGENT_VALUE_BYTES
|
|
462
|
+
|
|
463
|
+
|
|
464
|
+
def read_json_object(path: Path, max_bytes: int) -> dict[str, Any]:
|
|
465
|
+
record = json.loads(read_owner_verified_bounded(path, max_bytes=max_bytes))
|
|
466
|
+
if not isinstance(record, dict):
|
|
467
|
+
raise ValueError(f"{path.name} must be a JSON object.")
|
|
468
|
+
return record
|
|
469
|
+
|
|
470
|
+
|
|
471
|
+
def _optional_json(path: Path, max_bytes: int) -> dict[str, Any] | None:
|
|
472
|
+
try:
|
|
473
|
+
return read_json_object(path, max_bytes)
|
|
474
|
+
except OSError as exc:
|
|
475
|
+
if exc.errno in (errno.ENOENT, errno.ENOTDIR):
|
|
476
|
+
return None
|
|
477
|
+
raise
|
|
478
|
+
|
|
479
|
+
|
|
480
|
+
def _write_bounded_json(path: Path, payload: Mapping[str, Any], max_bytes: int) -> None:
|
|
481
|
+
encoded = _json_bytes(payload)
|
|
482
|
+
if len(encoded) > max_bytes:
|
|
483
|
+
raise ValueError(f"{path.name} exceeds the {max_bytes}-byte ceiling")
|
|
484
|
+
atomic_write_owner_only_bytes(path, encoded, create_parents=False)
|
|
485
|
+
|
|
486
|
+
|
|
487
|
+
def node_stderr_path(run_dir: Path, activation_id: str) -> Path:
|
|
488
|
+
return _node_file(run_dir, activation_id, 0, "acp-stderr", ".log")
|
|
489
|
+
|
|
490
|
+
|
|
491
|
+
def _json_bytes(payload: Mapping[str, Any]) -> bytes:
|
|
492
|
+
# As the trajectory writer encodes: a lone surrogate (a surrogateescaped path in the environment) becomes its
|
|
493
|
+
# JSON escape instead of raising, and reads back as the same str because json.dumps escaped every real backslash.
|
|
494
|
+
return json.dumps(payload, ensure_ascii=False, sort_keys=True, indent=1).encode("utf-8", errors="backslashreplace")
|