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,105 @@
|
|
|
1
|
+
"""Common formatters for TUI table displays."""
|
|
2
|
+
|
|
3
|
+
from datetime import datetime
|
|
4
|
+
from typing import Any
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def truncate_text(text: str, max_length: int = 40) -> str:
|
|
8
|
+
"""Truncate text with ellipsis if too long.
|
|
9
|
+
|
|
10
|
+
Args:
|
|
11
|
+
text: The text to truncate
|
|
12
|
+
max_length: Maximum length before truncation
|
|
13
|
+
|
|
14
|
+
Returns:
|
|
15
|
+
Truncated text with ellipsis, or original if short enough
|
|
16
|
+
"""
|
|
17
|
+
if len(text) <= max_length:
|
|
18
|
+
return text
|
|
19
|
+
return text[: max_length - 3] + "..."
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
# Threshold for considering content "long" and needing truncation
|
|
23
|
+
LONG_CONTENT_THRESHOLD = 2000 # characters
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def truncate_long_content(
|
|
27
|
+
text: str,
|
|
28
|
+
*,
|
|
29
|
+
threshold: int = LONG_CONTENT_THRESHOLD,
|
|
30
|
+
head_chars: int = 50,
|
|
31
|
+
tail_chars: int = 50,
|
|
32
|
+
) -> tuple[str, bool]:
|
|
33
|
+
"""Truncate long content for display, preserving head and tail.
|
|
34
|
+
|
|
35
|
+
Designed for chat message display where very long injected content
|
|
36
|
+
(e.g., from @fragment()) would overwhelm the TUI.
|
|
37
|
+
|
|
38
|
+
Args:
|
|
39
|
+
text: The text to potentially truncate
|
|
40
|
+
threshold: Character count above which to truncate
|
|
41
|
+
head_chars: Number of characters to show from the start
|
|
42
|
+
tail_chars: Number of characters to show from the end
|
|
43
|
+
|
|
44
|
+
Returns:
|
|
45
|
+
Tuple of (truncated_text, was_truncated)
|
|
46
|
+
- truncated_text: The possibly truncated text
|
|
47
|
+
- was_truncated: True if content was truncated
|
|
48
|
+
"""
|
|
49
|
+
if len(text) <= threshold:
|
|
50
|
+
return text, False
|
|
51
|
+
|
|
52
|
+
truncated_count = len(text) - head_chars - tail_chars
|
|
53
|
+
head = text[:head_chars]
|
|
54
|
+
tail = text[-tail_chars:]
|
|
55
|
+
|
|
56
|
+
# Build truncation indicator
|
|
57
|
+
truncated_text = f"{head}... [{truncated_count:,} chars truncated] ...{tail}"
|
|
58
|
+
|
|
59
|
+
return truncated_text, True
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
def format_tags_list(
|
|
63
|
+
tags: list[dict[str, Any]], path_key: str = "tag_path", max_display: int = 2
|
|
64
|
+
) -> str:
|
|
65
|
+
"""Format a list of tags for table display.
|
|
66
|
+
|
|
67
|
+
Args:
|
|
68
|
+
tags: List of tag dicts
|
|
69
|
+
path_key: Key to extract tag path from each dict
|
|
70
|
+
max_display: Maximum number of tags to show before truncating
|
|
71
|
+
|
|
72
|
+
Returns:
|
|
73
|
+
Formatted string like "tag1, tag2 (+3)"
|
|
74
|
+
"""
|
|
75
|
+
if not tags:
|
|
76
|
+
return "-"
|
|
77
|
+
|
|
78
|
+
tag_paths = [str(t.get(path_key, "")) for t in tags[:max_display]]
|
|
79
|
+
result = ", ".join(tag_paths)
|
|
80
|
+
|
|
81
|
+
if len(tags) > max_display:
|
|
82
|
+
result += f" (+{len(tags) - max_display})"
|
|
83
|
+
|
|
84
|
+
return result
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
def format_datetime(dt: datetime | str | None, fmt: str = "%Y-%m-%d") -> str:
|
|
88
|
+
"""Format a datetime for display.
|
|
89
|
+
|
|
90
|
+
Args:
|
|
91
|
+
dt: datetime object, ISO string, or None
|
|
92
|
+
fmt: strftime format string
|
|
93
|
+
|
|
94
|
+
Returns:
|
|
95
|
+
Formatted date string, or "-" if None/invalid
|
|
96
|
+
"""
|
|
97
|
+
if not dt:
|
|
98
|
+
return "-"
|
|
99
|
+
|
|
100
|
+
try:
|
|
101
|
+
if isinstance(dt, str):
|
|
102
|
+
dt = datetime.fromisoformat(dt.replace("Z", "+00:00"))
|
|
103
|
+
return dt.strftime(fmt)
|
|
104
|
+
except (ValueError, AttributeError):
|
|
105
|
+
return str(dt)[:10] if dt else "-"
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
"""Preview pane formatting utilities for TUI applications."""
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
def format_preview_field(label: str, value: str) -> str:
|
|
5
|
+
"""Format a single label/value pair for preview pane using Rich markup.
|
|
6
|
+
|
|
7
|
+
Args:
|
|
8
|
+
label: The field label (e.g., "ID", "Name")
|
|
9
|
+
value: The field value
|
|
10
|
+
|
|
11
|
+
Returns:
|
|
12
|
+
Formatted string with Rich markup
|
|
13
|
+
"""
|
|
14
|
+
return f"[bold]{label}:[/] {value}"
|
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
"""Copy-on-select widgets for TUI applications.
|
|
2
|
+
|
|
3
|
+
This module provides widgets that automatically copy selected text to the clipboard.
|
|
4
|
+
These are useful for allowing users to select and copy text from the TUI without
|
|
5
|
+
needing to use explicit keybindings.
|
|
6
|
+
|
|
7
|
+
Available widgets:
|
|
8
|
+
- CopyOnSelectTextArea: TextArea that copies selected text automatically
|
|
9
|
+
- SelectableTextArea: Read-only TextArea for displaying selectable content
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
import asyncio
|
|
13
|
+
import os
|
|
14
|
+
import subprocess
|
|
15
|
+
from typing import Any, Protocol, cast
|
|
16
|
+
|
|
17
|
+
import pyperclip
|
|
18
|
+
from textual import on, work
|
|
19
|
+
from textual.widgets import TextArea
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class SupportsClipboard(Protocol):
|
|
23
|
+
"""Minimal protocol for app clipboard support."""
|
|
24
|
+
|
|
25
|
+
def copy_to_clipboard(self, text: str) -> None: ...
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
class CopyOnSelectTextArea(TextArea):
|
|
29
|
+
"""TextArea that automatically copies selected text to clipboard.
|
|
30
|
+
|
|
31
|
+
This widget extends TextArea to provide copy-on-select functionality.
|
|
32
|
+
When the user selects text, it is automatically copied to the clipboard
|
|
33
|
+
after a short debounce period (to avoid copying while the user is still
|
|
34
|
+
making their selection).
|
|
35
|
+
|
|
36
|
+
The widget uses pyperclip for clipboard access with a fallback to
|
|
37
|
+
OSC 52 escape sequences for terminals that support it, and pbcopy
|
|
38
|
+
on macOS as a final fallback.
|
|
39
|
+
|
|
40
|
+
Attributes:
|
|
41
|
+
show_copy_notification: Whether to show a notification when text is copied.
|
|
42
|
+
Defaults to False to avoid notification spam.
|
|
43
|
+
"""
|
|
44
|
+
|
|
45
|
+
show_copy_notification: bool = False
|
|
46
|
+
|
|
47
|
+
def __init__(
|
|
48
|
+
self,
|
|
49
|
+
*args: Any,
|
|
50
|
+
show_copy_notification: bool = False,
|
|
51
|
+
**kwargs: Any,
|
|
52
|
+
) -> None:
|
|
53
|
+
"""Initialize the copy-on-select TextArea.
|
|
54
|
+
|
|
55
|
+
Args:
|
|
56
|
+
*args: Positional arguments passed to TextArea.
|
|
57
|
+
show_copy_notification: Whether to show notifications when copying.
|
|
58
|
+
**kwargs: Keyword arguments passed to TextArea.
|
|
59
|
+
"""
|
|
60
|
+
super().__init__(*args, **kwargs)
|
|
61
|
+
self._last_selection = ""
|
|
62
|
+
self._pending_copy: str | None = None
|
|
63
|
+
self.show_copy_notification = show_copy_notification
|
|
64
|
+
|
|
65
|
+
@on(TextArea.SelectionChanged)
|
|
66
|
+
def _on_selection_changed(self, event: TextArea.SelectionChanged) -> None:
|
|
67
|
+
"""Handle selection changes and schedule copy operation."""
|
|
68
|
+
if event.selection.is_empty:
|
|
69
|
+
self._pending_copy = None
|
|
70
|
+
return
|
|
71
|
+
|
|
72
|
+
selected = event.text_area.selected_text
|
|
73
|
+
if selected and selected != self._last_selection:
|
|
74
|
+
self._pending_copy = selected
|
|
75
|
+
self._schedule_copy()
|
|
76
|
+
|
|
77
|
+
@work(exclusive=True)
|
|
78
|
+
async def _schedule_copy(self) -> None:
|
|
79
|
+
"""Wait for selection to stabilize before copying.
|
|
80
|
+
|
|
81
|
+
This debounces the copy operation to avoid copying while the user
|
|
82
|
+
is still making their selection. Waits 150ms after the last
|
|
83
|
+
selection change before actually copying.
|
|
84
|
+
"""
|
|
85
|
+
await asyncio.sleep(0.15)
|
|
86
|
+
if self._pending_copy:
|
|
87
|
+
self._copy_to_clipboard(self._pending_copy)
|
|
88
|
+
self._last_selection = self._pending_copy
|
|
89
|
+
|
|
90
|
+
def _copy_to_clipboard(self, text: str) -> None:
|
|
91
|
+
"""Copy text to clipboard using the best available method.
|
|
92
|
+
|
|
93
|
+
Tries pyperclip first, then falls back to OSC 52 or pbcopy
|
|
94
|
+
depending on the terminal environment.
|
|
95
|
+
"""
|
|
96
|
+
try:
|
|
97
|
+
pyperclip.copy(text)
|
|
98
|
+
if self.show_copy_notification:
|
|
99
|
+
char_count = len(text)
|
|
100
|
+
label = f"{char_count} char{'s' if char_count != 1 else ''}"
|
|
101
|
+
self.notify(f"Copied {label}", timeout=1)
|
|
102
|
+
except Exception:
|
|
103
|
+
# Fallback to OSC 52 or pbcopy
|
|
104
|
+
self._copy_fallback(text)
|
|
105
|
+
|
|
106
|
+
def _copy_fallback(self, text: str) -> None:
|
|
107
|
+
"""Fallback clipboard copy methods."""
|
|
108
|
+
term_program = os.environ.get("TERM_PROGRAM", "")
|
|
109
|
+
|
|
110
|
+
# Apple Terminal doesn't support OSC 52
|
|
111
|
+
if term_program == "Apple_Terminal":
|
|
112
|
+
self._copy_via_pbcopy(text)
|
|
113
|
+
else:
|
|
114
|
+
# Try OSC 52 (works over SSH in supported terminals)
|
|
115
|
+
try:
|
|
116
|
+
app_obj = getattr(self, "app", None)
|
|
117
|
+
if app_obj is None:
|
|
118
|
+
raise RuntimeError("App not available")
|
|
119
|
+
app = cast(SupportsClipboard, app_obj)
|
|
120
|
+
app.copy_to_clipboard(text)
|
|
121
|
+
except Exception:
|
|
122
|
+
self._copy_via_pbcopy(text)
|
|
123
|
+
|
|
124
|
+
def _copy_via_pbcopy(self, text: str) -> None:
|
|
125
|
+
"""Copy text using macOS pbcopy."""
|
|
126
|
+
try:
|
|
127
|
+
subprocess.run("pbcopy", text=True, input=text, check=True)
|
|
128
|
+
except subprocess.SubprocessError:
|
|
129
|
+
pass # Silent failure - clipboard unavailable
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
class SelectableTextArea(CopyOnSelectTextArea):
|
|
133
|
+
"""Read-only TextArea for displaying selectable content.
|
|
134
|
+
|
|
135
|
+
This widget provides a read-only text area that users can select text from.
|
|
136
|
+
Selected text is automatically copied to the clipboard. This is useful for
|
|
137
|
+
displaying content like chat messages or preview panes where users need
|
|
138
|
+
to be able to copy specific portions of text.
|
|
139
|
+
|
|
140
|
+
The widget is styled to look like a Static widget but with selection
|
|
141
|
+
capabilities.
|
|
142
|
+
|
|
143
|
+
Attributes:
|
|
144
|
+
show_line_numbers: Always False for this widget.
|
|
145
|
+
read_only: Always True for this widget.
|
|
146
|
+
"""
|
|
147
|
+
|
|
148
|
+
DEFAULT_CSS = """
|
|
149
|
+
SelectableTextArea {
|
|
150
|
+
background: transparent;
|
|
151
|
+
border: none;
|
|
152
|
+
padding: 0;
|
|
153
|
+
min-height: 1;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
SelectableTextArea:focus {
|
|
157
|
+
border: none;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
SelectableTextArea > .text-area--cursor-line {
|
|
161
|
+
background: transparent;
|
|
162
|
+
}
|
|
163
|
+
"""
|
|
164
|
+
|
|
165
|
+
def __init__(
|
|
166
|
+
self,
|
|
167
|
+
text: str = "",
|
|
168
|
+
*,
|
|
169
|
+
id: str | None = None,
|
|
170
|
+
classes: str | None = None,
|
|
171
|
+
show_copy_notification: bool = False,
|
|
172
|
+
) -> None:
|
|
173
|
+
"""Initialize the selectable text area.
|
|
174
|
+
|
|
175
|
+
Args:
|
|
176
|
+
text: Initial text content to display.
|
|
177
|
+
id: The CSS ID of the widget.
|
|
178
|
+
classes: CSS classes for the widget.
|
|
179
|
+
show_copy_notification: Whether to show notifications when copying.
|
|
180
|
+
"""
|
|
181
|
+
super().__init__(
|
|
182
|
+
text,
|
|
183
|
+
id=id,
|
|
184
|
+
classes=classes,
|
|
185
|
+
read_only=True,
|
|
186
|
+
show_line_numbers=False,
|
|
187
|
+
show_copy_notification=show_copy_notification,
|
|
188
|
+
)
|
|
189
|
+
|
|
190
|
+
def set_content(self, content: str) -> None:
|
|
191
|
+
"""Set the text content of the widget.
|
|
192
|
+
|
|
193
|
+
This is a convenience method that replaces all text in the widget.
|
|
194
|
+
|
|
195
|
+
Args:
|
|
196
|
+
content: The new text content to display.
|
|
197
|
+
"""
|
|
198
|
+
self.text = content
|
|
File without changes
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
"""Tag path validation utilities for CLI.
|
|
2
|
+
|
|
3
|
+
Validates tag paths against server constraints before submission to provide
|
|
4
|
+
immediate feedback in the TUI instead of server-side errors.
|
|
5
|
+
|
|
6
|
+
This mirrors the server-side validation in domain/tag_validation.py.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
import re
|
|
10
|
+
|
|
11
|
+
# Matches the database constraint: ^[a-z0-9_.]+$
|
|
12
|
+
TAG_PATH_PATTERN = re.compile(r"^[a-z0-9_.]+$")
|
|
13
|
+
|
|
14
|
+
# Maximum hierarchy depth (matches database constraint: nlevel(tag_path) <= 10)
|
|
15
|
+
MAX_TAG_DEPTH = 10
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def validate_tag_path(tag_path: str) -> tuple[bool, str | None]:
|
|
19
|
+
"""
|
|
20
|
+
Validate a tag path against database constraints.
|
|
21
|
+
|
|
22
|
+
Returns a tuple of (is_valid, error_message).
|
|
23
|
+
If valid, error_message is None.
|
|
24
|
+
|
|
25
|
+
Constraints:
|
|
26
|
+
- Only lowercase letters (a-z), numbers (0-9), underscores (_), and dots (.)
|
|
27
|
+
- Dots are level separators (e.g., 'marketing.email.newsletter')
|
|
28
|
+
- Maximum 10 levels deep
|
|
29
|
+
- Cannot be empty
|
|
30
|
+
- Cannot start or end with a dot
|
|
31
|
+
- Cannot have consecutive dots
|
|
32
|
+
|
|
33
|
+
Args:
|
|
34
|
+
tag_path: The tag path to validate (e.g., 'marketing.email')
|
|
35
|
+
|
|
36
|
+
Returns:
|
|
37
|
+
Tuple of (is_valid, error_message or None)
|
|
38
|
+
"""
|
|
39
|
+
if not tag_path:
|
|
40
|
+
return False, "Tag path cannot be empty"
|
|
41
|
+
|
|
42
|
+
# Check for uppercase letters (common mistake)
|
|
43
|
+
if tag_path != tag_path.lower():
|
|
44
|
+
suggestion = tag_path.lower()
|
|
45
|
+
return False, f"Must be lowercase. Try: {suggestion}"
|
|
46
|
+
|
|
47
|
+
# Check for hyphens (common mistake - suggest underscore)
|
|
48
|
+
if "-" in tag_path:
|
|
49
|
+
suggestion = tag_path.replace("-", "_")
|
|
50
|
+
return False, f"Use underscores, not hyphens. Try: {suggestion}"
|
|
51
|
+
|
|
52
|
+
# Check for spaces
|
|
53
|
+
if " " in tag_path:
|
|
54
|
+
suggestion = tag_path.replace(" ", "_")
|
|
55
|
+
return False, f"No spaces allowed. Try: {suggestion}"
|
|
56
|
+
|
|
57
|
+
# Check for consecutive dots
|
|
58
|
+
if ".." in tag_path:
|
|
59
|
+
return False, "Cannot contain consecutive dots (..)"
|
|
60
|
+
|
|
61
|
+
# Check for leading/trailing dots
|
|
62
|
+
if tag_path.startswith(".") or tag_path.endswith("."):
|
|
63
|
+
return False, "Cannot start or end with a dot"
|
|
64
|
+
|
|
65
|
+
# Check general format (must match ^[a-z0-9_.]+$)
|
|
66
|
+
if not TAG_PATH_PATTERN.match(tag_path):
|
|
67
|
+
return False, "Only lowercase letters, numbers, underscores, and dots allowed"
|
|
68
|
+
|
|
69
|
+
# Check depth (count dots + 1 = levels)
|
|
70
|
+
depth = tag_path.count(".") + 1
|
|
71
|
+
if depth > MAX_TAG_DEPTH:
|
|
72
|
+
return False, f"Too deep ({depth} levels). Maximum is {MAX_TAG_DEPTH}"
|
|
73
|
+
|
|
74
|
+
return True, None
|