ct-toolkit 0.3.5__tar.gz → 0.3.6__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.5 → ct_toolkit-0.3.6}/PKG-INFO +9 -5
- {ct_toolkit-0.3.5 → ct_toolkit-0.3.6}/README.md +8 -4
- {ct_toolkit-0.3.5 → ct_toolkit-0.3.6}/ct_toolkit/__init__.py +1 -1
- ct_toolkit-0.3.5/ct_toolkit/middleware/deepagents.py → ct_toolkit-0.3.6/ct_toolkit/core/compression_guard.py +23 -60
- {ct_toolkit-0.3.5 → ct_toolkit-0.3.6}/ct_toolkit/core/wrapper.py +24 -0
- {ct_toolkit-0.3.5 → ct_toolkit-0.3.6}/ct_toolkit/middleware/crewai.py +4 -0
- ct_toolkit-0.3.6/ct_toolkit/middleware/deepagents.py +67 -0
- {ct_toolkit-0.3.5 → ct_toolkit-0.3.6}/ct_toolkit/middleware/langchain.py +5 -0
- {ct_toolkit-0.3.5 → ct_toolkit-0.3.6}/ct_toolkit.egg-info/PKG-INFO +9 -5
- {ct_toolkit-0.3.5 → ct_toolkit-0.3.6}/ct_toolkit.egg-info/SOURCES.txt +2 -0
- {ct_toolkit-0.3.5 → ct_toolkit-0.3.6}/pyproject.toml +1 -1
- ct_toolkit-0.3.6/tests/test_cli_extended.py +53 -0
- {ct_toolkit-0.3.5 → ct_toolkit-0.3.6}/LICENSE +0 -0
- {ct_toolkit-0.3.5 → ct_toolkit-0.3.6}/ct_toolkit/__main__.py +0 -0
- {ct_toolkit-0.3.5 → ct_toolkit-0.3.6}/ct_toolkit/cli.py +0 -0
- {ct_toolkit-0.3.5 → ct_toolkit-0.3.6}/ct_toolkit/core/__init__.py +0 -0
- {ct_toolkit-0.3.5 → ct_toolkit-0.3.6}/ct_toolkit/core/compatibility.py +0 -0
- {ct_toolkit-0.3.5 → ct_toolkit-0.3.6}/ct_toolkit/core/exceptions.py +0 -0
- {ct_toolkit-0.3.5 → ct_toolkit-0.3.6}/ct_toolkit/core/integrity.py +0 -0
- {ct_toolkit-0.3.5 → ct_toolkit-0.3.6}/ct_toolkit/core/kernel.py +0 -0
- {ct_toolkit-0.3.5 → ct_toolkit-0.3.6}/ct_toolkit/divergence/__init__.py +0 -0
- {ct_toolkit-0.3.5 → ct_toolkit-0.3.6}/ct_toolkit/divergence/analysis.py +0 -0
- {ct_toolkit-0.3.5 → ct_toolkit-0.3.6}/ct_toolkit/divergence/engine.py +0 -0
- {ct_toolkit-0.3.5 → ct_toolkit-0.3.6}/ct_toolkit/divergence/l2_judge.py +0 -0
- {ct_toolkit-0.3.5 → ct_toolkit-0.3.6}/ct_toolkit/divergence/l3_icm.py +0 -0
- {ct_toolkit-0.3.5 → ct_toolkit-0.3.6}/ct_toolkit/divergence/loss.py +0 -0
- {ct_toolkit-0.3.5 → ct_toolkit-0.3.6}/ct_toolkit/divergence/scheduler.py +0 -0
- {ct_toolkit-0.3.5 → ct_toolkit-0.3.6}/ct_toolkit/endorsement/__init__.py +0 -0
- {ct_toolkit-0.3.5 → ct_toolkit-0.3.6}/ct_toolkit/endorsement/probes/__init__.py +0 -0
- {ct_toolkit-0.3.5 → ct_toolkit-0.3.6}/ct_toolkit/endorsement/reflective.py +0 -0
- {ct_toolkit-0.3.5 → ct_toolkit-0.3.6}/ct_toolkit/identity/__init__.py +0 -0
- {ct_toolkit-0.3.5 → ct_toolkit-0.3.6}/ct_toolkit/identity/embedding.py +0 -0
- {ct_toolkit-0.3.5 → ct_toolkit-0.3.6}/ct_toolkit/identity/templates/__init__.py +0 -0
- {ct_toolkit-0.3.5 → ct_toolkit-0.3.6}/ct_toolkit/identity/templates/defense.yaml +0 -0
- {ct_toolkit-0.3.5 → ct_toolkit-0.3.6}/ct_toolkit/identity/templates/finance.yaml +0 -0
- {ct_toolkit-0.3.5 → ct_toolkit-0.3.6}/ct_toolkit/identity/templates/general.yaml +0 -0
- {ct_toolkit-0.3.5 → ct_toolkit-0.3.6}/ct_toolkit/identity/templates/medical.yaml +0 -0
- {ct_toolkit-0.3.5 → ct_toolkit-0.3.6}/ct_toolkit/kernels/__init__.py +0 -0
- {ct_toolkit-0.3.5 → ct_toolkit-0.3.6}/ct_toolkit/kernels/default.yaml +0 -0
- {ct_toolkit-0.3.5 → ct_toolkit-0.3.6}/ct_toolkit/kernels/defense.yaml +0 -0
- {ct_toolkit-0.3.5 → ct_toolkit-0.3.6}/ct_toolkit/middleware/__init__.py +0 -0
- {ct_toolkit-0.3.5 → ct_toolkit-0.3.6}/ct_toolkit/middleware/autogen.py +0 -0
- {ct_toolkit-0.3.5 → ct_toolkit-0.3.6}/ct_toolkit/provenance/__init__.py +0 -0
- {ct_toolkit-0.3.5 → ct_toolkit-0.3.6}/ct_toolkit/provenance/log.py +0 -0
- {ct_toolkit-0.3.5 → ct_toolkit-0.3.6}/ct_toolkit/provenance/vault/__init__.py +0 -0
- {ct_toolkit-0.3.5 → ct_toolkit-0.3.6}/ct_toolkit/utils/__init__.py +0 -0
- {ct_toolkit-0.3.5 → ct_toolkit-0.3.6}/ct_toolkit/utils/logger.py +0 -0
- {ct_toolkit-0.3.5 → ct_toolkit-0.3.6}/ct_toolkit.egg-info/dependency_links.txt +0 -0
- {ct_toolkit-0.3.5 → ct_toolkit-0.3.6}/ct_toolkit.egg-info/entry_points.txt +0 -0
- {ct_toolkit-0.3.5 → ct_toolkit-0.3.6}/ct_toolkit.egg-info/requires.txt +0 -0
- {ct_toolkit-0.3.5 → ct_toolkit-0.3.6}/ct_toolkit.egg-info/top_level.txt +0 -0
- {ct_toolkit-0.3.5 → ct_toolkit-0.3.6}/setup.cfg +0 -0
- {ct_toolkit-0.3.5 → ct_toolkit-0.3.6}/tests/test_analysis.py +0 -0
- {ct_toolkit-0.3.5 → ct_toolkit-0.3.6}/tests/test_cli.py +0 -0
- {ct_toolkit-0.3.5 → ct_toolkit-0.3.6}/tests/test_deep_agents_integration.py +0 -0
- {ct_toolkit-0.3.5 → ct_toolkit-0.3.6}/tests/test_loss.py +0 -0
- {ct_toolkit-0.3.5 → ct_toolkit-0.3.6}/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.6
|
|
4
4
|
Summary: Computational Theseus Toolkit — Identity Continuity Guardrails for Agentic Systems
|
|
5
5
|
Author: Hakan Damar
|
|
6
6
|
License: Apache-2.0
|
|
@@ -65,6 +65,7 @@ For full API reference, architecture details, examples, and integration guides,
|
|
|
65
65
|
|
|
66
66
|
In complex agentic workflows, LLMs tend to "drift" from their original instructions. CT Toolkit provides the mathematical and cryptographic guardrails to ensure your agents remain aligned with their core constitution, even across deep hierarchies.
|
|
67
67
|
|
|
68
|
+
- **Passive Context Compression Detection**: Automatically detects silent provider-side history compression (e.g., OpenAI/Anthropic) via history shrinkage heuristics.
|
|
68
69
|
- **Constitutional Kernels**: Axiomatic identity anchors.
|
|
69
70
|
- **Standalone Auditor CLI**: Rapidly audit any LLM endpoint for identity drift without writing code.
|
|
70
71
|
- **Autonomous Self-Correction**: Active L2->L1 feedback loop that retries and corrects divergent responses before they reach the user.
|
|
@@ -81,10 +82,13 @@ pip install ct-toolkit
|
|
|
81
82
|
```
|
|
82
83
|
|
|
83
84
|
```python
|
|
84
|
-
from ct_toolkit import TheseusWrapper
|
|
85
|
+
from ct_toolkit import TheseusWrapper, WrapperConfig
|
|
86
|
+
|
|
87
|
+
# Protect against silent provider context compression
|
|
88
|
+
config = WrapperConfig(compression_passive_detection=True)
|
|
85
89
|
|
|
86
90
|
# One-line injection for any LLM provider
|
|
87
|
-
client = TheseusWrapper(provider="openai")
|
|
91
|
+
client = TheseusWrapper(provider="openai", config=config)
|
|
88
92
|
|
|
89
93
|
# Guardrails and drift analysis applied automatically
|
|
90
94
|
response = client.chat("What are your core security axioms?")
|
|
@@ -112,9 +116,9 @@ ct-toolkit list-templates
|
|
|
112
116
|
|
|
113
117
|
| Metric | Status |
|
|
114
118
|
| :--------------- | :------------------------------------------------------ |
|
|
115
|
-
| **Tests** | ✅
|
|
119
|
+
| **Tests** | ✅ 269/272 passing (92% coverage) |
|
|
116
120
|
| **Last Phase** | ✅ Phase 6: Auditor Mode (Complete) |
|
|
117
|
-
| **Current Goal** | 🔶 Phase 7: Multi-Agent Synchronization (
|
|
121
|
+
| **Current Goal** | 🔶 Phase 7: Multi-Agent Synchronization (Integration) |
|
|
118
122
|
|
|
119
123
|
For a detailed breakdown of the 8-phase roadmap, see [**PROJECT_STATUS.md**](docs/PROJECT_STATUS.md).
|
|
120
124
|
|
|
@@ -24,6 +24,7 @@ For full API reference, architecture details, examples, and integration guides,
|
|
|
24
24
|
|
|
25
25
|
In complex agentic workflows, LLMs tend to "drift" from their original instructions. CT Toolkit provides the mathematical and cryptographic guardrails to ensure your agents remain aligned with their core constitution, even across deep hierarchies.
|
|
26
26
|
|
|
27
|
+
- **Passive Context Compression Detection**: Automatically detects silent provider-side history compression (e.g., OpenAI/Anthropic) via history shrinkage heuristics.
|
|
27
28
|
- **Constitutional Kernels**: Axiomatic identity anchors.
|
|
28
29
|
- **Standalone Auditor CLI**: Rapidly audit any LLM endpoint for identity drift without writing code.
|
|
29
30
|
- **Autonomous Self-Correction**: Active L2->L1 feedback loop that retries and corrects divergent responses before they reach the user.
|
|
@@ -40,10 +41,13 @@ pip install ct-toolkit
|
|
|
40
41
|
```
|
|
41
42
|
|
|
42
43
|
```python
|
|
43
|
-
from ct_toolkit import TheseusWrapper
|
|
44
|
+
from ct_toolkit import TheseusWrapper, WrapperConfig
|
|
45
|
+
|
|
46
|
+
# Protect against silent provider context compression
|
|
47
|
+
config = WrapperConfig(compression_passive_detection=True)
|
|
44
48
|
|
|
45
49
|
# One-line injection for any LLM provider
|
|
46
|
-
client = TheseusWrapper(provider="openai")
|
|
50
|
+
client = TheseusWrapper(provider="openai", config=config)
|
|
47
51
|
|
|
48
52
|
# Guardrails and drift analysis applied automatically
|
|
49
53
|
response = client.chat("What are your core security axioms?")
|
|
@@ -71,9 +75,9 @@ ct-toolkit list-templates
|
|
|
71
75
|
|
|
72
76
|
| Metric | Status |
|
|
73
77
|
| :--------------- | :------------------------------------------------------ |
|
|
74
|
-
| **Tests** | ✅
|
|
78
|
+
| **Tests** | ✅ 269/272 passing (92% coverage) |
|
|
75
79
|
| **Last Phase** | ✅ Phase 6: Auditor Mode (Complete) |
|
|
76
|
-
| **Current Goal** | 🔶 Phase 7: Multi-Agent Synchronization (
|
|
80
|
+
| **Current Goal** | 🔶 Phase 7: Multi-Agent Synchronization (Integration) |
|
|
77
81
|
|
|
78
82
|
For a detailed breakdown of the 8-phase roadmap, see [**PROJECT_STATUS.md**](docs/PROJECT_STATUS.md).
|
|
79
83
|
|
|
@@ -1,20 +1,18 @@
|
|
|
1
1
|
"""
|
|
2
|
-
ct_toolkit.
|
|
2
|
+
ct_toolkit.core.compression_guard
|
|
3
3
|
---------------------------------
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
identity-continuity guardrails, specifically ensuring that when a
|
|
8
|
-
Deep Agent spawns sub-agents, they inherit the mother agent's
|
|
9
|
-
Constitutional Kernel.
|
|
4
|
+
Provider-agnostic compression drift detector.
|
|
5
|
+
Works with OpenAI compaction, Anthropic compaction, LangChain memory,
|
|
6
|
+
or any framework that silently shortens context.
|
|
10
7
|
"""
|
|
11
8
|
from __future__ import annotations
|
|
12
9
|
|
|
13
|
-
from typing import Any, Dict, List,
|
|
14
|
-
from ct_toolkit.core.wrapper import TheseusWrapper, WrapperConfig
|
|
15
|
-
from ct_toolkit.middleware.langchain import TheseusChatModel
|
|
10
|
+
from typing import Any, Dict, List, TYPE_CHECKING
|
|
16
11
|
from ct_toolkit.utils.logger import get_logger
|
|
17
12
|
|
|
13
|
+
if TYPE_CHECKING:
|
|
14
|
+
from ct_toolkit.core.wrapper import TheseusWrapper
|
|
15
|
+
|
|
18
16
|
logger = get_logger(__name__)
|
|
19
17
|
|
|
20
18
|
class ContextCompressionGuard:
|
|
@@ -27,7 +25,7 @@ class ContextCompressionGuard:
|
|
|
27
25
|
|
|
28
26
|
def analyze_summary_drift(
|
|
29
27
|
self,
|
|
30
|
-
original_messages: List[Dict[str, str]],
|
|
28
|
+
original_messages: List[Dict[str, str]] | str,
|
|
31
29
|
summary_text: str
|
|
32
30
|
) -> Dict[str, Any]:
|
|
33
31
|
"""
|
|
@@ -37,9 +35,12 @@ class ContextCompressionGuard:
|
|
|
37
35
|
Returns:
|
|
38
36
|
Dict containing similarity score and drift status.
|
|
39
37
|
"""
|
|
40
|
-
# 1. Flatten original messages into a single identity string
|
|
41
|
-
|
|
42
|
-
|
|
38
|
+
# 1. Flatten original messages into a single identity string if it's a list
|
|
39
|
+
if isinstance(original_messages, list):
|
|
40
|
+
original_text = " ".join([m.get("content", "") for m in original_messages])
|
|
41
|
+
else:
|
|
42
|
+
original_text = original_messages
|
|
43
|
+
|
|
43
44
|
# 2. Compute embeddings via identity layer
|
|
44
45
|
original_emb = self.wrapper._identity_layer._compute_vector(original_text)
|
|
45
46
|
summary_emb = self.wrapper._identity_layer._compute_vector(summary_text)
|
|
@@ -49,7 +50,6 @@ class ContextCompressionGuard:
|
|
|
49
50
|
similarity = IdentityEmbeddingLayer.calculate_similarity(original_emb, summary_emb)
|
|
50
51
|
|
|
51
52
|
# 4. Identity Safety Floor (Internal protection against manipulated thresholds)
|
|
52
|
-
# Even if the user sets threshold to 0.4, 0.6 is still risky for LLM identity.
|
|
53
53
|
drift_detected = similarity < self.threshold
|
|
54
54
|
is_critical = similarity < 0.70 # A hard floor for identity integrity
|
|
55
55
|
|
|
@@ -88,48 +88,11 @@ class ContextCompressionGuard:
|
|
|
88
88
|
|
|
89
89
|
return result
|
|
90
90
|
|
|
91
|
-
def
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
)
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
inject Theseus guardrails, enable hierarchical kernel propagation,
|
|
100
|
-
and monitor context compression drift.
|
|
101
|
-
"""
|
|
102
|
-
_wrapper = wrapper or TheseusWrapper(config=wrapper_config)
|
|
103
|
-
guard = ContextCompressionGuard(_wrapper, threshold=compression_threshold)
|
|
104
|
-
|
|
105
|
-
def wrapped_create_deep_agent(*args: Any, **kwargs: Any) -> Any:
|
|
106
|
-
# 1. Inject TheseusChatModel
|
|
107
|
-
model = kwargs.get("model")
|
|
108
|
-
if isinstance(model, str) or model is None:
|
|
109
|
-
kwargs["model"] = TheseusChatModel(
|
|
110
|
-
wrapper=_wrapper,
|
|
111
|
-
model=model if isinstance(model, str) else "gpt-4o-mini"
|
|
112
|
-
)
|
|
113
|
-
|
|
114
|
-
# 2. Inject ContextCompressionGuard into the middleware stack if possible
|
|
115
|
-
# Since deepagents middleware is internal, we use the helper to signal it
|
|
116
|
-
# In a real integration, we'd wrap the SummarizationMiddleware.
|
|
117
|
-
|
|
118
|
-
return create_deep_agent_fn(*args, **kwargs)
|
|
119
|
-
|
|
120
|
-
return wrapped_create_deep_agent
|
|
121
|
-
|
|
122
|
-
class DeepAgentTheseusHelper:
|
|
123
|
-
"""
|
|
124
|
-
Helper for programmatic integration with Deep Agents.
|
|
125
|
-
"""
|
|
126
|
-
@staticmethod
|
|
127
|
-
def prepare_config(wrapper: TheseusWrapper) -> Dict[str, Any]:
|
|
128
|
-
"""Returns configuration for Deep Agents that includes identity constraints."""
|
|
129
|
-
return {
|
|
130
|
-
"callbacks": [], # We could add TheseusLangChainCallback here
|
|
131
|
-
"metadata": {
|
|
132
|
-
"ct_kernel": wrapper.kernel.name,
|
|
133
|
-
"ct_identity_protection": True
|
|
134
|
-
}
|
|
135
|
-
}
|
|
91
|
+
def on_passive_detection(self, original: List[Dict[str, str]], compressed: List[Dict[str, str]]) -> Dict[str, Any]:
|
|
92
|
+
"""
|
|
93
|
+
Triggered when TheseusWrapper detects a significant history shrinkage.
|
|
94
|
+
"""
|
|
95
|
+
logger.info("CT Toolkit | Passive compression detection triggered.")
|
|
96
|
+
original_text = " ".join(m.get("content", "") for m in original)
|
|
97
|
+
compressed_text = " ".join(m.get("content", "") for m in compressed)
|
|
98
|
+
return self.analyze_summary_drift(original_text, compressed_text)
|
|
@@ -34,6 +34,7 @@ from ct_toolkit.core.compatibility import CompatibilityLayer, CompatibilityResul
|
|
|
34
34
|
from ct_toolkit.core.exceptions import CTToolkitError, MissingClientError
|
|
35
35
|
from ct_toolkit.core.integrity import IntegrityMonitor
|
|
36
36
|
from ct_toolkit.divergence.scheduler import RiskProfile
|
|
37
|
+
from ct_toolkit.core.compression_guard import ContextCompressionGuard
|
|
37
38
|
from ct_toolkit.utils.logger import get_logger
|
|
38
39
|
|
|
39
40
|
logger = get_logger(__name__)
|
|
@@ -71,6 +72,10 @@ class WrapperConfig:
|
|
|
71
72
|
|
|
72
73
|
strict_embedding: bool = False # Raise error if embedding API fails
|
|
73
74
|
|
|
75
|
+
# -- Context Compression Guard --
|
|
76
|
+
compression_threshold: float = 0.85
|
|
77
|
+
compression_passive_detection: bool = True
|
|
78
|
+
|
|
74
79
|
|
|
75
80
|
@dataclass
|
|
76
81
|
class CTResponse:
|
|
@@ -165,6 +170,13 @@ class TheseusWrapper:
|
|
|
165
170
|
self._divergence_engine = self._init_divergence_engine()
|
|
166
171
|
self._last_model: str = "unknown"
|
|
167
172
|
|
|
173
|
+
# ── Context Compression Guard ──
|
|
174
|
+
self._compression_guard = ContextCompressionGuard(
|
|
175
|
+
self,
|
|
176
|
+
threshold=self._config.compression_threshold
|
|
177
|
+
)
|
|
178
|
+
self._shadow_history: Optional[List[Dict[str, str]]] = None
|
|
179
|
+
|
|
168
180
|
# ── Integrity Monitoring ──
|
|
169
181
|
self._integrity_monitor = IntegrityMonitor()
|
|
170
182
|
self._register_monitored_files()
|
|
@@ -490,6 +502,18 @@ class TheseusWrapper:
|
|
|
490
502
|
**kwargs: Any,
|
|
491
503
|
) -> Any:
|
|
492
504
|
"""Uses any_llm for unified provider calling."""
|
|
505
|
+
# --- Passive Context Compression Detection ---
|
|
506
|
+
if self._config.compression_passive_detection and self._shadow_history:
|
|
507
|
+
# Simple heuristic: message count dropped significantly
|
|
508
|
+
# We use 0.7 as a threshold (30% drop)
|
|
509
|
+
if len(messages) < len(self._shadow_history) * 0.7:
|
|
510
|
+
self._compression_guard.on_passive_detection(
|
|
511
|
+
original=self._shadow_history,
|
|
512
|
+
compressed=messages
|
|
513
|
+
)
|
|
514
|
+
|
|
515
|
+
# Update shadow history for next call
|
|
516
|
+
self._shadow_history = list(messages)
|
|
493
517
|
# Convert messages to any_llm format if necessary
|
|
494
518
|
# any_llm.completion handles different formats internally
|
|
495
519
|
|
|
@@ -92,6 +92,8 @@ class TheseusCrewMiddleware:
|
|
|
92
92
|
parent_kernel=manager_wrapper.kernel,
|
|
93
93
|
vault_path=manager_wrapper._config.vault_path,
|
|
94
94
|
template=manager_wrapper._config.template,
|
|
95
|
+
compression_threshold=manager_wrapper._config.compression_threshold,
|
|
96
|
+
compression_passive_detection=manager_wrapper._config.compression_passive_detection,
|
|
95
97
|
)
|
|
96
98
|
agent.llm = TheseusChatModel(
|
|
97
99
|
provider=manager_wrapper._provider,
|
|
@@ -134,6 +136,8 @@ class TheseusCrewMiddleware:
|
|
|
134
136
|
parent_kernel=manager_wrapper.kernel,
|
|
135
137
|
vault_path=manager_wrapper._config.vault_path,
|
|
136
138
|
template=manager_wrapper._config.template,
|
|
139
|
+
compression_threshold=manager_wrapper._config.compression_threshold,
|
|
140
|
+
compression_passive_detection=manager_wrapper._config.compression_passive_detection,
|
|
137
141
|
)
|
|
138
142
|
agent.llm = TheseusChatModel(
|
|
139
143
|
provider=manager_wrapper._provider,
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
"""
|
|
2
|
+
ct_toolkit.middleware.deepagents
|
|
3
|
+
---------------------------------
|
|
4
|
+
Specialized integration for LangChain Deep Agents (deepagents).
|
|
5
|
+
|
|
6
|
+
This module provides helpers to wrap Deep Agents with CT Toolkit's
|
|
7
|
+
identity-continuity guardrails, specifically ensuring that when a
|
|
8
|
+
Deep Agent spawns sub-agents, they inherit the mother agent's
|
|
9
|
+
Constitutional Kernel.
|
|
10
|
+
"""
|
|
11
|
+
from __future__ import annotations
|
|
12
|
+
|
|
13
|
+
from typing import Any, Dict, List, Optional, Union, Callable
|
|
14
|
+
from ct_toolkit.core.wrapper import TheseusWrapper, WrapperConfig
|
|
15
|
+
from ct_toolkit.core.compression_guard import ContextCompressionGuard
|
|
16
|
+
from ct_toolkit.middleware.langchain import TheseusChatModel
|
|
17
|
+
from ct_toolkit.utils.logger import get_logger
|
|
18
|
+
|
|
19
|
+
logger = get_logger(__name__)
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def wrap_deep_agent_factory(
|
|
24
|
+
create_deep_agent_fn: Callable,
|
|
25
|
+
wrapper: Optional[TheseusWrapper] = None,
|
|
26
|
+
wrapper_config: Optional[WrapperConfig] = None,
|
|
27
|
+
compression_threshold: float = 0.85,
|
|
28
|
+
) -> Callable:
|
|
29
|
+
"""
|
|
30
|
+
Wraps the LangChain `create_deep_agent` function to automatically
|
|
31
|
+
inject Theseus guardrails, enable hierarchical kernel propagation,
|
|
32
|
+
and monitor context compression drift.
|
|
33
|
+
"""
|
|
34
|
+
_wrapper = wrapper or TheseusWrapper(config=wrapper_config)
|
|
35
|
+
guard = ContextCompressionGuard(_wrapper, threshold=compression_threshold)
|
|
36
|
+
|
|
37
|
+
def wrapped_create_deep_agent(*args: Any, **kwargs: Any) -> Any:
|
|
38
|
+
# 1. Inject TheseusChatModel
|
|
39
|
+
model = kwargs.get("model")
|
|
40
|
+
if isinstance(model, str) or model is None:
|
|
41
|
+
kwargs["model"] = TheseusChatModel(
|
|
42
|
+
wrapper=_wrapper,
|
|
43
|
+
model=model if isinstance(model, str) else "gpt-4o-mini"
|
|
44
|
+
)
|
|
45
|
+
|
|
46
|
+
# 2. Inject ContextCompressionGuard into the middleware stack if possible
|
|
47
|
+
# Since deepagents middleware is internal, we use the helper to signal it
|
|
48
|
+
# In a real integration, we'd wrap the SummarizationMiddleware.
|
|
49
|
+
|
|
50
|
+
return create_deep_agent_fn(*args, **kwargs)
|
|
51
|
+
|
|
52
|
+
return wrapped_create_deep_agent
|
|
53
|
+
|
|
54
|
+
class DeepAgentTheseusHelper:
|
|
55
|
+
"""
|
|
56
|
+
Helper for programmatic integration with Deep Agents.
|
|
57
|
+
"""
|
|
58
|
+
@staticmethod
|
|
59
|
+
def prepare_config(wrapper: TheseusWrapper) -> Dict[str, Any]:
|
|
60
|
+
"""Returns configuration for Deep Agents that includes identity constraints."""
|
|
61
|
+
return {
|
|
62
|
+
"callbacks": [], # We could add TheseusLangChainCallback here
|
|
63
|
+
"metadata": {
|
|
64
|
+
"ct_kernel": wrapper.kernel.name,
|
|
65
|
+
"ct_identity_protection": True
|
|
66
|
+
}
|
|
67
|
+
}
|
|
@@ -204,6 +204,11 @@ class TheseusChatModel(BaseChatModel):
|
|
|
204
204
|
)
|
|
205
205
|
super().__init__(wrapper=_wrapper, model=model, **kwargs)
|
|
206
206
|
|
|
207
|
+
@property
|
|
208
|
+
def compression_guard(self) -> Any:
|
|
209
|
+
"""Access the underlying ContextCompressionGuard."""
|
|
210
|
+
return self.wrapper._compression_guard
|
|
211
|
+
|
|
207
212
|
@property
|
|
208
213
|
def _llm_type(self) -> str:
|
|
209
214
|
return "theseus-chat-model"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: ct-toolkit
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.6
|
|
4
4
|
Summary: Computational Theseus Toolkit — Identity Continuity Guardrails for Agentic Systems
|
|
5
5
|
Author: Hakan Damar
|
|
6
6
|
License: Apache-2.0
|
|
@@ -65,6 +65,7 @@ For full API reference, architecture details, examples, and integration guides,
|
|
|
65
65
|
|
|
66
66
|
In complex agentic workflows, LLMs tend to "drift" from their original instructions. CT Toolkit provides the mathematical and cryptographic guardrails to ensure your agents remain aligned with their core constitution, even across deep hierarchies.
|
|
67
67
|
|
|
68
|
+
- **Passive Context Compression Detection**: Automatically detects silent provider-side history compression (e.g., OpenAI/Anthropic) via history shrinkage heuristics.
|
|
68
69
|
- **Constitutional Kernels**: Axiomatic identity anchors.
|
|
69
70
|
- **Standalone Auditor CLI**: Rapidly audit any LLM endpoint for identity drift without writing code.
|
|
70
71
|
- **Autonomous Self-Correction**: Active L2->L1 feedback loop that retries and corrects divergent responses before they reach the user.
|
|
@@ -81,10 +82,13 @@ pip install ct-toolkit
|
|
|
81
82
|
```
|
|
82
83
|
|
|
83
84
|
```python
|
|
84
|
-
from ct_toolkit import TheseusWrapper
|
|
85
|
+
from ct_toolkit import TheseusWrapper, WrapperConfig
|
|
86
|
+
|
|
87
|
+
# Protect against silent provider context compression
|
|
88
|
+
config = WrapperConfig(compression_passive_detection=True)
|
|
85
89
|
|
|
86
90
|
# One-line injection for any LLM provider
|
|
87
|
-
client = TheseusWrapper(provider="openai")
|
|
91
|
+
client = TheseusWrapper(provider="openai", config=config)
|
|
88
92
|
|
|
89
93
|
# Guardrails and drift analysis applied automatically
|
|
90
94
|
response = client.chat("What are your core security axioms?")
|
|
@@ -112,9 +116,9 @@ ct-toolkit list-templates
|
|
|
112
116
|
|
|
113
117
|
| Metric | Status |
|
|
114
118
|
| :--------------- | :------------------------------------------------------ |
|
|
115
|
-
| **Tests** | ✅
|
|
119
|
+
| **Tests** | ✅ 269/272 passing (92% coverage) |
|
|
116
120
|
| **Last Phase** | ✅ Phase 6: Auditor Mode (Complete) |
|
|
117
|
-
| **Current Goal** | 🔶 Phase 7: Multi-Agent Synchronization (
|
|
121
|
+
| **Current Goal** | 🔶 Phase 7: Multi-Agent Synchronization (Integration) |
|
|
118
122
|
|
|
119
123
|
For a detailed breakdown of the 8-phase roadmap, see [**PROJECT_STATUS.md**](docs/PROJECT_STATUS.md).
|
|
120
124
|
|
|
@@ -12,6 +12,7 @@ ct_toolkit.egg-info/requires.txt
|
|
|
12
12
|
ct_toolkit.egg-info/top_level.txt
|
|
13
13
|
ct_toolkit/core/__init__.py
|
|
14
14
|
ct_toolkit/core/compatibility.py
|
|
15
|
+
ct_toolkit/core/compression_guard.py
|
|
15
16
|
ct_toolkit/core/exceptions.py
|
|
16
17
|
ct_toolkit/core/integrity.py
|
|
17
18
|
ct_toolkit/core/kernel.py
|
|
@@ -48,6 +49,7 @@ ct_toolkit/utils/__init__.py
|
|
|
48
49
|
ct_toolkit/utils/logger.py
|
|
49
50
|
tests/test_analysis.py
|
|
50
51
|
tests/test_cli.py
|
|
52
|
+
tests/test_cli_extended.py
|
|
51
53
|
tests/test_deep_agents_integration.py
|
|
52
54
|
tests/test_loss.py
|
|
53
55
|
tests/test_summarization_drift.py
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "ct-toolkit"
|
|
7
|
-
version = "0.3.
|
|
7
|
+
version = "0.3.6"
|
|
8
8
|
description = "Computational Theseus Toolkit — Identity Continuity Guardrails for Agentic Systems"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.11"
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import pytest
|
|
2
|
+
from typer.testing import CliRunner
|
|
3
|
+
from ct_toolkit.cli import app
|
|
4
|
+
from unittest.mock import MagicMock, patch
|
|
5
|
+
|
|
6
|
+
runner = CliRunner()
|
|
7
|
+
|
|
8
|
+
def test_cli_version():
|
|
9
|
+
result = runner.invoke(app, ["--version"])
|
|
10
|
+
assert result.exit_code == 0
|
|
11
|
+
assert "CT Toolkit v" in result.stdout
|
|
12
|
+
|
|
13
|
+
def test_cli_version_short():
|
|
14
|
+
result = runner.invoke(app, ["-v"])
|
|
15
|
+
assert result.exit_code == 0
|
|
16
|
+
assert "CT Toolkit v" in result.stdout
|
|
17
|
+
|
|
18
|
+
@patch("ct_toolkit.cli.TheseusWrapper")
|
|
19
|
+
def test_cli_audit_init_fail(mock_wrapper):
|
|
20
|
+
mock_wrapper.side_effect = Exception("Init failed")
|
|
21
|
+
result = runner.invoke(app, ["audit", "--url", "http://test", "--api-key", "test"])
|
|
22
|
+
assert result.exit_code == 1
|
|
23
|
+
assert "Initialization failed" in result.stdout
|
|
24
|
+
|
|
25
|
+
@patch("ct_toolkit.cli.TheseusWrapper")
|
|
26
|
+
@patch("ct_toolkit.cli.ICMRunner")
|
|
27
|
+
def test_cli_audit_no_probes(mock_icm, mock_wrapper):
|
|
28
|
+
mock_report = MagicMock()
|
|
29
|
+
mock_report.total_probes = 0
|
|
30
|
+
mock_icm.return_value.run.return_value = mock_report
|
|
31
|
+
|
|
32
|
+
result = runner.invoke(app, ["audit", "--url", "http://test", "--api-key", "test"])
|
|
33
|
+
assert result.exit_code == 1
|
|
34
|
+
assert "No probes were loaded" in result.stdout
|
|
35
|
+
|
|
36
|
+
@patch("ct_toolkit.cli.TheseusWrapper")
|
|
37
|
+
@patch("ct_toolkit.cli.ICMRunner")
|
|
38
|
+
def test_cli_audit_execution_fail(mock_icm, mock_wrapper):
|
|
39
|
+
mock_icm.return_value.run.side_effect = Exception("Run failed")
|
|
40
|
+
|
|
41
|
+
result = runner.invoke(app, ["audit", "--url", "http://test", "--api-key", "test"])
|
|
42
|
+
assert result.exit_code == 1
|
|
43
|
+
assert "Audit failed during execution" in result.stdout
|
|
44
|
+
|
|
45
|
+
def test_cli_list_kernels():
|
|
46
|
+
result = runner.invoke(app, ["list-kernels"])
|
|
47
|
+
assert result.exit_code == 0
|
|
48
|
+
assert "Available Kernels" in result.stdout
|
|
49
|
+
|
|
50
|
+
def test_cli_list_templates():
|
|
51
|
+
result = runner.invoke(app, ["list-templates"])
|
|
52
|
+
assert result.exit_code == 0
|
|
53
|
+
assert "Available Templates" in result.stdout
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|