kiarina-llm 1.0.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.
- kiarina_llm-1.0.0/.gitignore +39 -0
- kiarina_llm-1.0.0/CHANGELOG.md +41 -0
- kiarina_llm-1.0.0/PKG-INFO +286 -0
- kiarina_llm-1.0.0/README.md +257 -0
- kiarina_llm-1.0.0/pyproject.toml +45 -0
- kiarina_llm-1.0.0/src/kiarina/llm/__init__.py +3 -0
- kiarina_llm-1.0.0/src/kiarina/llm/py.typed +0 -0
- kiarina_llm-1.0.0/src/kiarina/llm/run_context/__init__.py +9 -0
- kiarina_llm-1.0.0/src/kiarina/llm/run_context/_model.py +76 -0
- kiarina_llm-1.0.0/src/kiarina/llm/run_context/_registry.py +34 -0
- kiarina_llm-1.0.0/src/kiarina/llm/run_context/_types/__init__.py +0 -0
- kiarina_llm-1.0.0/src/kiarina/llm/run_context/_types/fs_name.py +52 -0
- kiarina_llm-1.0.0/src/kiarina/llm/run_context/_types/id_str.py +15 -0
- kiarina_llm-1.0.0/src/kiarina/llm/run_context/settings.py +80 -0
- kiarina_llm-1.0.0/tests/conftest.py +0 -0
- kiarina_llm-1.0.0/tests/run_context/__init__.py +0 -0
- kiarina_llm-1.0.0/tests/run_context/conftest.py +12 -0
- kiarina_llm-1.0.0/tests/run_context/test_create_run_context.py +39 -0
- kiarina_llm-1.0.0/tests/run_context/test_fs_name.py +87 -0
- kiarina_llm-1.0.0/tests/run_context/test_id_str.py +73 -0
- kiarina_llm-1.0.0/tests/run_context/test_run_context.py +36 -0
@@ -0,0 +1,39 @@
|
|
1
|
+
# Python
|
2
|
+
__pycache__/
|
3
|
+
*.py[cod]
|
4
|
+
*.so
|
5
|
+
*.egg-info/
|
6
|
+
dist/
|
7
|
+
build/
|
8
|
+
.ruff_cache/
|
9
|
+
.mypy_cache/
|
10
|
+
.pytest_cache/
|
11
|
+
.coverage
|
12
|
+
coverage.xml
|
13
|
+
htmlcov/
|
14
|
+
|
15
|
+
# uv
|
16
|
+
.uv_cache/
|
17
|
+
|
18
|
+
# Virtual environments & config
|
19
|
+
.venv/
|
20
|
+
.env
|
21
|
+
|
22
|
+
# IDE
|
23
|
+
.vscode/
|
24
|
+
*.code-workspace
|
25
|
+
|
26
|
+
# OS
|
27
|
+
.DS_Store
|
28
|
+
|
29
|
+
# Project specific
|
30
|
+
*.log
|
31
|
+
tmp/
|
32
|
+
ai.yaml
|
33
|
+
|
34
|
+
# Test data
|
35
|
+
tests/data/large/
|
36
|
+
|
37
|
+
# mise tasks (always include)
|
38
|
+
!mise-tasks/
|
39
|
+
!mise-tasks/**
|
@@ -0,0 +1,41 @@
|
|
1
|
+
# Changelog
|
2
|
+
|
3
|
+
All notable changes to this project will be documented in this file.
|
4
|
+
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
6
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
7
|
+
|
8
|
+
## [Unreleased]
|
9
|
+
|
10
|
+
## [1.0.0] - 2025-09-09
|
11
|
+
|
12
|
+
### Added
|
13
|
+
- Initial release of kiarina-llm
|
14
|
+
- RunContext management for LLM pipeline processing
|
15
|
+
- Type-safe FSName validation for filesystem-safe names
|
16
|
+
- Type-safe IDStr validation for identifiers
|
17
|
+
- Configuration management using pydantic-settings-manager
|
18
|
+
- Environment variable configuration support
|
19
|
+
- Runtime configuration overrides
|
20
|
+
- Cross-platform compatibility with Windows reserved name validation
|
21
|
+
- Full type hints and Pydantic validation
|
22
|
+
- Comprehensive test suite
|
23
|
+
|
24
|
+
### Features
|
25
|
+
- **RunContext**: Structured context information holder
|
26
|
+
- Application author and name (filesystem safe)
|
27
|
+
- Tenant, user, agent, and runner identifiers
|
28
|
+
- Time zone and language settings
|
29
|
+
- Extensible metadata support
|
30
|
+
- **Type Safety**: Custom Pydantic types for validation
|
31
|
+
- FSName: Filesystem-safe names with cross-platform validation
|
32
|
+
- IDStr: Identifier strings with pattern validation
|
33
|
+
- **Configuration**: Flexible settings management
|
34
|
+
- Environment variable support with KIARINA_LLM_RUN_CONTEXT_ prefix
|
35
|
+
- Runtime configuration overrides
|
36
|
+
- Default value management
|
37
|
+
|
38
|
+
### Dependencies
|
39
|
+
- pydantic>=2.10.1
|
40
|
+
- pydantic-settings>=2.10.1
|
41
|
+
- pydantic-settings-manager>=2.1.0
|
@@ -0,0 +1,286 @@
|
|
1
|
+
Metadata-Version: 2.4
|
2
|
+
Name: kiarina-llm
|
3
|
+
Version: 1.0.0
|
4
|
+
Summary: LLM utilities and context management for kiarina namespace
|
5
|
+
Project-URL: Homepage, https://github.com/kiarina/kiarina-python
|
6
|
+
Project-URL: Repository, https://github.com/kiarina/kiarina-python
|
7
|
+
Project-URL: Issues, https://github.com/kiarina/kiarina-python/issues
|
8
|
+
Project-URL: Changelog, https://github.com/kiarina/kiarina-python/blob/main/packages/kiarina-llm/CHANGELOG.md
|
9
|
+
Project-URL: Documentation, https://github.com/kiarina/kiarina-python/tree/main/packages/kiarina-llm#readme
|
10
|
+
Author-email: kiarina <kiarinadawa@gmail.com>
|
11
|
+
Maintainer-email: kiarina <kiarinadawa@gmail.com>
|
12
|
+
License: MIT
|
13
|
+
Keywords: agent,ai,context,llm,pydantic,runner,settings
|
14
|
+
Classifier: Development Status :: 4 - Beta
|
15
|
+
Classifier: Intended Audience :: Developers
|
16
|
+
Classifier: License :: OSI Approved :: MIT License
|
17
|
+
Classifier: Operating System :: OS Independent
|
18
|
+
Classifier: Programming Language :: Python :: 3
|
19
|
+
Classifier: Programming Language :: Python :: 3.12
|
20
|
+
Classifier: Programming Language :: Python :: 3.13
|
21
|
+
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
22
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
23
|
+
Classifier: Typing :: Typed
|
24
|
+
Requires-Python: >=3.12
|
25
|
+
Requires-Dist: pydantic-settings-manager>=2.1.0
|
26
|
+
Requires-Dist: pydantic-settings>=2.10.1
|
27
|
+
Requires-Dist: pydantic>=2.10.1
|
28
|
+
Description-Content-Type: text/markdown
|
29
|
+
|
30
|
+
# kiarina-llm
|
31
|
+
|
32
|
+
A Python library for LLM utilities and context management with type safety and configuration management.
|
33
|
+
|
34
|
+
## Features
|
35
|
+
|
36
|
+
- **RunContext Management**: Structured context information for LLM pipeline processing
|
37
|
+
- **Type Safety**: Full type hints and Pydantic validation
|
38
|
+
- **Configuration Management**: Use `pydantic-settings-manager` for flexible configuration
|
39
|
+
- **Filesystem Safe Names**: Validated names for cross-platform compatibility
|
40
|
+
- **ID Validation**: Structured ID types with pattern validation
|
41
|
+
|
42
|
+
## Installation
|
43
|
+
|
44
|
+
```bash
|
45
|
+
pip install kiarina-llm
|
46
|
+
```
|
47
|
+
|
48
|
+
## Quick Start
|
49
|
+
|
50
|
+
### Basic RunContext Usage
|
51
|
+
|
52
|
+
```python
|
53
|
+
from kiarina.llm.run_context import create_run_context
|
54
|
+
|
55
|
+
# Create a run context with default settings
|
56
|
+
context = create_run_context(
|
57
|
+
tenant_id="tenant-123",
|
58
|
+
user_id="user-456",
|
59
|
+
agent_id="my-agent",
|
60
|
+
time_zone="Asia/Tokyo",
|
61
|
+
language="ja"
|
62
|
+
)
|
63
|
+
|
64
|
+
print(f"User: {context.user_id}")
|
65
|
+
print(f"Agent: {context.agent_id}")
|
66
|
+
print(f"Time Zone: {context.time_zone}")
|
67
|
+
print(f"Language: {context.language}")
|
68
|
+
```
|
69
|
+
|
70
|
+
### Configuration Management
|
71
|
+
|
72
|
+
```python
|
73
|
+
from kiarina.llm.run_context import settings_manager
|
74
|
+
|
75
|
+
# Configure default values
|
76
|
+
settings_manager.user_config = {
|
77
|
+
"app_author": "MyCompany",
|
78
|
+
"app_name": "MyAIApp",
|
79
|
+
"tenant_id": "default-tenant",
|
80
|
+
"user_id": "default-user",
|
81
|
+
"time_zone": "America/New_York",
|
82
|
+
"language": "en"
|
83
|
+
}
|
84
|
+
|
85
|
+
# Create context with configured defaults
|
86
|
+
context = create_run_context(
|
87
|
+
agent_id="specialized-agent" # Override only specific values
|
88
|
+
)
|
89
|
+
```
|
90
|
+
|
91
|
+
### Environment Variable Configuration
|
92
|
+
|
93
|
+
Configure defaults using environment variables:
|
94
|
+
|
95
|
+
```bash
|
96
|
+
export KIARINA_LLM_RUN_CONTEXT_APP_AUTHOR="MyCompany"
|
97
|
+
export KIARINA_LLM_RUN_CONTEXT_APP_NAME="MyAIApp"
|
98
|
+
export KIARINA_LLM_RUN_CONTEXT_TENANT_ID="prod-tenant"
|
99
|
+
export KIARINA_LLM_RUN_CONTEXT_TIME_ZONE="Asia/Tokyo"
|
100
|
+
export KIARINA_LLM_RUN_CONTEXT_LANGUAGE="ja"
|
101
|
+
```
|
102
|
+
|
103
|
+
## RunContext Fields
|
104
|
+
|
105
|
+
The `RunContext` model includes the following fields:
|
106
|
+
|
107
|
+
| Field | Type | Description | Example |
|
108
|
+
|-------|------|-------------|---------|
|
109
|
+
| `app_author` | `FSName` | Application author (filesystem safe) | `"MyCompany"` |
|
110
|
+
| `app_name` | `FSName` | Application name (filesystem safe) | `"MyAIApp"` |
|
111
|
+
| `tenant_id` | `IDStr` | Tenant identifier | `"tenant-123"` |
|
112
|
+
| `user_id` | `IDStr` | User identifier | `"user-456"` |
|
113
|
+
| `agent_id` | `IDStr` | Agent identifier | `"my-agent"` |
|
114
|
+
| `runner_id` | `IDStr` | Runner identifier | `"linux"` (auto-detected) |
|
115
|
+
| `time_zone` | `str` | IANA time zone | `"Asia/Tokyo"` |
|
116
|
+
| `language` | `str` | ISO 639-1 language code | `"ja"` |
|
117
|
+
| `metadata` | `dict[str, Any]` | Additional metadata | `{"version": "1.0"}` |
|
118
|
+
|
119
|
+
## Type Validation
|
120
|
+
|
121
|
+
### FSName (Filesystem Safe Name)
|
122
|
+
|
123
|
+
The `FSName` type ensures names are safe for use across different filesystems:
|
124
|
+
|
125
|
+
```python
|
126
|
+
from kiarina.llm.run_context import create_run_context
|
127
|
+
|
128
|
+
# Valid names
|
129
|
+
context = create_run_context(
|
130
|
+
app_author="My Company", # Spaces allowed
|
131
|
+
app_name="My-App_v1.0" # Hyphens, underscores, dots allowed
|
132
|
+
)
|
133
|
+
|
134
|
+
# Invalid names (will raise ValidationError)
|
135
|
+
try:
|
136
|
+
create_run_context(app_author="My App.") # Ends with dot
|
137
|
+
except ValueError as e:
|
138
|
+
print(f"Validation error: {e}")
|
139
|
+
|
140
|
+
try:
|
141
|
+
create_run_context(app_author=".hidden") # Starts with dot
|
142
|
+
except ValueError as e:
|
143
|
+
print(f"Validation error: {e}")
|
144
|
+
|
145
|
+
try:
|
146
|
+
create_run_context(app_author="CON") # Windows reserved name
|
147
|
+
except ValueError as e:
|
148
|
+
print(f"Validation error: {e}")
|
149
|
+
```
|
150
|
+
|
151
|
+
### IDStr (ID String)
|
152
|
+
|
153
|
+
The `IDStr` type validates identifiers:
|
154
|
+
|
155
|
+
```python
|
156
|
+
# Valid IDs
|
157
|
+
context = create_run_context(
|
158
|
+
tenant_id="tenant-123",
|
159
|
+
user_id="user.456",
|
160
|
+
agent_id="agent_v1.0"
|
161
|
+
)
|
162
|
+
|
163
|
+
# Invalid IDs (will raise ValidationError)
|
164
|
+
try:
|
165
|
+
create_run_context(tenant_id="") # Empty string
|
166
|
+
except ValueError as e:
|
167
|
+
print(f"Validation error: {e}")
|
168
|
+
|
169
|
+
try:
|
170
|
+
create_run_context(user_id="user@domain") # Invalid character
|
171
|
+
except ValueError as e:
|
172
|
+
print(f"Validation error: {e}")
|
173
|
+
```
|
174
|
+
|
175
|
+
## Advanced Usage
|
176
|
+
|
177
|
+
### Custom Metadata
|
178
|
+
|
179
|
+
```python
|
180
|
+
context = create_run_context(
|
181
|
+
tenant_id="tenant-123",
|
182
|
+
user_id="user-456",
|
183
|
+
metadata={
|
184
|
+
"session_id": "session-789",
|
185
|
+
"request_id": "req-abc123",
|
186
|
+
"version": "1.0.0",
|
187
|
+
"features": ["feature-a", "feature-b"]
|
188
|
+
}
|
189
|
+
)
|
190
|
+
|
191
|
+
print(f"Session: {context.metadata['session_id']}")
|
192
|
+
print(f"Features: {context.metadata['features']}")
|
193
|
+
```
|
194
|
+
|
195
|
+
### Integration with PlatformDirs
|
196
|
+
|
197
|
+
The `app_author` and `app_name` fields are designed to work with libraries like `platformdirs`:
|
198
|
+
|
199
|
+
```python
|
200
|
+
from platformdirs import user_data_dir
|
201
|
+
from kiarina.llm.run_context import create_run_context
|
202
|
+
|
203
|
+
context = create_run_context(
|
204
|
+
app_author="MyCompany",
|
205
|
+
app_name="MyAIApp"
|
206
|
+
)
|
207
|
+
|
208
|
+
# Use with platformdirs
|
209
|
+
data_dir = user_data_dir(
|
210
|
+
appname=context.app_name,
|
211
|
+
appauthor=context.app_author
|
212
|
+
)
|
213
|
+
print(f"Data directory: {data_dir}")
|
214
|
+
```
|
215
|
+
|
216
|
+
## Configuration Reference
|
217
|
+
|
218
|
+
| Setting | Environment Variable | Default | Description |
|
219
|
+
|---------|---------------------|---------|-------------|
|
220
|
+
| `app_author` | `KIARINA_LLM_RUN_CONTEXT_APP_AUTHOR` | `"kiarina"` | Default application author |
|
221
|
+
| `app_name` | `KIARINA_LLM_RUN_CONTEXT_APP_NAME` | `"myaikit"` | Default application name |
|
222
|
+
| `tenant_id` | `KIARINA_LLM_RUN_CONTEXT_TENANT_ID` | `""` | Default tenant ID |
|
223
|
+
| `user_id` | `KIARINA_LLM_RUN_CONTEXT_USER_ID` | `""` | Default user ID |
|
224
|
+
| `agent_id` | `KIARINA_LLM_RUN_CONTEXT_AGENT_ID` | `""` | Default agent ID |
|
225
|
+
| `runner_id` | `KIARINA_LLM_RUN_CONTEXT_RUNNER_ID` | `platform.system().lower()` | Default runner ID |
|
226
|
+
| `time_zone` | `KIARINA_LLM_RUN_CONTEXT_TIME_ZONE` | `"UTC"` | Default time zone |
|
227
|
+
| `language` | `KIARINA_LLM_RUN_CONTEXT_LANGUAGE` | `"en"` | Default language |
|
228
|
+
|
229
|
+
## Development
|
230
|
+
|
231
|
+
### Prerequisites
|
232
|
+
|
233
|
+
- Python 3.12+
|
234
|
+
|
235
|
+
### Setup
|
236
|
+
|
237
|
+
```bash
|
238
|
+
# Clone the repository
|
239
|
+
git clone https://github.com/kiarina/kiarina-python.git
|
240
|
+
cd kiarina-python
|
241
|
+
|
242
|
+
# Setup development environment (installs tools, syncs dependencies, downloads test data)
|
243
|
+
mise run setup
|
244
|
+
```
|
245
|
+
|
246
|
+
### Running Tests
|
247
|
+
|
248
|
+
```bash
|
249
|
+
# Run format, lint, type checks and tests
|
250
|
+
mise run package kiarina-llm
|
251
|
+
|
252
|
+
# Coverage report
|
253
|
+
mise run package:test kiarina-llm --coverage
|
254
|
+
|
255
|
+
# Run specific tests
|
256
|
+
uv run --group test pytest packages/kiarina-llm/tests/run_context/
|
257
|
+
```
|
258
|
+
|
259
|
+
## Dependencies
|
260
|
+
|
261
|
+
- [pydantic](https://docs.pydantic.dev/) - Data validation using Python type hints
|
262
|
+
- [pydantic-settings](https://docs.pydantic.dev/latest/concepts/pydantic_settings/) - Settings management
|
263
|
+
- [pydantic-settings-manager](https://github.com/kiarina/pydantic-settings-manager) - Advanced settings management
|
264
|
+
|
265
|
+
## Roadmap
|
266
|
+
|
267
|
+
This package is in active development. Planned features include:
|
268
|
+
|
269
|
+
- **Chat Model Management**: Unified interface for different LLM providers
|
270
|
+
- **Agent Framework**: Tools for building LLM agents
|
271
|
+
- **Pipeline Management**: Workflow management for LLM processing
|
272
|
+
- **Memory Management**: Context and conversation memory handling
|
273
|
+
- **Tool Integration**: Framework for LLM tool calling
|
274
|
+
|
275
|
+
## License
|
276
|
+
|
277
|
+
This project is licensed under the MIT License - see the [LICENSE](../../LICENSE) file for details.
|
278
|
+
|
279
|
+
## Contributing
|
280
|
+
|
281
|
+
This is a personal project, but contributions are welcome! Please feel free to submit issues or pull requests.
|
282
|
+
|
283
|
+
## Related Projects
|
284
|
+
|
285
|
+
- [kiarina-python](https://github.com/kiarina/kiarina-python) - The main monorepo containing this package
|
286
|
+
- [pydantic-settings-manager](https://github.com/kiarina/pydantic-settings-manager) - Configuration management library used by this package
|
@@ -0,0 +1,257 @@
|
|
1
|
+
# kiarina-llm
|
2
|
+
|
3
|
+
A Python library for LLM utilities and context management with type safety and configuration management.
|
4
|
+
|
5
|
+
## Features
|
6
|
+
|
7
|
+
- **RunContext Management**: Structured context information for LLM pipeline processing
|
8
|
+
- **Type Safety**: Full type hints and Pydantic validation
|
9
|
+
- **Configuration Management**: Use `pydantic-settings-manager` for flexible configuration
|
10
|
+
- **Filesystem Safe Names**: Validated names for cross-platform compatibility
|
11
|
+
- **ID Validation**: Structured ID types with pattern validation
|
12
|
+
|
13
|
+
## Installation
|
14
|
+
|
15
|
+
```bash
|
16
|
+
pip install kiarina-llm
|
17
|
+
```
|
18
|
+
|
19
|
+
## Quick Start
|
20
|
+
|
21
|
+
### Basic RunContext Usage
|
22
|
+
|
23
|
+
```python
|
24
|
+
from kiarina.llm.run_context import create_run_context
|
25
|
+
|
26
|
+
# Create a run context with default settings
|
27
|
+
context = create_run_context(
|
28
|
+
tenant_id="tenant-123",
|
29
|
+
user_id="user-456",
|
30
|
+
agent_id="my-agent",
|
31
|
+
time_zone="Asia/Tokyo",
|
32
|
+
language="ja"
|
33
|
+
)
|
34
|
+
|
35
|
+
print(f"User: {context.user_id}")
|
36
|
+
print(f"Agent: {context.agent_id}")
|
37
|
+
print(f"Time Zone: {context.time_zone}")
|
38
|
+
print(f"Language: {context.language}")
|
39
|
+
```
|
40
|
+
|
41
|
+
### Configuration Management
|
42
|
+
|
43
|
+
```python
|
44
|
+
from kiarina.llm.run_context import settings_manager
|
45
|
+
|
46
|
+
# Configure default values
|
47
|
+
settings_manager.user_config = {
|
48
|
+
"app_author": "MyCompany",
|
49
|
+
"app_name": "MyAIApp",
|
50
|
+
"tenant_id": "default-tenant",
|
51
|
+
"user_id": "default-user",
|
52
|
+
"time_zone": "America/New_York",
|
53
|
+
"language": "en"
|
54
|
+
}
|
55
|
+
|
56
|
+
# Create context with configured defaults
|
57
|
+
context = create_run_context(
|
58
|
+
agent_id="specialized-agent" # Override only specific values
|
59
|
+
)
|
60
|
+
```
|
61
|
+
|
62
|
+
### Environment Variable Configuration
|
63
|
+
|
64
|
+
Configure defaults using environment variables:
|
65
|
+
|
66
|
+
```bash
|
67
|
+
export KIARINA_LLM_RUN_CONTEXT_APP_AUTHOR="MyCompany"
|
68
|
+
export KIARINA_LLM_RUN_CONTEXT_APP_NAME="MyAIApp"
|
69
|
+
export KIARINA_LLM_RUN_CONTEXT_TENANT_ID="prod-tenant"
|
70
|
+
export KIARINA_LLM_RUN_CONTEXT_TIME_ZONE="Asia/Tokyo"
|
71
|
+
export KIARINA_LLM_RUN_CONTEXT_LANGUAGE="ja"
|
72
|
+
```
|
73
|
+
|
74
|
+
## RunContext Fields
|
75
|
+
|
76
|
+
The `RunContext` model includes the following fields:
|
77
|
+
|
78
|
+
| Field | Type | Description | Example |
|
79
|
+
|-------|------|-------------|---------|
|
80
|
+
| `app_author` | `FSName` | Application author (filesystem safe) | `"MyCompany"` |
|
81
|
+
| `app_name` | `FSName` | Application name (filesystem safe) | `"MyAIApp"` |
|
82
|
+
| `tenant_id` | `IDStr` | Tenant identifier | `"tenant-123"` |
|
83
|
+
| `user_id` | `IDStr` | User identifier | `"user-456"` |
|
84
|
+
| `agent_id` | `IDStr` | Agent identifier | `"my-agent"` |
|
85
|
+
| `runner_id` | `IDStr` | Runner identifier | `"linux"` (auto-detected) |
|
86
|
+
| `time_zone` | `str` | IANA time zone | `"Asia/Tokyo"` |
|
87
|
+
| `language` | `str` | ISO 639-1 language code | `"ja"` |
|
88
|
+
| `metadata` | `dict[str, Any]` | Additional metadata | `{"version": "1.0"}` |
|
89
|
+
|
90
|
+
## Type Validation
|
91
|
+
|
92
|
+
### FSName (Filesystem Safe Name)
|
93
|
+
|
94
|
+
The `FSName` type ensures names are safe for use across different filesystems:
|
95
|
+
|
96
|
+
```python
|
97
|
+
from kiarina.llm.run_context import create_run_context
|
98
|
+
|
99
|
+
# Valid names
|
100
|
+
context = create_run_context(
|
101
|
+
app_author="My Company", # Spaces allowed
|
102
|
+
app_name="My-App_v1.0" # Hyphens, underscores, dots allowed
|
103
|
+
)
|
104
|
+
|
105
|
+
# Invalid names (will raise ValidationError)
|
106
|
+
try:
|
107
|
+
create_run_context(app_author="My App.") # Ends with dot
|
108
|
+
except ValueError as e:
|
109
|
+
print(f"Validation error: {e}")
|
110
|
+
|
111
|
+
try:
|
112
|
+
create_run_context(app_author=".hidden") # Starts with dot
|
113
|
+
except ValueError as e:
|
114
|
+
print(f"Validation error: {e}")
|
115
|
+
|
116
|
+
try:
|
117
|
+
create_run_context(app_author="CON") # Windows reserved name
|
118
|
+
except ValueError as e:
|
119
|
+
print(f"Validation error: {e}")
|
120
|
+
```
|
121
|
+
|
122
|
+
### IDStr (ID String)
|
123
|
+
|
124
|
+
The `IDStr` type validates identifiers:
|
125
|
+
|
126
|
+
```python
|
127
|
+
# Valid IDs
|
128
|
+
context = create_run_context(
|
129
|
+
tenant_id="tenant-123",
|
130
|
+
user_id="user.456",
|
131
|
+
agent_id="agent_v1.0"
|
132
|
+
)
|
133
|
+
|
134
|
+
# Invalid IDs (will raise ValidationError)
|
135
|
+
try:
|
136
|
+
create_run_context(tenant_id="") # Empty string
|
137
|
+
except ValueError as e:
|
138
|
+
print(f"Validation error: {e}")
|
139
|
+
|
140
|
+
try:
|
141
|
+
create_run_context(user_id="user@domain") # Invalid character
|
142
|
+
except ValueError as e:
|
143
|
+
print(f"Validation error: {e}")
|
144
|
+
```
|
145
|
+
|
146
|
+
## Advanced Usage
|
147
|
+
|
148
|
+
### Custom Metadata
|
149
|
+
|
150
|
+
```python
|
151
|
+
context = create_run_context(
|
152
|
+
tenant_id="tenant-123",
|
153
|
+
user_id="user-456",
|
154
|
+
metadata={
|
155
|
+
"session_id": "session-789",
|
156
|
+
"request_id": "req-abc123",
|
157
|
+
"version": "1.0.0",
|
158
|
+
"features": ["feature-a", "feature-b"]
|
159
|
+
}
|
160
|
+
)
|
161
|
+
|
162
|
+
print(f"Session: {context.metadata['session_id']}")
|
163
|
+
print(f"Features: {context.metadata['features']}")
|
164
|
+
```
|
165
|
+
|
166
|
+
### Integration with PlatformDirs
|
167
|
+
|
168
|
+
The `app_author` and `app_name` fields are designed to work with libraries like `platformdirs`:
|
169
|
+
|
170
|
+
```python
|
171
|
+
from platformdirs import user_data_dir
|
172
|
+
from kiarina.llm.run_context import create_run_context
|
173
|
+
|
174
|
+
context = create_run_context(
|
175
|
+
app_author="MyCompany",
|
176
|
+
app_name="MyAIApp"
|
177
|
+
)
|
178
|
+
|
179
|
+
# Use with platformdirs
|
180
|
+
data_dir = user_data_dir(
|
181
|
+
appname=context.app_name,
|
182
|
+
appauthor=context.app_author
|
183
|
+
)
|
184
|
+
print(f"Data directory: {data_dir}")
|
185
|
+
```
|
186
|
+
|
187
|
+
## Configuration Reference
|
188
|
+
|
189
|
+
| Setting | Environment Variable | Default | Description |
|
190
|
+
|---------|---------------------|---------|-------------|
|
191
|
+
| `app_author` | `KIARINA_LLM_RUN_CONTEXT_APP_AUTHOR` | `"kiarina"` | Default application author |
|
192
|
+
| `app_name` | `KIARINA_LLM_RUN_CONTEXT_APP_NAME` | `"myaikit"` | Default application name |
|
193
|
+
| `tenant_id` | `KIARINA_LLM_RUN_CONTEXT_TENANT_ID` | `""` | Default tenant ID |
|
194
|
+
| `user_id` | `KIARINA_LLM_RUN_CONTEXT_USER_ID` | `""` | Default user ID |
|
195
|
+
| `agent_id` | `KIARINA_LLM_RUN_CONTEXT_AGENT_ID` | `""` | Default agent ID |
|
196
|
+
| `runner_id` | `KIARINA_LLM_RUN_CONTEXT_RUNNER_ID` | `platform.system().lower()` | Default runner ID |
|
197
|
+
| `time_zone` | `KIARINA_LLM_RUN_CONTEXT_TIME_ZONE` | `"UTC"` | Default time zone |
|
198
|
+
| `language` | `KIARINA_LLM_RUN_CONTEXT_LANGUAGE` | `"en"` | Default language |
|
199
|
+
|
200
|
+
## Development
|
201
|
+
|
202
|
+
### Prerequisites
|
203
|
+
|
204
|
+
- Python 3.12+
|
205
|
+
|
206
|
+
### Setup
|
207
|
+
|
208
|
+
```bash
|
209
|
+
# Clone the repository
|
210
|
+
git clone https://github.com/kiarina/kiarina-python.git
|
211
|
+
cd kiarina-python
|
212
|
+
|
213
|
+
# Setup development environment (installs tools, syncs dependencies, downloads test data)
|
214
|
+
mise run setup
|
215
|
+
```
|
216
|
+
|
217
|
+
### Running Tests
|
218
|
+
|
219
|
+
```bash
|
220
|
+
# Run format, lint, type checks and tests
|
221
|
+
mise run package kiarina-llm
|
222
|
+
|
223
|
+
# Coverage report
|
224
|
+
mise run package:test kiarina-llm --coverage
|
225
|
+
|
226
|
+
# Run specific tests
|
227
|
+
uv run --group test pytest packages/kiarina-llm/tests/run_context/
|
228
|
+
```
|
229
|
+
|
230
|
+
## Dependencies
|
231
|
+
|
232
|
+
- [pydantic](https://docs.pydantic.dev/) - Data validation using Python type hints
|
233
|
+
- [pydantic-settings](https://docs.pydantic.dev/latest/concepts/pydantic_settings/) - Settings management
|
234
|
+
- [pydantic-settings-manager](https://github.com/kiarina/pydantic-settings-manager) - Advanced settings management
|
235
|
+
|
236
|
+
## Roadmap
|
237
|
+
|
238
|
+
This package is in active development. Planned features include:
|
239
|
+
|
240
|
+
- **Chat Model Management**: Unified interface for different LLM providers
|
241
|
+
- **Agent Framework**: Tools for building LLM agents
|
242
|
+
- **Pipeline Management**: Workflow management for LLM processing
|
243
|
+
- **Memory Management**: Context and conversation memory handling
|
244
|
+
- **Tool Integration**: Framework for LLM tool calling
|
245
|
+
|
246
|
+
## License
|
247
|
+
|
248
|
+
This project is licensed under the MIT License - see the [LICENSE](../../LICENSE) file for details.
|
249
|
+
|
250
|
+
## Contributing
|
251
|
+
|
252
|
+
This is a personal project, but contributions are welcome! Please feel free to submit issues or pull requests.
|
253
|
+
|
254
|
+
## Related Projects
|
255
|
+
|
256
|
+
- [kiarina-python](https://github.com/kiarina/kiarina-python) - The main monorepo containing this package
|
257
|
+
- [pydantic-settings-manager](https://github.com/kiarina/pydantic-settings-manager) - Configuration management library used by this package
|
@@ -0,0 +1,45 @@
|
|
1
|
+
[project]
|
2
|
+
name = "kiarina-llm"
|
3
|
+
version = "1.0.0"
|
4
|
+
description = "LLM utilities and context management for kiarina namespace"
|
5
|
+
readme = "README.md"
|
6
|
+
license = { text = "MIT" }
|
7
|
+
authors = [
|
8
|
+
{ name = "kiarina", email = "kiarinadawa@gmail.com" }
|
9
|
+
]
|
10
|
+
maintainers = [
|
11
|
+
{ name = "kiarina", email = "kiarinadawa@gmail.com" }
|
12
|
+
]
|
13
|
+
keywords = ["llm", "ai", "context", "pydantic", "settings", "agent", "runner"]
|
14
|
+
classifiers = [
|
15
|
+
"Development Status :: 4 - Beta",
|
16
|
+
"Intended Audience :: Developers",
|
17
|
+
"License :: OSI Approved :: MIT License",
|
18
|
+
"Operating System :: OS Independent",
|
19
|
+
"Programming Language :: Python :: 3",
|
20
|
+
"Programming Language :: Python :: 3.12",
|
21
|
+
"Programming Language :: Python :: 3.13",
|
22
|
+
"Topic :: Scientific/Engineering :: Artificial Intelligence",
|
23
|
+
"Topic :: Software Development :: Libraries :: Python Modules",
|
24
|
+
"Typing :: Typed",
|
25
|
+
]
|
26
|
+
requires-python = ">=3.12"
|
27
|
+
dependencies = [
|
28
|
+
"pydantic>=2.10.1",
|
29
|
+
"pydantic-settings>=2.10.1",
|
30
|
+
"pydantic-settings-manager>=2.1.0",
|
31
|
+
]
|
32
|
+
|
33
|
+
[project.urls]
|
34
|
+
Homepage = "https://github.com/kiarina/kiarina-python"
|
35
|
+
Repository = "https://github.com/kiarina/kiarina-python"
|
36
|
+
Issues = "https://github.com/kiarina/kiarina-python/issues"
|
37
|
+
Changelog = "https://github.com/kiarina/kiarina-python/blob/main/packages/kiarina-llm/CHANGELOG.md"
|
38
|
+
Documentation = "https://github.com/kiarina/kiarina-python/tree/main/packages/kiarina-llm#readme"
|
39
|
+
|
40
|
+
[build-system]
|
41
|
+
requires = ["hatchling"]
|
42
|
+
build-backend = "hatchling.build"
|
43
|
+
|
44
|
+
[tool.hatch.build.targets.wheel]
|
45
|
+
packages = ["src/kiarina"]
|
File without changes
|
@@ -0,0 +1,76 @@
|
|
1
|
+
from typing import Any
|
2
|
+
|
3
|
+
from pydantic import BaseModel, Field
|
4
|
+
|
5
|
+
from ._types.fs_name import FSName
|
6
|
+
from ._types.id_str import IDStr
|
7
|
+
|
8
|
+
|
9
|
+
class RunContext(BaseModel):
|
10
|
+
"""
|
11
|
+
Run Context
|
12
|
+
|
13
|
+
Holds the context information used in the LLM pipeline processing.
|
14
|
+
"""
|
15
|
+
|
16
|
+
app_author: FSName
|
17
|
+
"""
|
18
|
+
Application author
|
19
|
+
|
20
|
+
Used in PlatformDirs.
|
21
|
+
"""
|
22
|
+
|
23
|
+
app_name: FSName
|
24
|
+
"""
|
25
|
+
Application name
|
26
|
+
|
27
|
+
Used in PlatformDirs.
|
28
|
+
"""
|
29
|
+
|
30
|
+
tenant_id: IDStr
|
31
|
+
"""
|
32
|
+
Tenant ID
|
33
|
+
|
34
|
+
Identifier for the tenant to which the user belongs.
|
35
|
+
"""
|
36
|
+
|
37
|
+
user_id: IDStr
|
38
|
+
"""
|
39
|
+
User ID
|
40
|
+
|
41
|
+
Identifier for the user.
|
42
|
+
"""
|
43
|
+
|
44
|
+
agent_id: IDStr
|
45
|
+
"""
|
46
|
+
Agent ID
|
47
|
+
|
48
|
+
Identifier for the agent used by the user.
|
49
|
+
"""
|
50
|
+
|
51
|
+
runner_id: IDStr
|
52
|
+
"""
|
53
|
+
Runner ID
|
54
|
+
|
55
|
+
Identifier for the runner used by the AI.
|
56
|
+
"""
|
57
|
+
|
58
|
+
time_zone: str
|
59
|
+
"""
|
60
|
+
Time Zone
|
61
|
+
|
62
|
+
IANA Time Zone.
|
63
|
+
Specify in continent/city format.
|
64
|
+
Example: "Asia/Tokyo"
|
65
|
+
"""
|
66
|
+
|
67
|
+
language: str
|
68
|
+
"""
|
69
|
+
Language
|
70
|
+
|
71
|
+
ISO 639-1 code.
|
72
|
+
Example: "en" (English), "ja" (Japanese)
|
73
|
+
"""
|
74
|
+
|
75
|
+
metadata: dict[str, Any] = Field(default_factory=lambda: {})
|
76
|
+
"""Metadata"""
|
@@ -0,0 +1,34 @@
|
|
1
|
+
from typing import Any
|
2
|
+
|
3
|
+
from ._model import RunContext
|
4
|
+
from .settings import settings_manager
|
5
|
+
|
6
|
+
|
7
|
+
def create_run_context(
|
8
|
+
*,
|
9
|
+
app_author: str | None = None,
|
10
|
+
app_name: str | None = None,
|
11
|
+
tenant_id: str | None = None,
|
12
|
+
user_id: str | None = None,
|
13
|
+
agent_id: str | None = None,
|
14
|
+
runner_id: str | None = None,
|
15
|
+
time_zone: str | None = None,
|
16
|
+
language: str | None = None,
|
17
|
+
metadata: dict[str, Any] | None = None,
|
18
|
+
) -> RunContext:
|
19
|
+
"""
|
20
|
+
Create RunContext
|
21
|
+
"""
|
22
|
+
settings = settings_manager.settings
|
23
|
+
|
24
|
+
return RunContext(
|
25
|
+
app_author=app_author if app_author is not None else settings.app_author,
|
26
|
+
app_name=app_name if app_name is not None else settings.app_name,
|
27
|
+
tenant_id=tenant_id if tenant_id is not None else settings.tenant_id,
|
28
|
+
user_id=user_id if user_id is not None else settings.user_id,
|
29
|
+
agent_id=agent_id if agent_id is not None else settings.agent_id,
|
30
|
+
runner_id=runner_id if runner_id is not None else settings.runner_id,
|
31
|
+
time_zone=time_zone if time_zone is not None else settings.time_zone,
|
32
|
+
language=language if language is not None else settings.language,
|
33
|
+
metadata=metadata if metadata is not None else settings.metadata,
|
34
|
+
)
|
File without changes
|
@@ -0,0 +1,52 @@
|
|
1
|
+
from typing import Annotated
|
2
|
+
|
3
|
+
from pydantic import AfterValidator, StringConstraints
|
4
|
+
|
5
|
+
FS_NAME_PATTERN = r"^[A-Za-z0-9._ -]+$"
|
6
|
+
"""
|
7
|
+
File system name pattern
|
8
|
+
|
9
|
+
Permit ASCII letters, dots, underscores, hyphens, and spaces.
|
10
|
+
Detailed constraints are checked by validation functions.
|
11
|
+
"""
|
12
|
+
|
13
|
+
WINDOWS_RESERVED = {
|
14
|
+
"con",
|
15
|
+
"prn",
|
16
|
+
"aux",
|
17
|
+
"nul",
|
18
|
+
*{f"com{i}" for i in range(1, 10)},
|
19
|
+
*{f"lpt{i}" for i in range(1, 10)},
|
20
|
+
}
|
21
|
+
"""
|
22
|
+
Set of reserved names in Windows
|
23
|
+
|
24
|
+
Uppercase and lowercase letters are ignored.
|
25
|
+
"""
|
26
|
+
|
27
|
+
|
28
|
+
def _validate_fs_name(v: str) -> str:
|
29
|
+
name = v.strip()
|
30
|
+
|
31
|
+
if name.lower() in WINDOWS_RESERVED:
|
32
|
+
raise ValueError(f"'{v}' is a reserved name on Windows")
|
33
|
+
|
34
|
+
# Prohibiting names beginning with a dot
|
35
|
+
if name.startswith("."):
|
36
|
+
raise ValueError(f"'{v}' cannot start with a dot")
|
37
|
+
|
38
|
+
# Prohibiting endings with a dot or space
|
39
|
+
if name.endswith(".") or name.endswith(" "):
|
40
|
+
raise ValueError(f"'{v}' cannot end with a dot or space")
|
41
|
+
|
42
|
+
return v
|
43
|
+
|
44
|
+
|
45
|
+
FSName = Annotated[
|
46
|
+
str,
|
47
|
+
StringConstraints(min_length=1, pattern=FS_NAME_PATTERN),
|
48
|
+
AfterValidator(_validate_fs_name),
|
49
|
+
]
|
50
|
+
"""
|
51
|
+
Filesystem Safe Name Type
|
52
|
+
"""
|
@@ -0,0 +1,15 @@
|
|
1
|
+
from typing import Annotated
|
2
|
+
|
3
|
+
from pydantic import StringConstraints
|
4
|
+
|
5
|
+
ID_PATTERN = r"^[a-zA-Z0-9._-]+$"
|
6
|
+
"""
|
7
|
+
Permitted ID patterns
|
8
|
+
|
9
|
+
Alphanumeric characters, dot, underscore, hyphen, one character or more.
|
10
|
+
"""
|
11
|
+
|
12
|
+
IDStr = Annotated[str, StringConstraints(min_length=1, pattern=ID_PATTERN)]
|
13
|
+
"""
|
14
|
+
ID String type
|
15
|
+
"""
|
@@ -0,0 +1,80 @@
|
|
1
|
+
import platform
|
2
|
+
from typing import Any
|
3
|
+
|
4
|
+
from pydantic import Field
|
5
|
+
from pydantic_settings import BaseSettings, SettingsConfigDict
|
6
|
+
from pydantic_settings_manager import SettingsManager
|
7
|
+
|
8
|
+
|
9
|
+
class RunContextSettings(BaseSettings):
|
10
|
+
"""
|
11
|
+
Run Context Settings
|
12
|
+
"""
|
13
|
+
|
14
|
+
model_config = SettingsConfigDict(env_prefix="KIARINA_LLM_RUN_CONTEXT_")
|
15
|
+
|
16
|
+
app_author: str = "kiarina"
|
17
|
+
"""
|
18
|
+
Default value for the application author.
|
19
|
+
|
20
|
+
Alphanumeric characters, dots, underscores, hyphens, and spaces are allowed.
|
21
|
+
Leading and trailing dots, as well as spaces, are not allowed.
|
22
|
+
"""
|
23
|
+
|
24
|
+
app_name: str = "kiarina-llm"
|
25
|
+
"""
|
26
|
+
Default value for the application name.
|
27
|
+
|
28
|
+
Alphanumeric characters, dots, underscores, hyphens, and spaces are allowed.
|
29
|
+
Leading and trailing dots, as well as spaces, are not allowed.
|
30
|
+
"""
|
31
|
+
|
32
|
+
tenant_id: str = ""
|
33
|
+
"""
|
34
|
+
Default value for the tenant ID.
|
35
|
+
|
36
|
+
Alphanumeric characters, underscores, and hyphens are allowed.
|
37
|
+
"""
|
38
|
+
|
39
|
+
user_id: str = ""
|
40
|
+
"""
|
41
|
+
Default value for the user ID.
|
42
|
+
|
43
|
+
Alphanumeric characters, underscores, and hyphens are allowed.
|
44
|
+
"""
|
45
|
+
|
46
|
+
agent_id: str = ""
|
47
|
+
"""
|
48
|
+
Default value for the agent ID.
|
49
|
+
|
50
|
+
Alphanumeric characters, underscores, and hyphens are allowed.
|
51
|
+
"""
|
52
|
+
|
53
|
+
runner_id: str = Field(default_factory=lambda: platform.system().lower())
|
54
|
+
"""
|
55
|
+
Default value for the runner ID.
|
56
|
+
|
57
|
+
Alphanumeric characters, underscores, and hyphens are allowed.
|
58
|
+
"""
|
59
|
+
|
60
|
+
time_zone: str = "UTC"
|
61
|
+
"""
|
62
|
+
Default value for the time zone.
|
63
|
+
|
64
|
+
IANA time zone names are used.
|
65
|
+
Example: "Asia/Tokyo"
|
66
|
+
"""
|
67
|
+
|
68
|
+
language: str = "en"
|
69
|
+
"""
|
70
|
+
Default value for the language.
|
71
|
+
|
72
|
+
ISO 639-1 codes are used.
|
73
|
+
Example: "ja"
|
74
|
+
"""
|
75
|
+
|
76
|
+
metadata: dict[str, Any] = Field(default_factory=dict)
|
77
|
+
"""Default value for the metadata."""
|
78
|
+
|
79
|
+
|
80
|
+
settings_manager = SettingsManager(RunContextSettings)
|
File without changes
|
File without changes
|
@@ -0,0 +1,12 @@
|
|
1
|
+
import pytest
|
2
|
+
|
3
|
+
from kiarina.llm.run_context import settings_manager
|
4
|
+
|
5
|
+
|
6
|
+
@pytest.fixture(scope="session", autouse=True)
|
7
|
+
def setup_settings():
|
8
|
+
settings_manager.user_config = {
|
9
|
+
"tenant_id": "test-tenant",
|
10
|
+
"user_id": "test-user",
|
11
|
+
"agent_id": "test-agent",
|
12
|
+
}
|
@@ -0,0 +1,39 @@
|
|
1
|
+
from kiarina.llm.run_context import create_run_context, settings_manager
|
2
|
+
|
3
|
+
|
4
|
+
def test_create_run_context_with_settings():
|
5
|
+
"""Test that RunContext is created using configuration values"""
|
6
|
+
context = create_run_context()
|
7
|
+
settings = settings_manager.settings
|
8
|
+
assert context.app_author == settings.app_author
|
9
|
+
assert context.app_name == settings.app_name
|
10
|
+
assert context.tenant_id == settings.tenant_id
|
11
|
+
assert context.user_id == settings.user_id
|
12
|
+
assert context.time_zone == settings.time_zone
|
13
|
+
assert context.language == settings.language
|
14
|
+
assert context.metadata == settings.metadata
|
15
|
+
|
16
|
+
|
17
|
+
def test_create_run_context_with_overrides():
|
18
|
+
"""Test that RunContext is created with argument overrides"""
|
19
|
+
context = create_run_context(
|
20
|
+
app_author="TestCompany",
|
21
|
+
app_name="TestApp",
|
22
|
+
tenant_id="tenant-123",
|
23
|
+
user_id="user-456",
|
24
|
+
agent_id="agent-789",
|
25
|
+
runner_id="test-runner",
|
26
|
+
time_zone="Asia/Tokyo",
|
27
|
+
language="ja",
|
28
|
+
metadata={"version": "1.0.0"},
|
29
|
+
)
|
30
|
+
|
31
|
+
assert context.app_author == "TestCompany"
|
32
|
+
assert context.app_name == "TestApp"
|
33
|
+
assert context.tenant_id == "tenant-123"
|
34
|
+
assert context.user_id == "user-456"
|
35
|
+
assert context.agent_id == "agent-789"
|
36
|
+
assert context.runner_id == "test-runner"
|
37
|
+
assert context.time_zone == "Asia/Tokyo"
|
38
|
+
assert context.language == "ja"
|
39
|
+
assert context.metadata == {"version": "1.0.0"}
|
@@ -0,0 +1,87 @@
|
|
1
|
+
import pytest
|
2
|
+
|
3
|
+
from kiarina.llm.run_context import create_run_context
|
4
|
+
|
5
|
+
|
6
|
+
# fmt: off
|
7
|
+
@pytest.mark.parametrize("name", [
|
8
|
+
"MyApp",
|
9
|
+
"My App",
|
10
|
+
"My-App",
|
11
|
+
"My_App",
|
12
|
+
"My.App",
|
13
|
+
"My App v1.0",
|
14
|
+
"Test-App_v2.1",
|
15
|
+
"Test App ", # Trailing space is stripped, so this becomes valid
|
16
|
+
"Test ", # Trailing space is stripped, so this becomes valid
|
17
|
+
])
|
18
|
+
# fmt: on
|
19
|
+
def test_fs_name_valid(name):
|
20
|
+
"""Test that valid FSName values are accepted"""
|
21
|
+
context = create_run_context(app_author=name, app_name=name)
|
22
|
+
assert context.app_author == name
|
23
|
+
assert context.app_name == name
|
24
|
+
|
25
|
+
|
26
|
+
# fmt: off
|
27
|
+
@pytest.mark.parametrize("name,expected_match", [
|
28
|
+
# Names ending with dots (spaces are stripped, so they're actually valid)
|
29
|
+
("Test App.", "cannot end with a dot or space"),
|
30
|
+
("Test.", "cannot end with a dot or space"),
|
31
|
+
|
32
|
+
# Names starting with dots
|
33
|
+
(".hidden", "cannot start with a dot"),
|
34
|
+
(".test", "cannot start with a dot"),
|
35
|
+
(".myapp", "cannot start with a dot"),
|
36
|
+
|
37
|
+
# Windows reserved names
|
38
|
+
("CON", "is a reserved name on Windows"),
|
39
|
+
("con", "is a reserved name on Windows"),
|
40
|
+
("Con", "is a reserved name on Windows"),
|
41
|
+
("PRN", "is a reserved name on Windows"),
|
42
|
+
("prn", "is a reserved name on Windows"),
|
43
|
+
("Prn", "is a reserved name on Windows"),
|
44
|
+
("AUX", "is a reserved name on Windows"),
|
45
|
+
("aux", "is a reserved name on Windows"),
|
46
|
+
("Aux", "is a reserved name on Windows"),
|
47
|
+
("NUL", "is a reserved name on Windows"),
|
48
|
+
("nul", "is a reserved name on Windows"),
|
49
|
+
("Nul", "is a reserved name on Windows"),
|
50
|
+
("COM1", "is a reserved name on Windows"),
|
51
|
+
("com1", "is a reserved name on Windows"),
|
52
|
+
("Com1", "is a reserved name on Windows"),
|
53
|
+
("COM9", "is a reserved name on Windows"),
|
54
|
+
("com9", "is a reserved name on Windows"),
|
55
|
+
("Com9", "is a reserved name on Windows"),
|
56
|
+
("LPT1", "is a reserved name on Windows"),
|
57
|
+
("lpt1", "is a reserved name on Windows"),
|
58
|
+
("Lpt1", "is a reserved name on Windows"),
|
59
|
+
("LPT9", "is a reserved name on Windows"),
|
60
|
+
("lpt9", "is a reserved name on Windows"),
|
61
|
+
("Lpt9", "is a reserved name on Windows"),
|
62
|
+
|
63
|
+
# Empty string
|
64
|
+
("", None), # No specific match pattern for empty string
|
65
|
+
|
66
|
+
# Invalid characters
|
67
|
+
("Test/App", None),
|
68
|
+
("Test\\App", None),
|
69
|
+
("Test:App", None),
|
70
|
+
("Test*App", None),
|
71
|
+
("Test?App", None),
|
72
|
+
("Test\"App", None),
|
73
|
+
("Test<App", None),
|
74
|
+
("Test>App", None),
|
75
|
+
("Test|App", None),
|
76
|
+
("Test@App", None),
|
77
|
+
("Test#App", None),
|
78
|
+
])
|
79
|
+
# fmt: on
|
80
|
+
def test_fs_name_invalid(name, expected_match):
|
81
|
+
"""Test that invalid FSName values are rejected"""
|
82
|
+
if expected_match:
|
83
|
+
with pytest.raises(ValueError, match=expected_match):
|
84
|
+
create_run_context(app_author=name)
|
85
|
+
else:
|
86
|
+
with pytest.raises(ValueError):
|
87
|
+
create_run_context(app_author=name)
|
@@ -0,0 +1,73 @@
|
|
1
|
+
import pytest
|
2
|
+
|
3
|
+
from kiarina.llm.run_context import create_run_context
|
4
|
+
|
5
|
+
|
6
|
+
@pytest.mark.parametrize(
|
7
|
+
"id_str",
|
8
|
+
[
|
9
|
+
"simple",
|
10
|
+
"with-hyphen",
|
11
|
+
"with_underscore",
|
12
|
+
"with.dot",
|
13
|
+
"mixed-id_v1.0",
|
14
|
+
"123",
|
15
|
+
"id123",
|
16
|
+
"a",
|
17
|
+
"A",
|
18
|
+
"ID-123_v2.0",
|
19
|
+
"tenant.123",
|
20
|
+
"user.456",
|
21
|
+
"agent.v1.0",
|
22
|
+
"runner.test",
|
23
|
+
"tenant-123",
|
24
|
+
"user_456",
|
25
|
+
"agent-v1_0",
|
26
|
+
"runner_test-1",
|
27
|
+
],
|
28
|
+
)
|
29
|
+
def test_id_str_valid(id_str):
|
30
|
+
"""Test that valid IDStr values are accepted"""
|
31
|
+
context = create_run_context(
|
32
|
+
tenant_id=id_str,
|
33
|
+
user_id=id_str,
|
34
|
+
agent_id=id_str,
|
35
|
+
runner_id=id_str,
|
36
|
+
)
|
37
|
+
assert context.tenant_id == id_str
|
38
|
+
assert context.user_id == id_str
|
39
|
+
assert context.agent_id == id_str
|
40
|
+
assert context.runner_id == id_str
|
41
|
+
|
42
|
+
|
43
|
+
@pytest.mark.parametrize(
|
44
|
+
"id_str",
|
45
|
+
[
|
46
|
+
"", # Empty string
|
47
|
+
"id@domain",
|
48
|
+
"id with space",
|
49
|
+
"id/path",
|
50
|
+
"id\\path",
|
51
|
+
"id:port",
|
52
|
+
"id*wildcard",
|
53
|
+
"id?query",
|
54
|
+
'id"quote',
|
55
|
+
"id<bracket",
|
56
|
+
"id>bracket",
|
57
|
+
"id|pipe",
|
58
|
+
"id#hash",
|
59
|
+
"id%percent",
|
60
|
+
"id&ersand",
|
61
|
+
"id+plus",
|
62
|
+
"id=equals",
|
63
|
+
"id[bracket]",
|
64
|
+
"id{brace}",
|
65
|
+
"id(paren)",
|
66
|
+
"id,comma",
|
67
|
+
"id;semicolon",
|
68
|
+
],
|
69
|
+
)
|
70
|
+
def test_id_str_invalid(id_str):
|
71
|
+
"""Test that invalid IDStr values are rejected"""
|
72
|
+
with pytest.raises(ValueError):
|
73
|
+
create_run_context(tenant_id=id_str)
|
@@ -0,0 +1,36 @@
|
|
1
|
+
import pytest
|
2
|
+
|
3
|
+
from kiarina.llm.run_context import RunContext
|
4
|
+
|
5
|
+
|
6
|
+
def test_valid():
|
7
|
+
data = {
|
8
|
+
"app_author": "TestCompany",
|
9
|
+
"app_name": "TestApp",
|
10
|
+
"tenant_id": "tenant-123",
|
11
|
+
"user_id": "user-456",
|
12
|
+
"agent_id": "agent-789",
|
13
|
+
"runner_id": "runner-001",
|
14
|
+
"time_zone": "UTC",
|
15
|
+
"language": "en",
|
16
|
+
"metadata": {"key": "value"},
|
17
|
+
}
|
18
|
+
|
19
|
+
run_context = RunContext.model_validate(data)
|
20
|
+
assert run_context.model_dump() == data
|
21
|
+
|
22
|
+
|
23
|
+
def test_invalid():
|
24
|
+
with pytest.raises(Exception):
|
25
|
+
RunContext.model_validate(
|
26
|
+
{
|
27
|
+
"app_author": "Invalid/Name", # Invalid character
|
28
|
+
"app_name": "TestApp",
|
29
|
+
"tenant_id": "tenant-123",
|
30
|
+
"user_id": "user-456",
|
31
|
+
"agent_id": "agent-789",
|
32
|
+
"runner_id": "runner-001",
|
33
|
+
"time_zone": "UTC",
|
34
|
+
"language": "en",
|
35
|
+
}
|
36
|
+
)
|