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,841 @@
|
|
|
1
|
+
# Copyright (c) Microsoft. All rights reserved.
|
|
2
|
+
# Copyright (c) Huawei Technologies Co., Ltd. 2026. All rights reserved.
|
|
3
|
+
# Contains code adapted from Microsoft Agent Framework (MIT License; see NOTICE).
|
|
4
|
+
|
|
5
|
+
"""Chrys skills context provider.
|
|
6
|
+
|
|
7
|
+
Owns the full skills surface on top of the chrys skill model
|
|
8
|
+
(:mod:`chrys.service.skills.model`):
|
|
9
|
+
|
|
10
|
+
1. Static skill instructions and the three stable skill tools
|
|
11
|
+
(``load_skill`` / ``read_skill_resource`` / ``run_skill_script``)
|
|
12
|
+
injected on every run.
|
|
13
|
+
2. Volatile runtime skill catalog (names, descriptions, revisions, skill
|
|
14
|
+
directories) rendered into system reminders once per user turn.
|
|
15
|
+
3. ``run_skill_script`` with positional ``arguments`` and explicit ``cwd``
|
|
16
|
+
parameters, routed through chrys's :class:`SubprocessScriptRunner`,
|
|
17
|
+
plus fuzzy script-name suggestions on a miss.
|
|
18
|
+
"""
|
|
19
|
+
|
|
20
|
+
from __future__ import annotations
|
|
21
|
+
|
|
22
|
+
import asyncio
|
|
23
|
+
import hashlib
|
|
24
|
+
import inspect
|
|
25
|
+
import logging
|
|
26
|
+
from dataclasses import dataclass, field
|
|
27
|
+
from difflib import get_close_matches
|
|
28
|
+
from html import escape as xml_escape
|
|
29
|
+
from pathlib import Path
|
|
30
|
+
from typing import TYPE_CHECKING, Any, ClassVar
|
|
31
|
+
|
|
32
|
+
from chrys.foundation.events.types import RuntimeSkillDetails
|
|
33
|
+
from chrys.foundation.platform.files import surrogate_safe_text
|
|
34
|
+
from chrys.foundation.platform.paths import resolve_cross_platform_path
|
|
35
|
+
from chrys.foundation.text.tokenizer import MixedLanguageTokenizer
|
|
36
|
+
from chrys.foundation.text.tool_output import truncate_output
|
|
37
|
+
from chrys.foundation.tool_call_context import set_tool_context_builder
|
|
38
|
+
from chrys.foundation.tool_kinds import KIND_SKILL, set_tool_kind
|
|
39
|
+
from chrys.kernel import ContextProvider, FunctionTool
|
|
40
|
+
from chrys.service.skills.constants import (
|
|
41
|
+
DEFAULT_RESOURCE_MAX_TOKENS,
|
|
42
|
+
DEFAULT_SCRIPT_RESULT_MAX_TOKENS,
|
|
43
|
+
RUN_SKILL_SCRIPT_TOOL_NAME,
|
|
44
|
+
)
|
|
45
|
+
from chrys.service.skills.loader import is_contained_skill_path
|
|
46
|
+
from chrys.service.skills.model import Skill, SkillResource, SkillScript
|
|
47
|
+
from chrys.service.tools.result_metadata import tool_error
|
|
48
|
+
|
|
49
|
+
if TYPE_CHECKING:
|
|
50
|
+
from collections.abc import Awaitable, Callable, Mapping, Sequence
|
|
51
|
+
|
|
52
|
+
from chrys.service.skills.model import SkillProviderWarning, SkillScriptRunner
|
|
53
|
+
|
|
54
|
+
logger = logging.getLogger(__name__)
|
|
55
|
+
|
|
56
|
+
_tokenizer = MixedLanguageTokenizer()
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
# Inserted as the {runner_instructions} value of SKILLS_STATIC_PROMPT.format(...);
|
|
60
|
+
# format values are never re-formatted, so braces here are literal prompt text
|
|
61
|
+
# and must stay single.
|
|
62
|
+
_SCRIPT_RUNNER_INSTRUCTIONS = """
|
|
63
|
+
- Use `run_skill_script` to run referenced scripts, using the name exactly as listed.
|
|
64
|
+
- File-based script names are relative paths from the skill directory. For a script in the skill's `scripts`
|
|
65
|
+
directory, pass `script_name: "scripts/{skill_script_name}.py"`, not `"{skill_script_name}.py"`.
|
|
66
|
+
- Use forward slashes in `script_name` exactly as listed, including on Windows.
|
|
67
|
+
- Pass the exact ordered script tokens inside `arguments` (e.g. `arguments: ["input.txt", "output.txt"]`).
|
|
68
|
+
- Use `arguments` for anything order-sensitive: subcommands, short flags, repeated flags, global flags
|
|
69
|
+
before a subcommand, or `--` passthrough.
|
|
70
|
+
- Use `args` only as optional sugar for flat, order-insensitive CLI flags
|
|
71
|
+
(e.g. `args: {"length": 24}` appends `--length 24` after `arguments`).
|
|
72
|
+
- Do not pass script arguments as top-level tool parameters.
|
|
73
|
+
"""
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
def _catalog_skill_dir(skill: Skill) -> str | None:
|
|
77
|
+
"""Return an absolute, platform-aware skill directory string for prompt display.
|
|
78
|
+
|
|
79
|
+
Inline skills have no filesystem directory, so the catalog hides the
|
|
80
|
+
``<skill_dir>`` element for them.
|
|
81
|
+
"""
|
|
82
|
+
if not skill.path or not skill.path.strip():
|
|
83
|
+
return None
|
|
84
|
+
return resolve_cross_platform_path(skill.path)
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
@dataclass(frozen=True)
|
|
88
|
+
class StagedSkillRefresh:
|
|
89
|
+
"""Discovered skill state that has not yet been committed to the provider cache."""
|
|
90
|
+
|
|
91
|
+
skills: list[Skill]
|
|
92
|
+
warnings: list[SkillProviderWarning] = field(default_factory=list)
|
|
93
|
+
|
|
94
|
+
def __post_init__(self) -> None:
|
|
95
|
+
# Fix each staged skill's revision at staging time — before any tool
|
|
96
|
+
# body can run — so catalog rendering and persisted provenance agree.
|
|
97
|
+
_warm_skill_revisions(self.skills)
|
|
98
|
+
|
|
99
|
+
def skill_names(self) -> list[str]:
|
|
100
|
+
"""Return staged skill names in source order."""
|
|
101
|
+
return [skill.name for skill in self.skills]
|
|
102
|
+
|
|
103
|
+
def skill_sources(self) -> dict[str, list[str]]:
|
|
104
|
+
"""Return staged skill names grouped by source directory."""
|
|
105
|
+
sources: dict[str, list[str]] = {}
|
|
106
|
+
for skill in self.skills:
|
|
107
|
+
source = _catalog_skill_dir(skill) or "Inline profile skills"
|
|
108
|
+
sources.setdefault(source, []).append(skill.name)
|
|
109
|
+
return sources
|
|
110
|
+
|
|
111
|
+
def skill_details(self) -> list[RuntimeSkillDetails]:
|
|
112
|
+
"""Return staged runtime skill metadata."""
|
|
113
|
+
return _runtime_skill_details(self.skills)
|
|
114
|
+
|
|
115
|
+
def render_catalog_reminder(self) -> str:
|
|
116
|
+
"""Return the staged runtime skill catalog for a system reminder."""
|
|
117
|
+
return _render_catalog_block(self.skills)
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
def _runtime_skill_details(skills: Sequence[Skill]) -> list[RuntimeSkillDetails]:
|
|
121
|
+
"""Describe *skills* for display and slash-reference reminders, which may reach the model."""
|
|
122
|
+
return [
|
|
123
|
+
RuntimeSkillDetails(
|
|
124
|
+
name=skill.name,
|
|
125
|
+
description=surrogate_safe_text(skill.description or ""),
|
|
126
|
+
source=surrogate_safe_text(_catalog_skill_dir(skill) or "Inline profile skills"),
|
|
127
|
+
)
|
|
128
|
+
for skill in skills
|
|
129
|
+
]
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
def _create_static_instructions(
|
|
133
|
+
prompt_template: str | None,
|
|
134
|
+
) -> str | None:
|
|
135
|
+
"""Create the stable skill instructions injected into the system prompt."""
|
|
136
|
+
if prompt_template is None:
|
|
137
|
+
return None
|
|
138
|
+
|
|
139
|
+
try:
|
|
140
|
+
result = prompt_template.format(runner_instructions="__EXEC_PROBE__")
|
|
141
|
+
except (KeyError, IndexError, ValueError) as exc:
|
|
142
|
+
raise ValueError(
|
|
143
|
+
"The provided instruction_template is not a valid format string. "
|
|
144
|
+
"Escape any literal '{' or '}' by doubling them ('{{' or '}}')."
|
|
145
|
+
) from exc
|
|
146
|
+
if "__EXEC_PROBE__" not in result:
|
|
147
|
+
raise ValueError("The provided instruction_template must contain a '{runner_instructions}' placeholder.")
|
|
148
|
+
|
|
149
|
+
return prompt_template.format(runner_instructions=_SCRIPT_RUNNER_INSTRUCTIONS)
|
|
150
|
+
|
|
151
|
+
|
|
152
|
+
def _file_signature(path: str) -> str:
|
|
153
|
+
"""Return a compact file identity string for catalog revision hashes.
|
|
154
|
+
|
|
155
|
+
Each catalog refresh stats one SKILL.md plus the discovered resource/script
|
|
156
|
+
files per skill. That is cheap on local filesystems; network-mounted skill
|
|
157
|
+
roots may need a batched strategy if this ever shows up in profiling.
|
|
158
|
+
"""
|
|
159
|
+
try:
|
|
160
|
+
stat = Path(path).stat()
|
|
161
|
+
except OSError:
|
|
162
|
+
return path
|
|
163
|
+
return f"{path}:{stat.st_mtime_ns}:{stat.st_size}"
|
|
164
|
+
|
|
165
|
+
|
|
166
|
+
def _skill_revision(skill: Skill) -> str:
|
|
167
|
+
"""Return the catalog revision for *skill*, computing and caching it once.
|
|
168
|
+
|
|
169
|
+
Cached on the staged ``Skill`` (``Skill.revision``) so every consumer —
|
|
170
|
+
catalog block, ``load_skill`` metadata suffix, persisted call provenance —
|
|
171
|
+
sees one stable value per staging, hashed from the file signatures as
|
|
172
|
+
staged. Provenance builders run *after* the tool body, so recomputing
|
|
173
|
+
there would let a ``run_skill_script`` that mutates its own skill files
|
|
174
|
+
persist a post-run revision instead of the version the model consulted.
|
|
175
|
+
"""
|
|
176
|
+
if skill.revision:
|
|
177
|
+
return skill.revision
|
|
178
|
+
digest = hashlib.sha256()
|
|
179
|
+
|
|
180
|
+
def add(value: object) -> None:
|
|
181
|
+
# Surrogatepass encodes every lone surrogate, a YAML "\ud800" escape
|
|
182
|
+
# as well as an undecodable path byte, so hashing never fails.
|
|
183
|
+
digest.update(str(value).encode("utf-8", "surrogatepass"))
|
|
184
|
+
digest.update(b"\0")
|
|
185
|
+
|
|
186
|
+
add(skill.name)
|
|
187
|
+
add(skill.description or "")
|
|
188
|
+
add(skill.content)
|
|
189
|
+
skill_dir = _catalog_skill_dir(skill)
|
|
190
|
+
if skill_dir is not None:
|
|
191
|
+
add(_file_signature(str(Path(skill_dir) / "SKILL.md")))
|
|
192
|
+
for resource in sorted(skill.resources, key=lambda r: r.name):
|
|
193
|
+
add(resource.name)
|
|
194
|
+
add(resource.description or "")
|
|
195
|
+
if resource.full_path is not None:
|
|
196
|
+
add(_file_signature(resource.full_path))
|
|
197
|
+
for script in sorted(skill.scripts, key=lambda s: s.name):
|
|
198
|
+
add(script.name)
|
|
199
|
+
add(script.description or "")
|
|
200
|
+
add(_file_signature(script.full_path))
|
|
201
|
+
skill.revision = digest.hexdigest()[:12]
|
|
202
|
+
return skill.revision
|
|
203
|
+
|
|
204
|
+
|
|
205
|
+
def _warm_skill_revisions(skills: Sequence[Skill]) -> None:
|
|
206
|
+
"""Eagerly stamp the per-staging revision cache on freshly discovered skills.
|
|
207
|
+
|
|
208
|
+
Discovery constructs fresh ``Skill`` objects, so warming at every staging
|
|
209
|
+
point both invalidates the previous cache and guarantees the revision is
|
|
210
|
+
fixed *before* any tool body can run.
|
|
211
|
+
"""
|
|
212
|
+
for skill in skills:
|
|
213
|
+
_skill_revision(skill)
|
|
214
|
+
|
|
215
|
+
|
|
216
|
+
def _render_catalog_block(skills: Sequence[Skill]) -> str:
|
|
217
|
+
"""Render the volatile runtime skill catalog for system reminders."""
|
|
218
|
+
lines: list[str] = []
|
|
219
|
+
lines.append("<available_skills>")
|
|
220
|
+
if not skills:
|
|
221
|
+
lines.append(" <none>No runtime skills are available for the current agent and workspace.</none>")
|
|
222
|
+
lines.append("</available_skills>")
|
|
223
|
+
return "\n".join(lines)
|
|
224
|
+
for skill in sorted(skills, key=lambda s: s.name):
|
|
225
|
+
skill_dir = _catalog_skill_dir(skill)
|
|
226
|
+
lines.append(" <skill>")
|
|
227
|
+
lines.append(f" <name>{xml_escape(skill.name)}</name>")
|
|
228
|
+
lines.append(f" <description>{xml_escape(skill.description or '')}</description>")
|
|
229
|
+
lines.append(_skill_revision_element(skill, indent=" "))
|
|
230
|
+
if skill_dir is not None:
|
|
231
|
+
lines.append(f" <skill_dir>{xml_escape(skill_dir)}</skill_dir>")
|
|
232
|
+
lines.append(" </skill>")
|
|
233
|
+
lines.append("</available_skills>")
|
|
234
|
+
|
|
235
|
+
return surrogate_safe_text("\n".join(lines))
|
|
236
|
+
|
|
237
|
+
|
|
238
|
+
def _skill_revision_element(skill: Skill, *, indent: str = "") -> str:
|
|
239
|
+
"""Return the model-visible revision element for a skill."""
|
|
240
|
+
return f"{indent}<revision>{xml_escape(_skill_revision(skill))}</revision>"
|
|
241
|
+
|
|
242
|
+
|
|
243
|
+
def _resource_element(resource: SkillResource) -> str:
|
|
244
|
+
"""Create a flat resource element for the load-skill metadata block."""
|
|
245
|
+
attrs = f'name="{xml_escape(resource.name, quote=True)}"'
|
|
246
|
+
if resource.description:
|
|
247
|
+
attrs += f' description="{xml_escape(resource.description, quote=True)}"'
|
|
248
|
+
return f" <resource {attrs}/>"
|
|
249
|
+
|
|
250
|
+
|
|
251
|
+
def _script_element(script: SkillScript) -> str:
|
|
252
|
+
"""Create a flat script element for the load-skill metadata block."""
|
|
253
|
+
attrs = f'name="{xml_escape(script.name, quote=True)}"'
|
|
254
|
+
if script.description:
|
|
255
|
+
attrs += f' description="{xml_escape(script.description, quote=True)}"'
|
|
256
|
+
return f" <script {attrs}/>"
|
|
257
|
+
|
|
258
|
+
|
|
259
|
+
def _metadata_block(tag_name: str, lines: list[str]) -> str:
|
|
260
|
+
"""Return a metadata block, self-closing when it has no child lines."""
|
|
261
|
+
if not lines:
|
|
262
|
+
return f"<{tag_name} />"
|
|
263
|
+
return f"<{tag_name}>\n" + "\n".join(lines) + f"\n</{tag_name}>"
|
|
264
|
+
|
|
265
|
+
|
|
266
|
+
def _file_skill_metadata(skill: Skill, skill_dir: str) -> str:
|
|
267
|
+
"""Return load-time metadata for file-based skills, including exact script names."""
|
|
268
|
+
lines = [f"<skill_dir>{xml_escape(skill_dir)}</skill_dir>"]
|
|
269
|
+
|
|
270
|
+
resource_lines = [_resource_element(resource) for resource in sorted(skill.resources, key=lambda r: r.name)]
|
|
271
|
+
lines.append(_metadata_block("resources", resource_lines))
|
|
272
|
+
|
|
273
|
+
script_lines = [_script_element(script) for script in sorted(skill.scripts, key=lambda s: s.name)]
|
|
274
|
+
lines.append(_metadata_block("scripts", script_lines))
|
|
275
|
+
return "\n".join(lines)
|
|
276
|
+
|
|
277
|
+
|
|
278
|
+
def _find_named[T: (SkillResource, SkillScript)](items: Sequence[T], requested: str) -> T | None:
|
|
279
|
+
"""Find the item named *requested*, ignoring case.
|
|
280
|
+
|
|
281
|
+
The model sees an undecodable byte in a name as ``\\udcXX`` text, so a name
|
|
282
|
+
it sends back may match only that shown form. That match counts when no
|
|
283
|
+
name matches as given and exactly one shows that way.
|
|
284
|
+
"""
|
|
285
|
+
wanted = requested.lower()
|
|
286
|
+
found = next((item for item in items if item.name.lower() == wanted), None)
|
|
287
|
+
if found is not None:
|
|
288
|
+
return found
|
|
289
|
+
shown = [item for item in items if surrogate_safe_text(item.name).lower() == wanted]
|
|
290
|
+
return shown[0] if len(shown) == 1 else None
|
|
291
|
+
|
|
292
|
+
|
|
293
|
+
def _suggest_script_name(query: str, scripts: Sequence[SkillScript]) -> str | None:
|
|
294
|
+
"""Find the best matching script name and return a suggestion message.
|
|
295
|
+
|
|
296
|
+
Checks for suffix matches (e.g. "abc.py" matches "scripts/abc.py") and
|
|
297
|
+
fuzzy matches via ``difflib.get_close_matches``.
|
|
298
|
+
|
|
299
|
+
Returns a suggestion string, or ``None`` if no plausible match is found.
|
|
300
|
+
"""
|
|
301
|
+
names = [s.name for s in scripts]
|
|
302
|
+
|
|
303
|
+
# Exact suffix match: "abc.py" → "scripts/abc.py"
|
|
304
|
+
query_lower = query.lower()
|
|
305
|
+
suffix_matches = [
|
|
306
|
+
n for n in names if n.lower().endswith("/" + query_lower) or n.lower().endswith("\\" + query_lower)
|
|
307
|
+
]
|
|
308
|
+
if suffix_matches:
|
|
309
|
+
return suffix_matches[0]
|
|
310
|
+
|
|
311
|
+
# Basename match: strip directories from both sides
|
|
312
|
+
query_base = query_lower.rsplit("/", 1)[-1].rsplit("\\", 1)[-1]
|
|
313
|
+
for name in names:
|
|
314
|
+
name_base = name.lower().rsplit("/", 1)[-1].rsplit("\\", 1)[-1]
|
|
315
|
+
if name_base == query_base:
|
|
316
|
+
return name
|
|
317
|
+
|
|
318
|
+
# Fuzzy match on full names
|
|
319
|
+
close = get_close_matches(query_lower, [n.lower() for n in names], n=1, cutoff=0.5)
|
|
320
|
+
if close:
|
|
321
|
+
# Map back to original casing
|
|
322
|
+
for name in names:
|
|
323
|
+
if name.lower() == close[0]:
|
|
324
|
+
return name
|
|
325
|
+
|
|
326
|
+
return None
|
|
327
|
+
|
|
328
|
+
|
|
329
|
+
class ChrysSkillsProvider(ContextProvider):
|
|
330
|
+
"""Chrys-owned skills provider on the chrys skill model.
|
|
331
|
+
|
|
332
|
+
Subclasses the chrys-owned kernel :class:`ContextProvider` base so the
|
|
333
|
+
chrys kernel agent invokes ``before_run`` like any other context provider;
|
|
334
|
+
everything else (discovery, catalog, tools, script execution) is chrys code.
|
|
335
|
+
|
|
336
|
+
* Runtime catalog rendering includes a ``<skill_dir>`` element for file-based skills.
|
|
337
|
+
* ``run_skill_script`` exposes chrys's ``args`` / ``arguments`` / ``cwd``
|
|
338
|
+
schema and routes execution through chrys's :class:`SubprocessScriptRunner`.
|
|
339
|
+
* ``load_skill`` appends file-skill resource/script metadata.
|
|
340
|
+
* Convenience accessors (:meth:`skill_names`, :meth:`skill_sources`,
|
|
341
|
+
:meth:`skill_details`) read from the provider's cached skills, which
|
|
342
|
+
Chrys refreshes before user turns so later skill edits can be discovered
|
|
343
|
+
without rebuilding the agent.
|
|
344
|
+
"""
|
|
345
|
+
|
|
346
|
+
DEFAULT_SOURCE_ID: ClassVar[str] = "agent_skills"
|
|
347
|
+
|
|
348
|
+
def __init__(
|
|
349
|
+
self,
|
|
350
|
+
load_skills: Callable[[], Awaitable[Sequence[Skill]]],
|
|
351
|
+
*,
|
|
352
|
+
instruction_template: str | None = None,
|
|
353
|
+
disable_caching: bool = False,
|
|
354
|
+
source_id: str | None = None,
|
|
355
|
+
script_runner: SkillScriptRunner | None = None,
|
|
356
|
+
warning_drain: Callable[[], list[SkillProviderWarning]] | None = None,
|
|
357
|
+
) -> None:
|
|
358
|
+
"""Initialize the chrys provider.
|
|
359
|
+
|
|
360
|
+
Args:
|
|
361
|
+
load_skills: Async callable performing skill discovery; invoked
|
|
362
|
+
once eagerly via :meth:`initialize` and again on every
|
|
363
|
+
:meth:`refresh_context`.
|
|
364
|
+
instruction_template: Custom static system-prompt template. When
|
|
365
|
+
runner instructions should be embedded, it must contain
|
|
366
|
+
``{runner_instructions}``.
|
|
367
|
+
disable_caching: Re-run discovery on every ``before_run`` instead
|
|
368
|
+
of serving the cached skill list.
|
|
369
|
+
source_id: Identifier used for instruction/tool attribution in the
|
|
370
|
+
session context. Defaults to :attr:`DEFAULT_SOURCE_ID`.
|
|
371
|
+
script_runner: chrys :class:`SubprocessScriptRunner` instance,
|
|
372
|
+
called with chrys's full ``args``/``arguments``/``cwd``
|
|
373
|
+
signature for file-based scripts.
|
|
374
|
+
warning_drain: Optional callback that returns newly accumulated
|
|
375
|
+
non-fatal discovery warnings after a refresh.
|
|
376
|
+
"""
|
|
377
|
+
super().__init__(source_id or self.DEFAULT_SOURCE_ID)
|
|
378
|
+
self._load_skills = load_skills
|
|
379
|
+
self._instruction_template = instruction_template
|
|
380
|
+
self._disable_caching = disable_caching
|
|
381
|
+
self._chrys_runner = script_runner
|
|
382
|
+
self._warning_drain = warning_drain
|
|
383
|
+
self._skills: list[Skill] = []
|
|
384
|
+
self._loaded = False
|
|
385
|
+
self._static_instructions = _create_static_instructions(prompt_template=instruction_template)
|
|
386
|
+
self._chrys_tools: list[FunctionTool] = self._create_tools()
|
|
387
|
+
|
|
388
|
+
@property
|
|
389
|
+
def tool_names(self) -> list[str]:
|
|
390
|
+
"""Return the stable skill tool names injected before each run."""
|
|
391
|
+
return [tool.name for tool in self._chrys_tools]
|
|
392
|
+
|
|
393
|
+
# ------------------------------------------------------------------ #
|
|
394
|
+
# Discovery and cached-skill accessors #
|
|
395
|
+
# ------------------------------------------------------------------ #
|
|
396
|
+
|
|
397
|
+
async def _reload(self) -> None:
|
|
398
|
+
"""Re-run discovery; on failure the previous skill list is retained."""
|
|
399
|
+
skills = list(await self._load_skills())
|
|
400
|
+
_warm_skill_revisions(skills)
|
|
401
|
+
self._skills = skills
|
|
402
|
+
self._loaded = True
|
|
403
|
+
|
|
404
|
+
async def initialize(self) -> None:
|
|
405
|
+
"""Run first discovery so synchronous accessors are populated.
|
|
406
|
+
|
|
407
|
+
``create_skills_provider`` always calls this before returning, so
|
|
408
|
+
chrys callers reading :meth:`skill_names` / :meth:`skill_sources` /
|
|
409
|
+
:meth:`skill_details` synchronously see the full list at startup.
|
|
410
|
+
"""
|
|
411
|
+
if not self._loaded:
|
|
412
|
+
await self._reload()
|
|
413
|
+
|
|
414
|
+
def skill_names(self) -> list[str]:
|
|
415
|
+
"""Return loaded skill names in source order."""
|
|
416
|
+
return [s.name for s in self._skills]
|
|
417
|
+
|
|
418
|
+
def skill_sources(self) -> dict[str, list[str]]:
|
|
419
|
+
"""Return loaded skill names grouped by their source directory."""
|
|
420
|
+
sources: dict[str, list[str]] = {}
|
|
421
|
+
for skill in self._skills:
|
|
422
|
+
source = _catalog_skill_dir(skill) or "Inline profile skills"
|
|
423
|
+
sources.setdefault(source, []).append(skill.name)
|
|
424
|
+
return sources
|
|
425
|
+
|
|
426
|
+
def skill_details(self) -> list[RuntimeSkillDetails]:
|
|
427
|
+
"""Return loaded skill metadata for runtime UI surfaces."""
|
|
428
|
+
return _runtime_skill_details(self._skills)
|
|
429
|
+
|
|
430
|
+
async def refresh_context(self) -> list[SkillProviderWarning]:
|
|
431
|
+
"""Refresh discovered skills and return newly accumulated warnings.
|
|
432
|
+
|
|
433
|
+
Chrys snapshots the runtime skill catalog into system reminders once
|
|
434
|
+
per user turn. Refreshing here lets later-added or edited file skills
|
|
435
|
+
become visible without rebuilding the whole agent.
|
|
436
|
+
|
|
437
|
+
On failure the previous skill list is retained because assignment
|
|
438
|
+
only happens after discovery succeeds; callers decide how to log or
|
|
439
|
+
surface the exception.
|
|
440
|
+
"""
|
|
441
|
+
staged = await self.stage_context_refresh()
|
|
442
|
+
return self.commit_context_refresh(staged)
|
|
443
|
+
|
|
444
|
+
async def stage_context_refresh(self) -> StagedSkillRefresh:
|
|
445
|
+
"""Discover skills without mutating the live provider cache."""
|
|
446
|
+
skills = list(await self._load_skills())
|
|
447
|
+
return StagedSkillRefresh(skills=skills)
|
|
448
|
+
|
|
449
|
+
def commit_context_refresh(self, staged: StagedSkillRefresh) -> list[SkillProviderWarning]:
|
|
450
|
+
"""Commit a staged runtime skill refresh to the provider cache."""
|
|
451
|
+
self._skills = list(staged.skills)
|
|
452
|
+
self._loaded = True
|
|
453
|
+
warnings = [] if self._warning_drain is None else self._warning_drain()
|
|
454
|
+
return [*staged.warnings, *warnings]
|
|
455
|
+
|
|
456
|
+
def render_catalog_reminder(self) -> str:
|
|
457
|
+
"""Return the current runtime skill catalog for a system reminder."""
|
|
458
|
+
return _render_catalog_block(self._skills)
|
|
459
|
+
|
|
460
|
+
# ------------------------------------------------------------------ #
|
|
461
|
+
# ContextProvider hook #
|
|
462
|
+
# ------------------------------------------------------------------ #
|
|
463
|
+
|
|
464
|
+
async def before_run(
|
|
465
|
+
self,
|
|
466
|
+
*,
|
|
467
|
+
agent: Any,
|
|
468
|
+
session: Any,
|
|
469
|
+
context: Any,
|
|
470
|
+
state: dict[str, Any],
|
|
471
|
+
) -> None:
|
|
472
|
+
"""Inject stable skill instructions/tools even when no skills exist."""
|
|
473
|
+
if self._disable_caching or not self._loaded:
|
|
474
|
+
await self._reload()
|
|
475
|
+
|
|
476
|
+
if self._static_instructions:
|
|
477
|
+
context.extend_instructions(self.source_id, self._static_instructions)
|
|
478
|
+
context.extend_tools(self.source_id, self._chrys_tools)
|
|
479
|
+
|
|
480
|
+
# ------------------------------------------------------------------ #
|
|
481
|
+
# Skill tools #
|
|
482
|
+
# ------------------------------------------------------------------ #
|
|
483
|
+
|
|
484
|
+
@staticmethod
|
|
485
|
+
def _find_skill(skills: Sequence[Skill], name: str) -> Skill | None:
|
|
486
|
+
"""Find a skill by name (case-insensitive linear scan)."""
|
|
487
|
+
name_lower = name.lower()
|
|
488
|
+
return next((s for s in skills if s.name.lower() == name_lower), None)
|
|
489
|
+
|
|
490
|
+
async def _load_skill(self, skills: Sequence[Skill], skill_name: str) -> str:
|
|
491
|
+
"""Return skill content, appending the revision and exact file-based metadata."""
|
|
492
|
+
if not skill_name or not skill_name.strip():
|
|
493
|
+
return tool_error("invalid_skill_name", "Skill name cannot be empty.")
|
|
494
|
+
|
|
495
|
+
skill = self._find_skill(skills, skill_name)
|
|
496
|
+
if skill is None:
|
|
497
|
+
return tool_error("skill_not_found", f"Skill '{skill_name}' not found.", details={"skill_name": skill_name})
|
|
498
|
+
|
|
499
|
+
logger.info("Loading skill: %s", skill_name)
|
|
500
|
+
|
|
501
|
+
metadata = [_skill_revision_element(skill)]
|
|
502
|
+
skill_dir = _catalog_skill_dir(skill)
|
|
503
|
+
if skill_dir is not None:
|
|
504
|
+
metadata.append(_file_skill_metadata(skill, skill_dir))
|
|
505
|
+
|
|
506
|
+
suffix = "\n".join(metadata)
|
|
507
|
+
return surrogate_safe_text(f"{skill.content.rstrip()}\n\n{suffix}")
|
|
508
|
+
|
|
509
|
+
async def _read_skill_resource(
|
|
510
|
+
self,
|
|
511
|
+
skills: Sequence[Skill],
|
|
512
|
+
skill_name: str,
|
|
513
|
+
resource_name: str,
|
|
514
|
+
max_tokens: int | None = None,
|
|
515
|
+
) -> Any:
|
|
516
|
+
"""Read a named resource from a skill."""
|
|
517
|
+
if not skill_name or not skill_name.strip():
|
|
518
|
+
return tool_error("invalid_skill_name", "Skill name cannot be empty.")
|
|
519
|
+
|
|
520
|
+
if not resource_name or not resource_name.strip():
|
|
521
|
+
return tool_error("invalid_resource_name", "Resource name cannot be empty.")
|
|
522
|
+
|
|
523
|
+
skill = self._find_skill(skills, skill_name)
|
|
524
|
+
if skill is None:
|
|
525
|
+
return tool_error("skill_not_found", f"Skill '{skill_name}' not found.", details={"skill_name": skill_name})
|
|
526
|
+
|
|
527
|
+
resource = _find_named(skill.resources, resource_name)
|
|
528
|
+
if resource is None:
|
|
529
|
+
return tool_error(
|
|
530
|
+
"resource_not_found",
|
|
531
|
+
f"Resource '{resource_name}' not found in skill '{skill_name}'.",
|
|
532
|
+
details={"skill_name": skill_name, "resource_name": resource_name},
|
|
533
|
+
)
|
|
534
|
+
|
|
535
|
+
if (
|
|
536
|
+
resource.full_path
|
|
537
|
+
and skill.path
|
|
538
|
+
and not await asyncio.to_thread(is_contained_skill_path, resource.full_path, skill.path)
|
|
539
|
+
):
|
|
540
|
+
return tool_error(
|
|
541
|
+
"resource_path_outside_skill",
|
|
542
|
+
f"Resource '{resource_name}' resolves outside skill '{skill_name}'.",
|
|
543
|
+
details={"skill_name": skill_name, "resource_name": resource_name},
|
|
544
|
+
)
|
|
545
|
+
|
|
546
|
+
try:
|
|
547
|
+
text = await resource.read()
|
|
548
|
+
except Exception:
|
|
549
|
+
logger.exception("Failed to read resource '%s' from skill '%s'", resource_name, skill_name)
|
|
550
|
+
return tool_error(
|
|
551
|
+
"resource_read_failed",
|
|
552
|
+
f"Failed to read resource '{resource_name}' from skill '{skill_name}'.",
|
|
553
|
+
details={"skill_name": skill_name, "resource_name": resource_name},
|
|
554
|
+
)
|
|
555
|
+
|
|
556
|
+
# Escaped before it is measured: each lone surrogate grows to six characters.
|
|
557
|
+
text = surrogate_safe_text(text)
|
|
558
|
+
requested = DEFAULT_RESOURCE_MAX_TOKENS if max_tokens is None else max_tokens
|
|
559
|
+
budget = max(100, requested)
|
|
560
|
+
if _tokenizer.count_tokens(text) <= budget:
|
|
561
|
+
return text
|
|
562
|
+
suffix = ""
|
|
563
|
+
if resource.full_path:
|
|
564
|
+
path = surrogate_safe_text(str(Path(resource.full_path)))
|
|
565
|
+
suffix = (
|
|
566
|
+
f"[Full resource available at: {path}\n"
|
|
567
|
+
f"{text.count(chr(10)) + 1} lines, ~{_tokenizer.count_tokens(text)} tokens. "
|
|
568
|
+
"Use read_file or shell tools to inspect it.]"
|
|
569
|
+
)
|
|
570
|
+
return truncate_output(text, budget, head_ratio=2 / 3, truncation_suffix=suffix)
|
|
571
|
+
|
|
572
|
+
# ------------------------------------------------------------------ #
|
|
573
|
+
# Persisted call provenance (context builders for the skill tools)
|
|
574
|
+
# ------------------------------------------------------------------ #
|
|
575
|
+
|
|
576
|
+
def _skill_provenance(self, args: Mapping[str, Any]) -> tuple[Skill | None, dict[str, Any]]:
|
|
577
|
+
"""Resolve canonical skill identity from the final call args.
|
|
578
|
+
|
|
579
|
+
Mirrors the tool bodies' own resolution (case-insensitive
|
|
580
|
+
``_find_skill``): a resolved skill records its canonical name plus the
|
|
581
|
+
staged revision; ``skill_not_found`` records the requested name
|
|
582
|
+
verbatim with no revision (nothing resolved).
|
|
583
|
+
"""
|
|
584
|
+
requested = args.get("skill_name")
|
|
585
|
+
if not isinstance(requested, str) or not requested.strip():
|
|
586
|
+
return None, {}
|
|
587
|
+
skill = self._find_skill(self._skills, requested)
|
|
588
|
+
if skill is None:
|
|
589
|
+
return None, {"skill_name": requested}
|
|
590
|
+
return skill, {"skill_name": skill.name, "skill_revision": _skill_revision(skill)}
|
|
591
|
+
|
|
592
|
+
def _load_skill_call_context(self, args: Mapping[str, Any]) -> dict[str, Any] | None:
|
|
593
|
+
_, context = self._skill_provenance(args)
|
|
594
|
+
return context or None
|
|
595
|
+
|
|
596
|
+
def _read_skill_resource_call_context(self, args: Mapping[str, Any]) -> dict[str, Any] | None:
|
|
597
|
+
skill, context = self._skill_provenance(args)
|
|
598
|
+
requested = args.get("resource_name")
|
|
599
|
+
if isinstance(requested, str) and requested.strip():
|
|
600
|
+
name = requested
|
|
601
|
+
if skill is not None:
|
|
602
|
+
match = _find_named(skill.resources, requested)
|
|
603
|
+
if match is not None:
|
|
604
|
+
name = match.name
|
|
605
|
+
context["resource_name"] = name
|
|
606
|
+
return context or None
|
|
607
|
+
|
|
608
|
+
def _run_skill_script_call_context(self, args: Mapping[str, Any]) -> dict[str, Any] | None:
|
|
609
|
+
skill, context = self._skill_provenance(args)
|
|
610
|
+
requested = args.get("script_name")
|
|
611
|
+
if isinstance(requested, str) and requested.strip():
|
|
612
|
+
name = requested
|
|
613
|
+
if skill is not None:
|
|
614
|
+
match = _find_named(skill.scripts, requested)
|
|
615
|
+
if match is not None:
|
|
616
|
+
name = match.name
|
|
617
|
+
context["script_name"] = name
|
|
618
|
+
return context or None
|
|
619
|
+
|
|
620
|
+
def _create_tools(self) -> list[FunctionTool]:
|
|
621
|
+
"""Create stable tools that resolve against the provider's current skills."""
|
|
622
|
+
|
|
623
|
+
async def _load(skill_name: str) -> str:
|
|
624
|
+
return await self._load_skill(self._skills, skill_name)
|
|
625
|
+
|
|
626
|
+
tools: list[FunctionTool] = [
|
|
627
|
+
FunctionTool(
|
|
628
|
+
name="load_skill",
|
|
629
|
+
description="Loads the full instructions for a specific skill.",
|
|
630
|
+
func=_load,
|
|
631
|
+
input_model={
|
|
632
|
+
"type": "object",
|
|
633
|
+
"properties": {
|
|
634
|
+
"skill_name": {"type": "string", "description": "The name of the skill to load."},
|
|
635
|
+
},
|
|
636
|
+
"required": ["skill_name"],
|
|
637
|
+
"additionalProperties": False,
|
|
638
|
+
},
|
|
639
|
+
),
|
|
640
|
+
]
|
|
641
|
+
|
|
642
|
+
async def _read_resource(
|
|
643
|
+
skill_name: str,
|
|
644
|
+
resource_name: str,
|
|
645
|
+
max_tokens: int | None = DEFAULT_RESOURCE_MAX_TOKENS,
|
|
646
|
+
) -> Any:
|
|
647
|
+
return await self._read_skill_resource(self._skills, skill_name, resource_name, max_tokens)
|
|
648
|
+
|
|
649
|
+
tools.append(
|
|
650
|
+
FunctionTool(
|
|
651
|
+
name="read_skill_resource",
|
|
652
|
+
description=(
|
|
653
|
+
"Reads a resource associated with a skill, such as references, assets, or dynamic data. "
|
|
654
|
+
"Large resources are truncated to max_tokens; file-backed resources include their original path."
|
|
655
|
+
),
|
|
656
|
+
func=_read_resource,
|
|
657
|
+
input_model={
|
|
658
|
+
"type": "object",
|
|
659
|
+
"properties": {
|
|
660
|
+
"skill_name": {"type": "string", "description": "The name of the skill."},
|
|
661
|
+
"resource_name": {
|
|
662
|
+
"type": "string",
|
|
663
|
+
"description": "The name of the resource.",
|
|
664
|
+
},
|
|
665
|
+
"max_tokens": {
|
|
666
|
+
"type": ["integer", "null"],
|
|
667
|
+
"default": DEFAULT_RESOURCE_MAX_TOKENS,
|
|
668
|
+
"description": (
|
|
669
|
+
"Estimated-token budget for returned content. Values below 100 are clamped to 100."
|
|
670
|
+
),
|
|
671
|
+
},
|
|
672
|
+
},
|
|
673
|
+
"required": ["skill_name", "resource_name"],
|
|
674
|
+
"additionalProperties": False,
|
|
675
|
+
},
|
|
676
|
+
)
|
|
677
|
+
)
|
|
678
|
+
|
|
679
|
+
async def _run_script(
|
|
680
|
+
skill_name: str,
|
|
681
|
+
script_name: str,
|
|
682
|
+
args: dict[str, Any] | list[str] | None = None,
|
|
683
|
+
arguments: list[str] | None = None,
|
|
684
|
+
cwd: str | None = None,
|
|
685
|
+
max_tokens: int | None = DEFAULT_SCRIPT_RESULT_MAX_TOKENS,
|
|
686
|
+
) -> Any:
|
|
687
|
+
return await self._run_skill_script_chrys(
|
|
688
|
+
self._skills,
|
|
689
|
+
skill_name,
|
|
690
|
+
script_name,
|
|
691
|
+
args,
|
|
692
|
+
arguments,
|
|
693
|
+
cwd,
|
|
694
|
+
max_tokens,
|
|
695
|
+
)
|
|
696
|
+
|
|
697
|
+
tools.append(
|
|
698
|
+
FunctionTool(
|
|
699
|
+
name=RUN_SKILL_SCRIPT_TOOL_NAME,
|
|
700
|
+
description=(
|
|
701
|
+
"Runs a script associated with a skill. Large output is truncated to max_tokens; very large "
|
|
702
|
+
"output keeps only its beginning and end, and the middle cannot be recovered. When possible, "
|
|
703
|
+
"the kept output is saved under the current session directory."
|
|
704
|
+
),
|
|
705
|
+
func=_run_script,
|
|
706
|
+
input_model={
|
|
707
|
+
"type": "object",
|
|
708
|
+
"properties": {
|
|
709
|
+
"skill_name": {"type": "string", "description": "The name of the skill."},
|
|
710
|
+
"script_name": {
|
|
711
|
+
"type": "string",
|
|
712
|
+
"description": (
|
|
713
|
+
"Use the exact name from load_skill, preserving any directory prefix "
|
|
714
|
+
"(e.g. scripts/convert.py, not convert.py). "
|
|
715
|
+
"Use forward slashes on all platforms."
|
|
716
|
+
),
|
|
717
|
+
},
|
|
718
|
+
"args": {
|
|
719
|
+
"type": ["object", "null"],
|
|
720
|
+
"additionalProperties": True,
|
|
721
|
+
"default": None,
|
|
722
|
+
"description": (
|
|
723
|
+
"Optional sugar for flat, order-insensitive CLI flags appended after arguments. "
|
|
724
|
+
"Keys without leading dashes map to long flags (--key value); keys that begin "
|
|
725
|
+
"with '-' pass through verbatim for short or combined flags. "
|
|
726
|
+
'For example: {"length": 24, "uppercase": true, "-i": true}. '
|
|
727
|
+
"If token ordering matters, put every token in arguments instead."
|
|
728
|
+
),
|
|
729
|
+
},
|
|
730
|
+
"arguments": {
|
|
731
|
+
"type": ["array", "null"],
|
|
732
|
+
"items": {"type": "string"},
|
|
733
|
+
"default": None,
|
|
734
|
+
"description": (
|
|
735
|
+
"Exact, ordered CLI tokens to pass after the script name, before any flags "
|
|
736
|
+
"derived from args. Use this for subcommands, positionals, repeated flags, "
|
|
737
|
+
"global flags before a subcommand, or -- passthrough. "
|
|
738
|
+
'For example: ["log", "--oneline", "--max-count", "5"].'
|
|
739
|
+
),
|
|
740
|
+
},
|
|
741
|
+
"cwd": {
|
|
742
|
+
"type": ["string", "null"],
|
|
743
|
+
"default": None,
|
|
744
|
+
"description": (
|
|
745
|
+
"Absolute working directory for the script. "
|
|
746
|
+
"When omitted, defaults to the primary working directory. "
|
|
747
|
+
"Relative paths are rejected — pass an absolute path only."
|
|
748
|
+
),
|
|
749
|
+
},
|
|
750
|
+
"max_tokens": {
|
|
751
|
+
"type": ["integer", "null"],
|
|
752
|
+
"default": DEFAULT_SCRIPT_RESULT_MAX_TOKENS,
|
|
753
|
+
"description": (
|
|
754
|
+
"Estimated-token budget for returned output. Values below 100 are clamped to 100."
|
|
755
|
+
),
|
|
756
|
+
},
|
|
757
|
+
},
|
|
758
|
+
"required": ["skill_name", "script_name"],
|
|
759
|
+
"additionalProperties": False,
|
|
760
|
+
},
|
|
761
|
+
)
|
|
762
|
+
)
|
|
763
|
+
|
|
764
|
+
context_builders = {
|
|
765
|
+
"load_skill": self._load_skill_call_context,
|
|
766
|
+
"read_skill_resource": self._read_skill_resource_call_context,
|
|
767
|
+
RUN_SKILL_SCRIPT_TOOL_NAME: self._run_skill_script_call_context,
|
|
768
|
+
}
|
|
769
|
+
for tool in tools:
|
|
770
|
+
set_tool_kind(tool, KIND_SKILL)
|
|
771
|
+
set_tool_context_builder(tool, context_builders[tool.name])
|
|
772
|
+
|
|
773
|
+
return tools
|
|
774
|
+
|
|
775
|
+
async def _run_skill_script_chrys(
|
|
776
|
+
self,
|
|
777
|
+
skills: Sequence[Skill],
|
|
778
|
+
skill_name: str,
|
|
779
|
+
script_name: str,
|
|
780
|
+
args: dict[str, Any] | list[str] | None = None,
|
|
781
|
+
arguments: list[str] | None = None,
|
|
782
|
+
cwd: str | None = None,
|
|
783
|
+
max_tokens: int | None = None,
|
|
784
|
+
) -> Any:
|
|
785
|
+
"""Run a named script with positional argument support and fuzzy matching.
|
|
786
|
+
|
|
787
|
+
Scripts in the chrys model are always file-backed (inline profile
|
|
788
|
+
skills cannot declare scripts), so execution always goes through the
|
|
789
|
+
provider's :class:`SubprocessScriptRunner`. Suggests the correct
|
|
790
|
+
script name on a miss using fuzzy matching.
|
|
791
|
+
"""
|
|
792
|
+
if not skill_name or not skill_name.strip():
|
|
793
|
+
return tool_error("invalid_skill_name", "Skill name cannot be empty.")
|
|
794
|
+
|
|
795
|
+
if not script_name or not script_name.strip():
|
|
796
|
+
return tool_error("invalid_script_name", "Script name cannot be empty.")
|
|
797
|
+
|
|
798
|
+
skill = self._find_skill(skills, skill_name)
|
|
799
|
+
if not skill:
|
|
800
|
+
return tool_error("skill_not_found", f"Skill '{skill_name}' not found.", details={"skill_name": skill_name})
|
|
801
|
+
|
|
802
|
+
scripts = skill.scripts
|
|
803
|
+
script = _find_named(scripts, script_name)
|
|
804
|
+
if not script:
|
|
805
|
+
suggestion = _suggest_script_name(script_name, scripts)
|
|
806
|
+
if suggestion:
|
|
807
|
+
return tool_error(
|
|
808
|
+
"script_not_found",
|
|
809
|
+
f"Script '{script_name}' not found in skill '{skill_name}'. Did you mean '{suggestion}'?",
|
|
810
|
+
details={"skill_name": skill_name, "script_name": script_name, "suggestion": suggestion},
|
|
811
|
+
)
|
|
812
|
+
available = ", ".join(f"'{s.name}'" for s in scripts)
|
|
813
|
+
return tool_error(
|
|
814
|
+
"script_not_found",
|
|
815
|
+
f"Script '{script_name}' not found in skill '{skill_name}'. Available scripts: {available}",
|
|
816
|
+
details={"skill_name": skill_name, "script_name": script_name},
|
|
817
|
+
)
|
|
818
|
+
|
|
819
|
+
runner = self._chrys_runner
|
|
820
|
+
if runner is None:
|
|
821
|
+
return tool_error(
|
|
822
|
+
"script_runner_missing",
|
|
823
|
+
(
|
|
824
|
+
f"Script '{script_name}' in skill '{skill_name}' requires a runner. "
|
|
825
|
+
"Provide a script_runner when constructing the provider for file-based scripts."
|
|
826
|
+
),
|
|
827
|
+
details={"skill_name": skill_name, "script_name": script_name},
|
|
828
|
+
)
|
|
829
|
+
|
|
830
|
+
try:
|
|
831
|
+
result = runner(skill, script, args, arguments=arguments, cwd=cwd, max_tokens=max_tokens)
|
|
832
|
+
if inspect.isawaitable(result):
|
|
833
|
+
result = await result
|
|
834
|
+
return result
|
|
835
|
+
except Exception:
|
|
836
|
+
logger.exception("Error running script '%s' in skill '%s'", script_name, skill_name)
|
|
837
|
+
return tool_error(
|
|
838
|
+
"script_run_failed",
|
|
839
|
+
f"Failed to run script '{script_name}' in skill '{skill_name}'.",
|
|
840
|
+
details={"skill_name": skill_name, "script_name": script_name},
|
|
841
|
+
)
|