ct-toolkit 0.3.20__tar.gz → 0.3.22__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.
- {ct_toolkit-0.3.20 → ct_toolkit-0.3.22}/PKG-INFO +10 -6
- {ct_toolkit-0.3.20 → ct_toolkit-0.3.22}/README.md +9 -5
- ct_toolkit-0.3.22/ct_toolkit/core/__init__.py +73 -0
- ct_toolkit-0.3.22/ct_toolkit/core/async_wrapper.py +226 -0
- ct_toolkit-0.3.22/ct_toolkit/core/circuit_breaker.py +347 -0
- {ct_toolkit-0.3.20 → ct_toolkit-0.3.22}/ct_toolkit/core/kernel.py +38 -6
- ct_toolkit-0.3.22/ct_toolkit/divergence/__init__.py +56 -0
- {ct_toolkit-0.3.20 → ct_toolkit-0.3.22}/ct_toolkit/divergence/l2_judge.py +73 -2
- {ct_toolkit-0.3.20 → ct_toolkit-0.3.22}/ct_toolkit/divergence/l3_icm.py +87 -25
- ct_toolkit-0.3.22/ct_toolkit/endorsement/__init__.py +22 -0
- ct_toolkit-0.3.22/ct_toolkit/identity/__init__.py +15 -0
- ct_toolkit-0.3.22/ct_toolkit/middleware/__init__.py +21 -0
- ct_toolkit-0.3.22/ct_toolkit/provenance/__init__.py +15 -0
- {ct_toolkit-0.3.20 → ct_toolkit-0.3.22}/ct_toolkit/provenance/log.py +47 -4
- ct_toolkit-0.3.22/ct_toolkit/utils/metrics.py +343 -0
- ct_toolkit-0.3.22/ct_toolkit/utils/sensitive_masker.py +246 -0
- {ct_toolkit-0.3.20 → ct_toolkit-0.3.22}/ct_toolkit.egg-info/PKG-INFO +10 -6
- {ct_toolkit-0.3.20 → ct_toolkit-0.3.22}/ct_toolkit.egg-info/SOURCES.txt +4 -0
- {ct_toolkit-0.3.20 → ct_toolkit-0.3.22}/pyproject.toml +1 -1
- ct_toolkit-0.3.20/ct_toolkit/endorsement/probes/__init__.py +0 -0
- ct_toolkit-0.3.20/ct_toolkit/identity/__init__.py +0 -0
- ct_toolkit-0.3.20/ct_toolkit/middleware/__init__.py +0 -5
- ct_toolkit-0.3.20/ct_toolkit/provenance/__init__.py +0 -0
- ct_toolkit-0.3.20/ct_toolkit/provenance/vault/__init__.py +0 -0
- ct_toolkit-0.3.20/ct_toolkit/utils/__init__.py +0 -0
- {ct_toolkit-0.3.20 → ct_toolkit-0.3.22}/LICENSE +0 -0
- {ct_toolkit-0.3.20 → ct_toolkit-0.3.22}/ct_toolkit/__init__.py +0 -0
- {ct_toolkit-0.3.20 → ct_toolkit-0.3.22}/ct_toolkit/__main__.py +0 -0
- {ct_toolkit-0.3.20 → ct_toolkit-0.3.22}/ct_toolkit/cli.py +0 -0
- {ct_toolkit-0.3.20 → ct_toolkit-0.3.22}/ct_toolkit/core/compatibility.py +0 -0
- {ct_toolkit-0.3.20 → ct_toolkit-0.3.22}/ct_toolkit/core/compression_guard.py +0 -0
- {ct_toolkit-0.3.20 → ct_toolkit-0.3.22}/ct_toolkit/core/exceptions.py +0 -0
- {ct_toolkit-0.3.20 → ct_toolkit-0.3.22}/ct_toolkit/core/integrity.py +0 -0
- {ct_toolkit-0.3.20 → ct_toolkit-0.3.22}/ct_toolkit/core/wrapper.py +0 -0
- {ct_toolkit-0.3.20 → ct_toolkit-0.3.22}/ct_toolkit/divergence/analysis.py +0 -0
- {ct_toolkit-0.3.20 → ct_toolkit-0.3.22}/ct_toolkit/divergence/engine.py +0 -0
- {ct_toolkit-0.3.20 → ct_toolkit-0.3.22}/ct_toolkit/divergence/loss.py +0 -0
- {ct_toolkit-0.3.20 → ct_toolkit-0.3.22}/ct_toolkit/divergence/scheduler.py +0 -0
- {ct_toolkit-0.3.20/ct_toolkit/core → ct_toolkit-0.3.22/ct_toolkit/endorsement/probes}/__init__.py +0 -0
- {ct_toolkit-0.3.20 → ct_toolkit-0.3.22}/ct_toolkit/endorsement/reflective.py +0 -0
- {ct_toolkit-0.3.20 → ct_toolkit-0.3.22}/ct_toolkit/identity/embedding.py +0 -0
- {ct_toolkit-0.3.20 → ct_toolkit-0.3.22}/ct_toolkit/identity/templates/__init__.py +0 -0
- {ct_toolkit-0.3.20 → ct_toolkit-0.3.22}/ct_toolkit/identity/templates/defense.yaml +0 -0
- {ct_toolkit-0.3.20 → ct_toolkit-0.3.22}/ct_toolkit/identity/templates/finance.yaml +0 -0
- {ct_toolkit-0.3.20 → ct_toolkit-0.3.22}/ct_toolkit/identity/templates/general.yaml +0 -0
- {ct_toolkit-0.3.20 → ct_toolkit-0.3.22}/ct_toolkit/identity/templates/medical.yaml +0 -0
- {ct_toolkit-0.3.20 → ct_toolkit-0.3.22}/ct_toolkit/kernels/__init__.py +0 -0
- {ct_toolkit-0.3.20 → ct_toolkit-0.3.22}/ct_toolkit/kernels/default.yaml +0 -0
- {ct_toolkit-0.3.20 → ct_toolkit-0.3.22}/ct_toolkit/kernels/defense.yaml +0 -0
- {ct_toolkit-0.3.20 → ct_toolkit-0.3.22}/ct_toolkit/middleware/autogen.py +0 -0
- {ct_toolkit-0.3.20 → ct_toolkit-0.3.22}/ct_toolkit/middleware/crewai.py +0 -0
- {ct_toolkit-0.3.20 → ct_toolkit-0.3.22}/ct_toolkit/middleware/deepagents.py +0 -0
- {ct_toolkit-0.3.20 → ct_toolkit-0.3.22}/ct_toolkit/middleware/langchain.py +0 -0
- {ct_toolkit-0.3.20 → ct_toolkit-0.3.22}/ct_toolkit/middleware/litellm.py +0 -0
- {ct_toolkit-0.3.20/ct_toolkit/divergence → ct_toolkit-0.3.22/ct_toolkit/provenance/vault}/__init__.py +0 -0
- {ct_toolkit-0.3.20 → ct_toolkit-0.3.22}/ct_toolkit/server.py +0 -0
- {ct_toolkit-0.3.20/ct_toolkit/endorsement → ct_toolkit-0.3.22/ct_toolkit/utils}/__init__.py +0 -0
- {ct_toolkit-0.3.20 → ct_toolkit-0.3.22}/ct_toolkit/utils/logger.py +0 -0
- {ct_toolkit-0.3.20 → ct_toolkit-0.3.22}/ct_toolkit.egg-info/dependency_links.txt +0 -0
- {ct_toolkit-0.3.20 → ct_toolkit-0.3.22}/ct_toolkit.egg-info/entry_points.txt +0 -0
- {ct_toolkit-0.3.20 → ct_toolkit-0.3.22}/ct_toolkit.egg-info/requires.txt +0 -0
- {ct_toolkit-0.3.20 → ct_toolkit-0.3.22}/ct_toolkit.egg-info/top_level.txt +0 -0
- {ct_toolkit-0.3.20 → ct_toolkit-0.3.22}/setup.cfg +0 -0
- {ct_toolkit-0.3.20 → ct_toolkit-0.3.22}/tests/test_analysis.py +0 -0
- {ct_toolkit-0.3.20 → ct_toolkit-0.3.22}/tests/test_cli.py +0 -0
- {ct_toolkit-0.3.20 → ct_toolkit-0.3.22}/tests/test_cli_extended.py +0 -0
- {ct_toolkit-0.3.20 → ct_toolkit-0.3.22}/tests/test_deep_agents_integration.py +0 -0
- {ct_toolkit-0.3.20 → ct_toolkit-0.3.22}/tests/test_loss.py +0 -0
- {ct_toolkit-0.3.20 → ct_toolkit-0.3.22}/tests/test_summarization_drift.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: ct-toolkit
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.22
|
|
4
4
|
Summary: Computational Theseus Toolkit — Identity Continuity Guardrails for Agentic Systems
|
|
5
5
|
Author: Hakan Damar
|
|
6
6
|
License: Apache-2.0
|
|
@@ -50,6 +50,7 @@ Dynamic: license-file
|
|
|
50
50
|
[](https://pypi.org/project/ct-toolkit/)
|
|
51
51
|
[](https://hakandamar.github.io/ct-toolkit/)
|
|
52
52
|
[](https://pepy.tech/projects/ct-toolkit)
|
|
53
|
+
[](https://codecov.io/gh/hakandamar/ct-toolkit)
|
|
53
54
|
|
|
54
55
|
CT Toolkit is an open-source security layer designed to preserve the **identity continuity** of AI agents over time. It implements the **Nested Agentic Architecture (NAA)** framework to prevent **Sequential Self-Compression (SSC)** in multi-agent hierarchies.
|
|
55
56
|
|
|
@@ -62,6 +63,7 @@ For full API reference, architecture details, examples, and integration guides,
|
|
|
62
63
|
|
|
63
64
|
- [**Live Examples & Case Studies**](https://hakandamar.github.io/ct-toolkit/examples/): Real-world scenarios like Financial Auditor Integrity.
|
|
64
65
|
- [**FastAPI Integration Test Project**](https://github.com/hakandamar/ct-toolkit-fastapi): Reference FastAPI app for validating CT Toolkit end-to-end across L1/L2/L3 guardrails and provenance logs with local model infrastructure.
|
|
66
|
+
- [**Deep Agents Integration Test Project**](https://github.com/hakandamar/ct-toolkit-deep-agents): Reference Deep Agents app for validating CT Toolkit end-to-end with hierarchical agent workflows, L1/L2/L3 guardrails, and provenance logs.
|
|
65
67
|
|
|
66
68
|
---
|
|
67
69
|
|
|
@@ -117,16 +119,18 @@ ct-toolkit list-templates
|
|
|
117
119
|
|
|
118
120
|
If you want a runnable application example instead of a CLI-only flow, see [**ct-toolkit-fastapi**](https://github.com/hakandamar/ct-toolkit-fastapi), a small FastAPI validation project that developers can use to test CT Toolkit locally with automated endpoints and pytest coverage.
|
|
119
121
|
|
|
122
|
+
For Deep Agents workflows, see [**ct-toolkit-deep-agents**](https://github.com/hakandamar/ct-toolkit-deep-agents), a reference integration project for validating CT Toolkit in multi-agent orchestration scenarios.
|
|
123
|
+
|
|
120
124
|
---
|
|
121
125
|
|
|
122
126
|
## 🚦 Project Health & Status
|
|
123
127
|
|
|
124
|
-
| Metric | Status
|
|
125
|
-
| :--------------- |
|
|
126
|
-
| **Tests** | ✅
|
|
128
|
+
| Metric | Status |
|
|
129
|
+
| :--------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
130
|
+
| **Tests** | ✅ 397 passed, 3 skipped (100% success rate, 90% coverage) |
|
|
127
131
|
| **Downloads** | [](https://pepy.tech/projects/ct-toolkit) |
|
|
128
|
-
| **Last Phase** | ✅ v0.3.
|
|
129
|
-
| **Current Goal** | 🔶 Phase 7: Multi-Agent Synchronization (Integration)
|
|
132
|
+
| **Last Phase** | ✅ v0.3.22: CI/CD pipeline fix — Proper dependency installation via `uv sync --all-extras --dev` in GitHub Actions |
|
|
133
|
+
| **Current Goal** | 🔶 Phase 7: Multi-Agent Synchronization (Integration) |
|
|
130
134
|
|
|
131
135
|
### Framework & Model Support
|
|
132
136
|
|
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
[](https://pypi.org/project/ct-toolkit/)
|
|
8
8
|
[](https://hakandamar.github.io/ct-toolkit/)
|
|
9
9
|
[](https://pepy.tech/projects/ct-toolkit)
|
|
10
|
+
[](https://codecov.io/gh/hakandamar/ct-toolkit)
|
|
10
11
|
|
|
11
12
|
CT Toolkit is an open-source security layer designed to preserve the **identity continuity** of AI agents over time. It implements the **Nested Agentic Architecture (NAA)** framework to prevent **Sequential Self-Compression (SSC)** in multi-agent hierarchies.
|
|
12
13
|
|
|
@@ -19,6 +20,7 @@ For full API reference, architecture details, examples, and integration guides,
|
|
|
19
20
|
|
|
20
21
|
- [**Live Examples & Case Studies**](https://hakandamar.github.io/ct-toolkit/examples/): Real-world scenarios like Financial Auditor Integrity.
|
|
21
22
|
- [**FastAPI Integration Test Project**](https://github.com/hakandamar/ct-toolkit-fastapi): Reference FastAPI app for validating CT Toolkit end-to-end across L1/L2/L3 guardrails and provenance logs with local model infrastructure.
|
|
23
|
+
- [**Deep Agents Integration Test Project**](https://github.com/hakandamar/ct-toolkit-deep-agents): Reference Deep Agents app for validating CT Toolkit end-to-end with hierarchical agent workflows, L1/L2/L3 guardrails, and provenance logs.
|
|
22
24
|
|
|
23
25
|
---
|
|
24
26
|
|
|
@@ -74,16 +76,18 @@ ct-toolkit list-templates
|
|
|
74
76
|
|
|
75
77
|
If you want a runnable application example instead of a CLI-only flow, see [**ct-toolkit-fastapi**](https://github.com/hakandamar/ct-toolkit-fastapi), a small FastAPI validation project that developers can use to test CT Toolkit locally with automated endpoints and pytest coverage.
|
|
76
78
|
|
|
79
|
+
For Deep Agents workflows, see [**ct-toolkit-deep-agents**](https://github.com/hakandamar/ct-toolkit-deep-agents), a reference integration project for validating CT Toolkit in multi-agent orchestration scenarios.
|
|
80
|
+
|
|
77
81
|
---
|
|
78
82
|
|
|
79
83
|
## 🚦 Project Health & Status
|
|
80
84
|
|
|
81
|
-
| Metric | Status
|
|
82
|
-
| :--------------- |
|
|
83
|
-
| **Tests** | ✅
|
|
85
|
+
| Metric | Status |
|
|
86
|
+
| :--------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
87
|
+
| **Tests** | ✅ 397 passed, 3 skipped (100% success rate, 90% coverage) |
|
|
84
88
|
| **Downloads** | [](https://pepy.tech/projects/ct-toolkit) |
|
|
85
|
-
| **Last Phase** | ✅ v0.3.
|
|
86
|
-
| **Current Goal** | 🔶 Phase 7: Multi-Agent Synchronization (Integration)
|
|
89
|
+
| **Last Phase** | ✅ v0.3.22: CI/CD pipeline fix — Proper dependency installation via `uv sync --all-extras --dev` in GitHub Actions |
|
|
90
|
+
| **Current Goal** | 🔶 Phase 7: Multi-Agent Synchronization (Integration) |
|
|
87
91
|
|
|
88
92
|
### Framework & Model Support
|
|
89
93
|
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
"""
|
|
2
|
+
ct_toolkit.core
|
|
3
|
+
===============
|
|
4
|
+
Core components of the Computational Theseus Toolkit.
|
|
5
|
+
|
|
6
|
+
This module provides:
|
|
7
|
+
- ConstitutionalKernel: Ethical and behavioral core of the system
|
|
8
|
+
- TheseusWrapper: LLM wrapper with constitutional guard
|
|
9
|
+
- CompatibilityLayer: Template/kernel compatibility checking
|
|
10
|
+
- ContextCompressionGuard: Context window protection
|
|
11
|
+
- IntegrityMonitor: File integrity monitoring
|
|
12
|
+
- Core exceptions
|
|
13
|
+
"""
|
|
14
|
+
|
|
15
|
+
from ct_toolkit.core.wrapper import TheseusWrapper, CTResponse, WrapperConfig
|
|
16
|
+
from ct_toolkit.core.kernel import ConstitutionalKernel, KernelProfile, AxiomaticAnchor, PlasticCommitment
|
|
17
|
+
from ct_toolkit.core.compatibility import CompatibilityLayer, CompatibilityLevel, CompatibilityResult
|
|
18
|
+
from ct_toolkit.core.exceptions import (
|
|
19
|
+
CTToolkitError,
|
|
20
|
+
AxiomaticViolationError,
|
|
21
|
+
PlasticConflictError,
|
|
22
|
+
IncompatibleProfileError,
|
|
23
|
+
)
|
|
24
|
+
from ct_toolkit.core.compression_guard import ContextCompressionGuard
|
|
25
|
+
from ct_toolkit.core.integrity import IntegrityMonitor
|
|
26
|
+
from ct_toolkit.core.circuit_breaker import (
|
|
27
|
+
CircuitBreaker,
|
|
28
|
+
CircuitBreakerError,
|
|
29
|
+
CircuitBreakerStats,
|
|
30
|
+
CircuitBreakerRegistry,
|
|
31
|
+
CircuitState,
|
|
32
|
+
)
|
|
33
|
+
|
|
34
|
+
__all__ = [
|
|
35
|
+
# Wrapper
|
|
36
|
+
"TheseusWrapper",
|
|
37
|
+
"CTResponse",
|
|
38
|
+
"WrapperConfig",
|
|
39
|
+
# Kernel
|
|
40
|
+
"ConstitutionalKernel",
|
|
41
|
+
"KernelProfile",
|
|
42
|
+
"AxiomaticAnchor",
|
|
43
|
+
"PlasticCommitment",
|
|
44
|
+
# Compatibility
|
|
45
|
+
"CompatibilityLayer",
|
|
46
|
+
"CompatibilityLevel",
|
|
47
|
+
"CompatibilityResult",
|
|
48
|
+
# Compression
|
|
49
|
+
"ContextCompressionGuard",
|
|
50
|
+
# Integrity
|
|
51
|
+
"IntegrityMonitor",
|
|
52
|
+
# Circuit Breaker
|
|
53
|
+
"CircuitBreaker",
|
|
54
|
+
"CircuitBreakerError",
|
|
55
|
+
"CircuitBreakerStats",
|
|
56
|
+
"CircuitBreakerRegistry",
|
|
57
|
+
"CircuitState",
|
|
58
|
+
# Exceptions
|
|
59
|
+
"CTToolkitError",
|
|
60
|
+
"MissingClientError",
|
|
61
|
+
"KernelError",
|
|
62
|
+
"AxiomaticViolationError",
|
|
63
|
+
"PlasticConflictError",
|
|
64
|
+
"CompatibilityError",
|
|
65
|
+
"IncompatibleProfileError",
|
|
66
|
+
"DivergenceError",
|
|
67
|
+
"CriticalDivergenceError",
|
|
68
|
+
"CriticalSandboxDivergenceError",
|
|
69
|
+
"ProvenanceError",
|
|
70
|
+
"ChainIntegrityError",
|
|
71
|
+
"VaultError",
|
|
72
|
+
"ConfigurationTamperingError",
|
|
73
|
+
]
|
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
"""
|
|
2
|
+
ct_toolkit.core.async_wrapper
|
|
3
|
+
==============================
|
|
4
|
+
Async support for TheseusWrapper LLM calls.
|
|
5
|
+
|
|
6
|
+
Provides:
|
|
7
|
+
- AsyncTheseusWrapper: Async-compatible wrapper around TheseusWrapper
|
|
8
|
+
- Async compatible circuit breaker integration
|
|
9
|
+
|
|
10
|
+
Usage:
|
|
11
|
+
async with AsyncTheseusWrapper(client) as wrapper:
|
|
12
|
+
response = await wrapper.chat("Hello!")
|
|
13
|
+
"""
|
|
14
|
+
from __future__ import annotations
|
|
15
|
+
|
|
16
|
+
import asyncio
|
|
17
|
+
import time
|
|
18
|
+
from typing import Any, Optional
|
|
19
|
+
from pathlib import Path
|
|
20
|
+
|
|
21
|
+
from ct_toolkit.core.wrapper import TheseusWrapper, CTResponse, WrapperConfig
|
|
22
|
+
from ct_toolkit.core.circuit_breaker import CircuitBreaker, CircuitBreakerError, CircuitBreakerRegistry
|
|
23
|
+
from ct_toolkit.utils.metrics import get_metrics_collector, MetricsCollector
|
|
24
|
+
from ct_toolkit.utils.logger import get_logger
|
|
25
|
+
|
|
26
|
+
logger = get_logger(__name__)
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
class AsyncTheseusWrapper:
|
|
30
|
+
"""
|
|
31
|
+
Async-compatible TheseusWrapper.
|
|
32
|
+
|
|
33
|
+
Provides async-compatible LLM calls with circuit breaker and metrics integration.
|
|
34
|
+
|
|
35
|
+
Usage:
|
|
36
|
+
wrapper = AsyncTheseusWrapper(provider="openai")
|
|
37
|
+
response = await wrapper.chat("Hello!")
|
|
38
|
+
|
|
39
|
+
# With circuit breaker
|
|
40
|
+
wrapper = AsyncTheseusWrapper(provider="openai", enable_circuit_breaker=True)
|
|
41
|
+
"""
|
|
42
|
+
|
|
43
|
+
def __init__(
|
|
44
|
+
self,
|
|
45
|
+
client: Any = None,
|
|
46
|
+
config: Optional[WrapperConfig] = None,
|
|
47
|
+
*,
|
|
48
|
+
provider: Optional[str] = None,
|
|
49
|
+
enable_circuit_breaker: bool = True,
|
|
50
|
+
circuit_breaker_threshold: int = 5,
|
|
51
|
+
circuit_breaker_recovery: float = 30.0,
|
|
52
|
+
metrics_enabled: bool = True,
|
|
53
|
+
) -> None:
|
|
54
|
+
self._sync_wrapper = TheseusWrapper(
|
|
55
|
+
client=client,
|
|
56
|
+
config=config,
|
|
57
|
+
provider=provider,
|
|
58
|
+
)
|
|
59
|
+
self._metrics_enabled = metrics_enabled
|
|
60
|
+
self._metrics = get_metrics_collector() if metrics_enabled else None
|
|
61
|
+
|
|
62
|
+
# Circuit breaker
|
|
63
|
+
self._circuit_breaker: Optional[CircuitBreaker] = None
|
|
64
|
+
if enable_circuit_breaker:
|
|
65
|
+
provider_name = self._sync_wrapper._provider or "unknown"
|
|
66
|
+
self._circuit_breaker = CircuitBreakerRegistry.global_instance().get_or_create(
|
|
67
|
+
name=f"llm-{provider_name}",
|
|
68
|
+
failure_threshold=circuit_breaker_threshold,
|
|
69
|
+
recovery_timeout=circuit_breaker_recovery,
|
|
70
|
+
)
|
|
71
|
+
logger.info(f"AsyncTheseusWrapper: Circuit breaker enabled for '{provider_name}'")
|
|
72
|
+
|
|
73
|
+
@property
|
|
74
|
+
def sync_wrapper(self) -> TheseusWrapper:
|
|
75
|
+
"""Get the underlying sync wrapper."""
|
|
76
|
+
return self._sync_wrapper
|
|
77
|
+
|
|
78
|
+
async def chat(
|
|
79
|
+
self,
|
|
80
|
+
message: str,
|
|
81
|
+
*,
|
|
82
|
+
model: Optional[str] = None,
|
|
83
|
+
system: Optional[str] = None,
|
|
84
|
+
history: Optional[list[dict[str, str]]] = None,
|
|
85
|
+
**kwargs: Any,
|
|
86
|
+
) -> CTResponse:
|
|
87
|
+
"""
|
|
88
|
+
Send a message asynchronously and get response with identity protection.
|
|
89
|
+
|
|
90
|
+
Uses run_in_executor to make sync LLM calls non-blocking.
|
|
91
|
+
"""
|
|
92
|
+
if self._metrics:
|
|
93
|
+
self._metrics.increment("llm.requests.async.total", tags={
|
|
94
|
+
"provider": self._sync_wrapper._provider or "unknown",
|
|
95
|
+
})
|
|
96
|
+
|
|
97
|
+
start_time = time.monotonic()
|
|
98
|
+
|
|
99
|
+
try:
|
|
100
|
+
# Run sync wrapper in executor to not block event loop
|
|
101
|
+
loop = asyncio.get_event_loop()
|
|
102
|
+
response = await loop.run_in_executor(
|
|
103
|
+
None,
|
|
104
|
+
lambda: self._sync_wrapper.chat(
|
|
105
|
+
message,
|
|
106
|
+
model=model,
|
|
107
|
+
system=system,
|
|
108
|
+
history=history,
|
|
109
|
+
**kwargs,
|
|
110
|
+
)
|
|
111
|
+
)
|
|
112
|
+
|
|
113
|
+
# Record metrics
|
|
114
|
+
latency = time.monotonic() - start_time
|
|
115
|
+
if self._metrics:
|
|
116
|
+
self._metrics.record("llm.latency.async.seconds", latency, tags={
|
|
117
|
+
"provider": self._sync_wrapper._provider or "unknown",
|
|
118
|
+
"model": response.model,
|
|
119
|
+
})
|
|
120
|
+
self._metrics.increment("llm.requests.async.success", tags={
|
|
121
|
+
"provider": self._sync_wrapper._provider or "unknown",
|
|
122
|
+
"success": "true",
|
|
123
|
+
})
|
|
124
|
+
|
|
125
|
+
return response
|
|
126
|
+
|
|
127
|
+
except CircuitBreakerError as e:
|
|
128
|
+
# Circuit breaker is already tracking this
|
|
129
|
+
if self._metrics:
|
|
130
|
+
self._metrics.increment("llm.requests.async.circuit_breaker", tags={
|
|
131
|
+
"provider": self._sync_wrapper._provider or "unknown",
|
|
132
|
+
"state": e.state.value,
|
|
133
|
+
})
|
|
134
|
+
logger.warning(f"Circuit breaker open for LLM call: {e}")
|
|
135
|
+
raise
|
|
136
|
+
|
|
137
|
+
except Exception as e:
|
|
138
|
+
# Record failure
|
|
139
|
+
latency = time.monotonic() - start_time
|
|
140
|
+
if self._metrics:
|
|
141
|
+
self._metrics.record("llm.latency.async.seconds", latency, tags={
|
|
142
|
+
"provider": self._sync_wrapper._provider or "unknown",
|
|
143
|
+
})
|
|
144
|
+
self._metrics.increment("llm.requests.async.failure", tags={
|
|
145
|
+
"provider": self._sync_wrapper._provider or "unknown",
|
|
146
|
+
"success": "false",
|
|
147
|
+
"error": type(e).__name__,
|
|
148
|
+
})
|
|
149
|
+
|
|
150
|
+
# Record circuit breaker failure if applicable
|
|
151
|
+
if self._circuit_breaker:
|
|
152
|
+
try:
|
|
153
|
+
self._circuit_breaker.record_failure()
|
|
154
|
+
except Exception:
|
|
155
|
+
pass
|
|
156
|
+
|
|
157
|
+
logger.error(f"Async LLM call failed: {type(e).__name__}: {e}")
|
|
158
|
+
raise
|
|
159
|
+
|
|
160
|
+
async def health_check(self) -> dict[str, Any]:
|
|
161
|
+
"""
|
|
162
|
+
Check health of the LLM connection.
|
|
163
|
+
|
|
164
|
+
Returns status of circuit breaker and basic connectivity.
|
|
165
|
+
"""
|
|
166
|
+
result: dict[str, Any] = {
|
|
167
|
+
"provider": self._sync_wrapper._provider or "unknown",
|
|
168
|
+
"status": "healthy",
|
|
169
|
+
"circuit_breaker": None,
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
if self._circuit_breaker:
|
|
173
|
+
cb_state = self._circuit_breaker.state
|
|
174
|
+
cb_stats = self._circuit_breaker.get_stats().to_dict()
|
|
175
|
+
result["circuit_breaker"] = {
|
|
176
|
+
"state": cb_state.value,
|
|
177
|
+
"stats": cb_stats,
|
|
178
|
+
"time_until_recovery": self._circuit_breaker.time_until_recovery(),
|
|
179
|
+
}
|
|
180
|
+
if cb_state.value == "open":
|
|
181
|
+
result["status"] = "degraded"
|
|
182
|
+
|
|
183
|
+
return result
|
|
184
|
+
|
|
185
|
+
def get_metrics(self) -> Optional[dict[str, Any]]:
|
|
186
|
+
"""Get current metrics."""
|
|
187
|
+
if not self._metrics:
|
|
188
|
+
return None
|
|
189
|
+
return self._metrics.get_all()
|
|
190
|
+
|
|
191
|
+
def get_circuit_breaker_stats(self) -> Optional[dict[str, Any]]:
|
|
192
|
+
"""Get circuit breaker statistics."""
|
|
193
|
+
if not self._circuit_breaker:
|
|
194
|
+
return None
|
|
195
|
+
return self._circuit_breaker.get_stats().to_dict()
|
|
196
|
+
|
|
197
|
+
def reset_circuit_breaker(self) -> None:
|
|
198
|
+
"""Manually reset the circuit breaker."""
|
|
199
|
+
if self._circuit_breaker:
|
|
200
|
+
self._circuit_breaker.reset()
|
|
201
|
+
logger.info("Circuit breaker manually reset")
|
|
202
|
+
|
|
203
|
+
|
|
204
|
+
def create_async_wrapper(
|
|
205
|
+
provider: str = "openai",
|
|
206
|
+
model: Optional[str] = None,
|
|
207
|
+
enable_circuit_breaker: bool = True,
|
|
208
|
+
metrics_enabled: bool = True,
|
|
209
|
+
) -> AsyncTheseusWrapper:
|
|
210
|
+
"""
|
|
211
|
+
Factory function to create an AsyncTheseusWrapper.
|
|
212
|
+
|
|
213
|
+
Args:
|
|
214
|
+
provider: LLM provider name.
|
|
215
|
+
model: Optional model override.
|
|
216
|
+
enable_circuit_breaker: Enable circuit breaker protection.
|
|
217
|
+
metrics_enabled: Enable metrics collection.
|
|
218
|
+
|
|
219
|
+
Returns:
|
|
220
|
+
Configured AsyncTheseusWrapper instance.
|
|
221
|
+
"""
|
|
222
|
+
return AsyncTheseusWrapper(
|
|
223
|
+
provider=provider,
|
|
224
|
+
enable_circuit_breaker=enable_circuit_breaker,
|
|
225
|
+
metrics_enabled=metrics_enabled,
|
|
226
|
+
)
|