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.
Files changed (71) hide show
  1. eq_chatbot_core-0.15.0/.claude/settings.local.json +37 -0
  2. eq_chatbot_core-0.15.0/.gitignore +87 -0
  3. eq_chatbot_core-0.15.0/.pre-commit-config.yaml +25 -0
  4. eq_chatbot_core-0.15.0/.project-tips +35 -0
  5. eq_chatbot_core-0.15.0/CHANGELOG.md +153 -0
  6. eq_chatbot_core-0.15.0/CLAUDE.md +200 -0
  7. eq_chatbot_core-0.15.0/LICENSE +21 -0
  8. eq_chatbot_core-0.15.0/MANIFEST.in +5 -0
  9. eq_chatbot_core-0.15.0/PKG-INFO +277 -0
  10. eq_chatbot_core-0.15.0/README.md +228 -0
  11. eq_chatbot_core-0.15.0/TASKS.md +59 -0
  12. eq_chatbot_core-0.15.0/TESTING.md +417 -0
  13. eq_chatbot_core-0.15.0/pyproject.toml +137 -0
  14. eq_chatbot_core-0.15.0/src/eq_chatbot_core/__init__.py +14 -0
  15. eq_chatbot_core-0.15.0/src/eq_chatbot_core/cli.py +298 -0
  16. eq_chatbot_core-0.15.0/src/eq_chatbot_core/mcp/__init__.py +90 -0
  17. eq_chatbot_core-0.15.0/src/eq_chatbot_core/mcp/client.py +884 -0
  18. eq_chatbot_core-0.15.0/src/eq_chatbot_core/providers/__init__.py +150 -0
  19. eq_chatbot_core-0.15.0/src/eq_chatbot_core/providers/anthropic_provider.py +566 -0
  20. eq_chatbot_core-0.15.0/src/eq_chatbot_core/providers/base.py +250 -0
  21. eq_chatbot_core-0.15.0/src/eq_chatbot_core/providers/langdock_provider.py +2131 -0
  22. eq_chatbot_core-0.15.0/src/eq_chatbot_core/providers/local_provider.py +423 -0
  23. eq_chatbot_core-0.15.0/src/eq_chatbot_core/providers/openai_provider.py +399 -0
  24. eq_chatbot_core-0.15.0/src/eq_chatbot_core/providers/openrouter_provider.py +495 -0
  25. eq_chatbot_core-0.15.0/src/eq_chatbot_core/rag/__init__.py +18 -0
  26. eq_chatbot_core-0.15.0/src/eq_chatbot_core/rag/chunker.py +162 -0
  27. eq_chatbot_core-0.15.0/src/eq_chatbot_core/rag/context_manager.py +255 -0
  28. eq_chatbot_core-0.15.0/src/eq_chatbot_core/rag/embedder.py +121 -0
  29. eq_chatbot_core-0.15.0/src/eq_chatbot_core/rag/retriever.py +250 -0
  30. eq_chatbot_core-0.15.0/src/eq_chatbot_core/security/__init__.py +54 -0
  31. eq_chatbot_core-0.15.0/src/eq_chatbot_core/security/encryption.py +138 -0
  32. eq_chatbot_core-0.15.0/src/eq_chatbot_core/security/file_validator.py +357 -0
  33. eq_chatbot_core-0.15.0/src/eq_chatbot_core/security/injection.py +294 -0
  34. eq_chatbot_core-0.15.0/src/eq_chatbot_core/security/rate_limit.py +184 -0
  35. eq_chatbot_core-0.15.0/src/eq_chatbot_core/services/__init__.py +32 -0
  36. eq_chatbot_core-0.15.0/src/eq_chatbot_core/services/cost_service.py +132 -0
  37. eq_chatbot_core-0.15.0/src/eq_chatbot_core/services/error_handler.py +327 -0
  38. eq_chatbot_core-0.15.0/src/eq_chatbot_core/services/knowledge_service.py +607 -0
  39. eq_chatbot_core-0.15.0/src/eq_chatbot_core/utils/__init__.py +18 -0
  40. eq_chatbot_core-0.15.0/src/eq_chatbot_core/utils/pdf.py +134 -0
  41. eq_chatbot_core-0.15.0/src/eq_chatbot_core/utils/pricing.py +7 -0
  42. eq_chatbot_core-0.15.0/src/eq_chatbot_core/version.py +3 -0
  43. eq_chatbot_core-0.15.0/tests/.env.example +71 -0
  44. eq_chatbot_core-0.15.0/tests/INTEGRATION_TESTS.md +261 -0
  45. eq_chatbot_core-0.15.0/tests/__init__.py +1 -0
  46. eq_chatbot_core-0.15.0/tests/conftest.py +733 -0
  47. eq_chatbot_core-0.15.0/tests/integration/__init__.py +0 -0
  48. eq_chatbot_core-0.15.0/tests/integration/test_local_live.py +338 -0
  49. eq_chatbot_core-0.15.0/tests/integration/test_mcp_live.py +237 -0
  50. eq_chatbot_core-0.15.0/tests/integration/test_openai_live.py +416 -0
  51. eq_chatbot_core-0.15.0/tests/reports/latest.md +1024 -0
  52. eq_chatbot_core-0.15.0/tests/unit/__init__.py +0 -0
  53. eq_chatbot_core-0.15.0/tests/unit/test_anthropic.py +758 -0
  54. eq_chatbot_core-0.15.0/tests/unit/test_chunker.py +413 -0
  55. eq_chatbot_core-0.15.0/tests/unit/test_context_manager.py +430 -0
  56. eq_chatbot_core-0.15.0/tests/unit/test_cost_service.py +223 -0
  57. eq_chatbot_core-0.15.0/tests/unit/test_encryption.py +816 -0
  58. eq_chatbot_core-0.15.0/tests/unit/test_error_handler.py +626 -0
  59. eq_chatbot_core-0.15.0/tests/unit/test_exceptions.py +511 -0
  60. eq_chatbot_core-0.15.0/tests/unit/test_factory.py +278 -0
  61. eq_chatbot_core-0.15.0/tests/unit/test_file_validator.py +1191 -0
  62. eq_chatbot_core-0.15.0/tests/unit/test_injection.py +1089 -0
  63. eq_chatbot_core-0.15.0/tests/unit/test_knowledge_service.py +396 -0
  64. eq_chatbot_core-0.15.0/tests/unit/test_langdock.py +964 -0
  65. eq_chatbot_core-0.15.0/tests/unit/test_local.py +703 -0
  66. eq_chatbot_core-0.15.0/tests/unit/test_mcp.py +1189 -0
  67. eq_chatbot_core-0.15.0/tests/unit/test_openai.py +725 -0
  68. eq_chatbot_core-0.15.0/tests/unit/test_openrouter.py +737 -0
  69. eq_chatbot_core-0.15.0/tests/unit/test_rate_limit.py +901 -0
  70. eq_chatbot_core-0.15.0/tests/unit/test_retriever.py +683 -0
  71. 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.
@@ -0,0 +1,5 @@
1
+ include LICENSE
2
+ include README.md
3
+ include CHANGELOG.md
4
+ recursive-exclude tests *
5
+ recursive-exclude .* *