qca-sdk 0.0.1.dev4__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.
Files changed (596) hide show
  1. qca/__init__.py +50 -0
  2. qca/_version.py +8 -0
  3. qca/common/__init__.py +43 -0
  4. qca/common/_base_client.py +450 -0
  5. qca/common/_exceptions.py +97 -0
  6. qca/common/_files.py +38 -0
  7. qca/common/_models.py +33 -0
  8. qca/common/_resource.py +35 -0
  9. qca/common/_response.py +220 -0
  10. qca/common/_streaming.py +143 -0
  11. qca/common/_types.py +25 -0
  12. qca/common/_utils.py +73 -0
  13. qca/common/credentials.py +13 -0
  14. qca/common/pagination.py +118 -0
  15. qca/forward/__init__.py +7 -0
  16. qca/forward/_client.py +142 -0
  17. qca/forward/resources/__init__.py +14 -0
  18. qca/forward/resources/batches/__init__.py +4 -0
  19. qca/forward/resources/batches/batches.py +308 -0
  20. qca/forward/resources/batches/tasks.py +71 -0
  21. qca/forward/resources/channel_pairings.py +111 -0
  22. qca/forward/resources/channels/__init__.py +4 -0
  23. qca/forward/resources/channels/channels.py +336 -0
  24. qca/forward/resources/channels/qr_sessions.py +106 -0
  25. qca/forward/resources/environments.py +305 -0
  26. qca/forward/resources/files.py +272 -0
  27. qca/forward/resources/identities/__init__.py +6 -0
  28. qca/forward/resources/identities/configs.py +249 -0
  29. qca/forward/resources/identities/identities.py +570 -0
  30. qca/forward/resources/identities/memory_stores.py +186 -0
  31. qca/forward/resources/memory_stores/__init__.py +6 -0
  32. qca/forward/resources/memory_stores/memories.py +290 -0
  33. qca/forward/resources/memory_stores/memory_stores.py +321 -0
  34. qca/forward/resources/memory_stores/memory_versions.py +179 -0
  35. qca/forward/resources/models.py +58 -0
  36. qca/forward/resources/schedule_runs.py +149 -0
  37. qca/forward/resources/schedules.py +545 -0
  38. qca/forward/resources/sessions/__init__.py +6 -0
  39. qca/forward/resources/sessions/events.py +208 -0
  40. qca/forward/resources/sessions/resources.py +66 -0
  41. qca/forward/resources/sessions/sessions.py +417 -0
  42. qca/forward/resources/sessions/threads/__init__.py +4 -0
  43. qca/forward/resources/sessions/threads/events.py +128 -0
  44. qca/forward/resources/sessions/threads/threads.py +177 -0
  45. qca/forward/resources/skills/__init__.py +4 -0
  46. qca/forward/resources/skills/skills.py +335 -0
  47. qca/forward/resources/skills/versions.py +253 -0
  48. qca/forward/resources/templates.py +426 -0
  49. qca/forward/resources/vaults/__init__.py +4 -0
  50. qca/forward/resources/vaults/credentials.py +227 -0
  51. qca/forward/resources/vaults/vaults.py +217 -0
  52. qca/forward/types/__init__.py +205 -0
  53. qca/forward/types/batch.py +35 -0
  54. qca/forward/types/batch_cancel_params.py +11 -0
  55. qca/forward/types/batch_create_params.py +14 -0
  56. qca/forward/types/batch_file.py +13 -0
  57. qca/forward/types/batch_list_params.py +14 -0
  58. qca/forward/types/batch_request_counts.py +17 -0
  59. qca/forward/types/batch_task.py +24 -0
  60. qca/forward/types/batch_task_artifacts_item.py +14 -0
  61. qca/forward/types/batch_task_error.py +12 -0
  62. qca/forward/types/batch_task_list_params.py +14 -0
  63. qca/forward/types/batch_task_usage.py +11 -0
  64. qca/forward/types/batch_usage.py +11 -0
  65. qca/forward/types/channel.py +27 -0
  66. qca/forward/types/channel_channel_config.py +14 -0
  67. qca/forward/types/channel_channel_config_response_options.py +12 -0
  68. qca/forward/types/channel_create_params.py +18 -0
  69. qca/forward/types/channel_identity_resolution.py +11 -0
  70. qca/forward/types/channel_list_params.py +18 -0
  71. qca/forward/types/channel_pairing.py +17 -0
  72. qca/forward/types/channel_pairing_create_params.py +14 -0
  73. qca/forward/types/channel_qr_session.py +19 -0
  74. qca/forward/types/channel_qr_session_create_params.py +11 -0
  75. qca/forward/types/channel_update_params.py +16 -0
  76. qca/forward/types/content_block_param.py +17 -0
  77. qca/forward/types/deleted_channel.py +12 -0
  78. qca/forward/types/deleted_channel_pairing.py +12 -0
  79. qca/forward/types/deleted_identity.py +12 -0
  80. qca/forward/types/deleted_memory.py +13 -0
  81. qca/forward/types/deleted_memory_store.py +13 -0
  82. qca/forward/types/deleted_memory_store_mount.py +13 -0
  83. qca/forward/types/deleted_skill_version.py +13 -0
  84. qca/forward/types/effective_config.py +23 -0
  85. qca/forward/types/effective_config_agent.py +19 -0
  86. qca/forward/types/effective_config_agent_tools_item.py +15 -0
  87. qca/forward/types/effective_config_agent_tools_item_configs_item.py +12 -0
  88. qca/forward/types/effective_config_session.py +17 -0
  89. qca/forward/types/effective_config_session_resources_item.py +14 -0
  90. qca/forward/types/environment.py +24 -0
  91. qca/forward/types/environment_config.py +15 -0
  92. qca/forward/types/environment_config_packages.py +17 -0
  93. qca/forward/types/environment_create_params.py +15 -0
  94. qca/forward/types/environment_list_params.py +14 -0
  95. qca/forward/types/environment_update_params.py +14 -0
  96. qca/forward/types/environment_variable_override.py +12 -0
  97. qca/forward/types/environment_variable_override_param.py +12 -0
  98. qca/forward/types/file_list_params.py +16 -0
  99. qca/forward/types/file_metadata.py +22 -0
  100. qca/forward/types/file_upload_params.py +17 -0
  101. qca/forward/types/git_hub_repository.py +13 -0
  102. qca/forward/types/git_hub_repository_param.py +14 -0
  103. qca/forward/types/identity.py +19 -0
  104. qca/forward/types/identity_clear_params.py +11 -0
  105. qca/forward/types/identity_clear_response.py +18 -0
  106. qca/forward/types/identity_clear_response_summary.py +16 -0
  107. qca/forward/types/identity_config.py +25 -0
  108. qca/forward/types/identity_config_list_params.py +15 -0
  109. qca/forward/types/identity_config_spec.py +31 -0
  110. qca/forward/types/identity_config_spec_param.py +31 -0
  111. qca/forward/types/identity_config_upsert_params.py +17 -0
  112. qca/forward/types/identity_create_params.py +15 -0
  113. qca/forward/types/identity_list_params.py +17 -0
  114. qca/forward/types/identity_list_templates_response.py +14 -0
  115. qca/forward/types/identity_memory_store_list_response.py +15 -0
  116. qca/forward/types/identity_memory_store_mount_params.py +9 -0
  117. qca/forward/types/identity_stats.py +14 -0
  118. qca/forward/types/identity_template.py +15 -0
  119. qca/forward/types/identity_update_params.py +15 -0
  120. qca/forward/types/image_source_param.py +15 -0
  121. qca/forward/types/mcp_server.py +13 -0
  122. qca/forward/types/mcp_server_override.py +13 -0
  123. qca/forward/types/mcp_server_override_param.py +13 -0
  124. qca/forward/types/mcp_server_param.py +13 -0
  125. qca/forward/types/memory.py +21 -0
  126. qca/forward/types/memory_store.py +25 -0
  127. qca/forward/types/memory_store_create_params.py +14 -0
  128. qca/forward/types/memory_store_list_params.py +14 -0
  129. qca/forward/types/memory_store_memory_create_params.py +13 -0
  130. qca/forward/types/memory_store_memory_list_params.py +14 -0
  131. qca/forward/types/memory_store_memory_update_params.py +13 -0
  132. qca/forward/types/memory_store_memory_version_list_params.py +14 -0
  133. qca/forward/types/memory_store_mount.py +20 -0
  134. qca/forward/types/memory_store_update_params.py +13 -0
  135. qca/forward/types/memory_version.py +23 -0
  136. qca/forward/types/model.py +23 -0
  137. qca/forward/types/model_config.py +13 -0
  138. qca/forward/types/model_config_param.py +13 -0
  139. qca/forward/types/model_list_response.py +15 -0
  140. qca/forward/types/multiagent_config.py +15 -0
  141. qca/forward/types/multiagent_config_param.py +15 -0
  142. qca/forward/types/multiagent_entry.py +13 -0
  143. qca/forward/types/multiagent_entry_param.py +13 -0
  144. qca/forward/types/permission_policy.py +11 -0
  145. qca/forward/types/permission_policy_param.py +9 -0
  146. qca/forward/types/resource_binding.py +11 -0
  147. qca/forward/types/resource_binding_param.py +11 -0
  148. qca/forward/types/schedule.py +34 -0
  149. qca/forward/types/schedule_archive_many_params.py +12 -0
  150. qca/forward/types/schedule_archive_many_response.py +11 -0
  151. qca/forward/types/schedule_archive_params.py +11 -0
  152. qca/forward/types/schedule_create_params.py +21 -0
  153. qca/forward/types/schedule_execution.py +14 -0
  154. qca/forward/types/schedule_initial_events_item.py +12 -0
  155. qca/forward/types/schedule_list_params.py +19 -0
  156. qca/forward/types/schedule_pause_params.py +11 -0
  157. qca/forward/types/schedule_paused_reason.py +11 -0
  158. qca/forward/types/schedule_run.py +33 -0
  159. qca/forward/types/schedule_run_list_params.py +20 -0
  160. qca/forward/types/schedule_run_params.py +11 -0
  161. qca/forward/types/schedule_run_retrieve_params.py +11 -0
  162. qca/forward/types/schedule_run_trigger_context.py +13 -0
  163. qca/forward/types/schedule_sinks_item.py +16 -0
  164. qca/forward/types/schedule_sinks_item_target.py +12 -0
  165. qca/forward/types/schedule_trigger_policy.py +15 -0
  166. qca/forward/types/schedule_unpause_params.py +11 -0
  167. qca/forward/types/schedule_update_params.py +20 -0
  168. qca/forward/types/session.py +33 -0
  169. qca/forward/types/session_archive_params.py +11 -0
  170. qca/forward/types/session_cancel_params.py +11 -0
  171. qca/forward/types/session_config.py +11 -0
  172. qca/forward/types/session_create_params.py +21 -0
  173. qca/forward/types/session_create_params_config_param.py +11 -0
  174. qca/forward/types/session_event.py +52 -0
  175. qca/forward/types/session_event_list_params.py +18 -0
  176. qca/forward/types/session_event_param.py +24 -0
  177. qca/forward/types/session_event_send_params.py +15 -0
  178. qca/forward/types/session_event_send_response.py +14 -0
  179. qca/forward/types/session_event_stream_params.py +14 -0
  180. qca/forward/types/session_list_params.py +27 -0
  181. qca/forward/types/session_resource.py +17 -0
  182. qca/forward/types/session_resource_add_params.py +13 -0
  183. qca/forward/types/session_resource_spec_param.py +13 -0
  184. qca/forward/types/session_stats.py +12 -0
  185. qca/forward/types/session_template.py +18 -0
  186. qca/forward/types/session_thread.py +27 -0
  187. qca/forward/types/session_thread_archive_params.py +11 -0
  188. qca/forward/types/session_thread_event_list_params.py +13 -0
  189. qca/forward/types/session_thread_event_stream_params.py +11 -0
  190. qca/forward/types/session_thread_list_params.py +13 -0
  191. qca/forward/types/session_thread_stop_reason.py +11 -0
  192. qca/forward/types/session_update_params.py +17 -0
  193. qca/forward/types/session_update_params_config_param.py +11 -0
  194. qca/forward/types/session_usage.py +11 -0
  195. qca/forward/types/skill.py +23 -0
  196. qca/forward/types/skill_binding.py +14 -0
  197. qca/forward/types/skill_binding_param.py +14 -0
  198. qca/forward/types/skill_create_params.py +20 -0
  199. qca/forward/types/skill_list_params.py +17 -0
  200. qca/forward/types/skill_override.py +13 -0
  201. qca/forward/types/skill_override_param.py +13 -0
  202. qca/forward/types/skill_retrieve_params.py +11 -0
  203. qca/forward/types/skill_update_params.py +16 -0
  204. qca/forward/types/skill_version.py +22 -0
  205. qca/forward/types/skill_version_create_params.py +13 -0
  206. qca/forward/types/skill_version_list_params.py +12 -0
  207. qca/forward/types/system_override.py +12 -0
  208. qca/forward/types/system_override_param.py +12 -0
  209. qca/forward/types/template.py +39 -0
  210. qca/forward/types/template_archive_params.py +11 -0
  211. qca/forward/types/template_clone_params.py +13 -0
  212. qca/forward/types/template_create_params.py +35 -0
  213. qca/forward/types/template_list_params.py +14 -0
  214. qca/forward/types/template_update_params.py +35 -0
  215. qca/forward/types/tool.py +21 -0
  216. qca/forward/types/tool_config.py +16 -0
  217. qca/forward/types/tool_config_param.py +16 -0
  218. qca/forward/types/tool_override.py +15 -0
  219. qca/forward/types/tool_override_param.py +15 -0
  220. qca/forward/types/tool_param.py +21 -0
  221. qca/forward/types/vault.py +18 -0
  222. qca/forward/types/vault_create_params.py +13 -0
  223. qca/forward/types/vault_credential.py +22 -0
  224. qca/forward/types/vault_credential_auth.py +12 -0
  225. qca/forward/types/vault_credential_create_params.py +14 -0
  226. qca/forward/types/vault_credential_list_params.py +15 -0
  227. qca/forward/types/vault_list_params.py +15 -0
  228. qca/managed/__init__.py +7 -0
  229. qca/managed/_client.py +115 -0
  230. qca/managed/resources/__init__.py +10 -0
  231. qca/managed/resources/agents/__init__.py +4 -0
  232. qca/managed/resources/agents/agents.py +386 -0
  233. qca/managed/resources/agents/versions.py +71 -0
  234. qca/managed/resources/deployment_runs.py +160 -0
  235. qca/managed/resources/deployments.py +552 -0
  236. qca/managed/resources/dreams.py +303 -0
  237. qca/managed/resources/environments/__init__.py +4 -0
  238. qca/managed/resources/environments/environments.py +359 -0
  239. qca/managed/resources/environments/work.py +449 -0
  240. qca/managed/resources/files.py +295 -0
  241. qca/managed/resources/memory_stores/__init__.py +6 -0
  242. qca/managed/resources/memory_stores/memories.py +358 -0
  243. qca/managed/resources/memory_stores/memory_stores.py +362 -0
  244. qca/managed/resources/memory_stores/memory_versions.py +228 -0
  245. qca/managed/resources/models.py +71 -0
  246. qca/managed/resources/sessions/__init__.py +6 -0
  247. qca/managed/resources/sessions/events.py +240 -0
  248. qca/managed/resources/sessions/resources.py +303 -0
  249. qca/managed/resources/sessions/sessions.py +472 -0
  250. qca/managed/resources/sessions/threads/__init__.py +4 -0
  251. qca/managed/resources/sessions/threads/events.py +141 -0
  252. qca/managed/resources/sessions/threads/threads.py +185 -0
  253. qca/managed/resources/skills/__init__.py +4 -0
  254. qca/managed/resources/skills/skills.py +254 -0
  255. qca/managed/resources/skills/versions.py +273 -0
  256. qca/managed/resources/vaults/__init__.py +4 -0
  257. qca/managed/resources/vaults/credentials.py +437 -0
  258. qca/managed/resources/vaults/vaults.py +296 -0
  259. qca/managed/types/__init__.py +421 -0
  260. qca/managed/types/actor_union.py +15 -0
  261. qca/managed/types/advisor_params.py +12 -0
  262. qca/managed/types/agent.py +33 -0
  263. qca/managed/types/agent_archive_params.py +12 -0
  264. qca/managed/types/agent_create_params.py +31 -0
  265. qca/managed/types/agent_list_params.py +18 -0
  266. qca/managed/types/agent_mcp_tool_result_event_content_union.py +21 -0
  267. qca/managed/types/agent_message_event_content_union.py +12 -0
  268. qca/managed/types/agent_params.py +13 -0
  269. qca/managed/types/agent_reference.py +13 -0
  270. qca/managed/types/agent_retrieve_params.py +13 -0
  271. qca/managed/types/agent_skill_union.py +13 -0
  272. qca/managed/types/agent_thread_message_received_event_content_union.py +20 -0
  273. qca/managed/types/agent_thread_message_received_event_content_union_source.py +15 -0
  274. qca/managed/types/agent_thread_message_sent_event_content_union.py +18 -0
  275. qca/managed/types/agent_thread_message_sent_event_content_union_source.py +15 -0
  276. qca/managed/types/agent_tool_config_union.py +22 -0
  277. qca/managed/types/agent_tool_config_union_permission_policy.py +11 -0
  278. qca/managed/types/agent_tool_result_event_content_union.py +21 -0
  279. qca/managed/types/agent_tool_union.py +25 -0
  280. qca/managed/types/agent_tool_union_default_config.py +15 -0
  281. qca/managed/types/agent_tool_union_default_config_permission_policy.py +11 -0
  282. qca/managed/types/agent_toolset20260401_params.py +37 -0
  283. qca/managed/types/agent_toolset_default_config_params.py +16 -0
  284. qca/managed/types/agent_update_params.py +32 -0
  285. qca/managed/types/agent_version_list_params.py +14 -0
  286. qca/managed/types/agent_with_overrides_params.py +27 -0
  287. qca/managed/types/always_allow_policy_param.py +11 -0
  288. qca/managed/types/always_ask_policy_param.py +11 -0
  289. qca/managed/types/base64_document_source_param.py +13 -0
  290. qca/managed/types/base64_image_source_param.py +13 -0
  291. qca/managed/types/bash_tool_config_params.py +18 -0
  292. qca/managed/types/branch_checkout_param.py +12 -0
  293. qca/managed/types/budget_limit.py +15 -0
  294. qca/managed/types/budget_limit_param.py +15 -0
  295. qca/managed/types/cache_creation_usage.py +12 -0
  296. qca/managed/types/capability_support.py +11 -0
  297. qca/managed/types/cloud_config_networking_union.py +14 -0
  298. qca/managed/types/cloud_config_params.py +19 -0
  299. qca/managed/types/commit_checkout_param.py +12 -0
  300. qca/managed/types/context_management_capability.py +17 -0
  301. qca/managed/types/credential.py +23 -0
  302. qca/managed/types/credential_auth_union.py +23 -0
  303. qca/managed/types/credential_validation.py +23 -0
  304. qca/managed/types/custom_skill_params.py +13 -0
  305. qca/managed/types/custom_tool_input_schema.py +13 -0
  306. qca/managed/types/custom_tool_input_schema_param.py +13 -0
  307. qca/managed/types/custom_tool_params.py +17 -0
  308. qca/managed/types/delete_session_resource.py +12 -0
  309. qca/managed/types/deleted_credential.py +12 -0
  310. qca/managed/types/deleted_file.py +12 -0
  311. qca/managed/types/deleted_memory.py +12 -0
  312. qca/managed/types/deleted_memory_store.py +12 -0
  313. qca/managed/types/deleted_session.py +12 -0
  314. qca/managed/types/deleted_skill.py +12 -0
  315. qca/managed/types/deleted_skill_version.py +12 -0
  316. qca/managed/types/deleted_vault.py +12 -0
  317. qca/managed/types/delta_content.py +16 -0
  318. qca/managed/types/deployment.py +37 -0
  319. qca/managed/types/deployment_archive_params.py +12 -0
  320. qca/managed/types/deployment_create_params.py +36 -0
  321. qca/managed/types/deployment_initial_event_union.py +20 -0
  322. qca/managed/types/deployment_list_params.py +22 -0
  323. qca/managed/types/deployment_pause_params.py +12 -0
  324. qca/managed/types/deployment_paused_reason_error_union.py +11 -0
  325. qca/managed/types/deployment_paused_reason_union.py +15 -0
  326. qca/managed/types/deployment_retrieve_params.py +12 -0
  327. qca/managed/types/deployment_run.py +24 -0
  328. qca/managed/types/deployment_run_error_union.py +12 -0
  329. qca/managed/types/deployment_run_list_params.py +24 -0
  330. qca/managed/types/deployment_run_params.py +12 -0
  331. qca/managed/types/deployment_run_retrieve_params.py +12 -0
  332. qca/managed/types/deployment_unpause_params.py +12 -0
  333. qca/managed/types/deployment_update_params.py +34 -0
  334. qca/managed/types/deployment_user_define_outcome_event_rubric_union.py +13 -0
  335. qca/managed/types/deployment_user_message_event_content_union.py +18 -0
  336. qca/managed/types/deployment_user_message_event_content_union_source.py +15 -0
  337. qca/managed/types/document_block_param.py +22 -0
  338. qca/managed/types/dream.py +33 -0
  339. qca/managed/types/dream_archive_params.py +12 -0
  340. qca/managed/types/dream_cancel_params.py +12 -0
  341. qca/managed/types/dream_create_params.py +23 -0
  342. qca/managed/types/dream_error.py +12 -0
  343. qca/managed/types/dream_input_union.py +13 -0
  344. qca/managed/types/dream_list_params.py +19 -0
  345. qca/managed/types/dream_memory_store_input_param.py +12 -0
  346. qca/managed/types/dream_model_config.py +12 -0
  347. qca/managed/types/dream_model_config_param.py +12 -0
  348. qca/managed/types/dream_output.py +12 -0
  349. qca/managed/types/dream_retrieve_params.py +12 -0
  350. qca/managed/types/dream_sessions_input_param.py +12 -0
  351. qca/managed/types/dream_usage.py +14 -0
  352. qca/managed/types/edit_tool_config_params.py +18 -0
  353. qca/managed/types/effort_capability.py +19 -0
  354. qca/managed/types/effort_high_param.py +11 -0
  355. qca/managed/types/effort_low_param.py +11 -0
  356. qca/managed/types/effort_max_param.py +11 -0
  357. qca/managed/types/effort_medium_param.py +11 -0
  358. qca/managed/types/effort_xhigh_param.py +11 -0
  359. qca/managed/types/environment.py +23 -0
  360. qca/managed/types/environment_archive_params.py +12 -0
  361. qca/managed/types/environment_config_union.py +17 -0
  362. qca/managed/types/environment_create_params.py +21 -0
  363. qca/managed/types/environment_delete_params.py +12 -0
  364. qca/managed/types/environment_delete_response.py +12 -0
  365. qca/managed/types/environment_list_params.py +18 -0
  366. qca/managed/types/environment_retrieve_params.py +12 -0
  367. qca/managed/types/environment_update_params.py +21 -0
  368. qca/managed/types/environment_variable_auth_response_networking_union.py +12 -0
  369. qca/managed/types/environment_variable_create_params.py +20 -0
  370. qca/managed/types/environment_variable_update_params.py +19 -0
  371. qca/managed/types/environment_work_ack_params.py +11 -0
  372. qca/managed/types/environment_work_heartbeat_params.py +13 -0
  373. qca/managed/types/environment_work_list_params.py +15 -0
  374. qca/managed/types/environment_work_poll_params.py +14 -0
  375. qca/managed/types/environment_work_retrieve_params.py +12 -0
  376. qca/managed/types/environment_work_stats_params.py +12 -0
  377. qca/managed/types/environment_work_stop_params.py +13 -0
  378. qca/managed/types/environment_work_update_params.py +13 -0
  379. qca/managed/types/file_delete_params.py +12 -0
  380. qca/managed/types/file_document_source_param.py +12 -0
  381. qca/managed/types/file_download_params.py +12 -0
  382. qca/managed/types/file_get_metadata_params.py +12 -0
  383. qca/managed/types/file_image_source_param.py +12 -0
  384. qca/managed/types/file_list_params.py +19 -0
  385. qca/managed/types/file_metadata.py +25 -0
  386. qca/managed/types/file_resource.py +17 -0
  387. qca/managed/types/file_resource_params.py +13 -0
  388. qca/managed/types/file_rubric_params.py +12 -0
  389. qca/managed/types/file_scope.py +12 -0
  390. qca/managed/types/file_upload_params.py +18 -0
  391. qca/managed/types/git_hub_repository_resource_checkout_union.py +13 -0
  392. qca/managed/types/git_hub_repository_resource_config_checkout_union.py +13 -0
  393. qca/managed/types/git_hub_repository_resource_params.py +19 -0
  394. qca/managed/types/glob_tool_config_params.py +18 -0
  395. qca/managed/types/grep_tool_config_params.py +18 -0
  396. qca/managed/types/image_block_param.py +17 -0
  397. qca/managed/types/injection_location_params.py +12 -0
  398. qca/managed/types/injection_location_response.py +12 -0
  399. qca/managed/types/injection_location_update_params.py +12 -0
  400. qca/managed/types/limited_credential_networking_params.py +12 -0
  401. qca/managed/types/limited_network_params.py +14 -0
  402. qca/managed/types/mcp_probe.py +15 -0
  403. qca/managed/types/mcp_server_url_definition.py +13 -0
  404. qca/managed/types/mcp_tool_config.py +16 -0
  405. qca/managed/types/mcp_tool_config_params.py +17 -0
  406. qca/managed/types/mcp_tool_config_permission_policy_union.py +11 -0
  407. qca/managed/types/mcp_toolset_default_config_params.py +16 -0
  408. qca/managed/types/mcp_toolset_params.py +18 -0
  409. qca/managed/types/mcpo_auth_create_params.py +19 -0
  410. qca/managed/types/mcpo_auth_refresh_params.py +23 -0
  411. qca/managed/types/mcpo_auth_refresh_response.py +18 -0
  412. qca/managed/types/mcpo_auth_refresh_response_token_endpoint_auth_union.py +11 -0
  413. qca/managed/types/mcpo_auth_refresh_update_params.py +17 -0
  414. qca/managed/types/mcpo_auth_update_params.py +18 -0
  415. qca/managed/types/memory.py +22 -0
  416. qca/managed/types/memory_list_item_union.py +21 -0
  417. qca/managed/types/memory_store.py +19 -0
  418. qca/managed/types/memory_store_archive_params.py +12 -0
  419. qca/managed/types/memory_store_create_params.py +15 -0
  420. qca/managed/types/memory_store_delete_params.py +12 -0
  421. qca/managed/types/memory_store_list_params.py +19 -0
  422. qca/managed/types/memory_store_memory_create_params.py +16 -0
  423. qca/managed/types/memory_store_memory_delete_params.py +13 -0
  424. qca/managed/types/memory_store_memory_list_params.py +17 -0
  425. qca/managed/types/memory_store_memory_retrieve_params.py +13 -0
  426. qca/managed/types/memory_store_memory_update_params.py +21 -0
  427. qca/managed/types/memory_store_memory_version_list_params.py +23 -0
  428. qca/managed/types/memory_store_memory_version_redact_params.py +12 -0
  429. qca/managed/types/memory_store_memory_version_retrieve_params.py +13 -0
  430. qca/managed/types/memory_store_resource_param.py +14 -0
  431. qca/managed/types/memory_store_retrieve_params.py +12 -0
  432. qca/managed/types/memory_store_update_params.py +15 -0
  433. qca/managed/types/memory_version.py +27 -0
  434. qca/managed/types/model_capabilities.py +25 -0
  435. qca/managed/types/model_config.py +18 -0
  436. qca/managed/types/model_config_effort_union.py +11 -0
  437. qca/managed/types/model_config_params.py +39 -0
  438. qca/managed/types/model_info.py +30 -0
  439. qca/managed/types/model_list_params.py +15 -0
  440. qca/managed/types/monetary_amount.py +12 -0
  441. qca/managed/types/monetary_amount_param.py +12 -0
  442. qca/managed/types/multiagent.py +15 -0
  443. qca/managed/types/multiagent_agent_union.py +17 -0
  444. qca/managed/types/multiagent_params.py +17 -0
  445. qca/managed/types/multiagent_self_params.py +11 -0
  446. qca/managed/types/outcome_evaluation_resource.py +18 -0
  447. qca/managed/types/output_behavior_create_new_param.py +11 -0
  448. qca/managed/types/output_behavior_union.py +12 -0
  449. qca/managed/types/output_behavior_update_existing_param.py +12 -0
  450. qca/managed/types/packages.py +17 -0
  451. qca/managed/types/packages_params.py +17 -0
  452. qca/managed/types/plain_text_document_source_param.py +13 -0
  453. qca/managed/types/precondition_param.py +12 -0
  454. qca/managed/types/qoder_skill_params.py +13 -0
  455. qca/managed/types/read_tool_config_params.py +18 -0
  456. qca/managed/types/redacted_block_param.py +11 -0
  457. qca/managed/types/refresh_http_response.py +14 -0
  458. qca/managed/types/refresh_object.py +15 -0
  459. qca/managed/types/schedule.py +16 -0
  460. qca/managed/types/schedule_params.py +13 -0
  461. qca/managed/types/search_result_block_param.py +19 -0
  462. qca/managed/types/search_result_citations.py +11 -0
  463. qca/managed/types/search_result_citations_param.py +9 -0
  464. qca/managed/types/search_result_content.py +12 -0
  465. qca/managed/types/search_result_content_param.py +12 -0
  466. qca/managed/types/self_hosted_config_params.py +11 -0
  467. qca/managed/types/self_hosted_work.py +26 -0
  468. qca/managed/types/self_hosted_work_heartbeat_response.py +15 -0
  469. qca/managed/types/self_hosted_work_queue_stats.py +15 -0
  470. qca/managed/types/send_session_events.py +14 -0
  471. qca/managed/types/send_session_events_data_union.py +39 -0
  472. qca/managed/types/server_tool_usage.py +12 -0
  473. qca/managed/types/session.py +37 -0
  474. qca/managed/types/session_agent.py +28 -0
  475. qca/managed/types/session_agent_skill_union.py +13 -0
  476. qca/managed/types/session_agent_tool_union.py +25 -0
  477. qca/managed/types/session_agent_tool_union_default_config.py +17 -0
  478. qca/managed/types/session_agent_tool_union_default_config_permission_policy.py +11 -0
  479. qca/managed/types/session_agent_update_param.py +24 -0
  480. qca/managed/types/session_archive_params.py +12 -0
  481. qca/managed/types/session_create_params.py +31 -0
  482. qca/managed/types/session_delete_params.py +12 -0
  483. qca/managed/types/session_error_event_error_union.py +19 -0
  484. qca/managed/types/session_error_event_error_union_retry_status.py +11 -0
  485. qca/managed/types/session_event.py +77 -0
  486. qca/managed/types/session_event_list_params.py +23 -0
  487. qca/managed/types/session_event_send_params.py +34 -0
  488. qca/managed/types/session_event_stop_reason.py +12 -0
  489. qca/managed/types/session_event_stream_params.py +13 -0
  490. qca/managed/types/session_event_usage.py +24 -0
  491. qca/managed/types/session_list_params.py +26 -0
  492. qca/managed/types/session_multiagent_coordinator.py +15 -0
  493. qca/managed/types/session_multiagent_coordinator_agent_union.py +26 -0
  494. qca/managed/types/session_resource_add_params.py +15 -0
  495. qca/managed/types/session_resource_config_union.py +21 -0
  496. qca/managed/types/session_resource_delete_params.py +12 -0
  497. qca/managed/types/session_resource_get_response_union.py +27 -0
  498. qca/managed/types/session_resource_list_params.py +16 -0
  499. qca/managed/types/session_resource_retrieve_params.py +12 -0
  500. qca/managed/types/session_resource_union.py +27 -0
  501. qca/managed/types/session_resource_update_params.py +14 -0
  502. qca/managed/types/session_resource_update_response_union.py +27 -0
  503. qca/managed/types/session_retrieve_params.py +12 -0
  504. qca/managed/types/session_stats.py +12 -0
  505. qca/managed/types/session_stream_event.py +82 -0
  506. qca/managed/types/session_stream_event_stop_reason.py +12 -0
  507. qca/managed/types/session_stream_event_usage.py +24 -0
  508. qca/managed/types/session_thread.py +27 -0
  509. qca/managed/types/session_thread_agent_skill_union.py +13 -0
  510. qca/managed/types/session_thread_agent_tool_union.py +25 -0
  511. qca/managed/types/session_thread_agent_tool_union_default_config.py +17 -0
  512. qca/managed/types/session_thread_agent_tool_union_default_config_permission_policy.py +11 -0
  513. qca/managed/types/session_thread_agent_union.py +26 -0
  514. qca/managed/types/session_thread_archive_params.py +12 -0
  515. qca/managed/types/session_thread_event_list_params.py +16 -0
  516. qca/managed/types/session_thread_event_stream_params.py +13 -0
  517. qca/managed/types/session_thread_list_params.py +14 -0
  518. qca/managed/types/session_thread_retrieve_params.py +12 -0
  519. qca/managed/types/session_thread_stats.py +13 -0
  520. qca/managed/types/session_thread_usage.py +22 -0
  521. qca/managed/types/session_update_params.py +22 -0
  522. qca/managed/types/session_usage.py +22 -0
  523. qca/managed/types/session_work_data.py +12 -0
  524. qca/managed/types/skill.py +22 -0
  525. qca/managed/types/skill_create_params.py +17 -0
  526. qca/managed/types/skill_delete_params.py +12 -0
  527. qca/managed/types/skill_list_params.py +19 -0
  528. qca/managed/types/skill_retrieve_params.py +12 -0
  529. qca/managed/types/skill_source.py +11 -0
  530. qca/managed/types/skill_version.py +19 -0
  531. qca/managed/types/skill_version_create_params.py +15 -0
  532. qca/managed/types/skill_version_delete_params.py +12 -0
  533. qca/managed/types/skill_version_download_params.py +12 -0
  534. qca/managed/types/skill_version_list_params.py +14 -0
  535. qca/managed/types/skill_version_retrieve_params.py +12 -0
  536. qca/managed/types/span_model_usage.py +15 -0
  537. qca/managed/types/start_event_preview_union.py +12 -0
  538. qca/managed/types/static_bearer_create_params.py +13 -0
  539. qca/managed/types/static_bearer_update_params.py +12 -0
  540. qca/managed/types/stream_session_thread_events_union.py +82 -0
  541. qca/managed/types/stream_session_thread_events_union_stop_reason.py +12 -0
  542. qca/managed/types/stream_session_thread_events_union_usage.py +24 -0
  543. qca/managed/types/system_content_block.py +12 -0
  544. qca/managed/types/system_content_block_param.py +12 -0
  545. qca/managed/types/system_message_event_params.py +15 -0
  546. qca/managed/types/text_block.py +12 -0
  547. qca/managed/types/text_block_param.py +12 -0
  548. qca/managed/types/text_rubric_params.py +12 -0
  549. qca/managed/types/thinking_capability.py +15 -0
  550. qca/managed/types/thinking_types.py +15 -0
  551. qca/managed/types/token_endpoint_auth_basic_param.py +12 -0
  552. qca/managed/types/token_endpoint_auth_basic_update_param.py +12 -0
  553. qca/managed/types/token_endpoint_auth_none_param.py +11 -0
  554. qca/managed/types/token_endpoint_auth_post_param.py +12 -0
  555. qca/managed/types/token_endpoint_auth_post_update_param.py +12 -0
  556. qca/managed/types/trigger_context_union.py +13 -0
  557. qca/managed/types/unrestricted_credential_networking_params.py +11 -0
  558. qca/managed/types/unrestricted_network_param.py +11 -0
  559. qca/managed/types/url_document_source_param.py +12 -0
  560. qca/managed/types/url_image_source_param.py +12 -0
  561. qca/managed/types/urlmcp_server_params.py +13 -0
  562. qca/managed/types/user_custom_tool_result_event_content_union.py +21 -0
  563. qca/managed/types/user_custom_tool_result_event_params.py +20 -0
  564. qca/managed/types/user_define_outcome_event_params.py +18 -0
  565. qca/managed/types/user_define_outcome_event_rubric_union.py +13 -0
  566. qca/managed/types/user_interrupt_event_params.py +12 -0
  567. qca/managed/types/user_location.py +15 -0
  568. qca/managed/types/user_location_param.py +15 -0
  569. qca/managed/types/user_message_event_content_union.py +18 -0
  570. qca/managed/types/user_message_event_content_union_source.py +15 -0
  571. qca/managed/types/user_message_event_params.py +18 -0
  572. qca/managed/types/user_tool_confirmation_event_params.py +14 -0
  573. qca/managed/types/user_tool_result_event_content_union.py +21 -0
  574. qca/managed/types/user_tool_result_event_params.py +20 -0
  575. qca/managed/types/vault.py +18 -0
  576. qca/managed/types/vault_archive_params.py +12 -0
  577. qca/managed/types/vault_create_params.py +14 -0
  578. qca/managed/types/vault_credential_archive_params.py +12 -0
  579. qca/managed/types/vault_credential_create_params.py +20 -0
  580. qca/managed/types/vault_credential_delete_params.py +12 -0
  581. qca/managed/types/vault_credential_list_params.py +18 -0
  582. qca/managed/types/vault_credential_mcpo_auth_validate_params.py +12 -0
  583. qca/managed/types/vault_credential_retrieve_params.py +12 -0
  584. qca/managed/types/vault_credential_update_params.py +19 -0
  585. qca/managed/types/vault_delete_params.py +12 -0
  586. qca/managed/types/vault_list_params.py +18 -0
  587. qca/managed/types/vault_retrieve_params.py +12 -0
  588. qca/managed/types/web_fetch_tool_config_params.py +21 -0
  589. qca/managed/types/web_search_tool_config_params.py +22 -0
  590. qca/managed/types/write_tool_config_params.py +18 -0
  591. qca/py.typed +0 -0
  592. qca_sdk-0.0.1.dev4.dist-info/METADATA +411 -0
  593. qca_sdk-0.0.1.dev4.dist-info/RECORD +596 -0
  594. qca_sdk-0.0.1.dev4.dist-info/WHEEL +5 -0
  595. qca_sdk-0.0.1.dev4.dist-info/licenses/LICENSE +21 -0
  596. qca_sdk-0.0.1.dev4.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,8 @@
1
+ from importlib.metadata import PackageNotFoundError, version
2
+
3
+ try:
4
+ # 分发名是 qca-sdk,导入名是 qca,元数据只认前者。
5
+ __version__ = version("qca-sdk")
6
+ except PackageNotFoundError:
7
+ # 直接从源码树导入(未安装)时没有包元数据可读。
8
+ __version__ = "0.0.0.dev0"
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_PAT")
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