kolega-code 0.1.0__py3-none-any.whl
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/__init__.py +151 -0
- kolega_code/agent/__init__.py +42 -0
- kolega_code/agent/baseagent.py +998 -0
- kolega_code/agent/browseragent.py +123 -0
- kolega_code/agent/coder.py +157 -0
- kolega_code/agent/common.py +41 -0
- kolega_code/agent/compression.py +81 -0
- kolega_code/agent/context.py +112 -0
- kolega_code/agent/conversation.py +408 -0
- kolega_code/agent/generalagent.py +146 -0
- kolega_code/agent/investigationagent.py +123 -0
- kolega_code/agent/planningagent.py +187 -0
- kolega_code/agent/prompt_provider.py +196 -0
- kolega_code/agent/prompt_templates/agents/browser.j2 +102 -0
- kolega_code/agent/prompt_templates/agents/coder_cli_mode.j2 +127 -0
- kolega_code/agent/prompt_templates/agents/general.j2 +68 -0
- kolega_code/agent/prompt_templates/agents/investigation.j2 +72 -0
- kolega_code/agent/prompt_templates/common/frontend_guidance.md +36 -0
- kolega_code/agent/prompt_templates/common/kolega_md_instructions.md +14 -0
- kolega_code/agent/prompt_templates/environment_variables/workspace_env_vars.md +11 -0
- kolega_code/agent/prompt_templates/template_guidance/expo-template.md +379 -0
- kolega_code/agent/prompt_templates/template_guidance/html-website-template.md +3 -0
- kolega_code/agent/prompt_templates/template_guidance/mern-stack-template.md +3 -0
- kolega_code/agent/prompt_templates/template_guidance/react-vite-shadcdn-template.md +182 -0
- kolega_code/agent/prompts.py +192 -0
- kolega_code/agent/tests/__init__.py +0 -0
- kolega_code/agent/tests/llm/__init__.py +0 -0
- kolega_code/agent/tests/llm/test_anthropic_token_counting.py +633 -0
- kolega_code/agent/tests/llm/test_billing_openai_cache.py +74 -0
- kolega_code/agent/tests/llm/test_client.py +773 -0
- kolega_code/agent/tests/llm/test_dashscope_mapping.py +32 -0
- kolega_code/agent/tests/llm/test_error_boundary.py +322 -0
- kolega_code/agent/tests/llm/test_exceptions.py +249 -0
- kolega_code/agent/tests/llm/test_instrumented_client.py +536 -0
- kolega_code/agent/tests/llm/test_instrumented_client_integration.py +547 -0
- kolega_code/agent/tests/llm/test_langfuse_normalization.py +39 -0
- kolega_code/agent/tests/llm/test_model_specs.py +17 -0
- kolega_code/agent/tests/llm/test_openai_cached_tokens.py +58 -0
- kolega_code/agent/tests/llm/test_openai_cached_tokens_stream.py +74 -0
- kolega_code/agent/tests/llm/test_openai_message_conversion.py +30 -0
- kolega_code/agent/tests/llm/test_openai_token_counting.py +687 -0
- kolega_code/agent/tests/llm/test_tool_execution_ids.py +193 -0
- kolega_code/agent/tests/services/__init__.py +1 -0
- kolega_code/agent/tests/services/test_browser.py +447 -0
- kolega_code/agent/tests/services/test_browser_parity.py +353 -0
- kolega_code/agent/tests/services/test_file_system.py +699 -0
- kolega_code/agent/tests/services/test_sandbox_terminal_input.py +98 -0
- kolega_code/agent/tests/services/test_terminal.py +154 -0
- kolega_code/agent/tests/services/test_terminal_command_tracking.py +385 -0
- kolega_code/agent/tests/services/test_terminal_state_serializer.py +262 -0
- kolega_code/agent/tests/test_agent_tools_inventory.py +267 -0
- kolega_code/agent/tests/test_base_agent.py +1942 -0
- kolega_code/agent/tests/test_coder_attachments.py +330 -0
- kolega_code/agent/tests/test_coder_prompt_extensions.py +61 -0
- kolega_code/agent/tests/test_commands.py +179 -0
- kolega_code/agent/tests/test_duplicate_tool_results.py +556 -0
- kolega_code/agent/tests/test_empty_message_handling.py +48 -0
- kolega_code/agent/tests/test_general_agent.py +242 -0
- kolega_code/agent/tests/test_html.py +320 -0
- kolega_code/agent/tests/test_parallel_tool_calls.py +291 -0
- kolega_code/agent/tests/test_planning_agent.py +227 -0
- kolega_code/agent/tests/test_prompt_provider.py +271 -0
- kolega_code/agent/tests/test_tool_registry.py +102 -0
- kolega_code/agent/tests/test_tools.py +549 -0
- kolega_code/agent/tests/tool_backend/__init__.py +0 -0
- kolega_code/agent/tests/tool_backend/test_agent_tool.py +356 -0
- kolega_code/agent/tests/tool_backend/test_base_tool.py +147 -0
- kolega_code/agent/tests/tool_backend/test_browser_tool.py +335 -0
- kolega_code/agent/tests/tool_backend/test_build_tool.py +93 -0
- kolega_code/agent/tests/tool_backend/test_create_file_tool.py +115 -0
- kolega_code/agent/tests/tool_backend/test_glob_tool.py +196 -0
- kolega_code/agent/tests/tool_backend/test_glob_tool_sandbox_parity.py +230 -0
- kolega_code/agent/tests/tool_backend/test_list_directory_tool.py +292 -0
- kolega_code/agent/tests/tool_backend/test_read_file_tool.py +173 -0
- kolega_code/agent/tests/tool_backend/test_replace_entire_file_tool.py +115 -0
- kolega_code/agent/tests/tool_backend/test_replace_lines_tool.py +141 -0
- kolega_code/agent/tests/tool_backend/test_search_and_replace_tool.py +174 -0
- kolega_code/agent/tests/tool_backend/test_search_codebase_tool.py +228 -0
- kolega_code/agent/tests/tool_backend/test_terminal_tool.py +482 -0
- kolega_code/agent/tests/tool_backend/test_think_hard_integration.py +189 -0
- kolega_code/agent/tests/tool_backend/test_think_hard_streaming.py +445 -0
- kolega_code/agent/tests/tool_backend/test_web_fetch_tool.py +194 -0
- kolega_code/agent/tool_backend/agent_tool.py +414 -0
- kolega_code/agent/tool_backend/apply_edit_tool.py +98 -0
- kolega_code/agent/tool_backend/apply_patch_tool.py +514 -0
- kolega_code/agent/tool_backend/base_tool.py +217 -0
- kolega_code/agent/tool_backend/browser_tool.py +271 -0
- kolega_code/agent/tool_backend/build_tool.py +93 -0
- kolega_code/agent/tool_backend/create_file_tool.py +52 -0
- kolega_code/agent/tool_backend/glob_tool.py +323 -0
- kolega_code/agent/tool_backend/list_directory_tool.py +300 -0
- kolega_code/agent/tool_backend/memory_tool.py +79 -0
- kolega_code/agent/tool_backend/read_file_tool.py +119 -0
- kolega_code/agent/tool_backend/replace_entire_file_tool.py +40 -0
- kolega_code/agent/tool_backend/replace_lines_tool.py +97 -0
- kolega_code/agent/tool_backend/search_and_replace_tool.py +146 -0
- kolega_code/agent/tool_backend/search_codebase_tool.py +377 -0
- kolega_code/agent/tool_backend/streaming_tool.py +47 -0
- kolega_code/agent/tool_backend/terminal_tool.py +643 -0
- kolega_code/agent/tool_backend/think_hard_tool.py +211 -0
- kolega_code/agent/tool_backend/web_fetch_tool.py +205 -0
- kolega_code/agent/tools.py +1704 -0
- kolega_code/agent/utils/commands.py +94 -0
- kolega_code/cli/__init__.py +1 -0
- kolega_code/cli/app.py +2756 -0
- kolega_code/cli/config.py +280 -0
- kolega_code/cli/connection.py +49 -0
- kolega_code/cli/file_index.py +147 -0
- kolega_code/cli/main.py +564 -0
- kolega_code/cli/mentions.py +155 -0
- kolega_code/cli/messages.py +89 -0
- kolega_code/cli/provider_registry.py +96 -0
- kolega_code/cli/session_store.py +207 -0
- kolega_code/cli/settings.py +87 -0
- kolega_code/cli/skills.py +409 -0
- kolega_code/cli/slash_commands.py +108 -0
- kolega_code/cli/tests/__init__.py +1 -0
- kolega_code/cli/tests/test_app.py +4251 -0
- kolega_code/cli/tests/test_cli_config.py +171 -0
- kolega_code/cli/tests/test_connection.py +26 -0
- kolega_code/cli/tests/test_file_index.py +103 -0
- kolega_code/cli/tests/test_main.py +455 -0
- kolega_code/cli/tests/test_mentions.py +108 -0
- kolega_code/cli/tests/test_session_store.py +67 -0
- kolega_code/cli/tests/test_settings.py +62 -0
- kolega_code/cli/tests/test_skills.py +157 -0
- kolega_code/cli/tests/test_slash_commands.py +88 -0
- kolega_code/cli/theme.py +180 -0
- kolega_code/config.py +154 -0
- kolega_code/events.py +202 -0
- kolega_code/llm/client.py +300 -0
- kolega_code/llm/exceptions.py +285 -0
- kolega_code/llm/instrumented_client.py +520 -0
- kolega_code/llm/models.py +1368 -0
- kolega_code/llm/providers/__init__.py +0 -0
- kolega_code/llm/providers/anthropic.py +387 -0
- kolega_code/llm/providers/base.py +71 -0
- kolega_code/llm/providers/google.py +157 -0
- kolega_code/llm/providers/models.py +37 -0
- kolega_code/llm/providers/openai.py +363 -0
- kolega_code/llm/ratelimit.py +40 -0
- kolega_code/llm/specs.py +67 -0
- kolega_code/llm/tool_execution_ids.py +18 -0
- kolega_code/models/__init__.py +9 -0
- kolega_code/models/sandbox_terminal_state.py +47 -0
- kolega_code/runtime.py +50 -0
- kolega_code/sandbox/README.md +200 -0
- kolega_code/sandbox/__init__.py +21 -0
- kolega_code/sandbox/async_filesystem.py +475 -0
- kolega_code/sandbox/base.py +297 -0
- kolega_code/sandbox/browser.py +25 -0
- kolega_code/sandbox/event_loop.py +43 -0
- kolega_code/sandbox/filesystem.py +341 -0
- kolega_code/sandbox/local.py +118 -0
- kolega_code/sandbox/serializer.py +175 -0
- kolega_code/sandbox/terminal.py +868 -0
- kolega_code/sandbox/utils.py +216 -0
- kolega_code/services/base.py +255 -0
- kolega_code/services/browser.py +444 -0
- kolega_code/services/file_system.py +749 -0
- kolega_code/services/html.py +221 -0
- kolega_code/services/terminal.py +903 -0
- kolega_code/tools/__init__.py +22 -0
- kolega_code/tools/core.py +33 -0
- kolega_code/tools/definitions.py +81 -0
- kolega_code/tools/registry.py +73 -0
- kolega_code-0.1.0.dist-info/METADATA +157 -0
- kolega_code-0.1.0.dist-info/RECORD +171 -0
- kolega_code-0.1.0.dist-info/WHEEL +4 -0
- kolega_code-0.1.0.dist-info/entry_points.txt +2 -0
- kolega_code-0.1.0.dist-info/licenses/LICENSE +21 -0
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import pytest
|
|
2
|
+
|
|
3
|
+
from kolega_code.llm.providers.openai import OpenAIProvider
|
|
4
|
+
from kolega_code.llm.models import Message, MessageHistory
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class _Delta:
|
|
8
|
+
def __init__(self, content=None, tool_calls=None):
|
|
9
|
+
self.content = content
|
|
10
|
+
self.tool_calls = tool_calls or []
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class _Choice:
|
|
14
|
+
def __init__(self, delta, finish_reason=None):
|
|
15
|
+
self.delta = delta
|
|
16
|
+
self.finish_reason = finish_reason
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class _Chunk:
|
|
20
|
+
def __init__(self, text=None, is_final=False):
|
|
21
|
+
self.choices = [_Choice(delta=_Delta(content=text), finish_reason='stop' if is_final else None)]
|
|
22
|
+
self.usage = None
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
class _Usage:
|
|
26
|
+
def __init__(self):
|
|
27
|
+
self.prompt_tokens = 3019
|
|
28
|
+
self.completion_tokens = 104
|
|
29
|
+
self.total_tokens = 3123
|
|
30
|
+
self.prompt_tokens_details = {'cached_tokens': 2048}
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
class _AsyncStream:
|
|
34
|
+
def __init__(self):
|
|
35
|
+
self._chunks = [_Chunk('hello '), _Chunk('world', is_final=True)]
|
|
36
|
+
self._i = 0
|
|
37
|
+
|
|
38
|
+
def __aiter__(self):
|
|
39
|
+
return self
|
|
40
|
+
|
|
41
|
+
async def __anext__(self):
|
|
42
|
+
if self._i >= len(self._chunks):
|
|
43
|
+
raise StopAsyncIteration
|
|
44
|
+
chunk = self._chunks[self._i]
|
|
45
|
+
self._i += 1
|
|
46
|
+
if self._i == len(self._chunks):
|
|
47
|
+
chunk.usage = _Usage() # final chunk carries usage
|
|
48
|
+
return chunk
|
|
49
|
+
|
|
50
|
+
async def aclose(self):
|
|
51
|
+
pass
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
# TODO: Fix after qwen-3-coder-plus PR is merged - needs OpenAI cache token extraction in streaming
|
|
55
|
+
@pytest.mark.asyncio
|
|
56
|
+
async def test_openai_stream_includes_cached_tokens(monkeypatch):
|
|
57
|
+
provider = OpenAIProvider(api_key='sk-test', base_url='https://api.openai.com/v1')
|
|
58
|
+
|
|
59
|
+
async def fake_create(*args, **kwargs):
|
|
60
|
+
return _AsyncStream()
|
|
61
|
+
|
|
62
|
+
monkeypatch.setattr(provider.async_client.chat.completions, 'create', fake_create)
|
|
63
|
+
|
|
64
|
+
stream = await provider.stream(messages=MessageHistory([Message(role='user', content='hi')]))
|
|
65
|
+
async with stream as s:
|
|
66
|
+
async for _ in s:
|
|
67
|
+
pass
|
|
68
|
+
final = await s.get_final_message()
|
|
69
|
+
assert final.usage_metadata['prompt_tokens'] == 3019
|
|
70
|
+
assert final.usage_metadata['total_tokens'] == 3123
|
|
71
|
+
assert final.usage_metadata['cache_read_input_tokens'] == 2048
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import pytest
|
|
2
|
+
|
|
3
|
+
from kolega_code.llm.models import Message, MessageHistory, ToolCall, ToolResult, TextBlock
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
# TODO: Fix after qwen-3-coder-plus PR is merged - needs tool result filtering in Message.to_openai()
|
|
7
|
+
def test_mixed_content_splits_tool_result_to_separate_tool_messages():
|
|
8
|
+
# Assistant message with text + tool_call + tool_result
|
|
9
|
+
tool_call = ToolCall(id='call_123', name='sum', input={'a': 1, 'b': 2})
|
|
10
|
+
tool_result = ToolResult(tool_use_id='call_123', content='3', name='sum', is_error=False)
|
|
11
|
+
assistant = Message(role='assistant', content=[TextBlock('ok'), tool_call, tool_result])
|
|
12
|
+
|
|
13
|
+
mh = MessageHistory([assistant])
|
|
14
|
+
messages = mh.to_openai()
|
|
15
|
+
|
|
16
|
+
# Expect two messages: assistant (with tool_calls) then tool with matching tool_call_id
|
|
17
|
+
assert messages[0]['role'] == 'assistant'
|
|
18
|
+
assert 'tool_calls' in messages[0]
|
|
19
|
+
assert messages[0]['tool_calls'][0]['id'] == 'call_123'
|
|
20
|
+
# content should not include tool_result; only text parts
|
|
21
|
+
assert isinstance(messages[0]['content'], list)
|
|
22
|
+
assert all(isinstance(p, dict) and p.get('type') in ('text', 'image_url') for p in messages[0]['content'])
|
|
23
|
+
|
|
24
|
+
assert messages[1]['role'] == 'tool'
|
|
25
|
+
assert messages[1]['tool_call_id'] == 'call_123'
|
|
26
|
+
# tool content can be a string or structured parts depending on our representation
|
|
27
|
+
assert 'content' in messages[1]
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
|