Package not found. Please check the package name and try again.
kolega-code 0.26.7__tar.gz → 0.26.8__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.
- {kolega_code-0.26.7 → kolega_code-0.26.8}/CHANGELOG.md +66 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/PKG-INFO +2 -1
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/__init__.py +1 -1
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/agent/__init__.py +1 -1
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/agent/baseagent.py +215 -30
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/agent/browseragent.py +2 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/agent/coder.py +2 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/agent/common.py +10 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/agent/compression.py +11 -8
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/agent/context.py +6 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/agent/conversation.py +2 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/agent/custom_agents.py +2 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/agent/eval/kernel.py +3 -2
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/agent/eval/runner.js +11 -4
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/agent/generalagent.py +2 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/agent/investigationagent.py +2 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/agent/planningagent.py +2 -0
- kolega_code-0.26.8/kolega_code/agent/prompt_templates/auxiliary/agent_loop/silent_turn_exhausted.user.md +3 -0
- kolega_code-0.26.8/kolega_code/agent/prompt_templates/auxiliary/agent_loop/silent_turn_nudge.user.md.j2 +9 -0
- kolega_code-0.26.8/kolega_code/agent/prompt_templates/auxiliary/agent_loop/truncated_turn_nudge.user.md.j2 +9 -0
- kolega_code-0.26.8/kolega_code/agent/prompt_templates/extensions/cli/mode_switch_notice.md.j2 +23 -0
- kolega_code-0.26.8/kolega_code/agent/prompt_templates/system/agents/coder_ask.md.j2 +5 -0
- kolega_code-0.26.7/kolega_code/agent/prompt_templates/system/agents/coder_ask.md.j2 → kolega_code-0.26.8/kolega_code/agent/prompt_templates/system/agents/coder_base.md.j2 +75 -11
- kolega_code-0.26.8/kolega_code/agent/prompt_templates/system/agents/coder_cli.md.j2 +3 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/agent/prompts.py +39 -1
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/agent/tool_backend/agent_tool.py +2 -0
- kolega_code-0.26.8/kolega_code/agent/tool_backend/network_status.py +90 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/agent/tool_backend/search_backends/__init__.py +2 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/agent/tool_backend/search_backends/duckduckgo.py +9 -2
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/agent/tool_backend/search_backends/errors.py +8 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/agent/tool_backend/search_backends/firecrawl.py +3 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/agent/tool_backend/search_backends/searxng.py +6 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/agent/tool_backend/search_backends/tavily.py +6 -1
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/agent/tool_backend/terminal_tool.py +31 -18
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/agent/tool_backend/think_hard_tool.py +14 -10
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/agent/tool_backend/web_fetch/pipeline.py +4 -1
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/agent/tool_backend/web_fetch/retrieval.py +30 -1
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/agent/tool_backend/web_fetch_tool.py +11 -3
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/agent/tool_backend/web_search_tool.py +11 -2
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/agent/tools.py +36 -11
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/cli/app.py +107 -3
- kolega_code-0.26.8/kolega_code/cli/ask_output.py +92 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/cli/main.py +70 -38
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/cli/messages.py +1 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/cli/model_connection.py +26 -14
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/cli/session_store.py +13 -2
- kolega_code-0.26.8/kolega_code/cli/session_usage.py +289 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/cli/tui/agent_runtime.py +90 -63
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/cli/tui/app_base.py +10 -1
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/cli/tui/loop_runtime.py +9 -16
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/cli/tui/onboarding_screen.py +1 -1
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/cli/tui/session_diff.py +39 -6
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/cli/tui/settings_panel.py +1 -1
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/cli/tui/status_dashboard.py +42 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/cli/tui/styles.tcss +8 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/cli/tui/transcript.py +4 -4
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/cli/tui/widgets.py +5 -1
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/llm/client.py +38 -2
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/llm/instrumented_client.py +13 -31
- kolega_code-0.26.8/kolega_code/llm/ledger.py +411 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/llm/models.py +69 -21
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/llm/providers/anthropic.py +6 -4
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/llm/providers/deepseek_responses.py +26 -1
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/llm/providers/google.py +15 -4
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/llm/providers/openai.py +55 -39
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/llm/providers/responses_common.py +41 -9
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/llm/specs/__init__.py +6 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/llm/specs/accessors.py +48 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/llm/specs/catalog/deepseek.py +17 -3
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/llm/specs/catalog/fireworks.py +7 -2
- kolega_code-0.26.8/kolega_code/llm/usage.py +357 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/sandbox/terminal.py +4 -3
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/services/base.py +7 -5
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/services/terminal.py +77 -14
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/tools/core.py +24 -1
- kolega_code-0.26.8/kolega_code/tools/param_aliases.py +128 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/pyproject.toml +5 -1
- kolega_code-0.26.7/kolega_code/agent/prompt_templates/system/agents/coder_cli.md.j2 +0 -133
- {kolega_code-0.26.7 → kolega_code-0.26.8}/.gitignore +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/CONTRIBUTING.md +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/LICENSE +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/MIGRATION.md +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/README.md +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/RELEASING.md +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/_bundled_skills/LICENSE +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/_bundled_skills/manifest.json +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/_bundled_skills/skills/deep-research/SKILL.md +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/_bundled_skills/skills/deep-research/references/evidence-and-reporting.md +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/_bundled_skills/skills/deep-research/references/gigacode-workflow.md +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/_bundled_skills/skills/deep-research/scripts/deep-research.workflow +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/_bundled_skills/skills/deep-research/scripts/materialize_report.py +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/_bundled_skills/skills/docx/LICENSE +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/_bundled_skills/skills/docx/SKILL.md +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/_bundled_skills/skills/docx/references/examples.md +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/_bundled_skills/skills/docx/references/limitations.md +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/_bundled_skills/skills/docx/references/operations.md +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/_bundled_skills/skills/docx/references/quality.md +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/_bundled_skills/skills/docx/requirements.txt +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/_bundled_skills/skills/docx/scripts/docx_tool.py +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/_bundled_skills/skills/docx/scripts/smoke_test.py +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/_bundled_skills/skills/humanizer/LICENSE +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/_bundled_skills/skills/humanizer/SKILL.md +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/_bundled_skills/skills/pdf/LICENSE +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/_bundled_skills/skills/pdf/SKILL.md +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/_bundled_skills/skills/pdf/references/examples.md +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/_bundled_skills/skills/pdf/references/limitations.md +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/_bundled_skills/skills/pdf/references/ocr.md +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/_bundled_skills/skills/pdf/references/operations.md +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/_bundled_skills/skills/pdf/references/quality.md +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/_bundled_skills/skills/pdf/references/redaction.md +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/_bundled_skills/skills/pdf/requirements-ocr-paddle.txt +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/_bundled_skills/skills/pdf/requirements-ocr-surya.txt +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/_bundled_skills/skills/pdf/requirements.txt +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/_bundled_skills/skills/pdf/scripts/pdf_tool.py +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/_bundled_skills/skills/pdf/scripts/smoke_test.py +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/_bundled_skills/skills/pptx/LICENSE +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/_bundled_skills/skills/pptx/SKILL.md +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/_bundled_skills/skills/pptx/references/examples.md +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/_bundled_skills/skills/pptx/references/limitations.md +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/_bundled_skills/skills/pptx/references/operations.md +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/_bundled_skills/skills/pptx/requirements.txt +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/_bundled_skills/skills/pptx/scripts/pptx_tool.py +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/_bundled_skills/skills/pptx/scripts/smoke_test.py +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/_bundled_skills/skills/review/SKILL.md +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/_bundled_skills/skills/review/references/github-publishing.md +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/_bundled_skills/skills/skill-authoring/SKILL.md +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/_bundled_skills/skills/skill-authoring/references/review-checklist.md +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/_bundled_skills/skills/xlsx/LICENSE +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/_bundled_skills/skills/xlsx/SKILL.md +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/_bundled_skills/skills/xlsx/references/examples.md +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/_bundled_skills/skills/xlsx/references/limitations.md +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/_bundled_skills/skills/xlsx/references/operations.md +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/_bundled_skills/skills/xlsx/references/quality.md +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/_bundled_skills/skills/xlsx/requirements.txt +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/_bundled_skills/skills/xlsx/scripts/smoke_test.py +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/_bundled_skills/skills/xlsx/scripts/xlsx_tool.py +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/agent/edit_protocols.py +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/agent/errors.py +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/agent/eval/__init__.py +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/agent/eval/bridge.py +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/agent/eval/bundle-requirements.in +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/agent/eval/bundle-requirements.txt +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/agent/eval/env.py +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/agent/eval/js_kernel.py +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/agent/eval/prelude.js +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/agent/eval/prelude.py +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/agent/eval/protocol.py +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/agent/eval/py_kernel.py +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/agent/eval/runner.py +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/agent/goal.py +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/agent/model_routing.py +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/agent/orchestration/__init__.py +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/agent/orchestration/accounting.py +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/agent/orchestration/budget.py +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/agent/orchestration/context.py +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/agent/orchestration/errors.py +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/agent/orchestration/executor.py +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/agent/orchestration/guide.py +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/agent/orchestration/journal.py +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/agent/orchestration/runtime.py +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/agent/orchestration/types.py +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/agent/prompt_dump.py +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/agent/prompt_overrides.py +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/agent/prompt_provider.py +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/agent/prompt_templates/auxiliary/compression/summary.system.md +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/agent/prompt_templates/auxiliary/compression/summary.user.md.j2 +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/agent/prompt_templates/auxiliary/terminal/output_summary.system.md +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/agent/prompt_templates/auxiliary/terminal/safety.system.md +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/agent/prompt_templates/auxiliary/tools/think_hard.system.md +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/agent/prompt_templates/extensions/cli/build_questions.md +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/agent/prompt_templates/extensions/cli/current_plan_artifact.md.j2 +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/agent/prompt_templates/extensions/cli/planning_questions.md +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/agent/prompt_templates/extensions/cli/scratchpad.md.j2 +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/agent/prompt_templates/extensions/cli/shared_task_list.md +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/agent/prompt_templates/extensions/cli/shared_task_list_readonly.md +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/agent/prompt_templates/extensions/cli/worktree_control.md.j2 +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/agent/prompt_templates/extensions/skills/catalog.md.j2 +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/agent/prompt_templates/system/agents/browser.md.j2 +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/agent/prompt_templates/system/agents/general.md.j2 +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/agent/prompt_templates/system/agents/investigation.md.j2 +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/agent/prompt_templates/system/agents/planning.md.j2 +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/agent/prompt_templates/system/includes/agents_md_instructions.md +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/agent/prompt_templates/system/includes/context_updates.md +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/agent/prompt_templates/system/includes/environment_variables/workspace_env_vars.md +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/agent/prompt_templates/system/includes/frontend_guidance.md +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/agent/prompt_templates/system/includes/starter_templates/expo.md +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/agent/prompt_templates/system/includes/starter_templates/html_website.md +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/agent/prompt_templates/system/includes/starter_templates/mern_stack.md +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/agent/prompt_templates/system/includes/starter_templates/react_vite_shadcdn.md +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/agent/prompt_templates/user_tasks/cli/implement_plan.md.j2 +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/agent/prompt_templates/user_tasks/cli/init_agents.md.j2 +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/agent/tool_backend/base_tool.py +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/agent/tool_backend/browser_tool.py +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/agent/tool_backend/build_tool.py +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/agent/tool_backend/codex_patch.py +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/agent/tool_backend/edit_preview.py +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/agent/tool_backend/edit_tool.py +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/agent/tool_backend/eval_tool.py +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/agent/tool_backend/glob_tool.py +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/agent/tool_backend/hashline_v2.py +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/agent/tool_backend/list_directory_tool.py +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/agent/tool_backend/lsp_tool.py +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/agent/tool_backend/memory_tool.py +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/agent/tool_backend/read_file_tool.py +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/agent/tool_backend/read_image_tool.py +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/agent/tool_backend/search_backends/base.py +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/agent/tool_backend/search_backends/models.py +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/agent/tool_backend/search_codebase_tool.py +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/agent/tool_backend/snapshot_tool.py +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/agent/tool_backend/streaming_tool.py +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/agent/tool_backend/web_fetch/__init__.py +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/agent/tool_backend/web_fetch/answering.py +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/agent/tool_backend/web_fetch/documents.py +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/agent/tool_backend/web_fetch/extractors.py +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/agent/tool_backend/workflow_tool.py +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/agent/utils/commands.py +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/agent/volatile_context.py +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/auth/__init__.py +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/auth/_jwt.py +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/auth/chatgpt_oauth.py +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/auth/constants.py +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/auth/tokens.py +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/browser_extension/__init__.py +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/browser_extension/framing.py +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/browser_extension/installer.py +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/browser_extension/manager.py +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/browser_extension/multiplex.py +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/browser_extension/native_host.py +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/browser_extension/protocol.py +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/browser_extension/registry.py +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/browser_extension/runtime.py +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/cli/__init__.py +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/cli/browser_backend.py +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/cli/clipboard_image.py +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/cli/config.py +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/cli/connection.py +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/cli/cron.py +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/cli/diagnostics.py +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/cli/file_index.py +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/cli/goal.py +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/cli/loop.py +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/cli/mentions.py +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/cli/model_catalog.py +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/cli/plan_artifacts.py +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/cli/provider_registry.py +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/cli/session_event_store.py +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/cli/session_journal.py +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/cli/settings.py +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/cli/skills.py +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/cli/slash_commands.py +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/cli/theme.py +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/cli/tui/__init__.py +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/cli/tui/changes_screen.py +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/cli/tui/command_handlers.py +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/cli/tui/constants.py +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/cli/tui/custom_model.py +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/cli/tui/memory_screen.py +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/cli/tui/prompt_flows.py +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/cli/tui/settings_screen.py +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/cli/tui/state.py +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/cli/tui/sub_agent_screen.py +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/cli/tui/terminal_display.py +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/cli/updater.py +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/config.py +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/events.py +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/git_env.py +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/hooks/__init__.py +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/hooks/backends.py +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/hooks/config.py +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/hooks/dispatcher.py +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/hooks/events.py +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/hooks/matcher.py +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/hooks/outcome.py +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/llm/exceptions.py +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/llm/providers/__init__.py +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/llm/providers/_token_encoding.py +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/llm/providers/base.py +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/llm/providers/chatgpt_oauth.py +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/llm/providers/models.py +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/llm/providers/openai_responses.py +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/llm/ratelimit.py +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/llm/specs/catalog/__init__.py +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/llm/specs/catalog/anthropic.py +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/llm/specs/catalog/dashscope.py +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/llm/specs/catalog/google.py +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/llm/specs/catalog/kimi_coding.py +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/llm/specs/catalog/moonshot.py +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/llm/specs/catalog/ollama_cloud.py +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/llm/specs/catalog/openai.py +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/llm/specs/catalog/openai_chatgpt.py +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/llm/specs/catalog/openrouter.py +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/llm/specs/catalog/together.py +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/llm/specs/catalog/xai.py +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/llm/specs/catalog/zai.py +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/llm/specs/openrouter_catalog.py +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/llm/specs/thinking.py +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/llm/specs/types.py +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/llm/timeouts.py +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/llm/tool_execution_ids.py +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/local_state.py +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/mcp/__init__.py +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/mcp/config.py +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/mcp/oauth.py +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/mcp/service.py +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/mcp/state.py +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/mcp/tools.py +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/mcp/transport.py +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/memory/__init__.py +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/memory/identity.py +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/memory/manager.py +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/memory/manifest.py +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/memory/markdown.py +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/memory/models.py +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/memory/protocol.py +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/memory/registry.py +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/models/__init__.py +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/models/sandbox_terminal_state.py +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/permissions.py +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/runtime.py +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/sandbox/README.md +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/sandbox/__init__.py +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/sandbox/async_filesystem.py +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/sandbox/base.py +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/sandbox/browser.py +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/sandbox/event_loop.py +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/sandbox/filesystem.py +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/sandbox/local.py +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/sandbox/serializer.py +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/sandbox/utils.py +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/scratchpad.py +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/security/__init__.py +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/security/secrets.py +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/services/browser.py +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/services/file_system.py +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/services/html.py +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/services/lsp/__init__.py +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/services/lsp/client.py +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/services/lsp/config.py +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/services/lsp/detector.py +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/services/lsp/diagnostics.py +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/services/lsp/edits.py +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/services/lsp/manager.py +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/services/lsp/registry.py +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/services/lsp/registry.yaml +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/services/snapshots.py +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/services/terminal_buffer.py +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/services/workspace_scan.py +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/session/__init__.py +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/session/control.py +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/session/inmemory.py +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/session/projection.py +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/session/recording.py +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/session/runtime.py +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/session/store.py +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/testing/__init__.py +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/testing/store_conformance.py +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/tools/__init__.py +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/tools/definitions.py +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/tools/registry.py +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/utils/__init__.py +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/utils/images.py +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/web/__init__.py +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/web/assets/fold.js +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/web/assets/player.css +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/web/assets/player.html +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/web/assets/player.js +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/web/bundle.py +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/web/hosting.py +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/web/redaction.py +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/web/server.py +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/web/singlefile.py +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/web/theme_css.py +0 -0
- {kolega_code-0.26.7 → kolega_code-0.26.8}/kolega_code/worktrees.py +0 -0
|
@@ -6,6 +6,72 @@ This project uses GitHub Releases for detailed generated release notes. This fil
|
|
|
6
6
|
|
|
7
7
|
## Unreleased
|
|
8
8
|
|
|
9
|
+
## 0.26.8 - 2026-08-03
|
|
10
|
+
|
|
11
|
+
### Added
|
|
12
|
+
|
|
13
|
+
- Completed model messages now carry normalized token usage across supported
|
|
14
|
+
providers. Session usage is persisted across resume, exported with provider
|
|
15
|
+
and model breakdowns, and shown in a dedicated Usage card on the Status tab.
|
|
16
|
+
- `kolega-code ask --json` now emits complete, replay-safe messages instead of
|
|
17
|
+
streaming prose chunks, including normalized usage and an explicit final
|
|
18
|
+
summary.
|
|
19
|
+
- Detached background terminal sessions now keep stdin open, so callers can
|
|
20
|
+
send multiple inputs to long-running processes with `write_stdin`.
|
|
21
|
+
|
|
22
|
+
### Changed
|
|
23
|
+
|
|
24
|
+
- Build and ask agents now share stronger act-first and independent-verification
|
|
25
|
+
guidance. Silent reasoning-only turns are retried with escalating prompts,
|
|
26
|
+
and visible responses cut off at the output limit are asked to continue.
|
|
27
|
+
- Tool dispatch accepts common parameter aliases for `exec_command`, `eval`,
|
|
28
|
+
and `find_files_by_pattern`, while canonical arguments still take precedence.
|
|
29
|
+
- Turn status now appears immediately while checkpoints are prepared, and
|
|
30
|
+
session-diff baseline/checkpoint work is asynchronous and caches unchanged
|
|
31
|
+
files for faster turns.
|
|
32
|
+
- Switching between Plan and Build with existing history now gives the model a
|
|
33
|
+
hidden toolset-change notice so it does not attempt tools from the old mode.
|
|
34
|
+
- Web connection failures now distinguish unreachable hosts, TLS failures,
|
|
35
|
+
rate limits, and retryable errors, with guidance that reflects whether
|
|
36
|
+
outbound access is available.
|
|
37
|
+
|
|
38
|
+
### Fixed
|
|
39
|
+
|
|
40
|
+
- Installing on an Intel Mac no longer fails with a `cryptography` source-build
|
|
41
|
+
error (`Failed to build cryptography==50.0.0` / missing OpenSSL). cryptography
|
|
42
|
+
49+ stopped publishing Intel-mac wheels, so the installer tried to compile it
|
|
43
|
+
with Rust and OpenSSL; Intel Macs now install the last release that ships a
|
|
44
|
+
prebuilt universal2 wheel. Other platforms are unaffected.
|
|
45
|
+
- DeepSeek requests now always carry an explicit output-token cap (64000, on
|
|
46
|
+
every provider that serves DeepSeek models: first-party, Fireworks, Ollama
|
|
47
|
+
Cloud, OpenRouter). DeepSeek's real per-response ceiling is ~64k — far below
|
|
48
|
+
its published 384000 — and a server-enforced cutoff is reported as a clean
|
|
49
|
+
finish, so long reasoning runs were being truncated silently mid-word. An
|
|
50
|
+
explicit client cap is enforced and reported honestly, so truncation now
|
|
51
|
+
surfaces as a real `max_tokens` stop the agent loop can react to.
|
|
52
|
+
- The Responses API stream wrapper now captures the terminal
|
|
53
|
+
`response.incomplete` event, so a response truncated at `max_output_tokens`
|
|
54
|
+
reports stop reason `max_tokens` (and keeps its usage/billing metadata)
|
|
55
|
+
instead of looking like a clean `end_turn` with no usage.
|
|
56
|
+
- A reply cut off at the output-token limit mid-message is no longer delivered
|
|
57
|
+
as-is: the agent asks the model to continue (up to 3 escalating continuation
|
|
58
|
+
prompts, mirroring the silent-turn guard), and only finalizes with the
|
|
59
|
+
partial output if the reply is still truncated after that.
|
|
60
|
+
- The non-streaming chat `generate()` path now maps `finish_reason` (it lives
|
|
61
|
+
on the choice, not the message), so its responses carry a real stop reason
|
|
62
|
+
instead of `None`.
|
|
63
|
+
- Quitting while a question or approval is pending no longer raises a Textual
|
|
64
|
+
teardown traceback.
|
|
65
|
+
- JavaScript eval kernels no longer wait for orphaned cell timers during
|
|
66
|
+
shutdown.
|
|
67
|
+
|
|
68
|
+
### Removed
|
|
69
|
+
|
|
70
|
+
- The `KOLEGA_CODE_OPENROUTER_MAX_TOKENS` environment variable. OpenRouter
|
|
71
|
+
requests still send no `max_tokens` by default (it acts as a routing filter
|
|
72
|
+
on the gateway), except DeepSeek models, which now always send the honest
|
|
73
|
+
clamped cap.
|
|
74
|
+
|
|
9
75
|
## 0.26.7 - 2026-08-03
|
|
10
76
|
|
|
11
77
|
### Fixed
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: kolega-code
|
|
3
|
-
Version: 0.26.
|
|
3
|
+
Version: 0.26.8
|
|
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
|
|
@@ -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
|
|
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
|
-
|
|
1055
|
-
|
|
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=
|
|
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
|
-
|
|
1409
|
-
|
|
1410
|
-
|
|
1411
|
-
|
|
1412
|
-
|
|
1413
|
-
|
|
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
|
-
|
|
1998
|
-
|
|
1999
|
-
|
|
2000
|
-
|
|
2001
|
-
|
|
2002
|
-
|
|
2003
|
-
|
|
2004
|
-
|
|
2005
|
-
|
|
2006
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
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()
|
|
@@ -75,6 +75,10 @@ class Telemetry:
|
|
|
75
75
|
user_email: Optional[str] = None
|
|
76
76
|
usage_recorder: Optional[Any] = None
|
|
77
77
|
sub_agent_recorder: Optional[Any] = None
|
|
78
|
+
# Process-wide runtime usage accounting (kolega_code/llm/ledger.py). Unlike
|
|
79
|
+
# the recorders above it does not require Langfuse: it reaches the plain
|
|
80
|
+
# LLMClient too.
|
|
81
|
+
usage_ledger: Optional[Any] = None
|
|
78
82
|
|
|
79
83
|
|
|
80
84
|
@dataclass
|
|
@@ -122,6 +126,7 @@ class AgentContext:
|
|
|
122
126
|
user_email=self.telemetry.user_email,
|
|
123
127
|
usage_recorder=self.telemetry.usage_recorder,
|
|
124
128
|
token_manager=self.config.get_chatgpt_token_manager(),
|
|
129
|
+
usage_ledger=self.telemetry.usage_ledger,
|
|
125
130
|
)
|
|
126
131
|
|
|
127
132
|
return LLMClient(
|
|
@@ -132,4 +137,5 @@ class AgentContext:
|
|
|
132
137
|
requests_per_minute=model_config.rate_limits.requests_per_minute,
|
|
133
138
|
tokens_per_minute=model_config.rate_limits.tokens_per_minute,
|
|
134
139
|
token_manager=self.config.get_chatgpt_token_manager(),
|
|
140
|
+
usage_ledger=self.telemetry.usage_ledger,
|
|
135
141
|
)
|
|
@@ -163,6 +163,7 @@ def _message_with_content(message: Message, content: List[Any]) -> Message:
|
|
|
163
163
|
stop_reason=message.stop_reason,
|
|
164
164
|
tool_calls=tool_calls,
|
|
165
165
|
usage_metadata=message.usage_metadata,
|
|
166
|
+
usage=message.usage,
|
|
166
167
|
)
|
|
167
168
|
|
|
168
169
|
|
|
@@ -699,6 +700,7 @@ class Conversation:
|
|
|
699
700
|
stop_reason=message.stop_reason,
|
|
700
701
|
tool_calls=message.tool_calls,
|
|
701
702
|
usage_metadata=message.usage_metadata,
|
|
703
|
+
usage=message.usage,
|
|
702
704
|
)
|
|
703
705
|
|
|
704
706
|
self.history.append(message)
|
|
@@ -384,6 +384,7 @@ class CustomAgent(BaseAgent):
|
|
|
384
384
|
permission_mode: Optional[Any] = None,
|
|
385
385
|
permission_callback: Optional[Any] = None,
|
|
386
386
|
usage_recorder: Optional[Any] = None,
|
|
387
|
+
usage_ledger: Optional[Any] = None,
|
|
387
388
|
sub_agent_recorder: Optional[Any] = None,
|
|
388
389
|
hook_dispatcher: Optional[Any] = None,
|
|
389
390
|
max_iterations: Optional[int] = None,
|
|
@@ -419,6 +420,7 @@ class CustomAgent(BaseAgent):
|
|
|
419
420
|
permission_mode=permission_mode,
|
|
420
421
|
permission_callback=permission_callback,
|
|
421
422
|
usage_recorder=usage_recorder,
|
|
423
|
+
usage_ledger=usage_ledger,
|
|
422
424
|
sub_agent_recorder=sub_agent_recorder,
|
|
423
425
|
hook_dispatcher=hook_dispatcher,
|
|
424
426
|
max_iterations=definition.max_iterations if definition.max_iterations is not None else max_iterations,
|
|
@@ -184,8 +184,9 @@ class BaseKernel:
|
|
|
184
184
|
try:
|
|
185
185
|
if proc.stdin is not None:
|
|
186
186
|
proc.stdin.write(encode_frame({"type": "exit"}))
|
|
187
|
-
|
|
188
|
-
|
|
187
|
+
proc.stdin.close()
|
|
188
|
+
await asyncio.wait_for(proc.stdin.wait_closed(), timeout=timeout)
|
|
189
|
+
except (BrokenPipeError, ConnectionError, RuntimeError, asyncio.TimeoutError):
|
|
189
190
|
pass
|
|
190
191
|
try:
|
|
191
192
|
await asyncio.wait_for(proc.wait(), timeout=timeout)
|
|
@@ -305,7 +305,14 @@ async function main() {
|
|
|
305
305
|
}
|
|
306
306
|
}
|
|
307
307
|
|
|
308
|
-
main()
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
308
|
+
main()
|
|
309
|
+
.then(() => {
|
|
310
|
+
// Exit explicitly: an interrupted cell can leave timers or sockets in the
|
|
311
|
+
// event loop that would otherwise keep the process alive after the host
|
|
312
|
+
// asked it to exit. Flush stdout first so no result frame is truncated.
|
|
313
|
+
process.stdout.write("", () => process.exit(0));
|
|
314
|
+
})
|
|
315
|
+
.catch((err) => {
|
|
316
|
+
emitError(CURRENT.id, err);
|
|
317
|
+
process.exit(1);
|
|
318
|
+
});
|