kalibr 1.0.25__py3-none-any.whl → 1.1.2a0__py3-none-any.whl

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 (61) hide show
  1. kalibr/__init__.py +170 -3
  2. kalibr/__main__.py +3 -203
  3. kalibr/capsule_middleware.py +108 -0
  4. kalibr/cli/__init__.py +5 -0
  5. kalibr/cli/capsule_cmd.py +174 -0
  6. kalibr/cli/deploy_cmd.py +114 -0
  7. kalibr/cli/main.py +67 -0
  8. kalibr/cli/run.py +203 -0
  9. kalibr/cli/serve.py +59 -0
  10. kalibr/client.py +293 -0
  11. kalibr/collector.py +173 -0
  12. kalibr/context.py +132 -0
  13. kalibr/cost_adapter.py +222 -0
  14. kalibr/decorators.py +140 -0
  15. kalibr/instrumentation/__init__.py +13 -0
  16. kalibr/instrumentation/anthropic_instr.py +282 -0
  17. kalibr/instrumentation/base.py +108 -0
  18. kalibr/instrumentation/google_instr.py +281 -0
  19. kalibr/instrumentation/openai_instr.py +265 -0
  20. kalibr/instrumentation/registry.py +153 -0
  21. kalibr/kalibr.py +144 -230
  22. kalibr/kalibr_app.py +53 -314
  23. kalibr/middleware/__init__.py +5 -0
  24. kalibr/middleware/auto_tracer.py +356 -0
  25. kalibr/models.py +41 -0
  26. kalibr/redaction.py +44 -0
  27. kalibr/schemas.py +116 -0
  28. kalibr/simple_tracer.py +258 -0
  29. kalibr/tokens.py +52 -0
  30. kalibr/trace_capsule.py +296 -0
  31. kalibr/trace_models.py +201 -0
  32. kalibr/tracer.py +354 -0
  33. kalibr/types.py +25 -93
  34. kalibr/utils.py +198 -0
  35. kalibr-1.1.2a0.dist-info/METADATA +236 -0
  36. kalibr-1.1.2a0.dist-info/RECORD +48 -0
  37. kalibr-1.1.2a0.dist-info/entry_points.txt +2 -0
  38. kalibr-1.1.2a0.dist-info/licenses/LICENSE +21 -0
  39. kalibr-1.1.2a0.dist-info/top_level.txt +4 -0
  40. kalibr_crewai/__init__.py +65 -0
  41. kalibr_crewai/callbacks.py +539 -0
  42. kalibr_crewai/instrumentor.py +513 -0
  43. kalibr_langchain/__init__.py +47 -0
  44. kalibr_langchain/async_callback.py +850 -0
  45. kalibr_langchain/callback.py +1064 -0
  46. kalibr_openai_agents/__init__.py +43 -0
  47. kalibr_openai_agents/processor.py +554 -0
  48. kalibr/deployment.py +0 -41
  49. kalibr/packager.py +0 -43
  50. kalibr/runtime_router.py +0 -138
  51. kalibr/schema_generators.py +0 -159
  52. kalibr/validator.py +0 -70
  53. kalibr-1.0.25.data/data/examples/README.md +0 -173
  54. kalibr-1.0.25.data/data/examples/basic_kalibr_example.py +0 -66
  55. kalibr-1.0.25.data/data/examples/enhanced_kalibr_example.py +0 -347
  56. kalibr-1.0.25.dist-info/METADATA +0 -231
  57. kalibr-1.0.25.dist-info/RECORD +0 -19
  58. kalibr-1.0.25.dist-info/entry_points.txt +0 -2
  59. kalibr-1.0.25.dist-info/licenses/LICENSE +0 -11
  60. kalibr-1.0.25.dist-info/top_level.txt +0 -1
  61. {kalibr-1.0.25.dist-info → kalibr-1.1.2a0.dist-info}/WHEEL +0 -0
@@ -1,347 +0,0 @@
1
- """
2
- Enhanced Kalibr App Example - App-level capabilities
3
- This demonstrates the new enhanced capabilities including file uploads,
4
- sessions, streaming, workflows, and multi-model schema generation.
5
- """
6
-
7
- from kalibr import KalibrApp
8
- from kalibr.types import FileUpload, Session, StreamingResponse, WorkflowState, AuthenticatedUser
9
- import asyncio
10
- import json
11
- from datetime import datetime
12
- from typing import List
13
-
14
- # Create an enhanced KalibrApp instance
15
- app = KalibrApp(title="Enhanced Kalibr Demo", base_url="http://localhost:8000")
16
-
17
- # Basic action (compatible with original Kalibr)
18
- @app.action("hello", "Say hello with enhanced capabilities")
19
- def hello_enhanced(name: str = "World", include_timestamp: bool = False):
20
- """Enhanced hello function with optional timestamp"""
21
- message = f"Hello, {name}! This is Enhanced Kalibr v2.0"
22
-
23
- response = {"message": message}
24
- if include_timestamp:
25
- response["timestamp"] = datetime.now().isoformat()
26
-
27
- return response
28
-
29
- # File upload handler
30
- @app.file_handler("analyze_document", [".txt", ".md", ".py", ".js", ".json"])
31
- async def analyze_document(file: FileUpload):
32
- """Analyze uploaded document and return insights"""
33
- try:
34
- # Decode file content
35
- content = file.content.decode('utf-8')
36
-
37
- # Basic analysis
38
- lines = content.split('\n')
39
- words = content.split()
40
-
41
- # Language detection based on file extension
42
- language = "text"
43
- if file.filename.endswith('.py'):
44
- language = "python"
45
- elif file.filename.endswith('.js'):
46
- language = "javascript"
47
- elif file.filename.endswith('.json'):
48
- language = "json"
49
- try:
50
- json_data = json.loads(content)
51
- return {
52
- "upload_id": file.upload_id,
53
- "filename": file.filename,
54
- "analysis": {
55
- "type": "json",
56
- "valid_json": True,
57
- "keys": list(json_data.keys()) if isinstance(json_data, dict) else None,
58
- "size_bytes": file.size
59
- }
60
- }
61
- except json.JSONDecodeError:
62
- pass
63
-
64
- return {
65
- "upload_id": file.upload_id,
66
- "filename": file.filename,
67
- "analysis": {
68
- "language": language,
69
- "line_count": len(lines),
70
- "word_count": len(words),
71
- "character_count": len(content),
72
- "size_bytes": file.size,
73
- "non_empty_lines": len([line for line in lines if line.strip()]),
74
- "estimated_reading_time_minutes": len(words) / 200 # Average reading speed
75
- }
76
- }
77
- except UnicodeDecodeError:
78
- return {
79
- "upload_id": file.upload_id,
80
- "filename": file.filename,
81
- "error": "File is not text-readable (binary file)",
82
- "size_bytes": file.size
83
- }
84
-
85
- # Session-aware action
86
- @app.session_action("save_note", "Save a note to user session")
87
- async def save_note(session: Session, note_title: str, note_content: str):
88
- """Save a note to the user's session"""
89
-
90
- # Initialize notes if not exists
91
- if 'notes' not in session.data:
92
- session.data['notes'] = []
93
-
94
- # Create note object
95
- note = {
96
- "id": len(session.data['notes']) + 1,
97
- "title": note_title,
98
- "content": note_content,
99
- "created_at": datetime.now().isoformat(),
100
- "updated_at": datetime.now().isoformat()
101
- }
102
-
103
- session.data['notes'].append(note)
104
- session.set('last_note_id', note['id'])
105
-
106
- return {
107
- "status": "saved",
108
- "note": note,
109
- "total_notes": len(session.data['notes']),
110
- "session_id": session.session_id
111
- }
112
-
113
- @app.session_action("get_notes", "Retrieve all notes from session")
114
- async def get_notes(session: Session):
115
- """Get all notes from the user's session"""
116
- notes = session.get('notes', [])
117
-
118
- return {
119
- "notes": notes,
120
- "count": len(notes),
121
- "session_id": session.session_id,
122
- "last_note_id": session.get('last_note_id')
123
- }
124
-
125
- # Streaming action
126
- @app.stream_action("count_with_progress", "Stream counting with progress updates")
127
- async def count_with_progress(max_count: int = 10, delay_seconds: float = 1.0):
128
- """Stream counting numbers with progress indication"""
129
-
130
- for i in range(max_count + 1):
131
- progress_percent = (i / max_count) * 100
132
-
133
- yield {
134
- "count": i,
135
- "max_count": max_count,
136
- "progress_percent": progress_percent,
137
- "message": f"Counting: {i}/{max_count}",
138
- "timestamp": datetime.now().isoformat(),
139
- "is_complete": (i == max_count)
140
- }
141
-
142
- if i < max_count: # Don't delay after the last item
143
- await asyncio.sleep(delay_seconds)
144
-
145
- @app.stream_action("generate_fibonacci", "Stream Fibonacci sequence")
146
- async def generate_fibonacci(count: int = 20, delay_seconds: float = 0.5):
147
- """Generate Fibonacci sequence as a stream"""
148
-
149
- a, b = 0, 1
150
- for i in range(count):
151
- yield {
152
- "position": i + 1,
153
- "fibonacci_number": a,
154
- "sequence_so_far": f"F({i+1}) = {a}",
155
- "timestamp": datetime.now().isoformat()
156
- }
157
-
158
- a, b = b, a + b
159
- await asyncio.sleep(delay_seconds)
160
-
161
- # Complex workflow
162
- @app.workflow("process_text_analysis", "Complete text analysis workflow")
163
- async def text_analysis_workflow(text: str, workflow_state: WorkflowState):
164
- """Multi-step text analysis workflow"""
165
-
166
- # Step 1: Validation
167
- workflow_state.step = "validation"
168
- workflow_state.status = "processing"
169
-
170
- if not text or len(text.strip()) < 10:
171
- workflow_state.status = "error"
172
- return {"error": "Text must be at least 10 characters long"}
173
-
174
- await asyncio.sleep(1) # Simulate processing time
175
-
176
- # Step 2: Basic analysis
177
- workflow_state.step = "basic_analysis"
178
- workflow_state.data["validation_passed"] = True
179
-
180
- words = text.split()
181
- sentences = [s.strip() for s in text.replace('!', '.').replace('?', '.').split('.') if s.strip()]
182
-
183
- basic_stats = {
184
- "character_count": len(text),
185
- "word_count": len(words),
186
- "sentence_count": len(sentences),
187
- "paragraph_count": len([p for p in text.split('\n\n') if p.strip()])
188
- }
189
-
190
- workflow_state.data["basic_stats"] = basic_stats
191
- await asyncio.sleep(1)
192
-
193
- # Step 3: Advanced analysis
194
- workflow_state.step = "advanced_analysis"
195
-
196
- # Word frequency
197
- word_freq = {}
198
- for word in words:
199
- clean_word = word.lower().strip('.,!?";:')
200
- word_freq[clean_word] = word_freq.get(clean_word, 0) + 1
201
-
202
- # Top words
203
- top_words = sorted(word_freq.items(), key=lambda x: x[1], reverse=True)[:5]
204
-
205
- advanced_stats = {
206
- "unique_words": len(word_freq),
207
- "average_word_length": sum(len(word) for word in words) / len(words) if words else 0,
208
- "longest_word": max(words, key=len) if words else None,
209
- "top_words": top_words,
210
- "readability_score": min(100, max(0, 100 - (len(words) / len(sentences) if sentences else 1) * 2))
211
- }
212
-
213
- workflow_state.data["advanced_stats"] = advanced_stats
214
- await asyncio.sleep(1)
215
-
216
- # Step 4: Final compilation
217
- workflow_state.step = "compilation"
218
-
219
- result = {
220
- "workflow_id": workflow_state.workflow_id,
221
- "analysis_type": "complete_text_analysis",
222
- "input_text_preview": text[:100] + "..." if len(text) > 100 else text,
223
- "basic_statistics": basic_stats,
224
- "advanced_statistics": advanced_stats,
225
- "processing_steps": ["validation", "basic_analysis", "advanced_analysis", "compilation"],
226
- "completed_at": datetime.now().isoformat()
227
- }
228
-
229
- workflow_state.step = "completed"
230
- workflow_state.status = "success"
231
- workflow_state.data["final_result"] = result
232
-
233
- return result
234
-
235
- # Data processing workflow
236
- @app.workflow("batch_text_processor", "Process multiple texts in batch")
237
- async def batch_text_processor(texts: List[str], workflow_state: WorkflowState):
238
- """Process multiple texts as a batch workflow"""
239
-
240
- workflow_state.step = "initialization"
241
- workflow_state.status = "processing"
242
-
243
- if not texts or len(texts) == 0:
244
- workflow_state.status = "error"
245
- return {"error": "No texts provided for processing"}
246
-
247
- results = []
248
- workflow_state.data["total_texts"] = len(texts)
249
-
250
- for i, text in enumerate(texts):
251
- workflow_state.step = f"processing_text_{i+1}"
252
- workflow_state.data["current_text"] = i + 1
253
- workflow_state.data["progress_percent"] = ((i + 1) / len(texts)) * 100
254
-
255
- # Process each text
256
- words = text.split()
257
- analysis = {
258
- "text_id": i + 1,
259
- "text_preview": text[:50] + "..." if len(text) > 50 else text,
260
- "word_count": len(words),
261
- "character_count": len(text),
262
- "sentence_count": len([s for s in text.split('.') if s.strip()])
263
- }
264
-
265
- results.append(analysis)
266
- await asyncio.sleep(0.5) # Simulate processing time
267
-
268
- # Final aggregation
269
- workflow_state.step = "aggregation"
270
-
271
- total_words = sum(r["word_count"] for r in results)
272
- total_chars = sum(r["character_count"] for r in results)
273
-
274
- final_result = {
275
- "workflow_id": workflow_state.workflow_id,
276
- "batch_summary": {
277
- "total_texts_processed": len(results),
278
- "total_words": total_words,
279
- "total_characters": total_chars,
280
- "average_words_per_text": total_words / len(results) if results else 0,
281
- "average_chars_per_text": total_chars / len(results) if results else 0
282
- },
283
- "individual_results": results,
284
- "completed_at": datetime.now().isoformat()
285
- }
286
-
287
- workflow_state.step = "completed"
288
- workflow_state.status = "success"
289
- workflow_state.data["final_result"] = final_result
290
-
291
- return final_result
292
-
293
- # Advanced action with multiple parameters
294
- @app.action("advanced_search", "Perform advanced search with multiple filters")
295
- def advanced_search(
296
- query: str,
297
- category: str = "all",
298
- min_score: float = 0.0,
299
- max_results: int = 10,
300
- include_metadata: bool = False,
301
- sort_by: str = "relevance"
302
- ):
303
- """Advanced search function demonstrating complex parameter handling"""
304
-
305
- # Simulate search results
306
- mock_results = [
307
- {"id": 1, "title": f"Result matching '{query}'", "score": 0.95, "category": category},
308
- {"id": 2, "title": f"Another match for '{query}'", "score": 0.87, "category": category},
309
- {"id": 3, "title": f"Related to '{query}'", "score": 0.73, "category": category},
310
- ]
311
-
312
- # Filter by score
313
- filtered_results = [r for r in mock_results if r["score"] >= min_score]
314
-
315
- # Limit results
316
- filtered_results = filtered_results[:max_results]
317
-
318
- # Sort results
319
- if sort_by == "score":
320
- filtered_results.sort(key=lambda x: x["score"], reverse=True)
321
-
322
- response = {
323
- "query": query,
324
- "filters": {
325
- "category": category,
326
- "min_score": min_score,
327
- "max_results": max_results,
328
- "sort_by": sort_by
329
- },
330
- "results": filtered_results,
331
- "result_count": len(filtered_results)
332
- }
333
-
334
- if include_metadata:
335
- response["metadata"] = {
336
- "search_performed_at": datetime.now().isoformat(),
337
- "processing_time_ms": 45,
338
- "total_available": len(mock_results)
339
- }
340
-
341
- return response
342
-
343
- # Enable authentication (optional)
344
- # app.enable_auth("your-secret-jwt-key-here")
345
-
346
- # The app instance is automatically discovered by the Kalibr CLI
347
- # To run this: kalibr serve enhanced_kalibr_example.py --app-mode
@@ -1,231 +0,0 @@
1
- Metadata-Version: 2.4
2
- Name: kalibr
3
- Version: 1.0.25
4
- Summary: Multi-Model MCP SDK — deploy to GPT, Claude, Gemini, Copilot from one codebase.
5
- Home-page: https://github.com/devonakelley/kalibr-sdk
6
- Author: Kalibr Team
7
- Author-email: team@kalibr.dev
8
- Requires-Python: >=3.11
9
- Description-Content-Type: text/markdown
10
- License-File: LICENSE
11
- Requires-Dist: fastapi>=0.110.1
12
- Requires-Dist: uvicorn>=0.25.0
13
- Requires-Dist: typer>=0.9.0
14
- Requires-Dist: pydantic>=2.6.4
15
- Requires-Dist: requests>=2.31.0
16
- Requires-Dist: aiofiles>=23.2.1
17
- Requires-Dist: jsonschema>=4.21.1
18
- Dynamic: author
19
- Dynamic: author-email
20
- Dynamic: home-page
21
- Dynamic: license-file
22
- Dynamic: requires-python
23
-
24
- # Kalibr SDK
25
- ### Multi-Model AI Integration Framework
26
-
27
- **Write once. Deploy anywhere. Connect to any AI model.**
28
-
29
- Kalibr turns Python functions into APIs that work seamlessly with GPT, Claude, Gemini, and Copilot — automatically generating model-specific schemas and endpoints.
30
-
31
- ---
32
-
33
- ## 🚀 Quick Start (2 minutes)
34
-
35
- ### 1. Install
36
- ```bash
37
- pip install kalibr
38
- ```
39
-
40
- ### 2. Get Examples
41
- ```bash
42
- kalibr-connect examples
43
- ```
44
- This copies example files to `./kalibr_examples/` in your current directory.
45
-
46
- ### 3. Run Demo
47
- ```bash
48
- kalibr-connect serve kalibr_examples/basic_kalibr_example.py
49
- ```
50
-
51
- ### 4. See All Schemas
52
- Kalibr now **auto-detects your environment** and generates the correct base URLs.
53
-
54
- | Environment | Example Base URL |
55
- |--------------|------------------|
56
- | Local Dev | `http://localhost:8000` |
57
- | Fly.io | `https://<app-name>.fly.dev` |
58
- | Custom Host | Use `KALIBR_BASE_URL` env var |
59
-
60
- Then open:
61
- ```
62
- <your-base-url>/gpt-actions.json # ChatGPT
63
- <your-base-url>/mcp.json # Claude
64
- <your-base-url>/schemas/gemini # Gemini
65
- <your-base-url>/schemas/copilot # Copilot
66
- ```
67
-
68
- ---
69
-
70
- ## 🧠 What Kalibr Does
71
-
72
- Kalibr turns your Python functions into production-ready multi-model APIs.
73
-
74
- ```python
75
- from kalibr import Kalibr
76
-
77
- app = Kalibr(title="Inventory API")
78
-
79
- @app.action("get_inventory", "Fetch inventory data")
80
- def get_inventory(product_id: str):
81
- return {"product_id": product_id, "stock": 42}
82
- ```
83
-
84
- Result:
85
- ChatGPT, Claude, Gemini, and Copilot can all call `get_inventory()` using their native protocols — no schema work required.
86
-
87
- ---
88
-
89
- ## 💪 Two Modes
90
-
91
- ### **Function-Level (Simple)**
92
- Ideal for one-off APIs or scripts.
93
-
94
- ```python
95
- from kalibr import Kalibr
96
-
97
- app = Kalibr(title="My API")
98
-
99
- @app.action("calculate_price", "Calculate price total")
100
- def calculate_price(product_id: str, quantity: int):
101
- return {"total": quantity * 19.99}
102
- ```
103
-
104
- ### **App-Level (Advanced)**
105
- Use `KalibrApp` for complete control — file uploads, sessions, streaming, and workflows.
106
-
107
- ```python
108
- from kalibr import KalibrApp
109
- from kalibr.types import FileUpload, Session
110
-
111
- app = KalibrApp(title="Advanced API")
112
-
113
- @app.file_handler("analyze_doc", [".pdf", ".docx"])
114
- async def analyze_doc(file: FileUpload):
115
- return {"filename": file.filename, "analysis": "..."}
116
-
117
- @app.session_action("save_data", "Save session data")
118
- async def save_data(session: Session, data: dict):
119
- session.set("my_data", data)
120
- return {"saved": True}
121
- ```
122
-
123
- ---
124
-
125
- ## 📚 Examples Included
126
-
127
- After running `kalibr-connect examples`, you’ll get:
128
-
129
- - `basic_kalibr_example.py` – simple function-level demo
130
- - `enhanced_kalibr_example.py` – full app with sessions, uploads, and streaming
131
-
132
- ---
133
-
134
- ## 🤖 AI Platform Integration
135
-
136
- ### ChatGPT (GPT Actions)
137
- 1. Copy schema URL:
138
- `https://<your-domain>/gpt-actions.json`
139
- 2. In GPT Builder → *Actions* → *Import from URL*
140
- 3. Done — ChatGPT can call your endpoints.
141
-
142
- ### Claude (MCP)
143
- Add to Claude Desktop config:
144
- ```json
145
- {
146
- "mcp": {
147
- "servers": {
148
- "my-api": {
149
- "url": "https://<your-domain>/mcp.json"
150
- }
151
- }
152
- }
153
- }
154
- ```
155
-
156
- ### Gemini / Copilot
157
- Use:
158
- ```
159
- https://<your-domain>/schemas/gemini
160
- https://<your-domain>/schemas/copilot
161
- ```
162
-
163
- ---
164
-
165
- ## 🎯 Common Use Cases
166
-
167
- - **Customer Service APIs** — let AI handle orders or refunds
168
- - **Data Analysis** — query your analytics through AI
169
- - **Document Processing** — parse or summarize uploaded docs
170
- - **Business Automation** — trigger internal workflows
171
- - **Internal Tools** — expose secure internal logic to assistants
172
-
173
- ---
174
-
175
- ## 🔧 CLI Reference
176
-
177
- ```bash
178
- kalibr-connect examples # Copy examples
179
- kalibr-connect serve my_app.py # Run locally
180
- kalibr-connect version # Show version
181
- kalibr-connect --help # Full CLI
182
- ```
183
-
184
- ---
185
-
186
- ## âš¡ Key Features
187
-
188
- ✅ Multi-Model Support — GPT, Claude, Gemini, Copilot
189
- ✅ Automatic Schema Generation
190
- ✅ Environment-Aware Base URLs (v1.0.21+)
191
- ✅ File Uploads
192
- ✅ Session Management
193
- ✅ Streaming Responses
194
- ✅ Workflow Support
195
- ✅ Type-Safe API Generation
196
- ✅ Async / Await Ready
197
-
198
- ---
199
-
200
- ## 🔥 Why Kalibr?
201
-
202
- Without Kalibr:
203
- - Learn 4 model specs
204
- - Maintain 4 codebases
205
- - Duplicate effort
206
-
207
- With Kalibr:
208
- - One Python function
209
- - Four schemas generated automatically
210
- - Deploy anywhere
211
-
212
- ---
213
-
214
- ## 🆕 Version 1.0.21+
215
-
216
- - **Automatic Base-URL Detection**
217
- - Works with `KALIBR_BASE_URL` or `FLY_APP_NAME`
218
- - Fixes all localhost references in deployed schemas
219
- - Ready for **MCP ecosystem production use**
220
- - Drop-in backwards compatibility
221
-
222
- ---
223
-
224
- ## 🧩 License
225
-
226
- MIT License — see `LICENSE` file for details.
227
-
228
- ---
229
-
230
- **Kalibr SDK — the unified layer between AI models and the real world.**
231
- Write once. Deploy anywhere. Integrate everything.
@@ -1,19 +0,0 @@
1
- kalibr/__init__.py,sha256=sm5S95QKw1J7NbsrdgJAd9sdn8wfO_mbEfRhytJ0_wg,119
2
- kalibr/__main__.py,sha256=nRQLefjyoy9c_-UKU1UZGcCRrypQWchJAbUlmNFPv2g,8353
3
- kalibr/deployment.py,sha256=GZ874FXQX1uIroTA-UM5A-pTVn2UY0NxXi39vmTowyI,1396
4
- kalibr/kalibr.py,sha256=yrgXVlTgadBbpnX_l7fAxxjxGp9oxcZhzGjaQPiIcpo,10469
5
- kalibr/kalibr_app.py,sha256=5ylagvKEsGN6T6AFr9rWHaAjdWcpKdDG7nhDPUEQAQA,13809
6
- kalibr/packager.py,sha256=vrwviRzZMjegbDXyjZZwA7gsqchd5V6PZAZTi5WNjyQ,1353
7
- kalibr/runtime_router.py,sha256=PTXMj5yt72cfzYtjWQ-mUF3t8eov9nuXXI0ScIVNMrU,4606
8
- kalibr/schema_generators.py,sha256=xxnY05KgHTJ7BPXMCIC-McJCCt8aIOF5s0ptCwDqs_Y,6716
9
- kalibr/types.py,sha256=bNmf_cOWXBmhaMVAPEp3_EdRCcdXY2pbOgOxZ1dZ0Mc,3476
10
- kalibr/validator.py,sha256=PezDmHG9dVINce91rdYQstJC41eZP21qEA3VDICE3C4,2333
11
- kalibr-1.0.25.data/data/examples/README.md,sha256=loo2nm6yfT-pqGb5uNg1VeEdOKflYzHISUHTuSltfY0,4875
12
- kalibr-1.0.25.data/data/examples/basic_kalibr_example.py,sha256=Kfrh-XZuJ0vwFLB_xBpdqpgpMJw2NpIx0yBsqrAqBnE,2188
13
- kalibr-1.0.25.data/data/examples/enhanced_kalibr_example.py,sha256=AuhTpyRUNVAJuZKRy9iydXusNkBgQ84eKNiXxsr4iUQ,11994
14
- kalibr-1.0.25.dist-info/licenses/LICENSE,sha256=1WLJDkrueNpHCROy9zANrK2Ar2weqZ_z88hw90UKDoc,451
15
- kalibr-1.0.25.dist-info/METADATA,sha256=78UxEYfpZk_-ijfDXhQ-v6DcDQF1TE9kkETi8cmVJZo,5424
16
- kalibr-1.0.25.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
17
- kalibr-1.0.25.dist-info/entry_points.txt,sha256=KiJfV_BaeYdIdYniww3wnSBBqSHpRxP9BTLNwu7IjyY,48
18
- kalibr-1.0.25.dist-info/top_level.txt,sha256=OkloC5_IfpE4-QwI30aLIYbFZk_-ChABWF7aBGddy28,7
19
- kalibr-1.0.25.dist-info/RECORD,,
@@ -1,2 +0,0 @@
1
- [console_scripts]
2
- kalibr = kalibr.__main__:main
@@ -1,11 +0,0 @@
1
- Kalibr Source-Available License
2
-
3
- Copyright (c) 2025 Kalibr Systems.
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining a copy of this software
6
- for the purpose of internal evaluation, testing, or demonstration only.
7
-
8
- Commercial, production, or revenue-generating use of this software requires a valid commercial
9
- license from Kalibr Systems (https://kalibr.systems).
10
-
11
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND.
@@ -1 +0,0 @@
1
- kalibr