eq-chatbot-core 0.15.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.
- eq_chatbot_core-0.15.0/.claude/settings.local.json +37 -0
- eq_chatbot_core-0.15.0/.gitignore +87 -0
- eq_chatbot_core-0.15.0/.pre-commit-config.yaml +25 -0
- eq_chatbot_core-0.15.0/.project-tips +35 -0
- eq_chatbot_core-0.15.0/CHANGELOG.md +153 -0
- eq_chatbot_core-0.15.0/CLAUDE.md +200 -0
- eq_chatbot_core-0.15.0/LICENSE +21 -0
- eq_chatbot_core-0.15.0/MANIFEST.in +5 -0
- eq_chatbot_core-0.15.0/PKG-INFO +277 -0
- eq_chatbot_core-0.15.0/README.md +228 -0
- eq_chatbot_core-0.15.0/TASKS.md +59 -0
- eq_chatbot_core-0.15.0/TESTING.md +417 -0
- eq_chatbot_core-0.15.0/pyproject.toml +137 -0
- eq_chatbot_core-0.15.0/src/eq_chatbot_core/__init__.py +14 -0
- eq_chatbot_core-0.15.0/src/eq_chatbot_core/cli.py +298 -0
- eq_chatbot_core-0.15.0/src/eq_chatbot_core/mcp/__init__.py +90 -0
- eq_chatbot_core-0.15.0/src/eq_chatbot_core/mcp/client.py +884 -0
- eq_chatbot_core-0.15.0/src/eq_chatbot_core/providers/__init__.py +150 -0
- eq_chatbot_core-0.15.0/src/eq_chatbot_core/providers/anthropic_provider.py +566 -0
- eq_chatbot_core-0.15.0/src/eq_chatbot_core/providers/base.py +250 -0
- eq_chatbot_core-0.15.0/src/eq_chatbot_core/providers/langdock_provider.py +2131 -0
- eq_chatbot_core-0.15.0/src/eq_chatbot_core/providers/local_provider.py +423 -0
- eq_chatbot_core-0.15.0/src/eq_chatbot_core/providers/openai_provider.py +399 -0
- eq_chatbot_core-0.15.0/src/eq_chatbot_core/providers/openrouter_provider.py +495 -0
- eq_chatbot_core-0.15.0/src/eq_chatbot_core/rag/__init__.py +18 -0
- eq_chatbot_core-0.15.0/src/eq_chatbot_core/rag/chunker.py +162 -0
- eq_chatbot_core-0.15.0/src/eq_chatbot_core/rag/context_manager.py +255 -0
- eq_chatbot_core-0.15.0/src/eq_chatbot_core/rag/embedder.py +121 -0
- eq_chatbot_core-0.15.0/src/eq_chatbot_core/rag/retriever.py +250 -0
- eq_chatbot_core-0.15.0/src/eq_chatbot_core/security/__init__.py +54 -0
- eq_chatbot_core-0.15.0/src/eq_chatbot_core/security/encryption.py +138 -0
- eq_chatbot_core-0.15.0/src/eq_chatbot_core/security/file_validator.py +357 -0
- eq_chatbot_core-0.15.0/src/eq_chatbot_core/security/injection.py +294 -0
- eq_chatbot_core-0.15.0/src/eq_chatbot_core/security/rate_limit.py +184 -0
- eq_chatbot_core-0.15.0/src/eq_chatbot_core/services/__init__.py +32 -0
- eq_chatbot_core-0.15.0/src/eq_chatbot_core/services/cost_service.py +132 -0
- eq_chatbot_core-0.15.0/src/eq_chatbot_core/services/error_handler.py +327 -0
- eq_chatbot_core-0.15.0/src/eq_chatbot_core/services/knowledge_service.py +607 -0
- eq_chatbot_core-0.15.0/src/eq_chatbot_core/utils/__init__.py +18 -0
- eq_chatbot_core-0.15.0/src/eq_chatbot_core/utils/pdf.py +134 -0
- eq_chatbot_core-0.15.0/src/eq_chatbot_core/utils/pricing.py +7 -0
- eq_chatbot_core-0.15.0/src/eq_chatbot_core/version.py +3 -0
- eq_chatbot_core-0.15.0/tests/.env.example +71 -0
- eq_chatbot_core-0.15.0/tests/INTEGRATION_TESTS.md +261 -0
- eq_chatbot_core-0.15.0/tests/__init__.py +1 -0
- eq_chatbot_core-0.15.0/tests/conftest.py +733 -0
- eq_chatbot_core-0.15.0/tests/integration/__init__.py +0 -0
- eq_chatbot_core-0.15.0/tests/integration/test_local_live.py +338 -0
- eq_chatbot_core-0.15.0/tests/integration/test_mcp_live.py +237 -0
- eq_chatbot_core-0.15.0/tests/integration/test_openai_live.py +416 -0
- eq_chatbot_core-0.15.0/tests/reports/latest.md +1024 -0
- eq_chatbot_core-0.15.0/tests/unit/__init__.py +0 -0
- eq_chatbot_core-0.15.0/tests/unit/test_anthropic.py +758 -0
- eq_chatbot_core-0.15.0/tests/unit/test_chunker.py +413 -0
- eq_chatbot_core-0.15.0/tests/unit/test_context_manager.py +430 -0
- eq_chatbot_core-0.15.0/tests/unit/test_cost_service.py +223 -0
- eq_chatbot_core-0.15.0/tests/unit/test_encryption.py +816 -0
- eq_chatbot_core-0.15.0/tests/unit/test_error_handler.py +626 -0
- eq_chatbot_core-0.15.0/tests/unit/test_exceptions.py +511 -0
- eq_chatbot_core-0.15.0/tests/unit/test_factory.py +278 -0
- eq_chatbot_core-0.15.0/tests/unit/test_file_validator.py +1191 -0
- eq_chatbot_core-0.15.0/tests/unit/test_injection.py +1089 -0
- eq_chatbot_core-0.15.0/tests/unit/test_knowledge_service.py +396 -0
- eq_chatbot_core-0.15.0/tests/unit/test_langdock.py +964 -0
- eq_chatbot_core-0.15.0/tests/unit/test_local.py +703 -0
- eq_chatbot_core-0.15.0/tests/unit/test_mcp.py +1189 -0
- eq_chatbot_core-0.15.0/tests/unit/test_openai.py +725 -0
- eq_chatbot_core-0.15.0/tests/unit/test_openrouter.py +737 -0
- eq_chatbot_core-0.15.0/tests/unit/test_rate_limit.py +901 -0
- eq_chatbot_core-0.15.0/tests/unit/test_retriever.py +683 -0
- eq_chatbot_core-0.15.0/uv.lock +2696 -0
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
{
|
|
2
|
+
"permissions": {
|
|
3
|
+
"allow": [
|
|
4
|
+
"Skill(eq-chatbot-core)",
|
|
5
|
+
"Skill(v18-chatbot)",
|
|
6
|
+
"Skill(odoo18)",
|
|
7
|
+
"Bash(mv:*)",
|
|
8
|
+
"Bash(pytest:*)",
|
|
9
|
+
"Skill(finalize)",
|
|
10
|
+
"Bash(git add:*)",
|
|
11
|
+
"Bash(git commit:*)",
|
|
12
|
+
"Bash(git push:*)",
|
|
13
|
+
"Bash(MCP_TEST_URL=\"http://127.0.0.1:8000/sse\" pytest tests/integration/test_mcp_live.py -v -s)",
|
|
14
|
+
"Bash(MCP_TEST_URL=\"http://127.0.0.1:8000/sse\" pytest tests/integration/test_mcp_live.py::TestMCPLive::test_list_tools_detailed -v -s)",
|
|
15
|
+
"Bash(MCP_TEST_URL=\"http://127.0.0.1:8000/sse\" pytest tests/integration/test_mcp_live.py -v)",
|
|
16
|
+
"Bash(python3:*)",
|
|
17
|
+
"Bash(ping:*)",
|
|
18
|
+
"Bash(ruff check:*)",
|
|
19
|
+
"Bash(black src/:*)",
|
|
20
|
+
"Bash(mypy:*)",
|
|
21
|
+
"Bash(twine check:*)",
|
|
22
|
+
"Bash(tar:*)",
|
|
23
|
+
"Bash(eq-chatbot info:*)",
|
|
24
|
+
"Bash(for f in /Users/picard/gitbase/PyPi-Projects/eq_chatbot_core/tests/unit/*.py)",
|
|
25
|
+
"Bash(done)",
|
|
26
|
+
"Bash(for:*)",
|
|
27
|
+
"Bash(black:*)",
|
|
28
|
+
"Bash(pip-audit:*)",
|
|
29
|
+
"Bash(git -C /Users/picard/gitbase/PyPi-Projects/eq_chatbot_core commit -m \"$\\(cat <<''EOF''\n[CHG] v0.14.0 - Security hardening, bug fixes, dependency updates, unit tests\n\n- Fix chunker infinite-loop bug when chunk_overlap >= chunk_size\n- Add configurable error messages to ChatbotErrorHandler \\(i18n-ready\\)\n- Add MCP client thread-safety \\(_pending_lock for concurrent requests\\)\n- Add Unicode NFKD normalization to injection detection\n- Add error handling to retriever \\(embedder + Qdrant failures\\)\n- Add context manager budget validation \\(ratio sum check\\)\n- Add longest-prefix matching to cost service\n- Add jitter to error handler retry backoff\n- Stricter MIME-type aliases in file validator\n- Fix Anthropic tool input serialization \\(json.dumps instead of str\\)\n- Add SSE parse error logging to OpenRouter provider\n- Update pricing table \\(Feb 2025: Claude 4.x, o3, gpt-4o corrected\\)\n- Raise minimum dependency versions \\(cryptography>=44, openai>=1.58, etc.\\)\n- Modernize ruff config to [tool.ruff.lint] section\n- Add 9 new unit test modules \\(918 tests total, 0 failures\\)\n- Add TASKS.md tracking document\n\nCo-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>\nEOF\n\\)\")",
|
|
30
|
+
"Bash(ruff format:*)",
|
|
31
|
+
"Bash(git check-ignore:*)",
|
|
32
|
+
"Bash(echo:*)",
|
|
33
|
+
"Bash(grep:*)",
|
|
34
|
+
"Bash(git remote add:*)"
|
|
35
|
+
]
|
|
36
|
+
}
|
|
37
|
+
}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
# Byte-compiled / optimized / DLL files
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*$py.class
|
|
5
|
+
|
|
6
|
+
# C extensions
|
|
7
|
+
*.so
|
|
8
|
+
|
|
9
|
+
# Distribution / packaging
|
|
10
|
+
.Python
|
|
11
|
+
build/
|
|
12
|
+
develop-eggs/
|
|
13
|
+
dist/
|
|
14
|
+
downloads/
|
|
15
|
+
eggs/
|
|
16
|
+
.eggs/
|
|
17
|
+
lib/
|
|
18
|
+
lib64/
|
|
19
|
+
parts/
|
|
20
|
+
sdist/
|
|
21
|
+
var/
|
|
22
|
+
wheels/
|
|
23
|
+
*.egg-info/
|
|
24
|
+
.installed.cfg
|
|
25
|
+
*.egg
|
|
26
|
+
|
|
27
|
+
# PyInstaller
|
|
28
|
+
*.manifest
|
|
29
|
+
*.spec
|
|
30
|
+
|
|
31
|
+
# Installer logs
|
|
32
|
+
pip-log.txt
|
|
33
|
+
pip-delete-this-directory.txt
|
|
34
|
+
|
|
35
|
+
# Unit test / coverage reports
|
|
36
|
+
htmlcov/
|
|
37
|
+
.tox/
|
|
38
|
+
.nox/
|
|
39
|
+
.coverage
|
|
40
|
+
.coverage.*
|
|
41
|
+
.cache
|
|
42
|
+
nosetests.xml
|
|
43
|
+
coverage.xml
|
|
44
|
+
*.cover
|
|
45
|
+
*.py,cover
|
|
46
|
+
.hypothesis/
|
|
47
|
+
.pytest_cache/
|
|
48
|
+
|
|
49
|
+
# Translations
|
|
50
|
+
*.mo
|
|
51
|
+
*.pot
|
|
52
|
+
|
|
53
|
+
# Environments
|
|
54
|
+
.env
|
|
55
|
+
.venv
|
|
56
|
+
env/
|
|
57
|
+
venv/
|
|
58
|
+
ENV/
|
|
59
|
+
env.bak/
|
|
60
|
+
venv.bak/
|
|
61
|
+
|
|
62
|
+
# IDE
|
|
63
|
+
.idea/
|
|
64
|
+
.vscode/
|
|
65
|
+
*.swp
|
|
66
|
+
*.swo
|
|
67
|
+
*~
|
|
68
|
+
|
|
69
|
+
# mypy
|
|
70
|
+
.mypy_cache/
|
|
71
|
+
.dmypy.json
|
|
72
|
+
dmypy.json
|
|
73
|
+
|
|
74
|
+
# ruff
|
|
75
|
+
.ruff_cache/
|
|
76
|
+
|
|
77
|
+
# OS
|
|
78
|
+
.DS_Store
|
|
79
|
+
Thumbs.db
|
|
80
|
+
|
|
81
|
+
# Project specific
|
|
82
|
+
*.log
|
|
83
|
+
.env.local
|
|
84
|
+
.env.test
|
|
85
|
+
tests/.env.test
|
|
86
|
+
tests/reports/test-report-*.md
|
|
87
|
+
!tests/reports/latest.md
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
repos:
|
|
2
|
+
- repo: https://github.com/pre-commit/pre-commit-hooks
|
|
3
|
+
rev: v4.5.0
|
|
4
|
+
hooks:
|
|
5
|
+
- id: trailing-whitespace
|
|
6
|
+
- id: end-of-file-fixer
|
|
7
|
+
- id: check-yaml
|
|
8
|
+
- id: check-added-large-files
|
|
9
|
+
- id: check-merge-conflict
|
|
10
|
+
|
|
11
|
+
- repo: https://github.com/astral-sh/ruff-pre-commit
|
|
12
|
+
rev: v0.1.9
|
|
13
|
+
hooks:
|
|
14
|
+
- id: ruff
|
|
15
|
+
args: [--fix, --exit-non-zero-on-fix]
|
|
16
|
+
- id: ruff-format
|
|
17
|
+
|
|
18
|
+
- repo: https://github.com/pre-commit/mirrors-mypy
|
|
19
|
+
rev: v1.8.0
|
|
20
|
+
hooks:
|
|
21
|
+
- id: mypy
|
|
22
|
+
additional_dependencies:
|
|
23
|
+
- types-requests
|
|
24
|
+
- pydantic
|
|
25
|
+
args: [--ignore-missing-imports]
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# eq-chatbot-core Quick Reference
|
|
2
|
+
# PyPI: https://pypi.org/project/eq-chatbot-core/
|
|
3
|
+
# GitHub: https://github.com/equitania/eq-chatbot-core
|
|
4
|
+
|
|
5
|
+
## Setup
|
|
6
|
+
uv venv && source .venv/bin/activate
|
|
7
|
+
uv pip install -e ".[dev,pdf,security]"
|
|
8
|
+
|
|
9
|
+
## Test
|
|
10
|
+
pytest tests/unit/ -v # Unit tests (fast, mocked)
|
|
11
|
+
pytest tests/ -v --cov=eq_chatbot_core # All tests with coverage
|
|
12
|
+
|
|
13
|
+
## Lint
|
|
14
|
+
ruff check src/ && ruff format src/ --check # Check
|
|
15
|
+
ruff check src/ --fix && ruff format src/ # Fix
|
|
16
|
+
|
|
17
|
+
## Build
|
|
18
|
+
rm -rf dist/
|
|
19
|
+
uv build
|
|
20
|
+
twine check dist/*
|
|
21
|
+
|
|
22
|
+
## Publish (TestPyPI)
|
|
23
|
+
uv publish --publish-url https://test.pypi.org/legacy/
|
|
24
|
+
|
|
25
|
+
## Publish (PyPI)
|
|
26
|
+
uv publish
|
|
27
|
+
|
|
28
|
+
## CLI
|
|
29
|
+
eq-chatbot info
|
|
30
|
+
eq-chatbot test-provider -p openai -k $OPENAI_API_KEY
|
|
31
|
+
eq-chatbot list-models -p openai -k $OPENAI_API_KEY --json
|
|
32
|
+
|
|
33
|
+
## Git Push (both remotes)
|
|
34
|
+
git push origin main --tags
|
|
35
|
+
git push upstream main --tags
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to eq-chatbot-core will be documented in this file.
|
|
4
|
+
|
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
|
+
|
|
8
|
+
## [0.15.0] - 2026-02-09
|
|
9
|
+
|
|
10
|
+
### Changed
|
|
11
|
+
|
|
12
|
+
- Tighten dependency version ranges with upper bounds (openai <3, anthropic <1, httpx <1, etc.)
|
|
13
|
+
- Replace python-magic with puremagic (pure Python, no libmagic system dependency)
|
|
14
|
+
- Replace black dependency, use ruff format exclusively
|
|
15
|
+
- Add twine to dev dependencies, add Python 3.13 classifier
|
|
16
|
+
- Update pre-commit config: replace black hook with ruff-format
|
|
17
|
+
|
|
18
|
+
### Added
|
|
19
|
+
|
|
20
|
+
- MCP client SSRF protection (private IP blocking, HTTP/HTTPS scheme validation)
|
|
21
|
+
- MCP stdio command whitelist (python, node, uvx, uv) and shell metachar validation
|
|
22
|
+
- 22 new unit tests for MCP validation (940 total, 0 failures)
|
|
23
|
+
|
|
24
|
+
### Fixed
|
|
25
|
+
|
|
26
|
+
- Replace bare `except Exception` handlers with specific catches + logging
|
|
27
|
+
|
|
28
|
+
## [0.14.0] - 2026-02-07
|
|
29
|
+
|
|
30
|
+
### Added
|
|
31
|
+
|
|
32
|
+
- Configurable error messages to ChatbotErrorHandler (i18n-ready)
|
|
33
|
+
- MCP client thread-safety (`_pending_lock` for concurrent requests)
|
|
34
|
+
- Unicode NFKD normalization to injection detection
|
|
35
|
+
- Error handling to retriever (embedder + Qdrant failures)
|
|
36
|
+
- Context manager budget validation (ratio sum check)
|
|
37
|
+
- Longest-prefix matching to cost service
|
|
38
|
+
- Jitter to error handler retry backoff
|
|
39
|
+
- 9 new unit test modules (918 tests total, 0 failures)
|
|
40
|
+
- TASKS.md tracking document
|
|
41
|
+
|
|
42
|
+
### Fixed
|
|
43
|
+
|
|
44
|
+
- Chunker infinite-loop bug when `chunk_overlap >= chunk_size`
|
|
45
|
+
- Anthropic tool input serialization (`json.dumps` instead of `str`)
|
|
46
|
+
|
|
47
|
+
### Changed
|
|
48
|
+
|
|
49
|
+
- Stricter MIME-type aliases in file validator
|
|
50
|
+
- Add SSE parse error logging to OpenRouter provider
|
|
51
|
+
- Update pricing table (Feb 2025: Claude 4.x, o3, gpt-4o corrected)
|
|
52
|
+
- Raise minimum dependency versions (cryptography>=44, openai>=1.58, etc.)
|
|
53
|
+
- Modernize ruff config to `[tool.ruff.lint]` section
|
|
54
|
+
|
|
55
|
+
## [0.13.0] - 2025-01-22
|
|
56
|
+
|
|
57
|
+
### Added
|
|
58
|
+
|
|
59
|
+
- **OverloadedError Exception**: New exception type for transient server overload errors (529/503)
|
|
60
|
+
- Distinct from RateLimitError for better retry handling
|
|
61
|
+
- Used by Anthropic provider for overload_error responses
|
|
62
|
+
- Properly exported from providers module
|
|
63
|
+
|
|
64
|
+
### Fixed
|
|
65
|
+
|
|
66
|
+
- **CLI AttributeError**: Fixed CLI `list-models` command crashing
|
|
67
|
+
- Changed `m.model_id` to `m.id` (matching ModelInfo dataclass)
|
|
68
|
+
- Removed non-existent `supports_temperature` and `max_tokens` attributes
|
|
69
|
+
- Fixed token usage display using correct `LLMResponse` attributes
|
|
70
|
+
- **README Examples**: Updated code examples to use correct API
|
|
71
|
+
- `response.usage.total_tokens` → `response.total_tokens`
|
|
72
|
+
- `model.model_id` → `model.id`
|
|
73
|
+
- **Export Completeness**: Added `OverloadedError` to `__all__` in providers module
|
|
74
|
+
- **MANIFEST.in**: Added manifest file to include LICENSE, README, CHANGELOG in sdist
|
|
75
|
+
|
|
76
|
+
### Changed
|
|
77
|
+
|
|
78
|
+
- Improved JSON output in `list-models` command with more model metadata
|
|
79
|
+
- Now includes: id, name, provider, supports_vision, supports_tools, supports_streaming, context_length
|
|
80
|
+
|
|
81
|
+
## [0.12.0] - 2025-01-17
|
|
82
|
+
|
|
83
|
+
### Added
|
|
84
|
+
|
|
85
|
+
- **OpenRouter Provider**: Access to 400+ AI models through unified API
|
|
86
|
+
- Supports OpenAI, Anthropic, Google, Meta, Mistral, and many more models
|
|
87
|
+
- Model ID format: `provider/model-name` (e.g., `openai/gpt-4o`, `anthropic/claude-3.5-sonnet`)
|
|
88
|
+
- Reasoning model detection for O1/O3/O4 series (auto-disables temperature)
|
|
89
|
+
- Streaming with tool-call accumulation
|
|
90
|
+
- Dynamic model list with constraints and pricing metadata
|
|
91
|
+
- Vision support detection from input_modalities
|
|
92
|
+
- Pricing extraction (input/output/image costs)
|
|
93
|
+
- OpenRouter support in provider factory: `get_provider("openrouter", api_key="...")`
|
|
94
|
+
- Comprehensive unit tests for OpenRouter provider (31 tests)
|
|
95
|
+
|
|
96
|
+
## [0.9.1] - 2025-12-30
|
|
97
|
+
|
|
98
|
+
### Fixed
|
|
99
|
+
|
|
100
|
+
- LangDock Provider: Added tool call accumulation for Anthropic backend streaming
|
|
101
|
+
- Handles content_block_start events for tool_use blocks
|
|
102
|
+
- Handles input_json_delta events for tool arguments
|
|
103
|
+
- Returns complete tool_calls on final StreamChunk
|
|
104
|
+
- MCP tool execution now works correctly with LangDock Anthropic backend
|
|
105
|
+
|
|
106
|
+
## [0.9.0] - 2025-12-30
|
|
107
|
+
|
|
108
|
+
### Added
|
|
109
|
+
|
|
110
|
+
- `StreamChunk.tool_calls` field for complete tool call data on final streaming chunk
|
|
111
|
+
- Tool call accumulation in streaming for all providers:
|
|
112
|
+
- OpenAI Provider: Accumulates tool_call_delta into complete tool_calls
|
|
113
|
+
- LangDock Provider: Same accumulation for OpenAI-compatible streaming
|
|
114
|
+
- Anthropic Provider: Handles content_block_start/input_json_delta events
|
|
115
|
+
|
|
116
|
+
### Fixed
|
|
117
|
+
|
|
118
|
+
- Streaming with function calling now properly returns accumulated tool calls
|
|
119
|
+
- Tool execution loop can now access complete tool call data from final StreamChunk
|
|
120
|
+
|
|
121
|
+
## [0.6.0] - 2025-12-29
|
|
122
|
+
|
|
123
|
+
### Added
|
|
124
|
+
|
|
125
|
+
- First standalone PyPI release
|
|
126
|
+
- CLI tool `eq-chatbot` with commands:
|
|
127
|
+
- `test-provider` - Test LLM provider connections
|
|
128
|
+
- `list-models` - List available models from providers
|
|
129
|
+
- `info` - Show package information
|
|
130
|
+
- Click framework for CLI implementation
|
|
131
|
+
- MIT License
|
|
132
|
+
|
|
133
|
+
### Changed
|
|
134
|
+
|
|
135
|
+
- Extracted from v18-chatbot monorepo to standalone package
|
|
136
|
+
- License changed from Proprietary to MIT
|
|
137
|
+
- Updated project URLs to GitHub
|
|
138
|
+
- Development status changed to Beta
|
|
139
|
+
|
|
140
|
+
### Previous History
|
|
141
|
+
|
|
142
|
+
This package was previously developed as part of the v18-chatbot project:
|
|
143
|
+
|
|
144
|
+
- 0.5.6: LangDock attachment upload URL fix
|
|
145
|
+
- 0.5.5: LangDock provider upload_attachment wrapper
|
|
146
|
+
- 0.5.4: LangDock Agent file upload support
|
|
147
|
+
- 0.5.3: Agent multimodal warning
|
|
148
|
+
- 0.5.2: Anthropic provider vision detection fix
|
|
149
|
+
- 0.5.1: Gemini multimodal format conversion
|
|
150
|
+
- 0.5.0: PDF-to-image conversion, model-based content format
|
|
151
|
+
- 0.4.2: Vision support detection improvements
|
|
152
|
+
- 0.4.1: File validator false positive fixes
|
|
153
|
+
- 0.4.0: Initial providers, security, RAG modules
|
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
# CLAUDE.md
|
|
2
|
+
|
|
3
|
+
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
|
4
|
+
|
|
5
|
+
## Project Overview
|
|
6
|
+
|
|
7
|
+
Standalone Python library for LLM chatbot integration. Provides unified API across multiple providers (OpenAI, Anthropic, LangDock, OpenRouter, local servers). Originally extracted from v18-chatbot Odoo project for independent PyPI publishing.
|
|
8
|
+
|
|
9
|
+
## Commands
|
|
10
|
+
|
|
11
|
+
### Development Setup
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
uv venv && source .venv/bin/activate # or: venv+
|
|
15
|
+
uv pip install -e ".[dev,pdf,security]"
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
### Testing
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
# Run all unit tests (fast, mocked)
|
|
22
|
+
pytest tests/unit/ -v
|
|
23
|
+
|
|
24
|
+
# Run all tests with coverage
|
|
25
|
+
pytest tests/ -v --cov=eq_chatbot_core --cov-report=html
|
|
26
|
+
|
|
27
|
+
# Run single test file
|
|
28
|
+
pytest tests/unit/test_openai.py -v
|
|
29
|
+
|
|
30
|
+
# Run single test function
|
|
31
|
+
pytest tests/unit/test_openai.py::TestOpenAIProviderInit::test_basic_init -v
|
|
32
|
+
|
|
33
|
+
# Run tests by marker
|
|
34
|
+
pytest -m unit -v # Unit tests only (mocked)
|
|
35
|
+
pytest -m integration -v # Integration tests (real API calls)
|
|
36
|
+
pytest -m local -v # Local server tests
|
|
37
|
+
|
|
38
|
+
# Skip expensive tests
|
|
39
|
+
SKIP_LIVE_TESTS=true pytest tests/ -v
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
### Linting
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
ruff check src/ && ruff format src/ --check # Check only
|
|
46
|
+
ruff check src/ --fix && ruff format src/ # Auto-fix
|
|
47
|
+
mypy src/ # Type checking
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
### Building
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
python -m build # Build package
|
|
54
|
+
twine check dist/* # Verify package
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
## Architecture
|
|
58
|
+
|
|
59
|
+
### Provider Factory Pattern
|
|
60
|
+
|
|
61
|
+
All providers use a factory function with consistent interface:
|
|
62
|
+
|
|
63
|
+
```python
|
|
64
|
+
from eq_chatbot_core.providers import get_provider
|
|
65
|
+
|
|
66
|
+
# Cloud providers
|
|
67
|
+
provider = get_provider("openai", api_key="sk-...")
|
|
68
|
+
provider = get_provider("anthropic", api_key="sk-ant-...")
|
|
69
|
+
provider = get_provider("langdock", api_key="ld-...")
|
|
70
|
+
provider = get_provider("openrouter", api_key="sk-or-...")
|
|
71
|
+
|
|
72
|
+
# Local providers (LM Studio, Ollama)
|
|
73
|
+
provider = get_provider("lm_studio") # defaults to localhost:1234
|
|
74
|
+
provider = get_provider("ollama") # defaults to localhost:11434
|
|
75
|
+
provider = get_provider("local", base_url="http://custom:port/v1")
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
### Provider Base Class
|
|
79
|
+
|
|
80
|
+
All providers inherit from `BaseLLMProvider` and must implement:
|
|
81
|
+
|
|
82
|
+
```python
|
|
83
|
+
class BaseLLMProvider(ABC):
|
|
84
|
+
provider_name: str # Property: "openai", "anthropic", etc.
|
|
85
|
+
default_model: str # Property: Default model ID
|
|
86
|
+
|
|
87
|
+
def chat_completion(messages, model, temperature, max_tokens, tools) -> LLMResponse
|
|
88
|
+
def stream_completion(messages, model, ...) -> Iterator[StreamChunk]
|
|
89
|
+
def list_models() -> list[dict]
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
### Response Types
|
|
93
|
+
|
|
94
|
+
- `LLMResponse`: Complete response with content, token counts, tool_calls
|
|
95
|
+
- `StreamChunk`: Streaming delta with is_final flag and accumulated tool_calls
|
|
96
|
+
- `ModelInfo`: Model metadata (id, context_length, supports_vision, etc.)
|
|
97
|
+
|
|
98
|
+
### Exception Hierarchy
|
|
99
|
+
|
|
100
|
+
```
|
|
101
|
+
ProviderError (base)
|
|
102
|
+
├── RateLimitError # 429 errors, has retry_after
|
|
103
|
+
├── AuthenticationError # 401/403 errors
|
|
104
|
+
├── ContextLengthError # Token limit exceeded
|
|
105
|
+
└── OverloadedError # 529/503 transient errors (retryable)
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
### Module Structure
|
|
109
|
+
|
|
110
|
+
```
|
|
111
|
+
src/eq_chatbot_core/
|
|
112
|
+
├── providers/ # LLM adapters
|
|
113
|
+
│ ├── base.py # BaseLLMProvider, response types, exceptions
|
|
114
|
+
│ ├── openai_provider.py # OpenAI + Azure
|
|
115
|
+
│ ├── anthropic_provider.py
|
|
116
|
+
│ ├── langdock_provider.py # LangDock gateway (EU/US regions)
|
|
117
|
+
│ ├── openrouter_provider.py # OpenRouter (400+ models)
|
|
118
|
+
│ └── local_provider.py # LM Studio, Ollama (OpenAI-compatible)
|
|
119
|
+
├── security/
|
|
120
|
+
│ ├── encryption.py # FernetEncryption for API key storage
|
|
121
|
+
│ ├── injection.py # Prompt injection detection
|
|
122
|
+
│ ├── rate_limit.py # Token bucket rate limiter
|
|
123
|
+
│ └── file_validator.py # MIME type validation (requires [security])
|
|
124
|
+
├── rag/
|
|
125
|
+
│ ├── chunker.py # Text chunking strategies
|
|
126
|
+
│ ├── embedder.py # Embedding generation
|
|
127
|
+
│ ├── retriever.py # Qdrant vector retrieval
|
|
128
|
+
│ └── context_manager.py # RAG context assembly
|
|
129
|
+
├── mcp/
|
|
130
|
+
│ └── client.py # MCP client (HTTP/SSE and stdio transports)
|
|
131
|
+
├── services/
|
|
132
|
+
│ ├── cost_service.py # Token cost calculation
|
|
133
|
+
│ ├── error_handler.py # Centralized error handling
|
|
134
|
+
│ └── knowledge_service.py # Knowledge export for vector DBs
|
|
135
|
+
├── utils/
|
|
136
|
+
│ ├── pricing.py # Model pricing data
|
|
137
|
+
│ └── pdf.py # PDF to image (requires [pdf])
|
|
138
|
+
├── cli.py # Click CLI: eq-chatbot
|
|
139
|
+
└── version.py # Version string
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
## Testing Patterns
|
|
143
|
+
|
|
144
|
+
### Unit Test Structure
|
|
145
|
+
|
|
146
|
+
Unit tests mock SDK clients at module level to avoid API calls:
|
|
147
|
+
|
|
148
|
+
```python
|
|
149
|
+
import sys
|
|
150
|
+
from unittest.mock import MagicMock
|
|
151
|
+
|
|
152
|
+
# Mock before importing provider
|
|
153
|
+
mock_openai_module = MagicMock()
|
|
154
|
+
sys.modules["openai"] = mock_openai_module
|
|
155
|
+
|
|
156
|
+
from eq_chatbot_core.providers.openai_provider import OpenAIProvider
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
### Test Markers
|
|
160
|
+
|
|
161
|
+
- `@pytest.mark.unit` - Mocked tests, no external dependencies
|
|
162
|
+
- `@pytest.mark.integration` - Real API calls, requires keys
|
|
163
|
+
- `@pytest.mark.local` - Requires running LM Studio/Ollama
|
|
164
|
+
- `@pytest.mark.expensive` - Uses expensive models, skipped in CI
|
|
165
|
+
- `@pytest.mark.slow` - Long-running tests
|
|
166
|
+
|
|
167
|
+
### Test Configuration
|
|
168
|
+
|
|
169
|
+
Copy `tests/.env.example` to `tests/.env.test` for API keys. Environment variables:
|
|
170
|
+
|
|
171
|
+
- `OPENAI_API_KEY`, `ANTHROPIC_API_KEY`, `LANGDOCK_API_KEY`
|
|
172
|
+
- `SKIP_LIVE_TESTS=true` - Skip integration tests
|
|
173
|
+
- `SKIP_LOCAL_TESTS=true` - Skip local server tests
|
|
174
|
+
- `TEST_MAX_TOKENS=20` - Limit tokens for cost control
|
|
175
|
+
|
|
176
|
+
### Fixtures (conftest.py)
|
|
177
|
+
|
|
178
|
+
- `test_config` - Session config from environment
|
|
179
|
+
- `mock_openai_client`, `mock_anthropic_client` - Pre-configured mocks
|
|
180
|
+
- `sample_messages`, `minimal_test_messages` - Test data
|
|
181
|
+
- `openai_provider`, `anthropic_provider` - Live provider instances
|
|
182
|
+
|
|
183
|
+
## Git Commit Conventions
|
|
184
|
+
|
|
185
|
+
- `[ADD]` - New features
|
|
186
|
+
- `[CHG]` - Modifications
|
|
187
|
+
- `[FIX]` - Bug fixes
|
|
188
|
+
|
|
189
|
+
## Dependencies
|
|
190
|
+
|
|
191
|
+
### Core (always installed)
|
|
192
|
+
|
|
193
|
+
openai, anthropic, httpx, pydantic, cryptography, tiktoken, qdrant-client, click
|
|
194
|
+
|
|
195
|
+
### Optional
|
|
196
|
+
|
|
197
|
+
- `[dev]` - pytest, ruff, mypy, twine, pytest-cov, pytest-asyncio
|
|
198
|
+
- `[security]` - puremagic (MIME validation)
|
|
199
|
+
- `[pdf]` - pymupdf (PDF to image conversion)
|
|
200
|
+
- `[local]` - sentence-transformers (local embeddings)
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Equitania Software GmbH
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|