abstractcore 2.35.1__tar.gz → 2.35.2__tar.gz
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.
- {abstractcore-2.35.1 → abstractcore-2.35.2}/PKG-INFO +3 -1
- {abstractcore-2.35.1 → abstractcore-2.35.2}/README.md +2 -0
- abstractcore-2.35.2/abstractcore/config/hub_discovery.py +68 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/config/model_catalog.py +153 -68
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/config/models_engines_cli.py +6 -2
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/utils/version.py +1 -1
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore.egg-info/PKG-INFO +3 -1
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore.egg-info/SOURCES.txt +1 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/LICENSE +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/__init__.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/apps/__init__.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/apps/__main__.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/apps/app_config_utils.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/apps/deepsearch.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/apps/extractor.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/apps/intent.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/apps/judge.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/apps/summarizer.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/architectures/__init__.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/architectures/detection.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/architectures/enums.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/architectures/response_postprocessing.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/architectures/thinking_controls.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/assets/OCRA.ttf +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/assets/OCRB.ttf +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/assets/OCRBL.ttf +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/assets/README.md +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/assets/abstractframework_identity.json +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/assets/adapter_metadata.schema.json +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/assets/architecture_formats.json +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/assets/bloc-schema.jsonld +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/assets/llamacpp_known_architectures.json +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/assets/model_capabilities.json +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/assets/model_capabilities.schema.json +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/assets/model_downloads_catalog.json +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/assets/model_downloads_catalog.schema.json +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/assets/semantic_models.md +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/assets/session_schema.json +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/capabilities/__init__.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/capabilities/errors.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/capabilities/host.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/capabilities/music_selectors.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/capabilities/registry.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/capabilities/scene3d_selectors.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/capabilities/types.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/capabilities/vision_catalog.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/comms/__init__.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/comms/email/__init__.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/comms/email/bodystructure.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/comms/email/client.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/comms/email/context.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/comms/email/discovery.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/comms/email/errors.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/comms/email/imap_codec.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/comms/email/legacy.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/comms/email/limits.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/comms/email/models.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/comms/email/oauth.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/comms/email/policy.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/comms/email/search.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/comms/email/store.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/comms/email/vault.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/compression/__init__.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/compression/analytics.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/compression/cache.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/compression/config.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/compression/exceptions.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/compression/glyph_processor.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/compression/optimizer.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/compression/orchestrator.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/compression/pil_text_renderer.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/compression/quality.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/compression/text_formatter.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/compression/vision_compressor.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/config/__init__.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/config/capability_defaults.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/config/email_cli.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/config/engines.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/config/host_jobs.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/config/main.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/config/manager.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/config/model_contexts.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/config/model_materializer.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/config/model_verify.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/config/provider_profiles.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/config/recommendations.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/config/route_engines.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/config/vision_config.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/console/__init__.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/console/theme_sync.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/console/themes.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/console/web.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/core/__init__.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/core/bloc_kv.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/core/bloc_metadata.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/core/cached_session.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/core/degeneration.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/core/endpoint_damping.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/core/enums.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/core/factory.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/core/file_blocs.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/core/file_boxes.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/core/generate_contract.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/core/interface.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/core/multimodal_generation.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/core/output_specs.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/core/retry.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/core/session.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/core/types.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/decision/__init__.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/decision/backends/__init__.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/decision/backends/base.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/decision/backends/gguf.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/decision/backends/hf.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/decision/backends/logits.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/decision/backends/mlx.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/decision/convert.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/decision/encoding.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/decision/engines/__init__.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/decision/engines/base.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/decision/engines/labels.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/decision/engines/laya.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/decision/engines/remote.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/decision/gguf_compat.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/decision/head.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/decision/kinds.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/decision/loader.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/decision/pool.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/decision/render.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/decision/runtime.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/decision/tokenizers.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/decision/types.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/download.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/embeddings/__init__.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/embeddings/manager.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/embeddings/models.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/endpoint/__init__.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/endpoint/app.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/events/__init__.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/exceptions/__init__.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/mcp/__init__.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/mcp/client.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/mcp/factory.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/mcp/naming.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/mcp/stdio_client.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/mcp/tool_source.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/media/__init__.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/media/auto_handler.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/media/base.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/media/capabilities.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/media/delivery.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/media/enrichment.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/media/handlers/__init__.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/media/handlers/anthropic_handler.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/media/handlers/local_handler.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/media/handlers/openai_handler.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/media/openai_parts.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/media/pdf_routing.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/media/processors/__init__.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/media/processors/audio_processor.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/media/processors/direct_pdf_processor.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/media/processors/glyph_pdf_processor.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/media/processors/image_processor.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/media/processors/office_processor.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/media/processors/pdf_processor.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/media/processors/text_processor.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/media/processors/video_processor.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/media/types.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/media/utils/__init__.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/media/utils/image_scaler.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/media/utils/video_frames.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/media/vision_fallback.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/processing/__init__.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/processing/basic_deepsearch.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/processing/basic_extractor.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/processing/basic_intent.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/processing/basic_judge.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/processing/basic_summarizer.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/providers/__init__.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/providers/_http.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/providers/anthropic_provider.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/providers/base.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/providers/capability_host.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/providers/endpoint_context.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/providers/generation_cancel.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/providers/generation_progress.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/providers/gguf_shared.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/providers/gguf_slots.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/providers/hf_residency.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/providers/huggingface_provider.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/providers/lmstudio_provider.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/providers/mlx_hy_v3.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/providers/mlx_model_rules.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/providers/mlx_native_cache.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/providers/mlx_native_session.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/providers/mlx_prefill_observer.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/providers/mlx_provider.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/providers/mlx_qwen4.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/providers/mlx_residency.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/providers/mlx_runtime.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/providers/mlx_vision_addon.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/providers/model_capabilities.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/providers/model_config_fingerprint.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/providers/ollama_provider.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/providers/openai_compatible_provider.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/providers/openai_provider.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/providers/openrouter_provider.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/providers/portkey_provider.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/providers/process_residency.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/providers/registry.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/providers/speculation.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/providers/streaming.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/providers/tokenizer_fingerprint.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/providers/typesafe_provider.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/providers/vllm_provider.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/providers/weights_fingerprint.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/py.typed +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/server/__init__.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/server/__main__.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/server/app.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/server/audio_endpoints.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/server/auth_policy.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/server/camera_endpoints.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/server/capability_generation.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/server/console_routes.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/server/credentials.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/server/email_routes.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/server/first_run.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/server/host_routes.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/server/managed.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/server/scene3d_endpoints.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/server/session_routes.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/server/vision_endpoints.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/structured/__init__.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/structured/handler.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/structured/json_schema.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/structured/retry.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/structured/schema_compat.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/testing/__init__.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/testing/mailserver.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/tools/__init__.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/tools/abstractignore.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/tools/arg_canonicalizer.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/tools/arg_coercion.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/tools/browser_tools.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/tools/code_analysis.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/tools/common_tools.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/tools/comms_tools.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/tools/core.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/tools/email_digests.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/tools/fetch_url_ssrf.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/tools/handler.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/tools/inventory.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/tools/parser.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/tools/process_tree.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/tools/registry.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/tools/risk_facts.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/tools/sandbox.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/tools/shell_session.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/tools/shell_tools.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/tools/syntax_rewriter.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/tools/tag_rewriter.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/tools/telegram_tdlib.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/tools/telegram_tools.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/tools/wire_naming.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/utils/__init__.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/utils/async_stream.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/utils/cli.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/utils/context_calibration.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/utils/context_estimate.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/utils/data_registry.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/utils/display.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/utils/file_filters.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/utils/host_profile.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/utils/hostinfo.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/utils/identity.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/utils/install_settings.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/utils/jsonish.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/utils/kv_geometry.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/utils/llama_cuda_swap.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/utils/memory.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/utils/message_preprocessor.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/utils/model_cache.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/utils/model_fit.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/utils/residency.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/utils/self_fixes.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/utils/stdio.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/utils/structured_logging.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/utils/token_utils.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/utils/trace_export.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/utils/truncation.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/utils/vlm_token_calculator.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/utils/windows_dll.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/utils/workspace_paths.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore.egg-info/dependency_links.txt +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore.egg-info/entry_points.txt +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore.egg-info/requires.txt +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore.egg-info/top_level.txt +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/pyproject.toml +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/setup.cfg +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/tests/test_abstractendpoint_singleton_provider.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/tests/test_agentic_cli_compatibility.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/tests/test_basic_session.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/tests/test_bloc_kv.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/tests/test_bloc_kv_cache_dtype.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/tests/test_bloc_kv_endpoint.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/tests/test_bloc_kv_engine_fingerprint.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/tests/test_bloc_kv_model_config_fingerprint.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/tests/test_bloc_kv_tokenizer_fingerprint.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/tests/test_bloc_kv_weights_fingerprint.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/tests/test_bloc_metadata_json_extract.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/tests/test_cached_session_kv_mode.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/tests/test_cached_session_kv_thinking_prefix.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/tests/test_capabilities_registry.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/tests/test_capabilities_registry_preferred_backends_from_config.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/tests/test_changelog_fragments.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/tests/test_complete_integration.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/tests/test_comprehensive_events.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/tests/test_console_about.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/tests/test_console_email_tab.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/tests/test_console_web.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/tests/test_core_components.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/tests/test_display_rule.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/tests/test_email_digests.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/tests/test_embedding_model_shared_unit.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/tests/test_embedding_model_token_warnings.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/tests/test_enhanced_prompt.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/tests/test_environment_variable_tool_call_tags.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/tests/test_factory.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/tests/test_file_bloc_store_unit.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/tests/test_file_boxes_cached_session.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/tests/test_final_accuracy.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/tests/test_final_comprehensive.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/tests/test_final_graceful_errors.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/tests/test_generate_contract.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/tests/test_generate_response_reasoning_property_unit.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/tests/test_generate_with_outputs.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/tests/test_graceful_fallback.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/tests/test_import_debug.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/tests/test_import_safety.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/tests/test_incremental_thinking_tag_stripper.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/tests/test_install_hints_no_bare_packages.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/tests/test_install_scripts.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/tests/test_install_settings.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/tests/test_integrated_functionality.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/tests/test_llms_sources.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/tests/test_mcp_handshake.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/tests/test_mcp_integration.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/tests/test_mcp_stdio_client.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/tests/test_model_not_downloaded_error_unit.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/tests/test_multimodal_generate_output.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/tests/test_openai_prompt_cache_key_passthrough.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/tests/test_output_specs.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/tests/test_packaging_assets.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/tests/test_packaging_extras.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/tests/test_packaging_packages_listed.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/tests/test_prompt_cache_api.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/tests/test_prompt_cache_bloc_composition.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/tests/test_prompt_cache_bloc_e2e_gate.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/tests/test_prompt_cache_control_plane.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/tests/test_prompt_cache_prepare_modules_thinking_http.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/tests/test_retry_observability.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/tests/test_retry_strategy.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/tests/test_seed_determinism.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/tests/test_seed_temperature_basic.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/tests/test_sensory_prompting.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/tests/test_server_prompt_cache_control_plane_proxy.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/tests/test_server_prompt_cache_key_passthrough.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/tests/test_session_reasoning_persistence_unit.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/tests/test_sound_effect_seconds_route.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/tests/test_sse_starlette_pin_unit.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/tests/test_structured_output_truncation_retry.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/tests/test_text_only_model_experience.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/tests/test_timing_helper.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/tests/test_unload_memory.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/tests/test_user_scenario_validation.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/tests/test_voice_host_credentials.py +0 -0
- {abstractcore-2.35.1 → abstractcore-2.35.2}/tests/test_windows_host_fixes.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: abstractcore
|
|
3
|
-
Version: 2.35.
|
|
3
|
+
Version: 2.35.2
|
|
4
4
|
Summary: Unified interface to all LLM providers with essential infrastructure for tool calling, streaming, and model management
|
|
5
5
|
Author-email: Laurent-Philippe Albou <contact@abstractcore.ai>
|
|
6
6
|
Maintainer-email: Laurent-Philippe Albou <contact@abstractcore.ai>
|
|
@@ -197,6 +197,8 @@ Dynamic: license-file
|
|
|
197
197
|
Unified LLM Interface
|
|
198
198
|
> Write once, run everywhere
|
|
199
199
|
|
|
200
|
+
What's new in 2.35.2: Hugging Face searches use bounded summary pages and a shared quota cooldown. Full repository metadata is an explicit selected-repo action; missing sizes stay unknown or estimated. See [model discovery](docs/models.md#the-catalog).
|
|
201
|
+
|
|
200
202
|
What's new in 2.35.1: a plain `pip install "abstractcore[gpu]"` on a Linux NVIDIA machine now runs GGUF models on the GPU (AbstractCore installs llama.cpp's CUDA build itself, once, the first time it is needed). In 2.35.0: the model capability registry covers the current vendor lineups (GPT-6 and GPT-6.1, Claude 5.5 and Fable 5.1, Grok 4.3 to 4.7, Qwen 3.8, DeepSeek V4.1 Flash, GLM 5.3, MiniMax M3.1 Flash, Kimi K3 and K3.1 Pro, LFM3, Spark X2.5/X2.6, Nemotron 3.5, Bonsai 2 and more), so an image, video or voice route can name them; and a GGUF or MLX re-packaging of a registered model (`unsloth/...-GGUF:Q4_K_M`, `mlx-community/...-4bit`, bartowski's `Org_Model-GGUF`) resolves to that model's entry instead of the text-only default. Transcriptions report `language` and `detected_language`. See the [changelog](CHANGELOG.md#2351---2026-11-10).
|
|
201
203
|
|
|
202
204
|
What's new in 2.34.0: a local model that no call has used for 60 minutes is unloaded from memory and loads
|
|
@@ -9,6 +9,8 @@
|
|
|
9
9
|
Unified LLM Interface
|
|
10
10
|
> Write once, run everywhere
|
|
11
11
|
|
|
12
|
+
What's new in 2.35.2: Hugging Face searches use bounded summary pages and a shared quota cooldown. Full repository metadata is an explicit selected-repo action; missing sizes stay unknown or estimated. See [model discovery](docs/models.md#the-catalog).
|
|
13
|
+
|
|
12
14
|
What's new in 2.35.1: a plain `pip install "abstractcore[gpu]"` on a Linux NVIDIA machine now runs GGUF models on the GPU (AbstractCore installs llama.cpp's CUDA build itself, once, the first time it is needed). In 2.35.0: the model capability registry covers the current vendor lineups (GPT-6 and GPT-6.1, Claude 5.5 and Fable 5.1, Grok 4.3 to 4.7, Qwen 3.8, DeepSeek V4.1 Flash, GLM 5.3, MiniMax M3.1 Flash, Kimi K3 and K3.1 Pro, LFM3, Spark X2.5/X2.6, Nemotron 3.5, Bonsai 2 and more), so an image, video or voice route can name them; and a GGUF or MLX re-packaging of a registered model (`unsloth/...-GGUF:Q4_K_M`, `mlx-community/...-4bit`, bartowski's `Org_Model-GGUF`) resolves to that model's entry instead of the text-only default. Transcriptions report `language` and `detected_language`. See the [changelog](CHANGELOG.md#2351---2026-11-10).
|
|
13
15
|
|
|
14
16
|
What's new in 2.34.0: a local model that no call has used for 60 minutes is unloaded from memory and loads
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
"""Bounded, read-only Hub discovery. Download clients keep their own transport."""
|
|
2
|
+
from __future__ import annotations
|
|
3
|
+
|
|
4
|
+
import hashlib
|
|
5
|
+
import json
|
|
6
|
+
import time
|
|
7
|
+
from types import SimpleNamespace
|
|
8
|
+
from urllib.parse import quote, urlparse
|
|
9
|
+
|
|
10
|
+
import httpx
|
|
11
|
+
|
|
12
|
+
_EXPAND = ['siblings', 'gguf', 'safetensors', 'gated', 'downloads', 'library_name', 'pipeline_tag', 'tags']
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def _info(value):
|
|
16
|
+
value = dict(value)
|
|
17
|
+
value['siblings'] = [SimpleNamespace(rfilename=s.get('rfilename'), size=s.get('size')) for s in value.get('siblings') or []]
|
|
18
|
+
return SimpleNamespace(**value)
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class HubDiscovery:
|
|
22
|
+
"""One HTTP attempt per page/detail, no redirects/retries; bounded body/deadline.
|
|
23
|
+
|
|
24
|
+
Pagination follows only same-origin model-list links. Callers persist the next
|
|
25
|
+
URL so advancing a page never downloads its preceding prefix again.
|
|
26
|
+
"""
|
|
27
|
+
def __init__(self, *, endpoint=None, token=None, transport=None):
|
|
28
|
+
from huggingface_hub import constants
|
|
29
|
+
from huggingface_hub.utils._headers import get_token_to_send
|
|
30
|
+
self.endpoint = (endpoint or constants.ENDPOINT).rstrip('/')
|
|
31
|
+
# Older SDKs resolve the cached token before checking this setting.
|
|
32
|
+
# Anonymous discovery must not even read that credential when disabled.
|
|
33
|
+
self.token = '' if token is None and constants.HF_HUB_DISABLE_IMPLICIT_TOKEN else (get_token_to_send(token) or '')
|
|
34
|
+
# SDK user-agent construction can fetch an agent registry. Discovery
|
|
35
|
+
# owns every HTTP attempt, so do not invoke that telemetry path.
|
|
36
|
+
self.headers = {'user-agent': 'abstractcore-hub-discovery'}
|
|
37
|
+
if self.token:
|
|
38
|
+
self.headers['authorization'] = 'Bearer ' + self.token
|
|
39
|
+
self.scope = hashlib.sha256((self.endpoint + '\0' + (self.token or '')).encode()).hexdigest()
|
|
40
|
+
self.transport = transport
|
|
41
|
+
|
|
42
|
+
def _get(self, url, *, params=None):
|
|
43
|
+
target, origin = urlparse(url), urlparse(self.endpoint)
|
|
44
|
+
if (target.scheme, target.netloc) != (origin.scheme, origin.netloc) or (target.path != '/api/models' and params is None):
|
|
45
|
+
raise ValueError('Invalid Hub discovery pagination URL')
|
|
46
|
+
headers = self.headers
|
|
47
|
+
deadline = time.monotonic() + 20
|
|
48
|
+
with httpx.Client(transport=self.transport, timeout=httpx.Timeout(5, connect=3), follow_redirects=False, headers=headers) as client:
|
|
49
|
+
with client.stream('GET', url, params=params) as response:
|
|
50
|
+
response.raise_for_status()
|
|
51
|
+
parts, size = [], 0
|
|
52
|
+
for chunk in response.iter_bytes():
|
|
53
|
+
size += len(chunk)
|
|
54
|
+
if size > 16 * 1024 * 1024 or time.monotonic() > deadline:
|
|
55
|
+
raise TimeoutError('Hub discovery response exceeded its size or time budget')
|
|
56
|
+
parts.append(chunk)
|
|
57
|
+
return json.loads(b''.join(parts)), response.links.get('next', {}).get('url')
|
|
58
|
+
|
|
59
|
+
def list_models_page(self, *, search, filter, limit, cursor=None):
|
|
60
|
+
params = None if cursor else {'search': search, 'filter': filter, 'sort': 'downloads', 'direction': -1, 'limit': limit, 'expand': _EXPAND}
|
|
61
|
+
values, next_url = self._get(cursor or self.endpoint + '/api/models', params=params)
|
|
62
|
+
if not isinstance(values, list):
|
|
63
|
+
raise ValueError('Unexpected Hub search response')
|
|
64
|
+
return [_info(value) for value in values[:limit]], next_url
|
|
65
|
+
|
|
66
|
+
def model_info(self, repo_id, *, files_metadata=True):
|
|
67
|
+
value, _ = self._get(self.endpoint + '/api/models/' + quote(repo_id, safe='/'), params={'blobs': 'true'})
|
|
68
|
+
return _info(value)
|
|
@@ -9,19 +9,21 @@ exist elsewhere and must not be re-derived by any surface:
|
|
|
9
9
|
fit utils.model_fit.estimate_fit() against utils.host_profile()
|
|
10
10
|
hub (opt-in) Hugging Face sizes/params (+ free-text search rows)
|
|
11
11
|
|
|
12
|
-
THE HUB IS OPT-IN AND CACHED. `hub=False`
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
keystroke would be rate-limited within minutes.
|
|
12
|
+
THE HUB IS OPT-IN AND CACHED. `hub=False` never contacts the network. Search
|
|
13
|
+
uses bounded bulk summary pages, not per-result enrichment. Full file metadata
|
|
14
|
+
requires one explicit `detail_repo` (or an exact handle). Discovery shares a
|
|
15
|
+
credential-scoped rate-limit cooldown, follows bounded cursor pages without SDK
|
|
16
|
+
retries, and uses its own finite transport limits. Missing sizes stay unknown
|
|
17
|
+
or labelled estimates. Successful answers are cached for 24 hours.
|
|
18
|
+
|
|
20
19
|
"""
|
|
21
20
|
|
|
22
21
|
from __future__ import annotations
|
|
23
22
|
|
|
24
23
|
import functools
|
|
24
|
+
import hashlib
|
|
25
|
+
import math
|
|
26
|
+
from email.utils import parsedate_to_datetime
|
|
25
27
|
import json
|
|
26
28
|
import os
|
|
27
29
|
import re
|
|
@@ -1289,6 +1291,8 @@ class _HubCache:
|
|
|
1289
1291
|
if isinstance(loaded, dict):
|
|
1290
1292
|
self.data["models"] = dict(loaded.get("models") or {})
|
|
1291
1293
|
self.data["searches"] = dict(loaded.get("searches") or {})
|
|
1294
|
+
self.data["scope"] = loaded.get("scope")
|
|
1295
|
+
self.data["retry_at"] = loaded.get("retry_at")
|
|
1292
1296
|
except Exception:
|
|
1293
1297
|
pass
|
|
1294
1298
|
|
|
@@ -1302,6 +1306,9 @@ class _HubCache:
|
|
|
1302
1306
|
|
|
1303
1307
|
def put(self, bucket: str, key: str, value: Dict[str, Any]) -> None:
|
|
1304
1308
|
self.data[bucket][key] = dict(value, fetched_at=time.time())
|
|
1309
|
+
while len(self.data[bucket]) > 512:
|
|
1310
|
+
oldest = min(self.data[bucket], key=lambda k: self.data[bucket][k].get("fetched_at", 0))
|
|
1311
|
+
del self.data[bucket][oldest]
|
|
1305
1312
|
self.dirty = True
|
|
1306
1313
|
|
|
1307
1314
|
def save(self) -> None:
|
|
@@ -1317,7 +1324,52 @@ class _HubCache:
|
|
|
1317
1324
|
|
|
1318
1325
|
|
|
1319
1326
|
class _RateLimited(Exception):
|
|
1320
|
-
|
|
1327
|
+
def __init__(self, message: str, retry_at: Optional[float] = None):
|
|
1328
|
+
super().__init__(message)
|
|
1329
|
+
self.retry_at = retry_at or time.time() + 60
|
|
1330
|
+
|
|
1331
|
+
|
|
1332
|
+
def _rate_limit(exc: BaseException, api: Any) -> _RateLimited:
|
|
1333
|
+
now = time.time()
|
|
1334
|
+
headers = getattr(getattr(exc, "response", None), "headers", {}) or {}
|
|
1335
|
+
retry = headers.get("Retry-After")
|
|
1336
|
+
delay = None
|
|
1337
|
+
try:
|
|
1338
|
+
candidate = float(retry)
|
|
1339
|
+
if math.isfinite(candidate) and candidate > 0:
|
|
1340
|
+
delay = candidate
|
|
1341
|
+
except (TypeError, ValueError, OverflowError):
|
|
1342
|
+
try:
|
|
1343
|
+
candidate = parsedate_to_datetime(retry).timestamp() - now
|
|
1344
|
+
if math.isfinite(candidate) and candidate > 0:
|
|
1345
|
+
delay = candidate
|
|
1346
|
+
except (TypeError, ValueError, OverflowError):
|
|
1347
|
+
pass
|
|
1348
|
+
if delay is None:
|
|
1349
|
+
reset = re.search(r"(?:^|;)\s*t\s*=\s*(\d+)", str(headers.get("RateLimit") or ""), re.I)
|
|
1350
|
+
try:
|
|
1351
|
+
if reset:
|
|
1352
|
+
candidate = float(reset.group(1))
|
|
1353
|
+
else:
|
|
1354
|
+
raw = float(headers.get("X-RateLimit-Reset") or headers.get("RateLimit-Reset"))
|
|
1355
|
+
candidate = raw - now if raw > now else raw
|
|
1356
|
+
if math.isfinite(candidate) and candidate > 0:
|
|
1357
|
+
delay = candidate
|
|
1358
|
+
except (TypeError, ValueError, OverflowError):
|
|
1359
|
+
pass
|
|
1360
|
+
deadline = now + max(1, delay if delay is not None else 60)
|
|
1361
|
+
for key in list(_hub_cooldowns):
|
|
1362
|
+
if _hub_cooldowns[key] <= now:
|
|
1363
|
+
del _hub_cooldowns[key]
|
|
1364
|
+
_hub_cooldowns[_hub_scope(api)] = deadline
|
|
1365
|
+
return _RateLimited(str(exc), deadline)
|
|
1366
|
+
|
|
1367
|
+
|
|
1368
|
+
_hub_cooldowns: Dict[str, float] = {}
|
|
1369
|
+
|
|
1370
|
+
|
|
1371
|
+
def _hub_scope(api: Any) -> str:
|
|
1372
|
+
return str(getattr(api, "scope", "") or hashlib.sha256((str(getattr(api, "endpoint", "https://huggingface.co")) + "\0" + str(getattr(api, "token", "") or "")).encode()).hexdigest())
|
|
1321
1373
|
|
|
1322
1374
|
|
|
1323
1375
|
def _status_code(exc: BaseException) -> Optional[int]:
|
|
@@ -1330,10 +1382,10 @@ def _status_code(exc: BaseException) -> Optional[int]:
|
|
|
1330
1382
|
|
|
1331
1383
|
|
|
1332
1384
|
def _default_hf_api() -> Any:
|
|
1333
|
-
from
|
|
1385
|
+
from .hub_discovery import HubDiscovery
|
|
1334
1386
|
|
|
1335
1387
|
token = os.environ.get("HF_TOKEN") or os.environ.get("HUGGING_FACE_HUB_TOKEN") or None
|
|
1336
|
-
return
|
|
1388
|
+
return HubDiscovery(token=token)
|
|
1337
1389
|
|
|
1338
1390
|
|
|
1339
1391
|
def _hub_model_facts(api: Any, cache: _HubCache, repo_id: str) -> Dict[str, Any]:
|
|
@@ -1348,9 +1400,15 @@ def _hub_model_facts(api: Any, cache: _HubCache, repo_id: str) -> Dict[str, Any]
|
|
|
1348
1400
|
info = api.model_info(repo_id, files_metadata=True)
|
|
1349
1401
|
except Exception as exc:
|
|
1350
1402
|
if _status_code(exc) == 429:
|
|
1351
|
-
raise
|
|
1403
|
+
raise _rate_limit(exc, api) from exc
|
|
1352
1404
|
cache.put("models", repo_id, {"error": f"{type(exc).__name__}: {str(exc)[:200]}"})
|
|
1353
1405
|
raise LookupError(str(exc)) from exc
|
|
1406
|
+
facts = _hub_info_facts(info)
|
|
1407
|
+
cache.put("models", repo_id, facts)
|
|
1408
|
+
return facts
|
|
1409
|
+
|
|
1410
|
+
|
|
1411
|
+
def _hub_info_facts(info: Any) -> Dict[str, Any]:
|
|
1354
1412
|
siblings = []
|
|
1355
1413
|
for s in getattr(info, "siblings", None) or []:
|
|
1356
1414
|
name = getattr(s, "rfilename", None)
|
|
@@ -1374,7 +1432,6 @@ def _hub_model_facts(api: Any, cache: _HubCache, repo_id: str) -> Dict[str, Any]
|
|
|
1374
1432
|
"gated": bool(getattr(info, "gated", False)),
|
|
1375
1433
|
"gguf_architecture": str(arch).strip() if isinstance(arch, str) and arch.strip() else None,
|
|
1376
1434
|
}
|
|
1377
|
-
cache.put("models", repo_id, facts)
|
|
1378
1435
|
return facts
|
|
1379
1436
|
|
|
1380
1437
|
|
|
@@ -1386,6 +1443,8 @@ def _size_for(facts: Mapping[str, Any], patterns: Optional[List[str]]) -> Option
|
|
|
1386
1443
|
for name, size in facts.get("siblings") or []:
|
|
1387
1444
|
if patterns and not _matches_any(str(name), patterns):
|
|
1388
1445
|
continue
|
|
1446
|
+
if not isinstance(size, int):
|
|
1447
|
+
return None
|
|
1389
1448
|
if isinstance(size, int):
|
|
1390
1449
|
total += size
|
|
1391
1450
|
counted = True
|
|
@@ -1401,17 +1460,14 @@ def _hub_search(
|
|
|
1401
1460
|
*,
|
|
1402
1461
|
page: int = 1,
|
|
1403
1462
|
page_size: int = _HUB_SEARCH_LIMIT,
|
|
1463
|
+
cache_only: bool = False,
|
|
1404
1464
|
) -> Tuple[List[Dict[str, Any]], bool]:
|
|
1405
|
-
"""
|
|
1406
|
-
|
|
1407
|
-
Each lane (GGUF; MLX on Apple silicon) is asked for the results up to the end of `page`
|
|
1408
|
-
plus one, most downloaded first, and cached per depth; the page is that slice. A handle
|
|
1409
|
-
(`Qwen/Qwen3.5-9B`) searches its name (`Qwen3.5-9B`): the GGUF and MLX builds of a model
|
|
1410
|
-
live under other organisations (`catalog` looks the handle itself up)."""
|
|
1411
|
-
|
|
1465
|
+
"""Cached summary pages: one listing per lane, never per-hit metadata."""
|
|
1412
1466
|
term = query.split("/", 1)[1] if _HUB_HANDLE_RE.match(query) else query
|
|
1413
1467
|
start = (page - 1) * page_size
|
|
1414
|
-
|
|
1468
|
+
if start >= _HUB_SEARCH_MAX_RESULTS:
|
|
1469
|
+
return [], False
|
|
1470
|
+
limit = min(page_size, _HUB_SEARCH_MAX_RESULTS - start)
|
|
1415
1471
|
lanes: List[Tuple[str, str]] = []
|
|
1416
1472
|
if engine in (None, "", "mlx") and (accelerator == "metal" or engine == "mlx"):
|
|
1417
1473
|
lanes.append(("mlx", "mlx"))
|
|
@@ -1420,25 +1476,33 @@ def _hub_search(
|
|
|
1420
1476
|
out: List[Dict[str, Any]] = []
|
|
1421
1477
|
more = False
|
|
1422
1478
|
for tag, provider in lanes:
|
|
1423
|
-
|
|
1479
|
+
prefix = f"summary-v2:{tag}:{term.lower()}:{page_size}:"
|
|
1480
|
+
key = prefix + str(page)
|
|
1424
1481
|
hit = cache.get("searches", key)
|
|
1482
|
+
if hit is None and cache_only:
|
|
1483
|
+
continue
|
|
1425
1484
|
if hit is None:
|
|
1485
|
+
previous = cache.get("searches", prefix + str(page - 1)) if page > 1 else None
|
|
1486
|
+
if page > 1 and previous is not None and not previous.get("next"):
|
|
1487
|
+
cache.put("searches", key, {"results": [], "next": None})
|
|
1488
|
+
continue # this lane is exhausted; other lanes can still advance
|
|
1489
|
+
if page > 1 and previous is None:
|
|
1490
|
+
raise LookupError("Search page expired; start the search again before requesting the next page")
|
|
1426
1491
|
try:
|
|
1427
|
-
results = api.
|
|
1428
|
-
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
]
|
|
1492
|
+
results, cursor = api.list_models_page(search=term, filter=tag, limit=limit,
|
|
1493
|
+
cursor=previous.get("next") if previous else None)
|
|
1494
|
+
rows = [{"repo_id": str(getattr(m, "id", None) or getattr(m, "modelId", "")),
|
|
1495
|
+
"downloads": getattr(m, "downloads", None), "facts": _hub_info_facts(m)} for m in results]
|
|
1432
1496
|
except Exception as exc:
|
|
1433
1497
|
if _status_code(exc) == 429:
|
|
1434
|
-
raise
|
|
1498
|
+
raise _rate_limit(exc, api) from exc
|
|
1435
1499
|
raise LookupError(str(exc)) from exc
|
|
1436
|
-
|
|
1437
|
-
|
|
1438
|
-
|
|
1439
|
-
|
|
1440
|
-
|
|
1441
|
-
|
|
1500
|
+
hit = {"results": rows, "next": cursor}
|
|
1501
|
+
cache.put("searches", key, hit)
|
|
1502
|
+
more = more or (bool(hit.get("next")) and start + limit < _HUB_SEARCH_MAX_RESULTS)
|
|
1503
|
+
for row in hit.get("results") or []:
|
|
1504
|
+
if row.get("repo_id"):
|
|
1505
|
+
out.append(dict(row, provider=provider))
|
|
1442
1506
|
return out, more
|
|
1443
1507
|
|
|
1444
1508
|
|
|
@@ -1920,6 +1984,7 @@ def catalog(
|
|
|
1920
1984
|
hub_page: int = 1,
|
|
1921
1985
|
hub_page_size: int = _HUB_SEARCH_LIMIT,
|
|
1922
1986
|
extended: bool = False,
|
|
1987
|
+
detail_repo: Optional[str] = None,
|
|
1923
1988
|
) -> Dict[str, Any]:
|
|
1924
1989
|
"""Contract C: the `model_catalog_v1` payload.
|
|
1925
1990
|
|
|
@@ -1929,18 +1994,19 @@ def catalog(
|
|
|
1929
1994
|
fits keep only artifacts that fit this host (`FITS_FILTER_VERDICTS`:
|
|
1930
1995
|
`fits`, `tight`, or `needs_gpu_limit` -- fits once the Mac's GPU
|
|
1931
1996
|
memory limit is raised, the command in `fit.gpu_limit`)
|
|
1932
|
-
hub
|
|
1933
|
-
|
|
1997
|
+
hub append bounded Hugging Face summary search rows when `q` is given;
|
|
1998
|
+
curated rows keep their catalog sizes (no eager metadata enrichment)
|
|
1999
|
+
detail_repo
|
|
2000
|
+
one exact org/repo whose full metadata is explicitly requested (with hub)
|
|
1934
2001
|
tags keep only rows carrying every tag (e.g. ["embedding"])
|
|
1935
2002
|
hub_page, hub_page_size
|
|
1936
2003
|
which page of Hugging Face search results to append (1-based; 20 per lane
|
|
1937
2004
|
by default). `hub.search` reports the page, how many rows it added and
|
|
1938
2005
|
whether another page exists. A query that is an exact handle
|
|
1939
2006
|
(`Qwen/Qwen3.5-9B`) also looks that repo up and lists it first (page 1).
|
|
1940
|
-
extended
|
|
1941
|
-
|
|
1942
|
-
|
|
1943
|
-
fetch exactly is left out. Never the pre-selection.
|
|
2007
|
+
extended lists verified quant labels from available summary/detail facts;
|
|
2008
|
+
it never causes additional repo lookups. Sizes may be unknown until
|
|
2009
|
+
explicit details. Variants are marked `extended`, never preselected.
|
|
1944
2010
|
"""
|
|
1945
2011
|
|
|
1946
2012
|
from ..utils.host_profile import host_profile, utc_now_iso
|
|
@@ -1958,7 +2024,11 @@ def catalog(
|
|
|
1958
2024
|
page_size = min(100, max(1, int(hub_page_size)))
|
|
1959
2025
|
except (TypeError, ValueError):
|
|
1960
2026
|
page_size = _HUB_SEARCH_LIMIT
|
|
1961
|
-
|
|
2027
|
+
if detail_repo and not hub:
|
|
2028
|
+
raise ValueError("detail_repo requires hub=True")
|
|
2029
|
+
if detail_repo and not _HUB_HANDLE_RE.fullmatch(detail_repo):
|
|
2030
|
+
raise ValueError("detail_repo must be one exact org/repo handle")
|
|
2031
|
+
handle = detail_repo or (query if _HUB_HANDLE_RE.match(query) else None)
|
|
1962
2032
|
search_more = False
|
|
1963
2033
|
want_tags = [_norm(t) for t in (tags or []) if _norm(t)]
|
|
1964
2034
|
seed = load_seed()
|
|
@@ -1999,42 +2069,53 @@ def catalog(
|
|
|
1999
2069
|
hub_block.update(ok=False)
|
|
2000
2070
|
hub_block["errors"].append(f"huggingface_hub unavailable: {exc}")
|
|
2001
2071
|
if api is not None:
|
|
2002
|
-
|
|
2003
|
-
|
|
2004
|
-
|
|
2005
|
-
|
|
2006
|
-
repo = mm.hf_artifact_parts(a["artifact"])[0]
|
|
2007
|
-
if repo not in repos:
|
|
2008
|
-
repos.append(repo)
|
|
2072
|
+
# Partition cache by endpoint and effective credentials; no token is serialized.
|
|
2073
|
+
scope = _hub_scope(api)
|
|
2074
|
+
if cache.data.get("scope") != scope:
|
|
2075
|
+
cache.data = {"models": {}, "searches": {}, "scope": scope}
|
|
2009
2076
|
try:
|
|
2077
|
+
cooldown = max(float(cache.data.get("retry_at") or 0), _hub_cooldowns.get(scope, 0))
|
|
2078
|
+
if cooldown > time.time():
|
|
2079
|
+
raise _RateLimited("discovery cooldown active", cooldown)
|
|
2010
2080
|
if handle and page == 1:
|
|
2011
2081
|
try:
|
|
2012
|
-
|
|
2082
|
+
was_cached = cache.get("models", handle) is not None
|
|
2083
|
+
facts = _hub_model_facts(api, cache, handle)
|
|
2084
|
+
hub_ctx["facts"][handle] = facts
|
|
2085
|
+
hub_block["cached" if was_cached else "fetched"] += 1
|
|
2086
|
+
exact = _hub_handle_hit(facts, handle)
|
|
2013
2087
|
except LookupError:
|
|
2014
|
-
exact = None
|
|
2088
|
+
exact = None
|
|
2015
2089
|
if exact is not None:
|
|
2016
2090
|
search_hits.append(exact)
|
|
2017
|
-
if query:
|
|
2091
|
+
if query and not detail_repo:
|
|
2018
2092
|
hits, search_more = _hub_search(api, cache, query, eng, accelerator, page=page, page_size=page_size)
|
|
2019
2093
|
search_hits.extend(hits)
|
|
2020
|
-
for hit in
|
|
2021
|
-
|
|
2022
|
-
|
|
2023
|
-
|
|
2024
|
-
|
|
2025
|
-
|
|
2026
|
-
|
|
2027
|
-
hub_block["cached" if was_cached else "fetched"] += 1
|
|
2028
|
-
except LookupError as exc:
|
|
2029
|
-
hub_block["errors"].append(f"{repo}: {str(exc)[:160]}")
|
|
2094
|
+
for hit in hits:
|
|
2095
|
+
repo = hit["repo_id"]
|
|
2096
|
+
# An explicitly fetched detail may enrich a listing, never trigger another request.
|
|
2097
|
+
hub_ctx["facts"].setdefault(repo, cache.get("models", repo) or hit.get("facts") or {})
|
|
2098
|
+
# Curated rows keep their verified catalog sizes. Enrichment is explicit and single-repo.
|
|
2099
|
+
if not query and not detail_repo:
|
|
2100
|
+
hub_block["mode"] = "offline"
|
|
2030
2101
|
except _RateLimited as exc:
|
|
2031
|
-
|
|
2032
|
-
|
|
2102
|
+
cache.data["retry_at"] = exc.retry_at
|
|
2103
|
+
cache.dirty = True
|
|
2104
|
+
hub_block.update(ok=False, rate_limited=True, retry_at=exc.retry_at,
|
|
2105
|
+
retry_after_seconds=max(1, math.ceil(exc.retry_at - time.time())))
|
|
2106
|
+
hub_block["errors"].append("rate limited by the Hugging Face API (429); wait until the retry deadline")
|
|
2107
|
+
if query and not detail_repo:
|
|
2108
|
+
cached_hits, search_more = _hub_search(api, cache, query, eng, accelerator,
|
|
2109
|
+
page=page, page_size=page_size, cache_only=True)
|
|
2110
|
+
seen = {hit["repo_id"] for hit in search_hits}
|
|
2111
|
+
for hit in cached_hits:
|
|
2112
|
+
if hit["repo_id"] not in seen:
|
|
2113
|
+
search_hits.append(hit)
|
|
2114
|
+
hub_ctx["facts"].setdefault(hit["repo_id"], hit.get("facts") or {})
|
|
2115
|
+
hub_block["cached_results"] = bool(cached_hits)
|
|
2033
2116
|
except LookupError as exc:
|
|
2034
2117
|
hub_block.update(ok=False)
|
|
2035
|
-
hub_block["errors"].append(f"hub search failed
|
|
2036
|
-
if repos and not (hub_block["fetched"] or hub_block["cached"]):
|
|
2037
|
-
hub_block["ok"] = False # every lookup failed: offline or blocked
|
|
2118
|
+
hub_block["errors"].append(f"hub search failed: {str(exc)[:200]}")
|
|
2038
2119
|
cache.save()
|
|
2039
2120
|
|
|
2040
2121
|
try:
|
|
@@ -2159,8 +2240,7 @@ def catalog(
|
|
|
2159
2240
|
quant = _pick_gguf_quant(facts)
|
|
2160
2241
|
if quant:
|
|
2161
2242
|
artifact = f"{artifact}:{quant}"
|
|
2162
|
-
|
|
2163
|
-
continue # a GGUF repo with no recognisable quant file is not one click
|
|
2243
|
+
# Missing summary siblings remain discoverable; require explicit details before download.
|
|
2164
2244
|
# else: the exact handle of a Transformers checkpoint, fetched whole
|
|
2165
2245
|
elif provider == "mlx":
|
|
2166
2246
|
import re as _re
|
|
@@ -2179,6 +2259,8 @@ def catalog(
|
|
|
2179
2259
|
hub_ctx,
|
|
2180
2260
|
installed_sizes,
|
|
2181
2261
|
)
|
|
2262
|
+
if provider == "huggingface" and not quant and not hit.get("exact"):
|
|
2263
|
+
art.update(downloadable=False, recommended=False, details_required=True)
|
|
2182
2264
|
name = hit["repo_id"].rsplit("/", 1)[-1]
|
|
2183
2265
|
row = {
|
|
2184
2266
|
"id": "hf:" + hit["repo_id"].lower(),
|
|
@@ -2191,6 +2273,7 @@ def catalog(
|
|
|
2191
2273
|
"license": None,
|
|
2192
2274
|
"capabilities": caps,
|
|
2193
2275
|
"source": "hf_search",
|
|
2276
|
+
"detail_repo": hit["repo_id"],
|
|
2194
2277
|
"tags": tags_hit,
|
|
2195
2278
|
"starter": False,
|
|
2196
2279
|
"notes": (
|
|
@@ -2202,6 +2285,8 @@ def catalog(
|
|
|
2202
2285
|
"exact": bool(hit.get("exact")),
|
|
2203
2286
|
"artifacts": [art],
|
|
2204
2287
|
}
|
|
2288
|
+
if extended and detail_repo and quant:
|
|
2289
|
+
row["artifacts"] += _extended_quant_artifacts(row, row["artifacts"], caps, profile, support, hub_ctx, installed_sizes)
|
|
2205
2290
|
if asset_kind == "adapter":
|
|
2206
2291
|
art["asset_kind"] = "adapter"
|
|
2207
2292
|
art["fit"] = {"verdict":"unknown", "notes":[]}
|
|
@@ -296,7 +296,9 @@ def _handle_repair_refs(args: argparse.Namespace) -> int:
|
|
|
296
296
|
def _catalog_args(parser: argparse.ArgumentParser) -> None:
|
|
297
297
|
parser.add_argument("--engine", default=None, help="Only artifacts for this engine/provider (ollama, lmstudio, mlx, huggingface, llamacpp)")
|
|
298
298
|
parser.add_argument("--fits", action="store_true", help="Only artifacts that fit this machine (fits or tight)")
|
|
299
|
-
parser.add_argument("--hub", action="store_true", help="
|
|
299
|
+
parser.add_argument("--hub", action="store_true", help="Search Hugging Face summary pages; cached 24 h")
|
|
300
|
+
parser.add_argument("--detail-repo", default=None, help="Read full metadata for one selected org/repo (implies --hub)")
|
|
301
|
+
parser.add_argument("--extended", action="store_true", help="List verified quant variants from available metadata")
|
|
300
302
|
parser.add_argument("--tag", action="append", default=None, help="Only rows with this tag (repeatable): chat, coding, vision, embedding...")
|
|
301
303
|
parser.add_argument("--json", action="store_true", help="Emit model_catalog_v1 JSON")
|
|
302
304
|
|
|
@@ -337,8 +339,10 @@ def _handle_catalog(args: argparse.Namespace) -> int:
|
|
|
337
339
|
getattr(args, "query", None),
|
|
338
340
|
engine=args.engine,
|
|
339
341
|
fits=bool(args.fits),
|
|
340
|
-
hub=bool(args.hub),
|
|
342
|
+
hub=bool(args.hub or getattr(args, "detail_repo", None)),
|
|
341
343
|
tags=args.tag,
|
|
344
|
+
**({"detail_repo": args.detail_repo} if getattr(args, "detail_repo", None) else {}),
|
|
345
|
+
**({"extended": True} if getattr(args, "extended", False) else {}),
|
|
342
346
|
)
|
|
343
347
|
if args.json:
|
|
344
348
|
_print_json(payload)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: abstractcore
|
|
3
|
-
Version: 2.35.
|
|
3
|
+
Version: 2.35.2
|
|
4
4
|
Summary: Unified interface to all LLM providers with essential infrastructure for tool calling, streaming, and model management
|
|
5
5
|
Author-email: Laurent-Philippe Albou <contact@abstractcore.ai>
|
|
6
6
|
Maintainer-email: Laurent-Philippe Albou <contact@abstractcore.ai>
|
|
@@ -197,6 +197,8 @@ Dynamic: license-file
|
|
|
197
197
|
Unified LLM Interface
|
|
198
198
|
> Write once, run everywhere
|
|
199
199
|
|
|
200
|
+
What's new in 2.35.2: Hugging Face searches use bounded summary pages and a shared quota cooldown. Full repository metadata is an explicit selected-repo action; missing sizes stay unknown or estimated. See [model discovery](docs/models.md#the-catalog).
|
|
201
|
+
|
|
200
202
|
What's new in 2.35.1: a plain `pip install "abstractcore[gpu]"` on a Linux NVIDIA machine now runs GGUF models on the GPU (AbstractCore installs llama.cpp's CUDA build itself, once, the first time it is needed). In 2.35.0: the model capability registry covers the current vendor lineups (GPT-6 and GPT-6.1, Claude 5.5 and Fable 5.1, Grok 4.3 to 4.7, Qwen 3.8, DeepSeek V4.1 Flash, GLM 5.3, MiniMax M3.1 Flash, Kimi K3 and K3.1 Pro, LFM3, Spark X2.5/X2.6, Nemotron 3.5, Bonsai 2 and more), so an image, video or voice route can name them; and a GGUF or MLX re-packaging of a registered model (`unsloth/...-GGUF:Q4_K_M`, `mlx-community/...-4bit`, bartowski's `Org_Model-GGUF`) resolves to that model's entry instead of the text-only default. Transcriptions report `language` and `detected_language`. See the [changelog](CHANGELOG.md#2351---2026-11-10).
|
|
201
203
|
|
|
202
204
|
What's new in 2.34.0: a local model that no call has used for 60 minutes is unloaded from memory and loads
|
|
@@ -79,6 +79,7 @@ abstractcore/config/capability_defaults.py
|
|
|
79
79
|
abstractcore/config/email_cli.py
|
|
80
80
|
abstractcore/config/engines.py
|
|
81
81
|
abstractcore/config/host_jobs.py
|
|
82
|
+
abstractcore/config/hub_discovery.py
|
|
82
83
|
abstractcore/config/main.py
|
|
83
84
|
abstractcore/config/manager.py
|
|
84
85
|
abstractcore/config/model_catalog.py
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/architectures/response_postprocessing.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/assets/abstractframework_identity.json
RENAMED
|
File without changes
|
{abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/assets/adapter_metadata.schema.json
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/assets/llamacpp_known_architectures.json
RENAMED
|
File without changes
|
|
File without changes
|
{abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/assets/model_capabilities.schema.json
RENAMED
|
File without changes
|
{abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/assets/model_downloads_catalog.json
RENAMED
|
File without changes
|
{abstractcore-2.35.1 → abstractcore-2.35.2}/abstractcore/assets/model_downloads_catalog.schema.json
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|