payi 0.1.0a96__tar.gz → 0.1.0a97__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of payi might be problematic. Click here for more details.

Files changed (190) hide show
  1. payi-0.1.0a97/.release-please-manifest.json +3 -0
  2. {payi-0.1.0a96 → payi-0.1.0a97}/CHANGELOG.md +4 -0
  3. {payi-0.1.0a96 → payi-0.1.0a97}/PKG-INFO +1 -1
  4. {payi-0.1.0a96 → payi-0.1.0a97}/pyproject.toml +1 -1
  5. {payi-0.1.0a96 → payi-0.1.0a97}/src/payi/_version.py +1 -1
  6. {payi-0.1.0a96 → payi-0.1.0a97}/src/payi/lib/VertexRequest.py +32 -6
  7. {payi-0.1.0a96 → payi-0.1.0a97}/src/payi/lib/instrument.py +120 -37
  8. payi-0.1.0a96/.release-please-manifest.json +0 -3
  9. {payi-0.1.0a96 → payi-0.1.0a97}/.gitignore +0 -0
  10. {payi-0.1.0a96 → payi-0.1.0a97}/CONTRIBUTING.md +0 -0
  11. {payi-0.1.0a96 → payi-0.1.0a97}/LICENSE +0 -0
  12. {payi-0.1.0a96 → payi-0.1.0a97}/README.md +0 -0
  13. {payi-0.1.0a96 → payi-0.1.0a97}/SECURITY.md +0 -0
  14. {payi-0.1.0a96 → payi-0.1.0a97}/api.md +0 -0
  15. {payi-0.1.0a96 → payi-0.1.0a97}/bin/check-release-environment +0 -0
  16. {payi-0.1.0a96 → payi-0.1.0a97}/bin/publish-pypi +0 -0
  17. {payi-0.1.0a96 → payi-0.1.0a97}/examples/.keep +0 -0
  18. {payi-0.1.0a96 → payi-0.1.0a97}/mypy.ini +0 -0
  19. {payi-0.1.0a96 → payi-0.1.0a97}/noxfile.py +0 -0
  20. {payi-0.1.0a96 → payi-0.1.0a97}/release-please-config.json +0 -0
  21. {payi-0.1.0a96 → payi-0.1.0a97}/requirements-dev.lock +0 -0
  22. {payi-0.1.0a96 → payi-0.1.0a97}/requirements.lock +0 -0
  23. {payi-0.1.0a96 → payi-0.1.0a97}/src/payi/__init__.py +0 -0
  24. {payi-0.1.0a96 → payi-0.1.0a97}/src/payi/_base_client.py +0 -0
  25. {payi-0.1.0a96 → payi-0.1.0a97}/src/payi/_client.py +0 -0
  26. {payi-0.1.0a96 → payi-0.1.0a97}/src/payi/_compat.py +0 -0
  27. {payi-0.1.0a96 → payi-0.1.0a97}/src/payi/_constants.py +0 -0
  28. {payi-0.1.0a96 → payi-0.1.0a97}/src/payi/_exceptions.py +0 -0
  29. {payi-0.1.0a96 → payi-0.1.0a97}/src/payi/_files.py +0 -0
  30. {payi-0.1.0a96 → payi-0.1.0a97}/src/payi/_models.py +0 -0
  31. {payi-0.1.0a96 → payi-0.1.0a97}/src/payi/_qs.py +0 -0
  32. {payi-0.1.0a96 → payi-0.1.0a97}/src/payi/_resource.py +0 -0
  33. {payi-0.1.0a96 → payi-0.1.0a97}/src/payi/_response.py +0 -0
  34. {payi-0.1.0a96 → payi-0.1.0a97}/src/payi/_streaming.py +0 -0
  35. {payi-0.1.0a96 → payi-0.1.0a97}/src/payi/_types.py +0 -0
  36. {payi-0.1.0a96 → payi-0.1.0a97}/src/payi/_utils/__init__.py +0 -0
  37. {payi-0.1.0a96 → payi-0.1.0a97}/src/payi/_utils/_logs.py +0 -0
  38. {payi-0.1.0a96 → payi-0.1.0a97}/src/payi/_utils/_proxy.py +0 -0
  39. {payi-0.1.0a96 → payi-0.1.0a97}/src/payi/_utils/_reflection.py +0 -0
  40. {payi-0.1.0a96 → payi-0.1.0a97}/src/payi/_utils/_resources_proxy.py +0 -0
  41. {payi-0.1.0a96 → payi-0.1.0a97}/src/payi/_utils/_streams.py +0 -0
  42. {payi-0.1.0a96 → payi-0.1.0a97}/src/payi/_utils/_sync.py +0 -0
  43. {payi-0.1.0a96 → payi-0.1.0a97}/src/payi/_utils/_transform.py +0 -0
  44. {payi-0.1.0a96 → payi-0.1.0a97}/src/payi/_utils/_typing.py +0 -0
  45. {payi-0.1.0a96 → payi-0.1.0a97}/src/payi/_utils/_utils.py +0 -0
  46. {payi-0.1.0a96 → payi-0.1.0a97}/src/payi/lib/.keep +0 -0
  47. {payi-0.1.0a96 → payi-0.1.0a97}/src/payi/lib/AnthropicInstrumentor.py +0 -0
  48. {payi-0.1.0a96 → payi-0.1.0a97}/src/payi/lib/BedrockInstrumentor.py +0 -0
  49. {payi-0.1.0a96 → payi-0.1.0a97}/src/payi/lib/GoogleGenAiInstrumentor.py +0 -0
  50. {payi-0.1.0a96 → payi-0.1.0a97}/src/payi/lib/OpenAIInstrumentor.py +0 -0
  51. {payi-0.1.0a96 → payi-0.1.0a97}/src/payi/lib/Stopwatch.py +0 -0
  52. {payi-0.1.0a96 → payi-0.1.0a97}/src/payi/lib/VertexInstrumentor.py +0 -0
  53. {payi-0.1.0a96 → payi-0.1.0a97}/src/payi/lib/helpers.py +0 -0
  54. {payi-0.1.0a96 → payi-0.1.0a97}/src/payi/pagination.py +0 -0
  55. {payi-0.1.0a96 → payi-0.1.0a97}/src/payi/py.typed +0 -0
  56. {payi-0.1.0a96 → payi-0.1.0a97}/src/payi/resources/__init__.py +0 -0
  57. {payi-0.1.0a96 → payi-0.1.0a97}/src/payi/resources/categories/__init__.py +0 -0
  58. {payi-0.1.0a96 → payi-0.1.0a97}/src/payi/resources/categories/categories.py +0 -0
  59. {payi-0.1.0a96 → payi-0.1.0a97}/src/payi/resources/categories/fixed_cost_resources.py +0 -0
  60. {payi-0.1.0a96 → payi-0.1.0a97}/src/payi/resources/categories/resources.py +0 -0
  61. {payi-0.1.0a96 → payi-0.1.0a97}/src/payi/resources/ingest.py +0 -0
  62. {payi-0.1.0a96 → payi-0.1.0a97}/src/payi/resources/limits/__init__.py +0 -0
  63. {payi-0.1.0a96 → payi-0.1.0a97}/src/payi/resources/limits/limits.py +0 -0
  64. {payi-0.1.0a96 → payi-0.1.0a97}/src/payi/resources/limits/tags.py +0 -0
  65. {payi-0.1.0a96 → payi-0.1.0a97}/src/payi/resources/requests/__init__.py +0 -0
  66. {payi-0.1.0a96 → payi-0.1.0a97}/src/payi/resources/requests/properties.py +0 -0
  67. {payi-0.1.0a96 → payi-0.1.0a97}/src/payi/resources/requests/requests.py +0 -0
  68. {payi-0.1.0a96 → payi-0.1.0a97}/src/payi/resources/requests/result.py +0 -0
  69. {payi-0.1.0a96 → payi-0.1.0a97}/src/payi/resources/use_cases/__init__.py +0 -0
  70. {payi-0.1.0a96 → payi-0.1.0a97}/src/payi/resources/use_cases/definitions/__init__.py +0 -0
  71. {payi-0.1.0a96 → payi-0.1.0a97}/src/payi/resources/use_cases/definitions/definitions.py +0 -0
  72. {payi-0.1.0a96 → payi-0.1.0a97}/src/payi/resources/use_cases/definitions/kpis.py +0 -0
  73. {payi-0.1.0a96 → payi-0.1.0a97}/src/payi/resources/use_cases/definitions/limit_config.py +0 -0
  74. {payi-0.1.0a96 → payi-0.1.0a97}/src/payi/resources/use_cases/definitions/version.py +0 -0
  75. {payi-0.1.0a96 → payi-0.1.0a97}/src/payi/resources/use_cases/kpis.py +0 -0
  76. {payi-0.1.0a96 → payi-0.1.0a97}/src/payi/resources/use_cases/properties.py +0 -0
  77. {payi-0.1.0a96 → payi-0.1.0a97}/src/payi/resources/use_cases/use_cases.py +0 -0
  78. {payi-0.1.0a96 → payi-0.1.0a97}/src/payi/types/__init__.py +0 -0
  79. {payi-0.1.0a96 → payi-0.1.0a97}/src/payi/types/bulk_ingest_response.py +0 -0
  80. {payi-0.1.0a96 → payi-0.1.0a97}/src/payi/types/categories/__init__.py +0 -0
  81. {payi-0.1.0a96 → payi-0.1.0a97}/src/payi/types/categories/fixed_cost_resource_create_params.py +0 -0
  82. {payi-0.1.0a96 → payi-0.1.0a97}/src/payi/types/categories/resource_create_params.py +0 -0
  83. {payi-0.1.0a96 → payi-0.1.0a97}/src/payi/types/categories/resource_list_params.py +0 -0
  84. {payi-0.1.0a96 → payi-0.1.0a97}/src/payi/types/category_delete_resource_response.py +0 -0
  85. {payi-0.1.0a96 → payi-0.1.0a97}/src/payi/types/category_delete_response.py +0 -0
  86. {payi-0.1.0a96 → payi-0.1.0a97}/src/payi/types/category_list_params.py +0 -0
  87. {payi-0.1.0a96 → payi-0.1.0a97}/src/payi/types/category_list_resources_params.py +0 -0
  88. {payi-0.1.0a96 → payi-0.1.0a97}/src/payi/types/category_resource_response.py +0 -0
  89. {payi-0.1.0a96 → payi-0.1.0a97}/src/payi/types/category_response.py +0 -0
  90. {payi-0.1.0a96 → payi-0.1.0a97}/src/payi/types/cost_data.py +0 -0
  91. {payi-0.1.0a96 → payi-0.1.0a97}/src/payi/types/cost_details.py +0 -0
  92. {payi-0.1.0a96 → payi-0.1.0a97}/src/payi/types/default_response.py +0 -0
  93. {payi-0.1.0a96 → payi-0.1.0a97}/src/payi/types/ingest_bulk_params.py +0 -0
  94. {payi-0.1.0a96 → payi-0.1.0a97}/src/payi/types/ingest_event_param.py +0 -0
  95. {payi-0.1.0a96 → payi-0.1.0a97}/src/payi/types/ingest_response.py +0 -0
  96. {payi-0.1.0a96 → payi-0.1.0a97}/src/payi/types/ingest_units_params.py +0 -0
  97. {payi-0.1.0a96 → payi-0.1.0a97}/src/payi/types/limit_create_params.py +0 -0
  98. {payi-0.1.0a96 → payi-0.1.0a97}/src/payi/types/limit_history_response.py +0 -0
  99. {payi-0.1.0a96 → payi-0.1.0a97}/src/payi/types/limit_list_params.py +0 -0
  100. {payi-0.1.0a96 → payi-0.1.0a97}/src/payi/types/limit_list_response.py +0 -0
  101. {payi-0.1.0a96 → payi-0.1.0a97}/src/payi/types/limit_reset_params.py +0 -0
  102. {payi-0.1.0a96 → payi-0.1.0a97}/src/payi/types/limit_response.py +0 -0
  103. {payi-0.1.0a96 → payi-0.1.0a97}/src/payi/types/limit_update_params.py +0 -0
  104. {payi-0.1.0a96 → payi-0.1.0a97}/src/payi/types/limits/__init__.py +0 -0
  105. {payi-0.1.0a96 → payi-0.1.0a97}/src/payi/types/limits/limit_tags.py +0 -0
  106. {payi-0.1.0a96 → payi-0.1.0a97}/src/payi/types/limits/tag_create_params.py +0 -0
  107. {payi-0.1.0a96 → payi-0.1.0a97}/src/payi/types/limits/tag_create_response.py +0 -0
  108. {payi-0.1.0a96 → payi-0.1.0a97}/src/payi/types/limits/tag_delete_response.py +0 -0
  109. {payi-0.1.0a96 → payi-0.1.0a97}/src/payi/types/limits/tag_list_response.py +0 -0
  110. {payi-0.1.0a96 → payi-0.1.0a97}/src/payi/types/limits/tag_remove_params.py +0 -0
  111. {payi-0.1.0a96 → payi-0.1.0a97}/src/payi/types/limits/tag_remove_response.py +0 -0
  112. {payi-0.1.0a96 → payi-0.1.0a97}/src/payi/types/limits/tag_update_params.py +0 -0
  113. {payi-0.1.0a96 → payi-0.1.0a97}/src/payi/types/limits/tag_update_response.py +0 -0
  114. {payi-0.1.0a96 → payi-0.1.0a97}/src/payi/types/pay_i_common_models_api_router_header_info_param.py +0 -0
  115. {payi-0.1.0a96 → payi-0.1.0a97}/src/payi/types/requests/__init__.py +0 -0
  116. {payi-0.1.0a96 → payi-0.1.0a97}/src/payi/types/requests/property_create_params.py +0 -0
  117. {payi-0.1.0a96 → payi-0.1.0a97}/src/payi/types/requests/request_result.py +0 -0
  118. {payi-0.1.0a96 → payi-0.1.0a97}/src/payi/types/requests_data.py +0 -0
  119. {payi-0.1.0a96 → payi-0.1.0a97}/src/payi/types/shared/__init__.py +0 -0
  120. {payi-0.1.0a96 → payi-0.1.0a97}/src/payi/types/shared/evaluation_response.py +0 -0
  121. {payi-0.1.0a96 → payi-0.1.0a97}/src/payi/types/shared/ingest_units.py +0 -0
  122. {payi-0.1.0a96 → payi-0.1.0a97}/src/payi/types/shared/pay_i_common_models_budget_management_cost_details_base.py +0 -0
  123. {payi-0.1.0a96 → payi-0.1.0a97}/src/payi/types/shared/pay_i_common_models_budget_management_create_limit_base.py +0 -0
  124. {payi-0.1.0a96 → payi-0.1.0a97}/src/payi/types/shared/properties_response.py +0 -0
  125. {payi-0.1.0a96 → payi-0.1.0a97}/src/payi/types/shared/xproxy_error.py +0 -0
  126. {payi-0.1.0a96 → payi-0.1.0a97}/src/payi/types/shared/xproxy_result.py +0 -0
  127. {payi-0.1.0a96 → payi-0.1.0a97}/src/payi/types/shared_params/__init__.py +0 -0
  128. {payi-0.1.0a96 → payi-0.1.0a97}/src/payi/types/shared_params/ingest_units.py +0 -0
  129. {payi-0.1.0a96 → payi-0.1.0a97}/src/payi/types/shared_params/pay_i_common_models_budget_management_create_limit_base.py +0 -0
  130. {payi-0.1.0a96 → payi-0.1.0a97}/src/payi/types/total_cost_data.py +0 -0
  131. {payi-0.1.0a96 → payi-0.1.0a97}/src/payi/types/use_case_create_response.py +0 -0
  132. {payi-0.1.0a96 → payi-0.1.0a97}/src/payi/types/use_case_delete_response.py +0 -0
  133. {payi-0.1.0a96 → payi-0.1.0a97}/src/payi/types/use_case_retrieve_response.py +0 -0
  134. {payi-0.1.0a96 → payi-0.1.0a97}/src/payi/types/use_cases/__init__.py +0 -0
  135. {payi-0.1.0a96 → payi-0.1.0a97}/src/payi/types/use_cases/definition_create_params.py +0 -0
  136. {payi-0.1.0a96 → payi-0.1.0a97}/src/payi/types/use_cases/definition_list_params.py +0 -0
  137. {payi-0.1.0a96 → payi-0.1.0a97}/src/payi/types/use_cases/definition_update_params.py +0 -0
  138. {payi-0.1.0a96 → payi-0.1.0a97}/src/payi/types/use_cases/definitions/__init__.py +0 -0
  139. {payi-0.1.0a96 → payi-0.1.0a97}/src/payi/types/use_cases/definitions/kpi_create_params.py +0 -0
  140. {payi-0.1.0a96 → payi-0.1.0a97}/src/payi/types/use_cases/definitions/kpi_create_response.py +0 -0
  141. {payi-0.1.0a96 → payi-0.1.0a97}/src/payi/types/use_cases/definitions/kpi_delete_response.py +0 -0
  142. {payi-0.1.0a96 → payi-0.1.0a97}/src/payi/types/use_cases/definitions/kpi_list_params.py +0 -0
  143. {payi-0.1.0a96 → payi-0.1.0a97}/src/payi/types/use_cases/definitions/kpi_list_response.py +0 -0
  144. {payi-0.1.0a96 → payi-0.1.0a97}/src/payi/types/use_cases/definitions/kpi_retrieve_response.py +0 -0
  145. {payi-0.1.0a96 → payi-0.1.0a97}/src/payi/types/use_cases/definitions/kpi_update_params.py +0 -0
  146. {payi-0.1.0a96 → payi-0.1.0a97}/src/payi/types/use_cases/definitions/kpi_update_response.py +0 -0
  147. {payi-0.1.0a96 → payi-0.1.0a97}/src/payi/types/use_cases/definitions/limit_config_create_params.py +0 -0
  148. {payi-0.1.0a96 → payi-0.1.0a97}/src/payi/types/use_cases/kpi_list_params.py +0 -0
  149. {payi-0.1.0a96 → payi-0.1.0a97}/src/payi/types/use_cases/kpi_list_response.py +0 -0
  150. {payi-0.1.0a96 → payi-0.1.0a97}/src/payi/types/use_cases/kpi_update_params.py +0 -0
  151. {payi-0.1.0a96 → payi-0.1.0a97}/src/payi/types/use_cases/property_create_params.py +0 -0
  152. {payi-0.1.0a96 → payi-0.1.0a97}/src/payi/types/use_cases/property_create_response.py +0 -0
  153. {payi-0.1.0a96 → payi-0.1.0a97}/src/payi/types/use_cases/use_case_definition.py +0 -0
  154. {payi-0.1.0a96 → payi-0.1.0a97}/tests/__init__.py +0 -0
  155. {payi-0.1.0a96 → payi-0.1.0a97}/tests/api_resources/__init__.py +0 -0
  156. {payi-0.1.0a96 → payi-0.1.0a97}/tests/api_resources/categories/__init__.py +0 -0
  157. {payi-0.1.0a96 → payi-0.1.0a97}/tests/api_resources/categories/test_fixed_cost_resources.py +0 -0
  158. {payi-0.1.0a96 → payi-0.1.0a97}/tests/api_resources/categories/test_resources.py +0 -0
  159. {payi-0.1.0a96 → payi-0.1.0a97}/tests/api_resources/limits/__init__.py +0 -0
  160. {payi-0.1.0a96 → payi-0.1.0a97}/tests/api_resources/limits/test_tags.py +0 -0
  161. {payi-0.1.0a96 → payi-0.1.0a97}/tests/api_resources/requests/__init__.py +0 -0
  162. {payi-0.1.0a96 → payi-0.1.0a97}/tests/api_resources/requests/test_properties.py +0 -0
  163. {payi-0.1.0a96 → payi-0.1.0a97}/tests/api_resources/requests/test_result.py +0 -0
  164. {payi-0.1.0a96 → payi-0.1.0a97}/tests/api_resources/test_categories.py +0 -0
  165. {payi-0.1.0a96 → payi-0.1.0a97}/tests/api_resources/test_ingest.py +0 -0
  166. {payi-0.1.0a96 → payi-0.1.0a97}/tests/api_resources/test_limits.py +0 -0
  167. {payi-0.1.0a96 → payi-0.1.0a97}/tests/api_resources/test_use_cases.py +0 -0
  168. {payi-0.1.0a96 → payi-0.1.0a97}/tests/api_resources/use_cases/__init__.py +0 -0
  169. {payi-0.1.0a96 → payi-0.1.0a97}/tests/api_resources/use_cases/definitions/__init__.py +0 -0
  170. {payi-0.1.0a96 → payi-0.1.0a97}/tests/api_resources/use_cases/definitions/test_kpis.py +0 -0
  171. {payi-0.1.0a96 → payi-0.1.0a97}/tests/api_resources/use_cases/definitions/test_limit_config.py +0 -0
  172. {payi-0.1.0a96 → payi-0.1.0a97}/tests/api_resources/use_cases/definitions/test_version.py +0 -0
  173. {payi-0.1.0a96 → payi-0.1.0a97}/tests/api_resources/use_cases/test_definitions.py +0 -0
  174. {payi-0.1.0a96 → payi-0.1.0a97}/tests/api_resources/use_cases/test_kpis.py +0 -0
  175. {payi-0.1.0a96 → payi-0.1.0a97}/tests/api_resources/use_cases/test_properties.py +0 -0
  176. {payi-0.1.0a96 → payi-0.1.0a97}/tests/conftest.py +0 -0
  177. {payi-0.1.0a96 → payi-0.1.0a97}/tests/sample_file.txt +0 -0
  178. {payi-0.1.0a96 → payi-0.1.0a97}/tests/test_client.py +0 -0
  179. {payi-0.1.0a96 → payi-0.1.0a97}/tests/test_deepcopy.py +0 -0
  180. {payi-0.1.0a96 → payi-0.1.0a97}/tests/test_extract_files.py +0 -0
  181. {payi-0.1.0a96 → payi-0.1.0a97}/tests/test_files.py +0 -0
  182. {payi-0.1.0a96 → payi-0.1.0a97}/tests/test_models.py +0 -0
  183. {payi-0.1.0a96 → payi-0.1.0a97}/tests/test_qs.py +0 -0
  184. {payi-0.1.0a96 → payi-0.1.0a97}/tests/test_required_args.py +0 -0
  185. {payi-0.1.0a96 → payi-0.1.0a97}/tests/test_response.py +0 -0
  186. {payi-0.1.0a96 → payi-0.1.0a97}/tests/test_streaming.py +0 -0
  187. {payi-0.1.0a96 → payi-0.1.0a97}/tests/test_transform.py +0 -0
  188. {payi-0.1.0a96 → payi-0.1.0a97}/tests/test_utils/test_proxy.py +0 -0
  189. {payi-0.1.0a96 → payi-0.1.0a97}/tests/test_utils/test_typing.py +0 -0
  190. {payi-0.1.0a96 → payi-0.1.0a97}/tests/utils.py +0 -0
@@ -0,0 +1,3 @@
1
+ {
2
+ ".": "0.1.0-alpha.97"
3
+ }
@@ -1,5 +1,9 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.1.0-alpha.97 (2025-07-08)
4
+
5
+ Full Changelog: [v0.1.0-alpha.96...v0.1.0-alpha.97](https://github.com/Pay-i/pay-i-python/compare/v0.1.0-alpha.96...v0.1.0-alpha.97)
6
+
3
7
  ## 0.1.0-alpha.96 (2025-07-07)
4
8
 
5
9
  Full Changelog: [v0.1.0-alpha.95...v0.1.0-alpha.96](https://github.com/Pay-i/pay-i-python/compare/v0.1.0-alpha.95...v0.1.0-alpha.96)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: payi
3
- Version: 0.1.0a96
3
+ Version: 0.1.0a97
4
4
  Summary: The official Python library for the payi API
5
5
  Project-URL: Homepage, https://github.com/Pay-i/pay-i-python
6
6
  Project-URL: Repository, https://github.com/Pay-i/pay-i-python
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "payi"
3
- version = "0.1.0-alpha.96"
3
+ version = "0.1.0-alpha.97"
4
4
  description = "The official Python library for the payi API"
5
5
  dynamic = ["readme"]
6
6
  license = "Apache-2.0"
@@ -1,4 +1,4 @@
1
1
  # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
2
2
 
3
3
  __title__ = "payi"
4
- __version__ = "0.1.0-alpha.96" # x-release-please-version
4
+ __version__ = "0.1.0-alpha.97" # x-release-please-version
@@ -10,6 +10,8 @@ from .instrument import _ChunkResult, _StreamingType, _ProviderRequest, _PayiIns
10
10
 
11
11
 
12
12
  class _VertexRequest(_ProviderRequest): # type: ignore
13
+ KNOWN_MODALITIES = ("VIDEO", "AUDIO", "TEXT", "VISION", "IMAGE")
14
+
13
15
  def __init__(self, instrumentor: _PayiInstrumentor):
14
16
  super().__init__(
15
17
  instrumentor=instrumentor,
@@ -154,6 +156,7 @@ class _VertexRequest(_ProviderRequest): # type: ignore
154
156
 
155
157
  prompt_tokens_details: list[dict[str, Any]] = usage.get("prompt_tokens_details", [])
156
158
  candidates_tokens_details: list[dict[str, Any]] = usage.get("candidates_tokens_details", [])
159
+ cache_tokens_details: list[dict[str, Any]] = usage.get("cache_tokens_details", [])
157
160
 
158
161
  if not model:
159
162
  model = ""
@@ -214,27 +217,50 @@ class _VertexRequest(_ProviderRequest): # type: ignore
214
217
  if is_large_context_token_model(model, input):
215
218
  large_context = "_large_context"
216
219
 
220
+ cache_details: dict[str, int] = {}
221
+
222
+ for details in cache_tokens_details:
223
+ modality = details.get("modality", "")
224
+ if not modality:
225
+ continue
226
+
227
+ modality_token_count = details.get("token_count", 0)
228
+
229
+ if modality == "IMAGE":
230
+ modality = "VISION"
231
+
232
+ if modality in _VertexRequest.KNOWN_MODALITIES:
233
+ cache_details[modality] = modality_token_count
234
+ add_units(self, modality.lower() + "_cache_read" + large_context, input=modality_token_count)
235
+
217
236
  for details in prompt_tokens_details:
218
237
  modality = details.get("modality", "")
219
238
  if not modality:
220
239
  continue
221
240
 
222
241
  modality_token_count = details.get("token_count", 0)
242
+
223
243
  if modality == "IMAGE":
224
- add_units(self, "vision"+large_context, input=modality_token_count)
225
- elif modality in ("VIDEO", "AUDIO", "TEXT"):
226
- add_units(self, modality.lower()+large_context, input=modality_token_count)
244
+ modality = "VISION"
245
+
246
+ if modality in _VertexRequest.KNOWN_MODALITIES:
247
+ # Subtract cache_details value if modality is present, floor at zero
248
+ if modality in cache_details:
249
+ modality_token_count = max(0, modality_token_count - cache_details[modality])
250
+
251
+ add_units(self, modality.lower() + large_context, input=modality_token_count)
252
+
227
253
  for details in candidates_tokens_details:
228
254
  modality = details.get("modality", "")
229
255
  if not modality:
230
256
  continue
231
257
 
232
258
  modality_token_count = details.get("token_count", 0)
233
- if modality in ("VIDEO", "AUDIO", "TEXT", "IMAGE"):
234
- add_units(self, modality.lower()+large_context, output=modality_token_count)
259
+ if modality in _VertexRequest.KNOWN_MODALITIES:
260
+ add_units(self, modality.lower() + large_context, output=modality_token_count)
235
261
 
236
262
  if thinking_token_count > 0:
237
- add_units(self, "reasoning"+large_context, output=thinking_token_count)
263
+ add_units(self, "reasoning" + large_context, output=thinking_token_count)
238
264
 
239
265
  if not self._ingest["units"]:
240
266
  input = usage.get("prompt_token_count", 0)
@@ -15,11 +15,13 @@ from dataclasses import dataclass
15
15
  import nest_asyncio # type: ignore
16
16
  from wrapt import ObjectProxy # type: ignore
17
17
 
18
- from payi import Payi, AsyncPayi, APIConnectionError, __version__ as _payi_version
18
+ from payi import Payi, AsyncPayi, APIStatusError, APIConnectionError, __version__ as _payi_version
19
19
  from payi.types import IngestUnitsParams
20
20
  from payi.lib.helpers import PayiHeaderNames
21
+ from payi.types.shared import XproxyResult
21
22
  from payi.types.ingest_response import IngestResponse
22
23
  from payi.types.ingest_units_params import Units, ProviderResponseFunctionCall
24
+ from payi.types.shared.xproxy_error import XproxyError
23
25
  from payi.types.pay_i_common_models_api_router_header_info_param import PayICommonModelsAPIRouterHeaderInfoParam
24
26
 
25
27
  from .helpers import PayiCategories
@@ -146,6 +148,19 @@ class PayiInstrumentConfig(TypedDict, total=False):
146
148
  user_id: Optional[str]
147
149
  request_tags: Optional["list[str]"]
148
150
 
151
+ class PayiContext(TypedDict, total=False):
152
+ use_case_name: Optional[str]
153
+ use_case_id: Optional[str]
154
+ use_case_version: Optional[int]
155
+ use_case_step: Optional[str]
156
+ limit_ids: Optional['list[str]']
157
+ user_id: Optional[str]
158
+ request_tags: Optional["list[str]"]
159
+ price_as_category: Optional[str]
160
+ price_as_resource: Optional[str]
161
+ resource_scope: Optional[str]
162
+ last_result: Optional[Union[XproxyResult, XproxyError]]
163
+
149
164
  class _Context(TypedDict, total=False):
150
165
  proxy: Optional[bool]
151
166
  use_case_name: Optional[str]
@@ -169,7 +184,7 @@ class _StreamingType(Enum):
169
184
  iterator = 1
170
185
  stream_manager = 2
171
186
 
172
- class _TrackContext:
187
+ class _InternalTrackContext:
173
188
  def __init__(
174
189
  self,
175
190
  context: _Context,
@@ -235,6 +250,8 @@ class _PayiInstrumentor:
235
250
 
236
251
  self._instrument_inline_data: bool = global_config.get("instrument_inline_data", False)
237
252
 
253
+ self._last_result: Optional[Union[XproxyResult, XproxyError]] = None
254
+
238
255
  global_instrumentation = global_config.pop("global_instrumentation", True)
239
256
 
240
257
  if instruments is None or "*" in instruments:
@@ -354,7 +371,7 @@ class _PayiInstrumentor:
354
371
 
355
372
  return log_ingest_units
356
373
 
357
- def _process_ingest_units(self, request: _ProviderRequest, log_data: 'dict[str, str]') -> bool:
374
+ def _process_ingest_units(self, request: _ProviderRequest, log_data: 'dict[str, str]') -> None:
358
375
  ingest_units = request._ingest
359
376
 
360
377
  if request._function_call_builder:
@@ -394,8 +411,6 @@ class _PayiInstrumentor:
394
411
  if stack_trace is not None:
395
412
  log_data["stack_trace"] = stack_trace
396
413
 
397
- return True
398
-
399
414
  def _process_ingest_units_response(self, ingest_response: IngestResponse) -> None:
400
415
  if ingest_response.xproxy_result.limits:
401
416
  for limit_id, state in ingest_response.xproxy_result.limits.items():
@@ -413,7 +428,7 @@ class _PayiInstrumentor:
413
428
  if removeBlockedId:
414
429
  self._blocked_limits.discard(limit_id)
415
430
 
416
- def _process_ingest_connection_error(self, e: APIConnectionError, ingest_units: IngestUnitsParams) -> None:
431
+ def _process_ingest_connection_error(self, e: APIConnectionError, ingest_units: IngestUnitsParams) -> XproxyError:
417
432
  now = time.time()
418
433
 
419
434
  if (now - self._api_connection_error_last_log_time) > self._api_connection_error_window:
@@ -430,7 +445,9 @@ class _PayiInstrumentor:
430
445
  # Suppress and count
431
446
  self._api_connection_error_count += 1
432
447
 
433
- async def _aingest_units(self, request: _ProviderRequest) -> Optional[IngestResponse]:
448
+ return XproxyError(code="api_connection_error", message=str(e))
449
+
450
+ async def _aingest_units_worker(self, request: _ProviderRequest) -> Optional[Union[XproxyResult, XproxyError]]:
434
451
  ingest_response: Optional[IngestResponse] = None
435
452
  ingest_units = request._ingest
436
453
 
@@ -438,9 +455,8 @@ class _PayiInstrumentor:
438
455
 
439
456
  # return early if there are no units to ingest and on a successul ingest request
440
457
  log_data: 'dict[str,str]' = {}
441
- if not self._process_ingest_units(request, log_data):
442
- self._logger.debug(f"_aingest_units: exit early")
443
- return None
458
+
459
+ self._process_ingest_units(request, log_data)
444
460
 
445
461
  try:
446
462
  if self._logger.isEnabledFor(logging.DEBUG):
@@ -452,7 +468,7 @@ class _PayiInstrumentor:
452
468
  ingest_response = self._payi.ingest.units(**ingest_units)
453
469
  else:
454
470
  self._logger.error("No payi instance to ingest units")
455
- return None
471
+ return XproxyError(code="configuration_error", message="No Payi or AsyncPayi instance configured for ingesting units")
456
472
 
457
473
  self._logger.debug(f"_aingest_units: success ({ingest_response})")
458
474
 
@@ -463,15 +479,21 @@ class _PayiInstrumentor:
463
479
  request_id = ingest_response.xproxy_result.request_id
464
480
  self._prompt_and_response_logger(request_id, log_data) # type: ignore
465
481
 
466
- return ingest_response
467
- except Exception as e:
468
- if isinstance(e, APIConnectionError) and self._api_connection_error_window > 0:
469
- self._process_ingest_connection_error(e, ingest_units)
470
- else:
471
- self._logger.error(f"Error Pay-i async ingesting: exception {e}, request {ingest_units}")
472
-
473
- return None
482
+ return ingest_response.xproxy_result
483
+
484
+ except APIConnectionError as api_ex:
485
+ return self._process_ingest_connection_error(api_ex, ingest_units)
486
+
487
+ except APIStatusError as api_status_ex:
488
+ return self._process_api_status_error(api_status_ex)
489
+
490
+ except Exception as ex:
491
+ self._logger.error(f"Error Pay-i async ingesting: exception {ex}, request {ingest_units}")
492
+ return XproxyError(code="unknown_error", message=str(ex))
474
493
 
494
+ async def _aingest_units(self, request: _ProviderRequest) -> Optional[Union[XproxyResult, XproxyError]]:
495
+ return self.set_xproxy_result(await self._aingest_units_worker(request))
496
+
475
497
  def _call_async_use_case_definition_create(self, use_case_name: str, use_case_description: str) -> None:
476
498
  if not self._apayi:
477
499
  return
@@ -491,7 +513,7 @@ class _PayiInstrumentor:
491
513
  except Exception as e:
492
514
  self._logger.error(f"Error calling async use_cases.definitions.create synchronously: {e}")
493
515
 
494
- def _call_aingest_sync(self, request: _ProviderRequest) -> Optional[IngestResponse]:
516
+ def _call_aingest_sync(self, request: _ProviderRequest) -> Optional[Union[XproxyResult, XproxyError]]:
495
517
  try:
496
518
  loop = asyncio.get_running_loop()
497
519
  except RuntimeError:
@@ -500,7 +522,7 @@ class _PayiInstrumentor:
500
522
  try:
501
523
  if loop and loop.is_running():
502
524
  nest_asyncio.apply(loop) # type: ignore
503
- return asyncio.run(self._aingest_units(request))
525
+ return asyncio.run(self._aingest_units(request))
504
526
  else:
505
527
  # When there's no running loop, create a new one
506
528
  return asyncio.run(self._aingest_units(request))
@@ -508,7 +530,41 @@ class _PayiInstrumentor:
508
530
  self._logger.error(f"Error calling aingest_units synchronously: {e}")
509
531
  return None
510
532
 
511
- def _ingest_units(self, request: _ProviderRequest) -> Optional[IngestResponse]:
533
+ def _process_api_status_error(self, e: APIStatusError) -> Optional[XproxyError]:
534
+ try:
535
+ body_dict: dict[str, Any] = {}
536
+
537
+ # Try to get the response body as JSON
538
+ body = e.body
539
+ if body is None:
540
+ self._logger.error("APIStatusError response has no body attribute")
541
+ return XproxyError(code="unknown_error", message=str(e))
542
+
543
+ # If body is bytes, decode to string
544
+ if isinstance(body, bytes):
545
+ body = body.decode("utf-8")
546
+ if isinstance(body, dict):
547
+ body_dict = body # type: ignore
548
+ else:
549
+ body = str(body)
550
+
551
+ if not body_dict:
552
+ try:
553
+ body_dict = json.loads(body) # type: ignore
554
+ except Exception as json_ex:
555
+ self._logger.error(f"Failed to parse response body as JSON: {json_ex}")
556
+ return XproxyError(code="invalid_json", message=str(e))
557
+
558
+ xproxy_error = body_dict.get("xproxy_error", {})
559
+ code = xproxy_error.get("code", "unknown_error")
560
+ message = xproxy_error.get("message", str(e))
561
+ return XproxyError(code=code, message=message)
562
+
563
+ except Exception as ex:
564
+ self._logger.error(f"Exception in _process_api_status_error: {ex}")
565
+ return XproxyError(code="exception", message=str(ex))
566
+
567
+ def _ingest_units_worker(self, request: _ProviderRequest) -> Optional[Union[XproxyResult, XproxyError]]:
512
568
  ingest_response: Optional[IngestResponse] = None
513
569
  ingest_units = request._ingest
514
570
 
@@ -516,9 +572,8 @@ class _PayiInstrumentor:
516
572
 
517
573
  # return early if there are no units to ingest and on a successul ingest request
518
574
  log_data: 'dict[str,str]' = {}
519
- if not self._process_ingest_units(request, log_data):
520
- self._logger.debug(f"_ingest_units: exit early")
521
- return None
575
+
576
+ self._process_ingest_units(request, log_data)
522
577
 
523
578
  try:
524
579
  if self._payi:
@@ -534,22 +589,28 @@ class _PayiInstrumentor:
534
589
  request_id = ingest_response.xproxy_result.request_id
535
590
  self._prompt_and_response_logger(request_id, log_data) # type: ignore
536
591
 
537
- return ingest_response
592
+ return ingest_response.xproxy_result
538
593
  elif self._apayi:
539
594
  # task runs async. aingest_units will invoke the callback and post process
540
- ingest_response = self._call_aingest_sync(request)
541
- self._logger.debug(f"_ingest_units: apayi success ({ingest_response})")
542
- return ingest_response
595
+ sync_response = self._call_aingest_sync(request)
596
+ self._logger.debug(f"_ingest_units: apayi success ({sync_response})")
597
+ return sync_response
543
598
  else:
544
599
  self._logger.error("No payi instance to ingest units")
600
+ return XproxyError(code="configuration_error", message="No Payi or AsyncPayi instance configured for ingesting units")
545
601
 
546
- except Exception as e:
547
- if isinstance(e, APIConnectionError) and self._api_connection_error_window > 0:
548
- self._process_ingest_connection_error(e, ingest_units)
549
- else:
550
- self._logger.error(f"Error Pay-i ingesting: exception {e}, request {ingest_units}")
602
+ except APIConnectionError as api_ex:
603
+ return self._process_ingest_connection_error(api_ex, ingest_units)
604
+
605
+ except APIStatusError as api_status_ex:
606
+ return self._process_api_status_error(api_status_ex)
607
+
608
+ except Exception as ex:
609
+ self._logger.error(f"Error Pay-i async ingesting: exception {ex}, request {ingest_units}")
610
+ return XproxyError(code="unknown_error", message=str(ex))
551
611
 
552
- return None
612
+ def _ingest_units(self, request: _ProviderRequest) -> Optional[Union[XproxyResult, XproxyError]]:
613
+ return self.set_xproxy_result(self._ingest_units_worker(request))
553
614
 
554
615
  def _setup_call_func(
555
616
  self
@@ -1040,6 +1101,10 @@ class _PayiInstrumentor:
1040
1101
 
1041
1102
  return extra_headers
1042
1103
 
1104
+ def set_xproxy_result(self, response: Optional[Union[XproxyResult, XproxyError]]) -> Optional[Union[XproxyResult, XproxyError]]:
1105
+ self._last_result = response
1106
+ return response
1107
+
1043
1108
  @staticmethod
1044
1109
  def _update_extra_headers(
1045
1110
  context: _Context,
@@ -1617,7 +1682,7 @@ def track_context(
1617
1682
  price_as_resource: Optional[str] = None,
1618
1683
  resource_scope: Optional[str] = None,
1619
1684
  proxy: Optional[bool] = None,
1620
- ) -> _TrackContext:
1685
+ ) -> _InternalTrackContext:
1621
1686
  # Create a new context for tracking
1622
1687
  context: _Context = {}
1623
1688
 
@@ -1637,4 +1702,22 @@ def track_context(
1637
1702
  context["price_as_resource"] = price_as_resource
1638
1703
  context["resource_scope"] = resource_scope
1639
1704
 
1640
- return _TrackContext(context)
1705
+ return _InternalTrackContext(context)
1706
+
1707
+ def get_context() -> PayiContext:
1708
+ """
1709
+ Returns the current tracking context from calls to @track and with track_context().
1710
+ If no context is active, returns an empty context.
1711
+ """
1712
+ if not _instrumentor:
1713
+ return PayiContext()
1714
+ internal_context = _instrumentor.get_context() or {}
1715
+
1716
+ context_dict = {
1717
+ key: value
1718
+ for key, value in internal_context.items()
1719
+ if key in PayiContext.__annotations__ and value is not None
1720
+ }
1721
+ if _instrumentor._last_result:
1722
+ context_dict["last_result"] = _instrumentor._last_result
1723
+ return PayiContext(**dict(context_dict)) # type: ignore
@@ -1,3 +0,0 @@
1
- {
2
- ".": "0.1.0-alpha.96"
3
- }
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes