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,552 @@
|
|
|
1
|
+
# Copyright (c) Huawei Technologies Co., Ltd. 2026. All rights reserved.
|
|
2
|
+
|
|
3
|
+
"""Session metadata extraction for the JSON file state store."""
|
|
4
|
+
|
|
5
|
+
from __future__ import annotations
|
|
6
|
+
|
|
7
|
+
import logging
|
|
8
|
+
from collections.abc import Mapping
|
|
9
|
+
from dataclasses import dataclass, field, replace
|
|
10
|
+
from datetime import datetime
|
|
11
|
+
from typing import Any, Literal
|
|
12
|
+
|
|
13
|
+
from chrys.foundation.models.history_markers import HistoryMarkerKind
|
|
14
|
+
from chrys.foundation.models.session_surface import SessionSurface, parse_session_surface
|
|
15
|
+
from chrys.foundation.models.turns import is_continuation_message
|
|
16
|
+
from chrys.foundation.util.time import parse_created_at
|
|
17
|
+
from chrys.kernel import Message
|
|
18
|
+
from chrys.service.context.providers.history import TURN_INDEX_KEY, CompressedBlock
|
|
19
|
+
from chrys.service.session.message_metadata import MESSAGE_CREATED_AT_KEY
|
|
20
|
+
from chrys.service.session.runtime_metadata import TOTAL_SESSION_TOKENS_KEY
|
|
21
|
+
from chrys.service.state.session_mru import coerce_utc
|
|
22
|
+
from chrys.service.state.workflow import WorkflowSessionState
|
|
23
|
+
from chrys.service.workflows.history import WorkflowRunMeta
|
|
24
|
+
|
|
25
|
+
logger = logging.getLogger(__name__)
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def resolve_session_kind(meta: dict[str, Any]) -> Literal["chat", "workflow"]:
|
|
29
|
+
"""Older Chat archives predate the discriminator; Workflow always records it."""
|
|
30
|
+
kind = meta.get("kind", "chat")
|
|
31
|
+
if kind not in ("chat", "workflow"):
|
|
32
|
+
raise ValueError(f"Invalid session kind: {kind!r}")
|
|
33
|
+
return kind
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
@dataclass(kw_only=True)
|
|
37
|
+
class SessionMetadata:
|
|
38
|
+
"""Identity and storage facts shared by Chat and Workflow sessions."""
|
|
39
|
+
|
|
40
|
+
session_id: str
|
|
41
|
+
created_at: datetime
|
|
42
|
+
updated_at: datetime
|
|
43
|
+
total_tokens: int = 0
|
|
44
|
+
primary_cwd: str = ""
|
|
45
|
+
working_dirs: list[str] = field(default_factory=list)
|
|
46
|
+
title: str = ""
|
|
47
|
+
custom_title: str = ""
|
|
48
|
+
generated_title: str = ""
|
|
49
|
+
size_bytes: int = 0
|
|
50
|
+
app_version: str = ""
|
|
51
|
+
schema_version: int = 0
|
|
52
|
+
os_name: str = ""
|
|
53
|
+
arch: str = ""
|
|
54
|
+
# The surface of the last turn or run; ``None`` for sessions saved before it was recorded.
|
|
55
|
+
last_surface: SessionSurface | None = None
|
|
56
|
+
|
|
57
|
+
@property
|
|
58
|
+
def display_title(self) -> str:
|
|
59
|
+
return self.custom_title or self.generated_title or self.title
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
@dataclass(kw_only=True)
|
|
63
|
+
class ChatSessionMeta(SessionMetadata):
|
|
64
|
+
"""Conversation metadata; never attached to Workflow history."""
|
|
65
|
+
|
|
66
|
+
kind: Literal["chat"] = field(default="chat", init=False)
|
|
67
|
+
agent_profile: str
|
|
68
|
+
agent_display_name: str
|
|
69
|
+
message_count: int
|
|
70
|
+
turn_count: int = 0
|
|
71
|
+
agent_profile_id: str = ""
|
|
72
|
+
agent_profile_history: list[str] = field(default_factory=list)
|
|
73
|
+
agent_profile_fingerprint: str = ""
|
|
74
|
+
model_provider: str = ""
|
|
75
|
+
model_api_style: str = ""
|
|
76
|
+
model_id: str = ""
|
|
77
|
+
model_profile_id: str = ""
|
|
78
|
+
model_base_url: str = ""
|
|
79
|
+
model_profile_fingerprint: str = ""
|
|
80
|
+
service_session_id: str = ""
|
|
81
|
+
parent_session_id: str = ""
|
|
82
|
+
# Bounded head/tail excerpts of user prompts, never full transcript text.
|
|
83
|
+
user_prompt_search_text: str = ""
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
@dataclass(kw_only=True)
|
|
87
|
+
class WorkflowSessionMeta(SessionMetadata):
|
|
88
|
+
"""A bounded summary; run history is loaded explicitly by the catalog."""
|
|
89
|
+
|
|
90
|
+
kind: Literal["workflow"] = field(default="workflow", init=False)
|
|
91
|
+
workflow_id: str = ""
|
|
92
|
+
run_count: int = 0
|
|
93
|
+
latest_run_id: str = ""
|
|
94
|
+
latest_run: WorkflowRunMeta | None = None
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
type SessionMeta = ChatSessionMeta | WorkflowSessionMeta
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
def copy_session_meta(meta: SessionMeta) -> SessionMeta:
|
|
101
|
+
"""Return a copy of *meta* that shares none of its mutable fields.
|
|
102
|
+
|
|
103
|
+
The store's listing caches hand out copies, so a caller that edits the
|
|
104
|
+
meta it was given cannot change what later listings read.
|
|
105
|
+
"""
|
|
106
|
+
if isinstance(meta, ChatSessionMeta):
|
|
107
|
+
return replace(
|
|
108
|
+
meta, working_dirs=list(meta.working_dirs), agent_profile_history=list(meta.agent_profile_history)
|
|
109
|
+
)
|
|
110
|
+
return replace(meta, working_dirs=list(meta.working_dirs))
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
def _is_visible_message(m: Message) -> bool:
|
|
114
|
+
"""Return True for user messages and non-marker assistant messages with text.
|
|
115
|
+
|
|
116
|
+
Synthetic ``continue`` nudges do not count: a crash-leftover nudge is a
|
|
117
|
+
orchestration placeholder, not user content, and must not inflate
|
|
118
|
+
``meta.message_count`` (or, through it, ``updated_at`` preservation and
|
|
119
|
+
the buddy total).
|
|
120
|
+
"""
|
|
121
|
+
chrys_kind = m.additional_properties.get(HistoryMarkerKind.KEY)
|
|
122
|
+
if chrys_kind in HistoryMarkerKind.SESSION_COUNT_EXCLUDED:
|
|
123
|
+
return False
|
|
124
|
+
if m.role == "user":
|
|
125
|
+
return not is_continuation_message(m)
|
|
126
|
+
if m.role == "assistant":
|
|
127
|
+
return any(c.type == "text" and (c.text or "").strip() for c in m.contents)
|
|
128
|
+
return False
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
def _parse_session_timestamp(value: object) -> datetime | None:
|
|
132
|
+
"""Return one persisted timestamp as an aware UTC datetime, if valid."""
|
|
133
|
+
parsed = parse_created_at(value)
|
|
134
|
+
return coerce_utc(parsed) if parsed is not None else None
|
|
135
|
+
|
|
136
|
+
|
|
137
|
+
def recorded_surface(
|
|
138
|
+
primary_meta: Mapping[str, Any], recovery_meta: Mapping[str, Any], *, sidecar_first: bool = False
|
|
139
|
+
) -> str | None:
|
|
140
|
+
"""The surface the session's last turn recorded, verbatim; ``None`` when none ever was.
|
|
141
|
+
|
|
142
|
+
A sidecar newer than the primary holds the turn a crash cut short, which
|
|
143
|
+
is the session's last one, so its surface outranks the primary's.
|
|
144
|
+
"""
|
|
145
|
+
primary_updated_at = _parse_session_timestamp(primary_meta.get("updated_at"))
|
|
146
|
+
recovery_updated_at = _parse_session_timestamp(recovery_meta.get("updated_at"))
|
|
147
|
+
recovery_first = sidecar_first or (
|
|
148
|
+
recovery_updated_at is not None and (primary_updated_at is None or recovery_updated_at > primary_updated_at)
|
|
149
|
+
)
|
|
150
|
+
candidates = (recovery_meta, primary_meta) if recovery_first else (primary_meta, recovery_meta)
|
|
151
|
+
return next((value for meta in candidates if isinstance(value := meta.get("last_surface"), str) and value), None)
|
|
152
|
+
|
|
153
|
+
|
|
154
|
+
def _message_created_at(message: object) -> datetime | None:
|
|
155
|
+
"""Read a Chrys message timestamp from either live or serialized state."""
|
|
156
|
+
if isinstance(message, Message):
|
|
157
|
+
properties = message.additional_properties
|
|
158
|
+
elif isinstance(message, dict):
|
|
159
|
+
raw_properties = message.get("additional_properties")
|
|
160
|
+
properties = raw_properties if isinstance(raw_properties, dict) else {}
|
|
161
|
+
else:
|
|
162
|
+
return None
|
|
163
|
+
return _parse_session_timestamp(properties.get(MESSAGE_CREATED_AT_KEY))
|
|
164
|
+
|
|
165
|
+
|
|
166
|
+
def _first_message_created_at(messages: object) -> datetime | None:
|
|
167
|
+
"""Return the first valid message timestamp in an ordered message list."""
|
|
168
|
+
if not isinstance(messages, list):
|
|
169
|
+
return None
|
|
170
|
+
for message in messages:
|
|
171
|
+
created_at = _message_created_at(message)
|
|
172
|
+
if created_at is not None:
|
|
173
|
+
return created_at
|
|
174
|
+
return None
|
|
175
|
+
|
|
176
|
+
|
|
177
|
+
def _earliest_history_created_at(state: dict[str, Any]) -> datetime | None:
|
|
178
|
+
"""Return the oldest available timestamp from ordered live or serialized history.
|
|
179
|
+
|
|
180
|
+
Compaction preserves chronological order. Scan blocks oldest-first until
|
|
181
|
+
one carries a timestamp, then fall back to the live tail; this handles a
|
|
182
|
+
legacy unstamped block followed by blocks created after timestamping was
|
|
183
|
+
introduced. Both runtime ``CompressedBlock`` values and serialized dict
|
|
184
|
+
mirrors are accepted.
|
|
185
|
+
"""
|
|
186
|
+
compressed_blocks = state.get("compressed_msgs")
|
|
187
|
+
if isinstance(compressed_blocks, list):
|
|
188
|
+
for block in compressed_blocks:
|
|
189
|
+
if isinstance(block, CompressedBlock):
|
|
190
|
+
compressed_messages: object = block.messages
|
|
191
|
+
elif isinstance(block, dict):
|
|
192
|
+
compressed_messages = block.get("messages")
|
|
193
|
+
else:
|
|
194
|
+
continue
|
|
195
|
+
created_at = _first_message_created_at(compressed_messages)
|
|
196
|
+
if created_at is not None:
|
|
197
|
+
return created_at
|
|
198
|
+
return _first_message_created_at(state.get("messages"))
|
|
199
|
+
|
|
200
|
+
|
|
201
|
+
_TITLE_MAX_LEN = 200
|
|
202
|
+
|
|
203
|
+
_PROMPT_SEARCH_EDGE_CHARS = 1000
|
|
204
|
+
"""Head AND tail characters kept per user message for prompt search."""
|
|
205
|
+
|
|
206
|
+
_PROMPT_SEARCH_TOTAL_CHARS = 8000
|
|
207
|
+
"""Per-session cap on ``SessionMeta.user_prompt_search_text`` (meta-cache bound)."""
|
|
208
|
+
|
|
209
|
+
_PROMPT_SEARCH_SCAN_BLOCK = 4096
|
|
210
|
+
"""Fixed raw-text block size for the bounded collapse scan — the transient
|
|
211
|
+
memory unit of ``_collapsed_prompt_excerpt`` (never a growing slice)."""
|
|
212
|
+
|
|
213
|
+
|
|
214
|
+
def _extract_title(messages: list[Message]) -> str:
|
|
215
|
+
"""Extract title from the first user message text, truncated.
|
|
216
|
+
|
|
217
|
+
Skips synthetic ``continue`` nudges: in the no-prior-user resume shape
|
|
218
|
+
the first user message IS a nudge and the session would be titled
|
|
219
|
+
"continue".
|
|
220
|
+
"""
|
|
221
|
+
for m in messages:
|
|
222
|
+
if m.role != "user" or is_continuation_message(m):
|
|
223
|
+
continue
|
|
224
|
+
for c in m.contents:
|
|
225
|
+
if c.type == "text":
|
|
226
|
+
text = c.text or ""
|
|
227
|
+
text = text.strip().replace("\n", " ")
|
|
228
|
+
if text:
|
|
229
|
+
if len(text) > _TITLE_MAX_LEN:
|
|
230
|
+
return text[:_TITLE_MAX_LEN] + "..."
|
|
231
|
+
return text
|
|
232
|
+
return ""
|
|
233
|
+
|
|
234
|
+
|
|
235
|
+
class SessionMetaMixin:
|
|
236
|
+
"""Session metadata extraction methods for JSON state stores."""
|
|
237
|
+
|
|
238
|
+
@staticmethod
|
|
239
|
+
def _envelope_turn_count(envelope: dict[str, Any]) -> int:
|
|
240
|
+
"""Total turns recorded in a serialized envelope's state payload.
|
|
241
|
+
|
|
242
|
+
Takes the max of ``state["turn_counter"]`` (authoritative — kept
|
|
243
|
+
aligned with history turn markers by ``SessionHistoryManager``) and
|
|
244
|
+
the evidence surviving on disk: the highest ``_turn`` index stamped
|
|
245
|
+
on live turn markers (with the marker count as a floor) and the
|
|
246
|
+
``turn_range`` ends of compacted blocks, whose original markers were
|
|
247
|
+
folded away. The max guards pre-counter sessions later re-saved
|
|
248
|
+
with a restarted counter.
|
|
249
|
+
"""
|
|
250
|
+
state = envelope.get("state")
|
|
251
|
+
if not isinstance(state, dict):
|
|
252
|
+
return 0
|
|
253
|
+
counter = state.get("turn_counter", 0)
|
|
254
|
+
best = counter if isinstance(counter, int) and counter > 0 else 0
|
|
255
|
+
messages = state.get("messages", [])
|
|
256
|
+
if isinstance(messages, list):
|
|
257
|
+
marker_count = 0
|
|
258
|
+
for message in messages:
|
|
259
|
+
if not isinstance(message, dict):
|
|
260
|
+
continue
|
|
261
|
+
props = message.get("additional_properties")
|
|
262
|
+
if not (isinstance(props, dict) and props.get(HistoryMarkerKind.KEY) == HistoryMarkerKind.TURN):
|
|
263
|
+
continue
|
|
264
|
+
marker_count += 1
|
|
265
|
+
turn_index = props.get(TURN_INDEX_KEY)
|
|
266
|
+
if isinstance(turn_index, int):
|
|
267
|
+
best = max(best, turn_index)
|
|
268
|
+
best = max(best, marker_count)
|
|
269
|
+
blocks = state.get("compressed_msgs", [])
|
|
270
|
+
if isinstance(blocks, list):
|
|
271
|
+
for block in blocks:
|
|
272
|
+
if not isinstance(block, dict):
|
|
273
|
+
continue
|
|
274
|
+
turn_range = block.get("turn_range", ())
|
|
275
|
+
if isinstance(turn_range, list | tuple) and len(turn_range) == 2 and isinstance(turn_range[1], int):
|
|
276
|
+
best = max(best, turn_range[1])
|
|
277
|
+
return best
|
|
278
|
+
|
|
279
|
+
@staticmethod
|
|
280
|
+
def _collapsed_prompt_excerpt(text: str, edge: int) -> str:
|
|
281
|
+
"""Whitespace-collapsed ``text``, capped to head+tail ``edge`` chars.
|
|
282
|
+
|
|
283
|
+
Output-equivalent to capping ``" ".join(text.split())`` in
|
|
284
|
+
O(edge + block) transient memory instead of O(input):
|
|
285
|
+
``str.split()`` on a multi-megabyte paste of short words costs
|
|
286
|
+
~14x its size, and even a growing window slice copies O(input)
|
|
287
|
+
raw text when whitespace-dominated input keeps the collapsed
|
|
288
|
+
yield low. The scan therefore walks FIXED-size blocks by index
|
|
289
|
+
from each end, collapsing block by block and stitching at block
|
|
290
|
+
boundaries: a boundary splitting a word glues the pieces, a
|
|
291
|
+
boundary touching whitespace on either side becomes the single
|
|
292
|
+
space the full collapse would have produced there, and an
|
|
293
|
+
all-whitespace block contributes nothing now but leaves a
|
|
294
|
+
whitespace boundary char for the next stitch to see. The head
|
|
295
|
+
accumulator is an exact PREFIX of the full collapse and the tail
|
|
296
|
+
accumulator an exact SUFFIX, so each side may stop as soon as it
|
|
297
|
+
covers its capped region.
|
|
298
|
+
"""
|
|
299
|
+
block = _PROMPT_SEARCH_SCAN_BLOCK
|
|
300
|
+
limit = 2 * edge
|
|
301
|
+
head = ""
|
|
302
|
+
pos = 0
|
|
303
|
+
while pos < len(text) and len(head) <= limit:
|
|
304
|
+
piece = " ".join(text[pos : pos + block].split())
|
|
305
|
+
if piece:
|
|
306
|
+
if not head:
|
|
307
|
+
head = piece
|
|
308
|
+
elif text[pos - 1].isspace() or text[pos].isspace():
|
|
309
|
+
head = f"{head} {piece}"
|
|
310
|
+
else:
|
|
311
|
+
head += piece
|
|
312
|
+
pos += block
|
|
313
|
+
if len(head) <= limit:
|
|
314
|
+
# The loop only exits with head <= limit once the whole text
|
|
315
|
+
# is consumed, so head IS the full collapse: no cap needed.
|
|
316
|
+
return head
|
|
317
|
+
tail = ""
|
|
318
|
+
pos = len(text)
|
|
319
|
+
while pos > 0 and len(tail) < edge:
|
|
320
|
+
start = max(0, pos - block)
|
|
321
|
+
piece = " ".join(text[start:pos].split())
|
|
322
|
+
if piece:
|
|
323
|
+
if not tail:
|
|
324
|
+
tail = piece
|
|
325
|
+
elif text[pos - 1].isspace() or text[pos].isspace():
|
|
326
|
+
tail = f"{piece} {tail}"
|
|
327
|
+
else:
|
|
328
|
+
tail = piece + tail
|
|
329
|
+
pos = start
|
|
330
|
+
return f"{head[:edge]}\n{tail[-edge:]}"
|
|
331
|
+
|
|
332
|
+
@staticmethod
|
|
333
|
+
def _message_prompt_excerpt(message: dict[str, Any]) -> str | None:
|
|
334
|
+
"""Capped search excerpt of one user-typed prompt, else ``None``.
|
|
335
|
+
|
|
336
|
+
``None`` means the message is not a user-typed prompt: wrong role,
|
|
337
|
+
synthetic history (turn/status markers, ``continue`` nudges), or no
|
|
338
|
+
text content. Legacy sessions store ``contents`` as plain strings;
|
|
339
|
+
those count as text under the same rule replay's
|
|
340
|
+
``_load_session_raw_sync`` uses (a ``Content(type=`` repr blob is
|
|
341
|
+
not text). Capping each block to its collapsed head+tail before
|
|
342
|
+
joining yields the same final excerpt as capping the full joined
|
|
343
|
+
collapse — the message-level windows only ever read a block's
|
|
344
|
+
first/last ``edge`` chars, which block-level capping preserves.
|
|
345
|
+
"""
|
|
346
|
+
if message.get("role") != "user":
|
|
347
|
+
return None
|
|
348
|
+
props = message.get("additional_properties")
|
|
349
|
+
if isinstance(props, dict) and (
|
|
350
|
+
props.get(HistoryMarkerKind.KEY) or props.get(HistoryMarkerKind.CONTINUATION_KEY)
|
|
351
|
+
):
|
|
352
|
+
return None
|
|
353
|
+
contents = message.get("contents")
|
|
354
|
+
if not isinstance(contents, list):
|
|
355
|
+
return None
|
|
356
|
+
chunks: list[str] = []
|
|
357
|
+
for content in contents:
|
|
358
|
+
if isinstance(content, dict) and content.get("type") == "text":
|
|
359
|
+
text = content.get("text")
|
|
360
|
+
elif isinstance(content, str) and not content.startswith("Content(type="):
|
|
361
|
+
text = content
|
|
362
|
+
else:
|
|
363
|
+
continue
|
|
364
|
+
if isinstance(text, str) and text and not text.isspace():
|
|
365
|
+
chunks.append(SessionMetaMixin._collapsed_prompt_excerpt(text, _PROMPT_SEARCH_EDGE_CHARS))
|
|
366
|
+
if not chunks:
|
|
367
|
+
return None
|
|
368
|
+
joined = "\n".join(chunks)
|
|
369
|
+
if len(joined) > 2 * _PROMPT_SEARCH_EDGE_CHARS:
|
|
370
|
+
joined = f"{joined[:_PROMPT_SEARCH_EDGE_CHARS]}\n{joined[-_PROMPT_SEARCH_EDGE_CHARS:]}"
|
|
371
|
+
return joined
|
|
372
|
+
|
|
373
|
+
@staticmethod
|
|
374
|
+
def _envelope_user_prompt_search_text(envelope: dict[str, Any]) -> str:
|
|
375
|
+
"""Capped search excerpts of the user-typed prompts in an envelope.
|
|
376
|
+
|
|
377
|
+
Walks the messages of the envelope the caller already parsed for
|
|
378
|
+
:meth:`_envelope_turn_count` — compacted originals folded into
|
|
379
|
+
``compressed_msgs`` blocks first (they are the older turns), then
|
|
380
|
+
the live list — keeping ``role == "user"`` text while skipping
|
|
381
|
+
synthetic history (turn/status markers, ``continue`` nudges).
|
|
382
|
+
Legacy sessions store ``contents`` as plain strings; those count as
|
|
383
|
+
text under the same rule replay's ``_load_session_raw_sync`` uses
|
|
384
|
+
(a ``Content(type=`` repr blob is not text).
|
|
385
|
+
Compaction can leave a message in both places; such twins dedup by
|
|
386
|
+
their capped TEXT, never by ``message_id`` — ids restart across
|
|
387
|
+
runs, so two different prompts can share one (observed in real
|
|
388
|
+
sessions), while an identical indexed string is worthless twice by
|
|
389
|
+
construction. Whitespace runs inside each text block collapse to single
|
|
390
|
+
spaces so a space-separated query matches a phrase that wrapped
|
|
391
|
+
across lines. Long prompts keep their head AND tail
|
|
392
|
+
(``_PROMPT_SEARCH_EDGE_CHARS`` each) — users often paste an error
|
|
393
|
+
dump first and type the actual ask at the end. When the session
|
|
394
|
+
total overruns ``_PROMPT_SEARCH_TOTAL_CHARS`` the same rule applies
|
|
395
|
+
across turns: the earliest and latest prompts survive (half the
|
|
396
|
+
budget each) and the middle is elided. Dedup then happens INSIDE
|
|
397
|
+
that front/back selection, not before it: repeats of an
|
|
398
|
+
already-kept text skip for free, so a text stays searchable
|
|
399
|
+
whenever ANY of its copies lands in a kept window. Collapsing
|
|
400
|
+
repeats up front would pin a text to its first copy — and when that
|
|
401
|
+
copy sits in the elided middle, a final-turn repeat of it would
|
|
402
|
+
vanish from the index (review-caught). Message joins and every
|
|
403
|
+
elision seam use a newline, so no phantom match can straddle them
|
|
404
|
+
(the single-line search box cannot type one). The scan is
|
|
405
|
+
memory-bounded end to end: block collapse walks fixed-size raw
|
|
406
|
+
blocks (:meth:`_collapsed_prompt_excerpt`), the accumulation
|
|
407
|
+
pass stops retaining as soon as the budget overruns, and the
|
|
408
|
+
over-budget pass re-derives excerpts per message while keeping
|
|
409
|
+
only the selected windows — so a huge paste or a very long session
|
|
410
|
+
allocates O(budget) transient text. The one whole-session
|
|
411
|
+
allocation left is the flat list of message REFERENCES below,
|
|
412
|
+
pointers into the already-parsed envelope.
|
|
413
|
+
"""
|
|
414
|
+
state = envelope.get("state")
|
|
415
|
+
if not isinstance(state, dict):
|
|
416
|
+
return ""
|
|
417
|
+
message_dicts: list[dict[str, Any]] = []
|
|
418
|
+
blocks = state.get("compressed_msgs", [])
|
|
419
|
+
if isinstance(blocks, list):
|
|
420
|
+
for block in blocks:
|
|
421
|
+
folded = block.get("messages", []) if isinstance(block, dict) else []
|
|
422
|
+
if isinstance(folded, list):
|
|
423
|
+
message_dicts.extend(message for message in folded if isinstance(message, dict))
|
|
424
|
+
messages = state.get("messages", [])
|
|
425
|
+
if isinstance(messages, list):
|
|
426
|
+
message_dicts.extend(message for message in messages if isinstance(message, dict))
|
|
427
|
+
|
|
428
|
+
excerpt = SessionMetaMixin._message_prompt_excerpt
|
|
429
|
+
deduped: list[str] = []
|
|
430
|
+
seen_texts: set[str] = set()
|
|
431
|
+
total = 0
|
|
432
|
+
over_budget = False
|
|
433
|
+
for message in message_dicts:
|
|
434
|
+
part = excerpt(message)
|
|
435
|
+
# Twin dedup keys on the indexed text, NEVER message_id: msg_N
|
|
436
|
+
# ids are positional and collide across compaction archives
|
|
437
|
+
# (same id, different prompt — observed in real sessions).
|
|
438
|
+
if part is None or part in seen_texts:
|
|
439
|
+
continue
|
|
440
|
+
# Separator newlines only exist BETWEEN excerpts — charging one
|
|
441
|
+
# for the first excerpt too would flag an index whose joined
|
|
442
|
+
# length is exactly the budget as over it and needlessly evict
|
|
443
|
+
# middle prompts (review-caught). total tracks the exact
|
|
444
|
+
# length of "\n".join(deduped).
|
|
445
|
+
total += len(part) + 1 if deduped else len(part)
|
|
446
|
+
seen_texts.add(part)
|
|
447
|
+
deduped.append(part)
|
|
448
|
+
if total > _PROMPT_SEARCH_TOTAL_CHARS:
|
|
449
|
+
over_budget = True
|
|
450
|
+
break
|
|
451
|
+
if not over_budget:
|
|
452
|
+
# Every unique text fits, so collapsing repeats onto their first
|
|
453
|
+
# copy loses nothing a substring search could ever see.
|
|
454
|
+
return "\n".join(deduped)
|
|
455
|
+
# Over budget: keep whole prompts from the front and the back until
|
|
456
|
+
# each half fills. The walks re-derive excerpts in RAW message
|
|
457
|
+
# order — repeats of an already-kept text skip for free (no budget,
|
|
458
|
+
# no break) rather than being pre-collapsed onto a first copy that
|
|
459
|
+
# the elided middle may swallow: a text survives if ANY copy lands
|
|
460
|
+
# in a window. A capped excerpt (≤ 2·edge+1 chars) always fits an
|
|
461
|
+
# empty half, so the earliest and latest prompts always stay
|
|
462
|
+
# searchable. Unlike the accumulation pass above, each half DOES
|
|
463
|
+
# charge a separator for its first excerpt: those two spare chars
|
|
464
|
+
# are what keep the final front+back join within the total budget.
|
|
465
|
+
half = _PROMPT_SEARCH_TOTAL_CHARS // 2
|
|
466
|
+
selected: set[str] = set()
|
|
467
|
+
front: list[str] = []
|
|
468
|
+
used = 0
|
|
469
|
+
boundary = len(message_dicts)
|
|
470
|
+
for index, message in enumerate(message_dicts):
|
|
471
|
+
part = excerpt(message)
|
|
472
|
+
if part is None or part in selected:
|
|
473
|
+
continue
|
|
474
|
+
if used + len(part) + 1 > half:
|
|
475
|
+
boundary = index
|
|
476
|
+
break
|
|
477
|
+
front.append(part)
|
|
478
|
+
selected.add(part)
|
|
479
|
+
used += len(part) + 1
|
|
480
|
+
back: list[str] = []
|
|
481
|
+
used = 0
|
|
482
|
+
# The message that overflowed the front half is still eligible for
|
|
483
|
+
# the back half, hence boundary itself is included in the walk.
|
|
484
|
+
for index in range(len(message_dicts) - 1, boundary - 1, -1):
|
|
485
|
+
part = excerpt(message_dicts[index])
|
|
486
|
+
if part is None or part in selected:
|
|
487
|
+
continue
|
|
488
|
+
if used + len(part) + 1 > half:
|
|
489
|
+
break
|
|
490
|
+
back.append(part)
|
|
491
|
+
selected.add(part)
|
|
492
|
+
used += len(part) + 1
|
|
493
|
+
return "\n".join([*front, *reversed(back)])
|
|
494
|
+
|
|
495
|
+
@staticmethod
|
|
496
|
+
def _envelope_total_tokens(envelope: dict[str, Any]) -> int:
|
|
497
|
+
"""Cumulative session token usage recorded in a serialized envelope."""
|
|
498
|
+
state = envelope.get("state")
|
|
499
|
+
if not isinstance(state, dict):
|
|
500
|
+
return 0
|
|
501
|
+
total = state.get(TOTAL_SESSION_TOKENS_KEY, 0)
|
|
502
|
+
return total if isinstance(total, int) and total > 0 else 0
|
|
503
|
+
|
|
504
|
+
@staticmethod
|
|
505
|
+
def _session_meta_from_envelope(envelope: dict[str, Any], *, size_bytes: int) -> SessionMeta:
|
|
506
|
+
"""Build the purpose-specific metadata without reading any run artifacts."""
|
|
507
|
+
meta = envelope["meta"]
|
|
508
|
+
common: dict[str, Any] = {
|
|
509
|
+
"session_id": meta["session_id"],
|
|
510
|
+
"created_at": datetime.fromisoformat(meta["created_at"]),
|
|
511
|
+
"updated_at": datetime.fromisoformat(meta["updated_at"]),
|
|
512
|
+
"total_tokens": SessionMetaMixin._envelope_total_tokens(envelope),
|
|
513
|
+
"primary_cwd": meta.get("primary_cwd") or "",
|
|
514
|
+
"working_dirs": meta.get("working_dirs") or [],
|
|
515
|
+
"title": meta.get("title", ""),
|
|
516
|
+
"custom_title": meta.get("custom_title", ""),
|
|
517
|
+
"generated_title": meta.get("generated_title", ""),
|
|
518
|
+
"size_bytes": size_bytes,
|
|
519
|
+
"app_version": meta.get("app_version", ""),
|
|
520
|
+
"schema_version": meta.get("schema_version", 0),
|
|
521
|
+
"os_name": meta.get("os_name", ""),
|
|
522
|
+
"arch": meta.get("arch", ""),
|
|
523
|
+
}
|
|
524
|
+
if resolve_session_kind(meta) == "workflow":
|
|
525
|
+
state = WorkflowSessionState.decode(envelope.get("state"))
|
|
526
|
+
return WorkflowSessionMeta(
|
|
527
|
+
**common,
|
|
528
|
+
last_surface=state.surface,
|
|
529
|
+
workflow_id=state.identity.workflow_id,
|
|
530
|
+
run_count=state.run_count,
|
|
531
|
+
latest_run_id=state.latest_run_id,
|
|
532
|
+
)
|
|
533
|
+
return ChatSessionMeta(
|
|
534
|
+
**common,
|
|
535
|
+
last_surface=parse_session_surface(meta.get("last_surface")),
|
|
536
|
+
agent_profile=meta.get("agent_profile", ""),
|
|
537
|
+
agent_display_name=meta.get("agent_display_name", meta.get("display_name", "")),
|
|
538
|
+
message_count=meta.get("message_count", 0),
|
|
539
|
+
turn_count=SessionMetaMixin._envelope_turn_count(envelope),
|
|
540
|
+
agent_profile_id=meta.get("agent_profile_id", ""),
|
|
541
|
+
agent_profile_history=meta.get("agent_profile_history", meta.get("profile_history", [])),
|
|
542
|
+
agent_profile_fingerprint=meta.get("agent_profile_fingerprint", ""),
|
|
543
|
+
model_provider=meta.get("model_provider", ""),
|
|
544
|
+
model_api_style=meta.get("model_api_style", ""),
|
|
545
|
+
model_id=meta.get("model_id", ""),
|
|
546
|
+
model_profile_id=meta.get("model_profile_id", ""),
|
|
547
|
+
model_base_url=meta.get("model_base_url", ""),
|
|
548
|
+
model_profile_fingerprint=meta.get("model_profile_fingerprint", ""),
|
|
549
|
+
service_session_id=meta.get("service_session_id", ""),
|
|
550
|
+
parent_session_id=meta.get("parent_session_id", ""),
|
|
551
|
+
user_prompt_search_text=SessionMetaMixin._envelope_user_prompt_search_text(envelope),
|
|
552
|
+
)
|