abstractcore 2.26.0__tar.gz → 2.26.3__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.26.0 → abstractcore-2.26.3}/PKG-INFO +1 -1
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/apps/deepsearch.py +3 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/apps/extractor.py +3 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/apps/intent.py +3 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/apps/judge.py +3 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/apps/summarizer.py +3 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/capabilities/vision_catalog.py +2 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/config/main.py +3 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/config/model_materializer.py +55 -2
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/endpoint/app.py +3 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/providers/huggingface_provider.py +12 -1
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/tools/process_tree.py +11 -1
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/tools/sandbox.py +8 -2
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/utils/cli.py +3 -0
- abstractcore-2.26.3/abstractcore/utils/stdio.py +29 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/utils/version.py +1 -1
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore.egg-info/PKG-INFO +1 -1
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore.egg-info/SOURCES.txt +3 -1
- abstractcore-2.26.3/tests/test_windows_host_fixes.py +176 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/LICENSE +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/README.md +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/__init__.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/apps/__init__.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/apps/__main__.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/apps/app_config_utils.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/architectures/__init__.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/architectures/detection.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/architectures/enums.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/architectures/response_postprocessing.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/architectures/thinking_controls.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/assets/OCRA.ttf +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/assets/OCRB.ttf +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/assets/OCRBL.ttf +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/assets/README.md +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/assets/abstractframework_identity.json +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/assets/architecture_formats.json +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/assets/bloc-schema.jsonld +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/assets/model_capabilities.json +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/assets/model_capabilities.schema.json +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/assets/model_downloads_catalog.json +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/assets/model_downloads_catalog.schema.json +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/assets/semantic_models.md +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/assets/session_schema.json +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/capabilities/__init__.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/capabilities/errors.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/capabilities/host.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/capabilities/music_selectors.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/capabilities/registry.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/capabilities/scene3d_selectors.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/capabilities/types.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/comms/__init__.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/comms/email/__init__.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/comms/email/bodystructure.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/comms/email/client.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/comms/email/context.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/comms/email/discovery.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/comms/email/errors.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/comms/email/imap_codec.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/comms/email/legacy.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/comms/email/limits.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/comms/email/models.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/comms/email/oauth.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/comms/email/policy.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/comms/email/search.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/comms/email/store.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/comms/email/vault.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/compression/__init__.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/compression/analytics.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/compression/cache.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/compression/config.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/compression/exceptions.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/compression/glyph_processor.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/compression/optimizer.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/compression/orchestrator.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/compression/pil_text_renderer.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/compression/quality.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/compression/text_formatter.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/compression/vision_compressor.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/config/__init__.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/config/capability_defaults.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/config/email_cli.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/config/engines.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/config/host_jobs.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/config/manager.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/config/model_catalog.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/config/model_verify.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/config/models_engines_cli.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/config/provider_profiles.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/config/recommendations.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/config/route_engines.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/config/vision_config.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/console/__init__.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/console/theme_sync.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/console/themes.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/console/web.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/core/__init__.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/core/bloc_kv.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/core/bloc_metadata.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/core/cached_session.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/core/degeneration.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/core/endpoint_damping.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/core/enums.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/core/factory.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/core/file_blocs.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/core/file_boxes.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/core/generate_contract.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/core/interface.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/core/multimodal_generation.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/core/output_specs.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/core/retry.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/core/session.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/core/types.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/download.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/embeddings/__init__.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/embeddings/manager.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/embeddings/models.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/endpoint/__init__.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/events/__init__.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/exceptions/__init__.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/mcp/__init__.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/mcp/client.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/mcp/factory.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/mcp/naming.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/mcp/stdio_client.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/mcp/tool_source.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/media/__init__.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/media/auto_handler.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/media/base.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/media/capabilities.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/media/delivery.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/media/enrichment.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/media/handlers/__init__.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/media/handlers/anthropic_handler.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/media/handlers/local_handler.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/media/handlers/openai_handler.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/media/openai_parts.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/media/pdf_routing.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/media/processors/__init__.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/media/processors/audio_processor.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/media/processors/direct_pdf_processor.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/media/processors/glyph_pdf_processor.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/media/processors/image_processor.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/media/processors/office_processor.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/media/processors/pdf_processor.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/media/processors/text_processor.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/media/processors/video_processor.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/media/types.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/media/utils/__init__.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/media/utils/image_scaler.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/media/utils/video_frames.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/media/vision_fallback.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/processing/__init__.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/processing/basic_deepsearch.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/processing/basic_extractor.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/processing/basic_intent.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/processing/basic_judge.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/processing/basic_summarizer.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/providers/__init__.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/providers/_http.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/providers/anthropic_provider.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/providers/base.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/providers/capability_host.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/providers/endpoint_context.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/providers/generation_cancel.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/providers/generation_progress.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/providers/hf_residency.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/providers/lmstudio_provider.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/providers/mlx_model_rules.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/providers/mlx_native_cache.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/providers/mlx_native_session.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/providers/mlx_prefill_observer.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/providers/mlx_provider.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/providers/mlx_qwen4.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/providers/mlx_residency.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/providers/mlx_runtime.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/providers/mlx_vision_addon.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/providers/model_capabilities.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/providers/model_config_fingerprint.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/providers/ollama_provider.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/providers/openai_compatible_provider.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/providers/openai_provider.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/providers/openrouter_provider.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/providers/portkey_provider.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/providers/process_residency.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/providers/registry.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/providers/speculation.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/providers/streaming.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/providers/tokenizer_fingerprint.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/providers/vllm_provider.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/providers/weights_fingerprint.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/py.typed +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/server/__init__.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/server/__main__.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/server/app.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/server/audio_endpoints.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/server/auth_policy.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/server/camera_endpoints.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/server/capability_generation.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/server/console_routes.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/server/credentials.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/server/email_routes.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/server/first_run.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/server/host_routes.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/server/scene3d_endpoints.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/server/session_routes.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/server/vision_endpoints.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/structured/__init__.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/structured/handler.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/structured/json_schema.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/structured/retry.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/structured/schema_compat.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/testing/__init__.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/testing/mailserver.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/tools/__init__.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/tools/abstractignore.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/tools/arg_canonicalizer.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/tools/arg_coercion.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/tools/browser_tools.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/tools/code_analysis.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/tools/common_tools.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/tools/comms_tools.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/tools/core.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/tools/email_digests.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/tools/fetch_url_ssrf.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/tools/handler.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/tools/inventory.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/tools/parser.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/tools/registry.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/tools/risk_facts.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/tools/shell_session.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/tools/shell_tools.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/tools/syntax_rewriter.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/tools/tag_rewriter.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/tools/telegram_tdlib.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/tools/telegram_tools.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/tools/wire_naming.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/utils/__init__.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/utils/async_stream.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/utils/context_calibration.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/utils/context_estimate.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/utils/data_registry.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/utils/display.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/utils/file_filters.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/utils/host_profile.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/utils/hostinfo.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/utils/identity.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/utils/install_settings.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/utils/jsonish.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/utils/memory.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/utils/message_preprocessor.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/utils/model_cache.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/utils/model_fit.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/utils/residency.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/utils/self_fixes.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/utils/structured_logging.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/utils/token_utils.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/utils/trace_export.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/utils/truncation.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/utils/vlm_token_calculator.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/utils/windows_dll.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/utils/workspace_paths.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore.egg-info/dependency_links.txt +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore.egg-info/entry_points.txt +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore.egg-info/requires.txt +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore.egg-info/top_level.txt +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/pyproject.toml +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/setup.cfg +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/tests/test_abstractendpoint_singleton_provider.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/tests/test_agentic_cli_compatibility.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/tests/test_basic_session.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/tests/test_bloc_kv.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/tests/test_bloc_kv_cache_dtype.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/tests/test_bloc_kv_endpoint.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/tests/test_bloc_kv_engine_fingerprint.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/tests/test_bloc_kv_model_config_fingerprint.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/tests/test_bloc_kv_tokenizer_fingerprint.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/tests/test_bloc_kv_weights_fingerprint.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/tests/test_bloc_metadata_json_extract.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/tests/test_cached_session_kv_mode.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/tests/test_cached_session_kv_thinking_prefix.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/tests/test_capabilities_registry.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/tests/test_capabilities_registry_preferred_backends_from_config.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/tests/test_complete_integration.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/tests/test_comprehensive_events.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/tests/test_console_about.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/tests/test_console_email_tab.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/tests/test_console_web.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/tests/test_core_components.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/tests/test_display_rule.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/tests/test_email_digests.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/tests/test_embedding_model_token_warnings.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/tests/test_enhanced_prompt.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/tests/test_environment_variable_tool_call_tags.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/tests/test_factory.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/tests/test_file_bloc_store_unit.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/tests/test_file_boxes_cached_session.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/tests/test_final_accuracy.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/tests/test_final_comprehensive.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/tests/test_final_graceful_errors.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/tests/test_generate_contract.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/tests/test_generate_response_reasoning_property_unit.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/tests/test_generate_with_outputs.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/tests/test_graceful_fallback.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/tests/test_import_debug.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/tests/test_import_safety.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/tests/test_incremental_thinking_tag_stripper.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/tests/test_install_hints_no_bare_packages.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/tests/test_install_settings.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/tests/test_integrated_functionality.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/tests/test_llms_sources.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/tests/test_mcp_handshake.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/tests/test_mcp_integration.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/tests/test_mcp_stdio_client.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/tests/test_multimodal_generate_output.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/tests/test_openai_prompt_cache_key_passthrough.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/tests/test_output_specs.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/tests/test_packaging_assets.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/tests/test_packaging_extras.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/tests/test_prompt_cache_api.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/tests/test_prompt_cache_bloc_composition.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/tests/test_prompt_cache_bloc_e2e_gate.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/tests/test_prompt_cache_control_plane.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/tests/test_prompt_cache_prepare_modules_thinking_http.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/tests/test_retry_observability.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/tests/test_retry_strategy.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/tests/test_seed_determinism.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/tests/test_seed_temperature_basic.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/tests/test_sensory_prompting.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/tests/test_server_prompt_cache_control_plane_proxy.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/tests/test_server_prompt_cache_key_passthrough.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/tests/test_session_reasoning_persistence_unit.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/tests/test_sound_effect_seconds_route.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/tests/test_structured_output_truncation_retry.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/tests/test_text_only_model_experience.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/tests/test_unload_memory.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/tests/test_user_scenario_validation.py +0 -0
- {abstractcore-2.26.0 → abstractcore-2.26.3}/tests/test_voice_host_credentials.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: abstractcore
|
|
3
|
-
Version: 2.26.
|
|
3
|
+
Version: 2.26.3
|
|
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>
|
|
@@ -348,6 +348,9 @@ def print_report(report, format_type: str) -> None:
|
|
|
348
348
|
|
|
349
349
|
def main():
|
|
350
350
|
"""Main CLI function"""
|
|
351
|
+
from abstractcore.utils.stdio import safe_stdio
|
|
352
|
+
|
|
353
|
+
safe_stdio()
|
|
351
354
|
parser = argparse.ArgumentParser(
|
|
352
355
|
description="AbstractCore Deep Search - Autonomous research agent",
|
|
353
356
|
formatter_class=argparse.RawDescriptionHelpFormatter,
|
|
@@ -145,6 +145,9 @@ def parse_extraction_length(length_str: Optional[str]) -> str:
|
|
|
145
145
|
|
|
146
146
|
def main():
|
|
147
147
|
"""Main CLI function"""
|
|
148
|
+
from abstractcore.utils.stdio import safe_stdio
|
|
149
|
+
|
|
150
|
+
safe_stdio()
|
|
148
151
|
parser = argparse.ArgumentParser(
|
|
149
152
|
description="AbstractCore Entity & Relationship Extractor - Default: qwen3:4b-instruct-2507-q4_K_M (requires Ollama)",
|
|
150
153
|
formatter_class=argparse.RawDescriptionHelpFormatter,
|
|
@@ -344,6 +344,9 @@ def _format_single_analysis_plain(analysis, analysis_time: float = None) -> list
|
|
|
344
344
|
|
|
345
345
|
def main():
|
|
346
346
|
"""Main CLI function"""
|
|
347
|
+
from abstractcore.utils.stdio import safe_stdio
|
|
348
|
+
|
|
349
|
+
safe_stdio()
|
|
347
350
|
parser = argparse.ArgumentParser(
|
|
348
351
|
description="AbstractCore Intent Analyzer - Identify and analyze intents behind text",
|
|
349
352
|
formatter_class=argparse.RawDescriptionHelpFormatter,
|
|
@@ -283,6 +283,9 @@ def format_assessment_plain(assessment: dict) -> str:
|
|
|
283
283
|
|
|
284
284
|
def main():
|
|
285
285
|
"""Main CLI function"""
|
|
286
|
+
from abstractcore.utils.stdio import safe_stdio
|
|
287
|
+
|
|
288
|
+
safe_stdio()
|
|
286
289
|
parser = argparse.ArgumentParser(
|
|
287
290
|
description="AbstractCore Basic Judge - LLM-as-a-judge for objective evaluation (Default: qwen3:4b-instruct-2507-q4_K_M)",
|
|
288
291
|
formatter_class=argparse.RawDescriptionHelpFormatter,
|
|
@@ -207,6 +207,9 @@ def format_summary_output(result) -> str:
|
|
|
207
207
|
|
|
208
208
|
def main():
|
|
209
209
|
"""Main CLI function"""
|
|
210
|
+
from abstractcore.utils.stdio import safe_stdio
|
|
211
|
+
|
|
212
|
+
safe_stdio()
|
|
210
213
|
parser = argparse.ArgumentParser(
|
|
211
214
|
description="AbstractCore Document Summarizer - Default: gemma3:1b-it-qat (requires Ollama)",
|
|
212
215
|
formatter_class=argparse.RawDescriptionHelpFormatter,
|
|
@@ -308,6 +308,8 @@ def _default_lmstudio_model_dirs() -> list[Path]:
|
|
|
308
308
|
|
|
309
309
|
sysname = platform.system().lower()
|
|
310
310
|
home = Path.home()
|
|
311
|
+
# LM Studio 0.3+ keeps its models in ~/.lmstudio/models on every OS (as utils/model_cache).
|
|
312
|
+
dirs.append(str(home / ".lmstudio" / "models"))
|
|
311
313
|
if sysname == "darwin":
|
|
312
314
|
dirs.append(str(home / "Library" / "Application Support" / "LM Studio" / "models"))
|
|
313
315
|
elif sysname == "linux":
|
|
@@ -3170,8 +3170,11 @@ def _hf_marker_unfinished(repo_dir: Path) -> Optional[int]:
|
|
|
3170
3170
|
etag = entry.get("etag") if isinstance(entry, dict) else None
|
|
3171
3171
|
size = entry.get("size") if isinstance(entry, dict) else None
|
|
3172
3172
|
blob = repo_dir / "blobs" / str(etag or "")
|
|
3173
|
+
name = entry.get("name") if isinstance(entry, dict) else None
|
|
3173
3174
|
try:
|
|
3174
3175
|
whole = bool(etag) and blob.is_file() and (not isinstance(size, int) or blob.stat().st_size == size)
|
|
3176
|
+
if not whole and etag and isinstance(name, str):
|
|
3177
|
+
whole = _hf_snapshot_copy_size(repo_dir, name, size if isinstance(size, int) else None) is not None
|
|
3175
3178
|
except Exception:
|
|
3176
3179
|
whole = False
|
|
3177
3180
|
if not whole:
|
|
@@ -3389,8 +3392,37 @@ def repair_hf_refs(*, apply: bool = False, cache_dirs: Optional[Iterable[Path]]
|
|
|
3389
3392
|
return {"apply": bool(apply), "cache_dirs": [str(d) for d in dirs], "rows": rows, "counts": counts}
|
|
3390
3393
|
|
|
3391
3394
|
|
|
3395
|
+
def _hf_snapshot_copy_size(repo_dir: Path, name: str, size: Optional[int]) -> Optional[int]:
|
|
3396
|
+
"""The size of a whole COPY of `name` in a snapshot folder, else None.
|
|
3397
|
+
|
|
3398
|
+
Where the cache cannot hold symbolic links (Windows without Developer Mode),
|
|
3399
|
+
huggingface_hub downloads into `blobs/<etag>.incomplete` and then MOVES the
|
|
3400
|
+
file into `snapshots/<rev>/<name>`: no blob is left behind, and the snapshot
|
|
3401
|
+
entry is a regular file, not a link to a blob. A copy of the planned size
|
|
3402
|
+
(any size when the plan has none) is that file, whole."""
|
|
3403
|
+
|
|
3404
|
+
if not name:
|
|
3405
|
+
return None
|
|
3406
|
+
try:
|
|
3407
|
+
snaps = [d for d in (repo_dir / "snapshots").iterdir() if d.is_dir()]
|
|
3408
|
+
except Exception:
|
|
3409
|
+
return None
|
|
3410
|
+
for snap in snaps:
|
|
3411
|
+
path = snap / name
|
|
3412
|
+
try:
|
|
3413
|
+
if path.is_symlink() or not path.is_file():
|
|
3414
|
+
continue
|
|
3415
|
+
found = path.stat().st_size
|
|
3416
|
+
except Exception:
|
|
3417
|
+
continue
|
|
3418
|
+
if not isinstance(size, int) or found == size:
|
|
3419
|
+
return found
|
|
3420
|
+
return None
|
|
3421
|
+
|
|
3422
|
+
|
|
3392
3423
|
class _HfBlobWatcher:
|
|
3393
|
-
"""Per-file progress from `blobs/<etag>(.incomplete)` sizes
|
|
3424
|
+
"""Per-file progress from `blobs/<etag>(.incomplete)` sizes, or from the
|
|
3425
|
+
snapshot copy when the cache holds no links (`_hf_snapshot_copy_size`)."""
|
|
3394
3426
|
|
|
3395
3427
|
def __init__(self, repo_dir: Path, plan: Optional[List[Dict[str, Any]]], emit: ProgressCallback, repo_id: str):
|
|
3396
3428
|
self.repo_dir = repo_dir
|
|
@@ -3435,6 +3467,11 @@ class _HfBlobWatcher:
|
|
|
3435
3467
|
row["bytes_done"] = whole.stat().st_size
|
|
3436
3468
|
row["state"] = "done"
|
|
3437
3469
|
continue
|
|
3470
|
+
copied = _hf_snapshot_copy_size(self.repo_dir, str(row.get("name") or ""), row.get("bytes_total"))
|
|
3471
|
+
if copied is not None and not _hf_partials(self.blobs, str(etag)):
|
|
3472
|
+
row["bytes_done"] = copied
|
|
3473
|
+
row["state"] = "done"
|
|
3474
|
+
continue
|
|
3438
3475
|
partial = _hf_partial_size(self.blobs, str(etag))
|
|
3439
3476
|
if partial is not None:
|
|
3440
3477
|
row["bytes_done"] = partial
|
|
@@ -3560,10 +3597,26 @@ import json, os, sys, threading, time
|
|
|
3560
3597
|
# The owner passes its pid (argv[2]): reading getppid() here could already
|
|
3561
3598
|
# see the re-parented value if the owner died during this interpreter's start.
|
|
3562
3599
|
_owner = int(sys.argv[2]) if len(sys.argv) > 2 else os.getppid()
|
|
3600
|
+
def _owner_gone_check():
|
|
3601
|
+
if os.name != "nt":
|
|
3602
|
+
return lambda: os.getppid() != _owner
|
|
3603
|
+
# Windows: a venv's python.exe is a launcher that starts the real
|
|
3604
|
+
# interpreter as ITS child, so getppid() is the launcher, never the owner.
|
|
3605
|
+
# Hold a handle on the owner instead (a handle pins the identity, unlike a
|
|
3606
|
+
# pid number) and ask whether that process has exited.
|
|
3607
|
+
import ctypes
|
|
3608
|
+
k32 = ctypes.WinDLL("kernel32", use_last_error=True)
|
|
3609
|
+
k32.OpenProcess.restype = ctypes.c_void_p
|
|
3610
|
+
k32.WaitForSingleObject.argtypes = [ctypes.c_void_p, ctypes.c_uint32]
|
|
3611
|
+
handle = k32.OpenProcess(0x00100000, False, _owner) # SYNCHRONIZE
|
|
3612
|
+
if not handle:
|
|
3613
|
+
return lambda: True
|
|
3614
|
+
return lambda: k32.WaitForSingleObject(handle, 0) == 0 # WAIT_OBJECT_0: exited
|
|
3615
|
+
_owner_gone = _owner_gone_check()
|
|
3563
3616
|
def _watch_owner():
|
|
3564
3617
|
while True:
|
|
3565
3618
|
time.sleep(1.0)
|
|
3566
|
-
if
|
|
3619
|
+
if _owner_gone():
|
|
3567
3620
|
os._exit(75) # no goodbye line: the owner's end of the pipe is gone
|
|
3568
3621
|
threading.Thread(target=_watch_owner, daemon=True).start()
|
|
3569
3622
|
from huggingface_hub import snapshot_download
|
|
@@ -1172,6 +1172,9 @@ def _parse_args(argv: Optional[List[str]] = None) -> EndpointConfig:
|
|
|
1172
1172
|
|
|
1173
1173
|
|
|
1174
1174
|
def main(argv: Optional[List[str]] = None) -> None:
|
|
1175
|
+
from abstractcore.utils.stdio import safe_stdio
|
|
1176
|
+
|
|
1177
|
+
safe_stdio()
|
|
1175
1178
|
cfg = _parse_args(argv)
|
|
1176
1179
|
app = create_app(provider_name=cfg.provider, model=cfg.model)
|
|
1177
1180
|
import uvicorn
|
|
@@ -4531,8 +4531,19 @@ class HuggingFaceProvider(BaseProvider):
|
|
|
4531
4531
|
)
|
|
4532
4532
|
return False
|
|
4533
4533
|
|
|
4534
|
+
# `crop(n)` with a positive `n` (keep n tokens) was deprecated and is gone in
|
|
4535
|
+
# transformers 5.20; a negative `n` (drop |n| tokens) works on every version.
|
|
4536
|
+
keep = int(keep_tokens)
|
|
4534
4537
|
try:
|
|
4535
|
-
|
|
4538
|
+
lengths = self._transformers_layer_seq_lengths(cache)
|
|
4539
|
+
except Exception:
|
|
4540
|
+
lengths = []
|
|
4541
|
+
current = max(lengths) if lengths else None
|
|
4542
|
+
try:
|
|
4543
|
+
if current is None:
|
|
4544
|
+
crop(keep) # length unknown: the legacy form is the only one available
|
|
4545
|
+
elif current > keep:
|
|
4546
|
+
crop(keep - current)
|
|
4536
4547
|
except Exception:
|
|
4537
4548
|
return False
|
|
4538
4549
|
|
|
@@ -71,13 +71,23 @@ def hard_kill_tree(proc: "subprocess.Popen") -> None:
|
|
|
71
71
|
POSIX: enumerate descendants first (while the tree is intact), kill the
|
|
72
72
|
worker's own group, then SIGKILL each descendant's process group and the
|
|
73
73
|
descendant itself — so a `setsid()`'d grandchild's group and its children
|
|
74
|
-
die too. Windows: `
|
|
74
|
+
die too. Windows: `taskkill /T /F` ends the worker and every process it started
|
|
75
|
+
(a browser driver's Chrome, a shell's children), then `proc.kill()` as the backstop.
|
|
75
76
|
|
|
76
77
|
Guarded throughout: a descendant reaped between enumeration and kill (or a
|
|
77
78
|
`getpgid` on a dead pid) must never raise — the point is to leave nothing
|
|
78
79
|
alive, not to account for every pid.
|
|
79
80
|
"""
|
|
80
81
|
if os.name != "posix":
|
|
82
|
+
if os.name == "nt":
|
|
83
|
+
try:
|
|
84
|
+
subprocess.run(
|
|
85
|
+
["taskkill", "/T", "/F", "/PID", str(proc.pid)],
|
|
86
|
+
stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL, timeout=15,
|
|
87
|
+
creationflags=getattr(subprocess, "CREATE_NO_WINDOW", 0),
|
|
88
|
+
)
|
|
89
|
+
except Exception:
|
|
90
|
+
pass
|
|
81
91
|
try:
|
|
82
92
|
proc.kill()
|
|
83
93
|
except Exception:
|
|
@@ -507,7 +507,10 @@ def macos_profile(spec: SandboxSpec) -> str:
|
|
|
507
507
|
while parent and parent != "/":
|
|
508
508
|
if parent not in ancestors:
|
|
509
509
|
ancestors.append(parent)
|
|
510
|
-
|
|
510
|
+
up = os.path.dirname(parent)
|
|
511
|
+
if up == parent: # a filesystem root that is not "/" (C:\ on Windows)
|
|
512
|
+
break
|
|
513
|
+
parent = up
|
|
511
514
|
if xcrun_rule and xcrun_tmp:
|
|
512
515
|
# Creating the cache file looks up its folder: metadata of the folder and its
|
|
513
516
|
# ancestors only (never a listing or a read of anything else in the temp root).
|
|
@@ -515,7 +518,10 @@ def macos_profile(spec: SandboxSpec) -> str:
|
|
|
515
518
|
while parent and parent != "/":
|
|
516
519
|
if parent not in ancestors:
|
|
517
520
|
ancestors.append(parent)
|
|
518
|
-
|
|
521
|
+
up = os.path.dirname(parent)
|
|
522
|
+
if up == parent:
|
|
523
|
+
break
|
|
524
|
+
parent = up
|
|
519
525
|
if ancestors:
|
|
520
526
|
lines.append("(allow file-read-metadata " + " ".join(f"(literal {_sbpl_str(a)})" for a in ancestors) + ")")
|
|
521
527
|
return "\n".join(lines) + "\n"
|
|
@@ -2671,6 +2671,9 @@ class SimpleCLI:
|
|
|
2671
2671
|
|
|
2672
2672
|
|
|
2673
2673
|
def main():
|
|
2674
|
+
from abstractcore.utils.stdio import safe_stdio
|
|
2675
|
+
|
|
2676
|
+
safe_stdio()
|
|
2674
2677
|
parser = argparse.ArgumentParser(
|
|
2675
2678
|
description="Simplified CLI REPL for AbstractCore",
|
|
2676
2679
|
formatter_class=argparse.RawDescriptionHelpFormatter,
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
"""Console output that never crashes on a character the terminal's code page lacks.
|
|
2
|
+
|
|
3
|
+
Windows sends a redirected or piped stream (``> file``, ``| Select-String``, CI logs) through
|
|
4
|
+
the ANSI code page, often cp1252, which has no emoji, arrows or box-drawing characters; a
|
|
5
|
+
print of one raised ``UnicodeEncodeError`` and ended the command. The command-line entry
|
|
6
|
+
points call `safe_stdio()` first: an encoding error then writes a replacement character.
|
|
7
|
+
Interactive consoles (UTF-16 through the console API) and UTF-8 streams are left as they are.
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
from __future__ import annotations
|
|
11
|
+
|
|
12
|
+
import sys
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def safe_stdio() -> None:
|
|
16
|
+
"""Make stdout/stderr replace characters their encoding cannot represent."""
|
|
17
|
+
|
|
18
|
+
for name in ("stdout", "stderr"):
|
|
19
|
+
stream = getattr(sys, name, None)
|
|
20
|
+
reconfigure = getattr(stream, "reconfigure", None)
|
|
21
|
+
if reconfigure is None:
|
|
22
|
+
continue
|
|
23
|
+
encoding = str(getattr(stream, "encoding", "") or "").lower().replace("_", "-")
|
|
24
|
+
if encoding in {"utf-8", "utf8", "utf-8-sig"}:
|
|
25
|
+
continue
|
|
26
|
+
try:
|
|
27
|
+
reconfigure(errors="replace")
|
|
28
|
+
except Exception: # a stream that cannot be reconfigured keeps its behavior
|
|
29
|
+
pass
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: abstractcore
|
|
3
|
-
Version: 2.26.
|
|
3
|
+
Version: 2.26.3
|
|
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>
|
|
@@ -253,6 +253,7 @@ abstractcore/utils/model_cache.py
|
|
|
253
253
|
abstractcore/utils/model_fit.py
|
|
254
254
|
abstractcore/utils/residency.py
|
|
255
255
|
abstractcore/utils/self_fixes.py
|
|
256
|
+
abstractcore/utils/stdio.py
|
|
256
257
|
abstractcore/utils/structured_logging.py
|
|
257
258
|
abstractcore/utils/token_utils.py
|
|
258
259
|
abstractcore/utils/trace_export.py
|
|
@@ -330,4 +331,5 @@ tests/test_structured_output_truncation_retry.py
|
|
|
330
331
|
tests/test_text_only_model_experience.py
|
|
331
332
|
tests/test_unload_memory.py
|
|
332
333
|
tests/test_user_scenario_validation.py
|
|
333
|
-
tests/test_voice_host_credentials.py
|
|
334
|
+
tests/test_voice_host_credentials.py
|
|
335
|
+
tests/test_windows_host_fixes.py
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
"""Windows host behavior: console output, process trees and LM Studio's model folder."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import io
|
|
6
|
+
import os
|
|
7
|
+
import subprocess
|
|
8
|
+
import sys
|
|
9
|
+
import time
|
|
10
|
+
from pathlib import Path
|
|
11
|
+
|
|
12
|
+
import pytest
|
|
13
|
+
|
|
14
|
+
from abstractcore.utils.stdio import safe_stdio
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def test_safe_stdio_replaces_what_a_cp1252_stream_cannot_encode(monkeypatch) -> None:
|
|
18
|
+
raw = io.BytesIO()
|
|
19
|
+
stream = io.TextIOWrapper(raw, encoding="cp1252", errors="strict")
|
|
20
|
+
monkeypatch.setattr(sys, "stdout", stream)
|
|
21
|
+
safe_stdio()
|
|
22
|
+
print("\U0001f4cb status → ok │", file=sys.stdout)
|
|
23
|
+
sys.stdout.flush()
|
|
24
|
+
assert raw.getvalue().decode("cp1252").strip() == "? status ? ok ?"
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def test_safe_stdio_leaves_a_utf8_stream_as_it_is(monkeypatch) -> None:
|
|
28
|
+
raw = io.BytesIO()
|
|
29
|
+
stream = io.TextIOWrapper(raw, encoding="utf-8", errors="strict")
|
|
30
|
+
monkeypatch.setattr(sys, "stdout", stream)
|
|
31
|
+
safe_stdio()
|
|
32
|
+
assert sys.stdout.errors == "strict"
|
|
33
|
+
print("→", file=sys.stdout)
|
|
34
|
+
sys.stdout.flush()
|
|
35
|
+
assert raw.getvalue().decode("utf-8").strip() == "→"
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def test_safe_stdio_tolerates_streams_without_reconfigure(monkeypatch) -> None:
|
|
39
|
+
monkeypatch.setattr(sys, "stdout", io.StringIO())
|
|
40
|
+
monkeypatch.setattr(sys, "stderr", None)
|
|
41
|
+
safe_stdio()
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
@pytest.mark.parametrize(
|
|
45
|
+
"module",
|
|
46
|
+
["abstractcore.config.main", "abstractcore.utils.cli", "abstractcore.endpoint.app", "abstractcore.apps.summarizer",
|
|
47
|
+
"abstractcore.apps.extractor", "abstractcore.apps.judge", "abstractcore.apps.intent", "abstractcore.apps.deepsearch"],
|
|
48
|
+
)
|
|
49
|
+
def test_every_console_entry_point_makes_stdio_safe_first(module) -> None:
|
|
50
|
+
import importlib.util
|
|
51
|
+
import inspect
|
|
52
|
+
|
|
53
|
+
spec = importlib.util.find_spec(module)
|
|
54
|
+
source = Path(spec.origin).read_text(encoding="utf-8")
|
|
55
|
+
body = source[source.index("\ndef main("):]
|
|
56
|
+
assert "safe_stdio()" in body.split("\ndef ", 2)[1], f"{module}.main does not call safe_stdio()"
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
def _alive(pid: int) -> bool:
|
|
60
|
+
out = subprocess.run(["tasklist", "/FI", f"PID eq {pid}", "/NH"], capture_output=True, text=True).stdout
|
|
61
|
+
return str(pid) in out
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
@pytest.mark.skipif(os.name != "nt", reason="Windows process tree")
|
|
65
|
+
def test_hard_kill_tree_ends_a_windows_workers_children() -> None:
|
|
66
|
+
from abstractcore.tools.process_tree import hard_kill_tree
|
|
67
|
+
|
|
68
|
+
code = ("import subprocess, sys, time; "
|
|
69
|
+
"p = subprocess.Popen([sys.executable, '-c', 'import time; time.sleep(60)']); "
|
|
70
|
+
"print(p.pid, flush=True); time.sleep(60)")
|
|
71
|
+
proc = subprocess.Popen([sys.executable, "-c", code], stdout=subprocess.PIPE, text=True)
|
|
72
|
+
grandchild = int(proc.stdout.readline())
|
|
73
|
+
assert _alive(proc.pid) and _alive(grandchild)
|
|
74
|
+
hard_kill_tree(proc)
|
|
75
|
+
deadline = time.time() + 10
|
|
76
|
+
while time.time() < deadline and (_alive(proc.pid) or _alive(grandchild)):
|
|
77
|
+
time.sleep(0.2)
|
|
78
|
+
assert not _alive(proc.pid) and not _alive(grandchild)
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
@pytest.mark.parametrize("system", ["Windows", "Darwin", "Linux"])
|
|
82
|
+
def test_lm_studio_models_in_the_home_folder_are_found_on_every_os(tmp_path, monkeypatch, system) -> None:
|
|
83
|
+
from abstractcore.capabilities import vision_catalog
|
|
84
|
+
|
|
85
|
+
models = tmp_path / ".lmstudio" / "models"
|
|
86
|
+
models.mkdir(parents=True)
|
|
87
|
+
monkeypatch.setattr(vision_catalog.platform, "system", lambda: system)
|
|
88
|
+
monkeypatch.setattr(vision_catalog.Path, "home", classmethod(lambda cls: tmp_path))
|
|
89
|
+
for key in ("LMSTUDIO_MODELS_DIR", "LMSTUDIO_MODEL_DIR", "LM_STUDIO_MODELS_DIR", "LOCALAPPDATA", "APPDATA"):
|
|
90
|
+
monkeypatch.delenv(key, raising=False)
|
|
91
|
+
assert models in vision_catalog._default_lmstudio_model_dirs()
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
def _copy_cache(tmp_path: Path) -> tuple[Path, list]:
|
|
95
|
+
"""A Hugging Face cache without links (Windows without Developer Mode): huggingface_hub moved
|
|
96
|
+
each finished file from blobs/ into snapshots/<rev>/ and left no blob behind."""
|
|
97
|
+
repo = tmp_path / "models--org--tiny"
|
|
98
|
+
snap = repo / "snapshots" / "abc123"
|
|
99
|
+
snap.mkdir(parents=True)
|
|
100
|
+
(repo / "blobs").mkdir()
|
|
101
|
+
(snap / "config.json").write_bytes(b"{}" * 10)
|
|
102
|
+
(snap / "model.safetensors").write_bytes(b"\0" * 300)
|
|
103
|
+
plan = [{"name": "config.json", "size": 20, "etag": "e1"}, {"name": "model.safetensors", "size": 300, "etag": "e2"}]
|
|
104
|
+
return repo, plan
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
def test_a_download_into_a_cache_without_links_is_whole(tmp_path) -> None:
|
|
108
|
+
from abstractcore.config import model_materializer as mm
|
|
109
|
+
|
|
110
|
+
repo, plan = _copy_cache(tmp_path)
|
|
111
|
+
watcher = mm._HfBlobWatcher(repo, plan, lambda *_a, **_k: None, "org/tiny")
|
|
112
|
+
assert watcher.missing() == []
|
|
113
|
+
assert watcher.bytes_done() == 320
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
def test_a_snapshot_copy_of_the_wrong_size_is_not_whole(tmp_path) -> None:
|
|
117
|
+
from abstractcore.config import model_materializer as mm
|
|
118
|
+
|
|
119
|
+
repo, plan = _copy_cache(tmp_path)
|
|
120
|
+
(repo / "snapshots" / "abc123" / "model.safetensors").write_bytes(b"\0" * 10)
|
|
121
|
+
watcher = mm._HfBlobWatcher(repo, plan, lambda *_a, **_k: None, "org/tiny")
|
|
122
|
+
assert watcher.missing() == ["model.safetensors"]
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
def test_the_download_marker_counts_snapshot_copies_as_whole(tmp_path) -> None:
|
|
126
|
+
import json
|
|
127
|
+
from abstractcore.config import model_materializer as mm
|
|
128
|
+
|
|
129
|
+
repo, plan = _copy_cache(tmp_path)
|
|
130
|
+
(repo / mm._HF_MARKER).write_text(json.dumps({"files": plan}), encoding="utf-8")
|
|
131
|
+
assert mm._hf_marker_unfinished(repo) == 0
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
def test_a_blob_layout_is_read_as_before(tmp_path) -> None:
|
|
135
|
+
from abstractcore.config import model_materializer as mm
|
|
136
|
+
|
|
137
|
+
repo = tmp_path / "models--org--tiny"
|
|
138
|
+
(repo / "blobs").mkdir(parents=True)
|
|
139
|
+
(repo / "snapshots" / "abc123").mkdir(parents=True)
|
|
140
|
+
(repo / "blobs" / "e1").write_bytes(b"x" * 20)
|
|
141
|
+
plan = [{"name": "config.json", "size": 20, "etag": "e1"}, {"name": "model.safetensors", "size": 300, "etag": "e2"}]
|
|
142
|
+
watcher = mm._HfBlobWatcher(repo, plan, lambda *_a, **_k: None, "org/tiny")
|
|
143
|
+
assert watcher.missing() == ["model.safetensors"]
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
def _owner_watch_header() -> str:
|
|
147
|
+
from abstractcore.config.model_materializer import _HF_CHILD
|
|
148
|
+
|
|
149
|
+
head, sep, _ = _HF_CHILD.partition("from huggingface_hub import snapshot_download")
|
|
150
|
+
assert sep, "the download child no longer has the expected shape"
|
|
151
|
+
return head
|
|
152
|
+
|
|
153
|
+
|
|
154
|
+
def test_the_download_child_keeps_running_while_its_owner_lives() -> None:
|
|
155
|
+
# On Windows sys.executable in a venv is a launcher: the child's parent pid is the
|
|
156
|
+
# launcher, not the owner. The child must not take that for a dead owner.
|
|
157
|
+
code = _owner_watch_header() + "time.sleep(3.5)\nprint('alive', flush=True)\n"
|
|
158
|
+
out = subprocess.run(
|
|
159
|
+
[sys.executable, "-c", code, "{}", str(os.getpid())],
|
|
160
|
+
capture_output=True, text=True, timeout=60,
|
|
161
|
+
)
|
|
162
|
+
assert out.returncode == 0, (out.returncode, out.stderr)
|
|
163
|
+
assert out.stdout.strip() == "alive"
|
|
164
|
+
|
|
165
|
+
|
|
166
|
+
def test_the_download_child_stops_when_its_owner_exits() -> None:
|
|
167
|
+
owner = subprocess.Popen([sys.executable, "-c", "import time; time.sleep(1.5)"])
|
|
168
|
+
code = _owner_watch_header() + "time.sleep(30)\nprint('outlived', flush=True)\n"
|
|
169
|
+
started = time.monotonic()
|
|
170
|
+
out = subprocess.run(
|
|
171
|
+
[sys.executable, "-c", code, "{}", str(owner.pid)],
|
|
172
|
+
capture_output=True, text=True, timeout=60,
|
|
173
|
+
)
|
|
174
|
+
owner.wait(timeout=30)
|
|
175
|
+
assert out.returncode == 75, (out.returncode, out.stdout, out.stderr)
|
|
176
|
+
assert time.monotonic() - started < 20
|
|
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.26.0 → abstractcore-2.26.3}/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.26.0 → abstractcore-2.26.3}/abstractcore/assets/abstractframework_identity.json
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/assets/model_capabilities.schema.json
RENAMED
|
File without changes
|
{abstractcore-2.26.0 → abstractcore-2.26.3}/abstractcore/assets/model_downloads_catalog.json
RENAMED
|
File without changes
|
{abstractcore-2.26.0 → abstractcore-2.26.3}/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
|
|
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|