kalibr 1.0.28__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.
- kalibr/__init__.py +170 -3
- kalibr/__main__.py +3 -203
- kalibr/capsule_middleware.py +108 -0
- kalibr/cli/__init__.py +5 -0
- kalibr/cli/capsule_cmd.py +174 -0
- kalibr/cli/deploy_cmd.py +114 -0
- kalibr/cli/main.py +67 -0
- kalibr/cli/run.py +203 -0
- kalibr/cli/serve.py +59 -0
- kalibr/client.py +293 -0
- kalibr/collector.py +173 -0
- kalibr/context.py +132 -0
- kalibr/cost_adapter.py +222 -0
- kalibr/decorators.py +140 -0
- kalibr/instrumentation/__init__.py +13 -0
- kalibr/instrumentation/anthropic_instr.py +282 -0
- kalibr/instrumentation/base.py +108 -0
- kalibr/instrumentation/google_instr.py +281 -0
- kalibr/instrumentation/openai_instr.py +265 -0
- kalibr/instrumentation/registry.py +153 -0
- kalibr/kalibr.py +144 -230
- kalibr/kalibr_app.py +53 -314
- kalibr/middleware/__init__.py +5 -0
- kalibr/middleware/auto_tracer.py +356 -0
- kalibr/models.py +41 -0
- kalibr/redaction.py +44 -0
- kalibr/schemas.py +116 -0
- kalibr/simple_tracer.py +258 -0
- kalibr/tokens.py +52 -0
- kalibr/trace_capsule.py +296 -0
- kalibr/trace_models.py +201 -0
- kalibr/tracer.py +354 -0
- kalibr/types.py +25 -93
- kalibr/utils.py +198 -0
- kalibr-1.1.2a0.dist-info/METADATA +236 -0
- kalibr-1.1.2a0.dist-info/RECORD +48 -0
- kalibr-1.1.2a0.dist-info/entry_points.txt +2 -0
- kalibr-1.1.2a0.dist-info/licenses/LICENSE +21 -0
- kalibr-1.1.2a0.dist-info/top_level.txt +4 -0
- kalibr_crewai/__init__.py +65 -0
- kalibr_crewai/callbacks.py +539 -0
- kalibr_crewai/instrumentor.py +513 -0
- kalibr_langchain/__init__.py +47 -0
- kalibr_langchain/async_callback.py +850 -0
- kalibr_langchain/callback.py +1064 -0
- kalibr_openai_agents/__init__.py +43 -0
- kalibr_openai_agents/processor.py +554 -0
- kalibr/deployment.py +0 -41
- kalibr/packager.py +0 -43
- kalibr/runtime_router.py +0 -138
- kalibr/schema_generators.py +0 -159
- kalibr/validator.py +0 -70
- kalibr-1.0.28.data/data/examples/README.md +0 -173
- kalibr-1.0.28.data/data/examples/basic_kalibr_example.py +0 -66
- kalibr-1.0.28.data/data/examples/enhanced_kalibr_example.py +0 -347
- kalibr-1.0.28.dist-info/METADATA +0 -175
- kalibr-1.0.28.dist-info/RECORD +0 -19
- kalibr-1.0.28.dist-info/entry_points.txt +0 -2
- kalibr-1.0.28.dist-info/licenses/LICENSE +0 -11
- kalibr-1.0.28.dist-info/top_level.txt +0 -1
- {kalibr-1.0.28.dist-info → kalibr-1.1.2a0.dist-info}/WHEEL +0 -0
kalibr/runtime_router.py
DELETED
|
@@ -1,138 +0,0 @@
|
|
|
1
|
-
"""
|
|
2
|
-
Runtime Router
|
|
3
|
-
--------------
|
|
4
|
-
Abstraction over deployment targets without hosting them ourselves.
|
|
5
|
-
Generates minimal configs and invokes the target's CLI/API where possible.
|
|
6
|
-
|
|
7
|
-
Supported:
|
|
8
|
-
- local (uvicorn)
|
|
9
|
-
- fly (fly.io) -> generates fly.toml and basic Dockerfile
|
|
10
|
-
- render -> generates render.yaml
|
|
11
|
-
|
|
12
|
-
Note: We do not ship vendor SDKs. We shell out to their CLIs if present.
|
|
13
|
-
"""
|
|
14
|
-
|
|
15
|
-
from __future__ import annotations
|
|
16
|
-
from pathlib import Path
|
|
17
|
-
import subprocess
|
|
18
|
-
import shutil
|
|
19
|
-
import os
|
|
20
|
-
import json
|
|
21
|
-
from typing import Dict, Any, Optional, Tuple
|
|
22
|
-
|
|
23
|
-
HERE = Path(__file__).parent
|
|
24
|
-
|
|
25
|
-
def which(cmd: str) -> Optional[str]:
|
|
26
|
-
return shutil.which(cmd)
|
|
27
|
-
|
|
28
|
-
def ensure_file(path: Path, content: str):
|
|
29
|
-
path.parent.mkdir(parents=True, exist_ok=True)
|
|
30
|
-
if not path.exists():
|
|
31
|
-
path.write_text(content)
|
|
32
|
-
|
|
33
|
-
def generate_fly_files(app_name: str) -> Tuple[Path, Path]:
|
|
34
|
-
fly_toml = Path("fly.toml")
|
|
35
|
-
dockerfile = Path("Dockerfile")
|
|
36
|
-
ensure_file(fly_toml, f"""# fly.toml
|
|
37
|
-
app = "{app_name}"
|
|
38
|
-
primary_region = "iad"
|
|
39
|
-
|
|
40
|
-
[build]
|
|
41
|
-
dockerfile = "Dockerfile"
|
|
42
|
-
|
|
43
|
-
[http_service]
|
|
44
|
-
internal_port = 8000
|
|
45
|
-
force_https = true
|
|
46
|
-
auto_stop_machines = "off"
|
|
47
|
-
auto_start_machines = true
|
|
48
|
-
min_machines_running = 1
|
|
49
|
-
""")
|
|
50
|
-
ensure_file(dockerfile, """# Dockerfile
|
|
51
|
-
FROM python:3.11-slim
|
|
52
|
-
WORKDIR /app
|
|
53
|
-
COPY . /app
|
|
54
|
-
RUN pip install --no-cache-dir -U pip && \
|
|
55
|
-
pip install --no-cache-dir fastapi uvicorn typer pydantic requests
|
|
56
|
-
EXPOSE 8000
|
|
57
|
-
CMD ["python", "-m", "kalibr", "serve", "kalibr_app.py", "--host", "0.0.0.0", "--port", "8000", "--base-url", "http://0.0.0.0:8000"]
|
|
58
|
-
""")
|
|
59
|
-
return fly_toml, dockerfile
|
|
60
|
-
|
|
61
|
-
def generate_render_file(service_name: str) -> Path:
|
|
62
|
-
render_yaml = Path("render.yaml")
|
|
63
|
-
ensure_file(render_yaml, f"""# render.yaml
|
|
64
|
-
services:
|
|
65
|
-
- type: web
|
|
66
|
-
name: {service_name}
|
|
67
|
-
env: docker
|
|
68
|
-
plan: free
|
|
69
|
-
dockerfilePath: ./Dockerfile
|
|
70
|
-
autoDeploy: true
|
|
71
|
-
""")
|
|
72
|
-
return render_yaml
|
|
73
|
-
|
|
74
|
-
def deploy_local(app_file: str, host: str = "0.0.0.0", port: int = 8000, base_url: str = "http://localhost:8000") -> Dict[str, Any]:
|
|
75
|
-
# Run uvicorn inline (non-blocking not handled here - CLI uses this to print guidance)
|
|
76
|
-
cmd = ["python", "-m", "kalibr", "serve", app_file, "--host", host, "--port", str(port), "--base-url", base_url]
|
|
77
|
-
print("▶︎", " ".join(cmd))
|
|
78
|
-
subprocess.run(cmd, check=False)
|
|
79
|
-
return {
|
|
80
|
-
"status": "started",
|
|
81
|
-
"endpoints": {
|
|
82
|
-
"root": f"{base_url}/",
|
|
83
|
-
"mcp": f"{base_url}/mcp.json",
|
|
84
|
-
"openapi": f"{base_url}/openapi.json",
|
|
85
|
-
"health": f"{base_url}/health"
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
def deploy_fly(app_name: str) -> Dict[str, Any]:
|
|
90
|
-
if not which("flyctl"):
|
|
91
|
-
raise RuntimeError("flyctl is not installed. See https://fly.io/docs/flyctl/install/")
|
|
92
|
-
# Ensure files exist
|
|
93
|
-
generate_fly_files(app_name)
|
|
94
|
-
# Launch or deploy
|
|
95
|
-
print("▶︎ flyctl apps list")
|
|
96
|
-
subprocess.run(["flyctl", "apps", "list"], check=False)
|
|
97
|
-
print(f"▶︎ flyctl deploy --app {app_name}")
|
|
98
|
-
subprocess.run(["flyctl", "deploy", "--app", app_name], check=False)
|
|
99
|
-
url = f"https://{app_name}.fly.dev"
|
|
100
|
-
return {
|
|
101
|
-
"status": "success",
|
|
102
|
-
"endpoints": {
|
|
103
|
-
"root": f"{url}/",
|
|
104
|
-
"mcp": f"{url}/mcp.json",
|
|
105
|
-
"openapi": f"{url}/openapi.json",
|
|
106
|
-
"health": f"{url}/health"
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
def deploy_render(service_name: str) -> Dict[str, Any]:
|
|
111
|
-
# We just generate render.yaml and Dockerfile. User connects repo in Render UI.
|
|
112
|
-
generate_render_file(service_name)
|
|
113
|
-
ensure_file(Path("Dockerfile"), """# Dockerfile for Render
|
|
114
|
-
FROM python:3.11-slim
|
|
115
|
-
WORKDIR /app
|
|
116
|
-
COPY . /app
|
|
117
|
-
RUN pip install --no-cache-dir -U pip && \
|
|
118
|
-
pip install --no-cache-dir fastapi uvicorn typer pydantic requests
|
|
119
|
-
EXPOSE 8000
|
|
120
|
-
CMD ["python", "-m", "kalibr", "serve", "kalibr_app.py", "--host", "0.0.0.0", "--port", "8000", "--base-url", "https://$RENDER_EXTERNAL_URL"]
|
|
121
|
-
""")
|
|
122
|
-
print("📄 Generated render.yaml and Dockerfile. Connect your repo in Render.com and auto-deploy.")
|
|
123
|
-
return {
|
|
124
|
-
"status": "success",
|
|
125
|
-
"endpoints": {},
|
|
126
|
-
"note": "Connect this repository to Render; it will build from render.yaml."
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
def deploy(runtime: str, app_name: str, app_file: str, host: str = "0.0.0.0", port: int = 8000, base_url: str = "http://localhost:8000") -> Dict[str, Any]:
|
|
130
|
-
runtime = runtime.lower()
|
|
131
|
-
if runtime in ("local", "dev"):
|
|
132
|
-
return deploy_local(app_file, host, port, base_url)
|
|
133
|
-
if runtime in ("fly", "flyio"):
|
|
134
|
-
return deploy_fly(app_name)
|
|
135
|
-
if runtime == "render":
|
|
136
|
-
return deploy_render(app_name)
|
|
137
|
-
raise ValueError(f"Unknown runtime: {runtime}")
|
|
138
|
-
|
kalibr/schema_generators.py
DELETED
|
@@ -1,159 +0,0 @@
|
|
|
1
|
-
"""
|
|
2
|
-
Multi-model schema generators for different AI platforms
|
|
3
|
-
"""
|
|
4
|
-
from typing import Dict, Any, List
|
|
5
|
-
from abc import ABC, abstractmethod
|
|
6
|
-
|
|
7
|
-
KALIBR_TITLE = "Kalibr Enhanced API"
|
|
8
|
-
KALIBR_VERSION = "2.0.0"
|
|
9
|
-
MCP_SPEC_VERSION = "1.0" # bump via validator when MCP evolves
|
|
10
|
-
|
|
11
|
-
class BaseSchemaGenerator(ABC):
|
|
12
|
-
"""Base class for AI model schema generators"""
|
|
13
|
-
@abstractmethod
|
|
14
|
-
def generate_schema(self, actions: Dict, base_url: str) -> Dict[str, Any]:
|
|
15
|
-
pass
|
|
16
|
-
|
|
17
|
-
class MCPSchemaGenerator(BaseSchemaGenerator):
|
|
18
|
-
"""Claude/GPT-AgentBuilder MCP schema generator"""
|
|
19
|
-
def generate_schema(self, actions: Dict, base_url: str) -> Dict[str, Any]:
|
|
20
|
-
tools = []
|
|
21
|
-
for action_name, action_data in actions.items():
|
|
22
|
-
properties = {}
|
|
23
|
-
required = []
|
|
24
|
-
for param_name, param_info in action_data["params"].items():
|
|
25
|
-
properties[param_name] = {"type": param_info["type"]}
|
|
26
|
-
if param_info["required"]:
|
|
27
|
-
required.append(param_name)
|
|
28
|
-
tools.append({
|
|
29
|
-
"name": action_name,
|
|
30
|
-
"description": action_data["description"],
|
|
31
|
-
"input_schema": {
|
|
32
|
-
"type": "object",
|
|
33
|
-
"properties": properties,
|
|
34
|
-
"required": required
|
|
35
|
-
},
|
|
36
|
-
"server": {"url": f"{base_url}/proxy/{action_name}"}
|
|
37
|
-
})
|
|
38
|
-
return {
|
|
39
|
-
"mcp": MCP_SPEC_VERSION,
|
|
40
|
-
"name": "kalibr-enhanced",
|
|
41
|
-
"tools": tools
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
class OpenAPISchemaGenerator(BaseSchemaGenerator):
|
|
45
|
-
"""GPT Actions OpenAPI schema generator (legacy but still useful)"""
|
|
46
|
-
def generate_schema(self, actions: Dict, base_url: str) -> Dict[str, Any]:
|
|
47
|
-
paths = {}
|
|
48
|
-
for action_name, action_data in actions.items():
|
|
49
|
-
properties = {}
|
|
50
|
-
required = []
|
|
51
|
-
for param_name, param_info in action_data["params"].items():
|
|
52
|
-
properties[param_name] = {"type": param_info["type"]}
|
|
53
|
-
if param_info["required"]:
|
|
54
|
-
required.append(param_name)
|
|
55
|
-
paths[f"/proxy/{action_name}"] = {
|
|
56
|
-
"post": {
|
|
57
|
-
"summary": action_data["description"],
|
|
58
|
-
"operationId": action_name,
|
|
59
|
-
"requestBody": {
|
|
60
|
-
"required": True,
|
|
61
|
-
"content": {
|
|
62
|
-
"application/json": {
|
|
63
|
-
"schema": {
|
|
64
|
-
"type": "object",
|
|
65
|
-
"properties": properties,
|
|
66
|
-
"required": required
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
},
|
|
71
|
-
"responses": {
|
|
72
|
-
"200": {
|
|
73
|
-
"description": "Successful response",
|
|
74
|
-
"content": {"application/json": {"schema": {"type": "object"}}}
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
return {
|
|
80
|
-
"openapi": "3.0.0",
|
|
81
|
-
"info": {"title": KALIBR_TITLE, "version": KALIBR_VERSION, "description": "Enhanced Kalibr API"},
|
|
82
|
-
"servers": [{"url": base_url}],
|
|
83
|
-
"paths": paths
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
class GeminiSchemaGenerator(BaseSchemaGenerator):
|
|
87
|
-
"""Google Gemini Extensions schema generator"""
|
|
88
|
-
def generate_schema(self, actions: Dict, base_url: str) -> Dict[str, Any]:
|
|
89
|
-
functions = []
|
|
90
|
-
for action_name, action_data in actions.items():
|
|
91
|
-
parameters = {"type": "object", "properties": {}, "required": []}
|
|
92
|
-
for param_name, param_info in action_data["params"].items():
|
|
93
|
-
parameters["properties"][param_name] = {"type": param_info["type"], "description": f"Parameter {param_name}"}
|
|
94
|
-
if param_info["required"]:
|
|
95
|
-
parameters["required"].append(param_name)
|
|
96
|
-
functions.append({
|
|
97
|
-
"name": action_name,
|
|
98
|
-
"description": action_data["description"],
|
|
99
|
-
"parameters": parameters,
|
|
100
|
-
"server": {"url": f"{base_url}/proxy/{action_name}"}
|
|
101
|
-
})
|
|
102
|
-
return {
|
|
103
|
-
"gemini_extension": "1.0",
|
|
104
|
-
"name": "kalibr_enhanced",
|
|
105
|
-
"description": "Enhanced Kalibr API for Gemini integration",
|
|
106
|
-
"functions": functions
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
class CopilotSchemaGenerator(BaseSchemaGenerator):
|
|
110
|
-
"""Microsoft Copilot plugin schema generator (transitional)"""
|
|
111
|
-
def generate_schema(self, actions: Dict, base_url: str) -> Dict[str, Any]:
|
|
112
|
-
apis = []
|
|
113
|
-
for action_name, action_data in actions.items():
|
|
114
|
-
request_schema = {"type": "object", "properties": {}, "required": []}
|
|
115
|
-
for param_name, param_info in action_data["params"].items():
|
|
116
|
-
request_schema["properties"][param_name] = {"type": param_info["type"]}
|
|
117
|
-
if param_info["required"]:
|
|
118
|
-
request_schema["required"].append(param_name)
|
|
119
|
-
apis.append({
|
|
120
|
-
"name": action_name,
|
|
121
|
-
"description": action_data["description"],
|
|
122
|
-
"url": f"{base_url}/proxy/{action_name}",
|
|
123
|
-
"method": "POST",
|
|
124
|
-
"request_schema": request_schema,
|
|
125
|
-
"response_schema": {"type": "object", "description": "API response"}
|
|
126
|
-
})
|
|
127
|
-
return {
|
|
128
|
-
"schema_version": "v1",
|
|
129
|
-
"name_for_model": "kalibr_enhanced",
|
|
130
|
-
"name_for_human": "Enhanced Kalibr API",
|
|
131
|
-
"description_for_model": "Enhanced Kalibr API with advanced capabilities",
|
|
132
|
-
"description_for_human": "API for advanced AI model integrations",
|
|
133
|
-
"auth": {"type": "none"},
|
|
134
|
-
"api": {"type": "openapi", "url": f"{base_url}/openapi.json"},
|
|
135
|
-
"apis": apis
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
class CustomModelSchemaGenerator(BaseSchemaGenerator):
|
|
139
|
-
"""Extensible generator for future AI models"""
|
|
140
|
-
def __init__(self, model_name: str, schema_format: str):
|
|
141
|
-
self.model_name = model_name
|
|
142
|
-
self.schema_format = schema_format
|
|
143
|
-
|
|
144
|
-
def generate_schema(self, actions: Dict, base_url: str) -> Dict[str, Any]:
|
|
145
|
-
return {
|
|
146
|
-
"model": self.model_name,
|
|
147
|
-
"format": self.schema_format,
|
|
148
|
-
"version": KALIBR_VERSION,
|
|
149
|
-
"base_url": base_url,
|
|
150
|
-
"actions": [
|
|
151
|
-
{
|
|
152
|
-
"name": name,
|
|
153
|
-
"description": data["description"],
|
|
154
|
-
"parameters": data["params"],
|
|
155
|
-
"endpoint": f"{base_url}/proxy/{name}"
|
|
156
|
-
}
|
|
157
|
-
for name, data in actions.items()
|
|
158
|
-
]
|
|
159
|
-
}
|
kalibr/validator.py
DELETED
|
@@ -1,70 +0,0 @@
|
|
|
1
|
-
"""
|
|
2
|
-
Validator
|
|
3
|
-
---------
|
|
4
|
-
- Validates MCP manifest structure (lightweight JSONSchema)
|
|
5
|
-
- Detects spec drift (compares manifest version vs. embedded known latest)
|
|
6
|
-
- Provides 'update-schemas' hook (stub here; can fetch from GH in future)
|
|
7
|
-
|
|
8
|
-
Note: We keep it offline-safe. You can later wire network fetch if desired.
|
|
9
|
-
"""
|
|
10
|
-
|
|
11
|
-
from __future__ import annotations
|
|
12
|
-
from typing import Dict, Any
|
|
13
|
-
import json
|
|
14
|
-
from jsonschema import validate, Draft7Validator
|
|
15
|
-
|
|
16
|
-
# Minimal MCP JSON schema (aligned with your generator shape)
|
|
17
|
-
MCP_SCHEMA = {
|
|
18
|
-
"type": "object",
|
|
19
|
-
"required": ["mcp", "name", "tools"],
|
|
20
|
-
"properties": {
|
|
21
|
-
"mcp": {"type": "string"},
|
|
22
|
-
"name": {"type": "string"},
|
|
23
|
-
"tools": {
|
|
24
|
-
"type": "array",
|
|
25
|
-
"items": {
|
|
26
|
-
"type": "object",
|
|
27
|
-
"required": ["name", "description", "input_schema", "server"],
|
|
28
|
-
"properties": {
|
|
29
|
-
"name": {"type": "string"},
|
|
30
|
-
"description": {"type": "string"},
|
|
31
|
-
"input_schema": {
|
|
32
|
-
"type": "object",
|
|
33
|
-
"required": ["type", "properties"],
|
|
34
|
-
"properties": {
|
|
35
|
-
"type": {"type": "string"},
|
|
36
|
-
"properties": {"type": "object"},
|
|
37
|
-
"required": {"type": "array", "items": {"type": "string"}}
|
|
38
|
-
}
|
|
39
|
-
},
|
|
40
|
-
"server": {
|
|
41
|
-
"type": "object",
|
|
42
|
-
"required": ["url"],
|
|
43
|
-
"properties": {"url": {"type": "string"}}
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
LATEST_MCP_SPEC_VERSION = "1.0" # bump here as spec evolves
|
|
52
|
-
|
|
53
|
-
def validate_mcp_manifest(manifest: Dict[str, Any]) -> None:
|
|
54
|
-
# Structural validation
|
|
55
|
-
validate(instance=manifest, schema=MCP_SCHEMA)
|
|
56
|
-
# Version guidance
|
|
57
|
-
version = str(manifest.get("mcp", ""))
|
|
58
|
-
if version != LATEST_MCP_SPEC_VERSION:
|
|
59
|
-
print(f"⚠️ MCP spec version in manifest is '{version}'. Latest known is '{LATEST_MCP_SPEC_VERSION}'.")
|
|
60
|
-
print(" Run `kalibr update-schemas` after updating the SDK, or regenerate the manifest.")
|
|
61
|
-
|
|
62
|
-
def update_schemas() -> None:
|
|
63
|
-
"""
|
|
64
|
-
Stub: In a connected environment, fetch updated schema templates.
|
|
65
|
-
Here, we simply print guidance so the CLI can expose the command now.
|
|
66
|
-
"""
|
|
67
|
-
print("🔄 Update schemas (stub):")
|
|
68
|
-
print(" - Upgrade kalibr SDK to latest version: pip install -U kalibr")
|
|
69
|
-
print(" - Re-run manifest generation to pick up spec changes.")
|
|
70
|
-
|
|
@@ -1,173 +0,0 @@
|
|
|
1
|
-
# Enhanced Kalibr SDK Examples
|
|
2
|
-
|
|
3
|
-
This directory contains examples demonstrating both the original function-level Kalibr capabilities and the new enhanced app-level features.
|
|
4
|
-
|
|
5
|
-
## Examples Included
|
|
6
|
-
|
|
7
|
-
### 1. Basic Kalibr Example (`basic_kalibr_example.py`)
|
|
8
|
-
Demonstrates the original Kalibr SDK capabilities:
|
|
9
|
-
- Simple function decoration with `@sdk.action()`
|
|
10
|
-
- Basic parameter handling and type inference
|
|
11
|
-
- Compatible with GPT Actions and Claude MCP
|
|
12
|
-
- Simple API endpoints
|
|
13
|
-
|
|
14
|
-
**Features shown:**
|
|
15
|
-
- Text processing functions
|
|
16
|
-
- Mathematical calculations
|
|
17
|
-
- Email validation
|
|
18
|
-
- Text statistics
|
|
19
|
-
|
|
20
|
-
**To run:**
|
|
21
|
-
```bash
|
|
22
|
-
kalibr serve basic_kalibr_example.py
|
|
23
|
-
```
|
|
24
|
-
|
|
25
|
-
**Test endpoints:**
|
|
26
|
-
- `POST /proxy/greet` - Greeting function
|
|
27
|
-
- `POST /proxy/calculate` - Basic calculator
|
|
28
|
-
- `POST /proxy/validate_email` - Email validation
|
|
29
|
-
- `POST /proxy/text_stats` - Text analysis
|
|
30
|
-
|
|
31
|
-
### 2. Enhanced Kalibr Example (`enhanced_kalibr_example.py`)
|
|
32
|
-
Demonstrates the new enhanced app-level capabilities:
|
|
33
|
-
- File upload handling
|
|
34
|
-
- Session management
|
|
35
|
-
- Streaming responses
|
|
36
|
-
- Complex workflows
|
|
37
|
-
- Multi-model schema generation
|
|
38
|
-
|
|
39
|
-
**Features shown:**
|
|
40
|
-
- File upload and analysis
|
|
41
|
-
- Session-based note taking
|
|
42
|
-
- Real-time streaming data
|
|
43
|
-
- Multi-step workflows
|
|
44
|
-
- Advanced parameter handling
|
|
45
|
-
|
|
46
|
-
**To run:**
|
|
47
|
-
```bash
|
|
48
|
-
kalibr serve enhanced_kalibr_example.py --app-mode
|
|
49
|
-
```
|
|
50
|
-
|
|
51
|
-
**Test endpoints:**
|
|
52
|
-
- `POST /upload/analyze_document` - File upload analysis
|
|
53
|
-
- `POST /session/save_note` - Session-based note saving
|
|
54
|
-
- `GET /stream/count_with_progress` - Streaming counter
|
|
55
|
-
- `POST /workflow/process_text_analysis` - Complex text workflow
|
|
56
|
-
|
|
57
|
-
## Multi-Model Integration
|
|
58
|
-
|
|
59
|
-
Both examples automatically generate schemas for multiple AI models:
|
|
60
|
-
|
|
61
|
-
### Available Schema Endpoints:
|
|
62
|
-
- **Claude MCP**: `/mcp.json`
|
|
63
|
-
- **GPT Actions**: `/openapi.json`
|
|
64
|
-
- **Gemini Extensions**: `/schemas/gemini`
|
|
65
|
-
- **Microsoft Copilot**: `/schemas/copilot`
|
|
66
|
-
|
|
67
|
-
### Management Endpoints:
|
|
68
|
-
- **Health Check**: `/health`
|
|
69
|
-
- **Supported Models**: `/models/supported`
|
|
70
|
-
- **API Documentation**: `/docs`
|
|
71
|
-
|
|
72
|
-
## Usage Examples
|
|
73
|
-
|
|
74
|
-
### Basic Function Call:
|
|
75
|
-
```bash
|
|
76
|
-
curl -X POST http://localhost:8000/proxy/greet \
|
|
77
|
-
-H "Content-Type: application/json" \
|
|
78
|
-
-d '{"name": "Alice", "greeting": "Hi"}'
|
|
79
|
-
```
|
|
80
|
-
|
|
81
|
-
### File Upload:
|
|
82
|
-
```bash
|
|
83
|
-
curl -X POST http://localhost:8000/upload/analyze_document \
|
|
84
|
-
-F "file=@example.txt"
|
|
85
|
-
```
|
|
86
|
-
|
|
87
|
-
### Session Management:
|
|
88
|
-
```bash
|
|
89
|
-
# Save a note (creates session)
|
|
90
|
-
curl -X POST http://localhost:8000/session/save_note \
|
|
91
|
-
-H "Content-Type: application/json" \
|
|
92
|
-
-d '{"note_title": "My Note", "note_content": "This is a test note"}'
|
|
93
|
-
|
|
94
|
-
# Get notes (use session ID from previous response)
|
|
95
|
-
curl -X POST http://localhost:8000/session/get_notes \
|
|
96
|
-
-H "Content-Type: application/json" \
|
|
97
|
-
-H "x-session-id: <session-id-here>" \
|
|
98
|
-
-d '{}'
|
|
99
|
-
```
|
|
100
|
-
|
|
101
|
-
### Streaming Data:
|
|
102
|
-
```bash
|
|
103
|
-
curl http://localhost:8000/stream/count_with_progress?max_count=5&delay_seconds=1
|
|
104
|
-
```
|
|
105
|
-
|
|
106
|
-
### Complex Workflow:
|
|
107
|
-
```bash
|
|
108
|
-
curl -X POST http://localhost:8000/workflow/process_text_analysis \
|
|
109
|
-
-H "Content-Type: application/json" \
|
|
110
|
-
-d '{"text": "This is a sample text for analysis. It contains multiple sentences and words for testing the workflow capabilities."}'
|
|
111
|
-
```
|
|
112
|
-
|
|
113
|
-
## Integration with AI Models
|
|
114
|
-
|
|
115
|
-
### GPT Actions Setup:
|
|
116
|
-
1. Copy the OpenAPI schema from `/openapi.json`
|
|
117
|
-
2. Create a new GPT Action in ChatGPT
|
|
118
|
-
3. Paste the schema and set the base URL
|
|
119
|
-
|
|
120
|
-
### Claude MCP Setup:
|
|
121
|
-
1. Add the MCP server configuration:
|
|
122
|
-
```json
|
|
123
|
-
{
|
|
124
|
-
"mcp": {
|
|
125
|
-
"servers": {
|
|
126
|
-
"kalibr": {
|
|
127
|
-
"command": "curl",
|
|
128
|
-
"args": ["http://localhost:8000/mcp.json"]
|
|
129
|
-
}
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
```
|
|
134
|
-
|
|
135
|
-
### Gemini Extensions:
|
|
136
|
-
1. Use the schema from `/schemas/gemini`
|
|
137
|
-
2. Configure according to Gemini's extension documentation
|
|
138
|
-
|
|
139
|
-
### Microsoft Copilot:
|
|
140
|
-
1. Use the schema from `/schemas/copilot`
|
|
141
|
-
2. Follow Microsoft's plugin development guidelines
|
|
142
|
-
|
|
143
|
-
## Advanced Features
|
|
144
|
-
|
|
145
|
-
### Authentication (Optional):
|
|
146
|
-
Uncomment the authentication line in enhanced example:
|
|
147
|
-
```python
|
|
148
|
-
app.enable_auth("your-secret-jwt-key-here")
|
|
149
|
-
```
|
|
150
|
-
|
|
151
|
-
### Custom Schema Generation:
|
|
152
|
-
The framework supports extensible schema generation for future AI models through the `CustomModelSchemaGenerator` class.
|
|
153
|
-
|
|
154
|
-
### Error Handling:
|
|
155
|
-
All endpoints include comprehensive error handling with meaningful error messages.
|
|
156
|
-
|
|
157
|
-
### Type Safety:
|
|
158
|
-
Full support for Python type hints with automatic schema generation.
|
|
159
|
-
|
|
160
|
-
## Development Notes
|
|
161
|
-
|
|
162
|
-
- The enhanced framework is backward compatible with original Kalibr apps
|
|
163
|
-
- Session data is stored in memory (use external storage for production)
|
|
164
|
-
- File uploads are handled in memory (implement persistent storage as needed)
|
|
165
|
-
- Streaming uses Server-Sent Events (SSE) format
|
|
166
|
-
- All examples include proper async/await handling where needed
|
|
167
|
-
|
|
168
|
-
## Next Steps
|
|
169
|
-
|
|
170
|
-
1. Try the examples with different AI models
|
|
171
|
-
2. Modify the examples to fit your specific use case
|
|
172
|
-
3. Explore the source code in `/app/backend/kalibr/` for advanced customization
|
|
173
|
-
4. Build your own enhanced Kalibr applications!
|
|
@@ -1,66 +0,0 @@
|
|
|
1
|
-
"""
|
|
2
|
-
Basic Kalibr SDK Example - Function-level API integration
|
|
3
|
-
This demonstrates the original function-level capabilities of Kalibr.
|
|
4
|
-
"""
|
|
5
|
-
|
|
6
|
-
from kalibr import Kalibr
|
|
7
|
-
|
|
8
|
-
# Create a basic Kalibr instance
|
|
9
|
-
sdk = Kalibr(title="Basic Kalibr Demo", base_url="http://localhost:8000")
|
|
10
|
-
|
|
11
|
-
@sdk.action("greet", "Greet someone with a personalized message")
|
|
12
|
-
def greet_user(name: str, greeting: str = "Hello"):
|
|
13
|
-
"""Simple greeting function"""
|
|
14
|
-
return {"message": f"{greeting}, {name}! Welcome to Kalibr SDK."}
|
|
15
|
-
|
|
16
|
-
@sdk.action("calculate", "Perform basic mathematical operations")
|
|
17
|
-
def calculate(operation: str, a: float, b: float):
|
|
18
|
-
"""Basic calculator functionality"""
|
|
19
|
-
operations = {
|
|
20
|
-
"add": a + b,
|
|
21
|
-
"subtract": a - b,
|
|
22
|
-
"multiply": a * b,
|
|
23
|
-
"divide": a / b if b != 0 else None
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
result = operations.get(operation)
|
|
27
|
-
if result is None:
|
|
28
|
-
return {"error": f"Invalid operation '{operation}' or division by zero"}
|
|
29
|
-
|
|
30
|
-
return {
|
|
31
|
-
"operation": operation,
|
|
32
|
-
"operands": [a, b],
|
|
33
|
-
"result": result
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
@sdk.action("validate_email", "Check if an email address is valid")
|
|
37
|
-
def validate_email(email: str):
|
|
38
|
-
"""Simple email validation"""
|
|
39
|
-
import re
|
|
40
|
-
|
|
41
|
-
pattern = r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$'
|
|
42
|
-
is_valid = bool(re.match(pattern, email))
|
|
43
|
-
|
|
44
|
-
return {
|
|
45
|
-
"email": email,
|
|
46
|
-
"is_valid": is_valid,
|
|
47
|
-
"message": "Valid email address" if is_valid else "Invalid email format"
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
@sdk.action("text_stats", "Get statistics about a text string")
|
|
51
|
-
def text_statistics(text: str):
|
|
52
|
-
"""Analyze text and return statistics"""
|
|
53
|
-
words = text.split()
|
|
54
|
-
sentences = text.split('.') + text.split('!') + text.split('?')
|
|
55
|
-
sentences = [s.strip() for s in sentences if s.strip()]
|
|
56
|
-
|
|
57
|
-
return {
|
|
58
|
-
"character_count": len(text),
|
|
59
|
-
"word_count": len(words),
|
|
60
|
-
"sentence_count": len(sentences),
|
|
61
|
-
"average_word_length": sum(len(word) for word in words) / len(words) if words else 0,
|
|
62
|
-
"longest_word": max(words, key=len) if words else None
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
# The SDK instance is automatically discovered by the Kalibr CLI
|
|
66
|
-
# To run this: kalibr serve basic_kalibr_example.py
|