tars-sdk 0.1.1__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.
- tars_sdk/__init__.py +219 -0
- tars_sdk/_sse.py +33 -0
- tars_sdk/_wire.py +49 -0
- tars_sdk/client.py +738 -0
- tars_sdk/errors.py +34 -0
- tars_sdk/events.py +284 -0
- tars_sdk/models.py +696 -0
- tars_sdk/py.typed +0 -0
- tars_sdk/session.py +119 -0
- tars_sdk-0.1.1.dist-info/METADATA +91 -0
- tars_sdk-0.1.1.dist-info/RECORD +12 -0
- tars_sdk-0.1.1.dist-info/WHEEL +4 -0
tars_sdk/__init__.py
ADDED
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
"""tars-sdk — the Python client for TARS.
|
|
2
|
+
|
|
3
|
+
from tars_sdk import TarsClient, TextDeltaEvent
|
|
4
|
+
|
|
5
|
+
async with TarsClient(api_key="tars_sk_…", base_url="https://your-tars-host") as tars:
|
|
6
|
+
agent = await tars.agents.create(name="assistant", system="You are helpful.")
|
|
7
|
+
session = await tars.sessions.create(agent_id=agent.id)
|
|
8
|
+
async for ev in session.send("Hello!"):
|
|
9
|
+
if isinstance(ev, TextDeltaEvent):
|
|
10
|
+
print(ev.text, end="")
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
from importlib.metadata import PackageNotFoundError, version as _version
|
|
14
|
+
|
|
15
|
+
from ._wire import UNSET
|
|
16
|
+
from .client import (
|
|
17
|
+
DEFAULT_BASE_URL,
|
|
18
|
+
KEYED_PROVIDERS,
|
|
19
|
+
AdminClient,
|
|
20
|
+
AgentsClient,
|
|
21
|
+
ApiKeysClient,
|
|
22
|
+
CompletionsClient,
|
|
23
|
+
FilesClient,
|
|
24
|
+
McpClient,
|
|
25
|
+
McpCredentialsClient,
|
|
26
|
+
SessionsClient,
|
|
27
|
+
SkillsClient,
|
|
28
|
+
TarsClient,
|
|
29
|
+
UsageClient,
|
|
30
|
+
)
|
|
31
|
+
from .errors import TarsApiError
|
|
32
|
+
from .events import (
|
|
33
|
+
AGENT_ERROR_CODES,
|
|
34
|
+
SESSION_EVENT_TYPES,
|
|
35
|
+
CompactionEvent,
|
|
36
|
+
ConnectRequiredEvent,
|
|
37
|
+
ErrorEvent,
|
|
38
|
+
McpConnectEvent,
|
|
39
|
+
MessageAttachment,
|
|
40
|
+
OutputFileEvent,
|
|
41
|
+
SessionEvent,
|
|
42
|
+
StatusEvent,
|
|
43
|
+
TextDeltaEvent,
|
|
44
|
+
TextEndEvent,
|
|
45
|
+
TextStartEvent,
|
|
46
|
+
ToolCallEvent,
|
|
47
|
+
ToolResultEvent,
|
|
48
|
+
TurnEndEvent,
|
|
49
|
+
TurnStartEvent,
|
|
50
|
+
TurnUsage,
|
|
51
|
+
UnknownEvent,
|
|
52
|
+
UserMessageEvent,
|
|
53
|
+
parse_event,
|
|
54
|
+
)
|
|
55
|
+
from .models import (
|
|
56
|
+
Agent,
|
|
57
|
+
AgentEnvironment,
|
|
58
|
+
AgentPackages,
|
|
59
|
+
AgentStatusResult,
|
|
60
|
+
AgentVersion,
|
|
61
|
+
ApiKeyInfo,
|
|
62
|
+
AttachResult,
|
|
63
|
+
BearerCredential,
|
|
64
|
+
BuiltinToolInfo,
|
|
65
|
+
ClientIdentity,
|
|
66
|
+
ClientTool,
|
|
67
|
+
ClientToolDeclaration,
|
|
68
|
+
CompactResult,
|
|
69
|
+
CompletionResult,
|
|
70
|
+
CompletionUsage,
|
|
71
|
+
CreatedApiKey,
|
|
72
|
+
CreatedTenant,
|
|
73
|
+
DailyUsageRow,
|
|
74
|
+
FileMeta,
|
|
75
|
+
InterruptResult,
|
|
76
|
+
McpCredential,
|
|
77
|
+
McpCredentialStatus,
|
|
78
|
+
McpServer,
|
|
79
|
+
McpServerTools,
|
|
80
|
+
McpToolAnnotations,
|
|
81
|
+
McpToolInfo,
|
|
82
|
+
ModelInfo,
|
|
83
|
+
ModelPricing,
|
|
84
|
+
MountResult,
|
|
85
|
+
OAuthCredential,
|
|
86
|
+
OkResult,
|
|
87
|
+
PlatformStats,
|
|
88
|
+
PlatformUsageTotals,
|
|
89
|
+
ProviderStatus,
|
|
90
|
+
ProviderStatusReport,
|
|
91
|
+
ReasoningConfig,
|
|
92
|
+
SessionClientTool,
|
|
93
|
+
SessionEventsPage,
|
|
94
|
+
SessionInfo,
|
|
95
|
+
SessionListItem,
|
|
96
|
+
SessionsPage,
|
|
97
|
+
SessionToolSurface,
|
|
98
|
+
SessionUsage,
|
|
99
|
+
SessionUsageFigures,
|
|
100
|
+
SessionUsageRow,
|
|
101
|
+
Skill,
|
|
102
|
+
SkillPin,
|
|
103
|
+
SkillVersion,
|
|
104
|
+
SkillVersionPushed,
|
|
105
|
+
Tenant,
|
|
106
|
+
TenantCounts,
|
|
107
|
+
TenantDetail,
|
|
108
|
+
TenantFirstKey,
|
|
109
|
+
TenantStats,
|
|
110
|
+
ToolHandler,
|
|
111
|
+
UsageBreakdownRow,
|
|
112
|
+
UsageSummary,
|
|
113
|
+
UsageTotals,
|
|
114
|
+
)
|
|
115
|
+
from .session import TarsSession
|
|
116
|
+
|
|
117
|
+
try:
|
|
118
|
+
__version__ = _version("tars-sdk")
|
|
119
|
+
except PackageNotFoundError: # running from a source checkout
|
|
120
|
+
__version__ = "0.0.0"
|
|
121
|
+
|
|
122
|
+
__all__ = [
|
|
123
|
+
"AGENT_ERROR_CODES",
|
|
124
|
+
"DEFAULT_BASE_URL",
|
|
125
|
+
"KEYED_PROVIDERS",
|
|
126
|
+
"SESSION_EVENT_TYPES",
|
|
127
|
+
"UNSET",
|
|
128
|
+
"AdminClient",
|
|
129
|
+
"Agent",
|
|
130
|
+
"AgentEnvironment",
|
|
131
|
+
"AgentPackages",
|
|
132
|
+
"AgentStatusResult",
|
|
133
|
+
"AgentVersion",
|
|
134
|
+
"AgentsClient",
|
|
135
|
+
"ApiKeyInfo",
|
|
136
|
+
"ApiKeysClient",
|
|
137
|
+
"AttachResult",
|
|
138
|
+
"BearerCredential",
|
|
139
|
+
"BuiltinToolInfo",
|
|
140
|
+
"ClientIdentity",
|
|
141
|
+
"ClientTool",
|
|
142
|
+
"ClientToolDeclaration",
|
|
143
|
+
"CompactResult",
|
|
144
|
+
"CompactionEvent",
|
|
145
|
+
"CompletionResult",
|
|
146
|
+
"CompletionUsage",
|
|
147
|
+
"CompletionsClient",
|
|
148
|
+
"ConnectRequiredEvent",
|
|
149
|
+
"CreatedApiKey",
|
|
150
|
+
"CreatedTenant",
|
|
151
|
+
"DailyUsageRow",
|
|
152
|
+
"ErrorEvent",
|
|
153
|
+
"FileMeta",
|
|
154
|
+
"FilesClient",
|
|
155
|
+
"InterruptResult",
|
|
156
|
+
"McpClient",
|
|
157
|
+
"McpConnectEvent",
|
|
158
|
+
"McpCredential",
|
|
159
|
+
"McpCredentialStatus",
|
|
160
|
+
"McpCredentialsClient",
|
|
161
|
+
"McpServer",
|
|
162
|
+
"McpServerTools",
|
|
163
|
+
"McpToolAnnotations",
|
|
164
|
+
"McpToolInfo",
|
|
165
|
+
"MessageAttachment",
|
|
166
|
+
"ModelInfo",
|
|
167
|
+
"ModelPricing",
|
|
168
|
+
"MountResult",
|
|
169
|
+
"OAuthCredential",
|
|
170
|
+
"OkResult",
|
|
171
|
+
"OutputFileEvent",
|
|
172
|
+
"PlatformStats",
|
|
173
|
+
"PlatformUsageTotals",
|
|
174
|
+
"ProviderStatus",
|
|
175
|
+
"ProviderStatusReport",
|
|
176
|
+
"ReasoningConfig",
|
|
177
|
+
"SessionClientTool",
|
|
178
|
+
"SessionEvent",
|
|
179
|
+
"SessionEventsPage",
|
|
180
|
+
"SessionInfo",
|
|
181
|
+
"SessionListItem",
|
|
182
|
+
"SessionToolSurface",
|
|
183
|
+
"SessionUsage",
|
|
184
|
+
"SessionUsageFigures",
|
|
185
|
+
"SessionUsageRow",
|
|
186
|
+
"SessionsClient",
|
|
187
|
+
"SessionsPage",
|
|
188
|
+
"Skill",
|
|
189
|
+
"SkillPin",
|
|
190
|
+
"SkillVersion",
|
|
191
|
+
"SkillVersionPushed",
|
|
192
|
+
"SkillsClient",
|
|
193
|
+
"StatusEvent",
|
|
194
|
+
"TarsApiError",
|
|
195
|
+
"TarsClient",
|
|
196
|
+
"TarsSession",
|
|
197
|
+
"Tenant",
|
|
198
|
+
"TenantCounts",
|
|
199
|
+
"TenantDetail",
|
|
200
|
+
"TenantFirstKey",
|
|
201
|
+
"TenantStats",
|
|
202
|
+
"TextDeltaEvent",
|
|
203
|
+
"TextEndEvent",
|
|
204
|
+
"TextStartEvent",
|
|
205
|
+
"ToolCallEvent",
|
|
206
|
+
"ToolHandler",
|
|
207
|
+
"ToolResultEvent",
|
|
208
|
+
"TurnEndEvent",
|
|
209
|
+
"TurnStartEvent",
|
|
210
|
+
"TurnUsage",
|
|
211
|
+
"UnknownEvent",
|
|
212
|
+
"UsageBreakdownRow",
|
|
213
|
+
"UsageClient",
|
|
214
|
+
"UsageSummary",
|
|
215
|
+
"UsageTotals",
|
|
216
|
+
"UserMessageEvent",
|
|
217
|
+
"__version__",
|
|
218
|
+
"parse_event",
|
|
219
|
+
]
|
tars_sdk/_sse.py
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
"""Minimal SSE reader for the session streams.
|
|
2
|
+
|
|
3
|
+
TARS writes ``id: <seq>\\ndata: <json>\\n\\n`` per event (``backend/src/http/sse.ts``);
|
|
4
|
+
the seq is also inside the JSON, so ``id:`` is ignored. ``data:`` lines of one
|
|
5
|
+
frame are joined, a blank line ends the frame, EOF flushes a frame the server
|
|
6
|
+
closed without a blank line.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from __future__ import annotations
|
|
10
|
+
|
|
11
|
+
import json
|
|
12
|
+
from collections.abc import AsyncIterator
|
|
13
|
+
|
|
14
|
+
import httpx
|
|
15
|
+
|
|
16
|
+
from .events import SessionEvent, parse_event
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
async def read_events(response: httpx.Response) -> AsyncIterator[SessionEvent]:
|
|
20
|
+
data: list[str] = []
|
|
21
|
+
async for line in response.aiter_lines():
|
|
22
|
+
if line == "":
|
|
23
|
+
if data:
|
|
24
|
+
yield parse_event(json.loads("".join(data)))
|
|
25
|
+
data = []
|
|
26
|
+
continue
|
|
27
|
+
if line.startswith("data: "):
|
|
28
|
+
data.append(line[6:])
|
|
29
|
+
elif line.startswith("data:"):
|
|
30
|
+
data.append(line[5:])
|
|
31
|
+
# id:, event:, retry:, comments — not used by this stream.
|
|
32
|
+
if data:
|
|
33
|
+
yield parse_event(json.loads("".join(data)))
|
tars_sdk/_wire.py
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
"""Request-body helpers.
|
|
2
|
+
|
|
3
|
+
``UNSET`` lets a method tell "the caller did not pass this" from "the caller
|
|
4
|
+
passed ``None``": for a PATCH that is "leave it" versus "clear it". ``body()``
|
|
5
|
+
drops the SDK's own unset/None fields; the caller's data inside them (tool
|
|
6
|
+
outputs, input schemas, metadata) is passed through verbatim.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from __future__ import annotations
|
|
10
|
+
|
|
11
|
+
from typing import Any, Final
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class _Unset:
|
|
15
|
+
__slots__ = ()
|
|
16
|
+
|
|
17
|
+
def __repr__(self) -> str:
|
|
18
|
+
return "UNSET"
|
|
19
|
+
|
|
20
|
+
def __bool__(self) -> bool:
|
|
21
|
+
return False
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
UNSET: Final = _Unset()
|
|
25
|
+
"""Default for optional update fields: not sent. Pass ``None`` to clear a field."""
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def body(**fields: Any) -> dict[str, Any]:
|
|
29
|
+
"""The SDK's own top-level fields, minus the ones left ``None``/``UNSET``."""
|
|
30
|
+
return {k: v for k, v in fields.items() if v is not None and v is not UNSET}
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def patch(**fields: Any) -> dict[str, Any]:
|
|
34
|
+
"""Like :func:`body`, but a ``None`` is kept (sent as JSON ``null``); only ``UNSET`` is dropped."""
|
|
35
|
+
return {k: v for k, v in fields.items() if v is not UNSET}
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def iso(at: Any) -> str:
|
|
39
|
+
"""UTC ISO 8601 with milliseconds and ``Z``, the shape the API expects."""
|
|
40
|
+
from datetime import datetime, timezone
|
|
41
|
+
|
|
42
|
+
if isinstance(at, str):
|
|
43
|
+
return at
|
|
44
|
+
if not isinstance(at, datetime):
|
|
45
|
+
raise TypeError(f"expected a datetime or ISO string, got {type(at).__name__}")
|
|
46
|
+
if at.tzinfo is None:
|
|
47
|
+
at = at.replace(tzinfo=timezone.utc)
|
|
48
|
+
at = at.astimezone(timezone.utc)
|
|
49
|
+
return at.strftime("%Y-%m-%dT%H:%M:%S.") + f"{at.microsecond // 1000:03d}Z"
|