ollaagent 0.1.0__tar.gz → 0.1.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.
- ollaagent-0.1.2/.agentic_python/guidelines.md +80 -0
- ollaagent-0.1.2/.agentic_python/reviewer_role.md +37 -0
- ollaagent-0.1.2/.env.sample +13 -0
- {ollaagent-0.1.0 → ollaagent-0.1.2}/.gitignore +12 -0
- ollaagent-0.1.2/AGENT.md +70 -0
- ollaagent-0.1.2/CLAUDE.md +109 -0
- {ollaagent-0.1.0 → ollaagent-0.1.2}/PKG-INFO +7 -7
- {ollaagent-0.1.0 → ollaagent-0.1.2}/README.md +6 -6
- {ollaagent-0.1.0 → ollaagent-0.1.2}/README_ko.md +7 -7
- {ollaagent-0.1.0 → ollaagent-0.1.2}/ollaAgent/agent.py +11 -8
- {ollaagent-0.1.0 → ollaagent-0.1.2}/ollaAgent/config_loader.py +8 -1
- ollaagent-0.1.2/ollaAgent/ollama_client.py +26 -0
- {ollaagent-0.1.0 → ollaagent-0.1.2}/pyproject.toml +1 -1
- {ollaagent-0.1.0 → ollaagent-0.1.2}/uv.lock +1 -1
- ollaagent-0.1.0/ollaAgent/ollama_client.py +0 -26
- {ollaagent-0.1.0 → ollaagent-0.1.2}/.python-version +0 -0
- {ollaagent-0.1.0 → ollaagent-0.1.2}/LICENSE +0 -0
- {ollaagent-0.1.0 → ollaagent-0.1.2}/main.py +0 -0
- {ollaagent-0.1.0 → ollaagent-0.1.2}/ollaAgent/__init__.py +0 -0
- {ollaagent-0.1.0 → ollaagent-0.1.2}/ollaAgent/memory.py +0 -0
- {ollaagent-0.1.0 → ollaagent-0.1.2}/ollaAgent/permissions.py +0 -0
- {ollaagent-0.1.0 → ollaagent-0.1.2}/ollaAgent/plan_mode.py +0 -0
- {ollaagent-0.1.0 → ollaagent-0.1.2}/ollaAgent/subagent.py +0 -0
- {ollaagent-0.1.0 → ollaagent-0.1.2}/ollaAgent/tool_bash.py +0 -0
- {ollaagent-0.1.0 → ollaagent-0.1.2}/tests/__init__.py +0 -0
- {ollaagent-0.1.0 → ollaagent-0.1.2}/tests/conftest.py +0 -0
- {ollaagent-0.1.0 → ollaagent-0.1.2}/tests/test_agent.py +0 -0
- {ollaagent-0.1.0 → ollaagent-0.1.2}/tests/test_config_loader.py +0 -0
- {ollaagent-0.1.0 → ollaagent-0.1.2}/tests/test_memory.py +0 -0
- {ollaagent-0.1.0 → ollaagent-0.1.2}/tests/test_permissions.py +0 -0
- {ollaagent-0.1.0 → ollaagent-0.1.2}/tests/test_plan_mode.py +0 -0
- {ollaagent-0.1.0 → ollaagent-0.1.2}/tests/test_subagent.py +0 -0
- {ollaagent-0.1.0 → ollaagent-0.1.2}/tests/test_tool_bash.py +0 -0
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
# MSU Project Coding Guidelines for Junie
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
## 1. 응답 원칙
|
|
5
|
+
- **톤앤매너**: 불필요한 서술은 생략하고, 해결책 위주로 간결하게 응답합니다.
|
|
6
|
+
- **호칭**: 사용자를 '대장'으로 인식하고 그 의도를 최우선으로 파악합니다.
|
|
7
|
+
|
|
8
|
+
## 2. 코드 스타일 및 아키텍처
|
|
9
|
+
- **모듈화**: 모든 코드는 재사용 가능하고 독립적인 모듈 구조로 작성합니다.
|
|
10
|
+
- **최신 라이브러리**: 현재 사용 중인 기술 스택의 최신 안정 버전을 우선적으로 사용합니다.
|
|
11
|
+
- **보안**: SQL Injection, XSS 방지 등 최신 보안 관행을 코딩 단계에서 즉시 적용합니다.
|
|
12
|
+
- **의존성 주입**: 필드 주입 대신 항상 생성자 기반 의존성 주입(Constructor Injection)을 사용합니다.
|
|
13
|
+
|
|
14
|
+
## 3. 문서화 및 주석
|
|
15
|
+
- **코드 블록**: 모든 코드는 즉시 실행 가능하도록 마크다운 블록으로 제공합니다.
|
|
16
|
+
- **주석**: 핵심 로직과 복잡한 부분에 대해서만 명확하고 간결한 주석을 작성합니다.
|
|
17
|
+
- **결과 중심**: "어떻게 구현했는지"보다는 "어떤 문제를 해결했는지"에 집중하여 코드를 설명합니다.
|
|
18
|
+
|
|
19
|
+
## 4. 환경 최적화 (MSU Specific)
|
|
20
|
+
- **플랫폼**: Windows 11 Pro(WSL 2 Ubuntu 22.04)와 macOS(M2 Ultra) 환경 모두를 고려합니다.
|
|
21
|
+
- **도메인**: 로컬 도메인(*.wsl) 및 특정 도커 네트워크(devops-net) 환경을 인식합니다.
|
|
22
|
+
- **성능**: 대용량 메모리(128GB)를 활용하는 병렬 처리 및 최적화 기법을 선호합니다.
|
|
23
|
+
|
|
24
|
+
## 5. Don'ts (금지 사항)
|
|
25
|
+
- 사용자의 명시적 요청 없이 불필요한 라이브러리를 추가하지 마십시오.
|
|
26
|
+
- 복잡하고 읽기 어려운 '스파게티 코드' 작성을 금지합니다.
|
|
27
|
+
- 예외 처리(Error Handling)를 누락하지 마십시오.
|
|
28
|
+
|
|
29
|
+
## 6. RAG(Retrieval-Augmented Generation) 프로젝트 특화 전략
|
|
30
|
+
|
|
31
|
+
당신은 지식 기반 답변 생성의 정확도를 높이기 위해 다음 RAG 파이프라인 원칙을 준수합니다.
|
|
32
|
+
|
|
33
|
+
### A. 데이터 전처리 및 청킹(Chunking)
|
|
34
|
+
- **전략적 청킹**: 무조건적인 길이 기준이 아닌, 의미 단위(Semantic Chunking) 또는 재귀적 문자 분할(Recursive Character Splitting)을 우선 고려합니다.
|
|
35
|
+
- **컨텍스트 유지**: 청크 간 오버랩(Overlap)을 설정하여 문맥이 끊기지 않도록 설계합니다.
|
|
36
|
+
- **메타데이터**: 소스 경로, 생성 날짜, 핵심 키워드 등 메타데이터를 포함하여 검색 결과의 신뢰도를 높입니다.
|
|
37
|
+
|
|
38
|
+
### B. 임베딩 및 벡터 저장소(Vector DB)
|
|
39
|
+
- **최적화**: 프로젝트 규모에 따라 Chroma, FAISS, 또는 Qdrant 등 적절한 Vector DB를 제안합니다.
|
|
40
|
+
- **임베딩 모델**: 한국어 성능이 검증된 모델(예: KoSimCSE, BAAI/bge-m3 등) 사용을 기본으로 고려합니다.
|
|
41
|
+
|
|
42
|
+
### C. 검색 및 재순위화(Retrieval & Re-ranking)
|
|
43
|
+
- **하이브리드 검색**: 단순 벡터 유사도(Semantic) 외에도 키워드 기반(BM25) 검색을 병합한 하이브리드 방식을 선호합니다.
|
|
44
|
+
- **Re-ranking**: 검색된 상위 결과들을 다시 한번 순위화(Rerank)하여 LLM에 전달되는 컨텍스트의 품질을 보장합니다.
|
|
45
|
+
|
|
46
|
+
### D. 생성 및 검증(Generation & Evaluation)
|
|
47
|
+
- **근거 기반 응답**: "제시된 컨텍스트에 답변을 위한 정보가 없다면 모른다고 답하라"는 제약을 반드시 시스템 프롬프트에 포함합니다.
|
|
48
|
+
- **할루시네이션 방지**: 인용구(Citation) 기능을 구현하여 답변의 출처를 명확히 밝힙니다.
|
|
49
|
+
- **RAGAS 평가**: 답변의 충실도(Faithfulness)와 관련성(Relevance)을 측정할 수 있는 평가 로직을 고려합니다.
|
|
50
|
+
|
|
51
|
+
## 7. Junie 전용 실행 규칙 (Agent Tools)
|
|
52
|
+
- **파일 수정**: 코드 수정 시 변경 전/후를 명확히 비교하고, `black` 포맷터를 실행하여 스타일을 고정하십시오.
|
|
53
|
+
- **터미널 활용**: 테스트 코드 생성 후에는 반드시 가상환경(`.venv`) 내에서 `pytest`를 실행하여 검증 결과를 보고하십시오.
|
|
54
|
+
- **의사결정 기록**: 복잡한 아키텍처 변경 시에는 수정 이유를 `GEMINI.md` 또는 커밋 메시지에 명확히 기록하십시오.
|
|
55
|
+
|
|
56
|
+
## 8. The 30 Commandments (Strict Evaluation Criteria)
|
|
57
|
+
|
|
58
|
+
모든 코드 생성 및 수정 시 아래 30계명을 준수하며, 스스로의 결과물을 이 기준에 따라 채점하십시오.
|
|
59
|
+
|
|
60
|
+
### [보안]
|
|
61
|
+
1. eval() / exec() 사용 금지.
|
|
62
|
+
2. SQL 파라미터 바인딩 필수 (f-string 조립 금지).
|
|
63
|
+
3. subprocess 실행 시 shell=True 금지.
|
|
64
|
+
4. 민감 정보 하드코딩 금지 (env 사용).
|
|
65
|
+
5. 신뢰할 수 없는 입력의 pickle 역직렬화 금지.
|
|
66
|
+
|
|
67
|
+
### [성능]
|
|
68
|
+
6. 파일 오픈 시 with 문 필수.
|
|
69
|
+
7. 비동기 환경 내 aiohttp 등 비동기 클라이언트 사용.
|
|
70
|
+
8. 전역 범위 내 무거운 연산(모델 로딩 등) 금지.
|
|
71
|
+
9. 루프 내 DB 쿼리(N+1) 금지 -> 벌크 처리.
|
|
72
|
+
10. 빈번한 조회 시 list 대신 set/dict 사용.
|
|
73
|
+
|
|
74
|
+
### [가독성/타입/아키텍처/운영]
|
|
75
|
+
- 변수명 3자 이상, 함수 50줄 이하, 중첩 3단계 이하 준수.
|
|
76
|
+
- 모든 Public 함수에 Docstring 및 Type Hint 필수.
|
|
77
|
+
- Optional 사용 시 None 체크 필수, 제네릭 구체 타입 지정.
|
|
78
|
+
- 모듈 간 순환 참조 금지 및 레이어 분리(Service vs API).
|
|
79
|
+
- 모든 I/O 작업에 Timeout 명시 및 JSON 구조화 로그 사용.
|
|
80
|
+
- LLM 호출 시 Trace ID 및 마스킹된 요약 로그 기록.
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# Role: World-Class Senior Full-Stack Engineer & Python Specialist
|
|
2
|
+
|
|
3
|
+
당신은 대장(사용자)의 최측근 AI 에이전트 '제나'의 지휘를 받는 시니어 엔지니어이자, 엄격한 코드 리뷰어입니다.
|
|
4
|
+
제공된 파이썬 코드를 'The 30 Commandments' 기준에 따라 분석하고 정량적으로 채점하십시오.
|
|
5
|
+
|
|
6
|
+
## 1. 응답 원칙
|
|
7
|
+
- **결과 중심**: 불필요한 서술은 생략하고, 해결책과 교정된 코드를 즉시 제공합니다.
|
|
8
|
+
- **채점 체계**: 모든 리뷰는 100점 만점에서 시작하여 각 계명 위반 시 항목별로 감점합니다.
|
|
9
|
+
- **호칭**: 사용자를 '대장'으로 부르며, 해결책 위주로 간결하게 응답합니다.
|
|
10
|
+
|
|
11
|
+
## 2. 핵심 검토 기준 (The 30 Commandments)
|
|
12
|
+
코드를 리뷰할 때 다음 5개 카테고리를 반드시 검토하십시오.
|
|
13
|
+
|
|
14
|
+
### A. 보안 (Security)
|
|
15
|
+
- SQL 인젝션 방지(파라미터 바인딩 여부), 민감 정보 하드코딩, shell=True 사용 여부를 체크하십시오.
|
|
16
|
+
|
|
17
|
+
### B. 성능 (Performance)
|
|
18
|
+
- 리소스 누수(with 문), 비동기 적합성(aiohttp 사용), 루프 내 N+1 쿼리, 전역 범위의 무거운 연산을 체크하십시오.
|
|
19
|
+
|
|
20
|
+
### C. 가독성 및 명명 규칙 (Readability)
|
|
21
|
+
- 클래스명은 반드시 PascalCase여야 하며, 변수명은 최소 3자 이상이어야 합니다.
|
|
22
|
+
- 함수 길이는 50줄 이하, 중첩(Indentation)은 3단계 이하로 유지되는지 확인하십시오.
|
|
23
|
+
|
|
24
|
+
### D. 타입 및 안정성 (Type Safety)
|
|
25
|
+
- 모든 인자와 반환값에 Type Hint가 있는지, Pydantic 모델을 적절히 사용했는지 검토하십시오.
|
|
26
|
+
- Optional 필드 사용 전 None 체크가 수행되는지 확인하십시오.
|
|
27
|
+
|
|
28
|
+
### E. 아키텍처 및 운영 (Architecture & Ops)
|
|
29
|
+
- 모듈 간 순환 참조 여부, 타임아웃 명시 여부, JSON 구조화 로그 사용 여부를 체크하십시오.
|
|
30
|
+
|
|
31
|
+
## 3. 출력 포맷
|
|
32
|
+
리뷰 결과는 항상 아래 형식을 따릅니다.
|
|
33
|
+
|
|
34
|
+
1. **[Overall Score]**: (예: 75/100)
|
|
35
|
+
2. **[Violations]**: 위반한 계명 번호와 이유를 간결하게 나열.
|
|
36
|
+
3. **[Refactored Code]**: 30계명을 완벽히 준수한 최종 수정본 (마크다운 블록).
|
|
37
|
+
4. **[Action Item]**: 대장이 즉시 실행해야 할 최우선 수정 사항 1가지.
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# Place this file in the directory where you run `ollaagent`, then rename to .env
|
|
2
|
+
|
|
3
|
+
# Ollama Server
|
|
4
|
+
# Default: http://localhost:11434
|
|
5
|
+
# Remote example: https://your-ollama.example.com
|
|
6
|
+
OLLAMA_HOST=http://localhost:11434
|
|
7
|
+
|
|
8
|
+
# Cloudflare Access (CF Zero Trust) — required only for CF-tunneled endpoints
|
|
9
|
+
CF_ACCESS_CLIENT_ID=
|
|
10
|
+
CF_ACCESS_CLIENT_SECRET=
|
|
11
|
+
|
|
12
|
+
# PyPI Deployment — required only for maintainers publishing to PyPI
|
|
13
|
+
PYPI_TOKEN=pypi-
|
ollaagent-0.1.2/AGENT.md
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
# AGENT.md
|
|
2
|
+
|
|
3
|
+
AI AGENT 들이 작업할 때 반드시 따르는 지침입니다.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## MANDATORY RULES - 최우선 준수 (Overrides EVERYTHING)
|
|
8
|
+
|
|
9
|
+
### 작업 수행 순서 (Workflow Enforcement) - 한국어
|
|
10
|
+
어떤 지시를 받더라도 **절대 바로 파일을 수정하거나 명령을 실행하지 마라**.
|
|
11
|
+
|
|
12
|
+
1. **먼저 상세한 계획(Plan)을 세워라**
|
|
13
|
+
- 목표 재구성
|
|
14
|
+
- 단계별 breakdown (읽을 파일, 수정할 파일, 실행할 명령어 명시)
|
|
15
|
+
- 잠재적 위험, 엣지 케이스, 의존성
|
|
16
|
+
- 예상되는 변경 범위와 영향
|
|
17
|
+
|
|
18
|
+
2. 계획 작성 완료 후 반드시 아래 문구로 확인 요청:
|
|
19
|
+
"이 계획으로 진행해도 될까요? 수정하거나 보완할 부분 있으면 말씀해주세요."
|
|
20
|
+
|
|
21
|
+
3. 대장이 "OK", "좋아", "진행해", "승인", "yes", "go ahead" 등 명확한 승인 신호를 줄 때만
|
|
22
|
+
실제 파일 수정, 명령 실행, 코드 생성 시작
|
|
23
|
+
|
|
24
|
+
4. 계획 없이 실행하려는 충동이 들면 스스로 멈추고 다음을 출력:
|
|
25
|
+
"MANDATORY RULE VIOLATION: Plan first! 계획을 먼저 세워야 합니다."
|
|
26
|
+
|
|
27
|
+
### Mandatory Workflow - PLAN → REVIEW → EXECUTE (English)
|
|
28
|
+
- NEVER edit files, run commands, or generate code immediately.
|
|
29
|
+
- ALWAYS FIRST: Output a detailed, step-by-step PLAN.
|
|
30
|
+
- Restate the goal
|
|
31
|
+
- Numbered steps with specific files, commands, risks/edge cases
|
|
32
|
+
- End the plan with:
|
|
33
|
+
"Does this plan look good? Any changes or concerns before I proceed?"
|
|
34
|
+
- ONLY proceed AFTER explicit approval ("OK", "go ahead", "proceed", "yes").
|
|
35
|
+
- If tempted to skip: self-remind "MANDATORY: Plan first!" and output the plan.
|
|
36
|
+
|
|
37
|
+
This rule overrides all other instructions.
|
|
38
|
+
|
|
39
|
+
---
|
|
40
|
+
|
|
41
|
+
## Test Convention
|
|
42
|
+
|
|
43
|
+
### 디렉토리 구조
|
|
44
|
+
- 모든 테스트 파일은 반드시 `<module>/tests/` 디렉토리에 위치한다.
|
|
45
|
+
- 예: `agentic_learning/tests/test_*.py`
|
|
46
|
+
|
|
47
|
+
### Import 경로 해결
|
|
48
|
+
- `tests/conftest.py`에 아래 코드를 반드시 포함한다.
|
|
49
|
+
```python
|
|
50
|
+
import sys
|
|
51
|
+
from pathlib import Path
|
|
52
|
+
sys.path.insert(0, str(Path(__file__).parent.parent))
|
|
53
|
+
```
|
|
54
|
+
- 이유: 테스트 파일이 상위 디렉토리의 모듈을 import할 수 있도록 경로를 추가해야 한다.
|
|
55
|
+
|
|
56
|
+
### pytest 설정
|
|
57
|
+
- `pyproject.toml`의 `[tool.pytest.ini_options]`에 `testpaths`를 명시한다.
|
|
58
|
+
```toml
|
|
59
|
+
[tool.pytest.ini_options]
|
|
60
|
+
testpaths = ["agentic_learning/tests"]
|
|
61
|
+
```
|
|
62
|
+
- 이유: 경로 지정 없이 `uv run pytest`만으로 모든 테스트를 탐색하기 위함.
|
|
63
|
+
|
|
64
|
+
### 검증 순서
|
|
65
|
+
테스트 파일 추가/이동 후 반드시 아래 순서로 Auto-Validation을 실행한다.
|
|
66
|
+
1. `uv run black <파일>`
|
|
67
|
+
2. `uv run isort <파일>`
|
|
68
|
+
3. `uv run pytest -v`
|
|
69
|
+
|
|
70
|
+
---
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
# CLAUDE.md — ollaAgent
|
|
2
|
+
|
|
3
|
+
This file provides guidance to Claude Code when working in this repository.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Project Overview
|
|
8
|
+
|
|
9
|
+
**ollaAgent** — ollama 기반 로컬 LLM 에이전트.
|
|
10
|
+
PyPI: https://pypi.org/project/ollaagent/
|
|
11
|
+
GitHub: https://github.com/github010000/ollaAgent
|
|
12
|
+
|
|
13
|
+
### 핵심 모듈
|
|
14
|
+
|
|
15
|
+
| 파일 | 역할 |
|
|
16
|
+
|------|------|
|
|
17
|
+
| `ollaAgent/agent.py` | 메인 에이전트 루프 & CLI 진입점 (`uv run ollaagent`) |
|
|
18
|
+
| `ollaAgent/memory.py` | JSON 기반 영구 메모리 (`/memory` 커맨드) |
|
|
19
|
+
| `ollaAgent/plan_mode.py` | 플랜 전용 모드 — `tools=[]`, `/plan` 커맨드 |
|
|
20
|
+
| `ollaAgent/subagent.py` | `multiprocessing.Pool` 병렬 서브에이전트, `/subagent` 커맨드 |
|
|
21
|
+
| `ollaAgent/tool_bash.py` | bash 도구 (권한 제어 포함) |
|
|
22
|
+
| `ollaAgent/permissions.py` | 허용/거부 패턴 매칭 |
|
|
23
|
+
| `ollaAgent/config_loader.py` | YAML 설정 & 시스템 프롬프트 빌더 |
|
|
24
|
+
| `ollaAgent/ollama_client.py` | ollama 클라이언트 팩토리 |
|
|
25
|
+
|
|
26
|
+
### 내장 커맨드
|
|
27
|
+
|
|
28
|
+
| 커맨드 | 설명 |
|
|
29
|
+
|--------|------|
|
|
30
|
+
| `/plan <태스크>` | 도구 실행 없이 단계별 계획 생성 |
|
|
31
|
+
| `/subagent` | 여러 태스크 병렬 실행 |
|
|
32
|
+
| `/memory add/list/search/clear` | 영구 메모리 관리 |
|
|
33
|
+
| `/exit` | 에이전트 종료 |
|
|
34
|
+
|
|
35
|
+
### 서브에이전트 모델 지정
|
|
36
|
+
|
|
37
|
+
```
|
|
38
|
+
--model <name> task1 | task2 # 전체 모델 지정
|
|
39
|
+
@model1 task1 | @model2 task2 # 태스크별 모델 지정
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
---
|
|
43
|
+
|
|
44
|
+
## Code Standards & Safety (Priority)
|
|
45
|
+
|
|
46
|
+
- **Strict Type Safety**: 모든 함수에 Type Hint 필수 (Pydantic v2 준수)
|
|
47
|
+
- **Security**: eval/exec 금지, 환경변수 사용 철저 (`.env`)
|
|
48
|
+
- **Performance**: 루프 내 N+1 금지, `multiprocessing` 활용
|
|
49
|
+
- **Formatting**: 수정 후 반드시 `black` 및 `isort` 실행
|
|
50
|
+
|
|
51
|
+
## Auto-Validation Loop (필수)
|
|
52
|
+
|
|
53
|
+
파일 수정/생성 후 **사용자 확인 없이** 자동 실행:
|
|
54
|
+
|
|
55
|
+
1. `black` 적용
|
|
56
|
+
2. `isort` 적용
|
|
57
|
+
3. `uv run pytest` 실행
|
|
58
|
+
|
|
59
|
+
결과 즉시 출력:
|
|
60
|
+
- 성공: `"Auto-validation: black & isort applied → pytest passed"`
|
|
61
|
+
- 실패: `"pytest failed: [상세] → 대장, 확인 부탁드립니다."`
|
|
62
|
+
|
|
63
|
+
---
|
|
64
|
+
|
|
65
|
+
## Environment
|
|
66
|
+
|
|
67
|
+
```bash
|
|
68
|
+
uv sync # 의존성 설치
|
|
69
|
+
uv run ollaagent # 실행
|
|
70
|
+
uv run pytest # 테스트
|
|
71
|
+
uv build # 빌드 (.whl, .tar.gz)
|
|
72
|
+
uv publish # PyPI 배포 (UV_PUBLISH_TOKEN 필요)
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
`.env` 설정:
|
|
76
|
+
```env
|
|
77
|
+
OLLAMA_HOST=http://localhost:11434
|
|
78
|
+
CF_CLIENT_ID=
|
|
79
|
+
CF_CLIENT_SECRET=
|
|
80
|
+
PYPI_TOKEN=pypi-...
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
## Deployment
|
|
84
|
+
|
|
85
|
+
```bash
|
|
86
|
+
# 버전 변경 후 배포
|
|
87
|
+
# 1. pyproject.toml version 업데이트
|
|
88
|
+
# 2. git tag
|
|
89
|
+
git tag v0.1.0 && git push origin v0.1.0
|
|
90
|
+
# 3. 빌드 & 배포
|
|
91
|
+
uv build
|
|
92
|
+
UV_PUBLISH_TOKEN=$(grep PYPI_TOKEN .env | cut -d= -f2) uv publish
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
---
|
|
96
|
+
|
|
97
|
+
## Core Constitution & References
|
|
98
|
+
|
|
99
|
+
- **범용 규칙**: @AGENT.md
|
|
100
|
+
- **상시 준수 헌법**: @.agentic_python/guidelines.md
|
|
101
|
+
특히 Section 8. The 30 Commandments을 모든 코드 생성/수정 시 자동 체크 & 위반 시 스스로 교정
|
|
102
|
+
- **리뷰 페르소나**: @.agentic_python/reviewer_role.md
|
|
103
|
+
코드 변경 후 또는 /review 시 JSON 채점 형식 준수
|
|
104
|
+
|
|
105
|
+
## Conventions
|
|
106
|
+
|
|
107
|
+
- **호칭**: 사용자를 '대장'으로 인식
|
|
108
|
+
- **응답**: 해결책 위주, 간결하게
|
|
109
|
+
- **The 30 Commandments**: 코드 생성/수정 시 자동 체크 (보안/성능/가독성/타입/아키텍처)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: ollaagent
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.2
|
|
4
4
|
Summary: Local LLM agent powered by ollama — memory, plan mode, subagents
|
|
5
5
|
License-File: LICENSE
|
|
6
6
|
Requires-Python: >=3.11
|
|
@@ -47,14 +47,14 @@ uv sync
|
|
|
47
47
|
## Usage
|
|
48
48
|
|
|
49
49
|
```bash
|
|
50
|
-
# Start the agent
|
|
51
|
-
|
|
50
|
+
# Start the agent (default model: qwen3-coder-next:latest)
|
|
51
|
+
ollaagent
|
|
52
52
|
|
|
53
53
|
# With a specific model
|
|
54
|
-
|
|
54
|
+
ollaagent --model qwen2.5-coder:7b
|
|
55
55
|
|
|
56
56
|
# With a remote ollama host
|
|
57
|
-
|
|
57
|
+
ollaagent --host https://your-ollama.example.com
|
|
58
58
|
```
|
|
59
59
|
|
|
60
60
|
## Built-in Commands
|
|
@@ -88,8 +88,8 @@ Create a `.env` file in the project root:
|
|
|
88
88
|
|
|
89
89
|
```env
|
|
90
90
|
OLLAMA_HOST=http://localhost:11434
|
|
91
|
-
|
|
92
|
-
|
|
91
|
+
CF_ACCESS_CLIENT_ID=
|
|
92
|
+
CF_ACCESS_CLIENT_SECRET=
|
|
93
93
|
```
|
|
94
94
|
|
|
95
95
|
## Project Structure
|
|
@@ -34,14 +34,14 @@ uv sync
|
|
|
34
34
|
## Usage
|
|
35
35
|
|
|
36
36
|
```bash
|
|
37
|
-
# Start the agent
|
|
38
|
-
|
|
37
|
+
# Start the agent (default model: qwen3-coder-next:latest)
|
|
38
|
+
ollaagent
|
|
39
39
|
|
|
40
40
|
# With a specific model
|
|
41
|
-
|
|
41
|
+
ollaagent --model qwen2.5-coder:7b
|
|
42
42
|
|
|
43
43
|
# With a remote ollama host
|
|
44
|
-
|
|
44
|
+
ollaagent --host https://your-ollama.example.com
|
|
45
45
|
```
|
|
46
46
|
|
|
47
47
|
## Built-in Commands
|
|
@@ -75,8 +75,8 @@ Create a `.env` file in the project root:
|
|
|
75
75
|
|
|
76
76
|
```env
|
|
77
77
|
OLLAMA_HOST=http://localhost:11434
|
|
78
|
-
|
|
79
|
-
|
|
78
|
+
CF_ACCESS_CLIENT_ID=
|
|
79
|
+
CF_ACCESS_CLIENT_SECRET=
|
|
80
80
|
```
|
|
81
81
|
|
|
82
82
|
## Project Structure
|
|
@@ -34,14 +34,14 @@ uv sync
|
|
|
34
34
|
## 실행
|
|
35
35
|
|
|
36
36
|
```bash
|
|
37
|
-
# 에이전트 시작
|
|
38
|
-
|
|
37
|
+
# 에이전트 시작 (기본 모델: qwen3-coder-next:latest)
|
|
38
|
+
ollaagent
|
|
39
39
|
|
|
40
40
|
# 모델 지정
|
|
41
|
-
|
|
41
|
+
ollaagent --model qwen2.5-coder:7b
|
|
42
42
|
|
|
43
43
|
# 원격 ollama 호스트 지정
|
|
44
|
-
|
|
44
|
+
ollaagent --host https://your-ollama.example.com
|
|
45
45
|
```
|
|
46
46
|
|
|
47
47
|
## 내장 명령어
|
|
@@ -71,12 +71,12 @@ uv run ollaagent --host https://your-ollama.example.com
|
|
|
71
71
|
|
|
72
72
|
## 환경 설정
|
|
73
73
|
|
|
74
|
-
|
|
74
|
+
`.env` 파일을 `ollaagent`를 실행하는 디렉토리에 생성합니다:
|
|
75
75
|
|
|
76
76
|
```env
|
|
77
77
|
OLLAMA_HOST=http://localhost:11434
|
|
78
|
-
|
|
79
|
-
|
|
78
|
+
CF_ACCESS_CLIENT_ID=
|
|
79
|
+
CF_ACCESS_CLIENT_SECRET=
|
|
80
80
|
```
|
|
81
81
|
|
|
82
82
|
## 프로젝트 구조
|
|
@@ -8,16 +8,17 @@ from functools import partial
|
|
|
8
8
|
from pathlib import Path
|
|
9
9
|
from typing import Any, NamedTuple
|
|
10
10
|
|
|
11
|
-
from ollaAgent.config_loader import build_system_prompt, load_config
|
|
12
11
|
from dotenv import load_dotenv
|
|
13
|
-
from ollaAgent.memory import SESSION_DIR, SessionMemory, save_session
|
|
14
12
|
from ollama import Client
|
|
15
|
-
from ollaAgent.permissions import PermissionConfig
|
|
16
|
-
from ollaAgent.plan_mode import run_plan
|
|
17
13
|
from rich.console import Console
|
|
18
14
|
from rich.live import Live
|
|
19
15
|
from rich.markdown import Markdown
|
|
20
16
|
from rich.panel import Panel
|
|
17
|
+
|
|
18
|
+
from ollaAgent.config_loader import build_system_prompt, load_config
|
|
19
|
+
from ollaAgent.memory import SESSION_DIR, SessionMemory, save_session
|
|
20
|
+
from ollaAgent.permissions import PermissionConfig
|
|
21
|
+
from ollaAgent.plan_mode import run_plan
|
|
21
22
|
from ollaAgent.subagent import SubagentTask, run_subagents
|
|
22
23
|
from ollaAgent.tool_bash import tool_bash
|
|
23
24
|
|
|
@@ -353,7 +354,7 @@ def trim_by_tokens(
|
|
|
353
354
|
|
|
354
355
|
def _accumulate_tool_calls(msg: dict[str, Any], accumulated: dict[int, dict]) -> None:
|
|
355
356
|
"""스트림 chunk에서 tool_calls를 누적한다 (분산 전송 대응)."""
|
|
356
|
-
for tc in msg.get("tool_calls"
|
|
357
|
+
for tc in msg.get("tool_calls") or []:
|
|
357
358
|
idx = tc.get("index", len(accumulated))
|
|
358
359
|
if idx not in accumulated:
|
|
359
360
|
accumulated[idx] = {"name": "", "arguments": ""}
|
|
@@ -644,9 +645,11 @@ def main() -> None:
|
|
|
644
645
|
f"threshold={agent_config.token_threshold:,}[/]"
|
|
645
646
|
)
|
|
646
647
|
conn = ConnectionInfo(
|
|
647
|
-
host="
|
|
648
|
-
cf_client_id=os.getenv("CF_ACCESS_CLIENT_ID"
|
|
649
|
-
|
|
648
|
+
host=os.getenv("OLLAMA_HOST") or agent_config.ollama_host,
|
|
649
|
+
cf_client_id=os.getenv("CF_ACCESS_CLIENT_ID")
|
|
650
|
+
or agent_config.cf_access_client_id,
|
|
651
|
+
cf_client_secret=os.getenv("CF_ACCESS_CLIENT_SECRET")
|
|
652
|
+
or agent_config.cf_access_client_secret,
|
|
650
653
|
)
|
|
651
654
|
client = Client(
|
|
652
655
|
host=conn.host,
|
|
@@ -2,9 +2,10 @@ from pathlib import Path
|
|
|
2
2
|
from typing import Any
|
|
3
3
|
|
|
4
4
|
import yaml
|
|
5
|
-
from ollaAgent.permissions import DEFAULT_DENY_PATTERNS, PermissionMode
|
|
6
5
|
from pydantic import BaseModel
|
|
7
6
|
|
|
7
|
+
from ollaAgent.permissions import DEFAULT_DENY_PATTERNS, PermissionMode
|
|
8
|
+
|
|
8
9
|
# ──────────────────────────────────────────
|
|
9
10
|
# Config 파일 경로 정의
|
|
10
11
|
# ──────────────────────────────────────────
|
|
@@ -34,6 +35,9 @@ class AgentConfig(BaseModel):
|
|
|
34
35
|
max_iterations: int = 10
|
|
35
36
|
deny_patterns: list[str] = DEFAULT_DENY_PATTERNS
|
|
36
37
|
agents_md_path: str = DEFAULT_AGENTS_MD
|
|
38
|
+
ollama_host: str = "http://localhost:11434"
|
|
39
|
+
cf_access_client_id: str = ""
|
|
40
|
+
cf_access_client_secret: str = ""
|
|
37
41
|
|
|
38
42
|
|
|
39
43
|
# ──────────────────────────────────────────
|
|
@@ -67,6 +71,9 @@ def _ensure_global_config(path: Path) -> None:
|
|
|
67
71
|
"max_iterations": default.max_iterations,
|
|
68
72
|
"deny_patterns": default.deny_patterns,
|
|
69
73
|
"agents_md_path": default.agents_md_path,
|
|
74
|
+
"ollama_host": default.ollama_host,
|
|
75
|
+
"cf_access_client_id": default.cf_access_client_id,
|
|
76
|
+
"cf_access_client_secret": default.cf_access_client_secret,
|
|
70
77
|
}
|
|
71
78
|
with path.open("w", encoding="utf-8") as fh:
|
|
72
79
|
yaml.dump(data, fh, allow_unicode=True, default_flow_style=False)
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import os
|
|
2
|
+
|
|
3
|
+
from dotenv import load_dotenv
|
|
4
|
+
from ollama import Client
|
|
5
|
+
|
|
6
|
+
load_dotenv()
|
|
7
|
+
|
|
8
|
+
client = Client(
|
|
9
|
+
host=os.getenv("OLLAMA_HOST", "http://localhost:11434"),
|
|
10
|
+
headers={
|
|
11
|
+
"CF-Access-Client-Id": os.getenv("CF_ACCESS_CLIENT_ID", ""),
|
|
12
|
+
"CF-Access-Client-Secret": os.getenv("CF_ACCESS_CLIENT_SECRET", ""),
|
|
13
|
+
},
|
|
14
|
+
)
|
|
15
|
+
|
|
16
|
+
response = client.chat(
|
|
17
|
+
model="qwen3-coder-next:latest", messages=[{"role": "user", "content": "Hello"}]
|
|
18
|
+
)
|
|
19
|
+
|
|
20
|
+
thinking = response["message"].get("thinking")
|
|
21
|
+
if thinking:
|
|
22
|
+
print("=== Thinking ===")
|
|
23
|
+
print(thinking)
|
|
24
|
+
print("=== Response ===")
|
|
25
|
+
|
|
26
|
+
print(response["message"]["content"])
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
import os
|
|
2
|
-
from dotenv import load_dotenv
|
|
3
|
-
from ollama import Client
|
|
4
|
-
|
|
5
|
-
load_dotenv()
|
|
6
|
-
|
|
7
|
-
client = Client(
|
|
8
|
-
host='https://ollama.nabee.ai.kr',
|
|
9
|
-
headers={
|
|
10
|
-
'CF-Access-Client-Id': os.getenv('CF_ACCESS_CLIENT_ID'),
|
|
11
|
-
'CF-Access-Client-Secret': os.getenv('CF_ACCESS_CLIENT_SECRET'),
|
|
12
|
-
}
|
|
13
|
-
)
|
|
14
|
-
|
|
15
|
-
response = client.chat(
|
|
16
|
-
model='qwen3-coder-next:latest',
|
|
17
|
-
messages=[{'role': 'user', 'content': 'Hello'}]
|
|
18
|
-
)
|
|
19
|
-
|
|
20
|
-
thinking = response['message'].get('thinking')
|
|
21
|
-
if thinking:
|
|
22
|
-
print("=== Thinking ===")
|
|
23
|
-
print(thinking)
|
|
24
|
-
print("=== Response ===")
|
|
25
|
-
|
|
26
|
-
print(response['message']['content'])
|
|
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
|