kolega-code 0.7.0__tar.gz → 0.7.2__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.7.0 → kolega_code-0.7.2}/.env.example +3 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/PKG-INFO +9 -1
- {kolega_code-0.7.0 → kolega_code-0.7.2}/README.md +8 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/RELEASING.md +6 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/docs/astro.config.mjs +4 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/docs/src/content/docs/configuration/providers-and-models.mdx +1 -0
- kolega_code-0.7.2/docs/src/content/docs/configuration/sign-in-with-chatgpt.mdx +93 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/docs/src/content/docs/hooks.md +1 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/docs/src/content/docs/tui/slash-commands.md +6 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/__init__.py +1 -1
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/agent/__init__.py +1 -1
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/agent/baseagent.py +63 -34
- kolega_code-0.7.2/kolega_code/agent/compression.py +146 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/agent/context.py +2 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/agent/conversation.py +131 -20
- kolega_code-0.7.2/kolega_code/agent/prompt_templates/auxiliary/compression/summary.system.md +28 -0
- kolega_code-0.7.2/kolega_code/agent/prompt_templates/auxiliary/compression/summary.user.md.j2 +17 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/agent/prompts.py +7 -3
- kolega_code-0.7.2/kolega_code/agent/tests/compaction_helpers.py +189 -0
- kolega_code-0.7.2/kolega_code/agent/tests/llm/test_chatgpt_live.py +101 -0
- kolega_code-0.7.2/kolega_code/agent/tests/llm/test_chatgpt_oauth_provider.py +365 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/agent/tests/llm/test_live_providers.py +5 -1
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/agent/tests/test_base_agent.py +75 -68
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/agent/tests/test_commands.py +51 -5
- kolega_code-0.7.2/kolega_code/agent/tests/test_compaction_integration.py +66 -0
- kolega_code-0.7.2/kolega_code/agent/tests/test_compaction_persistence.py +43 -0
- kolega_code-0.7.2/kolega_code/agent/tests/test_compaction_subagent.py +26 -0
- kolega_code-0.7.2/kolega_code/agent/tests/test_compaction_tui_events.py +98 -0
- kolega_code-0.7.2/kolega_code/agent/tests/test_compress_command.py +41 -0
- kolega_code-0.7.2/kolega_code/agent/tests/test_compression.py +143 -0
- kolega_code-0.7.2/kolega_code/agent/tests/test_conversation_compaction.py +192 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/agent/tests/test_prompts.py +1 -1
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/agent/tests/tool_backend/test_think_hard_streaming.py +1 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/agent/tool_backend/search_backends/firecrawl.py +10 -1
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/agent/tool_backend/terminal_tool.py +1 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/agent/tool_backend/think_hard_tool.py +2 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/agent/tool_backend/web_fetch_tool.py +1 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/agent/utils/commands.py +26 -6
- kolega_code-0.7.2/kolega_code/auth/__init__.py +17 -0
- kolega_code-0.7.2/kolega_code/auth/_jwt.py +53 -0
- kolega_code-0.7.2/kolega_code/auth/chatgpt_oauth.py +222 -0
- kolega_code-0.7.2/kolega_code/auth/constants.py +67 -0
- kolega_code-0.7.2/kolega_code/auth/tests/test_chatgpt_oauth.py +172 -0
- kolega_code-0.7.2/kolega_code/auth/tests/test_tokens.py +134 -0
- kolega_code-0.7.2/kolega_code/auth/tokens.py +170 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/cli/app.py +317 -23
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/cli/config.py +88 -8
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/cli/main.py +3 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/cli/messages.py +15 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/cli/provider_registry.py +12 -2
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/cli/session_store.py +3 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/cli/settings.py +41 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/cli/slash_commands.py +2 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/cli/tests/test_app.py +761 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/cli/tests/test_cli_config.py +25 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/cli/tests/test_session_store.py +27 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/cli/tests/test_settings.py +70 -1
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/config.py +45 -4
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/events.py +20 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/hooks/events.py +1 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/llm/client.py +19 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/llm/instrumented_client.py +2 -1
- kolega_code-0.7.2/kolega_code/llm/providers/chatgpt_oauth.py +501 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/llm/specs.py +70 -4
- kolega_code-0.7.2/kolega_code/tools/tests/__init__.py +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/pyproject.toml +1 -1
- {kolega_code-0.7.0 → kolega_code-0.7.2}/uv.lock +2 -2
- kolega_code-0.7.0/kolega_code/agent/compression.py +0 -81
- kolega_code-0.7.0/kolega_code/agent/prompt_templates/auxiliary/compression/summary.system.md +0 -59
- kolega_code-0.7.0/kolega_code/agent/prompt_templates/auxiliary/compression/summary.user.md.j2 +0 -18
- {kolega_code-0.7.0 → kolega_code-0.7.2}/.github/workflows/ci.yml +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/.github/workflows/docs.yml +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/.github/workflows/release.yml +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/.gitignore +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/CONTRIBUTING.md +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/LICENSE +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/SECURITY.md +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/conftest.py +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/docs/.gitignore +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/docs/README.md +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/docs/package-lock.json +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/docs/package.json +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/docs/public/favicon.svg +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/docs/src/assets/demo.gif +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/docs/src/assets/kolega-dark.svg +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/docs/src/assets/kolega-light.svg +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/docs/src/content/docs/cli/ask.md +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/docs/src/content/docs/cli/doctor.md +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/docs/src/content/docs/cli/overview.md +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/docs/src/content/docs/cli/sessions.md +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/docs/src/content/docs/concepts/agents.md +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/docs/src/content/docs/concepts/how-it-works.md +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/docs/src/content/docs/concepts/tools.md +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/docs/src/content/docs/configuration/environment-variables.md +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/docs/src/content/docs/configuration/settings-and-api-keys.mdx +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/docs/src/content/docs/getting-started/installation.mdx +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/docs/src/content/docs/getting-started/quick-start.mdx +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/docs/src/content/docs/gigacode.mdx +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/docs/src/content/docs/index.mdx +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/docs/src/content/docs/skills.mdx +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/docs/src/content/docs/tui/composer.md +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/docs/src/content/docs/tui/interface.md +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/docs/src/content/docs/tui/modes.md +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/docs/src/content/docs/tui/sessions-and-resume.md +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/docs/src/content.config.ts +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/docs/src/styles/brand.css +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/docs/tsconfig.json +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/agent/browseragent.py +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/agent/coder.py +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/agent/common.py +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/agent/generalagent.py +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/agent/investigationagent.py +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/agent/orchestration/__init__.py +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/agent/orchestration/budget.py +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/agent/orchestration/errors.py +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/agent/orchestration/executor.py +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/agent/orchestration/guide.py +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/agent/orchestration/journal.py +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/agent/orchestration/runtime.py +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/agent/orchestration/tests/__init__.py +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/agent/orchestration/tests/test_orchestration.py +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/agent/orchestration/types.py +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/agent/planningagent.py +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/agent/prompt_provider.py +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/agent/prompt_templates/auxiliary/terminal/output_summary.system.md +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/agent/prompt_templates/auxiliary/terminal/safety.system.md +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/agent/prompt_templates/auxiliary/tools/think_hard.system.md +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/agent/prompt_templates/extensions/cli/planning_questions.md +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/agent/prompt_templates/extensions/cli/shared_task_list.md +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/agent/prompt_templates/extensions/skills/catalog.md.j2 +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/agent/prompt_templates/system/agents/browser.md.j2 +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/agent/prompt_templates/system/agents/coder_cli.md.j2 +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/agent/prompt_templates/system/agents/general.md.j2 +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/agent/prompt_templates/system/agents/investigation.md.j2 +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/agent/prompt_templates/system/agents/planning.md.j2 +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/agent/prompt_templates/system/includes/agents_md_instructions.md +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/agent/prompt_templates/system/includes/environment_variables/workspace_env_vars.md +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/agent/prompt_templates/system/includes/frontend_guidance.md +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/agent/prompt_templates/system/includes/starter_templates/expo.md +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/agent/prompt_templates/system/includes/starter_templates/html_website.md +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/agent/prompt_templates/system/includes/starter_templates/mern_stack.md +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/agent/prompt_templates/system/includes/starter_templates/react_vite_shadcdn.md +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/agent/prompt_templates/user_tasks/cli/implement_plan.md.j2 +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/agent/prompt_templates/user_tasks/cli/init_agents.md.j2 +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/agent/tests/__init__.py +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/agent/tests/llm/__init__.py +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/agent/tests/llm/test_anthropic_token_counting.py +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/agent/tests/llm/test_billing_openai_cache.py +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/agent/tests/llm/test_client.py +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/agent/tests/llm/test_dashscope_mapping.py +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/agent/tests/llm/test_error_boundary.py +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/agent/tests/llm/test_exceptions.py +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/agent/tests/llm/test_google_thought_signature.py +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/agent/tests/llm/test_google_tool_signature_live.py +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/agent/tests/llm/test_instrumented_client.py +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/agent/tests/llm/test_instrumented_client_integration.py +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/agent/tests/llm/test_langfuse_normalization.py +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/agent/tests/llm/test_model_specs.py +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/agent/tests/llm/test_openai_cached_tokens.py +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/agent/tests/llm/test_openai_cached_tokens_stream.py +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/agent/tests/llm/test_openai_message_conversion.py +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/agent/tests/llm/test_openai_token_counting.py +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/agent/tests/llm/test_thinking_effort.py +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/agent/tests/llm/test_tool_execution_ids.py +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/agent/tests/services/__init__.py +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/agent/tests/services/test_browser.py +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/agent/tests/services/test_browser_parity.py +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/agent/tests/services/test_file_system.py +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/agent/tests/services/test_sandbox_terminal_input.py +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/agent/tests/services/test_terminal.py +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/agent/tests/services/test_terminal_buffer.py +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/agent/tests/services/test_terminal_state_serializer.py +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/agent/tests/test_agent_tools_inventory.py +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/agent/tests/test_coder_attachments.py +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/agent/tests/test_coder_prompt_extensions.py +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/agent/tests/test_duplicate_tool_results.py +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/agent/tests/test_empty_message_handling.py +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/agent/tests/test_event_emitter.py +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/agent/tests/test_general_agent.py +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/agent/tests/test_gigacode_gating.py +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/agent/tests/test_hooks_integration.py +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/agent/tests/test_html.py +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/agent/tests/test_parallel_tool_calls.py +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/agent/tests/test_permissions.py +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/agent/tests/test_planning_agent.py +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/agent/tests/test_prompt_provider.py +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/agent/tests/test_tool_registry.py +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/agent/tests/test_tools.py +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/agent/tests/tool_backend/__init__.py +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/agent/tests/tool_backend/test_agent_tool.py +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/agent/tests/tool_backend/test_base_tool.py +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/agent/tests/tool_backend/test_browser_tool.py +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/agent/tests/tool_backend/test_build_tool.py +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/agent/tests/tool_backend/test_create_file_tool.py +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/agent/tests/tool_backend/test_edit_preview.py +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/agent/tests/tool_backend/test_glob_tool.py +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/agent/tests/tool_backend/test_glob_tool_sandbox_parity.py +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/agent/tests/tool_backend/test_list_directory_tool.py +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/agent/tests/tool_backend/test_read_file_tool.py +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/agent/tests/tool_backend/test_replace_entire_file_tool.py +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/agent/tests/tool_backend/test_replace_lines_tool.py +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/agent/tests/tool_backend/test_search_and_replace_tool.py +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/agent/tests/tool_backend/test_search_codebase_tool.py +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/agent/tests/tool_backend/test_terminal_tool.py +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/agent/tests/tool_backend/test_think_hard_integration.py +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/agent/tests/tool_backend/test_web_fetch_tool.py +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/agent/tests/tool_backend/test_web_search_tool.py +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/agent/tests/tool_backend/test_workflow_tool.py +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/agent/tool_backend/agent_tool.py +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/agent/tool_backend/base_tool.py +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/agent/tool_backend/browser_tool.py +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/agent/tool_backend/build_tool.py +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/agent/tool_backend/create_file_tool.py +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/agent/tool_backend/edit_preview.py +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/agent/tool_backend/glob_tool.py +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/agent/tool_backend/list_directory_tool.py +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/agent/tool_backend/memory_tool.py +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/agent/tool_backend/read_file_tool.py +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/agent/tool_backend/replace_entire_file_tool.py +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/agent/tool_backend/replace_lines_tool.py +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/agent/tool_backend/search_and_replace_tool.py +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/agent/tool_backend/search_backends/__init__.py +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/agent/tool_backend/search_backends/base.py +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/agent/tool_backend/search_backends/duckduckgo.py +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/agent/tool_backend/search_backends/errors.py +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/agent/tool_backend/search_backends/models.py +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/agent/tool_backend/search_backends/searxng.py +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/agent/tool_backend/search_backends/tavily.py +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/agent/tool_backend/search_codebase_tool.py +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/agent/tool_backend/streaming_tool.py +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/agent/tool_backend/web_search_tool.py +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/agent/tool_backend/workflow_tool.py +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/agent/tools.py +0 -0
- {kolega_code-0.7.0/kolega_code/hooks → kolega_code-0.7.2/kolega_code/auth}/tests/__init__.py +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/cli/__init__.py +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/cli/connection.py +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/cli/file_index.py +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/cli/mentions.py +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/cli/skills.py +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/cli/tests/__init__.py +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/cli/tests/test_connection.py +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/cli/tests/test_file_index.py +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/cli/tests/test_main.py +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/cli/tests/test_mentions.py +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/cli/tests/test_skills.py +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/cli/tests/test_slash_commands.py +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/cli/tests/test_themes.py +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/cli/tests/test_updater.py +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/cli/theme.py +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/cli/updater.py +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/hooks/__init__.py +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/hooks/backends.py +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/hooks/config.py +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/hooks/dispatcher.py +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/hooks/matcher.py +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/hooks/outcome.py +0 -0
- {kolega_code-0.7.0/kolega_code/llm/providers → kolega_code-0.7.2/kolega_code/hooks/tests}/__init__.py +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/hooks/tests/test_hooks.py +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/llm/exceptions.py +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/llm/models.py +0 -0
- {kolega_code-0.7.0/kolega_code/tools/tests → kolega_code-0.7.2/kolega_code/llm/providers}/__init__.py +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/llm/providers/anthropic.py +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/llm/providers/base.py +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/llm/providers/google.py +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/llm/providers/models.py +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/llm/providers/openai.py +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/llm/ratelimit.py +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/llm/tool_execution_ids.py +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/models/__init__.py +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/models/sandbox_terminal_state.py +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/permissions.py +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/runtime.py +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/sandbox/README.md +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/sandbox/__init__.py +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/sandbox/async_filesystem.py +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/sandbox/base.py +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/sandbox/browser.py +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/sandbox/event_loop.py +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/sandbox/filesystem.py +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/sandbox/local.py +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/sandbox/serializer.py +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/sandbox/terminal.py +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/sandbox/utils.py +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/services/base.py +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/services/browser.py +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/services/file_system.py +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/services/html.py +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/services/terminal.py +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/services/terminal_buffer.py +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/tools/__init__.py +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/tools/core.py +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/tools/definitions.py +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/tools/registry.py +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/kolega_code/tools/tests/test_definitions.py +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/run_tests.sh +0 -0
- {kolega_code-0.7.0 → kolega_code-0.7.2}/scripts/install-kolega-code.sh +0 -0
|
@@ -3,6 +3,9 @@
|
|
|
3
3
|
|
|
4
4
|
ANTHROPIC_API_KEY=
|
|
5
5
|
OPENAI_API_KEY=
|
|
6
|
+
# Prefer a ChatGPT subscription over an OpenAI API key? Run `/login` in the TUI
|
|
7
|
+
# (no key needed). Optional override of the OAuth client id, for testing only:
|
|
8
|
+
# KOLEGA_CODE_CHATGPT_CLIENT_ID=
|
|
6
9
|
GOOGLE_API_KEY=
|
|
7
10
|
MOONSHOT_API_KEY=
|
|
8
11
|
DEEPSEEK_API_KEY=
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: kolega-code
|
|
3
|
-
Version: 0.7.
|
|
3
|
+
Version: 0.7.2
|
|
4
4
|
Summary: Local-first AI coding agent for the terminal
|
|
5
5
|
Project-URL: Homepage, https://kolega-ai.github.io/kolega-code/
|
|
6
6
|
Project-URL: Documentation, https://kolega-ai.github.io/kolega-code/
|
|
@@ -176,6 +176,14 @@ and DeepSeek — and lets you assign **different models to different roles**: a
|
|
|
176
176
|
long-context model for coding, a fast cheap model for small utility calls, and one for extended
|
|
177
177
|
"thinking". See [Providers & Models](https://kolega-ai.github.io/kolega-code/configuration/providers-and-models/).
|
|
178
178
|
|
|
179
|
+
## Sign in with ChatGPT
|
|
180
|
+
|
|
181
|
+
If you have a paid **ChatGPT** plan (Plus, Pro, or Business), you can use it to run OpenAI models
|
|
182
|
+
instead of a separate API key. Run `/login chatgpt` in the TUI, complete the browser sign-in, and
|
|
183
|
+
Kolega Code switches to the **OpenAI (ChatGPT subscription)** provider (default `gpt-5.5`). Tokens are
|
|
184
|
+
stored locally (chmod `600`) and refreshed automatically; `/logout chatgpt` removes them. See
|
|
185
|
+
[Sign in with ChatGPT](https://kolega-ai.github.io/kolega-code/configuration/sign-in-with-chatgpt/).
|
|
186
|
+
|
|
179
187
|
## Configuration
|
|
180
188
|
|
|
181
189
|
Set your provider, model, and API keys from the **Settings** tab in the UI, or via environment
|
|
@@ -103,6 +103,14 @@ and DeepSeek — and lets you assign **different models to different roles**: a
|
|
|
103
103
|
long-context model for coding, a fast cheap model for small utility calls, and one for extended
|
|
104
104
|
"thinking". See [Providers & Models](https://kolega-ai.github.io/kolega-code/configuration/providers-and-models/).
|
|
105
105
|
|
|
106
|
+
## Sign in with ChatGPT
|
|
107
|
+
|
|
108
|
+
If you have a paid **ChatGPT** plan (Plus, Pro, or Business), you can use it to run OpenAI models
|
|
109
|
+
instead of a separate API key. Run `/login chatgpt` in the TUI, complete the browser sign-in, and
|
|
110
|
+
Kolega Code switches to the **OpenAI (ChatGPT subscription)** provider (default `gpt-5.5`). Tokens are
|
|
111
|
+
stored locally (chmod `600`) and refreshed automatically; `/logout chatgpt` removes them. See
|
|
112
|
+
[Sign in with ChatGPT](https://kolega-ai.github.io/kolega-code/configuration/sign-in-with-chatgpt/).
|
|
113
|
+
|
|
106
114
|
## Configuration
|
|
107
115
|
|
|
108
116
|
Set your provider, model, and API keys from the **Settings** tab in the UI, or via environment
|
|
@@ -20,6 +20,12 @@ release branch.
|
|
|
20
20
|
2. Update `pyproject.toml`, `uv.lock`, and package `__version__` values to the
|
|
21
21
|
release version.
|
|
22
22
|
|
|
23
|
+
Running `uv lock` advances the `exclude-newer` cutoff recorded in `uv.lock`,
|
|
24
|
+
because `pyproject.toml` sets `exclude-newer = "1 week"` as a relative
|
|
25
|
+
duration. The cutoff timestamp moving forward, and any dependency versions
|
|
26
|
+
released within the new one-week window being pulled in, is expected and
|
|
27
|
+
acceptable. Do not revert these changes.
|
|
28
|
+
|
|
23
29
|
3. Run the fast test suite:
|
|
24
30
|
|
|
25
31
|
```bash
|
|
@@ -56,6 +56,10 @@ export default defineConfig({
|
|
|
56
56
|
label: "Providers & Models",
|
|
57
57
|
slug: "configuration/providers-and-models",
|
|
58
58
|
},
|
|
59
|
+
{
|
|
60
|
+
label: "Sign in with ChatGPT",
|
|
61
|
+
slug: "configuration/sign-in-with-chatgpt",
|
|
62
|
+
},
|
|
59
63
|
{
|
|
60
64
|
label: "Settings & API Keys",
|
|
61
65
|
slug: "configuration/settings-and-api-keys",
|
{kolega_code-0.7.0 → kolega_code-0.7.2}/docs/src/content/docs/configuration/providers-and-models.mdx
RENAMED
|
@@ -16,6 +16,7 @@ The agent runtime recognizes these providers:
|
|
|
16
16
|
| --- | --- | --- |
|
|
17
17
|
| Anthropic | `anthropic` | `ANTHROPIC_API_KEY` |
|
|
18
18
|
| OpenAI | `openai` | `OPENAI_API_KEY` |
|
|
19
|
+
| OpenAI (ChatGPT subscription) | `openai_chatgpt` | _none — [sign in with ChatGPT](../sign-in-with-chatgpt/)_ |
|
|
19
20
|
| Google | `google` | `GOOGLE_API_KEY` |
|
|
20
21
|
| Groq | `groq` | `GROQ_API_KEY` |
|
|
21
22
|
| Together.ai | `together` | `TOGETHER_API_KEY` |
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Sign in with ChatGPT
|
|
3
|
+
description: Use your ChatGPT subscription to run OpenAI models in Kolega Code, without an API key.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
import { Aside, Steps } from '@astrojs/starlight/components';
|
|
7
|
+
|
|
8
|
+
If you have a paid **ChatGPT** plan, you can use it to run OpenAI models in Kolega
|
|
9
|
+
Code — no separate `OPENAI_API_KEY` required. Sign in once with `/login chatgpt`
|
|
10
|
+
and Kolega Code uses your subscription for the **OpenAI (ChatGPT subscription)**
|
|
11
|
+
provider.
|
|
12
|
+
|
|
13
|
+
## Eligibility
|
|
14
|
+
|
|
15
|
+
| Plan | Runs models |
|
|
16
|
+
| --- | --- |
|
|
17
|
+
| Plus | Yes |
|
|
18
|
+
| Pro | Yes |
|
|
19
|
+
| Business | Yes |
|
|
20
|
+
| Free | No |
|
|
21
|
+
|
|
22
|
+
A Free plan can sign in, but can't run models this way — use an
|
|
23
|
+
[`OPENAI_API_KEY`](../providers-and-models/) instead.
|
|
24
|
+
|
|
25
|
+
## Signing in
|
|
26
|
+
|
|
27
|
+
<Steps>
|
|
28
|
+
|
|
29
|
+
1. In the TUI composer, run:
|
|
30
|
+
|
|
31
|
+
```text
|
|
32
|
+
/login chatgpt
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
2. Your browser opens to the ChatGPT sign-in page. Complete the sign-in there.
|
|
36
|
+
(If the browser doesn't open, the composer prints a URL you can paste in
|
|
37
|
+
yourself.)
|
|
38
|
+
|
|
39
|
+
3. When sign-in finishes, the browser shows a confirmation page and Kolega Code
|
|
40
|
+
switches to the **OpenAI (ChatGPT subscription)** provider, ready to use.
|
|
41
|
+
|
|
42
|
+
</Steps>
|
|
43
|
+
|
|
44
|
+
## Models
|
|
45
|
+
|
|
46
|
+
The ChatGPT-subscription provider (identifier `openai_chatgpt`) exposes the Codex
|
|
47
|
+
model line-up:
|
|
48
|
+
|
|
49
|
+
| Model | Label |
|
|
50
|
+
| --- | --- |
|
|
51
|
+
| `gpt-5.5` | GPT-5.5 — default, frontier coding and reasoning |
|
|
52
|
+
| `gpt-5.4` | GPT-5.4 — strong everyday coding |
|
|
53
|
+
| `gpt-5.4-mini` | GPT-5.4 Mini — fast and economical |
|
|
54
|
+
| `gpt-5.3-codex-spark` | GPT-5.3 Codex Spark — ultra-fast |
|
|
55
|
+
|
|
56
|
+
Switch between them with [`/model`](../../tui/slash-commands/) or from the
|
|
57
|
+
**Settings** tab. Each model supports a reasoning **thinking effort** you can set
|
|
58
|
+
with [`/effort`](../../tui/slash-commands/).
|
|
59
|
+
|
|
60
|
+
## Where credentials live
|
|
61
|
+
|
|
62
|
+
Sign-in tokens are stored in your `settings.json` under `oauth_tokens`, in the
|
|
63
|
+
same [state directory](../settings-and-api-keys/#where-settings-live) as the rest
|
|
64
|
+
of your settings, with `0600` permissions (readable and writable only by your
|
|
65
|
+
user). They refresh automatically in the background, so a single sign-in keeps
|
|
66
|
+
working across sessions.
|
|
67
|
+
|
|
68
|
+
## Checking status
|
|
69
|
+
|
|
70
|
+
`doctor` reports whether you're signed in, without exposing any token:
|
|
71
|
+
|
|
72
|
+
```bash
|
|
73
|
+
kolega-code doctor --project .
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
For the ChatGPT-subscription provider it shows `signed in as <email> (<plan>)` or
|
|
77
|
+
`not signed in`. See [`doctor`](../../cli/doctor/).
|
|
78
|
+
|
|
79
|
+
## Signing out
|
|
80
|
+
|
|
81
|
+
To remove your stored ChatGPT credentials:
|
|
82
|
+
|
|
83
|
+
```text
|
|
84
|
+
/logout chatgpt
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
After signing out, switch to another provider — or sign in again with
|
|
88
|
+
`/login chatgpt` — to keep working.
|
|
89
|
+
|
|
90
|
+
<Aside type="tip">
|
|
91
|
+
`/login` and `/logout` take a provider name so more sign-in options can be added
|
|
92
|
+
over time. Today, `chatgpt` is the available target.
|
|
93
|
+
</Aside>
|
|
@@ -63,6 +63,7 @@ Both files use the same shape:
|
|
|
63
63
|
| `PreToolUse` | Before a tool runs (after the permission gate) | Denies the tool; the reason is returned to the agent as a tool error, so it can adjust |
|
|
64
64
|
| `PostToolUse` | After a tool succeeds (and on failure) | Ends the turn; the reason is shown as a warning |
|
|
65
65
|
| `PreCompact` | Before the conversation is compacted | Advisory |
|
|
66
|
+
| `PostCompact` | After the conversation is compacted | Advisory; payload reports before/after token counts |
|
|
66
67
|
| `Stop` | The agent is about to finish its turn | Keeps the agent working; the reason becomes its next instruction |
|
|
67
68
|
| `SubagentStop` | A dispatched sub-agent finished | Advisory; can annotate the result the parent sees |
|
|
68
69
|
| `Notification` | A permission prompt is about to be shown | Advisory (desktop notifications, sounds) |
|
|
@@ -40,6 +40,8 @@ These control the app and your session.
|
|
|
40
40
|
| `/permissions` | Show or switch the shell/edit permission mode |
|
|
41
41
|
| `/model` | Choose the active model |
|
|
42
42
|
| `/effort` | Choose the active model's thinking effort |
|
|
43
|
+
| `/login` | Sign in to a provider, e.g. `/login chatgpt` |
|
|
44
|
+
| `/logout` | Sign out of a provider, e.g. `/logout chatgpt` |
|
|
43
45
|
| `/gigacode` | Toggle [gigacode](../../gigacode/) workflow orchestration on or off |
|
|
44
46
|
| `/copy` | Copy the last response to the clipboard |
|
|
45
47
|
| `/version` | Show the Kolega Code version |
|
|
@@ -53,6 +55,10 @@ provider. You can also switch directly with `/model <name>`.
|
|
|
53
55
|
Run `/effort` to open a selectable list of supported effort values for the
|
|
54
56
|
active model. You can also switch directly with `/effort <level>`.
|
|
55
57
|
|
|
58
|
+
Run `/login chatgpt` to sign in with a ChatGPT subscription and use OpenAI models
|
|
59
|
+
without an API key; `/logout chatgpt` removes the stored credentials. See
|
|
60
|
+
[Sign in with ChatGPT](../../configuration/sign-in-with-chatgpt/).
|
|
61
|
+
|
|
56
62
|
Run `/init` to have the agent inspect the repository and create or update a
|
|
57
63
|
concise root `AGENTS.md`. Extra text after the command is passed as focus or
|
|
58
64
|
constraints:
|
|
@@ -11,7 +11,7 @@ from pathlib import Path
|
|
|
11
11
|
from typing import Any, AsyncGenerator, Dict, List, Optional
|
|
12
12
|
|
|
13
13
|
from .common import LogMixin
|
|
14
|
-
from .compression import HistoryCompressor
|
|
14
|
+
from .compression import CompactionResult, HistoryCompressor
|
|
15
15
|
from kolega_code.config import AgentConfig, ModelProvider
|
|
16
16
|
from kolega_code.events import AgentConnectionManager
|
|
17
17
|
from .context import AgentContext, AgentServices, Telemetry, WorkspaceInfo
|
|
@@ -398,6 +398,14 @@ class BaseAgent(LogMixin):
|
|
|
398
398
|
"""Restores the message history from a list of dictionaries using custom methods."""
|
|
399
399
|
self.conversation.restore(serialized_history)
|
|
400
400
|
|
|
401
|
+
def dump_compaction_state(self) -> Dict[str, Any]:
|
|
402
|
+
"""Serialize the compaction boundary (summary + how many leading messages it folds)."""
|
|
403
|
+
return self.conversation.dump_compaction()
|
|
404
|
+
|
|
405
|
+
def restore_compaction_state(self, data: Optional[Dict[str, Any]]) -> None:
|
|
406
|
+
"""Restore the compaction boundary; must be called after restore_message_history."""
|
|
407
|
+
self.conversation.restore_compaction(data)
|
|
408
|
+
|
|
401
409
|
def _sanitize_oversized_tool_results(self) -> int:
|
|
402
410
|
return self.conversation.sanitize_oversized_tool_results()
|
|
403
411
|
|
|
@@ -549,9 +557,12 @@ class BaseAgent(LogMixin):
|
|
|
549
557
|
message=message,
|
|
550
558
|
)
|
|
551
559
|
|
|
552
|
-
async def compress_history(self) ->
|
|
560
|
+
async def compress_history(self) -> CompactionResult:
|
|
553
561
|
"""
|
|
554
|
-
Non-destructively summarize the current history
|
|
562
|
+
Non-destructively summarize the current history, keeping recent turns
|
|
563
|
+
verbatim. Emits a compaction_status event around the work so the UI can
|
|
564
|
+
show progress, then recounts + emits a context_update so the gauge
|
|
565
|
+
refreshes. Returns the structured outcome.
|
|
555
566
|
"""
|
|
556
567
|
|
|
557
568
|
async def on_info(message: str) -> None:
|
|
@@ -560,16 +571,34 @@ class BaseAgent(LogMixin):
|
|
|
560
571
|
async def on_error(message: str) -> None:
|
|
561
572
|
await self.log_error(message, sender=self.agent_name)
|
|
562
573
|
|
|
563
|
-
await self.
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
574
|
+
await self.emitter.compaction_status("started", "Compacting conversation…")
|
|
575
|
+
try:
|
|
576
|
+
result = await self.compressor.summarize(
|
|
577
|
+
self.conversation,
|
|
578
|
+
llm=self.llm,
|
|
579
|
+
model=self.primary_model_config.model,
|
|
580
|
+
temperature=self.model_default_temperature,
|
|
581
|
+
# No extended thinking: a bounded summary doesn't need it, and the
|
|
582
|
+
# thinking budget could otherwise exceed the small summary max_tokens.
|
|
583
|
+
thinking=None,
|
|
584
|
+
on_info=on_info,
|
|
585
|
+
on_error=on_error,
|
|
586
|
+
)
|
|
587
|
+
finally:
|
|
588
|
+
# Recount + emit so the context gauge reflects post-compaction reality
|
|
589
|
+
# (even on a no-op the UI may have been stale).
|
|
590
|
+
await self.count_current_context()
|
|
591
|
+
|
|
592
|
+
phase = "finished" if result.ok else "error"
|
|
593
|
+
summary_text = (
|
|
594
|
+
self.conversation.summary.get_text_content() if result.ok and self.conversation.summary else ""
|
|
572
595
|
)
|
|
596
|
+
await self.emitter.compaction_status(phase, result.message, summary=summary_text)
|
|
597
|
+
return result
|
|
598
|
+
|
|
599
|
+
def clear_history(self) -> None:
|
|
600
|
+
"""Drop all history and reset compaction state."""
|
|
601
|
+
self.conversation.clear()
|
|
573
602
|
|
|
574
603
|
# ------------------------------------------------------------------
|
|
575
604
|
# Tool execution
|
|
@@ -936,6 +965,7 @@ class BaseAgent(LogMixin):
|
|
|
936
965
|
max_retries=model_config.rate_limits.max_retries,
|
|
937
966
|
requests_per_minute=model_config.rate_limits.requests_per_minute,
|
|
938
967
|
tokens_per_minute=model_config.rate_limits.tokens_per_minute,
|
|
968
|
+
token_manager=self.config.get_chatgpt_token_manager(),
|
|
939
969
|
)
|
|
940
970
|
response = await client.generate(
|
|
941
971
|
model=model_config.model,
|
|
@@ -1135,9 +1165,8 @@ class BaseAgent(LogMixin):
|
|
|
1135
1165
|
#
|
|
1136
1166
|
# process_message_stream is the single canonical loop shared by every
|
|
1137
1167
|
# agent. Subclasses customize behavior through the hook methods below
|
|
1138
|
-
# (build_user_content,
|
|
1139
|
-
#
|
|
1140
|
-
# the loop itself.
|
|
1168
|
+
# (build_user_content, on_tool_use_start, should_stop_after_tools,
|
|
1169
|
+
# recap_agent_outcome) rather than overriding the loop itself.
|
|
1141
1170
|
# ------------------------------------------------------------------
|
|
1142
1171
|
|
|
1143
1172
|
completion_log_message = "Processing complete"
|
|
@@ -1165,21 +1194,6 @@ class BaseAgent(LogMixin):
|
|
|
1165
1194
|
|
|
1166
1195
|
return content_blocks
|
|
1167
1196
|
|
|
1168
|
-
def apply_compression_fallback(self) -> None:
|
|
1169
|
-
"""
|
|
1170
|
-
Hard-truncate history when compression alone could not get under budget.
|
|
1171
|
-
|
|
1172
|
-
Default: keep the first message (the original task) plus any protected
|
|
1173
|
-
skill-content messages.
|
|
1174
|
-
"""
|
|
1175
|
-
first_message = self.history[0]
|
|
1176
|
-
protected = [
|
|
1177
|
-
message
|
|
1178
|
-
for message in self.history
|
|
1179
|
-
if message is not first_message and self._is_protected_skill_content(message)
|
|
1180
|
-
]
|
|
1181
|
-
self.history = MessageHistory(protected + [first_message])
|
|
1182
|
-
|
|
1183
1197
|
async def on_tool_use_start(self, tool_call_delta: Dict[str, Any]) -> None:
|
|
1184
1198
|
"""
|
|
1185
1199
|
Called when the provider streams a tool_use_start event (Anthropic only).
|
|
@@ -1251,20 +1265,35 @@ class BaseAgent(LogMixin):
|
|
|
1251
1265
|
logger.debug("Input token count: %s", token_count)
|
|
1252
1266
|
|
|
1253
1267
|
if self.compressor.over_budget(token_count.input_tokens, self.model_context_length):
|
|
1268
|
+
before_tokens = token_count.input_tokens
|
|
1254
1269
|
# PreCompact hooks (advisory): observe before history is compacted.
|
|
1255
1270
|
await self.fire_hook(
|
|
1256
1271
|
HookEvent.PRE_COMPACT,
|
|
1257
1272
|
{
|
|
1258
1273
|
"trigger": "auto",
|
|
1259
|
-
"input_tokens":
|
|
1274
|
+
"input_tokens": before_tokens,
|
|
1260
1275
|
"model_context_length": self.model_context_length,
|
|
1261
1276
|
},
|
|
1262
1277
|
)
|
|
1263
|
-
await self.compress_history()
|
|
1278
|
+
result = await self.compress_history()
|
|
1264
1279
|
token_count = await self.count_current_context()
|
|
1265
1280
|
|
|
1266
|
-
|
|
1267
|
-
|
|
1281
|
+
# PostCompact hooks (advisory): observe the outcome. There is no
|
|
1282
|
+
# destructive fallback — a bounded summary plus capped tool results
|
|
1283
|
+
# and a small verbatim tail keep us under budget; if somehow not, we
|
|
1284
|
+
# send as-is rather than wipe history.
|
|
1285
|
+
await self.fire_hook(
|
|
1286
|
+
HookEvent.POST_COMPACT,
|
|
1287
|
+
{
|
|
1288
|
+
"trigger": "auto",
|
|
1289
|
+
"ok": result.ok,
|
|
1290
|
+
"reason": result.reason,
|
|
1291
|
+
"summarized_messages": result.summarized_messages,
|
|
1292
|
+
"input_tokens_before": before_tokens,
|
|
1293
|
+
"input_tokens_after": token_count.input_tokens,
|
|
1294
|
+
"model_context_length": self.model_context_length,
|
|
1295
|
+
},
|
|
1296
|
+
)
|
|
1268
1297
|
|
|
1269
1298
|
self.mark_cache_checkpoint()
|
|
1270
1299
|
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
"""History compression: summarize a conversation when it outgrows the context window."""
|
|
2
|
+
|
|
3
|
+
import logging
|
|
4
|
+
from dataclasses import dataclass
|
|
5
|
+
from typing import Awaitable, Callable, Optional
|
|
6
|
+
|
|
7
|
+
from .conversation import Conversation
|
|
8
|
+
from kolega_code.llm.models import Message, MessageHistory, TextBlock
|
|
9
|
+
from .prompts import (
|
|
10
|
+
build_compression_summary_user_prompt,
|
|
11
|
+
COMPRESSION_SUMMARY_SYSTEM_PROMPT,
|
|
12
|
+
)
|
|
13
|
+
|
|
14
|
+
logger = logging.getLogger(__name__)
|
|
15
|
+
|
|
16
|
+
LogCallback = Callable[[str], Awaitable[None]]
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
@dataclass(frozen=True)
|
|
20
|
+
class CompactionResult:
|
|
21
|
+
"""Outcome of a compaction attempt, surfaced to callers and the UI.
|
|
22
|
+
|
|
23
|
+
``reason`` is a machine tag: "ok" | "too_few" | "nothing_to_summarize" | "llm_error".
|
|
24
|
+
``message`` is a human-readable line for the command output / logs.
|
|
25
|
+
"""
|
|
26
|
+
|
|
27
|
+
ok: bool
|
|
28
|
+
reason: str
|
|
29
|
+
summarized_messages: int = 0
|
|
30
|
+
message: str = ""
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
class HistoryCompressor:
|
|
34
|
+
"""Summarizes a conversation non-destructively when it crosses the budget threshold."""
|
|
35
|
+
|
|
36
|
+
MIN_MESSAGES_TO_COMPRESS = 5
|
|
37
|
+
# How many of the most recent messages to keep verbatim after the summary.
|
|
38
|
+
KEEP_RECENT_MESSAGES = 6
|
|
39
|
+
# Don't bother summarizing a trivially short prefix.
|
|
40
|
+
MIN_PREFIX_TO_SUMMARIZE = 3
|
|
41
|
+
# Cap the summary length: the prompt targets ~600 words (~900 tokens), so a
|
|
42
|
+
# small ceiling keeps it tight and avoids the model's full completion budget.
|
|
43
|
+
SUMMARY_MAX_TOKENS = 2048
|
|
44
|
+
|
|
45
|
+
def __init__(self, threshold: float = 0.8) -> None:
|
|
46
|
+
# Fraction of the model context window above which compression kicks in
|
|
47
|
+
self.threshold = threshold
|
|
48
|
+
|
|
49
|
+
def over_budget(self, input_tokens: int, model_context_length: int) -> bool:
|
|
50
|
+
return input_tokens > model_context_length * self.threshold
|
|
51
|
+
|
|
52
|
+
async def summarize(
|
|
53
|
+
self,
|
|
54
|
+
conversation: Conversation,
|
|
55
|
+
*,
|
|
56
|
+
llm,
|
|
57
|
+
model: str,
|
|
58
|
+
temperature: float,
|
|
59
|
+
thinking,
|
|
60
|
+
on_info: Optional[LogCallback] = None,
|
|
61
|
+
on_error: Optional[LogCallback] = None,
|
|
62
|
+
) -> CompactionResult:
|
|
63
|
+
"""
|
|
64
|
+
Non-destructively summarize the aged-out prefix while keeping the most
|
|
65
|
+
recent turns verbatim, and move the compaction boundary.
|
|
66
|
+
|
|
67
|
+
Incremental: only the messages that have aged out since the previous
|
|
68
|
+
boundary are summarized, with the prior summary folded in for continuity.
|
|
69
|
+
Returns a CompactionResult describing what happened — never a silent no-op.
|
|
70
|
+
"""
|
|
71
|
+
history = conversation.history
|
|
72
|
+
if not history or len(history) < self.MIN_MESSAGES_TO_COMPRESS:
|
|
73
|
+
return CompactionResult(
|
|
74
|
+
ok=False,
|
|
75
|
+
reason="too_few",
|
|
76
|
+
message=(
|
|
77
|
+
f"Nothing to compress yet ({len(history)} message(s); "
|
|
78
|
+
f"need at least {self.MIN_MESSAGES_TO_COMPRESS})."
|
|
79
|
+
),
|
|
80
|
+
)
|
|
81
|
+
|
|
82
|
+
split = conversation.compaction_split_point(
|
|
83
|
+
keep_recent=self.KEEP_RECENT_MESSAGES, min_prefix=self.MIN_PREFIX_TO_SUMMARIZE
|
|
84
|
+
)
|
|
85
|
+
prior_through = conversation.compacted_through if conversation.summary is not None else 0
|
|
86
|
+
if split is None or split <= prior_through:
|
|
87
|
+
return CompactionResult(
|
|
88
|
+
ok=False,
|
|
89
|
+
reason="nothing_to_summarize",
|
|
90
|
+
message="Already compact — no older messages to summarize.",
|
|
91
|
+
)
|
|
92
|
+
|
|
93
|
+
if on_info:
|
|
94
|
+
await on_info("Compressing message history...")
|
|
95
|
+
|
|
96
|
+
try:
|
|
97
|
+
prefix = MessageHistory(list(history[prior_through:split]))
|
|
98
|
+
prefix_markdown = prefix.get_markdown_conversation()
|
|
99
|
+
previous_summary = conversation.summary.get_text_content() if conversation.summary is not None else None
|
|
100
|
+
user_prompt_filled = build_compression_summary_user_prompt(
|
|
101
|
+
prefix_markdown, previous_summary=previous_summary
|
|
102
|
+
)
|
|
103
|
+
|
|
104
|
+
messages = MessageHistory([Message(role="user", content=[TextBlock(text=user_prompt_filled)])])
|
|
105
|
+
system_message = Message(role="system", content=[TextBlock(text=COMPRESSION_SUMMARY_SYSTEM_PROMPT)])
|
|
106
|
+
|
|
107
|
+
# Stream and drain rather than calling generate(): the Anthropic SDK
|
|
108
|
+
# rejects non-streaming requests whose max_tokens is large enough to risk
|
|
109
|
+
# a >10-minute response, which the model's full completion budget triggers.
|
|
110
|
+
async with await llm.stream(
|
|
111
|
+
messages=messages,
|
|
112
|
+
system=system_message,
|
|
113
|
+
temperature=temperature,
|
|
114
|
+
model=model,
|
|
115
|
+
max_completion_tokens=self.SUMMARY_MAX_TOKENS,
|
|
116
|
+
thinking=thinking,
|
|
117
|
+
) as stream:
|
|
118
|
+
async for _event in stream:
|
|
119
|
+
pass
|
|
120
|
+
response = await stream.get_final_message()
|
|
121
|
+
|
|
122
|
+
summary_text = response.get_text_content()
|
|
123
|
+
if not summary_text or not summary_text.strip():
|
|
124
|
+
msg = "Compression produced an empty summary; history left unchanged."
|
|
125
|
+
if on_error:
|
|
126
|
+
await on_error(msg)
|
|
127
|
+
else:
|
|
128
|
+
logger.error(msg)
|
|
129
|
+
return CompactionResult(ok=False, reason="llm_error", message=msg)
|
|
130
|
+
|
|
131
|
+
folded = split - prior_through
|
|
132
|
+
conversation.apply_compaction(summary_text, split)
|
|
133
|
+
|
|
134
|
+
done = f"Compressed {folded} older message(s) into a summary; kept the latest turns verbatim."
|
|
135
|
+
if on_info:
|
|
136
|
+
await on_info(done)
|
|
137
|
+
return CompactionResult(ok=True, reason="ok", summarized_messages=folded, message=done)
|
|
138
|
+
|
|
139
|
+
except Exception as e:
|
|
140
|
+
# Never swallow into a fake success: log the full traceback and surface
|
|
141
|
+
# the real error to the caller.
|
|
142
|
+
logger.exception("Failed to compress message history")
|
|
143
|
+
msg = f"Failed to compress message history: {type(e).__name__}: {e}"
|
|
144
|
+
if on_error:
|
|
145
|
+
await on_error(msg)
|
|
146
|
+
return CompactionResult(ok=False, reason="llm_error", message=msg)
|
|
@@ -113,6 +113,7 @@ class AgentContext:
|
|
|
113
113
|
user_id=self.telemetry.user_id,
|
|
114
114
|
user_email=self.telemetry.user_email,
|
|
115
115
|
usage_recorder=self.telemetry.usage_recorder,
|
|
116
|
+
token_manager=self.config.get_chatgpt_token_manager(),
|
|
116
117
|
)
|
|
117
118
|
|
|
118
119
|
return LLMClient(
|
|
@@ -121,4 +122,5 @@ class AgentContext:
|
|
|
121
122
|
max_retries=model_config.rate_limits.max_retries,
|
|
122
123
|
requests_per_minute=model_config.rate_limits.requests_per_minute,
|
|
123
124
|
tokens_per_minute=model_config.rate_limits.tokens_per_minute,
|
|
125
|
+
token_manager=self.config.get_chatgpt_token_manager(),
|
|
124
126
|
)
|