kolega-code 0.35.1__tar.gz → 0.37.0__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 (488) hide show
  1. {kolega_code-0.35.1 → kolega_code-0.37.0}/CHANGELOG.md +50 -0
  2. {kolega_code-0.35.1 → kolega_code-0.37.0}/PKG-INFO +3 -1
  3. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/__init__.py +1 -1
  4. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/agent/__init__.py +1 -1
  5. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/cli/gateway.py +13 -0
  6. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/cli/main.py +19 -1
  7. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/cli/provider_registry.py +2 -0
  8. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/cli/settings.py +81 -4
  9. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/cli/tui/settings_panel.py +128 -2
  10. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/cli/tui/settings_screen.py +20 -0
  11. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/gateway/bridge.py +35 -7
  12. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/gateway/service.py +36 -0
  13. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/llm/specs/accessors.py +6 -2
  14. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/llm/specs/catalog/deepseek.py +21 -0
  15. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/llm/specs/catalog/openai.py +15 -0
  16. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/llm/specs/catalog/openai_chatgpt.py +17 -0
  17. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/mcp/config.py +73 -2
  18. kolega_code-0.37.0/kolega_code/mcp/oauth.py +403 -0
  19. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/mcp/service.py +22 -0
  20. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/mcp/state.py +12 -1
  21. {kolega_code-0.35.1 → kolega_code-0.37.0}/pyproject.toml +7 -1
  22. kolega_code-0.35.1/kolega_code/mcp/oauth.py +0 -241
  23. {kolega_code-0.35.1 → kolega_code-0.37.0}/.gitignore +0 -0
  24. {kolega_code-0.35.1 → kolega_code-0.37.0}/CONTRIBUTING.md +0 -0
  25. {kolega_code-0.35.1 → kolega_code-0.37.0}/LICENSE +0 -0
  26. {kolega_code-0.35.1 → kolega_code-0.37.0}/MIGRATION.md +0 -0
  27. {kolega_code-0.35.1 → kolega_code-0.37.0}/README.md +0 -0
  28. {kolega_code-0.35.1 → kolega_code-0.37.0}/RELEASING.md +0 -0
  29. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/_bundled_skills/LICENSE +0 -0
  30. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/_bundled_skills/manifest.json +0 -0
  31. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/_bundled_skills/skills/deep-research/SKILL.md +0 -0
  32. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/_bundled_skills/skills/deep-research/references/evidence-and-reporting.md +0 -0
  33. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/_bundled_skills/skills/deep-research/references/gigacode-workflow.md +0 -0
  34. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/_bundled_skills/skills/deep-research/scripts/deep-research.workflow +0 -0
  35. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/_bundled_skills/skills/deep-research/scripts/materialize_report.py +0 -0
  36. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/_bundled_skills/skills/docx/LICENSE +0 -0
  37. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/_bundled_skills/skills/docx/SKILL.md +0 -0
  38. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/_bundled_skills/skills/docx/references/examples.md +0 -0
  39. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/_bundled_skills/skills/docx/references/limitations.md +0 -0
  40. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/_bundled_skills/skills/docx/references/operations.md +0 -0
  41. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/_bundled_skills/skills/docx/references/quality.md +0 -0
  42. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/_bundled_skills/skills/docx/requirements.txt +0 -0
  43. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/_bundled_skills/skills/docx/scripts/docx_tool.py +0 -0
  44. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/_bundled_skills/skills/docx/scripts/smoke_test.py +0 -0
  45. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/_bundled_skills/skills/humanizer/LICENSE +0 -0
  46. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/_bundled_skills/skills/humanizer/SKILL.md +0 -0
  47. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/_bundled_skills/skills/pdf/LICENSE +0 -0
  48. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/_bundled_skills/skills/pdf/SKILL.md +0 -0
  49. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/_bundled_skills/skills/pdf/references/examples.md +0 -0
  50. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/_bundled_skills/skills/pdf/references/limitations.md +0 -0
  51. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/_bundled_skills/skills/pdf/references/ocr.md +0 -0
  52. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/_bundled_skills/skills/pdf/references/operations.md +0 -0
  53. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/_bundled_skills/skills/pdf/references/quality.md +0 -0
  54. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/_bundled_skills/skills/pdf/references/redaction.md +0 -0
  55. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/_bundled_skills/skills/pdf/requirements-ocr-paddle.txt +0 -0
  56. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/_bundled_skills/skills/pdf/requirements-ocr-surya.txt +0 -0
  57. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/_bundled_skills/skills/pdf/requirements.txt +0 -0
  58. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/_bundled_skills/skills/pdf/scripts/pdf_tool.py +0 -0
  59. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/_bundled_skills/skills/pdf/scripts/smoke_test.py +0 -0
  60. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/_bundled_skills/skills/pptx/LICENSE +0 -0
  61. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/_bundled_skills/skills/pptx/SKILL.md +0 -0
  62. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/_bundled_skills/skills/pptx/references/examples.md +0 -0
  63. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/_bundled_skills/skills/pptx/references/limitations.md +0 -0
  64. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/_bundled_skills/skills/pptx/references/operations.md +0 -0
  65. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/_bundled_skills/skills/pptx/requirements.txt +0 -0
  66. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/_bundled_skills/skills/pptx/scripts/pptx_tool.py +0 -0
  67. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/_bundled_skills/skills/pptx/scripts/smoke_test.py +0 -0
  68. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/_bundled_skills/skills/review/SKILL.md +0 -0
  69. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/_bundled_skills/skills/review/references/github-publishing.md +0 -0
  70. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/_bundled_skills/skills/skill-authoring/SKILL.md +0 -0
  71. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/_bundled_skills/skills/skill-authoring/references/review-checklist.md +0 -0
  72. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/_bundled_skills/skills/xlsx/LICENSE +0 -0
  73. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/_bundled_skills/skills/xlsx/SKILL.md +0 -0
  74. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/_bundled_skills/skills/xlsx/references/examples.md +0 -0
  75. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/_bundled_skills/skills/xlsx/references/limitations.md +0 -0
  76. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/_bundled_skills/skills/xlsx/references/operations.md +0 -0
  77. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/_bundled_skills/skills/xlsx/references/quality.md +0 -0
  78. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/_bundled_skills/skills/xlsx/requirements.txt +0 -0
  79. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/_bundled_skills/skills/xlsx/scripts/smoke_test.py +0 -0
  80. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/_bundled_skills/skills/xlsx/scripts/xlsx_tool.py +0 -0
  81. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/acp/__init__.py +0 -0
  82. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/acp/agent_factory.py +0 -0
  83. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/acp/bridge.py +0 -0
  84. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/acp/diffs.py +0 -0
  85. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/acp/permissions.py +0 -0
  86. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/acp/plans.py +0 -0
  87. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/acp/questions.py +0 -0
  88. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/acp/server.py +0 -0
  89. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/acp/session.py +0 -0
  90. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/acp/usage.py +0 -0
  91. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/agent/baseagent.py +0 -0
  92. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/agent/browseragent.py +0 -0
  93. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/agent/coder.py +0 -0
  94. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/agent/common.py +0 -0
  95. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/agent/compression.py +0 -0
  96. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/agent/context.py +0 -0
  97. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/agent/conversation.py +0 -0
  98. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/agent/custom_agents.py +0 -0
  99. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/agent/edit_protocols.py +0 -0
  100. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/agent/errors.py +0 -0
  101. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/agent/eval/__init__.py +0 -0
  102. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/agent/eval/bridge.py +0 -0
  103. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/agent/eval/bundle-requirements.in +0 -0
  104. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/agent/eval/bundle-requirements.txt +0 -0
  105. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/agent/eval/env.py +0 -0
  106. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/agent/eval/js_kernel.py +0 -0
  107. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/agent/eval/kernel.py +0 -0
  108. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/agent/eval/prelude.js +0 -0
  109. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/agent/eval/prelude.py +0 -0
  110. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/agent/eval/protocol.py +0 -0
  111. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/agent/eval/py_kernel.py +0 -0
  112. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/agent/eval/runner.js +0 -0
  113. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/agent/eval/runner.py +0 -0
  114. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/agent/generalagent.py +0 -0
  115. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/agent/goal.py +0 -0
  116. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/agent/handoff.py +0 -0
  117. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/agent/investigationagent.py +0 -0
  118. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/agent/model_routing.py +0 -0
  119. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/agent/orchestration/__init__.py +0 -0
  120. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/agent/orchestration/accounting.py +0 -0
  121. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/agent/orchestration/budget.py +0 -0
  122. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/agent/orchestration/context.py +0 -0
  123. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/agent/orchestration/errors.py +0 -0
  124. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/agent/orchestration/executor.py +0 -0
  125. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/agent/orchestration/guide.py +0 -0
  126. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/agent/orchestration/journal.py +0 -0
  127. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/agent/orchestration/runtime.py +0 -0
  128. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/agent/orchestration/types.py +0 -0
  129. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/agent/planningagent.py +0 -0
  130. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/agent/prompt_dump.py +0 -0
  131. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/agent/prompt_overrides.py +0 -0
  132. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/agent/prompt_provider.py +0 -0
  133. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/agent/prompt_templates/auxiliary/agent_loop/silent_turn_exhausted.user.md +0 -0
  134. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/agent/prompt_templates/auxiliary/agent_loop/silent_turn_nudge.user.md.j2 +0 -0
  135. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/agent/prompt_templates/auxiliary/agent_loop/truncated_turn_nudge.user.md.j2 +0 -0
  136. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/agent/prompt_templates/auxiliary/compression/summary.system.md +0 -0
  137. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/agent/prompt_templates/auxiliary/compression/summary.user.md.j2 +0 -0
  138. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/agent/prompt_templates/auxiliary/handoff/document.system.md +0 -0
  139. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/agent/prompt_templates/auxiliary/handoff/document.user.md.j2 +0 -0
  140. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/agent/prompt_templates/auxiliary/terminal/output_summary.system.md +0 -0
  141. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/agent/prompt_templates/auxiliary/terminal/safety.system.md +0 -0
  142. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/agent/prompt_templates/extensions/cli/build_questions.md +0 -0
  143. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/agent/prompt_templates/extensions/cli/current_plan_artifact.md.j2 +0 -0
  144. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/agent/prompt_templates/extensions/cli/mode_switch_notice.md.j2 +0 -0
  145. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/agent/prompt_templates/extensions/cli/planning_questions.md +0 -0
  146. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/agent/prompt_templates/extensions/cli/scratchpad.md.j2 +0 -0
  147. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/agent/prompt_templates/extensions/cli/shared_task_list.md +0 -0
  148. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/agent/prompt_templates/extensions/cli/shared_task_list_readonly.md +0 -0
  149. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/agent/prompt_templates/extensions/cli/worktree_control.md.j2 +0 -0
  150. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/agent/prompt_templates/extensions/skills/catalog.md.j2 +0 -0
  151. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/agent/prompt_templates/system/agents/browser.md.j2 +0 -0
  152. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/agent/prompt_templates/system/agents/coder_ask.md.j2 +0 -0
  153. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/agent/prompt_templates/system/agents/coder_base.md.j2 +0 -0
  154. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/agent/prompt_templates/system/agents/coder_cli.md.j2 +0 -0
  155. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/agent/prompt_templates/system/agents/general.md.j2 +0 -0
  156. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/agent/prompt_templates/system/agents/investigation.md.j2 +0 -0
  157. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/agent/prompt_templates/system/agents/planning.md.j2 +0 -0
  158. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/agent/prompt_templates/system/includes/agents_md_instructions.md +0 -0
  159. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/agent/prompt_templates/system/includes/context_updates.md +0 -0
  160. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/agent/prompt_templates/system/includes/environment_variables/workspace_env_vars.md +0 -0
  161. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/agent/prompt_templates/system/includes/frontend_guidance.md +0 -0
  162. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/agent/prompt_templates/system/includes/starter_templates/expo.md +0 -0
  163. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/agent/prompt_templates/system/includes/starter_templates/html_website.md +0 -0
  164. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/agent/prompt_templates/system/includes/starter_templates/mern_stack.md +0 -0
  165. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/agent/prompt_templates/system/includes/starter_templates/react_vite_shadcdn.md +0 -0
  166. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/agent/prompt_templates/system/includes/terminal_tools.md +0 -0
  167. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/agent/prompt_templates/tools/apply_patch.md +0 -0
  168. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/agent/prompt_templates/tools/ask_user_choice.md +0 -0
  169. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/agent/prompt_templates/tools/browser_click.md +0 -0
  170. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/agent/prompt_templates/tools/browser_close.md +0 -0
  171. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/agent/prompt_templates/tools/browser_console_messages.md +0 -0
  172. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/agent/prompt_templates/tools/browser_drag.md +0 -0
  173. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/agent/prompt_templates/tools/browser_drop.md +0 -0
  174. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/agent/prompt_templates/tools/browser_evaluate.md +0 -0
  175. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/agent/prompt_templates/tools/browser_file_upload.md +0 -0
  176. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/agent/prompt_templates/tools/browser_fill_form.md +0 -0
  177. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/agent/prompt_templates/tools/browser_find.md +0 -0
  178. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/agent/prompt_templates/tools/browser_handle_dialog.md +0 -0
  179. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/agent/prompt_templates/tools/browser_hover.md +0 -0
  180. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/agent/prompt_templates/tools/browser_navigate.md +0 -0
  181. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/agent/prompt_templates/tools/browser_navigate_back.md +0 -0
  182. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/agent/prompt_templates/tools/browser_network_request.md +0 -0
  183. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/agent/prompt_templates/tools/browser_network_requests.md +0 -0
  184. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/agent/prompt_templates/tools/browser_press_key.md +0 -0
  185. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/agent/prompt_templates/tools/browser_resize.md +0 -0
  186. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/agent/prompt_templates/tools/browser_scroll.md +0 -0
  187. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/agent/prompt_templates/tools/browser_select_option.md +0 -0
  188. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/agent/prompt_templates/tools/browser_snapshot.md +0 -0
  189. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/agent/prompt_templates/tools/browser_tabs.md +0 -0
  190. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/agent/prompt_templates/tools/browser_take_screenshot.md +0 -0
  191. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/agent/prompt_templates/tools/browser_type.md +0 -0
  192. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/agent/prompt_templates/tools/browser_wait_for.md +0 -0
  193. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/agent/prompt_templates/tools/build_backend.md +0 -0
  194. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/agent/prompt_templates/tools/build_frontend.md +0 -0
  195. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/agent/prompt_templates/tools/claude_edit.md +0 -0
  196. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/agent/prompt_templates/tools/claude_write.md +0 -0
  197. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/agent/prompt_templates/tools/dispatch_agent.md +0 -0
  198. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/agent/prompt_templates/tools/edit.md +0 -0
  199. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/agent/prompt_templates/tools/eval.md +0 -0
  200. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/agent/prompt_templates/tools/exec_command.md +0 -0
  201. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/agent/prompt_templates/tools/get_host.md +0 -0
  202. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/agent/prompt_templates/tools/get_task_list.md +0 -0
  203. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/agent/prompt_templates/tools/get_task_list_readonly.md +0 -0
  204. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/agent/prompt_templates/tools/hashline_edit.md +0 -0
  205. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/agent/prompt_templates/tools/hashline_write.md +0 -0
  206. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/agent/prompt_templates/tools/kill_command.md +0 -0
  207. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/agent/prompt_templates/tools/list_agents.md +0 -0
  208. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/agent/prompt_templates/tools/list_sessions.md +0 -0
  209. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/agent/prompt_templates/tools/list_subagent_models.md +0 -0
  210. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/agent/prompt_templates/tools/list_workflow_runs.md +0 -0
  211. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/agent/prompt_templates/tools/lsp.md +0 -0
  212. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/agent/prompt_templates/tools/lsp_edit.md +0 -0
  213. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/agent/prompt_templates/tools/multi_edit.md +0 -0
  214. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/agent/prompt_templates/tools/read.md +0 -0
  215. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/agent/prompt_templates/tools/read_image.md +0 -0
  216. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/agent/prompt_templates/tools/resolve.md +0 -0
  217. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/agent/prompt_templates/tools/run_workflow.md +0 -0
  218. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/agent/prompt_templates/tools/send_message.md +0 -0
  219. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/agent/prompt_templates/tools/set_goal.md +0 -0
  220. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/agent/prompt_templates/tools/skill.md +0 -0
  221. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/agent/prompt_templates/tools/snapshot.md +0 -0
  222. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/agent/prompt_templates/tools/switch_worktree.md +0 -0
  223. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/agent/prompt_templates/tools/update_task_list.md +0 -0
  224. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/agent/prompt_templates/tools/web_fetch.md +0 -0
  225. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/agent/prompt_templates/tools/web_search.md +0 -0
  226. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/agent/prompt_templates/tools/write.md +0 -0
  227. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/agent/prompt_templates/tools/write_plan.md +0 -0
  228. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/agent/prompt_templates/tools/write_stdin.md +0 -0
  229. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/agent/prompt_templates/user_tasks/cli/implement_plan.md.j2 +0 -0
  230. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/agent/prompt_templates/user_tasks/cli/init_agents.md.j2 +0 -0
  231. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/agent/prompts.py +0 -0
  232. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/agent/session_metadata.py +0 -0
  233. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/agent/tool_backend/agent_tool.py +0 -0
  234. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/agent/tool_backend/base_tool.py +0 -0
  235. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/agent/tool_backend/browser_tool.py +0 -0
  236. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/agent/tool_backend/build_tool.py +0 -0
  237. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/agent/tool_backend/codex_patch.py +0 -0
  238. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/agent/tool_backend/edit_preview.py +0 -0
  239. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/agent/tool_backend/edit_tool.py +0 -0
  240. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/agent/tool_backend/eval_tool.py +0 -0
  241. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/agent/tool_backend/hashline_v2.py +0 -0
  242. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/agent/tool_backend/lsp_tool.py +0 -0
  243. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/agent/tool_backend/memory_tool.py +0 -0
  244. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/agent/tool_backend/network_status.py +0 -0
  245. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/agent/tool_backend/read_file_tool.py +0 -0
  246. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/agent/tool_backend/read_image_tool.py +0 -0
  247. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/agent/tool_backend/search_backends/__init__.py +0 -0
  248. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/agent/tool_backend/search_backends/base.py +0 -0
  249. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/agent/tool_backend/search_backends/duckduckgo.py +0 -0
  250. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/agent/tool_backend/search_backends/errors.py +0 -0
  251. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/agent/tool_backend/search_backends/firecrawl.py +0 -0
  252. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/agent/tool_backend/search_backends/models.py +0 -0
  253. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/agent/tool_backend/search_backends/searxng.py +0 -0
  254. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/agent/tool_backend/search_backends/tavily.py +0 -0
  255. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/agent/tool_backend/snapshot_tool.py +0 -0
  256. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/agent/tool_backend/streaming_tool.py +0 -0
  257. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/agent/tool_backend/terminal_tool.py +0 -0
  258. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/agent/tool_backend/web_fetch/__init__.py +0 -0
  259. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/agent/tool_backend/web_fetch/answering.py +0 -0
  260. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/agent/tool_backend/web_fetch/documents.py +0 -0
  261. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/agent/tool_backend/web_fetch/extractors.py +0 -0
  262. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/agent/tool_backend/web_fetch/pipeline.py +0 -0
  263. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/agent/tool_backend/web_fetch/retrieval.py +0 -0
  264. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/agent/tool_backend/web_fetch_tool.py +0 -0
  265. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/agent/tool_backend/web_search_tool.py +0 -0
  266. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/agent/tool_backend/workflow_tool.py +0 -0
  267. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/agent/tool_definitions.py +0 -0
  268. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/agent/tools.py +0 -0
  269. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/agent/utils/commands.py +0 -0
  270. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/agent/volatile_context.py +0 -0
  271. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/auth/__init__.py +0 -0
  272. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/auth/_jwt.py +0 -0
  273. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/auth/chatgpt_oauth.py +0 -0
  274. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/auth/constants.py +0 -0
  275. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/auth/tokens.py +0 -0
  276. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/browser_extension/__init__.py +0 -0
  277. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/browser_extension/framing.py +0 -0
  278. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/browser_extension/installer.py +0 -0
  279. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/browser_extension/manager.py +0 -0
  280. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/browser_extension/multiplex.py +0 -0
  281. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/browser_extension/native_host.py +0 -0
  282. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/browser_extension/protocol.py +0 -0
  283. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/browser_extension/registry.py +0 -0
  284. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/browser_extension/runtime.py +0 -0
  285. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/cli/__init__.py +0 -0
  286. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/cli/acp.py +0 -0
  287. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/cli/app.py +0 -0
  288. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/cli/ask_output.py +0 -0
  289. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/cli/atif_export.py +0 -0
  290. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/cli/browser_backend.py +0 -0
  291. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/cli/clipboard_image.py +0 -0
  292. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/cli/config.py +0 -0
  293. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/cli/connection.py +0 -0
  294. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/cli/cron.py +0 -0
  295. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/cli/diagnostics.py +0 -0
  296. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/cli/file_index.py +0 -0
  297. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/cli/goal.py +0 -0
  298. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/cli/loop.py +0 -0
  299. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/cli/mentions.py +0 -0
  300. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/cli/messages.py +0 -0
  301. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/cli/model_catalog.py +0 -0
  302. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/cli/model_connection.py +0 -0
  303. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/cli/peer_messaging.py +0 -0
  304. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/cli/plan_artifacts.py +0 -0
  305. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/cli/prompt_history.py +0 -0
  306. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/cli/session_event_protocol.py +0 -0
  307. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/cli/session_event_store.py +0 -0
  308. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/cli/session_journal.py +0 -0
  309. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/cli/session_store.py +0 -0
  310. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/cli/session_usage.py +0 -0
  311. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/cli/skills.py +0 -0
  312. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/cli/slash_commands.py +0 -0
  313. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/cli/theme.py +0 -0
  314. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/cli/tui/__init__.py +0 -0
  315. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/cli/tui/agent_runtime.py +0 -0
  316. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/cli/tui/app_base.py +0 -0
  317. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/cli/tui/changes_screen.py +0 -0
  318. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/cli/tui/command_handlers.py +0 -0
  319. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/cli/tui/constants.py +0 -0
  320. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/cli/tui/custom_model.py +0 -0
  321. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/cli/tui/loop_runtime.py +0 -0
  322. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/cli/tui/memory_screen.py +0 -0
  323. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/cli/tui/onboarding_screen.py +0 -0
  324. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/cli/tui/pacing.py +0 -0
  325. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/cli/tui/prompt_flows.py +0 -0
  326. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/cli/tui/session_diff.py +0 -0
  327. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/cli/tui/state.py +0 -0
  328. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/cli/tui/status_dashboard.py +0 -0
  329. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/cli/tui/styles.tcss +0 -0
  330. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/cli/tui/sub_agent_screen.py +0 -0
  331. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/cli/tui/terminal_display.py +0 -0
  332. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/cli/tui/transcript.py +0 -0
  333. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/cli/tui/widgets.py +0 -0
  334. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/cli/updater.py +0 -0
  335. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/config.py +0 -0
  336. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/events.py +0 -0
  337. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/extensions.py +0 -0
  338. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/gateway/__init__.py +0 -0
  339. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/gateway/access.py +0 -0
  340. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/gateway/adapters/__init__.py +0 -0
  341. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/gateway/adapters/base.py +0 -0
  342. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/gateway/adapters/echo.py +0 -0
  343. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/gateway/adapters/telegram/__init__.py +0 -0
  344. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/gateway/adapters/telegram/adapter.py +0 -0
  345. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/gateway/adapters/telegram/formatting.py +0 -0
  346. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/gateway/commands.py +0 -0
  347. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/gateway/config.py +0 -0
  348. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/gateway/control_relay.py +0 -0
  349. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/gateway/daemon.py +0 -0
  350. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/gateway/event_router.py +0 -0
  351. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/gateway/questions.py +0 -0
  352. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/gateway/redaction.py +0 -0
  353. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/gateway/router.py +0 -0
  354. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/gateway/sessions.py +0 -0
  355. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/gateway/stt.py +0 -0
  356. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/git_env.py +0 -0
  357. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/hooks/__init__.py +0 -0
  358. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/hooks/backends.py +0 -0
  359. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/hooks/config.py +0 -0
  360. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/hooks/dispatcher.py +0 -0
  361. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/hooks/events.py +0 -0
  362. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/hooks/matcher.py +0 -0
  363. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/hooks/outcome.py +0 -0
  364. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/llm/client.py +0 -0
  365. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/llm/exceptions.py +0 -0
  366. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/llm/instrumented_client.py +0 -0
  367. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/llm/ledger.py +0 -0
  368. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/llm/models.py +0 -0
  369. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/llm/providers/__init__.py +0 -0
  370. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/llm/providers/_token_encoding.py +0 -0
  371. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/llm/providers/anthropic.py +0 -0
  372. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/llm/providers/base.py +0 -0
  373. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/llm/providers/chatgpt_oauth.py +0 -0
  374. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/llm/providers/deepseek_responses.py +0 -0
  375. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/llm/providers/google.py +0 -0
  376. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/llm/providers/models.py +0 -0
  377. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/llm/providers/openai.py +0 -0
  378. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/llm/providers/openai_responses.py +0 -0
  379. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/llm/providers/perplexity_responses.py +0 -0
  380. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/llm/providers/responses_common.py +0 -0
  381. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/llm/providers/tinker.py +0 -0
  382. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/llm/providers/tinker_trace.py +0 -0
  383. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/llm/ratelimit.py +0 -0
  384. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/llm/specs/__init__.py +0 -0
  385. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/llm/specs/catalog/__init__.py +0 -0
  386. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/llm/specs/catalog/anthropic.py +0 -0
  387. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/llm/specs/catalog/dashscope.py +0 -0
  388. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/llm/specs/catalog/fireworks.py +0 -0
  389. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/llm/specs/catalog/google.py +0 -0
  390. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/llm/specs/catalog/groq.py +0 -0
  391. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/llm/specs/catalog/kimi_coding.py +0 -0
  392. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/llm/specs/catalog/moonshot.py +0 -0
  393. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/llm/specs/catalog/ollama_cloud.py +0 -0
  394. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/llm/specs/catalog/openrouter.py +0 -0
  395. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/llm/specs/catalog/perplexity_agent.py +0 -0
  396. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/llm/specs/catalog/thinking_machines.py +0 -0
  397. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/llm/specs/catalog/tinker.py +0 -0
  398. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/llm/specs/catalog/together.py +0 -0
  399. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/llm/specs/catalog/xai.py +0 -0
  400. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/llm/specs/catalog/zai.py +0 -0
  401. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/llm/specs/custom_endpoints.py +0 -0
  402. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/llm/specs/ollama_cloud_catalog.py +0 -0
  403. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/llm/specs/openrouter_catalog.py +0 -0
  404. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/llm/specs/perplexity_catalog.py +0 -0
  405. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/llm/specs/thinking.py +0 -0
  406. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/llm/specs/tinker_catalog.py +0 -0
  407. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/llm/specs/types.py +0 -0
  408. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/llm/specs/validation.py +0 -0
  409. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/llm/timeouts.py +0 -0
  410. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/llm/tool_execution_ids.py +0 -0
  411. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/llm/usage.py +0 -0
  412. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/local_state.py +0 -0
  413. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/mcp/__init__.py +0 -0
  414. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/mcp/tools.py +0 -0
  415. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/mcp/transport.py +0 -0
  416. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/memory/__init__.py +0 -0
  417. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/memory/identity.py +0 -0
  418. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/memory/manager.py +0 -0
  419. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/memory/manifest.py +0 -0
  420. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/memory/markdown.py +0 -0
  421. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/memory/models.py +0 -0
  422. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/memory/protocol.py +0 -0
  423. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/memory/registry.py +0 -0
  424. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/models/__init__.py +0 -0
  425. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/models/sandbox_terminal_state.py +0 -0
  426. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/permissions.py +0 -0
  427. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/runtime.py +0 -0
  428. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/sandbox/README.md +0 -0
  429. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/sandbox/__init__.py +0 -0
  430. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/sandbox/async_filesystem.py +0 -0
  431. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/sandbox/base.py +0 -0
  432. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/sandbox/browser.py +0 -0
  433. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/sandbox/event_loop.py +0 -0
  434. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/sandbox/filesystem.py +0 -0
  435. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/sandbox/local.py +0 -0
  436. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/sandbox/serializer.py +0 -0
  437. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/sandbox/terminal.py +0 -0
  438. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/sandbox/utils.py +0 -0
  439. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/scratchpad.py +0 -0
  440. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/security/__init__.py +0 -0
  441. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/security/secrets.py +0 -0
  442. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/services/base.py +0 -0
  443. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/services/browser.py +0 -0
  444. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/services/file_system.py +0 -0
  445. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/services/html.py +0 -0
  446. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/services/lsp/__init__.py +0 -0
  447. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/services/lsp/client.py +0 -0
  448. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/services/lsp/config.py +0 -0
  449. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/services/lsp/detector.py +0 -0
  450. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/services/lsp/diagnostics.py +0 -0
  451. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/services/lsp/edits.py +0 -0
  452. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/services/lsp/manager.py +0 -0
  453. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/services/lsp/registry.py +0 -0
  454. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/services/lsp/registry.yaml +0 -0
  455. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/services/snapshots.py +0 -0
  456. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/services/terminal.py +0 -0
  457. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/services/terminal_buffer.py +0 -0
  458. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/services/workspace_scan.py +0 -0
  459. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/session/__init__.py +0 -0
  460. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/session/control.py +0 -0
  461. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/session/inbox.py +0 -0
  462. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/session/inmemory.py +0 -0
  463. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/session/projection.py +0 -0
  464. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/session/recording.py +0 -0
  465. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/session/runtime.py +0 -0
  466. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/session/store.py +0 -0
  467. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/testing/__init__.py +0 -0
  468. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/testing/store_conformance.py +0 -0
  469. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/tools/__init__.py +0 -0
  470. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/tools/ask_user.py +0 -0
  471. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/tools/core.py +0 -0
  472. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/tools/definitions.py +0 -0
  473. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/tools/param_aliases.py +0 -0
  474. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/tools/registry.py +0 -0
  475. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/utils/__init__.py +0 -0
  476. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/utils/images.py +0 -0
  477. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/web/__init__.py +0 -0
  478. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/web/assets/fold.js +0 -0
  479. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/web/assets/player.css +0 -0
  480. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/web/assets/player.html +0 -0
  481. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/web/assets/player.js +0 -0
  482. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/web/bundle.py +0 -0
  483. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/web/hosting.py +0 -0
  484. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/web/redaction.py +0 -0
  485. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/web/server.py +0 -0
  486. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/web/singlefile.py +0 -0
  487. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/web/theme_css.py +0 -0
  488. {kolega_code-0.35.1 → kolega_code-0.37.0}/kolega_code/worktrees.py +0 -0
@@ -6,6 +6,56 @@ This project uses GitHub Releases for detailed generated release notes. This fil
6
6
 
7
7
  ## Unreleased
8
8
 
9
+ ## 0.37.0 - 2026-09-09
10
+
11
+ ### Added
12
+
13
+ - **DeepSeek V4.1 Flash (preview).** DeepSeek's temporary
14
+ `deepseek-v4.1-flash-expires-on-0910` model is available under **DeepSeek V4.1
15
+ Flash (Preview, expires Sep 10)** in the model picker, with vision, hosted web
16
+ search, and `none`/`low`/`high`/`max` reasoning effort (default `high`). It is
17
+ not the default and is not aliased to a stable model; the ID expires on
18
+ September 10, 2026, after which an available stable model must be selected.
19
+
20
+ ### Fixed
21
+
22
+ - Pin PDFium and the Intel Python 3.11/3.12 ONNX Runtime dependency to restore
23
+ compatible wheel selection on macOS Monterey for both the installer and direct
24
+ package installs. Intel Monterey requires Python 3.11 or 3.12.
25
+ - Settings saves are merged with concurrent writers instead of replacing the whole
26
+ file, so a long-running instance can no longer drop a gateway token or API key
27
+ another process saved after it started.
28
+ - `kolega-code gateway status` now reports an installed background service that
29
+ is failing to start (service state, start count, last exit code, log path)
30
+ instead of only printing "not running".
31
+
32
+ ## 0.36.0 - 2026-09-07
33
+
34
+ ### Added
35
+
36
+ - **GPT-6 Astra.** OpenAI's new flagship model is available on both the API
37
+ and ChatGPT-subscription providers: 1M-token context with 128K output,
38
+ vision, hosted web search, `codex_apply_patch` editing, and
39
+ `low`–`max` reasoning effort levels (default `medium`). The
40
+ ChatGPT-subscription route keeps the conservative 400K input budget until
41
+ Astra's larger window is verified on the Codex backend.
42
+ - **Pre-registered OAuth credentials for remote MCP servers.** Servers that
43
+ don't implement Dynamic Client Registration (HubSpot, Slack, GitHub
44
+ Copilot, enterprise IdPs) can now be connected with a pre-registered
45
+ client: new `--oauth-client-id`, `--oauth-client-secret`,
46
+ `--oauth-client-secret-env`, and `--oauth-auth-method` flags on
47
+ `kolega-code mcp add`, matching OAuth controls on the MCP page in TUI
48
+ settings, preserved explicit redirect ports/hosts, actionable diagnostics
49
+ when registration fails, and PBKDF2-salted OAuth cache fingerprints with
50
+ refresh tokens preserved across reconnects.
51
+
52
+ ### Fixed
53
+
54
+ - **Gateway (Telegram):** the typing indicator now stays alive for the whole
55
+ turn. Telegram expires typing actions after ~5 seconds, so it previously
56
+ vanished during exactly the stretches where feedback matters — model
57
+ thinking before the first chunk and long-running tool calls.
58
+
9
59
  ## 0.35.1 - 2026-09-03
10
60
 
11
61
  ### Fixed
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: kolega-code
3
- Version: 0.35.1
3
+ Version: 0.37.0
4
4
  Summary: Multi-agent coding in 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/
@@ -47,6 +47,7 @@ Requires-Dist: markdownify==1.2.3
47
47
  Requires-Dist: markitdown[docx,pdf,pptx,xls,xlsx]==0.1.6
48
48
  Requires-Dist: mcp==1.28.1
49
49
  Requires-Dist: nest-asyncio==1.6.0
50
+ Requires-Dist: onnxruntime==1.19.2; sys_platform == 'darwin' and platform_machine == 'x86_64' and python_version < '3.13'
50
51
  Requires-Dist: onnxruntime==1.27.0; python_version >= '3.14' and sys_platform != 'win32'
51
52
  Requires-Dist: openai==2.46.0
52
53
  Requires-Dist: packaging==25.0
@@ -56,6 +57,7 @@ Requires-Dist: playwright==1.59.0
56
57
  Requires-Dist: psutil==7.2.2
57
58
  Requires-Dist: pydantic==2.13.4
58
59
  Requires-Dist: pygments==2.20.0
60
+ Requires-Dist: pypdfium2==5.11.0
59
61
  Requires-Dist: python-dotenv==1.2.2
60
62
  Requires-Dist: pyyaml==6.0.3
61
63
  Requires-Dist: readability-lxml==0.8.4.1
@@ -174,4 +174,4 @@ __all__ = [
174
174
  "parse_git_status_output",
175
175
  ]
176
176
 
177
- __version__ = "0.35.1"
177
+ __version__ = "0.37.0"
@@ -51,4 +51,4 @@ __all__ = [
51
51
  "ToolExtension",
52
52
  ]
53
53
 
54
- __version__ = "0.35.1"
54
+ __version__ = "0.37.0"
@@ -33,6 +33,7 @@ from kolega_code.gateway.service import (
33
33
  install_service,
34
34
  is_service_installed,
35
35
  restart_service,
36
+ service_state_summary,
36
37
  uninstall_service,
37
38
  )
38
39
 
@@ -290,6 +291,7 @@ def _gateway_status(config: GatewayConfig) -> int:
290
291
  if payload is not None:
291
292
  # A heartbeat from a process that no longer exists (e.g. SIGKILLed).
292
293
  print(f"gateway: not running (stale heartbeat from pid {payload.get('pid')})")
294
+ _print_service_state(config)
293
295
  return 0
294
296
  lock = FileLock(str(config.state_dir / LOCK_FILE_NAME))
295
297
  try:
@@ -303,9 +305,20 @@ def _gateway_status(config: GatewayConfig) -> int:
303
305
  return 0
304
306
  lock.release()
305
307
  print(f"gateway: not running (state: {config.state_dir})")
308
+ _print_service_state(config)
306
309
  return 0
307
310
 
308
311
 
312
+ def _print_service_state(config: GatewayConfig) -> None:
313
+ summary = service_state_summary()
314
+ if summary is None:
315
+ return
316
+ print(f" service: {summary}")
317
+ log_path = config.state_dir / "gateway.log"
318
+ if log_path.exists():
319
+ print(f" log: {log_path}")
320
+
321
+
309
322
  def _pid_alive(pid: Any) -> bool:
310
323
  if not isinstance(pid, int) or pid <= 0:
311
324
  return False
@@ -796,6 +796,14 @@ def _build_subcommand_parser() -> argparse.ArgumentParser:
796
796
  add.add_argument("--env", action="append", default=[], help="Environment variable as NAME=VALUE (repeatable).")
797
797
  add.add_argument("--cwd", help="Working directory for stdio command; relative paths resolve under project.")
798
798
  add.add_argument("--oauth", action="store_true", help="Enable OAuth for this HTTP MCP server.")
799
+ add.add_argument("--oauth-client-id", help="Pre-registered OAuth client ID.")
800
+ add.add_argument("--oauth-client-secret", help="Pre-registered OAuth client secret.")
801
+ add.add_argument("--oauth-client-secret-env", help="Environment variable name holding the OAuth client secret.")
802
+ add.add_argument(
803
+ "--oauth-auth-method",
804
+ choices=["client_secret_post", "client_secret_basic", "none"],
805
+ help="Token endpoint authentication method.",
806
+ )
799
807
  add.add_argument("--oauth-scope", help="OAuth scopes to request.")
800
808
  add.add_argument("--redirect-uri", help="OAuth redirect URI; defaults to an ephemeral localhost callback.")
801
809
  add.add_argument("--disabled", action="store_true", help="Add the server disabled.")
@@ -2697,6 +2705,12 @@ def _mcp_mutation_target(args: argparse.Namespace, project_path: Path, state_dir
2697
2705
  def _server_config_from_add_args(args: argparse.Namespace) -> MCPServerConfig:
2698
2706
  headers = _parse_key_value_options(getattr(args, "header", []) or [], "--header")
2699
2707
  env = _parse_key_value_options(getattr(args, "env", []) or [], "--env")
2708
+ oauth_client_id = getattr(args, "oauth_client_id", None)
2709
+ oauth_client_secret = getattr(args, "oauth_client_secret", None)
2710
+ oauth_client_secret_env = getattr(args, "oauth_client_secret_env", None)
2711
+ oauth_auth_method = getattr(args, "oauth_auth_method", None)
2712
+ oauth_enabled = bool(args.oauth) or bool(oauth_client_id or oauth_client_secret or oauth_client_secret_env)
2713
+
2700
2714
  payload: dict[str, Any] = {
2701
2715
  "id": args.server_id,
2702
2716
  "name": args.name,
@@ -2709,9 +2723,13 @@ def _server_config_from_add_args(args: argparse.Namespace) -> MCPServerConfig:
2709
2723
  "env": env,
2710
2724
  "cwd": args.cwd,
2711
2725
  "oauth": {
2712
- "enabled": bool(args.oauth),
2726
+ "enabled": oauth_enabled,
2713
2727
  "scope": args.oauth_scope,
2714
2728
  "redirect_uri": args.redirect_uri,
2729
+ "client_id": oauth_client_id,
2730
+ "client_secret": oauth_client_secret,
2731
+ "client_secret_env": oauth_client_secret_env,
2732
+ "token_endpoint_auth_method": oauth_auth_method,
2715
2733
  },
2716
2734
  }
2717
2735
  return MCPServerConfig.model_validate(payload)
@@ -70,6 +70,7 @@ MODEL_LABELS: dict[str, str] = {
70
70
  "kimi-for-coding": "Kimi for Coding",
71
71
  "kimi-for-coding-highspeed": "Kimi for Coding (HighSpeed)",
72
72
  # DeepSeek
73
+ "deepseek-v4.1-flash-expires-on-0910": "DeepSeek V4.1 Flash (Preview, expires Sep 10)",
73
74
  "deepseek-v4-pro": "DeepSeek V4 Pro",
74
75
  "deepseek-v4-flash": "DeepSeek V4 Flash",
75
76
  "deepseek-v4-flash-vision-exp": "DeepSeek V4 Flash Vision (Exp)",
@@ -90,6 +91,7 @@ MODEL_LABELS: dict[str, str] = {
90
91
  "claude-opus-4-5-20251101": "Claude Opus 4.5",
91
92
  "claude-haiku-4-5-20251001": "Claude Haiku 4.5",
92
93
  # OpenAI (shared labels across the API and ChatGPT-subscription providers)
94
+ "gpt-6-astra": "GPT-6 Astra",
93
95
  "gpt-5.6-sol": "GPT-5.6 Sol",
94
96
  "gpt-5.6-terra": "GPT-5.6 Terra",
95
97
  "gpt-5.6-luna": "GPT-5.6 Luna",
@@ -2,11 +2,15 @@
2
2
 
3
3
  from __future__ import annotations
4
4
 
5
+ import copy
5
6
  import json
6
7
  from dataclasses import dataclass, field
7
8
  from pathlib import Path
8
9
  from typing import Any, Optional
9
10
 
11
+ from filelock import FileLock
12
+ from filelock import Timeout as FileLockTimeout
13
+
10
14
  from kolega_code.local_state import write_private_text
11
15
  from kolega_code.llm.specs.custom_endpoints import (
12
16
  API_STYLES,
@@ -33,6 +37,41 @@ class SettingsStoreError(RuntimeError):
33
37
  """Raised when CLI settings cannot be loaded or saved."""
34
38
 
35
39
 
40
+ SETTINGS_LOCK_TIMEOUT_SECONDS = 10.0
41
+
42
+
43
+ def _merge_settings_documents(
44
+ base: dict[str, Any],
45
+ current: dict[str, Any],
46
+ on_disk: dict[str, Any],
47
+ ) -> dict[str, Any]:
48
+ """Apply one writer's changes on top of the current document.
49
+
50
+ ``base`` is the state the writer loaded, so keys it did not touch keep the
51
+ on-disk value and a stale writer cannot revert another process's change.
52
+ Nested dicts merge key by key, and keys the writer never saw survive.
53
+ """
54
+ merged: dict[str, Any] = {}
55
+ for key in set(base) | set(current) | set(on_disk):
56
+ if key not in current:
57
+ if key in base:
58
+ continue
59
+ if key in on_disk:
60
+ merged[key] = on_disk[key]
61
+ continue
62
+ if key in base and base[key] == current[key]:
63
+ merged[key] = on_disk[key] if key in on_disk else current[key]
64
+ continue
65
+ if key not in base and current[key] is None and key in on_disk:
66
+ merged[key] = on_disk[key]
67
+ continue
68
+ if isinstance(base.get(key), dict) and isinstance(current[key], dict) and isinstance(on_disk.get(key), dict):
69
+ merged[key] = _merge_settings_documents(base[key], current[key], on_disk[key])
70
+ continue
71
+ merged[key] = current[key]
72
+ return merged
73
+
74
+
36
75
  def _coerce_model_entries(raw: object) -> dict[str, dict]:
37
76
  """Normalize a stored key -> {provider, model, ...} mapping.
38
77
 
@@ -272,6 +311,9 @@ class CliSettings:
272
311
  # Additive optional field — absent in older files -> empty mapping.
273
312
  custom_endpoints: dict[str, dict] = field(default_factory=dict)
274
313
  schema_version: int = SETTINGS_SCHEMA_VERSION
314
+ # The document this instance was loaded from, used as the merge base by
315
+ # SettingsStore.save(). Never serialized.
316
+ _merge_base: Optional[dict[str, Any]] = field(default=None, repr=False, compare=False)
275
317
 
276
318
  @classmethod
277
319
  def from_dict(cls, data: dict) -> "CliSettings":
@@ -452,12 +494,47 @@ class SettingsStore:
452
494
 
453
495
  def load(self) -> CliSettings:
454
496
  if not self.path.exists():
455
- return CliSettings()
497
+ settings = CliSettings()
498
+ settings._merge_base = copy.deepcopy(settings.to_dict())
499
+ return settings
456
500
  try:
457
- return CliSettings.from_dict(json.loads(self.path.read_text(encoding="utf-8")))
501
+ data = json.loads(self.path.read_text(encoding="utf-8"))
502
+ settings = CliSettings.from_dict(data)
458
503
  except json.JSONDecodeError as exc:
459
504
  raise SettingsStoreError(f"Settings file is not valid JSON: {self.path}") from exc
505
+ # The merge base is what this process understood, not the raw file:
506
+ # a key it never saw (newer schema, hand-edit) must survive its save.
507
+ settings._merge_base = copy.deepcopy(settings.to_dict())
508
+ if isinstance(data, dict) and "schema_version" in data:
509
+ settings._merge_base["schema_version"] = data["schema_version"]
510
+ return settings
460
511
 
461
512
  def save(self, settings: CliSettings) -> None:
462
- payload = json.dumps(settings.to_dict(), indent=2, sort_keys=True)
463
- write_private_text(self.path, payload + "\n")
513
+ """Write this instance's changes, keeping concurrent writers' fields."""
514
+ lock = FileLock(f"{self.path}.lock")
515
+ try:
516
+ lock.acquire(timeout=SETTINGS_LOCK_TIMEOUT_SECONDS)
517
+ except FileLockTimeout as exc:
518
+ raise SettingsStoreError(f"Timed out locking the settings file: {self.path}") from exc
519
+ try:
520
+ merged = self._merged_document(settings)
521
+ payload = json.dumps(merged, indent=2, sort_keys=True)
522
+ write_private_text(self.path, payload + "\n")
523
+ finally:
524
+ lock.release()
525
+ settings._merge_base = copy.deepcopy(merged)
526
+
527
+ def _merged_document(self, settings: CliSettings) -> dict[str, Any]:
528
+ current = settings.to_dict()
529
+ if settings._merge_base is None:
530
+ return current
531
+ return _merge_settings_documents(settings._merge_base, current, self._read_document())
532
+
533
+ def _read_document(self) -> dict[str, Any]:
534
+ try:
535
+ raw = json.loads(self.path.read_text(encoding="utf-8"))
536
+ except FileNotFoundError:
537
+ return {}
538
+ except (json.JSONDecodeError, OSError) as exc:
539
+ raise SettingsStoreError(f"Settings file is not valid JSON: {self.path}") from exc
540
+ return raw if isinstance(raw, dict) else {}
@@ -104,6 +104,12 @@ MCP_TRANSPORT_OPTIONS = [
104
104
  ("stdio command", "stdio"),
105
105
  ]
106
106
  MCP_ENABLED_OPTIONS = [("Enabled", "true"), ("Disabled", "false")]
107
+ MCP_OAUTH_AUTH_METHOD_OPTIONS = [
108
+ ("Auto (POST if secret, none if public)", "auto"),
109
+ ("client_secret_post", "client_secret_post"),
110
+ ("client_secret_basic", "client_secret_basic"),
111
+ ("none (public client / PKCE)", "none"),
112
+ ]
107
113
  MCP_STATUS_MESSAGE_MAX = 96
108
114
  MCP_STATUS_NAME_MAX = 34
109
115
  # Compression threshold select: "default" maps to None (the agent's built-in 95%).
@@ -417,6 +423,16 @@ class SettingsPanelMixin(tui_app_base.KolegaAppBase):
417
423
  self._update_mcp_transport_fields(str(event.value))
418
424
  return
419
425
 
426
+ if select_id == "mcp_oauth_select":
427
+ transport = "streamable_http"
428
+ try:
429
+ transport = str(self._settings_query_one("#mcp_transport_select", Select).value)
430
+ except NoMatches:
431
+ pass
432
+ http = transport in {"streamable_http", "sse"}
433
+ self._update_mcp_oauth_fields(http and str(event.value) == "true")
434
+ return
435
+
420
436
  row = _row_for_widget(select_id)
421
437
  if row is not None and select_id == row.provider_id:
422
438
  provider = str(event.value)
@@ -1477,6 +1493,12 @@ class SettingsPanelMixin(tui_app_base.KolegaAppBase):
1477
1493
  set_input("mcp_url_input", "")
1478
1494
  set_input("mcp_headers_input", "")
1479
1495
  set_select("mcp_oauth_select", "false")
1496
+ set_input("mcp_oauth_client_id_input", "")
1497
+ set_input("mcp_oauth_client_secret_input", "")
1498
+ set_input("mcp_oauth_client_secret_env_input", "")
1499
+ set_input("mcp_oauth_redirect_uri_input", "")
1500
+ set_input("mcp_oauth_scope_input", "")
1501
+ set_select("mcp_oauth_auth_method_select", "auto")
1480
1502
  set_input("mcp_command_input", "")
1481
1503
  set_input("mcp_args_input", "")
1482
1504
  set_input("mcp_env_input", "")
@@ -1491,6 +1513,12 @@ class SettingsPanelMixin(tui_app_base.KolegaAppBase):
1491
1513
  set_input("mcp_url_input", server.url or "")
1492
1514
  set_input("mcp_headers_input", json.dumps(server.headers, sort_keys=True) if server.headers else "")
1493
1515
  set_select("mcp_oauth_select", "true" if server.oauth.enabled else "false")
1516
+ set_input("mcp_oauth_client_id_input", server.oauth.client_id or "")
1517
+ set_input("mcp_oauth_client_secret_input", server.oauth.client_secret or "")
1518
+ set_input("mcp_oauth_client_secret_env_input", server.oauth.client_secret_env or "")
1519
+ set_input("mcp_oauth_redirect_uri_input", server.oauth.redirect_uri or "")
1520
+ set_input("mcp_oauth_scope_input", server.oauth.scope or "")
1521
+ set_select("mcp_oauth_auth_method_select", server.oauth.token_endpoint_auth_method or "auto")
1494
1522
  set_input("mcp_command_input", server.command or "")
1495
1523
  set_input("mcp_args_input", " ".join(shlex.quote(arg) for arg in server.args))
1496
1524
  set_input("mcp_env_input", json.dumps(server.env, sort_keys=True) if server.env else "")
@@ -1503,6 +1531,26 @@ class SettingsPanelMixin(tui_app_base.KolegaAppBase):
1503
1531
  self._set_mcp_source_hint("This server is stored in your global MCP config.")
1504
1532
  self._update_mcp_transport_fields(server.transport)
1505
1533
 
1534
+ def _update_mcp_oauth_fields(self, visible: bool) -> None:
1535
+ for widget_id in (
1536
+ "mcp_oauth_client_id_label",
1537
+ "mcp_oauth_client_id_input",
1538
+ "mcp_oauth_client_secret_label",
1539
+ "mcp_oauth_client_secret_input",
1540
+ "mcp_oauth_client_secret_env_label",
1541
+ "mcp_oauth_client_secret_env_input",
1542
+ "mcp_oauth_redirect_uri_label",
1543
+ "mcp_oauth_redirect_uri_input",
1544
+ "mcp_oauth_scope_label",
1545
+ "mcp_oauth_scope_input",
1546
+ "mcp_oauth_auth_method_label",
1547
+ "mcp_oauth_auth_method_select",
1548
+ ):
1549
+ try:
1550
+ self._settings_query_one(f"#{widget_id}").display = visible
1551
+ except NoMatches:
1552
+ pass
1553
+
1506
1554
  def _update_mcp_transport_fields(self, transport: str) -> None:
1507
1555
  http = transport in {"streamable_http", "sse"}
1508
1556
  for widget_id, visible in (
@@ -1525,6 +1573,12 @@ class SettingsPanelMixin(tui_app_base.KolegaAppBase):
1525
1573
  self._settings_query_one(f"#{widget_id}").display = visible
1526
1574
  except NoMatches:
1527
1575
  pass
1576
+ oauth_enabled = False
1577
+ try:
1578
+ oauth_enabled = http and str(self._settings_query_one("#mcp_oauth_select", Select).value) == "true"
1579
+ except NoMatches:
1580
+ pass
1581
+ self._update_mcp_oauth_fields(oauth_enabled)
1528
1582
  try:
1529
1583
  url_input = self._settings_query_one("#mcp_url_input", Input)
1530
1584
  if transport == "streamable_http":
@@ -1621,7 +1675,8 @@ class SettingsPanelMixin(tui_app_base.KolegaAppBase):
1621
1675
  enabled = str(self._settings_query_one("#mcp_enabled_select", Select).value) == "true"
1622
1676
  url = self._settings_query_one("#mcp_url_input", Input).value.strip() or None
1623
1677
  headers_text = self._settings_query_one("#mcp_headers_input", Input).value.strip()
1624
- oauth_enabled = str(self._settings_query_one("#mcp_oauth_select", Select).value) == "true"
1678
+ http = transport in {"streamable_http", "sse"}
1679
+ oauth_enabled = http and str(self._settings_query_one("#mcp_oauth_select", Select).value) == "true"
1625
1680
  command = self._settings_query_one("#mcp_command_input", Input).value.strip() or None
1626
1681
  args_text = self._settings_query_one("#mcp_args_input", Input).value.strip()
1627
1682
  env_text = self._settings_query_one("#mcp_env_input", Input).value.strip()
@@ -1640,6 +1695,77 @@ class SettingsPanelMixin(tui_app_base.KolegaAppBase):
1640
1695
  else selected
1641
1696
  )
1642
1697
 
1698
+ oauth_client_id = None
1699
+ oauth_client_secret = None
1700
+ oauth_client_secret_env = None
1701
+ oauth_redirect_uri = None
1702
+ oauth_scope = None
1703
+ oauth_auth_method: Optional[Literal["client_secret_post", "client_secret_basic", "none"]] = None
1704
+
1705
+ if http:
1706
+ try:
1707
+ oauth_client_id = self._settings_query_one("#mcp_oauth_client_id_input", Input).value.strip() or None
1708
+ except NoMatches:
1709
+ pass
1710
+ try:
1711
+ oauth_client_secret = (
1712
+ self._settings_query_one("#mcp_oauth_client_secret_input", Input).value.strip() or None
1713
+ )
1714
+ except NoMatches:
1715
+ pass
1716
+ try:
1717
+ oauth_client_secret_env = (
1718
+ self._settings_query_one("#mcp_oauth_client_secret_env_input", Input).value.strip() or None
1719
+ )
1720
+ except NoMatches:
1721
+ pass
1722
+ try:
1723
+ oauth_redirect_uri = (
1724
+ self._settings_query_one("#mcp_oauth_redirect_uri_input", Input).value.strip() or None
1725
+ )
1726
+ except NoMatches:
1727
+ pass
1728
+ try:
1729
+ oauth_scope = self._settings_query_one("#mcp_oauth_scope_input", Input).value.strip() or None
1730
+ except NoMatches:
1731
+ pass
1732
+ try:
1733
+ method_val = str(self._settings_query_one("#mcp_oauth_auth_method_select", Select).value)
1734
+ if method_val in {"client_secret_post", "client_secret_basic", "none"}:
1735
+ oauth_auth_method = cast(Literal["client_secret_post", "client_secret_basic", "none"], method_val)
1736
+ except NoMatches:
1737
+ pass
1738
+
1739
+ client_name = "Kolega Code"
1740
+ client_uri = None
1741
+ client_metadata_url = None
1742
+ timeout_seconds = 300.0
1743
+ if selected != MCP_NEW_SERVER_VALUE:
1744
+ try:
1745
+ config = self._load_mcp_config_for_ui()
1746
+ existing = config.servers.get(selected)
1747
+ if existing:
1748
+ client_name = existing.oauth.client_name
1749
+ client_uri = existing.oauth.client_uri
1750
+ client_metadata_url = existing.oauth.client_metadata_url
1751
+ timeout_seconds = existing.oauth.timeout_seconds
1752
+ except Exception:
1753
+ pass
1754
+
1755
+ oauth = MCPOAuthConfig(
1756
+ enabled=oauth_enabled,
1757
+ client_id=oauth_client_id,
1758
+ client_secret=oauth_client_secret,
1759
+ client_secret_env=oauth_client_secret_env,
1760
+ redirect_uri=oauth_redirect_uri,
1761
+ scope=oauth_scope,
1762
+ token_endpoint_auth_method=oauth_auth_method,
1763
+ client_name=client_name,
1764
+ client_uri=client_uri,
1765
+ client_metadata_url=client_metadata_url,
1766
+ timeout_seconds=timeout_seconds,
1767
+ )
1768
+
1643
1769
  return MCPServerConfig(
1644
1770
  id=server_id,
1645
1771
  name=name,
@@ -1647,7 +1773,7 @@ class SettingsPanelMixin(tui_app_base.KolegaAppBase):
1647
1773
  enabled=enabled,
1648
1774
  url=url,
1649
1775
  headers=headers,
1650
- oauth=MCPOAuthConfig(enabled=oauth_enabled),
1776
+ oauth=oauth,
1651
1777
  command=command,
1652
1778
  args=args,
1653
1779
  env=env,
@@ -588,6 +588,26 @@ class SettingsScreen(ModalScreen[None]):
588
588
  allow_blank=False,
589
589
  value="false",
590
590
  )
591
+ yield Label("OAuth Client ID", id="mcp_oauth_client_id_label")
592
+ yield Input(id="mcp_oauth_client_id_input", placeholder="e.g. client_abc123")
593
+ yield Label("OAuth Client Secret", id="mcp_oauth_client_secret_label")
594
+ yield Input(id="mcp_oauth_client_secret_input", placeholder="optional direct secret", password=True)
595
+ yield Label("OAuth Client Secret Env Var", id="mcp_oauth_client_secret_env_label")
596
+ yield Input(id="mcp_oauth_client_secret_env_input", placeholder="e.g. HUBSPOT_MCP_CLIENT_SECRET")
597
+ yield Label("OAuth Redirect URI", id="mcp_oauth_redirect_uri_label")
598
+ yield Input(
599
+ id="mcp_oauth_redirect_uri_input",
600
+ placeholder="e.g. http://127.0.0.1:33418/callback (default: ephemeral port)",
601
+ )
602
+ yield Label("OAuth Scopes", id="mcp_oauth_scope_label")
603
+ yield Input(id="mcp_oauth_scope_input", placeholder="e.g. read write")
604
+ yield Label("OAuth Token Auth Method", id="mcp_oauth_auth_method_label")
605
+ yield Select(
606
+ settings_panel.MCP_OAUTH_AUTH_METHOD_OPTIONS,
607
+ id="mcp_oauth_auth_method_select",
608
+ allow_blank=False,
609
+ value="auto",
610
+ )
591
611
  yield Label("Command", id="mcp_command_label")
592
612
  yield Input(id="mcp_command_input", placeholder="npx")
593
613
  yield Label("Arguments", id="mcp_args_label")
@@ -18,7 +18,10 @@ turns:
18
18
  would surface above the latest text), and the messages persist as a trail
19
19
  of what the agent did during the turn;
20
20
  - text is chunked at the adapter's limit; the first chunk is the edited
21
- message and overflow chunks are sent as continuations on finalize.
21
+ message and overflow chunks are sent as continuations on finalize;
22
+ - a typing action is re-sent every few seconds for the whole turn (chat
23
+ platforms expire it after ~5s), so thinking and long tool runs keep
24
+ showing "typing…" until the reply lands.
22
25
 
23
26
  Chunk content is *incremental*, so the renderer appends and re-renders the
24
27
  accumulated text — it never replaces with the last segment.
@@ -39,6 +42,10 @@ logger = logging.getLogger(__name__)
39
42
 
40
43
  #: Cap on a round message's lines so a chatty turn cannot spam an unbounded edit.
41
44
  MAX_STATUS_LINES = 8
45
+ #: Chat platforms expire a typing action after ~5 seconds (Telegram: "status
46
+ #: is set for 5 seconds or less"); refresh slightly faster so the indicator
47
+ #: never lapses while a turn is in progress.
48
+ TYPING_REFRESH_SECONDS = 4.0
42
49
  #: Rendered status line: (icon, tool description, tool call id).
43
50
  StatusLine = tuple[str, str, str]
44
51
 
@@ -54,6 +61,7 @@ class TurnRenderer:
54
61
  event_queue: asyncio.Queue[AgentEvent],
55
62
  chunk_limit: Optional[int] = None,
56
63
  edit_throttle_seconds: float = 1.0,
64
+ typing_refresh_seconds: float = TYPING_REFRESH_SECONDS,
57
65
  monotonic: Any = time.monotonic,
58
66
  ) -> None:
59
67
  self._adapter = adapter
@@ -61,6 +69,7 @@ class TurnRenderer:
61
69
  self._events = event_queue
62
70
  self._chunk_limit = chunk_limit or adapter.capabilities.text_chunk_limit
63
71
  self._edit_throttle = edit_throttle_seconds
72
+ self._typing_refresh = typing_refresh_seconds
64
73
  self._monotonic = monotonic
65
74
  # Per-segment state, mirroring the TUI's stream fold: a segment is one
66
75
  # contiguous assistant response identified by its chunk uuid (the
@@ -92,10 +101,12 @@ class TurnRenderer:
92
101
  reply stays visible.
93
102
  """
94
103
  pump: Optional[asyncio.Task[None]] = None
104
+ typing: Optional[asyncio.Task[None]] = None
95
105
  if self._events is not None:
96
106
  pump = asyncio.create_task(self._event_pump(), name="gateway-turn-event-pump")
97
107
  try:
98
108
  await self._adapter.set_typing(self._chat_id, True)
109
+ typing = asyncio.create_task(self._typing_keepalive(), name="gateway-turn-typing")
99
110
  async for chunk in chunks:
100
111
  if chunk.get("type") != "response":
101
112
  # Thinking chunks stay off the wire; they are reasoning, not output.
@@ -121,14 +132,31 @@ class TurnRenderer:
121
132
  await self._finalize_segment()
122
133
  return self._total_text
123
134
  finally:
124
- if pump is not None:
125
- pump.cancel()
126
- try:
127
- await pump
128
- except asyncio.CancelledError:
129
- pass
135
+ for task in (pump, typing):
136
+ if task is not None:
137
+ task.cancel()
138
+ try:
139
+ await task
140
+ except asyncio.CancelledError:
141
+ pass
130
142
  await self._adapter.set_typing(self._chat_id, False)
131
143
 
144
+ async def _typing_keepalive(self) -> None:
145
+ """Re-send the typing action so the indicator outlives its ~5s expiry.
146
+
147
+ Covers the silent stretches of a turn — model thinking before the
148
+ first chunk and long-running tool calls, where no message is sent or
149
+ edited. Refresh only (never hides: the ``False`` call is the
150
+ adapter's business); a failing adapter must not end the loop, since
151
+ typing is cosmetic.
152
+ """
153
+ while True:
154
+ await asyncio.sleep(self._typing_refresh)
155
+ try:
156
+ await self._adapter.set_typing(self._chat_id, True)
157
+ except Exception: # noqa: BLE001 — typing indicators are cosmetic
158
+ logger.debug("gateway: typing refresh failed", exc_info=True)
159
+
132
160
  # -- Reply messages (one per response segment) -------------------------
133
161
 
134
162
  async def _finalize_segment(self) -> None:
@@ -12,6 +12,7 @@ from __future__ import annotations
12
12
 
13
13
  import os
14
14
  import plistlib
15
+ import re
15
16
  import shlex
16
17
  import shutil
17
18
  import subprocess
@@ -214,6 +215,41 @@ def run_service_command(argv: list[str]) -> subprocess.CompletedProcess[str] | N
214
215
  return None
215
216
 
216
217
 
218
+ def service_state_summary(
219
+ *,
220
+ systemd_dir: Optional[Path] = None,
221
+ launchd_dir: Optional[Path] = None,
222
+ platform: Optional[str] = None,
223
+ ) -> Optional[str]:
224
+ """One line of service-manager state for an installed gateway, else None.
225
+
226
+ ``gateway status`` uses this to explain a service that is installed but not
227
+ running, which the daemon's own status file cannot show.
228
+ """
229
+ platform = platform if platform is not None else sys.platform
230
+ if not is_service_installed(systemd_dir=systemd_dir, launchd_dir=launchd_dir, platform=platform):
231
+ return None
232
+ if platform == "darwin":
233
+ proc = run_service_command(["launchctl", "print", f"gui/{os.getuid()}/{LAUNCHD_LABEL}"])
234
+ if proc is None or proc.returncode != 0:
235
+ return "launchd agent installed but not loaded"
236
+ output = proc.stdout or ""
237
+ parts: list[str] = []
238
+ state = re.search(r"^\s*state = (.+)$", output, re.MULTILINE)
239
+ if state:
240
+ parts.append(f"state {state.group(1).strip()}")
241
+ runs = re.search(r"^\s*runs = (\d+)$", output, re.MULTILINE)
242
+ if runs:
243
+ parts.append(f"{runs.group(1)} starts")
244
+ last_exit = re.search(r"^\s*last exit code = (\d+)$", output, re.MULTILINE)
245
+ if last_exit:
246
+ parts.append(f"last exit code {last_exit.group(1)}")
247
+ return "launchd agent " + (", ".join(parts) if parts else "loaded")
248
+ proc = run_service_command(["systemctl", "--user", "is-active", SERVICE_NAME])
249
+ state_text = (proc.stdout or "").strip() if proc is not None else ""
250
+ return f"systemd unit {state_text or 'unknown'}"
251
+
252
+
217
253
  def restart_service(
218
254
  *,
219
255
  unit_path: Optional[Path] = None,