kiapi 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.
- kiapi/__init__.py +3 -0
- kiapi/__main__.py +4 -0
- kiapi/api/__init__.py +26 -0
- kiapi/api/_constants/require_auth.py +14 -0
- kiapi/api/_helpers/build_job_responses.py +73 -0
- kiapi/api/_helpers/build_openapi.py +55 -0
- kiapi/api/_helpers/build_train_responses.py +21 -0
- kiapi/api/_helpers/get_accept.py +20 -0
- kiapi/api/_helpers/get_ctx.py +7 -0
- kiapi/api/_helpers/get_worker.py +7 -0
- kiapi/api/_helpers/register_capability_endpoints.py +70 -0
- kiapi/api/_helpers/submit_and_maybe_wait.py +113 -0
- kiapi/api/_settings.py +50 -0
- kiapi/api/_views/async_job_response.py +21 -0
- kiapi/api/_views/capability_model_spec.py +49 -0
- kiapi/api/app.py +150 -0
- kiapi/api/audio/acestep/_views/extract_response.py +57 -0
- kiapi/api/audio/acestep/_views/track_response.py +57 -0
- kiapi/api/audio/acestep/router.py +190 -0
- kiapi/api/audio/audiogen/_views/audio_response.py +46 -0
- kiapi/api/audio/audiogen/router.py +77 -0
- kiapi/api/chat/_views/chat_completion_response.py +71 -0
- kiapi/api/chat/router.py +253 -0
- kiapi/api/embedding/_views/embedding_response.py +35 -0
- kiapi/api/embedding/router.py +82 -0
- kiapi/api/files/_operations/get_file.py +14 -0
- kiapi/api/files/_operations/get_file_id.py +18 -0
- kiapi/api/files/_views/file_delete_response.py +14 -0
- kiapi/api/files/_views/file_list_response.py +15 -0
- kiapi/api/files/router.py +105 -0
- kiapi/api/health/_views/health_response.py +26 -0
- kiapi/api/health/router.py +28 -0
- kiapi/api/image/depthpro/_views/estimate_response.py +70 -0
- kiapi/api/image/depthpro/router.py +81 -0
- kiapi/api/image/ernie/_views/image_response.py +50 -0
- kiapi/api/image/ernie/router.py +181 -0
- kiapi/api/image/flux2/_views/image_response.py +53 -0
- kiapi/api/image/flux2/router.py +197 -0
- kiapi/api/image/ideogram4/_views/image_response.py +55 -0
- kiapi/api/image/ideogram4/router.py +87 -0
- kiapi/api/image/qwen/_views/image_response.py +47 -0
- kiapi/api/image/qwen/router.py +141 -0
- kiapi/api/image/seedvr2/_views/image_response.py +50 -0
- kiapi/api/image/seedvr2/router.py +83 -0
- kiapi/api/image/zimage/_views/image_response.py +49 -0
- kiapi/api/image/zimage/router.py +131 -0
- kiapi/api/jobs/_operations/get_job_id.py +18 -0
- kiapi/api/jobs/_views/job_delete_response.py +19 -0
- kiapi/api/jobs/_views/job_list_response.py +15 -0
- kiapi/api/jobs/router.py +62 -0
- kiapi/api/models/_schemas/openai_model_spec.py +26 -0
- kiapi/api/models/_views/model_list_response.py +15 -0
- kiapi/api/models/router.py +29 -0
- kiapi/api/video/ltx2/_views/__init__.py +1 -0
- kiapi/api/video/ltx2/_views/video_response.py +59 -0
- kiapi/api/video/ltx2/router.py +89 -0
- kiapi/api/web/_views/__init__.py +7 -0
- kiapi/api/web/_views/fetch_api_request.py +26 -0
- kiapi/api/web/_views/fetch_error_response.py +25 -0
- kiapi/api/web/router.py +302 -0
- kiapi/capabilities/__init__.py +24 -0
- kiapi/capabilities/_exceptions/CapabilityError.py +2 -0
- kiapi/capabilities/_exceptions/ValidationError.py +2 -0
- kiapi/capabilities/_helpers/attach_mflux_progress.py +50 -0
- kiapi/capabilities/_helpers/get_file_path.py +20 -0
- kiapi/capabilities/_helpers/resolve_file_ref.py +16 -0
- kiapi/capabilities/acestep/README.ja.md +174 -0
- kiapi/capabilities/acestep/README.md +167 -0
- kiapi/capabilities/acestep/__init__.py +37 -0
- kiapi/capabilities/acestep/_constants/description.py +122 -0
- kiapi/capabilities/acestep/_exceptions/ace_step_engine_error.py +2 -0
- kiapi/capabilities/acestep/_helpers/register.py +96 -0
- kiapi/capabilities/acestep/_models/acestep.py +105 -0
- kiapi/capabilities/acestep/_operations/handle_cover.py +23 -0
- kiapi/capabilities/acestep/_operations/handle_extract.py +38 -0
- kiapi/capabilities/acestep/_operations/handle_generate.py +18 -0
- kiapi/capabilities/acestep/_operations/handle_repaint.py +25 -0
- kiapi/capabilities/acestep/_operations/resolve_ace_step_paths.py +30 -0
- kiapi/capabilities/acestep/_operations/resolve_cover_params.py +21 -0
- kiapi/capabilities/acestep/_operations/resolve_engine.py +10 -0
- kiapi/capabilities/acestep/_operations/resolve_extract_params.py +24 -0
- kiapi/capabilities/acestep/_operations/resolve_generate_params.py +18 -0
- kiapi/capabilities/acestep/_operations/resolve_repaint_params.py +22 -0
- kiapi/capabilities/acestep/_schemas/ace_step_paths.py +29 -0
- kiapi/capabilities/acestep/_services/ace_step_engine.py +143 -0
- kiapi/capabilities/acestep/_settings.py +82 -0
- kiapi/capabilities/acestep/_views/ace_step_base.py +61 -0
- kiapi/capabilities/acestep/_views/cover_params.py +26 -0
- kiapi/capabilities/acestep/_views/cover_request.py +49 -0
- kiapi/capabilities/acestep/_views/extract_params.py +24 -0
- kiapi/capabilities/acestep/_views/extract_request.py +33 -0
- kiapi/capabilities/acestep/_views/generate_params.py +25 -0
- kiapi/capabilities/acestep/_views/generate_request.py +54 -0
- kiapi/capabilities/acestep/_views/repaint_params.py +27 -0
- kiapi/capabilities/acestep/_views/repaint_request.py +51 -0
- kiapi/capabilities/acestep/_views/track_params.py +7 -0
- kiapi/capabilities/acestep/worker_subprocess.py +247 -0
- kiapi/capabilities/audiogen/README.ja.md +49 -0
- kiapi/capabilities/audiogen/README.md +48 -0
- kiapi/capabilities/audiogen/__init__.py +25 -0
- kiapi/capabilities/audiogen/_constants/description.py +60 -0
- kiapi/capabilities/audiogen/_helpers/attach_audiogen_progress.py +27 -0
- kiapi/capabilities/audiogen/_helpers/register.py +42 -0
- kiapi/capabilities/audiogen/_helpers/validate_generate.py +14 -0
- kiapi/capabilities/audiogen/_models/audiogen.py +98 -0
- kiapi/capabilities/audiogen/_operations/handle_generate.py +27 -0
- kiapi/capabilities/audiogen/_operations/resolve_generate_params.py +25 -0
- kiapi/capabilities/audiogen/_settings.py +34 -0
- kiapi/capabilities/audiogen/_views/generate_params.py +14 -0
- kiapi/capabilities/audiogen/_views/generate_request.py +96 -0
- kiapi/capabilities/chat/README.ja.md +822 -0
- kiapi/capabilities/chat/README.md +806 -0
- kiapi/capabilities/chat/__init__.py +25 -0
- kiapi/capabilities/chat/_constants/description.py +163 -0
- kiapi/capabilities/chat/_helpers/register.py +67 -0
- kiapi/capabilities/chat/_models/qwen3_5.py +183 -0
- kiapi/capabilities/chat/_models/qwen3_omni.py +242 -0
- kiapi/capabilities/chat/_operations/apply_template.py +74 -0
- kiapi/capabilities/chat/_operations/completed_hermes_tool_call_text.py +9 -0
- kiapi/capabilities/chat/_operations/emit_streaming_response.py +297 -0
- kiapi/capabilities/chat/_operations/ensure_streaming_detokenizer_compat.py +49 -0
- kiapi/capabilities/chat/_operations/format_response.py +72 -0
- kiapi/capabilities/chat/_operations/handle_chat.py +25 -0
- kiapi/capabilities/chat/_operations/parse_hermes_tool_calls.py +63 -0
- kiapi/capabilities/chat/_operations/parse_json_tool_calls.py +66 -0
- kiapi/capabilities/chat/_operations/parse_messages.py +326 -0
- kiapi/capabilities/chat/_operations/resolve_chat_params.py +50 -0
- kiapi/capabilities/chat/_operations/stream_text_from_tokens.py +32 -0
- kiapi/capabilities/chat/_operations/strip_tool_calls.py +15 -0
- kiapi/capabilities/chat/_settings.py +74 -0
- kiapi/capabilities/chat/_utils/apply_parallel_tool_call_policy.py +17 -0
- kiapi/capabilities/chat/_utils/apply_seed.py +8 -0
- kiapi/capabilities/chat/_utils/load_audio_mono.py +31 -0
- kiapi/capabilities/chat/_utils/load_mlx_vlm.py +12 -0
- kiapi/capabilities/chat/_utils/warmup_params.py +26 -0
- kiapi/capabilities/chat/_views/chat_params.py +34 -0
- kiapi/capabilities/chat/_views/chat_request.py +153 -0
- kiapi/capabilities/depthpro/README.ja.md +131 -0
- kiapi/capabilities/depthpro/README.md +124 -0
- kiapi/capabilities/depthpro/__init__.py +23 -0
- kiapi/capabilities/depthpro/_constants/description.py +39 -0
- kiapi/capabilities/depthpro/_helpers/register.py +46 -0
- kiapi/capabilities/depthpro/_helpers/validate_estimate.py +32 -0
- kiapi/capabilities/depthpro/_models/depthpro.py +144 -0
- kiapi/capabilities/depthpro/_operations/handle_estimate.py +50 -0
- kiapi/capabilities/depthpro/_operations/is_quantize_override.py +12 -0
- kiapi/capabilities/depthpro/_operations/resolve_estimate_params.py +24 -0
- kiapi/capabilities/depthpro/_settings.py +46 -0
- kiapi/capabilities/depthpro/_views/estimate_params.py +21 -0
- kiapi/capabilities/depthpro/_views/estimate_request.py +63 -0
- kiapi/capabilities/embedding/README.ja.md +137 -0
- kiapi/capabilities/embedding/README.md +128 -0
- kiapi/capabilities/embedding/__init__.py +24 -0
- kiapi/capabilities/embedding/_constants/description.py +47 -0
- kiapi/capabilities/embedding/_helpers/register.py +66 -0
- kiapi/capabilities/embedding/_models/qwen3_text.py +53 -0
- kiapi/capabilities/embedding/_models/qwen3_vl.py +97 -0
- kiapi/capabilities/embedding/_operations/format_response.py +24 -0
- kiapi/capabilities/embedding/_operations/handle_embed.py +24 -0
- kiapi/capabilities/embedding/_operations/parse_inputs.py +108 -0
- kiapi/capabilities/embedding/_operations/resolve_embed_params.py +18 -0
- kiapi/capabilities/embedding/_settings.py +27 -0
- kiapi/capabilities/embedding/_utils/to_vector.py +20 -0
- kiapi/capabilities/embedding/_views/embed_params.py +17 -0
- kiapi/capabilities/embedding/_views/embed_request.py +39 -0
- kiapi/capabilities/ernie/README.ja.md +242 -0
- kiapi/capabilities/ernie/README.md +223 -0
- kiapi/capabilities/ernie/__init__.py +34 -0
- kiapi/capabilities/ernie/_constants/description.py +71 -0
- kiapi/capabilities/ernie/_helpers/register.py +60 -0
- kiapi/capabilities/ernie/_helpers/validate_edit.py +19 -0
- kiapi/capabilities/ernie/_helpers/validate_generate.py +8 -0
- kiapi/capabilities/ernie/_models/ernie.py +356 -0
- kiapi/capabilities/ernie/_operations/handle_edit.py +39 -0
- kiapi/capabilities/ernie/_operations/handle_generate.py +38 -0
- kiapi/capabilities/ernie/_operations/handle_train.py +77 -0
- kiapi/capabilities/ernie/_operations/is_quantize_override.py +16 -0
- kiapi/capabilities/ernie/_operations/resolve_edit_params.py +44 -0
- kiapi/capabilities/ernie/_operations/resolve_generate_params.py +40 -0
- kiapi/capabilities/ernie/_operations/resolve_lora_params.py +23 -0
- kiapi/capabilities/ernie/_operations/resolve_train_params.py +43 -0
- kiapi/capabilities/ernie/_operations/validate_common.py +33 -0
- kiapi/capabilities/ernie/_schemas/lora_ref.py +27 -0
- kiapi/capabilities/ernie/_settings.py +151 -0
- kiapi/capabilities/ernie/_views/edit_params.py +36 -0
- kiapi/capabilities/ernie/_views/edit_request.py +142 -0
- kiapi/capabilities/ernie/_views/generate_params.py +32 -0
- kiapi/capabilities/ernie/_views/generate_request.py +127 -0
- kiapi/capabilities/ernie/_views/train_params.py +28 -0
- kiapi/capabilities/ernie/_views/train_request.py +96 -0
- kiapi/capabilities/flux2/README.ja.md +260 -0
- kiapi/capabilities/flux2/README.md +241 -0
- kiapi/capabilities/flux2/__init__.py +36 -0
- kiapi/capabilities/flux2/_constants/description.py +81 -0
- kiapi/capabilities/flux2/_helpers/register.py +98 -0
- kiapi/capabilities/flux2/_helpers/validate_edit.py +12 -0
- kiapi/capabilities/flux2/_helpers/validate_generate.py +8 -0
- kiapi/capabilities/flux2/_models/flux2.py +396 -0
- kiapi/capabilities/flux2/_operations/handle_edit.py +44 -0
- kiapi/capabilities/flux2/_operations/handle_generate.py +46 -0
- kiapi/capabilities/flux2/_operations/handle_train.py +105 -0
- kiapi/capabilities/flux2/_operations/is_quantize_override.py +16 -0
- kiapi/capabilities/flux2/_operations/resolve_edit_params.py +43 -0
- kiapi/capabilities/flux2/_operations/resolve_generate_params.py +44 -0
- kiapi/capabilities/flux2/_operations/resolve_lora_params.py +23 -0
- kiapi/capabilities/flux2/_operations/resolve_train_params.py +42 -0
- kiapi/capabilities/flux2/_operations/role_spec.py +13 -0
- kiapi/capabilities/flux2/_operations/split_repo.py +11 -0
- kiapi/capabilities/flux2/_operations/validate_common.py +35 -0
- kiapi/capabilities/flux2/_schemas/lora_ref.py +27 -0
- kiapi/capabilities/flux2/_settings.py +181 -0
- kiapi/capabilities/flux2/_views/edit_params.py +36 -0
- kiapi/capabilities/flux2/_views/edit_request.py +145 -0
- kiapi/capabilities/flux2/_views/generate_params.py +36 -0
- kiapi/capabilities/flux2/_views/generate_request.py +150 -0
- kiapi/capabilities/flux2/_views/train_params.py +32 -0
- kiapi/capabilities/flux2/_views/train_request.py +102 -0
- kiapi/capabilities/ideogram4/README.ja.md +230 -0
- kiapi/capabilities/ideogram4/README.md +219 -0
- kiapi/capabilities/ideogram4/__init__.py +24 -0
- kiapi/capabilities/ideogram4/_constants/description.py +65 -0
- kiapi/capabilities/ideogram4/_helpers/register.py +44 -0
- kiapi/capabilities/ideogram4/_helpers/validate_generate.py +31 -0
- kiapi/capabilities/ideogram4/_models/ideogram4.py +120 -0
- kiapi/capabilities/ideogram4/_operations/handle_generate.py +30 -0
- kiapi/capabilities/ideogram4/_operations/is_quantize_override.py +12 -0
- kiapi/capabilities/ideogram4/_operations/resolve_generate_params.py +30 -0
- kiapi/capabilities/ideogram4/_settings.py +89 -0
- kiapi/capabilities/ideogram4/_views/generate_params.py +27 -0
- kiapi/capabilities/ideogram4/_views/generate_request.py +118 -0
- kiapi/capabilities/ltx2/README.ja.md +287 -0
- kiapi/capabilities/ltx2/README.md +274 -0
- kiapi/capabilities/ltx2/__init__.py +26 -0
- kiapi/capabilities/ltx2/_constants/description.py +81 -0
- kiapi/capabilities/ltx2/_helpers/register.py +58 -0
- kiapi/capabilities/ltx2/_helpers/validate_generate.py +42 -0
- kiapi/capabilities/ltx2/_models/ltx2.py +106 -0
- kiapi/capabilities/ltx2/_operations/detect_mode.py +19 -0
- kiapi/capabilities/ltx2/_operations/handle_generate.py +52 -0
- kiapi/capabilities/ltx2/_operations/resolve_generate_params.py +31 -0
- kiapi/capabilities/ltx2/_settings.py +93 -0
- kiapi/capabilities/ltx2/_views/generate_params.py +34 -0
- kiapi/capabilities/ltx2/_views/generate_request.py +151 -0
- kiapi/capabilities/qwen/README.ja.md +251 -0
- kiapi/capabilities/qwen/README.md +235 -0
- kiapi/capabilities/qwen/__init__.py +30 -0
- kiapi/capabilities/qwen/_constants/description.py +53 -0
- kiapi/capabilities/qwen/_helpers/register.py +60 -0
- kiapi/capabilities/qwen/_helpers/validate_edit.py +12 -0
- kiapi/capabilities/qwen/_helpers/validate_generate.py +12 -0
- kiapi/capabilities/qwen/_models/qwen.py +224 -0
- kiapi/capabilities/qwen/_operations/handle_edit.py +44 -0
- kiapi/capabilities/qwen/_operations/handle_generate.py +46 -0
- kiapi/capabilities/qwen/_operations/is_quantize_override.py +15 -0
- kiapi/capabilities/qwen/_operations/resolve_edit_params.py +35 -0
- kiapi/capabilities/qwen/_operations/resolve_generate_params.py +39 -0
- kiapi/capabilities/qwen/_operations/resolve_lora_params.py +23 -0
- kiapi/capabilities/qwen/_operations/validate_common.py +32 -0
- kiapi/capabilities/qwen/_schemas/lora_ref.py +27 -0
- kiapi/capabilities/qwen/_settings.py +107 -0
- kiapi/capabilities/qwen/_views/edit_params.py +36 -0
- kiapi/capabilities/qwen/_views/edit_request.py +138 -0
- kiapi/capabilities/qwen/_views/generate_params.py +37 -0
- kiapi/capabilities/qwen/_views/generate_request.py +149 -0
- kiapi/capabilities/seedvr2/README.ja.md +234 -0
- kiapi/capabilities/seedvr2/README.md +219 -0
- kiapi/capabilities/seedvr2/__init__.py +24 -0
- kiapi/capabilities/seedvr2/_constants/description.py +46 -0
- kiapi/capabilities/seedvr2/_helpers/register.py +60 -0
- kiapi/capabilities/seedvr2/_helpers/validate_upscale.py +52 -0
- kiapi/capabilities/seedvr2/_models/seedvr2.py +140 -0
- kiapi/capabilities/seedvr2/_operations/handle_upscale.py +42 -0
- kiapi/capabilities/seedvr2/_operations/is_quantize_override.py +12 -0
- kiapi/capabilities/seedvr2/_operations/resolve_upscale_params.py +30 -0
- kiapi/capabilities/seedvr2/_settings.py +74 -0
- kiapi/capabilities/seedvr2/_views/upscale_params.py +27 -0
- kiapi/capabilities/seedvr2/_views/upscale_request.py +94 -0
- kiapi/capabilities/web/README.ja.md +187 -0
- kiapi/capabilities/web/README.md +171 -0
- kiapi/capabilities/web/__init__.py +30 -0
- kiapi/capabilities/web/_constants/description.py +38 -0
- kiapi/capabilities/web/_exceptions/FetchError.py +24 -0
- kiapi/capabilities/web/_exceptions/SearchBackendError.py +11 -0
- kiapi/capabilities/web/_helpers/register.py +59 -0
- kiapi/capabilities/web/_models/crawl4ai.py +32 -0
- kiapi/capabilities/web/_models/searxng.py +44 -0
- kiapi/capabilities/web/_operations/handle_fetch.py +145 -0
- kiapi/capabilities/web/_operations/handle_search.py +56 -0
- kiapi/capabilities/web/_operations/resolve_fetch_params.py +19 -0
- kiapi/capabilities/web/_operations/resolve_search_params.py +34 -0
- kiapi/capabilities/web/_operations/resolve_searxng_config_dir.py +21 -0
- kiapi/capabilities/web/_services/__init__.py +1 -0
- kiapi/capabilities/web/_services/web_backend_process.py +144 -0
- kiapi/capabilities/web/_settings.py +138 -0
- kiapi/capabilities/web/_views/fetch_params.py +27 -0
- kiapi/capabilities/web/_views/fetch_request.py +29 -0
- kiapi/capabilities/web/_views/fetch_result.py +20 -0
- kiapi/capabilities/web/_views/search_params.py +43 -0
- kiapi/capabilities/web/_views/search_request.py +93 -0
- kiapi/capabilities/web/_views/search_response.py +49 -0
- kiapi/capabilities/web/resources/__init__.py +0 -0
- kiapi/capabilities/web/resources/searxng/__init__.py +0 -0
- kiapi/capabilities/web/resources/searxng/settings.yml +11 -0
- kiapi/capabilities/zimage/README.ja.md +249 -0
- kiapi/capabilities/zimage/README.md +231 -0
- kiapi/capabilities/zimage/__init__.py +34 -0
- kiapi/capabilities/zimage/_constants/description.py +73 -0
- kiapi/capabilities/zimage/_helpers/register.py +62 -0
- kiapi/capabilities/zimage/_helpers/validate_generate.py +37 -0
- kiapi/capabilities/zimage/_models/zimage.py +278 -0
- kiapi/capabilities/zimage/_operations/handle_generate.py +38 -0
- kiapi/capabilities/zimage/_operations/handle_train.py +78 -0
- kiapi/capabilities/zimage/_operations/is_quantize_override.py +11 -0
- kiapi/capabilities/zimage/_operations/resolve_generate_params.py +39 -0
- kiapi/capabilities/zimage/_operations/resolve_lora_params.py +23 -0
- kiapi/capabilities/zimage/_operations/resolve_train_params.py +38 -0
- kiapi/capabilities/zimage/_schemas/lora_ref.py +27 -0
- kiapi/capabilities/zimage/_settings.py +166 -0
- kiapi/capabilities/zimage/_views/generate_params.py +23 -0
- kiapi/capabilities/zimage/_views/generate_request.py +127 -0
- kiapi/capabilities/zimage/_views/train_params.py +22 -0
- kiapi/capabilities/zimage/_views/train_request.py +101 -0
- kiapi/cli/__init__.py +11 -0
- kiapi/cli/_helpers/dedupe_resources.py +12 -0
- kiapi/cli/_helpers/register_all_capabilities.py +36 -0
- kiapi/cli/_helpers/run_resources.py +24 -0
- kiapi/cli/_helpers/select_specs.py +67 -0
- kiapi/cli/activate/_operations/preflight_hf_access.py +129 -0
- kiapi/cli/activate/cli.py +37 -0
- kiapi/cli/check/_helpers/check_audio_acestep_turbo.py +22 -0
- kiapi/cli/check/_helpers/check_audio_acestep_xl_base.py +22 -0
- kiapi/cli/check/_helpers/check_audio_audiogen_medium.py +24 -0
- kiapi/cli/check/_helpers/check_chat_chat_qwen3_6_27b.py +19 -0
- kiapi/cli/check/_helpers/check_chat_chat_qwen3_omni.py +19 -0
- kiapi/cli/check/_helpers/check_embedding_embedding_qwen3_embedding_8b.py +14 -0
- kiapi/cli/check/_helpers/check_embedding_embedding_qwen3_vl_embedding_2b.py +19 -0
- kiapi/cli/check/_helpers/check_image_depthpro_base.py +21 -0
- kiapi/cli/check/_helpers/check_image_ernie_base.py +23 -0
- kiapi/cli/check/_helpers/check_image_ernie_turbo.py +23 -0
- kiapi/cli/check/_helpers/check_image_flux2_klein_9b.py +23 -0
- kiapi/cli/check/_helpers/check_image_flux2_klein_base_4b.py +23 -0
- kiapi/cli/check/_helpers/check_image_flux2_klein_base_9b.py +23 -0
- kiapi/cli/check/_helpers/check_image_ideogram4_fp8.py +23 -0
- kiapi/cli/check/_helpers/check_image_qwen_edit_2509.py +27 -0
- kiapi/cli/check/_helpers/check_image_qwen_image.py +23 -0
- kiapi/cli/check/_helpers/check_image_seedvr2_3b.py +23 -0
- kiapi/cli/check/_helpers/check_image_seedvr2_7b.py +23 -0
- kiapi/cli/check/_helpers/check_image_zimage_base.py +23 -0
- kiapi/cli/check/_helpers/check_image_zimage_turbo.py +23 -0
- kiapi/cli/check/_helpers/check_video_ltx2_distilled.py +26 -0
- kiapi/cli/check/_helpers/check_web_web_fetch.py +14 -0
- kiapi/cli/check/_helpers/check_web_web_search.py +14 -0
- kiapi/cli/check/_operations/build_check_result.py +20 -0
- kiapi/cli/check/_operations/check_context.py +10 -0
- kiapi/cli/check/_operations/create_sample_image.py +46 -0
- kiapi/cli/check/_schemas/check_result.py +12 -0
- kiapi/cli/check/cli.py +89 -0
- kiapi/cli/cli.py +29 -0
- kiapi/cli/config/cli.py +17 -0
- kiapi/cli/config/edit/cli.py +32 -0
- kiapi/cli/config/init/cli.py +33 -0
- kiapi/cli/config/show/cli.py +13 -0
- kiapi/cli/config/template/cli.py +36 -0
- kiapi/cli/deactivate/cli.py +49 -0
- kiapi/cli/run/asgi.py +16 -0
- kiapi/cli/run/cli.py +59 -0
- kiapi/cli/service/__init__.py +5 -0
- kiapi/cli/service/_services/service_manager.py +107 -0
- kiapi/cli/service/cli.py +19 -0
- kiapi/cli/service/install/cli.py +17 -0
- kiapi/cli/service/start/cli.py +22 -0
- kiapi/cli/service/status/cli.py +81 -0
- kiapi/cli/service/stop/cli.py +19 -0
- kiapi/cli/service/uninstall/cli.py +16 -0
- kiapi/cli/status/cli.py +226 -0
- kiapi/core/app/__init__.py +16 -0
- kiapi/core/app/_schemas/app_context.py +28 -0
- kiapi/core/app/_services/user_directory.py +59 -0
- kiapi/core/app/_settings.py +46 -0
- kiapi/core/capability/__init__.py +11 -0
- kiapi/core/capability/_schemas/capability_spec.py +17 -0
- kiapi/core/capability/_services/capability_spec_registry.py +21 -0
- kiapi/core/config/__init__.py +11 -0
- kiapi/core/config/_exceptions/user_config_error.py +2 -0
- kiapi/core/config/_helpers/get_user_settings_path.py +7 -0
- kiapi/core/config/_helpers/load_user_settings.py +54 -0
- kiapi/core/file/__init__.py +37 -0
- kiapi/core/file/_helpers/create_file_store.py +7 -0
- kiapi/core/file/_helpers/resolve_file_ref.py +90 -0
- kiapi/core/file/_schemas/file_data_url_ref.py +19 -0
- kiapi/core/file/_schemas/file_id_ref.py +16 -0
- kiapi/core/file/_schemas/file_record.py +46 -0
- kiapi/core/file/_schemas/file_url_ref.py +16 -0
- kiapi/core/file/_services/file_store.py +138 -0
- kiapi/core/file/_settings.py +22 -0
- kiapi/core/file/_types/file_id.py +2 -0
- kiapi/core/file/_types/file_ref.py +12 -0
- kiapi/core/file/_views/resolved_file_ref.py +16 -0
- kiapi/core/job/__init__.py +24 -0
- kiapi/core/job/_enums/job_status.py +9 -0
- kiapi/core/job/_helpers/creep_progress.py +123 -0
- kiapi/core/job/_models/job.py +121 -0
- kiapi/core/job/_services/job_store.py +33 -0
- kiapi/core/job/_services/progress_reporter.py +79 -0
- kiapi/core/job/_types/job_id.py +3 -0
- kiapi/core/job/_types/job_result.py +5 -0
- kiapi/core/job/_types/job_type.py +4 -0
- kiapi/core/logging/__init__.py +14 -0
- kiapi/core/logging/_helpers/get_log_level.py +8 -0
- kiapi/core/logging/_helpers/setup_logger.py +14 -0
- kiapi/core/logging/_settings.py +34 -0
- kiapi/core/logging/_types/log_level.py +3 -0
- kiapi/core/memory/__init__.py +21 -0
- kiapi/core/memory/_exceptions/memory_budget_error.py +2 -0
- kiapi/core/memory/_helpers/create_memory_manager.py +17 -0
- kiapi/core/memory/_operations/log_memory_limit.py +29 -0
- kiapi/core/memory/_operations/resolve_effective_memory_limit_gb.py +13 -0
- kiapi/core/memory/_operations/resolve_framework_strategy.py +42 -0
- kiapi/core/memory/_schemas/framework_strategy.py +14 -0
- kiapi/core/memory/_schemas/memory_stats.py +24 -0
- kiapi/core/memory/_schemas/resident_model.py +14 -0
- kiapi/core/memory/_schemas/resident_model_stats.py +49 -0
- kiapi/core/memory/_services/memory_manager.py +257 -0
- kiapi/core/memory/_settings.py +36 -0
- kiapi/core/memory/_types/framework_name.py +4 -0
- kiapi/core/memory/_types/resident_key.py +4 -0
- kiapi/core/model/__init__.py +36 -0
- kiapi/core/model/_exceptions/unknown_model_error.py +2 -0
- kiapi/core/model/_schemas/model_spec.py +145 -0
- kiapi/core/model/_services/model_registry.py +85 -0
- kiapi/core/model/_types/model_alias.py +2 -0
- kiapi/core/model/_types/model_domain.py +6 -0
- kiapi/core/model/_types/model_family.py +5 -0
- kiapi/core/model/_types/model_key.py +8 -0
- kiapi/core/model/_types/model_name.py +4 -0
- kiapi/core/model/_types/model_repo.py +3 -0
- kiapi/core/net/__init__.py +16 -0
- kiapi/core/net/_exceptions/unsafe_url_error.py +7 -0
- kiapi/core/net/_helpers/verify_public_url.py +68 -0
- kiapi/core/net/_settings.py +28 -0
- kiapi/core/setup/__init__.py +25 -0
- kiapi/core/setup/_exceptions/setup_required_error.py +2 -0
- kiapi/core/setup/_schemas/docker_image_resource.py +37 -0
- kiapi/core/setup/_schemas/hf_snapshot_resource.py +50 -0
- kiapi/core/setup/_schemas/local_path_resource.py +43 -0
- kiapi/core/setup/_schemas/python_package_resource.py +58 -0
- kiapi/core/setup/_schemas/python_venv_resource.py +63 -0
- kiapi/core/setup/_schemas/setup_status.py +7 -0
- kiapi/core/setup/_schemas/url_file_resource.py +43 -0
- kiapi/core/setup/_services/setup_manager.py +331 -0
- kiapi/core/setup/_types/setup_resource.py +21 -0
- kiapi/core/setup/_types/setup_target.py +11 -0
- kiapi/core/workdir/__init__.py +8 -0
- kiapi/core/workdir/_helpers/create_work_dir.py +11 -0
- kiapi/core/workdir/_settings.py +21 -0
- kiapi/core/worker/__init__.py +23 -0
- kiapi/core/worker/_helpers/create_worker.py +9 -0
- kiapi/core/worker/_services/worker.py +165 -0
- kiapi/core/worker/_settings.py +36 -0
- kiapi/core/worker/_types/job_thunk.py +6 -0
- kiapi-0.1.0.dist-info/METADATA +337 -0
- kiapi-0.1.0.dist-info/RECORD +465 -0
- kiapi-0.1.0.dist-info/WHEEL +4 -0
- kiapi-0.1.0.dist-info/entry_points.txt +2 -0
- kiapi-0.1.0.dist-info/licenses/LICENSE +21 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import shutil
|
|
2
|
+
from importlib.resources import files
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
|
|
5
|
+
from kiapi.core.app import get_user_config_dir
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def resolve_searxng_config_dir() -> Path:
|
|
9
|
+
config_dir = Path(get_user_config_dir()).expanduser() / "searxng"
|
|
10
|
+
config_dir.mkdir(parents=True, exist_ok=True)
|
|
11
|
+
|
|
12
|
+
settings_path = config_dir / "settings.yml"
|
|
13
|
+
if not settings_path.exists():
|
|
14
|
+
bundled_settings = (
|
|
15
|
+
files("kiapi.capabilities.web.resources.searxng") / "settings.yml"
|
|
16
|
+
)
|
|
17
|
+
with bundled_settings.open("rb") as source:
|
|
18
|
+
with settings_path.open("wb") as target:
|
|
19
|
+
shutil.copyfileobj(source, target)
|
|
20
|
+
|
|
21
|
+
return config_dir
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
"""Foreground subprocess wrapper for web backend containers.
|
|
2
|
+
|
|
3
|
+
The web capability treats SearXNG and Crawl4AI like resident subprocess models:
|
|
4
|
+
``load`` starts a foreground ``docker run --rm`` process on a free localhost port,
|
|
5
|
+
and ``release`` terminates that process. Docker is only an implementation detail
|
|
6
|
+
of this payload.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
import socket
|
|
10
|
+
import subprocess
|
|
11
|
+
import time
|
|
12
|
+
import uuid
|
|
13
|
+
from collections.abc import Callable
|
|
14
|
+
from pathlib import Path
|
|
15
|
+
from typing import BinaryIO, Self
|
|
16
|
+
|
|
17
|
+
import httpx
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class WebBackendProcess:
|
|
21
|
+
def __init__(
|
|
22
|
+
self,
|
|
23
|
+
*,
|
|
24
|
+
name: str,
|
|
25
|
+
proc: subprocess.Popen,
|
|
26
|
+
base_url: str,
|
|
27
|
+
port: int,
|
|
28
|
+
log_file: BinaryIO,
|
|
29
|
+
log_path: Path,
|
|
30
|
+
) -> None:
|
|
31
|
+
self.name = name
|
|
32
|
+
self.proc = proc
|
|
33
|
+
self.base_url = base_url
|
|
34
|
+
self.port = port
|
|
35
|
+
self.log_file = log_file
|
|
36
|
+
self.log_path = log_path
|
|
37
|
+
self.started_at = time.time()
|
|
38
|
+
|
|
39
|
+
def release(self) -> None:
|
|
40
|
+
proc = self.proc
|
|
41
|
+
if proc.poll() is None:
|
|
42
|
+
try:
|
|
43
|
+
proc.terminate()
|
|
44
|
+
proc.wait(timeout=15)
|
|
45
|
+
except Exception:
|
|
46
|
+
proc.kill()
|
|
47
|
+
proc.wait(timeout=5)
|
|
48
|
+
try:
|
|
49
|
+
self.log_file.close()
|
|
50
|
+
except Exception:
|
|
51
|
+
pass
|
|
52
|
+
|
|
53
|
+
@classmethod
|
|
54
|
+
def start(
|
|
55
|
+
cls,
|
|
56
|
+
*,
|
|
57
|
+
name: str,
|
|
58
|
+
image: str,
|
|
59
|
+
container_port: int,
|
|
60
|
+
log_dir: str,
|
|
61
|
+
ready_timeout_s: float,
|
|
62
|
+
healthcheck: Callable[[str], None],
|
|
63
|
+
extra_args: list[str] | None = None,
|
|
64
|
+
attempts: int = 3,
|
|
65
|
+
) -> Self:
|
|
66
|
+
last_error: Exception | None = None
|
|
67
|
+
for _ in range(attempts):
|
|
68
|
+
port = _pick_free_port()
|
|
69
|
+
log_path = _log_path(log_dir, name, port)
|
|
70
|
+
log_file = log_path.open("ab")
|
|
71
|
+
container_name = f"kiapi-web-{name}-{uuid.uuid4().hex[:12]}"
|
|
72
|
+
cmd = [
|
|
73
|
+
"docker",
|
|
74
|
+
"run",
|
|
75
|
+
"--rm",
|
|
76
|
+
"--name",
|
|
77
|
+
container_name,
|
|
78
|
+
"-p",
|
|
79
|
+
f"127.0.0.1:{port}:{container_port}",
|
|
80
|
+
*(extra_args or []),
|
|
81
|
+
image,
|
|
82
|
+
]
|
|
83
|
+
proc = subprocess.Popen(
|
|
84
|
+
cmd,
|
|
85
|
+
stdout=log_file,
|
|
86
|
+
stderr=subprocess.STDOUT,
|
|
87
|
+
start_new_session=True,
|
|
88
|
+
)
|
|
89
|
+
backend = cls(
|
|
90
|
+
name=name,
|
|
91
|
+
proc=proc,
|
|
92
|
+
base_url=f"http://127.0.0.1:{port}",
|
|
93
|
+
port=port,
|
|
94
|
+
log_file=log_file,
|
|
95
|
+
log_path=log_path,
|
|
96
|
+
)
|
|
97
|
+
try:
|
|
98
|
+
_wait_ready(backend, ready_timeout_s, healthcheck)
|
|
99
|
+
return backend
|
|
100
|
+
except Exception as exc:
|
|
101
|
+
last_error = exc
|
|
102
|
+
backend.release()
|
|
103
|
+
|
|
104
|
+
assert last_error is not None
|
|
105
|
+
raise last_error
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
def _pick_free_port() -> int:
|
|
109
|
+
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock:
|
|
110
|
+
sock.bind(("127.0.0.1", 0))
|
|
111
|
+
return int(sock.getsockname()[1])
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
def _log_path(log_dir: str, name: str, port: int) -> Path:
|
|
115
|
+
path = Path(log_dir).expanduser()
|
|
116
|
+
path.mkdir(parents=True, exist_ok=True)
|
|
117
|
+
return path / f"kiapi-web-{name}-{port}.log"
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
def _wait_ready(
|
|
121
|
+
backend: WebBackendProcess,
|
|
122
|
+
timeout_s: float,
|
|
123
|
+
healthcheck: Callable[[str], None],
|
|
124
|
+
) -> None:
|
|
125
|
+
deadline = time.monotonic() + timeout_s
|
|
126
|
+
last_error: Exception | None = None
|
|
127
|
+
while time.monotonic() < deadline:
|
|
128
|
+
if backend.proc.poll() is not None:
|
|
129
|
+
raise RuntimeError(
|
|
130
|
+
f"{backend.name} backend exited early "
|
|
131
|
+
f"(code {backend.proc.returncode}); log: {backend.log_path}"
|
|
132
|
+
)
|
|
133
|
+
try:
|
|
134
|
+
healthcheck(backend.base_url)
|
|
135
|
+
return
|
|
136
|
+
except (httpx.HTTPError, ValueError, RuntimeError) as exc:
|
|
137
|
+
last_error = exc
|
|
138
|
+
time.sleep(0.5)
|
|
139
|
+
|
|
140
|
+
detail = f": {last_error}" if last_error else ""
|
|
141
|
+
raise RuntimeError(
|
|
142
|
+
f"{backend.name} backend did not become ready within {timeout_s}s{detail}; "
|
|
143
|
+
f"log: {backend.log_path}"
|
|
144
|
+
)
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
"""web capability defaults, read from ``KIAPI_WEB_`` env vars."""
|
|
2
|
+
|
|
3
|
+
from pydantic import Field
|
|
4
|
+
from pydantic_settings import BaseSettings, SettingsConfigDict
|
|
5
|
+
from pydantic_settings_manager import SettingsManager
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class WebSettings(BaseSettings):
|
|
9
|
+
"""Settings for Web search/fetch backends and request defaults."""
|
|
10
|
+
|
|
11
|
+
model_config = SettingsConfigDict(
|
|
12
|
+
env_prefix="KIAPI_WEB_",
|
|
13
|
+
extra="ignore",
|
|
14
|
+
protected_namespaces=(),
|
|
15
|
+
)
|
|
16
|
+
|
|
17
|
+
# --------------------------------------------------
|
|
18
|
+
# search
|
|
19
|
+
# --------------------------------------------------
|
|
20
|
+
|
|
21
|
+
search_image: str = Field(
|
|
22
|
+
default="searxng/searxng:latest",
|
|
23
|
+
title="Search backend Docker image",
|
|
24
|
+
description="SearXNG Docker image name launched as the Web search backend.",
|
|
25
|
+
)
|
|
26
|
+
|
|
27
|
+
fetch_image: str = Field(
|
|
28
|
+
default="unclecode/crawl4ai:latest",
|
|
29
|
+
title="Fetch backend Docker image",
|
|
30
|
+
description="Crawl4AI Docker image name launched as the Web page fetch backend.",
|
|
31
|
+
)
|
|
32
|
+
|
|
33
|
+
backend_ready_timeout_s: float = Field(
|
|
34
|
+
default=60.0,
|
|
35
|
+
title="Backend ready timeout seconds",
|
|
36
|
+
description="Maximum seconds to wait for the search/fetch backend subprocess to become ready.",
|
|
37
|
+
)
|
|
38
|
+
|
|
39
|
+
backend_log_dir: str = Field(
|
|
40
|
+
default="/tmp/kiapi/logs/web",
|
|
41
|
+
title="Backend log directory",
|
|
42
|
+
description="Directory where search/fetch backend subprocess logs are written.",
|
|
43
|
+
)
|
|
44
|
+
|
|
45
|
+
timeout_s: float = Field(
|
|
46
|
+
default=10.0,
|
|
47
|
+
title="Search timeout seconds",
|
|
48
|
+
description="Maximum seconds allowed for one search request to SearXNG.",
|
|
49
|
+
)
|
|
50
|
+
|
|
51
|
+
default_categories: list[str] | None = Field(
|
|
52
|
+
default=None,
|
|
53
|
+
title="Default search categories",
|
|
54
|
+
description=(
|
|
55
|
+
"Categories passed to SearXNG when a request omits categories.\n"
|
|
56
|
+
"When None, SearXNG decides from its own defaults."
|
|
57
|
+
),
|
|
58
|
+
)
|
|
59
|
+
|
|
60
|
+
default_engines: list[str] | None = Field(
|
|
61
|
+
default=None,
|
|
62
|
+
title="Default search engines",
|
|
63
|
+
description=(
|
|
64
|
+
"SearXNG engine names used when a request omits engines.\n"
|
|
65
|
+
"When None, SearXNG decides from its own defaults."
|
|
66
|
+
),
|
|
67
|
+
)
|
|
68
|
+
|
|
69
|
+
default_language: str | None = Field(
|
|
70
|
+
default=None,
|
|
71
|
+
title="Default search language",
|
|
72
|
+
description=(
|
|
73
|
+
"Language code passed to SearXNG when a request omits language.\n"
|
|
74
|
+
"When None, SearXNG decides from its own defaults."
|
|
75
|
+
),
|
|
76
|
+
)
|
|
77
|
+
|
|
78
|
+
default_safesearch: int | None = Field(
|
|
79
|
+
default=None,
|
|
80
|
+
title="Default SafeSearch level",
|
|
81
|
+
description=(
|
|
82
|
+
"SearXNG SafeSearch value used when a request omits safesearch.\n"
|
|
83
|
+
"Typically 0 disables it, 1 is moderate, and 2 is stricter. None "
|
|
84
|
+
"uses the SearXNG default."
|
|
85
|
+
),
|
|
86
|
+
)
|
|
87
|
+
|
|
88
|
+
default_max_results: int | None = Field(
|
|
89
|
+
default=10,
|
|
90
|
+
title="Default maximum search results",
|
|
91
|
+
description=(
|
|
92
|
+
"Maximum number of results returned when a request omits max_results.\n"
|
|
93
|
+
"Set to None to disable client-side truncation in kiapi."
|
|
94
|
+
),
|
|
95
|
+
)
|
|
96
|
+
|
|
97
|
+
# --------------------------------------------------
|
|
98
|
+
# fetch
|
|
99
|
+
# --------------------------------------------------
|
|
100
|
+
|
|
101
|
+
fetch_timeout_s: float = Field(
|
|
102
|
+
default=30.0,
|
|
103
|
+
title="Page fetch timeout seconds",
|
|
104
|
+
description="Maximum seconds allowed for one page fetch request to Crawl4AI.",
|
|
105
|
+
)
|
|
106
|
+
|
|
107
|
+
fetch_min_content_chars: int = Field(
|
|
108
|
+
default=1,
|
|
109
|
+
title="Minimum fetched content characters",
|
|
110
|
+
description=(
|
|
111
|
+
"Minimum stripped Markdown length before fetched content is treated as empty.\n"
|
|
112
|
+
"With 1, only truly empty renders fail. Higher values also reject "
|
|
113
|
+
"near-empty pages."
|
|
114
|
+
),
|
|
115
|
+
)
|
|
116
|
+
|
|
117
|
+
fetch_filter: str = Field(
|
|
118
|
+
default="fit",
|
|
119
|
+
title="Fetch Markdown filter",
|
|
120
|
+
description=(
|
|
121
|
+
"Body extraction mode for Crawl4AI /md.\n"
|
|
122
|
+
"fit returns readability-pruned Markdown; raw returns Markdown "
|
|
123
|
+
"closer to the full DOM."
|
|
124
|
+
),
|
|
125
|
+
)
|
|
126
|
+
|
|
127
|
+
fetch_cache: str = Field(
|
|
128
|
+
default="0",
|
|
129
|
+
title="Fetch cache-bust value",
|
|
130
|
+
description=(
|
|
131
|
+
"Cache control value passed to Crawl4AI /md.\n"
|
|
132
|
+
"0 lets the server cache normally. Changing the value can act as a "
|
|
133
|
+
"cache-busting identifier."
|
|
134
|
+
),
|
|
135
|
+
)
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
settings_manager = SettingsManager(WebSettings)
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
"""The complete contract for one Crawl4AI fetch call.
|
|
2
|
+
|
|
3
|
+
Built from settings + request by ``resolve_fetch_params``: it carries the
|
|
4
|
+
backend address, the Crawl4AI ``/md`` knobs (filter/cache), and the limits
|
|
5
|
+
(timeout, concurrency, empty threshold) ``handle_fetch`` needs to issue the
|
|
6
|
+
request and judge its result. Nothing here is caller-tunable in this op.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from typing import Literal
|
|
10
|
+
|
|
11
|
+
from pydantic import BaseModel
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class FetchParams(BaseModel):
|
|
15
|
+
url: str
|
|
16
|
+
format: Literal["markdown", "pdf"]
|
|
17
|
+
|
|
18
|
+
# Crawl4AI backend base URL.
|
|
19
|
+
base_url: str
|
|
20
|
+
timeout_s: float
|
|
21
|
+
|
|
22
|
+
# Crawl4AI /md knobs (ignored for the /pdf format).
|
|
23
|
+
filter: str
|
|
24
|
+
cache: str
|
|
25
|
+
|
|
26
|
+
# Empty-result threshold.
|
|
27
|
+
min_content_chars: int
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
"""web fetch request model.
|
|
2
|
+
|
|
3
|
+
``GET /v1/web/fetch?url=...`` renders one page to readable text (or PDF) via the
|
|
4
|
+
Crawl4AI backend. The output ``format`` is chosen by the request's ``Accept``
|
|
5
|
+
header at the router and folded in here. Like ``search`` there is no ``mode``;
|
|
6
|
+
the router runs it as a synchronous Job on the single worker.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from typing import Literal
|
|
10
|
+
|
|
11
|
+
from pydantic import BaseModel, ConfigDict, Field, field_validator
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class FetchRequest(BaseModel):
|
|
15
|
+
model_config = ConfigDict(extra="forbid")
|
|
16
|
+
|
|
17
|
+
# Absolute http(s) URL of the page to fetch. Passed to Crawl4AI verbatim.
|
|
18
|
+
url: str = Field(..., min_length=1)
|
|
19
|
+
|
|
20
|
+
# Resolved from Accept: text/markdown (default) → "markdown",
|
|
21
|
+
# application/pdf → "pdf".
|
|
22
|
+
format: Literal["markdown", "pdf"] = "markdown"
|
|
23
|
+
|
|
24
|
+
@field_validator("url")
|
|
25
|
+
@classmethod
|
|
26
|
+
def _require_http_scheme(cls, v: str) -> str:
|
|
27
|
+
if not v.startswith(("http://", "https://")):
|
|
28
|
+
raise ValueError("url must be an absolute http:// or https:// URL")
|
|
29
|
+
return v
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
"""web fetch result — the raw body the router streams back.
|
|
2
|
+
|
|
3
|
+
fetch returns the rendered page directly (not a JSON envelope): ``content`` is
|
|
4
|
+
the bytes to write, ``media_type`` the response Content-Type (``text/markdown``
|
|
5
|
+
or ``application/pdf``). ``content_type`` is the *upstream* page's MIME (from the
|
|
6
|
+
preflight probe), echoed in a response header for visibility. This mirrors the
|
|
7
|
+
generation families' raw-bytes-by-default house style.
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
from pydantic import BaseModel
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class FetchResult(BaseModel):
|
|
14
|
+
content: bytes
|
|
15
|
+
media_type: str
|
|
16
|
+
|
|
17
|
+
# Final URL after redirects, and the upstream page's detected MIME (or None
|
|
18
|
+
# when the probe could not determine it).
|
|
19
|
+
url: str
|
|
20
|
+
content_type: str | None
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
"""The complete contract for one SearXNG search call.
|
|
2
|
+
|
|
3
|
+
Built from settings + request by ``resolve_search_params``: list fields are
|
|
4
|
+
already comma-joined into SearXNG's wire form, and ``max_results`` carries the
|
|
5
|
+
resolved truncation limit applied after the page is fetched. Everything needed
|
|
6
|
+
to issue the HTTP request and shape the response lives here.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from pydantic import BaseModel
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class SearchParams(BaseModel):
|
|
13
|
+
query: str
|
|
14
|
+
|
|
15
|
+
# SearXNG wire form: comma-joined strings, or None to omit the parameter.
|
|
16
|
+
categories: str | None
|
|
17
|
+
engines: str | None
|
|
18
|
+
language: str | None
|
|
19
|
+
time_range: str | None
|
|
20
|
+
safesearch: int | None
|
|
21
|
+
pageno: int
|
|
22
|
+
|
|
23
|
+
# Client-side truncation limit; None keeps the full page.
|
|
24
|
+
max_results: int | None
|
|
25
|
+
|
|
26
|
+
def query_params(self) -> dict:
|
|
27
|
+
"""SearXNG ``/search`` querystring (``format=json`` is forced here)."""
|
|
28
|
+
params: dict[str, object] = {
|
|
29
|
+
"q": self.query,
|
|
30
|
+
"format": "json",
|
|
31
|
+
"pageno": self.pageno,
|
|
32
|
+
}
|
|
33
|
+
if self.categories is not None:
|
|
34
|
+
params["categories"] = self.categories
|
|
35
|
+
if self.engines is not None:
|
|
36
|
+
params["engines"] = self.engines
|
|
37
|
+
if self.language is not None:
|
|
38
|
+
params["language"] = self.language
|
|
39
|
+
if self.time_range is not None:
|
|
40
|
+
params["time_range"] = self.time_range
|
|
41
|
+
if self.safesearch is not None:
|
|
42
|
+
params["safesearch"] = self.safesearch
|
|
43
|
+
return params
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
"""web search request model.
|
|
2
|
+
|
|
3
|
+
A thin wrapper over SearXNG's ``/search`` query parameters. ``query`` is passed
|
|
4
|
+
through verbatim, so SearXNG's inline operators (``!images``, ``!wp``, ``:ja``,
|
|
5
|
+
``site:``) work unchanged. ``format=json`` is added internally and is not a
|
|
6
|
+
caller concern. There is no ``mode``: web search is run as a synchronous Job on
|
|
7
|
+
the single worker.
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
from typing import Literal
|
|
11
|
+
|
|
12
|
+
from pydantic import BaseModel, ConfigDict, Field
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class SearchRequest(BaseModel):
|
|
16
|
+
model_config = ConfigDict(extra="forbid")
|
|
17
|
+
|
|
18
|
+
query: str = Field(
|
|
19
|
+
...,
|
|
20
|
+
min_length=1,
|
|
21
|
+
description=(
|
|
22
|
+
"Search query passed to SearXNG as-is. SearXNG inline operators "
|
|
23
|
+
"work here, for example `site:github.com kiapi`, `!wp Python`, "
|
|
24
|
+
"`!images cat`, or `:ja mlx`."
|
|
25
|
+
),
|
|
26
|
+
examples=["site:github.com kiarina kiapi"],
|
|
27
|
+
)
|
|
28
|
+
|
|
29
|
+
categories: list[str] | None = Field(
|
|
30
|
+
default=None,
|
|
31
|
+
description=(
|
|
32
|
+
"SearXNG categories to search. Omit to use "
|
|
33
|
+
"`KIAPI_WEB_DEFAULT_CATEGORIES`; if that is unset, SearXNG chooses "
|
|
34
|
+
"its own default. Common values include `general`, `it`, `science`, "
|
|
35
|
+
"`news`, `images`, `videos`, `map`, `music`, `files`, and "
|
|
36
|
+
"`social_media`."
|
|
37
|
+
),
|
|
38
|
+
examples=[["general"], ["it", "science"]],
|
|
39
|
+
)
|
|
40
|
+
engines: list[str] | None = Field(
|
|
41
|
+
default=None,
|
|
42
|
+
description=(
|
|
43
|
+
"Specific SearXNG engines to use. Omit to use "
|
|
44
|
+
"`KIAPI_WEB_DEFAULT_ENGINES`; if that is unset, SearXNG selects "
|
|
45
|
+
"engines from the requested categories. Examples: `google`, `bing`, "
|
|
46
|
+
"`duckduckgo`, `github`, `wikipedia`, `arxiv`."
|
|
47
|
+
),
|
|
48
|
+
examples=[["duckduckgo"], ["github", "stackoverflow"]],
|
|
49
|
+
)
|
|
50
|
+
|
|
51
|
+
language: str | None = Field(
|
|
52
|
+
default=None,
|
|
53
|
+
description=(
|
|
54
|
+
"Optional SearXNG language code such as `ja`, `en`, or `en-US`. "
|
|
55
|
+
"Omit to use `KIAPI_WEB_DEFAULT_LANGUAGE`."
|
|
56
|
+
),
|
|
57
|
+
examples=["ja", "en"],
|
|
58
|
+
)
|
|
59
|
+
time_range: Literal["day", "week", "month", "year"] | None = Field(
|
|
60
|
+
default=None,
|
|
61
|
+
description=(
|
|
62
|
+
"Optional freshness filter. Supported values are `day`, `week`, "
|
|
63
|
+
"`month`, and `year`. Support depends on the selected engines."
|
|
64
|
+
),
|
|
65
|
+
)
|
|
66
|
+
safesearch: Literal[0, 1, 2] | None = Field(
|
|
67
|
+
default=None,
|
|
68
|
+
description=(
|
|
69
|
+
"SearXNG safe-search level: `0` disables filtering, `1` is moderate, "
|
|
70
|
+
"and `2` is strict. Omit to use `KIAPI_WEB_DEFAULT_SAFESEARCH`."
|
|
71
|
+
),
|
|
72
|
+
)
|
|
73
|
+
|
|
74
|
+
page: int = Field(
|
|
75
|
+
default=1,
|
|
76
|
+
ge=1,
|
|
77
|
+
description=(
|
|
78
|
+
"One-based SearXNG result page (`pageno`). kiapi fetches exactly one "
|
|
79
|
+
"page per request; increase this value to request the next page."
|
|
80
|
+
),
|
|
81
|
+
)
|
|
82
|
+
|
|
83
|
+
max_results: int | None = Field(
|
|
84
|
+
default=None,
|
|
85
|
+
ge=1,
|
|
86
|
+
description=(
|
|
87
|
+
"Maximum number of `results` to keep from the returned SearXNG page. "
|
|
88
|
+
"SearXNG has no native max-results parameter, so kiapi truncates "
|
|
89
|
+
"client-side. Omit to use `KIAPI_WEB_DEFAULT_MAX_RESULTS`; set the "
|
|
90
|
+
"server default to null to keep the full page."
|
|
91
|
+
),
|
|
92
|
+
examples=[5, 10],
|
|
93
|
+
)
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
"""web search response.
|
|
2
|
+
|
|
3
|
+
SearXNG's JSON is passed through with only the top level typed: the per-result
|
|
4
|
+
dicts are forwarded verbatim (``list[dict]``) so SearXNG's evolving fields
|
|
5
|
+
(``title``/``url``/``content``/``engine``/``score``/``img_src``/…) reach the
|
|
6
|
+
caller without kiapi re-modelling them. ``results`` is truncated to the request's
|
|
7
|
+
``max_results``; the auxiliary blocks (``answers``/``infoboxes``/``suggestions``)
|
|
8
|
+
are forwarded untruncated because agents find direct answers there.
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
from typing import Any
|
|
12
|
+
|
|
13
|
+
from pydantic import BaseModel, Field
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class SearchResponse(BaseModel):
|
|
17
|
+
query: str = Field(
|
|
18
|
+
description=(
|
|
19
|
+
"Normalized query returned by SearXNG. This usually matches the "
|
|
20
|
+
"submitted `query`, but SearXNG may normalize whitespace or operators."
|
|
21
|
+
)
|
|
22
|
+
)
|
|
23
|
+
results: list[dict[str, Any]] = Field(
|
|
24
|
+
description=(
|
|
25
|
+
"Search result dictionaries forwarded from SearXNG and truncated by "
|
|
26
|
+
"`max_results`. Common keys include `title`, `url`, `content`, "
|
|
27
|
+
"`engine`, `score`, `img_src`, and `publishedDate`; exact fields "
|
|
28
|
+
"depend on the engine and result type."
|
|
29
|
+
)
|
|
30
|
+
)
|
|
31
|
+
answers: list[Any] = Field(
|
|
32
|
+
description=("Direct-answer blocks from SearXNG, forwarded without truncation.")
|
|
33
|
+
)
|
|
34
|
+
infoboxes: list[Any] = Field(
|
|
35
|
+
description=(
|
|
36
|
+
"Knowledge-panel style infoboxes from SearXNG, forwarded without "
|
|
37
|
+
"truncation."
|
|
38
|
+
)
|
|
39
|
+
)
|
|
40
|
+
suggestions: list[Any] = Field(
|
|
41
|
+
description="Search suggestions from SearXNG, forwarded without truncation."
|
|
42
|
+
)
|
|
43
|
+
unresponsive_engines: list[Any] = Field(
|
|
44
|
+
description=(
|
|
45
|
+
"SearXNG `unresponsive_engines`: engines that failed or timed out for "
|
|
46
|
+
"this query, usually as `[engine, reason]` pairs. Results may still "
|
|
47
|
+
"be usable when this list is non-empty."
|
|
48
|
+
)
|
|
49
|
+
)
|
|
File without changes
|
|
File without changes
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
use_default_settings: true
|
|
2
|
+
|
|
3
|
+
server:
|
|
4
|
+
# Local-only backend; override with KIAPI_SEARXNG_SECRET in the environment.
|
|
5
|
+
secret_key: "kiapi-searxng-local-dev-secret-change-me"
|
|
6
|
+
|
|
7
|
+
search:
|
|
8
|
+
# kiapi consumes /search?format=json; SearXNG only enables json when listed here.
|
|
9
|
+
formats:
|
|
10
|
+
- html
|
|
11
|
+
- json
|