trodo-python 1.0.0__py3-none-any.whl → 1.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.
- trodo/__init__.py +177 -134
- trodo/api/async_client.py +96 -96
- trodo/api/endpoints.py +21 -20
- trodo/api/http_client.py +90 -87
- trodo/auto/auto_event_manager.py +134 -134
- trodo/client.py +318 -195
- trodo/managers/group_manager.py +106 -106
- trodo/managers/people_manager.py +77 -77
- trodo/queue/batch_flusher.py +52 -52
- trodo/queue/event_queue.py +32 -32
- trodo/session/server_session.py +74 -74
- trodo/session/session_manager.py +74 -74
- trodo/types.py +154 -79
- trodo/user_context.py +224 -224
- trodo_python-1.2.0.dist-info/METADATA +358 -0
- trodo_python-1.2.0.dist-info/RECORD +23 -0
- trodo_python-1.0.0.dist-info/METADATA +0 -227
- trodo_python-1.0.0.dist-info/RECORD +0 -23
- {trodo_python-1.0.0.dist-info → trodo_python-1.2.0.dist-info}/WHEEL +0 -0
- {trodo_python-1.0.0.dist-info → trodo_python-1.2.0.dist-info}/top_level.txt +0 -0
trodo/session/server_session.py
CHANGED
|
@@ -1,74 +1,74 @@
|
|
|
1
|
-
"""Server session creation utilities."""
|
|
2
|
-
|
|
3
|
-
from __future__ import annotations
|
|
4
|
-
|
|
5
|
-
import time
|
|
6
|
-
import uuid
|
|
7
|
-
from datetime import datetime, timezone
|
|
8
|
-
from typing import Any, Dict, Optional
|
|
9
|
-
|
|
10
|
-
from ..types import ServerSession
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
def now_iso() -> str:
|
|
14
|
-
return datetime.now(timezone.utc).isoformat()
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
def create_server_session(
|
|
18
|
-
site_id: str,
|
|
19
|
-
distinct_id: str,
|
|
20
|
-
session_id: Optional[str] = None,
|
|
21
|
-
) -> ServerSession:
|
|
22
|
-
return ServerSession(
|
|
23
|
-
session_id=session_id or str(uuid.uuid4()),
|
|
24
|
-
site_id=site_id,
|
|
25
|
-
distinct_id=distinct_id,
|
|
26
|
-
start_time=now_iso(),
|
|
27
|
-
last_activity=time.time(),
|
|
28
|
-
confirmed=False,
|
|
29
|
-
)
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
def build_session_payload(session: ServerSession) -> Dict[str, Any]:
|
|
33
|
-
return {
|
|
34
|
-
"session_id": session.session_id,
|
|
35
|
-
"site_id": session.site_id,
|
|
36
|
-
"user_id": session.distinct_id,
|
|
37
|
-
"distinct_id": session.distinct_id,
|
|
38
|
-
"team_id": None,
|
|
39
|
-
"start_time": session.start_time,
|
|
40
|
-
"end_time": None,
|
|
41
|
-
"last_activity": int(session.last_activity * 1000),
|
|
42
|
-
"duration": 0,
|
|
43
|
-
"pages_viewed": 0,
|
|
44
|
-
"is_bounce": False,
|
|
45
|
-
"previous_session_id": None,
|
|
46
|
-
"time_since_last_session": None,
|
|
47
|
-
"entry_page": None,
|
|
48
|
-
"exit_page": None,
|
|
49
|
-
"referrer": "server",
|
|
50
|
-
"ip_address": None,
|
|
51
|
-
"city": None,
|
|
52
|
-
"region": None,
|
|
53
|
-
"country": None,
|
|
54
|
-
"browser_name": None,
|
|
55
|
-
"browser_version": None,
|
|
56
|
-
"device_type": "server",
|
|
57
|
-
"os": None,
|
|
58
|
-
"resolution": None,
|
|
59
|
-
"user_agent": None,
|
|
60
|
-
"language": None,
|
|
61
|
-
"wallet_address": None,
|
|
62
|
-
"wallet_type": None,
|
|
63
|
-
"chain_name": None,
|
|
64
|
-
"is_web3_user": False,
|
|
65
|
-
"wallet_connected": False,
|
|
66
|
-
"utm_source": None,
|
|
67
|
-
"utm_medium": None,
|
|
68
|
-
"utm_campaign": None,
|
|
69
|
-
"utm_term": None,
|
|
70
|
-
"utm_content": None,
|
|
71
|
-
"utm_id": None,
|
|
72
|
-
"visited_pages": [],
|
|
73
|
-
"active_time_ms": 0,
|
|
74
|
-
}
|
|
1
|
+
"""Server session creation utilities."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import time
|
|
6
|
+
import uuid
|
|
7
|
+
from datetime import datetime, timezone
|
|
8
|
+
from typing import Any, Dict, Optional
|
|
9
|
+
|
|
10
|
+
from ..types import ServerSession
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def now_iso() -> str:
|
|
14
|
+
return datetime.now(timezone.utc).isoformat()
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def create_server_session(
|
|
18
|
+
site_id: str,
|
|
19
|
+
distinct_id: str,
|
|
20
|
+
session_id: Optional[str] = None,
|
|
21
|
+
) -> ServerSession:
|
|
22
|
+
return ServerSession(
|
|
23
|
+
session_id=session_id or str(uuid.uuid4()),
|
|
24
|
+
site_id=site_id,
|
|
25
|
+
distinct_id=distinct_id,
|
|
26
|
+
start_time=now_iso(),
|
|
27
|
+
last_activity=time.time(),
|
|
28
|
+
confirmed=False,
|
|
29
|
+
)
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def build_session_payload(session: ServerSession) -> Dict[str, Any]:
|
|
33
|
+
return {
|
|
34
|
+
"session_id": session.session_id,
|
|
35
|
+
"site_id": session.site_id,
|
|
36
|
+
"user_id": session.distinct_id,
|
|
37
|
+
"distinct_id": session.distinct_id,
|
|
38
|
+
"team_id": None,
|
|
39
|
+
"start_time": session.start_time,
|
|
40
|
+
"end_time": None,
|
|
41
|
+
"last_activity": int(session.last_activity * 1000),
|
|
42
|
+
"duration": 0,
|
|
43
|
+
"pages_viewed": 0,
|
|
44
|
+
"is_bounce": False,
|
|
45
|
+
"previous_session_id": None,
|
|
46
|
+
"time_since_last_session": None,
|
|
47
|
+
"entry_page": None,
|
|
48
|
+
"exit_page": None,
|
|
49
|
+
"referrer": "server",
|
|
50
|
+
"ip_address": None,
|
|
51
|
+
"city": None,
|
|
52
|
+
"region": None,
|
|
53
|
+
"country": None,
|
|
54
|
+
"browser_name": None,
|
|
55
|
+
"browser_version": None,
|
|
56
|
+
"device_type": "server",
|
|
57
|
+
"os": None,
|
|
58
|
+
"resolution": None,
|
|
59
|
+
"user_agent": None,
|
|
60
|
+
"language": None,
|
|
61
|
+
"wallet_address": None,
|
|
62
|
+
"wallet_type": None,
|
|
63
|
+
"chain_name": None,
|
|
64
|
+
"is_web3_user": False,
|
|
65
|
+
"wallet_connected": False,
|
|
66
|
+
"utm_source": None,
|
|
67
|
+
"utm_medium": None,
|
|
68
|
+
"utm_campaign": None,
|
|
69
|
+
"utm_term": None,
|
|
70
|
+
"utm_content": None,
|
|
71
|
+
"utm_id": None,
|
|
72
|
+
"visited_pages": [],
|
|
73
|
+
"active_time_ms": 0,
|
|
74
|
+
}
|
trodo/session/session_manager.py
CHANGED
|
@@ -1,74 +1,74 @@
|
|
|
1
|
-
"""Thread-safe in-process session cache."""
|
|
2
|
-
|
|
3
|
-
from __future__ import annotations
|
|
4
|
-
|
|
5
|
-
import threading
|
|
6
|
-
from typing import Dict, Optional
|
|
7
|
-
|
|
8
|
-
from ..types import ServerSession
|
|
9
|
-
from .server_session import build_session_payload, create_server_session
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
class SessionManager:
|
|
13
|
-
def __init__(self) -> None:
|
|
14
|
-
self._sessions: Dict[str, ServerSession] = {}
|
|
15
|
-
self._lock = threading.Lock()
|
|
16
|
-
self._confirmation_locks: Dict[str, threading.Event] = {}
|
|
17
|
-
self._confirmation_started: Dict[str, bool] = {}
|
|
18
|
-
|
|
19
|
-
def get_or_create(
|
|
20
|
-
self,
|
|
21
|
-
distinct_id: str,
|
|
22
|
-
site_id: str,
|
|
23
|
-
session_id: Optional[str] = None,
|
|
24
|
-
) -> ServerSession:
|
|
25
|
-
with self._lock:
|
|
26
|
-
if distinct_id in self._sessions:
|
|
27
|
-
return self._sessions[distinct_id]
|
|
28
|
-
session = create_server_session(site_id, distinct_id, session_id)
|
|
29
|
-
self._sessions[distinct_id] = session
|
|
30
|
-
return session
|
|
31
|
-
|
|
32
|
-
def ensure_confirmed(self, session: ServerSession, http_client: object) -> None:
|
|
33
|
-
"""
|
|
34
|
-
Block until the session has been confirmed via POST /api/sdk/track.
|
|
35
|
-
Idempotent — concurrent callers share a single confirmation attempt.
|
|
36
|
-
"""
|
|
37
|
-
if session.confirmed:
|
|
38
|
-
return
|
|
39
|
-
|
|
40
|
-
key = session.distinct_id
|
|
41
|
-
|
|
42
|
-
with self._lock:
|
|
43
|
-
if session.confirmed:
|
|
44
|
-
return
|
|
45
|
-
# Check if confirmation already in-flight
|
|
46
|
-
if key not in self._confirmation_locks:
|
|
47
|
-
event = threading.Event()
|
|
48
|
-
self._confirmation_locks[key] = event
|
|
49
|
-
should_run = True
|
|
50
|
-
else:
|
|
51
|
-
event = self._confirmation_locks[key]
|
|
52
|
-
should_run = False
|
|
53
|
-
|
|
54
|
-
if should_run:
|
|
55
|
-
try:
|
|
56
|
-
payload = build_session_payload(session)
|
|
57
|
-
http_client.post_track(payload) # type: ignore[attr-defined]
|
|
58
|
-
except Exception:
|
|
59
|
-
pass # Confirmation failure is non-fatal
|
|
60
|
-
finally:
|
|
61
|
-
session.confirmed = True
|
|
62
|
-
with self._lock:
|
|
63
|
-
self._confirmation_locks.pop(key, None)
|
|
64
|
-
event.set()
|
|
65
|
-
else:
|
|
66
|
-
event.wait(timeout=10)
|
|
67
|
-
|
|
68
|
-
def invalidate(self, distinct_id: str) -> None:
|
|
69
|
-
with self._lock:
|
|
70
|
-
self._sessions.pop(distinct_id, None)
|
|
71
|
-
self._confirmation_locks.pop(distinct_id, None)
|
|
72
|
-
|
|
73
|
-
def get_global_session(self, site_id: str) -> ServerSession:
|
|
74
|
-
return self.get_or_create("server_global", site_id)
|
|
1
|
+
"""Thread-safe in-process session cache."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import threading
|
|
6
|
+
from typing import Dict, Optional
|
|
7
|
+
|
|
8
|
+
from ..types import ServerSession
|
|
9
|
+
from .server_session import build_session_payload, create_server_session
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class SessionManager:
|
|
13
|
+
def __init__(self) -> None:
|
|
14
|
+
self._sessions: Dict[str, ServerSession] = {}
|
|
15
|
+
self._lock = threading.Lock()
|
|
16
|
+
self._confirmation_locks: Dict[str, threading.Event] = {}
|
|
17
|
+
self._confirmation_started: Dict[str, bool] = {}
|
|
18
|
+
|
|
19
|
+
def get_or_create(
|
|
20
|
+
self,
|
|
21
|
+
distinct_id: str,
|
|
22
|
+
site_id: str,
|
|
23
|
+
session_id: Optional[str] = None,
|
|
24
|
+
) -> ServerSession:
|
|
25
|
+
with self._lock:
|
|
26
|
+
if distinct_id in self._sessions:
|
|
27
|
+
return self._sessions[distinct_id]
|
|
28
|
+
session = create_server_session(site_id, distinct_id, session_id)
|
|
29
|
+
self._sessions[distinct_id] = session
|
|
30
|
+
return session
|
|
31
|
+
|
|
32
|
+
def ensure_confirmed(self, session: ServerSession, http_client: object) -> None:
|
|
33
|
+
"""
|
|
34
|
+
Block until the session has been confirmed via POST /api/sdk/track.
|
|
35
|
+
Idempotent — concurrent callers share a single confirmation attempt.
|
|
36
|
+
"""
|
|
37
|
+
if session.confirmed:
|
|
38
|
+
return
|
|
39
|
+
|
|
40
|
+
key = session.distinct_id
|
|
41
|
+
|
|
42
|
+
with self._lock:
|
|
43
|
+
if session.confirmed:
|
|
44
|
+
return
|
|
45
|
+
# Check if confirmation already in-flight
|
|
46
|
+
if key not in self._confirmation_locks:
|
|
47
|
+
event = threading.Event()
|
|
48
|
+
self._confirmation_locks[key] = event
|
|
49
|
+
should_run = True
|
|
50
|
+
else:
|
|
51
|
+
event = self._confirmation_locks[key]
|
|
52
|
+
should_run = False
|
|
53
|
+
|
|
54
|
+
if should_run:
|
|
55
|
+
try:
|
|
56
|
+
payload = build_session_payload(session)
|
|
57
|
+
http_client.post_track(payload) # type: ignore[attr-defined]
|
|
58
|
+
except Exception:
|
|
59
|
+
pass # Confirmation failure is non-fatal
|
|
60
|
+
finally:
|
|
61
|
+
session.confirmed = True
|
|
62
|
+
with self._lock:
|
|
63
|
+
self._confirmation_locks.pop(key, None)
|
|
64
|
+
event.set()
|
|
65
|
+
else:
|
|
66
|
+
event.wait(timeout=10)
|
|
67
|
+
|
|
68
|
+
def invalidate(self, distinct_id: str) -> None:
|
|
69
|
+
with self._lock:
|
|
70
|
+
self._sessions.pop(distinct_id, None)
|
|
71
|
+
self._confirmation_locks.pop(distinct_id, None)
|
|
72
|
+
|
|
73
|
+
def get_global_session(self, site_id: str) -> ServerSession:
|
|
74
|
+
return self.get_or_create("server_global", site_id)
|
trodo/types.py
CHANGED
|
@@ -1,79 +1,154 @@
|
|
|
1
|
-
"""Type definitions for the Trodo Python SDK."""
|
|
2
|
-
|
|
3
|
-
from __future__ import annotations
|
|
4
|
-
|
|
5
|
-
from dataclasses import dataclass, field
|
|
6
|
-
from typing import Any, Dict, List, Optional, Union
|
|
7
|
-
|
|
8
|
-
# ----------------------------------------------------------------------------
|
|
9
|
-
# Configuration
|
|
10
|
-
# ----------------------------------------------------------------------------
|
|
11
|
-
|
|
12
|
-
@dataclass
|
|
13
|
-
class TrodoConfig:
|
|
14
|
-
site_id: str
|
|
15
|
-
api_base: str = "https://sdkapi.trodo.ai"
|
|
16
|
-
timeout: int = 10
|
|
17
|
-
retries: int = 2
|
|
18
|
-
batch_enabled: bool = False
|
|
19
|
-
batch_size: int = 50
|
|
20
|
-
batch_flush_interval: float = 5.0
|
|
21
|
-
auto_events: bool = False
|
|
22
|
-
on_error: Optional[Any] = None # Callable[[Exception], None]
|
|
23
|
-
debug: bool = False
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
# ----------------------------------------------------------------------------
|
|
27
|
-
# Session
|
|
28
|
-
# ----------------------------------------------------------------------------
|
|
29
|
-
|
|
30
|
-
@dataclass
|
|
31
|
-
class ServerSession:
|
|
32
|
-
session_id: str
|
|
33
|
-
site_id: str
|
|
34
|
-
distinct_id: str
|
|
35
|
-
start_time: str # ISO 8601
|
|
36
|
-
last_activity: float # epoch seconds
|
|
37
|
-
confirmed: bool = False
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
# ----------------------------------------------------------------------------
|
|
41
|
-
# Events
|
|
42
|
-
# ----------------------------------------------------------------------------
|
|
43
|
-
|
|
44
|
-
@dataclass
|
|
45
|
-
class EventPayload:
|
|
46
|
-
event_type: str # 'custom' | 'auto'
|
|
47
|
-
event_name: str
|
|
48
|
-
event_category: str
|
|
49
|
-
session_id: str
|
|
50
|
-
user_id: str
|
|
51
|
-
custom_properties: Dict[str, Any] = field(default_factory=dict)
|
|
52
|
-
page_data: None = None
|
|
53
|
-
auto_event_data: Optional[Dict[str, Any]] = None
|
|
54
|
-
element_data: None = None
|
|
55
|
-
override_data: None = None
|
|
56
|
-
|
|
57
|
-
def to_dict(self) -> Dict[str, Any]:
|
|
58
|
-
return {
|
|
59
|
-
"event_type": self.event_type,
|
|
60
|
-
"event_name": self.event_name,
|
|
61
|
-
"event_category": self.event_category,
|
|
62
|
-
"session_id": self.session_id,
|
|
63
|
-
"user_id": self.user_id,
|
|
64
|
-
"custom_properties": self.custom_properties,
|
|
65
|
-
"page_data": self.page_data,
|
|
66
|
-
"auto_event_data": self.auto_event_data,
|
|
67
|
-
"element_data": self.element_data,
|
|
68
|
-
"override_data": self.override_data,
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
# ----------------------------------------------------------------------------
|
|
73
|
-
# Results
|
|
74
|
-
# ----------------------------------------------------------------------------
|
|
75
|
-
|
|
76
|
-
ApiResult = Dict[str, Any]
|
|
77
|
-
IdentifyResult = Dict[str, Any]
|
|
78
|
-
WalletAddressResult = Dict[str, Any]
|
|
79
|
-
ResetResult = Dict[str, Any]
|
|
1
|
+
"""Type definitions for the Trodo Python SDK."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from dataclasses import dataclass, field
|
|
6
|
+
from typing import Any, Dict, List, Optional, Union
|
|
7
|
+
|
|
8
|
+
# ----------------------------------------------------------------------------
|
|
9
|
+
# Configuration
|
|
10
|
+
# ----------------------------------------------------------------------------
|
|
11
|
+
|
|
12
|
+
@dataclass
|
|
13
|
+
class TrodoConfig:
|
|
14
|
+
site_id: str
|
|
15
|
+
api_base: str = "https://sdkapi.trodo.ai"
|
|
16
|
+
timeout: int = 10
|
|
17
|
+
retries: int = 2
|
|
18
|
+
batch_enabled: bool = False
|
|
19
|
+
batch_size: int = 50
|
|
20
|
+
batch_flush_interval: float = 5.0
|
|
21
|
+
auto_events: bool = False
|
|
22
|
+
on_error: Optional[Any] = None # Callable[[Exception], None]
|
|
23
|
+
debug: bool = False
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
# ----------------------------------------------------------------------------
|
|
27
|
+
# Session
|
|
28
|
+
# ----------------------------------------------------------------------------
|
|
29
|
+
|
|
30
|
+
@dataclass
|
|
31
|
+
class ServerSession:
|
|
32
|
+
session_id: str
|
|
33
|
+
site_id: str
|
|
34
|
+
distinct_id: str
|
|
35
|
+
start_time: str # ISO 8601
|
|
36
|
+
last_activity: float # epoch seconds
|
|
37
|
+
confirmed: bool = False
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
# ----------------------------------------------------------------------------
|
|
41
|
+
# Events
|
|
42
|
+
# ----------------------------------------------------------------------------
|
|
43
|
+
|
|
44
|
+
@dataclass
|
|
45
|
+
class EventPayload:
|
|
46
|
+
event_type: str # 'custom' | 'auto'
|
|
47
|
+
event_name: str
|
|
48
|
+
event_category: str
|
|
49
|
+
session_id: str
|
|
50
|
+
user_id: str
|
|
51
|
+
custom_properties: Dict[str, Any] = field(default_factory=dict)
|
|
52
|
+
page_data: None = None
|
|
53
|
+
auto_event_data: Optional[Dict[str, Any]] = None
|
|
54
|
+
element_data: None = None
|
|
55
|
+
override_data: None = None
|
|
56
|
+
|
|
57
|
+
def to_dict(self) -> Dict[str, Any]:
|
|
58
|
+
return {
|
|
59
|
+
"event_type": self.event_type,
|
|
60
|
+
"event_name": self.event_name,
|
|
61
|
+
"event_category": self.event_category,
|
|
62
|
+
"session_id": self.session_id,
|
|
63
|
+
"user_id": self.user_id,
|
|
64
|
+
"custom_properties": self.custom_properties,
|
|
65
|
+
"page_data": self.page_data,
|
|
66
|
+
"auto_event_data": self.auto_event_data,
|
|
67
|
+
"element_data": self.element_data,
|
|
68
|
+
"override_data": self.override_data,
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
# ----------------------------------------------------------------------------
|
|
73
|
+
# Results
|
|
74
|
+
# ----------------------------------------------------------------------------
|
|
75
|
+
|
|
76
|
+
ApiResult = Dict[str, Any]
|
|
77
|
+
IdentifyResult = Dict[str, Any]
|
|
78
|
+
WalletAddressResult = Dict[str, Any]
|
|
79
|
+
ResetResult = Dict[str, Any]
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
# ----------------------------------------------------------------------------
|
|
83
|
+
# Agent Analytics
|
|
84
|
+
# ----------------------------------------------------------------------------
|
|
85
|
+
|
|
86
|
+
@dataclass
|
|
87
|
+
class AgentCallProps:
|
|
88
|
+
agent_id: str
|
|
89
|
+
conversation_id: str
|
|
90
|
+
message_id: str
|
|
91
|
+
distinct_id: Optional[str] = None
|
|
92
|
+
prompt: Optional[str] = None
|
|
93
|
+
model: Optional[str] = None
|
|
94
|
+
temperature: Optional[float] = None
|
|
95
|
+
system_prompt_version: Optional[str] = None
|
|
96
|
+
provider: Optional[str] = None
|
|
97
|
+
timestamp: Optional[str] = None
|
|
98
|
+
properties: Dict[str, Any] = field(default_factory=dict)
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
@dataclass
|
|
102
|
+
class ToolUseProps:
|
|
103
|
+
agent_id: str
|
|
104
|
+
conversation_id: str
|
|
105
|
+
message_id: str
|
|
106
|
+
tool_name: str
|
|
107
|
+
distinct_id: Optional[str] = None
|
|
108
|
+
input: Optional[Any] = None
|
|
109
|
+
output: Optional[Any] = None
|
|
110
|
+
latency_ms: Optional[int] = None
|
|
111
|
+
status: Optional[str] = None # 'success' | 'failure'
|
|
112
|
+
timestamp: Optional[str] = None
|
|
113
|
+
properties: Dict[str, Any] = field(default_factory=dict)
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
@dataclass
|
|
117
|
+
class AgentResponseProps:
|
|
118
|
+
agent_id: str
|
|
119
|
+
conversation_id: str
|
|
120
|
+
message_id: str
|
|
121
|
+
distinct_id: Optional[str] = None
|
|
122
|
+
output: Optional[str] = None
|
|
123
|
+
model: Optional[str] = None
|
|
124
|
+
completion_tokens: Optional[int] = None
|
|
125
|
+
prompt_tokens: Optional[int] = None
|
|
126
|
+
total_tokens: Optional[int] = None
|
|
127
|
+
finish_reason: Optional[str] = None
|
|
128
|
+
timestamp: Optional[str] = None
|
|
129
|
+
properties: Dict[str, Any] = field(default_factory=dict)
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
@dataclass
|
|
133
|
+
class AgentErrorProps:
|
|
134
|
+
agent_id: str
|
|
135
|
+
conversation_id: str
|
|
136
|
+
message_id: str
|
|
137
|
+
distinct_id: Optional[str] = None
|
|
138
|
+
error_type: Optional[str] = None
|
|
139
|
+
error_message: Optional[str] = None
|
|
140
|
+
failed_tool: Optional[str] = None
|
|
141
|
+
traceback: Optional[str] = None
|
|
142
|
+
timestamp: Optional[str] = None
|
|
143
|
+
properties: Dict[str, Any] = field(default_factory=dict)
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
@dataclass
|
|
147
|
+
class FeedbackProps:
|
|
148
|
+
agent_id: str
|
|
149
|
+
conversation_id: str
|
|
150
|
+
message_id: str
|
|
151
|
+
feedback: str # 'positive' | 'negative' | 'unreact'
|
|
152
|
+
distinct_id: Optional[str] = None
|
|
153
|
+
timestamp: Optional[str] = None
|
|
154
|
+
properties: Dict[str, Any] = field(default_factory=dict)
|