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,188 @@
|
|
|
1
|
+
"""Configuration management for CLI.
|
|
2
|
+
|
|
3
|
+
Loads configuration with hierarchy: CLI flags > Environment variables > Config file
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
import os
|
|
7
|
+
|
|
8
|
+
from pydantic import BaseModel, Field, field_validator
|
|
9
|
+
|
|
10
|
+
from cli.infrastructure.auth_storage import load_credentials
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
# Global storage for CLI flag overrides (set by main.py callback)
|
|
14
|
+
_global_api_url: str | None = None
|
|
15
|
+
_global_api_key: str | None = None
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def set_global_overrides(
|
|
19
|
+
api_url: str | None = None, api_key: str | None = None
|
|
20
|
+
) -> None:
|
|
21
|
+
"""Set global CLI flag overrides.
|
|
22
|
+
|
|
23
|
+
Called by the main app callback to store --api-url and --api-key flags.
|
|
24
|
+
|
|
25
|
+
Args:
|
|
26
|
+
api_url: Global --api-url flag value
|
|
27
|
+
api_key: Global --api-key flag value
|
|
28
|
+
"""
|
|
29
|
+
global _global_api_url, _global_api_key
|
|
30
|
+
_global_api_url = api_url
|
|
31
|
+
_global_api_key = api_key
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def get_api_url(default: str = "http://localhost:8000") -> str:
|
|
35
|
+
"""Get API URL using the configuration hierarchy.
|
|
36
|
+
|
|
37
|
+
Precedence order (highest to lowest):
|
|
38
|
+
1. Global CLI flag (--api-url)
|
|
39
|
+
2. Environment variable (ALLOY_RUNTIME_API_URL)
|
|
40
|
+
3. Config file (~/.alloy-runtime/config)
|
|
41
|
+
4. Default value
|
|
42
|
+
|
|
43
|
+
Args:
|
|
44
|
+
default: Fallback value if no configuration source provides URL
|
|
45
|
+
|
|
46
|
+
Returns:
|
|
47
|
+
API URL string
|
|
48
|
+
|
|
49
|
+
Example:
|
|
50
|
+
api_url = get_api_url() # Uses hierarchy with localhost default
|
|
51
|
+
"""
|
|
52
|
+
# Try global flag (highest priority)
|
|
53
|
+
if _global_api_url:
|
|
54
|
+
return _global_api_url
|
|
55
|
+
|
|
56
|
+
# Try environment variable
|
|
57
|
+
env_url = os.environ.get("ALLOY_RUNTIME_API_URL")
|
|
58
|
+
if env_url:
|
|
59
|
+
return env_url
|
|
60
|
+
|
|
61
|
+
# Try config file
|
|
62
|
+
file_config = load_credentials()
|
|
63
|
+
if file_config:
|
|
64
|
+
return file_config[0]
|
|
65
|
+
|
|
66
|
+
# Use default
|
|
67
|
+
return default
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
class CLIConfig(BaseModel):
|
|
71
|
+
"""CLI configuration with hierarchical loading.
|
|
72
|
+
|
|
73
|
+
Precedence order (highest to lowest):
|
|
74
|
+
1. CLI flags (--api-key, --api-url)
|
|
75
|
+
2. Environment variables (ALLOY_RUNTIME_API_KEY, ALLOY_RUNTIME_API_URL)
|
|
76
|
+
3. Config file (~/.alloy-runtime/config)
|
|
77
|
+
"""
|
|
78
|
+
|
|
79
|
+
api_url: str = Field(..., description="Alloy Runtime server base URL")
|
|
80
|
+
api_key: str = Field(..., description="API authentication key")
|
|
81
|
+
timeout: float | None = Field(
|
|
82
|
+
default=None, description="Request timeout in seconds"
|
|
83
|
+
)
|
|
84
|
+
|
|
85
|
+
@field_validator("api_url")
|
|
86
|
+
@classmethod
|
|
87
|
+
def validate_api_url(cls, v: str) -> str:
|
|
88
|
+
"""Ensure API URL is non-empty and properly formatted."""
|
|
89
|
+
_ = cls # Required by Pydantic validator
|
|
90
|
+
if not v or not v.strip():
|
|
91
|
+
raise ValueError("API URL cannot be empty")
|
|
92
|
+
return v.rstrip("/") # Remove trailing slash
|
|
93
|
+
|
|
94
|
+
@field_validator("api_key")
|
|
95
|
+
@classmethod
|
|
96
|
+
def validate_api_key(cls, v: str) -> str:
|
|
97
|
+
"""Ensure API key is non-empty."""
|
|
98
|
+
_ = cls # Required by Pydantic validator
|
|
99
|
+
if not v or not v.strip():
|
|
100
|
+
raise ValueError("API key cannot be empty")
|
|
101
|
+
return v
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
class ConfigurationError(Exception):
|
|
105
|
+
"""Raised when configuration cannot be loaded."""
|
|
106
|
+
|
|
107
|
+
pass
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
def load_config() -> CLIConfig:
|
|
111
|
+
"""Load CLI configuration with hierarchical precedence.
|
|
112
|
+
|
|
113
|
+
Precedence order (highest to lowest):
|
|
114
|
+
1. Global CLI flags (--api-key, --api-url set via callback)
|
|
115
|
+
2. Environment variables (ALLOY_RUNTIME_API_KEY, ALLOY_RUNTIME_API_URL)
|
|
116
|
+
3. Config file (~/.alloy-runtime/config)
|
|
117
|
+
|
|
118
|
+
Returns:
|
|
119
|
+
Validated CLI configuration
|
|
120
|
+
|
|
121
|
+
Raises:
|
|
122
|
+
ConfigurationError: If no configuration source provides required values
|
|
123
|
+
|
|
124
|
+
Example:
|
|
125
|
+
# Load with hierarchy
|
|
126
|
+
config = load_config()
|
|
127
|
+
|
|
128
|
+
# CLI usage:
|
|
129
|
+
alloy --api-url https://prod.example.com sync models
|
|
130
|
+
alloy --api-key sk_prod_... credentials update <id>
|
|
131
|
+
"""
|
|
132
|
+
# Load from config file (lowest priority)
|
|
133
|
+
file_config = load_credentials()
|
|
134
|
+
api_url_from_file = file_config[0] if file_config else None
|
|
135
|
+
api_key_from_file = file_config[1] if file_config else None
|
|
136
|
+
|
|
137
|
+
# Load from environment variables (middle priority)
|
|
138
|
+
api_url_from_env = os.environ.get("ALLOY_RUNTIME_API_URL")
|
|
139
|
+
api_key_from_env = os.environ.get("ALLOY_RUNTIME_API_KEY")
|
|
140
|
+
|
|
141
|
+
# Apply hierarchy: Global CLI flags > env vars > config file
|
|
142
|
+
# Note: Must check "is not None" because flags can be explicitly None when not passed
|
|
143
|
+
if _global_api_url is not None:
|
|
144
|
+
api_url = _global_api_url
|
|
145
|
+
elif api_url_from_env:
|
|
146
|
+
api_url = api_url_from_env
|
|
147
|
+
else:
|
|
148
|
+
api_url = api_url_from_file
|
|
149
|
+
|
|
150
|
+
if _global_api_key is not None:
|
|
151
|
+
api_key = _global_api_key
|
|
152
|
+
elif api_key_from_env:
|
|
153
|
+
api_key = api_key_from_env
|
|
154
|
+
else:
|
|
155
|
+
api_key = api_key_from_file
|
|
156
|
+
|
|
157
|
+
# Validate that we have the required configuration
|
|
158
|
+
if not api_url:
|
|
159
|
+
raise ConfigurationError(
|
|
160
|
+
"API URL not configured. Please provide via:\n"
|
|
161
|
+
" 1. CLI flag: --api-url http://localhost:8000\n"
|
|
162
|
+
" 2. Environment variable: ALLOY_RUNTIME_API_URL\n"
|
|
163
|
+
" 3. Login first: alloy login"
|
|
164
|
+
)
|
|
165
|
+
|
|
166
|
+
if not api_key:
|
|
167
|
+
raise ConfigurationError(
|
|
168
|
+
"API key not configured. Please provide via:\n"
|
|
169
|
+
" 1. CLI flag: --api-key sk_live_...\n"
|
|
170
|
+
" 2. Environment variable: ALLOY_RUNTIME_API_KEY\n"
|
|
171
|
+
" 3. Login first: alloy login"
|
|
172
|
+
)
|
|
173
|
+
|
|
174
|
+
# Load optional timeout
|
|
175
|
+
timeout = None
|
|
176
|
+
timeout_str = os.environ.get("ALLOY_RUNTIME_TIMEOUT")
|
|
177
|
+
if timeout_str:
|
|
178
|
+
try:
|
|
179
|
+
timeout = float(timeout_str)
|
|
180
|
+
except ValueError:
|
|
181
|
+
raise ConfigurationError(
|
|
182
|
+
"ALLOY_RUNTIME_TIMEOUT must be a valid number (seconds)"
|
|
183
|
+
)
|
|
184
|
+
|
|
185
|
+
try:
|
|
186
|
+
return CLIConfig(api_url=api_url, api_key=api_key, timeout=timeout)
|
|
187
|
+
except ValueError as e:
|
|
188
|
+
raise ConfigurationError(f"Invalid configuration: {e}")
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
"""Unified console service for all CLI output.
|
|
2
|
+
|
|
3
|
+
This is the single source of truth for console output. All features
|
|
4
|
+
MUST use this module for output instead of creating their own Console.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from rich.console import Console
|
|
8
|
+
from rich.prompt import Confirm, Prompt
|
|
9
|
+
|
|
10
|
+
# Singleton console instance
|
|
11
|
+
_console: Console | None = None
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def get_console() -> Console:
|
|
15
|
+
"""Get the global console instance.
|
|
16
|
+
|
|
17
|
+
Returns:
|
|
18
|
+
Shared Console instance for all CLI output
|
|
19
|
+
"""
|
|
20
|
+
global _console
|
|
21
|
+
if _console is None:
|
|
22
|
+
_console = Console()
|
|
23
|
+
return _console
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
# Re-export Rich prompts for convenience
|
|
27
|
+
__all__ = ["get_console", "Prompt", "Confirm"]
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
"""External editor integration for template content editing.
|
|
2
|
+
|
|
3
|
+
Opens the user's preferred $EDITOR to edit template content,
|
|
4
|
+
with fallback to common terminal editors.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import os
|
|
8
|
+
import shutil
|
|
9
|
+
import subprocess
|
|
10
|
+
import tempfile
|
|
11
|
+
from pathlib import Path
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class EditorError(Exception):
|
|
15
|
+
"""Raised when editor operations fail."""
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def get_editor() -> str:
|
|
19
|
+
"""Get the user's preferred editor.
|
|
20
|
+
|
|
21
|
+
Checks in order:
|
|
22
|
+
1. $EDITOR environment variable
|
|
23
|
+
2. $VISUAL environment variable
|
|
24
|
+
3. Common editors on PATH (nano, vim, vi)
|
|
25
|
+
|
|
26
|
+
Returns:
|
|
27
|
+
Path/name of editor to use
|
|
28
|
+
|
|
29
|
+
Raises:
|
|
30
|
+
EditorError: If no suitable editor is found
|
|
31
|
+
"""
|
|
32
|
+
# Check environment variables first
|
|
33
|
+
editor = os.environ.get("EDITOR") or os.environ.get("VISUAL")
|
|
34
|
+
if editor:
|
|
35
|
+
return editor
|
|
36
|
+
|
|
37
|
+
# Fall back to common editors
|
|
38
|
+
for fallback in ("nano", "vim", "vi"):
|
|
39
|
+
if shutil.which(fallback):
|
|
40
|
+
return fallback
|
|
41
|
+
|
|
42
|
+
raise EditorError(
|
|
43
|
+
"No editor found. Set $EDITOR environment variable or install nano/vim."
|
|
44
|
+
)
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def open_editor(initial_content: str = "") -> str | None:
|
|
48
|
+
"""Open the user's editor with optional initial content.
|
|
49
|
+
|
|
50
|
+
Creates a temporary file, opens it in the editor, waits for the editor
|
|
51
|
+
to close, then reads and returns the file content.
|
|
52
|
+
|
|
53
|
+
Args:
|
|
54
|
+
initial_content: Initial content to populate the file with
|
|
55
|
+
|
|
56
|
+
Returns:
|
|
57
|
+
The edited content from the file, or None if the editor failed
|
|
58
|
+
or the user quit without saving.
|
|
59
|
+
|
|
60
|
+
Raises:
|
|
61
|
+
EditorError: If no editor is available
|
|
62
|
+
"""
|
|
63
|
+
editor = get_editor()
|
|
64
|
+
|
|
65
|
+
# Create temp file with .jinja2 extension for syntax highlighting
|
|
66
|
+
with tempfile.NamedTemporaryFile(
|
|
67
|
+
mode="w",
|
|
68
|
+
suffix=".jinja2",
|
|
69
|
+
delete=False,
|
|
70
|
+
) as f:
|
|
71
|
+
f.write(initial_content)
|
|
72
|
+
temp_path = Path(f.name)
|
|
73
|
+
|
|
74
|
+
try:
|
|
75
|
+
# Get file modification time before editing
|
|
76
|
+
mtime_before = temp_path.stat().st_mtime
|
|
77
|
+
|
|
78
|
+
# Open editor and wait for it to close
|
|
79
|
+
# Shell=False for security, but we need to handle editor args
|
|
80
|
+
editor_parts = editor.split()
|
|
81
|
+
cmd = editor_parts + [str(temp_path)]
|
|
82
|
+
|
|
83
|
+
result = subprocess.call(cmd)
|
|
84
|
+
|
|
85
|
+
if result != 0:
|
|
86
|
+
return None
|
|
87
|
+
|
|
88
|
+
# Check if file was modified
|
|
89
|
+
mtime_after = temp_path.stat().st_mtime
|
|
90
|
+
if mtime_after == mtime_before:
|
|
91
|
+
# File wasn't modified - could mean user quit without saving
|
|
92
|
+
# Still return content in case they just didn't change anything
|
|
93
|
+
pass
|
|
94
|
+
|
|
95
|
+
# Read the edited content
|
|
96
|
+
content = temp_path.read_text()
|
|
97
|
+
return content
|
|
98
|
+
|
|
99
|
+
finally:
|
|
100
|
+
# Clean up temp file
|
|
101
|
+
try:
|
|
102
|
+
temp_path.unlink()
|
|
103
|
+
except OSError:
|
|
104
|
+
pass # Best effort cleanup
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
def open_editor_with_hints(initial_content: str = "") -> str | None:
|
|
108
|
+
"""Open editor with helpful comments about macro syntax.
|
|
109
|
+
|
|
110
|
+
Adds instructional comments at the top of the file that explain
|
|
111
|
+
the macro syntax. These comments are stripped from the final output.
|
|
112
|
+
|
|
113
|
+
Args:
|
|
114
|
+
initial_content: Initial content to populate the file with
|
|
115
|
+
|
|
116
|
+
Returns:
|
|
117
|
+
The edited content with hint comments removed, or None if failed
|
|
118
|
+
"""
|
|
119
|
+
# Only show hints when content is empty
|
|
120
|
+
if initial_content:
|
|
121
|
+
full_content = initial_content
|
|
122
|
+
else:
|
|
123
|
+
hints = """@fragment(name) - Include fragment
|
|
124
|
+
@text(name) - Insert text from a content part
|
|
125
|
+
@json(name) - Insert JSON from a content part
|
|
126
|
+
@schema(name) - Reference a schema
|
|
127
|
+
{{ var }} - Variable interpolation
|
|
128
|
+
"""
|
|
129
|
+
full_content = hints
|
|
130
|
+
|
|
131
|
+
result = open_editor(full_content)
|
|
132
|
+
|
|
133
|
+
if result is None:
|
|
134
|
+
return None
|
|
135
|
+
|
|
136
|
+
# Don't strip comments - let user decide what to keep
|
|
137
|
+
# They're valid Jinja2 comments anyway
|
|
138
|
+
return result
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
"""Error display using Rich panels.
|
|
2
|
+
|
|
3
|
+
Centralizes error formatting for consistent, user-friendly error messages.
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
from rich.panel import Panel
|
|
7
|
+
|
|
8
|
+
from cli.infrastructure.config import ConfigurationError
|
|
9
|
+
from cli.infrastructure.console import get_console
|
|
10
|
+
from alloy_runtime_sdk.exceptions.errors import (
|
|
11
|
+
AuthenticationError,
|
|
12
|
+
ConflictError,
|
|
13
|
+
ForbiddenError,
|
|
14
|
+
NotFoundError,
|
|
15
|
+
RequestError,
|
|
16
|
+
ServerError,
|
|
17
|
+
ValidationError,
|
|
18
|
+
)
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def display_error(error: Exception) -> None:
|
|
22
|
+
"""Display an error in a Rich panel with appropriate styling.
|
|
23
|
+
|
|
24
|
+
Args:
|
|
25
|
+
error: Exception to display
|
|
26
|
+
"""
|
|
27
|
+
if isinstance(error, ConfigurationError):
|
|
28
|
+
_display_configuration_error(error)
|
|
29
|
+
elif isinstance(error, AuthenticationError):
|
|
30
|
+
_display_authentication_error(error)
|
|
31
|
+
elif isinstance(error, ForbiddenError):
|
|
32
|
+
_display_forbidden_error(error)
|
|
33
|
+
elif isinstance(error, NotFoundError):
|
|
34
|
+
_display_not_found_error(error)
|
|
35
|
+
elif isinstance(error, ValidationError):
|
|
36
|
+
_display_validation_error(error)
|
|
37
|
+
elif isinstance(error, ConflictError):
|
|
38
|
+
_display_conflict_error(error)
|
|
39
|
+
elif isinstance(error, RequestError):
|
|
40
|
+
_display_request_error(error)
|
|
41
|
+
elif isinstance(error, ServerError):
|
|
42
|
+
_display_server_error(error)
|
|
43
|
+
else:
|
|
44
|
+
_display_unexpected_error(error)
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def _display_configuration_error(error: ConfigurationError) -> None:
|
|
48
|
+
"""Display configuration error panel."""
|
|
49
|
+
console = get_console()
|
|
50
|
+
console.print(
|
|
51
|
+
Panel(
|
|
52
|
+
f"[red]Configuration Error[/red]\n\n{str(error)}",
|
|
53
|
+
title="⚙️ Configuration Required",
|
|
54
|
+
border_style="red",
|
|
55
|
+
)
|
|
56
|
+
)
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
def _display_authentication_error(error: AuthenticationError) -> None:
|
|
60
|
+
"""Display authentication error panel."""
|
|
61
|
+
console = get_console()
|
|
62
|
+
console.print(
|
|
63
|
+
Panel(
|
|
64
|
+
f"[red]Authentication Failed[/red]\n\n{str(error)}\n\n"
|
|
65
|
+
"Please check your ALLOY_RUNTIME_API_KEY environment variable.\n"
|
|
66
|
+
"Ensure you have a valid API key with appropriate permissions.",
|
|
67
|
+
title="❌ Authentication Error",
|
|
68
|
+
border_style="red",
|
|
69
|
+
)
|
|
70
|
+
)
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
def _display_forbidden_error(error: ForbiddenError) -> None:
|
|
74
|
+
"""Display forbidden error panel."""
|
|
75
|
+
console = get_console()
|
|
76
|
+
console.print(
|
|
77
|
+
Panel(
|
|
78
|
+
f"[red]Access Forbidden[/red]\n\n{str(error)}\n\n"
|
|
79
|
+
"Your API key does not have permission to perform this operation.\n"
|
|
80
|
+
"System credential management requires system admin privileges.",
|
|
81
|
+
title="🚫 Forbidden",
|
|
82
|
+
border_style="red",
|
|
83
|
+
)
|
|
84
|
+
)
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
def _display_not_found_error(error: NotFoundError) -> None:
|
|
88
|
+
"""Display not found error panel."""
|
|
89
|
+
console = get_console()
|
|
90
|
+
console.print(
|
|
91
|
+
Panel(
|
|
92
|
+
f"[yellow]Resource Not Found[/yellow]\n\n{str(error)}\n\n"
|
|
93
|
+
"Please verify the credential ID is correct.\n"
|
|
94
|
+
"Use the credentials list command to see available credentials.",
|
|
95
|
+
title="⚠️ Not Found",
|
|
96
|
+
border_style="yellow",
|
|
97
|
+
)
|
|
98
|
+
)
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
def _display_validation_error(error: ValidationError) -> None:
|
|
102
|
+
"""Display validation error panel."""
|
|
103
|
+
console = get_console()
|
|
104
|
+
error_lines = ["[red]Validation Failed[/red]\n"]
|
|
105
|
+
|
|
106
|
+
if error.errors:
|
|
107
|
+
error_lines.append("The following validation errors occurred:\n")
|
|
108
|
+
for err in error.errors:
|
|
109
|
+
# Extract field path and message from error dict
|
|
110
|
+
field = " -> ".join(str(loc) for loc in err.get("loc", []))
|
|
111
|
+
message = err.get("msg", "Unknown error")
|
|
112
|
+
error_lines.append(f" • [cyan]{field}[/cyan]: {message}")
|
|
113
|
+
else:
|
|
114
|
+
error_lines.append(str(error))
|
|
115
|
+
|
|
116
|
+
console.print(
|
|
117
|
+
Panel(
|
|
118
|
+
"\n".join(error_lines),
|
|
119
|
+
title="❌ Validation Error",
|
|
120
|
+
border_style="red",
|
|
121
|
+
)
|
|
122
|
+
)
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
def _display_conflict_error(error: ConflictError) -> None:
|
|
126
|
+
"""Display conflict error panel."""
|
|
127
|
+
console = get_console()
|
|
128
|
+
console.print(
|
|
129
|
+
Panel(
|
|
130
|
+
f"[yellow]Conflict Detected[/yellow]\n\n{str(error)}\n\n"
|
|
131
|
+
"The requested operation conflicts with existing data.",
|
|
132
|
+
title="⚠️ Conflict",
|
|
133
|
+
border_style="yellow",
|
|
134
|
+
)
|
|
135
|
+
)
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
def _display_request_error(error: RequestError) -> None:
|
|
139
|
+
"""Display request/network error panel."""
|
|
140
|
+
console = get_console()
|
|
141
|
+
console.print(
|
|
142
|
+
Panel(
|
|
143
|
+
f"[red]Request Failed[/red]\n\n{str(error)}\n\n"
|
|
144
|
+
"Possible causes:\n"
|
|
145
|
+
" • Network connectivity issues\n"
|
|
146
|
+
" • Server is not running\n"
|
|
147
|
+
" • Incorrect ALLOY_RUNTIME_API_URL\n"
|
|
148
|
+
" • Request timeout",
|
|
149
|
+
title="🌐 Network Error",
|
|
150
|
+
border_style="red",
|
|
151
|
+
)
|
|
152
|
+
)
|
|
153
|
+
|
|
154
|
+
|
|
155
|
+
def _display_server_error(error: ServerError) -> None:
|
|
156
|
+
"""Display server error panel."""
|
|
157
|
+
console = get_console()
|
|
158
|
+
console.print(
|
|
159
|
+
Panel(
|
|
160
|
+
f"[red]Server Error[/red]\n\n{str(error)}\n\n"
|
|
161
|
+
"The server encountered an internal error.\n"
|
|
162
|
+
"Please try again.",
|
|
163
|
+
title="❌ Server Error",
|
|
164
|
+
border_style="red",
|
|
165
|
+
)
|
|
166
|
+
)
|
|
167
|
+
|
|
168
|
+
|
|
169
|
+
def _display_unexpected_error(error: Exception) -> None:
|
|
170
|
+
"""Display unexpected error panel."""
|
|
171
|
+
console = get_console()
|
|
172
|
+
console.print(
|
|
173
|
+
Panel(
|
|
174
|
+
f"[red]Unexpected Error[/red]\n\n{type(error).__name__}: {str(error)}",
|
|
175
|
+
title="❌ Error",
|
|
176
|
+
border_style="red",
|
|
177
|
+
)
|
|
178
|
+
)
|