mirascope 2.0.0a5__py3-none-any.whl → 2.0.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- mirascope/__init__.py +10 -1
- mirascope/_stubs.py +363 -0
- mirascope/api/__init__.py +8 -0
- mirascope/api/_generated/__init__.py +285 -2
- mirascope/api/_generated/annotations/__init__.py +33 -0
- mirascope/api/_generated/annotations/client.py +506 -0
- mirascope/api/_generated/annotations/raw_client.py +1414 -0
- mirascope/api/_generated/annotations/types/__init__.py +31 -0
- mirascope/api/_generated/annotations/types/annotations_create_request_label.py +5 -0
- mirascope/api/_generated/annotations/types/annotations_create_response.py +48 -0
- mirascope/api/_generated/annotations/types/annotations_create_response_label.py +5 -0
- mirascope/api/_generated/annotations/types/annotations_get_response.py +48 -0
- mirascope/api/_generated/annotations/types/annotations_get_response_label.py +5 -0
- mirascope/api/_generated/annotations/types/annotations_list_request_label.py +5 -0
- mirascope/api/_generated/annotations/types/annotations_list_response.py +21 -0
- mirascope/api/_generated/annotations/types/annotations_list_response_annotations_item.py +50 -0
- mirascope/api/_generated/annotations/types/annotations_list_response_annotations_item_label.py +5 -0
- mirascope/api/_generated/annotations/types/annotations_update_request_label.py +5 -0
- mirascope/api/_generated/annotations/types/annotations_update_response.py +48 -0
- mirascope/api/_generated/annotations/types/annotations_update_response_label.py +5 -0
- mirascope/api/_generated/api_keys/__init__.py +12 -2
- mirascope/api/_generated/api_keys/client.py +77 -0
- mirascope/api/_generated/api_keys/raw_client.py +422 -39
- mirascope/api/_generated/api_keys/types/__init__.py +7 -1
- mirascope/api/_generated/api_keys/types/api_keys_create_response.py +4 -12
- mirascope/api/_generated/api_keys/types/api_keys_get_response.py +4 -12
- mirascope/api/_generated/api_keys/types/api_keys_list_all_for_org_response_item.py +40 -0
- mirascope/api/_generated/api_keys/types/api_keys_list_response_item.py +4 -12
- mirascope/api/_generated/client.py +42 -0
- mirascope/api/_generated/core/client_wrapper.py +2 -14
- mirascope/api/_generated/core/datetime_utils.py +1 -3
- mirascope/api/_generated/core/file.py +2 -5
- mirascope/api/_generated/core/http_client.py +36 -112
- mirascope/api/_generated/core/jsonable_encoder.py +1 -3
- mirascope/api/_generated/core/pydantic_utilities.py +19 -74
- mirascope/api/_generated/core/query_encoder.py +1 -3
- mirascope/api/_generated/core/serialization.py +4 -10
- mirascope/api/_generated/docs/client.py +2 -6
- mirascope/api/_generated/docs/raw_client.py +51 -5
- mirascope/api/_generated/environment.py +3 -3
- mirascope/api/_generated/environments/__init__.py +6 -0
- mirascope/api/_generated/environments/client.py +117 -0
- mirascope/api/_generated/environments/raw_client.py +530 -51
- mirascope/api/_generated/environments/types/__init__.py +10 -0
- mirascope/api/_generated/environments/types/environments_create_response.py +1 -3
- mirascope/api/_generated/environments/types/environments_get_analytics_response.py +60 -0
- mirascope/api/_generated/environments/types/environments_get_analytics_response_top_functions_item.py +24 -0
- mirascope/api/_generated/environments/types/environments_get_analytics_response_top_models_item.py +22 -0
- mirascope/api/_generated/environments/types/environments_get_response.py +1 -3
- mirascope/api/_generated/environments/types/environments_list_response_item.py +1 -3
- mirascope/api/_generated/environments/types/environments_update_response.py +1 -3
- mirascope/api/_generated/errors/__init__.py +8 -0
- mirascope/api/_generated/errors/bad_request_error.py +1 -2
- mirascope/api/_generated/errors/conflict_error.py +1 -2
- mirascope/api/_generated/errors/forbidden_error.py +1 -5
- mirascope/api/_generated/errors/internal_server_error.py +1 -6
- mirascope/api/_generated/errors/not_found_error.py +1 -5
- mirascope/api/_generated/errors/payment_required_error.py +15 -0
- mirascope/api/_generated/errors/service_unavailable_error.py +14 -0
- mirascope/api/_generated/errors/too_many_requests_error.py +15 -0
- mirascope/api/_generated/errors/unauthorized_error.py +11 -0
- mirascope/api/_generated/functions/__init__.py +39 -0
- mirascope/api/_generated/functions/client.py +647 -0
- mirascope/api/_generated/functions/raw_client.py +1890 -0
- mirascope/api/_generated/functions/types/__init__.py +53 -0
- mirascope/api/_generated/functions/types/functions_create_request_dependencies_value.py +20 -0
- mirascope/api/_generated/functions/types/functions_create_response.py +37 -0
- mirascope/api/_generated/functions/types/functions_create_response_dependencies_value.py +20 -0
- mirascope/api/_generated/functions/types/functions_find_by_hash_response.py +39 -0
- mirascope/api/_generated/functions/types/functions_find_by_hash_response_dependencies_value.py +20 -0
- mirascope/api/_generated/functions/types/functions_get_by_env_response.py +53 -0
- mirascope/api/_generated/functions/types/functions_get_by_env_response_dependencies_value.py +22 -0
- mirascope/api/_generated/functions/types/functions_get_response.py +37 -0
- mirascope/api/_generated/functions/types/functions_get_response_dependencies_value.py +20 -0
- mirascope/api/_generated/functions/types/functions_list_by_env_response.py +25 -0
- mirascope/api/_generated/functions/types/functions_list_by_env_response_functions_item.py +56 -0
- mirascope/api/_generated/functions/types/functions_list_by_env_response_functions_item_dependencies_value.py +22 -0
- mirascope/api/_generated/functions/types/functions_list_response.py +21 -0
- mirascope/api/_generated/functions/types/functions_list_response_functions_item.py +41 -0
- mirascope/api/_generated/functions/types/functions_list_response_functions_item_dependencies_value.py +20 -0
- mirascope/api/_generated/health/client.py +2 -6
- mirascope/api/_generated/health/raw_client.py +51 -5
- mirascope/api/_generated/health/types/health_check_response.py +1 -3
- mirascope/api/_generated/organization_invitations/__init__.py +33 -0
- mirascope/api/_generated/organization_invitations/client.py +546 -0
- mirascope/api/_generated/organization_invitations/raw_client.py +1519 -0
- mirascope/api/_generated/organization_invitations/types/__init__.py +53 -0
- mirascope/api/_generated/organization_invitations/types/organization_invitations_accept_response.py +34 -0
- mirascope/api/_generated/organization_invitations/types/organization_invitations_accept_response_role.py +7 -0
- mirascope/api/_generated/organization_invitations/types/organization_invitations_create_request_role.py +7 -0
- mirascope/api/_generated/organization_invitations/types/organization_invitations_create_response.py +48 -0
- mirascope/api/_generated/organization_invitations/types/organization_invitations_create_response_role.py +7 -0
- mirascope/api/_generated/organization_invitations/types/organization_invitations_create_response_status.py +7 -0
- mirascope/api/_generated/organization_invitations/types/organization_invitations_get_response.py +48 -0
- mirascope/api/_generated/organization_invitations/types/organization_invitations_get_response_role.py +7 -0
- mirascope/api/_generated/organization_invitations/types/organization_invitations_get_response_status.py +7 -0
- mirascope/api/_generated/organization_invitations/types/organization_invitations_list_response_item.py +48 -0
- mirascope/api/_generated/organization_invitations/types/organization_invitations_list_response_item_role.py +7 -0
- mirascope/api/_generated/organization_invitations/types/organization_invitations_list_response_item_status.py +7 -0
- mirascope/api/_generated/organization_memberships/__init__.py +19 -0
- mirascope/api/_generated/organization_memberships/client.py +302 -0
- mirascope/api/_generated/organization_memberships/raw_client.py +736 -0
- mirascope/api/_generated/organization_memberships/types/__init__.py +27 -0
- mirascope/api/_generated/organization_memberships/types/organization_memberships_list_response_item.py +33 -0
- mirascope/api/_generated/organization_memberships/types/organization_memberships_list_response_item_role.py +7 -0
- mirascope/api/_generated/organization_memberships/types/organization_memberships_update_request_role.py +7 -0
- mirascope/api/_generated/organization_memberships/types/organization_memberships_update_response.py +31 -0
- mirascope/api/_generated/organization_memberships/types/organization_memberships_update_response_role.py +7 -0
- mirascope/api/_generated/organizations/__init__.py +26 -0
- mirascope/api/_generated/organizations/client.py +465 -0
- mirascope/api/_generated/organizations/raw_client.py +1799 -108
- mirascope/api/_generated/organizations/types/__init__.py +48 -0
- mirascope/api/_generated/organizations/types/organizations_create_payment_intent_response.py +24 -0
- mirascope/api/_generated/organizations/types/organizations_create_response.py +4 -3
- mirascope/api/_generated/organizations/types/organizations_create_response_role.py +1 -3
- mirascope/api/_generated/organizations/types/organizations_get_response.py +4 -3
- mirascope/api/_generated/organizations/types/organizations_get_response_role.py +1 -3
- mirascope/api/_generated/organizations/types/organizations_list_response_item.py +4 -3
- mirascope/api/_generated/organizations/types/organizations_list_response_item_role.py +1 -3
- mirascope/api/_generated/organizations/types/organizations_preview_subscription_change_request_target_plan.py +7 -0
- mirascope/api/_generated/organizations/types/organizations_preview_subscription_change_response.py +47 -0
- mirascope/api/_generated/organizations/types/organizations_preview_subscription_change_response_validation_errors_item.py +33 -0
- mirascope/api/_generated/organizations/types/organizations_preview_subscription_change_response_validation_errors_item_resource.py +7 -0
- mirascope/api/_generated/organizations/types/organizations_router_balance_response.py +24 -0
- mirascope/api/_generated/organizations/types/organizations_subscription_response.py +53 -0
- mirascope/api/_generated/organizations/types/organizations_subscription_response_current_plan.py +7 -0
- mirascope/api/_generated/organizations/types/organizations_subscription_response_payment_method.py +26 -0
- mirascope/api/_generated/organizations/types/organizations_subscription_response_scheduled_change.py +34 -0
- mirascope/api/_generated/organizations/types/organizations_subscription_response_scheduled_change_target_plan.py +7 -0
- mirascope/api/_generated/organizations/types/organizations_update_response.py +4 -3
- mirascope/api/_generated/organizations/types/organizations_update_response_role.py +1 -3
- mirascope/api/_generated/organizations/types/organizations_update_subscription_request_target_plan.py +7 -0
- mirascope/api/_generated/organizations/types/organizations_update_subscription_response.py +35 -0
- mirascope/api/_generated/project_memberships/__init__.py +25 -0
- mirascope/api/_generated/project_memberships/client.py +437 -0
- mirascope/api/_generated/project_memberships/raw_client.py +1039 -0
- mirascope/api/_generated/project_memberships/types/__init__.py +29 -0
- mirascope/api/_generated/project_memberships/types/project_memberships_create_request_role.py +7 -0
- mirascope/api/_generated/project_memberships/types/project_memberships_create_response.py +35 -0
- mirascope/api/_generated/project_memberships/types/project_memberships_create_response_role.py +7 -0
- mirascope/api/_generated/project_memberships/types/project_memberships_list_response_item.py +33 -0
- mirascope/api/_generated/project_memberships/types/project_memberships_list_response_item_role.py +7 -0
- mirascope/api/_generated/project_memberships/types/project_memberships_update_request_role.py +7 -0
- mirascope/api/_generated/project_memberships/types/project_memberships_update_response.py +35 -0
- mirascope/api/_generated/project_memberships/types/project_memberships_update_response_role.py +7 -0
- mirascope/api/_generated/projects/__init__.py +2 -12
- mirascope/api/_generated/projects/client.py +17 -71
- mirascope/api/_generated/projects/raw_client.py +295 -51
- mirascope/api/_generated/projects/types/__init__.py +1 -6
- mirascope/api/_generated/projects/types/projects_create_response.py +3 -9
- mirascope/api/_generated/projects/types/projects_get_response.py +3 -9
- mirascope/api/_generated/projects/types/projects_list_response_item.py +3 -9
- mirascope/api/_generated/projects/types/projects_update_response.py +3 -9
- mirascope/api/_generated/reference.md +3619 -182
- mirascope/api/_generated/tags/__init__.py +19 -0
- mirascope/api/_generated/tags/client.py +504 -0
- mirascope/api/_generated/tags/raw_client.py +1288 -0
- mirascope/api/_generated/tags/types/__init__.py +17 -0
- mirascope/api/_generated/tags/types/tags_create_response.py +41 -0
- mirascope/api/_generated/tags/types/tags_get_response.py +41 -0
- mirascope/api/_generated/tags/types/tags_list_response.py +23 -0
- mirascope/api/_generated/tags/types/tags_list_response_tags_item.py +41 -0
- mirascope/api/_generated/tags/types/tags_update_response.py +41 -0
- mirascope/api/_generated/token_cost/__init__.py +7 -0
- mirascope/api/_generated/token_cost/client.py +160 -0
- mirascope/api/_generated/token_cost/raw_client.py +264 -0
- mirascope/api/_generated/token_cost/types/__init__.py +8 -0
- mirascope/api/_generated/token_cost/types/token_cost_calculate_request_usage.py +54 -0
- mirascope/api/_generated/token_cost/types/token_cost_calculate_response.py +52 -0
- mirascope/api/_generated/traces/__init__.py +42 -0
- mirascope/api/_generated/traces/client.py +941 -0
- mirascope/api/_generated/traces/raw_client.py +2177 -23
- mirascope/api/_generated/traces/types/__init__.py +60 -0
- mirascope/api/_generated/traces/types/traces_create_request_resource_spans_item.py +4 -11
- mirascope/api/_generated/traces/types/traces_create_request_resource_spans_item_resource.py +2 -6
- mirascope/api/_generated/traces/types/traces_create_request_resource_spans_item_resource_attributes_item.py +1 -3
- mirascope/api/_generated/traces/types/traces_create_request_resource_spans_item_resource_attributes_item_value.py +8 -24
- mirascope/api/_generated/traces/types/traces_create_request_resource_spans_item_resource_attributes_item_value_array_value.py +2 -6
- mirascope/api/_generated/traces/types/traces_create_request_resource_spans_item_resource_attributes_item_value_kvlist_value.py +3 -9
- mirascope/api/_generated/traces/types/traces_create_request_resource_spans_item_resource_attributes_item_value_kvlist_value_values_item.py +2 -6
- mirascope/api/_generated/traces/types/traces_create_request_resource_spans_item_scope_spans_item.py +3 -9
- mirascope/api/_generated/traces/types/traces_create_request_resource_spans_item_scope_spans_item_scope.py +4 -8
- mirascope/api/_generated/traces/types/traces_create_request_resource_spans_item_scope_spans_item_scope_attributes_item.py +2 -6
- mirascope/api/_generated/traces/types/traces_create_request_resource_spans_item_scope_spans_item_scope_attributes_item_value.py +8 -24
- mirascope/api/_generated/traces/types/traces_create_request_resource_spans_item_scope_spans_item_scope_attributes_item_value_array_value.py +2 -6
- mirascope/api/_generated/traces/types/traces_create_request_resource_spans_item_scope_spans_item_scope_attributes_item_value_kvlist_value.py +3 -9
- mirascope/api/_generated/traces/types/traces_create_request_resource_spans_item_scope_spans_item_scope_attributes_item_value_kvlist_value_values_item.py +1 -3
- mirascope/api/_generated/traces/types/traces_create_request_resource_spans_item_scope_spans_item_spans_item.py +6 -18
- mirascope/api/_generated/traces/types/traces_create_request_resource_spans_item_scope_spans_item_spans_item_attributes_item.py +3 -9
- mirascope/api/_generated/traces/types/traces_create_request_resource_spans_item_scope_spans_item_spans_item_attributes_item_value.py +8 -24
- mirascope/api/_generated/traces/types/traces_create_request_resource_spans_item_scope_spans_item_spans_item_attributes_item_value_array_value.py +2 -6
- mirascope/api/_generated/traces/types/traces_create_request_resource_spans_item_scope_spans_item_spans_item_attributes_item_value_kvlist_value.py +2 -6
- mirascope/api/_generated/traces/types/traces_create_request_resource_spans_item_scope_spans_item_spans_item_attributes_item_value_kvlist_value_values_item.py +1 -3
- mirascope/api/_generated/traces/types/traces_create_request_resource_spans_item_scope_spans_item_spans_item_status.py +2 -6
- mirascope/api/_generated/traces/types/traces_create_response.py +2 -5
- mirascope/api/_generated/traces/types/traces_create_response_partial_success.py +3 -9
- mirascope/api/_generated/traces/types/traces_get_analytics_summary_response.py +60 -0
- mirascope/api/_generated/traces/types/traces_get_analytics_summary_response_top_functions_item.py +24 -0
- mirascope/api/_generated/traces/types/traces_get_analytics_summary_response_top_models_item.py +22 -0
- mirascope/api/_generated/traces/types/traces_get_trace_detail_by_env_response.py +33 -0
- mirascope/api/_generated/traces/types/traces_get_trace_detail_by_env_response_spans_item.py +88 -0
- mirascope/api/_generated/traces/types/traces_get_trace_detail_response.py +33 -0
- mirascope/api/_generated/traces/types/traces_get_trace_detail_response_spans_item.py +88 -0
- mirascope/api/_generated/traces/types/traces_list_by_function_hash_response.py +25 -0
- mirascope/api/_generated/traces/types/traces_list_by_function_hash_response_traces_item.py +44 -0
- mirascope/api/_generated/traces/types/traces_search_by_env_request_attribute_filters_item.py +26 -0
- mirascope/api/_generated/traces/types/traces_search_by_env_request_attribute_filters_item_operator.py +7 -0
- mirascope/api/_generated/traces/types/traces_search_by_env_request_sort_by.py +7 -0
- mirascope/api/_generated/traces/types/traces_search_by_env_request_sort_order.py +7 -0
- mirascope/api/_generated/traces/types/traces_search_by_env_response.py +26 -0
- mirascope/api/_generated/traces/types/traces_search_by_env_response_spans_item.py +50 -0
- mirascope/api/_generated/traces/types/traces_search_request_attribute_filters_item.py +26 -0
- mirascope/api/_generated/traces/types/traces_search_request_attribute_filters_item_operator.py +7 -0
- mirascope/api/_generated/traces/types/traces_search_request_sort_by.py +7 -0
- mirascope/api/_generated/traces/types/traces_search_request_sort_order.py +5 -0
- mirascope/api/_generated/traces/types/traces_search_response.py +26 -0
- mirascope/api/_generated/traces/types/traces_search_response_spans_item.py +50 -0
- mirascope/api/_generated/types/__init__.py +48 -0
- mirascope/api/_generated/types/already_exists_error.py +1 -3
- mirascope/api/_generated/types/bad_request_error_body.py +50 -0
- mirascope/api/_generated/types/click_house_error.py +22 -0
- mirascope/api/_generated/types/database_error.py +1 -3
- mirascope/api/_generated/types/date.py +3 -0
- mirascope/api/_generated/types/http_api_decode_error.py +1 -3
- mirascope/api/_generated/types/immutable_resource_error.py +22 -0
- mirascope/api/_generated/types/internal_server_error_body.py +49 -0
- mirascope/api/_generated/types/issue.py +1 -3
- mirascope/api/_generated/types/issue_tag.py +1 -8
- mirascope/api/_generated/types/not_found_error_body.py +1 -3
- mirascope/api/_generated/types/number_from_string.py +3 -0
- mirascope/api/_generated/types/permission_denied_error.py +1 -3
- mirascope/api/_generated/types/permission_denied_error_tag.py +1 -3
- mirascope/api/_generated/types/plan_limit_exceeded_error.py +32 -0
- mirascope/api/_generated/types/plan_limit_exceeded_error_tag.py +7 -0
- mirascope/api/_generated/types/pricing_unavailable_error.py +23 -0
- mirascope/api/_generated/types/property_key_key.py +1 -3
- mirascope/api/_generated/types/rate_limit_error.py +31 -0
- mirascope/api/_generated/types/rate_limit_error_tag.py +5 -0
- mirascope/api/_generated/types/service_unavailable_error_body.py +24 -0
- mirascope/api/_generated/types/service_unavailable_error_tag.py +7 -0
- mirascope/api/_generated/types/stripe_error.py +20 -0
- mirascope/api/_generated/types/subscription_past_due_error.py +31 -0
- mirascope/api/_generated/types/subscription_past_due_error_tag.py +7 -0
- mirascope/api/_generated/types/unauthorized_error_body.py +21 -0
- mirascope/api/_generated/types/unauthorized_error_tag.py +5 -0
- mirascope/api/settings.py +19 -1
- mirascope/llm/__init__.py +55 -8
- mirascope/llm/calls/__init__.py +2 -1
- mirascope/llm/calls/calls.py +3 -1
- mirascope/llm/calls/decorator.py +21 -7
- mirascope/llm/content/tool_call.py +6 -0
- mirascope/llm/content/tool_output.py +22 -5
- mirascope/llm/exceptions.py +284 -71
- mirascope/llm/formatting/__init__.py +19 -2
- mirascope/llm/formatting/format.py +219 -30
- mirascope/llm/formatting/output_parser.py +178 -0
- mirascope/llm/formatting/partial.py +80 -7
- mirascope/llm/formatting/primitives.py +192 -0
- mirascope/llm/formatting/types.py +21 -64
- mirascope/llm/mcp/__init__.py +2 -2
- mirascope/llm/mcp/mcp_client.py +130 -0
- mirascope/llm/messages/__init__.py +3 -0
- mirascope/llm/messages/_utils.py +34 -0
- mirascope/llm/models/__init__.py +5 -0
- mirascope/llm/models/models.py +137 -69
- mirascope/llm/{providers/base → models}/params.py +16 -37
- mirascope/llm/models/thinking_config.py +61 -0
- mirascope/llm/prompts/_utils.py +0 -32
- mirascope/llm/prompts/decorator.py +16 -5
- mirascope/llm/prompts/prompts.py +131 -68
- mirascope/llm/providers/__init__.py +18 -2
- mirascope/llm/providers/anthropic/__init__.py +3 -21
- mirascope/llm/providers/anthropic/_utils/__init__.py +2 -0
- mirascope/llm/providers/anthropic/_utils/beta_decode.py +22 -11
- mirascope/llm/providers/anthropic/_utils/beta_encode.py +75 -25
- mirascope/llm/providers/anthropic/_utils/decode.py +22 -11
- mirascope/llm/providers/anthropic/_utils/encode.py +82 -20
- mirascope/llm/providers/anthropic/_utils/errors.py +2 -2
- mirascope/llm/providers/anthropic/beta_provider.py +64 -18
- mirascope/llm/providers/anthropic/provider.py +91 -33
- mirascope/llm/providers/base/__init__.py +0 -2
- mirascope/llm/providers/base/_utils.py +55 -11
- mirascope/llm/providers/base/base_provider.py +116 -37
- mirascope/llm/providers/google/__init__.py +2 -17
- mirascope/llm/providers/google/_utils/__init__.py +2 -0
- mirascope/llm/providers/google/_utils/decode.py +37 -15
- mirascope/llm/providers/google/_utils/encode.py +127 -19
- mirascope/llm/providers/google/_utils/errors.py +3 -2
- mirascope/llm/providers/google/model_info.py +1 -0
- mirascope/llm/providers/google/provider.py +68 -19
- mirascope/llm/providers/mirascope/__init__.py +5 -0
- mirascope/llm/providers/mirascope/_utils.py +73 -0
- mirascope/llm/providers/mirascope/provider.py +349 -0
- mirascope/llm/providers/mlx/__init__.py +2 -17
- mirascope/llm/providers/mlx/_utils.py +8 -3
- mirascope/llm/providers/mlx/encoding/base.py +5 -2
- mirascope/llm/providers/mlx/encoding/transformers.py +5 -2
- mirascope/llm/providers/mlx/mlx.py +23 -6
- mirascope/llm/providers/mlx/provider.py +42 -13
- mirascope/llm/providers/ollama/__init__.py +1 -13
- mirascope/llm/providers/openai/_utils/errors.py +2 -2
- mirascope/llm/providers/openai/completions/__init__.py +2 -20
- mirascope/llm/providers/openai/completions/_utils/decode.py +14 -3
- mirascope/llm/providers/openai/completions/_utils/encode.py +35 -28
- mirascope/llm/providers/openai/completions/base_provider.py +40 -11
- mirascope/llm/providers/openai/provider.py +40 -10
- mirascope/llm/providers/openai/responses/__init__.py +1 -17
- mirascope/llm/providers/openai/responses/_utils/__init__.py +2 -0
- mirascope/llm/providers/openai/responses/_utils/decode.py +21 -8
- mirascope/llm/providers/openai/responses/_utils/encode.py +59 -19
- mirascope/llm/providers/openai/responses/provider.py +56 -18
- mirascope/llm/providers/provider_id.py +1 -0
- mirascope/llm/providers/provider_registry.py +96 -19
- mirascope/llm/providers/together/__init__.py +1 -13
- mirascope/llm/responses/__init__.py +6 -1
- mirascope/llm/responses/_utils.py +102 -12
- mirascope/llm/responses/base_response.py +5 -2
- mirascope/llm/responses/base_stream_response.py +139 -45
- mirascope/llm/responses/response.py +2 -1
- mirascope/llm/responses/root_response.py +89 -17
- mirascope/llm/responses/stream_response.py +6 -9
- mirascope/llm/tools/decorator.py +17 -8
- mirascope/llm/tools/tool_schema.py +43 -10
- mirascope/llm/tools/toolkit.py +35 -27
- mirascope/llm/tools/tools.py +123 -30
- mirascope/ops/__init__.py +64 -109
- mirascope/ops/_internal/configuration.py +82 -31
- mirascope/ops/_internal/exporters/exporters.py +64 -11
- mirascope/ops/_internal/instrumentation/llm/common.py +530 -0
- mirascope/ops/_internal/instrumentation/llm/cost.py +190 -0
- mirascope/ops/_internal/instrumentation/llm/encode.py +1 -1
- mirascope/ops/_internal/instrumentation/llm/llm.py +116 -1243
- mirascope/ops/_internal/instrumentation/llm/model.py +1798 -0
- mirascope/ops/_internal/instrumentation/llm/response.py +521 -0
- mirascope/ops/_internal/instrumentation/llm/serialize.py +300 -0
- mirascope/ops/_internal/protocols.py +83 -1
- mirascope/ops/_internal/traced_calls.py +4 -0
- mirascope/ops/_internal/traced_functions.py +141 -12
- mirascope/ops/_internal/tracing.py +78 -1
- mirascope/ops/_internal/utils.py +52 -4
- mirascope/ops/_internal/versioned_functions.py +54 -43
- {mirascope-2.0.0a5.dist-info → mirascope-2.0.1.dist-info}/METADATA +14 -13
- mirascope-2.0.1.dist-info/RECORD +423 -0
- {mirascope-2.0.0a5.dist-info → mirascope-2.0.1.dist-info}/licenses/LICENSE +1 -1
- mirascope/llm/formatting/_utils.py +0 -78
- mirascope/llm/mcp/client.py +0 -118
- mirascope/llm/providers/_missing_import_stubs.py +0 -49
- mirascope-2.0.0a5.dist-info/RECORD +0 -265
- {mirascope-2.0.0a5.dist-info → mirascope-2.0.1.dist-info}/WHEEL +0 -0
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
"""Utilities for handling primitive types in formatting."""
|
|
2
|
+
|
|
3
|
+
import inspect
|
|
4
|
+
from enum import Enum
|
|
5
|
+
from types import UnionType
|
|
6
|
+
from typing import (
|
|
7
|
+
Annotated,
|
|
8
|
+
Any,
|
|
9
|
+
Literal,
|
|
10
|
+
Protocol,
|
|
11
|
+
TypeAlias,
|
|
12
|
+
Union,
|
|
13
|
+
cast,
|
|
14
|
+
get_args,
|
|
15
|
+
get_origin,
|
|
16
|
+
)
|
|
17
|
+
from typing_extensions import TypeIs
|
|
18
|
+
|
|
19
|
+
from pydantic import create_model
|
|
20
|
+
|
|
21
|
+
PrimitiveType: TypeAlias = (
|
|
22
|
+
str
|
|
23
|
+
| int
|
|
24
|
+
| float
|
|
25
|
+
| bool
|
|
26
|
+
| bytes
|
|
27
|
+
| list[Any]
|
|
28
|
+
| set[Any]
|
|
29
|
+
| tuple[Any, ...]
|
|
30
|
+
| dict[Any, Any]
|
|
31
|
+
)
|
|
32
|
+
"""Primitive types that can be used with format parameter.
|
|
33
|
+
|
|
34
|
+
These types are automatically wrapped in a BaseModel for schema generation,
|
|
35
|
+
then unwrapped after validation to return the primitive value.
|
|
36
|
+
"""
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
class PrimitiveWrapperModel(Protocol):
|
|
40
|
+
"""Protocol for wrapper models with an output field."""
|
|
41
|
+
|
|
42
|
+
output: Any
|
|
43
|
+
model_fields: Any
|
|
44
|
+
|
|
45
|
+
def __init__(self, *, output: Any) -> None: ... # noqa: ANN401
|
|
46
|
+
|
|
47
|
+
@classmethod
|
|
48
|
+
def model_json_schema(cls) -> dict[str, Any]: ...
|
|
49
|
+
|
|
50
|
+
@classmethod
|
|
51
|
+
def model_validate_json(cls, json_data: str) -> "PrimitiveWrapperModel": ...
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
def is_primitive_type(
|
|
55
|
+
type_: Any, # noqa: ANN401
|
|
56
|
+
) -> TypeIs[type[PrimitiveType]]:
|
|
57
|
+
"""Check if a type is a primitive type that needs wrapping.
|
|
58
|
+
|
|
59
|
+
Returns True for:
|
|
60
|
+
- Basic primitives: str, int, float, bool, bytes, list, set, tuple, dict
|
|
61
|
+
- Enum types
|
|
62
|
+
- Generic types with primitive origins: list[Book], dict[str, int]
|
|
63
|
+
- Literal types
|
|
64
|
+
- Union types (including Optional)
|
|
65
|
+
- Annotated types
|
|
66
|
+
|
|
67
|
+
Returns False for:
|
|
68
|
+
- BaseModel subclasses (already have model_json_schema)
|
|
69
|
+
- None/NoneType
|
|
70
|
+
|
|
71
|
+
Args:
|
|
72
|
+
type_: The type to check
|
|
73
|
+
|
|
74
|
+
Returns:
|
|
75
|
+
True if the type is a primitive that needs wrapping
|
|
76
|
+
|
|
77
|
+
Example:
|
|
78
|
+
>>> is_primitive_type(str)
|
|
79
|
+
True
|
|
80
|
+
>>> is_primitive_type(list[int])
|
|
81
|
+
True
|
|
82
|
+
>>> from pydantic import BaseModel
|
|
83
|
+
>>> class Book(BaseModel):
|
|
84
|
+
... title: str
|
|
85
|
+
>>> is_primitive_type(Book)
|
|
86
|
+
False
|
|
87
|
+
"""
|
|
88
|
+
primitive_types: set[type[PrimitiveType]] = {
|
|
89
|
+
str,
|
|
90
|
+
int,
|
|
91
|
+
float,
|
|
92
|
+
bool,
|
|
93
|
+
bytes,
|
|
94
|
+
list,
|
|
95
|
+
set,
|
|
96
|
+
tuple,
|
|
97
|
+
dict,
|
|
98
|
+
}
|
|
99
|
+
special_types: set[Any] = {Annotated, Literal, Union, UnionType}
|
|
100
|
+
|
|
101
|
+
return (
|
|
102
|
+
(inspect.isclass(type_) and issubclass(type_, Enum))
|
|
103
|
+
or type_ in primitive_types
|
|
104
|
+
or get_origin(type_) in primitive_types.union(special_types)
|
|
105
|
+
)
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
def _get_type_name(type_: Any) -> str: # noqa: ANN401
|
|
109
|
+
"""Extract a clean name from a type for use in model naming.
|
|
110
|
+
|
|
111
|
+
Handles Annotated types by extracting the underlying type,
|
|
112
|
+
and generates clean names for generic types.
|
|
113
|
+
|
|
114
|
+
Args:
|
|
115
|
+
type_: The type to extract a name from
|
|
116
|
+
|
|
117
|
+
Returns:
|
|
118
|
+
A clean string suitable for use in a Python class name
|
|
119
|
+
|
|
120
|
+
Example:
|
|
121
|
+
>>> _get_type_name(str)
|
|
122
|
+
'str'
|
|
123
|
+
>>> _get_type_name(list[int])
|
|
124
|
+
'list_int_'
|
|
125
|
+
"""
|
|
126
|
+
# Import Annotated locally
|
|
127
|
+
# Check if this is an Annotated type
|
|
128
|
+
if get_origin(type_) in {Annotated}:
|
|
129
|
+
# For Annotated types, use the first arg (the actual type)
|
|
130
|
+
return _get_type_name(get_args(type_)[0])
|
|
131
|
+
|
|
132
|
+
# If the type has a __name__ attribute, use it
|
|
133
|
+
if hasattr(type_, "__name__"):
|
|
134
|
+
return type_.__name__
|
|
135
|
+
|
|
136
|
+
# For complex generics like list[Book], use string representation
|
|
137
|
+
type_str = str(type_)
|
|
138
|
+
|
|
139
|
+
# Clean up the string to make it a valid Python identifier
|
|
140
|
+
# Replace brackets and commas with underscores
|
|
141
|
+
clean = (
|
|
142
|
+
type_str.replace("[", "_")
|
|
143
|
+
.replace("]", "_")
|
|
144
|
+
.replace(", ", "_")
|
|
145
|
+
.replace(" ", "")
|
|
146
|
+
.replace("'", "")
|
|
147
|
+
.replace('"', "")
|
|
148
|
+
)
|
|
149
|
+
|
|
150
|
+
return clean
|
|
151
|
+
|
|
152
|
+
|
|
153
|
+
def create_wrapper_model(
|
|
154
|
+
primitive_type: Any, # noqa: ANN401
|
|
155
|
+
) -> type[PrimitiveWrapperModel]:
|
|
156
|
+
"""Create a wrapper BaseModel for a primitive type.
|
|
157
|
+
|
|
158
|
+
The wrapper has a single field called "output" containing the primitive value.
|
|
159
|
+
Uses Pydantic's create_model() to generate the wrapper dynamically.
|
|
160
|
+
|
|
161
|
+
Args:
|
|
162
|
+
primitive_type: The primitive type to wrap
|
|
163
|
+
|
|
164
|
+
Returns:
|
|
165
|
+
A dynamically created BaseModel with an "output" field
|
|
166
|
+
|
|
167
|
+
Example:
|
|
168
|
+
>>> wrapper = create_wrapper_model(str)
|
|
169
|
+
>>> instance = wrapper(output="hello")
|
|
170
|
+
>>> instance.output
|
|
171
|
+
'hello'
|
|
172
|
+
|
|
173
|
+
>>> from pydantic import BaseModel
|
|
174
|
+
>>> class Book(BaseModel):
|
|
175
|
+
... title: str
|
|
176
|
+
>>> wrapper = create_wrapper_model(list[Book])
|
|
177
|
+
>>> books = [Book(title="Test")]
|
|
178
|
+
>>> instance = wrapper(output=books)
|
|
179
|
+
>>> len(instance.output)
|
|
180
|
+
1
|
|
181
|
+
"""
|
|
182
|
+
# Get a clean name for the wrapper class
|
|
183
|
+
type_name = _get_type_name(primitive_type)
|
|
184
|
+
|
|
185
|
+
# Create wrapper model with "output" field (required)
|
|
186
|
+
wrapper = create_model(
|
|
187
|
+
f"{type_name}Output",
|
|
188
|
+
__doc__=f"Wrapper for primitive type {type_name}",
|
|
189
|
+
output=(primitive_type, ...), # ... means required
|
|
190
|
+
)
|
|
191
|
+
|
|
192
|
+
return cast(type[PrimitiveWrapperModel], wrapper)
|
|
@@ -1,18 +1,26 @@
|
|
|
1
1
|
"""Type for the formatting module."""
|
|
2
2
|
|
|
3
|
-
from
|
|
4
|
-
from typing import Generic, Literal, Protocol, runtime_checkable
|
|
3
|
+
from typing import Literal, Protocol, runtime_checkable
|
|
5
4
|
from typing_extensions import TypeVar
|
|
6
5
|
|
|
7
6
|
from pydantic import BaseModel
|
|
8
7
|
|
|
9
|
-
|
|
10
|
-
|
|
8
|
+
from .primitives import PrimitiveType
|
|
9
|
+
|
|
10
|
+
FormattableT = TypeVar(
|
|
11
|
+
"FormattableT", bound=BaseModel | PrimitiveType | None, default=None
|
|
12
|
+
)
|
|
11
13
|
"""Type variable for structured response format types.
|
|
12
14
|
|
|
13
15
|
This TypeVar represents the type of structured output format that LLM responses
|
|
14
|
-
can be parsed into, or None if no format is specified.
|
|
15
|
-
|
|
16
|
+
can be parsed into, or None if no format is specified.
|
|
17
|
+
|
|
18
|
+
Supported format types:
|
|
19
|
+
- Pydantic BaseModel subclasses
|
|
20
|
+
- Primitive types: str, int, float, bool, bytes, list, set, tuple, dict
|
|
21
|
+
- Generic collections: list[Book], dict[str, int], etc.
|
|
22
|
+
- Union, Literal, and Annotated types
|
|
23
|
+
- Enum types
|
|
16
24
|
"""
|
|
17
25
|
|
|
18
26
|
|
|
@@ -20,15 +28,14 @@ FormattingMode = Literal[
|
|
|
20
28
|
"strict",
|
|
21
29
|
"json",
|
|
22
30
|
"tool",
|
|
31
|
+
"parser",
|
|
23
32
|
]
|
|
24
33
|
"""Available modes for response format generation.
|
|
25
34
|
|
|
26
35
|
- "strict": Use strict mode for structured outputs, asking the LLM to strictly adhere
|
|
27
36
|
to a given JSON schema. Not all providers or models support it, and may not be
|
|
28
|
-
compatible with tool calling. When making a call using this mode, an
|
|
29
|
-
`llm.
|
|
30
|
-
unsupported), or an `llm.FeatureNotSupportedError` may be raised (if trying to use
|
|
31
|
-
strict along with tools and that is unsupported).
|
|
37
|
+
compatible with tool calling. When making a call using this mode, an
|
|
38
|
+
`llm.FeatureNotSupportedError` error may be raised if the mode is unsupported.
|
|
32
39
|
|
|
33
40
|
- "json": Use JSON mode for structured outputs. In contrast to strict mode, we ask the
|
|
34
41
|
LLM to output JSON as text, though without guarantees that the model will output
|
|
@@ -43,64 +50,14 @@ FormattingMode = Literal[
|
|
|
43
50
|
content (abstracting over the tool call). If other tools are present, they will
|
|
44
51
|
be handled as regular tool calls.
|
|
45
52
|
|
|
53
|
+
- "parser": Use custom parsing with formatting instructions. No schema generation or
|
|
54
|
+
structured output features. The LLM receives only formatting instructions and the
|
|
55
|
+
response is parsed using a custom parser function created with `@llm.output_parser`.
|
|
56
|
+
|
|
46
57
|
Note: When `llm.format` is not used, the provider will automatically choose a mode at call time.
|
|
47
58
|
"""
|
|
48
59
|
|
|
49
60
|
|
|
50
|
-
@dataclass(kw_only=True)
|
|
51
|
-
class Format(Generic[FormattableT]):
|
|
52
|
-
"""Class representing a structured output format for LLM responses.
|
|
53
|
-
|
|
54
|
-
A `Format` contains metadata needed to describe a structured output type
|
|
55
|
-
to the LLM, including the expected schema. This class is not instantiated directly,
|
|
56
|
-
but is created by calling `llm.format`, or is automatically generated by LLM
|
|
57
|
-
providers when a `Formattable` is passed to a call method.
|
|
58
|
-
|
|
59
|
-
Example:
|
|
60
|
-
|
|
61
|
-
```python
|
|
62
|
-
from mirascope import llm
|
|
63
|
-
|
|
64
|
-
class Book:
|
|
65
|
-
title: str
|
|
66
|
-
author: str
|
|
67
|
-
|
|
68
|
-
print(llm.format(Book, mode="tool"))
|
|
69
|
-
```
|
|
70
|
-
"""
|
|
71
|
-
|
|
72
|
-
name: str
|
|
73
|
-
"""The name of the response format."""
|
|
74
|
-
|
|
75
|
-
description: str | None
|
|
76
|
-
"""A description of the response format, if available."""
|
|
77
|
-
|
|
78
|
-
schema: dict[str, object]
|
|
79
|
-
"""JSON schema representation of the structured output format."""
|
|
80
|
-
|
|
81
|
-
mode: FormattingMode
|
|
82
|
-
"""The decorator-provided mode of the response format.
|
|
83
|
-
|
|
84
|
-
Determines how the LLM call may be modified in order to extract the expected format.
|
|
85
|
-
"""
|
|
86
|
-
|
|
87
|
-
formatting_instructions: str | None
|
|
88
|
-
"""The formatting instructions that will be added to the LLM system prompt.
|
|
89
|
-
|
|
90
|
-
If the format type has a `formatting_instructions` class method, the output of that
|
|
91
|
-
call will be used for instructions. Otherwise, instructions may be auto-generated
|
|
92
|
-
based on the formatting mode.
|
|
93
|
-
"""
|
|
94
|
-
|
|
95
|
-
formattable: type[FormattableT]
|
|
96
|
-
"""The `Formattable` type that this `Format` describes.
|
|
97
|
-
|
|
98
|
-
While the `FormattbleT` typevar allows for `None`, a `Format` will never be
|
|
99
|
-
constructed when the `FormattableT` is `None`, so you may treat this as
|
|
100
|
-
a `RequiredFormattableT` in practice.
|
|
101
|
-
"""
|
|
102
|
-
|
|
103
|
-
|
|
104
61
|
@runtime_checkable
|
|
105
62
|
class HasFormattingInstructions(Protocol):
|
|
106
63
|
"""Protocol for classes that have been decorated with `@format()`."""
|
mirascope/llm/mcp/__init__.py
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
"""MCP compatibility module."""
|
|
2
2
|
|
|
3
|
-
from .
|
|
3
|
+
from .mcp_client import MCPClient, sse_client, stdio_client, streamable_http_client
|
|
4
4
|
|
|
5
|
-
__all__ = ["MCPClient", "sse_client", "stdio_client", "
|
|
5
|
+
__all__ = ["MCPClient", "sse_client", "stdio_client", "streamable_http_client"]
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import contextlib
|
|
2
|
+
from collections.abc import AsyncIterator
|
|
3
|
+
from datetime import timedelta
|
|
4
|
+
from typing import cast
|
|
5
|
+
|
|
6
|
+
from mcp import ClientSession
|
|
7
|
+
from mcp.client.sse import sse_client as mcp_sse_client
|
|
8
|
+
from mcp.client.stdio import StdioServerParameters, stdio_client as mcp_stdio_client
|
|
9
|
+
from mcp.client.streamable_http import (
|
|
10
|
+
streamable_http_client as mcp_streamable_http_client,
|
|
11
|
+
)
|
|
12
|
+
from mcp.types import CallToolResult, Tool as MCPTool
|
|
13
|
+
|
|
14
|
+
from ..tools import AsyncTool
|
|
15
|
+
from ..tools.tool_schema import ToolParameterSchema
|
|
16
|
+
from ..types import Jsonable
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class MCPClient:
|
|
20
|
+
"""Mirascope wrapper around a MCP ClientSession.
|
|
21
|
+
|
|
22
|
+
It provides a way to get MCP results that are pre-converted into Mirascope-friendly
|
|
23
|
+
types.
|
|
24
|
+
|
|
25
|
+
The underlying MCP ClientSession may be accessed by .session if needed.
|
|
26
|
+
"""
|
|
27
|
+
|
|
28
|
+
def __init__(self, session: ClientSession) -> None:
|
|
29
|
+
self._session = session
|
|
30
|
+
|
|
31
|
+
@property
|
|
32
|
+
def session(self) -> ClientSession:
|
|
33
|
+
"""Access the underlying MCP ClientSession if needed."""
|
|
34
|
+
return self._session
|
|
35
|
+
|
|
36
|
+
def _convert_mcp_tool_to_async_tool(self, mcp_tool: MCPTool) -> AsyncTool:
|
|
37
|
+
"""Convert an MCP Tool to a Mirascope AsyncTool.
|
|
38
|
+
|
|
39
|
+
Args:
|
|
40
|
+
mcp_tool: The MCP tool to convert.
|
|
41
|
+
|
|
42
|
+
Returns:
|
|
43
|
+
An `AsyncTool` that wraps the MCP tool.
|
|
44
|
+
"""
|
|
45
|
+
|
|
46
|
+
# Create an async function that calls the MCP tool
|
|
47
|
+
async def tool_fn(**kwargs: object) -> Jsonable:
|
|
48
|
+
tool_result: CallToolResult = await self._session.call_tool(
|
|
49
|
+
mcp_tool.name, kwargs
|
|
50
|
+
)
|
|
51
|
+
# Convert ContentBlock objects to JSON-serializable dicts
|
|
52
|
+
# Cast to Jsonable since model_dump() returns dict[str, Any]
|
|
53
|
+
return cast(
|
|
54
|
+
Jsonable, [content.model_dump() for content in tool_result.content]
|
|
55
|
+
)
|
|
56
|
+
|
|
57
|
+
# Convert MCP tool's inputSchema to Mirascope's ToolParameterSchema
|
|
58
|
+
input_schema = mcp_tool.inputSchema
|
|
59
|
+
parameters = ToolParameterSchema(
|
|
60
|
+
properties=input_schema.get("properties", {}),
|
|
61
|
+
required=input_schema.get("required", []),
|
|
62
|
+
additionalProperties=input_schema.get("additionalProperties", False),
|
|
63
|
+
)
|
|
64
|
+
if "$defs" in input_schema:
|
|
65
|
+
parameters.defs = input_schema["$defs"]
|
|
66
|
+
|
|
67
|
+
# Create the AsyncTool instance
|
|
68
|
+
return AsyncTool(
|
|
69
|
+
fn=tool_fn,
|
|
70
|
+
name=mcp_tool.name,
|
|
71
|
+
description=mcp_tool.description or mcp_tool.name,
|
|
72
|
+
parameters=parameters,
|
|
73
|
+
strict=False,
|
|
74
|
+
)
|
|
75
|
+
|
|
76
|
+
async def list_tools(self) -> list[AsyncTool]:
|
|
77
|
+
"""List all tools available on the MCP server.
|
|
78
|
+
|
|
79
|
+
Returns:
|
|
80
|
+
A list of dynamically created `AsyncTool`s.
|
|
81
|
+
"""
|
|
82
|
+
result = await self._session.list_tools()
|
|
83
|
+
return [self._convert_mcp_tool_to_async_tool(tool) for tool in result.tools]
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
@contextlib.asynccontextmanager
|
|
87
|
+
async def streamable_http_client(
|
|
88
|
+
url: str,
|
|
89
|
+
) -> AsyncIterator[MCPClient]: # pragma: no cover
|
|
90
|
+
"""Create a Mirascope MCPClient using StreamableHTTP."""
|
|
91
|
+
# NOTE: If updating this function, unskip and manually run the TestTransportModes
|
|
92
|
+
# tests in test_mcp_client.py. (Skipped because they are flaky)
|
|
93
|
+
async with (
|
|
94
|
+
mcp_streamable_http_client(url) as (read, write, _),
|
|
95
|
+
ClientSession(read, write) as session,
|
|
96
|
+
):
|
|
97
|
+
await session.initialize()
|
|
98
|
+
yield MCPClient(session)
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
@contextlib.asynccontextmanager
|
|
102
|
+
async def stdio_client(
|
|
103
|
+
server_parameters: StdioServerParameters,
|
|
104
|
+
name: str | None = None,
|
|
105
|
+
) -> AsyncIterator[MCPClient]:
|
|
106
|
+
"""Create a Mirascope MCPClient using stdio."""
|
|
107
|
+
async with (
|
|
108
|
+
mcp_stdio_client(server_parameters) as (read, write),
|
|
109
|
+
ClientSession(read, write) as session,
|
|
110
|
+
):
|
|
111
|
+
await session.initialize()
|
|
112
|
+
yield MCPClient(session)
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
@contextlib.asynccontextmanager
|
|
116
|
+
async def sse_client(
|
|
117
|
+
url: str,
|
|
118
|
+
read_timeout_seconds: timedelta | None = None,
|
|
119
|
+
) -> AsyncIterator[MCPClient]: # pragma: no cover
|
|
120
|
+
"""Create a Mirascope MCPClient using sse."""
|
|
121
|
+
# NOTE: If updating this function, unskip and manually run the TestTransportModes
|
|
122
|
+
# tests in test_mcp_client.py. (Skipped because they are flaky)
|
|
123
|
+
async with (
|
|
124
|
+
mcp_sse_client(url) as (read, write),
|
|
125
|
+
ClientSession(
|
|
126
|
+
read, write, read_timeout_seconds=read_timeout_seconds
|
|
127
|
+
) as session,
|
|
128
|
+
):
|
|
129
|
+
await session.initialize()
|
|
130
|
+
yield MCPClient(session)
|
|
@@ -5,6 +5,7 @@ as a unified `Message` class with different roles (system, user, assistant) and
|
|
|
5
5
|
content arrays that can include text, images, audio, documents, and tool interactions.
|
|
6
6
|
"""
|
|
7
7
|
|
|
8
|
+
from ._utils import is_messages, promote_to_messages
|
|
8
9
|
from .message import (
|
|
9
10
|
AssistantContent,
|
|
10
11
|
AssistantMessage,
|
|
@@ -27,6 +28,8 @@ __all__ = [
|
|
|
27
28
|
"UserContent",
|
|
28
29
|
"UserMessage",
|
|
29
30
|
"assistant",
|
|
31
|
+
"is_messages",
|
|
32
|
+
"promote_to_messages",
|
|
30
33
|
"system",
|
|
31
34
|
"user",
|
|
32
35
|
]
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
"""Utility functions for message handling."""
|
|
2
|
+
|
|
3
|
+
from collections.abc import Sequence
|
|
4
|
+
from typing_extensions import TypeIs
|
|
5
|
+
|
|
6
|
+
from .message import (
|
|
7
|
+
AssistantMessage,
|
|
8
|
+
Message,
|
|
9
|
+
SystemMessage,
|
|
10
|
+
UserContent,
|
|
11
|
+
UserMessage,
|
|
12
|
+
user,
|
|
13
|
+
)
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def is_messages(
|
|
17
|
+
content: UserContent | Sequence[Message],
|
|
18
|
+
) -> TypeIs[Sequence[Message]]:
|
|
19
|
+
if isinstance(content, list):
|
|
20
|
+
if not content:
|
|
21
|
+
raise ValueError("Empty array may not be used as message content")
|
|
22
|
+
return isinstance(content[0], SystemMessage | UserMessage | AssistantMessage)
|
|
23
|
+
return False
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def promote_to_messages(content: UserContent | Sequence[Message]) -> Sequence[Message]:
|
|
27
|
+
"""Promote a prompt result to a list of messages.
|
|
28
|
+
|
|
29
|
+
If the result is already a list of Messages, returns it as-is.
|
|
30
|
+
If the result is str/UserContentPart/Sequence of content parts, wraps it in a user message.
|
|
31
|
+
"""
|
|
32
|
+
if is_messages(content):
|
|
33
|
+
return content
|
|
34
|
+
return [user(content)]
|
mirascope/llm/models/__init__.py
CHANGED
|
@@ -7,9 +7,14 @@ creates a default one.
|
|
|
7
7
|
"""
|
|
8
8
|
|
|
9
9
|
from .models import Model, model, model_from_context, use_model
|
|
10
|
+
from .params import Params
|
|
11
|
+
from .thinking_config import ThinkingConfig, ThinkingLevel
|
|
10
12
|
|
|
11
13
|
__all__ = [
|
|
12
14
|
"Model",
|
|
15
|
+
"Params",
|
|
16
|
+
"ThinkingConfig",
|
|
17
|
+
"ThinkingLevel",
|
|
13
18
|
"model",
|
|
14
19
|
"model_from_context",
|
|
15
20
|
"use_model",
|