unique_toolkit 0.5.43__py3-none-any.whl → 0.5.45__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.
- unique_toolkit/app/verification.py +9 -8
- unique_toolkit/short_term_memory/schemas.py +49 -0
- unique_toolkit/short_term_memory/service.py +57 -0
- {unique_toolkit-0.5.43.dist-info → unique_toolkit-0.5.45.dist-info}/METADATA +6 -2
- {unique_toolkit-0.5.43.dist-info → unique_toolkit-0.5.45.dist-info}/RECORD +7 -5
- {unique_toolkit-0.5.43.dist-info → unique_toolkit-0.5.45.dist-info}/LICENSE +0 -0
- {unique_toolkit-0.5.43.dist-info → unique_toolkit-0.5.45.dist-info}/WHEEL +0 -0
@@ -1,4 +1,5 @@
|
|
1
1
|
import logging
|
2
|
+
from typing import Callable, TypeVar
|
2
3
|
|
3
4
|
import unique_sdk
|
4
5
|
|
@@ -11,12 +12,16 @@ class WebhookVerificationError(Exception):
|
|
11
12
|
pass
|
12
13
|
|
13
14
|
|
15
|
+
T = TypeVar("T")
|
16
|
+
|
17
|
+
|
14
18
|
def verify_signature_and_construct_event(
|
15
19
|
headers: dict[str, str],
|
16
20
|
payload: bytes,
|
17
21
|
endpoint_secret: str,
|
18
22
|
logger: logging.Logger = logging.getLogger(__name__),
|
19
|
-
|
23
|
+
event_constructor: Callable[..., T] = Event,
|
24
|
+
) -> T:
|
20
25
|
"""
|
21
26
|
Verify the signature of a webhook and construct an event object.
|
22
27
|
|
@@ -25,18 +30,14 @@ def verify_signature_and_construct_event(
|
|
25
30
|
payload (bytes): The raw payload of the webhook request.
|
26
31
|
endpoint_secret (str): The secret used to verify the webhook signature.
|
27
32
|
logger (logging.Logger): A logger instance for logging messages.
|
28
|
-
|
33
|
+
event_constructor (Callable[..., T]): A callable that constructs an event object.
|
29
34
|
Returns:
|
30
|
-
|
31
|
-
If successful, returns an Event object.
|
32
|
-
If unsuccessful, returns a tuple with an error response and HTTP status code.
|
35
|
+
T: The constructed event object.
|
33
36
|
|
34
37
|
Raises:
|
35
38
|
WebhookVerificationError: If there's an error during verification or event construction.
|
36
39
|
"""
|
37
40
|
|
38
|
-
# Only verify the event if there is an endpoint secret defined
|
39
|
-
# Otherwise use the basic event deserialized with json
|
40
41
|
sig_header = headers.get("X-Unique-Signature")
|
41
42
|
timestamp = headers.get("X-Unique-Created-At")
|
42
43
|
|
@@ -52,7 +53,7 @@ def verify_signature_and_construct_event(
|
|
52
53
|
endpoint_secret,
|
53
54
|
)
|
54
55
|
logger.info("✅ Webhook signature verification successful.")
|
55
|
-
return
|
56
|
+
return event_constructor(**event)
|
56
57
|
except unique_sdk.SignatureVerificationError as e:
|
57
58
|
logger.error("⚠️ Webhook signature verification failed. " + str(e))
|
58
59
|
raise WebhookVerificationError(f"Signature verification failed: {str(e)}")
|
@@ -0,0 +1,49 @@
|
|
1
|
+
import json
|
2
|
+
|
3
|
+
from humps import camelize
|
4
|
+
from pydantic import BaseModel, ConfigDict, Field, field_validator
|
5
|
+
|
6
|
+
model_config = ConfigDict(
|
7
|
+
alias_generator=camelize,
|
8
|
+
populate_by_name=True,
|
9
|
+
arbitrary_types_allowed=True,
|
10
|
+
)
|
11
|
+
|
12
|
+
|
13
|
+
class ShortTermMemory(BaseModel):
|
14
|
+
model_config = model_config
|
15
|
+
|
16
|
+
id: str
|
17
|
+
key: str = Field(alias="object")
|
18
|
+
chat_id: str | None
|
19
|
+
message_id: str | None
|
20
|
+
data: str | dict | int | float | bool | list | None
|
21
|
+
|
22
|
+
@field_validator("chat_id", "message_id", mode="before")
|
23
|
+
def validate_chat_id_or_message_id(cls, v, info):
|
24
|
+
field_name = info.field_name
|
25
|
+
data = info.data
|
26
|
+
|
27
|
+
# Get the other field's value
|
28
|
+
other_field = "message_id" if field_name == "chat_id" else "chat_id"
|
29
|
+
other_value = data.get(other_field)
|
30
|
+
|
31
|
+
# Check if both are None
|
32
|
+
if v is None and other_value is None:
|
33
|
+
camel_name = camelize(field_name)
|
34
|
+
raise ValueError(
|
35
|
+
f"Either {camel_name} or messageId must be provided"
|
36
|
+
if field_name == "chat_id"
|
37
|
+
else f"Either chatId or {camel_name} must be provided"
|
38
|
+
)
|
39
|
+
|
40
|
+
return v
|
41
|
+
|
42
|
+
@field_validator("data", mode="before")
|
43
|
+
def validate_data(cls, v):
|
44
|
+
if isinstance(v, str):
|
45
|
+
try:
|
46
|
+
return json.loads(v)
|
47
|
+
except json.JSONDecodeError:
|
48
|
+
return v
|
49
|
+
return v
|
@@ -0,0 +1,57 @@
|
|
1
|
+
import json
|
2
|
+
|
3
|
+
from unique_sdk.api_resources._short_term_memory import (
|
4
|
+
ShortTermMemory as ShortTermMemoryAPI,
|
5
|
+
)
|
6
|
+
|
7
|
+
from unique_toolkit.app import Event
|
8
|
+
|
9
|
+
from .schemas import ShortTermMemory
|
10
|
+
|
11
|
+
|
12
|
+
class ShortTermMemoryService:
|
13
|
+
def __init__(
|
14
|
+
self,
|
15
|
+
user_id: str,
|
16
|
+
company_id: str,
|
17
|
+
chat_id: str | None,
|
18
|
+
message_id: str | None = None,
|
19
|
+
):
|
20
|
+
assert chat_id or message_id, "Either chat_id or message_id must be provided"
|
21
|
+
self.user_id = user_id
|
22
|
+
self.company_id = company_id
|
23
|
+
self.chat_id = chat_id
|
24
|
+
self.message_id = message_id
|
25
|
+
|
26
|
+
@classmethod
|
27
|
+
def from_chat_event(cls, chat_event: Event) -> "ShortTermMemoryService":
|
28
|
+
return cls(
|
29
|
+
user_id=chat_event.user_id,
|
30
|
+
company_id=chat_event.company_id,
|
31
|
+
chat_id=chat_event.payload.chat_id,
|
32
|
+
message_id=chat_event.payload.user_message.id,
|
33
|
+
)
|
34
|
+
|
35
|
+
async def get(self, key: str) -> ShortTermMemory:
|
36
|
+
stm = await ShortTermMemoryAPI.find_latest_async(
|
37
|
+
user_id=self.user_id,
|
38
|
+
company_id=self.company_id,
|
39
|
+
memoryName=key,
|
40
|
+
chatId=self.chat_id,
|
41
|
+
messageId=self.message_id,
|
42
|
+
)
|
43
|
+
|
44
|
+
return ShortTermMemory(**stm)
|
45
|
+
|
46
|
+
async def set(self, key: str, value: str | dict):
|
47
|
+
if isinstance(value, dict):
|
48
|
+
value = json.dumps(value)
|
49
|
+
stm = await ShortTermMemoryAPI.create_async(
|
50
|
+
user_id=self.user_id,
|
51
|
+
company_id=self.company_id,
|
52
|
+
memoryName=key,
|
53
|
+
chatId=self.chat_id,
|
54
|
+
messageId=self.message_id,
|
55
|
+
data=value,
|
56
|
+
)
|
57
|
+
return ShortTermMemory(**stm)
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: unique_toolkit
|
3
|
-
Version: 0.5.
|
3
|
+
Version: 0.5.45
|
4
4
|
Summary:
|
5
5
|
License: Proprietary
|
6
6
|
Author: Martin Fadler
|
@@ -17,7 +17,7 @@ Requires-Dist: python-dotenv (>=1.0.1,<2.0.0)
|
|
17
17
|
Requires-Dist: regex (>=2024.5.15,<2025.0.0)
|
18
18
|
Requires-Dist: tiktoken (>=0.7.0,<0.8.0)
|
19
19
|
Requires-Dist: typing-extensions (>=4.9.0,<5.0.0)
|
20
|
-
Requires-Dist: unique-sdk (>=0.9.
|
20
|
+
Requires-Dist: unique-sdk (>=0.9.17,<0.10.0)
|
21
21
|
Description-Content-Type: text/markdown
|
22
22
|
|
23
23
|
# Unique Toolkit
|
@@ -100,7 +100,11 @@ All notable changes to this project will be documented in this file.
|
|
100
100
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
101
101
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
102
102
|
|
103
|
+
## [0.5.45] - 2025-01-03
|
104
|
+
- Added `ShortTermMemoryService` class to handle short term memory.
|
103
105
|
|
106
|
+
## [0.5.44] - 2024-12-18
|
107
|
+
- Add `event_constructor` to `verify_signature_and_construct_event` to allow for custom event construction.
|
104
108
|
|
105
109
|
## [0.5.43] - 2024-12-13
|
106
110
|
- Add `Prompt` class to handle templated prompts that can be formatted into LanguageModelSystemMessage and LanguageModelUserMessage.
|
@@ -9,7 +9,7 @@ unique_toolkit/app/init_sdk.py,sha256=Nv4Now4pMfM0AgRhbtatLpm_39rKxn0WmRLwmPhRl-
|
|
9
9
|
unique_toolkit/app/performance/async_tasks.py,sha256=H0l3OAcosLwNHZ8d2pd-Di4wHIXfclEvagi5kfqLFPA,1941
|
10
10
|
unique_toolkit/app/performance/async_wrapper.py,sha256=yVVcRDkcdyfjsxro-N29SBvi-7773wnfDplef6-y8xw,1077
|
11
11
|
unique_toolkit/app/schemas.py,sha256=6RY7Ex-B3pOnFILlitHEi9sqJvupbpdxlN9xt33qRsM,1571
|
12
|
-
unique_toolkit/app/verification.py,sha256=
|
12
|
+
unique_toolkit/app/verification.py,sha256=mffa6wm0i4hJbwzofePrkaia46xumMzECwQ0T3eKAx0,1929
|
13
13
|
unique_toolkit/chat/__init__.py,sha256=1prdTVfLOf6NgU-Aa1VIO-XiR6OYuRm51LaVRfKDCqc,267
|
14
14
|
unique_toolkit/chat/schemas.py,sha256=IHOnb3pWlRlSPoEUWBTl6LK8YeMdlg2iXi9ghyBeiLw,1495
|
15
15
|
unique_toolkit/chat/service.py,sha256=lFcwCKHRHVLkMIO1cBHwH_Py0uZ4mmvgkUwQuZkpsxI,21438
|
@@ -41,7 +41,9 @@ unique_toolkit/language_model/prompt.py,sha256=JSawaLjQg3VR-E2fK8engFyJnNdk21zaO
|
|
41
41
|
unique_toolkit/language_model/schemas.py,sha256=MBwEAFnnCYjSpbZDUYLrqkCc-0bsarsepSQEj1v6YEY,6991
|
42
42
|
unique_toolkit/language_model/service.py,sha256=brNCPRA0XxgqHi2rI5i2lyFCkUiw4MNMe1VaR3UgWmY,15500
|
43
43
|
unique_toolkit/language_model/utils.py,sha256=bPQ4l6_YO71w-zaIPanUUmtbXC1_hCvLK0tAFc3VCRc,1902
|
44
|
-
unique_toolkit
|
45
|
-
unique_toolkit
|
46
|
-
unique_toolkit-0.5.
|
47
|
-
unique_toolkit-0.5.
|
44
|
+
unique_toolkit/short_term_memory/schemas.py,sha256=OhfcXyF6ACdwIXW45sKzjtZX_gkcJs8FEZXcgQTNenw,1406
|
45
|
+
unique_toolkit/short_term_memory/service.py,sha256=Jd9P72-VvJy7hnqNrjmrmB5BHmsKuOpTiT0Jr-dBbsQ,1682
|
46
|
+
unique_toolkit-0.5.45.dist-info/LICENSE,sha256=GlN8wHNdh53xwOPg44URnwag6TEolCjoq3YD_KrWgss,193
|
47
|
+
unique_toolkit-0.5.45.dist-info/METADATA,sha256=hHpirT_B8QwGgqPLxXFkOC0UDBYRcHmmcDdhjLGXqKw,15248
|
48
|
+
unique_toolkit-0.5.45.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
|
49
|
+
unique_toolkit-0.5.45.dist-info/RECORD,,
|
File without changes
|
File without changes
|