ollaagent 0.1.9__tar.gz → 0.2.0__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.
- {ollaagent-0.1.9 → ollaagent-0.2.0}/CHANGELOG.md +13 -0
- {ollaagent-0.1.9 → ollaagent-0.2.0}/PKG-INFO +1 -1
- {ollaagent-0.1.9 → ollaagent-0.2.0}/ollaAgent/agent.py +3 -8
- {ollaagent-0.1.9 → ollaagent-0.2.0}/pyproject.toml +1 -1
- {ollaagent-0.1.9 → ollaagent-0.2.0}/tests/test_agent.py +0 -45
- {ollaagent-0.1.9 → ollaagent-0.2.0}/uv.lock +1 -1
- {ollaagent-0.1.9 → ollaagent-0.2.0}/.agentic_python/guidelines.md +0 -0
- {ollaagent-0.1.9 → ollaagent-0.2.0}/.agentic_python/reviewer_role.md +0 -0
- {ollaagent-0.1.9 → ollaagent-0.2.0}/.env.sample +0 -0
- {ollaagent-0.1.9 → ollaagent-0.2.0}/.gitignore +0 -0
- {ollaagent-0.1.9 → ollaagent-0.2.0}/.python-version +0 -0
- {ollaagent-0.1.9 → ollaagent-0.2.0}/AGENT.md +0 -0
- {ollaagent-0.1.9 → ollaagent-0.2.0}/CLAUDE.md +0 -0
- {ollaagent-0.1.9 → ollaagent-0.2.0}/LICENSE +0 -0
- {ollaagent-0.1.9 → ollaagent-0.2.0}/README.md +0 -0
- {ollaagent-0.1.9 → ollaagent-0.2.0}/README_ko.md +0 -0
- {ollaagent-0.1.9 → ollaagent-0.2.0}/main.py +0 -0
- {ollaagent-0.1.9 → ollaagent-0.2.0}/ollaAgent/__init__.py +0 -0
- {ollaagent-0.1.9 → ollaagent-0.2.0}/ollaAgent/config_loader.py +0 -0
- {ollaagent-0.1.9 → ollaagent-0.2.0}/ollaAgent/memory.py +0 -0
- {ollaagent-0.1.9 → ollaagent-0.2.0}/ollaAgent/ollama_client.py +0 -0
- {ollaagent-0.1.9 → ollaagent-0.2.0}/ollaAgent/permissions.py +0 -0
- {ollaagent-0.1.9 → ollaagent-0.2.0}/ollaAgent/plan_mode.py +0 -0
- {ollaagent-0.1.9 → ollaagent-0.2.0}/ollaAgent/subagent.py +0 -0
- {ollaagent-0.1.9 → ollaagent-0.2.0}/ollaAgent/tool_bash.py +0 -0
- {ollaagent-0.1.9 → ollaagent-0.2.0}/tests/__init__.py +0 -0
- {ollaagent-0.1.9 → ollaagent-0.2.0}/tests/conftest.py +0 -0
- {ollaagent-0.1.9 → ollaagent-0.2.0}/tests/test_config_loader.py +0 -0
- {ollaagent-0.1.9 → ollaagent-0.2.0}/tests/test_memory.py +0 -0
- {ollaagent-0.1.9 → ollaagent-0.2.0}/tests/test_permissions.py +0 -0
- {ollaagent-0.1.9 → ollaagent-0.2.0}/tests/test_plan_mode.py +0 -0
- {ollaagent-0.1.9 → ollaagent-0.2.0}/tests/test_subagent.py +0 -0
- {ollaagent-0.1.9 → ollaagent-0.2.0}/tests/test_tool_bash.py +0 -0
|
@@ -7,6 +7,19 @@ Versioning: [Semantic Versioning](https://semver.org/spec/v2.0.0.html)
|
|
|
7
7
|
|
|
8
8
|
---
|
|
9
9
|
|
|
10
|
+
## [0.2.0] - 2026-03-23
|
|
11
|
+
|
|
12
|
+
### Fixed
|
|
13
|
+
- 이중 출력 완전 해결 — `Live(auto_refresh=False)` + `live.refresh()` + `Markdown` 유지
|
|
14
|
+
- `Text` + 완료 후 Markdown 재출력 방식 폐기
|
|
15
|
+
- chunk마다 즉시 Markdown 갱신 → 실시간성 + 가독성 동시 확보
|
|
16
|
+
|
|
17
|
+
### Removed
|
|
18
|
+
- 불필요해진 `Text` import 제거
|
|
19
|
+
- `transient=True` 관련 테스트 3종 제거
|
|
20
|
+
|
|
21
|
+
---
|
|
22
|
+
|
|
10
23
|
## [0.1.9] - 2026-03-23
|
|
11
24
|
|
|
12
25
|
### Fixed
|
|
@@ -15,7 +15,7 @@ try:
|
|
|
15
15
|
except ImportError:
|
|
16
16
|
pass # Windows 환경에서는 무시
|
|
17
17
|
|
|
18
|
-
__version__ = "0.
|
|
18
|
+
__version__ = "0.2.0"
|
|
19
19
|
|
|
20
20
|
from dotenv import load_dotenv
|
|
21
21
|
from ollama import Client
|
|
@@ -23,7 +23,6 @@ from rich.console import Console
|
|
|
23
23
|
from rich.live import Live
|
|
24
24
|
from rich.markdown import Markdown
|
|
25
25
|
from rich.panel import Panel
|
|
26
|
-
from rich.text import Text
|
|
27
26
|
|
|
28
27
|
from ollaAgent.config_loader import build_system_prompt, load_config
|
|
29
28
|
from ollaAgent.memory import SESSION_DIR, SessionMemory, save_session
|
|
@@ -411,7 +410,7 @@ def stream_response(stream: Any) -> tuple[str, str, dict[int, dict], int]:
|
|
|
411
410
|
accumulated_tool_calls: dict[int, dict] = {}
|
|
412
411
|
prompt_eval_count: int = 0
|
|
413
412
|
|
|
414
|
-
with Live(console=console, auto_refresh=False
|
|
413
|
+
with Live(console=console, auto_refresh=False) as live:
|
|
415
414
|
for chunk in stream:
|
|
416
415
|
msg = chunk.get("message") or {}
|
|
417
416
|
thinking = msg.get("thinking") or ""
|
|
@@ -420,17 +419,13 @@ def stream_response(stream: Any) -> tuple[str, str, dict[int, dict], int]:
|
|
|
420
419
|
content = msg.get("content") or ""
|
|
421
420
|
if content:
|
|
422
421
|
assistant_content += content
|
|
423
|
-
live.update(
|
|
422
|
+
live.update(Markdown(assistant_content))
|
|
424
423
|
live.refresh() # 매 chunk 즉시 출력
|
|
425
424
|
_accumulate_tool_calls(msg, accumulated_tool_calls)
|
|
426
425
|
# done=True 인 마지막 chunk에서 토큰 수 캡처
|
|
427
426
|
if chunk.get("done"):
|
|
428
427
|
prompt_eval_count = chunk.get("prompt_eval_count") or 0
|
|
429
428
|
|
|
430
|
-
# 스트림 완료 후 Markdown으로 최종 렌더링 (가독성 확보)
|
|
431
|
-
if assistant_content:
|
|
432
|
-
console.print(Markdown(assistant_content))
|
|
433
|
-
|
|
434
429
|
return (
|
|
435
430
|
assistant_content,
|
|
436
431
|
thinking_content,
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
from unittest.mock import MagicMock, patch
|
|
2
2
|
|
|
3
3
|
import pytest
|
|
4
|
-
from rich.markdown import Markdown
|
|
5
4
|
|
|
6
5
|
import ollaAgent.agent as agent
|
|
7
6
|
from ollaAgent.agent import (_is_model_available, _parse_subagent_input,
|
|
@@ -451,50 +450,6 @@ class TestStreamResponse:
|
|
|
451
450
|
content, _, _, _ = self._run(chunks)
|
|
452
451
|
assert content == ""
|
|
453
452
|
|
|
454
|
-
def test_markdown_printed_once_after_stream(self):
|
|
455
|
-
"""스트림 완료 후 console.print(Markdown)이 정확히 1회 호출된다."""
|
|
456
|
-
chunks = [
|
|
457
|
-
{"message": {"content": "hello"}, "done": True, "prompt_eval_count": 0}
|
|
458
|
-
]
|
|
459
|
-
with (
|
|
460
|
-
patch("ollaAgent.agent.Live"),
|
|
461
|
-
patch("ollaAgent.agent.console") as mock_console,
|
|
462
|
-
):
|
|
463
|
-
stream_response(iter(chunks))
|
|
464
|
-
|
|
465
|
-
calls = mock_console.print.call_args_list
|
|
466
|
-
markdown_calls = [
|
|
467
|
-
c for c in calls if c.args and isinstance(c.args[0], Markdown)
|
|
468
|
-
]
|
|
469
|
-
assert len(markdown_calls) == 1
|
|
470
|
-
|
|
471
|
-
def test_markdown_not_printed_when_no_content(self):
|
|
472
|
-
"""content 없으면 console.print(Markdown)이 호출되지 않는다."""
|
|
473
|
-
chunks = [{"message": {"content": ""}, "done": True, "prompt_eval_count": 0}]
|
|
474
|
-
with (
|
|
475
|
-
patch("ollaAgent.agent.Live"),
|
|
476
|
-
patch("ollaAgent.agent.console") as mock_console,
|
|
477
|
-
):
|
|
478
|
-
stream_response(iter(chunks))
|
|
479
|
-
|
|
480
|
-
calls = mock_console.print.call_args_list
|
|
481
|
-
markdown_calls = [
|
|
482
|
-
c for c in calls if c.args and isinstance(c.args[0], Markdown)
|
|
483
|
-
]
|
|
484
|
-
assert len(markdown_calls) == 0
|
|
485
|
-
|
|
486
|
-
def test_live_created_with_transient_true(self):
|
|
487
|
-
"""Live가 transient=True로 생성된다 (plain text가 화면에 남지 않음)."""
|
|
488
|
-
chunks = [{"message": {"content": "hi"}, "done": True, "prompt_eval_count": 0}]
|
|
489
|
-
with (
|
|
490
|
-
patch("ollaAgent.agent.Live") as mock_live,
|
|
491
|
-
patch("ollaAgent.agent.console"),
|
|
492
|
-
):
|
|
493
|
-
stream_response(iter(chunks))
|
|
494
|
-
|
|
495
|
-
_, kwargs = mock_live.call_args
|
|
496
|
-
assert kwargs.get("transient") is True
|
|
497
|
-
|
|
498
453
|
|
|
499
454
|
# ──────────────────────────────────────────
|
|
500
455
|
# Unit Tests: _read_user_input
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|