alloy-runtime-cli 0.1.0__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.
- alloy_runtime_cli-0.1.0.dist-info/METADATA +61 -0
- alloy_runtime_cli-0.1.0.dist-info/RECORD +451 -0
- alloy_runtime_cli-0.1.0.dist-info/WHEEL +5 -0
- alloy_runtime_cli-0.1.0.dist-info/entry_points.txt +2 -0
- alloy_runtime_cli-0.1.0.dist-info/top_level.txt +1 -0
- cli/__init__.py +0 -0
- cli/commands/__init__.py +0 -0
- cli/commands/admin/__init__.py +0 -0
- cli/commands/admin/bootstrap_command.py +118 -0
- cli/commands/admin/credentials/__init__.py +0 -0
- cli/commands/admin/credentials/create/__init__.py +0 -0
- cli/commands/admin/credentials/create/command.py +148 -0
- cli/commands/admin/credentials/create/presenter.py +16 -0
- cli/commands/admin/credentials/grant/__init__.py +0 -0
- cli/commands/admin/credentials/grant/command.py +119 -0
- cli/commands/admin/credentials/grant/fields.py +33 -0
- cli/commands/admin/credentials/grant/presenter.py +23 -0
- cli/commands/agents/__init__.py +0 -0
- cli/commands/agents/create/__init__.py +0 -0
- cli/commands/agents/create/command.py +475 -0
- cli/commands/agents/create/fields.py +64 -0
- cli/commands/agents/create/presenter.py +68 -0
- cli/commands/agents/delete/__init__.py +0 -0
- cli/commands/agents/delete/command.py +47 -0
- cli/commands/agents/delete/presenter.py +16 -0
- cli/commands/agents/get/command.py +37 -0
- cli/commands/agents/get/presenter.py +32 -0
- cli/commands/agents/list/__init__.py +1 -0
- cli/commands/agents/list/command.py +54 -0
- cli/commands/agents/list/presenter.py +82 -0
- cli/commands/agents/update/__init__.py +0 -0
- cli/commands/agents/update/command.py +435 -0
- cli/commands/agents/update/fields.py +40 -0
- cli/commands/agents/update/presenter.py +68 -0
- cli/commands/audio/__init__.py +0 -0
- cli/commands/audio/transcribe/__init__.py +0 -0
- cli/commands/audio/transcribe/command.py +144 -0
- cli/commands/audio/transcribe/presenter.py +15 -0
- cli/commands/auth/__init__.py +0 -0
- cli/commands/auth/login/__init__.py +0 -0
- cli/commands/auth/login/command.py +80 -0
- cli/commands/auth/signup/__init__.py +0 -0
- cli/commands/auth/signup/command.py +115 -0
- cli/commands/billing/__init__.py +1 -0
- cli/commands/billing/costs/__init__.py +1 -0
- cli/commands/billing/costs/by_agent/__init__.py +1 -0
- cli/commands/billing/costs/by_agent/command.py +57 -0
- cli/commands/billing/costs/by_agent/presenter.py +81 -0
- cli/commands/billing/costs/by_model/__init__.py +1 -0
- cli/commands/billing/costs/by_model/command.py +57 -0
- cli/commands/billing/costs/by_model/presenter.py +80 -0
- cli/commands/billing/costs/daily/__init__.py +1 -0
- cli/commands/billing/costs/daily/command.py +55 -0
- cli/commands/billing/costs/daily/presenter.py +75 -0
- cli/commands/billing/costs/summary/__init__.py +1 -0
- cli/commands/billing/costs/summary/command.py +57 -0
- cli/commands/billing/costs/summary/presenter.py +42 -0
- cli/commands/billing/projects/__init__.py +1 -0
- cli/commands/billing/projects/create/__init__.py +1 -0
- cli/commands/billing/projects/create/command.py +60 -0
- cli/commands/billing/projects/create/presenter.py +26 -0
- cli/commands/billing/projects/get/__init__.py +1 -0
- cli/commands/billing/projects/get/command.py +33 -0
- cli/commands/billing/projects/get/presenter.py +32 -0
- cli/commands/billing/projects/list/__init__.py +1 -0
- cli/commands/billing/projects/list/command.py +40 -0
- cli/commands/billing/projects/list/presenter.py +57 -0
- cli/commands/content/__init__.py +1 -0
- cli/commands/content/delete/__init__.py +0 -0
- cli/commands/content/delete/command.py +49 -0
- cli/commands/content/delete/presenter.py +18 -0
- cli/commands/content/edit/__init__.py +1 -0
- cli/commands/content/edit/command.py +155 -0
- cli/commands/content/edit/editor.py +150 -0
- cli/commands/content/edit/presenter.py +146 -0
- cli/commands/content/get/__init__.py +1 -0
- cli/commands/content/get/command.py +39 -0
- cli/commands/content/get/presenter.py +176 -0
- cli/commands/content/list/__init__.py +1 -0
- cli/commands/content/list/command.py +347 -0
- cli/commands/content/list/export_formatters.py +409 -0
- cli/commands/content/list/export_handler.py +165 -0
- cli/commands/content/list/presenter.py +190 -0
- cli/commands/credentials/__init__.py +0 -0
- cli/commands/credentials/create/__init__.py +0 -0
- cli/commands/credentials/create/command.py +165 -0
- cli/commands/credentials/create/fields.py +38 -0
- cli/commands/credentials/create/presenter.py +20 -0
- cli/commands/credentials/update/__init__.py +0 -0
- cli/commands/credentials/update/command.py +53 -0
- cli/commands/credentials/update/fields.py +71 -0
- cli/commands/credentials/update/presenter.py +16 -0
- cli/commands/flag_utils.py +366 -0
- cli/commands/generate/__init__.py +0 -0
- cli/commands/generate/cancel/__init__.py +1 -0
- cli/commands/generate/cancel/command.py +44 -0
- cli/commands/generate/cancel/presenter.py +26 -0
- cli/commands/generate/status/__init__.py +1 -0
- cli/commands/generate/status/command.py +58 -0
- cli/commands/generate/status/presenter.py +78 -0
- cli/commands/generate/text/__init__.py +0 -0
- cli/commands/generate/text/command.py +1325 -0
- cli/commands/generate/text/concurrent_renderer.py +355 -0
- cli/commands/generate/text/presenter.py +287 -0
- cli/commands/generate/text/stream_renderer.py +129 -0
- cli/commands/knowledge/__init__.py +0 -0
- cli/commands/knowledge/collections/__init__.py +0 -0
- cli/commands/knowledge/collections/cluster/__init__.py +0 -0
- cli/commands/knowledge/collections/cluster/command.py +64 -0
- cli/commands/knowledge/collections/cluster/presenter.py +74 -0
- cli/commands/knowledge/collections/cluster_status/__init__.py +0 -0
- cli/commands/knowledge/collections/cluster_status/command.py +46 -0
- cli/commands/knowledge/collections/cluster_status/presenter.py +10 -0
- cli/commands/knowledge/collections/create/__init__.py +0 -0
- cli/commands/knowledge/collections/create/command.py +137 -0
- cli/commands/knowledge/collections/create/presenter.py +38 -0
- cli/commands/knowledge/collections/delete/__init__.py +1 -0
- cli/commands/knowledge/collections/delete/command.py +47 -0
- cli/commands/knowledge/collections/delete/presenter.py +20 -0
- cli/commands/knowledge/collections/get/__init__.py +1 -0
- cli/commands/knowledge/collections/get/command.py +30 -0
- cli/commands/knowledge/collections/get/presenter.py +44 -0
- cli/commands/knowledge/collections/list/__init__.py +1 -0
- cli/commands/knowledge/collections/list/command.py +41 -0
- cli/commands/knowledge/collections/list/presenter.py +68 -0
- cli/commands/knowledge/collections/update/__init__.py +0 -0
- cli/commands/knowledge/collections/update/command.py +97 -0
- cli/commands/knowledge/collections/update/presenter.py +42 -0
- cli/commands/knowledge/documents/__init__.py +0 -0
- cli/commands/knowledge/documents/bulk_metadata/__init__.py +0 -0
- cli/commands/knowledge/documents/bulk_metadata/command.py +119 -0
- cli/commands/knowledge/documents/bulk_metadata/presenter.py +36 -0
- cli/commands/knowledge/documents/delete/__init__.py +0 -0
- cli/commands/knowledge/documents/delete/command.py +47 -0
- cli/commands/knowledge/documents/delete/presenter.py +20 -0
- cli/commands/knowledge/documents/get/__init__.py +0 -0
- cli/commands/knowledge/documents/get/command.py +39 -0
- cli/commands/knowledge/documents/get/presenter.py +78 -0
- cli/commands/knowledge/documents/ingest/__init__.py +0 -0
- cli/commands/knowledge/documents/ingest/command.py +222 -0
- cli/commands/knowledge/documents/ingest/presenter.py +41 -0
- cli/commands/knowledge/documents/list/__init__.py +0 -0
- cli/commands/knowledge/documents/list/command.py +69 -0
- cli/commands/knowledge/documents/list/presenter.py +86 -0
- cli/commands/knowledge/documents/reingest/__init__.py +0 -0
- cli/commands/knowledge/documents/reingest/command.py +102 -0
- cli/commands/knowledge/documents/reingest/presenter.py +70 -0
- cli/commands/knowledge/documents/update/__init__.py +0 -0
- cli/commands/knowledge/documents/update/command.py +85 -0
- cli/commands/knowledge/documents/update/presenter.py +37 -0
- cli/commands/knowledge/recover/__init__.py +0 -0
- cli/commands/knowledge/recover/command.py +46 -0
- cli/commands/knowledge/recover/presenter.py +79 -0
- cli/commands/knowledge/search/__init__.py +0 -0
- cli/commands/knowledge/search/command.py +218 -0
- cli/commands/knowledge/search/presenter.py +111 -0
- cli/commands/knowledge/synthesis/__init__.py +0 -0
- cli/commands/knowledge/synthesis/create/__init__.py +0 -0
- cli/commands/knowledge/synthesis/create/command.py +127 -0
- cli/commands/knowledge/synthesis/create/presenter.py +33 -0
- cli/commands/knowledge/synthesis/delete/__init__.py +0 -0
- cli/commands/knowledge/synthesis/delete/command.py +53 -0
- cli/commands/knowledge/synthesis/delete/presenter.py +31 -0
- cli/commands/knowledge/synthesis/get/__init__.py +0 -0
- cli/commands/knowledge/synthesis/get/command.py +55 -0
- cli/commands/knowledge/synthesis/get/presenter.py +114 -0
- cli/commands/knowledge/synthesis/list/__init__.py +0 -0
- cli/commands/knowledge/synthesis/list/command.py +132 -0
- cli/commands/knowledge/synthesis/list/presenter.py +84 -0
- cli/commands/knowledge/synthesis/refresh/__init__.py +0 -0
- cli/commands/knowledge/synthesis/refresh/command.py +42 -0
- cli/commands/knowledge/synthesis/refresh/presenter.py +33 -0
- cli/commands/knowledge/synthesis/update/__init__.py +0 -0
- cli/commands/knowledge/synthesis/update/command.py +76 -0
- cli/commands/knowledge/synthesis/update/presenter.py +41 -0
- cli/commands/models/__init__.py +0 -0
- cli/commands/models/list/__init__.py +0 -0
- cli/commands/models/list/command.py +84 -0
- cli/commands/models/list/presenter.py +114 -0
- cli/commands/organizations/__init__.py +0 -0
- cli/commands/organizations/create/command.py +32 -0
- cli/commands/organizations/create/presenter.py +9 -0
- cli/commands/pipelines/__init__.py +1 -0
- cli/commands/pipelines/approvals/__init__.py +1 -0
- cli/commands/pipelines/approvals/decide_command.py +77 -0
- cli/commands/pipelines/approvals/get_command.py +44 -0
- cli/commands/pipelines/approvals/presenter.py +56 -0
- cli/commands/pipelines/costs/__init__.py +1 -0
- cli/commands/pipelines/costs/command.py +57 -0
- cli/commands/pipelines/costs/daily_command.py +54 -0
- cli/commands/pipelines/costs/daily_presenter.py +59 -0
- cli/commands/pipelines/costs/presenter.py +37 -0
- cli/commands/pipelines/create/__init__.py +1 -0
- cli/commands/pipelines/create/command.py +103 -0
- cli/commands/pipelines/create/presenter.py +22 -0
- cli/commands/pipelines/env_vars/__init__.py +1 -0
- cli/commands/pipelines/env_vars/command.py +51 -0
- cli/commands/pipelines/env_vars/presenter.py +16 -0
- cli/commands/pipelines/execute/__init__.py +1 -0
- cli/commands/pipelines/execute/command.py +142 -0
- cli/commands/pipelines/execute/presenter.py +47 -0
- cli/commands/pipelines/executions/__init__.py +1 -0
- cli/commands/pipelines/executions/costs/__init__.py +1 -0
- cli/commands/pipelines/executions/costs/command.py +48 -0
- cli/commands/pipelines/executions/costs/presenter.py +29 -0
- cli/commands/pipelines/executions/costs_by_model/__init__.py +1 -0
- cli/commands/pipelines/executions/costs_by_model/command.py +50 -0
- cli/commands/pipelines/executions/costs_by_model/presenter.py +78 -0
- cli/commands/pipelines/executions/costs_by_step/__init__.py +1 -0
- cli/commands/pipelines/executions/costs_by_step/command.py +50 -0
- cli/commands/pipelines/executions/costs_by_step/presenter.py +72 -0
- cli/commands/pipelines/executions/get_command.py +38 -0
- cli/commands/pipelines/executions/list_command.py +123 -0
- cli/commands/pipelines/executions/presenter.py +131 -0
- cli/commands/pipelines/executions/rerun_command.py +41 -0
- cli/commands/pipelines/executions/update/__init__.py +1 -0
- cli/commands/pipelines/executions/update/command.py +110 -0
- cli/commands/pipelines/executions/update/presenter.py +28 -0
- cli/commands/pipelines/get/__init__.py +1 -0
- cli/commands/pipelines/get/command.py +33 -0
- cli/commands/pipelines/get/presenter.py +48 -0
- cli/commands/pipelines/list/__init__.py +1 -0
- cli/commands/pipelines/list/command.py +53 -0
- cli/commands/pipelines/list/presenter.py +66 -0
- cli/commands/pipelines/schedules/__init__.py +1 -0
- cli/commands/pipelines/schedules/create_command.py +119 -0
- cli/commands/pipelines/schedules/create_presenter.py +35 -0
- cli/commands/pipelines/schedules/delete_command.py +52 -0
- cli/commands/pipelines/schedules/env_vars_command.py +59 -0
- cli/commands/pipelines/schedules/env_vars_presenter.py +16 -0
- cli/commands/pipelines/schedules/get_command.py +38 -0
- cli/commands/pipelines/schedules/list_command.py +33 -0
- cli/commands/pipelines/schedules/once_command.py +90 -0
- cli/commands/pipelines/schedules/once_presenter.py +30 -0
- cli/commands/pipelines/schedules/presenter.py +104 -0
- cli/commands/pipelines/schedules/update_command.py +139 -0
- cli/commands/pipelines/schedules/update_presenter.py +29 -0
- cli/commands/render/__init__.py +0 -0
- cli/commands/render/html_to_image/__init__.py +0 -0
- cli/commands/render/html_to_image/command.py +170 -0
- cli/commands/schemas/__init__.py +0 -0
- cli/commands/schemas/create/__init__.py +0 -0
- cli/commands/schemas/create/command.py +122 -0
- cli/commands/schemas/create/presenter.py +53 -0
- cli/commands/schemas/delete/command.py +45 -0
- cli/commands/schemas/delete/presenter.py +9 -0
- cli/commands/schemas/get/__init__.py +0 -0
- cli/commands/schemas/get/command.py +56 -0
- cli/commands/schemas/get/presenter.py +129 -0
- cli/commands/schemas/list/__init__.py +0 -0
- cli/commands/schemas/list/command.py +64 -0
- cli/commands/schemas/list/presenter.py +133 -0
- cli/commands/schemas/update/__init__.py +0 -0
- cli/commands/schemas/update/command.py +369 -0
- cli/commands/schemas/update/presenter.py +53 -0
- cli/commands/sessions/__init__.py +1 -0
- cli/commands/sessions/delete/__init__.py +1 -0
- cli/commands/sessions/delete/command.py +47 -0
- cli/commands/sessions/delete/presenter.py +10 -0
- cli/commands/sessions/get/__init__.py +1 -0
- cli/commands/sessions/get/command.py +42 -0
- cli/commands/sessions/get/presenter.py +59 -0
- cli/commands/sessions/list/__init__.py +1 -0
- cli/commands/sessions/list/command.py +61 -0
- cli/commands/sessions/list/presenter.py +68 -0
- cli/commands/sessions/messages/__init__.py +1 -0
- cli/commands/sessions/messages/command.py +78 -0
- cli/commands/sessions/messages/presenter.py +79 -0
- cli/commands/shared_flags.py +500 -0
- cli/commands/sync/__init__.py +0 -0
- cli/commands/sync/command.py +45 -0
- cli/commands/sync/presenter.py +49 -0
- cli/commands/tags/__init__.py +1 -0
- cli/commands/tags/create/__init__.py +1 -0
- cli/commands/tags/create/command.py +60 -0
- cli/commands/tags/delete/__init__.py +1 -0
- cli/commands/tags/delete/command.py +47 -0
- cli/commands/tags/delete/presenter.py +10 -0
- cli/commands/tags/get/command.py +31 -0
- cli/commands/tags/get/presenter.py +23 -0
- cli/commands/tags/list/__init__.py +1 -0
- cli/commands/tags/list/command.py +52 -0
- cli/commands/tags/list/presenter.py +49 -0
- cli/commands/tags/update/command.py +64 -0
- cli/commands/tags/update/presenter.py +9 -0
- cli/commands/templates/__init__.py +0 -0
- cli/commands/templates/create/__init__.py +0 -0
- cli/commands/templates/create/command.py +152 -0
- cli/commands/templates/create/presenter.py +86 -0
- cli/commands/templates/delete/__init__.py +0 -0
- cli/commands/templates/delete/command.py +47 -0
- cli/commands/templates/delete/presenter.py +16 -0
- cli/commands/templates/get/__init__.py +0 -0
- cli/commands/templates/get/command.py +52 -0
- cli/commands/templates/get/presenter.py +233 -0
- cli/commands/templates/get_by_version/command.py +32 -0
- cli/commands/templates/get_by_version/presenter.py +30 -0
- cli/commands/templates/list/__init__.py +1 -0
- cli/commands/templates/list/command.py +102 -0
- cli/commands/templates/list/presenter.py +93 -0
- cli/commands/templates/render/__init__.py +0 -0
- cli/commands/templates/render/command.py +115 -0
- cli/commands/templates/render/presenter.py +276 -0
- cli/commands/templates/update/__init__.py +0 -0
- cli/commands/templates/update/command.py +199 -0
- cli/commands/templates/update/presenter.py +94 -0
- cli/commands/templates/version/__init__.py +1 -0
- cli/commands/templates/version/command.py +116 -0
- cli/commands/templates/version/presenter.py +100 -0
- cli/commands/tool_configs/__init__.py +0 -0
- cli/commands/tool_configs/create/__init__.py +0 -0
- cli/commands/tool_configs/create/command.py +118 -0
- cli/commands/tool_configs/create/presenter.py +53 -0
- cli/commands/tool_configs/delete/__init__.py +0 -0
- cli/commands/tool_configs/delete/command.py +47 -0
- cli/commands/tool_configs/delete/presenter.py +18 -0
- cli/commands/tool_configs/get/__init__.py +0 -0
- cli/commands/tool_configs/get/command.py +31 -0
- cli/commands/tool_configs/get/presenter.py +62 -0
- cli/commands/tool_configs/list/__init__.py +0 -0
- cli/commands/tool_configs/list/command.py +59 -0
- cli/commands/tool_configs/list/presenter.py +60 -0
- cli/commands/tool_configs/update/__init__.py +0 -0
- cli/commands/tool_configs/update/command.py +128 -0
- cli/commands/tool_configs/update/presenter.py +53 -0
- cli/commands/tools/__init__.py +1 -0
- cli/commands/tools/get/__init__.py +1 -0
- cli/commands/tools/get/command.py +42 -0
- cli/commands/tools/get/presenter.py +45 -0
- cli/commands/tools/list/__init__.py +1 -0
- cli/commands/tools/list/command.py +56 -0
- cli/commands/tools/list/presenter.py +44 -0
- cli/commands/users/__init__.py +0 -0
- cli/commands/users/create/command.py +53 -0
- cli/commands/users/create/presenter.py +9 -0
- cli/commands/whoami/__init__.py +0 -0
- cli/commands/whoami/command.py +42 -0
- cli/infrastructure/__init__.py +0 -0
- cli/infrastructure/auth_storage.py +71 -0
- cli/infrastructure/client_factory.py +36 -0
- cli/infrastructure/command.py +75 -0
- cli/infrastructure/config.py +188 -0
- cli/infrastructure/console.py +27 -0
- cli/infrastructure/editor.py +138 -0
- cli/infrastructure/error_display.py +178 -0
- cli/infrastructure/field_extractor.py +360 -0
- cli/infrastructure/file_content.py +210 -0
- cli/infrastructure/filter_parser.py +256 -0
- cli/infrastructure/formatters/__init__.py +0 -0
- cli/infrastructure/formatters/base.py +99 -0
- cli/infrastructure/formatters/compact_formatter.py +245 -0
- cli/infrastructure/formatters/json_formatter.py +84 -0
- cli/infrastructure/formatters/lines_formatter.py +102 -0
- cli/infrastructure/formatting/__init__.py +0 -0
- cli/infrastructure/formatting/fields.py +193 -0
- cli/infrastructure/forms/__init__.py +0 -0
- cli/infrastructure/forms/agent_picker.py +123 -0
- cli/infrastructure/forms/agent_tool_editor.py +384 -0
- cli/infrastructure/forms/agent_tools_manager.py +212 -0
- cli/infrastructure/forms/base_picker.py +469 -0
- cli/infrastructure/forms/components.py +126 -0
- cli/infrastructure/forms/json_schema_builder.py +149 -0
- cli/infrastructure/forms/model_picker.py +134 -0
- cli/infrastructure/forms/parsers.py +173 -0
- cli/infrastructure/forms/resolution_modal.py +302 -0
- cli/infrastructure/forms/schema_picker.py +137 -0
- cli/infrastructure/forms/tag_management_modal.py +103 -0
- cli/infrastructure/forms/tag_picker.py +207 -0
- cli/infrastructure/forms/template_picker.py +131 -0
- cli/infrastructure/forms/tool_config_picker.py +130 -0
- cli/infrastructure/forms/tool_picker.py +103 -0
- cli/infrastructure/injection/__init__.py +0 -0
- cli/infrastructure/injection/parser.py +302 -0
- cli/infrastructure/injection/resolver.py +399 -0
- cli/infrastructure/kv_parser.py +130 -0
- cli/infrastructure/local_storage.py +227 -0
- cli/infrastructure/macro_parser.py +215 -0
- cli/infrastructure/output.py +192 -0
- cli/infrastructure/provider_setup.py +81 -0
- cli/infrastructure/renderers/__init__.py +0 -0
- cli/infrastructure/renderers/entity_renderer.py +77 -0
- cli/infrastructure/renderers/list_renderer.py +114 -0
- cli/infrastructure/scope_utils.py +47 -0
- cli/infrastructure/spinner.py +101 -0
- cli/infrastructure/tui/__init__.py +0 -0
- cli/infrastructure/tui/clipboard.py +41 -0
- cli/infrastructure/tui/formatters.py +105 -0
- cli/infrastructure/tui/preview.py +14 -0
- cli/infrastructure/tui/selectable.py +198 -0
- cli/infrastructure/validation/__init__.py +0 -0
- cli/infrastructure/validation/tag_validation.py +74 -0
- cli/main.py +759 -0
- cli/tui/__init__.py +0 -0
- cli/tui/app.py +199 -0
- cli/tui/app_store.py +73 -0
- cli/tui/chat/__init__.py +0 -0
- cli/tui/chat/commands/__init__.py +0 -0
- cli/tui/chat/commands/base.py +65 -0
- cli/tui/chat/commands/create_session.py +135 -0
- cli/tui/chat/commands/load_session.py +119 -0
- cli/tui/chat/commands/regenerate.py +120 -0
- cli/tui/chat/commands/reload_session.py +63 -0
- cli/tui/chat/commands/send_message.py +190 -0
- cli/tui/chat/commands/undo.py +66 -0
- cli/tui/chat/editor.py +71 -0
- cli/tui/chat/messages.py +223 -0
- cli/tui/chat/pane.py +141 -0
- cli/tui/chat/renderers/__init__.py +0 -0
- cli/tui/chat/renderers/base.py +72 -0
- cli/tui/chat/renderers/markdown.py +250 -0
- cli/tui/chat/renderers/plain.py +83 -0
- cli/tui/chat/screen.py +1155 -0
- cli/tui/chat/services/__init__.py +0 -0
- cli/tui/chat/services/injection.py +386 -0
- cli/tui/chat/services/name_generator.py +256 -0
- cli/tui/chat/slash_commands.py +424 -0
- cli/tui/chat/store.py +280 -0
- cli/tui/chat/types.py +220 -0
- cli/tui/chat/widgets/__init__.py +0 -0
- cli/tui/chat/widgets/chat_header.py +75 -0
- cli/tui/chat/widgets/chat_input.py +362 -0
- cli/tui/chat/widgets/injection_popup.py +161 -0
- cli/tui/chat/widgets/message_display.py +287 -0
- cli/tui/chat/widgets/session_sidebar.py +214 -0
- cli/tui/chat/widgets/welcome_screen.py +290 -0
- cli/tui/screens/__init__.py +0 -0
- cli/tui/screens/agents.py +344 -0
- cli/tui/screens/base.py +301 -0
- cli/tui/screens/content.py +508 -0
- cli/tui/screens/dashboard.py +89 -0
- cli/tui/screens/models.py +96 -0
- cli/tui/screens/nav_screen.py +186 -0
- cli/tui/screens/schemas.py +522 -0
- cli/tui/screens/templates.py +734 -0
- cli/tui/screens/tool_configs.py +335 -0
- cli/tui/styles/__init__.py +0 -0
- cli/tui/widgets/__init__.py +0 -0
- cli/tui/widgets/agent_create_modal.py +139 -0
- cli/tui/widgets/agent_form_modal.py +659 -0
- cli/tui/widgets/agent_update_modal.py +299 -0
- cli/tui/widgets/base_form_modal.py +77 -0
- cli/tui/widgets/confirm_modal.py +75 -0
- cli/tui/widgets/help_modal.py +145 -0
- cli/tui/widgets/new_session_modal.py +328 -0
- cli/tui/widgets/schema_create_modal.py +271 -0
- cli/tui/widgets/schema_update_modal.py +188 -0
- cli/tui/widgets/status_footer.py +147 -0
- cli/tui/widgets/template_create_modal.py +502 -0
- cli/tui/widgets/template_update_modal.py +308 -0
- cli/tui/widgets/tool_config_create_modal.py +216 -0
- cli/tui/widgets/tool_config_update_modal.py +208 -0
|
@@ -0,0 +1,522 @@
|
|
|
1
|
+
"""Schemas screen for browsing and managing validation schemas.
|
|
2
|
+
|
|
3
|
+
This screen provides:
|
|
4
|
+
- Search and browse input/output schemas
|
|
5
|
+
- View schema definitions in preview panel
|
|
6
|
+
- Edit schema definitions in $EDITOR
|
|
7
|
+
- Create new schema versions
|
|
8
|
+
- Copy schema names and definitions
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
import json
|
|
12
|
+
import os
|
|
13
|
+
import subprocess
|
|
14
|
+
import tempfile
|
|
15
|
+
from typing import TYPE_CHECKING, Any
|
|
16
|
+
from uuid import UUID
|
|
17
|
+
|
|
18
|
+
from textual import on, work
|
|
19
|
+
from textual.app import ComposeResult
|
|
20
|
+
from textual.binding import Binding
|
|
21
|
+
from textual.widgets import DataTable, Static
|
|
22
|
+
|
|
23
|
+
from alloy_runtime_types.dtos.schemas import (
|
|
24
|
+
GetSchemaResponse,
|
|
25
|
+
SchemaSummary,
|
|
26
|
+
UpdateSchemaRequest,
|
|
27
|
+
)
|
|
28
|
+
|
|
29
|
+
from cli.infrastructure.scope_utils import format_scope_label
|
|
30
|
+
from cli.infrastructure.tui.clipboard import copy_to_clipboard
|
|
31
|
+
from cli.infrastructure.tui.formatters import format_datetime, truncate_text
|
|
32
|
+
from cli.tui.screens.base import BrowserWidget
|
|
33
|
+
from cli.tui.screens.nav_screen import NavScreen
|
|
34
|
+
from cli.tui.widgets.schema_create_modal import SchemaCreateModal, SchemaCreateResult
|
|
35
|
+
from cli.tui.widgets.schema_update_modal import SchemaUpdateModal, SchemaUpdateResult
|
|
36
|
+
|
|
37
|
+
if TYPE_CHECKING:
|
|
38
|
+
from cli.tui.app import AlloyRuntimeApp
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
class SchemasWidget(BrowserWidget[SchemaSummary]):
|
|
42
|
+
"""Widget for browsing and managing schemas."""
|
|
43
|
+
|
|
44
|
+
app: "AlloyRuntimeApp"
|
|
45
|
+
|
|
46
|
+
TITLE = "Schemas"
|
|
47
|
+
TABLE_COLUMNS = ["Name", "Format", "Version", "Updated"]
|
|
48
|
+
|
|
49
|
+
def __init__(self, **kwargs: Any) -> None:
|
|
50
|
+
super().__init__(**kwargs)
|
|
51
|
+
# Cache for full schema details (keyed by schema ID)
|
|
52
|
+
self._schema_cache: dict[str, GetSchemaResponse] = {}
|
|
53
|
+
|
|
54
|
+
async def _fetch_items(self, query: str) -> tuple[list[SchemaSummary], int]:
|
|
55
|
+
"""Fetch schemas from the API."""
|
|
56
|
+
client = await self._ensure_client()
|
|
57
|
+
response = await client.list_schemas(
|
|
58
|
+
search=query if query else None,
|
|
59
|
+
limit=50,
|
|
60
|
+
)
|
|
61
|
+
return response.schemas, response.total
|
|
62
|
+
|
|
63
|
+
def _format_row(self, item: SchemaSummary) -> tuple[str, ...]:
|
|
64
|
+
"""Format a schema as a table row."""
|
|
65
|
+
return (
|
|
66
|
+
truncate_text(item.schema_name, max_length=40),
|
|
67
|
+
item.schema_format_id,
|
|
68
|
+
f"v{item.version}" if item.is_latest else f"v{item.version} (old)",
|
|
69
|
+
format_datetime(item.updated_at),
|
|
70
|
+
)
|
|
71
|
+
|
|
72
|
+
@on(DataTable.RowHighlighted)
|
|
73
|
+
def _on_row_highlighted(self, event: DataTable.RowHighlighted) -> None:
|
|
74
|
+
"""Fetch full schema details when row is highlighted."""
|
|
75
|
+
row_index = event.cursor_row
|
|
76
|
+
if 0 <= row_index < len(self._items):
|
|
77
|
+
schema_summary = self._items[row_index]
|
|
78
|
+
schema_id = str(schema_summary.id)
|
|
79
|
+
|
|
80
|
+
# Check cache first
|
|
81
|
+
if schema_id in self._schema_cache:
|
|
82
|
+
self._update_preview_with_full_schema(
|
|
83
|
+
schema_summary, self._schema_cache[schema_id]
|
|
84
|
+
)
|
|
85
|
+
else:
|
|
86
|
+
# Fetch full details and update preview
|
|
87
|
+
self._fetch_full_schema(schema_summary)
|
|
88
|
+
|
|
89
|
+
@work(exclusive=True, group="schema_fetch")
|
|
90
|
+
async def _fetch_full_schema(self, schema_summary: SchemaSummary) -> None:
|
|
91
|
+
"""Fetch full schema details from API and update preview."""
|
|
92
|
+
try:
|
|
93
|
+
client = await self._ensure_client()
|
|
94
|
+
full_schema = await client.get_schema(str(schema_summary.id))
|
|
95
|
+
|
|
96
|
+
# Cache the result
|
|
97
|
+
self._schema_cache[str(schema_summary.id)] = full_schema
|
|
98
|
+
|
|
99
|
+
# Update preview with full details
|
|
100
|
+
self._update_preview_with_full_schema(schema_summary, full_schema)
|
|
101
|
+
|
|
102
|
+
except Exception as e:
|
|
103
|
+
# Fall back to summary-only preview
|
|
104
|
+
self._update_preview(schema_summary)
|
|
105
|
+
self.app.notify(f"Failed to fetch schema details: {e}", severity="warning")
|
|
106
|
+
|
|
107
|
+
def _update_preview(self, item: SchemaSummary) -> None:
|
|
108
|
+
"""Update the preview pane with schema summary (fallback)."""
|
|
109
|
+
preview = self.query_one("#preview-content", Static)
|
|
110
|
+
|
|
111
|
+
created = format_datetime(item.created_at)
|
|
112
|
+
scope = format_scope_label(
|
|
113
|
+
str(item.organization_id) if item.organization_id else None,
|
|
114
|
+
str(item.user_id) if item.user_id else None,
|
|
115
|
+
)
|
|
116
|
+
|
|
117
|
+
preview_text = f"""[bold]Schema ID:[/] {item.id}
|
|
118
|
+
[bold]Name:[/] {item.schema_name}
|
|
119
|
+
[bold]Format:[/] {item.schema_format_id}
|
|
120
|
+
[bold]Version:[/] v{item.version} {"(latest)" if item.is_latest else "(superseded)"}
|
|
121
|
+
[bold]Scope:[/] {scope}
|
|
122
|
+
|
|
123
|
+
[bold]Description:[/]
|
|
124
|
+
{item.description or "(no description)"}
|
|
125
|
+
|
|
126
|
+
[bold]Created:[/] {created}
|
|
127
|
+
|
|
128
|
+
[italic]Loading schema definition...[/]"""
|
|
129
|
+
|
|
130
|
+
preview.update(preview_text)
|
|
131
|
+
|
|
132
|
+
def _update_preview_with_full_schema(
|
|
133
|
+
self, summary: SchemaSummary, full_schema: GetSchemaResponse
|
|
134
|
+
) -> None:
|
|
135
|
+
"""Update the preview pane with full schema details including definition."""
|
|
136
|
+
preview = self.query_one("#preview-content", Static)
|
|
137
|
+
|
|
138
|
+
created = format_datetime(summary.created_at)
|
|
139
|
+
scope = format_scope_label(
|
|
140
|
+
str(summary.organization_id) if summary.organization_id else None,
|
|
141
|
+
str(summary.user_id) if summary.user_id else None,
|
|
142
|
+
)
|
|
143
|
+
|
|
144
|
+
# Format the schema definition for display
|
|
145
|
+
definition_display = self._format_definition_for_display(
|
|
146
|
+
full_schema.schema_definition, full_schema.schema_format_id
|
|
147
|
+
)
|
|
148
|
+
|
|
149
|
+
preview_text = f"""[bold]Schema ID:[/] {summary.id}
|
|
150
|
+
[bold]Name:[/] {summary.schema_name}
|
|
151
|
+
[bold]Format:[/] {summary.schema_format_id}
|
|
152
|
+
[bold]Version:[/] v{summary.version} {"(latest)" if summary.is_latest else "(superseded)"}
|
|
153
|
+
[bold]Scope:[/] {scope}
|
|
154
|
+
|
|
155
|
+
[bold]Description:[/]
|
|
156
|
+
{summary.description or "(no description)"}
|
|
157
|
+
|
|
158
|
+
[bold]Created:[/] {created}
|
|
159
|
+
|
|
160
|
+
[bold]Definition:[/]
|
|
161
|
+
{definition_display}"""
|
|
162
|
+
|
|
163
|
+
preview.update(preview_text)
|
|
164
|
+
|
|
165
|
+
def _format_definition_for_display(
|
|
166
|
+
self, definition: str, schema_format: str
|
|
167
|
+
) -> str:
|
|
168
|
+
"""Format schema definition for preview display."""
|
|
169
|
+
if schema_format == "json_schema":
|
|
170
|
+
try:
|
|
171
|
+
parsed = json.loads(definition)
|
|
172
|
+
formatted = json.dumps(parsed, indent=2, ensure_ascii=False)
|
|
173
|
+
# Truncate if too long
|
|
174
|
+
max_length = 2000
|
|
175
|
+
if len(formatted) > max_length:
|
|
176
|
+
formatted = formatted[:max_length] + "\n... (truncated)"
|
|
177
|
+
return formatted
|
|
178
|
+
except (json.JSONDecodeError, TypeError):
|
|
179
|
+
return definition
|
|
180
|
+
else:
|
|
181
|
+
# Regex or other formats - display as-is
|
|
182
|
+
return definition
|
|
183
|
+
|
|
184
|
+
def _get_cached_schema(self, schema_id: str) -> GetSchemaResponse | None:
|
|
185
|
+
"""Get cached full schema details, or None if not cached."""
|
|
186
|
+
return self._schema_cache.get(schema_id)
|
|
187
|
+
|
|
188
|
+
def _open_editor_for_schema(
|
|
189
|
+
self, name_hint: str, initial_content: str, schema_format: str
|
|
190
|
+
) -> str | None:
|
|
191
|
+
"""Open external editor with schema definition.
|
|
192
|
+
|
|
193
|
+
Args:
|
|
194
|
+
name_hint: Name to include in temp file name
|
|
195
|
+
initial_content: Initial schema definition content
|
|
196
|
+
schema_format: Schema format (json_schema or regex)
|
|
197
|
+
|
|
198
|
+
Returns:
|
|
199
|
+
Edited content, or None if editor failed
|
|
200
|
+
"""
|
|
201
|
+
editor = os.environ.get("EDITOR") or os.environ.get("VISUAL") or "vi"
|
|
202
|
+
|
|
203
|
+
# Choose file extension based on schema format for syntax highlighting
|
|
204
|
+
if schema_format == "json_schema":
|
|
205
|
+
suffix = ".json"
|
|
206
|
+
# Pretty-print JSON for better editing experience
|
|
207
|
+
try:
|
|
208
|
+
parsed = json.loads(initial_content)
|
|
209
|
+
initial_content = json.dumps(parsed, indent=2, ensure_ascii=False)
|
|
210
|
+
except (json.JSONDecodeError, TypeError):
|
|
211
|
+
pass
|
|
212
|
+
else:
|
|
213
|
+
suffix = ".txt"
|
|
214
|
+
|
|
215
|
+
try:
|
|
216
|
+
with tempfile.NamedTemporaryFile(
|
|
217
|
+
mode="w",
|
|
218
|
+
suffix=suffix,
|
|
219
|
+
prefix=f"schema_{name_hint}_",
|
|
220
|
+
delete=False,
|
|
221
|
+
encoding="utf-8",
|
|
222
|
+
) as f:
|
|
223
|
+
f.write(initial_content)
|
|
224
|
+
temp_path = f.name
|
|
225
|
+
|
|
226
|
+
with self.app.suspend():
|
|
227
|
+
subprocess.run([editor, temp_path], check=False)
|
|
228
|
+
|
|
229
|
+
with open(temp_path, encoding="utf-8") as f:
|
|
230
|
+
new_content = f.read()
|
|
231
|
+
|
|
232
|
+
try:
|
|
233
|
+
os.unlink(temp_path)
|
|
234
|
+
except OSError:
|
|
235
|
+
pass
|
|
236
|
+
|
|
237
|
+
return new_content
|
|
238
|
+
|
|
239
|
+
except Exception as e:
|
|
240
|
+
self.app.notify(f"Failed to open editor: {e}", severity="error")
|
|
241
|
+
return None
|
|
242
|
+
|
|
243
|
+
# =========================================================================
|
|
244
|
+
# Public methods for parent Screen to call
|
|
245
|
+
# =========================================================================
|
|
246
|
+
|
|
247
|
+
def copy_schema_name(self) -> None:
|
|
248
|
+
"""Copy the schema name to clipboard."""
|
|
249
|
+
schema = self.get_selected_item()
|
|
250
|
+
if not schema:
|
|
251
|
+
self.app.notify("No schema selected", severity="warning")
|
|
252
|
+
return
|
|
253
|
+
|
|
254
|
+
copy_to_clipboard(self.app, schema.schema_name, "Schema name")
|
|
255
|
+
|
|
256
|
+
async def open_new_schema_modal(self) -> None:
|
|
257
|
+
"""Open the schema creation form."""
|
|
258
|
+
client = await self._ensure_client()
|
|
259
|
+
|
|
260
|
+
def on_schema_created(result: SchemaCreateResult | None) -> None:
|
|
261
|
+
if result is not None:
|
|
262
|
+
self.app.notify(
|
|
263
|
+
f"Created schema: {result.schema_name} v{result.version}",
|
|
264
|
+
severity="information",
|
|
265
|
+
)
|
|
266
|
+
self.refresh_data()
|
|
267
|
+
|
|
268
|
+
self.app.push_screen(
|
|
269
|
+
SchemaCreateModal(client=client),
|
|
270
|
+
on_schema_created,
|
|
271
|
+
)
|
|
272
|
+
|
|
273
|
+
def copy_schema_definition(self) -> None:
|
|
274
|
+
"""Copy the schema definition to clipboard."""
|
|
275
|
+
schema = self.get_selected_item()
|
|
276
|
+
if not schema:
|
|
277
|
+
self.app.notify("No schema selected", severity="warning")
|
|
278
|
+
return
|
|
279
|
+
|
|
280
|
+
# Get full schema from cache
|
|
281
|
+
full_schema = self._get_cached_schema(str(schema.id))
|
|
282
|
+
if not full_schema:
|
|
283
|
+
self.app.notify(
|
|
284
|
+
"Schema definition not loaded yet. Please wait.", severity="warning"
|
|
285
|
+
)
|
|
286
|
+
return
|
|
287
|
+
|
|
288
|
+
# Format JSON nicely for clipboard
|
|
289
|
+
definition = full_schema.schema_definition
|
|
290
|
+
if full_schema.schema_format_id == "json_schema":
|
|
291
|
+
try:
|
|
292
|
+
parsed = json.loads(definition)
|
|
293
|
+
definition = json.dumps(parsed, indent=2, ensure_ascii=False)
|
|
294
|
+
except (json.JSONDecodeError, TypeError):
|
|
295
|
+
pass
|
|
296
|
+
|
|
297
|
+
copy_to_clipboard(self.app, definition, "Schema definition")
|
|
298
|
+
|
|
299
|
+
def edit_schema_definition(self) -> None:
|
|
300
|
+
"""Open schema definition in $EDITOR for editing.
|
|
301
|
+
|
|
302
|
+
If the definition changes, creates a new version of the schema.
|
|
303
|
+
"""
|
|
304
|
+
schema = self.get_selected_item()
|
|
305
|
+
if not schema:
|
|
306
|
+
self.app.notify("No schema selected", severity="warning")
|
|
307
|
+
return
|
|
308
|
+
|
|
309
|
+
# Get full schema from cache
|
|
310
|
+
full_schema = self._get_cached_schema(str(schema.id))
|
|
311
|
+
if not full_schema:
|
|
312
|
+
self.app.notify(
|
|
313
|
+
"Schema definition not loaded yet. Please wait.", severity="warning"
|
|
314
|
+
)
|
|
315
|
+
return
|
|
316
|
+
|
|
317
|
+
# Open in editor
|
|
318
|
+
new_content = self._open_editor_for_schema(
|
|
319
|
+
name_hint=schema.schema_name,
|
|
320
|
+
initial_content=full_schema.schema_definition,
|
|
321
|
+
schema_format=full_schema.schema_format_id,
|
|
322
|
+
)
|
|
323
|
+
|
|
324
|
+
if new_content is None:
|
|
325
|
+
return
|
|
326
|
+
|
|
327
|
+
# Normalize for comparison (strip whitespace, compact JSON)
|
|
328
|
+
original = full_schema.schema_definition.strip()
|
|
329
|
+
edited = new_content.strip()
|
|
330
|
+
|
|
331
|
+
# For JSON schemas, compare parsed content to ignore formatting differences
|
|
332
|
+
if full_schema.schema_format_id == "json_schema":
|
|
333
|
+
try:
|
|
334
|
+
original_parsed = json.loads(original)
|
|
335
|
+
edited_parsed = json.loads(edited)
|
|
336
|
+
if original_parsed == edited_parsed:
|
|
337
|
+
self.app.notify("No changes made", severity="information")
|
|
338
|
+
return
|
|
339
|
+
except json.JSONDecodeError:
|
|
340
|
+
# Fall back to string comparison
|
|
341
|
+
if original == edited:
|
|
342
|
+
self.app.notify("No changes made", severity="information")
|
|
343
|
+
return
|
|
344
|
+
else:
|
|
345
|
+
if original == edited:
|
|
346
|
+
self.app.notify("No changes made", severity="information")
|
|
347
|
+
return
|
|
348
|
+
|
|
349
|
+
# Save the updated schema (creates new version)
|
|
350
|
+
self._save_schema_update(str(schema.id), edited)
|
|
351
|
+
|
|
352
|
+
def create_schema_version(self) -> None:
|
|
353
|
+
"""Create a new version of the schema in $EDITOR.
|
|
354
|
+
|
|
355
|
+
Opens the current definition in editor. If content changes,
|
|
356
|
+
creates a new version.
|
|
357
|
+
"""
|
|
358
|
+
# Same as edit - both create new versions on change
|
|
359
|
+
self.edit_schema_definition()
|
|
360
|
+
|
|
361
|
+
@work(exclusive=True)
|
|
362
|
+
async def _save_schema_update(self, schema_id: str, new_definition: str) -> None:
|
|
363
|
+
"""Save updated schema definition via API (creates new version)."""
|
|
364
|
+
try:
|
|
365
|
+
client = await self._ensure_client()
|
|
366
|
+
request = UpdateSchemaRequest(schema_definition=new_definition)
|
|
367
|
+
response = await client.update_schema(UUID(schema_id), request)
|
|
368
|
+
|
|
369
|
+
# Clear cache for this schema (new version has new ID)
|
|
370
|
+
if schema_id in self._schema_cache:
|
|
371
|
+
del self._schema_cache[schema_id]
|
|
372
|
+
|
|
373
|
+
self.app.notify(
|
|
374
|
+
f"Schema updated: {response.schema_name} v{response.version}",
|
|
375
|
+
severity="information",
|
|
376
|
+
)
|
|
377
|
+
|
|
378
|
+
# Refresh the list to show new version
|
|
379
|
+
self._do_search(self._last_search)
|
|
380
|
+
|
|
381
|
+
except Exception as e:
|
|
382
|
+
self.app.notify(f"Failed to update schema: {e}", severity="error")
|
|
383
|
+
|
|
384
|
+
def open_edit_schema_modal(self) -> None:
|
|
385
|
+
"""Open the schema update modal to edit name/description."""
|
|
386
|
+
schema = self.get_selected_item()
|
|
387
|
+
if not schema:
|
|
388
|
+
self.app.notify("No schema selected", severity="warning")
|
|
389
|
+
return
|
|
390
|
+
|
|
391
|
+
# Get full schema from cache
|
|
392
|
+
full_schema = self._get_cached_schema(str(schema.id))
|
|
393
|
+
if not full_schema:
|
|
394
|
+
self.app.notify(
|
|
395
|
+
"Schema details not loaded yet. Please wait.", severity="warning"
|
|
396
|
+
)
|
|
397
|
+
return
|
|
398
|
+
|
|
399
|
+
self._open_schema_update_modal(full_schema)
|
|
400
|
+
|
|
401
|
+
@work(exclusive=True)
|
|
402
|
+
async def _open_schema_update_modal(self, schema: GetSchemaResponse) -> None:
|
|
403
|
+
"""Open the schema update modal."""
|
|
404
|
+
try:
|
|
405
|
+
client = await self._ensure_client()
|
|
406
|
+
self.app.push_screen(
|
|
407
|
+
SchemaUpdateModal(client=client, schema=schema),
|
|
408
|
+
self._on_schema_updated,
|
|
409
|
+
)
|
|
410
|
+
except Exception as e:
|
|
411
|
+
self.app.notify(f"Failed to open schema editor: {e}", severity="error")
|
|
412
|
+
|
|
413
|
+
def _on_schema_updated(self, result: SchemaUpdateResult | None) -> None:
|
|
414
|
+
"""Callback when schema update modal is dismissed."""
|
|
415
|
+
if result is not None:
|
|
416
|
+
# Clear cache for this schema (name may have changed)
|
|
417
|
+
if result.schema_id in self._schema_cache:
|
|
418
|
+
del self._schema_cache[result.schema_id]
|
|
419
|
+
|
|
420
|
+
self.app.notify(
|
|
421
|
+
f"Updated schema: {result.schema_name}",
|
|
422
|
+
severity="information",
|
|
423
|
+
)
|
|
424
|
+
# Refresh the schema list
|
|
425
|
+
self._do_search(self._last_search)
|
|
426
|
+
|
|
427
|
+
|
|
428
|
+
class SchemasScreen(NavScreen):
|
|
429
|
+
"""Screen for browsing and managing schemas.
|
|
430
|
+
|
|
431
|
+
This is a proper Textual Screen that wraps the SchemasWidget
|
|
432
|
+
and provides keybindings that work regardless of focus.
|
|
433
|
+
"""
|
|
434
|
+
|
|
435
|
+
app: "AlloyRuntimeApp"
|
|
436
|
+
|
|
437
|
+
SCREEN_ID = "schemas"
|
|
438
|
+
|
|
439
|
+
DEFAULT_CSS = """
|
|
440
|
+
SchemasScreen #screen-root {
|
|
441
|
+
height: 1fr;
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
SchemasScreen .browser-widget {
|
|
445
|
+
height: 100%;
|
|
446
|
+
width: 100%;
|
|
447
|
+
}
|
|
448
|
+
"""
|
|
449
|
+
|
|
450
|
+
# Screen-specific bindings (Ctrl+ prefixed)
|
|
451
|
+
BINDINGS = NavScreen.BINDINGS + [
|
|
452
|
+
Binding("ctrl+f", "focus_search", "Search", show=True),
|
|
453
|
+
Binding("ctrl+r", "refresh", "Refresh", show=True),
|
|
454
|
+
Binding("ctrl+y", "copy_name", "Copy Name", show=True),
|
|
455
|
+
Binding("ctrl+shift+y", "copy_definition", "Copy Definition", show=True),
|
|
456
|
+
Binding("ctrl+e", "edit_definition", "Edit Def", show=True),
|
|
457
|
+
Binding("ctrl+u", "edit_schema", "Edit Name", show=True),
|
|
458
|
+
Binding("ctrl+v", "create_version", "New Version", show=True),
|
|
459
|
+
Binding("ctrl+n", "new_schema", "New", show=True),
|
|
460
|
+
Binding("escape", "focus_table", "Focus List", show=False),
|
|
461
|
+
Binding("enter", "copy_name", "Copy Name", show=False),
|
|
462
|
+
]
|
|
463
|
+
|
|
464
|
+
def compose_content(self) -> ComposeResult:
|
|
465
|
+
"""Compose the screen content."""
|
|
466
|
+
yield SchemasWidget(id="schemas-widget")
|
|
467
|
+
|
|
468
|
+
def on_screen_resume(self) -> None:
|
|
469
|
+
"""Focus the data table when screen becomes active."""
|
|
470
|
+
self.call_after_refresh(self._focus_table)
|
|
471
|
+
|
|
472
|
+
def _focus_table(self) -> None:
|
|
473
|
+
"""Focus the data table."""
|
|
474
|
+
try:
|
|
475
|
+
widget = self.query_one("#schemas-widget", SchemasWidget)
|
|
476
|
+
widget.focus_table()
|
|
477
|
+
except Exception:
|
|
478
|
+
pass
|
|
479
|
+
|
|
480
|
+
def _get_widget(self) -> SchemasWidget:
|
|
481
|
+
"""Get the schemas widget."""
|
|
482
|
+
return self.query_one("#schemas-widget", SchemasWidget)
|
|
483
|
+
|
|
484
|
+
# =========================================================================
|
|
485
|
+
# Actions (keybinding handlers)
|
|
486
|
+
# =========================================================================
|
|
487
|
+
|
|
488
|
+
def action_focus_search(self) -> None:
|
|
489
|
+
"""Focus the search input."""
|
|
490
|
+
self._get_widget().focus_search()
|
|
491
|
+
|
|
492
|
+
def action_focus_table(self) -> None:
|
|
493
|
+
"""Focus the data table."""
|
|
494
|
+
self._get_widget().focus_table()
|
|
495
|
+
|
|
496
|
+
def action_refresh(self) -> None:
|
|
497
|
+
"""Refresh the current search results."""
|
|
498
|
+
self._get_widget().refresh_data()
|
|
499
|
+
|
|
500
|
+
def action_copy_name(self) -> None:
|
|
501
|
+
"""Copy the schema name to clipboard."""
|
|
502
|
+
self._get_widget().copy_schema_name()
|
|
503
|
+
|
|
504
|
+
def action_copy_definition(self) -> None:
|
|
505
|
+
"""Copy the schema definition to clipboard."""
|
|
506
|
+
self._get_widget().copy_schema_definition()
|
|
507
|
+
|
|
508
|
+
def action_edit_definition(self) -> None:
|
|
509
|
+
"""Edit the schema definition in $EDITOR."""
|
|
510
|
+
self._get_widget().edit_schema_definition()
|
|
511
|
+
|
|
512
|
+
def action_edit_schema(self) -> None:
|
|
513
|
+
"""Edit the schema name and description in a modal."""
|
|
514
|
+
self._get_widget().open_edit_schema_modal()
|
|
515
|
+
|
|
516
|
+
def action_create_version(self) -> None:
|
|
517
|
+
"""Create a new version of the schema."""
|
|
518
|
+
self._get_widget().create_schema_version()
|
|
519
|
+
|
|
520
|
+
async def action_new_schema(self) -> None:
|
|
521
|
+
"""Open the schema creation modal."""
|
|
522
|
+
await self._get_widget().open_new_schema_modal()
|