kolega-code 0.8.2__tar.gz → 0.8.3__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 (327) hide show
  1. {kolega_code-0.8.2 → kolega_code-0.8.3}/.github/workflows/ci.yml +1 -1
  2. {kolega_code-0.8.2 → kolega_code-0.8.3}/CONTRIBUTING.md +1 -1
  3. {kolega_code-0.8.2 → kolega_code-0.8.3}/PKG-INFO +1 -1
  4. {kolega_code-0.8.2 → kolega_code-0.8.3}/RELEASING.md +1 -1
  5. {kolega_code-0.8.2 → kolega_code-0.8.3}/kolega_code/__init__.py +1 -1
  6. {kolega_code-0.8.2 → kolega_code-0.8.3}/kolega_code/agent/__init__.py +1 -1
  7. {kolega_code-0.8.2 → kolega_code-0.8.3}/kolega_code/cli/app.py +3 -3
  8. {kolega_code-0.8.2 → kolega_code-0.8.3}/kolega_code/cli/main.py +36 -7
  9. {kolega_code-0.8.2 → kolega_code-0.8.3}/kolega_code/cli/settings.py +18 -0
  10. kolega_code-0.8.3/kolega_code/cli/tui/styles.tcss +335 -0
  11. {kolega_code-0.8.2 → kolega_code-0.8.3}/pyproject.toml +2 -1
  12. {kolega_code-0.8.2/kolega_code/agent/tests → kolega_code-0.8.3/tests/agent}/llm/test_anthropic_token_counting.py +4 -6
  13. {kolega_code-0.8.2/kolega_code/agent/tests → kolega_code-0.8.3/tests/agent}/llm/test_chatgpt_live.py +1 -1
  14. {kolega_code-0.8.2/kolega_code/agent/tests → kolega_code-0.8.3/tests/agent}/llm/test_client.py +8 -17
  15. {kolega_code-0.8.2/kolega_code/agent/tests → kolega_code-0.8.3/tests/agent}/llm/test_instrumented_client_integration.py +5 -6
  16. {kolega_code-0.8.2/kolega_code/agent/tests → kolega_code-0.8.3/tests/agent}/llm/test_live_providers.py +1 -1
  17. {kolega_code-0.8.2/kolega_code/agent/tests → kolega_code-0.8.3/tests/agent}/llm/test_openai_token_counting.py +5 -6
  18. {kolega_code-0.8.2/kolega_code/agent/tests → kolega_code-0.8.3/tests/agent}/test_commands.py +1 -1
  19. {kolega_code-0.8.2/kolega_code/agent/tests → kolega_code-0.8.3/tests/agent}/test_prompt_provider.py +1 -1
  20. {kolega_code-0.8.2/kolega_code/auth/tests → kolega_code-0.8.3/tests/auth}/test_chatgpt_oauth.py +1 -1
  21. {kolega_code-0.8.2/kolega_code/cli/tests → kolega_code-0.8.3/tests/cli}/test_app.py +8 -0
  22. {kolega_code-0.8.2/kolega_code/cli/tests → kolega_code-0.8.3/tests/cli}/test_clipboard_image.py +1 -1
  23. {kolega_code-0.8.2/kolega_code/cli/tests → kolega_code-0.8.3/tests/cli}/test_main.py +59 -2
  24. {kolega_code-0.8.2/kolega_code/cli/tests → kolega_code-0.8.3/tests/cli}/test_settings.py +29 -0
  25. {kolega_code-0.8.2/kolega_code/cli/tests → kolega_code-0.8.3/tests/cli}/test_slash_commands.py +2 -2
  26. kolega_code-0.8.3/tests/cli/test_tui_stylesheet.py +87 -0
  27. {kolega_code-0.8.2 → kolega_code-0.8.3/tests}/conftest.py +1 -1
  28. kolega_code-0.8.3/tests/utils/__init__.py +0 -0
  29. {kolega_code-0.8.2 → kolega_code-0.8.3}/uv.lock +5 -5
  30. kolega_code-0.8.2/kolega_code/cli/tui/styles.py +0 -339
  31. {kolega_code-0.8.2 → kolega_code-0.8.3}/.env.example +0 -0
  32. {kolega_code-0.8.2 → kolega_code-0.8.3}/.github/workflows/docs.yml +0 -0
  33. {kolega_code-0.8.2 → kolega_code-0.8.3}/.github/workflows/release.yml +0 -0
  34. {kolega_code-0.8.2 → kolega_code-0.8.3}/.gitignore +0 -0
  35. {kolega_code-0.8.2 → kolega_code-0.8.3}/LICENSE +0 -0
  36. {kolega_code-0.8.2 → kolega_code-0.8.3}/README.md +0 -0
  37. {kolega_code-0.8.2 → kolega_code-0.8.3}/SECURITY.md +0 -0
  38. {kolega_code-0.8.2 → kolega_code-0.8.3}/docs/.gitignore +0 -0
  39. {kolega_code-0.8.2 → kolega_code-0.8.3}/docs/README.md +0 -0
  40. {kolega_code-0.8.2 → kolega_code-0.8.3}/docs/astro.config.mjs +0 -0
  41. {kolega_code-0.8.2 → kolega_code-0.8.3}/docs/package-lock.json +0 -0
  42. {kolega_code-0.8.2 → kolega_code-0.8.3}/docs/package.json +0 -0
  43. {kolega_code-0.8.2 → kolega_code-0.8.3}/docs/public/favicon.svg +0 -0
  44. {kolega_code-0.8.2 → kolega_code-0.8.3}/docs/src/assets/demo.gif +0 -0
  45. {kolega_code-0.8.2 → kolega_code-0.8.3}/docs/src/assets/kolega-dark.svg +0 -0
  46. {kolega_code-0.8.2 → kolega_code-0.8.3}/docs/src/assets/kolega-light.svg +0 -0
  47. {kolega_code-0.8.2 → kolega_code-0.8.3}/docs/src/content/docs/cli/ask.md +0 -0
  48. {kolega_code-0.8.2 → kolega_code-0.8.3}/docs/src/content/docs/cli/doctor.md +0 -0
  49. {kolega_code-0.8.2 → kolega_code-0.8.3}/docs/src/content/docs/cli/overview.md +0 -0
  50. {kolega_code-0.8.2 → kolega_code-0.8.3}/docs/src/content/docs/cli/sessions.md +0 -0
  51. {kolega_code-0.8.2 → kolega_code-0.8.3}/docs/src/content/docs/concepts/agents.md +0 -0
  52. {kolega_code-0.8.2 → kolega_code-0.8.3}/docs/src/content/docs/concepts/how-it-works.md +0 -0
  53. {kolega_code-0.8.2 → kolega_code-0.8.3}/docs/src/content/docs/concepts/tools.md +0 -0
  54. {kolega_code-0.8.2 → kolega_code-0.8.3}/docs/src/content/docs/configuration/environment-variables.md +0 -0
  55. {kolega_code-0.8.2 → kolega_code-0.8.3}/docs/src/content/docs/configuration/providers-and-models.mdx +0 -0
  56. {kolega_code-0.8.2 → kolega_code-0.8.3}/docs/src/content/docs/configuration/settings-and-api-keys.mdx +0 -0
  57. {kolega_code-0.8.2 → kolega_code-0.8.3}/docs/src/content/docs/configuration/sign-in-with-chatgpt.mdx +0 -0
  58. {kolega_code-0.8.2 → kolega_code-0.8.3}/docs/src/content/docs/getting-started/installation.mdx +0 -0
  59. {kolega_code-0.8.2 → kolega_code-0.8.3}/docs/src/content/docs/getting-started/quick-start.mdx +0 -0
  60. {kolega_code-0.8.2 → kolega_code-0.8.3}/docs/src/content/docs/gigacode.mdx +0 -0
  61. {kolega_code-0.8.2 → kolega_code-0.8.3}/docs/src/content/docs/hooks.md +0 -0
  62. {kolega_code-0.8.2 → kolega_code-0.8.3}/docs/src/content/docs/index.mdx +0 -0
  63. {kolega_code-0.8.2 → kolega_code-0.8.3}/docs/src/content/docs/skills.mdx +0 -0
  64. {kolega_code-0.8.2 → kolega_code-0.8.3}/docs/src/content/docs/tui/composer.md +0 -0
  65. {kolega_code-0.8.2 → kolega_code-0.8.3}/docs/src/content/docs/tui/interface.md +0 -0
  66. {kolega_code-0.8.2 → kolega_code-0.8.3}/docs/src/content/docs/tui/modes.md +0 -0
  67. {kolega_code-0.8.2 → kolega_code-0.8.3}/docs/src/content/docs/tui/sessions-and-resume.md +0 -0
  68. {kolega_code-0.8.2 → kolega_code-0.8.3}/docs/src/content/docs/tui/slash-commands.md +0 -0
  69. {kolega_code-0.8.2 → kolega_code-0.8.3}/docs/src/content.config.ts +0 -0
  70. {kolega_code-0.8.2 → kolega_code-0.8.3}/docs/src/styles/brand.css +0 -0
  71. {kolega_code-0.8.2 → kolega_code-0.8.3}/docs/tsconfig.json +0 -0
  72. {kolega_code-0.8.2 → kolega_code-0.8.3}/kolega_code/agent/baseagent.py +0 -0
  73. {kolega_code-0.8.2 → kolega_code-0.8.3}/kolega_code/agent/browseragent.py +0 -0
  74. {kolega_code-0.8.2 → kolega_code-0.8.3}/kolega_code/agent/coder.py +0 -0
  75. {kolega_code-0.8.2 → kolega_code-0.8.3}/kolega_code/agent/common.py +0 -0
  76. {kolega_code-0.8.2 → kolega_code-0.8.3}/kolega_code/agent/compression.py +0 -0
  77. {kolega_code-0.8.2 → kolega_code-0.8.3}/kolega_code/agent/context.py +0 -0
  78. {kolega_code-0.8.2 → kolega_code-0.8.3}/kolega_code/agent/conversation.py +0 -0
  79. {kolega_code-0.8.2 → kolega_code-0.8.3}/kolega_code/agent/errors.py +0 -0
  80. {kolega_code-0.8.2 → kolega_code-0.8.3}/kolega_code/agent/generalagent.py +0 -0
  81. {kolega_code-0.8.2 → kolega_code-0.8.3}/kolega_code/agent/investigationagent.py +0 -0
  82. {kolega_code-0.8.2 → kolega_code-0.8.3}/kolega_code/agent/orchestration/__init__.py +0 -0
  83. {kolega_code-0.8.2 → kolega_code-0.8.3}/kolega_code/agent/orchestration/budget.py +0 -0
  84. {kolega_code-0.8.2 → kolega_code-0.8.3}/kolega_code/agent/orchestration/errors.py +0 -0
  85. {kolega_code-0.8.2 → kolega_code-0.8.3}/kolega_code/agent/orchestration/executor.py +0 -0
  86. {kolega_code-0.8.2 → kolega_code-0.8.3}/kolega_code/agent/orchestration/guide.py +0 -0
  87. {kolega_code-0.8.2 → kolega_code-0.8.3}/kolega_code/agent/orchestration/journal.py +0 -0
  88. {kolega_code-0.8.2 → kolega_code-0.8.3}/kolega_code/agent/orchestration/runtime.py +0 -0
  89. {kolega_code-0.8.2 → kolega_code-0.8.3}/kolega_code/agent/orchestration/types.py +0 -0
  90. {kolega_code-0.8.2 → kolega_code-0.8.3}/kolega_code/agent/planningagent.py +0 -0
  91. {kolega_code-0.8.2 → kolega_code-0.8.3}/kolega_code/agent/prompt_provider.py +0 -0
  92. {kolega_code-0.8.2 → kolega_code-0.8.3}/kolega_code/agent/prompt_templates/auxiliary/compression/summary.system.md +0 -0
  93. {kolega_code-0.8.2 → kolega_code-0.8.3}/kolega_code/agent/prompt_templates/auxiliary/compression/summary.user.md.j2 +0 -0
  94. {kolega_code-0.8.2 → kolega_code-0.8.3}/kolega_code/agent/prompt_templates/auxiliary/terminal/output_summary.system.md +0 -0
  95. {kolega_code-0.8.2 → kolega_code-0.8.3}/kolega_code/agent/prompt_templates/auxiliary/terminal/safety.system.md +0 -0
  96. {kolega_code-0.8.2 → kolega_code-0.8.3}/kolega_code/agent/prompt_templates/auxiliary/tools/think_hard.system.md +0 -0
  97. {kolega_code-0.8.2 → kolega_code-0.8.3}/kolega_code/agent/prompt_templates/extensions/cli/planning_questions.md +0 -0
  98. {kolega_code-0.8.2 → kolega_code-0.8.3}/kolega_code/agent/prompt_templates/extensions/cli/shared_task_list.md +0 -0
  99. {kolega_code-0.8.2 → kolega_code-0.8.3}/kolega_code/agent/prompt_templates/extensions/skills/catalog.md.j2 +0 -0
  100. {kolega_code-0.8.2 → kolega_code-0.8.3}/kolega_code/agent/prompt_templates/system/agents/browser.md.j2 +0 -0
  101. {kolega_code-0.8.2 → kolega_code-0.8.3}/kolega_code/agent/prompt_templates/system/agents/coder_cli.md.j2 +0 -0
  102. {kolega_code-0.8.2 → kolega_code-0.8.3}/kolega_code/agent/prompt_templates/system/agents/general.md.j2 +0 -0
  103. {kolega_code-0.8.2 → kolega_code-0.8.3}/kolega_code/agent/prompt_templates/system/agents/investigation.md.j2 +0 -0
  104. {kolega_code-0.8.2 → kolega_code-0.8.3}/kolega_code/agent/prompt_templates/system/agents/planning.md.j2 +0 -0
  105. {kolega_code-0.8.2 → kolega_code-0.8.3}/kolega_code/agent/prompt_templates/system/includes/agents_md_instructions.md +0 -0
  106. {kolega_code-0.8.2 → kolega_code-0.8.3}/kolega_code/agent/prompt_templates/system/includes/environment_variables/workspace_env_vars.md +0 -0
  107. {kolega_code-0.8.2 → kolega_code-0.8.3}/kolega_code/agent/prompt_templates/system/includes/frontend_guidance.md +0 -0
  108. {kolega_code-0.8.2 → kolega_code-0.8.3}/kolega_code/agent/prompt_templates/system/includes/starter_templates/expo.md +0 -0
  109. {kolega_code-0.8.2 → kolega_code-0.8.3}/kolega_code/agent/prompt_templates/system/includes/starter_templates/html_website.md +0 -0
  110. {kolega_code-0.8.2 → kolega_code-0.8.3}/kolega_code/agent/prompt_templates/system/includes/starter_templates/mern_stack.md +0 -0
  111. {kolega_code-0.8.2 → kolega_code-0.8.3}/kolega_code/agent/prompt_templates/system/includes/starter_templates/react_vite_shadcdn.md +0 -0
  112. {kolega_code-0.8.2 → kolega_code-0.8.3}/kolega_code/agent/prompt_templates/user_tasks/cli/implement_plan.md.j2 +0 -0
  113. {kolega_code-0.8.2 → kolega_code-0.8.3}/kolega_code/agent/prompt_templates/user_tasks/cli/init_agents.md.j2 +0 -0
  114. {kolega_code-0.8.2 → kolega_code-0.8.3}/kolega_code/agent/prompts.py +0 -0
  115. {kolega_code-0.8.2 → kolega_code-0.8.3}/kolega_code/agent/tool_backend/agent_tool.py +0 -0
  116. {kolega_code-0.8.2 → kolega_code-0.8.3}/kolega_code/agent/tool_backend/base_tool.py +0 -0
  117. {kolega_code-0.8.2 → kolega_code-0.8.3}/kolega_code/agent/tool_backend/browser_tool.py +0 -0
  118. {kolega_code-0.8.2 → kolega_code-0.8.3}/kolega_code/agent/tool_backend/build_tool.py +0 -0
  119. {kolega_code-0.8.2 → kolega_code-0.8.3}/kolega_code/agent/tool_backend/create_file_tool.py +0 -0
  120. {kolega_code-0.8.2 → kolega_code-0.8.3}/kolega_code/agent/tool_backend/edit_preview.py +0 -0
  121. {kolega_code-0.8.2 → kolega_code-0.8.3}/kolega_code/agent/tool_backend/glob_tool.py +0 -0
  122. {kolega_code-0.8.2 → kolega_code-0.8.3}/kolega_code/agent/tool_backend/list_directory_tool.py +0 -0
  123. {kolega_code-0.8.2 → kolega_code-0.8.3}/kolega_code/agent/tool_backend/memory_tool.py +0 -0
  124. {kolega_code-0.8.2 → kolega_code-0.8.3}/kolega_code/agent/tool_backend/read_file_tool.py +0 -0
  125. {kolega_code-0.8.2 → kolega_code-0.8.3}/kolega_code/agent/tool_backend/read_image_tool.py +0 -0
  126. {kolega_code-0.8.2 → kolega_code-0.8.3}/kolega_code/agent/tool_backend/replace_entire_file_tool.py +0 -0
  127. {kolega_code-0.8.2 → kolega_code-0.8.3}/kolega_code/agent/tool_backend/replace_lines_tool.py +0 -0
  128. {kolega_code-0.8.2 → kolega_code-0.8.3}/kolega_code/agent/tool_backend/search_and_replace_tool.py +0 -0
  129. {kolega_code-0.8.2 → kolega_code-0.8.3}/kolega_code/agent/tool_backend/search_backends/__init__.py +0 -0
  130. {kolega_code-0.8.2 → kolega_code-0.8.3}/kolega_code/agent/tool_backend/search_backends/base.py +0 -0
  131. {kolega_code-0.8.2 → kolega_code-0.8.3}/kolega_code/agent/tool_backend/search_backends/duckduckgo.py +0 -0
  132. {kolega_code-0.8.2 → kolega_code-0.8.3}/kolega_code/agent/tool_backend/search_backends/errors.py +0 -0
  133. {kolega_code-0.8.2 → kolega_code-0.8.3}/kolega_code/agent/tool_backend/search_backends/firecrawl.py +0 -0
  134. {kolega_code-0.8.2 → kolega_code-0.8.3}/kolega_code/agent/tool_backend/search_backends/models.py +0 -0
  135. {kolega_code-0.8.2 → kolega_code-0.8.3}/kolega_code/agent/tool_backend/search_backends/searxng.py +0 -0
  136. {kolega_code-0.8.2 → kolega_code-0.8.3}/kolega_code/agent/tool_backend/search_backends/tavily.py +0 -0
  137. {kolega_code-0.8.2 → kolega_code-0.8.3}/kolega_code/agent/tool_backend/search_codebase_tool.py +0 -0
  138. {kolega_code-0.8.2 → kolega_code-0.8.3}/kolega_code/agent/tool_backend/streaming_tool.py +0 -0
  139. {kolega_code-0.8.2 → kolega_code-0.8.3}/kolega_code/agent/tool_backend/terminal_tool.py +0 -0
  140. {kolega_code-0.8.2 → kolega_code-0.8.3}/kolega_code/agent/tool_backend/think_hard_tool.py +0 -0
  141. {kolega_code-0.8.2 → kolega_code-0.8.3}/kolega_code/agent/tool_backend/web_fetch_tool.py +0 -0
  142. {kolega_code-0.8.2 → kolega_code-0.8.3}/kolega_code/agent/tool_backend/web_search_tool.py +0 -0
  143. {kolega_code-0.8.2 → kolega_code-0.8.3}/kolega_code/agent/tool_backend/workflow_tool.py +0 -0
  144. {kolega_code-0.8.2 → kolega_code-0.8.3}/kolega_code/agent/tools.py +0 -0
  145. {kolega_code-0.8.2 → kolega_code-0.8.3}/kolega_code/agent/utils/commands.py +0 -0
  146. {kolega_code-0.8.2 → kolega_code-0.8.3}/kolega_code/auth/__init__.py +0 -0
  147. {kolega_code-0.8.2 → kolega_code-0.8.3}/kolega_code/auth/_jwt.py +0 -0
  148. {kolega_code-0.8.2 → kolega_code-0.8.3}/kolega_code/auth/chatgpt_oauth.py +0 -0
  149. {kolega_code-0.8.2 → kolega_code-0.8.3}/kolega_code/auth/constants.py +0 -0
  150. {kolega_code-0.8.2 → kolega_code-0.8.3}/kolega_code/auth/tokens.py +0 -0
  151. {kolega_code-0.8.2 → kolega_code-0.8.3}/kolega_code/cli/__init__.py +0 -0
  152. {kolega_code-0.8.2 → kolega_code-0.8.3}/kolega_code/cli/clipboard_image.py +0 -0
  153. {kolega_code-0.8.2 → kolega_code-0.8.3}/kolega_code/cli/config.py +0 -0
  154. {kolega_code-0.8.2 → kolega_code-0.8.3}/kolega_code/cli/connection.py +0 -0
  155. {kolega_code-0.8.2 → kolega_code-0.8.3}/kolega_code/cli/file_index.py +0 -0
  156. {kolega_code-0.8.2 → kolega_code-0.8.3}/kolega_code/cli/mentions.py +0 -0
  157. {kolega_code-0.8.2 → kolega_code-0.8.3}/kolega_code/cli/messages.py +0 -0
  158. {kolega_code-0.8.2 → kolega_code-0.8.3}/kolega_code/cli/provider_registry.py +0 -0
  159. {kolega_code-0.8.2 → kolega_code-0.8.3}/kolega_code/cli/session_store.py +0 -0
  160. {kolega_code-0.8.2 → kolega_code-0.8.3}/kolega_code/cli/skills.py +0 -0
  161. {kolega_code-0.8.2 → kolega_code-0.8.3}/kolega_code/cli/slash_commands.py +0 -0
  162. {kolega_code-0.8.2 → kolega_code-0.8.3}/kolega_code/cli/theme.py +0 -0
  163. {kolega_code-0.8.2 → kolega_code-0.8.3}/kolega_code/cli/tui/__init__.py +0 -0
  164. {kolega_code-0.8.2 → kolega_code-0.8.3}/kolega_code/cli/tui/agent_runtime.py +0 -0
  165. {kolega_code-0.8.2 → kolega_code-0.8.3}/kolega_code/cli/tui/command_handlers.py +0 -0
  166. {kolega_code-0.8.2 → kolega_code-0.8.3}/kolega_code/cli/tui/constants.py +0 -0
  167. {kolega_code-0.8.2 → kolega_code-0.8.3}/kolega_code/cli/tui/prompt_flows.py +0 -0
  168. {kolega_code-0.8.2 → kolega_code-0.8.3}/kolega_code/cli/tui/settings_panel.py +0 -0
  169. {kolega_code-0.8.2 → kolega_code-0.8.3}/kolega_code/cli/tui/state.py +0 -0
  170. {kolega_code-0.8.2 → kolega_code-0.8.3}/kolega_code/cli/tui/status_dashboard.py +0 -0
  171. {kolega_code-0.8.2 → kolega_code-0.8.3}/kolega_code/cli/tui/sub_agent_screen.py +0 -0
  172. {kolega_code-0.8.2 → kolega_code-0.8.3}/kolega_code/cli/tui/transcript.py +0 -0
  173. {kolega_code-0.8.2 → kolega_code-0.8.3}/kolega_code/cli/tui/widgets.py +0 -0
  174. {kolega_code-0.8.2 → kolega_code-0.8.3}/kolega_code/cli/updater.py +0 -0
  175. {kolega_code-0.8.2 → kolega_code-0.8.3}/kolega_code/config.py +0 -0
  176. {kolega_code-0.8.2 → kolega_code-0.8.3}/kolega_code/events.py +0 -0
  177. {kolega_code-0.8.2 → kolega_code-0.8.3}/kolega_code/hooks/__init__.py +0 -0
  178. {kolega_code-0.8.2 → kolega_code-0.8.3}/kolega_code/hooks/backends.py +0 -0
  179. {kolega_code-0.8.2 → kolega_code-0.8.3}/kolega_code/hooks/config.py +0 -0
  180. {kolega_code-0.8.2 → kolega_code-0.8.3}/kolega_code/hooks/dispatcher.py +0 -0
  181. {kolega_code-0.8.2 → kolega_code-0.8.3}/kolega_code/hooks/events.py +0 -0
  182. {kolega_code-0.8.2 → kolega_code-0.8.3}/kolega_code/hooks/matcher.py +0 -0
  183. {kolega_code-0.8.2 → kolega_code-0.8.3}/kolega_code/hooks/outcome.py +0 -0
  184. {kolega_code-0.8.2 → kolega_code-0.8.3}/kolega_code/llm/client.py +0 -0
  185. {kolega_code-0.8.2 → kolega_code-0.8.3}/kolega_code/llm/exceptions.py +0 -0
  186. {kolega_code-0.8.2 → kolega_code-0.8.3}/kolega_code/llm/instrumented_client.py +0 -0
  187. {kolega_code-0.8.2 → kolega_code-0.8.3}/kolega_code/llm/models.py +0 -0
  188. {kolega_code-0.8.2/kolega_code/agent/orchestration/tests → kolega_code-0.8.3/kolega_code/llm/providers}/__init__.py +0 -0
  189. {kolega_code-0.8.2 → kolega_code-0.8.3}/kolega_code/llm/providers/anthropic.py +0 -0
  190. {kolega_code-0.8.2 → kolega_code-0.8.3}/kolega_code/llm/providers/base.py +0 -0
  191. {kolega_code-0.8.2 → kolega_code-0.8.3}/kolega_code/llm/providers/chatgpt_oauth.py +0 -0
  192. {kolega_code-0.8.2 → kolega_code-0.8.3}/kolega_code/llm/providers/google.py +0 -0
  193. {kolega_code-0.8.2 → kolega_code-0.8.3}/kolega_code/llm/providers/models.py +0 -0
  194. {kolega_code-0.8.2 → kolega_code-0.8.3}/kolega_code/llm/providers/openai.py +0 -0
  195. {kolega_code-0.8.2 → kolega_code-0.8.3}/kolega_code/llm/providers/openai_responses.py +0 -0
  196. {kolega_code-0.8.2 → kolega_code-0.8.3}/kolega_code/llm/providers/responses_common.py +0 -0
  197. {kolega_code-0.8.2 → kolega_code-0.8.3}/kolega_code/llm/ratelimit.py +0 -0
  198. {kolega_code-0.8.2 → kolega_code-0.8.3}/kolega_code/llm/specs.py +0 -0
  199. {kolega_code-0.8.2 → kolega_code-0.8.3}/kolega_code/llm/tool_execution_ids.py +0 -0
  200. {kolega_code-0.8.2 → kolega_code-0.8.3}/kolega_code/models/__init__.py +0 -0
  201. {kolega_code-0.8.2 → kolega_code-0.8.3}/kolega_code/models/sandbox_terminal_state.py +0 -0
  202. {kolega_code-0.8.2 → kolega_code-0.8.3}/kolega_code/permissions.py +0 -0
  203. {kolega_code-0.8.2 → kolega_code-0.8.3}/kolega_code/runtime.py +0 -0
  204. {kolega_code-0.8.2 → kolega_code-0.8.3}/kolega_code/sandbox/README.md +0 -0
  205. {kolega_code-0.8.2 → kolega_code-0.8.3}/kolega_code/sandbox/__init__.py +0 -0
  206. {kolega_code-0.8.2 → kolega_code-0.8.3}/kolega_code/sandbox/async_filesystem.py +0 -0
  207. {kolega_code-0.8.2 → kolega_code-0.8.3}/kolega_code/sandbox/base.py +0 -0
  208. {kolega_code-0.8.2 → kolega_code-0.8.3}/kolega_code/sandbox/browser.py +0 -0
  209. {kolega_code-0.8.2 → kolega_code-0.8.3}/kolega_code/sandbox/event_loop.py +0 -0
  210. {kolega_code-0.8.2 → kolega_code-0.8.3}/kolega_code/sandbox/filesystem.py +0 -0
  211. {kolega_code-0.8.2 → kolega_code-0.8.3}/kolega_code/sandbox/local.py +0 -0
  212. {kolega_code-0.8.2 → kolega_code-0.8.3}/kolega_code/sandbox/serializer.py +0 -0
  213. {kolega_code-0.8.2 → kolega_code-0.8.3}/kolega_code/sandbox/terminal.py +0 -0
  214. {kolega_code-0.8.2 → kolega_code-0.8.3}/kolega_code/sandbox/utils.py +0 -0
  215. {kolega_code-0.8.2 → kolega_code-0.8.3}/kolega_code/services/base.py +0 -0
  216. {kolega_code-0.8.2 → kolega_code-0.8.3}/kolega_code/services/browser.py +0 -0
  217. {kolega_code-0.8.2 → kolega_code-0.8.3}/kolega_code/services/file_system.py +0 -0
  218. {kolega_code-0.8.2 → kolega_code-0.8.3}/kolega_code/services/html.py +0 -0
  219. {kolega_code-0.8.2 → kolega_code-0.8.3}/kolega_code/services/terminal.py +0 -0
  220. {kolega_code-0.8.2 → kolega_code-0.8.3}/kolega_code/services/terminal_buffer.py +0 -0
  221. {kolega_code-0.8.2 → kolega_code-0.8.3}/kolega_code/tools/__init__.py +0 -0
  222. {kolega_code-0.8.2 → kolega_code-0.8.3}/kolega_code/tools/core.py +0 -0
  223. {kolega_code-0.8.2 → kolega_code-0.8.3}/kolega_code/tools/definitions.py +0 -0
  224. {kolega_code-0.8.2 → kolega_code-0.8.3}/kolega_code/tools/registry.py +0 -0
  225. {kolega_code-0.8.2 → kolega_code-0.8.3}/kolega_code/utils/__init__.py +0 -0
  226. {kolega_code-0.8.2 → kolega_code-0.8.3}/kolega_code/utils/images.py +0 -0
  227. {kolega_code-0.8.2 → kolega_code-0.8.3}/run_tests.sh +0 -0
  228. {kolega_code-0.8.2 → kolega_code-0.8.3}/scripts/install-kolega-code.sh +0 -0
  229. {kolega_code-0.8.2/kolega_code/agent → kolega_code-0.8.3}/tests/__init__.py +0 -0
  230. {kolega_code-0.8.2/kolega_code/agent/tests/llm → kolega_code-0.8.3/tests/agent}/__init__.py +0 -0
  231. {kolega_code-0.8.2/kolega_code/agent/tests → kolega_code-0.8.3/tests/agent}/compaction_helpers.py +0 -0
  232. {kolega_code-0.8.2/kolega_code/agent/tests/tool_backend → kolega_code-0.8.3/tests/agent/llm}/__init__.py +0 -0
  233. {kolega_code-0.8.2/kolega_code/agent/tests → kolega_code-0.8.3/tests/agent}/llm/test_billing_openai_cache.py +0 -0
  234. {kolega_code-0.8.2/kolega_code/agent/tests → kolega_code-0.8.3/tests/agent}/llm/test_chatgpt_oauth_provider.py +0 -0
  235. {kolega_code-0.8.2/kolega_code/agent/tests → kolega_code-0.8.3/tests/agent}/llm/test_dashscope_mapping.py +0 -0
  236. {kolega_code-0.8.2/kolega_code/agent/tests → kolega_code-0.8.3/tests/agent}/llm/test_error_boundary.py +0 -0
  237. {kolega_code-0.8.2/kolega_code/agent/tests → kolega_code-0.8.3/tests/agent}/llm/test_exceptions.py +0 -0
  238. {kolega_code-0.8.2/kolega_code/agent/tests → kolega_code-0.8.3/tests/agent}/llm/test_google_thought_signature.py +0 -0
  239. {kolega_code-0.8.2/kolega_code/agent/tests → kolega_code-0.8.3/tests/agent}/llm/test_google_tool_signature_live.py +0 -0
  240. {kolega_code-0.8.2/kolega_code/agent/tests → kolega_code-0.8.3/tests/agent}/llm/test_instrumented_client.py +0 -0
  241. {kolega_code-0.8.2/kolega_code/agent/tests → kolega_code-0.8.3/tests/agent}/llm/test_langfuse_normalization.py +0 -0
  242. {kolega_code-0.8.2/kolega_code/agent/tests → kolega_code-0.8.3/tests/agent}/llm/test_model_specs.py +0 -0
  243. {kolega_code-0.8.2/kolega_code/agent/tests → kolega_code-0.8.3/tests/agent}/llm/test_openai_cached_tokens.py +0 -0
  244. {kolega_code-0.8.2/kolega_code/agent/tests → kolega_code-0.8.3/tests/agent}/llm/test_openai_cached_tokens_stream.py +0 -0
  245. {kolega_code-0.8.2/kolega_code/agent/tests → kolega_code-0.8.3/tests/agent}/llm/test_openai_message_conversion.py +0 -0
  246. {kolega_code-0.8.2/kolega_code/agent/tests → kolega_code-0.8.3/tests/agent}/llm/test_openai_responses_provider.py +0 -0
  247. {kolega_code-0.8.2/kolega_code/agent/tests → kolega_code-0.8.3/tests/agent}/llm/test_supports_vision.py +0 -0
  248. {kolega_code-0.8.2/kolega_code/agent/tests → kolega_code-0.8.3/tests/agent}/llm/test_thinking_effort.py +0 -0
  249. {kolega_code-0.8.2/kolega_code/agent/tests → kolega_code-0.8.3/tests/agent}/llm/test_tool_execution_ids.py +0 -0
  250. {kolega_code-0.8.2/kolega_code/auth/tests → kolega_code-0.8.3/tests/agent/orchestration}/__init__.py +0 -0
  251. {kolega_code-0.8.2/kolega_code/agent/orchestration/tests → kolega_code-0.8.3/tests/agent/orchestration}/test_orchestration.py +0 -0
  252. {kolega_code-0.8.2/kolega_code/agent/tests → kolega_code-0.8.3/tests/agent}/services/__init__.py +0 -0
  253. {kolega_code-0.8.2/kolega_code/agent/tests → kolega_code-0.8.3/tests/agent}/services/test_browser.py +0 -0
  254. {kolega_code-0.8.2/kolega_code/agent/tests → kolega_code-0.8.3/tests/agent}/services/test_browser_parity.py +0 -0
  255. {kolega_code-0.8.2/kolega_code/agent/tests → kolega_code-0.8.3/tests/agent}/services/test_file_system.py +0 -0
  256. {kolega_code-0.8.2/kolega_code/agent/tests → kolega_code-0.8.3/tests/agent}/services/test_sandbox_terminal_input.py +0 -0
  257. {kolega_code-0.8.2/kolega_code/agent/tests → kolega_code-0.8.3/tests/agent}/services/test_terminal.py +0 -0
  258. {kolega_code-0.8.2/kolega_code/agent/tests → kolega_code-0.8.3/tests/agent}/services/test_terminal_buffer.py +0 -0
  259. {kolega_code-0.8.2/kolega_code/agent/tests → kolega_code-0.8.3/tests/agent}/services/test_terminal_state_serializer.py +0 -0
  260. {kolega_code-0.8.2/kolega_code/agent/tests → kolega_code-0.8.3/tests/agent}/test_agent_tools_inventory.py +0 -0
  261. {kolega_code-0.8.2/kolega_code/agent/tests → kolega_code-0.8.3/tests/agent}/test_base_agent.py +0 -0
  262. {kolega_code-0.8.2/kolega_code/agent/tests → kolega_code-0.8.3/tests/agent}/test_coder_attachments.py +0 -0
  263. {kolega_code-0.8.2/kolega_code/agent/tests → kolega_code-0.8.3/tests/agent}/test_coder_prompt_extensions.py +0 -0
  264. {kolega_code-0.8.2/kolega_code/agent/tests → kolega_code-0.8.3/tests/agent}/test_compaction_integration.py +0 -0
  265. {kolega_code-0.8.2/kolega_code/agent/tests → kolega_code-0.8.3/tests/agent}/test_compaction_persistence.py +0 -0
  266. {kolega_code-0.8.2/kolega_code/agent/tests → kolega_code-0.8.3/tests/agent}/test_compaction_subagent.py +0 -0
  267. {kolega_code-0.8.2/kolega_code/agent/tests → kolega_code-0.8.3/tests/agent}/test_compaction_tui_events.py +0 -0
  268. {kolega_code-0.8.2/kolega_code/agent/tests → kolega_code-0.8.3/tests/agent}/test_compress_command.py +0 -0
  269. {kolega_code-0.8.2/kolega_code/agent/tests → kolega_code-0.8.3/tests/agent}/test_compression.py +0 -0
  270. {kolega_code-0.8.2/kolega_code/agent/tests → kolega_code-0.8.3/tests/agent}/test_conversation_compaction.py +0 -0
  271. {kolega_code-0.8.2/kolega_code/agent/tests → kolega_code-0.8.3/tests/agent}/test_duplicate_tool_results.py +0 -0
  272. {kolega_code-0.8.2/kolega_code/agent/tests → kolega_code-0.8.3/tests/agent}/test_empty_message_handling.py +0 -0
  273. {kolega_code-0.8.2/kolega_code/agent/tests → kolega_code-0.8.3/tests/agent}/test_event_emitter.py +0 -0
  274. {kolega_code-0.8.2/kolega_code/agent/tests → kolega_code-0.8.3/tests/agent}/test_general_agent.py +0 -0
  275. {kolega_code-0.8.2/kolega_code/agent/tests → kolega_code-0.8.3/tests/agent}/test_gigacode_gating.py +0 -0
  276. {kolega_code-0.8.2/kolega_code/agent/tests → kolega_code-0.8.3/tests/agent}/test_hooks_integration.py +0 -0
  277. {kolega_code-0.8.2/kolega_code/agent/tests → kolega_code-0.8.3/tests/agent}/test_html.py +0 -0
  278. {kolega_code-0.8.2/kolega_code/agent/tests → kolega_code-0.8.3/tests/agent}/test_image_compat.py +0 -0
  279. {kolega_code-0.8.2/kolega_code/agent/tests → kolega_code-0.8.3/tests/agent}/test_parallel_tool_calls.py +0 -0
  280. {kolega_code-0.8.2/kolega_code/agent/tests → kolega_code-0.8.3/tests/agent}/test_permissions.py +0 -0
  281. {kolega_code-0.8.2/kolega_code/agent/tests → kolega_code-0.8.3/tests/agent}/test_planning_agent.py +0 -0
  282. {kolega_code-0.8.2/kolega_code/agent/tests → kolega_code-0.8.3/tests/agent}/test_prompts.py +0 -0
  283. {kolega_code-0.8.2/kolega_code/agent/tests → kolega_code-0.8.3/tests/agent}/test_read_image_tool.py +0 -0
  284. {kolega_code-0.8.2/kolega_code/agent/tests → kolega_code-0.8.3/tests/agent}/test_tool_registry.py +0 -0
  285. {kolega_code-0.8.2/kolega_code/agent/tests → kolega_code-0.8.3/tests/agent}/test_tools.py +0 -0
  286. {kolega_code-0.8.2/kolega_code/hooks/tests → kolega_code-0.8.3/tests/agent/tool_backend}/__init__.py +0 -0
  287. {kolega_code-0.8.2/kolega_code/agent/tests → kolega_code-0.8.3/tests/agent}/tool_backend/test_agent_tool.py +0 -0
  288. {kolega_code-0.8.2/kolega_code/agent/tests → kolega_code-0.8.3/tests/agent}/tool_backend/test_base_tool.py +0 -0
  289. {kolega_code-0.8.2/kolega_code/agent/tests → kolega_code-0.8.3/tests/agent}/tool_backend/test_browser_tool.py +0 -0
  290. {kolega_code-0.8.2/kolega_code/agent/tests → kolega_code-0.8.3/tests/agent}/tool_backend/test_build_tool.py +0 -0
  291. {kolega_code-0.8.2/kolega_code/agent/tests → kolega_code-0.8.3/tests/agent}/tool_backend/test_create_file_tool.py +0 -0
  292. {kolega_code-0.8.2/kolega_code/agent/tests → kolega_code-0.8.3/tests/agent}/tool_backend/test_edit_preview.py +0 -0
  293. {kolega_code-0.8.2/kolega_code/agent/tests → kolega_code-0.8.3/tests/agent}/tool_backend/test_glob_tool.py +0 -0
  294. {kolega_code-0.8.2/kolega_code/agent/tests → kolega_code-0.8.3/tests/agent}/tool_backend/test_glob_tool_sandbox_parity.py +0 -0
  295. {kolega_code-0.8.2/kolega_code/agent/tests → kolega_code-0.8.3/tests/agent}/tool_backend/test_list_directory_tool.py +0 -0
  296. {kolega_code-0.8.2/kolega_code/agent/tests → kolega_code-0.8.3/tests/agent}/tool_backend/test_read_file_tool.py +0 -0
  297. {kolega_code-0.8.2/kolega_code/agent/tests → kolega_code-0.8.3/tests/agent}/tool_backend/test_replace_entire_file_tool.py +0 -0
  298. {kolega_code-0.8.2/kolega_code/agent/tests → kolega_code-0.8.3/tests/agent}/tool_backend/test_replace_lines_tool.py +0 -0
  299. {kolega_code-0.8.2/kolega_code/agent/tests → kolega_code-0.8.3/tests/agent}/tool_backend/test_search_and_replace_tool.py +0 -0
  300. {kolega_code-0.8.2/kolega_code/agent/tests → kolega_code-0.8.3/tests/agent}/tool_backend/test_search_codebase_tool.py +0 -0
  301. {kolega_code-0.8.2/kolega_code/agent/tests → kolega_code-0.8.3/tests/agent}/tool_backend/test_terminal_tool.py +0 -0
  302. {kolega_code-0.8.2/kolega_code/agent/tests → kolega_code-0.8.3/tests/agent}/tool_backend/test_think_hard_integration.py +0 -0
  303. {kolega_code-0.8.2/kolega_code/agent/tests → kolega_code-0.8.3/tests/agent}/tool_backend/test_think_hard_streaming.py +0 -0
  304. {kolega_code-0.8.2/kolega_code/agent/tests → kolega_code-0.8.3/tests/agent}/tool_backend/test_web_fetch_tool.py +0 -0
  305. {kolega_code-0.8.2/kolega_code/agent/tests → kolega_code-0.8.3/tests/agent}/tool_backend/test_web_search_tool.py +0 -0
  306. {kolega_code-0.8.2/kolega_code/agent/tests → kolega_code-0.8.3/tests/agent}/tool_backend/test_workflow_tool.py +0 -0
  307. {kolega_code-0.8.2/kolega_code/llm/providers → kolega_code-0.8.3/tests/auth}/__init__.py +0 -0
  308. {kolega_code-0.8.2/kolega_code/auth/tests → kolega_code-0.8.3/tests/auth}/test_tokens.py +0 -0
  309. {kolega_code-0.8.2/kolega_code/cli/tests → kolega_code-0.8.3/tests/cli}/__init__.py +0 -0
  310. {kolega_code-0.8.2/kolega_code/cli/tests → kolega_code-0.8.3/tests/cli}/test_app_compaction_restore.py +0 -0
  311. {kolega_code-0.8.2/kolega_code/cli/tests → kolega_code-0.8.3/tests/cli}/test_app_image_vision_warning.py +0 -0
  312. {kolega_code-0.8.2/kolega_code/cli/tests → kolega_code-0.8.3/tests/cli}/test_app_model_switch_vision.py +0 -0
  313. {kolega_code-0.8.2/kolega_code/cli/tests → kolega_code-0.8.3/tests/cli}/test_cli_config.py +0 -0
  314. {kolega_code-0.8.2/kolega_code/cli/tests → kolega_code-0.8.3/tests/cli}/test_connection.py +0 -0
  315. {kolega_code-0.8.2/kolega_code/cli/tests → kolega_code-0.8.3/tests/cli}/test_file_index.py +0 -0
  316. {kolega_code-0.8.2/kolega_code/cli/tests → kolega_code-0.8.3/tests/cli}/test_mentions.py +0 -0
  317. {kolega_code-0.8.2/kolega_code/cli/tests → kolega_code-0.8.3/tests/cli}/test_provider_registry.py +0 -0
  318. {kolega_code-0.8.2/kolega_code/cli/tests → kolega_code-0.8.3/tests/cli}/test_session_store.py +0 -0
  319. {kolega_code-0.8.2/kolega_code/cli/tests → kolega_code-0.8.3/tests/cli}/test_skills.py +0 -0
  320. {kolega_code-0.8.2/kolega_code/cli/tests → kolega_code-0.8.3/tests/cli}/test_themes.py +0 -0
  321. {kolega_code-0.8.2/kolega_code/cli/tests → kolega_code-0.8.3/tests/cli}/test_updater.py +0 -0
  322. {kolega_code-0.8.2/kolega_code/tools/tests → kolega_code-0.8.3/tests/hooks}/__init__.py +0 -0
  323. {kolega_code-0.8.2/kolega_code/hooks/tests → kolega_code-0.8.3/tests/hooks}/test_hooks.py +0 -0
  324. {kolega_code-0.8.2/kolega_code/utils/tests → kolega_code-0.8.3/tests/tools}/__init__.py +0 -0
  325. {kolega_code-0.8.2/kolega_code/tools/tests → kolega_code-0.8.3/tests/tools}/test_definitions.py +0 -0
  326. {kolega_code-0.8.2/kolega_code/utils/tests → kolega_code-0.8.3/tests/utils}/test_images.py +0 -0
  327. {kolega_code-0.8.2/kolega_code/utils/tests → kolega_code-0.8.3/tests/utils}/test_images_ascii.py +0 -0
@@ -43,4 +43,4 @@ jobs:
43
43
  run: uv sync --extra dev --frozen
44
44
 
45
45
  - name: Run fast tests
46
- run: uv run pytest -ra --durations=50 --import-mode=importlib -m "not slow"
46
+ run: ./run_tests.sh
@@ -46,7 +46,7 @@ Run slow and integration tests only when you have the required credentials:
46
46
  You can pass additional pytest arguments through the wrapper:
47
47
 
48
48
  ```bash
49
- ./run_tests.sh kolega_code/agent/tests/llm/test_client.py -ra
49
+ ./run_tests.sh tests/agent/llm/test_client.py -ra
50
50
  ```
51
51
 
52
52
  ## Documentation
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: kolega-code
3
- Version: 0.8.2
3
+ Version: 0.8.3
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/
@@ -29,7 +29,7 @@ release branch.
29
29
  3. Run the fast test suite:
30
30
 
31
31
  ```bash
32
- uv run pytest -ra --durations=50 --import-mode=importlib -m "not slow"
32
+ ./run_tests.sh
33
33
  ```
34
34
 
35
35
  4. Commit the release bump and open a pull request against `main`:
@@ -151,4 +151,4 @@ __all__ = [
151
151
  "parse_git_status_output",
152
152
  ]
153
153
 
154
- __version__ = "0.8.2"
154
+ __version__ = "0.8.3"
@@ -44,4 +44,4 @@ __all__ = [
44
44
  "ToolExtension",
45
45
  ]
46
46
 
47
- __version__ = "0.8.2"
47
+ __version__ = "0.8.3"
@@ -86,7 +86,6 @@ from .tui import state as tui_state
86
86
  from .tui import sub_agent_screen as tui_sub_agents
87
87
  from .tui import transcript as tui_transcript
88
88
  from .tui import widgets as tui_widgets
89
- from .tui.styles import APP_CSS
90
89
 
91
90
  CLI_AGENT_MODE = AgentMode.CLI.value
92
91
  LOG_MAX_LINES = 10_000
@@ -106,8 +105,7 @@ class KolegaCodeApp(
106
105
  ):
107
106
  """Interactive terminal UI for Kolega Code."""
108
107
 
109
- CSS = APP_CSS
110
-
108
+ CSS_PATH = "tui/styles.tcss"
111
109
 
112
110
  BINDINGS = [
113
111
  Binding(
@@ -978,7 +976,9 @@ class KolegaCodeApp(
978
976
 
979
977
  self.permission_mode = mode
980
978
  self.session.permission_mode = mode.value
979
+ self.settings.permission_mode = mode.value
981
980
  await self._save_session_async()
981
+ await asyncio.to_thread(self.settings_store.save, self.settings)
982
982
  if self.agent is not None:
983
983
  self.agent.set_permission_mode(mode)
984
984
  self.agent.set_permission_callback(self._permission_callback)
@@ -36,7 +36,7 @@ from .config import (
36
36
  from .connection import CliConnectionManager
37
37
  from .mentions import build_file_attachments
38
38
  from .session_store import SessionRecord, SessionStore, SessionStoreError
39
- from .settings import SettingsStore, SettingsStoreError
39
+ from .settings import CliSettings, SettingsStore, SettingsStoreError
40
40
  from .slash_commands import SKILLS_LIST_COMMAND, agent_command_names
41
41
  from .skills import (
42
42
  SkillCatalog,
@@ -327,6 +327,32 @@ def _resolve_tui_session(
327
327
  return store.create(project_path, CLI_AGENT_MODE, summary)
328
328
 
329
329
 
330
+ def _safe_permission_mode_value(value: Optional[str]) -> str:
331
+ try:
332
+ return normalize_permission_mode(value, default=PermissionMode.ASK).value
333
+ except ValueError:
334
+ return PermissionMode.ASK.value
335
+
336
+
337
+ def _resolve_tui_permission_mode(
338
+ session: SessionRecord,
339
+ settings: CliSettings,
340
+ requested_permission_mode: Optional[str],
341
+ *,
342
+ resumed: bool,
343
+ ) -> str:
344
+ """Resolve the TUI permission mode for this launch.
345
+
346
+ Precedence: explicit CLI flag, resumed session value, then global setting for
347
+ new sessions. Invalid legacy values fall back to ask.
348
+ """
349
+ if requested_permission_mode:
350
+ return normalize_permission_mode(requested_permission_mode, default=PermissionMode.ASK).value
351
+ if resumed:
352
+ return _safe_permission_mode_value(session.permission_mode)
353
+ return _safe_permission_mode_value(settings.permission_mode)
354
+
355
+
330
356
  def _run_version() -> int:
331
357
  result = check_for_update()
332
358
  print(f"kolega-code {result.current_version}")
@@ -374,11 +400,14 @@ def _run_tui(args: argparse.Namespace) -> int:
374
400
  args.resume,
375
401
  args.session,
376
402
  )
377
- if args.permission_mode:
378
- session.permission_mode = normalize_permission_mode(
379
- args.permission_mode,
380
- default=PermissionMode.ASK,
381
- ).value
403
+ effective_permission_mode = _resolve_tui_permission_mode(
404
+ session,
405
+ settings,
406
+ args.permission_mode,
407
+ resumed=args.resume is not None or bool(args.session),
408
+ )
409
+ if session.permission_mode != effective_permission_mode:
410
+ session.permission_mode = effective_permission_mode
382
411
  store.save(session)
383
412
 
384
413
  from .app import KolegaCodeApp
@@ -391,7 +420,7 @@ def _run_tui(args: argparse.Namespace) -> int:
391
420
  settings_store=settings_store,
392
421
  overrides=_overrides_from_args(args),
393
422
  session=session,
394
- permission_mode=args.permission_mode,
423
+ permission_mode=effective_permission_mode,
395
424
  browser_visible=args.browser_visible,
396
425
  check_for_updates=True,
397
426
  show_logs=args.show_logs,
@@ -8,6 +8,8 @@ from dataclasses import dataclass, field
8
8
  from pathlib import Path
9
9
  from typing import Optional
10
10
 
11
+ from kolega_code.permissions import PermissionMode
12
+
11
13
  from .session_store import default_state_dir
12
14
 
13
15
  SETTINGS_SCHEMA_VERSION = 3
@@ -59,6 +61,16 @@ def _coerce_oauth_tokens(raw: object) -> dict[str, dict]:
59
61
  return result
60
62
 
61
63
 
64
+ def _coerce_permission_mode(raw: object) -> str:
65
+ """Normalize a stored permission mode, falling back safely for old/bad files."""
66
+ if raw is None:
67
+ return PermissionMode.ASK.value
68
+ try:
69
+ return PermissionMode(str(raw).lower()).value
70
+ except ValueError:
71
+ return PermissionMode.ASK.value
72
+
73
+
62
74
  @dataclass
63
75
  class CliSettings:
64
76
  active_provider: Optional[str] = None
@@ -83,6 +95,9 @@ class CliSettings:
83
95
  # field — absent in older files -> empty mapping, no schema bump (same
84
96
  # convention as web_search_backend / active_theme).
85
97
  oauth_tokens: dict[str, dict] = field(default_factory=dict)
98
+ # Global default for new TUI sessions. Resumed sessions keep their own
99
+ # SessionRecord.permission_mode unless a CLI override is supplied.
100
+ permission_mode: str = PermissionMode.ASK.value
86
101
  schema_version: int = SETTINGS_SCHEMA_VERSION
87
102
 
88
103
  @classmethod
@@ -109,6 +124,8 @@ class CliSettings:
109
124
  web_search_base_url=data.get("web_search_base_url"),
110
125
  # Additive optional field; absent in older files -> empty mapping.
111
126
  oauth_tokens=_coerce_oauth_tokens(data.get("oauth_tokens")),
127
+ # Additive optional field; absent in older files -> ask.
128
+ permission_mode=_coerce_permission_mode(data.get("permission_mode")),
112
129
  )
113
130
 
114
131
  def to_dict(self) -> dict:
@@ -124,6 +141,7 @@ class CliSettings:
124
141
  "web_search_backend": self.web_search_backend,
125
142
  "web_search_base_url": self.web_search_base_url,
126
143
  "oauth_tokens": self.oauth_tokens,
144
+ "permission_mode": _coerce_permission_mode(self.permission_mode),
127
145
  }
128
146
 
129
147
  def get_api_key(self, provider: str) -> Optional[str]:
@@ -0,0 +1,335 @@
1
+ Screen {
2
+ layout: vertical;
3
+ }
4
+
5
+ #body {
6
+ height: 1fr;
7
+ }
8
+
9
+ #conversation_panel {
10
+ width: 2fr;
11
+ height: 100%;
12
+ }
13
+
14
+ #side_panel {
15
+ width: 1fr;
16
+ min-width: 34;
17
+ height: 100%;
18
+ }
19
+
20
+ #conversation, #logs, #terminal {
21
+ height: 1fr;
22
+ border: round $surface;
23
+ }
24
+
25
+ ConversationEntryWidget {
26
+ height: auto;
27
+ padding-bottom: 1;
28
+ }
29
+
30
+ ToolEntryWidget {
31
+ height: auto;
32
+ padding-bottom: 1;
33
+ }
34
+
35
+ ToolEntryWidget Collapsible {
36
+ background: transparent;
37
+ border-top: none;
38
+ padding-bottom: 0;
39
+ padding-left: 0;
40
+ }
41
+
42
+ ToolEntryWidget Collapsible Contents {
43
+ padding-left: 3;
44
+ }
45
+
46
+ ToolEntryWidget .tool-body {
47
+ color: $text-muted;
48
+ }
49
+
50
+ #jump_to_bottom {
51
+ display: none;
52
+ height: 1;
53
+ padding: 0 1;
54
+ background: $surface;
55
+ color: $text-muted;
56
+ text-align: center;
57
+ }
58
+
59
+ #status_container {
60
+ height: 1fr;
61
+ }
62
+
63
+ #status_dashboard {
64
+ height: 1fr;
65
+ min-height: 15;
66
+ border: round $surface;
67
+ padding: 1;
68
+ }
69
+
70
+ #settings_form, #planning_form {
71
+ height: 1fr;
72
+ padding: 1;
73
+ }
74
+
75
+ .settings-section {
76
+ height: auto;
77
+ border: round $surface;
78
+ border-title-color: $text;
79
+ border-title-style: bold;
80
+ padding: 0 1;
81
+ margin-bottom: 1;
82
+ }
83
+
84
+ #settings_status {
85
+ margin-top: 1;
86
+ }
87
+
88
+ #settings_form Label {
89
+ margin-top: 1;
90
+ }
91
+
92
+ #settings_form Button {
93
+ margin-top: 1;
94
+ }
95
+
96
+ .settings-hint {
97
+ color: $text-muted;
98
+ margin-top: 0;
99
+ }
100
+
101
+ .agent-model-group {
102
+ height: auto;
103
+ margin-top: 1;
104
+ }
105
+
106
+ .agent-model-role {
107
+ text-style: bold;
108
+ color: $text;
109
+ }
110
+
111
+ .agent-model-field {
112
+ height: auto;
113
+ margin-top: 1;
114
+ }
115
+
116
+ .agent-model-field-label {
117
+ width: 10;
118
+ margin-top: 1;
119
+ color: $text-muted;
120
+ }
121
+
122
+ .agent-model-field Select {
123
+ width: 1fr;
124
+ }
125
+
126
+ #settings_actions {
127
+ height: auto;
128
+ padding: 0 1;
129
+ margin-top: 1;
130
+ }
131
+
132
+ #planning_form Markdown.empty-state {
133
+ color: $text-muted;
134
+ }
135
+
136
+ #composer {
137
+ dock: bottom;
138
+ height: 5;
139
+ border: round $surface;
140
+ }
141
+
142
+ #turn_status {
143
+ display: none;
144
+ height: 1;
145
+ padding: 0 1;
146
+ color: $text-muted;
147
+ background: $surface;
148
+ }
149
+
150
+ #composer_hint_row {
151
+ display: none;
152
+ height: auto;
153
+ max-height: 4;
154
+ background: $surface;
155
+ }
156
+
157
+ #composer_hint_row #composer_hint {
158
+ width: 1fr;
159
+ height: auto;
160
+ padding: 0 1;
161
+ }
162
+
163
+ #composer_hint_row #detach_btn {
164
+ width: 3;
165
+ height: 1;
166
+ min-height: 1;
167
+ border: none;
168
+ background: transparent;
169
+ color: $text-muted;
170
+ padding: 0 1;
171
+ }
172
+
173
+ #composer_hint_row #detach_btn:hover {
174
+ color: $warning;
175
+ }
176
+
177
+ #composer_hint_row #detach_btn:focus {
178
+ color: $warning;
179
+ text-style: bold;
180
+ }
181
+
182
+ #completion_dropdown {
183
+ display: none;
184
+ height: auto;
185
+ max-height: 10;
186
+ border: round $surface;
187
+ background: $surface;
188
+ }
189
+
190
+ #composer_hint.hint-warning {
191
+ color: $warning;
192
+ }
193
+
194
+ #composer_hint.hint-info {
195
+ color: $text-muted;
196
+ }
197
+
198
+ #composer:disabled {
199
+ opacity: 0.6;
200
+ }
201
+
202
+ #plan_actions, #model_actions, #effort_actions, #theme_actions {
203
+ display: none;
204
+ height: auto;
205
+ max-height: 12;
206
+ border: round $surface;
207
+ background: $surface;
208
+ }
209
+
210
+ /* Question / approval prompts: the question is folded into the panel header
211
+ (the border title) above its options, so the whole prompt reads as one
212
+ bordered unit. The inner ActionList drops its own border. */
213
+ #question_prompt, #approval_prompt {
214
+ display: none;
215
+ height: auto;
216
+ max-height: 14;
217
+ border: round $surface;
218
+ background: $surface;
219
+ border-title-color: $text;
220
+ border-title-style: bold;
221
+ padding: 0 1;
222
+ }
223
+
224
+ #question_prompt > .prompt-header-scroll, #approval_prompt > .prompt-header-scroll {
225
+ height: auto;
226
+ max-height: 6;
227
+ overflow-y: auto;
228
+ background: $surface;
229
+ }
230
+
231
+ #question_prompt > ActionList, #approval_prompt > ActionList {
232
+ border: none;
233
+ background: $surface;
234
+ height: auto;
235
+ max-height: 6;
236
+ padding: 0;
237
+ }
238
+
239
+ .prompt-header {
240
+ height: auto;
241
+ padding: 0 0 1 0;
242
+ background: $surface;
243
+ }
244
+
245
+ /* Neutralize the selected-row highlight on every choice list. Textual paints
246
+ it with $block-cursor-background (= $primary, a saturated brand color),
247
+ which clashes with the otherwise-neutral chrome and looks wrong in 256-color
248
+ Terminal.app. Each theme pins $surface-lighten-2 to a near-neutral gray
249
+ (see theme.build_textual_theme) so the highlight stays subtle across all
250
+ themes — incl. Solarized, whose auto-derived $surface-lighten-2 would
251
+ otherwise quantize to a saturated teal. The OptionList type selector also
252
+ covers its subclasses: ActionList, CompletionDropdown, and the Select's
253
+ SelectOverlay dropdown. */
254
+ OptionList > .option-list--option-highlighted {
255
+ background: $surface-lighten-2;
256
+ color: $text;
257
+ }
258
+
259
+ .meta {
260
+ color: $text-muted;
261
+ }
262
+
263
+ Footer {
264
+ background: $surface;
265
+ }
266
+
267
+ Input {
268
+ border: round $surface;
269
+ }
270
+
271
+ Input:focus {
272
+ border: round $surface-lighten-2;
273
+ }
274
+
275
+ Select > SelectCurrent {
276
+ border: round $surface;
277
+ }
278
+
279
+ Select:focus > SelectCurrent {
280
+ border: round $surface-lighten-2;
281
+ }
282
+
283
+ Select > SelectOverlay {
284
+ border: round $surface;
285
+ }
286
+
287
+ SubAgentInspectorScreen {
288
+ align: center middle;
289
+ }
290
+
291
+ SubAgentInspectorScreen #inspector_body {
292
+ width: 100%;
293
+ height: 1fr;
294
+ }
295
+
296
+ SubAgentInspectorScreen #inspector_roster {
297
+ width: 40;
298
+ height: 100%;
299
+ border: round $surface;
300
+ padding: 0 1;
301
+ }
302
+
303
+ SubAgentInspectorScreen #inspector_main {
304
+ width: 1fr;
305
+ height: 100%;
306
+ }
307
+
308
+ SubAgentInspectorScreen #inspector_header {
309
+ height: auto;
310
+ border: round $surface;
311
+ padding: 0 1;
312
+ }
313
+
314
+ SubAgentInspectorScreen #inspector_trajectory {
315
+ height: 1fr;
316
+ border: round $surface;
317
+ padding: 0 1;
318
+ }
319
+
320
+ SubAgentRosterRow {
321
+ height: auto;
322
+ padding: 0 0 1 0;
323
+ }
324
+
325
+ SubAgentInspectorScreen .inspector-empty {
326
+ color: $text-muted;
327
+ padding: 1;
328
+ }
329
+
330
+ SubAgentInspectorScreen #inspector_footer {
331
+ height: 1;
332
+ padding: 0 1;
333
+ background: $surface;
334
+ color: $text-muted;
335
+ }
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "kolega-code"
7
- version = "0.8.2"
7
+ version = "0.8.3"
8
8
  description = "Local-first AI coding agent for the terminal"
9
9
  readme = "README.md"
10
10
  license = {file = "LICENSE"}
@@ -73,6 +73,7 @@ kolega-code = "kolega_code.cli.main:main"
73
73
  packages = ["kolega_code"]
74
74
 
75
75
  [tool.pytest.ini_options]
76
+ testpaths = ["tests"]
76
77
  asyncio_mode = "strict"
77
78
  asyncio_default_fixture_loop_scope = "function"
78
79
  markers = [
@@ -21,12 +21,10 @@ from kolega_code.llm.providers.anthropic import AnthropicProvider
21
21
  from kolega_code.agent.prompt_provider import AgentMode, AgentType, PromptContext, PromptProvider
22
22
  from kolega_code.agent.tools import ToolCollection, ToolCollectionConfig
23
23
 
24
- # Load environment variables
25
- # Navigate up to backend directory: llm -> tests -> agent -> kolega_code -> backend
26
- dotenv_path = os.path.join(
27
- os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname(__file__))))), ".env"
28
- )
29
- if os.path.exists(dotenv_path):
24
+ # Load environment variables from the repository root.
25
+ REPO_ROOT = Path(__file__).resolve().parents[3]
26
+ dotenv_path = REPO_ROOT / ".env"
27
+ if dotenv_path.exists():
30
28
  load_dotenv(dotenv_path)
31
29
 
32
30
 
@@ -4,7 +4,7 @@ Unlike the key-based providers, this one needs OAuth tokens from an interactive
4
4
  ``/login``. It is skipped unless real tokens are available, so it never runs in
5
5
  CI. To run it locally after signing in via the TUI::
6
6
 
7
- pytest -m integration kolega_code/agent/tests/llm/test_chatgpt_live.py -v
7
+ pytest -m integration tests/agent/llm/test_chatgpt_live.py -v
8
8
 
9
9
  Token source (first match wins):
10
10
  - KOLEGA_CODE_CHATGPT_TOKENS env var holding the JSON of an OAuthTokens dump, or
@@ -1,13 +1,16 @@
1
1
  import asyncio
2
2
  import os
3
+ from pathlib import Path
3
4
  from unittest.mock import AsyncMock, patch
4
5
 
5
6
  import pytest
6
7
  from dotenv import load_dotenv
7
8
 
8
- # Load environment variables directly at module level
9
- dotenv_path = os.path.join(os.path.dirname(os.path.dirname(os.path.dirname(__file__))), ".env")
10
- if os.path.exists(dotenv_path):
9
+ # Load repository-local environment variables directly at module level.
10
+ REPO_ROOT = Path(__file__).resolve().parents[3]
11
+
12
+ dotenv_path = REPO_ROOT / ".env"
13
+ if dotenv_path.exists():
11
14
  print(f"Loading environment variables from: {dotenv_path}")
12
15
  load_dotenv(dotenv_path)
13
16
  print(f"ANTHROPIC_API_KEY present: {bool(os.getenv('ANTHROPIC_API_KEY'))}")
@@ -18,24 +21,12 @@ else:
18
21
  print(f"Warning: .env file not found at {dotenv_path}")
19
22
  print("Tests requiring API keys may be skipped.")
20
23
 
21
- backend_env_local_path = os.path.join(
22
- os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname(__file__))))),
23
- ".env.local",
24
- )
25
- if os.path.exists(backend_env_local_path):
24
+ backend_env_local_path = REPO_ROOT / ".env.local"
25
+ if backend_env_local_path.exists():
26
26
  print(f"Loading environment variables from: {backend_env_local_path}")
27
27
  load_dotenv(backend_env_local_path)
28
28
  print(f"MOONSHOT_API_KEY present: {bool(os.getenv('MOONSHOT_API_KEY'))}")
29
29
 
30
- backend_env_path = os.path.join(
31
- os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname(__file__))))),
32
- ".env",
33
- )
34
- if os.path.exists(backend_env_path):
35
- print(f"Loading environment variables from: {backend_env_path}")
36
- load_dotenv(backend_env_path)
37
- print(f"MOONSHOT_API_KEY present: {bool(os.getenv('MOONSHOT_API_KEY'))}")
38
-
39
30
  from kolega_code.llm.client import (
40
31
  GenerationParams,
41
32
  LLMClient,
@@ -8,6 +8,7 @@ and Langfuse tracing.
8
8
 
9
9
  import asyncio
10
10
  import os
11
+ from pathlib import Path
11
12
  from unittest.mock import Mock
12
13
 
13
14
  import pytest
@@ -18,12 +19,10 @@ from opentelemetry.sdk.trace import TracerProvider as _OtelTracerProvider
18
19
  from kolega_code.llm.instrumented_client import InstrumentedLLMClient
19
20
  from kolega_code.llm.models import Message, MessageHistory, TextBlock, ToolCall
20
21
 
21
- # Load environment variables
22
- # Navigate up to backend directory: tests/llm -> tests -> agent -> kolega_code -> backend
23
- dotenv_path = os.path.join(
24
- os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname(__file__))))), ".env"
25
- )
26
- if os.path.exists(dotenv_path):
22
+ # Load environment variables from the repository root.
23
+ REPO_ROOT = Path(__file__).resolve().parents[3]
24
+ dotenv_path = REPO_ROOT / ".env"
25
+ if dotenv_path.exists():
27
26
  print(f"Loading environment variables from: {dotenv_path}")
28
27
  load_dotenv(dotenv_path)
29
28
  print(f"ANTHROPIC_API_KEY present: {bool(os.getenv('ANTHROPIC_API_KEY'))}")
@@ -8,7 +8,7 @@ retired ID surfaces here as a 4xx instead of silently shipping.
8
8
 
9
9
  Run them explicitly with the relevant keys set, e.g.::
10
10
 
11
- pytest -m integration kolega_code/agent/tests/llm/test_live_providers.py -v
11
+ pytest -m integration tests/agent/llm/test_live_providers.py -v
12
12
 
13
13
  The provider/model matrix is derived from the catalog itself, so new models are
14
14
  covered automatically.
@@ -6,6 +6,7 @@ of OpenAI's official API token counting, using real system prompts and tool defi
6
6
  """
7
7
 
8
8
  import os
9
+ from pathlib import Path
9
10
  from unittest.mock import Mock
10
11
 
11
12
  import pytest
@@ -25,12 +26,10 @@ from kolega_code.llm.providers.openai import OpenAIProvider
25
26
  from kolega_code.agent.prompt_provider import AgentMode, AgentType, PromptContext, PromptProvider
26
27
  from kolega_code.agent.tools import ToolCollection, ToolCollectionConfig
27
28
 
28
- # Load environment variables
29
- # Navigate up to backend directory: llm -> tests -> agent -> kolega_code -> backend
30
- dotenv_path = os.path.join(
31
- os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname(__file__))))), ".env"
32
- )
33
- if os.path.exists(dotenv_path):
29
+ # Load environment variables from the repository root.
30
+ REPO_ROOT = Path(__file__).resolve().parents[3]
31
+ dotenv_path = REPO_ROOT / ".env"
32
+ if dotenv_path.exists():
34
33
  load_dotenv(dotenv_path)
35
34
 
36
35