kolega-code 0.26.7__tar.gz → 0.26.9__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 (374) hide show
  1. {kolega_code-0.26.7 → kolega_code-0.26.9}/CHANGELOG.md +116 -0
  2. {kolega_code-0.26.7 → kolega_code-0.26.9}/PKG-INFO +13 -1
  3. {kolega_code-0.26.7 → kolega_code-0.26.9}/README.md +11 -0
  4. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/__init__.py +1 -1
  5. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/agent/__init__.py +1 -1
  6. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/agent/baseagent.py +215 -30
  7. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/agent/browseragent.py +2 -0
  8. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/agent/coder.py +2 -0
  9. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/agent/common.py +10 -0
  10. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/agent/compression.py +11 -8
  11. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/agent/context.py +6 -0
  12. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/agent/conversation.py +2 -0
  13. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/agent/custom_agents.py +2 -0
  14. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/agent/eval/kernel.py +3 -2
  15. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/agent/eval/runner.js +11 -4
  16. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/agent/generalagent.py +2 -0
  17. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/agent/investigationagent.py +2 -0
  18. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/agent/planningagent.py +2 -0
  19. kolega_code-0.26.9/kolega_code/agent/prompt_templates/auxiliary/agent_loop/silent_turn_exhausted.user.md +3 -0
  20. kolega_code-0.26.9/kolega_code/agent/prompt_templates/auxiliary/agent_loop/silent_turn_nudge.user.md.j2 +9 -0
  21. kolega_code-0.26.9/kolega_code/agent/prompt_templates/auxiliary/agent_loop/truncated_turn_nudge.user.md.j2 +9 -0
  22. kolega_code-0.26.9/kolega_code/agent/prompt_templates/extensions/cli/mode_switch_notice.md.j2 +23 -0
  23. kolega_code-0.26.9/kolega_code/agent/prompt_templates/system/agents/coder_ask.md.j2 +5 -0
  24. kolega_code-0.26.7/kolega_code/agent/prompt_templates/system/agents/coder_ask.md.j2 → kolega_code-0.26.9/kolega_code/agent/prompt_templates/system/agents/coder_base.md.j2 +75 -11
  25. kolega_code-0.26.9/kolega_code/agent/prompt_templates/system/agents/coder_cli.md.j2 +3 -0
  26. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/agent/prompts.py +39 -1
  27. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/agent/tool_backend/agent_tool.py +2 -0
  28. kolega_code-0.26.9/kolega_code/agent/tool_backend/network_status.py +90 -0
  29. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/agent/tool_backend/search_backends/__init__.py +2 -0
  30. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/agent/tool_backend/search_backends/duckduckgo.py +9 -2
  31. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/agent/tool_backend/search_backends/errors.py +8 -0
  32. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/agent/tool_backend/search_backends/firecrawl.py +3 -0
  33. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/agent/tool_backend/search_backends/searxng.py +6 -0
  34. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/agent/tool_backend/search_backends/tavily.py +6 -1
  35. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/agent/tool_backend/terminal_tool.py +31 -18
  36. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/agent/tool_backend/think_hard_tool.py +14 -10
  37. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/agent/tool_backend/web_fetch/pipeline.py +4 -1
  38. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/agent/tool_backend/web_fetch/retrieval.py +30 -1
  39. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/agent/tool_backend/web_fetch_tool.py +11 -3
  40. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/agent/tool_backend/web_search_tool.py +11 -2
  41. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/agent/tools.py +36 -11
  42. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/cli/app.py +111 -7
  43. kolega_code-0.26.9/kolega_code/cli/ask_output.py +92 -0
  44. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/cli/config.py +136 -81
  45. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/cli/main.py +70 -38
  46. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/cli/messages.py +19 -0
  47. kolega_code-0.26.9/kolega_code/cli/model_connection.py +85 -0
  48. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/cli/provider_registry.py +18 -1
  49. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/cli/session_store.py +13 -2
  50. kolega_code-0.26.9/kolega_code/cli/session_usage.py +289 -0
  51. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/cli/settings.py +30 -6
  52. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/cli/tui/agent_runtime.py +90 -63
  53. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/cli/tui/app_base.py +10 -1
  54. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/cli/tui/loop_runtime.py +9 -16
  55. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/cli/tui/onboarding_screen.py +10 -1
  56. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/cli/tui/session_diff.py +39 -6
  57. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/cli/tui/settings_panel.py +443 -116
  58. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/cli/tui/settings_screen.py +105 -48
  59. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/cli/tui/status_dashboard.py +42 -0
  60. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/cli/tui/styles.tcss +19 -1
  61. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/cli/tui/transcript.py +4 -4
  62. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/cli/tui/widgets.py +5 -1
  63. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/llm/client.py +38 -2
  64. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/llm/instrumented_client.py +13 -31
  65. kolega_code-0.26.9/kolega_code/llm/ledger.py +411 -0
  66. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/llm/models.py +69 -21
  67. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/llm/providers/anthropic.py +6 -4
  68. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/llm/providers/deepseek_responses.py +26 -1
  69. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/llm/providers/google.py +15 -4
  70. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/llm/providers/openai.py +55 -39
  71. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/llm/providers/responses_common.py +41 -9
  72. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/llm/specs/__init__.py +6 -0
  73. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/llm/specs/accessors.py +54 -0
  74. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/llm/specs/catalog/deepseek.py +20 -2
  75. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/llm/specs/catalog/fireworks.py +7 -2
  76. kolega_code-0.26.9/kolega_code/llm/usage.py +357 -0
  77. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/sandbox/terminal.py +4 -3
  78. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/services/base.py +7 -5
  79. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/services/terminal.py +77 -14
  80. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/tools/core.py +24 -1
  81. kolega_code-0.26.9/kolega_code/tools/param_aliases.py +128 -0
  82. {kolega_code-0.26.7 → kolega_code-0.26.9}/pyproject.toml +5 -1
  83. kolega_code-0.26.7/kolega_code/agent/prompt_templates/system/agents/coder_cli.md.j2 +0 -133
  84. kolega_code-0.26.7/kolega_code/cli/model_connection.py +0 -68
  85. {kolega_code-0.26.7 → kolega_code-0.26.9}/.gitignore +0 -0
  86. {kolega_code-0.26.7 → kolega_code-0.26.9}/CONTRIBUTING.md +0 -0
  87. {kolega_code-0.26.7 → kolega_code-0.26.9}/LICENSE +0 -0
  88. {kolega_code-0.26.7 → kolega_code-0.26.9}/MIGRATION.md +0 -0
  89. {kolega_code-0.26.7 → kolega_code-0.26.9}/RELEASING.md +0 -0
  90. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/_bundled_skills/LICENSE +0 -0
  91. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/_bundled_skills/manifest.json +0 -0
  92. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/_bundled_skills/skills/deep-research/SKILL.md +0 -0
  93. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/_bundled_skills/skills/deep-research/references/evidence-and-reporting.md +0 -0
  94. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/_bundled_skills/skills/deep-research/references/gigacode-workflow.md +0 -0
  95. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/_bundled_skills/skills/deep-research/scripts/deep-research.workflow +0 -0
  96. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/_bundled_skills/skills/deep-research/scripts/materialize_report.py +0 -0
  97. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/_bundled_skills/skills/docx/LICENSE +0 -0
  98. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/_bundled_skills/skills/docx/SKILL.md +0 -0
  99. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/_bundled_skills/skills/docx/references/examples.md +0 -0
  100. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/_bundled_skills/skills/docx/references/limitations.md +0 -0
  101. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/_bundled_skills/skills/docx/references/operations.md +0 -0
  102. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/_bundled_skills/skills/docx/references/quality.md +0 -0
  103. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/_bundled_skills/skills/docx/requirements.txt +0 -0
  104. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/_bundled_skills/skills/docx/scripts/docx_tool.py +0 -0
  105. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/_bundled_skills/skills/docx/scripts/smoke_test.py +0 -0
  106. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/_bundled_skills/skills/humanizer/LICENSE +0 -0
  107. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/_bundled_skills/skills/humanizer/SKILL.md +0 -0
  108. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/_bundled_skills/skills/pdf/LICENSE +0 -0
  109. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/_bundled_skills/skills/pdf/SKILL.md +0 -0
  110. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/_bundled_skills/skills/pdf/references/examples.md +0 -0
  111. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/_bundled_skills/skills/pdf/references/limitations.md +0 -0
  112. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/_bundled_skills/skills/pdf/references/ocr.md +0 -0
  113. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/_bundled_skills/skills/pdf/references/operations.md +0 -0
  114. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/_bundled_skills/skills/pdf/references/quality.md +0 -0
  115. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/_bundled_skills/skills/pdf/references/redaction.md +0 -0
  116. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/_bundled_skills/skills/pdf/requirements-ocr-paddle.txt +0 -0
  117. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/_bundled_skills/skills/pdf/requirements-ocr-surya.txt +0 -0
  118. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/_bundled_skills/skills/pdf/requirements.txt +0 -0
  119. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/_bundled_skills/skills/pdf/scripts/pdf_tool.py +0 -0
  120. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/_bundled_skills/skills/pdf/scripts/smoke_test.py +0 -0
  121. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/_bundled_skills/skills/pptx/LICENSE +0 -0
  122. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/_bundled_skills/skills/pptx/SKILL.md +0 -0
  123. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/_bundled_skills/skills/pptx/references/examples.md +0 -0
  124. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/_bundled_skills/skills/pptx/references/limitations.md +0 -0
  125. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/_bundled_skills/skills/pptx/references/operations.md +0 -0
  126. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/_bundled_skills/skills/pptx/requirements.txt +0 -0
  127. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/_bundled_skills/skills/pptx/scripts/pptx_tool.py +0 -0
  128. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/_bundled_skills/skills/pptx/scripts/smoke_test.py +0 -0
  129. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/_bundled_skills/skills/review/SKILL.md +0 -0
  130. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/_bundled_skills/skills/review/references/github-publishing.md +0 -0
  131. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/_bundled_skills/skills/skill-authoring/SKILL.md +0 -0
  132. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/_bundled_skills/skills/skill-authoring/references/review-checklist.md +0 -0
  133. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/_bundled_skills/skills/xlsx/LICENSE +0 -0
  134. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/_bundled_skills/skills/xlsx/SKILL.md +0 -0
  135. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/_bundled_skills/skills/xlsx/references/examples.md +0 -0
  136. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/_bundled_skills/skills/xlsx/references/limitations.md +0 -0
  137. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/_bundled_skills/skills/xlsx/references/operations.md +0 -0
  138. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/_bundled_skills/skills/xlsx/references/quality.md +0 -0
  139. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/_bundled_skills/skills/xlsx/requirements.txt +0 -0
  140. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/_bundled_skills/skills/xlsx/scripts/smoke_test.py +0 -0
  141. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/_bundled_skills/skills/xlsx/scripts/xlsx_tool.py +0 -0
  142. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/agent/edit_protocols.py +0 -0
  143. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/agent/errors.py +0 -0
  144. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/agent/eval/__init__.py +0 -0
  145. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/agent/eval/bridge.py +0 -0
  146. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/agent/eval/bundle-requirements.in +0 -0
  147. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/agent/eval/bundle-requirements.txt +0 -0
  148. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/agent/eval/env.py +0 -0
  149. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/agent/eval/js_kernel.py +0 -0
  150. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/agent/eval/prelude.js +0 -0
  151. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/agent/eval/prelude.py +0 -0
  152. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/agent/eval/protocol.py +0 -0
  153. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/agent/eval/py_kernel.py +0 -0
  154. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/agent/eval/runner.py +0 -0
  155. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/agent/goal.py +0 -0
  156. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/agent/model_routing.py +0 -0
  157. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/agent/orchestration/__init__.py +0 -0
  158. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/agent/orchestration/accounting.py +0 -0
  159. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/agent/orchestration/budget.py +0 -0
  160. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/agent/orchestration/context.py +0 -0
  161. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/agent/orchestration/errors.py +0 -0
  162. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/agent/orchestration/executor.py +0 -0
  163. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/agent/orchestration/guide.py +0 -0
  164. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/agent/orchestration/journal.py +0 -0
  165. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/agent/orchestration/runtime.py +0 -0
  166. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/agent/orchestration/types.py +0 -0
  167. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/agent/prompt_dump.py +0 -0
  168. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/agent/prompt_overrides.py +0 -0
  169. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/agent/prompt_provider.py +0 -0
  170. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/agent/prompt_templates/auxiliary/compression/summary.system.md +0 -0
  171. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/agent/prompt_templates/auxiliary/compression/summary.user.md.j2 +0 -0
  172. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/agent/prompt_templates/auxiliary/terminal/output_summary.system.md +0 -0
  173. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/agent/prompt_templates/auxiliary/terminal/safety.system.md +0 -0
  174. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/agent/prompt_templates/auxiliary/tools/think_hard.system.md +0 -0
  175. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/agent/prompt_templates/extensions/cli/build_questions.md +0 -0
  176. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/agent/prompt_templates/extensions/cli/current_plan_artifact.md.j2 +0 -0
  177. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/agent/prompt_templates/extensions/cli/planning_questions.md +0 -0
  178. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/agent/prompt_templates/extensions/cli/scratchpad.md.j2 +0 -0
  179. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/agent/prompt_templates/extensions/cli/shared_task_list.md +0 -0
  180. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/agent/prompt_templates/extensions/cli/shared_task_list_readonly.md +0 -0
  181. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/agent/prompt_templates/extensions/cli/worktree_control.md.j2 +0 -0
  182. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/agent/prompt_templates/extensions/skills/catalog.md.j2 +0 -0
  183. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/agent/prompt_templates/system/agents/browser.md.j2 +0 -0
  184. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/agent/prompt_templates/system/agents/general.md.j2 +0 -0
  185. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/agent/prompt_templates/system/agents/investigation.md.j2 +0 -0
  186. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/agent/prompt_templates/system/agents/planning.md.j2 +0 -0
  187. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/agent/prompt_templates/system/includes/agents_md_instructions.md +0 -0
  188. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/agent/prompt_templates/system/includes/context_updates.md +0 -0
  189. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/agent/prompt_templates/system/includes/environment_variables/workspace_env_vars.md +0 -0
  190. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/agent/prompt_templates/system/includes/frontend_guidance.md +0 -0
  191. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/agent/prompt_templates/system/includes/starter_templates/expo.md +0 -0
  192. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/agent/prompt_templates/system/includes/starter_templates/html_website.md +0 -0
  193. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/agent/prompt_templates/system/includes/starter_templates/mern_stack.md +0 -0
  194. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/agent/prompt_templates/system/includes/starter_templates/react_vite_shadcdn.md +0 -0
  195. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/agent/prompt_templates/user_tasks/cli/implement_plan.md.j2 +0 -0
  196. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/agent/prompt_templates/user_tasks/cli/init_agents.md.j2 +0 -0
  197. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/agent/tool_backend/base_tool.py +0 -0
  198. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/agent/tool_backend/browser_tool.py +0 -0
  199. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/agent/tool_backend/build_tool.py +0 -0
  200. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/agent/tool_backend/codex_patch.py +0 -0
  201. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/agent/tool_backend/edit_preview.py +0 -0
  202. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/agent/tool_backend/edit_tool.py +0 -0
  203. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/agent/tool_backend/eval_tool.py +0 -0
  204. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/agent/tool_backend/glob_tool.py +0 -0
  205. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/agent/tool_backend/hashline_v2.py +0 -0
  206. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/agent/tool_backend/list_directory_tool.py +0 -0
  207. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/agent/tool_backend/lsp_tool.py +0 -0
  208. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/agent/tool_backend/memory_tool.py +0 -0
  209. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/agent/tool_backend/read_file_tool.py +0 -0
  210. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/agent/tool_backend/read_image_tool.py +0 -0
  211. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/agent/tool_backend/search_backends/base.py +0 -0
  212. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/agent/tool_backend/search_backends/models.py +0 -0
  213. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/agent/tool_backend/search_codebase_tool.py +0 -0
  214. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/agent/tool_backend/snapshot_tool.py +0 -0
  215. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/agent/tool_backend/streaming_tool.py +0 -0
  216. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/agent/tool_backend/web_fetch/__init__.py +0 -0
  217. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/agent/tool_backend/web_fetch/answering.py +0 -0
  218. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/agent/tool_backend/web_fetch/documents.py +0 -0
  219. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/agent/tool_backend/web_fetch/extractors.py +0 -0
  220. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/agent/tool_backend/workflow_tool.py +0 -0
  221. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/agent/utils/commands.py +0 -0
  222. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/agent/volatile_context.py +0 -0
  223. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/auth/__init__.py +0 -0
  224. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/auth/_jwt.py +0 -0
  225. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/auth/chatgpt_oauth.py +0 -0
  226. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/auth/constants.py +0 -0
  227. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/auth/tokens.py +0 -0
  228. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/browser_extension/__init__.py +0 -0
  229. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/browser_extension/framing.py +0 -0
  230. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/browser_extension/installer.py +0 -0
  231. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/browser_extension/manager.py +0 -0
  232. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/browser_extension/multiplex.py +0 -0
  233. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/browser_extension/native_host.py +0 -0
  234. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/browser_extension/protocol.py +0 -0
  235. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/browser_extension/registry.py +0 -0
  236. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/browser_extension/runtime.py +0 -0
  237. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/cli/__init__.py +0 -0
  238. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/cli/browser_backend.py +0 -0
  239. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/cli/clipboard_image.py +0 -0
  240. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/cli/connection.py +0 -0
  241. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/cli/cron.py +0 -0
  242. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/cli/diagnostics.py +0 -0
  243. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/cli/file_index.py +0 -0
  244. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/cli/goal.py +0 -0
  245. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/cli/loop.py +0 -0
  246. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/cli/mentions.py +0 -0
  247. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/cli/model_catalog.py +0 -0
  248. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/cli/plan_artifacts.py +0 -0
  249. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/cli/session_event_store.py +0 -0
  250. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/cli/session_journal.py +0 -0
  251. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/cli/skills.py +0 -0
  252. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/cli/slash_commands.py +0 -0
  253. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/cli/theme.py +0 -0
  254. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/cli/tui/__init__.py +0 -0
  255. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/cli/tui/changes_screen.py +0 -0
  256. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/cli/tui/command_handlers.py +0 -0
  257. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/cli/tui/constants.py +0 -0
  258. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/cli/tui/custom_model.py +0 -0
  259. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/cli/tui/memory_screen.py +0 -0
  260. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/cli/tui/prompt_flows.py +0 -0
  261. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/cli/tui/state.py +0 -0
  262. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/cli/tui/sub_agent_screen.py +0 -0
  263. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/cli/tui/terminal_display.py +0 -0
  264. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/cli/updater.py +0 -0
  265. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/config.py +0 -0
  266. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/events.py +0 -0
  267. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/git_env.py +0 -0
  268. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/hooks/__init__.py +0 -0
  269. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/hooks/backends.py +0 -0
  270. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/hooks/config.py +0 -0
  271. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/hooks/dispatcher.py +0 -0
  272. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/hooks/events.py +0 -0
  273. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/hooks/matcher.py +0 -0
  274. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/hooks/outcome.py +0 -0
  275. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/llm/exceptions.py +0 -0
  276. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/llm/providers/__init__.py +0 -0
  277. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/llm/providers/_token_encoding.py +0 -0
  278. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/llm/providers/base.py +0 -0
  279. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/llm/providers/chatgpt_oauth.py +0 -0
  280. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/llm/providers/models.py +0 -0
  281. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/llm/providers/openai_responses.py +0 -0
  282. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/llm/ratelimit.py +0 -0
  283. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/llm/specs/catalog/__init__.py +0 -0
  284. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/llm/specs/catalog/anthropic.py +0 -0
  285. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/llm/specs/catalog/dashscope.py +0 -0
  286. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/llm/specs/catalog/google.py +0 -0
  287. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/llm/specs/catalog/kimi_coding.py +0 -0
  288. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/llm/specs/catalog/moonshot.py +0 -0
  289. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/llm/specs/catalog/ollama_cloud.py +0 -0
  290. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/llm/specs/catalog/openai.py +0 -0
  291. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/llm/specs/catalog/openai_chatgpt.py +0 -0
  292. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/llm/specs/catalog/openrouter.py +0 -0
  293. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/llm/specs/catalog/together.py +0 -0
  294. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/llm/specs/catalog/xai.py +0 -0
  295. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/llm/specs/catalog/zai.py +0 -0
  296. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/llm/specs/openrouter_catalog.py +0 -0
  297. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/llm/specs/thinking.py +0 -0
  298. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/llm/specs/types.py +0 -0
  299. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/llm/timeouts.py +0 -0
  300. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/llm/tool_execution_ids.py +0 -0
  301. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/local_state.py +0 -0
  302. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/mcp/__init__.py +0 -0
  303. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/mcp/config.py +0 -0
  304. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/mcp/oauth.py +0 -0
  305. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/mcp/service.py +0 -0
  306. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/mcp/state.py +0 -0
  307. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/mcp/tools.py +0 -0
  308. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/mcp/transport.py +0 -0
  309. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/memory/__init__.py +0 -0
  310. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/memory/identity.py +0 -0
  311. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/memory/manager.py +0 -0
  312. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/memory/manifest.py +0 -0
  313. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/memory/markdown.py +0 -0
  314. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/memory/models.py +0 -0
  315. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/memory/protocol.py +0 -0
  316. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/memory/registry.py +0 -0
  317. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/models/__init__.py +0 -0
  318. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/models/sandbox_terminal_state.py +0 -0
  319. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/permissions.py +0 -0
  320. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/runtime.py +0 -0
  321. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/sandbox/README.md +0 -0
  322. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/sandbox/__init__.py +0 -0
  323. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/sandbox/async_filesystem.py +0 -0
  324. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/sandbox/base.py +0 -0
  325. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/sandbox/browser.py +0 -0
  326. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/sandbox/event_loop.py +0 -0
  327. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/sandbox/filesystem.py +0 -0
  328. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/sandbox/local.py +0 -0
  329. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/sandbox/serializer.py +0 -0
  330. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/sandbox/utils.py +0 -0
  331. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/scratchpad.py +0 -0
  332. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/security/__init__.py +0 -0
  333. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/security/secrets.py +0 -0
  334. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/services/browser.py +0 -0
  335. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/services/file_system.py +0 -0
  336. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/services/html.py +0 -0
  337. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/services/lsp/__init__.py +0 -0
  338. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/services/lsp/client.py +0 -0
  339. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/services/lsp/config.py +0 -0
  340. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/services/lsp/detector.py +0 -0
  341. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/services/lsp/diagnostics.py +0 -0
  342. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/services/lsp/edits.py +0 -0
  343. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/services/lsp/manager.py +0 -0
  344. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/services/lsp/registry.py +0 -0
  345. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/services/lsp/registry.yaml +0 -0
  346. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/services/snapshots.py +0 -0
  347. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/services/terminal_buffer.py +0 -0
  348. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/services/workspace_scan.py +0 -0
  349. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/session/__init__.py +0 -0
  350. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/session/control.py +0 -0
  351. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/session/inmemory.py +0 -0
  352. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/session/projection.py +0 -0
  353. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/session/recording.py +0 -0
  354. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/session/runtime.py +0 -0
  355. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/session/store.py +0 -0
  356. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/testing/__init__.py +0 -0
  357. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/testing/store_conformance.py +0 -0
  358. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/tools/__init__.py +0 -0
  359. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/tools/definitions.py +0 -0
  360. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/tools/registry.py +0 -0
  361. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/utils/__init__.py +0 -0
  362. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/utils/images.py +0 -0
  363. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/web/__init__.py +0 -0
  364. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/web/assets/fold.js +0 -0
  365. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/web/assets/player.css +0 -0
  366. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/web/assets/player.html +0 -0
  367. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/web/assets/player.js +0 -0
  368. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/web/bundle.py +0 -0
  369. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/web/hosting.py +0 -0
  370. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/web/redaction.py +0 -0
  371. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/web/server.py +0 -0
  372. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/web/singlefile.py +0 -0
  373. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/web/theme_css.py +0 -0
  374. {kolega_code-0.26.7 → kolega_code-0.26.9}/kolega_code/worktrees.py +0 -0
@@ -6,6 +6,122 @@ This project uses GitHub Releases for detailed generated release notes. This fil
6
6
 
7
7
  ## Unreleased
8
8
 
9
+ ## 0.26.9 - 2026-08-03
10
+
11
+ ### Added
12
+
13
+ - Settings → Model & Account gains a **Model Slots** section for pinning the fast
14
+ and thinking models, each with its own provider. Previously these slots were
15
+ reachable only through CLI flags and environment variables, so in the TUI they
16
+ silently inherited the active model — every `web_fetch` answering call ran on
17
+ the main coding model. Slots still inherit by default, and each row now shows
18
+ which model it currently resolves to.
19
+ - The README now includes a direct invitation to the Kolega Code Discord
20
+ community.
21
+
22
+ ### Changed
23
+
24
+ - Settings gains a **Providers** category, first in the rail, holding every model
25
+ provider's API key and the ChatGPT sign-in, each row labelled with its live
26
+ credential status. **Model & Account** is renamed **Models** and keeps only what
27
+ runs. Keys now stage per provider, so credentials for a provider you are not
28
+ currently using — needed by a fast/thinking slot or an agent-role override — can be
29
+ entered without switching your main model and switching back. **Test Connection**
30
+ moves with them and probes the selected provider rather than the active model, so a
31
+ credential can be checked without running on that provider.
32
+ - **Breaking:** provider and model are now always specified together. `--provider`
33
+ without `--model` (and the per-role/per-slot equivalents such as
34
+ `KOLEGA_CODE_FAST_PROVIDER`) is an error instead of silently selecting that
35
+ provider's default model, and a model named without a provider is rejected rather
36
+ than assumed to be Anthropic's. Scripts passing only one of the pair need updating;
37
+ the error names the missing flag. Saved settings are unaffected — the Settings UI
38
+ always writes both — and a saved model that later leaves the catalog still degrades
39
+ to the provider's default rather than blocking startup.
40
+
41
+ ### Fixed
42
+
43
+ - `deepseek-v4-flash` no longer has its reasoning truncated mid-derivation. The
44
+ 64000-token output cap added in 0.26.8 was measured on the chat API for
45
+ `deepseek-v4-pro` and applied to flash by assumption; flash actually runs to
46
+ at least 112990 output tokens in a single Responses call. Hard tasks that
47
+ reason for a long time before acting were cut off at the cap and produced no
48
+ tool call at all. flash now uses its full published output budget, while pro
49
+ and the fireworks/openrouter DeepSeek routes keep the 64000 cap where their
50
+ measured ceilings apply.
51
+
52
+ ### Removed
53
+
54
+ - The unreachable `DEFAULT_LONG_MODEL`, `DEFAULT_FAST_MODEL`, `DEFAULT_THINKING_MODEL`
55
+ and their provider constants. No model was ever resolved through them — an unset
56
+ slot inherits the active model — but they were documented as defaults, which is
57
+ where "what is my fast model?" became unanswerable.
58
+
59
+ ## 0.26.8 - 2026-08-03
60
+
61
+ ### Added
62
+
63
+ - Completed model messages now carry normalized token usage across supported
64
+ providers. Session usage is persisted across resume, exported with provider
65
+ and model breakdowns, and shown in a dedicated Usage card on the Status tab.
66
+ - `kolega-code ask --json` now emits complete, replay-safe messages instead of
67
+ streaming prose chunks, including normalized usage and an explicit final
68
+ summary.
69
+ - Detached background terminal sessions now keep stdin open, so callers can
70
+ send multiple inputs to long-running processes with `write_stdin`.
71
+
72
+ ### Changed
73
+
74
+ - Build and ask agents now share stronger act-first and independent-verification
75
+ guidance. Silent reasoning-only turns are retried with escalating prompts,
76
+ and visible responses cut off at the output limit are asked to continue.
77
+ - Tool dispatch accepts common parameter aliases for `exec_command`, `eval`,
78
+ and `find_files_by_pattern`, while canonical arguments still take precedence.
79
+ - Turn status now appears immediately while checkpoints are prepared, and
80
+ session-diff baseline/checkpoint work is asynchronous and caches unchanged
81
+ files for faster turns.
82
+ - Switching between Plan and Build with existing history now gives the model a
83
+ hidden toolset-change notice so it does not attempt tools from the old mode.
84
+ - Web connection failures now distinguish unreachable hosts, TLS failures,
85
+ rate limits, and retryable errors, with guidance that reflects whether
86
+ outbound access is available.
87
+
88
+ ### Fixed
89
+
90
+ - Installing on an Intel Mac no longer fails with a `cryptography` source-build
91
+ error (`Failed to build cryptography==50.0.0` / missing OpenSSL). cryptography
92
+ 49+ stopped publishing Intel-mac wheels, so the installer tried to compile it
93
+ with Rust and OpenSSL; Intel Macs now install the last release that ships a
94
+ prebuilt universal2 wheel. Other platforms are unaffected.
95
+ - DeepSeek requests now always carry an explicit output-token cap (64000, on
96
+ every provider that serves DeepSeek models: first-party, Fireworks, Ollama
97
+ Cloud, OpenRouter). DeepSeek's real per-response ceiling is ~64k — far below
98
+ its published 384000 — and a server-enforced cutoff is reported as a clean
99
+ finish, so long reasoning runs were being truncated silently mid-word. An
100
+ explicit client cap is enforced and reported honestly, so truncation now
101
+ surfaces as a real `max_tokens` stop the agent loop can react to.
102
+ - The Responses API stream wrapper now captures the terminal
103
+ `response.incomplete` event, so a response truncated at `max_output_tokens`
104
+ reports stop reason `max_tokens` (and keeps its usage/billing metadata)
105
+ instead of looking like a clean `end_turn` with no usage.
106
+ - A reply cut off at the output-token limit mid-message is no longer delivered
107
+ as-is: the agent asks the model to continue (up to 3 escalating continuation
108
+ prompts, mirroring the silent-turn guard), and only finalizes with the
109
+ partial output if the reply is still truncated after that.
110
+ - The non-streaming chat `generate()` path now maps `finish_reason` (it lives
111
+ on the choice, not the message), so its responses carry a real stop reason
112
+ instead of `None`.
113
+ - Quitting while a question or approval is pending no longer raises a Textual
114
+ teardown traceback.
115
+ - JavaScript eval kernels no longer wait for orphaned cell timers during
116
+ shutdown.
117
+
118
+ ### Removed
119
+
120
+ - The `KOLEGA_CODE_OPENROUTER_MAX_TOKENS` environment variable. OpenRouter
121
+ requests still send no `max_tokens` by default (it acts as a routing filter
122
+ on the gateway), except DeepSeek models, which now always send the honest
123
+ clamped cap.
124
+
9
125
  ## 0.26.7 - 2026-08-03
10
126
 
11
127
  ### Fixed
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: kolega-code
3
- Version: 0.26.7
3
+ Version: 0.26.9
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/
@@ -230,6 +230,7 @@ Classifier: Topic :: Utilities
230
230
  Requires-Python: >=3.11
231
231
  Requires-Dist: anthropic==0.101.0
232
232
  Requires-Dist: beautifulsoup4==4.14.3
233
+ Requires-Dist: cryptography==48.0.1; sys_platform == 'darwin' and platform_machine == 'x86_64'
233
234
  Requires-Dist: ddgs==9.14.4
234
235
  Requires-Dist: fastapi==0.139.2
235
236
  Requires-Dist: filelock==3.20.3
@@ -493,6 +494,7 @@ Full documentation lives at **[kolega-ai.github.io/kolega-code](https://kolega-a
493
494
  - [Contributing](CONTRIBUTING.md)
494
495
  - [Security policy](SECURITY.md)
495
496
  - [Issue tracker](https://github.com/kolega-ai/kolega-code/issues)
497
+ - [Discord community](https://discord.gg/kaS8PKKp4)
496
498
 
497
499
  ## Contributing
498
500
 
@@ -503,3 +505,13 @@ privately per [SECURITY.md](SECURITY.md).
503
505
  ## License
504
506
 
505
507
  Released under the [Apache License 2.0](LICENSE).
508
+
509
+ ## Join the community
510
+
511
+ Building something with Kolega Code, hit a rough edge, or want to shape where
512
+ Gigacode goes next? Come talk to us.
513
+
514
+ [![Join our Discord](https://img.shields.io/badge/Discord-join%20the%20community-5865F2?logo=discord&logoColor=white)](https://discord.gg/kaS8PKKp4)
515
+
516
+ **→ [Join the Kolega Code Discord](https://discord.gg/kaS8PKKp4)** — share workflows,
517
+ get help, and hear about releases first.
@@ -215,6 +215,7 @@ Full documentation lives at **[kolega-ai.github.io/kolega-code](https://kolega-a
215
215
  - [Contributing](CONTRIBUTING.md)
216
216
  - [Security policy](SECURITY.md)
217
217
  - [Issue tracker](https://github.com/kolega-ai/kolega-code/issues)
218
+ - [Discord community](https://discord.gg/kaS8PKKp4)
218
219
 
219
220
  ## Contributing
220
221
 
@@ -225,3 +226,13 @@ privately per [SECURITY.md](SECURITY.md).
225
226
  ## License
226
227
 
227
228
  Released under the [Apache License 2.0](LICENSE).
229
+
230
+ ## Join the community
231
+
232
+ Building something with Kolega Code, hit a rough edge, or want to shape where
233
+ Gigacode goes next? Come talk to us.
234
+
235
+ [![Join our Discord](https://img.shields.io/badge/Discord-join%20the%20community-5865F2?logo=discord&logoColor=white)](https://discord.gg/kaS8PKKp4)
236
+
237
+ **→ [Join the Kolega Code Discord](https://discord.gg/kaS8PKKp4)** — share workflows,
238
+ get help, and hear about releases first.
@@ -151,4 +151,4 @@ __all__ = [
151
151
  "parse_git_status_output",
152
152
  ]
153
153
 
154
- __version__ = "0.26.7"
154
+ __version__ = "0.26.9"
@@ -51,4 +51,4 @@ __all__ = [
51
51
  "ToolExtension",
52
52
  ]
53
53
 
54
- __version__ = "0.26.7"
54
+ __version__ = "0.26.9"
@@ -42,9 +42,15 @@ from kolega_code.llm.exceptions import (
42
42
  map_to_llm_error,
43
43
  )
44
44
  from kolega_code.llm.instrumented_client import get_output_tokens
45
+ from kolega_code.llm.ledger import HISTORY_ORIGIN, LlmCallOrigin, helper_origin, llm_call_origin
45
46
  from kolega_code.llm.models import ImageBlock, Message, MessageHistory, TextBlock, ToolCall, ToolResult
46
47
  from kolega_code.llm.providers.models import TokenCount
47
- from kolega_code.llm.specs import get_model_specs, supports_vision as model_supports_vision
48
+ from kolega_code.llm.specs import (
49
+ deepseek_output_token_cap,
50
+ get_model_specs,
51
+ is_deepseek_model,
52
+ supports_vision as model_supports_vision,
53
+ )
48
54
  from kolega_code.permissions import (
49
55
  PermissionDecision,
50
56
  PermissionMode,
@@ -133,6 +139,25 @@ class BaseAgent(LogMixin):
133
139
  # Cap on how many times a Stop hook may force the agent to keep working in one
134
140
  # turn, so a misbehaving "don't stop until X" hook cannot loop forever.
135
141
  MAX_STOP_HOOK_OVERRIDES = 5
142
+ # Cap on consecutive re-prompts after a "silent turn": the model ended its
143
+ # turn with no tool call and no visible text (empty or reasoning-only).
144
+ # Finalizing such a turn reports nothing — in non-interactive modes that
145
+ # reads as success with empty output — so the loop nudges the model to act
146
+ # instead, and after the cap terminates the turn and surfaces the failure.
147
+ # Runtime half of the coder_base.md.j2 invariant ("Thinking is invisible
148
+ # and changes nothing on its own").
149
+ MAX_SILENT_TURN_NUDGES = 3
150
+ # Cap on consecutive continuation prompts after a truncated turn: the model
151
+ # hit the output-token limit mid-reply (honest "max_tokens" stop, visible
152
+ # text, no tool call). Unlike a silent turn there IS partial content, so
153
+ # exhausting the cap finalizes the turn with what was produced instead of
154
+ # reporting no result.
155
+ MAX_TRUNCATED_TURN_NUDGES = 3
156
+ # A DeepSeek response whose output lands within this many tokens of the wire
157
+ # output cap without an honest "max_tokens" stop was likely truncated
158
+ # server-side: DeepSeek reports its own cutoff as a clean finish (probed
159
+ # 2026-08-03; see DEEPSEEK_WIRE_OUTPUT_CAP in llm/specs/accessors.py).
160
+ DEEPSEEK_OUTPUT_CAP_SLACK = 1024
136
161
  long_content_tool_calls = ["write"]
137
162
  max_tool_result_chars_in_history = 100_000
138
163
  skill_content_pattern = re.compile(r'<skill_content name="[^"]+">')
@@ -163,6 +188,7 @@ class BaseAgent(LogMixin):
163
188
  permission_callback: Optional[Any] = None,
164
189
  usage_recorder: Optional[Any] = None,
165
190
  sub_agent_recorder: Optional[Any] = None,
191
+ usage_ledger: Optional[Any] = None,
166
192
  session_recorder: Optional[Any] = None,
167
193
  hook_dispatcher: Optional[HookDispatcher] = None,
168
194
  context: Optional[AgentContext] = None,
@@ -241,6 +267,7 @@ class BaseAgent(LogMixin):
241
267
  user_email=user_email,
242
268
  usage_recorder=usage_recorder,
243
269
  sub_agent_recorder=sub_agent_recorder,
270
+ usage_ledger=usage_ledger,
244
271
  ),
245
272
  agent_mode=agent_mode,
246
273
  prompt_provider=prompt_provider,
@@ -301,6 +328,7 @@ class BaseAgent(LogMixin):
301
328
  self.hook_dispatcher = context.hook_dispatcher or NO_OP_DISPATCHER
302
329
  self.usage_recorder = context.telemetry.usage_recorder
303
330
  self.sub_agent_recorder = context.telemetry.sub_agent_recorder
331
+ self.usage_ledger = context.telemetry.usage_ledger
304
332
  self.session_recorder = None if sub_agent else session_recorder
305
333
  self.custom_agent_catalog = custom_agent_catalog
306
334
  self.memory_manager = context.services.memory_manager
@@ -416,6 +444,18 @@ class BaseAgent(LogMixin):
416
444
  self.model_context_length = model_specs["context_length"]
417
445
  self.model_completion_tokens = model_specs["max_completion_tokens"]
418
446
  self.model_default_temperature = model_specs.get("default_temperature", 1.0)
447
+ # The clamped cap DeepSeek requests carry on the wire (None for other
448
+ # models). Used to flag probable silent server-side truncation — see the
449
+ # at-ceiling warning in process_message_stream.
450
+ self.deepseek_wire_output_cap = (
451
+ deepseek_output_token_cap(
452
+ self.primary_model_config.provider,
453
+ self.primary_model_config.model,
454
+ self.model_completion_tokens,
455
+ )
456
+ if is_deepseek_model(self.primary_model_config.model)
457
+ else None
458
+ )
419
459
  # Whether this agent's primary model can accept image input. Read by the
420
460
  # ToolCollection read_image tool gate (so non-vision models never see the
421
461
  # tool) and used by _unsupported_attachment_message to reject image
@@ -492,6 +532,15 @@ class BaseAgent(LogMixin):
492
532
  """
493
533
  self.conversation.append_assistant(message)
494
534
 
535
+ async def _record_context_user_message(self, text: str) -> None:
536
+ """Journal and append a runtime-injected user message (not typed by the user)."""
537
+ if self.session_recorder is not None:
538
+ await asyncio.to_thread(
539
+ self.session_recorder.record_context_message,
540
+ Message(role="user", content=[TextBlock(text=text)]),
541
+ )
542
+ self.append_user_message([TextBlock(text=text)])
543
+
495
544
  def extend_history(self, messages: List[Message]) -> None:
496
545
  """
497
546
  Safely extend history with multiple messages, validating the sequence.
@@ -1051,11 +1100,14 @@ class BaseAgent(LogMixin):
1051
1100
  try:
1052
1101
  registry = self.tool_collection.registry()
1053
1102
  if tool_name not in registry:
1054
- error_message = f"Tool '{tool_name}' is not available in this mode."
1055
- await self.log_error(error_message, sender=self.agent_name)
1103
+ short_message = f"Tool '{tool_name}' is not available in this mode."
1104
+ # The model gets the available-tool list so it can self-correct;
1105
+ # the transcript row keeps the short form.
1106
+ error_message = f"{short_message} Available tools: {', '.join(sorted(registry.names()))}."
1107
+ await self.log_error(short_message, sender=self.agent_name)
1056
1108
  await self.send_chat_message(
1057
1109
  message_type="tool_error",
1058
- content=error_message,
1110
+ content=short_message,
1059
1111
  is_streaming=False,
1060
1112
  tool_description=tool_name,
1061
1113
  tool_call_id=tool_execution_id,
@@ -1379,6 +1431,27 @@ class BaseAgent(LogMixin):
1379
1431
  async def _log_hook_message(self, message: str) -> None:
1380
1432
  await self.log_warning(message, sender=self.agent_name)
1381
1433
 
1434
+ def _main_loop_origin(self) -> LlmCallOrigin:
1435
+ """Attribution for this agent's main-loop LLM calls.
1436
+
1437
+ HISTORY marks exactly the responses the session recorder journals as
1438
+ ``assistant.message`` (the same ``session_recorder is not None``
1439
+ condition guards ``record_assistant``), so the persistence sink skips
1440
+ them and no response is ever journaled twice.
1441
+ """
1442
+ if self.session_recorder is not None:
1443
+ return HISTORY_ORIGIN
1444
+ if self.sub_agent:
1445
+ context = getattr(self, "sub_agent_context", None) or {}
1446
+ return LlmCallOrigin(
1447
+ kind="sub_agent",
1448
+ agent_name=self.agent_name,
1449
+ agent_id=context.get("agent_id"),
1450
+ parent_tool_call_id=context.get("parent_tool_call_id") or getattr(self, "parent_tool_call_id", None),
1451
+ depth=context.get("depth"),
1452
+ )
1453
+ return LlmCallOrigin(kind="primary", agent_name=self.agent_name)
1454
+
1382
1455
  async def _run_hook_prompt(self, prompt_text: str, model_hint: Optional[str]) -> str:
1383
1456
  """Run a `prompt` hook: a single completion on a chosen model slot.
1384
1457
 
@@ -1404,14 +1477,16 @@ class BaseAgent(LogMixin):
1404
1477
  requests_per_minute=model_config.rate_limits.requests_per_minute,
1405
1478
  tokens_per_minute=model_config.rate_limits.tokens_per_minute,
1406
1479
  token_manager=self.config.get_chatgpt_token_manager(),
1480
+ usage_ledger=self.usage_ledger,
1407
1481
  )
1408
- response = await client.generate(
1409
- model=model_config.model,
1410
- max_completion_tokens=512,
1411
- system=Message(role="system", content=[TextBlock(text=HOOK_DECISION_SYSTEM_PROMPT)]),
1412
- messages=MessageHistory([Message(role="user", content=[TextBlock(text=prompt_text)])]),
1413
- temperature=0.0,
1414
- )
1482
+ with llm_call_origin(helper_origin("hook_prompt")):
1483
+ response = await client.generate(
1484
+ model=model_config.model,
1485
+ max_completion_tokens=512,
1486
+ system=Message(role="system", content=[TextBlock(text=HOOK_DECISION_SYSTEM_PROMPT)]),
1487
+ messages=MessageHistory([Message(role="user", content=[TextBlock(text=prompt_text)])]),
1488
+ temperature=0.0,
1489
+ )
1415
1490
  return response.get_text_content() or ""
1416
1491
 
1417
1492
  async def _run_hook_agent(self, task: str) -> str:
@@ -1712,6 +1787,17 @@ class BaseAgent(LogMixin):
1712
1787
  """Return the agent's final report: the text of the last message in history."""
1713
1788
  return self.history[-1].get_text_content()
1714
1789
 
1790
+ @staticmethod
1791
+ def _is_silent_turn(message: Message) -> bool:
1792
+ """True when an assistant message has no tool calls and no visible text.
1793
+
1794
+ ThinkingBlock carries ``.thinking`` rather than ``.text``, so a
1795
+ reasoning-only message reads as empty here. Evaluate the streamed
1796
+ message, not history: Conversation.append_assistant replaces empty
1797
+ content with a placeholder TextBlock.
1798
+ """
1799
+ return not message.tool_calls and not message.get_text_content().strip()
1800
+
1715
1801
  async def _deliver_queued_user_inputs(self) -> None:
1716
1802
  """Append user inputs drained from the host while the current turn is running."""
1717
1803
  if self.queued_input_provider is None:
@@ -1911,6 +1997,8 @@ class BaseAgent(LogMixin):
1911
1997
 
1912
1998
  stop_reason = None
1913
1999
  stop_overrides = 0
2000
+ silent_turn_nudges = 0
2001
+ truncated_turn_nudges = 0
1914
2002
  iterations = 0
1915
2003
  while stop_reason not in ["end_turn", "max_tokens", "stop_sequence"]:
1916
2004
  iterations += 1
@@ -1994,18 +2082,19 @@ class BaseAgent(LogMixin):
1994
2082
  # provider is ``async def``, so the call is always a coroutine that we
1995
2083
  # await into the context manager. Cast to the coroutine form for the type
1996
2084
  # checker rather than awaiting the union directly.
1997
- stream_cm = await cast(
1998
- Coroutine[Any, Any, AbstractAsyncContextManager[Any]],
1999
- self.llm.stream(
2000
- system=self.system_prompt,
2001
- max_completion_tokens=self.model_completion_tokens,
2002
- temperature=self.model_default_temperature,
2003
- messages=fixed_history,
2004
- model=self.primary_model_config.model,
2005
- tools=self.tool_collection.get_tool_list(),
2006
- thinking=self.primary_model_config.thinking_effort,
2007
- ),
2008
- )
2085
+ with llm_call_origin(self._main_loop_origin()):
2086
+ stream_cm = await cast(
2087
+ Coroutine[Any, Any, AbstractAsyncContextManager[Any]],
2088
+ self.llm.stream(
2089
+ system=self.system_prompt,
2090
+ max_completion_tokens=self.model_completion_tokens,
2091
+ temperature=self.model_default_temperature,
2092
+ messages=fixed_history,
2093
+ model=self.primary_model_config.model,
2094
+ tools=self.tool_collection.get_tool_list(),
2095
+ thinking=self.primary_model_config.thinking_effort,
2096
+ ),
2097
+ )
2009
2098
  async with stream_cm as stream:
2010
2099
  async for event in stream:
2011
2100
  if event.type == "text":
@@ -2049,10 +2138,11 @@ class BaseAgent(LogMixin):
2049
2138
  assistant_message = await stream.get_final_message()
2050
2139
  self._normalize_freeform_tool_calls(assistant_message)
2051
2140
  assistant_message.usage_metadata["edit_protocol"] = self.edit_protocol.value
2052
- self.total_tokens_used += get_output_tokens(
2141
+ response_output_tokens = get_output_tokens(
2053
2142
  assistant_message.usage_metadata,
2054
2143
  self.primary_model_config.provider.value,
2055
2144
  )
2145
+ self.total_tokens_used += response_output_tokens
2056
2146
  if self._accounting_reservation is not None:
2057
2147
  self._accounting_reservation.report_total(self.total_tokens_used)
2058
2148
  stop_reason = assistant_message.stop_reason
@@ -2063,6 +2153,23 @@ class BaseAgent(LogMixin):
2063
2153
  elapsed_s=round(time.monotonic() - _req_start, 2),
2064
2154
  stop_reason=stop_reason,
2065
2155
  )
2156
+ # DeepSeek reports a SERVER-side output cutoff as a clean finish;
2157
+ # the clamped wire cap should always fire first as an honest
2158
+ # "max_tokens" stop. A response landing at/near the cap without
2159
+ # one was likely truncated silently — surface it in the
2160
+ # trajectory (log_message event) since the stop reason cannot be
2161
+ # recovered.
2162
+ if (
2163
+ self.deepseek_wire_output_cap is not None
2164
+ and stop_reason != "max_tokens"
2165
+ and response_output_tokens >= self.deepseek_wire_output_cap - self.DEEPSEEK_OUTPUT_CAP_SLACK
2166
+ ):
2167
+ await self.log_warning(
2168
+ f"DeepSeek response used {response_output_tokens} output tokens — at or near "
2169
+ f"the {self.deepseek_wire_output_cap}-token output cap — but reported "
2170
+ f"stop_reason={stop_reason!r}; the output was likely truncated server-side.",
2171
+ sender=self.agent_name,
2172
+ )
2066
2173
 
2067
2174
  if self.session_recorder is not None:
2068
2175
  await asyncio.to_thread(self.session_recorder.record_assistant, assistant_message)
@@ -2070,6 +2177,15 @@ class BaseAgent(LogMixin):
2070
2177
  # A clean stream resets the transient-failure budget, so the cap measures
2071
2178
  # only consecutive failures, not lifetime failures across the turn.
2072
2179
  self._consecutive_llm_retries = 0
2180
+ # Likewise, a response with a tool call or visible text resets the
2181
+ # silent-turn budget: the cap measures only consecutive silence.
2182
+ if not self._is_silent_turn(assistant_message):
2183
+ silent_turn_nudges = 0
2184
+ # And any response that was not cut off at the output limit
2185
+ # resets the truncation budget: the cap measures only
2186
+ # consecutive truncations.
2187
+ if stop_reason != "max_tokens":
2188
+ truncated_turn_nudges = 0
2073
2189
 
2074
2190
  if thinking_started or current_thinking:
2075
2191
  yield {"type": "thinking", "content": current_thinking, "complete": True, "uuid": thinking_uuid}
@@ -2123,18 +2239,87 @@ class BaseAgent(LogMixin):
2123
2239
  # host UI so the next model request sees them.
2124
2240
  await self._deliver_queued_user_inputs()
2125
2241
 
2242
+ # Silent-turn guard: the model ended this iteration with no tool
2243
+ # call and no visible text (reasoning-only or empty). Finalizing
2244
+ # would report nothing, so re-prompt with an escalating reminder;
2245
+ # after the cap, terminate the turn and surface the failure. Runs
2246
+ # before the Stop hook: a nudged iteration is not a turn end, and
2247
+ # clearing stop_reason makes the stop-hook block skip itself.
2248
+ if stop_reason in ["end_turn", "max_tokens", "stop_sequence"] and self._is_silent_turn(
2249
+ assistant_message
2250
+ ):
2251
+ from .prompts import SILENT_TURN_EXHAUSTED_NOTICE, build_silent_turn_nudge
2252
+
2253
+ if silent_turn_nudges < self.MAX_SILENT_TURN_NUDGES:
2254
+ silent_turn_nudges += 1
2255
+ await self.emitter.llm_status(
2256
+ "info",
2257
+ "Model returned no output — asking it to act "
2258
+ f"({silent_turn_nudges}/{self.MAX_SILENT_TURN_NUDGES})…",
2259
+ )
2260
+ await self._record_context_user_message(build_silent_turn_nudge(silent_turn_nudges))
2261
+ stop_reason = None
2262
+ else:
2263
+ await self.log_warning(
2264
+ f"Model ended {self.MAX_SILENT_TURN_NUDGES + 1} consecutive responses with "
2265
+ "no tool call and no visible output; terminating the turn.",
2266
+ sender=self.agent_name,
2267
+ )
2268
+ await self.emitter.llm_status(
2269
+ "warning",
2270
+ "Model returned no output after repeated reminders — ending the turn with no result.",
2271
+ )
2272
+ await self._record_context_user_message(SILENT_TURN_EXHAUSTED_NOTICE)
2273
+ yield {
2274
+ "type": "response",
2275
+ "content": (
2276
+ "[no output] The model ended its turn with no tool call and no visible "
2277
+ f"message {self.MAX_SILENT_TURN_NUDGES + 1} times in a row despite "
2278
+ "reminders. The turn was terminated without a result."
2279
+ ),
2280
+ "complete": True,
2281
+ "uuid": str(uuid.uuid4()),
2282
+ }
2283
+ break
2284
+
2285
+ # Truncated-turn guard: an honest "max_tokens" stop with visible
2286
+ # text and no tool call means the reply was cut off mid-message
2287
+ # (the silent-turn guard above owns the no-visible-output case
2288
+ # and cleared stop_reason if it fired). Finalizing would deliver
2289
+ # a partial answer, so ask the model to continue; after the cap,
2290
+ # finalize with the partial output — unlike a silent turn there
2291
+ # IS content worth delivering.
2292
+ if stop_reason == "max_tokens" and not assistant_message.tool_calls:
2293
+ from .prompts import build_truncated_turn_nudge
2294
+
2295
+ if truncated_turn_nudges < self.MAX_TRUNCATED_TURN_NUDGES:
2296
+ truncated_turn_nudges += 1
2297
+ await self.emitter.llm_status(
2298
+ "info",
2299
+ "Response hit the output limit — asking the model to continue "
2300
+ f"({truncated_turn_nudges}/{self.MAX_TRUNCATED_TURN_NUDGES})…",
2301
+ )
2302
+ await self._record_context_user_message(build_truncated_turn_nudge(truncated_turn_nudges))
2303
+ stop_reason = None
2304
+ else:
2305
+ await self.log_warning(
2306
+ f"Model hit the output-token limit {self.MAX_TRUNCATED_TURN_NUDGES + 1} times "
2307
+ "in a row; finalizing the turn with the partial output.",
2308
+ sender=self.agent_name,
2309
+ )
2310
+ await self.emitter.llm_status(
2311
+ "warning",
2312
+ "Response still truncated after repeated continuation prompts — "
2313
+ "delivering the partial output.",
2314
+ )
2315
+
2126
2316
  # Stop hooks (main agent only). On a natural turn end, a hook may
2127
2317
  # keep the agent working by blocking the stop and returning a reason.
2128
2318
  if stop_reason in ["end_turn", "max_tokens", "stop_sequence"] and not self.sub_agent:
2129
2319
  keep_working = await self._fire_stop_hook(stop_reason)
2130
2320
  if keep_working is not None and stop_overrides < self.MAX_STOP_HOOK_OVERRIDES:
2131
2321
  stop_overrides += 1
2132
- if self.session_recorder is not None:
2133
- await asyncio.to_thread(
2134
- self.session_recorder.record_context_message,
2135
- Message(role="user", content=[TextBlock(text=keep_working)]),
2136
- )
2137
- self.append_user_message([TextBlock(text=keep_working)])
2322
+ await self._record_context_user_message(keep_working)
2138
2323
  stop_reason = None
2139
2324
 
2140
2325
  except Exception as ex:
@@ -74,6 +74,7 @@ class BrowserAgent(BaseAgent):
74
74
  permission_mode: Optional[Any] = None,
75
75
  permission_callback: Optional[Any] = None,
76
76
  usage_recorder: Optional[Any] = None,
77
+ usage_ledger: Optional[Any] = None,
77
78
  sub_agent_recorder: Optional[Any] = None,
78
79
  hook_dispatcher: Optional[Any] = None,
79
80
  max_iterations: Optional[int] = None,
@@ -130,6 +131,7 @@ class BrowserAgent(BaseAgent):
130
131
  permission_mode=permission_mode,
131
132
  permission_callback=permission_callback,
132
133
  usage_recorder=usage_recorder,
134
+ usage_ledger=usage_ledger,
133
135
  sub_agent_recorder=sub_agent_recorder,
134
136
  hook_dispatcher=hook_dispatcher,
135
137
  max_iterations=max_iterations,
@@ -46,6 +46,7 @@ class CoderAgent(BaseAgent, LogMixin):
46
46
  permission_mode: Optional[Any] = None,
47
47
  permission_callback: Optional[Any] = None,
48
48
  usage_recorder: Optional[Any] = None,
49
+ usage_ledger: Optional[Any] = None,
49
50
  sub_agent_recorder: Optional[Any] = None,
50
51
  session_recorder: Optional[Any] = None,
51
52
  hook_dispatcher: Optional[Any] = None,
@@ -111,6 +112,7 @@ class CoderAgent(BaseAgent, LogMixin):
111
112
  permission_mode=permission_mode,
112
113
  permission_callback=permission_callback,
113
114
  usage_recorder=usage_recorder,
115
+ usage_ledger=usage_ledger,
114
116
  sub_agent_recorder=sub_agent_recorder,
115
117
  session_recorder=session_recorder,
116
118
  hook_dispatcher=hook_dispatcher,
@@ -49,3 +49,13 @@ class LogMixin:
49
49
  """
50
50
  log_event = AgentEvent(event_type="log_message", sender=sender, content={"text": message, "level": "warning"})
51
51
  await self.connection_manager.broadcast_event(log_event, self.workspace_id, self.thread_id)
52
+
53
+ async def log_debug(self, message: str, sender: str = "agent") -> None:
54
+ """
55
+ Log a debug-level message to the logs panel.
56
+
57
+ Args:
58
+ message: The debug message to log
59
+ """
60
+ log_event = AgentEvent(event_type="log_message", sender=sender, content={"text": message, "level": "debug"})
61
+ await self.connection_manager.broadcast_event(log_event, self.workspace_id, self.thread_id)
@@ -5,6 +5,7 @@ from dataclasses import dataclass
5
5
  from typing import Awaitable, Callable, Optional
6
6
 
7
7
  from .conversation import Conversation
8
+ from kolega_code.llm.ledger import helper_origin, llm_call_origin
8
9
  from kolega_code.llm.models import Message, MessageHistory, TextBlock
9
10
  from .prompts import (
10
11
  build_compression_summary_user_prompt,
@@ -109,14 +110,16 @@ class HistoryCompressor:
109
110
  # Stream and drain rather than calling generate(): the Anthropic SDK
110
111
  # rejects non-streaming requests whose max_tokens is large enough to risk
111
112
  # a >10-minute response, which the model's full completion budget triggers.
112
- async with await llm.stream(
113
- messages=messages,
114
- system=system_message,
115
- temperature=temperature,
116
- model=model,
117
- max_completion_tokens=self.SUMMARY_MAX_TOKENS,
118
- thinking=thinking,
119
- ) as stream:
113
+ with llm_call_origin(helper_origin("compression")):
114
+ stream_cm = await llm.stream(
115
+ messages=messages,
116
+ system=system_message,
117
+ temperature=temperature,
118
+ model=model,
119
+ max_completion_tokens=self.SUMMARY_MAX_TOKENS,
120
+ thinking=thinking,
121
+ )
122
+ async with stream_cm as stream:
120
123
  async for _event in stream:
121
124
  pass
122
125
  response = await stream.get_final_message()