nemo-platform-plugin 0.1.0__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 (1224) hide show
  1. nemo_platform/__init__.py +117 -0
  2. nemo_platform/_base_client.py +2146 -0
  3. nemo_platform/_client.py +1200 -0
  4. nemo_platform/_compat.py +241 -0
  5. nemo_platform/_constants.py +29 -0
  6. nemo_platform/_decoders/jsonl.py +138 -0
  7. nemo_platform/_exceptions.py +123 -0
  8. nemo_platform/_files.py +188 -0
  9. nemo_platform/_models.py +967 -0
  10. nemo_platform/_qs.py +164 -0
  11. nemo_platform/_resource.py +58 -0
  12. nemo_platform/_response.py +872 -0
  13. nemo_platform/_streaming.py +391 -0
  14. nemo_platform/_types.py +288 -0
  15. nemo_platform/_utils/__init__.py +79 -0
  16. nemo_platform/_utils/_compat.py +60 -0
  17. nemo_platform/_utils/_datetime_parse.py +151 -0
  18. nemo_platform/_utils/_json.py +50 -0
  19. nemo_platform/_utils/_logs.py +40 -0
  20. nemo_platform/_utils/_path.py +142 -0
  21. nemo_platform/_utils/_proxy.py +80 -0
  22. nemo_platform/_utils/_reflection.py +57 -0
  23. nemo_platform/_utils/_resources_proxy.py +39 -0
  24. nemo_platform/_utils/_streams.py +27 -0
  25. nemo_platform/_utils/_sync.py +73 -0
  26. nemo_platform/_utils/_transform.py +472 -0
  27. nemo_platform/_utils/_typing.py +171 -0
  28. nemo_platform/_utils/_utils.py +448 -0
  29. nemo_platform/_version.py +21 -0
  30. nemo_platform/auth/__init__.py +15 -0
  31. nemo_platform/auth/device_flow.py +303 -0
  32. nemo_platform/auth/helpers.py +211 -0
  33. nemo_platform/auth/token_provider.py +239 -0
  34. nemo_platform/beta/evaluator/__init__.py +120 -0
  35. nemo_platform/beta/evaluator/agent_inference.py +360 -0
  36. nemo_platform/beta/evaluator/constants.py +4 -0
  37. nemo_platform/beta/evaluator/dataset_schemas/common.py +177 -0
  38. nemo_platform/beta/evaluator/dataset_schemas/compatibility.py +353 -0
  39. nemo_platform/beta/evaluator/dataset_schemas/templates.py +389 -0
  40. nemo_platform/beta/evaluator/datasets/__init__.py +28 -0
  41. nemo_platform/beta/evaluator/datasets/loader.py +415 -0
  42. nemo_platform/beta/evaluator/enums.py +64 -0
  43. nemo_platform/beta/evaluator/execution/_protocols.py +20 -0
  44. nemo_platform/beta/evaluator/execution/backends/base.py +86 -0
  45. nemo_platform/beta/evaluator/execution/backends/local/backend.py +132 -0
  46. nemo_platform/beta/evaluator/execution/benchmark_execution.py +666 -0
  47. nemo_platform/beta/evaluator/execution/config.py +64 -0
  48. nemo_platform/beta/evaluator/execution/evaluator.py +289 -0
  49. nemo_platform/beta/evaluator/execution/job_poll.py +98 -0
  50. nemo_platform/beta/evaluator/execution/metric_execution.py +878 -0
  51. nemo_platform/beta/evaluator/execution/pipeline.py +64 -0
  52. nemo_platform/beta/evaluator/execution/runs.py +143 -0
  53. nemo_platform/beta/evaluator/execution/scoring.py +224 -0
  54. nemo_platform/beta/evaluator/execution/utils.py +116 -0
  55. nemo_platform/beta/evaluator/execution/values.py +53 -0
  56. nemo_platform/beta/evaluator/inference.py +456 -0
  57. nemo_platform/beta/evaluator/metrics/aggregation.py +451 -0
  58. nemo_platform/beta/evaluator/metrics/bleu.py +94 -0
  59. nemo_platform/beta/evaluator/metrics/exact_match.py +52 -0
  60. nemo_platform/beta/evaluator/metrics/f1.py +50 -0
  61. nemo_platform/beta/evaluator/metrics/hooks.py +41 -0
  62. nemo_platform/beta/evaluator/metrics/llm_judge.py +392 -0
  63. nemo_platform/beta/evaluator/metrics/number_check.py +95 -0
  64. nemo_platform/beta/evaluator/metrics/protocol.py +241 -0
  65. nemo_platform/beta/evaluator/metrics/ragas/__init__.py +41 -0
  66. nemo_platform/beta/evaluator/metrics/ragas/base.py +521 -0
  67. nemo_platform/beta/evaluator/metrics/ragas/git_patch.py +36 -0
  68. nemo_platform/beta/evaluator/metrics/ragas/imports.py +192 -0
  69. nemo_platform/beta/evaluator/metrics/ragas/metrics.py +183 -0
  70. nemo_platform/beta/evaluator/metrics/remote.py +250 -0
  71. nemo_platform/beta/evaluator/metrics/rouge.py +71 -0
  72. nemo_platform/beta/evaluator/metrics/string_check.py +69 -0
  73. nemo_platform/beta/evaluator/metrics/template_rendering.py +141 -0
  74. nemo_platform/beta/evaluator/metrics/tool_calling.py +173 -0
  75. nemo_platform/beta/evaluator/metrics/types.py +62 -0
  76. nemo_platform/beta/evaluator/metrics/utils.py +54 -0
  77. nemo_platform/beta/evaluator/resilience/api.py +142 -0
  78. nemo_platform/beta/evaluator/resilience/classifier.py +142 -0
  79. nemo_platform/beta/evaluator/resilience/config.py +69 -0
  80. nemo_platform/beta/evaluator/resilience/errors.py +117 -0
  81. nemo_platform/beta/evaluator/resilience/policy.py +50 -0
  82. nemo_platform/beta/evaluator/resilience/scheduler.py +459 -0
  83. nemo_platform/beta/evaluator/resilience/types.py +93 -0
  84. nemo_platform/beta/evaluator/structured_output.py +184 -0
  85. nemo_platform/beta/evaluator/templates.py +115 -0
  86. nemo_platform/beta/evaluator/values/__init__.py +162 -0
  87. nemo_platform/beta/evaluator/values/agents.py +84 -0
  88. nemo_platform/beta/evaluator/values/common.py +28 -0
  89. nemo_platform/beta/evaluator/values/dataset_schemas.py +112 -0
  90. nemo_platform/beta/evaluator/values/datasets.py +28 -0
  91. nemo_platform/beta/evaluator/values/metrics.py +587 -0
  92. nemo_platform/beta/evaluator/values/models.py +157 -0
  93. nemo_platform/beta/evaluator/values/multi_metric_results.py +359 -0
  94. nemo_platform/beta/evaluator/values/params.py +109 -0
  95. nemo_platform/beta/evaluator/values/results.py +699 -0
  96. nemo_platform/beta/evaluator/values/scores.py +300 -0
  97. nemo_platform/beta/safe_synthesizer/__init__.py +4 -0
  98. nemo_platform/beta/safe_synthesizer/config.py +29 -0
  99. nemo_platform/beta/safe_synthesizer/job.py +309 -0
  100. nemo_platform/beta/safe_synthesizer/job_builder.py +355 -0
  101. nemo_platform/cli/__init__.py +4 -0
  102. nemo_platform/cli/app.py +321 -0
  103. nemo_platform/cli/commands/__init__.py +15 -0
  104. nemo_platform/cli/commands/api/__init__.py +114 -0
  105. nemo_platform/cli/commands/api/adapters.py +384 -0
  106. nemo_platform/cli/commands/api/files/__init__.py +237 -0
  107. nemo_platform/cli/commands/api/files/filesets.py +386 -0
  108. nemo_platform/cli/commands/api/files/otlp/__init__.py +12 -0
  109. nemo_platform/cli/commands/api/files/otlp/logs.py +116 -0
  110. nemo_platform/cli/commands/api/guardrail/__init__.py +270 -0
  111. nemo_platform/cli/commands/api/guardrail/configs.py +311 -0
  112. nemo_platform/cli/commands/api/iam/__init__.py +12 -0
  113. nemo_platform/cli/commands/api/iam/role_bindings.py +264 -0
  114. nemo_platform/cli/commands/api/inference/__init__.py +76 -0
  115. nemo_platform/cli/commands/api/inference/deployment_configs/__init__.py +370 -0
  116. nemo_platform/cli/commands/api/inference/deployment_configs/versions.py +132 -0
  117. nemo_platform/cli/commands/api/inference/deployments/__init__.py +565 -0
  118. nemo_platform/cli/commands/api/inference/deployments/versions.py +141 -0
  119. nemo_platform/cli/commands/api/inference/gateway/__init__.py +14 -0
  120. nemo_platform/cli/commands/api/inference/gateway/model.py +324 -0
  121. nemo_platform/cli/commands/api/inference/gateway/openai/__init__.py +12 -0
  122. nemo_platform/cli/commands/api/inference/gateway/openai/v1/__init__.py +12 -0
  123. nemo_platform/cli/commands/api/inference/gateway/openai/v1/models.py +106 -0
  124. nemo_platform/cli/commands/api/inference/gateway/provider.py +327 -0
  125. nemo_platform/cli/commands/api/inference/models.py +106 -0
  126. nemo_platform/cli/commands/api/inference/providers.py +612 -0
  127. nemo_platform/cli/commands/api/inference/virtual_models.py +412 -0
  128. nemo_platform/cli/commands/api/intake/__init__.py +18 -0
  129. nemo_platform/cli/commands/api/intake/apps/__init__.py +326 -0
  130. nemo_platform/cli/commands/api/intake/apps/tasks.py +340 -0
  131. nemo_platform/cli/commands/api/intake/entries/__init__.py +445 -0
  132. nemo_platform/cli/commands/api/intake/entries/events.py +118 -0
  133. nemo_platform/cli/commands/api/intake/evaluator_results.py +267 -0
  134. nemo_platform/cli/commands/api/intake/exports/__init__.py +63 -0
  135. nemo_platform/cli/commands/api/intake/exports/jobs.py +245 -0
  136. nemo_platform/cli/commands/api/intake/ingest/__init__.py +14 -0
  137. nemo_platform/cli/commands/api/intake/ingest/atif.py +115 -0
  138. nemo_platform/cli/commands/api/intake/ingest/chat_completions.py +125 -0
  139. nemo_platform/cli/commands/api/intake/ingest/otlp/__init__.py +12 -0
  140. nemo_platform/cli/commands/api/intake/ingest/otlp/v1/__init__.py +12 -0
  141. nemo_platform/cli/commands/api/intake/ingest/otlp/v1/traces.py +72 -0
  142. nemo_platform/cli/commands/api/intake/spans/__init__.py +202 -0
  143. nemo_platform/cli/commands/api/intake/spans/evaluator_results.py +65 -0
  144. nemo_platform/cli/commands/api/intake/traces.py +183 -0
  145. nemo_platform/cli/commands/api/jobs/__init__.py +576 -0
  146. nemo_platform/cli/commands/api/jobs/results.py +211 -0
  147. nemo_platform/cli/commands/api/jobs/steps.py +243 -0
  148. nemo_platform/cli/commands/api/jobs/tasks.py +210 -0
  149. nemo_platform/cli/commands/api/members.py +304 -0
  150. nemo_platform/cli/commands/api/models/__init__.py +555 -0
  151. nemo_platform/cli/commands/api/models/adapters.py +261 -0
  152. nemo_platform/cli/commands/api/projects.py +332 -0
  153. nemo_platform/cli/commands/api/safe_synthesizer/__init__.py +12 -0
  154. nemo_platform/cli/commands/api/safe_synthesizer/jobs/__init__.py +417 -0
  155. nemo_platform/cli/commands/api/safe_synthesizer/jobs/results.py +211 -0
  156. nemo_platform/cli/commands/api/secrets/__init__.py +315 -0
  157. nemo_platform/cli/commands/api/secrets/admin.py +44 -0
  158. nemo_platform/cli/commands/api/workspaces.py +339 -0
  159. nemo_platform/cli/commands/auth.py +803 -0
  160. nemo_platform/cli/commands/config.py +308 -0
  161. nemo_platform/cli/commands/docs.py +277 -0
  162. nemo_platform/cli/commands/manifest_registry.py +180 -0
  163. nemo_platform/cli/commands/plugins.py +87 -0
  164. nemo_platform/cli/commands/quickstart/__init__.py +15 -0
  165. nemo_platform/cli/commands/quickstart/cli.py +1178 -0
  166. nemo_platform/cli/commands/services/_process.py +472 -0
  167. nemo_platform/cli/commands/services/cli.py +694 -0
  168. nemo_platform/cli/commands/setup.py +1947 -0
  169. nemo_platform/cli/commands/skills/agents/claude.py +29 -0
  170. nemo_platform/cli/commands/skills/agents/codex.py +32 -0
  171. nemo_platform/cli/commands/skills/agents/cursor.py +18 -0
  172. nemo_platform/cli/commands/skills/agents/opencode.py +20 -0
  173. nemo_platform/cli/commands/skills/base.py +53 -0
  174. nemo_platform/cli/commands/skills/cli.py +313 -0
  175. nemo_platform/cli/commands/skills/installer.py +51 -0
  176. nemo_platform/cli/commands/skills/registry.py +396 -0
  177. nemo_platform/cli/commands/use_cases/__init__.py +15 -0
  178. nemo_platform/cli/commands/use_cases/agent.py +245 -0
  179. nemo_platform/cli/commands/use_cases/chat.py +965 -0
  180. nemo_platform/cli/commands/use_cases/wait.py +151 -0
  181. nemo_platform/cli/core/__init__.py +8 -0
  182. nemo_platform/cli/core/agent_helpers.py +84 -0
  183. nemo_platform/cli/core/api.py +160 -0
  184. nemo_platform/cli/core/autocomplete.py +63 -0
  185. nemo_platform/cli/core/code_generator.py +306 -0
  186. nemo_platform/cli/core/context.py +179 -0
  187. nemo_platform/cli/core/errors.py +349 -0
  188. nemo_platform/cli/core/formatters.py +718 -0
  189. nemo_platform/cli/core/help_formatter.py +868 -0
  190. nemo_platform/cli/core/lazy_load.py +187 -0
  191. nemo_platform/cli/core/logging.py +24 -0
  192. nemo_platform/cli/core/pagination.py +255 -0
  193. nemo_platform/cli/core/stdin_utils.py +233 -0
  194. nemo_platform/cli/core/streaming.py +30 -0
  195. nemo_platform/cli/core/table_config.py +302 -0
  196. nemo_platform/cli/core/timestamp_formatter.py +127 -0
  197. nemo_platform/cli/core/types.py +112 -0
  198. nemo_platform/cli/core/waiters.py +339 -0
  199. nemo_platform/cli/manifest.py +108 -0
  200. nemo_platform/client/__init__.py +15 -0
  201. nemo_platform/client/factory.py +597 -0
  202. nemo_platform/config/README.md +168 -0
  203. nemo_platform/config/__init__.py +23 -0
  204. nemo_platform/config/config.py +538 -0
  205. nemo_platform/config/models.py +377 -0
  206. nemo_platform/config/types.py +7 -0
  207. nemo_platform/filesets/__init__.py +19 -0
  208. nemo_platform/filesets/filesystem/callbacks.py +229 -0
  209. nemo_platform/filesets/filesystem/filesystem.py +940 -0
  210. nemo_platform/filesets/resources.py +1120 -0
  211. nemo_platform/lib/.keep +4 -0
  212. nemo_platform/models/__init__.py +14 -0
  213. nemo_platform/models/resources.py +836 -0
  214. nemo_platform/pagination.py +149 -0
  215. nemo_platform/py.typed +0 -0
  216. nemo_platform/quickstart/__init__.py +99 -0
  217. nemo_platform/quickstart/cluster.py +198 -0
  218. nemo_platform/quickstart/config.py +402 -0
  219. nemo_platform/quickstart/container.py +758 -0
  220. nemo_platform/quickstart/gpu_config.py +111 -0
  221. nemo_platform/quickstart/platform_config.py +82 -0
  222. nemo_platform/quickstart/preflight.py +451 -0
  223. nemo_platform/quickstart/prompts.py +426 -0
  224. nemo_platform/quickstart/storage.py +90 -0
  225. nemo_platform/quickstart/validators.py +268 -0
  226. nemo_platform/resources/__init__.py +16 -0
  227. nemo_platform/resources/adapters/__init__.py +34 -0
  228. nemo_platform/resources/adapters/adapters.py +704 -0
  229. nemo_platform/resources/adapters/api.md +15 -0
  230. nemo_platform/resources/audit/__init__.py +16 -0
  231. nemo_platform/resources/entities/__init__.py +34 -0
  232. nemo_platform/resources/entities/api.md +16 -0
  233. nemo_platform/resources/entities/entities.py +1014 -0
  234. nemo_platform/resources/evaluation/__init__.py +118 -0
  235. nemo_platform/resources/evaluation/api.md +303 -0
  236. nemo_platform/resources/evaluation/benchmark_job_results.py +541 -0
  237. nemo_platform/resources/evaluation/benchmark_jobs/__init__.py +48 -0
  238. nemo_platform/resources/evaluation/benchmark_jobs/benchmark_jobs.py +900 -0
  239. nemo_platform/resources/evaluation/benchmark_jobs/results/__init__.py +76 -0
  240. nemo_platform/resources/evaluation/benchmark_jobs/results/aggregate_scores.py +197 -0
  241. nemo_platform/resources/evaluation/benchmark_jobs/results/artifacts.py +206 -0
  242. nemo_platform/resources/evaluation/benchmark_jobs/results/results.py +516 -0
  243. nemo_platform/resources/evaluation/benchmark_jobs/results/row_scores.py +213 -0
  244. nemo_platform/resources/evaluation/benchmarks.py +690 -0
  245. nemo_platform/resources/evaluation/evaluation.py +277 -0
  246. nemo_platform/resources/evaluation/metric_job_results.py +533 -0
  247. nemo_platform/resources/evaluation/metric_jobs/__init__.py +48 -0
  248. nemo_platform/resources/evaluation/metric_jobs/metric_jobs.py +888 -0
  249. nemo_platform/resources/evaluation/metric_jobs/results/__init__.py +76 -0
  250. nemo_platform/resources/evaluation/metric_jobs/results/aggregate_scores.py +197 -0
  251. nemo_platform/resources/evaluation/metric_jobs/results/artifacts.py +206 -0
  252. nemo_platform/resources/evaluation/metric_jobs/results/results.py +512 -0
  253. nemo_platform/resources/evaluation/metric_jobs/results/row_scores.py +213 -0
  254. nemo_platform/resources/evaluation/metrics.py +3495 -0
  255. nemo_platform/resources/files/__init__.py +62 -0
  256. nemo_platform/resources/files/api.md +65 -0
  257. nemo_platform/resources/files/files.py +683 -0
  258. nemo_platform/resources/files/filesets.py +783 -0
  259. nemo_platform/resources/files/otlp/__init__.py +48 -0
  260. nemo_platform/resources/files/otlp/logs.py +337 -0
  261. nemo_platform/resources/files/otlp/otlp.py +117 -0
  262. nemo_platform/resources/guardrail/__init__.py +48 -0
  263. nemo_platform/resources/guardrail/api.md +116 -0
  264. nemo_platform/resources/guardrail/configs.py +679 -0
  265. nemo_platform/resources/guardrail/guardrail.py +463 -0
  266. nemo_platform/resources/iam/__init__.py +48 -0
  267. nemo_platform/resources/iam/api.md +22 -0
  268. nemo_platform/resources/iam/iam.py +117 -0
  269. nemo_platform/resources/iam/role_bindings.py +537 -0
  270. nemo_platform/resources/inference/__init__.py +118 -0
  271. nemo_platform/resources/inference/api.md +224 -0
  272. nemo_platform/resources/inference/deployment_configs/__init__.py +48 -0
  273. nemo_platform/resources/inference/deployment_configs/deployment_configs.py +756 -0
  274. nemo_platform/resources/inference/deployment_configs/versions.py +418 -0
  275. nemo_platform/resources/inference/deployments/__init__.py +48 -0
  276. nemo_platform/resources/inference/deployments/deployments.py +1017 -0
  277. nemo_platform/resources/inference/deployments/versions.py +434 -0
  278. nemo_platform/resources/inference/gateway/__init__.py +76 -0
  279. nemo_platform/resources/inference/gateway/gateway.py +181 -0
  280. nemo_platform/resources/inference/gateway/model.py +708 -0
  281. nemo_platform/resources/inference/gateway/openai/__init__.py +48 -0
  282. nemo_platform/resources/inference/gateway/openai/openai.py +700 -0
  283. nemo_platform/resources/inference/gateway/openai/v1/__init__.py +48 -0
  284. nemo_platform/resources/inference/gateway/openai/v1/models.py +290 -0
  285. nemo_platform/resources/inference/gateway/openai/v1/v1.py +117 -0
  286. nemo_platform/resources/inference/gateway/provider.py +749 -0
  287. nemo_platform/resources/inference/inference.py +277 -0
  288. nemo_platform/resources/inference/models.py +290 -0
  289. nemo_platform/resources/inference/providers.py +1049 -0
  290. nemo_platform/resources/inference/virtual_models.py +846 -0
  291. nemo_platform/resources/intake/__init__.py +132 -0
  292. nemo_platform/resources/intake/api.md +268 -0
  293. nemo_platform/resources/intake/apps/__init__.py +48 -0
  294. nemo_platform/resources/intake/apps/apps.py +718 -0
  295. nemo_platform/resources/intake/apps/tasks.py +731 -0
  296. nemo_platform/resources/intake/entries/__init__.py +48 -0
  297. nemo_platform/resources/intake/entries/entries.py +855 -0
  298. nemo_platform/resources/intake/entries/events.py +320 -0
  299. nemo_platform/resources/intake/evaluator_results.py +512 -0
  300. nemo_platform/resources/intake/exports/__init__.py +48 -0
  301. nemo_platform/resources/intake/exports/exports.py +229 -0
  302. nemo_platform/resources/intake/exports/jobs.py +464 -0
  303. nemo_platform/resources/intake/ingest/__init__.py +76 -0
  304. nemo_platform/resources/intake/ingest/atif.py +242 -0
  305. nemo_platform/resources/intake/ingest/chat_completions.py +270 -0
  306. nemo_platform/resources/intake/ingest/ingest.py +181 -0
  307. nemo_platform/resources/intake/ingest/otlp/__init__.py +48 -0
  308. nemo_platform/resources/intake/ingest/otlp/otlp.py +117 -0
  309. nemo_platform/resources/intake/ingest/otlp/v1/__init__.py +48 -0
  310. nemo_platform/resources/intake/ingest/otlp/v1/traces.py +183 -0
  311. nemo_platform/resources/intake/ingest/otlp/v1/v1.py +117 -0
  312. nemo_platform/resources/intake/intake.py +309 -0
  313. nemo_platform/resources/intake/spans/__init__.py +48 -0
  314. nemo_platform/resources/intake/spans/evaluator_results.py +197 -0
  315. nemo_platform/resources/intake/spans/spans.py +367 -0
  316. nemo_platform/resources/intake/traces.py +351 -0
  317. nemo_platform/resources/jobs/__init__.py +76 -0
  318. nemo_platform/resources/jobs/api.md +118 -0
  319. nemo_platform/resources/jobs/jobs.py +1300 -0
  320. nemo_platform/resources/jobs/results.py +555 -0
  321. nemo_platform/resources/jobs/steps.py +491 -0
  322. nemo_platform/resources/jobs/tasks.py +470 -0
  323. nemo_platform/resources/members/__init__.py +34 -0
  324. nemo_platform/resources/members/api.md +19 -0
  325. nemo_platform/resources/members/members.py +634 -0
  326. nemo_platform/resources/models/__init__.py +48 -0
  327. nemo_platform/resources/models/adapters.py +514 -0
  328. nemo_platform/resources/models/api.md +44 -0
  329. nemo_platform/resources/models/models.py +981 -0
  330. nemo_platform/resources/projects/__init__.py +34 -0
  331. nemo_platform/resources/projects/api.md +21 -0
  332. nemo_platform/resources/projects/projects.py +736 -0
  333. nemo_platform/resources/safe_synthesizer/__init__.py +48 -0
  334. nemo_platform/resources/safe_synthesizer/api.md +62 -0
  335. nemo_platform/resources/safe_synthesizer/jobs/__init__.py +48 -0
  336. nemo_platform/resources/safe_synthesizer/jobs/jobs.py +895 -0
  337. nemo_platform/resources/safe_synthesizer/jobs/results.py +819 -0
  338. nemo_platform/resources/safe_synthesizer/safe_synthesizer.py +117 -0
  339. nemo_platform/resources/secrets/__init__.py +48 -0
  340. nemo_platform/resources/secrets/admin.py +150 -0
  341. nemo_platform/resources/secrets/api.md +34 -0
  342. nemo_platform/resources/secrets/secrets.py +756 -0
  343. nemo_platform/resources/workspaces/__init__.py +34 -0
  344. nemo_platform/resources/workspaces/api.md +20 -0
  345. nemo_platform/resources/workspaces/workspaces.py +734 -0
  346. nemo_platform/skills/__init__.py +28 -0
  347. nemo_platform/skills/inference/SKILL.md +564 -0
  348. nemo_platform/skills/nemo-build-agent/SKILL.md +221 -0
  349. nemo_platform/skills/nemo-build-agent/references/templates/data-designer-config.py +80 -0
  350. nemo_platform/skills/nemo-evaluator/SKILL.md +140 -0
  351. nemo_platform/skills/nemo-explore/SKILL.md +70 -0
  352. nemo_platform/skills/nemo-files/SKILL.md +81 -0
  353. nemo_platform/skills/nemo-fine-tune/SKILL.md +43 -0
  354. nemo_platform/skills/nemo-guardrails/SKILL.md +519 -0
  355. nemo_platform/skills/nemo-secrets/SKILL.md +60 -0
  356. nemo_platform/skills/nemo-skill-selection/SKILL.md +146 -0
  357. nemo_platform/skills/nemo-spec/SKILL.md +76 -0
  358. nemo_platform/skills/nemo-spec/references/templates/agent-spec.md +68 -0
  359. nemo_platform/skills/nemo-status/SKILL.md +115 -0
  360. nemo_platform/skills/nemo-teardown/SKILL.md +185 -0
  361. nemo_platform/skills/nemo-try-agent/SKILL.md +102 -0
  362. nemo_platform/types/__init__.py +54 -0
  363. nemo_platform/types/adapters/__init__.py +24 -0
  364. nemo_platform/types/adapters/adapter_create_params.py +63 -0
  365. nemo_platform/types/adapters/adapter_entity_filter_param.py +56 -0
  366. nemo_platform/types/adapters/adapter_list_params.py +46 -0
  367. nemo_platform/types/adapters/adapter_patch_params.py +35 -0
  368. nemo_platform/types/adapters/adapters_page.py +37 -0
  369. nemo_platform/types/audit/__init__.py +18 -0
  370. nemo_platform/types/audit/jobs/__init__.py +18 -0
  371. nemo_platform/types/entities/__init__.py +26 -0
  372. nemo_platform/types/entities/entities_page.py +37 -0
  373. nemo_platform/types/entities/entity.py +63 -0
  374. nemo_platform/types/entities/entity_create_params.py +46 -0
  375. nemo_platform/types/entities/entity_delete_entity_by_name_params.py +31 -0
  376. nemo_platform/types/entities/entity_get_entity_by_name_params.py +31 -0
  377. nemo_platform/types/entities/entity_list_params.py +47 -0
  378. nemo_platform/types/entities/entity_update_entity_by_name_params.py +52 -0
  379. nemo_platform/types/evaluation/__init__.py +242 -0
  380. nemo_platform/types/evaluation/agent.py +68 -0
  381. nemo_platform/types/evaluation/agent_goal_accuracy_metric.py +92 -0
  382. nemo_platform/types/evaluation/agent_goal_accuracy_metric_param.py +69 -0
  383. nemo_platform/types/evaluation/agent_goal_accuracy_metric_param_param.py +70 -0
  384. nemo_platform/types/evaluation/agent_goal_accuracy_metric_response.py +88 -0
  385. nemo_platform/types/evaluation/agent_param.py +69 -0
  386. nemo_platform/types/evaluation/aggregate_range_score.py +65 -0
  387. nemo_platform/types/evaluation/aggregate_rubric_score.py +64 -0
  388. nemo_platform/types/evaluation/aggregated_metric_result.py +34 -0
  389. nemo_platform/types/evaluation/answer_accuracy_metric.py +89 -0
  390. nemo_platform/types/evaluation/answer_accuracy_metric_param.py +66 -0
  391. nemo_platform/types/evaluation/answer_accuracy_metric_param_param.py +67 -0
  392. nemo_platform/types/evaluation/answer_accuracy_metric_response.py +85 -0
  393. nemo_platform/types/evaluation/benchmark.py +81 -0
  394. nemo_platform/types/evaluation/benchmark_create_params.py +64 -0
  395. nemo_platform/types/evaluation/benchmark_create_response.py +26 -0
  396. nemo_platform/types/evaluation/benchmark_evaluation_job.py +75 -0
  397. nemo_platform/types/evaluation/benchmark_evaluation_jobs_list_filter_param.py +49 -0
  398. nemo_platform/types/evaluation/benchmark_evaluation_jobs_page.py +37 -0
  399. nemo_platform/types/evaluation/benchmark_evaluation_jobs_sort_field.py +22 -0
  400. nemo_platform/types/evaluation/benchmark_job_create_params.py +58 -0
  401. nemo_platform/types/evaluation/benchmark_job_get_logs_params.py +30 -0
  402. nemo_platform/types/evaluation/benchmark_job_list_params.py +44 -0
  403. nemo_platform/types/evaluation/benchmark_job_result.py +93 -0
  404. nemo_platform/types/evaluation/benchmark_job_result_list_params.py +116 -0
  405. nemo_platform/types/evaluation/benchmark_job_result_retrieve_params.py +50 -0
  406. nemo_platform/types/evaluation/benchmark_job_results_list_response.py +37 -0
  407. nemo_platform/types/evaluation/benchmark_jobs/__init__.py +18 -0
  408. nemo_platform/types/evaluation/benchmark_jobs/results/__init__.py +22 -0
  409. nemo_platform/types/evaluation/benchmark_jobs/results/benchmark_evaluation_result.py +30 -0
  410. nemo_platform/types/evaluation/benchmark_jobs/results/benchmark_metric_result.py +44 -0
  411. nemo_platform/types/evaluation/benchmark_jobs/results/row_score_download_params.py +28 -0
  412. nemo_platform/types/evaluation/benchmark_list_params.py +84 -0
  413. nemo_platform/types/evaluation/benchmark_offline_job.py +43 -0
  414. nemo_platform/types/evaluation/benchmark_offline_job_param.py +44 -0
  415. nemo_platform/types/evaluation/benchmark_online_agent_job.py +71 -0
  416. nemo_platform/types/evaluation/benchmark_online_agent_job_param.py +74 -0
  417. nemo_platform/types/evaluation/benchmark_online_job.py +66 -0
  418. nemo_platform/types/evaluation/benchmark_online_job_param.py +68 -0
  419. nemo_platform/types/evaluation/benchmark_ref.py +22 -0
  420. nemo_platform/types/evaluation/benchmark_retrieve_params.py +29 -0
  421. nemo_platform/types/evaluation/benchmark_retrieve_response.py +27 -0
  422. nemo_platform/types/evaluation/benchmarks_list_response.py +42 -0
  423. nemo_platform/types/evaluation/bleu_metric.py +76 -0
  424. nemo_platform/types/evaluation/bleu_metric_param.py +50 -0
  425. nemo_platform/types/evaluation/bleu_metric_param_param.py +52 -0
  426. nemo_platform/types/evaluation/bleu_metric_response.py +69 -0
  427. nemo_platform/types/evaluation/built_in_dataset.py +46 -0
  428. nemo_platform/types/evaluation/context_entity_recall_metric.py +89 -0
  429. nemo_platform/types/evaluation/context_entity_recall_metric_param.py +66 -0
  430. nemo_platform/types/evaluation/context_entity_recall_metric_param_param.py +67 -0
  431. nemo_platform/types/evaluation/context_entity_recall_metric_response.py +85 -0
  432. nemo_platform/types/evaluation/context_precision_metric.py +89 -0
  433. nemo_platform/types/evaluation/context_precision_metric_param.py +66 -0
  434. nemo_platform/types/evaluation/context_precision_metric_param_param.py +67 -0
  435. nemo_platform/types/evaluation/context_precision_metric_response.py +85 -0
  436. nemo_platform/types/evaluation/context_recall_metric.py +89 -0
  437. nemo_platform/types/evaluation/context_recall_metric_param.py +66 -0
  438. nemo_platform/types/evaluation/context_recall_metric_param_param.py +67 -0
  439. nemo_platform/types/evaluation/context_recall_metric_response.py +85 -0
  440. nemo_platform/types/evaluation/context_relevance_metric.py +89 -0
  441. nemo_platform/types/evaluation/context_relevance_metric_param.py +66 -0
  442. nemo_platform/types/evaluation/context_relevance_metric_param_param.py +67 -0
  443. nemo_platform/types/evaluation/context_relevance_metric_response.py +85 -0
  444. nemo_platform/types/evaluation/dataset_rows.py +35 -0
  445. nemo_platform/types/evaluation/dataset_rows_param.py +36 -0
  446. nemo_platform/types/evaluation/evaluate_dataset_rows_param.py +33 -0
  447. nemo_platform/types/evaluation/exact_match_metric.py +79 -0
  448. nemo_platform/types/evaluation/exact_match_metric_param.py +53 -0
  449. nemo_platform/types/evaluation/exact_match_metric_param_param.py +53 -0
  450. nemo_platform/types/evaluation/exact_match_metric_response.py +72 -0
  451. nemo_platform/types/evaluation/extended_benchmark.py +130 -0
  452. nemo_platform/types/evaluation/f1_metric.py +76 -0
  453. nemo_platform/types/evaluation/f1_metric_param.py +50 -0
  454. nemo_platform/types/evaluation/f1_metric_param_param.py +50 -0
  455. nemo_platform/types/evaluation/f1_metric_response.py +69 -0
  456. nemo_platform/types/evaluation/faithfulness_metric.py +89 -0
  457. nemo_platform/types/evaluation/faithfulness_metric_param.py +66 -0
  458. nemo_platform/types/evaluation/faithfulness_metric_param_param.py +67 -0
  459. nemo_platform/types/evaluation/faithfulness_metric_response.py +85 -0
  460. nemo_platform/types/evaluation/field_mapping.py +56 -0
  461. nemo_platform/types/evaluation/field_mapping_param.py +57 -0
  462. nemo_platform/types/evaluation/fileset.py +48 -0
  463. nemo_platform/types/evaluation/fileset_param.py +49 -0
  464. nemo_platform/types/evaluation/fileset_ref.py +22 -0
  465. nemo_platform/types/evaluation/histogram.py +30 -0
  466. nemo_platform/types/evaluation/histogram_bin.py +33 -0
  467. nemo_platform/types/evaluation/inference_params.py +65 -0
  468. nemo_platform/types/evaluation/inference_params_param.py +53 -0
  469. nemo_platform/types/evaluation/json_score_parser.py +35 -0
  470. nemo_platform/types/evaluation/json_score_parser_param.py +34 -0
  471. nemo_platform/types/evaluation/llm_judge_metric.py +126 -0
  472. nemo_platform/types/evaluation/llm_judge_metric_param.py +103 -0
  473. nemo_platform/types/evaluation/llm_judge_metric_param_param.py +105 -0
  474. nemo_platform/types/evaluation/llm_judge_metric_response.py +120 -0
  475. nemo_platform/types/evaluation/metric_create_params.py +959 -0
  476. nemo_platform/types/evaluation/metric_create_response.py +75 -0
  477. nemo_platform/types/evaluation/metric_evaluate_params.py +111 -0
  478. nemo_platform/types/evaluation/metric_evaluation_job.py +65 -0
  479. nemo_platform/types/evaluation/metric_evaluation_jobs_list_filter_param.py +49 -0
  480. nemo_platform/types/evaluation/metric_evaluation_jobs_page.py +37 -0
  481. nemo_platform/types/evaluation/metric_evaluation_jobs_sort_field.py +22 -0
  482. nemo_platform/types/evaluation/metric_evaluation_response.py +98 -0
  483. nemo_platform/types/evaluation/metric_evaluation_row_score.py +45 -0
  484. nemo_platform/types/evaluation/metric_job_create_params.py +48 -0
  485. nemo_platform/types/evaluation/metric_job_get_logs_params.py +30 -0
  486. nemo_platform/types/evaluation/metric_job_list_params.py +44 -0
  487. nemo_platform/types/evaluation/metric_job_result.py +93 -0
  488. nemo_platform/types/evaluation/metric_job_result_list_params.py +114 -0
  489. nemo_platform/types/evaluation/metric_job_result_retrieve_params.py +50 -0
  490. nemo_platform/types/evaluation/metric_job_results_list_response.py +37 -0
  491. nemo_platform/types/evaluation/metric_jobs/__init__.py +18 -0
  492. nemo_platform/types/evaluation/metric_jobs/results/__init__.py +20 -0
  493. nemo_platform/types/evaluation/metric_jobs/results/row_score_download_params.py +28 -0
  494. nemo_platform/types/evaluation/metric_list_params.py +73 -0
  495. nemo_platform/types/evaluation/metric_offline_job.py +106 -0
  496. nemo_platform/types/evaluation/metric_offline_job_param.py +107 -0
  497. nemo_platform/types/evaluation/metric_online_agent_job.py +133 -0
  498. nemo_platform/types/evaluation/metric_online_agent_job_param.py +135 -0
  499. nemo_platform/types/evaluation/metric_online_job.py +127 -0
  500. nemo_platform/types/evaluation/metric_online_job_param.py +129 -0
  501. nemo_platform/types/evaluation/metric_output.py +30 -0
  502. nemo_platform/types/evaluation/metric_ref.py +22 -0
  503. nemo_platform/types/evaluation/metric_retrieve_response.py +98 -0
  504. nemo_platform/types/evaluation/metric_retriever_job.py +64 -0
  505. nemo_platform/types/evaluation/metric_retriever_job_param.py +65 -0
  506. nemo_platform/types/evaluation/metric_type.py +47 -0
  507. nemo_platform/types/evaluation/metrics_list_response.py +90 -0
  508. nemo_platform/types/evaluation/model.py +44 -0
  509. nemo_platform/types/evaluation/model_param.py +44 -0
  510. nemo_platform/types/evaluation/model_ref.py +22 -0
  511. nemo_platform/types/evaluation/nemo_agent_toolkit_remote_metric.py +87 -0
  512. nemo_platform/types/evaluation/nemo_agent_toolkit_remote_metric_param.py +64 -0
  513. nemo_platform/types/evaluation/nemo_agent_toolkit_remote_metric_param_param.py +65 -0
  514. nemo_platform/types/evaluation/nemo_agent_toolkit_remote_metric_response.py +80 -0
  515. nemo_platform/types/evaluation/noise_sensitivity_metric.py +89 -0
  516. nemo_platform/types/evaluation/noise_sensitivity_metric_param.py +66 -0
  517. nemo_platform/types/evaluation/noise_sensitivity_metric_param_param.py +67 -0
  518. nemo_platform/types/evaluation/noise_sensitivity_metric_response.py +85 -0
  519. nemo_platform/types/evaluation/number_check_metric.py +104 -0
  520. nemo_platform/types/evaluation/number_check_metric_param.py +81 -0
  521. nemo_platform/types/evaluation/number_check_metric_param_param.py +83 -0
  522. nemo_platform/types/evaluation/number_check_metric_response.py +97 -0
  523. nemo_platform/types/evaluation/parameter.py +42 -0
  524. nemo_platform/types/evaluation/parameter_param.py +40 -0
  525. nemo_platform/types/evaluation/percentiles.py +54 -0
  526. nemo_platform/types/evaluation/range_score.py +56 -0
  527. nemo_platform/types/evaluation/range_score_param.py +57 -0
  528. nemo_platform/types/evaluation/reasoning_params.py +41 -0
  529. nemo_platform/types/evaluation/reasoning_params_param.py +41 -0
  530. nemo_platform/types/evaluation/regex_score_parser.py +38 -0
  531. nemo_platform/types/evaluation/regex_score_parser_param.py +37 -0
  532. nemo_platform/types/evaluation/remote_metric.py +91 -0
  533. nemo_platform/types/evaluation/remote_metric_param.py +68 -0
  534. nemo_platform/types/evaluation/remote_metric_param_param.py +69 -0
  535. nemo_platform/types/evaluation/remote_metric_response.py +84 -0
  536. nemo_platform/types/evaluation/remote_score.py +49 -0
  537. nemo_platform/types/evaluation/remote_score_param.py +50 -0
  538. nemo_platform/types/evaluation/response_groundedness_metric.py +89 -0
  539. nemo_platform/types/evaluation/response_groundedness_metric_param.py +66 -0
  540. nemo_platform/types/evaluation/response_groundedness_metric_param_param.py +67 -0
  541. nemo_platform/types/evaluation/response_groundedness_metric_response.py +85 -0
  542. nemo_platform/types/evaluation/response_relevancy_metric.py +95 -0
  543. nemo_platform/types/evaluation/response_relevancy_metric_param.py +74 -0
  544. nemo_platform/types/evaluation/response_relevancy_metric_param_param.py +75 -0
  545. nemo_platform/types/evaluation/response_relevancy_metric_response.py +93 -0
  546. nemo_platform/types/evaluation/retriever_pipeline.py +34 -0
  547. nemo_platform/types/evaluation/retriever_pipeline_param.py +35 -0
  548. nemo_platform/types/evaluation/rouge_metric.py +76 -0
  549. nemo_platform/types/evaluation/rouge_metric_param.py +53 -0
  550. nemo_platform/types/evaluation/rouge_metric_param_param.py +53 -0
  551. nemo_platform/types/evaluation/rouge_metric_response.py +69 -0
  552. nemo_platform/types/evaluation/row_score.py +59 -0
  553. nemo_platform/types/evaluation/rubric.py +40 -0
  554. nemo_platform/types/evaluation/rubric_param.py +40 -0
  555. nemo_platform/types/evaluation/rubric_score.py +54 -0
  556. nemo_platform/types/evaluation/rubric_score_param.py +55 -0
  557. nemo_platform/types/evaluation/rubric_score_stat.py +38 -0
  558. nemo_platform/types/evaluation/run_config.py +39 -0
  559. nemo_platform/types/evaluation/run_config_online.py +51 -0
  560. nemo_platform/types/evaluation/run_config_online_model.py +73 -0
  561. nemo_platform/types/evaluation/run_config_online_model_param.py +75 -0
  562. nemo_platform/types/evaluation/run_config_online_param.py +51 -0
  563. nemo_platform/types/evaluation/run_config_param.py +39 -0
  564. nemo_platform/types/evaluation/string_check_metric.py +82 -0
  565. nemo_platform/types/evaluation/string_check_metric_param.py +59 -0
  566. nemo_platform/types/evaluation/string_check_metric_param_param.py +61 -0
  567. nemo_platform/types/evaluation/string_check_metric_response.py +75 -0
  568. nemo_platform/types/evaluation/system_benchmark.py +71 -0
  569. nemo_platform/types/evaluation/system_benchmark_offline_job.py +58 -0
  570. nemo_platform/types/evaluation/system_benchmark_offline_job_param.py +60 -0
  571. nemo_platform/types/evaluation/system_benchmark_online_job.py +54 -0
  572. nemo_platform/types/evaluation/system_benchmark_online_job_param.py +55 -0
  573. nemo_platform/types/evaluation/system_metric.py +70 -0
  574. nemo_platform/types/evaluation/system_metric_param.py +50 -0
  575. nemo_platform/types/evaluation/system_metric_param_param.py +51 -0
  576. nemo_platform/types/evaluation/system_metric_response.py +66 -0
  577. nemo_platform/types/evaluation/tool_call_accuracy_metric.py +70 -0
  578. nemo_platform/types/evaluation/tool_call_accuracy_metric_param.py +44 -0
  579. nemo_platform/types/evaluation/tool_call_accuracy_metric_param_param.py +44 -0
  580. nemo_platform/types/evaluation/tool_call_accuracy_metric_response.py +63 -0
  581. nemo_platform/types/evaluation/tool_calling_metric.py +70 -0
  582. nemo_platform/types/evaluation/tool_calling_metric_param.py +47 -0
  583. nemo_platform/types/evaluation/tool_calling_metric_param_param.py +47 -0
  584. nemo_platform/types/evaluation/tool_calling_metric_response.py +63 -0
  585. nemo_platform/types/evaluation/topic_adherence_metric.py +92 -0
  586. nemo_platform/types/evaluation/topic_adherence_metric_param.py +69 -0
  587. nemo_platform/types/evaluation/topic_adherence_metric_param_param.py +70 -0
  588. nemo_platform/types/evaluation/topic_adherence_metric_response.py +88 -0
  589. nemo_platform/types/files/__init__.py +45 -0
  590. nemo_platform/types/files/cache_status.py +22 -0
  591. nemo_platform/types/files/dataset_metadata_content.py +46 -0
  592. nemo_platform/types/files/dataset_metadata_content_param.py +45 -0
  593. nemo_platform/types/files/file_list_files_params.py +35 -0
  594. nemo_platform/types/files/file_upload_file_params.py +28 -0
  595. nemo_platform/types/files/fileset.py +62 -0
  596. nemo_platform/types/files/fileset_create_params.py +74 -0
  597. nemo_platform/types/files/fileset_file.py +36 -0
  598. nemo_platform/types/files/fileset_filter_param.py +54 -0
  599. nemo_platform/types/files/fileset_list_params.py +47 -0
  600. nemo_platform/types/files/fileset_metadata_param.py +46 -0
  601. nemo_platform/types/files/fileset_metadata_param_param.py +47 -0
  602. nemo_platform/types/files/fileset_outputs_page.py +37 -0
  603. nemo_platform/types/files/fileset_purpose.py +22 -0
  604. nemo_platform/types/files/fileset_update_params.py +49 -0
  605. nemo_platform/types/files/huggingface_storage_config.py +60 -0
  606. nemo_platform/types/files/huggingface_storage_config_param.py +60 -0
  607. nemo_platform/types/files/list_fileset_files_response.py +27 -0
  608. nemo_platform/types/files/local_storage_config.py +39 -0
  609. nemo_platform/types/files/local_storage_config_param.py +38 -0
  610. nemo_platform/types/files/ngc_storage_config.py +66 -0
  611. nemo_platform/types/files/ngc_storage_config_param.py +66 -0
  612. nemo_platform/types/files/otlp/__init__.py +22 -0
  613. nemo_platform/types/files/otlp/log_query_params.py +36 -0
  614. nemo_platform/types/files/otlp/otel_export_logs_partial_success.py +34 -0
  615. nemo_platform/types/files/otlp/otel_export_logs_service_response.py +35 -0
  616. nemo_platform/types/files/s3_storage_config.py +85 -0
  617. nemo_platform/types/files/s3_storage_config_param.py +85 -0
  618. nemo_platform/types/files/secret_ref.py +22 -0
  619. nemo_platform/types/files/storage_config_type.py +22 -0
  620. nemo_platform/types/guardrail/__init__.py +165 -0
  621. nemo_platform/types/guardrail/action_rails.py +36 -0
  622. nemo_platform/types/guardrail/action_rails_param.py +38 -0
  623. nemo_platform/types/guardrail/activated_rail.py +61 -0
  624. nemo_platform/types/guardrail/ai_defense_rail_config.py +36 -0
  625. nemo_platform/types/guardrail/ai_defense_rail_config_param.py +36 -0
  626. nemo_platform/types/guardrail/auto_align_options.py +29 -0
  627. nemo_platform/types/guardrail/auto_align_options_param.py +30 -0
  628. nemo_platform/types/guardrail/auto_align_rail_config.py +35 -0
  629. nemo_platform/types/guardrail/auto_align_rail_config_param.py +37 -0
  630. nemo_platform/types/guardrail/cache_stats_config.py +32 -0
  631. nemo_platform/types/guardrail/cache_stats_config_param.py +32 -0
  632. nemo_platform/types/guardrail/chat_completion_assistant_message_param.py +45 -0
  633. nemo_platform/types/guardrail/chat_completion_content_part_image_param.py +34 -0
  634. nemo_platform/types/guardrail/chat_completion_content_part_text_param.py +32 -0
  635. nemo_platform/types/guardrail/chat_completion_function_message_param.py +35 -0
  636. nemo_platform/types/guardrail/chat_completion_message_tool_call_param.py +37 -0
  637. nemo_platform/types/guardrail/chat_completion_system_message_param.py +35 -0
  638. nemo_platform/types/guardrail/chat_completion_tool_message_param.py +35 -0
  639. nemo_platform/types/guardrail/chat_completion_user_message_param.py +41 -0
  640. nemo_platform/types/guardrail/clavata_rail_config.py +47 -0
  641. nemo_platform/types/guardrail/clavata_rail_config_param.py +48 -0
  642. nemo_platform/types/guardrail/clavata_rail_options.py +36 -0
  643. nemo_platform/types/guardrail/clavata_rail_options_param.py +38 -0
  644. nemo_platform/types/guardrail/config_create_params.py +36 -0
  645. nemo_platform/types/guardrail/config_list_params.py +47 -0
  646. nemo_platform/types/guardrail/config_update_params.py +33 -0
  647. nemo_platform/types/guardrail/content_safety_config.py +34 -0
  648. nemo_platform/types/guardrail/content_safety_config_param.py +35 -0
  649. nemo_platform/types/guardrail/crowd_strike_aidr_rail_config.py +29 -0
  650. nemo_platform/types/guardrail/crowd_strike_aidr_rail_config_param.py +29 -0
  651. nemo_platform/types/guardrail/dialog_rails.py +34 -0
  652. nemo_platform/types/guardrail/dialog_rails_param.py +35 -0
  653. nemo_platform/types/guardrail/executed_action.py +48 -0
  654. nemo_platform/types/guardrail/fact_checking_rail_config.py +31 -0
  655. nemo_platform/types/guardrail/fact_checking_rail_config_param.py +32 -0
  656. nemo_platform/types/guardrail/fiddler_guardrails.py +35 -0
  657. nemo_platform/types/guardrail/fiddler_guardrails_param.py +35 -0
  658. nemo_platform/types/guardrail/function_call_param.py +35 -0
  659. nemo_platform/types/guardrail/function_param.py +35 -0
  660. nemo_platform/types/guardrail/g_li_ner_detection.py +51 -0
  661. nemo_platform/types/guardrail/g_li_ner_detection_options.py +29 -0
  662. nemo_platform/types/guardrail/g_li_ner_detection_options_param.py +31 -0
  663. nemo_platform/types/guardrail/g_li_ner_detection_param.py +52 -0
  664. nemo_platform/types/guardrail/generation_log.py +44 -0
  665. nemo_platform/types/guardrail/generation_log_options_param.py +50 -0
  666. nemo_platform/types/guardrail/generation_options_param.py +55 -0
  667. nemo_platform/types/guardrail/generation_rails_options_param.py +53 -0
  668. nemo_platform/types/guardrail/generation_stats.py +56 -0
  669. nemo_platform/types/guardrail/guardrail_check_params.py +164 -0
  670. nemo_platform/types/guardrail/guardrail_check_response.py +36 -0
  671. nemo_platform/types/guardrail/guardrail_config.py +59 -0
  672. nemo_platform/types/guardrail/guardrail_config_filter_param.py +49 -0
  673. nemo_platform/types/guardrail/guardrail_configs_page.py +37 -0
  674. nemo_platform/types/guardrail/guardrails_ai_rail_config.py +33 -0
  675. nemo_platform/types/guardrail/guardrails_ai_rail_config_param.py +35 -0
  676. nemo_platform/types/guardrail/guardrails_ai_validator_config.py +44 -0
  677. nemo_platform/types/guardrail/guardrails_ai_validator_config_param.py +45 -0
  678. nemo_platform/types/guardrail/guardrails_data.py +40 -0
  679. nemo_platform/types/guardrail/guardrails_data_param.py +67 -0
  680. nemo_platform/types/guardrail/image_u_rl_param.py +32 -0
  681. nemo_platform/types/guardrail/injection_detection.py +49 -0
  682. nemo_platform/types/guardrail/injection_detection_param.py +52 -0
  683. nemo_platform/types/guardrail/input_rails.py +32 -0
  684. nemo_platform/types/guardrail/input_rails_param.py +34 -0
  685. nemo_platform/types/guardrail/instruction.py +30 -0
  686. nemo_platform/types/guardrail/instruction_param.py +32 -0
  687. nemo_platform/types/guardrail/jailbreak_detection_config.py +52 -0
  688. nemo_platform/types/guardrail/jailbreak_detection_config_param.py +58 -0
  689. nemo_platform/types/guardrail/llm_call_info.py +63 -0
  690. nemo_platform/types/guardrail/log_adapter_config.py +41 -0
  691. nemo_platform/types/guardrail/log_adapter_config_param.py +27 -0
  692. nemo_platform/types/guardrail/message_template.py +30 -0
  693. nemo_platform/types/guardrail/message_template_param.py +32 -0
  694. nemo_platform/types/guardrail/model.py +55 -0
  695. nemo_platform/types/guardrail/model_cache_config.py +36 -0
  696. nemo_platform/types/guardrail/model_cache_config_param.py +37 -0
  697. nemo_platform/types/guardrail/model_param.py +55 -0
  698. nemo_platform/types/guardrail/model_parameters.py +51 -0
  699. nemo_platform/types/guardrail/model_parameters_param.py +38 -0
  700. nemo_platform/types/guardrail/multilingual_config.py +40 -0
  701. nemo_platform/types/guardrail/multilingual_config_param.py +41 -0
  702. nemo_platform/types/guardrail/output_rails.py +44 -0
  703. nemo_platform/types/guardrail/output_rails_param.py +46 -0
  704. nemo_platform/types/guardrail/output_rails_streaming_config.py +44 -0
  705. nemo_platform/types/guardrail/output_rails_streaming_config_param.py +44 -0
  706. nemo_platform/types/guardrail/pangea_rail_config.py +33 -0
  707. nemo_platform/types/guardrail/pangea_rail_config_param.py +34 -0
  708. nemo_platform/types/guardrail/pangea_rail_options.py +31 -0
  709. nemo_platform/types/guardrail/pangea_rail_options_param.py +33 -0
  710. nemo_platform/types/guardrail/patronus_evaluate_api_params.py +38 -0
  711. nemo_platform/types/guardrail/patronus_evaluate_api_params_param.py +40 -0
  712. nemo_platform/types/guardrail/patronus_evaluate_config.py +30 -0
  713. nemo_platform/types/guardrail/patronus_evaluate_config_param.py +31 -0
  714. nemo_platform/types/guardrail/patronus_evaluation_success_strategy.py +22 -0
  715. nemo_platform/types/guardrail/patronus_rail_config.py +33 -0
  716. nemo_platform/types/guardrail/patronus_rail_config_param.py +34 -0
  717. nemo_platform/types/guardrail/private_ai_detection.py +39 -0
  718. nemo_platform/types/guardrail/private_ai_detection_options.py +29 -0
  719. nemo_platform/types/guardrail/private_ai_detection_options_param.py +31 -0
  720. nemo_platform/types/guardrail/private_ai_detection_param.py +40 -0
  721. nemo_platform/types/guardrail/rail_status.py +26 -0
  722. nemo_platform/types/guardrail/rails.py +73 -0
  723. nemo_platform/types/guardrail/rails_config.py +79 -0
  724. nemo_platform/types/guardrail/rails_config_data.py +94 -0
  725. nemo_platform/types/guardrail/rails_config_data_param.py +95 -0
  726. nemo_platform/types/guardrail/rails_config_param.py +81 -0
  727. nemo_platform/types/guardrail/rails_param.py +74 -0
  728. nemo_platform/types/guardrail/reasoning_config.py +32 -0
  729. nemo_platform/types/guardrail/reasoning_config_param.py +32 -0
  730. nemo_platform/types/guardrail/regex_detection.py +36 -0
  731. nemo_platform/types/guardrail/regex_detection_options.py +32 -0
  732. nemo_platform/types/guardrail/regex_detection_options_param.py +34 -0
  733. nemo_platform/types/guardrail/regex_detection_param.py +37 -0
  734. nemo_platform/types/guardrail/retrieval_rails.py +29 -0
  735. nemo_platform/types/guardrail/retrieval_rails_param.py +31 -0
  736. nemo_platform/types/guardrail/sensitive_data_detection.py +43 -0
  737. nemo_platform/types/guardrail/sensitive_data_detection_options.py +37 -0
  738. nemo_platform/types/guardrail/sensitive_data_detection_options_param.py +39 -0
  739. nemo_platform/types/guardrail/sensitive_data_detection_param.py +45 -0
  740. nemo_platform/types/guardrail/single_call_config.py +31 -0
  741. nemo_platform/types/guardrail/single_call_config_param.py +31 -0
  742. nemo_platform/types/guardrail/status_enum.py +22 -0
  743. nemo_platform/types/guardrail/task_prompt.py +63 -0
  744. nemo_platform/types/guardrail/task_prompt_param.py +65 -0
  745. nemo_platform/types/guardrail/tool_input_rails.py +36 -0
  746. nemo_platform/types/guardrail/tool_input_rails_param.py +38 -0
  747. nemo_platform/types/guardrail/tool_output_rails.py +36 -0
  748. nemo_platform/types/guardrail/tool_output_rails_param.py +38 -0
  749. nemo_platform/types/guardrail/tracing_config.py +48 -0
  750. nemo_platform/types/guardrail/tracing_config_param.py +50 -0
  751. nemo_platform/types/guardrail/trend_micro_rail_config.py +51 -0
  752. nemo_platform/types/guardrail/trend_micro_rail_config_param.py +51 -0
  753. nemo_platform/types/guardrail/user_messages_config.py +42 -0
  754. nemo_platform/types/guardrail/user_messages_config_param.py +42 -0
  755. nemo_platform/types/iam/__init__.py +26 -0
  756. nemo_platform/types/iam/date_range_filter_param.py +36 -0
  757. nemo_platform/types/iam/role_binding.py +42 -0
  758. nemo_platform/types/iam/role_binding_create_params.py +39 -0
  759. nemo_platform/types/iam/role_binding_delete_params.py +30 -0
  760. nemo_platform/types/iam/role_binding_filter_param.py +49 -0
  761. nemo_platform/types/iam/role_binding_list_params.py +44 -0
  762. nemo_platform/types/iam/role_bindings_page.py +37 -0
  763. nemo_platform/types/inference/__init__.py +60 -0
  764. nemo_platform/types/inference/deployment_config_create_params.py +47 -0
  765. nemo_platform/types/inference/deployment_config_list_params.py +46 -0
  766. nemo_platform/types/inference/deployment_config_update_params.py +37 -0
  767. nemo_platform/types/inference/deployment_configs/__init__.py +20 -0
  768. nemo_platform/types/inference/deployment_configs/version_list_response.py +25 -0
  769. nemo_platform/types/inference/deployment_create_params.py +45 -0
  770. nemo_platform/types/inference/deployment_list_models_response.py +23 -0
  771. nemo_platform/types/inference/deployment_list_params.py +52 -0
  772. nemo_platform/types/inference/deployment_update_params.py +35 -0
  773. nemo_platform/types/inference/deployment_update_status_params.py +42 -0
  774. nemo_platform/types/inference/deployments/__init__.py +20 -0
  775. nemo_platform/types/inference/deployments/version_list_response.py +25 -0
  776. nemo_platform/types/inference/gateway/__init__.py +38 -0
  777. nemo_platform/types/inference/gateway/model_patch_params.py +31 -0
  778. nemo_platform/types/inference/gateway/model_patch_response.py +23 -0
  779. nemo_platform/types/inference/gateway/model_post_params.py +31 -0
  780. nemo_platform/types/inference/gateway/model_post_response.py +23 -0
  781. nemo_platform/types/inference/gateway/model_put_params.py +31 -0
  782. nemo_platform/types/inference/gateway/model_put_response.py +23 -0
  783. nemo_platform/types/inference/gateway/openai/__init__.py +18 -0
  784. nemo_platform/types/inference/gateway/openai/v1/__init__.py +21 -0
  785. nemo_platform/types/inference/gateway/openai/v1/openai_list_models_resp.py +31 -0
  786. nemo_platform/types/inference/gateway/openai/v1/openai_model_resp.py +34 -0
  787. nemo_platform/types/inference/gateway/openai_patch_params.py +29 -0
  788. nemo_platform/types/inference/gateway/openai_patch_response.py +23 -0
  789. nemo_platform/types/inference/gateway/openai_post_params.py +29 -0
  790. nemo_platform/types/inference/gateway/openai_post_response.py +23 -0
  791. nemo_platform/types/inference/gateway/openai_put_params.py +29 -0
  792. nemo_platform/types/inference/gateway/openai_put_response.py +23 -0
  793. nemo_platform/types/inference/gateway/provider_patch_params.py +31 -0
  794. nemo_platform/types/inference/gateway/provider_patch_response.py +23 -0
  795. nemo_platform/types/inference/gateway/provider_post_params.py +31 -0
  796. nemo_platform/types/inference/gateway/provider_post_response.py +23 -0
  797. nemo_platform/types/inference/gateway/provider_put_params.py +31 -0
  798. nemo_platform/types/inference/gateway/provider_put_response.py +23 -0
  799. nemo_platform/types/inference/gateway/provider_ready_response.py +23 -0
  800. nemo_platform/types/inference/k8s_nim_operator_config.py +57 -0
  801. nemo_platform/types/inference/k8s_nim_operator_config_param.py +58 -0
  802. nemo_platform/types/inference/middleware_call.py +55 -0
  803. nemo_platform/types/inference/middleware_call_param.py +56 -0
  804. nemo_platform/types/inference/model_deployment.py +97 -0
  805. nemo_platform/types/inference/model_deployment_config.py +76 -0
  806. nemo_platform/types/inference/model_deployment_config_filter_param.py +49 -0
  807. nemo_platform/types/inference/model_deployment_configs_page.py +37 -0
  808. nemo_platform/types/inference/model_deployment_filter_param.py +56 -0
  809. nemo_platform/types/inference/model_deployment_status.py +24 -0
  810. nemo_platform/types/inference/model_deployment_status_history_item.py +37 -0
  811. nemo_platform/types/inference/model_deployments_page.py +37 -0
  812. nemo_platform/types/inference/model_provider.py +134 -0
  813. nemo_platform/types/inference/model_provider_filter_param.py +56 -0
  814. nemo_platform/types/inference/model_provider_sort.py +24 -0
  815. nemo_platform/types/inference/model_provider_status.py +24 -0
  816. nemo_platform/types/inference/model_providers_page.py +37 -0
  817. nemo_platform/types/inference/model_type.py +22 -0
  818. nemo_platform/types/inference/nim_deployment.py +96 -0
  819. nemo_platform/types/inference/nim_deployment_param.py +93 -0
  820. nemo_platform/types/inference/provider_create_params.py +94 -0
  821. nemo_platform/types/inference/provider_list_params.py +47 -0
  822. nemo_platform/types/inference/provider_update_params.py +87 -0
  823. nemo_platform/types/inference/provider_update_status_params.py +48 -0
  824. nemo_platform/types/inference/served_model_mapping.py +35 -0
  825. nemo_platform/types/inference/served_model_mapping_param.py +32 -0
  826. nemo_platform/types/inference/virtual_model.py +91 -0
  827. nemo_platform/types/inference/virtual_model_create_params.py +83 -0
  828. nemo_platform/types/inference/virtual_model_inference_config.py +32 -0
  829. nemo_platform/types/inference/virtual_model_inference_config_param.py +34 -0
  830. nemo_platform/types/inference/virtual_model_list_params.py +35 -0
  831. nemo_platform/types/inference/virtual_model_patch_params.py +80 -0
  832. nemo_platform/types/inference/virtual_models_page.py +37 -0
  833. nemo_platform/types/intake/__init__.py +86 -0
  834. nemo_platform/types/intake/app.py +51 -0
  835. nemo_platform/types/intake/app_create_params.py +38 -0
  836. nemo_platform/types/intake/app_filter_param.py +46 -0
  837. nemo_platform/types/intake/app_list_params.py +44 -0
  838. nemo_platform/types/intake/app_patch_params.py +35 -0
  839. nemo_platform/types/intake/app_sort_field.py +22 -0
  840. nemo_platform/types/intake/apps/__init__.py +26 -0
  841. nemo_platform/types/intake/apps/task.py +54 -0
  842. nemo_platform/types/intake/apps/task_create_params.py +40 -0
  843. nemo_platform/types/intake/apps/task_filter_param.py +49 -0
  844. nemo_platform/types/intake/apps/task_list_params.py +44 -0
  845. nemo_platform/types/intake/apps/task_patch_params.py +37 -0
  846. nemo_platform/types/intake/apps/task_sort_field.py +22 -0
  847. nemo_platform/types/intake/apps/tasks_page.py +37 -0
  848. nemo_platform/types/intake/apps_page.py +37 -0
  849. nemo_platform/types/intake/entries/__init__.py +20 -0
  850. nemo_platform/types/intake/entries/event_create_params.py +40 -0
  851. nemo_platform/types/intake/entry.py +98 -0
  852. nemo_platform/types/intake/entry_context.py +79 -0
  853. nemo_platform/types/intake/entry_context_filter_param.py +41 -0
  854. nemo_platform/types/intake/entry_context_param.py +82 -0
  855. nemo_platform/types/intake/entry_create_params.py +85 -0
  856. nemo_platform/types/intake/entry_data.py +48 -0
  857. nemo_platform/types/intake/entry_data_param.py +51 -0
  858. nemo_platform/types/intake/entry_filter_param.py +85 -0
  859. nemo_platform/types/intake/entry_list_params.py +47 -0
  860. nemo_platform/types/intake/entry_patch_params.py +79 -0
  861. nemo_platform/types/intake/entry_sort_field.py +22 -0
  862. nemo_platform/types/intake/entry_user_rating_filter_param.py +31 -0
  863. nemo_platform/types/intake/entrys_page.py +37 -0
  864. nemo_platform/types/intake/evaluation_context_param.py +41 -0
  865. nemo_platform/types/intake/evaluator_result.py +52 -0
  866. nemo_platform/types/intake/evaluator_result_create_params.py +52 -0
  867. nemo_platform/types/intake/evaluator_result_data_type.py +22 -0
  868. nemo_platform/types/intake/evaluator_result_event.py +67 -0
  869. nemo_platform/types/intake/evaluator_result_event_param.py +69 -0
  870. nemo_platform/types/intake/evaluator_result_filter_param.py +49 -0
  871. nemo_platform/types/intake/evaluator_result_list_params.py +43 -0
  872. nemo_platform/types/intake/evaluator_result_sort_field.py +22 -0
  873. nemo_platform/types/intake/evaluator_results_page.py +37 -0
  874. nemo_platform/types/intake/export_config_param.py +44 -0
  875. nemo_platform/types/intake/export_config_param_param.py +45 -0
  876. nemo_platform/types/intake/export_preview_params.py +34 -0
  877. nemo_platform/types/intake/export_preview_response.py +39 -0
  878. nemo_platform/types/intake/exports/__init__.py +28 -0
  879. nemo_platform/types/intake/exports/export_config.py +44 -0
  880. nemo_platform/types/intake/exports/export_job.py +76 -0
  881. nemo_platform/types/intake/exports/export_job_filter_param.py +50 -0
  882. nemo_platform/types/intake/exports/export_job_sort_field.py +22 -0
  883. nemo_platform/types/intake/exports/export_jobs_page.py +37 -0
  884. nemo_platform/types/intake/exports/export_status_details.py +35 -0
  885. nemo_platform/types/intake/exports/job_create_params.py +40 -0
  886. nemo_platform/types/intake/exports/job_list_params.py +46 -0
  887. nemo_platform/types/intake/exports/job_status.py +22 -0
  888. nemo_platform/types/intake/flexible_entry_request.py +63 -0
  889. nemo_platform/types/intake/flexible_entry_request_param.py +51 -0
  890. nemo_platform/types/intake/flexible_entry_response.py +62 -0
  891. nemo_platform/types/intake/flexible_entry_response_param.py +49 -0
  892. nemo_platform/types/intake/flexible_message.py +56 -0
  893. nemo_platform/types/intake/flexible_message_param.py +43 -0
  894. nemo_platform/types/intake/float_filter_param.py +32 -0
  895. nemo_platform/types/intake/ingest/__init__.py +37 -0
  896. nemo_platform/types/intake/ingest/atif_agent_param.py +35 -0
  897. nemo_platform/types/intake/ingest/atif_content_part_image_param.py +30 -0
  898. nemo_platform/types/intake/ingest/atif_content_part_param.py +28 -0
  899. nemo_platform/types/intake/ingest/atif_content_part_text_param.py +28 -0
  900. nemo_platform/types/intake/ingest/atif_create_params.py +52 -0
  901. nemo_platform/types/intake/ingest/atif_final_metrics_param.py +37 -0
  902. nemo_platform/types/intake/ingest/atif_image_source_param.py +28 -0
  903. nemo_platform/types/intake/ingest/atif_metrics_param.py +41 -0
  904. nemo_platform/types/intake/ingest/atif_observation_param.py +29 -0
  905. nemo_platform/types/intake/ingest/atif_observation_result_param.py +36 -0
  906. nemo_platform/types/intake/ingest/atif_step_agent_param.py +58 -0
  907. nemo_platform/types/intake/ingest/atif_step_param.py +29 -0
  908. nemo_platform/types/intake/ingest/atif_step_system_param.py +43 -0
  909. nemo_platform/types/intake/ingest/atif_step_user_param.py +43 -0
  910. nemo_platform/types/intake/ingest/atif_subagent_trajectory_ref_param.py +33 -0
  911. nemo_platform/types/intake/ingest/atif_tool_call_param.py +31 -0
  912. nemo_platform/types/intake/ingest/chat_completion_create_params.py +66 -0
  913. nemo_platform/types/intake/ingest/chat_completions_ingest_response.py +26 -0
  914. nemo_platform/types/intake/ingest/otlp/__init__.py +18 -0
  915. nemo_platform/types/intake/ingest/otlp/v1/__init__.py +20 -0
  916. nemo_platform/types/intake/ingest/otlp/v1/ingest_response.py +26 -0
  917. nemo_platform/types/intake/message_role.py +22 -0
  918. nemo_platform/types/intake/reviewer_annotation_event.py +95 -0
  919. nemo_platform/types/intake/reviewer_annotation_event_param.py +97 -0
  920. nemo_platform/types/intake/span.py +100 -0
  921. nemo_platform/types/intake/span_evaluation_context.py +40 -0
  922. nemo_platform/types/intake/span_filter_param.py +95 -0
  923. nemo_platform/types/intake/span_kind.py +24 -0
  924. nemo_platform/types/intake/span_list_params.py +46 -0
  925. nemo_platform/types/intake/span_sort_field.py +22 -0
  926. nemo_platform/types/intake/span_status.py +22 -0
  927. nemo_platform/types/intake/spans/__init__.py +20 -0
  928. nemo_platform/types/intake/spans/evaluator_result_list_response.py +25 -0
  929. nemo_platform/types/intake/spans_page.py +37 -0
  930. nemo_platform/types/intake/thumb_direction.py +22 -0
  931. nemo_platform/types/intake/trace.py +65 -0
  932. nemo_platform/types/intake/trace_filter_param.py +60 -0
  933. nemo_platform/types/intake/trace_list_params.py +49 -0
  934. nemo_platform/types/intake/trace_retrieve_params.py +32 -0
  935. nemo_platform/types/intake/trace_sort_field.py +22 -0
  936. nemo_platform/types/intake/traces_page.py +37 -0
  937. nemo_platform/types/intake/usage.py +65 -0
  938. nemo_platform/types/intake/usage_param.py +68 -0
  939. nemo_platform/types/intake/user_action_event.py +65 -0
  940. nemo_platform/types/intake/user_action_event_param.py +68 -0
  941. nemo_platform/types/intake/user_feedback_event.py +84 -0
  942. nemo_platform/types/intake/user_feedback_event_param.py +86 -0
  943. nemo_platform/types/intake/user_rating.py +68 -0
  944. nemo_platform/types/intake/user_rating_param.py +70 -0
  945. nemo_platform/types/jobs/__init__.py +95 -0
  946. nemo_platform/types/jobs/compute_resource_spec.py +32 -0
  947. nemo_platform/types/jobs/compute_resource_spec_param.py +32 -0
  948. nemo_platform/types/jobs/compute_resources.py +46 -0
  949. nemo_platform/types/jobs/compute_resources_param.py +47 -0
  950. nemo_platform/types/jobs/container_spec.py +35 -0
  951. nemo_platform/types/jobs/container_spec_param.py +37 -0
  952. nemo_platform/types/jobs/cpu_execution_provider.py +46 -0
  953. nemo_platform/types/jobs/cpu_execution_provider_param.py +46 -0
  954. nemo_platform/types/jobs/distributed_gpu_execution_provider.py +46 -0
  955. nemo_platform/types/jobs/distributed_gpu_execution_provider_param.py +46 -0
  956. nemo_platform/types/jobs/docker_job_execution_profile.py +43 -0
  957. nemo_platform/types/jobs/docker_job_execution_profile_config.py +52 -0
  958. nemo_platform/types/jobs/docker_job_network_config.py +27 -0
  959. nemo_platform/types/jobs/docker_job_storage_config.py +36 -0
  960. nemo_platform/types/jobs/docker_volume_mount.py +47 -0
  961. nemo_platform/types/jobs/e2e_job_execution_profile.py +43 -0
  962. nemo_platform/types/jobs/gpu_execution_provider.py +46 -0
  963. nemo_platform/types/jobs/gpu_execution_provider_param.py +46 -0
  964. nemo_platform/types/jobs/image_pull_secret.py +27 -0
  965. nemo_platform/types/jobs/job_create_params.py +46 -0
  966. nemo_platform/types/jobs/job_execution_profile_config.py +42 -0
  967. nemo_platform/types/jobs/job_get_logs_params.py +41 -0
  968. nemo_platform/types/jobs/job_list_execution_profiles_response.py +37 -0
  969. nemo_platform/types/jobs/job_list_params.py +47 -0
  970. nemo_platform/types/jobs/job_update_status_details_params.py +29 -0
  971. nemo_platform/types/jobs/kubernetes_empty_dir_volume.py +32 -0
  972. nemo_platform/types/jobs/kubernetes_job_execution_profile.py +43 -0
  973. nemo_platform/types/jobs/kubernetes_job_execution_profile_config.py +101 -0
  974. nemo_platform/types/jobs/kubernetes_job_storage_config.py +40 -0
  975. nemo_platform/types/jobs/kubernetes_object_metadata.py +28 -0
  976. nemo_platform/types/jobs/kubernetes_persistent_volume_claim.py +32 -0
  977. nemo_platform/types/jobs/kubernetes_volume.py +37 -0
  978. nemo_platform/types/jobs/kubernetes_volume_mount.py +38 -0
  979. nemo_platform/types/jobs/platform_job_environment_variable.py +36 -0
  980. nemo_platform/types/jobs/platform_job_environment_variable_param.py +37 -0
  981. nemo_platform/types/jobs/platform_job_list_task_response.py +29 -0
  982. nemo_platform/types/jobs/platform_job_response.py +75 -0
  983. nemo_platform/types/jobs/platform_job_responses_page.py +37 -0
  984. nemo_platform/types/jobs/platform_job_secret_environment_variable_ref.py +27 -0
  985. nemo_platform/types/jobs/platform_job_secret_environment_variable_ref_param.py +29 -0
  986. nemo_platform/types/jobs/platform_job_sort_field.py +22 -0
  987. nemo_platform/types/jobs/platform_job_spec.py +30 -0
  988. nemo_platform/types/jobs/platform_job_spec_param.py +32 -0
  989. nemo_platform/types/jobs/platform_job_step.py +75 -0
  990. nemo_platform/types/jobs/platform_job_step_spec.py +63 -0
  991. nemo_platform/types/jobs/platform_job_step_spec_param.py +65 -0
  992. nemo_platform/types/jobs/platform_job_step_with_context.py +67 -0
  993. nemo_platform/types/jobs/platform_job_step_with_contexts_page.py +37 -0
  994. nemo_platform/types/jobs/platform_job_steps_list_filter_param.py +38 -0
  995. nemo_platform/types/jobs/platform_job_task.py +75 -0
  996. nemo_platform/types/jobs/platform_jobs_list_filter_param.py +51 -0
  997. nemo_platform/types/jobs/result_create_params.py +34 -0
  998. nemo_platform/types/jobs/result_list_params.py +34 -0
  999. nemo_platform/types/jobs/step_lifecycle.py +37 -0
  1000. nemo_platform/types/jobs/step_lifecycle_param.py +37 -0
  1001. nemo_platform/types/jobs/step_list_params.py +44 -0
  1002. nemo_platform/types/jobs/step_update_status_params.py +44 -0
  1003. nemo_platform/types/jobs/subprocess_execution_provider.py +33 -0
  1004. nemo_platform/types/jobs/subprocess_execution_provider_param.py +34 -0
  1005. nemo_platform/types/jobs/subprocess_job_execution_profile.py +36 -0
  1006. nemo_platform/types/jobs/subprocess_job_execution_profile_config.py +49 -0
  1007. nemo_platform/types/jobs/task_create_or_update_params.py +46 -0
  1008. nemo_platform/types/jobs/volcano_job_execution_profile.py +39 -0
  1009. nemo_platform/types/jobs/volcano_job_execution_profile_config.py +114 -0
  1010. nemo_platform/types/members/__init__.py +24 -0
  1011. nemo_platform/types/members/member_create_params.py +40 -0
  1012. nemo_platform/types/members/member_delete_params.py +32 -0
  1013. nemo_platform/types/members/member_update_params.py +37 -0
  1014. nemo_platform/types/members/workspace_member.py +39 -0
  1015. nemo_platform/types/members/workspace_member_list_response.py +29 -0
  1016. nemo_platform/types/models/__init__.py +34 -0
  1017. nemo_platform/types/models/adapter.py +73 -0
  1018. nemo_platform/types/models/adapter_create_params.py +54 -0
  1019. nemo_platform/types/models/adapter_update_params.py +37 -0
  1020. nemo_platform/types/models/base_model_filter_param.py +29 -0
  1021. nemo_platform/types/models/finetuning_type_filter_param.py +31 -0
  1022. nemo_platform/types/models/lora.py +30 -0
  1023. nemo_platform/types/models/lora_param.py +30 -0
  1024. nemo_platform/types/models/model_create_params.py +93 -0
  1025. nemo_platform/types/models/model_entity.py +112 -0
  1026. nemo_platform/types/models/model_entity_filter_param.py +72 -0
  1027. nemo_platform/types/models/model_entity_sort_field.py +22 -0
  1028. nemo_platform/types/models/model_entitys_page.py +37 -0
  1029. nemo_platform/types/models/model_list_params.py +50 -0
  1030. nemo_platform/types/models/model_retrieve_params.py +29 -0
  1031. nemo_platform/types/models/model_update_params.py +86 -0
  1032. nemo_platform/types/projects/__init__.py +25 -0
  1033. nemo_platform/types/projects/project.py +45 -0
  1034. nemo_platform/types/projects/project_create_params.py +37 -0
  1035. nemo_platform/types/projects/project_list_params.py +49 -0
  1036. nemo_platform/types/projects/project_sort_field.py +22 -0
  1037. nemo_platform/types/projects/project_update_params.py +29 -0
  1038. nemo_platform/types/projects/projects_page.py +37 -0
  1039. nemo_platform/types/safe_synthesizer/__init__.py +68 -0
  1040. nemo_platform/types/safe_synthesizer/classify_config.py +41 -0
  1041. nemo_platform/types/safe_synthesizer/classify_config_param.py +43 -0
  1042. nemo_platform/types/safe_synthesizer/column.py +46 -0
  1043. nemo_platform/types/safe_synthesizer/column_actions.py +36 -0
  1044. nemo_platform/types/safe_synthesizer/column_actions_param.py +38 -0
  1045. nemo_platform/types/safe_synthesizer/column_param.py +49 -0
  1046. nemo_platform/types/safe_synthesizer/data_parameters.py +69 -0
  1047. nemo_platform/types/safe_synthesizer/data_parameters_param.py +69 -0
  1048. nemo_platform/types/safe_synthesizer/differential_privacy_hyperparams.py +48 -0
  1049. nemo_platform/types/safe_synthesizer/differential_privacy_hyperparams_param.py +48 -0
  1050. nemo_platform/types/safe_synthesizer/evaluation_parameters.py +64 -0
  1051. nemo_platform/types/safe_synthesizer/evaluation_parameters_param.py +66 -0
  1052. nemo_platform/types/safe_synthesizer/generate_parameters.py +104 -0
  1053. nemo_platform/types/safe_synthesizer/generate_parameters_param.py +102 -0
  1054. nemo_platform/types/safe_synthesizer/gliner_config.py +41 -0
  1055. nemo_platform/types/safe_synthesizer/gliner_config_param.py +41 -0
  1056. nemo_platform/types/safe_synthesizer/globals.py +45 -0
  1057. nemo_platform/types/safe_synthesizer/globals_param.py +47 -0
  1058. nemo_platform/types/safe_synthesizer/job_create_params.py +46 -0
  1059. nemo_platform/types/safe_synthesizer/job_get_logs_params.py +30 -0
  1060. nemo_platform/types/safe_synthesizer/job_list_params.py +44 -0
  1061. nemo_platform/types/safe_synthesizer/jobs/__init__.py +21 -0
  1062. nemo_platform/types/safe_synthesizer/jobs/safe_synthesizer_summary.py +95 -0
  1063. nemo_platform/types/safe_synthesizer/jobs/safe_synthesizer_timing.py +41 -0
  1064. nemo_platform/types/safe_synthesizer/ner_config.py +42 -0
  1065. nemo_platform/types/safe_synthesizer/ner_config_param.py +44 -0
  1066. nemo_platform/types/safe_synthesizer/pii_replacer_config.py +40 -0
  1067. nemo_platform/types/safe_synthesizer/pii_replacer_config_param.py +42 -0
  1068. nemo_platform/types/safe_synthesizer/row.py +50 -0
  1069. nemo_platform/types/safe_synthesizer/row_actions.py +33 -0
  1070. nemo_platform/types/safe_synthesizer/row_actions_param.py +35 -0
  1071. nemo_platform/types/safe_synthesizer/row_param.py +53 -0
  1072. nemo_platform/types/safe_synthesizer/safe_synthesizer_job.py +63 -0
  1073. nemo_platform/types/safe_synthesizer/safe_synthesizer_job_config.py +55 -0
  1074. nemo_platform/types/safe_synthesizer/safe_synthesizer_job_config_param.py +56 -0
  1075. nemo_platform/types/safe_synthesizer/safe_synthesizer_jobs_list_filter_param.py +49 -0
  1076. nemo_platform/types/safe_synthesizer/safe_synthesizer_jobs_page.py +37 -0
  1077. nemo_platform/types/safe_synthesizer/safe_synthesizer_jobs_sort_field.py +22 -0
  1078. nemo_platform/types/safe_synthesizer/safe_synthesizer_parameters.py +91 -0
  1079. nemo_platform/types/safe_synthesizer/safe_synthesizer_parameters_param.py +92 -0
  1080. nemo_platform/types/safe_synthesizer/step_definition.py +39 -0
  1081. nemo_platform/types/safe_synthesizer/step_definition_param.py +41 -0
  1082. nemo_platform/types/safe_synthesizer/time_series_parameters.py +73 -0
  1083. nemo_platform/types/safe_synthesizer/time_series_parameters_param.py +74 -0
  1084. nemo_platform/types/safe_synthesizer/training_hyperparams.py +165 -0
  1085. nemo_platform/types/safe_synthesizer/training_hyperparams_param.py +167 -0
  1086. nemo_platform/types/safe_synthesizer/validation_parameters.py +54 -0
  1087. nemo_platform/types/safe_synthesizer/validation_parameters_param.py +54 -0
  1088. nemo_platform/types/secrets/__init__.py +28 -0
  1089. nemo_platform/types/secrets/platform_secret_access_response.py +33 -0
  1090. nemo_platform/types/secrets/platform_secret_admin_rotation_response.py +28 -0
  1091. nemo_platform/types/secrets/platform_secret_response.py +40 -0
  1092. nemo_platform/types/secrets/platform_secret_responses_page.py +37 -0
  1093. nemo_platform/types/secrets/secret_create_params.py +39 -0
  1094. nemo_platform/types/secrets/secret_list_params.py +32 -0
  1095. nemo_platform/types/secrets/secret_update_params.py +32 -0
  1096. nemo_platform/types/shared/__init__.py +50 -0
  1097. nemo_platform/types/shared/api_endpoint_data.py +43 -0
  1098. nemo_platform/types/shared/auth_context.py +48 -0
  1099. nemo_platform/types/shared/auth_discovery_response.py +32 -0
  1100. nemo_platform/types/shared/backend_format.py +22 -0
  1101. nemo_platform/types/shared/datetime_filter.py +33 -0
  1102. nemo_platform/types/shared/delete_response.py +33 -0
  1103. nemo_platform/types/shared/error_response.py +46 -0
  1104. nemo_platform/types/shared/field_error.py +28 -0
  1105. nemo_platform/types/shared/file_storage_type.py +22 -0
  1106. nemo_platform/types/shared/fileset_metadata.py +46 -0
  1107. nemo_platform/types/shared/finetuning_type.py +48 -0
  1108. nemo_platform/types/shared/generic_sort_field.py +22 -0
  1109. nemo_platform/types/shared/http_validation_error.py +27 -0
  1110. nemo_platform/types/shared/linear_layer_spec.py +33 -0
  1111. nemo_platform/types/shared/mamba_config.py +44 -0
  1112. nemo_platform/types/shared/mo_e_config.py +41 -0
  1113. nemo_platform/types/shared/model_metadata_content.py +38 -0
  1114. nemo_platform/types/shared/model_spec.py +111 -0
  1115. nemo_platform/types/shared/oidc_discovery_response.py +42 -0
  1116. nemo_platform/types/shared/pagination_data.py +37 -0
  1117. nemo_platform/types/shared/platform_job_list_result_response.py +27 -0
  1118. nemo_platform/types/shared/platform_job_log.py +34 -0
  1119. nemo_platform/types/shared/platform_job_log_page.py +33 -0
  1120. nemo_platform/types/shared/platform_job_result_response.py +44 -0
  1121. nemo_platform/types/shared/platform_job_status.py +24 -0
  1122. nemo_platform/types/shared/platform_job_status_response.py +48 -0
  1123. nemo_platform/types/shared/platform_job_step_status_response.py +48 -0
  1124. nemo_platform/types/shared/platform_job_task_status_response.py +47 -0
  1125. nemo_platform/types/shared/prompt_data.py +47 -0
  1126. nemo_platform/types/shared/sliding_window_config.py +27 -0
  1127. nemo_platform/types/shared/tool_call_config.py +46 -0
  1128. nemo_platform/types/shared/tool_calling_metadata_content.py +48 -0
  1129. nemo_platform/types/shared/validation_error.py +34 -0
  1130. nemo_platform/types/shared_params/__init__.py +33 -0
  1131. nemo_platform/types/shared_params/api_endpoint_data.py +38 -0
  1132. nemo_platform/types/shared_params/backend_format.py +24 -0
  1133. nemo_platform/types/shared_params/datetime_filter.py +34 -0
  1134. nemo_platform/types/shared_params/file_storage_type.py +24 -0
  1135. nemo_platform/types/shared_params/finetuning_type.py +50 -0
  1136. nemo_platform/types/shared_params/generic_sort_field.py +24 -0
  1137. nemo_platform/types/shared_params/linear_layer_spec.py +35 -0
  1138. nemo_platform/types/shared_params/mamba_config.py +44 -0
  1139. nemo_platform/types/shared_params/mo_e_config.py +41 -0
  1140. nemo_platform/types/shared_params/model_metadata_content.py +39 -0
  1141. nemo_platform/types/shared_params/model_spec.py +113 -0
  1142. nemo_platform/types/shared_params/platform_job_status.py +26 -0
  1143. nemo_platform/types/shared_params/prompt_data.py +48 -0
  1144. nemo_platform/types/shared_params/sliding_window_config.py +29 -0
  1145. nemo_platform/types/shared_params/tool_call_config.py +46 -0
  1146. nemo_platform/types/shared_params/tool_calling_metadata_content.py +48 -0
  1147. nemo_platform/types/workspaces/__init__.py +24 -0
  1148. nemo_platform/types/workspaces/workspace.py +48 -0
  1149. nemo_platform/types/workspaces/workspace_create_params.py +41 -0
  1150. nemo_platform/types/workspaces/workspace_list_params.py +47 -0
  1151. nemo_platform/types/workspaces/workspace_update_params.py +27 -0
  1152. nemo_platform/types/workspaces/workspaces_page.py +37 -0
  1153. nemo_platform/ui/__init__.py +15 -0
  1154. nemo_platform/ui/output.py +109 -0
  1155. nemo_platform/ui/prompts.py +678 -0
  1156. nemo_platform_plugin/.agents/skills/creating-a-plugin/SKILL.md +275 -0
  1157. nemo_platform_plugin/.agents/skills/plugin-config/SKILL.md +168 -0
  1158. nemo_platform_plugin/.agents/skills/plugin-controller/SKILL.md +320 -0
  1159. nemo_platform_plugin/.agents/skills/plugin-entities/SKILL.md +290 -0
  1160. nemo_platform_plugin/.agents/skills/plugin-function/SKILL.md +292 -0
  1161. nemo_platform_plugin/.agents/skills/plugin-inference-middleware/SKILL.md +346 -0
  1162. nemo_platform_plugin/.agents/skills/plugin-job/SKILL.md +247 -0
  1163. nemo_platform_plugin/.agents/skills/plugin-platform-services/SKILL.md +239 -0
  1164. nemo_platform_plugin/.agents/skills/plugin-platform-services/services-reference.md +192 -0
  1165. nemo_platform_plugin/.agents/skills/plugin-service/SKILL.md +181 -0
  1166. nemo_platform_plugin/.agents/skills/plugin-service/crud-example.md +353 -0
  1167. nemo_platform_plugin/.agents/skills/plugin-testing/SKILL.md +206 -0
  1168. nemo_platform_plugin/README.md +43 -0
  1169. nemo_platform_plugin/_base.py +53 -0
  1170. nemo_platform_plugin/_spec_flags.py +573 -0
  1171. nemo_platform_plugin/api/filter.py +189 -0
  1172. nemo_platform_plugin/api/parsed_filter.py +288 -0
  1173. nemo_platform_plugin/api/text_filter.py +291 -0
  1174. nemo_platform_plugin/cli.py +152 -0
  1175. nemo_platform_plugin/cli_errors.py +232 -0
  1176. nemo_platform_plugin/cli_renderer.py +92 -0
  1177. nemo_platform_plugin/commands.py +1433 -0
  1178. nemo_platform_plugin/config.py +844 -0
  1179. nemo_platform_plugin/controller.py +148 -0
  1180. nemo_platform_plugin/dependencies.py +64 -0
  1181. nemo_platform_plugin/discovery.py +484 -0
  1182. nemo_platform_plugin/docs/ARCHITECTURE.md +160 -0
  1183. nemo_platform_plugin/docs/CONFIG.md +151 -0
  1184. nemo_platform_plugin/docs/CONTROLLER.md +209 -0
  1185. nemo_platform_plugin/docs/ENTITY.md +186 -0
  1186. nemo_platform_plugin/docs/INFERENCE_MIDDLEWARE.md +408 -0
  1187. nemo_platform_plugin/docs/JOB.md +237 -0
  1188. nemo_platform_plugin/docs/QUICKSTART.md +306 -0
  1189. nemo_platform_plugin/docs/SERVICE.md +302 -0
  1190. nemo_platform_plugin/entities.py +793 -0
  1191. nemo_platform_plugin/entity.py +79 -0
  1192. nemo_platform_plugin/entity_client.py +54 -0
  1193. nemo_platform_plugin/filter_ops.py +169 -0
  1194. nemo_platform_plugin/function.py +299 -0
  1195. nemo_platform_plugin/function_context.py +61 -0
  1196. nemo_platform_plugin/functions/frames.py +69 -0
  1197. nemo_platform_plugin/functions/routes.py +454 -0
  1198. nemo_platform_plugin/inference_middleware.py +1191 -0
  1199. nemo_platform_plugin/interface.py +28 -0
  1200. nemo_platform_plugin/job.py +370 -0
  1201. nemo_platform_plugin/job_context.py +86 -0
  1202. nemo_platform_plugin/job_results.py +209 -0
  1203. nemo_platform_plugin/jobs/_cli_options.py +204 -0
  1204. nemo_platform_plugin/jobs/api_factory.py +1178 -0
  1205. nemo_platform_plugin/jobs/constants.py +27 -0
  1206. nemo_platform_plugin/jobs/docker.py +76 -0
  1207. nemo_platform_plugin/jobs/exceptions.py +8 -0
  1208. nemo_platform_plugin/jobs/file_manager.py +238 -0
  1209. nemo_platform_plugin/jobs/openapi_utils.py +174 -0
  1210. nemo_platform_plugin/jobs/profile.py +110 -0
  1211. nemo_platform_plugin/jobs/result_manager.py +291 -0
  1212. nemo_platform_plugin/jobs/routes.py +297 -0
  1213. nemo_platform_plugin/jobs/schemas.py +174 -0
  1214. nemo_platform_plugin/refs.py +154 -0
  1215. nemo_platform_plugin/run_dependencies.py +137 -0
  1216. nemo_platform_plugin/scheduler.py +537 -0
  1217. nemo_platform_plugin/schema.py +216 -0
  1218. nemo_platform_plugin/sdk.py +34 -0
  1219. nemo_platform_plugin/seed.py +71 -0
  1220. nemo_platform_plugin/service.py +130 -0
  1221. nemo_platform_plugin/tasks/dispatcher.py +226 -0
  1222. nemo_platform_plugin-0.1.0.dist-info/METADATA +88 -0
  1223. nemo_platform_plugin-0.1.0.dist-info/RECORD +1224 -0
  1224. nemo_platform_plugin-0.1.0.dist-info/WHEEL +4 -0
@@ -0,0 +1,2146 @@
1
+ # SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
2
+ # SPDX-License-Identifier: Apache-2.0
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+
16
+ from __future__ import annotations
17
+
18
+ import sys
19
+ import json
20
+ import time
21
+ import uuid
22
+ import email
23
+ import asyncio
24
+ import inspect
25
+ import logging
26
+ import platform
27
+ import warnings
28
+ import email.utils
29
+ from types import TracebackType
30
+ from random import random
31
+ from typing import (
32
+ TYPE_CHECKING,
33
+ Any,
34
+ Dict,
35
+ Type,
36
+ Union,
37
+ Generic,
38
+ Mapping,
39
+ TypeVar,
40
+ Iterable,
41
+ Iterator,
42
+ Optional,
43
+ Generator,
44
+ AsyncIterator,
45
+ cast,
46
+ overload,
47
+ )
48
+ from typing_extensions import Literal, override, get_origin
49
+
50
+ import anyio
51
+ import httpx
52
+ import distro
53
+ import pydantic
54
+ from httpx import URL
55
+ from pydantic import PrivateAttr
56
+
57
+ from . import _exceptions
58
+ from ._qs import Querystring
59
+ from ._files import to_httpx_files, async_to_httpx_files
60
+ from ._types import (
61
+ Body,
62
+ Omit,
63
+ Query,
64
+ Headers,
65
+ Timeout,
66
+ NotGiven,
67
+ ResponseT,
68
+ AnyMapping,
69
+ PostParser,
70
+ BinaryTypes,
71
+ RequestFiles,
72
+ HttpxSendArgs,
73
+ RequestOptions,
74
+ AsyncBinaryTypes,
75
+ HttpxRequestFiles,
76
+ ModelBuilderProtocol,
77
+ not_given,
78
+ )
79
+ from ._utils import is_dict, is_list, asyncify, is_given, lru_cache, is_mapping
80
+ from ._compat import PYDANTIC_V1, model_copy, model_dump
81
+ from ._models import GenericModel, FinalRequestOptions, validate_type, construct_type
82
+ from ._response import (
83
+ APIResponse,
84
+ BaseAPIResponse,
85
+ AsyncAPIResponse,
86
+ extract_response_type,
87
+ )
88
+ from ._constants import (
89
+ DEFAULT_TIMEOUT,
90
+ MAX_RETRY_DELAY,
91
+ DEFAULT_MAX_RETRIES,
92
+ INITIAL_RETRY_DELAY,
93
+ RAW_RESPONSE_HEADER,
94
+ OVERRIDE_CAST_TO_HEADER,
95
+ DEFAULT_CONNECTION_LIMITS,
96
+ )
97
+ from ._streaming import Stream, SSEDecoder, AsyncStream, SSEBytesDecoder
98
+ from ._exceptions import (
99
+ APIStatusError,
100
+ APITimeoutError,
101
+ APIConnectionError,
102
+ APIResponseValidationError,
103
+ )
104
+ from ._utils._json import openapi_dumps
105
+
106
+ log: logging.Logger = logging.getLogger(__name__)
107
+
108
+ # TODO: make base page type vars covariant
109
+ SyncPageT = TypeVar("SyncPageT", bound="BaseSyncPage[Any]")
110
+ AsyncPageT = TypeVar("AsyncPageT", bound="BaseAsyncPage[Any]")
111
+
112
+
113
+ _T = TypeVar("_T")
114
+ _T_co = TypeVar("_T_co", covariant=True)
115
+
116
+ _StreamT = TypeVar("_StreamT", bound=Stream[Any])
117
+ _AsyncStreamT = TypeVar("_AsyncStreamT", bound=AsyncStream[Any])
118
+
119
+ if TYPE_CHECKING:
120
+ from httpx._config import (
121
+ DEFAULT_TIMEOUT_CONFIG, # pyright: ignore[reportPrivateImportUsage]
122
+ )
123
+
124
+ HTTPX_DEFAULT_TIMEOUT = DEFAULT_TIMEOUT_CONFIG
125
+ else:
126
+ try:
127
+ from httpx._config import DEFAULT_TIMEOUT_CONFIG as HTTPX_DEFAULT_TIMEOUT
128
+ except ImportError:
129
+ # taken from https://github.com/encode/httpx/blob/3ba5fe0d7ac70222590e759c31442b1cab263791/httpx/_config.py#L366
130
+ HTTPX_DEFAULT_TIMEOUT = Timeout(5.0)
131
+
132
+
133
+ class PageInfo:
134
+ """Stores the necessary information to build the request to retrieve the next page.
135
+
136
+ Either `url` or `params` must be set.
137
+ """
138
+
139
+ url: URL | NotGiven
140
+ params: Query | NotGiven
141
+ json: Body | NotGiven
142
+
143
+ @overload
144
+ def __init__(
145
+ self,
146
+ *,
147
+ url: URL,
148
+ ) -> None: ...
149
+
150
+ @overload
151
+ def __init__(
152
+ self,
153
+ *,
154
+ params: Query,
155
+ ) -> None: ...
156
+
157
+ @overload
158
+ def __init__(
159
+ self,
160
+ *,
161
+ json: Body,
162
+ ) -> None: ...
163
+
164
+ def __init__(
165
+ self,
166
+ *,
167
+ url: URL | NotGiven = not_given,
168
+ json: Body | NotGiven = not_given,
169
+ params: Query | NotGiven = not_given,
170
+ ) -> None:
171
+ self.url = url
172
+ self.json = json
173
+ self.params = params
174
+
175
+ @override
176
+ def __repr__(self) -> str:
177
+ if self.url:
178
+ return f"{self.__class__.__name__}(url={self.url})"
179
+ if self.json:
180
+ return f"{self.__class__.__name__}(json={self.json})"
181
+ return f"{self.__class__.__name__}(params={self.params})"
182
+
183
+
184
+ class BasePage(GenericModel, Generic[_T]):
185
+ """
186
+ Defines the core interface for pagination.
187
+
188
+ Type Args:
189
+ ModelT: The pydantic model that represents an item in the response.
190
+
191
+ Methods:
192
+ has_next_page(): Check if there is another page available
193
+ next_page_info(): Get the necessary information to make a request for the next page
194
+ """
195
+
196
+ _options: FinalRequestOptions = PrivateAttr()
197
+ _model: Type[_T] = PrivateAttr()
198
+
199
+ def has_next_page(self) -> bool:
200
+ items = self._get_page_items()
201
+ if not items:
202
+ return False
203
+ return self.next_page_info() is not None
204
+
205
+ def next_page_info(self) -> Optional[PageInfo]: ...
206
+
207
+ def _get_page_items(self) -> Iterable[_T]: # type: ignore[empty-body]
208
+ ...
209
+
210
+ def _params_from_url(self, url: URL) -> httpx.QueryParams:
211
+ # TODO: do we have to preprocess params here?
212
+ return httpx.QueryParams(cast(Any, self._options.params)).merge(url.params)
213
+
214
+ def _info_to_options(self, info: PageInfo) -> FinalRequestOptions:
215
+ options = model_copy(self._options)
216
+ options._strip_raw_response_header()
217
+
218
+ if not isinstance(info.params, NotGiven):
219
+ options.params = {**options.params, **info.params}
220
+ return options
221
+
222
+ if not isinstance(info.url, NotGiven):
223
+ params = self._params_from_url(info.url)
224
+ url = info.url.copy_with(params=params)
225
+ options.params = dict(url.params)
226
+ options.url = str(url)
227
+ return options
228
+
229
+ if not isinstance(info.json, NotGiven):
230
+ if not is_mapping(info.json):
231
+ raise TypeError("Pagination is only supported with mappings")
232
+
233
+ if not options.json_data:
234
+ options.json_data = {**info.json}
235
+ else:
236
+ if not is_mapping(options.json_data):
237
+ raise TypeError("Pagination is only supported with mappings")
238
+
239
+ options.json_data = {**options.json_data, **info.json}
240
+ return options
241
+
242
+ raise ValueError("Unexpected PageInfo state")
243
+
244
+
245
+ class BaseSyncPage(BasePage[_T], Generic[_T]):
246
+ _client: SyncAPIClient = pydantic.PrivateAttr()
247
+
248
+ def _set_private_attributes(
249
+ self,
250
+ client: SyncAPIClient,
251
+ model: Type[_T],
252
+ options: FinalRequestOptions,
253
+ ) -> None:
254
+ if (not PYDANTIC_V1) and getattr(self, "__pydantic_private__", None) is None:
255
+ self.__pydantic_private__ = {}
256
+
257
+ self._model = model
258
+ self._client = client
259
+ self._options = options
260
+
261
+ # Pydantic uses a custom `__iter__` method to support casting BaseModels
262
+ # to dictionaries. e.g. dict(model).
263
+ # As we want to support `for item in page`, this is inherently incompatible
264
+ # with the default pydantic behaviour. It is not possible to support both
265
+ # use cases at once. Fortunately, this is not a big deal as all other pydantic
266
+ # methods should continue to work as expected as there is an alternative method
267
+ # to cast a model to a dictionary, model.dict(), which is used internally
268
+ # by pydantic.
269
+ def __iter__(self) -> Iterator[_T]: # type: ignore
270
+ for page in self.iter_pages():
271
+ for item in page._get_page_items():
272
+ yield item
273
+
274
+ def iter_pages(self: SyncPageT) -> Iterator[SyncPageT]:
275
+ page = self
276
+ while True:
277
+ yield page
278
+ if page.has_next_page():
279
+ page = page.get_next_page()
280
+ else:
281
+ return
282
+
283
+ def get_next_page(self: SyncPageT) -> SyncPageT:
284
+ info = self.next_page_info()
285
+ if not info:
286
+ raise RuntimeError(
287
+ "No next page expected; please check `.has_next_page()` before calling `.get_next_page()`."
288
+ )
289
+
290
+ options = self._info_to_options(info)
291
+ return self._client._request_api_list(self._model, page=self.__class__, options=options)
292
+
293
+
294
+ class AsyncPaginator(Generic[_T, AsyncPageT]):
295
+ def __init__(
296
+ self,
297
+ client: AsyncAPIClient,
298
+ options: FinalRequestOptions,
299
+ page_cls: Type[AsyncPageT],
300
+ model: Type[_T],
301
+ ) -> None:
302
+ self._model = model
303
+ self._client = client
304
+ self._options = options
305
+ self._page_cls = page_cls
306
+
307
+ def __await__(self) -> Generator[Any, None, AsyncPageT]:
308
+ return self._get_page().__await__()
309
+
310
+ async def _get_page(self) -> AsyncPageT:
311
+ def _parser(resp: AsyncPageT) -> AsyncPageT:
312
+ resp._set_private_attributes(
313
+ model=self._model,
314
+ options=self._options,
315
+ client=self._client,
316
+ )
317
+ return resp
318
+
319
+ self._options.post_parser = _parser
320
+
321
+ return await self._client.request(self._page_cls, self._options)
322
+
323
+ async def __aiter__(self) -> AsyncIterator[_T]:
324
+ # https://github.com/microsoft/pyright/issues/3464
325
+ page = cast(
326
+ AsyncPageT,
327
+ await self, # type: ignore
328
+ )
329
+ async for item in page:
330
+ yield item
331
+
332
+
333
+ class BaseAsyncPage(BasePage[_T], Generic[_T]):
334
+ _client: AsyncAPIClient = pydantic.PrivateAttr()
335
+
336
+ def _set_private_attributes(
337
+ self,
338
+ model: Type[_T],
339
+ client: AsyncAPIClient,
340
+ options: FinalRequestOptions,
341
+ ) -> None:
342
+ if (not PYDANTIC_V1) and getattr(self, "__pydantic_private__", None) is None:
343
+ self.__pydantic_private__ = {}
344
+
345
+ self._model = model
346
+ self._client = client
347
+ self._options = options
348
+
349
+ async def __aiter__(self) -> AsyncIterator[_T]:
350
+ async for page in self.iter_pages():
351
+ for item in page._get_page_items():
352
+ yield item
353
+
354
+ async def iter_pages(self: AsyncPageT) -> AsyncIterator[AsyncPageT]:
355
+ page = self
356
+ while True:
357
+ yield page
358
+ if page.has_next_page():
359
+ page = await page.get_next_page()
360
+ else:
361
+ return
362
+
363
+ async def get_next_page(self: AsyncPageT) -> AsyncPageT:
364
+ info = self.next_page_info()
365
+ if not info:
366
+ raise RuntimeError(
367
+ "No next page expected; please check `.has_next_page()` before calling `.get_next_page()`."
368
+ )
369
+
370
+ options = self._info_to_options(info)
371
+ return await self._client._request_api_list(self._model, page=self.__class__, options=options)
372
+
373
+
374
+ _HttpxClientT = TypeVar("_HttpxClientT", bound=Union[httpx.Client, httpx.AsyncClient])
375
+ _DefaultStreamT = TypeVar("_DefaultStreamT", bound=Union[Stream[Any], AsyncStream[Any]])
376
+
377
+
378
+ class BaseClient(Generic[_HttpxClientT, _DefaultStreamT]):
379
+ _client: _HttpxClientT
380
+ _version: str
381
+ _base_url: URL
382
+ max_retries: int
383
+ timeout: Union[float, Timeout, None]
384
+ _strict_response_validation: bool
385
+ _idempotency_header: str | None
386
+ _default_stream_cls: type[_DefaultStreamT] | None = None
387
+
388
+ def __init__(
389
+ self,
390
+ *,
391
+ version: str,
392
+ base_url: str | URL,
393
+ _strict_response_validation: bool,
394
+ max_retries: int = DEFAULT_MAX_RETRIES,
395
+ timeout: float | Timeout | None = DEFAULT_TIMEOUT,
396
+ custom_headers: Mapping[str, str] | None = None,
397
+ custom_query: Mapping[str, object] | None = None,
398
+ ) -> None:
399
+ self._version = version
400
+ self._base_url = self._enforce_trailing_slash(URL(base_url))
401
+ self.max_retries = max_retries
402
+ self.timeout = timeout
403
+ self._custom_headers = custom_headers or {}
404
+ self._custom_query = custom_query or {}
405
+ self._strict_response_validation = _strict_response_validation
406
+ self._idempotency_header = None
407
+ self._platform: Platform | None = None
408
+
409
+ if max_retries is None: # pyright: ignore[reportUnnecessaryComparison]
410
+ raise TypeError(
411
+ "max_retries cannot be None. If you want to disable retries, pass `0`; if you want unlimited retries, pass `math.inf` or a very high number; if you want the default behavior, pass `nemo_platform.DEFAULT_MAX_RETRIES`"
412
+ )
413
+
414
+ def _enforce_trailing_slash(self, url: URL) -> URL:
415
+ if url.raw_path.endswith(b"/"):
416
+ return url
417
+ return url.copy_with(raw_path=url.raw_path + b"/")
418
+
419
+ def _make_status_error_from_response(
420
+ self,
421
+ response: httpx.Response,
422
+ ) -> APIStatusError:
423
+ if response.is_closed and not response.is_stream_consumed:
424
+ # We can't read the response body as it has been closed
425
+ # before it was read. This can happen if an event hook
426
+ # raises a status error.
427
+ body = None
428
+ err_msg = f"Error code: {response.status_code}"
429
+ else:
430
+ err_text = response.text.strip()
431
+ body = err_text
432
+
433
+ try:
434
+ body = json.loads(err_text)
435
+ err_msg = f"Error code: {response.status_code} - {body}"
436
+ except Exception:
437
+ err_msg = err_text or f"Error code: {response.status_code}"
438
+
439
+ return self._make_status_error(err_msg, body=body, response=response)
440
+
441
+ def _make_status_error(
442
+ self,
443
+ err_msg: str,
444
+ *,
445
+ body: object,
446
+ response: httpx.Response,
447
+ ) -> _exceptions.APIStatusError:
448
+ raise NotImplementedError()
449
+
450
+ def _build_headers(self, options: FinalRequestOptions, *, retries_taken: int = 0) -> httpx.Headers:
451
+ custom_headers = options.headers or {}
452
+ headers_dict = _merge_mappings(self.default_headers, custom_headers)
453
+ self._validate_headers(headers_dict, custom_headers)
454
+
455
+ # headers are case-insensitive while dictionaries are not.
456
+ headers = httpx.Headers(headers_dict)
457
+
458
+ idempotency_header = self._idempotency_header
459
+ if idempotency_header and options.idempotency_key and idempotency_header not in headers:
460
+ headers[idempotency_header] = options.idempotency_key
461
+
462
+ # Don't set these headers if they were already set or removed by the caller. We check
463
+ # `custom_headers`, which can contain `Omit()`, instead of `headers` to account for the removal case.
464
+ lower_custom_headers = [header.lower() for header in custom_headers]
465
+ if "x-stainless-retry-count" not in lower_custom_headers:
466
+ headers["x-stainless-retry-count"] = str(retries_taken)
467
+ if "x-stainless-read-timeout" not in lower_custom_headers:
468
+ timeout = self.timeout if isinstance(options.timeout, NotGiven) else options.timeout
469
+ if isinstance(timeout, Timeout):
470
+ timeout = timeout.read
471
+ if timeout is not None:
472
+ headers["x-stainless-read-timeout"] = str(timeout)
473
+
474
+ return headers
475
+
476
+ def _prepare_url(self, url: str) -> URL:
477
+ """
478
+ Merge a URL argument together with any 'base_url' on the client,
479
+ to create the URL used for the outgoing request.
480
+ """
481
+ # Copied from httpx's `_merge_url` method.
482
+ merge_url = URL(url)
483
+ if merge_url.is_relative_url:
484
+ merge_raw_path = self.base_url.raw_path + merge_url.raw_path.lstrip(b"/")
485
+ return self.base_url.copy_with(raw_path=merge_raw_path)
486
+
487
+ return merge_url
488
+
489
+ def _make_sse_decoder(self) -> SSEDecoder | SSEBytesDecoder:
490
+ return SSEDecoder()
491
+
492
+ def _build_request(
493
+ self,
494
+ options: FinalRequestOptions,
495
+ *,
496
+ retries_taken: int = 0,
497
+ ) -> httpx.Request:
498
+ if log.isEnabledFor(logging.DEBUG):
499
+ log.debug(
500
+ "Request options: %s",
501
+ model_dump(
502
+ options,
503
+ exclude_unset=True,
504
+ # Pydantic v1 can't dump every type we support in content, so we exclude it for now.
505
+ exclude={
506
+ "content",
507
+ }
508
+ if PYDANTIC_V1
509
+ else {},
510
+ ),
511
+ )
512
+ kwargs: dict[str, Any] = {}
513
+
514
+ json_data = options.json_data
515
+ if options.extra_json is not None:
516
+ if json_data is None:
517
+ json_data = cast(Body, options.extra_json)
518
+ elif is_mapping(json_data):
519
+ json_data = _merge_mappings(json_data, options.extra_json)
520
+ else:
521
+ raise RuntimeError(f"Unexpected JSON data type, {type(json_data)}, cannot merge with `extra_body`")
522
+
523
+ headers = self._build_headers(options, retries_taken=retries_taken)
524
+ params = _merge_mappings(self.default_query, options.params)
525
+ content_type = headers.get("Content-Type")
526
+ files = options.files
527
+
528
+ # If the given Content-Type header is multipart/form-data then it
529
+ # has to be removed so that httpx can generate the header with
530
+ # additional information for us as it has to be in this form
531
+ # for the server to be able to correctly parse the request:
532
+ # multipart/form-data; boundary=---abc--
533
+ if content_type is not None and content_type.startswith("multipart/form-data"):
534
+ if "boundary" not in content_type:
535
+ # only remove the header if the boundary hasn't been explicitly set
536
+ # as the caller doesn't want httpx to come up with their own boundary
537
+ headers.pop("Content-Type")
538
+
539
+ # As we are now sending multipart/form-data instead of application/json
540
+ # we need to tell httpx to use it, https://www.python-httpx.org/advanced/clients/#multipart-file-encoding
541
+ if json_data:
542
+ if not is_dict(json_data):
543
+ raise TypeError(
544
+ f"Expected query input to be a dictionary for multipart requests but got {type(json_data)} instead."
545
+ )
546
+ kwargs["data"] = self._serialize_multipartform(json_data)
547
+
548
+ # httpx determines whether or not to send a "multipart/form-data"
549
+ # request based on the truthiness of the "files" argument.
550
+ # This gets around that issue by generating a dict value that
551
+ # evaluates to true.
552
+ #
553
+ # https://github.com/encode/httpx/discussions/2399#discussioncomment-3814186
554
+ if not files:
555
+ files = cast(HttpxRequestFiles, ForceMultipartDict())
556
+
557
+ prepared_url = self._prepare_url(options.url)
558
+ # preserve hard-coded query params from the url
559
+ if params and prepared_url.query:
560
+ params = {**dict(prepared_url.params.items()), **params}
561
+ prepared_url = prepared_url.copy_with(raw_path=prepared_url.raw_path.split(b"?", 1)[0])
562
+ if "_" in prepared_url.host:
563
+ # work around https://github.com/encode/httpx/discussions/2880
564
+ kwargs["extensions"] = {"sni_hostname": prepared_url.host.replace("_", "-")}
565
+
566
+ is_body_allowed = options.method.lower() != "get"
567
+
568
+ if is_body_allowed:
569
+ if options.content is not None and json_data is not None:
570
+ raise TypeError("Passing both `content` and `json_data` is not supported")
571
+ if options.content is not None and files is not None:
572
+ raise TypeError("Passing both `content` and `files` is not supported")
573
+ if options.content is not None:
574
+ kwargs["content"] = options.content
575
+ elif isinstance(json_data, bytes):
576
+ kwargs["content"] = json_data
577
+ elif not files:
578
+ # Don't set content when JSON is sent as multipart/form-data,
579
+ # since httpx's content param overrides other body arguments
580
+ kwargs["content"] = openapi_dumps(json_data) if is_given(json_data) and json_data is not None else None
581
+ kwargs["files"] = files
582
+ else:
583
+ headers.pop("Content-Type", None)
584
+ kwargs.pop("data", None)
585
+
586
+ # TODO: report this error to httpx
587
+ return self._client.build_request( # pyright: ignore[reportUnknownMemberType]
588
+ headers=headers,
589
+ timeout=self.timeout if isinstance(options.timeout, NotGiven) else options.timeout,
590
+ method=options.method,
591
+ url=prepared_url,
592
+ # the `Query` type that we use is incompatible with qs'
593
+ # `Params` type as it needs to be typed as `Mapping[str, object]`
594
+ # so that passing a `TypedDict` doesn't cause an error.
595
+ # https://github.com/microsoft/pyright/issues/3526#event-6715453066
596
+ params=self.qs.stringify(cast(Mapping[str, Any], params)) if params else None,
597
+ **kwargs,
598
+ )
599
+
600
+ def _serialize_multipartform(self, data: Mapping[object, object]) -> dict[str, object]:
601
+ items = self.qs.stringify_items(
602
+ # TODO: type ignore is required as stringify_items is well typed but we can't be
603
+ # well typed without heavy validation.
604
+ data, # type: ignore
605
+ array_format="brackets",
606
+ )
607
+ serialized: dict[str, object] = {}
608
+ for key, value in items:
609
+ existing = serialized.get(key)
610
+
611
+ if not existing:
612
+ serialized[key] = value
613
+ continue
614
+
615
+ # If a value has already been set for this key then that
616
+ # means we're sending data like `array[]=[1, 2, 3]` and we
617
+ # need to tell httpx that we want to send multiple values with
618
+ # the same key which is done by using a list or a tuple.
619
+ #
620
+ # Note: 2d arrays should never result in the same key at both
621
+ # levels so it's safe to assume that if the value is a list,
622
+ # it was because we changed it to be a list.
623
+ if is_list(existing):
624
+ existing.append(value)
625
+ else:
626
+ serialized[key] = [existing, value]
627
+
628
+ return serialized
629
+
630
+ def _maybe_override_cast_to(self, cast_to: type[ResponseT], options: FinalRequestOptions) -> type[ResponseT]:
631
+ if not is_given(options.headers):
632
+ return cast_to
633
+
634
+ # make a copy of the headers so we don't mutate user-input
635
+ headers = dict(options.headers)
636
+
637
+ # we internally support defining a temporary header to override the
638
+ # default `cast_to` type for use with `.with_raw_response` and `.with_streaming_response`
639
+ # see _response.py for implementation details
640
+ override_cast_to = headers.pop(OVERRIDE_CAST_TO_HEADER, not_given)
641
+ if is_given(override_cast_to):
642
+ options.headers = headers
643
+ return cast(Type[ResponseT], override_cast_to)
644
+
645
+ return cast_to
646
+
647
+ def _should_stream_response_body(self, request: httpx.Request) -> bool:
648
+ return request.headers.get(RAW_RESPONSE_HEADER) == "stream" # type: ignore[no-any-return]
649
+
650
+ def _process_response_data(
651
+ self,
652
+ *,
653
+ data: object,
654
+ cast_to: type[ResponseT],
655
+ response: httpx.Response,
656
+ ) -> ResponseT:
657
+ if data is None:
658
+ return cast(ResponseT, None)
659
+
660
+ if cast_to is object:
661
+ return cast(ResponseT, data)
662
+
663
+ try:
664
+ if inspect.isclass(cast_to) and issubclass(cast_to, ModelBuilderProtocol):
665
+ return cast(ResponseT, cast_to.build(response=response, data=data))
666
+
667
+ if self._strict_response_validation:
668
+ return cast(ResponseT, validate_type(type_=cast_to, value=data))
669
+
670
+ return cast(ResponseT, construct_type(type_=cast_to, value=data))
671
+ except pydantic.ValidationError as err:
672
+ raise APIResponseValidationError(response=response, body=data) from err
673
+
674
+ @property
675
+ def qs(self) -> Querystring:
676
+ return Querystring()
677
+
678
+ @property
679
+ def custom_auth(self) -> httpx.Auth | None:
680
+ return None
681
+
682
+ @property
683
+ def auth_headers(self) -> dict[str, str]:
684
+ return {}
685
+
686
+ @property
687
+ def default_headers(self) -> dict[str, str | Omit]:
688
+ return {
689
+ "Accept": "application/json",
690
+ "Content-Type": "application/json",
691
+ "User-Agent": self.user_agent,
692
+ **self.platform_headers(),
693
+ **self.auth_headers,
694
+ **self._custom_headers,
695
+ }
696
+
697
+ @property
698
+ def default_query(self) -> dict[str, object]:
699
+ return {
700
+ **self._custom_query,
701
+ }
702
+
703
+ def _validate_headers(
704
+ self,
705
+ headers: Headers, # noqa: ARG002
706
+ custom_headers: Headers, # noqa: ARG002
707
+ ) -> None:
708
+ """Validate the given default headers and custom headers.
709
+
710
+ Does nothing by default.
711
+ """
712
+ return
713
+
714
+ @property
715
+ def user_agent(self) -> str:
716
+ return f"{self.__class__.__name__}/Python {self._version}"
717
+
718
+ @property
719
+ def base_url(self) -> URL:
720
+ return self._base_url
721
+
722
+ @base_url.setter
723
+ def base_url(self, url: URL | str) -> None:
724
+ self._base_url = self._enforce_trailing_slash(url if isinstance(url, URL) else URL(url))
725
+
726
+ def platform_headers(self) -> Dict[str, str]:
727
+ # the actual implementation is in a separate `lru_cache` decorated
728
+ # function because adding `lru_cache` to methods will leak memory
729
+ # https://github.com/python/cpython/issues/88476
730
+ return platform_headers(self._version, platform=self._platform)
731
+
732
+ def _parse_retry_after_header(self, response_headers: Optional[httpx.Headers] = None) -> float | None:
733
+ """Returns a float of the number of seconds (not milliseconds) to wait after retrying, or None if unspecified.
734
+
735
+ About the Retry-After header: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Retry-After
736
+ See also https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Retry-After#syntax
737
+ """
738
+ if response_headers is None:
739
+ return None
740
+
741
+ # First, try the non-standard `retry-after-ms` header for milliseconds,
742
+ # which is more precise than integer-seconds `retry-after`
743
+ try:
744
+ retry_ms_header = response_headers.get("retry-after-ms", None)
745
+ return float(retry_ms_header) / 1000
746
+ except (TypeError, ValueError):
747
+ pass
748
+
749
+ # Next, try parsing `retry-after` header as seconds (allowing nonstandard floats).
750
+ retry_header = response_headers.get("retry-after")
751
+ try:
752
+ # note: the spec indicates that this should only ever be an integer
753
+ # but if someone sends a float there's no reason for us to not respect it
754
+ return float(retry_header)
755
+ except (TypeError, ValueError):
756
+ pass
757
+
758
+ # Last, try parsing `retry-after` as a date.
759
+ retry_date_tuple = email.utils.parsedate_tz(retry_header)
760
+ if retry_date_tuple is None:
761
+ return None
762
+
763
+ retry_date = email.utils.mktime_tz(retry_date_tuple)
764
+ return float(retry_date - time.time())
765
+
766
+ def _calculate_retry_timeout(
767
+ self,
768
+ remaining_retries: int,
769
+ options: FinalRequestOptions,
770
+ response_headers: Optional[httpx.Headers] = None,
771
+ ) -> float:
772
+ max_retries = options.get_max_retries(self.max_retries)
773
+
774
+ # If the API asks us to wait a certain amount of time (and it's a reasonable amount), just do what it says.
775
+ retry_after = self._parse_retry_after_header(response_headers)
776
+ if retry_after is not None and 0 < retry_after <= 60:
777
+ return retry_after
778
+
779
+ # Also cap retry count to 1000 to avoid any potential overflows with `pow`
780
+ nb_retries = min(max_retries - remaining_retries, 1000)
781
+
782
+ # Apply exponential backoff, but not more than the max.
783
+ sleep_seconds = min(INITIAL_RETRY_DELAY * pow(2.0, nb_retries), MAX_RETRY_DELAY)
784
+
785
+ # Apply some jitter, plus-or-minus half a second.
786
+ jitter = 1 - 0.25 * random()
787
+ timeout = sleep_seconds * jitter
788
+ return timeout if timeout >= 0 else 0
789
+
790
+ def _should_retry(self, response: httpx.Response) -> bool:
791
+ # Note: this is not a standard header
792
+ should_retry_header = response.headers.get("x-should-retry")
793
+
794
+ # If the server explicitly says whether or not to retry, obey.
795
+ if should_retry_header == "true":
796
+ log.debug("Retrying as header `x-should-retry` is set to `true`")
797
+ return True
798
+ if should_retry_header == "false":
799
+ log.debug("Not retrying as header `x-should-retry` is set to `false`")
800
+ return False
801
+
802
+ # Retry on request timeouts.
803
+ if response.status_code == 408:
804
+ log.debug("Retrying due to status code %i", response.status_code)
805
+ return True
806
+
807
+ # Retry on lock timeouts.
808
+ if response.status_code == 409:
809
+ log.debug("Retrying due to status code %i", response.status_code)
810
+ return True
811
+
812
+ # Retry on rate limits.
813
+ if response.status_code == 429:
814
+ log.debug("Retrying due to status code %i", response.status_code)
815
+ return True
816
+
817
+ # Retry internal errors.
818
+ if response.status_code >= 500:
819
+ log.debug("Retrying due to status code %i", response.status_code)
820
+ return True
821
+
822
+ log.debug("Not retrying")
823
+ return False
824
+
825
+ def _idempotency_key(self) -> str:
826
+ return f"stainless-python-retry-{uuid.uuid4()}"
827
+
828
+
829
+ class _DefaultHttpxClient(httpx.Client):
830
+ def __init__(self, **kwargs: Any) -> None:
831
+ kwargs.setdefault("timeout", DEFAULT_TIMEOUT)
832
+ kwargs.setdefault("limits", DEFAULT_CONNECTION_LIMITS)
833
+ kwargs.setdefault("follow_redirects", True)
834
+ super().__init__(**kwargs)
835
+
836
+
837
+ if TYPE_CHECKING:
838
+ DefaultHttpxClient = httpx.Client
839
+ """An alias to `httpx.Client` that provides the same defaults that this SDK
840
+ uses internally.
841
+
842
+ This is useful because overriding the `http_client` with your own instance of
843
+ `httpx.Client` will result in httpx's defaults being used, not ours.
844
+ """
845
+ else:
846
+ DefaultHttpxClient = _DefaultHttpxClient
847
+
848
+
849
+ class SyncHttpxClientWrapper(DefaultHttpxClient):
850
+ def __del__(self) -> None:
851
+ if self.is_closed:
852
+ return
853
+
854
+ try:
855
+ self.close()
856
+ except Exception:
857
+ pass
858
+
859
+
860
+ class SyncAPIClient(BaseClient[httpx.Client, Stream[Any]]):
861
+ _client: httpx.Client
862
+ _default_stream_cls: type[Stream[Any]] | None = None
863
+
864
+ def __init__(
865
+ self,
866
+ *,
867
+ version: str,
868
+ base_url: str | URL,
869
+ max_retries: int = DEFAULT_MAX_RETRIES,
870
+ timeout: float | Timeout | None | NotGiven = not_given,
871
+ http_client: httpx.Client | None = None,
872
+ custom_headers: Mapping[str, str] | None = None,
873
+ custom_query: Mapping[str, object] | None = None,
874
+ _strict_response_validation: bool,
875
+ ) -> None:
876
+ if not is_given(timeout):
877
+ # if the user passed in a custom http client with a non-default
878
+ # timeout set then we use that timeout.
879
+ #
880
+ # note: there is an edge case here where the user passes in a client
881
+ # where they've explicitly set the timeout to match the default timeout
882
+ # as this check is structural, meaning that we'll think they didn't
883
+ # pass in a timeout and will ignore it
884
+ if http_client and http_client.timeout != HTTPX_DEFAULT_TIMEOUT:
885
+ timeout = http_client.timeout
886
+ else:
887
+ timeout = DEFAULT_TIMEOUT
888
+
889
+ if http_client is not None and not isinstance(http_client, httpx.Client): # pyright: ignore[reportUnnecessaryIsInstance]
890
+ raise TypeError(
891
+ f"Invalid `http_client` argument; Expected an instance of `httpx.Client` but got {type(http_client)}"
892
+ )
893
+
894
+ super().__init__(
895
+ version=version,
896
+ # cast to a valid type because mypy doesn't understand our type narrowing
897
+ timeout=cast(Timeout, timeout),
898
+ base_url=base_url,
899
+ max_retries=max_retries,
900
+ custom_query=custom_query,
901
+ custom_headers=custom_headers,
902
+ _strict_response_validation=_strict_response_validation,
903
+ )
904
+ self._client = http_client or SyncHttpxClientWrapper(
905
+ base_url=base_url,
906
+ # cast to a valid type because mypy doesn't understand our type narrowing
907
+ timeout=cast(Timeout, timeout),
908
+ )
909
+
910
+ def is_closed(self) -> bool:
911
+ return self._client.is_closed
912
+
913
+ def close(self) -> None:
914
+ """Close the underlying HTTPX client.
915
+
916
+ The client will *not* be usable after this.
917
+ """
918
+ # If an error is thrown while constructing a client, self._client
919
+ # may not be present
920
+ if hasattr(self, "_client"):
921
+ self._client.close()
922
+
923
+ def __enter__(self: _T) -> _T:
924
+ return self
925
+
926
+ def __exit__(
927
+ self,
928
+ exc_type: type[BaseException] | None,
929
+ exc: BaseException | None,
930
+ exc_tb: TracebackType | None,
931
+ ) -> None:
932
+ self.close()
933
+
934
+ def _prepare_options(
935
+ self,
936
+ options: FinalRequestOptions, # noqa: ARG002
937
+ ) -> FinalRequestOptions:
938
+ """Hook for mutating the given options"""
939
+ return options
940
+
941
+ def _prepare_request(
942
+ self,
943
+ request: httpx.Request, # noqa: ARG002
944
+ ) -> None:
945
+ """This method is used as a callback for mutating the `Request` object
946
+ after it has been constructed.
947
+ This is useful for cases where you want to add certain headers based off of
948
+ the request properties, e.g. `url`, `method` etc.
949
+ """
950
+ return None
951
+
952
+ @overload
953
+ def request(
954
+ self,
955
+ cast_to: Type[ResponseT],
956
+ options: FinalRequestOptions,
957
+ *,
958
+ stream: Literal[True],
959
+ stream_cls: Type[_StreamT],
960
+ ) -> _StreamT: ...
961
+
962
+ @overload
963
+ def request(
964
+ self,
965
+ cast_to: Type[ResponseT],
966
+ options: FinalRequestOptions,
967
+ *,
968
+ stream: Literal[False] = False,
969
+ ) -> ResponseT: ...
970
+
971
+ @overload
972
+ def request(
973
+ self,
974
+ cast_to: Type[ResponseT],
975
+ options: FinalRequestOptions,
976
+ *,
977
+ stream: bool = False,
978
+ stream_cls: Type[_StreamT] | None = None,
979
+ ) -> ResponseT | _StreamT: ...
980
+
981
+ def request(
982
+ self,
983
+ cast_to: Type[ResponseT],
984
+ options: FinalRequestOptions,
985
+ *,
986
+ stream: bool = False,
987
+ stream_cls: type[_StreamT] | None = None,
988
+ ) -> ResponseT | _StreamT:
989
+ cast_to = self._maybe_override_cast_to(cast_to, options)
990
+
991
+ # create a copy of the options we were given so that if the
992
+ # options are mutated later & we then retry, the retries are
993
+ # given the original options
994
+ input_options = model_copy(options)
995
+ if input_options.idempotency_key is None and input_options.method.lower() != "get":
996
+ # ensure the idempotency key is reused between requests
997
+ input_options.idempotency_key = self._idempotency_key()
998
+
999
+ response: httpx.Response | None = None
1000
+ max_retries = input_options.get_max_retries(self.max_retries)
1001
+
1002
+ retries_taken = 0
1003
+ for retries_taken in range(max_retries + 1):
1004
+ options = model_copy(input_options)
1005
+ options = self._prepare_options(options)
1006
+
1007
+ remaining_retries = max_retries - retries_taken
1008
+ request = self._build_request(options, retries_taken=retries_taken)
1009
+ self._prepare_request(request)
1010
+
1011
+ kwargs: HttpxSendArgs = {}
1012
+ if self.custom_auth is not None:
1013
+ kwargs["auth"] = self.custom_auth
1014
+
1015
+ if options.follow_redirects is not None:
1016
+ kwargs["follow_redirects"] = options.follow_redirects
1017
+
1018
+ log.debug("Sending HTTP Request: %s %s", request.method, request.url)
1019
+
1020
+ response = None
1021
+ try:
1022
+ response = self._client.send(
1023
+ request,
1024
+ stream=stream or self._should_stream_response_body(request=request),
1025
+ **kwargs,
1026
+ )
1027
+ except httpx.TimeoutException as err:
1028
+ log.debug("Encountered httpx.TimeoutException", exc_info=True)
1029
+
1030
+ if remaining_retries > 0:
1031
+ self._sleep_for_retry(
1032
+ retries_taken=retries_taken,
1033
+ max_retries=max_retries,
1034
+ options=input_options,
1035
+ response=None,
1036
+ )
1037
+ continue
1038
+
1039
+ log.debug("Raising timeout error")
1040
+ raise APITimeoutError(request=request) from err
1041
+ except Exception as err:
1042
+ log.debug("Encountered Exception", exc_info=True)
1043
+
1044
+ if remaining_retries > 0:
1045
+ self._sleep_for_retry(
1046
+ retries_taken=retries_taken,
1047
+ max_retries=max_retries,
1048
+ options=input_options,
1049
+ response=None,
1050
+ )
1051
+ continue
1052
+
1053
+ log.debug("Raising connection error")
1054
+ raise APIConnectionError(request=request) from err
1055
+
1056
+ log.debug(
1057
+ 'HTTP Response: %s %s "%i %s" %s',
1058
+ request.method,
1059
+ request.url,
1060
+ response.status_code,
1061
+ response.reason_phrase,
1062
+ response.headers,
1063
+ )
1064
+
1065
+ try:
1066
+ response.raise_for_status()
1067
+ except httpx.HTTPStatusError as err: # thrown on 4xx and 5xx status code
1068
+ log.debug("Encountered httpx.HTTPStatusError", exc_info=True)
1069
+
1070
+ if remaining_retries > 0 and self._should_retry(err.response):
1071
+ err.response.close()
1072
+ self._sleep_for_retry(
1073
+ retries_taken=retries_taken,
1074
+ max_retries=max_retries,
1075
+ options=input_options,
1076
+ response=response,
1077
+ )
1078
+ continue
1079
+
1080
+ # If the response is streamed then we need to explicitly read the response
1081
+ # to completion before attempting to access the response text.
1082
+ if not err.response.is_closed:
1083
+ err.response.read()
1084
+
1085
+ log.debug("Re-raising status error")
1086
+ raise self._make_status_error_from_response(err.response) from None
1087
+
1088
+ break
1089
+
1090
+ assert response is not None, "could not resolve response (should never happen)"
1091
+ return self._process_response(
1092
+ cast_to=cast_to,
1093
+ options=options,
1094
+ response=response,
1095
+ stream=stream,
1096
+ stream_cls=stream_cls,
1097
+ retries_taken=retries_taken,
1098
+ )
1099
+
1100
+ def _sleep_for_retry(
1101
+ self, *, retries_taken: int, max_retries: int, options: FinalRequestOptions, response: httpx.Response | None
1102
+ ) -> None:
1103
+ remaining_retries = max_retries - retries_taken
1104
+ if remaining_retries == 1:
1105
+ log.debug("1 retry left")
1106
+ else:
1107
+ log.debug("%i retries left", remaining_retries)
1108
+
1109
+ timeout = self._calculate_retry_timeout(remaining_retries, options, response.headers if response else None)
1110
+ log.info("Retrying request to %s in %f seconds", options.url, timeout)
1111
+
1112
+ time.sleep(timeout)
1113
+
1114
+ def _process_response(
1115
+ self,
1116
+ *,
1117
+ cast_to: Type[ResponseT],
1118
+ options: FinalRequestOptions,
1119
+ response: httpx.Response,
1120
+ stream: bool,
1121
+ stream_cls: type[Stream[Any]] | type[AsyncStream[Any]] | None,
1122
+ retries_taken: int = 0,
1123
+ ) -> ResponseT:
1124
+ origin = get_origin(cast_to) or cast_to
1125
+
1126
+ if (
1127
+ inspect.isclass(origin)
1128
+ and issubclass(origin, BaseAPIResponse)
1129
+ # we only want to actually return the custom BaseAPIResponse class if we're
1130
+ # returning the raw response, or if we're not streaming SSE, as if we're streaming
1131
+ # SSE then `cast_to` doesn't actively reflect the type we need to parse into
1132
+ and (not stream or bool(response.request.headers.get(RAW_RESPONSE_HEADER)))
1133
+ ):
1134
+ if not issubclass(origin, APIResponse):
1135
+ raise TypeError(f"API Response types must subclass {APIResponse}; Received {origin}")
1136
+
1137
+ response_cls = cast("type[BaseAPIResponse[Any]]", cast_to)
1138
+ return cast(
1139
+ ResponseT,
1140
+ response_cls(
1141
+ raw=response,
1142
+ client=self,
1143
+ cast_to=extract_response_type(response_cls),
1144
+ stream=stream,
1145
+ stream_cls=stream_cls,
1146
+ options=options,
1147
+ retries_taken=retries_taken,
1148
+ ),
1149
+ )
1150
+
1151
+ if cast_to == httpx.Response:
1152
+ return cast(ResponseT, response)
1153
+
1154
+ api_response = APIResponse(
1155
+ raw=response,
1156
+ client=self,
1157
+ cast_to=cast("type[ResponseT]", cast_to), # pyright: ignore[reportUnnecessaryCast]
1158
+ stream=stream,
1159
+ stream_cls=stream_cls,
1160
+ options=options,
1161
+ retries_taken=retries_taken,
1162
+ )
1163
+ if bool(response.request.headers.get(RAW_RESPONSE_HEADER)):
1164
+ return cast(ResponseT, api_response)
1165
+
1166
+ return api_response.parse()
1167
+
1168
+ def _request_api_list(
1169
+ self,
1170
+ model: Type[object],
1171
+ page: Type[SyncPageT],
1172
+ options: FinalRequestOptions,
1173
+ ) -> SyncPageT:
1174
+ def _parser(resp: SyncPageT) -> SyncPageT:
1175
+ resp._set_private_attributes(
1176
+ client=self,
1177
+ model=model,
1178
+ options=options,
1179
+ )
1180
+ return resp
1181
+
1182
+ options.post_parser = _parser
1183
+
1184
+ return self.request(page, options, stream=False)
1185
+
1186
+ @overload
1187
+ def get(
1188
+ self,
1189
+ path: str,
1190
+ *,
1191
+ cast_to: Type[ResponseT],
1192
+ options: RequestOptions = {},
1193
+ stream: Literal[False] = False,
1194
+ ) -> ResponseT: ...
1195
+
1196
+ @overload
1197
+ def get(
1198
+ self,
1199
+ path: str,
1200
+ *,
1201
+ cast_to: Type[ResponseT],
1202
+ options: RequestOptions = {},
1203
+ stream: Literal[True],
1204
+ stream_cls: type[_StreamT],
1205
+ ) -> _StreamT: ...
1206
+
1207
+ @overload
1208
+ def get(
1209
+ self,
1210
+ path: str,
1211
+ *,
1212
+ cast_to: Type[ResponseT],
1213
+ options: RequestOptions = {},
1214
+ stream: bool,
1215
+ stream_cls: type[_StreamT] | None = None,
1216
+ ) -> ResponseT | _StreamT: ...
1217
+
1218
+ def get(
1219
+ self,
1220
+ path: str,
1221
+ *,
1222
+ cast_to: Type[ResponseT],
1223
+ options: RequestOptions = {},
1224
+ stream: bool = False,
1225
+ stream_cls: type[_StreamT] | None = None,
1226
+ ) -> ResponseT | _StreamT:
1227
+ opts = FinalRequestOptions.construct(method="get", url=path, **options)
1228
+ # cast is required because mypy complains about returning Any even though
1229
+ # it understands the type variables
1230
+ return cast(ResponseT, self.request(cast_to, opts, stream=stream, stream_cls=stream_cls))
1231
+
1232
+ @overload
1233
+ def post(
1234
+ self,
1235
+ path: str,
1236
+ *,
1237
+ cast_to: Type[ResponseT],
1238
+ body: Body | None = None,
1239
+ content: BinaryTypes | None = None,
1240
+ options: RequestOptions = {},
1241
+ files: RequestFiles | None = None,
1242
+ stream: Literal[False] = False,
1243
+ ) -> ResponseT: ...
1244
+
1245
+ @overload
1246
+ def post(
1247
+ self,
1248
+ path: str,
1249
+ *,
1250
+ cast_to: Type[ResponseT],
1251
+ body: Body | None = None,
1252
+ content: BinaryTypes | None = None,
1253
+ options: RequestOptions = {},
1254
+ files: RequestFiles | None = None,
1255
+ stream: Literal[True],
1256
+ stream_cls: type[_StreamT],
1257
+ ) -> _StreamT: ...
1258
+
1259
+ @overload
1260
+ def post(
1261
+ self,
1262
+ path: str,
1263
+ *,
1264
+ cast_to: Type[ResponseT],
1265
+ body: Body | None = None,
1266
+ content: BinaryTypes | None = None,
1267
+ options: RequestOptions = {},
1268
+ files: RequestFiles | None = None,
1269
+ stream: bool,
1270
+ stream_cls: type[_StreamT] | None = None,
1271
+ ) -> ResponseT | _StreamT: ...
1272
+
1273
+ def post(
1274
+ self,
1275
+ path: str,
1276
+ *,
1277
+ cast_to: Type[ResponseT],
1278
+ body: Body | None = None,
1279
+ content: BinaryTypes | None = None,
1280
+ options: RequestOptions = {},
1281
+ files: RequestFiles | None = None,
1282
+ stream: bool = False,
1283
+ stream_cls: type[_StreamT] | None = None,
1284
+ ) -> ResponseT | _StreamT:
1285
+ if body is not None and content is not None:
1286
+ raise TypeError("Passing both `body` and `content` is not supported")
1287
+ if files is not None and content is not None:
1288
+ raise TypeError("Passing both `files` and `content` is not supported")
1289
+ if isinstance(body, bytes):
1290
+ warnings.warn(
1291
+ "Passing raw bytes as `body` is deprecated and will be removed in a future version. "
1292
+ "Please pass raw bytes via the `content` parameter instead.",
1293
+ DeprecationWarning,
1294
+ stacklevel=2,
1295
+ )
1296
+ opts = FinalRequestOptions.construct(
1297
+ method="post", url=path, json_data=body, content=content, files=to_httpx_files(files), **options
1298
+ )
1299
+ return cast(ResponseT, self.request(cast_to, opts, stream=stream, stream_cls=stream_cls))
1300
+
1301
+ def patch(
1302
+ self,
1303
+ path: str,
1304
+ *,
1305
+ cast_to: Type[ResponseT],
1306
+ body: Body | None = None,
1307
+ content: BinaryTypes | None = None,
1308
+ files: RequestFiles | None = None,
1309
+ options: RequestOptions = {},
1310
+ ) -> ResponseT:
1311
+ if body is not None and content is not None:
1312
+ raise TypeError("Passing both `body` and `content` is not supported")
1313
+ if files is not None and content is not None:
1314
+ raise TypeError("Passing both `files` and `content` is not supported")
1315
+ if isinstance(body, bytes):
1316
+ warnings.warn(
1317
+ "Passing raw bytes as `body` is deprecated and will be removed in a future version. "
1318
+ "Please pass raw bytes via the `content` parameter instead.",
1319
+ DeprecationWarning,
1320
+ stacklevel=2,
1321
+ )
1322
+ opts = FinalRequestOptions.construct(
1323
+ method="patch", url=path, json_data=body, content=content, files=to_httpx_files(files), **options
1324
+ )
1325
+ return self.request(cast_to, opts)
1326
+
1327
+ def put(
1328
+ self,
1329
+ path: str,
1330
+ *,
1331
+ cast_to: Type[ResponseT],
1332
+ body: Body | None = None,
1333
+ content: BinaryTypes | None = None,
1334
+ files: RequestFiles | None = None,
1335
+ options: RequestOptions = {},
1336
+ ) -> ResponseT:
1337
+ if body is not None and content is not None:
1338
+ raise TypeError("Passing both `body` and `content` is not supported")
1339
+ if files is not None and content is not None:
1340
+ raise TypeError("Passing both `files` and `content` is not supported")
1341
+ if isinstance(body, bytes):
1342
+ warnings.warn(
1343
+ "Passing raw bytes as `body` is deprecated and will be removed in a future version. "
1344
+ "Please pass raw bytes via the `content` parameter instead.",
1345
+ DeprecationWarning,
1346
+ stacklevel=2,
1347
+ )
1348
+ opts = FinalRequestOptions.construct(
1349
+ method="put", url=path, json_data=body, content=content, files=to_httpx_files(files), **options
1350
+ )
1351
+ return self.request(cast_to, opts)
1352
+
1353
+ def delete(
1354
+ self,
1355
+ path: str,
1356
+ *,
1357
+ cast_to: Type[ResponseT],
1358
+ body: Body | None = None,
1359
+ content: BinaryTypes | None = None,
1360
+ options: RequestOptions = {},
1361
+ ) -> ResponseT:
1362
+ if body is not None and content is not None:
1363
+ raise TypeError("Passing both `body` and `content` is not supported")
1364
+ if isinstance(body, bytes):
1365
+ warnings.warn(
1366
+ "Passing raw bytes as `body` is deprecated and will be removed in a future version. "
1367
+ "Please pass raw bytes via the `content` parameter instead.",
1368
+ DeprecationWarning,
1369
+ stacklevel=2,
1370
+ )
1371
+ opts = FinalRequestOptions.construct(method="delete", url=path, json_data=body, content=content, **options)
1372
+ return self.request(cast_to, opts)
1373
+
1374
+ def get_api_list(
1375
+ self,
1376
+ path: str,
1377
+ *,
1378
+ model: Type[object],
1379
+ page: Type[SyncPageT],
1380
+ body: Body | None = None,
1381
+ options: RequestOptions = {},
1382
+ method: str = "get",
1383
+ ) -> SyncPageT:
1384
+ opts = FinalRequestOptions.construct(method=method, url=path, json_data=body, **options)
1385
+ return self._request_api_list(model, page, opts)
1386
+
1387
+
1388
+ class _DefaultAsyncHttpxClient(httpx.AsyncClient):
1389
+ def __init__(self, **kwargs: Any) -> None:
1390
+ kwargs.setdefault("timeout", DEFAULT_TIMEOUT)
1391
+ kwargs.setdefault("limits", DEFAULT_CONNECTION_LIMITS)
1392
+ kwargs.setdefault("follow_redirects", True)
1393
+ super().__init__(**kwargs)
1394
+
1395
+
1396
+ try:
1397
+ import httpx_aiohttp
1398
+ except ImportError:
1399
+
1400
+ class _DefaultAioHttpClient(httpx.AsyncClient):
1401
+ def __init__(self, **_kwargs: Any) -> None:
1402
+ raise RuntimeError("To use the aiohttp client you must have installed the package with the `aiohttp` extra")
1403
+ else:
1404
+
1405
+ class _DefaultAioHttpClient(httpx_aiohttp.HttpxAiohttpClient): # type: ignore
1406
+ def __init__(self, **kwargs: Any) -> None:
1407
+ kwargs.setdefault("timeout", DEFAULT_TIMEOUT)
1408
+ kwargs.setdefault("limits", DEFAULT_CONNECTION_LIMITS)
1409
+ kwargs.setdefault("follow_redirects", True)
1410
+
1411
+ super().__init__(**kwargs)
1412
+
1413
+
1414
+ if TYPE_CHECKING:
1415
+ DefaultAsyncHttpxClient = httpx.AsyncClient
1416
+ """An alias to `httpx.AsyncClient` that provides the same defaults that this SDK
1417
+ uses internally.
1418
+
1419
+ This is useful because overriding the `http_client` with your own instance of
1420
+ `httpx.AsyncClient` will result in httpx's defaults being used, not ours.
1421
+ """
1422
+
1423
+ DefaultAioHttpClient = httpx.AsyncClient
1424
+ """An alias to `httpx.AsyncClient` that changes the default HTTP transport to `aiohttp`."""
1425
+ else:
1426
+ DefaultAsyncHttpxClient = _DefaultAsyncHttpxClient
1427
+ DefaultAioHttpClient = _DefaultAioHttpClient
1428
+
1429
+
1430
+ class AsyncHttpxClientWrapper(DefaultAsyncHttpxClient):
1431
+ def __del__(self) -> None:
1432
+ if self.is_closed:
1433
+ return
1434
+
1435
+ try:
1436
+ # TODO(someday): support non asyncio runtimes here
1437
+ asyncio.get_running_loop().create_task(self.aclose())
1438
+ except Exception:
1439
+ pass
1440
+
1441
+
1442
+ class AsyncAPIClient(BaseClient[httpx.AsyncClient, AsyncStream[Any]]):
1443
+ _client: httpx.AsyncClient
1444
+ _default_stream_cls: type[AsyncStream[Any]] | None = None
1445
+
1446
+ def __init__(
1447
+ self,
1448
+ *,
1449
+ version: str,
1450
+ base_url: str | URL,
1451
+ _strict_response_validation: bool,
1452
+ max_retries: int = DEFAULT_MAX_RETRIES,
1453
+ timeout: float | Timeout | None | NotGiven = not_given,
1454
+ http_client: httpx.AsyncClient | None = None,
1455
+ custom_headers: Mapping[str, str] | None = None,
1456
+ custom_query: Mapping[str, object] | None = None,
1457
+ ) -> None:
1458
+ if not is_given(timeout):
1459
+ # if the user passed in a custom http client with a non-default
1460
+ # timeout set then we use that timeout.
1461
+ #
1462
+ # note: there is an edge case here where the user passes in a client
1463
+ # where they've explicitly set the timeout to match the default timeout
1464
+ # as this check is structural, meaning that we'll think they didn't
1465
+ # pass in a timeout and will ignore it
1466
+ if http_client and http_client.timeout != HTTPX_DEFAULT_TIMEOUT:
1467
+ timeout = http_client.timeout
1468
+ else:
1469
+ timeout = DEFAULT_TIMEOUT
1470
+
1471
+ if http_client is not None and not isinstance(http_client, httpx.AsyncClient): # pyright: ignore[reportUnnecessaryIsInstance]
1472
+ raise TypeError(
1473
+ f"Invalid `http_client` argument; Expected an instance of `httpx.AsyncClient` but got {type(http_client)}"
1474
+ )
1475
+
1476
+ super().__init__(
1477
+ version=version,
1478
+ base_url=base_url,
1479
+ # cast to a valid type because mypy doesn't understand our type narrowing
1480
+ timeout=cast(Timeout, timeout),
1481
+ max_retries=max_retries,
1482
+ custom_query=custom_query,
1483
+ custom_headers=custom_headers,
1484
+ _strict_response_validation=_strict_response_validation,
1485
+ )
1486
+ self._client = http_client or AsyncHttpxClientWrapper(
1487
+ base_url=base_url,
1488
+ # cast to a valid type because mypy doesn't understand our type narrowing
1489
+ timeout=cast(Timeout, timeout),
1490
+ )
1491
+
1492
+ def is_closed(self) -> bool:
1493
+ return self._client.is_closed
1494
+
1495
+ async def close(self) -> None:
1496
+ """Close the underlying HTTPX client.
1497
+
1498
+ The client will *not* be usable after this.
1499
+ """
1500
+ await self._client.aclose()
1501
+
1502
+ async def __aenter__(self: _T) -> _T:
1503
+ return self
1504
+
1505
+ async def __aexit__(
1506
+ self,
1507
+ exc_type: type[BaseException] | None,
1508
+ exc: BaseException | None,
1509
+ exc_tb: TracebackType | None,
1510
+ ) -> None:
1511
+ await self.close()
1512
+
1513
+ async def _prepare_options(
1514
+ self,
1515
+ options: FinalRequestOptions, # noqa: ARG002
1516
+ ) -> FinalRequestOptions:
1517
+ """Hook for mutating the given options"""
1518
+ return options
1519
+
1520
+ async def _prepare_request(
1521
+ self,
1522
+ request: httpx.Request, # noqa: ARG002
1523
+ ) -> None:
1524
+ """This method is used as a callback for mutating the `Request` object
1525
+ after it has been constructed.
1526
+ This is useful for cases where you want to add certain headers based off of
1527
+ the request properties, e.g. `url`, `method` etc.
1528
+ """
1529
+ return None
1530
+
1531
+ @overload
1532
+ async def request(
1533
+ self,
1534
+ cast_to: Type[ResponseT],
1535
+ options: FinalRequestOptions,
1536
+ *,
1537
+ stream: Literal[False] = False,
1538
+ ) -> ResponseT: ...
1539
+
1540
+ @overload
1541
+ async def request(
1542
+ self,
1543
+ cast_to: Type[ResponseT],
1544
+ options: FinalRequestOptions,
1545
+ *,
1546
+ stream: Literal[True],
1547
+ stream_cls: type[_AsyncStreamT],
1548
+ ) -> _AsyncStreamT: ...
1549
+
1550
+ @overload
1551
+ async def request(
1552
+ self,
1553
+ cast_to: Type[ResponseT],
1554
+ options: FinalRequestOptions,
1555
+ *,
1556
+ stream: bool,
1557
+ stream_cls: type[_AsyncStreamT] | None = None,
1558
+ ) -> ResponseT | _AsyncStreamT: ...
1559
+
1560
+ async def request(
1561
+ self,
1562
+ cast_to: Type[ResponseT],
1563
+ options: FinalRequestOptions,
1564
+ *,
1565
+ stream: bool = False,
1566
+ stream_cls: type[_AsyncStreamT] | None = None,
1567
+ ) -> ResponseT | _AsyncStreamT:
1568
+ if self._platform is None:
1569
+ # `get_platform` can make blocking IO calls so we
1570
+ # execute it earlier while we are in an async context
1571
+ self._platform = await asyncify(get_platform)()
1572
+
1573
+ cast_to = self._maybe_override_cast_to(cast_to, options)
1574
+
1575
+ # create a copy of the options we were given so that if the
1576
+ # options are mutated later & we then retry, the retries are
1577
+ # given the original options
1578
+ input_options = model_copy(options)
1579
+ if input_options.idempotency_key is None and input_options.method.lower() != "get":
1580
+ # ensure the idempotency key is reused between requests
1581
+ input_options.idempotency_key = self._idempotency_key()
1582
+
1583
+ response: httpx.Response | None = None
1584
+ max_retries = input_options.get_max_retries(self.max_retries)
1585
+
1586
+ retries_taken = 0
1587
+ for retries_taken in range(max_retries + 1):
1588
+ options = model_copy(input_options)
1589
+ options = await self._prepare_options(options)
1590
+
1591
+ remaining_retries = max_retries - retries_taken
1592
+ request = self._build_request(options, retries_taken=retries_taken)
1593
+ await self._prepare_request(request)
1594
+
1595
+ kwargs: HttpxSendArgs = {}
1596
+ if self.custom_auth is not None:
1597
+ kwargs["auth"] = self.custom_auth
1598
+
1599
+ if options.follow_redirects is not None:
1600
+ kwargs["follow_redirects"] = options.follow_redirects
1601
+
1602
+ log.debug("Sending HTTP Request: %s %s", request.method, request.url)
1603
+
1604
+ response = None
1605
+ try:
1606
+ response = await self._client.send(
1607
+ request,
1608
+ stream=stream or self._should_stream_response_body(request=request),
1609
+ **kwargs,
1610
+ )
1611
+ except httpx.TimeoutException as err:
1612
+ log.debug("Encountered httpx.TimeoutException", exc_info=True)
1613
+
1614
+ if remaining_retries > 0:
1615
+ await self._sleep_for_retry(
1616
+ retries_taken=retries_taken,
1617
+ max_retries=max_retries,
1618
+ options=input_options,
1619
+ response=None,
1620
+ )
1621
+ continue
1622
+
1623
+ log.debug("Raising timeout error")
1624
+ raise APITimeoutError(request=request) from err
1625
+ except Exception as err:
1626
+ log.debug("Encountered Exception", exc_info=True)
1627
+
1628
+ if remaining_retries > 0:
1629
+ await self._sleep_for_retry(
1630
+ retries_taken=retries_taken,
1631
+ max_retries=max_retries,
1632
+ options=input_options,
1633
+ response=None,
1634
+ )
1635
+ continue
1636
+
1637
+ log.debug("Raising connection error")
1638
+ raise APIConnectionError(request=request) from err
1639
+
1640
+ log.debug(
1641
+ 'HTTP Response: %s %s "%i %s" %s',
1642
+ request.method,
1643
+ request.url,
1644
+ response.status_code,
1645
+ response.reason_phrase,
1646
+ response.headers,
1647
+ )
1648
+
1649
+ try:
1650
+ response.raise_for_status()
1651
+ except httpx.HTTPStatusError as err: # thrown on 4xx and 5xx status code
1652
+ log.debug("Encountered httpx.HTTPStatusError", exc_info=True)
1653
+
1654
+ if remaining_retries > 0 and self._should_retry(err.response):
1655
+ await err.response.aclose()
1656
+ await self._sleep_for_retry(
1657
+ retries_taken=retries_taken,
1658
+ max_retries=max_retries,
1659
+ options=input_options,
1660
+ response=response,
1661
+ )
1662
+ continue
1663
+
1664
+ # If the response is streamed then we need to explicitly read the response
1665
+ # to completion before attempting to access the response text.
1666
+ if not err.response.is_closed:
1667
+ await err.response.aread()
1668
+
1669
+ log.debug("Re-raising status error")
1670
+ raise self._make_status_error_from_response(err.response) from None
1671
+
1672
+ break
1673
+
1674
+ assert response is not None, "could not resolve response (should never happen)"
1675
+ return await self._process_response(
1676
+ cast_to=cast_to,
1677
+ options=options,
1678
+ response=response,
1679
+ stream=stream,
1680
+ stream_cls=stream_cls,
1681
+ retries_taken=retries_taken,
1682
+ )
1683
+
1684
+ async def _sleep_for_retry(
1685
+ self, *, retries_taken: int, max_retries: int, options: FinalRequestOptions, response: httpx.Response | None
1686
+ ) -> None:
1687
+ remaining_retries = max_retries - retries_taken
1688
+ if remaining_retries == 1:
1689
+ log.debug("1 retry left")
1690
+ else:
1691
+ log.debug("%i retries left", remaining_retries)
1692
+
1693
+ timeout = self._calculate_retry_timeout(remaining_retries, options, response.headers if response else None)
1694
+ log.info("Retrying request to %s in %f seconds", options.url, timeout)
1695
+
1696
+ await anyio.sleep(timeout)
1697
+
1698
+ async def _process_response(
1699
+ self,
1700
+ *,
1701
+ cast_to: Type[ResponseT],
1702
+ options: FinalRequestOptions,
1703
+ response: httpx.Response,
1704
+ stream: bool,
1705
+ stream_cls: type[Stream[Any]] | type[AsyncStream[Any]] | None,
1706
+ retries_taken: int = 0,
1707
+ ) -> ResponseT:
1708
+ origin = get_origin(cast_to) or cast_to
1709
+
1710
+ if (
1711
+ inspect.isclass(origin)
1712
+ and issubclass(origin, BaseAPIResponse)
1713
+ # we only want to actually return the custom BaseAPIResponse class if we're
1714
+ # returning the raw response, or if we're not streaming SSE, as if we're streaming
1715
+ # SSE then `cast_to` doesn't actively reflect the type we need to parse into
1716
+ and (not stream or bool(response.request.headers.get(RAW_RESPONSE_HEADER)))
1717
+ ):
1718
+ if not issubclass(origin, AsyncAPIResponse):
1719
+ raise TypeError(f"API Response types must subclass {AsyncAPIResponse}; Received {origin}")
1720
+
1721
+ response_cls = cast("type[BaseAPIResponse[Any]]", cast_to)
1722
+ return cast(
1723
+ "ResponseT",
1724
+ response_cls(
1725
+ raw=response,
1726
+ client=self,
1727
+ cast_to=extract_response_type(response_cls),
1728
+ stream=stream,
1729
+ stream_cls=stream_cls,
1730
+ options=options,
1731
+ retries_taken=retries_taken,
1732
+ ),
1733
+ )
1734
+
1735
+ if cast_to == httpx.Response:
1736
+ return cast(ResponseT, response)
1737
+
1738
+ api_response = AsyncAPIResponse(
1739
+ raw=response,
1740
+ client=self,
1741
+ cast_to=cast("type[ResponseT]", cast_to), # pyright: ignore[reportUnnecessaryCast]
1742
+ stream=stream,
1743
+ stream_cls=stream_cls,
1744
+ options=options,
1745
+ retries_taken=retries_taken,
1746
+ )
1747
+ if bool(response.request.headers.get(RAW_RESPONSE_HEADER)):
1748
+ return cast(ResponseT, api_response)
1749
+
1750
+ return await api_response.parse()
1751
+
1752
+ def _request_api_list(
1753
+ self,
1754
+ model: Type[_T],
1755
+ page: Type[AsyncPageT],
1756
+ options: FinalRequestOptions,
1757
+ ) -> AsyncPaginator[_T, AsyncPageT]:
1758
+ return AsyncPaginator(client=self, options=options, page_cls=page, model=model)
1759
+
1760
+ @overload
1761
+ async def get(
1762
+ self,
1763
+ path: str,
1764
+ *,
1765
+ cast_to: Type[ResponseT],
1766
+ options: RequestOptions = {},
1767
+ stream: Literal[False] = False,
1768
+ ) -> ResponseT: ...
1769
+
1770
+ @overload
1771
+ async def get(
1772
+ self,
1773
+ path: str,
1774
+ *,
1775
+ cast_to: Type[ResponseT],
1776
+ options: RequestOptions = {},
1777
+ stream: Literal[True],
1778
+ stream_cls: type[_AsyncStreamT],
1779
+ ) -> _AsyncStreamT: ...
1780
+
1781
+ @overload
1782
+ async def get(
1783
+ self,
1784
+ path: str,
1785
+ *,
1786
+ cast_to: Type[ResponseT],
1787
+ options: RequestOptions = {},
1788
+ stream: bool,
1789
+ stream_cls: type[_AsyncStreamT] | None = None,
1790
+ ) -> ResponseT | _AsyncStreamT: ...
1791
+
1792
+ async def get(
1793
+ self,
1794
+ path: str,
1795
+ *,
1796
+ cast_to: Type[ResponseT],
1797
+ options: RequestOptions = {},
1798
+ stream: bool = False,
1799
+ stream_cls: type[_AsyncStreamT] | None = None,
1800
+ ) -> ResponseT | _AsyncStreamT:
1801
+ opts = FinalRequestOptions.construct(method="get", url=path, **options)
1802
+ return await self.request(cast_to, opts, stream=stream, stream_cls=stream_cls)
1803
+
1804
+ @overload
1805
+ async def post(
1806
+ self,
1807
+ path: str,
1808
+ *,
1809
+ cast_to: Type[ResponseT],
1810
+ body: Body | None = None,
1811
+ content: AsyncBinaryTypes | None = None,
1812
+ files: RequestFiles | None = None,
1813
+ options: RequestOptions = {},
1814
+ stream: Literal[False] = False,
1815
+ ) -> ResponseT: ...
1816
+
1817
+ @overload
1818
+ async def post(
1819
+ self,
1820
+ path: str,
1821
+ *,
1822
+ cast_to: Type[ResponseT],
1823
+ body: Body | None = None,
1824
+ content: AsyncBinaryTypes | None = None,
1825
+ files: RequestFiles | None = None,
1826
+ options: RequestOptions = {},
1827
+ stream: Literal[True],
1828
+ stream_cls: type[_AsyncStreamT],
1829
+ ) -> _AsyncStreamT: ...
1830
+
1831
+ @overload
1832
+ async def post(
1833
+ self,
1834
+ path: str,
1835
+ *,
1836
+ cast_to: Type[ResponseT],
1837
+ body: Body | None = None,
1838
+ content: AsyncBinaryTypes | None = None,
1839
+ files: RequestFiles | None = None,
1840
+ options: RequestOptions = {},
1841
+ stream: bool,
1842
+ stream_cls: type[_AsyncStreamT] | None = None,
1843
+ ) -> ResponseT | _AsyncStreamT: ...
1844
+
1845
+ async def post(
1846
+ self,
1847
+ path: str,
1848
+ *,
1849
+ cast_to: Type[ResponseT],
1850
+ body: Body | None = None,
1851
+ content: AsyncBinaryTypes | None = None,
1852
+ files: RequestFiles | None = None,
1853
+ options: RequestOptions = {},
1854
+ stream: bool = False,
1855
+ stream_cls: type[_AsyncStreamT] | None = None,
1856
+ ) -> ResponseT | _AsyncStreamT:
1857
+ if body is not None and content is not None:
1858
+ raise TypeError("Passing both `body` and `content` is not supported")
1859
+ if files is not None and content is not None:
1860
+ raise TypeError("Passing both `files` and `content` is not supported")
1861
+ if isinstance(body, bytes):
1862
+ warnings.warn(
1863
+ "Passing raw bytes as `body` is deprecated and will be removed in a future version. "
1864
+ "Please pass raw bytes via the `content` parameter instead.",
1865
+ DeprecationWarning,
1866
+ stacklevel=2,
1867
+ )
1868
+ opts = FinalRequestOptions.construct(
1869
+ method="post", url=path, json_data=body, content=content, files=await async_to_httpx_files(files), **options
1870
+ )
1871
+ return await self.request(cast_to, opts, stream=stream, stream_cls=stream_cls)
1872
+
1873
+ async def patch(
1874
+ self,
1875
+ path: str,
1876
+ *,
1877
+ cast_to: Type[ResponseT],
1878
+ body: Body | None = None,
1879
+ content: AsyncBinaryTypes | None = None,
1880
+ files: RequestFiles | None = None,
1881
+ options: RequestOptions = {},
1882
+ ) -> ResponseT:
1883
+ if body is not None and content is not None:
1884
+ raise TypeError("Passing both `body` and `content` is not supported")
1885
+ if files is not None and content is not None:
1886
+ raise TypeError("Passing both `files` and `content` is not supported")
1887
+ if isinstance(body, bytes):
1888
+ warnings.warn(
1889
+ "Passing raw bytes as `body` is deprecated and will be removed in a future version. "
1890
+ "Please pass raw bytes via the `content` parameter instead.",
1891
+ DeprecationWarning,
1892
+ stacklevel=2,
1893
+ )
1894
+ opts = FinalRequestOptions.construct(
1895
+ method="patch",
1896
+ url=path,
1897
+ json_data=body,
1898
+ content=content,
1899
+ files=await async_to_httpx_files(files),
1900
+ **options,
1901
+ )
1902
+ return await self.request(cast_to, opts)
1903
+
1904
+ async def put(
1905
+ self,
1906
+ path: str,
1907
+ *,
1908
+ cast_to: Type[ResponseT],
1909
+ body: Body | None = None,
1910
+ content: AsyncBinaryTypes | None = None,
1911
+ files: RequestFiles | None = None,
1912
+ options: RequestOptions = {},
1913
+ ) -> ResponseT:
1914
+ if body is not None and content is not None:
1915
+ raise TypeError("Passing both `body` and `content` is not supported")
1916
+ if files is not None and content is not None:
1917
+ raise TypeError("Passing both `files` and `content` is not supported")
1918
+ if isinstance(body, bytes):
1919
+ warnings.warn(
1920
+ "Passing raw bytes as `body` is deprecated and will be removed in a future version. "
1921
+ "Please pass raw bytes via the `content` parameter instead.",
1922
+ DeprecationWarning,
1923
+ stacklevel=2,
1924
+ )
1925
+ opts = FinalRequestOptions.construct(
1926
+ method="put", url=path, json_data=body, content=content, files=await async_to_httpx_files(files), **options
1927
+ )
1928
+ return await self.request(cast_to, opts)
1929
+
1930
+ async def delete(
1931
+ self,
1932
+ path: str,
1933
+ *,
1934
+ cast_to: Type[ResponseT],
1935
+ body: Body | None = None,
1936
+ content: AsyncBinaryTypes | None = None,
1937
+ options: RequestOptions = {},
1938
+ ) -> ResponseT:
1939
+ if body is not None and content is not None:
1940
+ raise TypeError("Passing both `body` and `content` is not supported")
1941
+ if isinstance(body, bytes):
1942
+ warnings.warn(
1943
+ "Passing raw bytes as `body` is deprecated and will be removed in a future version. "
1944
+ "Please pass raw bytes via the `content` parameter instead.",
1945
+ DeprecationWarning,
1946
+ stacklevel=2,
1947
+ )
1948
+ opts = FinalRequestOptions.construct(method="delete", url=path, json_data=body, content=content, **options)
1949
+ return await self.request(cast_to, opts)
1950
+
1951
+ def get_api_list(
1952
+ self,
1953
+ path: str,
1954
+ *,
1955
+ model: Type[_T],
1956
+ page: Type[AsyncPageT],
1957
+ body: Body | None = None,
1958
+ options: RequestOptions = {},
1959
+ method: str = "get",
1960
+ ) -> AsyncPaginator[_T, AsyncPageT]:
1961
+ opts = FinalRequestOptions.construct(method=method, url=path, json_data=body, **options)
1962
+ return self._request_api_list(model, page, opts)
1963
+
1964
+
1965
+ def make_request_options(
1966
+ *,
1967
+ query: Query | None = None,
1968
+ extra_headers: Headers | None = None,
1969
+ extra_query: Query | None = None,
1970
+ extra_body: Body | None = None,
1971
+ idempotency_key: str | None = None,
1972
+ timeout: float | httpx.Timeout | None | NotGiven = not_given,
1973
+ post_parser: PostParser | NotGiven = not_given,
1974
+ ) -> RequestOptions:
1975
+ """Create a dict of type RequestOptions without keys of NotGiven values."""
1976
+ options: RequestOptions = {}
1977
+ if extra_headers is not None:
1978
+ options["headers"] = extra_headers
1979
+
1980
+ if extra_body is not None:
1981
+ options["extra_json"] = cast(AnyMapping, extra_body)
1982
+
1983
+ if query is not None:
1984
+ options["params"] = query
1985
+
1986
+ if extra_query is not None:
1987
+ options["params"] = {**options.get("params", {}), **extra_query}
1988
+
1989
+ if not isinstance(timeout, NotGiven):
1990
+ options["timeout"] = timeout
1991
+
1992
+ if idempotency_key is not None:
1993
+ options["idempotency_key"] = idempotency_key
1994
+
1995
+ if is_given(post_parser):
1996
+ # internal
1997
+ options["post_parser"] = post_parser # type: ignore
1998
+
1999
+ return options
2000
+
2001
+
2002
+ class ForceMultipartDict(Dict[str, None]):
2003
+ def __bool__(self) -> bool:
2004
+ return True
2005
+
2006
+
2007
+ class OtherPlatform:
2008
+ def __init__(self, name: str) -> None:
2009
+ self.name = name
2010
+
2011
+ @override
2012
+ def __str__(self) -> str:
2013
+ return f"Other:{self.name}"
2014
+
2015
+
2016
+ Platform = Union[
2017
+ OtherPlatform,
2018
+ Literal[
2019
+ "MacOS",
2020
+ "Linux",
2021
+ "Windows",
2022
+ "FreeBSD",
2023
+ "OpenBSD",
2024
+ "iOS",
2025
+ "Android",
2026
+ "Unknown",
2027
+ ],
2028
+ ]
2029
+
2030
+
2031
+ def get_platform() -> Platform:
2032
+ try:
2033
+ system = platform.system().lower()
2034
+ platform_name = platform.platform().lower()
2035
+ except Exception:
2036
+ return "Unknown"
2037
+
2038
+ if "iphone" in platform_name or "ipad" in platform_name:
2039
+ # Tested using Python3IDE on an iPhone 11 and Pythonista on an iPad 7
2040
+ # system is Darwin and platform_name is a string like:
2041
+ # - Darwin-21.6.0-iPhone12,1-64bit
2042
+ # - Darwin-21.6.0-iPad7,11-64bit
2043
+ return "iOS"
2044
+
2045
+ if system == "darwin":
2046
+ return "MacOS"
2047
+
2048
+ if system == "windows":
2049
+ return "Windows"
2050
+
2051
+ if "android" in platform_name:
2052
+ # Tested using Pydroid 3
2053
+ # system is Linux and platform_name is a string like 'Linux-5.10.81-android12-9-00001-geba40aecb3b7-ab8534902-aarch64-with-libc'
2054
+ return "Android"
2055
+
2056
+ if system == "linux":
2057
+ # https://distro.readthedocs.io/en/latest/#distro.id
2058
+ distro_id = distro.id()
2059
+ if distro_id == "freebsd":
2060
+ return "FreeBSD"
2061
+
2062
+ if distro_id == "openbsd":
2063
+ return "OpenBSD"
2064
+
2065
+ return "Linux"
2066
+
2067
+ if platform_name:
2068
+ return OtherPlatform(platform_name)
2069
+
2070
+ return "Unknown"
2071
+
2072
+
2073
+ @lru_cache(maxsize=None)
2074
+ def platform_headers(version: str, *, platform: Platform | None) -> Dict[str, str]:
2075
+ return {
2076
+ "X-Stainless-Lang": "python",
2077
+ "X-Stainless-Package-Version": version,
2078
+ "X-Stainless-OS": str(platform or get_platform()),
2079
+ "X-Stainless-Arch": str(get_architecture()),
2080
+ "X-Stainless-Runtime": get_python_runtime(),
2081
+ "X-Stainless-Runtime-Version": get_python_version(),
2082
+ }
2083
+
2084
+
2085
+ class OtherArch:
2086
+ def __init__(self, name: str) -> None:
2087
+ self.name = name
2088
+
2089
+ @override
2090
+ def __str__(self) -> str:
2091
+ return f"other:{self.name}"
2092
+
2093
+
2094
+ Arch = Union[OtherArch, Literal["x32", "x64", "arm", "arm64", "unknown"]]
2095
+
2096
+
2097
+ def get_python_runtime() -> str:
2098
+ try:
2099
+ return platform.python_implementation()
2100
+ except Exception:
2101
+ return "unknown"
2102
+
2103
+
2104
+ def get_python_version() -> str:
2105
+ try:
2106
+ return platform.python_version()
2107
+ except Exception:
2108
+ return "unknown"
2109
+
2110
+
2111
+ def get_architecture() -> Arch:
2112
+ try:
2113
+ machine = platform.machine().lower()
2114
+ except Exception:
2115
+ return "unknown"
2116
+
2117
+ if machine in ("arm64", "aarch64"):
2118
+ return "arm64"
2119
+
2120
+ # TODO: untested
2121
+ if machine == "arm":
2122
+ return "arm"
2123
+
2124
+ if machine == "x86_64":
2125
+ return "x64"
2126
+
2127
+ # TODO: untested
2128
+ if sys.maxsize <= 2**32:
2129
+ return "x32"
2130
+
2131
+ if machine:
2132
+ return OtherArch(machine)
2133
+
2134
+ return "unknown"
2135
+
2136
+
2137
+ def _merge_mappings(
2138
+ obj1: Mapping[_T_co, Union[_T, Omit]],
2139
+ obj2: Mapping[_T_co, Union[_T, Omit]],
2140
+ ) -> Dict[_T_co, _T]:
2141
+ """Merge two mappings of the same type, removing any values that are instances of `Omit`.
2142
+
2143
+ In cases with duplicate keys the second mapping takes precedence.
2144
+ """
2145
+ merged = {**obj1, **obj2}
2146
+ return {key: value for key, value in merged.items() if not isinstance(value, Omit)}