kolega-code 0.7.0__tar.gz → 0.7.1__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 (285) hide show
  1. {kolega_code-0.7.0 → kolega_code-0.7.1}/.env.example +3 -0
  2. {kolega_code-0.7.0 → kolega_code-0.7.1}/PKG-INFO +9 -1
  3. {kolega_code-0.7.0 → kolega_code-0.7.1}/README.md +8 -0
  4. {kolega_code-0.7.0 → kolega_code-0.7.1}/docs/astro.config.mjs +4 -0
  5. {kolega_code-0.7.0 → kolega_code-0.7.1}/docs/src/content/docs/configuration/providers-and-models.mdx +1 -0
  6. kolega_code-0.7.1/docs/src/content/docs/configuration/sign-in-with-chatgpt.mdx +93 -0
  7. {kolega_code-0.7.0 → kolega_code-0.7.1}/docs/src/content/docs/tui/slash-commands.md +6 -0
  8. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/__init__.py +1 -1
  9. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/agent/__init__.py +1 -1
  10. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/agent/baseagent.py +1 -0
  11. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/agent/context.py +2 -0
  12. kolega_code-0.7.1/kolega_code/agent/tests/llm/test_chatgpt_live.py +101 -0
  13. kolega_code-0.7.1/kolega_code/agent/tests/llm/test_chatgpt_oauth_provider.py +365 -0
  14. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/agent/tests/llm/test_live_providers.py +5 -1
  15. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/agent/tests/tool_backend/test_think_hard_streaming.py +1 -0
  16. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/agent/tool_backend/search_backends/firecrawl.py +10 -1
  17. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/agent/tool_backend/terminal_tool.py +1 -0
  18. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/agent/tool_backend/think_hard_tool.py +2 -0
  19. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/agent/tool_backend/web_fetch_tool.py +1 -0
  20. kolega_code-0.7.1/kolega_code/auth/__init__.py +17 -0
  21. kolega_code-0.7.1/kolega_code/auth/_jwt.py +53 -0
  22. kolega_code-0.7.1/kolega_code/auth/chatgpt_oauth.py +222 -0
  23. kolega_code-0.7.1/kolega_code/auth/constants.py +67 -0
  24. kolega_code-0.7.1/kolega_code/auth/tests/test_chatgpt_oauth.py +172 -0
  25. kolega_code-0.7.1/kolega_code/auth/tests/test_tokens.py +134 -0
  26. kolega_code-0.7.1/kolega_code/auth/tokens.py +170 -0
  27. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/cli/app.py +105 -2
  28. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/cli/config.py +88 -8
  29. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/cli/messages.py +13 -0
  30. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/cli/provider_registry.py +12 -2
  31. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/cli/settings.py +41 -0
  32. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/cli/slash_commands.py +2 -0
  33. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/cli/tests/test_cli_config.py +25 -0
  34. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/cli/tests/test_settings.py +70 -1
  35. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/config.py +45 -4
  36. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/llm/client.py +19 -0
  37. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/llm/instrumented_client.py +2 -1
  38. kolega_code-0.7.1/kolega_code/llm/providers/chatgpt_oauth.py +501 -0
  39. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/llm/specs.py +66 -0
  40. kolega_code-0.7.1/kolega_code/tools/tests/__init__.py +0 -0
  41. {kolega_code-0.7.0 → kolega_code-0.7.1}/pyproject.toml +1 -1
  42. {kolega_code-0.7.0 → kolega_code-0.7.1}/uv.lock +1 -1
  43. {kolega_code-0.7.0 → kolega_code-0.7.1}/.github/workflows/ci.yml +0 -0
  44. {kolega_code-0.7.0 → kolega_code-0.7.1}/.github/workflows/docs.yml +0 -0
  45. {kolega_code-0.7.0 → kolega_code-0.7.1}/.github/workflows/release.yml +0 -0
  46. {kolega_code-0.7.0 → kolega_code-0.7.1}/.gitignore +0 -0
  47. {kolega_code-0.7.0 → kolega_code-0.7.1}/CONTRIBUTING.md +0 -0
  48. {kolega_code-0.7.0 → kolega_code-0.7.1}/LICENSE +0 -0
  49. {kolega_code-0.7.0 → kolega_code-0.7.1}/RELEASING.md +0 -0
  50. {kolega_code-0.7.0 → kolega_code-0.7.1}/SECURITY.md +0 -0
  51. {kolega_code-0.7.0 → kolega_code-0.7.1}/conftest.py +0 -0
  52. {kolega_code-0.7.0 → kolega_code-0.7.1}/docs/.gitignore +0 -0
  53. {kolega_code-0.7.0 → kolega_code-0.7.1}/docs/README.md +0 -0
  54. {kolega_code-0.7.0 → kolega_code-0.7.1}/docs/package-lock.json +0 -0
  55. {kolega_code-0.7.0 → kolega_code-0.7.1}/docs/package.json +0 -0
  56. {kolega_code-0.7.0 → kolega_code-0.7.1}/docs/public/favicon.svg +0 -0
  57. {kolega_code-0.7.0 → kolega_code-0.7.1}/docs/src/assets/demo.gif +0 -0
  58. {kolega_code-0.7.0 → kolega_code-0.7.1}/docs/src/assets/kolega-dark.svg +0 -0
  59. {kolega_code-0.7.0 → kolega_code-0.7.1}/docs/src/assets/kolega-light.svg +0 -0
  60. {kolega_code-0.7.0 → kolega_code-0.7.1}/docs/src/content/docs/cli/ask.md +0 -0
  61. {kolega_code-0.7.0 → kolega_code-0.7.1}/docs/src/content/docs/cli/doctor.md +0 -0
  62. {kolega_code-0.7.0 → kolega_code-0.7.1}/docs/src/content/docs/cli/overview.md +0 -0
  63. {kolega_code-0.7.0 → kolega_code-0.7.1}/docs/src/content/docs/cli/sessions.md +0 -0
  64. {kolega_code-0.7.0 → kolega_code-0.7.1}/docs/src/content/docs/concepts/agents.md +0 -0
  65. {kolega_code-0.7.0 → kolega_code-0.7.1}/docs/src/content/docs/concepts/how-it-works.md +0 -0
  66. {kolega_code-0.7.0 → kolega_code-0.7.1}/docs/src/content/docs/concepts/tools.md +0 -0
  67. {kolega_code-0.7.0 → kolega_code-0.7.1}/docs/src/content/docs/configuration/environment-variables.md +0 -0
  68. {kolega_code-0.7.0 → kolega_code-0.7.1}/docs/src/content/docs/configuration/settings-and-api-keys.mdx +0 -0
  69. {kolega_code-0.7.0 → kolega_code-0.7.1}/docs/src/content/docs/getting-started/installation.mdx +0 -0
  70. {kolega_code-0.7.0 → kolega_code-0.7.1}/docs/src/content/docs/getting-started/quick-start.mdx +0 -0
  71. {kolega_code-0.7.0 → kolega_code-0.7.1}/docs/src/content/docs/gigacode.mdx +0 -0
  72. {kolega_code-0.7.0 → kolega_code-0.7.1}/docs/src/content/docs/hooks.md +0 -0
  73. {kolega_code-0.7.0 → kolega_code-0.7.1}/docs/src/content/docs/index.mdx +0 -0
  74. {kolega_code-0.7.0 → kolega_code-0.7.1}/docs/src/content/docs/skills.mdx +0 -0
  75. {kolega_code-0.7.0 → kolega_code-0.7.1}/docs/src/content/docs/tui/composer.md +0 -0
  76. {kolega_code-0.7.0 → kolega_code-0.7.1}/docs/src/content/docs/tui/interface.md +0 -0
  77. {kolega_code-0.7.0 → kolega_code-0.7.1}/docs/src/content/docs/tui/modes.md +0 -0
  78. {kolega_code-0.7.0 → kolega_code-0.7.1}/docs/src/content/docs/tui/sessions-and-resume.md +0 -0
  79. {kolega_code-0.7.0 → kolega_code-0.7.1}/docs/src/content.config.ts +0 -0
  80. {kolega_code-0.7.0 → kolega_code-0.7.1}/docs/src/styles/brand.css +0 -0
  81. {kolega_code-0.7.0 → kolega_code-0.7.1}/docs/tsconfig.json +0 -0
  82. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/agent/browseragent.py +0 -0
  83. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/agent/coder.py +0 -0
  84. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/agent/common.py +0 -0
  85. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/agent/compression.py +0 -0
  86. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/agent/conversation.py +0 -0
  87. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/agent/generalagent.py +0 -0
  88. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/agent/investigationagent.py +0 -0
  89. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/agent/orchestration/__init__.py +0 -0
  90. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/agent/orchestration/budget.py +0 -0
  91. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/agent/orchestration/errors.py +0 -0
  92. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/agent/orchestration/executor.py +0 -0
  93. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/agent/orchestration/guide.py +0 -0
  94. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/agent/orchestration/journal.py +0 -0
  95. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/agent/orchestration/runtime.py +0 -0
  96. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/agent/orchestration/tests/__init__.py +0 -0
  97. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/agent/orchestration/tests/test_orchestration.py +0 -0
  98. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/agent/orchestration/types.py +0 -0
  99. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/agent/planningagent.py +0 -0
  100. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/agent/prompt_provider.py +0 -0
  101. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/agent/prompt_templates/auxiliary/compression/summary.system.md +0 -0
  102. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/agent/prompt_templates/auxiliary/compression/summary.user.md.j2 +0 -0
  103. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/agent/prompt_templates/auxiliary/terminal/output_summary.system.md +0 -0
  104. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/agent/prompt_templates/auxiliary/terminal/safety.system.md +0 -0
  105. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/agent/prompt_templates/auxiliary/tools/think_hard.system.md +0 -0
  106. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/agent/prompt_templates/extensions/cli/planning_questions.md +0 -0
  107. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/agent/prompt_templates/extensions/cli/shared_task_list.md +0 -0
  108. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/agent/prompt_templates/extensions/skills/catalog.md.j2 +0 -0
  109. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/agent/prompt_templates/system/agents/browser.md.j2 +0 -0
  110. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/agent/prompt_templates/system/agents/coder_cli.md.j2 +0 -0
  111. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/agent/prompt_templates/system/agents/general.md.j2 +0 -0
  112. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/agent/prompt_templates/system/agents/investigation.md.j2 +0 -0
  113. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/agent/prompt_templates/system/agents/planning.md.j2 +0 -0
  114. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/agent/prompt_templates/system/includes/agents_md_instructions.md +0 -0
  115. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/agent/prompt_templates/system/includes/environment_variables/workspace_env_vars.md +0 -0
  116. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/agent/prompt_templates/system/includes/frontend_guidance.md +0 -0
  117. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/agent/prompt_templates/system/includes/starter_templates/expo.md +0 -0
  118. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/agent/prompt_templates/system/includes/starter_templates/html_website.md +0 -0
  119. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/agent/prompt_templates/system/includes/starter_templates/mern_stack.md +0 -0
  120. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/agent/prompt_templates/system/includes/starter_templates/react_vite_shadcdn.md +0 -0
  121. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/agent/prompt_templates/user_tasks/cli/implement_plan.md.j2 +0 -0
  122. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/agent/prompt_templates/user_tasks/cli/init_agents.md.j2 +0 -0
  123. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/agent/prompts.py +0 -0
  124. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/agent/tests/__init__.py +0 -0
  125. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/agent/tests/llm/__init__.py +0 -0
  126. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/agent/tests/llm/test_anthropic_token_counting.py +0 -0
  127. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/agent/tests/llm/test_billing_openai_cache.py +0 -0
  128. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/agent/tests/llm/test_client.py +0 -0
  129. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/agent/tests/llm/test_dashscope_mapping.py +0 -0
  130. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/agent/tests/llm/test_error_boundary.py +0 -0
  131. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/agent/tests/llm/test_exceptions.py +0 -0
  132. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/agent/tests/llm/test_google_thought_signature.py +0 -0
  133. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/agent/tests/llm/test_google_tool_signature_live.py +0 -0
  134. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/agent/tests/llm/test_instrumented_client.py +0 -0
  135. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/agent/tests/llm/test_instrumented_client_integration.py +0 -0
  136. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/agent/tests/llm/test_langfuse_normalization.py +0 -0
  137. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/agent/tests/llm/test_model_specs.py +0 -0
  138. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/agent/tests/llm/test_openai_cached_tokens.py +0 -0
  139. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/agent/tests/llm/test_openai_cached_tokens_stream.py +0 -0
  140. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/agent/tests/llm/test_openai_message_conversion.py +0 -0
  141. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/agent/tests/llm/test_openai_token_counting.py +0 -0
  142. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/agent/tests/llm/test_thinking_effort.py +0 -0
  143. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/agent/tests/llm/test_tool_execution_ids.py +0 -0
  144. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/agent/tests/services/__init__.py +0 -0
  145. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/agent/tests/services/test_browser.py +0 -0
  146. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/agent/tests/services/test_browser_parity.py +0 -0
  147. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/agent/tests/services/test_file_system.py +0 -0
  148. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/agent/tests/services/test_sandbox_terminal_input.py +0 -0
  149. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/agent/tests/services/test_terminal.py +0 -0
  150. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/agent/tests/services/test_terminal_buffer.py +0 -0
  151. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/agent/tests/services/test_terminal_state_serializer.py +0 -0
  152. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/agent/tests/test_agent_tools_inventory.py +0 -0
  153. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/agent/tests/test_base_agent.py +0 -0
  154. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/agent/tests/test_coder_attachments.py +0 -0
  155. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/agent/tests/test_coder_prompt_extensions.py +0 -0
  156. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/agent/tests/test_commands.py +0 -0
  157. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/agent/tests/test_duplicate_tool_results.py +0 -0
  158. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/agent/tests/test_empty_message_handling.py +0 -0
  159. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/agent/tests/test_event_emitter.py +0 -0
  160. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/agent/tests/test_general_agent.py +0 -0
  161. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/agent/tests/test_gigacode_gating.py +0 -0
  162. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/agent/tests/test_hooks_integration.py +0 -0
  163. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/agent/tests/test_html.py +0 -0
  164. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/agent/tests/test_parallel_tool_calls.py +0 -0
  165. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/agent/tests/test_permissions.py +0 -0
  166. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/agent/tests/test_planning_agent.py +0 -0
  167. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/agent/tests/test_prompt_provider.py +0 -0
  168. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/agent/tests/test_prompts.py +0 -0
  169. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/agent/tests/test_tool_registry.py +0 -0
  170. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/agent/tests/test_tools.py +0 -0
  171. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/agent/tests/tool_backend/__init__.py +0 -0
  172. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/agent/tests/tool_backend/test_agent_tool.py +0 -0
  173. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/agent/tests/tool_backend/test_base_tool.py +0 -0
  174. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/agent/tests/tool_backend/test_browser_tool.py +0 -0
  175. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/agent/tests/tool_backend/test_build_tool.py +0 -0
  176. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/agent/tests/tool_backend/test_create_file_tool.py +0 -0
  177. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/agent/tests/tool_backend/test_edit_preview.py +0 -0
  178. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/agent/tests/tool_backend/test_glob_tool.py +0 -0
  179. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/agent/tests/tool_backend/test_glob_tool_sandbox_parity.py +0 -0
  180. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/agent/tests/tool_backend/test_list_directory_tool.py +0 -0
  181. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/agent/tests/tool_backend/test_read_file_tool.py +0 -0
  182. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/agent/tests/tool_backend/test_replace_entire_file_tool.py +0 -0
  183. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/agent/tests/tool_backend/test_replace_lines_tool.py +0 -0
  184. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/agent/tests/tool_backend/test_search_and_replace_tool.py +0 -0
  185. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/agent/tests/tool_backend/test_search_codebase_tool.py +0 -0
  186. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/agent/tests/tool_backend/test_terminal_tool.py +0 -0
  187. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/agent/tests/tool_backend/test_think_hard_integration.py +0 -0
  188. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/agent/tests/tool_backend/test_web_fetch_tool.py +0 -0
  189. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/agent/tests/tool_backend/test_web_search_tool.py +0 -0
  190. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/agent/tests/tool_backend/test_workflow_tool.py +0 -0
  191. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/agent/tool_backend/agent_tool.py +0 -0
  192. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/agent/tool_backend/base_tool.py +0 -0
  193. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/agent/tool_backend/browser_tool.py +0 -0
  194. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/agent/tool_backend/build_tool.py +0 -0
  195. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/agent/tool_backend/create_file_tool.py +0 -0
  196. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/agent/tool_backend/edit_preview.py +0 -0
  197. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/agent/tool_backend/glob_tool.py +0 -0
  198. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/agent/tool_backend/list_directory_tool.py +0 -0
  199. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/agent/tool_backend/memory_tool.py +0 -0
  200. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/agent/tool_backend/read_file_tool.py +0 -0
  201. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/agent/tool_backend/replace_entire_file_tool.py +0 -0
  202. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/agent/tool_backend/replace_lines_tool.py +0 -0
  203. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/agent/tool_backend/search_and_replace_tool.py +0 -0
  204. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/agent/tool_backend/search_backends/__init__.py +0 -0
  205. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/agent/tool_backend/search_backends/base.py +0 -0
  206. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/agent/tool_backend/search_backends/duckduckgo.py +0 -0
  207. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/agent/tool_backend/search_backends/errors.py +0 -0
  208. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/agent/tool_backend/search_backends/models.py +0 -0
  209. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/agent/tool_backend/search_backends/searxng.py +0 -0
  210. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/agent/tool_backend/search_backends/tavily.py +0 -0
  211. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/agent/tool_backend/search_codebase_tool.py +0 -0
  212. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/agent/tool_backend/streaming_tool.py +0 -0
  213. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/agent/tool_backend/web_search_tool.py +0 -0
  214. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/agent/tool_backend/workflow_tool.py +0 -0
  215. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/agent/tools.py +0 -0
  216. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/agent/utils/commands.py +0 -0
  217. {kolega_code-0.7.0/kolega_code/hooks → kolega_code-0.7.1/kolega_code/auth}/tests/__init__.py +0 -0
  218. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/cli/__init__.py +0 -0
  219. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/cli/connection.py +0 -0
  220. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/cli/file_index.py +0 -0
  221. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/cli/main.py +0 -0
  222. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/cli/mentions.py +0 -0
  223. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/cli/session_store.py +0 -0
  224. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/cli/skills.py +0 -0
  225. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/cli/tests/__init__.py +0 -0
  226. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/cli/tests/test_app.py +0 -0
  227. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/cli/tests/test_connection.py +0 -0
  228. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/cli/tests/test_file_index.py +0 -0
  229. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/cli/tests/test_main.py +0 -0
  230. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/cli/tests/test_mentions.py +0 -0
  231. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/cli/tests/test_session_store.py +0 -0
  232. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/cli/tests/test_skills.py +0 -0
  233. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/cli/tests/test_slash_commands.py +0 -0
  234. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/cli/tests/test_themes.py +0 -0
  235. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/cli/tests/test_updater.py +0 -0
  236. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/cli/theme.py +0 -0
  237. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/cli/updater.py +0 -0
  238. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/events.py +0 -0
  239. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/hooks/__init__.py +0 -0
  240. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/hooks/backends.py +0 -0
  241. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/hooks/config.py +0 -0
  242. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/hooks/dispatcher.py +0 -0
  243. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/hooks/events.py +0 -0
  244. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/hooks/matcher.py +0 -0
  245. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/hooks/outcome.py +0 -0
  246. {kolega_code-0.7.0/kolega_code/llm/providers → kolega_code-0.7.1/kolega_code/hooks/tests}/__init__.py +0 -0
  247. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/hooks/tests/test_hooks.py +0 -0
  248. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/llm/exceptions.py +0 -0
  249. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/llm/models.py +0 -0
  250. {kolega_code-0.7.0/kolega_code/tools/tests → kolega_code-0.7.1/kolega_code/llm/providers}/__init__.py +0 -0
  251. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/llm/providers/anthropic.py +0 -0
  252. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/llm/providers/base.py +0 -0
  253. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/llm/providers/google.py +0 -0
  254. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/llm/providers/models.py +0 -0
  255. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/llm/providers/openai.py +0 -0
  256. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/llm/ratelimit.py +0 -0
  257. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/llm/tool_execution_ids.py +0 -0
  258. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/models/__init__.py +0 -0
  259. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/models/sandbox_terminal_state.py +0 -0
  260. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/permissions.py +0 -0
  261. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/runtime.py +0 -0
  262. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/sandbox/README.md +0 -0
  263. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/sandbox/__init__.py +0 -0
  264. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/sandbox/async_filesystem.py +0 -0
  265. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/sandbox/base.py +0 -0
  266. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/sandbox/browser.py +0 -0
  267. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/sandbox/event_loop.py +0 -0
  268. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/sandbox/filesystem.py +0 -0
  269. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/sandbox/local.py +0 -0
  270. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/sandbox/serializer.py +0 -0
  271. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/sandbox/terminal.py +0 -0
  272. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/sandbox/utils.py +0 -0
  273. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/services/base.py +0 -0
  274. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/services/browser.py +0 -0
  275. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/services/file_system.py +0 -0
  276. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/services/html.py +0 -0
  277. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/services/terminal.py +0 -0
  278. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/services/terminal_buffer.py +0 -0
  279. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/tools/__init__.py +0 -0
  280. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/tools/core.py +0 -0
  281. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/tools/definitions.py +0 -0
  282. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/tools/registry.py +0 -0
  283. {kolega_code-0.7.0 → kolega_code-0.7.1}/kolega_code/tools/tests/test_definitions.py +0 -0
  284. {kolega_code-0.7.0 → kolega_code-0.7.1}/run_tests.sh +0 -0
  285. {kolega_code-0.7.0 → kolega_code-0.7.1}/scripts/install-kolega-code.sh +0 -0
@@ -3,6 +3,9 @@
3
3
 
4
4
  ANTHROPIC_API_KEY=
5
5
  OPENAI_API_KEY=
6
+ # Prefer a ChatGPT subscription over an OpenAI API key? Run `/login` in the TUI
7
+ # (no key needed). Optional override of the OAuth client id, for testing only:
8
+ # KOLEGA_CODE_CHATGPT_CLIENT_ID=
6
9
  GOOGLE_API_KEY=
7
10
  MOONSHOT_API_KEY=
8
11
  DEEPSEEK_API_KEY=
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: kolega-code
3
- Version: 0.7.0
3
+ Version: 0.7.1
4
4
  Summary: Local-first AI coding agent for the terminal
5
5
  Project-URL: Homepage, https://kolega-ai.github.io/kolega-code/
6
6
  Project-URL: Documentation, https://kolega-ai.github.io/kolega-code/
@@ -176,6 +176,14 @@ and DeepSeek — and lets you assign **different models to different roles**: a
176
176
  long-context model for coding, a fast cheap model for small utility calls, and one for extended
177
177
  "thinking". See [Providers & Models](https://kolega-ai.github.io/kolega-code/configuration/providers-and-models/).
178
178
 
179
+ ## Sign in with ChatGPT
180
+
181
+ If you have a paid **ChatGPT** plan (Plus, Pro, or Business), you can use it to run OpenAI models
182
+ instead of a separate API key. Run `/login chatgpt` in the TUI, complete the browser sign-in, and
183
+ Kolega Code switches to the **OpenAI (ChatGPT subscription)** provider (default `gpt-5.5`). Tokens are
184
+ stored locally (chmod `600`) and refreshed automatically; `/logout chatgpt` removes them. See
185
+ [Sign in with ChatGPT](https://kolega-ai.github.io/kolega-code/configuration/sign-in-with-chatgpt/).
186
+
179
187
  ## Configuration
180
188
 
181
189
  Set your provider, model, and API keys from the **Settings** tab in the UI, or via environment
@@ -103,6 +103,14 @@ and DeepSeek — and lets you assign **different models to different roles**: a
103
103
  long-context model for coding, a fast cheap model for small utility calls, and one for extended
104
104
  "thinking". See [Providers & Models](https://kolega-ai.github.io/kolega-code/configuration/providers-and-models/).
105
105
 
106
+ ## Sign in with ChatGPT
107
+
108
+ If you have a paid **ChatGPT** plan (Plus, Pro, or Business), you can use it to run OpenAI models
109
+ instead of a separate API key. Run `/login chatgpt` in the TUI, complete the browser sign-in, and
110
+ Kolega Code switches to the **OpenAI (ChatGPT subscription)** provider (default `gpt-5.5`). Tokens are
111
+ stored locally (chmod `600`) and refreshed automatically; `/logout chatgpt` removes them. See
112
+ [Sign in with ChatGPT](https://kolega-ai.github.io/kolega-code/configuration/sign-in-with-chatgpt/).
113
+
106
114
  ## Configuration
107
115
 
108
116
  Set your provider, model, and API keys from the **Settings** tab in the UI, or via environment
@@ -56,6 +56,10 @@ export default defineConfig({
56
56
  label: "Providers & Models",
57
57
  slug: "configuration/providers-and-models",
58
58
  },
59
+ {
60
+ label: "Sign in with ChatGPT",
61
+ slug: "configuration/sign-in-with-chatgpt",
62
+ },
59
63
  {
60
64
  label: "Settings & API Keys",
61
65
  slug: "configuration/settings-and-api-keys",
@@ -16,6 +16,7 @@ The agent runtime recognizes these providers:
16
16
  | --- | --- | --- |
17
17
  | Anthropic | `anthropic` | `ANTHROPIC_API_KEY` |
18
18
  | OpenAI | `openai` | `OPENAI_API_KEY` |
19
+ | OpenAI (ChatGPT subscription) | `openai_chatgpt` | _none — [sign in with ChatGPT](../sign-in-with-chatgpt/)_ |
19
20
  | Google | `google` | `GOOGLE_API_KEY` |
20
21
  | Groq | `groq` | `GROQ_API_KEY` |
21
22
  | Together.ai | `together` | `TOGETHER_API_KEY` |
@@ -0,0 +1,93 @@
1
+ ---
2
+ title: Sign in with ChatGPT
3
+ description: Use your ChatGPT subscription to run OpenAI models in Kolega Code, without an API key.
4
+ ---
5
+
6
+ import { Aside, Steps } from '@astrojs/starlight/components';
7
+
8
+ If you have a paid **ChatGPT** plan, you can use it to run OpenAI models in Kolega
9
+ Code — no separate `OPENAI_API_KEY` required. Sign in once with `/login chatgpt`
10
+ and Kolega Code uses your subscription for the **OpenAI (ChatGPT subscription)**
11
+ provider.
12
+
13
+ ## Eligibility
14
+
15
+ | Plan | Runs models |
16
+ | --- | --- |
17
+ | Plus | Yes |
18
+ | Pro | Yes |
19
+ | Business | Yes |
20
+ | Free | No |
21
+
22
+ A Free plan can sign in, but can't run models this way — use an
23
+ [`OPENAI_API_KEY`](../providers-and-models/) instead.
24
+
25
+ ## Signing in
26
+
27
+ <Steps>
28
+
29
+ 1. In the TUI composer, run:
30
+
31
+ ```text
32
+ /login chatgpt
33
+ ```
34
+
35
+ 2. Your browser opens to the ChatGPT sign-in page. Complete the sign-in there.
36
+ (If the browser doesn't open, the composer prints a URL you can paste in
37
+ yourself.)
38
+
39
+ 3. When sign-in finishes, the browser shows a confirmation page and Kolega Code
40
+ switches to the **OpenAI (ChatGPT subscription)** provider, ready to use.
41
+
42
+ </Steps>
43
+
44
+ ## Models
45
+
46
+ The ChatGPT-subscription provider (identifier `openai_chatgpt`) exposes the Codex
47
+ model line-up:
48
+
49
+ | Model | Label |
50
+ | --- | --- |
51
+ | `gpt-5.5` | GPT-5.5 — default, frontier coding and reasoning |
52
+ | `gpt-5.4` | GPT-5.4 — strong everyday coding |
53
+ | `gpt-5.4-mini` | GPT-5.4 Mini — fast and economical |
54
+ | `gpt-5.3-codex-spark` | GPT-5.3 Codex Spark — ultra-fast |
55
+
56
+ Switch between them with [`/model`](../../tui/slash-commands/) or from the
57
+ **Settings** tab. Each model supports a reasoning **thinking effort** you can set
58
+ with [`/effort`](../../tui/slash-commands/).
59
+
60
+ ## Where credentials live
61
+
62
+ Sign-in tokens are stored in your `settings.json` under `oauth_tokens`, in the
63
+ same [state directory](../settings-and-api-keys/#where-settings-live) as the rest
64
+ of your settings, with `0600` permissions (readable and writable only by your
65
+ user). They refresh automatically in the background, so a single sign-in keeps
66
+ working across sessions.
67
+
68
+ ## Checking status
69
+
70
+ `doctor` reports whether you're signed in, without exposing any token:
71
+
72
+ ```bash
73
+ kolega-code doctor --project .
74
+ ```
75
+
76
+ For the ChatGPT-subscription provider it shows `signed in as <email> (<plan>)` or
77
+ `not signed in`. See [`doctor`](../../cli/doctor/).
78
+
79
+ ## Signing out
80
+
81
+ To remove your stored ChatGPT credentials:
82
+
83
+ ```text
84
+ /logout chatgpt
85
+ ```
86
+
87
+ After signing out, switch to another provider — or sign in again with
88
+ `/login chatgpt` — to keep working.
89
+
90
+ <Aside type="tip">
91
+ `/login` and `/logout` take a provider name so more sign-in options can be added
92
+ over time. Today, `chatgpt` is the available target.
93
+ </Aside>
@@ -40,6 +40,8 @@ These control the app and your session.
40
40
  | `/permissions` | Show or switch the shell/edit permission mode |
41
41
  | `/model` | Choose the active model |
42
42
  | `/effort` | Choose the active model's thinking effort |
43
+ | `/login` | Sign in to a provider, e.g. `/login chatgpt` |
44
+ | `/logout` | Sign out of a provider, e.g. `/logout chatgpt` |
43
45
  | `/gigacode` | Toggle [gigacode](../../gigacode/) workflow orchestration on or off |
44
46
  | `/copy` | Copy the last response to the clipboard |
45
47
  | `/version` | Show the Kolega Code version |
@@ -53,6 +55,10 @@ provider. You can also switch directly with `/model <name>`.
53
55
  Run `/effort` to open a selectable list of supported effort values for the
54
56
  active model. You can also switch directly with `/effort <level>`.
55
57
 
58
+ Run `/login chatgpt` to sign in with a ChatGPT subscription and use OpenAI models
59
+ without an API key; `/logout chatgpt` removes the stored credentials. See
60
+ [Sign in with ChatGPT](../../configuration/sign-in-with-chatgpt/).
61
+
56
62
  Run `/init` to have the agent inspect the repository and create or update a
57
63
  concise root `AGENTS.md`. Extra text after the command is passed as focus or
58
64
  constraints:
@@ -148,4 +148,4 @@ __all__ = [
148
148
  "parse_git_status_output",
149
149
  ]
150
150
 
151
- __version__ = "0.7.0"
151
+ __version__ = "0.7.1"
@@ -39,4 +39,4 @@ __all__ = [
39
39
  "ToolExtension",
40
40
  ]
41
41
 
42
- __version__ = "0.7.0"
42
+ __version__ = "0.7.1"
@@ -936,6 +936,7 @@ class BaseAgent(LogMixin):
936
936
  max_retries=model_config.rate_limits.max_retries,
937
937
  requests_per_minute=model_config.rate_limits.requests_per_minute,
938
938
  tokens_per_minute=model_config.rate_limits.tokens_per_minute,
939
+ token_manager=self.config.get_chatgpt_token_manager(),
939
940
  )
940
941
  response = await client.generate(
941
942
  model=model_config.model,
@@ -113,6 +113,7 @@ class AgentContext:
113
113
  user_id=self.telemetry.user_id,
114
114
  user_email=self.telemetry.user_email,
115
115
  usage_recorder=self.telemetry.usage_recorder,
116
+ token_manager=self.config.get_chatgpt_token_manager(),
116
117
  )
117
118
 
118
119
  return LLMClient(
@@ -121,4 +122,5 @@ class AgentContext:
121
122
  max_retries=model_config.rate_limits.max_retries,
122
123
  requests_per_minute=model_config.rate_limits.requests_per_minute,
123
124
  tokens_per_minute=model_config.rate_limits.tokens_per_minute,
125
+ token_manager=self.config.get_chatgpt_token_manager(),
124
126
  )
@@ -0,0 +1,101 @@
1
+ """Live test for the ChatGPT-subscription (OAuth) provider.
2
+
3
+ Unlike the key-based providers, this one needs OAuth tokens from an interactive
4
+ ``/login``. It is skipped unless real tokens are available, so it never runs in
5
+ CI. To run it locally after signing in via the TUI::
6
+
7
+ pytest -m integration kolega_code/agent/tests/llm/test_chatgpt_live.py -v
8
+
9
+ Token source (first match wins):
10
+ - KOLEGA_CODE_CHATGPT_TOKENS env var holding the JSON of an OAuthTokens dump, or
11
+ - the stored token in the local settings file (the one /login writes).
12
+ """
13
+
14
+ import json
15
+ import os
16
+
17
+ import pytest
18
+
19
+ from kolega_code.auth.tokens import ChatGPTTokenManager, OAuthTokens
20
+ from kolega_code.auth import constants as chatgpt_constants
21
+ from kolega_code.cli.settings import SettingsStore
22
+ from kolega_code.llm.client import LLMClient
23
+ from kolega_code.llm.models import Message, MessageHistory, TextBlock
24
+
25
+ pytestmark = pytest.mark.integration
26
+
27
+ SKIP_IN_CI = bool(os.getenv("CI")) or bool(os.getenv("GITLAB_CI"))
28
+
29
+
30
+ def _load_tokens() -> OAuthTokens | None:
31
+ raw = os.getenv("KOLEGA_CODE_CHATGPT_TOKENS")
32
+ if raw:
33
+ try:
34
+ return OAuthTokens.model_validate(json.loads(raw))
35
+ except (ValueError, TypeError):
36
+ return None
37
+ stored = SettingsStore().load().get_oauth_token(chatgpt_constants.PROVIDER_KEY)
38
+ if stored:
39
+ try:
40
+ return OAuthTokens.model_validate(stored)
41
+ except (ValueError, TypeError):
42
+ return None
43
+ return None
44
+
45
+
46
+ def _require_tokens() -> OAuthTokens:
47
+ if SKIP_IN_CI:
48
+ pytest.skip("Skipping live ChatGPT call in CI")
49
+ tokens = _load_tokens()
50
+ if tokens is None:
51
+ pytest.skip("No ChatGPT tokens available; sign in with /login or set KOLEGA_CODE_CHATGPT_TOKENS")
52
+ return tokens
53
+
54
+
55
+ @pytest.mark.asyncio
56
+ async def test_live_chatgpt_generate() -> None:
57
+ tokens = _require_tokens()
58
+ client = LLMClient(
59
+ provider=chatgpt_constants.PROVIDER_KEY,
60
+ api_key="unused",
61
+ token_manager=ChatGPTTokenManager(tokens),
62
+ )
63
+
64
+ response = await client.generate(
65
+ messages=MessageHistory(
66
+ [Message(role="user", content=[TextBlock(text="What is 2 + 2? Reply with just the number.")])]
67
+ ),
68
+ system=Message(role="system", content=[TextBlock(text="You are concise.")]),
69
+ model=chatgpt_constants.DEFAULT_MODEL,
70
+ max_completion_tokens=4096,
71
+ thinking="low",
72
+ )
73
+
74
+ assert response.role == "assistant"
75
+ assert response.get_text_content(), "empty response from ChatGPT backend"
76
+
77
+
78
+ @pytest.mark.asyncio
79
+ async def test_live_chatgpt_stream() -> None:
80
+ tokens = _require_tokens()
81
+ client = LLMClient(
82
+ provider=chatgpt_constants.PROVIDER_KEY,
83
+ api_key="unused",
84
+ token_manager=ChatGPTTokenManager(tokens),
85
+ )
86
+
87
+ text = ""
88
+ async with await client.stream(
89
+ messages=MessageHistory(
90
+ [Message(role="user", content=[TextBlock(text="Say the word 'ready' and nothing else.")])]
91
+ ),
92
+ model=chatgpt_constants.DEFAULT_MODEL,
93
+ max_completion_tokens=4096,
94
+ thinking="low",
95
+ ) as stream:
96
+ async for chunk in stream:
97
+ if chunk.type == "text" and chunk.text:
98
+ text += chunk.text
99
+ message = await stream.get_final_message()
100
+
101
+ assert text or message.get_text_content(), "empty stream from ChatGPT backend"