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,37 @@
|
|
|
1
|
+
"""Presenter for knowledge document update metadata command output."""
|
|
2
|
+
|
|
3
|
+
import json
|
|
4
|
+
|
|
5
|
+
from rich.panel import Panel
|
|
6
|
+
from rich.table import Table
|
|
7
|
+
|
|
8
|
+
from cli.infrastructure.formatting.fields import format_datetime, format_uuid
|
|
9
|
+
from cli.infrastructure.output import OutputService
|
|
10
|
+
from alloy_runtime_types.dtos.knowledge import UpdateDocumentMetadataResponse
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def present_update_metadata_result(
|
|
14
|
+
response: UpdateDocumentMetadataResponse,
|
|
15
|
+
) -> None:
|
|
16
|
+
"""Present document metadata update result.
|
|
17
|
+
|
|
18
|
+
Args:
|
|
19
|
+
response: UpdateDocumentMetadataResponse from server
|
|
20
|
+
"""
|
|
21
|
+
output = OutputService.get()
|
|
22
|
+
|
|
23
|
+
output.success(f"Document '{response.title}' metadata updated")
|
|
24
|
+
|
|
25
|
+
table = Table(show_header=False, box=None, padding=(0, 1))
|
|
26
|
+
table.add_column("Field", style="dim")
|
|
27
|
+
table.add_column("Value")
|
|
28
|
+
|
|
29
|
+
table.add_row("ID", format_uuid(response.id, short=False))
|
|
30
|
+
table.add_row("Collection ID", format_uuid(response.collection_id, short=False))
|
|
31
|
+
table.add_row("Title", response.title)
|
|
32
|
+
if response.metadata:
|
|
33
|
+
table.add_row("Metadata", json.dumps(response.metadata, indent=2))
|
|
34
|
+
table.add_row("Updated At", format_datetime(response.updated_at))
|
|
35
|
+
|
|
36
|
+
panel = Panel(table, title="Document Updated", border_style="green")
|
|
37
|
+
output.console.print(panel)
|
|
File without changes
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
"""Knowledge recover command implementation."""
|
|
2
|
+
|
|
3
|
+
from typing import Optional
|
|
4
|
+
|
|
5
|
+
import typer
|
|
6
|
+
|
|
7
|
+
from cli.commands.knowledge.recover.presenter import present_recovery_result
|
|
8
|
+
from cli.infrastructure.command import async_command, authenticated_client
|
|
9
|
+
from alloy_runtime_types.dtos.knowledge import RecoverDocumentsRequest
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def knowledge_recover_command(
|
|
13
|
+
max_retries: Optional[int] = typer.Option(
|
|
14
|
+
None,
|
|
15
|
+
"-r",
|
|
16
|
+
"--max-retries",
|
|
17
|
+
min=1,
|
|
18
|
+
max=10,
|
|
19
|
+
help="Override max retry attempts (default: 3)",
|
|
20
|
+
),
|
|
21
|
+
) -> None:
|
|
22
|
+
"""Recover stuck documents.
|
|
23
|
+
|
|
24
|
+
Finds documents stuck in 'processing' or 'pending' state and either
|
|
25
|
+
re-queues them for processing or marks them as permanently failed.
|
|
26
|
+
|
|
27
|
+
Documents can get stuck when:
|
|
28
|
+
- Processing is interrupted (container crash, API timeout, etc.)
|
|
29
|
+
- Celery never picks up the task (message lost, worker unavailable)
|
|
30
|
+
|
|
31
|
+
Examples:
|
|
32
|
+
ai2 knowledge recover
|
|
33
|
+
ai2 kb recover --max-retries 5
|
|
34
|
+
"""
|
|
35
|
+
_execute_recover(max_retries=max_retries)
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
@async_command
|
|
39
|
+
async def _execute_recover(max_retries: Optional[int]) -> None:
|
|
40
|
+
"""Execute document recovery operation."""
|
|
41
|
+
request = RecoverDocumentsRequest(max_retries=max_retries) if max_retries else None
|
|
42
|
+
|
|
43
|
+
async with authenticated_client() as (_config, client):
|
|
44
|
+
response = await client.recover_documents(request)
|
|
45
|
+
|
|
46
|
+
present_recovery_result(response)
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
"""Presenter for document recovery output."""
|
|
2
|
+
|
|
3
|
+
from uuid import UUID
|
|
4
|
+
|
|
5
|
+
from rich.panel import Panel
|
|
6
|
+
from rich.table import Table
|
|
7
|
+
|
|
8
|
+
from cli.infrastructure.formatting.fields import format_uuid
|
|
9
|
+
from cli.infrastructure.output import OutputService
|
|
10
|
+
from alloy_runtime_types.dtos.knowledge import RecoverDocumentsResponse
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def present_recovery_result(response: RecoverDocumentsResponse) -> None:
|
|
14
|
+
"""Present document recovery results.
|
|
15
|
+
|
|
16
|
+
Args:
|
|
17
|
+
response: Recovery response from server
|
|
18
|
+
"""
|
|
19
|
+
output = OutputService.get()
|
|
20
|
+
|
|
21
|
+
total_affected = (
|
|
22
|
+
response.recovered_count + response.failed_count + response.requeued_count
|
|
23
|
+
)
|
|
24
|
+
|
|
25
|
+
if total_affected == 0:
|
|
26
|
+
output.info("No stuck documents found")
|
|
27
|
+
return
|
|
28
|
+
|
|
29
|
+
output.success("Document recovery completed")
|
|
30
|
+
|
|
31
|
+
# Build summary table
|
|
32
|
+
table = Table(show_header=False, box=None, padding=(0, 1))
|
|
33
|
+
table.add_column("Metric", style="dim")
|
|
34
|
+
table.add_column("Value")
|
|
35
|
+
|
|
36
|
+
table.add_row("Documents recovered", str(response.recovered_count))
|
|
37
|
+
table.add_row("Documents re-queued", str(response.requeued_count))
|
|
38
|
+
table.add_row("Documents permanently failed", str(response.failed_count))
|
|
39
|
+
|
|
40
|
+
panel = Panel(table, title="Recovery Summary", border_style="green")
|
|
41
|
+
output.console.print(panel)
|
|
42
|
+
|
|
43
|
+
# Show document IDs if any
|
|
44
|
+
if response.requeued_document_ids:
|
|
45
|
+
_present_document_ids(
|
|
46
|
+
output, "Re-queued for processing", response.requeued_document_ids
|
|
47
|
+
)
|
|
48
|
+
|
|
49
|
+
if response.recovered_document_ids:
|
|
50
|
+
_present_document_ids(
|
|
51
|
+
output, "Reset for retry", response.recovered_document_ids
|
|
52
|
+
)
|
|
53
|
+
|
|
54
|
+
if response.failed_document_ids:
|
|
55
|
+
_present_document_ids(
|
|
56
|
+
output, "Permanently failed", response.failed_document_ids, style="red"
|
|
57
|
+
)
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
def _present_document_ids(
|
|
61
|
+
output: OutputService,
|
|
62
|
+
title: str,
|
|
63
|
+
doc_ids: list[UUID],
|
|
64
|
+
style: str = "cyan",
|
|
65
|
+
max_display: int = 10,
|
|
66
|
+
) -> None:
|
|
67
|
+
"""Present a list of document IDs."""
|
|
68
|
+
if not doc_ids:
|
|
69
|
+
return
|
|
70
|
+
|
|
71
|
+
output.console.print(f"\n[{style}]{title}:[/{style}]")
|
|
72
|
+
|
|
73
|
+
displayed: list[UUID] = doc_ids[:max_display]
|
|
74
|
+
for doc_id in displayed:
|
|
75
|
+
output.console.print(f" {format_uuid(doc_id, short=False)}")
|
|
76
|
+
|
|
77
|
+
remaining = len(doc_ids) - max_display
|
|
78
|
+
if remaining > 0:
|
|
79
|
+
output.console.print(f" [dim]...and {remaining} more[/dim]")
|
|
File without changes
|
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
"""Knowledge search command implementation."""
|
|
2
|
+
|
|
3
|
+
import json
|
|
4
|
+
from typing import Any, Optional
|
|
5
|
+
from uuid import UUID
|
|
6
|
+
|
|
7
|
+
import typer
|
|
8
|
+
|
|
9
|
+
from cli.commands.flag_utils import validate_uuid
|
|
10
|
+
from cli.commands.knowledge.search.presenter import present_search_results
|
|
11
|
+
from cli.infrastructure.command import async_command, authenticated_client
|
|
12
|
+
from alloy_runtime_types.dtos.knowledge import SearchRequest
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def knowledge_search_command(
|
|
16
|
+
query: str = typer.Argument(..., help="Search query"),
|
|
17
|
+
collections: Optional[str] = typer.Option(
|
|
18
|
+
None,
|
|
19
|
+
"-C",
|
|
20
|
+
"--collections",
|
|
21
|
+
help="Comma-separated collection IDs to search",
|
|
22
|
+
),
|
|
23
|
+
collection_filter: Optional[str] = typer.Option(
|
|
24
|
+
None,
|
|
25
|
+
"-F",
|
|
26
|
+
"--collection-filter",
|
|
27
|
+
help="Filter by collection name pattern (e.g., 'Product*')",
|
|
28
|
+
),
|
|
29
|
+
tag_filter: Optional[str] = typer.Option(
|
|
30
|
+
None,
|
|
31
|
+
"-T",
|
|
32
|
+
"--tag-filter",
|
|
33
|
+
help="Filter by document tag pattern (e.g., 'engineering.*', 'docs')",
|
|
34
|
+
),
|
|
35
|
+
top_k: int = typer.Option(
|
|
36
|
+
5,
|
|
37
|
+
"-k",
|
|
38
|
+
"--top-k",
|
|
39
|
+
min=1,
|
|
40
|
+
max=20,
|
|
41
|
+
help="Number of results to return (1-20)",
|
|
42
|
+
),
|
|
43
|
+
hyde_agent: Optional[str] = typer.Option(
|
|
44
|
+
None,
|
|
45
|
+
"--hyde-agent",
|
|
46
|
+
help="Agent ID for HyDE hypothetical document generation",
|
|
47
|
+
),
|
|
48
|
+
hyde_template: Optional[str] = typer.Option(
|
|
49
|
+
None,
|
|
50
|
+
"--hyde-template",
|
|
51
|
+
help="Template ID for HyDE hypothetical document generation",
|
|
52
|
+
),
|
|
53
|
+
decomposition_agent: Optional[str] = typer.Option(
|
|
54
|
+
None,
|
|
55
|
+
"--decomposition-agent",
|
|
56
|
+
help="Agent ID for query decomposition",
|
|
57
|
+
),
|
|
58
|
+
decomposition_template: Optional[str] = typer.Option(
|
|
59
|
+
None,
|
|
60
|
+
"--decomposition-template",
|
|
61
|
+
help="Template ID for query decomposition",
|
|
62
|
+
),
|
|
63
|
+
rerank_instruction: Optional[str] = typer.Option(
|
|
64
|
+
None,
|
|
65
|
+
"-r",
|
|
66
|
+
"--rerank-instruction",
|
|
67
|
+
help="Custom instruction for reranking (e.g., 'Prioritize recent docs')",
|
|
68
|
+
),
|
|
69
|
+
min_confidence: Optional[float] = typer.Option(
|
|
70
|
+
None,
|
|
71
|
+
"--min-confidence",
|
|
72
|
+
min=0.0,
|
|
73
|
+
max=1.0,
|
|
74
|
+
help="Minimum confidence threshold (0.0-1.0)",
|
|
75
|
+
),
|
|
76
|
+
retrieval_k: Optional[int] = typer.Option(
|
|
77
|
+
None,
|
|
78
|
+
"--retrieval-k",
|
|
79
|
+
min=1,
|
|
80
|
+
max=1000,
|
|
81
|
+
help="Override initial candidate retrieval count",
|
|
82
|
+
),
|
|
83
|
+
metadata_filter: Optional[str] = typer.Option(
|
|
84
|
+
None,
|
|
85
|
+
"--metadata-filter",
|
|
86
|
+
help='Filter by chunk metadata as JSON (e.g., \'{"author": "John"}\')',
|
|
87
|
+
),
|
|
88
|
+
output: str = typer.Option(
|
|
89
|
+
"table",
|
|
90
|
+
"-o",
|
|
91
|
+
"--output",
|
|
92
|
+
help="Output format: 'table' or 'json'",
|
|
93
|
+
),
|
|
94
|
+
) -> None:
|
|
95
|
+
"""Search the knowledge base.
|
|
96
|
+
|
|
97
|
+
Performs semantic search across document collections using hybrid retrieval
|
|
98
|
+
(vector + full-text search). Opt in to HyDE or query decomposition by
|
|
99
|
+
providing the corresponding agent and template IDs.
|
|
100
|
+
|
|
101
|
+
Examples:
|
|
102
|
+
ai2 knowledge search "How do I authenticate?"
|
|
103
|
+
ai2 kb search "API documentation" --collection-filter "Product*"
|
|
104
|
+
ai2 kb search "complex query" \\
|
|
105
|
+
--hyde-agent <id> --hyde-template <id> \\
|
|
106
|
+
--decomposition-agent <id> --decomposition-template <id>
|
|
107
|
+
ai2 kb search "test query" --output json
|
|
108
|
+
ai2 kb search "query" --retrieval-k 100
|
|
109
|
+
ai2 kb search "query" --metadata-filter '{"author": "John"}'
|
|
110
|
+
"""
|
|
111
|
+
_execute_search_from_flags(
|
|
112
|
+
query=query,
|
|
113
|
+
collections=collections,
|
|
114
|
+
collection_filter=collection_filter,
|
|
115
|
+
tag_filter=tag_filter,
|
|
116
|
+
top_k=top_k,
|
|
117
|
+
hyde_agent=hyde_agent,
|
|
118
|
+
hyde_template=hyde_template,
|
|
119
|
+
decomposition_agent=decomposition_agent,
|
|
120
|
+
decomposition_template=decomposition_template,
|
|
121
|
+
rerank_instruction=rerank_instruction,
|
|
122
|
+
min_confidence=min_confidence,
|
|
123
|
+
retrieval_k=retrieval_k,
|
|
124
|
+
metadata_filter=metadata_filter,
|
|
125
|
+
output=output,
|
|
126
|
+
)
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
def _execute_search_from_flags(
|
|
130
|
+
query: str,
|
|
131
|
+
collections: Optional[str],
|
|
132
|
+
collection_filter: Optional[str],
|
|
133
|
+
tag_filter: Optional[str],
|
|
134
|
+
top_k: int,
|
|
135
|
+
hyde_agent: Optional[str],
|
|
136
|
+
hyde_template: Optional[str],
|
|
137
|
+
decomposition_agent: Optional[str],
|
|
138
|
+
decomposition_template: Optional[str],
|
|
139
|
+
rerank_instruction: Optional[str],
|
|
140
|
+
min_confidence: Optional[float],
|
|
141
|
+
retrieval_k: Optional[int],
|
|
142
|
+
metadata_filter: Optional[str],
|
|
143
|
+
output: str,
|
|
144
|
+
) -> None:
|
|
145
|
+
"""Validate flags and build search request."""
|
|
146
|
+
output_format = output.lower()
|
|
147
|
+
if output_format not in ("table", "json"):
|
|
148
|
+
raise typer.BadParameter(
|
|
149
|
+
f"Invalid output format '{output}'. Valid: table, json"
|
|
150
|
+
)
|
|
151
|
+
|
|
152
|
+
collection_ids: list[UUID] | None = None
|
|
153
|
+
if collections:
|
|
154
|
+
parsed_collection_ids: list[UUID] = []
|
|
155
|
+
for cid in collections.split(","):
|
|
156
|
+
cid = cid.strip()
|
|
157
|
+
if cid:
|
|
158
|
+
parsed_collection_ids.append(validate_uuid(cid, "collection"))
|
|
159
|
+
collection_ids = parsed_collection_ids
|
|
160
|
+
|
|
161
|
+
hyde_agent_id: UUID | None = None
|
|
162
|
+
hyde_template_id: UUID | None = None
|
|
163
|
+
decomposition_agent_id: UUID | None = None
|
|
164
|
+
decomposition_template_id: UUID | None = None
|
|
165
|
+
|
|
166
|
+
if hyde_agent:
|
|
167
|
+
hyde_agent_id = validate_uuid(hyde_agent, "hyde-agent")
|
|
168
|
+
if hyde_template:
|
|
169
|
+
hyde_template_id = validate_uuid(hyde_template, "hyde-template")
|
|
170
|
+
if decomposition_agent:
|
|
171
|
+
decomposition_agent_id = validate_uuid(
|
|
172
|
+
decomposition_agent, "decomposition-agent"
|
|
173
|
+
)
|
|
174
|
+
if decomposition_template:
|
|
175
|
+
decomposition_template_id = validate_uuid(
|
|
176
|
+
decomposition_template, "decomposition-template"
|
|
177
|
+
)
|
|
178
|
+
|
|
179
|
+
parsed_metadata_filter: dict[str, Any] | None = None
|
|
180
|
+
if metadata_filter:
|
|
181
|
+
try:
|
|
182
|
+
parsed_metadata_filter = json.loads(metadata_filter)
|
|
183
|
+
if not isinstance(parsed_metadata_filter, dict):
|
|
184
|
+
raise typer.BadParameter(
|
|
185
|
+
"--metadata-filter must be a JSON object, not "
|
|
186
|
+
f"{type(parsed_metadata_filter).__name__}"
|
|
187
|
+
)
|
|
188
|
+
except json.JSONDecodeError as e:
|
|
189
|
+
raise typer.BadParameter(f"Invalid JSON in --metadata-filter: {e}")
|
|
190
|
+
|
|
191
|
+
request = SearchRequest(
|
|
192
|
+
query=query,
|
|
193
|
+
collection_ids=collection_ids,
|
|
194
|
+
collection_filter=collection_filter,
|
|
195
|
+
top_k=top_k,
|
|
196
|
+
metadata_filter=parsed_metadata_filter,
|
|
197
|
+
tag_filter=tag_filter,
|
|
198
|
+
source_date_from=None,
|
|
199
|
+
source_date_to=None,
|
|
200
|
+
rerank_instruction=rerank_instruction,
|
|
201
|
+
retrieval_k=retrieval_k,
|
|
202
|
+
min_retrieval_confidence=min_confidence,
|
|
203
|
+
hyde_agent_id=hyde_agent_id,
|
|
204
|
+
hyde_template_id=hyde_template_id,
|
|
205
|
+
decomposition_agent_id=decomposition_agent_id,
|
|
206
|
+
decomposition_template_id=decomposition_template_id,
|
|
207
|
+
)
|
|
208
|
+
|
|
209
|
+
_execute_search(request, output_format)
|
|
210
|
+
|
|
211
|
+
|
|
212
|
+
@async_command
|
|
213
|
+
async def _execute_search(request: SearchRequest, output_format: str) -> None:
|
|
214
|
+
"""Execute knowledge base search."""
|
|
215
|
+
async with authenticated_client() as (_config, client):
|
|
216
|
+
response = await client.search_knowledge(request)
|
|
217
|
+
|
|
218
|
+
present_search_results(response, output_format)
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
"""Presenter for knowledge search output."""
|
|
2
|
+
|
|
3
|
+
import json
|
|
4
|
+
|
|
5
|
+
from rich.panel import Panel
|
|
6
|
+
from rich.table import Table
|
|
7
|
+
|
|
8
|
+
from cli.infrastructure.output import OutputService
|
|
9
|
+
from alloy_runtime_types.dtos.knowledge import SearchResponse
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def present_search_results(response: SearchResponse, output_format: str) -> None:
|
|
13
|
+
"""Present search results in specified format.
|
|
14
|
+
|
|
15
|
+
Args:
|
|
16
|
+
response: Search response from server
|
|
17
|
+
output_format: Output format ('table' or 'json')
|
|
18
|
+
"""
|
|
19
|
+
if output_format == "json":
|
|
20
|
+
_present_json_results(response)
|
|
21
|
+
else:
|
|
22
|
+
_present_table_results(response)
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def _present_table_results(response: SearchResponse) -> None:
|
|
26
|
+
"""Present search results as formatted table."""
|
|
27
|
+
output = OutputService.get()
|
|
28
|
+
|
|
29
|
+
if not response.results:
|
|
30
|
+
output.info(f"No results found for: {response.query}")
|
|
31
|
+
return
|
|
32
|
+
|
|
33
|
+
# Build summary panel
|
|
34
|
+
summary_table = Table(show_header=False, box=None, padding=(0, 1))
|
|
35
|
+
summary_table.add_column("Field", style="dim")
|
|
36
|
+
summary_table.add_column("Value")
|
|
37
|
+
|
|
38
|
+
summary_table.add_row("Query", response.query)
|
|
39
|
+
summary_table.add_row("Results", str(len(response.results)))
|
|
40
|
+
summary_table.add_row("Candidates evaluated", str(response.total_candidates))
|
|
41
|
+
summary_table.add_row("Avg relevance", f"{response.avg_relevance_score:.3f}")
|
|
42
|
+
|
|
43
|
+
# Add timing breakdown
|
|
44
|
+
timing_parts: list[str] = []
|
|
45
|
+
for key, value in response.timing_ms.items():
|
|
46
|
+
timing_parts.append(f"{key}={value}ms")
|
|
47
|
+
if timing_parts:
|
|
48
|
+
summary_table.add_row("Timing", ", ".join(timing_parts))
|
|
49
|
+
|
|
50
|
+
summary_panel = Panel(summary_table, title="Search Summary", border_style="blue")
|
|
51
|
+
output.console.print(summary_panel)
|
|
52
|
+
|
|
53
|
+
# Show transformations if applied
|
|
54
|
+
if response.transformations_applied:
|
|
55
|
+
output.console.print(
|
|
56
|
+
f"\n[dim]Transformations applied:[/dim] "
|
|
57
|
+
f"[cyan]{', '.join(response.transformations_applied)}[/cyan]"
|
|
58
|
+
)
|
|
59
|
+
|
|
60
|
+
if response.sub_queries_used:
|
|
61
|
+
output.console.print("[dim]Sub-queries used:[/dim]")
|
|
62
|
+
for i, sq in enumerate(response.sub_queries_used, 1):
|
|
63
|
+
output.console.print(f" [cyan]{i}.[/cyan] {sq}")
|
|
64
|
+
|
|
65
|
+
# Build results table
|
|
66
|
+
output.console.print()
|
|
67
|
+
results_table = Table(title="Results", show_header=True, header_style="bold")
|
|
68
|
+
results_table.add_column("#", style="dim", width=3, justify="right")
|
|
69
|
+
results_table.add_column("Document", style="white", no_wrap=True, max_width=30)
|
|
70
|
+
results_table.add_column("Score", style="cyan", width=7, justify="right")
|
|
71
|
+
results_table.add_column("Content", style="dim", overflow="ellipsis")
|
|
72
|
+
|
|
73
|
+
low_confidence_results: list[int] = []
|
|
74
|
+
for i, result in enumerate(response.results, 1):
|
|
75
|
+
# Truncate content preview
|
|
76
|
+
content_preview = result.content.replace("\n", " ")[:100]
|
|
77
|
+
if len(result.content) > 100:
|
|
78
|
+
content_preview += "..."
|
|
79
|
+
|
|
80
|
+
# Mark low confidence results
|
|
81
|
+
score_display = f"{result.relevance_score:.3f}"
|
|
82
|
+
if result.low_confidence:
|
|
83
|
+
score_display = f"[yellow]{score_display}*[/yellow]"
|
|
84
|
+
low_confidence_results.append(i)
|
|
85
|
+
|
|
86
|
+
results_table.add_row(
|
|
87
|
+
str(i),
|
|
88
|
+
result.document_title,
|
|
89
|
+
score_display,
|
|
90
|
+
content_preview,
|
|
91
|
+
)
|
|
92
|
+
|
|
93
|
+
output.console.print(results_table)
|
|
94
|
+
|
|
95
|
+
# Show low confidence warning
|
|
96
|
+
if low_confidence_results:
|
|
97
|
+
output.console.print(
|
|
98
|
+
f"\n[yellow]* Results {', '.join(map(str, low_confidence_results))} "
|
|
99
|
+
"are below the confidence threshold[/yellow]"
|
|
100
|
+
)
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
def _present_json_results(response: SearchResponse) -> None:
|
|
104
|
+
"""Present search results as JSON."""
|
|
105
|
+
output = OutputService.get()
|
|
106
|
+
|
|
107
|
+
# Convert response to JSON-serializable dict
|
|
108
|
+
data = response.model_dump(mode="json")
|
|
109
|
+
|
|
110
|
+
# Pretty-print JSON
|
|
111
|
+
output.console.print_json(json.dumps(data))
|
|
File without changes
|
|
File without changes
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
"""Knowledge synthesis create command implementation."""
|
|
2
|
+
|
|
3
|
+
from typing import Annotated, Optional
|
|
4
|
+
from uuid import UUID
|
|
5
|
+
|
|
6
|
+
import typer
|
|
7
|
+
|
|
8
|
+
from cli.commands.flag_utils import validate_uuid
|
|
9
|
+
from cli.commands.knowledge.synthesis.create.presenter import (
|
|
10
|
+
present_synthesis_create_success,
|
|
11
|
+
)
|
|
12
|
+
from cli.infrastructure.command import async_command, authenticated_client
|
|
13
|
+
from cli.infrastructure.kv_parser import parse_kv_pairs
|
|
14
|
+
from alloy_runtime_types.dtos.knowledge import CreateSynthesisRequest
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def knowledge_synthesis_create_command(
|
|
18
|
+
topic: str = typer.Option(
|
|
19
|
+
...,
|
|
20
|
+
"-t",
|
|
21
|
+
"--topic",
|
|
22
|
+
help="Topic to research and synthesize",
|
|
23
|
+
),
|
|
24
|
+
collections: str = typer.Option(
|
|
25
|
+
...,
|
|
26
|
+
"-C",
|
|
27
|
+
"--collections",
|
|
28
|
+
help="Comma-separated collection UUIDs to include",
|
|
29
|
+
),
|
|
30
|
+
agent: str = typer.Option(
|
|
31
|
+
...,
|
|
32
|
+
"-a",
|
|
33
|
+
"--agent",
|
|
34
|
+
help="Synthesizer agent UUID (must have rag_search tool)",
|
|
35
|
+
),
|
|
36
|
+
template: str = typer.Option(
|
|
37
|
+
...,
|
|
38
|
+
"-T",
|
|
39
|
+
"--template",
|
|
40
|
+
help="Synthesis template UUID (receives {{ topic }} variable)",
|
|
41
|
+
),
|
|
42
|
+
title: Optional[str] = typer.Option(
|
|
43
|
+
None,
|
|
44
|
+
"--title",
|
|
45
|
+
help="Title for the synthesis (defaults to topic)",
|
|
46
|
+
),
|
|
47
|
+
metadata: Annotated[
|
|
48
|
+
Optional[list[str]],
|
|
49
|
+
typer.Option(
|
|
50
|
+
"-m",
|
|
51
|
+
"--metadata",
|
|
52
|
+
help="Metadata (key=value or key:=json). Repeatable.",
|
|
53
|
+
),
|
|
54
|
+
] = None,
|
|
55
|
+
) -> None:
|
|
56
|
+
"""Create a corpus-level synthesis.
|
|
57
|
+
|
|
58
|
+
A synthesis uses an agent with RAG tools to research a topic across
|
|
59
|
+
specified collections and generate a comprehensive response. The
|
|
60
|
+
synthesis is processed asynchronously - poll the synthesis status
|
|
61
|
+
to check for completion.
|
|
62
|
+
|
|
63
|
+
Examples:
|
|
64
|
+
ai2 knowledge synthesis create -t "API authentication methods" \\
|
|
65
|
+
-C <collection-uuid> -a <agent-uuid> -T <template-uuid>
|
|
66
|
+
|
|
67
|
+
ai2 kb synthesis create -t "Product roadmap summary" \\
|
|
68
|
+
-C <col1>,<col2> -a <agent> -T <template> --title "Q1 Roadmap"
|
|
69
|
+
|
|
70
|
+
ai2 kb synthesis create -t "Security best practices" \\
|
|
71
|
+
-C <collection> -a <agent> -T <template> -m priority=high
|
|
72
|
+
"""
|
|
73
|
+
_execute_create_from_flags(
|
|
74
|
+
topic=topic,
|
|
75
|
+
collections=collections,
|
|
76
|
+
agent=agent,
|
|
77
|
+
template=template,
|
|
78
|
+
title=title,
|
|
79
|
+
metadata=metadata,
|
|
80
|
+
)
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
def _execute_create_from_flags(
|
|
84
|
+
topic: str,
|
|
85
|
+
collections: str,
|
|
86
|
+
agent: str,
|
|
87
|
+
template: str,
|
|
88
|
+
title: Optional[str],
|
|
89
|
+
metadata: Optional[list[str]],
|
|
90
|
+
) -> None:
|
|
91
|
+
"""Build and execute synthesis creation from command flags."""
|
|
92
|
+
# Parse collection IDs
|
|
93
|
+
collection_ids: list[UUID] = []
|
|
94
|
+
for cid in collections.split(","):
|
|
95
|
+
cid = cid.strip()
|
|
96
|
+
if cid:
|
|
97
|
+
collection_ids.append(validate_uuid(cid, "collection"))
|
|
98
|
+
|
|
99
|
+
if not collection_ids:
|
|
100
|
+
raise typer.BadParameter("At least one collection UUID is required")
|
|
101
|
+
|
|
102
|
+
# Validate agent and template UUIDs
|
|
103
|
+
agent_id = validate_uuid(agent, "agent")
|
|
104
|
+
template_id = validate_uuid(template, "template")
|
|
105
|
+
|
|
106
|
+
# Parse metadata (httpie style)
|
|
107
|
+
parsed_metadata = parse_kv_pairs(metadata) if metadata else None
|
|
108
|
+
|
|
109
|
+
request = CreateSynthesisRequest(
|
|
110
|
+
topic=topic,
|
|
111
|
+
collection_ids=collection_ids,
|
|
112
|
+
synthesizer_agent_id=agent_id,
|
|
113
|
+
synthesis_template_id=template_id,
|
|
114
|
+
title=title,
|
|
115
|
+
metadata=parsed_metadata,
|
|
116
|
+
)
|
|
117
|
+
|
|
118
|
+
_execute_create(request)
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
@async_command
|
|
122
|
+
async def _execute_create(request: CreateSynthesisRequest) -> None:
|
|
123
|
+
"""Execute the synthesis creation with the given request."""
|
|
124
|
+
async with authenticated_client() as (_config, client):
|
|
125
|
+
response = await client.create_synthesis(request)
|
|
126
|
+
|
|
127
|
+
present_synthesis_create_success(response)
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
"""Presenter for synthesis creation output."""
|
|
2
|
+
|
|
3
|
+
from rich.panel import Panel
|
|
4
|
+
from rich.table import Table
|
|
5
|
+
|
|
6
|
+
from cli.infrastructure.formatting.fields import format_uuid
|
|
7
|
+
from cli.infrastructure.output import OutputService
|
|
8
|
+
from alloy_runtime_types.dtos.knowledge import CreateSynthesisResponse
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def present_synthesis_create_success(response: CreateSynthesisResponse) -> None:
|
|
12
|
+
"""Present successful synthesis creation.
|
|
13
|
+
|
|
14
|
+
Args:
|
|
15
|
+
response: Synthesis creation response from server
|
|
16
|
+
"""
|
|
17
|
+
output = OutputService.get()
|
|
18
|
+
|
|
19
|
+
output.success("Synthesis queued for generation")
|
|
20
|
+
|
|
21
|
+
# Build a simple table for entity display
|
|
22
|
+
table = Table(show_header=False, box=None, padding=(0, 1))
|
|
23
|
+
table.add_column("Field", style="dim")
|
|
24
|
+
table.add_column("Value")
|
|
25
|
+
|
|
26
|
+
table.add_row("Synthesis ID", format_uuid(response.synthesis_id, short=False))
|
|
27
|
+
table.add_row("Status", f"[yellow]{response.status}[/yellow]")
|
|
28
|
+
table.add_row("Message", response.message)
|
|
29
|
+
|
|
30
|
+
panel = Panel(table, title="Synthesis Created", border_style="green")
|
|
31
|
+
output.console.print(panel)
|
|
32
|
+
|
|
33
|
+
output.info(f"Poll status with: ai2 kb synthesis get {response.synthesis_id}")
|
|
File without changes
|