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,502 @@
|
|
|
1
|
+
"""Template creation modal for creating new templates.
|
|
2
|
+
|
|
3
|
+
Provides a comprehensive modal screen that allows users to create a new template
|
|
4
|
+
with all required fields, external editor integration, and macro resolution.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from dataclasses import dataclass
|
|
8
|
+
from typing import TYPE_CHECKING, Any
|
|
9
|
+
|
|
10
|
+
from textual import on, work
|
|
11
|
+
from textual.app import ComposeResult
|
|
12
|
+
from textual.containers import Horizontal, VerticalScroll
|
|
13
|
+
from textual.widgets import (
|
|
14
|
+
Button,
|
|
15
|
+
Checkbox,
|
|
16
|
+
Input,
|
|
17
|
+
Label,
|
|
18
|
+
RadioButton,
|
|
19
|
+
RadioSet,
|
|
20
|
+
Static,
|
|
21
|
+
)
|
|
22
|
+
|
|
23
|
+
from cli.tui.widgets.base_form_modal import BaseFormModal
|
|
24
|
+
|
|
25
|
+
from alloy_runtime_sdk.api_client.client import ApiClient
|
|
26
|
+
from alloy_runtime_types.dtos.templates import CreateTemplateRequest
|
|
27
|
+
from alloy_runtime_types.enums.template_enums import (
|
|
28
|
+
TemplateContentType,
|
|
29
|
+
TemplateVisibility,
|
|
30
|
+
)
|
|
31
|
+
|
|
32
|
+
from cli.infrastructure.editor import EditorError, open_editor_with_hints
|
|
33
|
+
from cli.infrastructure.forms.resolution_modal import ResolutionModal
|
|
34
|
+
from cli.infrastructure.forms.tag_picker import TagPicker
|
|
35
|
+
from cli.infrastructure.macro_parser import (
|
|
36
|
+
MacroMatch,
|
|
37
|
+
build_jinja_replacement,
|
|
38
|
+
compile_content,
|
|
39
|
+
deduplicate_macros,
|
|
40
|
+
parse_macros,
|
|
41
|
+
)
|
|
42
|
+
|
|
43
|
+
if TYPE_CHECKING:
|
|
44
|
+
from cli.tui.app import AlloyRuntimeApp
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
@dataclass
|
|
48
|
+
class TemplateCreateResult:
|
|
49
|
+
"""Result of successful template creation."""
|
|
50
|
+
|
|
51
|
+
template_id: str
|
|
52
|
+
template_name: str
|
|
53
|
+
version_id: str
|
|
54
|
+
version_number: int
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
class TemplateCreateModal(BaseFormModal[TemplateCreateResult]):
|
|
58
|
+
"""Modal for creating a new template.
|
|
59
|
+
|
|
60
|
+
Provides a comprehensive form with:
|
|
61
|
+
- Required fields: name, content type, visibility, tags
|
|
62
|
+
- External editor integration for content
|
|
63
|
+
- Macro resolution flow for @fragment, @text, @json, @schema
|
|
64
|
+
- Optional fields: description, upsert, escape_jinja
|
|
65
|
+
|
|
66
|
+
Usage:
|
|
67
|
+
def on_template_created(result: TemplateCreateResult | None):
|
|
68
|
+
if result is not None:
|
|
69
|
+
# Template was created successfully
|
|
70
|
+
self.notify(f"Created template: {result.template_name}")
|
|
71
|
+
self._do_search("") # Refresh list
|
|
72
|
+
|
|
73
|
+
client = await self.app.store.get_client()
|
|
74
|
+
self.app.push_screen(
|
|
75
|
+
TemplateCreateModal(client=client),
|
|
76
|
+
on_template_created
|
|
77
|
+
)
|
|
78
|
+
"""
|
|
79
|
+
|
|
80
|
+
app: "AlloyRuntimeApp"
|
|
81
|
+
|
|
82
|
+
def __init__(
|
|
83
|
+
self,
|
|
84
|
+
client: ApiClient,
|
|
85
|
+
**kwargs: Any,
|
|
86
|
+
) -> None:
|
|
87
|
+
"""Initialize the template creation modal.
|
|
88
|
+
|
|
89
|
+
Args:
|
|
90
|
+
client: ApiClient instance for API calls
|
|
91
|
+
"""
|
|
92
|
+
super().__init__(**kwargs)
|
|
93
|
+
self._client = client
|
|
94
|
+
|
|
95
|
+
# Template content state
|
|
96
|
+
self._content: str = ""
|
|
97
|
+
self._pending_macros: list[MacroMatch] = [] # Unique macros to resolve
|
|
98
|
+
self._all_macros: list[MacroMatch] = [] # All macros for replacement mapping
|
|
99
|
+
self._replacements: dict[str, str] = {}
|
|
100
|
+
self._current_macro_index: int = 0
|
|
101
|
+
self._macros_resolved: bool = False
|
|
102
|
+
|
|
103
|
+
def compose(self) -> ComposeResult:
|
|
104
|
+
with VerticalScroll(id="template-create-modal"):
|
|
105
|
+
yield Label("Create New Template", classes="modal-title")
|
|
106
|
+
|
|
107
|
+
# ===== REQUIRED FIELDS =====
|
|
108
|
+
yield Static("[bold]Required[/]", classes="form-section")
|
|
109
|
+
|
|
110
|
+
yield Static(
|
|
111
|
+
"Name (lowercase, dots/dashes/underscores)", classes="field-label"
|
|
112
|
+
)
|
|
113
|
+
yield Input(
|
|
114
|
+
placeholder="e.g., email.welcome-header, system.default_prompt",
|
|
115
|
+
id="name-input",
|
|
116
|
+
)
|
|
117
|
+
|
|
118
|
+
yield Static("Content Type", classes="field-label")
|
|
119
|
+
with RadioSet(id="content-type-radios"):
|
|
120
|
+
yield RadioButton("System Instruction", id="type-system", value=True)
|
|
121
|
+
yield RadioButton("User Message", id="type-user")
|
|
122
|
+
yield RadioButton("Fragment", id="type-fragment")
|
|
123
|
+
|
|
124
|
+
yield Static("Visibility", classes="field-label")
|
|
125
|
+
with RadioSet(id="visibility-radios"):
|
|
126
|
+
yield RadioButton("Private", id="vis-private", value=True)
|
|
127
|
+
yield RadioButton("Organization", id="vis-org")
|
|
128
|
+
yield RadioButton("Public", id="vis-public")
|
|
129
|
+
|
|
130
|
+
# ===== TEMPLATE CONTENT =====
|
|
131
|
+
yield Static("[bold]Template Content[/]", classes="form-section")
|
|
132
|
+
|
|
133
|
+
yield Static(
|
|
134
|
+
"No content yet. Click 'Edit Content' to open your editor.",
|
|
135
|
+
id="content-status",
|
|
136
|
+
classes="content-status no-content",
|
|
137
|
+
)
|
|
138
|
+
|
|
139
|
+
with Horizontal(classes="content-buttons"):
|
|
140
|
+
yield Button(
|
|
141
|
+
"Edit Content",
|
|
142
|
+
id="edit-content-btn",
|
|
143
|
+
variant="primary",
|
|
144
|
+
)
|
|
145
|
+
yield Button(
|
|
146
|
+
"Resolve Macros",
|
|
147
|
+
id="resolve-macros-btn",
|
|
148
|
+
variant="warning",
|
|
149
|
+
disabled=True,
|
|
150
|
+
)
|
|
151
|
+
|
|
152
|
+
yield Static("Tags (required)", classes="field-label")
|
|
153
|
+
yield TagPicker(
|
|
154
|
+
client=self._client,
|
|
155
|
+
placeholder="Search tags...",
|
|
156
|
+
empty_message="No tags selected (required)",
|
|
157
|
+
id="tag-picker",
|
|
158
|
+
)
|
|
159
|
+
|
|
160
|
+
# ===== OPTIONAL FIELDS =====
|
|
161
|
+
yield Static("[bold]Optional[/]", classes="form-section")
|
|
162
|
+
|
|
163
|
+
yield Static("Description", classes="field-label")
|
|
164
|
+
yield Input(
|
|
165
|
+
placeholder="Brief description of this template's purpose",
|
|
166
|
+
id="description-input",
|
|
167
|
+
)
|
|
168
|
+
|
|
169
|
+
with Horizontal(classes="checkbox-row"):
|
|
170
|
+
yield Checkbox(
|
|
171
|
+
"Return existing if name exists (upsert)",
|
|
172
|
+
id="upsert-checkbox",
|
|
173
|
+
)
|
|
174
|
+
|
|
175
|
+
with Horizontal(classes="checkbox-row"):
|
|
176
|
+
yield Checkbox(
|
|
177
|
+
"Escape Jinja syntax ({{, {%, {#)",
|
|
178
|
+
id="escape-jinja-checkbox",
|
|
179
|
+
)
|
|
180
|
+
|
|
181
|
+
# Error display
|
|
182
|
+
yield Static("", id="error-display", classes="error-display")
|
|
183
|
+
|
|
184
|
+
with Horizontal(classes="button-row"):
|
|
185
|
+
yield Button("Create", id="create-btn", variant="success")
|
|
186
|
+
yield Button("Cancel", id="cancel-btn", variant="default")
|
|
187
|
+
|
|
188
|
+
def on_mount(self) -> None:
|
|
189
|
+
"""Focus the name input on mount."""
|
|
190
|
+
self.query_one("#name-input", Input).focus()
|
|
191
|
+
|
|
192
|
+
@on(Button.Pressed, "#edit-content-btn")
|
|
193
|
+
def on_edit_content_pressed(self, event: Button.Pressed) -> None:
|
|
194
|
+
"""Open the external editor for content editing."""
|
|
195
|
+
with self.app.suspend():
|
|
196
|
+
try:
|
|
197
|
+
content = open_editor_with_hints(self._content)
|
|
198
|
+
if content is not None:
|
|
199
|
+
self._content = content
|
|
200
|
+
# Reset resolution state when content changes
|
|
201
|
+
self._macros_resolved = False
|
|
202
|
+
self._replacements = {}
|
|
203
|
+
self._update_content_status()
|
|
204
|
+
except EditorError as e:
|
|
205
|
+
self._show_error(str(e))
|
|
206
|
+
|
|
207
|
+
@on(Button.Pressed, "#resolve-macros-btn")
|
|
208
|
+
def on_resolve_macros_pressed(self, event: Button.Pressed) -> None:
|
|
209
|
+
"""Start the macro resolution flow."""
|
|
210
|
+
self._start_macro_resolution()
|
|
211
|
+
|
|
212
|
+
@on(Button.Pressed, "#create-btn")
|
|
213
|
+
def on_create_pressed(self, event: Button.Pressed) -> None:
|
|
214
|
+
"""Handle create button press."""
|
|
215
|
+
self.action_submit()
|
|
216
|
+
|
|
217
|
+
@on(Button.Pressed, "#cancel-btn")
|
|
218
|
+
def on_cancel_pressed(self, event: Button.Pressed) -> None:
|
|
219
|
+
"""Handle cancel button press."""
|
|
220
|
+
self.dismiss(None)
|
|
221
|
+
|
|
222
|
+
def action_submit(self) -> None:
|
|
223
|
+
"""Handle form submission."""
|
|
224
|
+
try:
|
|
225
|
+
self._validate_fields()
|
|
226
|
+
|
|
227
|
+
# Check if there are unresolved macros
|
|
228
|
+
macros = parse_macros(self._content)
|
|
229
|
+
if macros and not self._macros_resolved:
|
|
230
|
+
self._show_error(
|
|
231
|
+
f"Found {len(macros)} unresolved macro(s). "
|
|
232
|
+
"Click 'Resolve Macros' first, or remove the macros from your content."
|
|
233
|
+
)
|
|
234
|
+
return
|
|
235
|
+
|
|
236
|
+
# Clear any previous error
|
|
237
|
+
self._hide_error()
|
|
238
|
+
|
|
239
|
+
# Submit to API
|
|
240
|
+
self._finalize_submission()
|
|
241
|
+
|
|
242
|
+
except ValueError as e:
|
|
243
|
+
self._show_error(str(e))
|
|
244
|
+
|
|
245
|
+
def _validate_fields(self) -> None:
|
|
246
|
+
"""Validate all required fields."""
|
|
247
|
+
import re
|
|
248
|
+
|
|
249
|
+
name = self.query_one("#name-input", Input).value.strip()
|
|
250
|
+
if not name:
|
|
251
|
+
raise ValueError("Name is required")
|
|
252
|
+
|
|
253
|
+
if not re.match(r"^[a-z0-9._-]+$", name):
|
|
254
|
+
raise ValueError(
|
|
255
|
+
"Name must be lowercase alphanumeric with dots, dashes, or underscores only"
|
|
256
|
+
)
|
|
257
|
+
|
|
258
|
+
if not self._content.strip():
|
|
259
|
+
raise ValueError(
|
|
260
|
+
"Template content is required. Click 'Edit Content' to add content."
|
|
261
|
+
)
|
|
262
|
+
|
|
263
|
+
tag_picker = self.query_one("#tag-picker", TagPicker)
|
|
264
|
+
tag_paths = tag_picker.selected_tags
|
|
265
|
+
if not tag_paths:
|
|
266
|
+
raise ValueError("At least one tag is required")
|
|
267
|
+
|
|
268
|
+
def _update_content_status(self) -> None:
|
|
269
|
+
"""Update the content status display and resolve button state."""
|
|
270
|
+
status = self.query_one("#content-status", Static)
|
|
271
|
+
resolve_btn = self.query_one("#resolve-macros-btn", Button)
|
|
272
|
+
|
|
273
|
+
if not self._content.strip():
|
|
274
|
+
status.update("No content yet. Click 'Edit Content' to open your editor.")
|
|
275
|
+
status.remove_class("has-content", "has-macros", "macros-resolved")
|
|
276
|
+
status.add_class("no-content")
|
|
277
|
+
resolve_btn.disabled = True
|
|
278
|
+
return
|
|
279
|
+
|
|
280
|
+
# Parse macros from content
|
|
281
|
+
all_macros = parse_macros(self._content)
|
|
282
|
+
unique_macros = deduplicate_macros(all_macros)
|
|
283
|
+
char_count = len(self._content)
|
|
284
|
+
line_count = self._content.count("\n") + 1
|
|
285
|
+
|
|
286
|
+
if unique_macros:
|
|
287
|
+
if self._macros_resolved:
|
|
288
|
+
# Macros have been resolved
|
|
289
|
+
resolved_keys = {
|
|
290
|
+
(m.macro_type, m.query)
|
|
291
|
+
for m in all_macros
|
|
292
|
+
if m.original_text in self._replacements
|
|
293
|
+
}
|
|
294
|
+
resolved_count = len(resolved_keys)
|
|
295
|
+
skipped_count = len(unique_macros) - resolved_count
|
|
296
|
+
|
|
297
|
+
total_instances = len(all_macros)
|
|
298
|
+
status_text = (
|
|
299
|
+
f"Content: {char_count} chars, {line_count} lines\n"
|
|
300
|
+
f"Macros resolved: {resolved_count}/{len(unique_macros)} unique"
|
|
301
|
+
)
|
|
302
|
+
if total_instances > len(unique_macros):
|
|
303
|
+
status_text += f" ({total_instances} total instances)"
|
|
304
|
+
if skipped_count > 0:
|
|
305
|
+
status_text += f"\n({skipped_count} skipped - will remain as-is)"
|
|
306
|
+
status.update(status_text)
|
|
307
|
+
status.remove_class("no-content", "has-content", "has-macros")
|
|
308
|
+
status.add_class("macros-resolved")
|
|
309
|
+
resolve_btn.disabled = False
|
|
310
|
+
resolve_btn.label = "Re-resolve Macros"
|
|
311
|
+
else:
|
|
312
|
+
# Macros found but not yet resolved
|
|
313
|
+
macro_summary = ", ".join(
|
|
314
|
+
f"@{m.macro_type}({m.query[:20]}...)"
|
|
315
|
+
if len(m.query) > 20
|
|
316
|
+
else f"@{m.macro_type}({m.query})"
|
|
317
|
+
for m in unique_macros[:3]
|
|
318
|
+
)
|
|
319
|
+
if len(unique_macros) > 3:
|
|
320
|
+
macro_summary += f", +{len(unique_macros) - 3} more"
|
|
321
|
+
|
|
322
|
+
total_instances = len(all_macros)
|
|
323
|
+
instance_note = ""
|
|
324
|
+
if total_instances > len(unique_macros):
|
|
325
|
+
instance_note = f" ({total_instances} total instances)"
|
|
326
|
+
|
|
327
|
+
status.update(
|
|
328
|
+
f"Content: {char_count} chars, {line_count} lines\n"
|
|
329
|
+
f"Macros found: {len(unique_macros)} unique{instance_note} - {macro_summary}\n"
|
|
330
|
+
f"[bold]Click 'Resolve Macros' before submitting[/bold]"
|
|
331
|
+
)
|
|
332
|
+
status.remove_class("no-content", "has-content", "macros-resolved")
|
|
333
|
+
status.add_class("has-macros")
|
|
334
|
+
resolve_btn.disabled = False
|
|
335
|
+
resolve_btn.label = "Resolve Macros"
|
|
336
|
+
else:
|
|
337
|
+
status.update(f"Content ready: {char_count} chars, {line_count} lines")
|
|
338
|
+
status.remove_class("no-content", "has-macros", "macros-resolved")
|
|
339
|
+
status.add_class("has-content")
|
|
340
|
+
resolve_btn.disabled = True
|
|
341
|
+
|
|
342
|
+
def _start_macro_resolution(self) -> None:
|
|
343
|
+
"""Start the macro resolution flow."""
|
|
344
|
+
self._all_macros = parse_macros(self._content)
|
|
345
|
+
self._pending_macros = deduplicate_macros(self._all_macros)
|
|
346
|
+
self._replacements = {}
|
|
347
|
+
self._current_macro_index = 0
|
|
348
|
+
self._macros_resolved = False
|
|
349
|
+
|
|
350
|
+
if self._pending_macros:
|
|
351
|
+
self._process_next_macro()
|
|
352
|
+
else:
|
|
353
|
+
self.app.notify("No macros to resolve", severity="information")
|
|
354
|
+
|
|
355
|
+
def _process_next_macro(self) -> None:
|
|
356
|
+
"""Process the next macro in the queue."""
|
|
357
|
+
if self._current_macro_index >= len(self._pending_macros):
|
|
358
|
+
# All macros processed
|
|
359
|
+
self._macros_resolved = True
|
|
360
|
+
self._update_content_status()
|
|
361
|
+
|
|
362
|
+
resolved_keys = {
|
|
363
|
+
(m.macro_type, m.query)
|
|
364
|
+
for m in self._all_macros
|
|
365
|
+
if m.original_text in self._replacements
|
|
366
|
+
}
|
|
367
|
+
resolved_count = len(resolved_keys)
|
|
368
|
+
total_unique = len(self._pending_macros)
|
|
369
|
+
total_instances = len(self._all_macros)
|
|
370
|
+
|
|
371
|
+
if total_instances > total_unique:
|
|
372
|
+
self.app.notify(
|
|
373
|
+
f"Resolution complete: {resolved_count}/{total_unique} unique macros resolved ({total_instances} instances)",
|
|
374
|
+
severity="information",
|
|
375
|
+
)
|
|
376
|
+
else:
|
|
377
|
+
self.app.notify(
|
|
378
|
+
f"Resolution complete: {resolved_count}/{total_unique} macros resolved",
|
|
379
|
+
severity="information",
|
|
380
|
+
)
|
|
381
|
+
return
|
|
382
|
+
|
|
383
|
+
macro = self._pending_macros[self._current_macro_index]
|
|
384
|
+
|
|
385
|
+
# Open resolution modal for this macro
|
|
386
|
+
self.app.push_screen(
|
|
387
|
+
ResolutionModal(
|
|
388
|
+
client=self._client,
|
|
389
|
+
macro_type=macro.macro_type,
|
|
390
|
+
query=macro.query,
|
|
391
|
+
),
|
|
392
|
+
self._on_macro_resolved,
|
|
393
|
+
)
|
|
394
|
+
|
|
395
|
+
def _on_macro_resolved(self, result: dict[str, Any] | None) -> None:
|
|
396
|
+
"""Callback when a macro resolution modal is dismissed."""
|
|
397
|
+
macro = self._pending_macros[self._current_macro_index]
|
|
398
|
+
|
|
399
|
+
if result is not None:
|
|
400
|
+
# User selected a value
|
|
401
|
+
resolved_value = result["value"]
|
|
402
|
+
jinja_replacement = build_jinja_replacement(
|
|
403
|
+
macro.macro_type, resolved_value
|
|
404
|
+
)
|
|
405
|
+
|
|
406
|
+
# Find all macros with the same (macro_type, query) and add replacements
|
|
407
|
+
matching_count = 0
|
|
408
|
+
for m in self._all_macros:
|
|
409
|
+
if m.macro_type == macro.macro_type and m.query == macro.query:
|
|
410
|
+
self._replacements[m.original_text] = jinja_replacement
|
|
411
|
+
matching_count += 1
|
|
412
|
+
|
|
413
|
+
if matching_count > 1:
|
|
414
|
+
self.app.notify(
|
|
415
|
+
f"Resolved {matching_count} instances of @{macro.macro_type}({macro.query}) -> {result['display']}",
|
|
416
|
+
severity="information",
|
|
417
|
+
)
|
|
418
|
+
else:
|
|
419
|
+
self.app.notify(
|
|
420
|
+
f"Resolved {macro.original_text} -> {result['display']}",
|
|
421
|
+
severity="information",
|
|
422
|
+
)
|
|
423
|
+
else:
|
|
424
|
+
# User skipped this macro
|
|
425
|
+
self.app.notify(
|
|
426
|
+
f"Skipped resolution for {macro.original_text}",
|
|
427
|
+
severity="warning",
|
|
428
|
+
)
|
|
429
|
+
|
|
430
|
+
# Move to next macro
|
|
431
|
+
self._current_macro_index += 1
|
|
432
|
+
self._process_next_macro()
|
|
433
|
+
|
|
434
|
+
@work(exclusive=True)
|
|
435
|
+
async def _finalize_submission(self) -> None:
|
|
436
|
+
"""Compile content and submit to API."""
|
|
437
|
+
try:
|
|
438
|
+
# Apply all replacements
|
|
439
|
+
final_content = compile_content(self._content, self._replacements)
|
|
440
|
+
|
|
441
|
+
# Build the request
|
|
442
|
+
request = self._build_request(final_content)
|
|
443
|
+
|
|
444
|
+
# Submit to API
|
|
445
|
+
response = await self._client.create_template(request)
|
|
446
|
+
|
|
447
|
+
# Return success result
|
|
448
|
+
result = TemplateCreateResult(
|
|
449
|
+
template_id=str(response.template.id),
|
|
450
|
+
template_name=response.template.name,
|
|
451
|
+
version_id=str(response.version.id),
|
|
452
|
+
version_number=response.version.version,
|
|
453
|
+
)
|
|
454
|
+
self.dismiss(result)
|
|
455
|
+
|
|
456
|
+
except Exception as e:
|
|
457
|
+
self._show_error(f"Failed to create template: {e}")
|
|
458
|
+
|
|
459
|
+
# Template-specific RadioSet parsers (not scope-related)
|
|
460
|
+
def _get_content_type(self) -> TemplateContentType:
|
|
461
|
+
"""Get content type from RadioSet."""
|
|
462
|
+
radios = self.query_one("#content-type-radios", RadioSet)
|
|
463
|
+
pressed = radios.pressed_button
|
|
464
|
+
if pressed is None or pressed.id == "type-system":
|
|
465
|
+
return TemplateContentType.SYSTEM_INSTRUCTION
|
|
466
|
+
elif pressed.id == "type-user":
|
|
467
|
+
return TemplateContentType.USER_MESSAGE
|
|
468
|
+
else:
|
|
469
|
+
return TemplateContentType.FRAGMENT
|
|
470
|
+
|
|
471
|
+
def _get_visibility(self) -> TemplateVisibility:
|
|
472
|
+
"""Get visibility from RadioSet."""
|
|
473
|
+
radios = self.query_one("#visibility-radios", RadioSet)
|
|
474
|
+
pressed = radios.pressed_button
|
|
475
|
+
if pressed is None or pressed.id == "vis-private":
|
|
476
|
+
return TemplateVisibility.PRIVATE
|
|
477
|
+
elif pressed.id == "vis-org":
|
|
478
|
+
return TemplateVisibility.ORGANIZATION
|
|
479
|
+
else:
|
|
480
|
+
return TemplateVisibility.PUBLIC
|
|
481
|
+
|
|
482
|
+
def _build_request(self, final_content: str) -> CreateTemplateRequest:
|
|
483
|
+
"""Build the API request."""
|
|
484
|
+
name = self.query_one("#name-input", Input).value.strip()
|
|
485
|
+
description = self.query_one("#description-input", Input).value.strip() or None
|
|
486
|
+
|
|
487
|
+
tag_picker = self.query_one("#tag-picker", TagPicker)
|
|
488
|
+
tag_paths = tag_picker.selected_tags
|
|
489
|
+
|
|
490
|
+
upsert = self.query_one("#upsert-checkbox", Checkbox).value
|
|
491
|
+
escape_jinja = self.query_one("#escape-jinja-checkbox", Checkbox).value
|
|
492
|
+
|
|
493
|
+
return CreateTemplateRequest(
|
|
494
|
+
name=name,
|
|
495
|
+
content_type=self._get_content_type(),
|
|
496
|
+
visibility=self._get_visibility(),
|
|
497
|
+
initial_content=final_content,
|
|
498
|
+
tag_paths=tag_paths,
|
|
499
|
+
description=description,
|
|
500
|
+
upsert=upsert,
|
|
501
|
+
escape_jinja=escape_jinja,
|
|
502
|
+
)
|