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 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
+ ]
@@ -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,9 @@
1
+ from tada_core.contracts.events import Event
2
+ from tada_core.contracts.messages import ContentBlock, ConversationMessage, MessageRole
3
+
4
+ __all__ = [
5
+ "Event",
6
+ "ContentBlock",
7
+ "ConversationMessage",
8
+ "MessageRole",
9
+ ]
@@ -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