tada-core 0.2.0__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.
- tada_core/__init__.py +57 -0
- tada_core/cli/harness.py +36 -0
- tada_core/contracts/__init__.py +9 -0
- tada_core/contracts/budget.py +43 -0
- tada_core/contracts/compaction.py +622 -0
- tada_core/contracts/events.py +233 -0
- tada_core/contracts/hooks.py +322 -0
- tada_core/contracts/messages.py +113 -0
- tada_core/contracts/model.py +109 -0
- tada_core/contracts/models.py +39 -0
- tada_core/contracts/permissions.py +89 -0
- tada_core/contracts/session.py +42 -0
- tada_core/contracts/tokenization.py +88 -0
- tada_core/contracts/tools.py +176 -0
- tada_core/extensions/__init__.py +1 -0
- tada_core/extensions/mcp_optional.py +18 -0
- tada_core/loop/__init__.py +22 -0
- tada_core/loop/message_sanitizer.py +232 -0
- tada_core/loop/model_client.py +84 -0
- tada_core/loop/retry.py +78 -0
- tada_core/loop/runner.py +831 -0
- tada_core/providers/__init__.py +13 -0
- tada_core/providers/anthropic.py +753 -0
- tada_core/providers/bedrock.py +454 -0
- tada_core/providers/google.py +327 -0
- tada_core/providers/openai_completions.py +341 -0
- tada_core/providers/openai_responses.py +446 -0
- tada_core/providers/openai_utils.py +254 -0
- tada_core/providers/registry.py +53 -0
- tada_core/utils/__init__.py +2 -0
- tada_core/utils/content_normalizer.py +193 -0
- tada_core-0.2.0.dist-info/METADATA +489 -0
- tada_core-0.2.0.dist-info/RECORD +36 -0
- tada_core-0.2.0.dist-info/WHEEL +4 -0
- tada_core-0.2.0.dist-info/entry_points.txt +2 -0
- tada_core-0.2.0.dist-info/licenses/LICENSE +21 -0
tada_core/__init__.py
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
"""Public SDK surface for tada-core."""
|
|
2
|
+
|
|
3
|
+
from tada_core.contracts.budget import BudgetLimits
|
|
4
|
+
from tada_core.contracts.compaction import (
|
|
5
|
+
CompactionConfig,
|
|
6
|
+
CompactionMode,
|
|
7
|
+
CompactionStrategy,
|
|
8
|
+
ModelSummaryCompaction,
|
|
9
|
+
NeverCompact,
|
|
10
|
+
StructuredSummaryCompaction,
|
|
11
|
+
ToolResultPruningConfig,
|
|
12
|
+
TruncateCompaction,
|
|
13
|
+
)
|
|
14
|
+
from tada_core.contracts.events import Event
|
|
15
|
+
from tada_core.contracts.messages import ContentBlock, ConversationMessage, MessageRole
|
|
16
|
+
from tada_core.contracts.model import StopReason
|
|
17
|
+
from tada_core.contracts.models import ModelSpec
|
|
18
|
+
from tada_core.contracts.session import SessionState
|
|
19
|
+
from tada_core.contracts.tokenization import CharacterTokenEstimator, TokenEstimator
|
|
20
|
+
from tada_core.contracts.tools import ChainedToolExecutor, ToolResult
|
|
21
|
+
from tada_core.loop import AgentLoop, AnthropicModelClient
|
|
22
|
+
from tada_core.loop.retry import RetryingModelClient, RetryPolicy
|
|
23
|
+
from tada_core.providers import build_model_client
|
|
24
|
+
from tada_core.utils.content_normalizer import ContentNormalizerConfig, normalize_messages
|
|
25
|
+
|
|
26
|
+
__version__ = "0.2.0"
|
|
27
|
+
|
|
28
|
+
__all__ = [
|
|
29
|
+
"AgentLoop",
|
|
30
|
+
"AnthropicModelClient",
|
|
31
|
+
"BudgetLimits",
|
|
32
|
+
"CharacterTokenEstimator",
|
|
33
|
+
"ChainedToolExecutor",
|
|
34
|
+
"CompactionConfig",
|
|
35
|
+
"CompactionMode",
|
|
36
|
+
"CompactionStrategy",
|
|
37
|
+
"ContentNormalizerConfig",
|
|
38
|
+
"ContentBlock",
|
|
39
|
+
"ConversationMessage",
|
|
40
|
+
"Event",
|
|
41
|
+
"MessageRole",
|
|
42
|
+
"ModelSpec",
|
|
43
|
+
"ModelSummaryCompaction",
|
|
44
|
+
"NeverCompact",
|
|
45
|
+
"SessionState",
|
|
46
|
+
"StopReason",
|
|
47
|
+
"StructuredSummaryCompaction",
|
|
48
|
+
"TokenEstimator",
|
|
49
|
+
"ToolResult",
|
|
50
|
+
"ToolResultPruningConfig",
|
|
51
|
+
"TruncateCompaction",
|
|
52
|
+
"RetryPolicy",
|
|
53
|
+
"RetryingModelClient",
|
|
54
|
+
"build_model_client",
|
|
55
|
+
"normalize_messages",
|
|
56
|
+
"__version__",
|
|
57
|
+
]
|
tada_core/cli/harness.py
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
"""Minimal echo-only CLI harness for manual smoke tests."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import asyncio
|
|
6
|
+
import sys
|
|
7
|
+
|
|
8
|
+
from tada_core.contracts.session import SessionState
|
|
9
|
+
from tada_core.loop import AgentLoop
|
|
10
|
+
from tada_core.loop.model_client import OpenAICompatibleModelClient, make_echo_transport
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def main(argv: list[str] | None = None) -> None:
|
|
14
|
+
import argparse
|
|
15
|
+
|
|
16
|
+
p = argparse.ArgumentParser(
|
|
17
|
+
prog="tada-core-smoke",
|
|
18
|
+
description="Manual smoke harness for the tada-core AgentLoop",
|
|
19
|
+
)
|
|
20
|
+
p.add_argument("--text", default="hello", help="user message")
|
|
21
|
+
p.add_argument("--stream", action="store_true", help="use streaming transport")
|
|
22
|
+
args = p.parse_args(argv)
|
|
23
|
+
|
|
24
|
+
model = OpenAICompatibleModelClient(make_echo_transport(), streaming=args.stream)
|
|
25
|
+
loop = AgentLoop(model)
|
|
26
|
+
state = SessionState()
|
|
27
|
+
|
|
28
|
+
async def _run() -> None:
|
|
29
|
+
async for ev in loop.run_turn(state, args.text):
|
|
30
|
+
print(ev.model_dump_json())
|
|
31
|
+
|
|
32
|
+
asyncio.run(_run())
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
if __name__ == "__main__":
|
|
36
|
+
main(sys.argv[1:])
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
"""Runtime budget controls for AgentLoop.
|
|
2
|
+
|
|
3
|
+
Budgets are provider-agnostic execution limits. They intentionally do not
|
|
4
|
+
contain provider prices, routing priorities, quota accounts, or OAuth details.
|
|
5
|
+
Hosts may translate token usage into cost externally and feed a derived limit
|
|
6
|
+
back into this contract later.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from __future__ import annotations
|
|
10
|
+
|
|
11
|
+
from pydantic import BaseModel
|
|
12
|
+
|
|
13
|
+
from tada_core.contracts.session import TokenUsage
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class BudgetLimits(BaseModel):
|
|
17
|
+
"""Simple per-turn/session budget limits enforced by AgentLoop."""
|
|
18
|
+
|
|
19
|
+
max_input_tokens: int | None = None
|
|
20
|
+
max_output_tokens: int | None = None
|
|
21
|
+
max_total_tokens: int | None = None
|
|
22
|
+
max_iterations: int | None = None
|
|
23
|
+
max_tool_calls: int | None = None
|
|
24
|
+
|
|
25
|
+
def check_usage(self, usage: TokenUsage) -> str | None:
|
|
26
|
+
if self.max_input_tokens is not None and usage.input_tokens > self.max_input_tokens:
|
|
27
|
+
return f"input token budget exceeded: {usage.input_tokens} > {self.max_input_tokens}"
|
|
28
|
+
if self.max_output_tokens is not None and usage.output_tokens > self.max_output_tokens:
|
|
29
|
+
return f"output token budget exceeded: {usage.output_tokens} > {self.max_output_tokens}"
|
|
30
|
+
total = usage.input_tokens + usage.output_tokens
|
|
31
|
+
if self.max_total_tokens is not None and total > self.max_total_tokens:
|
|
32
|
+
return f"total token budget exceeded: {total} > {self.max_total_tokens}"
|
|
33
|
+
return None
|
|
34
|
+
|
|
35
|
+
def check_iteration(self, iterations_used: int) -> str | None:
|
|
36
|
+
if self.max_iterations is not None and iterations_used >= self.max_iterations:
|
|
37
|
+
return f"iteration budget exceeded: {iterations_used} >= {self.max_iterations}"
|
|
38
|
+
return None
|
|
39
|
+
|
|
40
|
+
def check_tool_calls(self, tool_calls_used: int) -> str | None:
|
|
41
|
+
if self.max_tool_calls is not None and tool_calls_used > self.max_tool_calls:
|
|
42
|
+
return f"tool call budget exceeded: {tool_calls_used} > {self.max_tool_calls}"
|
|
43
|
+
return None
|