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,299 @@
|
|
|
1
|
+
"""Agent update modal for editing existing agents.
|
|
2
|
+
|
|
3
|
+
Provides a comprehensive modal screen that allows users to edit an existing agent
|
|
4
|
+
with all its current fields pre-populated.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from typing import Any
|
|
8
|
+
|
|
9
|
+
from textual import work
|
|
10
|
+
from textual.widgets import Input, TextArea
|
|
11
|
+
|
|
12
|
+
from alloy_runtime_sdk.api_client.client import ApiClient
|
|
13
|
+
from alloy_runtime_types.dtos.agents import (
|
|
14
|
+
GetAgentResponse,
|
|
15
|
+
UpdateAgentRequest,
|
|
16
|
+
)
|
|
17
|
+
from alloy_runtime_types.dtos.models import ModelListItemResponse
|
|
18
|
+
from alloy_runtime_types.enums.ownership_scope import OwnershipScope
|
|
19
|
+
|
|
20
|
+
from cli.infrastructure.forms.schema_picker import SchemaPicker
|
|
21
|
+
from cli.infrastructure.forms.tag_picker import TagPicker
|
|
22
|
+
from cli.infrastructure.forms.template_picker import TemplatePicker
|
|
23
|
+
from cli.tui.widgets.agent_form_modal import AgentFormModal, AgentFormResult
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
class AgentUpdateModal(AgentFormModal):
|
|
27
|
+
"""Modal for updating an existing agent.
|
|
28
|
+
|
|
29
|
+
Pre-populates all form fields with the current agent configuration.
|
|
30
|
+
Scope cannot be changed after creation.
|
|
31
|
+
|
|
32
|
+
Usage:
|
|
33
|
+
def on_agent_updated(result: AgentFormResult | None):
|
|
34
|
+
if result is not None:
|
|
35
|
+
self.notify(f"Updated agent: {result.agent_name}")
|
|
36
|
+
self._do_search("") # Refresh list
|
|
37
|
+
|
|
38
|
+
client = await self.app.store.get_client()
|
|
39
|
+
agent = await client.get_agent(agent_id)
|
|
40
|
+
self.app.push_screen(
|
|
41
|
+
AgentUpdateModal(client=client, agent=agent),
|
|
42
|
+
on_agent_updated
|
|
43
|
+
)
|
|
44
|
+
"""
|
|
45
|
+
|
|
46
|
+
def __init__(
|
|
47
|
+
self,
|
|
48
|
+
client: ApiClient,
|
|
49
|
+
agent: GetAgentResponse,
|
|
50
|
+
**kwargs: Any,
|
|
51
|
+
) -> None:
|
|
52
|
+
"""Initialize the agent update modal.
|
|
53
|
+
|
|
54
|
+
Args:
|
|
55
|
+
client: ApiClient instance for API calls
|
|
56
|
+
agent: The agent to edit (full details from get_agent)
|
|
57
|
+
"""
|
|
58
|
+
super().__init__(client=client, **kwargs)
|
|
59
|
+
self._agent = agent
|
|
60
|
+
|
|
61
|
+
def _get_modal_title(self) -> str:
|
|
62
|
+
"""Return the modal title."""
|
|
63
|
+
return f"Edit Agent: {self._agent.name}"
|
|
64
|
+
|
|
65
|
+
def _get_submit_button_text(self) -> str:
|
|
66
|
+
"""Return the submit button text."""
|
|
67
|
+
return "Update Agent"
|
|
68
|
+
|
|
69
|
+
def _is_scope_editable(self) -> bool:
|
|
70
|
+
"""Return whether the scope can be changed (not allowed for updates)."""
|
|
71
|
+
return False
|
|
72
|
+
|
|
73
|
+
def on_mount(self) -> None:
|
|
74
|
+
"""Populate form fields with existing agent data."""
|
|
75
|
+
super().on_mount()
|
|
76
|
+
self._populate_form_async()
|
|
77
|
+
|
|
78
|
+
@work(exclusive=True)
|
|
79
|
+
async def _populate_form_async(self) -> None:
|
|
80
|
+
"""Populate all form fields with the existing agent data (async for API calls)."""
|
|
81
|
+
agent = self._agent
|
|
82
|
+
|
|
83
|
+
# Basic fields
|
|
84
|
+
self._set_name(agent.name)
|
|
85
|
+
self._set_description(agent.description)
|
|
86
|
+
|
|
87
|
+
# Scope (read-only, just display)
|
|
88
|
+
scope = self._infer_scope_from_agent(agent)
|
|
89
|
+
self._set_scope(scope)
|
|
90
|
+
|
|
91
|
+
# Models - need to convert AgentModelResponse to ModelListItemResponse-like objects
|
|
92
|
+
if agent.models:
|
|
93
|
+
model_items = [
|
|
94
|
+
ModelListItemResponse(
|
|
95
|
+
provider_key=m.provider_key.value, # Use .value to get string from enum
|
|
96
|
+
provider_model_name=m.provider_model_name,
|
|
97
|
+
is_active=True, # Assume active since it's assigned to agent
|
|
98
|
+
input_modalities=["text"], # Default, actual not stored on agent
|
|
99
|
+
output_modalities=["text"], # Default, actual not stored on agent
|
|
100
|
+
)
|
|
101
|
+
for m in sorted(agent.models, key=lambda x: x.preference_order)
|
|
102
|
+
]
|
|
103
|
+
self._set_models(model_items)
|
|
104
|
+
|
|
105
|
+
# Tags - need to convert AgentTagResponse to dict format
|
|
106
|
+
if agent.tags:
|
|
107
|
+
tag_items = [
|
|
108
|
+
{
|
|
109
|
+
"tag_path": t.tag_path,
|
|
110
|
+
"display_name": t.display_name,
|
|
111
|
+
"id": str(t.tag_id),
|
|
112
|
+
}
|
|
113
|
+
for t in agent.tags
|
|
114
|
+
]
|
|
115
|
+
self._set_tags(tag_items)
|
|
116
|
+
|
|
117
|
+
# Base agent
|
|
118
|
+
if agent.base_agent_id:
|
|
119
|
+
self._set_base_agent(str(agent.base_agent_id), "Base Agent")
|
|
120
|
+
|
|
121
|
+
# System instruction template - fetch actual data
|
|
122
|
+
if agent.system_instruction_version_id:
|
|
123
|
+
template_data = await self._fetch_template_data(
|
|
124
|
+
str(agent.system_instruction_version_id)
|
|
125
|
+
)
|
|
126
|
+
if template_data:
|
|
127
|
+
# Use the set_initial_selection with full data for proper display
|
|
128
|
+
template_picker = self.query_one(
|
|
129
|
+
"#system-template-picker", TemplatePicker
|
|
130
|
+
)
|
|
131
|
+
template_picker.set_initial_selection(template_data)
|
|
132
|
+
|
|
133
|
+
# Output schema - fetch actual data
|
|
134
|
+
if agent.output_schema_id:
|
|
135
|
+
schema_data = await self._fetch_schema_data(str(agent.output_schema_id))
|
|
136
|
+
if schema_data:
|
|
137
|
+
# Use the set_initial_selection with full data for proper display
|
|
138
|
+
output_schema_picker = self.query_one(
|
|
139
|
+
"#output-schema-picker", SchemaPicker
|
|
140
|
+
)
|
|
141
|
+
output_schema_picker.set_initial_selection(schema_data)
|
|
142
|
+
|
|
143
|
+
# Generation params
|
|
144
|
+
if agent.generation_params:
|
|
145
|
+
self._set_generation_params(agent.generation_params)
|
|
146
|
+
|
|
147
|
+
# Default headers
|
|
148
|
+
if agent.default_request_headers:
|
|
149
|
+
self._set_default_headers(agent.default_request_headers)
|
|
150
|
+
|
|
151
|
+
# Tools
|
|
152
|
+
if agent.tools:
|
|
153
|
+
self._set_tools(agent.tools)
|
|
154
|
+
|
|
155
|
+
def _infer_scope_from_agent(self, agent: GetAgentResponse) -> OwnershipScope:
|
|
156
|
+
"""Infer the scope from agent ownership fields."""
|
|
157
|
+
if agent.user_id:
|
|
158
|
+
return OwnershipScope.USER
|
|
159
|
+
elif agent.organization_id:
|
|
160
|
+
return OwnershipScope.ORGANIZATION
|
|
161
|
+
else:
|
|
162
|
+
return OwnershipScope.GLOBAL
|
|
163
|
+
|
|
164
|
+
async def _fetch_template_data(self, version_id: str) -> dict[str, Any] | None:
|
|
165
|
+
"""Fetch the template data for a given version ID.
|
|
166
|
+
|
|
167
|
+
Args:
|
|
168
|
+
version_id: Template version UUID
|
|
169
|
+
|
|
170
|
+
Returns:
|
|
171
|
+
Template data dict for display, or None if fetch fails
|
|
172
|
+
"""
|
|
173
|
+
try:
|
|
174
|
+
# Get template by version ID using the new endpoint
|
|
175
|
+
from uuid import UUID
|
|
176
|
+
|
|
177
|
+
response = await self._client.get_template_by_version(UUID(version_id))
|
|
178
|
+
|
|
179
|
+
# Find the specific version to get its version number
|
|
180
|
+
matching_version = next(
|
|
181
|
+
(v for v in response.versions if str(v.id) == version_id), None
|
|
182
|
+
)
|
|
183
|
+
version_number = matching_version.version if matching_version else "?"
|
|
184
|
+
|
|
185
|
+
# Build data dict that matches what the picker's formatter expects
|
|
186
|
+
return {
|
|
187
|
+
"latest_version_id": version_id,
|
|
188
|
+
"name": response.template.name,
|
|
189
|
+
"latest_version_number": version_number,
|
|
190
|
+
"visibility_id": response.template.visibility_id,
|
|
191
|
+
"content_type_id": response.template.content_type_id,
|
|
192
|
+
}
|
|
193
|
+
except Exception:
|
|
194
|
+
# If fetch fails, create a minimal fallback dict
|
|
195
|
+
return {
|
|
196
|
+
"latest_version_id": version_id,
|
|
197
|
+
"name": f"Template ({version_id[:8]}...)",
|
|
198
|
+
"latest_version_number": "?",
|
|
199
|
+
"visibility_id": "private",
|
|
200
|
+
"content_type_id": "",
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
async def _fetch_schema_data(self, schema_id: str) -> dict[str, Any] | None:
|
|
204
|
+
"""Fetch the schema data for a given schema ID.
|
|
205
|
+
|
|
206
|
+
Args:
|
|
207
|
+
schema_id: Schema UUID
|
|
208
|
+
|
|
209
|
+
Returns:
|
|
210
|
+
Schema data dict for display, or None if fetch fails
|
|
211
|
+
"""
|
|
212
|
+
try:
|
|
213
|
+
response = await self._client.get_schema(schema_id)
|
|
214
|
+
# Build data dict that matches what the picker's formatter expects
|
|
215
|
+
return {
|
|
216
|
+
"id": schema_id,
|
|
217
|
+
"schema_name": response.schema_name,
|
|
218
|
+
"version": response.version,
|
|
219
|
+
"schema_format_id": response.schema_format_id,
|
|
220
|
+
"user_id": str(response.user_id) if response.user_id else None,
|
|
221
|
+
"organization_id": str(response.organization_id)
|
|
222
|
+
if response.organization_id
|
|
223
|
+
else None,
|
|
224
|
+
"description": response.description,
|
|
225
|
+
}
|
|
226
|
+
except Exception:
|
|
227
|
+
# If fetch fails, create a minimal fallback dict
|
|
228
|
+
return {
|
|
229
|
+
"id": schema_id,
|
|
230
|
+
"schema_name": f"Schema ({schema_id[:8]}...)",
|
|
231
|
+
"version": "?",
|
|
232
|
+
"schema_format_id": "unknown",
|
|
233
|
+
"user_id": None,
|
|
234
|
+
"organization_id": None,
|
|
235
|
+
"description": None,
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
async def _submit_form(self) -> AgentFormResult:
|
|
239
|
+
"""Submit the form to update the agent."""
|
|
240
|
+
request = self._build_update_request()
|
|
241
|
+
response = await self._client.update_agent(self._agent.id, request)
|
|
242
|
+
|
|
243
|
+
return AgentFormResult(
|
|
244
|
+
agent_id=str(response.id),
|
|
245
|
+
agent_name=response.name,
|
|
246
|
+
is_update=True,
|
|
247
|
+
)
|
|
248
|
+
|
|
249
|
+
def _build_update_request(self) -> UpdateAgentRequest:
|
|
250
|
+
"""Build the UpdateAgentRequest from form fields."""
|
|
251
|
+
# Name
|
|
252
|
+
name = self.query_one("#name-input", Input).value.strip()
|
|
253
|
+
|
|
254
|
+
# Models
|
|
255
|
+
model_configs = self._build_model_configs()
|
|
256
|
+
|
|
257
|
+
# Tags
|
|
258
|
+
tag_picker = self.query_one("#tag-picker", TagPicker)
|
|
259
|
+
tags = tag_picker.selected_tags
|
|
260
|
+
|
|
261
|
+
# Description
|
|
262
|
+
description = self.query_one("#description-input", Input).value.strip() or None
|
|
263
|
+
|
|
264
|
+
# System instruction template
|
|
265
|
+
template_picker = self.query_one("#system-template-picker", TemplatePicker)
|
|
266
|
+
system_instruction_version_id = self._parse_uuid(
|
|
267
|
+
template_picker.selected_id, "System Template"
|
|
268
|
+
)
|
|
269
|
+
|
|
270
|
+
# Schemas
|
|
271
|
+
output_schema_picker = self.query_one("#output-schema-picker", SchemaPicker)
|
|
272
|
+
output_schema_id = self._parse_uuid(
|
|
273
|
+
output_schema_picker.selected_id, "Output Schema"
|
|
274
|
+
)
|
|
275
|
+
|
|
276
|
+
# Output schema from JSON builder
|
|
277
|
+
output_schema = self._get_output_schema()
|
|
278
|
+
|
|
279
|
+
# Generation parameters
|
|
280
|
+
gen_params = self._build_generation_params()
|
|
281
|
+
|
|
282
|
+
# Default headers
|
|
283
|
+
default_headers = self._parse_json(
|
|
284
|
+
self.query_one("#default-headers-textarea", TextArea).text,
|
|
285
|
+
"Default Headers",
|
|
286
|
+
)
|
|
287
|
+
|
|
288
|
+
return UpdateAgentRequest(
|
|
289
|
+
name=name,
|
|
290
|
+
models=model_configs,
|
|
291
|
+
tags=tags,
|
|
292
|
+
description=description,
|
|
293
|
+
system_instruction_version_id=system_instruction_version_id,
|
|
294
|
+
output_schema_id=output_schema_id,
|
|
295
|
+
output_schema=output_schema,
|
|
296
|
+
default_request_headers=default_headers,
|
|
297
|
+
generation_params=gen_params,
|
|
298
|
+
tools=self._build_tools(),
|
|
299
|
+
)
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
"""Base class for form modals with error handling.
|
|
2
|
+
|
|
3
|
+
Provides common functionality for all form modals:
|
|
4
|
+
- Standard cancel/submit bindings
|
|
5
|
+
- Error display methods
|
|
6
|
+
- Auto-hide error on input change
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from typing import Generic, TypeVar
|
|
10
|
+
|
|
11
|
+
from textual import on
|
|
12
|
+
from textual.binding import Binding
|
|
13
|
+
from textual.screen import ModalScreen
|
|
14
|
+
from textual.widgets import Input, Static, TextArea
|
|
15
|
+
|
|
16
|
+
T = TypeVar("T")
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class BaseFormModal(ModalScreen[T | None], Generic[T]):
|
|
20
|
+
"""Abstract base for all form modals with error handling.
|
|
21
|
+
|
|
22
|
+
Provides:
|
|
23
|
+
- Standard cancel/submit bindings (escape, ctrl+s)
|
|
24
|
+
- Error display methods (_show_error, _hide_error)
|
|
25
|
+
- Auto-hide error on input/textarea change
|
|
26
|
+
- Standard action_cancel implementation
|
|
27
|
+
|
|
28
|
+
Subclasses must:
|
|
29
|
+
- Include Static(id="error-display") in compose()
|
|
30
|
+
- Implement action_submit()
|
|
31
|
+
|
|
32
|
+
Usage:
|
|
33
|
+
class MyModal(BaseFormModal[MyResult]):
|
|
34
|
+
def compose(self) -> ComposeResult:
|
|
35
|
+
# ... form fields ...
|
|
36
|
+
yield Static("", id="error-display", classes="error-display")
|
|
37
|
+
# ... buttons ...
|
|
38
|
+
|
|
39
|
+
def action_submit(self) -> None:
|
|
40
|
+
try:
|
|
41
|
+
self._validate()
|
|
42
|
+
self._hide_error()
|
|
43
|
+
self._finalize()
|
|
44
|
+
except ValueError as e:
|
|
45
|
+
self._show_error(str(e))
|
|
46
|
+
"""
|
|
47
|
+
|
|
48
|
+
BINDINGS = [
|
|
49
|
+
Binding("escape", "cancel", "Cancel", show=True),
|
|
50
|
+
Binding("ctrl+s", "submit", "Submit", show=True, priority=True),
|
|
51
|
+
]
|
|
52
|
+
|
|
53
|
+
def _show_error(self, message: str) -> None:
|
|
54
|
+
"""Show an error message."""
|
|
55
|
+
error_display = self.query_one("#error-display", Static)
|
|
56
|
+
error_display.update(f"[red]Error: {message}[/]")
|
|
57
|
+
error_display.add_class("visible")
|
|
58
|
+
|
|
59
|
+
def _hide_error(self) -> None:
|
|
60
|
+
"""Hide the error display."""
|
|
61
|
+
error_display = self.query_one("#error-display", Static)
|
|
62
|
+
error_display.update("")
|
|
63
|
+
error_display.remove_class("visible")
|
|
64
|
+
|
|
65
|
+
def action_cancel(self) -> None:
|
|
66
|
+
"""Cancel and dismiss the modal."""
|
|
67
|
+
self.dismiss(None)
|
|
68
|
+
|
|
69
|
+
@on(Input.Changed)
|
|
70
|
+
def on_input_changed(self, event: Input.Changed) -> None:
|
|
71
|
+
"""Auto-hide error when any input changes."""
|
|
72
|
+
self._hide_error()
|
|
73
|
+
|
|
74
|
+
@on(TextArea.Changed)
|
|
75
|
+
def on_textarea_changed(self, event: TextArea.Changed) -> None:
|
|
76
|
+
"""Auto-hide error when any textarea changes."""
|
|
77
|
+
self._hide_error()
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
"""Confirmation modal for destructive actions."""
|
|
2
|
+
|
|
3
|
+
from typing import Any
|
|
4
|
+
|
|
5
|
+
from textual import on
|
|
6
|
+
from textual.app import ComposeResult
|
|
7
|
+
from textual.binding import Binding
|
|
8
|
+
from textual.containers import Horizontal, Vertical
|
|
9
|
+
from textual.screen import ModalScreen
|
|
10
|
+
from textual.widgets import Button, Static
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class ConfirmModal(ModalScreen[bool]):
|
|
14
|
+
"""Modal for confirming destructive actions.
|
|
15
|
+
|
|
16
|
+
Usage:
|
|
17
|
+
def callback(confirmed: bool) -> None:
|
|
18
|
+
if confirmed:
|
|
19
|
+
# Perform action
|
|
20
|
+
pass
|
|
21
|
+
|
|
22
|
+
self.app.push_screen(
|
|
23
|
+
ConfirmModal(
|
|
24
|
+
title="Delete Agent",
|
|
25
|
+
message="Delete agent 'my-agent'? This cannot be undone.",
|
|
26
|
+
),
|
|
27
|
+
callback
|
|
28
|
+
)
|
|
29
|
+
"""
|
|
30
|
+
|
|
31
|
+
BINDINGS = [
|
|
32
|
+
Binding("escape", "cancel", "Cancel", show=True),
|
|
33
|
+
Binding("n", "cancel", "No", show=False),
|
|
34
|
+
]
|
|
35
|
+
|
|
36
|
+
def __init__(
|
|
37
|
+
self,
|
|
38
|
+
title: str = "Confirm Action",
|
|
39
|
+
message: str = "Are you sure?",
|
|
40
|
+
**kwargs: Any,
|
|
41
|
+
) -> None:
|
|
42
|
+
"""Initialize the confirmation modal.
|
|
43
|
+
|
|
44
|
+
Args:
|
|
45
|
+
title: Modal title
|
|
46
|
+
message: Confirmation message to display
|
|
47
|
+
**kwargs: Additional keyword arguments for ModalScreen
|
|
48
|
+
"""
|
|
49
|
+
super().__init__(**kwargs)
|
|
50
|
+
self._title = title
|
|
51
|
+
self._message = message
|
|
52
|
+
|
|
53
|
+
def compose(self) -> ComposeResult:
|
|
54
|
+
"""Compose the modal layout."""
|
|
55
|
+
with Vertical(id="confirm-modal"):
|
|
56
|
+
yield Static(self._title, classes="modal-title")
|
|
57
|
+
yield Static(self._message, id="confirm-message")
|
|
58
|
+
|
|
59
|
+
with Horizontal(classes="button-row"):
|
|
60
|
+
yield Button("Cancel", id="cancel-btn", variant="default")
|
|
61
|
+
yield Button("Confirm", id="confirm-btn", variant="error")
|
|
62
|
+
|
|
63
|
+
@on(Button.Pressed, "#confirm-btn")
|
|
64
|
+
def on_confirm_pressed(self, event: Button.Pressed) -> None:
|
|
65
|
+
"""Confirm the action."""
|
|
66
|
+
self.dismiss(True)
|
|
67
|
+
|
|
68
|
+
@on(Button.Pressed, "#cancel-btn")
|
|
69
|
+
def on_cancel_pressed(self, event: Button.Pressed) -> None:
|
|
70
|
+
"""Cancel the action."""
|
|
71
|
+
self.dismiss(False)
|
|
72
|
+
|
|
73
|
+
def action_cancel(self) -> None:
|
|
74
|
+
"""Cancel via escape or n key."""
|
|
75
|
+
self.dismiss(False)
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
"""Help modal showing keyboard shortcuts and features.
|
|
2
|
+
|
|
3
|
+
Provides a modal screen with comprehensive keyboard shortcut reference
|
|
4
|
+
for all screens in the TUI application.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from typing import Any
|
|
8
|
+
|
|
9
|
+
from textual import on
|
|
10
|
+
from textual.app import ComposeResult
|
|
11
|
+
from textual.binding import Binding
|
|
12
|
+
from textual.containers import Vertical, VerticalScroll
|
|
13
|
+
from textual.screen import ModalScreen
|
|
14
|
+
from textual.widgets import Button, Static
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class HelpModal(ModalScreen[None]):
|
|
18
|
+
"""Modal showing keyboard shortcuts and help information.
|
|
19
|
+
|
|
20
|
+
Usage:
|
|
21
|
+
self.app.push_screen(HelpModal())
|
|
22
|
+
"""
|
|
23
|
+
|
|
24
|
+
BINDINGS = [
|
|
25
|
+
Binding("escape", "close", "Close", show=True),
|
|
26
|
+
Binding("q", "close", "Close", show=False),
|
|
27
|
+
]
|
|
28
|
+
|
|
29
|
+
def __init__(self, **kwargs: Any) -> None:
|
|
30
|
+
super().__init__(**kwargs)
|
|
31
|
+
|
|
32
|
+
def compose(self) -> ComposeResult:
|
|
33
|
+
with Vertical():
|
|
34
|
+
yield Static("Keyboard Shortcuts", classes="modal-title")
|
|
35
|
+
|
|
36
|
+
with VerticalScroll():
|
|
37
|
+
# Global navigation (works everywhere)
|
|
38
|
+
yield Static("[bold]Global Navigation[/]", classes="section-title")
|
|
39
|
+
yield Static("[cyan]c[/] Switch to Chat screen")
|
|
40
|
+
yield Static("[cyan]a[/] Switch to Agents screen")
|
|
41
|
+
yield Static("[cyan]t[/] Switch to Templates screen")
|
|
42
|
+
yield Static("[cyan]m[/] Switch to Content (media) screen")
|
|
43
|
+
yield Static("[cyan]s[/] Switch to Schemas screen")
|
|
44
|
+
yield Static("[cyan]g[/] Switch to Tool Configs screen")
|
|
45
|
+
yield Static("[cyan]d[/] Show Dashboard")
|
|
46
|
+
yield Static("[cyan]?[/] Show this help")
|
|
47
|
+
yield Static("[cyan]Ctrl+C[/] Quit application")
|
|
48
|
+
|
|
49
|
+
# Chat screen
|
|
50
|
+
yield Static("[bold]Chat Screen[/]", classes="section-title")
|
|
51
|
+
yield Static("[cyan]Ctrl+N[/] New chat session")
|
|
52
|
+
yield Static("[cyan]Ctrl+D[/] Send message")
|
|
53
|
+
yield Static("[cyan]Ctrl+E[/] Open message in $EDITOR")
|
|
54
|
+
yield Static("[cyan]Ctrl+R[/] Regenerate last response")
|
|
55
|
+
yield Static("[cyan]Ctrl+U[/] Undo last turn")
|
|
56
|
+
yield Static("[cyan]Ctrl+Y[/] Copy last response")
|
|
57
|
+
yield Static("[cyan]Ctrl+Shift+Y[/] Copy all messages")
|
|
58
|
+
yield Static("[cyan]Ctrl+L[/] Clear display")
|
|
59
|
+
yield Static("[cyan]Ctrl+B[/] Toggle sidebar")
|
|
60
|
+
yield Static("[cyan]Escape[/] Cancel streaming / Focus input")
|
|
61
|
+
yield Static("[cyan]g[/] Scroll to top")
|
|
62
|
+
yield Static("[cyan]G[/] Scroll to bottom")
|
|
63
|
+
|
|
64
|
+
# Chat split view
|
|
65
|
+
yield Static("[bold]Chat Split View[/]", classes="section-title")
|
|
66
|
+
yield Static("[cyan]Ctrl+Shift+S[/] Toggle split view")
|
|
67
|
+
yield Static("[cyan]Ctrl+Shift+Tab[/] Switch between panes")
|
|
68
|
+
yield Static("[cyan]Ctrl+Shift+Y[/] Toggle sync mode (send to both)")
|
|
69
|
+
|
|
70
|
+
# Welcome screen (when no session active)
|
|
71
|
+
yield Static(
|
|
72
|
+
"[bold]Welcome Screen (Agent Quick Select)[/]",
|
|
73
|
+
classes="section-title",
|
|
74
|
+
)
|
|
75
|
+
yield Static("[cyan]1-9[/] Select agent by number")
|
|
76
|
+
|
|
77
|
+
# Browser screens (Agents/Templates/Content/Schemas)
|
|
78
|
+
yield Static(
|
|
79
|
+
"[bold]Browser Screens (Agents/Templates/Content/Schemas)[/]",
|
|
80
|
+
classes="section-title",
|
|
81
|
+
)
|
|
82
|
+
yield Static("[cyan]Ctrl+F[/] Focus search input")
|
|
83
|
+
yield Static("[cyan]Ctrl+R[/] Refresh results")
|
|
84
|
+
yield Static("[cyan]Ctrl+Y[/] Copy name/content")
|
|
85
|
+
yield Static("[cyan]Ctrl+N[/] Create new item")
|
|
86
|
+
yield Static("[cyan]Escape[/] Focus list")
|
|
87
|
+
yield Static("[cyan]Enter[/] Copy name/content")
|
|
88
|
+
yield Static("[cyan]Up/Down[/] Navigate list")
|
|
89
|
+
|
|
90
|
+
# Agents specific
|
|
91
|
+
yield Static("[bold]Agents Screen[/]", classes="section-title")
|
|
92
|
+
yield Static("[cyan]Ctrl+E[/] Edit selected agent")
|
|
93
|
+
yield Static("[cyan]Ctrl+D[/] Delete selected agent")
|
|
94
|
+
|
|
95
|
+
# Templates specific
|
|
96
|
+
yield Static("[bold]Templates Screen[/]", classes="section-title")
|
|
97
|
+
yield Static("[cyan]Ctrl+Shift+Y[/] Copy template content")
|
|
98
|
+
yield Static("[cyan]Ctrl+E[/] Edit template in $EDITOR")
|
|
99
|
+
yield Static("[cyan]Ctrl+U[/] Edit template name/description")
|
|
100
|
+
yield Static("[cyan]Ctrl+V[/] Create new version")
|
|
101
|
+
yield Static("[cyan]Ctrl+O[/] Render and open template")
|
|
102
|
+
|
|
103
|
+
# Content specific
|
|
104
|
+
yield Static("[bold]Content Screen[/]", classes="section-title")
|
|
105
|
+
yield Static(
|
|
106
|
+
"[cyan]Three search inputs:[/] Fuzzy, Tag filter, External ID"
|
|
107
|
+
)
|
|
108
|
+
yield Static(
|
|
109
|
+
"[cyan]Ctrl+I[/] Copy ID (external_id if set, else UUID)"
|
|
110
|
+
)
|
|
111
|
+
yield Static("[cyan]Ctrl+T[/] Manage tags")
|
|
112
|
+
yield Static("[cyan]Ctrl+E[/] View in $EDITOR")
|
|
113
|
+
yield Static("[cyan]Ctrl+D[/] Delete selected content")
|
|
114
|
+
|
|
115
|
+
# Schemas specific
|
|
116
|
+
yield Static("[bold]Schemas Screen[/]", classes="section-title")
|
|
117
|
+
yield Static("[cyan]Ctrl+Shift+Y[/] Copy schema definition")
|
|
118
|
+
yield Static("[cyan]Ctrl+E[/] Edit definition in $EDITOR")
|
|
119
|
+
yield Static("[cyan]Ctrl+U[/] Edit schema name/description")
|
|
120
|
+
yield Static("[cyan]Ctrl+V[/] Create new version")
|
|
121
|
+
|
|
122
|
+
# Tool Configs specific
|
|
123
|
+
yield Static("[bold]Tool Configs Screen[/]", classes="section-title")
|
|
124
|
+
yield Static("[cyan]Ctrl+E[/] Edit selected config")
|
|
125
|
+
yield Static(
|
|
126
|
+
"[cyan]Ctrl+D[/] Delete selected config (blocked if in use)"
|
|
127
|
+
)
|
|
128
|
+
|
|
129
|
+
# Modals
|
|
130
|
+
yield Static("[bold]Modals & Dialogs[/]", classes="section-title")
|
|
131
|
+
yield Static("[cyan]Escape[/] Cancel / Close modal")
|
|
132
|
+
yield Static("[cyan]Ctrl+S[/] Submit form")
|
|
133
|
+
yield Static("[cyan]n[/] Cancel (confirmation dialogs)")
|
|
134
|
+
|
|
135
|
+
with Vertical(classes="button-row"):
|
|
136
|
+
yield Button("Close", id="close-btn", variant="primary")
|
|
137
|
+
|
|
138
|
+
@on(Button.Pressed, "#close-btn")
|
|
139
|
+
def on_close_pressed(self, event: Button.Pressed) -> None:
|
|
140
|
+
"""Close the modal."""
|
|
141
|
+
self.dismiss(None)
|
|
142
|
+
|
|
143
|
+
def action_close(self) -> None:
|
|
144
|
+
"""Close via escape or q key."""
|
|
145
|
+
self.dismiss(None)
|