ccproxy-api 0.2.4__tar.gz → 0.2.5__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.
Files changed (422) hide show
  1. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/PKG-INFO +19 -19
  2. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/core/_version.py +2 -2
  3. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/core/plugins/factories.py +25 -1
  4. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/llms/formatters/context.py +24 -0
  5. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/llms/formatters/openai_to_openai/responses.py +6 -1
  6. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/llms/formatters/openai_to_openai/streams.py +7 -5
  7. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/llms/models/anthropic.py +9 -1
  8. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/plugins/claude_api/adapter.py +4 -5
  9. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/plugins/codex/adapter.py +140 -27
  10. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/plugins/codex/config.py +7 -0
  11. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/plugins/codex/detection_service.py +61 -6
  12. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/plugins/codex/plugin.py +1 -0
  13. ccproxy_api-0.2.5/ccproxy/plugins/codex/routes.py +604 -0
  14. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/services/adapters/base.py +1 -0
  15. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/services/adapters/format_adapter.py +8 -0
  16. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/services/adapters/mock_adapter.py +59 -11
  17. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/services/factories.py +18 -0
  18. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/services/mocking/mock_handler.py +227 -18
  19. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/pyproject.toml +27 -27
  20. ccproxy_api-0.2.4/ccproxy/plugins/codex/routes.py +0 -129
  21. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/.gitignore +0 -0
  22. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/LICENSE +0 -0
  23. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/README.md +0 -0
  24. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/__main__.py +0 -0
  25. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/api/__init__.py +0 -0
  26. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/api/app.py +0 -0
  27. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/api/bootstrap.py +0 -0
  28. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/api/decorators.py +0 -0
  29. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/api/dependencies.py +0 -0
  30. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/api/format_validation.py +0 -0
  31. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/api/middleware/__init__.py +0 -0
  32. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/api/middleware/cors.py +0 -0
  33. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/api/middleware/errors.py +0 -0
  34. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/api/middleware/hooks.py +0 -0
  35. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/api/middleware/normalize_headers.py +0 -0
  36. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/api/middleware/request_id.py +0 -0
  37. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/api/middleware/streaming_hooks.py +0 -0
  38. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/api/routes/__init__.py +0 -0
  39. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/api/routes/health.py +0 -0
  40. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/api/routes/plugins.py +0 -0
  41. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/auth/__init__.py +0 -0
  42. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/auth/bearer.py +0 -0
  43. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/auth/dependencies.py +0 -0
  44. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/auth/exceptions.py +0 -0
  45. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/auth/manager.py +0 -0
  46. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/auth/managers/__init__.py +0 -0
  47. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/auth/managers/base.py +0 -0
  48. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/auth/managers/base_enhanced.py +0 -0
  49. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/auth/managers/token_snapshot.py +0 -0
  50. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/auth/models/__init__.py +0 -0
  51. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/auth/models/base.py +0 -0
  52. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/auth/models/credentials.py +0 -0
  53. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/auth/oauth/__init__.py +0 -0
  54. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/auth/oauth/base.py +0 -0
  55. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/auth/oauth/cli_errors.py +0 -0
  56. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/auth/oauth/flows.py +0 -0
  57. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/auth/oauth/protocol.py +0 -0
  58. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/auth/oauth/registry.py +0 -0
  59. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/auth/oauth/router.py +0 -0
  60. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/auth/oauth/routes.py +0 -0
  61. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/auth/oauth/session.py +0 -0
  62. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/auth/oauth/templates.py +0 -0
  63. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/auth/storage/__init__.py +0 -0
  64. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/auth/storage/base.py +0 -0
  65. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/auth/storage/generic.py +0 -0
  66. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/cli/__init__.py +0 -0
  67. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/cli/_settings_help.py +0 -0
  68. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/cli/commands/__init__.py +0 -0
  69. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/cli/commands/auth.py +0 -0
  70. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/cli/commands/config/__init__.py +0 -0
  71. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/cli/commands/config/commands.py +0 -0
  72. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/cli/commands/config/schema_commands.py +0 -0
  73. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/cli/commands/plugins.py +0 -0
  74. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/cli/commands/serve.py +0 -0
  75. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/cli/commands/status.py +0 -0
  76. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/cli/decorators.py +0 -0
  77. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/cli/helpers.py +0 -0
  78. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/cli/main.py +0 -0
  79. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/cli/options/__init__.py +0 -0
  80. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/cli/options/claude_options.py +0 -0
  81. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/cli/options/core_options.py +0 -0
  82. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/cli/options/security_options.py +0 -0
  83. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/cli/options/server_options.py +0 -0
  84. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/config/__init__.py +0 -0
  85. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/config/core.py +0 -0
  86. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/config/env_generator.py +0 -0
  87. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/config/runtime.py +0 -0
  88. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/config/security.py +0 -0
  89. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/config/settings.py +0 -0
  90. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/config/toml_generator.py +0 -0
  91. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/config/utils.py +0 -0
  92. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/core/__init__.py +0 -0
  93. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/core/async_task_manager.py +0 -0
  94. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/core/async_utils.py +0 -0
  95. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/core/auth/__init__.py +0 -0
  96. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/core/constants.py +0 -0
  97. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/core/errors.py +0 -0
  98. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/core/id_utils.py +0 -0
  99. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/core/interfaces.py +0 -0
  100. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/core/logging.py +0 -0
  101. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/core/middleware.py +0 -0
  102. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/core/plugins/__init__.py +0 -0
  103. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/core/plugins/cli_discovery.py +0 -0
  104. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/core/plugins/declaration.py +0 -0
  105. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/core/plugins/discovery.py +0 -0
  106. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/core/plugins/hooks/__init__.py +0 -0
  107. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/core/plugins/hooks/base.py +0 -0
  108. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/core/plugins/hooks/events.py +0 -0
  109. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/core/plugins/hooks/implementations/__init__.py +0 -0
  110. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/core/plugins/hooks/implementations/formatters/__init__.py +0 -0
  111. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/core/plugins/hooks/implementations/formatters/json.py +0 -0
  112. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/core/plugins/hooks/implementations/formatters/raw.py +0 -0
  113. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/core/plugins/hooks/implementations/http_tracer.py +0 -0
  114. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/core/plugins/hooks/layers.py +0 -0
  115. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/core/plugins/hooks/manager.py +0 -0
  116. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/core/plugins/hooks/registry.py +0 -0
  117. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/core/plugins/hooks/thread_manager.py +0 -0
  118. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/core/plugins/hooks/types.py +0 -0
  119. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/core/plugins/interfaces.py +0 -0
  120. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/core/plugins/loader.py +0 -0
  121. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/core/plugins/middleware.py +0 -0
  122. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/core/plugins/models.py +0 -0
  123. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/core/plugins/protocol.py +0 -0
  124. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/core/plugins/runtime.py +0 -0
  125. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/core/request_context.py +0 -0
  126. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/core/status_report.py +0 -0
  127. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/core/system.py +0 -0
  128. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/core/transformers.py +0 -0
  129. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/core/types.py +0 -0
  130. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/data/claude_headers_fallback.json +0 -0
  131. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/data/codex_headers_fallback.json +0 -0
  132. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/http/__init__.py +0 -0
  133. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/http/base.py +0 -0
  134. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/http/client.py +0 -0
  135. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/http/hooks.py +0 -0
  136. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/http/pool.py +0 -0
  137. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/llms/formatters/__init__.py +0 -0
  138. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/llms/formatters/anthropic_to_openai/__init__.py +0 -0
  139. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/llms/formatters/anthropic_to_openai/_helpers.py +0 -0
  140. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/llms/formatters/anthropic_to_openai/errors.py +0 -0
  141. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/llms/formatters/anthropic_to_openai/requests.py +0 -0
  142. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/llms/formatters/anthropic_to_openai/responses.py +0 -0
  143. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/llms/formatters/anthropic_to_openai/streams.py +0 -0
  144. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/llms/formatters/base.py +0 -0
  145. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/llms/formatters/base_model.py +0 -0
  146. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/llms/formatters/common/__init__.py +0 -0
  147. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/llms/formatters/common/identifiers.py +0 -0
  148. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/llms/formatters/common/streams.py +0 -0
  149. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/llms/formatters/common/thinking.py +0 -0
  150. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/llms/formatters/common/usage.py +0 -0
  151. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/llms/formatters/constants.py +0 -0
  152. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/llms/formatters/mapping.py +0 -0
  153. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/llms/formatters/openai_to_anthropic/__init__.py +0 -0
  154. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/llms/formatters/openai_to_anthropic/_helpers.py +0 -0
  155. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/llms/formatters/openai_to_anthropic/errors.py +0 -0
  156. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/llms/formatters/openai_to_anthropic/requests.py +0 -0
  157. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/llms/formatters/openai_to_anthropic/responses.py +0 -0
  158. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/llms/formatters/openai_to_anthropic/streams.py +0 -0
  159. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/llms/formatters/openai_to_openai/__init__.py +0 -0
  160. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/llms/formatters/openai_to_openai/_helpers.py +0 -0
  161. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/llms/formatters/openai_to_openai/errors.py +0 -0
  162. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/llms/formatters/openai_to_openai/requests.py +0 -0
  163. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/llms/formatters/utils.py +0 -0
  164. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/llms/models/__init__.py +0 -0
  165. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/llms/models/openai.py +0 -0
  166. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/llms/streaming/__init__.py +0 -0
  167. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/llms/streaming/accumulators.py +0 -0
  168. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/llms/streaming/formatters.py +0 -0
  169. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/llms/streaming/processors.py +0 -0
  170. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/models/__init__.py +0 -0
  171. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/models/detection.py +0 -0
  172. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/models/provider.py +0 -0
  173. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/plugins/access_log/README.md +0 -0
  174. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/plugins/access_log/__init__.py +0 -0
  175. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/plugins/access_log/config.py +0 -0
  176. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/plugins/access_log/formatter.py +0 -0
  177. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/plugins/access_log/hook.py +0 -0
  178. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/plugins/access_log/logger.py +0 -0
  179. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/plugins/access_log/plugin.py +0 -0
  180. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/plugins/access_log/writer.py +0 -0
  181. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/plugins/analytics/README.md +0 -0
  182. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/plugins/analytics/__init__.py +0 -0
  183. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/plugins/analytics/config.py +0 -0
  184. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/plugins/analytics/ingest.py +0 -0
  185. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/plugins/analytics/models.py +0 -0
  186. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/plugins/analytics/plugin.py +0 -0
  187. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/plugins/analytics/routes.py +0 -0
  188. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/plugins/analytics/service.py +0 -0
  189. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/plugins/claude_api/README.md +0 -0
  190. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/plugins/claude_api/__init__.py +0 -0
  191. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/plugins/claude_api/config.py +0 -0
  192. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/plugins/claude_api/detection_service.py +0 -0
  193. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/plugins/claude_api/health.py +0 -0
  194. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/plugins/claude_api/hooks.py +0 -0
  195. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/plugins/claude_api/models.py +0 -0
  196. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/plugins/claude_api/plugin.py +0 -0
  197. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/plugins/claude_api/routes.py +0 -0
  198. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/plugins/claude_api/streaming_metrics.py +0 -0
  199. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/plugins/claude_api/tasks.py +0 -0
  200. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/plugins/claude_sdk/README.md +0 -0
  201. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/plugins/claude_sdk/__init__.py +0 -0
  202. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/plugins/claude_sdk/adapter.py +0 -0
  203. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/plugins/claude_sdk/auth.py +0 -0
  204. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/plugins/claude_sdk/client.py +0 -0
  205. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/plugins/claude_sdk/config.py +0 -0
  206. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/plugins/claude_sdk/converter.py +0 -0
  207. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/plugins/claude_sdk/detection_service.py +0 -0
  208. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/plugins/claude_sdk/exceptions.py +0 -0
  209. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/plugins/claude_sdk/handler.py +0 -0
  210. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/plugins/claude_sdk/health.py +0 -0
  211. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/plugins/claude_sdk/hooks.py +0 -0
  212. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/plugins/claude_sdk/manager.py +0 -0
  213. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/plugins/claude_sdk/message_queue.py +0 -0
  214. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/plugins/claude_sdk/models.py +0 -0
  215. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/plugins/claude_sdk/options.py +0 -0
  216. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/plugins/claude_sdk/parser.py +0 -0
  217. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/plugins/claude_sdk/plugin.py +0 -0
  218. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/plugins/claude_sdk/routes.py +0 -0
  219. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/plugins/claude_sdk/session_client.py +0 -0
  220. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/plugins/claude_sdk/session_pool.py +0 -0
  221. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/plugins/claude_sdk/stream_handle.py +0 -0
  222. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/plugins/claude_sdk/stream_worker.py +0 -0
  223. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/plugins/claude_sdk/streaming.py +0 -0
  224. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/plugins/claude_sdk/tasks.py +0 -0
  225. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/plugins/claude_shared/README.md +0 -0
  226. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/plugins/claude_shared/__init__.py +0 -0
  227. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/plugins/claude_shared/model_defaults.py +0 -0
  228. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/plugins/codex/README.md +0 -0
  229. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/plugins/codex/__init__.py +0 -0
  230. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/plugins/codex/health.py +0 -0
  231. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/plugins/codex/hooks.py +0 -0
  232. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/plugins/codex/model_defaults.py +0 -0
  233. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/plugins/codex/models.py +0 -0
  234. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/plugins/codex/streaming_metrics.py +0 -0
  235. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/plugins/codex/tasks.py +0 -0
  236. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/plugins/codex/utils/__init__.py +0 -0
  237. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/plugins/codex/utils/sse_parser.py +0 -0
  238. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/plugins/command_replay/README.md +0 -0
  239. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/plugins/command_replay/__init__.py +0 -0
  240. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/plugins/command_replay/config.py +0 -0
  241. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/plugins/command_replay/formatter.py +0 -0
  242. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/plugins/command_replay/hook.py +0 -0
  243. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/plugins/command_replay/plugin.py +0 -0
  244. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/plugins/copilot/README.md +0 -0
  245. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/plugins/copilot/__init__.py +0 -0
  246. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/plugins/copilot/adapter.py +0 -0
  247. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/plugins/copilot/config.py +0 -0
  248. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/plugins/copilot/data/copilot_fallback.json +0 -0
  249. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/plugins/copilot/detection_service.py +0 -0
  250. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/plugins/copilot/manager.py +0 -0
  251. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/plugins/copilot/model_defaults.py +0 -0
  252. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/plugins/copilot/models.py +0 -0
  253. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/plugins/copilot/oauth/__init__.py +0 -0
  254. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/plugins/copilot/oauth/client.py +0 -0
  255. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/plugins/copilot/oauth/models.py +0 -0
  256. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/plugins/copilot/oauth/provider.py +0 -0
  257. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/plugins/copilot/oauth/storage.py +0 -0
  258. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/plugins/copilot/plugin.py +0 -0
  259. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/plugins/copilot/routes.py +0 -0
  260. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/plugins/credential_balancer/README.md +0 -0
  261. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/plugins/credential_balancer/__init__.py +0 -0
  262. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/plugins/credential_balancer/config.py +0 -0
  263. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/plugins/credential_balancer/factory.py +0 -0
  264. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/plugins/credential_balancer/hook.py +0 -0
  265. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/plugins/credential_balancer/manager.py +0 -0
  266. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/plugins/credential_balancer/plugin.py +0 -0
  267. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/plugins/dashboard/README.md +0 -0
  268. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/plugins/dashboard/__init__.py +0 -0
  269. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/plugins/dashboard/config.py +0 -0
  270. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/plugins/dashboard/plugin.py +0 -0
  271. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/plugins/dashboard/routes.py +0 -0
  272. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/plugins/docker/README.md +0 -0
  273. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/plugins/docker/__init__.py +0 -0
  274. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/plugins/docker/adapter.py +0 -0
  275. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/plugins/docker/config.py +0 -0
  276. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/plugins/docker/docker_path.py +0 -0
  277. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/plugins/docker/middleware.py +0 -0
  278. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/plugins/docker/models.py +0 -0
  279. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/plugins/docker/plugin.py +0 -0
  280. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/plugins/docker/protocol.py +0 -0
  281. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/plugins/docker/stream_process.py +0 -0
  282. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/plugins/docker/validators.py +0 -0
  283. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/plugins/duckdb_storage/README.md +0 -0
  284. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/plugins/duckdb_storage/__init__.py +0 -0
  285. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/plugins/duckdb_storage/config.py +0 -0
  286. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/plugins/duckdb_storage/plugin.py +0 -0
  287. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/plugins/duckdb_storage/routes.py +0 -0
  288. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/plugins/duckdb_storage/storage.py +0 -0
  289. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/plugins/max_tokens/README.md +0 -0
  290. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/plugins/max_tokens/__init__.py +0 -0
  291. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/plugins/max_tokens/adapter.py +0 -0
  292. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/plugins/max_tokens/config.py +0 -0
  293. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/plugins/max_tokens/models.py +0 -0
  294. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/plugins/max_tokens/plugin.py +0 -0
  295. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/plugins/max_tokens/service.py +0 -0
  296. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/plugins/max_tokens/token_limits.json +0 -0
  297. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/plugins/metrics/README.md +0 -0
  298. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/plugins/metrics/__init__.py +0 -0
  299. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/plugins/metrics/collector.py +0 -0
  300. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/plugins/metrics/config.py +0 -0
  301. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/plugins/metrics/grafana/dashboards/ccproxy-dashboard.json +0 -0
  302. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/plugins/metrics/hook.py +0 -0
  303. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/plugins/metrics/plugin.py +0 -0
  304. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/plugins/metrics/pushgateway.py +0 -0
  305. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/plugins/metrics/routes.py +0 -0
  306. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/plugins/metrics/tasks.py +0 -0
  307. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/plugins/oauth_claude/README.md +0 -0
  308. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/plugins/oauth_claude/__init__.py +0 -0
  309. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/plugins/oauth_claude/client.py +0 -0
  310. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/plugins/oauth_claude/config.py +0 -0
  311. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/plugins/oauth_claude/manager.py +0 -0
  312. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/plugins/oauth_claude/models.py +0 -0
  313. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/plugins/oauth_claude/plugin.py +0 -0
  314. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/plugins/oauth_claude/provider.py +0 -0
  315. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/plugins/oauth_claude/storage.py +0 -0
  316. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/plugins/oauth_codex/README.md +0 -0
  317. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/plugins/oauth_codex/__init__.py +0 -0
  318. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/plugins/oauth_codex/client.py +0 -0
  319. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/plugins/oauth_codex/config.py +0 -0
  320. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/plugins/oauth_codex/manager.py +0 -0
  321. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/plugins/oauth_codex/models.py +0 -0
  322. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/plugins/oauth_codex/plugin.py +0 -0
  323. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/plugins/oauth_codex/provider.py +0 -0
  324. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/plugins/oauth_codex/storage.py +0 -0
  325. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/plugins/permissions/README.md +0 -0
  326. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/plugins/permissions/__init__.py +0 -0
  327. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/plugins/permissions/config.py +0 -0
  328. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/plugins/permissions/handlers/__init__.py +0 -0
  329. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/plugins/permissions/handlers/cli.py +0 -0
  330. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/plugins/permissions/handlers/protocol.py +0 -0
  331. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/plugins/permissions/handlers/terminal.py +0 -0
  332. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/plugins/permissions/mcp.py +0 -0
  333. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/plugins/permissions/models.py +0 -0
  334. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/plugins/permissions/plugin.py +0 -0
  335. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/plugins/permissions/routes.py +0 -0
  336. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/plugins/permissions/service.py +0 -0
  337. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/plugins/permissions/ui/__init__.py +0 -0
  338. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/plugins/permissions/ui/permission_handler_protocol.py +0 -0
  339. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/plugins/permissions/ui/terminal_permission_handler.py +0 -0
  340. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/plugins/pricing/README.md +0 -0
  341. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/plugins/pricing/__init__.py +0 -0
  342. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/plugins/pricing/cache.py +0 -0
  343. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/plugins/pricing/config.py +0 -0
  344. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/plugins/pricing/exceptions.py +0 -0
  345. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/plugins/pricing/loader.py +0 -0
  346. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/plugins/pricing/models.py +0 -0
  347. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/plugins/pricing/plugin.py +0 -0
  348. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/plugins/pricing/service.py +0 -0
  349. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/plugins/pricing/tasks.py +0 -0
  350. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/plugins/pricing/updater.py +0 -0
  351. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/plugins/pricing/utils.py +0 -0
  352. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/plugins/request_tracer/README.md +0 -0
  353. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/plugins/request_tracer/__init__.py +0 -0
  354. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/plugins/request_tracer/config.py +0 -0
  355. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/plugins/request_tracer/hook.py +0 -0
  356. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/plugins/request_tracer/plugin.py +0 -0
  357. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/scheduler/__init__.py +0 -0
  358. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/scheduler/core.py +0 -0
  359. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/scheduler/errors.py +0 -0
  360. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/scheduler/manager.py +0 -0
  361. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/scheduler/registry.py +0 -0
  362. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/scheduler/tasks.py +0 -0
  363. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/services/__init__.py +0 -0
  364. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/services/adapters/__init__.py +0 -0
  365. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/services/adapters/chain_composer.py +0 -0
  366. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/services/adapters/chain_validation.py +0 -0
  367. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/services/adapters/chat_accumulator.py +0 -0
  368. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/services/adapters/delta_utils.py +0 -0
  369. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/services/adapters/format_context.py +0 -0
  370. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/services/adapters/format_registry.py +0 -0
  371. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/services/adapters/http_adapter.py +0 -0
  372. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/services/adapters/protocols.py +0 -0
  373. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/services/adapters/simple_converters.py +0 -0
  374. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/services/auth_registry.py +0 -0
  375. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/services/cache/__init__.py +0 -0
  376. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/services/cache/response_cache.py +0 -0
  377. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/services/cli_detection.py +0 -0
  378. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/services/config/__init__.py +0 -0
  379. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/services/config/proxy_configuration.py +0 -0
  380. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/services/container.py +0 -0
  381. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/services/handler_config.py +0 -0
  382. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/services/interfaces.py +0 -0
  383. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/services/mocking/__init__.py +0 -0
  384. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/services/tracing/__init__.py +0 -0
  385. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/services/tracing/interfaces.py +0 -0
  386. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/services/tracing/null_tracer.py +0 -0
  387. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/streaming/__init__.py +0 -0
  388. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/streaming/buffer.py +0 -0
  389. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/streaming/deferred.py +0 -0
  390. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/streaming/handler.py +0 -0
  391. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/streaming/interfaces.py +0 -0
  392. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/streaming/simple_adapter.py +0 -0
  393. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/streaming/sse.py +0 -0
  394. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/streaming/sse_parser.py +0 -0
  395. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/templates/__init__.py +0 -0
  396. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/templates/plugin_scaffold.py +0 -0
  397. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/testing/__init__.py +0 -0
  398. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/testing/config.py +0 -0
  399. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/testing/content_generation.py +0 -0
  400. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/testing/endpoints/__init__.py +0 -0
  401. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/testing/endpoints/cli.py +0 -0
  402. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/testing/endpoints/config.py +0 -0
  403. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/testing/endpoints/console.py +0 -0
  404. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/testing/endpoints/models.py +0 -0
  405. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/testing/endpoints/runner.py +0 -0
  406. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/testing/endpoints/tools.py +0 -0
  407. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/testing/mock_responses.py +0 -0
  408. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/testing/response_handlers.py +0 -0
  409. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/testing/scenarios.py +0 -0
  410. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/utils/__init__.py +0 -0
  411. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/utils/binary_resolver.py +0 -0
  412. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/utils/caching.py +0 -0
  413. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/utils/cli_logging.py +0 -0
  414. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/utils/command_line.py +0 -0
  415. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/utils/headers.py +0 -0
  416. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/utils/id_generator.py +0 -0
  417. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/utils/model_mapper.py +0 -0
  418. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/utils/startup_helpers.py +0 -0
  419. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/ccproxy/utils/version_checker.py +0 -0
  420. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/examples/README.md +0 -0
  421. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/tests/factories/README.md +0 -0
  422. {ccproxy_api-0.2.4 → ccproxy_api-0.2.5}/tests/fixtures/README.md +0 -0
@@ -1,42 +1,42 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ccproxy-api
3
- Version: 0.2.4
3
+ Version: 0.2.5
4
4
  Summary: API server that provides an Anthropic and OpenAI compatible interface over Claude Code, allowing to use your Claude OAuth account or over the API.
5
5
  License-File: LICENSE
6
6
  Requires-Python: >=3.11
7
- Requires-Dist: aiofiles>=24.1.0
8
- Requires-Dist: fastapi[standard]>=0.115.14
7
+ Requires-Dist: aiofiles>=25.1.0
8
+ Requires-Dist: fastapi[standard]>=0.119.0
9
9
  Requires-Dist: httpx[http2]>=0.28.1
10
10
  Requires-Dist: packaging>=25.0
11
- Requires-Dist: pydantic-settings>=2.4.0
12
- Requires-Dist: pydantic>=2.8.0
11
+ Requires-Dist: pydantic-settings>=2.11.0
12
+ Requires-Dist: pydantic>=2.12.2
13
13
  Requires-Dist: pyjwt>=2.10.1
14
- Requires-Dist: rich-toolkit>=0.14.8
15
- Requires-Dist: rich>=13.0.0
14
+ Requires-Dist: rich-toolkit>=0.15.1
15
+ Requires-Dist: rich>=14.2.0
16
16
  Requires-Dist: sortedcontainers>=2.4.0
17
17
  Requires-Dist: structlog>=25.4.0
18
- Requires-Dist: typer>=0.16.0
19
- Requires-Dist: typing-extensions>=4.0.0
20
- Requires-Dist: uvicorn>=0.34.0
18
+ Requires-Dist: typer>=0.19.2
19
+ Requires-Dist: typing-extensions>=4.15.0
20
+ Requires-Dist: uvicorn>=0.37.0
21
21
  Provides-Extra: plugins-claude
22
- Requires-Dist: claude-agent-sdk>=0.1.0; extra == 'plugins-claude'
23
- Requires-Dist: keyring>=25.0.0; extra == 'plugins-claude'
22
+ Requires-Dist: claude-agent-sdk>=0.1.4; extra == 'plugins-claude'
23
+ Requires-Dist: keyring>=25.7.0; extra == 'plugins-claude'
24
24
  Requires-Dist: qrcode>=8.2; extra == 'plugins-claude'
25
25
  Provides-Extra: plugins-codex
26
26
  Requires-Dist: pyjwt>=2.10.1; extra == 'plugins-codex'
27
27
  Requires-Dist: qrcode>=8.2; extra == 'plugins-codex'
28
28
  Provides-Extra: plugins-mcp
29
- Requires-Dist: fastapi-mcp>=0.3.7; extra == 'plugins-mcp'
29
+ Requires-Dist: fastapi-mcp>=0.4.0; extra == 'plugins-mcp'
30
30
  Provides-Extra: plugins-metrics
31
- Requires-Dist: prometheus-client>=0.22.1; extra == 'plugins-metrics'
31
+ Requires-Dist: prometheus-client>=0.23.1; extra == 'plugins-metrics'
32
32
  Provides-Extra: plugins-storage
33
33
  Requires-Dist: duckdb-engine>=0.17.0; extra == 'plugins-storage'
34
- Requires-Dist: duckdb<1.4.0,>=1.1.0; extra == 'plugins-storage'
35
- Requires-Dist: sqlalchemy>=2.0.0; extra == 'plugins-storage'
36
- Requires-Dist: sqlmodel>=0.0.24; extra == 'plugins-storage'
34
+ Requires-Dist: duckdb>=1.3.2; extra == 'plugins-storage'
35
+ Requires-Dist: sqlalchemy>=2.0.44; extra == 'plugins-storage'
36
+ Requires-Dist: sqlmodel>=0.0.27; extra == 'plugins-storage'
37
37
  Provides-Extra: plugins-tui
38
- Requires-Dist: aioconsole>=0.8.1; extra == 'plugins-tui'
39
- Requires-Dist: textual>=3.7.1; extra == 'plugins-tui'
38
+ Requires-Dist: aioconsole>=0.8.2; extra == 'plugins-tui'
39
+ Requires-Dist: textual>=6.3.0; extra == 'plugins-tui'
40
40
  Description-Content-Type: text/markdown
41
41
 
42
42
  # CCProxy API Server
@@ -28,7 +28,7 @@ version_tuple: VERSION_TUPLE
28
28
  commit_id: COMMIT_ID
29
29
  __commit_id__: COMMIT_ID
30
30
 
31
- __version__ = version = '0.2.4'
32
- __version_tuple__ = version_tuple = (0, 2, 4)
31
+ __version__ = version = '0.2.5'
32
+ __version_tuple__ = version_tuple = (0, 2, 5)
33
33
 
34
34
  __commit_id__ = commit_id = None
@@ -14,6 +14,7 @@ from fastapi import APIRouter
14
14
  from ccproxy.models.provider import ProviderConfig
15
15
  from ccproxy.services.adapters.base import BaseAdapter
16
16
  from ccproxy.services.adapters.http_adapter import BaseHTTPAdapter
17
+ from ccproxy.services.adapters.mock_adapter import MockAdapter
17
18
  from ccproxy.services.interfaces import (
18
19
  IMetricsCollector,
19
20
  IRequestTracer,
@@ -104,6 +105,7 @@ class BaseProviderPluginFactory(ProviderPluginFactory):
104
105
  cli_commands: list[CliCommandSpec] = []
105
106
  cli_arguments: list[CliArgumentSpec] = []
106
107
  tool_accumulator_class: type | None = None
108
+ use_mock_adapter_in_bypass_mode: bool = True
107
109
 
108
110
  def __init__(self) -> None:
109
111
  """Initialize factory with manifest built from class attributes."""
@@ -215,6 +217,24 @@ class BaseProviderPluginFactory(ProviderPluginFactory):
215
217
  Returns:
216
218
  Adapter instance
217
219
  """
220
+ settings = context.get("settings")
221
+ service_container = context.get("service_container")
222
+ if settings and getattr(settings.server, "bypass_mode", False):
223
+ if not service_container:
224
+ raise RuntimeError(
225
+ f"Cannot initialize plugin '{self.plugin_name}' in bypass mode: "
226
+ "service container is required to create mock adapter. "
227
+ "This is likely a configuration issue."
228
+ )
229
+ logger.warning(
230
+ "plugin_bypass_mode_enabled",
231
+ plugin=self.plugin_name,
232
+ adapter=self.adapter_class.__name__,
233
+ category="lifecycle",
234
+ )
235
+ if self.use_mock_adapter_in_bypass_mode:
236
+ return MockAdapter(service_container.get_mock_handler())
237
+
218
238
  # Extract services from context (one-time extraction)
219
239
  http_pool_manager: HTTPPoolManager | None = cast(
220
240
  "HTTPPoolManager | None", context.get("http_pool_manager")
@@ -232,7 +252,6 @@ class BaseProviderPluginFactory(ProviderPluginFactory):
232
252
  config = context.get("config")
233
253
 
234
254
  # Get all adapter dependencies from service container
235
- service_container = context.get("service_container")
236
255
  if not service_container:
237
256
  raise RuntimeError("Service container is required for adapter services")
238
257
 
@@ -268,6 +287,8 @@ class BaseProviderPluginFactory(ProviderPluginFactory):
268
287
  if hasattr(context, "get")
269
288
  else None,
270
289
  }
290
+ if settings and getattr(settings.server, "bypass_mode", False):
291
+ adapter_kwargs["mock_handler"] = service_container.get_mock_handler()
271
292
  if self.tool_accumulator_class:
272
293
  adapter_kwargs["tool_accumulator_class"] = self.tool_accumulator_class
273
294
 
@@ -303,6 +324,9 @@ class BaseProviderPluginFactory(ProviderPluginFactory):
303
324
  "model_mapper": context.get("model_mapper")
304
325
  if hasattr(context, "get")
305
326
  else None,
327
+ "mock_handler": service_container.get_mock_handler()
328
+ if settings and getattr(settings.server, "bypass_mode", False)
329
+ else None,
306
330
  }
307
331
  if self.tool_accumulator_class:
308
332
  non_http_adapter_kwargs["tool_accumulator_class"] = (
@@ -11,6 +11,9 @@ _INSTRUCTIONS_VAR: ContextVar[str | None] = ContextVar(
11
11
  "formatter_instructions", default=None
12
12
  )
13
13
  _TOOLS_VAR: ContextVar[list[Any] | None] = ContextVar("formatter_tools", default=None)
14
+ _OPENAI_THINKING_XML_VAR: ContextVar[bool | None] = ContextVar(
15
+ "formatter_openai_thinking_xml", default=None
16
+ )
14
17
 
15
18
 
16
19
  def register_request(request: Any | None, instructions: str | None = None) -> None:
@@ -114,3 +117,24 @@ def get_last_request_tools() -> list[Any] | None:
114
117
 
115
118
  cached = _TOOLS_VAR.get()
116
119
  return list(cached) if cached else None
120
+
121
+
122
+ def register_openai_thinking_xml(enabled: bool | None) -> None:
123
+ """Cache OpenAI thinking serialization preference for active conversions.
124
+
125
+ Args:
126
+ enabled: Whether thinking blocks should be serialized with XML wrappers.
127
+ ``None`` means downstream conversion logic should use its default.
128
+
129
+ Note:
130
+ The value is stored in a ``ContextVar``, so concurrent async requests
131
+ keep independent preferences without leaking into each other.
132
+ """
133
+
134
+ _OPENAI_THINKING_XML_VAR.set(enabled)
135
+
136
+
137
+ def get_openai_thinking_xml() -> bool | None:
138
+ """Return the OpenAI thinking serialization preference for active conversions."""
139
+
140
+ return _OPENAI_THINKING_XML_VAR.get()
@@ -15,6 +15,7 @@ from ccproxy.llms.formatters.common import (
15
15
  convert_openai_responses_usage_to_completion_usage,
16
16
  merge_thinking_segments,
17
17
  )
18
+ from ccproxy.llms.formatters.context import get_openai_thinking_xml
18
19
  from ccproxy.llms.models import openai as openai_models
19
20
 
20
21
  from ._helpers import (
@@ -333,6 +334,10 @@ def convert__openai_responses_to_openai_chat__response(
333
334
  response: openai_models.ResponseObject,
334
335
  ) -> openai_models.ChatCompletionResponse:
335
336
  """Convert an OpenAI ResponseObject to a ChatCompletionResponse."""
337
+ include_thinking = get_openai_thinking_xml()
338
+ if include_thinking is None:
339
+ include_thinking = True
340
+
336
341
  text_segments: list[str] = []
337
342
  added_reasoning: set[tuple[str, str]] = set()
338
343
  tool_calls: list[openai_models.ToolCall] = []
@@ -353,7 +358,7 @@ def convert__openai_responses_to_openai_chat__response(
353
358
  if thinking_text and len(thinking_text) > 30
354
359
  else thinking_text,
355
360
  )
356
- if thinking_text:
361
+ if include_thinking and thinking_text:
357
362
  key = (signature or "", thinking_text)
358
363
  if key not in added_reasoning:
359
364
  text_segments.append(_wrap_thinking(signature, thinking_text))
@@ -27,16 +27,14 @@ from ccproxy.llms.formatters.context import (
27
27
  get_last_instructions,
28
28
  get_last_request,
29
29
  get_last_request_tools,
30
+ get_openai_thinking_xml,
30
31
  register_request,
31
32
  register_request_tools,
32
33
  )
33
34
  from ccproxy.llms.models import openai as openai_models
34
35
  from ccproxy.llms.streaming.accumulators import OpenAIAccumulator
35
36
 
36
- from ._helpers import (
37
- _convert_tools_chat_to_responses,
38
- _get_attr,
39
- )
37
+ from ._helpers import _convert_tools_chat_to_responses, _get_attr
40
38
  from .requests import _build_responses_payload_from_chat_request
41
39
  from .responses import (
42
40
  _collect_reasoning_segments,
@@ -61,6 +59,10 @@ class OpenAIResponsesToChatStreamAdapter:
61
59
  async def generator() -> AsyncGenerator[
62
60
  openai_models.ChatCompletionChunk, None
63
61
  ]:
62
+ include_thinking = get_openai_thinking_xml()
63
+ if include_thinking is None:
64
+ include_thinking = True
65
+
64
66
  model_id = ""
65
67
  role_sent = False
66
68
 
@@ -537,7 +539,7 @@ class OpenAIResponsesToChatStreamAdapter:
537
539
  for entry in summary_list:
538
540
  text = _get_attr(entry, "text")
539
541
  signature = _get_attr(entry, "signature")
540
- if isinstance(text, str) and text:
542
+ if include_thinking and isinstance(text, str) and text:
541
543
  chunk_text = _wrap_thinking(signature, text)
542
544
  sequence_counter += 1
543
545
  yield openai_models.ChatCompletionChunk(
@@ -352,8 +352,16 @@ class ThinkingConfigDisabled(ThinkingConfigBase):
352
352
  type: Literal["disabled"] = Field(default="disabled", alias="type")
353
353
 
354
354
 
355
+ class ThinkingConfigAdaptive(ThinkingConfigBase):
356
+ """Configuration for adaptive thinking (Claude 4-6+)."""
357
+
358
+ type: Literal["adaptive"] = Field(default="adaptive", alias="type")
359
+ display: Literal["summarized", "omitted"] | None = None
360
+
361
+
355
362
  ThinkingConfig = Annotated[
356
- ThinkingConfigEnabled | ThinkingConfigDisabled, Field(discriminator="type")
363
+ ThinkingConfigEnabled | ThinkingConfigDisabled | ThinkingConfigAdaptive,
364
+ Field(discriminator="type"),
357
365
  ]
358
366
 
359
367
 
@@ -85,15 +85,14 @@ class ClaudeAPIAdapter(BaseHTTPAdapter):
85
85
  # Always set Authorization from OAuth-managed access token
86
86
  filtered_headers["authorization"] = f"Bearer {token_value}"
87
87
 
88
- # PATCH: Add Computer Use beta headers for Anthropic API
89
- # These are required for browser automation tools to work
88
+ # Minimal beta tags required for OAuth-based Claude Code auth
90
89
  filtered_headers["anthropic-version"] = "2023-06-01"
91
- filtered_headers["anthropic-beta"] = "computer-use-2025-01-24"
90
+ filtered_headers["anthropic-beta"] = "claude-code-20250219,oauth-2025-04-20"
92
91
 
93
- # Add CLI headers if available, but never allow overriding auth
92
+ # Add CLI headers if available, but never allow overriding auth or beta
94
93
  cli_headers = self._collect_cli_headers()
95
94
  if cli_headers:
96
- blocked_overrides = {"authorization", "x-api-key"}
95
+ blocked_overrides = {"authorization", "x-api-key", "anthropic-beta"}
97
96
  for key, value in cli_headers.items():
98
97
  lk = key.lower()
99
98
  if lk in blocked_overrides:
@@ -1,4 +1,5 @@
1
1
  import contextlib
2
+ import copy
2
3
  import json
3
4
  import uuid
4
5
  from typing import Any, cast
@@ -16,6 +17,7 @@ from ccproxy.core.plugins.interfaces import (
16
17
  )
17
18
  from ccproxy.services.adapters.chain_composer import compose_from_chain
18
19
  from ccproxy.services.adapters.http_adapter import BaseHTTPAdapter
20
+ from ccproxy.services.adapters.mock_adapter import MockAdapter
19
21
  from ccproxy.services.handler_config import HandlerConfig
20
22
  from ccproxy.streaming import DeferredStreaming, StreamingBufferService
21
23
  from ccproxy.utils.headers import (
@@ -57,18 +59,16 @@ class CodexAdapter(BaseHTTPAdapter):
57
59
  # Context + request info
58
60
  ctx = request.state.context
59
61
  self._ensure_tool_accumulator(ctx)
62
+ if self.mock_handler:
63
+ return await MockAdapter(self.mock_handler).handle_request(request)
64
+
60
65
  endpoint = ctx.metadata.get("endpoint", "")
61
66
  body = await request.body()
62
67
  body = await self._map_request_model(ctx, body)
63
68
  headers = extract_request_headers(request)
64
69
 
65
70
  # Determine client streaming intent from body flag (fallback to False)
66
- wants_stream = False
67
- try:
68
- data = json.loads(body.decode()) if body else {}
69
- wants_stream = bool(data.get("stream", False))
70
- except Exception: # Malformed/missing JSON -> assume non-streaming
71
- wants_stream = False
71
+ wants_stream = self._detect_streaming_intent(body, headers)
72
72
  logger.trace(
73
73
  "codex_adapter_request_intent",
74
74
  wants_stream=wants_stream,
@@ -256,37 +256,58 @@ class CodexAdapter(BaseHTTPAdapter):
256
256
  async def prepare_provider_request(
257
257
  self, body: bytes, headers: dict[str, str], endpoint: str
258
258
  ) -> tuple[bytes, dict[str, str]]:
259
- token_value = await self._resolve_access_token()
259
+ filtered_headers = await self.prepare_provider_headers(headers)
260
260
 
261
- # Get profile to extract chatgpt_account_id
262
- profile = await self.token_manager.get_profile_quick()
263
- chatgpt_account_id = (
264
- getattr(profile, "chatgpt_account_id", None) if profile else None
265
- )
261
+ if self._request_body_is_encoded(headers):
262
+ return body, filtered_headers
263
+
264
+ # Body will be re-serialized as plain JSON; drop stale encoding header
265
+ filtered_headers.pop("content-encoding", None)
266
266
 
267
267
  # Parse body (format conversion is now handled by format chain)
268
268
  body_data = json.loads(body.decode()) if body else {}
269
+ if self._should_apply_detection_payload():
270
+ body_data = self._apply_request_template(body_data)
271
+ else:
272
+ body_data = self._normalize_input_messages(body_data)
269
273
 
270
- # Inject instructions mandatory for being allow to
271
- # to used the Codex API endpoint
272
- # Fetch detected instructions from detection service
273
- instructions = self._get_instructions()
274
+ detected_instructions = (
275
+ self._get_instructions() if self._should_apply_detection_payload() else ""
276
+ )
274
277
 
275
278
  existing_instructions = body_data.get("instructions")
276
279
  if isinstance(existing_instructions, str) and existing_instructions:
277
- if instructions:
278
- instructions = instructions + "\n" + existing_instructions
279
- else:
280
- instructions = existing_instructions
280
+ instructions = (
281
+ detected_instructions + "\n" + existing_instructions
282
+ if detected_instructions
283
+ else existing_instructions
284
+ )
285
+ else:
286
+ instructions = detected_instructions
287
+
288
+ if instructions:
289
+ body_data["instructions"] = instructions
290
+ else:
291
+ body_data.pop("instructions", None)
281
292
 
282
- body_data["instructions"] = instructions
293
+ body_data = self._sanitize_provider_body(body_data)
294
+
295
+ return json.dumps(body_data).encode(), filtered_headers
296
+
297
+ def _sanitize_provider_body(self, body_data: dict[str, Any]) -> dict[str, Any]:
298
+ """Apply Codex-specific payload sanitization shared by all request paths."""
283
299
 
284
300
  # Codex backend requires stream=true, always override
285
301
  body_data["stream"] = True
286
302
  body_data["store"] = False
287
303
 
288
304
  # Remove unsupported keys for Codex
289
- for key in ("max_output_tokens", "max_completion_tokens", "temperature"):
305
+ for key in (
306
+ "max_output_tokens",
307
+ "max_completion_tokens",
308
+ "max_tokens",
309
+ "temperature",
310
+ ):
290
311
  body_data.pop(key, None)
291
312
 
292
313
  list_input = body_data.get("input", [])
@@ -295,12 +316,23 @@ class CodexAdapter(BaseHTTPAdapter):
295
316
  input for input in list_input if input.get("type") != "item_reference"
296
317
  ]
297
318
 
298
- #
299
319
  # Remove any prefixed metadata fields that shouldn't be sent to the API
300
320
  body_data = self._remove_metadata_fields(body_data)
301
321
 
302
- # Filter and add headers
322
+ return body_data
323
+
324
+ async def prepare_provider_headers(self, headers: dict[str, str]) -> dict[str, str]:
325
+ token_value = await self._resolve_access_token()
326
+
327
+ profile = await self.token_manager.get_profile_quick()
328
+ chatgpt_account_id = (
329
+ getattr(profile, "chatgpt_account_id", None) if profile else None
330
+ )
331
+
303
332
  filtered_headers = filter_request_headers(headers, preserve_auth=False)
333
+ content_encoding = headers.get("content-encoding")
334
+ if content_encoding:
335
+ filtered_headers["content-encoding"] = content_encoding
304
336
 
305
337
  session_id = filtered_headers.get("session_id") or str(uuid.uuid4())
306
338
  conversation_id = filtered_headers.get("conversation_id") or str(uuid.uuid4())
@@ -318,10 +350,10 @@ class CodexAdapter(BaseHTTPAdapter):
318
350
  filtered_headers.update(base_headers)
319
351
 
320
352
  cli_headers = self._collect_cli_headers()
321
- if cli_headers:
322
- filtered_headers.update(cli_headers)
353
+ for key, value in cli_headers.items():
354
+ filtered_headers.setdefault(key, value)
323
355
 
324
- return json.dumps(body_data).encode(), filtered_headers
356
+ return filtered_headers
325
357
 
326
358
  async def process_provider_response(
327
359
  self, response: httpx.Response, endpoint: str
@@ -453,6 +485,10 @@ class CodexAdapter(BaseHTTPAdapter):
453
485
  if not self.streaming_handler:
454
486
  # Fallback to base behavior
455
487
  return await super().handle_streaming(request, endpoint, **kwargs)
488
+ if self.mock_handler:
489
+ return await MockAdapter(self.mock_handler).handle_streaming(
490
+ request, endpoint, **kwargs
491
+ )
456
492
 
457
493
  # Get context
458
494
  ctx = request.state.context
@@ -581,6 +617,73 @@ class CodexAdapter(BaseHTTPAdapter):
581
617
 
582
618
  return cleaned_data
583
619
 
620
+ def _apply_request_template(self, data: dict[str, Any]) -> dict[str, Any]:
621
+ if not isinstance(data, dict):
622
+ return data
623
+
624
+ template = self._get_request_template()
625
+ if not template:
626
+ return self._normalize_input_messages(data)
627
+
628
+ merged = copy.deepcopy(data)
629
+
630
+ for key in ("include", "parallel_tool_calls", "reasoning", "tool_choice"):
631
+ if key not in merged and key in template:
632
+ merged[key] = copy.deepcopy(template[key])
633
+
634
+ if not merged.get("tools") and isinstance(template.get("tools"), list):
635
+ merged["tools"] = copy.deepcopy(template["tools"])
636
+
637
+ if "prompt_cache_key" not in merged:
638
+ prompt_cache_key = template.get("prompt_cache_key")
639
+ if isinstance(prompt_cache_key, str) and prompt_cache_key:
640
+ merged["prompt_cache_key"] = str(uuid.uuid4())
641
+
642
+ return self._normalize_input_messages(merged)
643
+
644
+ def _normalize_input_messages(self, data: dict[str, Any]) -> dict[str, Any]:
645
+ input_items = data.get("input")
646
+ if not isinstance(input_items, list):
647
+ return data
648
+
649
+ normalized_items: list[Any] = []
650
+ for item in input_items:
651
+ if (
652
+ isinstance(item, dict)
653
+ and "type" not in item
654
+ and "role" in item
655
+ and "content" in item
656
+ ):
657
+ normalized_item = dict(item)
658
+ normalized_item["type"] = "message"
659
+ normalized_items.append(normalized_item)
660
+ continue
661
+
662
+ normalized_items.append(item)
663
+
664
+ result = dict(data)
665
+ result["input"] = normalized_items
666
+ return result
667
+
668
+ def _request_body_is_encoded(self, headers: dict[str, str]) -> bool:
669
+ encoding = headers.get("content-encoding", "").strip().lower()
670
+ return bool(encoding and encoding != "identity")
671
+
672
+ def _detect_streaming_intent(self, body: bytes, headers: dict[str, str]) -> bool:
673
+ if self._request_body_is_encoded(headers):
674
+ accept = headers.get("accept", "").lower()
675
+ return "text/event-stream" in accept
676
+
677
+ try:
678
+ data = json.loads(body.decode()) if body else {}
679
+ return bool(data.get("stream", False))
680
+ except Exception:
681
+ accept = headers.get("accept", "").lower()
682
+ return "text/event-stream" in accept
683
+
684
+ def _should_apply_detection_payload(self) -> bool:
685
+ return bool(getattr(self.config, "inject_detection_payload", True))
686
+
584
687
  def _get_instructions(self) -> str:
585
688
  if not self.detection_service:
586
689
  return ""
@@ -601,6 +704,16 @@ class CodexAdapter(BaseHTTPAdapter):
601
704
 
602
705
  return ""
603
706
 
707
+ def _get_request_template(self) -> dict[str, Any]:
708
+ if not self.detection_service:
709
+ return {}
710
+
711
+ prompts = self.detection_service.get_detected_prompts()
712
+ if isinstance(prompts.raw, dict) and prompts.raw:
713
+ return prompts.raw
714
+
715
+ return {}
716
+
604
717
  def adapt_error(self, error_body: dict[str, Any]) -> dict[str, Any]:
605
718
  """Convert Codex error format to appropriate API error format.
606
719
 
@@ -124,6 +124,13 @@ class CodexSettings(ProviderConfig):
124
124
  enable_format_registry: bool = Field(
125
125
  default=True, description="Whether to enable format adapter registry"
126
126
  )
127
+ inject_detection_payload: bool = Field(
128
+ default=True,
129
+ description=(
130
+ "Whether to inject the captured Codex CLI instructions/template into "
131
+ "provider requests. Disable this for generic OpenAI-compatible API usage."
132
+ ),
133
+ )
127
134
 
128
135
  # Detection configuration
129
136
  detection_home_mode: Literal["temp", "home"] = Field(
@@ -12,6 +12,7 @@ from pathlib import Path
12
12
  from typing import Any, cast
13
13
 
14
14
  from fastapi import FastAPI, Request, Response
15
+ from pydantic import ValidationError
15
16
 
16
17
  from ccproxy.config.settings import Settings
17
18
  from ccproxy.config.utils import get_ccproxy_cache_dir
@@ -43,6 +44,7 @@ class CodexDetectionService:
43
44
  ignores_header: list[str] = [
44
45
  "host",
45
46
  "content-length",
47
+ "content-encoding",
46
48
  "authorization",
47
49
  "x-api-key",
48
50
  "session_id",
@@ -133,17 +135,40 @@ class CodexDetectionService:
133
135
  """Return cached headers as structured data."""
134
136
 
135
137
  data = self.get_cached_data()
136
- if not data:
137
- return DetectedHeaders()
138
- return data.headers
138
+ headers = data.headers if data else DetectedHeaders()
139
+
140
+ required_headers = {
141
+ "accept",
142
+ "content-type",
143
+ "openai-beta",
144
+ "originator",
145
+ "version",
146
+ }
147
+ missing_required = [key for key in required_headers if not headers.get(key)]
148
+ if not missing_required:
149
+ return headers
150
+
151
+ fallback = self._safe_fallback_data()
152
+ if fallback is None:
153
+ return headers
154
+
155
+ merged_headers = fallback.headers.as_dict()
156
+ merged_headers.update(
157
+ {key: value for key, value in headers.as_dict().items() if value}
158
+ )
159
+ return DetectedHeaders(merged_headers)
139
160
 
140
161
  def get_detected_prompts(self) -> DetectedPrompts:
141
162
  """Return cached prompt metadata as structured data."""
142
163
 
143
164
  data = self.get_cached_data()
144
- if not data:
145
- return DetectedPrompts()
146
- return data.prompts
165
+ prompts = data.prompts if data else DetectedPrompts()
166
+
167
+ fallback = self._safe_fallback_data()
168
+ if fallback is None:
169
+ return prompts
170
+
171
+ return self._merge_detected_prompts(prompts, fallback.prompts)
147
172
 
148
173
  def get_ignored_headers(self) -> list[str]:
149
174
  """Headers that should be ignored when forwarding CLI values."""
@@ -496,6 +521,36 @@ class CodexDetectionService:
496
521
  fallback_data_dict = json.load(f)
497
522
  return CodexCacheData.model_validate(fallback_data_dict)
498
523
 
524
+ def _safe_fallback_data(self) -> CodexCacheData | None:
525
+ """Best-effort fallback data loader for partial detection caches."""
526
+ try:
527
+ return self._get_fallback_data()
528
+ except (OSError, json.JSONDecodeError, ValidationError):
529
+ logger.debug(
530
+ "safe_fallback_data_load_failed", exc_info=True, category="plugin"
531
+ )
532
+ return None
533
+
534
+ @staticmethod
535
+ def _merge_detected_prompts(
536
+ prompts: DetectedPrompts, fallback: DetectedPrompts
537
+ ) -> DetectedPrompts:
538
+ """Merge partial prompt caches with fallback defaults."""
539
+
540
+ prompt_raw = prompts.raw if isinstance(prompts.raw, dict) else {}
541
+ fallback_raw = fallback.raw if isinstance(fallback.raw, dict) else {}
542
+ merged_raw = dict(fallback_raw)
543
+ merged_raw.update(prompt_raw)
544
+
545
+ instructions = prompts.instructions or fallback.instructions
546
+ system = prompts.system if prompts.system is not None else fallback.system
547
+
548
+ return DetectedPrompts(
549
+ instructions=instructions,
550
+ system=system,
551
+ raw=merged_raw,
552
+ )
553
+
499
554
  def invalidate_cache(self) -> None:
500
555
  """Clear all cached detection data."""
501
556
  # Clear the async cache for _get_codex_version
@@ -222,6 +222,7 @@ class CodexFactory(BaseProviderPluginFactory):
222
222
  """Factory for Codex provider plugin."""
223
223
 
224
224
  cli_safe = False # Heavy provider plugin - not safe for CLI
225
+ use_mock_adapter_in_bypass_mode = False
225
226
 
226
227
  # Plugin configuration via class attributes
227
228
  plugin_name = "codex"