kolega-code 0.26.1__tar.gz → 0.26.3__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (359) hide show
  1. {kolega_code-0.26.1 → kolega_code-0.26.3}/CHANGELOG.md +41 -0
  2. {kolega_code-0.26.1 → kolega_code-0.26.3}/PKG-INFO +1 -1
  3. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/__init__.py +1 -1
  4. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/agent/__init__.py +1 -1
  5. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/agent/baseagent.py +13 -6
  6. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/agent/browseragent.py +19 -2
  7. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/agent/coder.py +2 -0
  8. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/agent/orchestration/__init__.py +2 -2
  9. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/agent/orchestration/guide.py +20 -0
  10. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/agent/orchestration/runtime.py +7 -10
  11. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/agent/planningagent.py +2 -0
  12. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/agent/tool_backend/search_codebase_tool.py +121 -30
  13. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/agent/tools.py +29 -5
  14. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/cli/main.py +19 -0
  15. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/cli/tui/command_handlers.py +3 -12
  16. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/memory/manager.py +49 -5
  17. kolega_code-0.26.3/kolega_code/tools/core.py +71 -0
  18. {kolega_code-0.26.1 → kolega_code-0.26.3}/pyproject.toml +8 -2
  19. kolega_code-0.26.1/kolega_code/tools/core.py +0 -33
  20. {kolega_code-0.26.1 → kolega_code-0.26.3}/.gitignore +0 -0
  21. {kolega_code-0.26.1 → kolega_code-0.26.3}/CONTRIBUTING.md +0 -0
  22. {kolega_code-0.26.1 → kolega_code-0.26.3}/LICENSE +0 -0
  23. {kolega_code-0.26.1 → kolega_code-0.26.3}/MIGRATION.md +0 -0
  24. {kolega_code-0.26.1 → kolega_code-0.26.3}/README.md +0 -0
  25. {kolega_code-0.26.1 → kolega_code-0.26.3}/RELEASING.md +0 -0
  26. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/_bundled_skills/LICENSE +0 -0
  27. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/_bundled_skills/manifest.json +0 -0
  28. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/_bundled_skills/skills/deep-research/SKILL.md +0 -0
  29. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/_bundled_skills/skills/deep-research/references/evidence-and-reporting.md +0 -0
  30. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/_bundled_skills/skills/deep-research/references/gigacode-workflow.md +0 -0
  31. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/_bundled_skills/skills/deep-research/scripts/deep-research.workflow +0 -0
  32. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/_bundled_skills/skills/deep-research/scripts/materialize_report.py +0 -0
  33. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/_bundled_skills/skills/docx/LICENSE +0 -0
  34. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/_bundled_skills/skills/docx/SKILL.md +0 -0
  35. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/_bundled_skills/skills/docx/references/examples.md +0 -0
  36. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/_bundled_skills/skills/docx/references/limitations.md +0 -0
  37. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/_bundled_skills/skills/docx/references/operations.md +0 -0
  38. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/_bundled_skills/skills/docx/references/quality.md +0 -0
  39. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/_bundled_skills/skills/docx/requirements.txt +0 -0
  40. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/_bundled_skills/skills/docx/scripts/docx_tool.py +0 -0
  41. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/_bundled_skills/skills/docx/scripts/smoke_test.py +0 -0
  42. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/_bundled_skills/skills/humanizer/LICENSE +0 -0
  43. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/_bundled_skills/skills/humanizer/SKILL.md +0 -0
  44. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/_bundled_skills/skills/pdf/LICENSE +0 -0
  45. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/_bundled_skills/skills/pdf/SKILL.md +0 -0
  46. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/_bundled_skills/skills/pdf/references/examples.md +0 -0
  47. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/_bundled_skills/skills/pdf/references/limitations.md +0 -0
  48. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/_bundled_skills/skills/pdf/references/ocr.md +0 -0
  49. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/_bundled_skills/skills/pdf/references/operations.md +0 -0
  50. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/_bundled_skills/skills/pdf/references/quality.md +0 -0
  51. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/_bundled_skills/skills/pdf/references/redaction.md +0 -0
  52. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/_bundled_skills/skills/pdf/requirements-ocr-paddle.txt +0 -0
  53. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/_bundled_skills/skills/pdf/requirements-ocr-surya.txt +0 -0
  54. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/_bundled_skills/skills/pdf/requirements.txt +0 -0
  55. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/_bundled_skills/skills/pdf/scripts/pdf_tool.py +0 -0
  56. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/_bundled_skills/skills/pdf/scripts/smoke_test.py +0 -0
  57. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/_bundled_skills/skills/pptx/LICENSE +0 -0
  58. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/_bundled_skills/skills/pptx/SKILL.md +0 -0
  59. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/_bundled_skills/skills/pptx/references/examples.md +0 -0
  60. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/_bundled_skills/skills/pptx/references/limitations.md +0 -0
  61. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/_bundled_skills/skills/pptx/references/operations.md +0 -0
  62. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/_bundled_skills/skills/pptx/requirements.txt +0 -0
  63. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/_bundled_skills/skills/pptx/scripts/pptx_tool.py +0 -0
  64. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/_bundled_skills/skills/pptx/scripts/smoke_test.py +0 -0
  65. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/_bundled_skills/skills/review/SKILL.md +0 -0
  66. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/_bundled_skills/skills/review/references/github-publishing.md +0 -0
  67. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/_bundled_skills/skills/skill-authoring/SKILL.md +0 -0
  68. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/_bundled_skills/skills/skill-authoring/references/review-checklist.md +0 -0
  69. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/_bundled_skills/skills/xlsx/LICENSE +0 -0
  70. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/_bundled_skills/skills/xlsx/SKILL.md +0 -0
  71. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/_bundled_skills/skills/xlsx/references/examples.md +0 -0
  72. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/_bundled_skills/skills/xlsx/references/limitations.md +0 -0
  73. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/_bundled_skills/skills/xlsx/references/operations.md +0 -0
  74. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/_bundled_skills/skills/xlsx/references/quality.md +0 -0
  75. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/_bundled_skills/skills/xlsx/requirements.txt +0 -0
  76. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/_bundled_skills/skills/xlsx/scripts/smoke_test.py +0 -0
  77. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/_bundled_skills/skills/xlsx/scripts/xlsx_tool.py +0 -0
  78. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/agent/common.py +0 -0
  79. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/agent/compression.py +0 -0
  80. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/agent/context.py +0 -0
  81. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/agent/conversation.py +0 -0
  82. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/agent/custom_agents.py +0 -0
  83. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/agent/edit_protocols.py +0 -0
  84. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/agent/errors.py +0 -0
  85. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/agent/eval/__init__.py +0 -0
  86. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/agent/eval/bridge.py +0 -0
  87. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/agent/eval/bundle-requirements.in +0 -0
  88. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/agent/eval/bundle-requirements.txt +0 -0
  89. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/agent/eval/env.py +0 -0
  90. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/agent/eval/js_kernel.py +0 -0
  91. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/agent/eval/kernel.py +0 -0
  92. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/agent/eval/prelude.js +0 -0
  93. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/agent/eval/prelude.py +0 -0
  94. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/agent/eval/protocol.py +0 -0
  95. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/agent/eval/py_kernel.py +0 -0
  96. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/agent/eval/runner.js +0 -0
  97. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/agent/eval/runner.py +0 -0
  98. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/agent/generalagent.py +0 -0
  99. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/agent/goal.py +0 -0
  100. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/agent/investigationagent.py +0 -0
  101. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/agent/model_routing.py +0 -0
  102. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/agent/orchestration/accounting.py +0 -0
  103. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/agent/orchestration/budget.py +0 -0
  104. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/agent/orchestration/context.py +0 -0
  105. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/agent/orchestration/errors.py +0 -0
  106. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/agent/orchestration/executor.py +0 -0
  107. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/agent/orchestration/journal.py +0 -0
  108. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/agent/orchestration/types.py +0 -0
  109. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/agent/prompt_dump.py +0 -0
  110. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/agent/prompt_overrides.py +0 -0
  111. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/agent/prompt_provider.py +0 -0
  112. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/agent/prompt_templates/auxiliary/compression/summary.system.md +0 -0
  113. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/agent/prompt_templates/auxiliary/compression/summary.user.md.j2 +0 -0
  114. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/agent/prompt_templates/auxiliary/terminal/output_summary.system.md +0 -0
  115. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/agent/prompt_templates/auxiliary/terminal/safety.system.md +0 -0
  116. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/agent/prompt_templates/auxiliary/tools/think_hard.system.md +0 -0
  117. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/agent/prompt_templates/extensions/cli/build_questions.md +0 -0
  118. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/agent/prompt_templates/extensions/cli/current_plan_artifact.md.j2 +0 -0
  119. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/agent/prompt_templates/extensions/cli/planning_questions.md +0 -0
  120. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/agent/prompt_templates/extensions/cli/scratchpad.md.j2 +0 -0
  121. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/agent/prompt_templates/extensions/cli/shared_task_list.md +0 -0
  122. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/agent/prompt_templates/extensions/cli/shared_task_list_readonly.md +0 -0
  123. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/agent/prompt_templates/extensions/cli/worktree_control.md.j2 +0 -0
  124. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/agent/prompt_templates/extensions/skills/catalog.md.j2 +0 -0
  125. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/agent/prompt_templates/system/agents/browser.md.j2 +0 -0
  126. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/agent/prompt_templates/system/agents/coder_cli.md.j2 +0 -0
  127. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/agent/prompt_templates/system/agents/general.md.j2 +0 -0
  128. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/agent/prompt_templates/system/agents/investigation.md.j2 +0 -0
  129. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/agent/prompt_templates/system/agents/planning.md.j2 +0 -0
  130. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/agent/prompt_templates/system/includes/agents_md_instructions.md +0 -0
  131. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/agent/prompt_templates/system/includes/context_updates.md +0 -0
  132. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/agent/prompt_templates/system/includes/environment_variables/workspace_env_vars.md +0 -0
  133. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/agent/prompt_templates/system/includes/frontend_guidance.md +0 -0
  134. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/agent/prompt_templates/system/includes/starter_templates/expo.md +0 -0
  135. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/agent/prompt_templates/system/includes/starter_templates/html_website.md +0 -0
  136. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/agent/prompt_templates/system/includes/starter_templates/mern_stack.md +0 -0
  137. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/agent/prompt_templates/system/includes/starter_templates/react_vite_shadcdn.md +0 -0
  138. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/agent/prompt_templates/user_tasks/cli/implement_plan.md.j2 +0 -0
  139. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/agent/prompt_templates/user_tasks/cli/init_agents.md.j2 +0 -0
  140. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/agent/prompts.py +0 -0
  141. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/agent/tool_backend/agent_tool.py +0 -0
  142. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/agent/tool_backend/base_tool.py +0 -0
  143. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/agent/tool_backend/browser_tool.py +0 -0
  144. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/agent/tool_backend/build_tool.py +0 -0
  145. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/agent/tool_backend/codex_patch.py +0 -0
  146. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/agent/tool_backend/edit_preview.py +0 -0
  147. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/agent/tool_backend/edit_tool.py +0 -0
  148. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/agent/tool_backend/eval_tool.py +0 -0
  149. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/agent/tool_backend/glob_tool.py +0 -0
  150. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/agent/tool_backend/hashline_v2.py +0 -0
  151. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/agent/tool_backend/list_directory_tool.py +0 -0
  152. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/agent/tool_backend/lsp_tool.py +0 -0
  153. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/agent/tool_backend/memory_tool.py +0 -0
  154. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/agent/tool_backend/read_file_tool.py +0 -0
  155. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/agent/tool_backend/read_image_tool.py +0 -0
  156. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/agent/tool_backend/search_backends/__init__.py +0 -0
  157. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/agent/tool_backend/search_backends/base.py +0 -0
  158. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/agent/tool_backend/search_backends/duckduckgo.py +0 -0
  159. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/agent/tool_backend/search_backends/errors.py +0 -0
  160. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/agent/tool_backend/search_backends/firecrawl.py +0 -0
  161. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/agent/tool_backend/search_backends/models.py +0 -0
  162. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/agent/tool_backend/search_backends/searxng.py +0 -0
  163. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/agent/tool_backend/search_backends/tavily.py +0 -0
  164. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/agent/tool_backend/snapshot_tool.py +0 -0
  165. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/agent/tool_backend/streaming_tool.py +0 -0
  166. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/agent/tool_backend/terminal_tool.py +0 -0
  167. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/agent/tool_backend/think_hard_tool.py +0 -0
  168. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/agent/tool_backend/web_fetch/__init__.py +0 -0
  169. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/agent/tool_backend/web_fetch/answering.py +0 -0
  170. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/agent/tool_backend/web_fetch/documents.py +0 -0
  171. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/agent/tool_backend/web_fetch/extractors.py +0 -0
  172. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/agent/tool_backend/web_fetch/pipeline.py +0 -0
  173. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/agent/tool_backend/web_fetch/retrieval.py +0 -0
  174. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/agent/tool_backend/web_fetch_tool.py +0 -0
  175. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/agent/tool_backend/web_search_tool.py +0 -0
  176. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/agent/tool_backend/workflow_tool.py +0 -0
  177. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/agent/utils/commands.py +0 -0
  178. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/agent/volatile_context.py +0 -0
  179. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/auth/__init__.py +0 -0
  180. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/auth/_jwt.py +0 -0
  181. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/auth/chatgpt_oauth.py +0 -0
  182. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/auth/constants.py +0 -0
  183. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/auth/tokens.py +0 -0
  184. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/browser_extension/__init__.py +0 -0
  185. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/browser_extension/framing.py +0 -0
  186. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/browser_extension/installer.py +0 -0
  187. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/browser_extension/manager.py +0 -0
  188. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/browser_extension/multiplex.py +0 -0
  189. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/browser_extension/native_host.py +0 -0
  190. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/browser_extension/protocol.py +0 -0
  191. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/browser_extension/registry.py +0 -0
  192. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/browser_extension/runtime.py +0 -0
  193. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/cli/__init__.py +0 -0
  194. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/cli/app.py +0 -0
  195. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/cli/browser_backend.py +0 -0
  196. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/cli/clipboard_image.py +0 -0
  197. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/cli/config.py +0 -0
  198. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/cli/connection.py +0 -0
  199. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/cli/cron.py +0 -0
  200. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/cli/diagnostics.py +0 -0
  201. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/cli/file_index.py +0 -0
  202. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/cli/goal.py +0 -0
  203. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/cli/loop.py +0 -0
  204. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/cli/mentions.py +0 -0
  205. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/cli/messages.py +0 -0
  206. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/cli/model_catalog.py +0 -0
  207. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/cli/model_connection.py +0 -0
  208. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/cli/plan_artifacts.py +0 -0
  209. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/cli/provider_registry.py +0 -0
  210. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/cli/session_event_store.py +0 -0
  211. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/cli/session_journal.py +0 -0
  212. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/cli/session_store.py +0 -0
  213. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/cli/settings.py +0 -0
  214. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/cli/skills.py +0 -0
  215. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/cli/slash_commands.py +0 -0
  216. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/cli/theme.py +0 -0
  217. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/cli/tui/__init__.py +0 -0
  218. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/cli/tui/agent_runtime.py +0 -0
  219. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/cli/tui/app_base.py +0 -0
  220. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/cli/tui/changes_screen.py +0 -0
  221. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/cli/tui/constants.py +0 -0
  222. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/cli/tui/custom_model.py +0 -0
  223. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/cli/tui/loop_runtime.py +0 -0
  224. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/cli/tui/memory_screen.py +0 -0
  225. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/cli/tui/onboarding_screen.py +0 -0
  226. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/cli/tui/prompt_flows.py +0 -0
  227. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/cli/tui/session_diff.py +0 -0
  228. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/cli/tui/settings_panel.py +0 -0
  229. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/cli/tui/settings_screen.py +0 -0
  230. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/cli/tui/state.py +0 -0
  231. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/cli/tui/status_dashboard.py +0 -0
  232. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/cli/tui/styles.tcss +0 -0
  233. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/cli/tui/sub_agent_screen.py +0 -0
  234. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/cli/tui/terminal_display.py +0 -0
  235. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/cli/tui/transcript.py +0 -0
  236. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/cli/tui/widgets.py +0 -0
  237. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/cli/updater.py +0 -0
  238. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/config.py +0 -0
  239. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/events.py +0 -0
  240. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/git_env.py +0 -0
  241. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/hooks/__init__.py +0 -0
  242. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/hooks/backends.py +0 -0
  243. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/hooks/config.py +0 -0
  244. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/hooks/dispatcher.py +0 -0
  245. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/hooks/events.py +0 -0
  246. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/hooks/matcher.py +0 -0
  247. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/hooks/outcome.py +0 -0
  248. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/llm/client.py +0 -0
  249. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/llm/exceptions.py +0 -0
  250. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/llm/instrumented_client.py +0 -0
  251. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/llm/models.py +0 -0
  252. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/llm/providers/__init__.py +0 -0
  253. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/llm/providers/anthropic.py +0 -0
  254. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/llm/providers/base.py +0 -0
  255. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/llm/providers/chatgpt_oauth.py +0 -0
  256. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/llm/providers/google.py +0 -0
  257. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/llm/providers/models.py +0 -0
  258. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/llm/providers/openai.py +0 -0
  259. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/llm/providers/openai_responses.py +0 -0
  260. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/llm/providers/responses_common.py +0 -0
  261. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/llm/ratelimit.py +0 -0
  262. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/llm/specs/__init__.py +0 -0
  263. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/llm/specs/accessors.py +0 -0
  264. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/llm/specs/catalog/__init__.py +0 -0
  265. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/llm/specs/catalog/anthropic.py +0 -0
  266. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/llm/specs/catalog/dashscope.py +0 -0
  267. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/llm/specs/catalog/deepseek.py +0 -0
  268. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/llm/specs/catalog/fireworks.py +0 -0
  269. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/llm/specs/catalog/google.py +0 -0
  270. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/llm/specs/catalog/kimi_coding.py +0 -0
  271. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/llm/specs/catalog/moonshot.py +0 -0
  272. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/llm/specs/catalog/ollama_cloud.py +0 -0
  273. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/llm/specs/catalog/openai.py +0 -0
  274. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/llm/specs/catalog/openai_chatgpt.py +0 -0
  275. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/llm/specs/catalog/openrouter.py +0 -0
  276. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/llm/specs/catalog/together.py +0 -0
  277. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/llm/specs/catalog/xai.py +0 -0
  278. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/llm/specs/catalog/zai.py +0 -0
  279. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/llm/specs/openrouter_catalog.py +0 -0
  280. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/llm/specs/thinking.py +0 -0
  281. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/llm/specs/types.py +0 -0
  282. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/llm/timeouts.py +0 -0
  283. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/llm/tool_execution_ids.py +0 -0
  284. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/local_state.py +0 -0
  285. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/mcp/__init__.py +0 -0
  286. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/mcp/config.py +0 -0
  287. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/mcp/oauth.py +0 -0
  288. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/mcp/service.py +0 -0
  289. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/mcp/state.py +0 -0
  290. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/mcp/tools.py +0 -0
  291. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/mcp/transport.py +0 -0
  292. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/memory/__init__.py +0 -0
  293. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/memory/identity.py +0 -0
  294. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/memory/manifest.py +0 -0
  295. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/memory/markdown.py +0 -0
  296. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/memory/models.py +0 -0
  297. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/memory/protocol.py +0 -0
  298. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/memory/registry.py +0 -0
  299. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/models/__init__.py +0 -0
  300. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/models/sandbox_terminal_state.py +0 -0
  301. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/permissions.py +0 -0
  302. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/runtime.py +0 -0
  303. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/sandbox/README.md +0 -0
  304. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/sandbox/__init__.py +0 -0
  305. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/sandbox/async_filesystem.py +0 -0
  306. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/sandbox/base.py +0 -0
  307. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/sandbox/browser.py +0 -0
  308. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/sandbox/event_loop.py +0 -0
  309. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/sandbox/filesystem.py +0 -0
  310. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/sandbox/local.py +0 -0
  311. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/sandbox/serializer.py +0 -0
  312. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/sandbox/terminal.py +0 -0
  313. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/sandbox/utils.py +0 -0
  314. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/scratchpad.py +0 -0
  315. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/security/__init__.py +0 -0
  316. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/security/secrets.py +0 -0
  317. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/services/base.py +0 -0
  318. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/services/browser.py +0 -0
  319. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/services/file_system.py +0 -0
  320. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/services/html.py +0 -0
  321. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/services/lsp/__init__.py +0 -0
  322. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/services/lsp/client.py +0 -0
  323. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/services/lsp/config.py +0 -0
  324. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/services/lsp/detector.py +0 -0
  325. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/services/lsp/diagnostics.py +0 -0
  326. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/services/lsp/edits.py +0 -0
  327. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/services/lsp/manager.py +0 -0
  328. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/services/lsp/registry.py +0 -0
  329. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/services/lsp/registry.yaml +0 -0
  330. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/services/snapshots.py +0 -0
  331. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/services/terminal.py +0 -0
  332. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/services/terminal_buffer.py +0 -0
  333. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/services/workspace_scan.py +0 -0
  334. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/session/__init__.py +0 -0
  335. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/session/control.py +0 -0
  336. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/session/inmemory.py +0 -0
  337. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/session/projection.py +0 -0
  338. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/session/recording.py +0 -0
  339. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/session/runtime.py +0 -0
  340. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/session/store.py +0 -0
  341. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/testing/__init__.py +0 -0
  342. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/testing/store_conformance.py +0 -0
  343. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/tools/__init__.py +0 -0
  344. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/tools/definitions.py +0 -0
  345. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/tools/registry.py +0 -0
  346. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/utils/__init__.py +0 -0
  347. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/utils/images.py +0 -0
  348. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/web/__init__.py +0 -0
  349. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/web/assets/fold.js +0 -0
  350. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/web/assets/player.css +0 -0
  351. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/web/assets/player.html +0 -0
  352. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/web/assets/player.js +0 -0
  353. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/web/bundle.py +0 -0
  354. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/web/hosting.py +0 -0
  355. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/web/redaction.py +0 -0
  356. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/web/server.py +0 -0
  357. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/web/singlefile.py +0 -0
  358. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/web/theme_css.py +0 -0
  359. {kolega_code-0.26.1 → kolega_code-0.26.3}/kolega_code/worktrees.py +0 -0
@@ -6,6 +6,47 @@ This project uses GitHub Releases for detailed generated release notes. This fil
6
6
 
7
7
  ## Unreleased
8
8
 
9
+ ## 0.26.3 - 2026-08-02
10
+
11
+ ### Added
12
+
13
+ - `kolega-code ask --no-memory-tools` disables the persistent project-memory
14
+ tools (read/list/write/edit/delete memory) and their prompt guidance for a
15
+ run — useful for headless or benchmark use where there is no durable memory
16
+ store.
17
+ - `search_codebase` accepts `path` to restrict the search to a subdirectory and
18
+ `max_results` to cap how many files are returned.
19
+
20
+ ### Changed
21
+
22
+ - `eval` now defaults `language` to `py`, so a call that omits the language runs
23
+ Python instead of failing.
24
+ - A tool call made with the wrong arguments now returns a clear message naming
25
+ the expected signature (for example `Usage: eval(code, language='py', …)`) and
26
+ no longer exposes internal class or method names.
27
+ - "Memory off" now has a single, consistent representation: a non-local host,
28
+ the new `--no-memory-tools` flag, and the memory toggle all behave the same
29
+ way, hiding both the memory tools and the memory prompt section.
30
+ - The browser agent's dispatch tool is now hidden when the model configured for
31
+ the browser agent cannot accept images, instead of failing only when invoked.
32
+
33
+ ## 0.26.2 - 2026-07-31
34
+
35
+ ### Added
36
+
37
+ - `kolega-code ask --gigacode` enables gigacode workflow orchestration in
38
+ headless runs, matching the TUI's `/gigacode` toggle: the `run_workflow` and
39
+ `list_workflow_runs` tools are exposed and the authoring guide is injected.
40
+ The setting persists with the session, so `ask --session <id>` resumes with
41
+ gigacode still on.
42
+
43
+ ### Changed
44
+
45
+ - Gigacode's concurrent-worker cap is now a flat 8 instead of being derived from
46
+ the host's core count. Workers wait on provider responses rather than CPU, so
47
+ the old formula only made fan-out width vary with the machine — and collapse to
48
+ a single serial worker on a one-CPU host or container.
49
+
9
50
  ## 0.26.1 - 2026-07-31
10
51
 
11
52
  ### Fixed
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: kolega-code
3
- Version: 0.26.1
3
+ Version: 0.26.3
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/
@@ -151,4 +151,4 @@ __all__ = [
151
151
  "parse_git_status_output",
152
152
  ]
153
153
 
154
- __version__ = "0.26.1"
154
+ __version__ = "0.26.3"
@@ -51,4 +51,4 @@ __all__ = [
51
51
  "ToolExtension",
52
52
  ]
53
53
 
54
- __version__ = "0.26.1"
54
+ __version__ = "0.26.3"
@@ -170,6 +170,7 @@ class BaseAgent(LogMixin):
170
170
  custom_agent_catalog: Optional[Any] = None,
171
171
  memory_manager: Optional[Any] = None,
172
172
  memory_project_path: Optional[Path] = None,
173
+ memory_enabled: bool = True,
173
174
  ) -> None:
174
175
  """
175
176
  Initialize a new BaseAgent instance.
@@ -308,15 +309,21 @@ class BaseAgent(LogMixin):
308
309
  from kolega_code.memory import MemoryAccessScope
309
310
 
310
311
  self.memory_manager = self.memory_manager.with_scope(MemoryAccessScope.SUBAGENT)
311
- if self.memory_manager is None and not sub_agent and isinstance(self.filesystem, LocalFileSystem):
312
- # Keep non-local/sandbox hosts unchanged unless they inject a manager.
312
+ elif self.memory_manager is None and not sub_agent:
313
313
  from kolega_code.cli.session_store import default_state_dir
314
314
  from kolega_code.memory import ProjectMemoryManager
315
315
 
316
- self.memory_manager = ProjectMemoryManager(
317
- memory_project_path if memory_project_path is not None else self.project_path,
318
- default_state_dir(),
319
- )
316
+ project = memory_project_path if memory_project_path is not None else self.project_path
317
+ # "Memory off" has one representation everywhere: a present-but-disabled
318
+ # manager, never a None. Memory is live only for a local project with the
319
+ # per-run opt-out unset; a non-local/sandbox host (whose storage would be a
320
+ # local state dir, disconnected from the remote project) or an explicit
321
+ # `--no-memory-tools` opt-out gets an inert, storage-inert manager that
322
+ # writes nothing. Dispatched sub-agents inherit whichever it is.
323
+ if memory_enabled and isinstance(self.filesystem, LocalFileSystem):
324
+ self.memory_manager = ProjectMemoryManager(project, default_state_dir())
325
+ else:
326
+ self.memory_manager = ProjectMemoryManager.disabled(project, default_state_dir())
320
327
  self.context.services.memory_manager = self.memory_manager
321
328
  self._owns_memory_manager = True
322
329
 
@@ -19,13 +19,30 @@ class BrowserAgent(BaseAgent):
19
19
 
20
20
  agent_name = "browser-agent"
21
21
 
22
+ @classmethod
23
+ def resolved_model_supports_vision(cls, config: AgentConfig) -> bool:
24
+ """True if the model resolved for the browser-agent role accepts image input.
25
+
26
+ The browser agent may run on its own ``agent_models`` override, so this is
27
+ deliberately keyed on the browser-agent's resolved model — not the main
28
+ coding model, which can differ in either direction.
29
+ """
30
+ model_config = config.model_config_for_agent(cls.agent_name)
31
+ provider = getattr(model_config.provider, "value", model_config.provider)
32
+ try:
33
+ return model_supports_vision(provider, model_config.model)
34
+ except ValueError:
35
+ # Unknown model → can't confirm image support → treat as no vision.
36
+ # This runs on every tool-list build, so it must never raise.
37
+ return False
38
+
22
39
  @classmethod
23
40
  def validate_model_capabilities(cls, config: AgentConfig) -> None:
24
41
  """Require the resolved browser-agent model to accept image input."""
42
+ if cls.resolved_model_supports_vision(config):
43
+ return
25
44
  model_config = config.model_config_for_agent(cls.agent_name)
26
45
  provider = getattr(model_config.provider, "value", model_config.provider)
27
- if model_supports_vision(provider, model_config.model):
28
- return
29
46
  raise ValueError(
30
47
  "BrowserAgent requires a vision-capable model, but "
31
48
  f"{provider}/{model_config.model} does not support image input. "
@@ -53,6 +53,7 @@ class CoderAgent(BaseAgent, LogMixin):
53
53
  custom_agent_catalog: Optional[Any] = None,
54
54
  memory_manager: Optional[Any] = None,
55
55
  memory_project_path: Optional[Path] = None,
56
+ memory_enabled: bool = True,
56
57
  ) -> None:
57
58
  """
58
59
  Initialize a new CoderAgent instance.
@@ -117,6 +118,7 @@ class CoderAgent(BaseAgent, LogMixin):
117
118
  custom_agent_catalog=custom_agent_catalog,
118
119
  memory_manager=memory_manager,
119
120
  memory_project_path=memory_project_path,
121
+ memory_enabled=memory_enabled,
120
122
  )
121
123
 
122
124
  # Configure tool collection with custom coder agent tools
@@ -20,7 +20,7 @@ from .errors import (
20
20
  )
21
21
  from .executor import DEFAULT_MAX_AGENT_DEPTH, MAX_AGENT_DEPTH, extract_meta, run_script, safe_builtins
22
22
  from .journal import ResumeCache, RunJournal, saved_workflows_dir, workflows_root
23
- from .runtime import DEFAULT_AGENT_CAP, MAX_FANOUT, WorkflowRuntime, default_concurrency
23
+ from .runtime import DEFAULT_AGENT_CAP, DEFAULT_WORKFLOW_CONCURRENCY, MAX_FANOUT, WorkflowRuntime
24
24
  from .types import AgentRunResult, AgentRunSpec, DispatchFn, EmitFn
25
25
 
26
26
  __all__ = [
@@ -39,7 +39,7 @@ __all__ = [
39
39
  "workflows_root",
40
40
  "saved_workflows_dir",
41
41
  "WorkflowRuntime",
42
- "default_concurrency",
42
+ "DEFAULT_WORKFLOW_CONCURRENCY",
43
43
  "MAX_FANOUT",
44
44
  "DEFAULT_AGENT_CAP",
45
45
  "AgentRunSpec",
@@ -5,6 +5,8 @@ it in sync with the primitives in :mod:`runtime` and the tool in
5
5
  ``tool_backend/workflow_tool.py``.
6
6
  """
7
7
 
8
+ from ..prompt_provider import PromptExtension
9
+
8
10
  GIGACODE_AUTHORING_GUIDE = """\
9
11
  ## gigacode — dynamic workflow orchestration
10
12
 
@@ -299,3 +301,21 @@ id as `resume_from_run_id` — every agent call it completed replays from the jo
299
301
  no cost. `list_workflow_runs` shows only this session's runs; a run still listed as
300
302
  "running" when no workflow is in flight died mid-run and is resumable the same way.
301
303
  """
304
+
305
+
306
+ def gigacode_prompt_extension() -> PromptExtension:
307
+ """The authoring guide as a prompt extension, for every frontend that enables gigacode.
308
+
309
+ The TUI's ``/gigacode`` toggle and ``kolega-code ask --gigacode`` share this
310
+ so a headless run sees exactly the guidance an interactive session does.
311
+ """
312
+ return PromptExtension(
313
+ id="gigacode",
314
+ title="gigacode — workflow orchestration",
315
+ markdown=GIGACODE_AUTHORING_GUIDE,
316
+ agent_types=None,
317
+ modes=None,
318
+ # Sub-agents can't run workflows (run_workflow is gated off for them),
319
+ # so the authoring guide is just prompt bloat for a sub-agent.
320
+ propagate_to_sub_agents=False,
321
+ )
@@ -13,7 +13,6 @@ from __future__ import annotations
13
13
 
14
14
  import asyncio
15
15
  import inspect
16
- import os
17
16
  import random
18
17
  from typing import Any, Awaitable, Callable, Dict, Iterable, List, Optional
19
18
 
@@ -43,14 +42,12 @@ DROPPED_ITEM_LOG_LIMIT = 10
43
42
  START_STAGGER_SECONDS = 0.75
44
43
 
45
44
 
46
- def default_concurrency() -> int:
47
- """Concurrent-agent cap: a few below the core count, clamped to [1, 8].
48
-
49
- Kept modest so a fan-out doesn't burst enough simultaneous LLM requests to trip
50
- account-level rate limits; the jittered start-stagger further de-correlates them.
51
- """
52
- cpus = os.cpu_count() or 4
53
- return max(1, min(8, cpus - 2))
45
+ # Concurrent-agent cap for one workflow. A worker spends nearly all its wall-clock
46
+ # waiting on a provider response, so the binding constraint is the account's rate
47
+ # limit, not the host's core count — deriving this from cores only made the fan-out
48
+ # width vary arbitrarily with the machine (and collapse to 1 in a single-CPU
49
+ # container). The jittered start-stagger de-correlates the burst on top of this cap.
50
+ DEFAULT_WORKFLOW_CONCURRENCY = 8
54
51
 
55
52
 
56
53
  def _call_with_arity(fn: Callable[..., Any], *args: Any) -> Any:
@@ -97,7 +94,7 @@ class WorkflowRuntime:
97
94
  if self._accounting.budget is not budget:
98
95
  raise ValueError("workflow accounting must own the runtime budget")
99
96
  self.budget = self._accounting.budget
100
- self._sem = asyncio.Semaphore(concurrency or default_concurrency())
97
+ self._sem = asyncio.Semaphore(concurrency or DEFAULT_WORKFLOW_CONCURRENCY)
101
98
  self._max_agent_depth = max_agent_depth
102
99
  self._resolver = workflow_resolver
103
100
  self._routing_fingerprint = routing_fingerprint
@@ -47,6 +47,7 @@ class PlanningAgent(BaseAgent):
47
47
  max_iterations: Optional[int] = None,
48
48
  custom_agent_catalog: Optional[Any] = None,
49
49
  memory_manager: Optional[Any] = None,
50
+ memory_enabled: bool = True,
50
51
  ) -> None:
51
52
  if custom_agent_catalog is not None:
52
53
  custom_agent_catalog = custom_agent_catalog.for_mode("plan")
@@ -81,6 +82,7 @@ class PlanningAgent(BaseAgent):
81
82
  max_iterations=max_iterations,
82
83
  custom_agent_catalog=custom_agent_catalog,
83
84
  memory_manager=memory_manager,
85
+ memory_enabled=memory_enabled,
84
86
  )
85
87
 
86
88
  self._completed_plan: Optional[str] = None
@@ -22,6 +22,8 @@ _RC_MARKER = "__KOLEGA_RG_RC"
22
22
 
23
23
  # Display caps (shared by every engine via the single formatter).
24
24
  _MAX_FILES = 128
25
+ # Ceiling for a caller-supplied ``max_results`` so a huge request can't flood context.
26
+ _MAX_FILES_CEILING = 512
25
27
  _MAX_LINES_PER_FILE = 5
26
28
  _MAX_LINE_LENGTH = 200
27
29
  _MAX_FILE_SIZE = 10 * 1024 * 1024 # 10MB
@@ -46,6 +48,10 @@ class _EngineUnavailable(Exception):
46
48
  flag, non-regex error) so the caller falls back to the next engine tier."""
47
49
 
48
50
 
51
+ class _InvalidSearchPath(Exception):
52
+ """A caller-supplied ``path`` that escapes the project or isn't a directory."""
53
+
54
+
49
55
  class _SearchTimedOut(Exception):
50
56
  """Raised when an otherwise valid search exceeds its execution budget."""
51
57
 
@@ -147,6 +153,31 @@ class SearchCodebaseTool(BaseTool):
147
153
  excluded.update(_BROAD_ROOT_EXCLUDE_DIRS)
148
154
  return excluded
149
155
 
156
+ def _resolve_search_target(self, path: Optional[str]) -> str:
157
+ """Validate a caller-supplied ``path`` and return a project-relative search
158
+ root (``.`` for the whole project). Rejects absolute paths, parent escapes,
159
+ and non-directories so the search can never wander outside the project."""
160
+ if not path or path.strip() in ("", ".", "./"):
161
+ return "."
162
+ candidate = Path(path.strip())
163
+ if candidate.is_absolute() or ".." in candidate.parts:
164
+ raise _InvalidSearchPath(f"path must be a relative directory inside the project, got '{path}'")
165
+ rel = candidate.as_posix().strip("/")
166
+ if not rel:
167
+ return "."
168
+ try:
169
+ exists = self.filesystem.exists(rel)
170
+ is_dir = exists and self.filesystem.is_dir(rel)
171
+ except Exception:
172
+ # If the filesystem can't answer (e.g. an exotic sandbox), let the
173
+ # engine handle the path rather than blocking a legitimate search.
174
+ return rel
175
+ if not exists:
176
+ raise _InvalidSearchPath(f"path '{path}' was not found in the project")
177
+ if not is_dir:
178
+ raise _InvalidSearchPath(f"path '{path}' is not a directory; use file_pattern to filter files")
179
+ return rel
180
+
150
181
  async def search_codebase(
151
182
  self,
152
183
  pattern: str,
@@ -154,6 +185,8 @@ class SearchCodebaseTool(BaseTool):
154
185
  case_sensitive: bool = False,
155
186
  literal: bool = False,
156
187
  *,
188
+ path: Optional[str] = None,
189
+ max_results: int = _MAX_FILES,
157
190
  line_formatter: Optional[Callable[[int, str], str]] = None,
158
191
  ) -> str:
159
192
  """
@@ -170,9 +203,11 @@ class SearchCodebaseTool(BaseTool):
170
203
  file_pattern: Optional glob to filter which files to search (default: all files)
171
204
  case_sensitive: Whether the search is case-sensitive (default: False)
172
205
  literal: Treat the pattern as plain text instead of a regular expression (default: False)
206
+ path: Optional directory (relative to the project root) to restrict the search to; searches the whole project when omitted
207
+ max_results: Maximum number of matching files to return (default 128, capped at 512)
173
208
 
174
209
  Returns:
175
- Markdown formatted list of files and matches, limited to 128 results
210
+ Markdown formatted list of files and matches, capped at ``max_results`` files
176
211
 
177
212
  Raises:
178
213
  Exception: If any error occurs during the search operation
@@ -198,10 +233,16 @@ class SearchCodebaseTool(BaseTool):
198
233
  await self.log_error(error_msg, sender=self.caller.agent_name)
199
234
  return f"Error: {error_msg}"
200
235
 
236
+ limit = max(1, min(int(max_results), _MAX_FILES_CEILING))
237
+ try:
238
+ search_target = self._resolve_search_target(path)
239
+ except _InvalidSearchPath as exc:
240
+ return f"Error: {exc}"
241
+
201
242
  # Run the first available engine; fall back down the tiers on failure.
202
243
  for runner in await self._engine_chain():
203
244
  try:
204
- run = await runner(pattern, file_pattern, case_sensitive, literal, regex)
245
+ run = await runner(pattern, file_pattern, case_sensitive, literal, regex, search_target, limit)
205
246
  except _EngineUnavailable:
206
247
  continue
207
248
  except _SearchTimedOut:
@@ -213,7 +254,7 @@ class SearchCodebaseTool(BaseTool):
213
254
  f"elapsed={run.elapsed_seconds:.2f}s)",
214
255
  sender=self.caller.agent_name,
215
256
  )
216
- return self._format_results(run, pattern, line_formatter=line_formatter)
257
+ return self._format_results(run, pattern, limit=limit, line_formatter=line_formatter)
217
258
 
218
259
  # The Python tier never raises _EngineUnavailable, so this is unreachable.
219
260
  return f"No matches found for pattern '{pattern}'"
@@ -266,7 +307,9 @@ class SearchCodebaseTool(BaseTool):
266
307
  # ripgrep engine
267
308
  # ------------------------------------------------------------------
268
309
 
269
- def _rg_args(self, pattern: str, file_pattern: str, case_sensitive: bool, literal: bool) -> List[str]:
310
+ def _rg_args(
311
+ self, pattern: str, file_pattern: str, case_sensitive: bool, literal: bool, search_target: str = "."
312
+ ) -> List[str]:
270
313
  args = [
271
314
  "--json",
272
315
  "--no-config",
@@ -297,17 +340,25 @@ class SearchCodebaseTool(BaseTool):
297
340
  if file_pattern != "*":
298
341
  glob = file_pattern if "/" not in file_pattern else f"**/{file_pattern}"
299
342
  args += ["-g", glob]
300
- # Pattern as its own argv element (after -e) and an explicit search path so
301
- # ripgrep never reads stdin in a headless context.
302
- args += ["-e", pattern, "."]
343
+ # Pattern as its own argv element (after -e) and an explicit search path
344
+ # (the whole tree, or the caller's ``path`` subtree) so ripgrep never reads
345
+ # stdin in a headless context.
346
+ args += ["-e", pattern, search_target]
303
347
  return args
304
348
 
305
349
  async def _run_rg_local(
306
- self, pattern: str, file_pattern: str, case_sensitive: bool, literal: bool, regex
350
+ self,
351
+ pattern: str,
352
+ file_pattern: str,
353
+ case_sensitive: bool,
354
+ literal: bool,
355
+ regex,
356
+ search_target: str = ".",
357
+ limit: int = _MAX_FILES,
307
358
  ) -> SearchRun:
308
359
  if shutil.which("rg") is None:
309
360
  raise _EngineUnavailable()
310
- args = self._rg_args(pattern, file_pattern, case_sensitive, literal)
361
+ args = self._rg_args(pattern, file_pattern, case_sensitive, literal, search_target)
311
362
  env = {**os.environ, "RIPGREP_CONFIG_FILE": ""}
312
363
  try:
313
364
  proc = await asyncio.create_subprocess_exec(
@@ -329,9 +380,16 @@ class SearchCodebaseTool(BaseTool):
329
380
  return SearchRun(self._parse_rg_json(stdout.decode("utf-8", "replace")))
330
381
 
331
382
  async def _run_rg_sandbox(
332
- self, pattern: str, file_pattern: str, case_sensitive: bool, literal: bool, regex
383
+ self,
384
+ pattern: str,
385
+ file_pattern: str,
386
+ case_sensitive: bool,
387
+ literal: bool,
388
+ regex,
389
+ search_target: str = ".",
390
+ limit: int = _MAX_FILES,
333
391
  ) -> SearchRun:
334
- args = self._rg_args(pattern, file_pattern, case_sensitive, literal)
392
+ args = self._rg_args(pattern, file_pattern, case_sensitive, literal, search_target)
335
393
  cmd = "RIPGREP_CONFIG_FILE= rg " + " ".join(shlex.quote(a) for a in args)
336
394
  full_cmd = f"cd {shlex.quote(self._fs_root)} && {cmd} ; echo {_RC_MARKER}=$?"
337
395
  try:
@@ -390,7 +448,9 @@ class SearchCodebaseTool(BaseTool):
390
448
  # grep engine
391
449
  # ------------------------------------------------------------------
392
450
 
393
- def _grep_argv(self, pattern: str, file_pattern: str, case_sensitive: bool, literal: bool) -> List[str]:
451
+ def _grep_argv(
452
+ self, pattern: str, file_pattern: str, case_sensitive: bool, literal: bool, search_target: str = "."
453
+ ) -> List[str]:
394
454
  argv = ["grep", "-r", "-n", "--binary-files=without-match"]
395
455
  if not case_sensitive:
396
456
  argv.append("-i")
@@ -403,16 +463,24 @@ class SearchCodebaseTool(BaseTool):
403
463
  argv.append("--exclude-dir=.*")
404
464
  for ext in sorted(self.BINARY_EXTENSIONS):
405
465
  argv.append(f"--exclude=*{ext}")
406
- # -e guards a pattern that starts with '-'; '.' is the search root.
407
- argv += ["-e", pattern, "."]
466
+ # -e guards a pattern that starts with '-'; search_target is the search
467
+ # root (the whole tree, or the caller's ``path`` subtree).
468
+ argv += ["-e", pattern, search_target]
408
469
  return argv
409
470
 
410
471
  async def _run_grep_local(
411
- self, pattern: str, file_pattern: str, case_sensitive: bool, literal: bool, regex
472
+ self,
473
+ pattern: str,
474
+ file_pattern: str,
475
+ case_sensitive: bool,
476
+ literal: bool,
477
+ regex,
478
+ search_target: str = ".",
479
+ limit: int = _MAX_FILES,
412
480
  ) -> SearchRun:
413
481
  if shutil.which("grep") is None:
414
482
  raise _EngineUnavailable()
415
- argv = self._grep_argv(pattern, file_pattern, case_sensitive, literal)
483
+ argv = self._grep_argv(pattern, file_pattern, case_sensitive, literal, search_target)
416
484
  try:
417
485
  proc = await asyncio.create_subprocess_exec(
418
486
  *argv,
@@ -431,9 +499,16 @@ class SearchCodebaseTool(BaseTool):
431
499
  return SearchRun(self._drop_oversize_local(records))
432
500
 
433
501
  async def _run_grep_sandbox(
434
- self, pattern: str, file_pattern: str, case_sensitive: bool, literal: bool, regex
502
+ self,
503
+ pattern: str,
504
+ file_pattern: str,
505
+ case_sensitive: bool,
506
+ literal: bool,
507
+ regex,
508
+ search_target: str = ".",
509
+ limit: int = _MAX_FILES,
435
510
  ) -> SearchRun:
436
- argv = self._grep_argv(pattern, file_pattern, case_sensitive, literal)
511
+ argv = self._grep_argv(pattern, file_pattern, case_sensitive, literal, search_target)
437
512
  cmd = " ".join(shlex.quote(a) for a in argv)
438
513
  full_cmd = f"cd {shlex.quote(self._fs_root)} && {cmd} ; echo {_RC_MARKER}=$?"
439
514
  try:
@@ -524,15 +599,23 @@ class SearchCodebaseTool(BaseTool):
524
599
  # ------------------------------------------------------------------
525
600
 
526
601
  async def _run_python(
527
- self, pattern: str, file_pattern: str, case_sensitive: bool, literal: bool, regex
602
+ self,
603
+ pattern: str,
604
+ file_pattern: str,
605
+ case_sensitive: bool,
606
+ literal: bool,
607
+ regex,
608
+ search_target: str = ".",
609
+ limit: int = _MAX_FILES,
528
610
  ) -> SearchRun:
529
611
  if hasattr(self.filesystem, "sandbox"):
530
- return await self._run_python_sandbox_fallback(file_pattern, regex)
612
+ return await self._run_python_sandbox_fallback(file_pattern, regex, search_target, limit)
531
613
 
532
614
  normalized_pattern = "**/*" if file_pattern == "*" else f"**/{file_pattern}"
533
615
  self._load_gitignore_patterns()
616
+ scan_root = Path(self._fs_root) if search_target == "." else Path(self._fs_root) / search_target
534
617
  scan = await scan_workspace(
535
- Path(self._fs_root),
618
+ scan_root,
536
619
  pattern=normalized_pattern,
537
620
  include_files=True,
538
621
  include_directories=False,
@@ -543,9 +626,9 @@ class SearchCodebaseTool(BaseTool):
543
626
  ignore_spec=getattr(self, "_gitignore_spec", None),
544
627
  limits=ScanLimits(timeout_seconds=_SCAN_TIMEOUT_SECONDS, max_entries=_SCAN_MAX_ENTRIES),
545
628
  )
546
- return await self._search_scanned_files(scan, regex)
629
+ return await self._search_scanned_files(scan, regex, limit)
547
630
 
548
- async def _search_scanned_files(self, scan: ScanOutcome, regex) -> SearchRun:
631
+ async def _search_scanned_files(self, scan: ScanOutcome, regex, limit: int = _MAX_FILES) -> SearchRun:
549
632
  cancel_event = threading.Event()
550
633
  started = time.monotonic()
551
634
  remaining = max(0.01, _SEARCH_TIMEOUT_SECONDS - scan.elapsed_seconds)
@@ -570,7 +653,7 @@ class SearchCodebaseTool(BaseTool):
570
653
  if regex.search(line):
571
654
  records.append((norm, line_num, line))
572
655
  matched_files.add(norm)
573
- if len(matched_files) > _MAX_FILES:
656
+ if len(matched_files) > limit:
574
657
  return SearchRun(
575
658
  records,
576
659
  False,
@@ -598,28 +681,37 @@ class SearchCodebaseTool(BaseTool):
598
681
  task.cancel()
599
682
  return SearchRun([], False, "deadline", scan.visited_entries, _SEARCH_TIMEOUT_SECONDS)
600
683
 
601
- async def _run_python_sandbox_fallback(self, file_pattern: str, regex) -> SearchRun:
684
+ async def _run_python_sandbox_fallback(
685
+ self, file_pattern: str, regex, search_target: str = ".", limit: int = _MAX_FILES
686
+ ) -> SearchRun:
602
687
  """Keep the legacy remote-files fallback off-loop and time bounded."""
603
688
  cancel_event = threading.Event()
604
689
  started = time.monotonic()
690
+ prefix = "" if search_target == "." else search_target.rstrip("/") + "/"
605
691
 
606
692
  def search() -> SearchRun:
607
693
  records: List[Record] = []
694
+ matched_files: set[str] = set()
608
695
  for file_path, file_size in self._get_files_batch_sync(file_pattern):
609
696
  if cancel_event.is_set() or time.monotonic() - started >= _SEARCH_TIMEOUT_SECONDS:
610
697
  return SearchRun(records, False, "deadline", elapsed_seconds=time.monotonic() - started)
611
698
  if file_size > _MAX_FILE_SIZE or self._is_likely_binary_by_extension(file_path):
612
699
  continue
700
+ norm = self._normalize_path(file_path)
701
+ if prefix and not norm.startswith(prefix):
702
+ continue
613
703
  try:
614
704
  content = self.filesystem.read_text(file_path)
615
705
  if "\x00" in content[:1024]:
616
706
  continue
617
707
  except Exception:
618
708
  continue
619
- norm = self._normalize_path(file_path)
620
709
  for line_num, line in enumerate(content.splitlines(), start=1):
621
710
  if regex.search(line):
622
711
  records.append((norm, line_num, line))
712
+ matched_files.add(norm)
713
+ if len(matched_files) > limit:
714
+ return SearchRun(records, False, "result_limit", elapsed_seconds=time.monotonic() - started)
623
715
  return SearchRun(records, elapsed_seconds=time.monotonic() - started)
624
716
 
625
717
  task = asyncio.create_task(asyncio.to_thread(search))
@@ -643,6 +735,7 @@ class SearchCodebaseTool(BaseTool):
643
735
  run: SearchRun,
644
736
  original_pattern: str,
645
737
  *,
738
+ limit: int = _MAX_FILES,
646
739
  line_formatter: Optional[Callable[[int, str], str]] = None,
647
740
  ) -> str:
648
741
  """Group records by file (first-seen order), apply the display caps, and
@@ -652,7 +745,7 @@ class SearchCodebaseTool(BaseTool):
652
745
  for path, line_num, raw in run.records:
653
746
  if path in files:
654
747
  files[path].append((line_num, raw))
655
- elif len(files) < _MAX_FILES:
748
+ elif len(files) < limit:
656
749
  files[path] = [(line_num, raw)]
657
750
  else:
658
751
  limit_hit = True
@@ -690,9 +783,7 @@ class SearchCodebaseTool(BaseTool):
690
783
 
691
784
  output = f"# Search Results for '{original_pattern}'\n\n"
692
785
  if limit_hit or run.stop_reason == "result_limit":
693
- output += (
694
- f"⚠️ **Note:** Showing only the first {_MAX_FILES} results. There are more matches in the codebase.\n\n"
695
- )
786
+ output += f"⚠️ **Note:** Showing only the first {limit} results. There are more matches in the codebase.\n\n"
696
787
  elif not run.complete:
697
788
  output += (
698
789
  f"⚠️ **Incomplete search:** stopped because of {run.stop_reason or 'a search limit'}. "