qca 0.0.1.dev1__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.
- qca/__init__.py +50 -0
- qca/_version.py +1 -0
- qca/common/__init__.py +43 -0
- qca/common/_base_client.py +450 -0
- qca/common/_exceptions.py +97 -0
- qca/common/_files.py +38 -0
- qca/common/_models.py +33 -0
- qca/common/_resource.py +35 -0
- qca/common/_response.py +220 -0
- qca/common/_streaming.py +143 -0
- qca/common/_types.py +25 -0
- qca/common/_utils.py +73 -0
- qca/common/credentials.py +13 -0
- qca/common/pagination.py +118 -0
- qca/forward/__init__.py +7 -0
- qca/forward/_client.py +142 -0
- qca/forward/resources/__init__.py +14 -0
- qca/forward/resources/batches/__init__.py +4 -0
- qca/forward/resources/batches/batches.py +308 -0
- qca/forward/resources/batches/tasks.py +71 -0
- qca/forward/resources/channel_pairings.py +111 -0
- qca/forward/resources/channels/__init__.py +4 -0
- qca/forward/resources/channels/channels.py +336 -0
- qca/forward/resources/channels/qr_sessions.py +106 -0
- qca/forward/resources/environments.py +305 -0
- qca/forward/resources/files.py +272 -0
- qca/forward/resources/identities/__init__.py +6 -0
- qca/forward/resources/identities/configs.py +249 -0
- qca/forward/resources/identities/identities.py +570 -0
- qca/forward/resources/identities/memory_stores.py +186 -0
- qca/forward/resources/memory_stores/__init__.py +6 -0
- qca/forward/resources/memory_stores/memories.py +290 -0
- qca/forward/resources/memory_stores/memory_stores.py +321 -0
- qca/forward/resources/memory_stores/memory_versions.py +179 -0
- qca/forward/resources/models.py +58 -0
- qca/forward/resources/schedule_runs.py +149 -0
- qca/forward/resources/schedules.py +545 -0
- qca/forward/resources/sessions/__init__.py +6 -0
- qca/forward/resources/sessions/events.py +208 -0
- qca/forward/resources/sessions/resources.py +66 -0
- qca/forward/resources/sessions/sessions.py +417 -0
- qca/forward/resources/sessions/threads/__init__.py +4 -0
- qca/forward/resources/sessions/threads/events.py +128 -0
- qca/forward/resources/sessions/threads/threads.py +177 -0
- qca/forward/resources/skills/__init__.py +4 -0
- qca/forward/resources/skills/skills.py +335 -0
- qca/forward/resources/skills/versions.py +253 -0
- qca/forward/resources/templates.py +426 -0
- qca/forward/resources/vaults/__init__.py +4 -0
- qca/forward/resources/vaults/credentials.py +227 -0
- qca/forward/resources/vaults/vaults.py +217 -0
- qca/forward/types/__init__.py +205 -0
- qca/forward/types/batch.py +35 -0
- qca/forward/types/batch_cancel_params.py +11 -0
- qca/forward/types/batch_create_params.py +14 -0
- qca/forward/types/batch_file.py +13 -0
- qca/forward/types/batch_list_params.py +14 -0
- qca/forward/types/batch_request_counts.py +17 -0
- qca/forward/types/batch_task.py +24 -0
- qca/forward/types/batch_task_artifacts_item.py +14 -0
- qca/forward/types/batch_task_error.py +12 -0
- qca/forward/types/batch_task_list_params.py +14 -0
- qca/forward/types/batch_task_usage.py +11 -0
- qca/forward/types/batch_usage.py +11 -0
- qca/forward/types/channel.py +27 -0
- qca/forward/types/channel_channel_config.py +14 -0
- qca/forward/types/channel_channel_config_response_options.py +12 -0
- qca/forward/types/channel_create_params.py +18 -0
- qca/forward/types/channel_identity_resolution.py +11 -0
- qca/forward/types/channel_list_params.py +18 -0
- qca/forward/types/channel_pairing.py +17 -0
- qca/forward/types/channel_pairing_create_params.py +14 -0
- qca/forward/types/channel_qr_session.py +19 -0
- qca/forward/types/channel_qr_session_create_params.py +11 -0
- qca/forward/types/channel_update_params.py +16 -0
- qca/forward/types/content_block_param.py +17 -0
- qca/forward/types/deleted_channel.py +12 -0
- qca/forward/types/deleted_channel_pairing.py +12 -0
- qca/forward/types/deleted_identity.py +12 -0
- qca/forward/types/deleted_memory.py +13 -0
- qca/forward/types/deleted_memory_store.py +13 -0
- qca/forward/types/deleted_memory_store_mount.py +13 -0
- qca/forward/types/deleted_skill_version.py +13 -0
- qca/forward/types/effective_config.py +23 -0
- qca/forward/types/effective_config_agent.py +19 -0
- qca/forward/types/effective_config_agent_tools_item.py +15 -0
- qca/forward/types/effective_config_agent_tools_item_configs_item.py +12 -0
- qca/forward/types/effective_config_session.py +17 -0
- qca/forward/types/effective_config_session_resources_item.py +14 -0
- qca/forward/types/environment.py +24 -0
- qca/forward/types/environment_config.py +15 -0
- qca/forward/types/environment_config_packages.py +17 -0
- qca/forward/types/environment_create_params.py +15 -0
- qca/forward/types/environment_list_params.py +14 -0
- qca/forward/types/environment_update_params.py +14 -0
- qca/forward/types/environment_variable_override.py +12 -0
- qca/forward/types/environment_variable_override_param.py +12 -0
- qca/forward/types/file_list_params.py +16 -0
- qca/forward/types/file_metadata.py +22 -0
- qca/forward/types/file_upload_params.py +17 -0
- qca/forward/types/git_hub_repository.py +13 -0
- qca/forward/types/git_hub_repository_param.py +14 -0
- qca/forward/types/identity.py +19 -0
- qca/forward/types/identity_clear_params.py +11 -0
- qca/forward/types/identity_clear_response.py +18 -0
- qca/forward/types/identity_clear_response_summary.py +16 -0
- qca/forward/types/identity_config.py +25 -0
- qca/forward/types/identity_config_list_params.py +15 -0
- qca/forward/types/identity_config_spec.py +31 -0
- qca/forward/types/identity_config_spec_param.py +31 -0
- qca/forward/types/identity_config_upsert_params.py +17 -0
- qca/forward/types/identity_create_params.py +15 -0
- qca/forward/types/identity_list_params.py +17 -0
- qca/forward/types/identity_list_templates_response.py +14 -0
- qca/forward/types/identity_memory_store_list_response.py +15 -0
- qca/forward/types/identity_memory_store_mount_params.py +9 -0
- qca/forward/types/identity_stats.py +14 -0
- qca/forward/types/identity_template.py +15 -0
- qca/forward/types/identity_update_params.py +15 -0
- qca/forward/types/image_source_param.py +15 -0
- qca/forward/types/mcp_server.py +13 -0
- qca/forward/types/mcp_server_override.py +13 -0
- qca/forward/types/mcp_server_override_param.py +13 -0
- qca/forward/types/mcp_server_param.py +13 -0
- qca/forward/types/memory.py +21 -0
- qca/forward/types/memory_store.py +25 -0
- qca/forward/types/memory_store_create_params.py +14 -0
- qca/forward/types/memory_store_list_params.py +14 -0
- qca/forward/types/memory_store_memory_create_params.py +13 -0
- qca/forward/types/memory_store_memory_list_params.py +14 -0
- qca/forward/types/memory_store_memory_update_params.py +13 -0
- qca/forward/types/memory_store_memory_version_list_params.py +14 -0
- qca/forward/types/memory_store_mount.py +20 -0
- qca/forward/types/memory_store_update_params.py +13 -0
- qca/forward/types/memory_version.py +23 -0
- qca/forward/types/model.py +23 -0
- qca/forward/types/model_config.py +13 -0
- qca/forward/types/model_config_param.py +13 -0
- qca/forward/types/model_list_response.py +15 -0
- qca/forward/types/multiagent_config.py +15 -0
- qca/forward/types/multiagent_config_param.py +15 -0
- qca/forward/types/multiagent_entry.py +13 -0
- qca/forward/types/multiagent_entry_param.py +13 -0
- qca/forward/types/permission_policy.py +11 -0
- qca/forward/types/permission_policy_param.py +9 -0
- qca/forward/types/resource_binding.py +11 -0
- qca/forward/types/resource_binding_param.py +11 -0
- qca/forward/types/schedule.py +34 -0
- qca/forward/types/schedule_archive_many_params.py +12 -0
- qca/forward/types/schedule_archive_many_response.py +11 -0
- qca/forward/types/schedule_archive_params.py +11 -0
- qca/forward/types/schedule_create_params.py +21 -0
- qca/forward/types/schedule_execution.py +14 -0
- qca/forward/types/schedule_initial_events_item.py +12 -0
- qca/forward/types/schedule_list_params.py +19 -0
- qca/forward/types/schedule_pause_params.py +11 -0
- qca/forward/types/schedule_paused_reason.py +11 -0
- qca/forward/types/schedule_run.py +33 -0
- qca/forward/types/schedule_run_list_params.py +20 -0
- qca/forward/types/schedule_run_params.py +11 -0
- qca/forward/types/schedule_run_retrieve_params.py +11 -0
- qca/forward/types/schedule_run_trigger_context.py +13 -0
- qca/forward/types/schedule_sinks_item.py +16 -0
- qca/forward/types/schedule_sinks_item_target.py +12 -0
- qca/forward/types/schedule_trigger_policy.py +15 -0
- qca/forward/types/schedule_unpause_params.py +11 -0
- qca/forward/types/schedule_update_params.py +20 -0
- qca/forward/types/session.py +33 -0
- qca/forward/types/session_archive_params.py +11 -0
- qca/forward/types/session_cancel_params.py +11 -0
- qca/forward/types/session_config.py +11 -0
- qca/forward/types/session_create_params.py +21 -0
- qca/forward/types/session_create_params_config_param.py +11 -0
- qca/forward/types/session_event.py +52 -0
- qca/forward/types/session_event_list_params.py +18 -0
- qca/forward/types/session_event_param.py +24 -0
- qca/forward/types/session_event_send_params.py +15 -0
- qca/forward/types/session_event_send_response.py +14 -0
- qca/forward/types/session_event_stream_params.py +14 -0
- qca/forward/types/session_list_params.py +27 -0
- qca/forward/types/session_resource.py +17 -0
- qca/forward/types/session_resource_add_params.py +13 -0
- qca/forward/types/session_resource_spec_param.py +13 -0
- qca/forward/types/session_stats.py +12 -0
- qca/forward/types/session_template.py +18 -0
- qca/forward/types/session_thread.py +27 -0
- qca/forward/types/session_thread_archive_params.py +11 -0
- qca/forward/types/session_thread_event_list_params.py +13 -0
- qca/forward/types/session_thread_event_stream_params.py +11 -0
- qca/forward/types/session_thread_list_params.py +13 -0
- qca/forward/types/session_thread_stop_reason.py +11 -0
- qca/forward/types/session_update_params.py +17 -0
- qca/forward/types/session_update_params_config_param.py +11 -0
- qca/forward/types/session_usage.py +11 -0
- qca/forward/types/skill.py +23 -0
- qca/forward/types/skill_binding.py +14 -0
- qca/forward/types/skill_binding_param.py +14 -0
- qca/forward/types/skill_create_params.py +20 -0
- qca/forward/types/skill_list_params.py +17 -0
- qca/forward/types/skill_override.py +13 -0
- qca/forward/types/skill_override_param.py +13 -0
- qca/forward/types/skill_retrieve_params.py +11 -0
- qca/forward/types/skill_update_params.py +16 -0
- qca/forward/types/skill_version.py +22 -0
- qca/forward/types/skill_version_create_params.py +13 -0
- qca/forward/types/skill_version_list_params.py +12 -0
- qca/forward/types/system_override.py +12 -0
- qca/forward/types/system_override_param.py +12 -0
- qca/forward/types/template.py +39 -0
- qca/forward/types/template_archive_params.py +11 -0
- qca/forward/types/template_clone_params.py +13 -0
- qca/forward/types/template_create_params.py +35 -0
- qca/forward/types/template_list_params.py +14 -0
- qca/forward/types/template_update_params.py +35 -0
- qca/forward/types/tool.py +21 -0
- qca/forward/types/tool_config.py +16 -0
- qca/forward/types/tool_config_param.py +16 -0
- qca/forward/types/tool_override.py +15 -0
- qca/forward/types/tool_override_param.py +15 -0
- qca/forward/types/tool_param.py +21 -0
- qca/forward/types/vault.py +18 -0
- qca/forward/types/vault_create_params.py +13 -0
- qca/forward/types/vault_credential.py +22 -0
- qca/forward/types/vault_credential_auth.py +12 -0
- qca/forward/types/vault_credential_create_params.py +14 -0
- qca/forward/types/vault_credential_list_params.py +15 -0
- qca/forward/types/vault_list_params.py +15 -0
- qca/managed/__init__.py +7 -0
- qca/managed/_client.py +115 -0
- qca/managed/resources/__init__.py +10 -0
- qca/managed/resources/agents/__init__.py +4 -0
- qca/managed/resources/agents/agents.py +386 -0
- qca/managed/resources/agents/versions.py +71 -0
- qca/managed/resources/deployment_runs.py +160 -0
- qca/managed/resources/deployments.py +552 -0
- qca/managed/resources/dreams.py +303 -0
- qca/managed/resources/environments/__init__.py +4 -0
- qca/managed/resources/environments/environments.py +359 -0
- qca/managed/resources/environments/work.py +449 -0
- qca/managed/resources/files.py +295 -0
- qca/managed/resources/memory_stores/__init__.py +6 -0
- qca/managed/resources/memory_stores/memories.py +358 -0
- qca/managed/resources/memory_stores/memory_stores.py +362 -0
- qca/managed/resources/memory_stores/memory_versions.py +228 -0
- qca/managed/resources/models.py +71 -0
- qca/managed/resources/sessions/__init__.py +6 -0
- qca/managed/resources/sessions/events.py +240 -0
- qca/managed/resources/sessions/resources.py +303 -0
- qca/managed/resources/sessions/sessions.py +472 -0
- qca/managed/resources/sessions/threads/__init__.py +4 -0
- qca/managed/resources/sessions/threads/events.py +141 -0
- qca/managed/resources/sessions/threads/threads.py +185 -0
- qca/managed/resources/skills/__init__.py +4 -0
- qca/managed/resources/skills/skills.py +254 -0
- qca/managed/resources/skills/versions.py +273 -0
- qca/managed/resources/vaults/__init__.py +4 -0
- qca/managed/resources/vaults/credentials.py +437 -0
- qca/managed/resources/vaults/vaults.py +296 -0
- qca/managed/types/__init__.py +421 -0
- qca/managed/types/actor_union.py +15 -0
- qca/managed/types/advisor_params.py +12 -0
- qca/managed/types/agent.py +33 -0
- qca/managed/types/agent_archive_params.py +12 -0
- qca/managed/types/agent_create_params.py +31 -0
- qca/managed/types/agent_list_params.py +18 -0
- qca/managed/types/agent_mcp_tool_result_event_content_union.py +21 -0
- qca/managed/types/agent_message_event_content_union.py +12 -0
- qca/managed/types/agent_params.py +13 -0
- qca/managed/types/agent_reference.py +13 -0
- qca/managed/types/agent_retrieve_params.py +13 -0
- qca/managed/types/agent_skill_union.py +13 -0
- qca/managed/types/agent_thread_message_received_event_content_union.py +20 -0
- qca/managed/types/agent_thread_message_received_event_content_union_source.py +15 -0
- qca/managed/types/agent_thread_message_sent_event_content_union.py +18 -0
- qca/managed/types/agent_thread_message_sent_event_content_union_source.py +15 -0
- qca/managed/types/agent_tool_config_union.py +22 -0
- qca/managed/types/agent_tool_config_union_permission_policy.py +11 -0
- qca/managed/types/agent_tool_result_event_content_union.py +21 -0
- qca/managed/types/agent_tool_union.py +25 -0
- qca/managed/types/agent_tool_union_default_config.py +15 -0
- qca/managed/types/agent_tool_union_default_config_permission_policy.py +11 -0
- qca/managed/types/agent_toolset20260401_params.py +37 -0
- qca/managed/types/agent_toolset_default_config_params.py +16 -0
- qca/managed/types/agent_update_params.py +32 -0
- qca/managed/types/agent_version_list_params.py +14 -0
- qca/managed/types/agent_with_overrides_params.py +27 -0
- qca/managed/types/always_allow_policy_param.py +11 -0
- qca/managed/types/always_ask_policy_param.py +11 -0
- qca/managed/types/base64_document_source_param.py +13 -0
- qca/managed/types/base64_image_source_param.py +13 -0
- qca/managed/types/bash_tool_config_params.py +18 -0
- qca/managed/types/branch_checkout_param.py +12 -0
- qca/managed/types/budget_limit.py +15 -0
- qca/managed/types/budget_limit_param.py +15 -0
- qca/managed/types/cache_creation_usage.py +12 -0
- qca/managed/types/capability_support.py +11 -0
- qca/managed/types/cloud_config_networking_union.py +14 -0
- qca/managed/types/cloud_config_params.py +19 -0
- qca/managed/types/commit_checkout_param.py +12 -0
- qca/managed/types/context_management_capability.py +17 -0
- qca/managed/types/credential.py +23 -0
- qca/managed/types/credential_auth_union.py +23 -0
- qca/managed/types/credential_validation.py +23 -0
- qca/managed/types/custom_skill_params.py +13 -0
- qca/managed/types/custom_tool_input_schema.py +13 -0
- qca/managed/types/custom_tool_input_schema_param.py +13 -0
- qca/managed/types/custom_tool_params.py +17 -0
- qca/managed/types/delete_session_resource.py +12 -0
- qca/managed/types/deleted_credential.py +12 -0
- qca/managed/types/deleted_file.py +12 -0
- qca/managed/types/deleted_memory.py +12 -0
- qca/managed/types/deleted_memory_store.py +12 -0
- qca/managed/types/deleted_session.py +12 -0
- qca/managed/types/deleted_skill.py +12 -0
- qca/managed/types/deleted_skill_version.py +12 -0
- qca/managed/types/deleted_vault.py +12 -0
- qca/managed/types/delta_content.py +16 -0
- qca/managed/types/deployment.py +37 -0
- qca/managed/types/deployment_archive_params.py +12 -0
- qca/managed/types/deployment_create_params.py +36 -0
- qca/managed/types/deployment_initial_event_union.py +20 -0
- qca/managed/types/deployment_list_params.py +22 -0
- qca/managed/types/deployment_pause_params.py +12 -0
- qca/managed/types/deployment_paused_reason_error_union.py +11 -0
- qca/managed/types/deployment_paused_reason_union.py +15 -0
- qca/managed/types/deployment_retrieve_params.py +12 -0
- qca/managed/types/deployment_run.py +24 -0
- qca/managed/types/deployment_run_error_union.py +12 -0
- qca/managed/types/deployment_run_list_params.py +24 -0
- qca/managed/types/deployment_run_params.py +12 -0
- qca/managed/types/deployment_run_retrieve_params.py +12 -0
- qca/managed/types/deployment_unpause_params.py +12 -0
- qca/managed/types/deployment_update_params.py +34 -0
- qca/managed/types/deployment_user_define_outcome_event_rubric_union.py +13 -0
- qca/managed/types/deployment_user_message_event_content_union.py +18 -0
- qca/managed/types/deployment_user_message_event_content_union_source.py +15 -0
- qca/managed/types/document_block_param.py +22 -0
- qca/managed/types/dream.py +33 -0
- qca/managed/types/dream_archive_params.py +12 -0
- qca/managed/types/dream_cancel_params.py +12 -0
- qca/managed/types/dream_create_params.py +23 -0
- qca/managed/types/dream_error.py +12 -0
- qca/managed/types/dream_input_union.py +13 -0
- qca/managed/types/dream_list_params.py +19 -0
- qca/managed/types/dream_memory_store_input_param.py +12 -0
- qca/managed/types/dream_model_config.py +12 -0
- qca/managed/types/dream_model_config_param.py +12 -0
- qca/managed/types/dream_output.py +12 -0
- qca/managed/types/dream_retrieve_params.py +12 -0
- qca/managed/types/dream_sessions_input_param.py +12 -0
- qca/managed/types/dream_usage.py +14 -0
- qca/managed/types/edit_tool_config_params.py +18 -0
- qca/managed/types/effort_capability.py +19 -0
- qca/managed/types/effort_high_param.py +11 -0
- qca/managed/types/effort_low_param.py +11 -0
- qca/managed/types/effort_max_param.py +11 -0
- qca/managed/types/effort_medium_param.py +11 -0
- qca/managed/types/effort_xhigh_param.py +11 -0
- qca/managed/types/environment.py +23 -0
- qca/managed/types/environment_archive_params.py +12 -0
- qca/managed/types/environment_config_union.py +17 -0
- qca/managed/types/environment_create_params.py +21 -0
- qca/managed/types/environment_delete_params.py +12 -0
- qca/managed/types/environment_delete_response.py +12 -0
- qca/managed/types/environment_list_params.py +18 -0
- qca/managed/types/environment_retrieve_params.py +12 -0
- qca/managed/types/environment_update_params.py +21 -0
- qca/managed/types/environment_variable_auth_response_networking_union.py +12 -0
- qca/managed/types/environment_variable_create_params.py +20 -0
- qca/managed/types/environment_variable_update_params.py +19 -0
- qca/managed/types/environment_work_ack_params.py +11 -0
- qca/managed/types/environment_work_heartbeat_params.py +13 -0
- qca/managed/types/environment_work_list_params.py +15 -0
- qca/managed/types/environment_work_poll_params.py +14 -0
- qca/managed/types/environment_work_retrieve_params.py +12 -0
- qca/managed/types/environment_work_stats_params.py +12 -0
- qca/managed/types/environment_work_stop_params.py +13 -0
- qca/managed/types/environment_work_update_params.py +13 -0
- qca/managed/types/file_delete_params.py +12 -0
- qca/managed/types/file_document_source_param.py +12 -0
- qca/managed/types/file_download_params.py +12 -0
- qca/managed/types/file_get_metadata_params.py +12 -0
- qca/managed/types/file_image_source_param.py +12 -0
- qca/managed/types/file_list_params.py +19 -0
- qca/managed/types/file_metadata.py +25 -0
- qca/managed/types/file_resource.py +17 -0
- qca/managed/types/file_resource_params.py +13 -0
- qca/managed/types/file_rubric_params.py +12 -0
- qca/managed/types/file_scope.py +12 -0
- qca/managed/types/file_upload_params.py +18 -0
- qca/managed/types/git_hub_repository_resource_checkout_union.py +13 -0
- qca/managed/types/git_hub_repository_resource_config_checkout_union.py +13 -0
- qca/managed/types/git_hub_repository_resource_params.py +19 -0
- qca/managed/types/glob_tool_config_params.py +18 -0
- qca/managed/types/grep_tool_config_params.py +18 -0
- qca/managed/types/image_block_param.py +17 -0
- qca/managed/types/injection_location_params.py +12 -0
- qca/managed/types/injection_location_response.py +12 -0
- qca/managed/types/injection_location_update_params.py +12 -0
- qca/managed/types/limited_credential_networking_params.py +12 -0
- qca/managed/types/limited_network_params.py +14 -0
- qca/managed/types/mcp_probe.py +15 -0
- qca/managed/types/mcp_server_url_definition.py +13 -0
- qca/managed/types/mcp_tool_config.py +16 -0
- qca/managed/types/mcp_tool_config_params.py +17 -0
- qca/managed/types/mcp_tool_config_permission_policy_union.py +11 -0
- qca/managed/types/mcp_toolset_default_config_params.py +16 -0
- qca/managed/types/mcp_toolset_params.py +18 -0
- qca/managed/types/mcpo_auth_create_params.py +19 -0
- qca/managed/types/mcpo_auth_refresh_params.py +23 -0
- qca/managed/types/mcpo_auth_refresh_response.py +18 -0
- qca/managed/types/mcpo_auth_refresh_response_token_endpoint_auth_union.py +11 -0
- qca/managed/types/mcpo_auth_refresh_update_params.py +17 -0
- qca/managed/types/mcpo_auth_update_params.py +18 -0
- qca/managed/types/memory.py +22 -0
- qca/managed/types/memory_list_item_union.py +21 -0
- qca/managed/types/memory_store.py +19 -0
- qca/managed/types/memory_store_archive_params.py +12 -0
- qca/managed/types/memory_store_create_params.py +15 -0
- qca/managed/types/memory_store_delete_params.py +12 -0
- qca/managed/types/memory_store_list_params.py +19 -0
- qca/managed/types/memory_store_memory_create_params.py +16 -0
- qca/managed/types/memory_store_memory_delete_params.py +13 -0
- qca/managed/types/memory_store_memory_list_params.py +17 -0
- qca/managed/types/memory_store_memory_retrieve_params.py +13 -0
- qca/managed/types/memory_store_memory_update_params.py +21 -0
- qca/managed/types/memory_store_memory_version_list_params.py +23 -0
- qca/managed/types/memory_store_memory_version_redact_params.py +12 -0
- qca/managed/types/memory_store_memory_version_retrieve_params.py +13 -0
- qca/managed/types/memory_store_resource_param.py +14 -0
- qca/managed/types/memory_store_retrieve_params.py +12 -0
- qca/managed/types/memory_store_update_params.py +15 -0
- qca/managed/types/memory_version.py +27 -0
- qca/managed/types/model_capabilities.py +25 -0
- qca/managed/types/model_config.py +18 -0
- qca/managed/types/model_config_effort_union.py +11 -0
- qca/managed/types/model_config_params.py +39 -0
- qca/managed/types/model_info.py +30 -0
- qca/managed/types/model_list_params.py +15 -0
- qca/managed/types/monetary_amount.py +12 -0
- qca/managed/types/monetary_amount_param.py +12 -0
- qca/managed/types/multiagent.py +15 -0
- qca/managed/types/multiagent_agent_union.py +17 -0
- qca/managed/types/multiagent_params.py +17 -0
- qca/managed/types/multiagent_self_params.py +11 -0
- qca/managed/types/outcome_evaluation_resource.py +18 -0
- qca/managed/types/output_behavior_create_new_param.py +11 -0
- qca/managed/types/output_behavior_union.py +12 -0
- qca/managed/types/output_behavior_update_existing_param.py +12 -0
- qca/managed/types/packages.py +17 -0
- qca/managed/types/packages_params.py +17 -0
- qca/managed/types/plain_text_document_source_param.py +13 -0
- qca/managed/types/precondition_param.py +12 -0
- qca/managed/types/qoder_skill_params.py +13 -0
- qca/managed/types/read_tool_config_params.py +18 -0
- qca/managed/types/redacted_block_param.py +11 -0
- qca/managed/types/refresh_http_response.py +14 -0
- qca/managed/types/refresh_object.py +15 -0
- qca/managed/types/schedule.py +16 -0
- qca/managed/types/schedule_params.py +13 -0
- qca/managed/types/search_result_block_param.py +19 -0
- qca/managed/types/search_result_citations.py +11 -0
- qca/managed/types/search_result_citations_param.py +9 -0
- qca/managed/types/search_result_content.py +12 -0
- qca/managed/types/search_result_content_param.py +12 -0
- qca/managed/types/self_hosted_config_params.py +11 -0
- qca/managed/types/self_hosted_work.py +26 -0
- qca/managed/types/self_hosted_work_heartbeat_response.py +15 -0
- qca/managed/types/self_hosted_work_queue_stats.py +15 -0
- qca/managed/types/send_session_events.py +14 -0
- qca/managed/types/send_session_events_data_union.py +39 -0
- qca/managed/types/server_tool_usage.py +12 -0
- qca/managed/types/session.py +37 -0
- qca/managed/types/session_agent.py +28 -0
- qca/managed/types/session_agent_skill_union.py +13 -0
- qca/managed/types/session_agent_tool_union.py +25 -0
- qca/managed/types/session_agent_tool_union_default_config.py +17 -0
- qca/managed/types/session_agent_tool_union_default_config_permission_policy.py +11 -0
- qca/managed/types/session_agent_update_param.py +24 -0
- qca/managed/types/session_archive_params.py +12 -0
- qca/managed/types/session_create_params.py +31 -0
- qca/managed/types/session_delete_params.py +12 -0
- qca/managed/types/session_error_event_error_union.py +19 -0
- qca/managed/types/session_error_event_error_union_retry_status.py +11 -0
- qca/managed/types/session_event.py +77 -0
- qca/managed/types/session_event_list_params.py +23 -0
- qca/managed/types/session_event_send_params.py +34 -0
- qca/managed/types/session_event_stop_reason.py +12 -0
- qca/managed/types/session_event_stream_params.py +13 -0
- qca/managed/types/session_event_usage.py +24 -0
- qca/managed/types/session_list_params.py +26 -0
- qca/managed/types/session_multiagent_coordinator.py +15 -0
- qca/managed/types/session_multiagent_coordinator_agent_union.py +26 -0
- qca/managed/types/session_resource_add_params.py +15 -0
- qca/managed/types/session_resource_config_union.py +21 -0
- qca/managed/types/session_resource_delete_params.py +12 -0
- qca/managed/types/session_resource_get_response_union.py +27 -0
- qca/managed/types/session_resource_list_params.py +16 -0
- qca/managed/types/session_resource_retrieve_params.py +12 -0
- qca/managed/types/session_resource_union.py +27 -0
- qca/managed/types/session_resource_update_params.py +14 -0
- qca/managed/types/session_resource_update_response_union.py +27 -0
- qca/managed/types/session_retrieve_params.py +12 -0
- qca/managed/types/session_stats.py +12 -0
- qca/managed/types/session_stream_event.py +82 -0
- qca/managed/types/session_stream_event_stop_reason.py +12 -0
- qca/managed/types/session_stream_event_usage.py +24 -0
- qca/managed/types/session_thread.py +27 -0
- qca/managed/types/session_thread_agent_skill_union.py +13 -0
- qca/managed/types/session_thread_agent_tool_union.py +25 -0
- qca/managed/types/session_thread_agent_tool_union_default_config.py +17 -0
- qca/managed/types/session_thread_agent_tool_union_default_config_permission_policy.py +11 -0
- qca/managed/types/session_thread_agent_union.py +26 -0
- qca/managed/types/session_thread_archive_params.py +12 -0
- qca/managed/types/session_thread_event_list_params.py +16 -0
- qca/managed/types/session_thread_event_stream_params.py +13 -0
- qca/managed/types/session_thread_list_params.py +14 -0
- qca/managed/types/session_thread_retrieve_params.py +12 -0
- qca/managed/types/session_thread_stats.py +13 -0
- qca/managed/types/session_thread_usage.py +22 -0
- qca/managed/types/session_update_params.py +22 -0
- qca/managed/types/session_usage.py +22 -0
- qca/managed/types/session_work_data.py +12 -0
- qca/managed/types/skill.py +22 -0
- qca/managed/types/skill_create_params.py +17 -0
- qca/managed/types/skill_delete_params.py +12 -0
- qca/managed/types/skill_list_params.py +19 -0
- qca/managed/types/skill_retrieve_params.py +12 -0
- qca/managed/types/skill_source.py +11 -0
- qca/managed/types/skill_version.py +19 -0
- qca/managed/types/skill_version_create_params.py +15 -0
- qca/managed/types/skill_version_delete_params.py +12 -0
- qca/managed/types/skill_version_download_params.py +12 -0
- qca/managed/types/skill_version_list_params.py +14 -0
- qca/managed/types/skill_version_retrieve_params.py +12 -0
- qca/managed/types/span_model_usage.py +15 -0
- qca/managed/types/start_event_preview_union.py +12 -0
- qca/managed/types/static_bearer_create_params.py +13 -0
- qca/managed/types/static_bearer_update_params.py +12 -0
- qca/managed/types/stream_session_thread_events_union.py +82 -0
- qca/managed/types/stream_session_thread_events_union_stop_reason.py +12 -0
- qca/managed/types/stream_session_thread_events_union_usage.py +24 -0
- qca/managed/types/system_content_block.py +12 -0
- qca/managed/types/system_content_block_param.py +12 -0
- qca/managed/types/system_message_event_params.py +15 -0
- qca/managed/types/text_block.py +12 -0
- qca/managed/types/text_block_param.py +12 -0
- qca/managed/types/text_rubric_params.py +12 -0
- qca/managed/types/thinking_capability.py +15 -0
- qca/managed/types/thinking_types.py +15 -0
- qca/managed/types/token_endpoint_auth_basic_param.py +12 -0
- qca/managed/types/token_endpoint_auth_basic_update_param.py +12 -0
- qca/managed/types/token_endpoint_auth_none_param.py +11 -0
- qca/managed/types/token_endpoint_auth_post_param.py +12 -0
- qca/managed/types/token_endpoint_auth_post_update_param.py +12 -0
- qca/managed/types/trigger_context_union.py +13 -0
- qca/managed/types/unrestricted_credential_networking_params.py +11 -0
- qca/managed/types/unrestricted_network_param.py +11 -0
- qca/managed/types/url_document_source_param.py +12 -0
- qca/managed/types/url_image_source_param.py +12 -0
- qca/managed/types/urlmcp_server_params.py +13 -0
- qca/managed/types/user_custom_tool_result_event_content_union.py +21 -0
- qca/managed/types/user_custom_tool_result_event_params.py +20 -0
- qca/managed/types/user_define_outcome_event_params.py +18 -0
- qca/managed/types/user_define_outcome_event_rubric_union.py +13 -0
- qca/managed/types/user_interrupt_event_params.py +12 -0
- qca/managed/types/user_location.py +15 -0
- qca/managed/types/user_location_param.py +15 -0
- qca/managed/types/user_message_event_content_union.py +18 -0
- qca/managed/types/user_message_event_content_union_source.py +15 -0
- qca/managed/types/user_message_event_params.py +18 -0
- qca/managed/types/user_tool_confirmation_event_params.py +14 -0
- qca/managed/types/user_tool_result_event_content_union.py +21 -0
- qca/managed/types/user_tool_result_event_params.py +20 -0
- qca/managed/types/vault.py +18 -0
- qca/managed/types/vault_archive_params.py +12 -0
- qca/managed/types/vault_create_params.py +14 -0
- qca/managed/types/vault_credential_archive_params.py +12 -0
- qca/managed/types/vault_credential_create_params.py +20 -0
- qca/managed/types/vault_credential_delete_params.py +12 -0
- qca/managed/types/vault_credential_list_params.py +18 -0
- qca/managed/types/vault_credential_mcpo_auth_validate_params.py +12 -0
- qca/managed/types/vault_credential_retrieve_params.py +12 -0
- qca/managed/types/vault_credential_update_params.py +19 -0
- qca/managed/types/vault_delete_params.py +12 -0
- qca/managed/types/vault_list_params.py +18 -0
- qca/managed/types/vault_retrieve_params.py +12 -0
- qca/managed/types/web_fetch_tool_config_params.py +21 -0
- qca/managed/types/web_search_tool_config_params.py +22 -0
- qca/managed/types/write_tool_config_params.py +18 -0
- qca/py.typed +0 -0
- qca-0.0.1.dev1.dist-info/METADATA +279 -0
- qca-0.0.1.dev1.dist-info/RECORD +596 -0
- qca-0.0.1.dev1.dist-info/WHEEL +5 -0
- qca-0.0.1.dev1.dist-info/licenses/LICENSE +21 -0
- qca-0.0.1.dev1.dist-info/top_level.txt +1 -0
qca/__init__.py
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
from ._version import __version__ as __version__
|
|
2
|
+
from .common import (
|
|
3
|
+
NOT_GIVEN as NOT_GIVEN,
|
|
4
|
+
)
|
|
5
|
+
from .common import (
|
|
6
|
+
APIConnectionError as APIConnectionError,
|
|
7
|
+
)
|
|
8
|
+
from .common import (
|
|
9
|
+
APIError as APIError,
|
|
10
|
+
)
|
|
11
|
+
from .common import (
|
|
12
|
+
APIResponseValidationError as APIResponseValidationError,
|
|
13
|
+
)
|
|
14
|
+
from .common import (
|
|
15
|
+
APIStatusError as APIStatusError,
|
|
16
|
+
)
|
|
17
|
+
from .common import (
|
|
18
|
+
APITimeoutError as APITimeoutError,
|
|
19
|
+
)
|
|
20
|
+
from .common import (
|
|
21
|
+
AuthenticationError as AuthenticationError,
|
|
22
|
+
)
|
|
23
|
+
from .common import (
|
|
24
|
+
BadRequestError as BadRequestError,
|
|
25
|
+
)
|
|
26
|
+
from .common import (
|
|
27
|
+
ConflictError as ConflictError,
|
|
28
|
+
)
|
|
29
|
+
from .common import (
|
|
30
|
+
InternalServerError as InternalServerError,
|
|
31
|
+
)
|
|
32
|
+
from .common import (
|
|
33
|
+
NotFoundError as NotFoundError,
|
|
34
|
+
)
|
|
35
|
+
from .common import (
|
|
36
|
+
NotGiven as NotGiven,
|
|
37
|
+
)
|
|
38
|
+
from .common import (
|
|
39
|
+
PermissionDeniedError as PermissionDeniedError,
|
|
40
|
+
)
|
|
41
|
+
from .common import (
|
|
42
|
+
RateLimitError as RateLimitError,
|
|
43
|
+
)
|
|
44
|
+
from .common import (
|
|
45
|
+
UnprocessableEntityError as UnprocessableEntityError,
|
|
46
|
+
)
|
|
47
|
+
from .forward import AsyncForward as AsyncForward
|
|
48
|
+
from .forward import Forward as Forward
|
|
49
|
+
from .managed import AsyncManaged as AsyncManaged
|
|
50
|
+
from .managed import Managed as Managed
|
qca/_version.py
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "0.1.0"
|
qca/common/__init__.py
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
from ._exceptions import (
|
|
2
|
+
APIConnectionError as APIConnectionError,
|
|
3
|
+
)
|
|
4
|
+
from ._exceptions import (
|
|
5
|
+
APIError as APIError,
|
|
6
|
+
)
|
|
7
|
+
from ._exceptions import (
|
|
8
|
+
APIResponseValidationError as APIResponseValidationError,
|
|
9
|
+
)
|
|
10
|
+
from ._exceptions import (
|
|
11
|
+
APIStatusError as APIStatusError,
|
|
12
|
+
)
|
|
13
|
+
from ._exceptions import (
|
|
14
|
+
APITimeoutError as APITimeoutError,
|
|
15
|
+
)
|
|
16
|
+
from ._exceptions import (
|
|
17
|
+
AuthenticationError as AuthenticationError,
|
|
18
|
+
)
|
|
19
|
+
from ._exceptions import (
|
|
20
|
+
BadRequestError as BadRequestError,
|
|
21
|
+
)
|
|
22
|
+
from ._exceptions import (
|
|
23
|
+
ConflictError as ConflictError,
|
|
24
|
+
)
|
|
25
|
+
from ._exceptions import (
|
|
26
|
+
InternalServerError as InternalServerError,
|
|
27
|
+
)
|
|
28
|
+
from ._exceptions import (
|
|
29
|
+
NotFoundError as NotFoundError,
|
|
30
|
+
)
|
|
31
|
+
from ._exceptions import (
|
|
32
|
+
PermissionDeniedError as PermissionDeniedError,
|
|
33
|
+
)
|
|
34
|
+
from ._exceptions import (
|
|
35
|
+
RateLimitError as RateLimitError,
|
|
36
|
+
)
|
|
37
|
+
from ._exceptions import (
|
|
38
|
+
UnprocessableEntityError as UnprocessableEntityError,
|
|
39
|
+
)
|
|
40
|
+
from ._models import BaseModel as BaseModel
|
|
41
|
+
from ._types import NOT_GIVEN as NOT_GIVEN
|
|
42
|
+
from ._types import FileTypes as FileTypes
|
|
43
|
+
from ._types import NotGiven as NotGiven
|
|
@@ -0,0 +1,450 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import inspect
|
|
4
|
+
import os
|
|
5
|
+
import random
|
|
6
|
+
import time
|
|
7
|
+
from email.utils import parsedate_to_datetime
|
|
8
|
+
from typing import Any, Mapping
|
|
9
|
+
|
|
10
|
+
import anyio
|
|
11
|
+
import httpx
|
|
12
|
+
from typing_extensions import Self
|
|
13
|
+
|
|
14
|
+
from qca._version import __version__
|
|
15
|
+
|
|
16
|
+
from ._exceptions import APIConnectionError, APIResponseValidationError, APITimeoutError, status_error
|
|
17
|
+
from ._files import multipart_parts
|
|
18
|
+
from ._models import parse_response
|
|
19
|
+
from ._response import (
|
|
20
|
+
APIResponse,
|
|
21
|
+
AsyncAPIResponse,
|
|
22
|
+
AsyncBinaryAPIResponse,
|
|
23
|
+
BinaryAPIResponse,
|
|
24
|
+
aread_response,
|
|
25
|
+
read_response,
|
|
26
|
+
)
|
|
27
|
+
from ._streaming import AsyncStream, Stream
|
|
28
|
+
from ._types import NOT_GIVEN, NotGiven
|
|
29
|
+
from ._utils import query_pairs, strip_not_given
|
|
30
|
+
from .credentials import AsyncCredential, Credential
|
|
31
|
+
from .pagination import AsyncPage, SyncPage
|
|
32
|
+
|
|
33
|
+
DEFAULT_TIMEOUT = httpx.Timeout(60.0, connect=10.0)
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
class BaseClient:
|
|
37
|
+
_client: Any
|
|
38
|
+
_default_base_url: str
|
|
39
|
+
_base_url_env: str
|
|
40
|
+
_raw_response = False
|
|
41
|
+
_stream_response = False
|
|
42
|
+
_is_async = False
|
|
43
|
+
|
|
44
|
+
def _configure(
|
|
45
|
+
self,
|
|
46
|
+
*,
|
|
47
|
+
access_token: str | None,
|
|
48
|
+
base_url: str | httpx.URL | None,
|
|
49
|
+
timeout: float | httpx.Timeout | None,
|
|
50
|
+
max_retries: int,
|
|
51
|
+
default_headers: Mapping[str, str] | None,
|
|
52
|
+
default_query: Mapping[str, Any] | None,
|
|
53
|
+
credential: Credential | AsyncCredential | None,
|
|
54
|
+
) -> None:
|
|
55
|
+
if not isinstance(max_retries, int) or isinstance(max_retries, bool) or max_retries < 0:
|
|
56
|
+
raise ValueError("max_retries must be a non-negative integer")
|
|
57
|
+
self.access_token = access_token if access_token is not None else os.environ.get("QODER_ACCESS_TOKEN")
|
|
58
|
+
self.credential = credential
|
|
59
|
+
self.base_url = httpx.URL(base_url or os.environ.get(self._base_url_env) or self._default_base_url)
|
|
60
|
+
if self.base_url.scheme not in ("http", "https") or not self.base_url.host or self.base_url.userinfo:
|
|
61
|
+
raise ValueError("base_url must be an absolute HTTP(S) URL without credentials")
|
|
62
|
+
if self.base_url.query or self.base_url.fragment:
|
|
63
|
+
raise ValueError("base_url must not contain a query or fragment")
|
|
64
|
+
if not self.base_url.path.endswith("/"):
|
|
65
|
+
self.base_url = self.base_url.copy_with(path=self.base_url.path + "/")
|
|
66
|
+
self.timeout = timeout
|
|
67
|
+
self.max_retries = max_retries
|
|
68
|
+
self.default_headers = dict(default_headers or {})
|
|
69
|
+
self.default_query = dict(default_query or {})
|
|
70
|
+
|
|
71
|
+
def _copy(self, *, raw: bool = False, streaming: bool = False, **overrides: Any) -> Self:
|
|
72
|
+
options = dict(
|
|
73
|
+
access_token=self.access_token,
|
|
74
|
+
base_url=self.base_url,
|
|
75
|
+
timeout=self.timeout,
|
|
76
|
+
max_retries=self.max_retries,
|
|
77
|
+
default_headers=self.default_headers,
|
|
78
|
+
default_query=self.default_query,
|
|
79
|
+
credential=self.credential,
|
|
80
|
+
http_client=self._client,
|
|
81
|
+
)
|
|
82
|
+
options.update(overrides)
|
|
83
|
+
client = type(self)(**options)
|
|
84
|
+
client._raw_response = raw
|
|
85
|
+
client._stream_response = streaming
|
|
86
|
+
return client
|
|
87
|
+
|
|
88
|
+
def with_options(
|
|
89
|
+
self,
|
|
90
|
+
*,
|
|
91
|
+
access_token: str | NotGiven = NOT_GIVEN,
|
|
92
|
+
base_url: str | httpx.URL | NotGiven = NOT_GIVEN,
|
|
93
|
+
timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN,
|
|
94
|
+
max_retries: int | NotGiven = NOT_GIVEN,
|
|
95
|
+
default_headers: Mapping[str, str] | NotGiven = NOT_GIVEN,
|
|
96
|
+
default_query: Mapping[str, Any] | NotGiven = NOT_GIVEN,
|
|
97
|
+
) -> Self:
|
|
98
|
+
values: dict[str, Any] = dict(
|
|
99
|
+
access_token=access_token, base_url=base_url, timeout=timeout, max_retries=max_retries
|
|
100
|
+
)
|
|
101
|
+
if not isinstance(default_headers, NotGiven):
|
|
102
|
+
values["default_headers"] = {**self.default_headers, **default_headers}
|
|
103
|
+
if not isinstance(default_query, NotGiven):
|
|
104
|
+
values["default_query"] = {**self.default_query, **default_query}
|
|
105
|
+
return self._copy(**{k: v for k, v in values.items() if not isinstance(v, NotGiven)})
|
|
106
|
+
|
|
107
|
+
def _raw_response_view(self, *, streaming: bool = False) -> Self:
|
|
108
|
+
return self._copy(raw=True, streaming=streaming)
|
|
109
|
+
|
|
110
|
+
def is_closed(self) -> bool:
|
|
111
|
+
return self._client.is_closed
|
|
112
|
+
|
|
113
|
+
def _headers(self, options: dict[str, Any], token: str | None) -> httpx.Headers:
|
|
114
|
+
headers = httpx.Headers({"Accept": "application/json", "User-Agent": f"qca-python/{__version__}"})
|
|
115
|
+
if token:
|
|
116
|
+
headers["Authorization"] = f"Bearer {token}"
|
|
117
|
+
for source in (self.default_headers, options.get("headers", {})):
|
|
118
|
+
for key, value in source.items():
|
|
119
|
+
headers[key] = ",".join(str(v) for v in value) if isinstance(value, (list, tuple)) else str(value)
|
|
120
|
+
return headers
|
|
121
|
+
|
|
122
|
+
def _request_args(
|
|
123
|
+
self,
|
|
124
|
+
method: str,
|
|
125
|
+
path: str,
|
|
126
|
+
options: dict[str, Any],
|
|
127
|
+
token: str | None,
|
|
128
|
+
file_fields: list[str] | None,
|
|
129
|
+
) -> dict[str, Any]:
|
|
130
|
+
headers = self._headers(options, token)
|
|
131
|
+
timeout = options.get("timeout", NOT_GIVEN)
|
|
132
|
+
args = dict(
|
|
133
|
+
method=method,
|
|
134
|
+
url=self.base_url.join(path.lstrip("/")),
|
|
135
|
+
headers=headers,
|
|
136
|
+
params=query_pairs({**self.default_query, **options.get("query", {})}),
|
|
137
|
+
timeout=self.timeout if isinstance(timeout, NotGiven) else timeout,
|
|
138
|
+
)
|
|
139
|
+
if file_fields:
|
|
140
|
+
args["files"] = multipart_parts(options.get("body", {}), file_fields)
|
|
141
|
+
elif method not in ("GET", "HEAD") and options.get("body") is not None:
|
|
142
|
+
args["json"] = strip_not_given(options["body"])
|
|
143
|
+
return args
|
|
144
|
+
|
|
145
|
+
def _retryable(self, request: httpx.Request, response: httpx.Response | None) -> bool:
|
|
146
|
+
safe = request.method in ("GET", "HEAD") or bool(request.headers.get("Idempotency-Key"))
|
|
147
|
+
if response is None:
|
|
148
|
+
return safe
|
|
149
|
+
if response.status_code == 409:
|
|
150
|
+
return False
|
|
151
|
+
if not safe and response.status_code != 429:
|
|
152
|
+
return False
|
|
153
|
+
directive = response.headers.get("x-should-retry")
|
|
154
|
+
if directive == "false":
|
|
155
|
+
return False
|
|
156
|
+
if directive == "true":
|
|
157
|
+
return True
|
|
158
|
+
return response.status_code in (408, 429) or response.status_code >= 500
|
|
159
|
+
|
|
160
|
+
def _retry_delay(self, retry: int, response: httpx.Response | None) -> float:
|
|
161
|
+
if response is not None:
|
|
162
|
+
for header, divisor in (("retry-after-ms", 1000), ("retry-after", 1)):
|
|
163
|
+
value = response.headers.get(header)
|
|
164
|
+
if value is None:
|
|
165
|
+
continue
|
|
166
|
+
try:
|
|
167
|
+
delay = float(value) / divisor
|
|
168
|
+
except ValueError:
|
|
169
|
+
try:
|
|
170
|
+
delay = parsedate_to_datetime(value).timestamp() - time.time()
|
|
171
|
+
except (ValueError, TypeError, OverflowError):
|
|
172
|
+
continue
|
|
173
|
+
if 0 <= delay <= 60:
|
|
174
|
+
return delay
|
|
175
|
+
return min(0.5 * (2 ** min(retry, 10)), 8.0) * (1 - 0.25 * random.random())
|
|
176
|
+
|
|
177
|
+
def _download_request(self, response: httpx.Response, data: Any) -> httpx.Request:
|
|
178
|
+
try:
|
|
179
|
+
url = httpx.URL(data["url"])
|
|
180
|
+
except (KeyError, TypeError, ValueError) as exc:
|
|
181
|
+
raise APIResponseValidationError(response=response, body=data) from exc
|
|
182
|
+
if url.scheme not in ("http", "https") or not url.host or url.userinfo:
|
|
183
|
+
raise APIResponseValidationError(response=response, body=data)
|
|
184
|
+
# Construct directly: build_request would merge API client defaults and cookies.
|
|
185
|
+
return httpx.Request("GET", url, extensions={"timeout": response.request.extensions.get("timeout", {})})
|
|
186
|
+
|
|
187
|
+
def _data(self, response: httpx.Response) -> Any:
|
|
188
|
+
if response.status_code == 204 or not response.content:
|
|
189
|
+
return None
|
|
190
|
+
try:
|
|
191
|
+
return response.json()
|
|
192
|
+
except ValueError as exc:
|
|
193
|
+
raise APIResponseValidationError(response=response, body=response.text) from exc
|
|
194
|
+
|
|
195
|
+
def _parse_api_response(
|
|
196
|
+
self,
|
|
197
|
+
response: httpx.Response,
|
|
198
|
+
method: str,
|
|
199
|
+
path: str,
|
|
200
|
+
cast_to: Any,
|
|
201
|
+
options: dict[str, Any],
|
|
202
|
+
page_style: str | None,
|
|
203
|
+
) -> Any:
|
|
204
|
+
if cast_to is None:
|
|
205
|
+
return None
|
|
206
|
+
data = self._data(response)
|
|
207
|
+
if not page_style:
|
|
208
|
+
return parse_response(cast_to, data, response)
|
|
209
|
+
page_cls = AsyncPage if self._is_async else SyncPage
|
|
210
|
+
page = parse_response(page_cls[cast_to], data, response)
|
|
211
|
+
page._style = page_style
|
|
212
|
+
page._query = {**self.default_query, **options.get("query", {})}
|
|
213
|
+
client = self._copy() if self._raw_response else self
|
|
214
|
+
page._fetch = lambda query: getattr(client, "request")(
|
|
215
|
+
method, path, cast_to=cast_to, options={**options, "query": query}, page_style=page_style
|
|
216
|
+
)
|
|
217
|
+
return page
|
|
218
|
+
|
|
219
|
+
|
|
220
|
+
class SyncAPIClient(BaseClient):
|
|
221
|
+
def __init__(
|
|
222
|
+
self,
|
|
223
|
+
*,
|
|
224
|
+
access_token: str | None = None,
|
|
225
|
+
base_url: str | httpx.URL | None = None,
|
|
226
|
+
timeout: float | httpx.Timeout | None = DEFAULT_TIMEOUT,
|
|
227
|
+
max_retries: int = 2,
|
|
228
|
+
default_headers: Mapping[str, str] | None = None,
|
|
229
|
+
default_query: Mapping[str, Any] | None = None,
|
|
230
|
+
http_client: httpx.Client | None = None,
|
|
231
|
+
credential: Credential | None = None,
|
|
232
|
+
) -> None:
|
|
233
|
+
self._configure(
|
|
234
|
+
access_token=access_token,
|
|
235
|
+
base_url=base_url,
|
|
236
|
+
timeout=timeout,
|
|
237
|
+
max_retries=max_retries,
|
|
238
|
+
default_headers=default_headers,
|
|
239
|
+
default_query=default_query,
|
|
240
|
+
credential=credential,
|
|
241
|
+
)
|
|
242
|
+
if http_client is not None and not isinstance(http_client, httpx.Client):
|
|
243
|
+
raise TypeError("http_client must be an httpx.Client")
|
|
244
|
+
self._client = http_client or httpx.Client(timeout=timeout, follow_redirects=False)
|
|
245
|
+
|
|
246
|
+
def _send(self, request: httpx.Request, *, storage: bool = False) -> httpx.Response:
|
|
247
|
+
for attempt in range(self.max_retries + 1):
|
|
248
|
+
if (
|
|
249
|
+
not storage
|
|
250
|
+
and self.credential
|
|
251
|
+
and not self.access_token
|
|
252
|
+
and "Authorization" not in self.default_headers
|
|
253
|
+
):
|
|
254
|
+
# Dynamic credentials can rotate between retries. Explicit request
|
|
255
|
+
# headers still take priority and are marked by request().
|
|
256
|
+
if not request.extensions.get("qca_explicit_auth"):
|
|
257
|
+
request.headers["Authorization"] = f"Bearer {self.credential.get_token()}"
|
|
258
|
+
try:
|
|
259
|
+
response = self._client.send(request, stream=True, auth=None, follow_redirects=False)
|
|
260
|
+
except httpx.TransportError as exc:
|
|
261
|
+
if attempt < self.max_retries and self._retryable(request, None):
|
|
262
|
+
time.sleep(self._retry_delay(attempt, None))
|
|
263
|
+
continue
|
|
264
|
+
cls = APITimeoutError if isinstance(exc, httpx.TimeoutException) else APIConnectionError
|
|
265
|
+
raise cls(request=request) from exc
|
|
266
|
+
if response.is_success:
|
|
267
|
+
return response
|
|
268
|
+
if attempt < self.max_retries and self._retryable(request, response):
|
|
269
|
+
delay = self._retry_delay(attempt, response)
|
|
270
|
+
response.close()
|
|
271
|
+
time.sleep(delay)
|
|
272
|
+
continue
|
|
273
|
+
try:
|
|
274
|
+
read_response(response)
|
|
275
|
+
raise status_error(response)
|
|
276
|
+
finally:
|
|
277
|
+
response.close()
|
|
278
|
+
raise AssertionError("Unreachable retry state")
|
|
279
|
+
|
|
280
|
+
def request(
|
|
281
|
+
self,
|
|
282
|
+
method: str,
|
|
283
|
+
path: str,
|
|
284
|
+
*,
|
|
285
|
+
cast_to: Any,
|
|
286
|
+
options: dict[str, Any],
|
|
287
|
+
page_style: str | None = None,
|
|
288
|
+
stream: bool = False,
|
|
289
|
+
binary: bool = False,
|
|
290
|
+
download_link: bool = False,
|
|
291
|
+
file_fields: list[str] | None = None,
|
|
292
|
+
) -> Any:
|
|
293
|
+
args = self._request_args(method, path, options, self.access_token, file_fields)
|
|
294
|
+
if stream:
|
|
295
|
+
args["headers"]["Accept"] = "text/event-stream"
|
|
296
|
+
request = self._client.build_request(**args)
|
|
297
|
+
request.extensions["qca_explicit_auth"] = any(
|
|
298
|
+
key.lower() == "authorization" for key in (*self.default_headers, *options.get("headers", {}))
|
|
299
|
+
)
|
|
300
|
+
# httpx multipart streams are single-use. Cache the encoded request once.
|
|
301
|
+
request.read()
|
|
302
|
+
response = self._send(request)
|
|
303
|
+
if stream:
|
|
304
|
+
return Stream(response, cast_to)
|
|
305
|
+
if binary and not download_link:
|
|
306
|
+
return BinaryAPIResponse(response)
|
|
307
|
+
|
|
308
|
+
def parse() -> Any:
|
|
309
|
+
return self._parse_api_response(response, method, path, cast_to, options, page_style)
|
|
310
|
+
|
|
311
|
+
if self._stream_response and not binary:
|
|
312
|
+
return APIResponse(response, parse)
|
|
313
|
+
try:
|
|
314
|
+
read_response(response)
|
|
315
|
+
if binary:
|
|
316
|
+
storage = self._download_request(response, self._data(response))
|
|
317
|
+
return BinaryAPIResponse(self._send(storage, storage=True))
|
|
318
|
+
|
|
319
|
+
return APIResponse(response, parse) if self._raw_response else parse()
|
|
320
|
+
finally:
|
|
321
|
+
response.close()
|
|
322
|
+
|
|
323
|
+
def close(self) -> None:
|
|
324
|
+
self._client.close()
|
|
325
|
+
|
|
326
|
+
def __enter__(self) -> Self:
|
|
327
|
+
return self
|
|
328
|
+
|
|
329
|
+
def __exit__(self, *_: object) -> None:
|
|
330
|
+
self.close()
|
|
331
|
+
|
|
332
|
+
|
|
333
|
+
class AsyncAPIClient(BaseClient):
|
|
334
|
+
_is_async = True
|
|
335
|
+
|
|
336
|
+
def __init__(
|
|
337
|
+
self,
|
|
338
|
+
*,
|
|
339
|
+
access_token: str | None = None,
|
|
340
|
+
base_url: str | httpx.URL | None = None,
|
|
341
|
+
timeout: float | httpx.Timeout | None = DEFAULT_TIMEOUT,
|
|
342
|
+
max_retries: int = 2,
|
|
343
|
+
default_headers: Mapping[str, str] | None = None,
|
|
344
|
+
default_query: Mapping[str, Any] | None = None,
|
|
345
|
+
http_client: httpx.AsyncClient | None = None,
|
|
346
|
+
credential: Credential | AsyncCredential | None = None,
|
|
347
|
+
) -> None:
|
|
348
|
+
self._configure(
|
|
349
|
+
access_token=access_token,
|
|
350
|
+
base_url=base_url,
|
|
351
|
+
timeout=timeout,
|
|
352
|
+
max_retries=max_retries,
|
|
353
|
+
default_headers=default_headers,
|
|
354
|
+
default_query=default_query,
|
|
355
|
+
credential=credential,
|
|
356
|
+
)
|
|
357
|
+
if http_client is not None and not isinstance(http_client, httpx.AsyncClient):
|
|
358
|
+
raise TypeError("http_client must be an httpx.AsyncClient")
|
|
359
|
+
self._client = http_client or httpx.AsyncClient(timeout=timeout, follow_redirects=False)
|
|
360
|
+
|
|
361
|
+
async def _send(self, request: httpx.Request, *, storage: bool = False) -> httpx.Response:
|
|
362
|
+
for attempt in range(self.max_retries + 1):
|
|
363
|
+
if (
|
|
364
|
+
not storage
|
|
365
|
+
and self.credential
|
|
366
|
+
and not self.access_token
|
|
367
|
+
and not request.extensions.get("qca_explicit_auth")
|
|
368
|
+
):
|
|
369
|
+
token = self.credential.get_token()
|
|
370
|
+
if inspect.isawaitable(token):
|
|
371
|
+
token = await token
|
|
372
|
+
request.headers["Authorization"] = f"Bearer {token}"
|
|
373
|
+
try:
|
|
374
|
+
response = await self._client.send(request, stream=True, auth=None, follow_redirects=False)
|
|
375
|
+
except httpx.TransportError as exc:
|
|
376
|
+
if attempt < self.max_retries and self._retryable(request, None):
|
|
377
|
+
await anyio.sleep(self._retry_delay(attempt, None))
|
|
378
|
+
continue
|
|
379
|
+
cls = APITimeoutError if isinstance(exc, httpx.TimeoutException) else APIConnectionError
|
|
380
|
+
raise cls(request=request) from exc
|
|
381
|
+
if response.is_success:
|
|
382
|
+
return response
|
|
383
|
+
if attempt < self.max_retries and self._retryable(request, response):
|
|
384
|
+
delay = self._retry_delay(attempt, response)
|
|
385
|
+
await response.aclose()
|
|
386
|
+
await anyio.sleep(delay)
|
|
387
|
+
continue
|
|
388
|
+
try:
|
|
389
|
+
await aread_response(response)
|
|
390
|
+
raise status_error(response)
|
|
391
|
+
finally:
|
|
392
|
+
await response.aclose()
|
|
393
|
+
raise AssertionError("Unreachable retry state")
|
|
394
|
+
|
|
395
|
+
async def request(
|
|
396
|
+
self,
|
|
397
|
+
method: str,
|
|
398
|
+
path: str,
|
|
399
|
+
*,
|
|
400
|
+
cast_to: Any,
|
|
401
|
+
options: dict[str, Any],
|
|
402
|
+
page_style: str | None = None,
|
|
403
|
+
stream: bool = False,
|
|
404
|
+
binary: bool = False,
|
|
405
|
+
download_link: bool = False,
|
|
406
|
+
file_fields: list[str] | None = None,
|
|
407
|
+
) -> Any:
|
|
408
|
+
if file_fields:
|
|
409
|
+
# Reading local file objects should not block the event loop.
|
|
410
|
+
args = await anyio.to_thread.run_sync(
|
|
411
|
+
lambda: self._request_args(method, path, options, self.access_token, file_fields)
|
|
412
|
+
)
|
|
413
|
+
else:
|
|
414
|
+
args = self._request_args(method, path, options, self.access_token, None)
|
|
415
|
+
if stream:
|
|
416
|
+
args["headers"]["Accept"] = "text/event-stream"
|
|
417
|
+
request = self._client.build_request(**args)
|
|
418
|
+
request.extensions["qca_explicit_auth"] = any(
|
|
419
|
+
key.lower() == "authorization" for key in (*self.default_headers, *options.get("headers", {}))
|
|
420
|
+
)
|
|
421
|
+
await request.aread()
|
|
422
|
+
response = await self._send(request)
|
|
423
|
+
if stream:
|
|
424
|
+
return AsyncStream(response, cast_to)
|
|
425
|
+
if binary and not download_link:
|
|
426
|
+
return AsyncBinaryAPIResponse(response)
|
|
427
|
+
|
|
428
|
+
def parse() -> Any:
|
|
429
|
+
return self._parse_api_response(response, method, path, cast_to, options, page_style)
|
|
430
|
+
|
|
431
|
+
if self._stream_response and not binary:
|
|
432
|
+
return AsyncAPIResponse(response, parse)
|
|
433
|
+
try:
|
|
434
|
+
await aread_response(response)
|
|
435
|
+
if binary:
|
|
436
|
+
storage = self._download_request(response, self._data(response))
|
|
437
|
+
return AsyncBinaryAPIResponse(await self._send(storage, storage=True))
|
|
438
|
+
|
|
439
|
+
return AsyncAPIResponse(response, parse) if self._raw_response else parse()
|
|
440
|
+
finally:
|
|
441
|
+
await response.aclose()
|
|
442
|
+
|
|
443
|
+
async def close(self) -> None:
|
|
444
|
+
await self._client.aclose()
|
|
445
|
+
|
|
446
|
+
async def __aenter__(self) -> Self:
|
|
447
|
+
return self
|
|
448
|
+
|
|
449
|
+
async def __aexit__(self, *_: object) -> None:
|
|
450
|
+
await self.close()
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from typing import Any
|
|
4
|
+
|
|
5
|
+
import httpx
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class APIError(Exception):
|
|
9
|
+
def __init__(self, message: str, *, request: httpx.Request, body: Any = None) -> None:
|
|
10
|
+
super().__init__(message)
|
|
11
|
+
self.message = message
|
|
12
|
+
self.request = request
|
|
13
|
+
self.body = body
|
|
14
|
+
error = body.get("error", body) if isinstance(body, dict) else {}
|
|
15
|
+
error = error if isinstance(error, dict) else {}
|
|
16
|
+
self.code = error.get("code")
|
|
17
|
+
self.type = error.get("type")
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class APIConnectionError(APIError):
|
|
21
|
+
def __init__(self, *, request: httpx.Request, message: str = "Connection error.") -> None:
|
|
22
|
+
super().__init__(message, request=request)
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
class APITimeoutError(APIConnectionError):
|
|
26
|
+
def __init__(self, *, request: httpx.Request) -> None:
|
|
27
|
+
super().__init__(request=request, message="Request timed out.")
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
class APIResponseValidationError(APIError):
|
|
31
|
+
def __init__(self, *, response: httpx.Response, body: Any) -> None:
|
|
32
|
+
super().__init__("Response does not match the expected schema.", request=response.request, body=body)
|
|
33
|
+
self.response = response
|
|
34
|
+
self.status_code = response.status_code
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
class APIStatusError(APIError):
|
|
38
|
+
def __init__(self, message: str, *, response: httpx.Response, body: Any) -> None:
|
|
39
|
+
super().__init__(message, request=response.request, body=body)
|
|
40
|
+
self.response = response
|
|
41
|
+
self.status_code = response.status_code
|
|
42
|
+
self.request_id = (
|
|
43
|
+
response.headers.get("x-request-id")
|
|
44
|
+
or response.headers.get("request-id")
|
|
45
|
+
or (body.get("request_id") if isinstance(body, dict) else None)
|
|
46
|
+
)
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
class BadRequestError(APIStatusError):
|
|
50
|
+
pass
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
class AuthenticationError(APIStatusError):
|
|
54
|
+
pass
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
class PermissionDeniedError(APIStatusError):
|
|
58
|
+
pass
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
class NotFoundError(APIStatusError):
|
|
62
|
+
pass
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
class ConflictError(APIStatusError):
|
|
66
|
+
pass
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
class UnprocessableEntityError(APIStatusError):
|
|
70
|
+
pass
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
class RateLimitError(APIStatusError):
|
|
74
|
+
pass
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
class InternalServerError(APIStatusError):
|
|
78
|
+
pass
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
def status_error(response: httpx.Response) -> APIStatusError:
|
|
82
|
+
try:
|
|
83
|
+
body = response.json()
|
|
84
|
+
except ValueError:
|
|
85
|
+
body = response.text
|
|
86
|
+
error = body.get("error", body) if isinstance(body, dict) else body
|
|
87
|
+
message = error.get("message", str(error)) if isinstance(error, dict) else str(error)
|
|
88
|
+
cls = {
|
|
89
|
+
400: BadRequestError,
|
|
90
|
+
401: AuthenticationError,
|
|
91
|
+
403: PermissionDeniedError,
|
|
92
|
+
404: NotFoundError,
|
|
93
|
+
409: ConflictError,
|
|
94
|
+
422: UnprocessableEntityError,
|
|
95
|
+
429: RateLimitError,
|
|
96
|
+
}.get(response.status_code, InternalServerError if response.status_code >= 500 else APIStatusError)
|
|
97
|
+
return cls(f"Error code: {response.status_code} - {message}", response=response, body=body)
|
qca/common/_files.py
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import json
|
|
4
|
+
import os
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
from typing import Any
|
|
7
|
+
|
|
8
|
+
from ._utils import strip_not_given
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def file_tuple(value: Any) -> tuple[Any, ...]:
|
|
12
|
+
if isinstance(value, tuple):
|
|
13
|
+
name, content, *rest = value
|
|
14
|
+
else:
|
|
15
|
+
content, rest = value, []
|
|
16
|
+
name = Path(value).name if isinstance(value, os.PathLike) else Path(getattr(value, "name", "upload")).name
|
|
17
|
+
if isinstance(content, os.PathLike):
|
|
18
|
+
content = Path(content).read_bytes()
|
|
19
|
+
elif hasattr(content, "read"):
|
|
20
|
+
content = content.read()
|
|
21
|
+
if not isinstance(content, bytes):
|
|
22
|
+
raise TypeError("File content must be bytes, a binary file, or a pathlib.Path")
|
|
23
|
+
return (name, content, *rest)
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def multipart_parts(body: dict[str, Any], file_fields: list[str]) -> list[tuple[str, Any]]:
|
|
27
|
+
# Snapshot each upload once so retries replay the same bytes. File handles
|
|
28
|
+
# supplied by callers remain open; Path inputs are opened and closed here.
|
|
29
|
+
parts: list[tuple[str, Any]] = []
|
|
30
|
+
for key, value in body.items():
|
|
31
|
+
if key in file_fields and value is not None:
|
|
32
|
+
values = value if isinstance(value, list) else [value]
|
|
33
|
+
parts.extend((key, file_tuple(item)) for item in values)
|
|
34
|
+
else:
|
|
35
|
+
value = strip_not_given(value)
|
|
36
|
+
text = value if isinstance(value, str) else json.dumps(value, ensure_ascii=False, separators=(",", ":"))
|
|
37
|
+
parts.append((key, (None, text)))
|
|
38
|
+
return parts
|