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,222 @@
|
|
|
1
|
+
"""Knowledge document ingest command implementation."""
|
|
2
|
+
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
from typing import Annotated, Optional
|
|
5
|
+
from uuid import UUID
|
|
6
|
+
|
|
7
|
+
import typer
|
|
8
|
+
|
|
9
|
+
from cli.commands.flag_utils import (
|
|
10
|
+
require_one_of,
|
|
11
|
+
validate_document_type,
|
|
12
|
+
validate_source_type,
|
|
13
|
+
)
|
|
14
|
+
from cli.commands.knowledge.documents.ingest.presenter import present_ingest_success
|
|
15
|
+
from cli.infrastructure.command import async_command, authenticated_client
|
|
16
|
+
from cli.infrastructure.file_content import FileContentError, resolve_content
|
|
17
|
+
from cli.infrastructure.kv_parser import parse_kv_pairs
|
|
18
|
+
from alloy_runtime_types.dtos.knowledge import IngestDocumentRequest
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def knowledge_documents_ingest_command(
|
|
22
|
+
collection: UUID = typer.Option(
|
|
23
|
+
...,
|
|
24
|
+
"-C",
|
|
25
|
+
"--collection",
|
|
26
|
+
help="Target collection UUID",
|
|
27
|
+
),
|
|
28
|
+
title: str = typer.Option(
|
|
29
|
+
...,
|
|
30
|
+
"-t",
|
|
31
|
+
"--title",
|
|
32
|
+
help="Document title",
|
|
33
|
+
),
|
|
34
|
+
file: Optional[Path] = typer.Option(
|
|
35
|
+
None,
|
|
36
|
+
"-f",
|
|
37
|
+
"--file",
|
|
38
|
+
help="Path to document file",
|
|
39
|
+
exists=True,
|
|
40
|
+
readable=True,
|
|
41
|
+
),
|
|
42
|
+
content: Optional[str] = typer.Option(
|
|
43
|
+
None,
|
|
44
|
+
"-c",
|
|
45
|
+
"--content",
|
|
46
|
+
help="Document content (or @file, or @- for stdin)",
|
|
47
|
+
),
|
|
48
|
+
question_agent: Optional[UUID] = typer.Option(
|
|
49
|
+
None,
|
|
50
|
+
"-Q",
|
|
51
|
+
"--question-agent",
|
|
52
|
+
help="Agent UUID for question generation (required unless --skip-question-gen)",
|
|
53
|
+
),
|
|
54
|
+
question_template: Optional[UUID] = typer.Option(
|
|
55
|
+
None,
|
|
56
|
+
"-T",
|
|
57
|
+
"--question-template",
|
|
58
|
+
help="Template UUID for question generation (required unless --skip-question-gen)",
|
|
59
|
+
),
|
|
60
|
+
source_type: str = typer.Option(
|
|
61
|
+
"upload",
|
|
62
|
+
"-s",
|
|
63
|
+
"--source-type",
|
|
64
|
+
help="Source type: upload, paste, api_import, url_scrape",
|
|
65
|
+
),
|
|
66
|
+
metadata: Annotated[
|
|
67
|
+
Optional[list[str]],
|
|
68
|
+
typer.Option(
|
|
69
|
+
"-m",
|
|
70
|
+
"--metadata",
|
|
71
|
+
help="Metadata (key=value or key:=json). Repeatable.",
|
|
72
|
+
),
|
|
73
|
+
] = None,
|
|
74
|
+
tag: Annotated[
|
|
75
|
+
Optional[list[str]],
|
|
76
|
+
typer.Option(
|
|
77
|
+
"--tag",
|
|
78
|
+
help="Hierarchical tag path (e.g., 'engineering.backend'). Repeatable.",
|
|
79
|
+
),
|
|
80
|
+
] = None,
|
|
81
|
+
document_type: str = typer.Option(
|
|
82
|
+
"document",
|
|
83
|
+
"-D",
|
|
84
|
+
"--document-type",
|
|
85
|
+
help="Document type for preprocessing: transcript, sales_call, markdown, document",
|
|
86
|
+
),
|
|
87
|
+
external_id: Optional[str] = typer.Option(
|
|
88
|
+
None,
|
|
89
|
+
"-e",
|
|
90
|
+
"--external-id",
|
|
91
|
+
help="Caller-provided ID for idempotency and correlation (unique per org)",
|
|
92
|
+
),
|
|
93
|
+
dry_run: bool = typer.Option(
|
|
94
|
+
False,
|
|
95
|
+
"--dry-run",
|
|
96
|
+
help="Only preprocess - don't persist. Useful for testing preprocessing.",
|
|
97
|
+
),
|
|
98
|
+
skip_question_gen: bool = typer.Option(
|
|
99
|
+
False,
|
|
100
|
+
"--skip-question-gen",
|
|
101
|
+
help="Skip question generation during ingestion. Makes -Q and -T optional.",
|
|
102
|
+
),
|
|
103
|
+
) -> None:
|
|
104
|
+
"""Ingest a document into a knowledge collection.
|
|
105
|
+
|
|
106
|
+
Document content can be provided via:
|
|
107
|
+
- --file: Read from a file path
|
|
108
|
+
- --content: Direct text, @file reference, or @- for stdin
|
|
109
|
+
|
|
110
|
+
Document types control preprocessing:
|
|
111
|
+
- transcript: Podcasts/videos/meetings with timestamps and natural speech
|
|
112
|
+
- sales_call: Sales/customer calls with speaker labels
|
|
113
|
+
- markdown: Markdown-formatted content
|
|
114
|
+
- document: General text documents (default)
|
|
115
|
+
|
|
116
|
+
Examples:
|
|
117
|
+
ai2 knowledge documents ingest -C <uuid> -t "API Docs" -f ./api.md -Q <agent> -T <template>
|
|
118
|
+
ai2 kb documents ingest -C <uuid> -t "Notes" -c "My content" -Q <agent> -T <template>
|
|
119
|
+
cat doc.txt | ai2 kb documents ingest -C <uuid> -t "Doc" -c @- -Q <agent> -T <template>
|
|
120
|
+
ai2 kb documents ingest -C <uuid> -t "Doc" -c @notes.md -Q <agent> -T <template> -m author=John
|
|
121
|
+
ai2 kb documents ingest -C <uuid> -t "Meeting" -f meeting.vtt -D transcript -Q <agent> -T <template>
|
|
122
|
+
ai2 kb documents ingest -C <uuid> -t "Test" -f doc.md --dry-run -Q <agent> -T <template>
|
|
123
|
+
"""
|
|
124
|
+
require_one_of(("--file", file), ("--content", content))
|
|
125
|
+
|
|
126
|
+
_execute_ingest_from_flags(
|
|
127
|
+
collection=collection,
|
|
128
|
+
title=title,
|
|
129
|
+
file=file,
|
|
130
|
+
content=content,
|
|
131
|
+
question_agent=question_agent,
|
|
132
|
+
question_template=question_template,
|
|
133
|
+
source_type=source_type,
|
|
134
|
+
metadata=metadata,
|
|
135
|
+
tag=tag,
|
|
136
|
+
document_type=document_type,
|
|
137
|
+
external_id=external_id,
|
|
138
|
+
dry_run=dry_run,
|
|
139
|
+
skip_question_gen=skip_question_gen,
|
|
140
|
+
)
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
def _execute_ingest_from_flags(
|
|
144
|
+
collection: UUID,
|
|
145
|
+
title: str,
|
|
146
|
+
file: Optional[Path],
|
|
147
|
+
content: Optional[str],
|
|
148
|
+
question_agent: Optional[UUID],
|
|
149
|
+
question_template: Optional[UUID],
|
|
150
|
+
source_type: str,
|
|
151
|
+
metadata: Optional[list[str]],
|
|
152
|
+
tag: Optional[list[str]],
|
|
153
|
+
document_type: str,
|
|
154
|
+
external_id: Optional[str],
|
|
155
|
+
dry_run: bool,
|
|
156
|
+
skip_question_gen: bool,
|
|
157
|
+
) -> None:
|
|
158
|
+
"""Build and execute document ingestion from command flags."""
|
|
159
|
+
# Validate source type
|
|
160
|
+
validated_source_type = validate_source_type(source_type)
|
|
161
|
+
|
|
162
|
+
# Validate document type
|
|
163
|
+
validated_document_type = validate_document_type(document_type)
|
|
164
|
+
|
|
165
|
+
# Resolve content from file or inline
|
|
166
|
+
if file:
|
|
167
|
+
if not file.is_file():
|
|
168
|
+
raise typer.BadParameter(f"Not a file: {file}")
|
|
169
|
+
try:
|
|
170
|
+
document_content = file.read_text(encoding="utf-8")
|
|
171
|
+
except UnicodeDecodeError:
|
|
172
|
+
raise typer.BadParameter(
|
|
173
|
+
f"File is not valid UTF-8 text: {file}. Only text files are supported."
|
|
174
|
+
)
|
|
175
|
+
else:
|
|
176
|
+
try:
|
|
177
|
+
document_content = resolve_content(content) or ""
|
|
178
|
+
except FileContentError as e:
|
|
179
|
+
raise typer.BadParameter(str(e))
|
|
180
|
+
|
|
181
|
+
if not document_content.strip():
|
|
182
|
+
raise typer.BadParameter("Document content cannot be empty")
|
|
183
|
+
|
|
184
|
+
# Validate question generation requirements
|
|
185
|
+
if not skip_question_gen:
|
|
186
|
+
if question_agent is None:
|
|
187
|
+
raise typer.BadParameter(
|
|
188
|
+
"--question-agent (-Q) is required unless --skip-question-gen is set"
|
|
189
|
+
)
|
|
190
|
+
if question_template is None:
|
|
191
|
+
raise typer.BadParameter(
|
|
192
|
+
"--question-template (-T) is required unless --skip-question-gen is set"
|
|
193
|
+
)
|
|
194
|
+
|
|
195
|
+
# Parse metadata (httpie style)
|
|
196
|
+
parsed_metadata = parse_kv_pairs(metadata) if metadata else None
|
|
197
|
+
|
|
198
|
+
request = IngestDocumentRequest(
|
|
199
|
+
collection_id=collection,
|
|
200
|
+
title=title,
|
|
201
|
+
content=document_content,
|
|
202
|
+
question_gen_agent_id=question_agent,
|
|
203
|
+
question_gen_template_id=question_template,
|
|
204
|
+
source_type=validated_source_type,
|
|
205
|
+
document_type=validated_document_type, # type: ignore[arg-type]
|
|
206
|
+
metadata=parsed_metadata,
|
|
207
|
+
tags=tag,
|
|
208
|
+
external_id=external_id,
|
|
209
|
+
dry_run=dry_run,
|
|
210
|
+
skip_question_generation=skip_question_gen,
|
|
211
|
+
)
|
|
212
|
+
|
|
213
|
+
_execute_ingest(request)
|
|
214
|
+
|
|
215
|
+
|
|
216
|
+
@async_command
|
|
217
|
+
async def _execute_ingest(request: IngestDocumentRequest) -> None:
|
|
218
|
+
"""Execute the document ingestion with the given request."""
|
|
219
|
+
async with authenticated_client() as (_config, client):
|
|
220
|
+
response = await client.ingest_document(request)
|
|
221
|
+
|
|
222
|
+
present_ingest_success(response)
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
"""Presenter for document ingest 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 IngestDocumentResponse
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def present_ingest_success(response: IngestDocumentResponse) -> None:
|
|
12
|
+
"""Present successful document ingestion (queued for processing).
|
|
13
|
+
|
|
14
|
+
Args:
|
|
15
|
+
response: Document ingestion response from server
|
|
16
|
+
"""
|
|
17
|
+
output = OutputService.get()
|
|
18
|
+
|
|
19
|
+
if response.document_id is None:
|
|
20
|
+
output.info("Dry run complete - document not persisted")
|
|
21
|
+
else:
|
|
22
|
+
output.info("Document queued for processing")
|
|
23
|
+
|
|
24
|
+
table = Table(show_header=False, box=None, padding=(0, 1))
|
|
25
|
+
table.add_column("Field", style="dim")
|
|
26
|
+
table.add_column("Value")
|
|
27
|
+
|
|
28
|
+
if response.document_id is not None:
|
|
29
|
+
table.add_row("Document ID", format_uuid(response.document_id, short=False))
|
|
30
|
+
table.add_row("Title", response.title)
|
|
31
|
+
table.add_row("Status", f"[yellow]{response.status}[/yellow]")
|
|
32
|
+
|
|
33
|
+
if response.document_id is not None:
|
|
34
|
+
table.add_row("", "")
|
|
35
|
+
table.add_row(
|
|
36
|
+
"[dim]Next Step[/dim]",
|
|
37
|
+
"[dim]Poll with: ai2 knowledge documents get <id>[/dim]",
|
|
38
|
+
)
|
|
39
|
+
|
|
40
|
+
panel = Panel(table, title=f"Document: {response.title}", border_style="blue")
|
|
41
|
+
output.console.print(panel)
|
|
File without changes
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
"""Knowledge documents list command implementation."""
|
|
2
|
+
|
|
3
|
+
import typer
|
|
4
|
+
|
|
5
|
+
from cli.commands.knowledge.documents.list.presenter import present_documents_list
|
|
6
|
+
from cli.infrastructure.command import async_command, authenticated_client
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def knowledge_documents_list_command(
|
|
10
|
+
collection: str | None = typer.Option(
|
|
11
|
+
None,
|
|
12
|
+
"-C",
|
|
13
|
+
"--collection",
|
|
14
|
+
help="Filter by collection ID or name",
|
|
15
|
+
),
|
|
16
|
+
status: str | None = typer.Option(
|
|
17
|
+
None,
|
|
18
|
+
"-s",
|
|
19
|
+
"--status",
|
|
20
|
+
help="Filter by status: pending|processing|completed|failed",
|
|
21
|
+
),
|
|
22
|
+
limit: int = typer.Option(
|
|
23
|
+
50,
|
|
24
|
+
"-l",
|
|
25
|
+
"--limit",
|
|
26
|
+
min=1,
|
|
27
|
+
max=100,
|
|
28
|
+
help="Max results",
|
|
29
|
+
),
|
|
30
|
+
offset: int = typer.Option(
|
|
31
|
+
0,
|
|
32
|
+
"--offset",
|
|
33
|
+
min=0,
|
|
34
|
+
help="Skip N results",
|
|
35
|
+
),
|
|
36
|
+
) -> None:
|
|
37
|
+
"""List documents in the knowledge base.
|
|
38
|
+
|
|
39
|
+
Examples:
|
|
40
|
+
ai2 knowledge documents list
|
|
41
|
+
ai2 kb documents list -C my-collection
|
|
42
|
+
ai2 kb documents list -s completed -l 20
|
|
43
|
+
ai2 kb documents list --status failed
|
|
44
|
+
"""
|
|
45
|
+
_execute_list(
|
|
46
|
+
collection_id=collection,
|
|
47
|
+
processing_status=status,
|
|
48
|
+
limit=limit,
|
|
49
|
+
offset=offset,
|
|
50
|
+
)
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
@async_command
|
|
54
|
+
async def _execute_list(
|
|
55
|
+
collection_id: str | None,
|
|
56
|
+
processing_status: str | None,
|
|
57
|
+
limit: int,
|
|
58
|
+
offset: int,
|
|
59
|
+
) -> None:
|
|
60
|
+
"""Execute list documents operation."""
|
|
61
|
+
async with authenticated_client() as (_config, client):
|
|
62
|
+
response = await client.list_documents(
|
|
63
|
+
limit=limit,
|
|
64
|
+
offset=offset,
|
|
65
|
+
collection_id=collection_id,
|
|
66
|
+
processing_status=processing_status,
|
|
67
|
+
)
|
|
68
|
+
|
|
69
|
+
present_documents_list(response)
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
"""Presenter for knowledge documents list command output."""
|
|
2
|
+
|
|
3
|
+
from alloy_runtime_types.dtos.knowledge import ListDocumentsResponse
|
|
4
|
+
|
|
5
|
+
from cli.infrastructure.output import OutputService
|
|
6
|
+
from cli.infrastructure.renderers.list_renderer import ColumnConfig
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def _format_status(status: str) -> str:
|
|
10
|
+
"""Format processing status with color."""
|
|
11
|
+
status_colors = {
|
|
12
|
+
"completed": "[green]completed[/]",
|
|
13
|
+
"processing": "[yellow]processing[/]",
|
|
14
|
+
"pending": "[blue]pending[/]",
|
|
15
|
+
"failed": "[red]failed[/]",
|
|
16
|
+
}
|
|
17
|
+
return status_colors.get(status, status)
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def present_documents_list(response: ListDocumentsResponse) -> None:
|
|
21
|
+
"""Present list of documents with Rich table formatting.
|
|
22
|
+
|
|
23
|
+
Args:
|
|
24
|
+
response: List documents response from server
|
|
25
|
+
"""
|
|
26
|
+
output = OutputService.get()
|
|
27
|
+
|
|
28
|
+
if not response.documents:
|
|
29
|
+
output.info("No documents found")
|
|
30
|
+
return
|
|
31
|
+
|
|
32
|
+
columns = [
|
|
33
|
+
ColumnConfig(
|
|
34
|
+
source_field="id",
|
|
35
|
+
header_label="ID",
|
|
36
|
+
compact_line=1,
|
|
37
|
+
compact_style="cyan",
|
|
38
|
+
),
|
|
39
|
+
ColumnConfig(
|
|
40
|
+
source_field="processing_status",
|
|
41
|
+
header_label="Status",
|
|
42
|
+
formatter=_format_status,
|
|
43
|
+
compact_line=1,
|
|
44
|
+
),
|
|
45
|
+
ColumnConfig(
|
|
46
|
+
source_field="chunks_count",
|
|
47
|
+
header_label="Chunks",
|
|
48
|
+
align="right",
|
|
49
|
+
compact_line=1,
|
|
50
|
+
compact_style="blue",
|
|
51
|
+
),
|
|
52
|
+
ColumnConfig(
|
|
53
|
+
source_field="questions_generated",
|
|
54
|
+
header_label="Questions",
|
|
55
|
+
align="right",
|
|
56
|
+
compact_line=1,
|
|
57
|
+
compact_style="magenta",
|
|
58
|
+
),
|
|
59
|
+
ColumnConfig(
|
|
60
|
+
source_field="updated_at",
|
|
61
|
+
header_label="Updated",
|
|
62
|
+
formatter=lambda x: x.strftime("%Y-%m-%d") if x else "-",
|
|
63
|
+
compact_line=1,
|
|
64
|
+
compact_style="dim",
|
|
65
|
+
),
|
|
66
|
+
ColumnConfig(
|
|
67
|
+
source_field="title",
|
|
68
|
+
header_label="Title",
|
|
69
|
+
formatter=lambda x: x[:60] + "..." if x and len(x) > 60 else (x or "-"),
|
|
70
|
+
compact_line=2,
|
|
71
|
+
compact_style="white bold",
|
|
72
|
+
),
|
|
73
|
+
ColumnConfig(
|
|
74
|
+
source_field="collection_id",
|
|
75
|
+
header_label="Collection",
|
|
76
|
+
formatter=lambda x: str(x)[:8] + "..." if x else "-",
|
|
77
|
+
compact_line=2,
|
|
78
|
+
compact_style="dim",
|
|
79
|
+
),
|
|
80
|
+
]
|
|
81
|
+
|
|
82
|
+
output.table(
|
|
83
|
+
items=response.documents, # type: ignore[arg-type]
|
|
84
|
+
title=f"Documents ({response.total})",
|
|
85
|
+
columns=columns,
|
|
86
|
+
)
|
|
File without changes
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
"""Knowledge documents reingest command implementation."""
|
|
2
|
+
|
|
3
|
+
from typing import 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.documents.reingest.presenter import (
|
|
10
|
+
present_reingest_result,
|
|
11
|
+
)
|
|
12
|
+
from cli.infrastructure.command import async_command, authenticated_client
|
|
13
|
+
from alloy_runtime_types.dtos.knowledge import ReingestDocumentRequest
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def knowledge_documents_reingest_command(
|
|
17
|
+
document_id: str = typer.Argument(
|
|
18
|
+
...,
|
|
19
|
+
help="Document UUID",
|
|
20
|
+
),
|
|
21
|
+
question_gen_agent: Optional[str] = typer.Option(
|
|
22
|
+
None,
|
|
23
|
+
"--question-gen-agent",
|
|
24
|
+
help="Agent UUID for question generation",
|
|
25
|
+
),
|
|
26
|
+
question_gen_template: Optional[str] = typer.Option(
|
|
27
|
+
None,
|
|
28
|
+
"--question-gen-template",
|
|
29
|
+
help="Template UUID for question generation",
|
|
30
|
+
),
|
|
31
|
+
document_type: Optional[str] = typer.Option(
|
|
32
|
+
None,
|
|
33
|
+
"--document-type",
|
|
34
|
+
help="Document type for preprocessing: transcript, markdown, document",
|
|
35
|
+
),
|
|
36
|
+
dry_run: bool = typer.Option(
|
|
37
|
+
False,
|
|
38
|
+
"--dry-run",
|
|
39
|
+
help="Preview changes without committing",
|
|
40
|
+
),
|
|
41
|
+
) -> None:
|
|
42
|
+
"""Reingest a document with new processing parameters.
|
|
43
|
+
|
|
44
|
+
Re-processes an existing document, optionally with updated question
|
|
45
|
+
generation agents, templates, or document type. The document's
|
|
46
|
+
original content is preserved; only derived data is regenerated.
|
|
47
|
+
|
|
48
|
+
Use --dry-run to preview preprocessing changes without committing.
|
|
49
|
+
|
|
50
|
+
Examples:
|
|
51
|
+
ai2 knowledge documents reingest <uuid>
|
|
52
|
+
ai2 kb documents reingest <uuid> --document-type transcript
|
|
53
|
+
ai2 kb documents reingest <uuid> --question-gen-agent <agent-uuid> --dry-run
|
|
54
|
+
"""
|
|
55
|
+
_execute_reingest(
|
|
56
|
+
document_id=document_id,
|
|
57
|
+
question_gen_agent=question_gen_agent,
|
|
58
|
+
question_gen_template=question_gen_template,
|
|
59
|
+
document_type=document_type,
|
|
60
|
+
dry_run=dry_run,
|
|
61
|
+
)
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
@async_command
|
|
65
|
+
async def _execute_reingest(
|
|
66
|
+
document_id: str,
|
|
67
|
+
question_gen_agent: Optional[str],
|
|
68
|
+
question_gen_template: Optional[str],
|
|
69
|
+
document_type: Optional[str],
|
|
70
|
+
dry_run: bool,
|
|
71
|
+
) -> None:
|
|
72
|
+
"""Execute document reingest operation."""
|
|
73
|
+
|
|
74
|
+
agent_id: UUID | None = None
|
|
75
|
+
if question_gen_agent is not None:
|
|
76
|
+
agent_id = validate_uuid(question_gen_agent, "question-gen-agent")
|
|
77
|
+
|
|
78
|
+
template_id: UUID | None = None
|
|
79
|
+
if question_gen_template is not None:
|
|
80
|
+
template_id = validate_uuid(question_gen_template, "question-gen-template")
|
|
81
|
+
|
|
82
|
+
valid_types = ("transcript", "markdown", "document")
|
|
83
|
+
if document_type is not None and document_type not in valid_types:
|
|
84
|
+
raise typer.BadParameter(
|
|
85
|
+
f"Invalid document type '{document_type}'. "
|
|
86
|
+
f"Must be one of: {', '.join(valid_types)}"
|
|
87
|
+
)
|
|
88
|
+
|
|
89
|
+
request = ReingestDocumentRequest(
|
|
90
|
+
question_gen_agent_id=agent_id,
|
|
91
|
+
question_gen_template_id=template_id,
|
|
92
|
+
document_type=document_type, # type: ignore[arg-type]
|
|
93
|
+
dry_run=dry_run,
|
|
94
|
+
)
|
|
95
|
+
|
|
96
|
+
async with authenticated_client() as (_config, client):
|
|
97
|
+
response = await client.reingest_document(
|
|
98
|
+
document_id=document_id,
|
|
99
|
+
request=request,
|
|
100
|
+
)
|
|
101
|
+
|
|
102
|
+
present_reingest_result(response)
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
"""Presenter for knowledge document reingest command 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 ReingestDocumentResponse
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def _format_reingest_status(status: str) -> str:
|
|
12
|
+
"""Format reingest status with color."""
|
|
13
|
+
status_colors = {
|
|
14
|
+
"pending": "[yellow]pending[/]",
|
|
15
|
+
"dry_run_complete": "[blue]dry_run_complete[/]",
|
|
16
|
+
}
|
|
17
|
+
return status_colors.get(status, status)
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def present_reingest_result(response: ReingestDocumentResponse) -> None:
|
|
21
|
+
"""Present document reingest result.
|
|
22
|
+
|
|
23
|
+
Args:
|
|
24
|
+
response: ReingestDocumentResponse from server
|
|
25
|
+
"""
|
|
26
|
+
output = OutputService.get()
|
|
27
|
+
|
|
28
|
+
if response.dry_run:
|
|
29
|
+
output.info("Dry run — no changes committed")
|
|
30
|
+
else:
|
|
31
|
+
output.success("Document queued for reingestion")
|
|
32
|
+
|
|
33
|
+
table = Table(show_header=False, box=None, padding=(0, 1))
|
|
34
|
+
table.add_column("Field", style="dim")
|
|
35
|
+
table.add_column("Value")
|
|
36
|
+
|
|
37
|
+
table.add_row("Document ID", format_uuid(response.document_id, short=False))
|
|
38
|
+
table.add_row("Status", _format_reingest_status(response.status))
|
|
39
|
+
table.add_row("Message", response.message)
|
|
40
|
+
table.add_row("Document Type", response.document_type)
|
|
41
|
+
|
|
42
|
+
if response.question_gen_agent_id:
|
|
43
|
+
table.add_row(
|
|
44
|
+
"Question Gen Agent",
|
|
45
|
+
format_uuid(response.question_gen_agent_id, short=False),
|
|
46
|
+
)
|
|
47
|
+
if response.question_gen_template_id:
|
|
48
|
+
table.add_row(
|
|
49
|
+
"Question Gen Template",
|
|
50
|
+
format_uuid(response.question_gen_template_id, short=False),
|
|
51
|
+
)
|
|
52
|
+
|
|
53
|
+
if response.dry_run and response.diff_stats:
|
|
54
|
+
table.add_row("Diff Stats", str(response.diff_stats))
|
|
55
|
+
|
|
56
|
+
if response.rejected:
|
|
57
|
+
table.add_row("Rejected", f"[red]{response.rejection_reason}[/]")
|
|
58
|
+
|
|
59
|
+
border_style = "blue" if response.dry_run else "green"
|
|
60
|
+
title = "Reingest Dry Run" if response.dry_run else "Document Reingested"
|
|
61
|
+
panel = Panel(table, title=title, border_style=border_style)
|
|
62
|
+
output.console.print(panel)
|
|
63
|
+
|
|
64
|
+
if response.dry_run and response.diff_unified:
|
|
65
|
+
diff_panel = Panel(
|
|
66
|
+
response.diff_unified,
|
|
67
|
+
title="Preprocessing Diff",
|
|
68
|
+
border_style="cyan",
|
|
69
|
+
)
|
|
70
|
+
output.console.print(diff_panel)
|
|
File without changes
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
"""Knowledge documents update metadata command implementation."""
|
|
2
|
+
|
|
3
|
+
import json
|
|
4
|
+
from typing import Any, cast
|
|
5
|
+
|
|
6
|
+
import typer
|
|
7
|
+
|
|
8
|
+
from cli.commands.knowledge.documents.update.presenter import (
|
|
9
|
+
present_update_metadata_result,
|
|
10
|
+
)
|
|
11
|
+
from cli.infrastructure.command import async_command, authenticated_client
|
|
12
|
+
from cli.infrastructure.file_content import resolve_content_or_raise
|
|
13
|
+
from alloy_runtime_types.dtos.knowledge import UpdateDocumentMetadataRequest
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def knowledge_documents_update_command(
|
|
17
|
+
document_id: str = typer.Argument(
|
|
18
|
+
...,
|
|
19
|
+
help="Document UUID",
|
|
20
|
+
),
|
|
21
|
+
metadata: str = typer.Option(
|
|
22
|
+
...,
|
|
23
|
+
"--metadata",
|
|
24
|
+
help="Metadata JSON object (or @file.json)",
|
|
25
|
+
),
|
|
26
|
+
metadata_mode: str = typer.Option(
|
|
27
|
+
"merge",
|
|
28
|
+
"--metadata-mode",
|
|
29
|
+
help="Metadata update mode: 'merge' (default) or 'replace'",
|
|
30
|
+
),
|
|
31
|
+
) -> None:
|
|
32
|
+
"""Update a document's metadata.
|
|
33
|
+
|
|
34
|
+
The --metadata flag accepts a JSON string or @file reference.
|
|
35
|
+
Use --metadata-mode to control whether keys are merged with
|
|
36
|
+
existing metadata (default) or replace it entirely.
|
|
37
|
+
|
|
38
|
+
Examples:
|
|
39
|
+
ai2 knowledge documents update <uuid> --metadata '{"key": "value"}'
|
|
40
|
+
ai2 kb documents update <uuid> --metadata @meta.json --metadata-mode replace
|
|
41
|
+
"""
|
|
42
|
+
_execute_update(
|
|
43
|
+
document_id=document_id,
|
|
44
|
+
metadata_raw=metadata,
|
|
45
|
+
metadata_mode=metadata_mode,
|
|
46
|
+
)
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
@async_command
|
|
50
|
+
async def _execute_update(
|
|
51
|
+
document_id: str,
|
|
52
|
+
metadata_raw: str,
|
|
53
|
+
metadata_mode: str,
|
|
54
|
+
) -> None:
|
|
55
|
+
"""Execute document metadata update operation."""
|
|
56
|
+
|
|
57
|
+
if metadata_mode not in ("merge", "replace"):
|
|
58
|
+
raise typer.BadParameter(
|
|
59
|
+
f"Invalid metadata mode '{metadata_mode}'. Must be 'merge' or 'replace'."
|
|
60
|
+
)
|
|
61
|
+
|
|
62
|
+
resolved = resolve_content_or_raise(metadata_raw)
|
|
63
|
+
if resolved is None:
|
|
64
|
+
raise typer.BadParameter("--metadata is required")
|
|
65
|
+
|
|
66
|
+
try:
|
|
67
|
+
parsed = json.loads(resolved)
|
|
68
|
+
except json.JSONDecodeError as e:
|
|
69
|
+
raise typer.BadParameter(f"Invalid JSON for --metadata: {e}")
|
|
70
|
+
if not isinstance(parsed, dict):
|
|
71
|
+
raise typer.BadParameter("--metadata must be a JSON object")
|
|
72
|
+
metadata_dict = cast(dict[str, Any], parsed)
|
|
73
|
+
|
|
74
|
+
request = UpdateDocumentMetadataRequest(
|
|
75
|
+
metadata=metadata_dict,
|
|
76
|
+
metadata_mode=metadata_mode, # type: ignore[arg-type]
|
|
77
|
+
)
|
|
78
|
+
|
|
79
|
+
async with authenticated_client() as (_config, client):
|
|
80
|
+
response = await client.update_document_metadata(
|
|
81
|
+
document_id=document_id,
|
|
82
|
+
request=request,
|
|
83
|
+
)
|
|
84
|
+
|
|
85
|
+
present_update_metadata_result(response)
|