hyperpocket 0.0.3__py3-none-any.whl → 0.1.8__py3-none-any.whl
Sign up to get free protection for your applications and to get access to all the features.
- hyperpocket/auth/README.md +3 -3
- hyperpocket/auth/__init__.py +0 -8
- hyperpocket/auth/gumloop/context.py +13 -0
- hyperpocket/auth/gumloop/token_context.py +15 -0
- hyperpocket/auth/gumloop/token_handler.py +66 -0
- hyperpocket/auth/gumloop/token_schema.py +8 -0
- hyperpocket/auth/linear/token_context.py +1 -1
- hyperpocket/auth/notion/README.md +28 -0
- hyperpocket/auth/notion/context.py +15 -0
- hyperpocket/auth/notion/token_context.py +14 -0
- hyperpocket/auth/notion/token_handler.py +65 -0
- hyperpocket/auth/notion/token_schema.py +10 -0
- hyperpocket/auth/provider.py +8 -5
- hyperpocket/auth/reddit/context.py +15 -0
- hyperpocket/auth/reddit/oauth2_context.py +32 -0
- hyperpocket/auth/reddit/oauth2_handler.py +151 -0
- hyperpocket/auth/reddit/oauth2_schema.py +18 -0
- hyperpocket/auth/slack/token_context.py +1 -1
- hyperpocket/builtin.py +63 -0
- hyperpocket/cli/__main__.py +12 -0
- hyperpocket/cli/auth.py +83 -0
- hyperpocket/cli/codegen/auth/__init__.py +13 -0
- hyperpocket/cli/codegen/auth/auth_context_template.py +16 -0
- hyperpocket/cli/codegen/auth/auth_token_context_template.py +16 -0
- hyperpocket/cli/codegen/auth/auth_token_handler_template.py +69 -0
- hyperpocket/cli/codegen/auth/auth_token_schema_template.py +12 -0
- hyperpocket/cli/codegen/auth/server_auth_template.py +18 -0
- hyperpocket/cli/eject.py +19 -0
- hyperpocket/cli/sync.py +5 -5
- hyperpocket/config/settings.py +2 -4
- hyperpocket/futures/futurestore.py +0 -1
- hyperpocket/pocket_auth.py +25 -5
- hyperpocket/pocket_core.py +262 -0
- hyperpocket/pocket_main.py +124 -173
- hyperpocket/prompts.py +6 -8
- hyperpocket/repository/__init__.py +2 -2
- hyperpocket/repository/lock.py +19 -0
- hyperpocket/repository/lockfile.py +19 -13
- hyperpocket/repository/repository.py +26 -1
- hyperpocket/server/auth/__init__.py +0 -6
- hyperpocket/server/auth/gumloop.py +16 -0
- hyperpocket/server/auth/notion.py +19 -0
- hyperpocket/server/auth/reddit.py +16 -0
- hyperpocket/server/server.py +52 -16
- hyperpocket/server/tool/dto/script.py +15 -2
- hyperpocket/server/tool/wasm.py +20 -8
- hyperpocket/session/README.md +2 -2
- hyperpocket/session/in_memory.py +18 -5
- hyperpocket/session/interface.py +14 -0
- hyperpocket/session/redis.py +29 -5
- hyperpocket/tool/README.md +16 -12
- hyperpocket/tool/__init__.py +4 -3
- hyperpocket/tool/function/README.md +39 -10
- hyperpocket/tool/function/__init__.py +2 -0
- hyperpocket/tool/function/annotation.py +2 -1
- hyperpocket/tool/function/tool.py +98 -13
- hyperpocket/tool/tests/test_function_tool.py +55 -0
- hyperpocket/tool/tests/test_wasm_tool.py +73 -0
- hyperpocket/tool/tool.py +65 -2
- hyperpocket/tool/wasm/README.md +27 -5
- hyperpocket/tool/wasm/script.py +40 -1
- hyperpocket/tool/wasm/templates/python.py +32 -14
- hyperpocket/tool/wasm/tool.py +21 -18
- hyperpocket/tool_like.py +5 -0
- hyperpocket/util/__init__.py +1 -1
- hyperpocket/util/extract_func_param_desc_from_docstring.py +4 -4
- hyperpocket/util/function_to_model.py +5 -2
- hyperpocket/util/json_schema_to_model.py +45 -26
- {hyperpocket-0.0.3.dist-info → hyperpocket-0.1.8.dist-info}/METADATA +101 -72
- hyperpocket-0.1.8.dist-info/RECORD +139 -0
- {hyperpocket-0.0.3.dist-info → hyperpocket-0.1.8.dist-info}/WHEEL +1 -1
- hyperpocket-0.1.8.dist-info/entry_points.txt +2 -0
- hyperpocket/auth/README.KR.md +0 -309
- hyperpocket/auth/slack/tests/test_oauth2_handler.py +0 -32
- hyperpocket/auth/slack/tests/test_token_handler.py +0 -23
- hyperpocket/auth/tests/test_google_oauth2_handler.py +0 -147
- hyperpocket/auth/tests/test_slack_oauth2_handler.py +0 -147
- hyperpocket/auth/tests/test_slack_token_handler.py +0 -66
- hyperpocket/external/__init__.py +0 -7
- hyperpocket/external/github_client.py +0 -19
- hyperpocket/session/README.KR.md +0 -62
- hyperpocket/session/tests/test_in_memory.py +0 -145
- hyperpocket/session/tests/test_redis.py +0 -151
- hyperpocket/tests/test_pocket.py +0 -116
- hyperpocket/tests/test_pocket_auth.py +0 -982
- hyperpocket/tool/README.KR.md +0 -68
- hyperpocket/tool/builtins/__init__.py +0 -0
- hyperpocket/tool/builtins/example/__init__.py +0 -0
- hyperpocket/tool/builtins/example/add_tool.py +0 -18
- hyperpocket/tool/function/README.KR.md +0 -159
- hyperpocket/tool/wasm/README.KR.md +0 -144
- hyperpocket-0.0.3.dist-info/RECORD +0 -130
- hyperpocket-0.0.3.dist-info/entry_points.txt +0 -3
- /hyperpocket/auth/{slack/tests → gumloop}/__init__.py +0 -0
- /hyperpocket/auth/{tests → notion}/__init__.py +0 -0
- /hyperpocket/{session/tests → auth/reddit}/__init__.py +0 -0
- /hyperpocket/{tests → cli/codegen}/__init__.py +0 -0
@@ -1,66 +0,0 @@
|
|
1
|
-
from unittest.async_case import IsolatedAsyncioTestCase
|
2
|
-
from urllib.parse import urlparse, parse_qs
|
3
|
-
|
4
|
-
from hyperpocket.auth import SlackTokenAuthContext
|
5
|
-
from hyperpocket.auth.slack.token_handler import SlackTokenAuthHandler
|
6
|
-
from hyperpocket.auth.slack.token_schema import SlackTokenRequest
|
7
|
-
from hyperpocket.futures import FutureStore
|
8
|
-
|
9
|
-
|
10
|
-
class TestSlackTokenAuthHandler(IsolatedAsyncioTestCase):
|
11
|
-
|
12
|
-
async def asyncSetUp(self):
|
13
|
-
self.handler: SlackTokenAuthHandler = SlackTokenAuthHandler()
|
14
|
-
self.auth_req = SlackTokenRequest()
|
15
|
-
|
16
|
-
async def test_make_auth_url(self):
|
17
|
-
auth_url = self.handler._make_auth_url(
|
18
|
-
req=self.auth_req,
|
19
|
-
redirect_uri="http://test-redirect-uri.com",
|
20
|
-
state="test-future-id"
|
21
|
-
)
|
22
|
-
parsed = urlparse(auth_url)
|
23
|
-
query_params = parse_qs(parsed.query)
|
24
|
-
base_url = f"{parsed.scheme}://{parsed.netloc}{parsed.path}"
|
25
|
-
|
26
|
-
# then
|
27
|
-
self.assertEqual(base_url, self.handler._TOKEN_URL)
|
28
|
-
self.assertEqual(query_params["state"][0], "test-future-id")
|
29
|
-
self.assertEqual(query_params["redirect_uri"][0], "http://test-redirect-uri.com")
|
30
|
-
|
31
|
-
async def test_prepare(self):
|
32
|
-
# when
|
33
|
-
prepare: str = self.handler.prepare(
|
34
|
-
auth_req=self.auth_req,
|
35
|
-
thread_id="test-prepare-thread-id",
|
36
|
-
profile="test-prepare-profile",
|
37
|
-
future_uid="test-prepare-future-uid",
|
38
|
-
)
|
39
|
-
auth_url = prepare.removeprefix("User needs to authenticate using the following URL:").strip()
|
40
|
-
future_data = FutureStore.get_future( uid="test-prepare-future-uid")
|
41
|
-
|
42
|
-
# then
|
43
|
-
self.assertTrue(auth_url.startswith(self.handler._TOKEN_URL))
|
44
|
-
self.assertIsNotNone(future_data)
|
45
|
-
self.assertEqual(future_data.data["thread_id"], "test-prepare-thread-id")
|
46
|
-
self.assertEqual(future_data.data["profile"], "test-prepare-profile")
|
47
|
-
self.assertFalse(future_data.future.done())
|
48
|
-
|
49
|
-
async def test_authenticate(self):
|
50
|
-
self.handler.prepare(
|
51
|
-
auth_req=self.auth_req,
|
52
|
-
thread_id="test-thread-id",
|
53
|
-
profile="test-profile",
|
54
|
-
future_uid="test-future-uid"
|
55
|
-
)
|
56
|
-
future_data = FutureStore.get_future( uid="test-future-uid")
|
57
|
-
future_data.future.set_result("test-token")
|
58
|
-
|
59
|
-
response: SlackTokenAuthContext = await self.handler.authenticate(
|
60
|
-
auth_req=self.auth_req,
|
61
|
-
future_uid="test-future-uid"
|
62
|
-
)
|
63
|
-
|
64
|
-
self.assertIsInstance(response, SlackTokenAuthContext)
|
65
|
-
self.assertEqual(response.access_token, "test-token")
|
66
|
-
self.assertIsNone(response.expires_at)
|
hyperpocket/external/__init__.py
DELETED
@@ -1,19 +0,0 @@
|
|
1
|
-
from github import Auth, Github, GithubIntegration
|
2
|
-
|
3
|
-
from hyperpocket.config import config
|
4
|
-
|
5
|
-
_github = None
|
6
|
-
|
7
|
-
|
8
|
-
def github_instance() -> Github:
|
9
|
-
global _github
|
10
|
-
if _github is None:
|
11
|
-
if config.git.github.github_token:
|
12
|
-
_github = Github(auth=Auth.Token(config.git.github.github_token))
|
13
|
-
elif config.git.github.app_id:
|
14
|
-
auth = Auth.AppAuth(config.git.github.app_id, config.git.github.app_private_key)
|
15
|
-
gi = GithubIntegration(auth=auth)
|
16
|
-
_github = gi.get_github_for_installation(config.git.github.app_installation_id)
|
17
|
-
else:
|
18
|
-
_github = Github()
|
19
|
-
return _github
|
hyperpocket/session/README.KR.md
DELETED
@@ -1,62 +0,0 @@
|
|
1
|
-
# Session Storage
|
2
|
-
|
3
|
-
유저의 authentication(auth) session을 저장하기 위한 storage
|
4
|
-
|
5
|
-
## Current supported session storage
|
6
|
-
|
7
|
-
- [x] InMemory
|
8
|
-
- [x] Redis
|
9
|
-
- [ ] Postgres
|
10
|
-
- [ ] Mysql
|
11
|
-
- [ ] Mongodb
|
12
|
-
|
13
|
-
## SessionKey
|
14
|
-
|
15
|
-
세션 키는 유저의 인증 정보를 식별하기 위한 유니크 키이다.
|
16
|
-
|
17
|
-
일반적으로 세션 키는 다음 세 가지 요소로 식별될 수 있다.
|
18
|
-
|
19
|
-
- auth provider
|
20
|
-
- profile
|
21
|
-
- thread_id
|
22
|
-
|
23
|
-
하나의 auth provider에서는 하나의 session만 가질 수 있다.
|
24
|
-
|
25
|
-
- 예를 들어 slack token으로 이미 인증한 사용자가 oauth로 인증하려 하면 이전 세션은 사라지게 된다.
|
26
|
-
|
27
|
-
- profile은 pocket에서 지원하는 개념으로 하나의 thread_id에 여러 profile이 존재할 수 있다.
|
28
|
-
|
29
|
-
- profile을 이용해 한 사용자는 여러 persona를 갖고 작업을 수행하도록 할 수 있다.
|
30
|
-
- e.g., A group의 슬랙 메세지를 읽어 B group으로 요약해서 전달
|
31
|
-
|
32
|
-
## BaseSessionValue
|
33
|
-
|
34
|
-
```python
|
35
|
-
class BaseSessionValue(BaseModel):
|
36
|
-
auth_provider_name: str
|
37
|
-
auth_context: Optional[AuthContext] = None
|
38
|
-
scoped: bool
|
39
|
-
auth_scopes: Optional[Set[str]] = None
|
40
|
-
auth_resolve_uid: Optional[str] = None
|
41
|
-
```
|
42
|
-
|
43
|
-
기본적으로 Session에는 다음 정보들을 갖고 있다.
|
44
|
-
|
45
|
-
- auth_provider_name : 현재 세션을 인증한 auth provider name
|
46
|
-
- auth_context : 실제 세션 내용이 들어있는 auth context
|
47
|
-
- scoped : 현재 세션이 scoped session인지 여부
|
48
|
-
- auth_scopes : 현재 세션의 auth scopes. scoped session의 경우에만 존재
|
49
|
-
- auth_resolve_uid : 유저가 auth 인증을 완료했는지를 비동기적으로 확인하기 위한 uid
|
50
|
-
|
51
|
-
## SessionStorageInterface
|
52
|
-
|
53
|
-
TBU
|
54
|
-
|
55
|
-
## How To Implement
|
56
|
-
|
57
|
-
1. `pocket/config/session.py` 내에 새로운 SessionType Enum 추가
|
58
|
-
2. `pocket/config/session.py` 내에 새로운 SessionConfig 추가
|
59
|
-
3. SessionStorageInterface 구현
|
60
|
-
- session storage가 초기화될 때 위에서 정의한 SessionConfig를 입력으로 받아야 한다.
|
61
|
-
|
62
|
-
|
@@ -1,145 +0,0 @@
|
|
1
|
-
import unittest
|
2
|
-
|
3
|
-
from hyperpocket.auth import AuthProvider, SlackTokenAuthContext
|
4
|
-
from hyperpocket.config.session import SessionConfigInMemory
|
5
|
-
from hyperpocket.session.in_memory import InMemorySessionStorage, InMemorySessionValue
|
6
|
-
|
7
|
-
|
8
|
-
class TestInMemorySessionStorage(unittest.TestCase):
|
9
|
-
storage: InMemorySessionStorage
|
10
|
-
context: SlackTokenAuthContext
|
11
|
-
|
12
|
-
def setUp(self):
|
13
|
-
self.storage = InMemorySessionStorage(SessionConfigInMemory())
|
14
|
-
self.auth_context = SlackTokenAuthContext(
|
15
|
-
access_token="test",
|
16
|
-
description="test-description",
|
17
|
-
expires_at=None,
|
18
|
-
detail=None,
|
19
|
-
)
|
20
|
-
|
21
|
-
def tearDown(self):
|
22
|
-
del self.storage
|
23
|
-
del self.auth_context
|
24
|
-
|
25
|
-
def test_make_session_key(self):
|
26
|
-
key = self.storage._make_session_key(
|
27
|
-
auth_provider=AuthProvider.SLACK,
|
28
|
-
thread_id="default_thread_id",
|
29
|
-
profile="default_profile"
|
30
|
-
)
|
31
|
-
|
32
|
-
self.assertEqual(key, "SLACK__default_thread_id__default_profile")
|
33
|
-
|
34
|
-
def test_make_session(self):
|
35
|
-
session = self.storage._make_session(
|
36
|
-
auth_provider_name=AuthProvider.SLACK.name,
|
37
|
-
auth_scopes=["scope1", "scope2"],
|
38
|
-
auth_context=self.auth_context,
|
39
|
-
auth_resolve_uid="test-resolve-uid",
|
40
|
-
is_auth_scope_universal=True
|
41
|
-
)
|
42
|
-
|
43
|
-
# then
|
44
|
-
self.assertIsInstance(session, InMemorySessionValue)
|
45
|
-
self.assertEqual(session.auth_provider_name, AuthProvider.SLACK.name)
|
46
|
-
self.assertEqual(session.auth_context.access_token, "test")
|
47
|
-
self.assertEqual(session.auth_context.description, "test-description")
|
48
|
-
|
49
|
-
def test_set(self):
|
50
|
-
session = self.storage.set(
|
51
|
-
auth_provider=AuthProvider.SLACK,
|
52
|
-
thread_id="default_thread_id",
|
53
|
-
profile="default_profile",
|
54
|
-
auth_scopes=["scope1", "scope2"],
|
55
|
-
auth_resolve_uid="test-resolve-uid",
|
56
|
-
auth_context=self.auth_context,
|
57
|
-
is_auth_scope_universal=True
|
58
|
-
)
|
59
|
-
|
60
|
-
self.assertIsInstance(session, InMemorySessionValue)
|
61
|
-
self.assertEqual(session.auth_provider_name, AuthProvider.SLACK.name)
|
62
|
-
self.assertEqual(session.auth_context.access_token, self.auth_context.access_token)
|
63
|
-
self.assertEqual(session.auth_context.description, self.auth_context.description)
|
64
|
-
|
65
|
-
def test_get_existing_data(self):
|
66
|
-
# given
|
67
|
-
self.storage.set(
|
68
|
-
auth_provider=AuthProvider.SLACK,
|
69
|
-
thread_id="default_thread_id",
|
70
|
-
profile="default_profile",
|
71
|
-
auth_scopes=["scope1", "scope2"],
|
72
|
-
auth_resolve_uid="test-resolve-uid",
|
73
|
-
auth_context=self.auth_context,
|
74
|
-
is_auth_scope_universal=True
|
75
|
-
)
|
76
|
-
|
77
|
-
# when
|
78
|
-
session = self.storage.get(
|
79
|
-
auth_provider=AuthProvider.SLACK,
|
80
|
-
thread_id="default_thread_id",
|
81
|
-
profile="default_profile",
|
82
|
-
)
|
83
|
-
|
84
|
-
# then
|
85
|
-
self.assertIsInstance(session, InMemorySessionValue)
|
86
|
-
self.assertEqual(session.auth_provider_name, AuthProvider.SLACK.name)
|
87
|
-
self.assertEqual(session.auth_context.access_token, "test")
|
88
|
-
self.assertEqual(session.auth_context.description, "test-description")
|
89
|
-
|
90
|
-
def test_get_not_existing_data(self):
|
91
|
-
# when
|
92
|
-
session = self.storage.get(
|
93
|
-
auth_provider=AuthProvider.SLACK,
|
94
|
-
thread_id="default_thread_id",
|
95
|
-
profile="default_profile",
|
96
|
-
)
|
97
|
-
|
98
|
-
# then
|
99
|
-
self.assertIsNone(session)
|
100
|
-
|
101
|
-
def test_delete_existing_data(self):
|
102
|
-
# given
|
103
|
-
self.storage.set(
|
104
|
-
auth_provider=AuthProvider.SLACK,
|
105
|
-
thread_id="default_thread_id",
|
106
|
-
profile="default_profile",
|
107
|
-
auth_scopes=["scope1", "scope2"],
|
108
|
-
auth_resolve_uid="test-resolve-uid",
|
109
|
-
auth_context=self.auth_context,
|
110
|
-
is_auth_scope_universal=True
|
111
|
-
)
|
112
|
-
|
113
|
-
# when
|
114
|
-
before_session = self.storage.get(
|
115
|
-
auth_provider=AuthProvider.SLACK,
|
116
|
-
thread_id="default_thread_id",
|
117
|
-
profile="default_profile",
|
118
|
-
)
|
119
|
-
|
120
|
-
deleted = self.storage.delete(
|
121
|
-
auth_provider=AuthProvider.SLACK,
|
122
|
-
thread_id="default_thread_id",
|
123
|
-
profile="default_profile",
|
124
|
-
)
|
125
|
-
|
126
|
-
after_session = self.storage.get(
|
127
|
-
auth_provider=AuthProvider.SLACK,
|
128
|
-
thread_id="default_thread_id",
|
129
|
-
profile="default_profile",
|
130
|
-
)
|
131
|
-
|
132
|
-
# then
|
133
|
-
self.assertTrue(deleted)
|
134
|
-
self.assertIsNotNone(before_session)
|
135
|
-
self.assertIsNone(after_session)
|
136
|
-
|
137
|
-
def test_delete_not_existing_data(self):
|
138
|
-
deleted = self.storage.delete(
|
139
|
-
auth_provider=AuthProvider.SLACK,
|
140
|
-
thread_id="default_thread_id",
|
141
|
-
profile="default_profile",
|
142
|
-
)
|
143
|
-
|
144
|
-
# then
|
145
|
-
self.assertFalse(deleted)
|
@@ -1,151 +0,0 @@
|
|
1
|
-
import unittest
|
2
|
-
|
3
|
-
from hyperpocket.auth import AuthProvider, SlackTokenAuthContext
|
4
|
-
from hyperpocket.config.session import SessionConfigRedis
|
5
|
-
from hyperpocket.session.in_memory import InMemorySessionValue
|
6
|
-
from hyperpocket.session.redis import RedisSessionStorage, RedisSessionValue
|
7
|
-
|
8
|
-
|
9
|
-
class TestRedisSessionStorage(unittest.TestCase):
|
10
|
-
storage: RedisSessionStorage
|
11
|
-
context: SlackTokenAuthContext
|
12
|
-
|
13
|
-
def setUp(self):
|
14
|
-
self.storage = RedisSessionStorage(SessionConfigRedis(
|
15
|
-
host="localhost",
|
16
|
-
port=6379,
|
17
|
-
db="9"
|
18
|
-
))
|
19
|
-
self.storage.client.flushdb()
|
20
|
-
|
21
|
-
self.auth_context = SlackTokenAuthContext(
|
22
|
-
access_token="test",
|
23
|
-
description="test-description",
|
24
|
-
expires_at=None,
|
25
|
-
detail=None,
|
26
|
-
)
|
27
|
-
|
28
|
-
def tearDown(self):
|
29
|
-
self.storage.client.flushdb()
|
30
|
-
|
31
|
-
def test_make_session_key(self):
|
32
|
-
key = self.storage._make_session_key(
|
33
|
-
auth_provider=AuthProvider.SLACK,
|
34
|
-
thread_id="default_thread_id",
|
35
|
-
profile="default_profile"
|
36
|
-
)
|
37
|
-
|
38
|
-
self.assertEqual(key, "SLACK__default_thread_id__default_profile")
|
39
|
-
|
40
|
-
def test_make_session(self):
|
41
|
-
session = self.storage._make_session(
|
42
|
-
auth_provider_name=AuthProvider.SLACK.name,
|
43
|
-
auth_scopes=["scope1", "scope2"],
|
44
|
-
auth_context=self.auth_context,
|
45
|
-
auth_resolve_uid="test-resolve-uid",
|
46
|
-
is_auth_scope_universal=True
|
47
|
-
)
|
48
|
-
|
49
|
-
# then
|
50
|
-
self.assertIsInstance(session, RedisSessionValue)
|
51
|
-
self.assertEqual(session.auth_provider_name, AuthProvider.SLACK.name)
|
52
|
-
self.assertEqual(session.auth_context.access_token, "test")
|
53
|
-
self.assertEqual(session.auth_context.description, "test-description")
|
54
|
-
|
55
|
-
def test_set(self):
|
56
|
-
session = self.storage.set(
|
57
|
-
auth_provider=AuthProvider.SLACK,
|
58
|
-
thread_id="default_thread_id",
|
59
|
-
profile="default_profile",
|
60
|
-
auth_scopes=["scope1", "scope2"],
|
61
|
-
auth_resolve_uid="test-resolve-uid",
|
62
|
-
auth_context=self.auth_context,
|
63
|
-
is_auth_scope_universal=True
|
64
|
-
)
|
65
|
-
|
66
|
-
self.assertIsInstance(session, InMemorySessionValue)
|
67
|
-
self.assertEqual(session.auth_provider_name, AuthProvider.SLACK.name)
|
68
|
-
self.assertEqual(session.auth_context.access_token, self.auth_context.access_token)
|
69
|
-
self.assertEqual(session.auth_context.description, self.auth_context.description)
|
70
|
-
|
71
|
-
def test_get_existing_data(self):
|
72
|
-
# given
|
73
|
-
self.storage.set(
|
74
|
-
auth_provider=AuthProvider.SLACK,
|
75
|
-
thread_id="default_thread_id",
|
76
|
-
profile="default_profile",
|
77
|
-
auth_scopes=["scope1", "scope2"],
|
78
|
-
auth_resolve_uid="test-resolve-uid",
|
79
|
-
auth_context=self.auth_context,
|
80
|
-
is_auth_scope_universal=True
|
81
|
-
)
|
82
|
-
|
83
|
-
# when
|
84
|
-
session = self.storage.get(
|
85
|
-
auth_provider=AuthProvider.SLACK,
|
86
|
-
thread_id="default_thread_id",
|
87
|
-
profile="default_profile",
|
88
|
-
)
|
89
|
-
|
90
|
-
# then
|
91
|
-
self.assertIsInstance(session, InMemorySessionValue)
|
92
|
-
self.assertEqual(session.auth_provider_name, AuthProvider.SLACK.name)
|
93
|
-
self.assertEqual(session.auth_context.access_token, "test")
|
94
|
-
self.assertEqual(session.auth_context.description, "test-description")
|
95
|
-
|
96
|
-
def test_get_not_existing_data(self):
|
97
|
-
# when
|
98
|
-
session = self.storage.get(
|
99
|
-
auth_provider=AuthProvider.SLACK,
|
100
|
-
thread_id="default_thread_id",
|
101
|
-
profile="default_profile",
|
102
|
-
)
|
103
|
-
|
104
|
-
# then
|
105
|
-
self.assertIsNone(session)
|
106
|
-
|
107
|
-
def test_delete_existing_data(self):
|
108
|
-
# given
|
109
|
-
self.storage.set(
|
110
|
-
auth_provider=AuthProvider.SLACK,
|
111
|
-
thread_id="default_thread_id",
|
112
|
-
profile="default_profile",
|
113
|
-
auth_scopes=["scope1", "scope2"],
|
114
|
-
auth_resolve_uid="test-resolve-uid",
|
115
|
-
auth_context=self.auth_context,
|
116
|
-
is_auth_scope_universal=True
|
117
|
-
)
|
118
|
-
|
119
|
-
# when
|
120
|
-
before_session = self.storage.get(
|
121
|
-
auth_provider=AuthProvider.SLACK,
|
122
|
-
thread_id="default_thread_id",
|
123
|
-
profile="default_profile",
|
124
|
-
)
|
125
|
-
|
126
|
-
deleted = self.storage.delete(
|
127
|
-
auth_provider=AuthProvider.SLACK,
|
128
|
-
thread_id="default_thread_id",
|
129
|
-
profile="default_profile",
|
130
|
-
)
|
131
|
-
|
132
|
-
after_session = self.storage.get(
|
133
|
-
auth_provider=AuthProvider.SLACK,
|
134
|
-
thread_id="default_thread_id",
|
135
|
-
profile="default_profile",
|
136
|
-
)
|
137
|
-
|
138
|
-
# then
|
139
|
-
self.assertTrue(deleted)
|
140
|
-
self.assertIsNotNone(before_session)
|
141
|
-
self.assertIsNone(after_session)
|
142
|
-
|
143
|
-
def test_delete_not_existing_data(self):
|
144
|
-
deleted = self.storage.delete(
|
145
|
-
auth_provider=AuthProvider.SLACK,
|
146
|
-
thread_id="default_thread_id",
|
147
|
-
profile="default_profile",
|
148
|
-
)
|
149
|
-
|
150
|
-
# then
|
151
|
-
self.assertFalse(deleted)
|
hyperpocket/tests/test_pocket.py
DELETED
@@ -1,116 +0,0 @@
|
|
1
|
-
from pathlib import Path
|
2
|
-
from unittest.async_case import IsolatedAsyncioTestCase
|
3
|
-
|
4
|
-
from pydantic import BaseModel
|
5
|
-
|
6
|
-
from hyperpocket import Pocket
|
7
|
-
from hyperpocket.config import config
|
8
|
-
from hyperpocket.tool import from_local, from_git
|
9
|
-
|
10
|
-
|
11
|
-
class TestPocket(IsolatedAsyncioTestCase):
|
12
|
-
|
13
|
-
async def asyncSetUp(self):
|
14
|
-
self.profile = "test-profile"
|
15
|
-
self.thread_id = "test_thread_id"
|
16
|
-
|
17
|
-
config.public_server_port = "https"
|
18
|
-
config.public_hostname = "localhost"
|
19
|
-
config.public_server_port = 8001
|
20
|
-
config.internal_server_port = 8000
|
21
|
-
config.enable_local_callback_proxy = True
|
22
|
-
|
23
|
-
self.pocket = Pocket(
|
24
|
-
tools=[
|
25
|
-
from_git("https://github.com/vessl-ai/hyperawesometools", "main", "managed-tools/simple-echo-tool"),
|
26
|
-
self.add,
|
27
|
-
self.add_pydantic_args
|
28
|
-
],
|
29
|
-
)
|
30
|
-
|
31
|
-
async def test_function_tool(self):
|
32
|
-
# given
|
33
|
-
tool_name = "add"
|
34
|
-
|
35
|
-
# when
|
36
|
-
result = await self.pocket.ainvoke(
|
37
|
-
tool_name=tool_name,
|
38
|
-
body={
|
39
|
-
"a": 1,
|
40
|
-
"b": 3
|
41
|
-
},
|
42
|
-
thread_id=self.thread_id,
|
43
|
-
profile=self.profile,
|
44
|
-
)
|
45
|
-
|
46
|
-
# then
|
47
|
-
self.assertEqual(result, "4")
|
48
|
-
|
49
|
-
async def test_pydantic_arg_function_tool(self):
|
50
|
-
# given
|
51
|
-
tool_name = "add_pydantic_args"
|
52
|
-
|
53
|
-
# when
|
54
|
-
result = await self.pocket.ainvoke(
|
55
|
-
tool_name=tool_name,
|
56
|
-
body={
|
57
|
-
"a": {
|
58
|
-
"first": 1
|
59
|
-
},
|
60
|
-
"b": {
|
61
|
-
"second": 3
|
62
|
-
}
|
63
|
-
},
|
64
|
-
thread_id=self.thread_id,
|
65
|
-
profile=self.profile,
|
66
|
-
)
|
67
|
-
|
68
|
-
# then
|
69
|
-
self.assertEqual(result, "4")
|
70
|
-
|
71
|
-
async def test_wasm_tool(self):
|
72
|
-
# given
|
73
|
-
tool_name = "simple_echo_text"
|
74
|
-
|
75
|
-
# when
|
76
|
-
result = await self.pocket.ainvoke(
|
77
|
-
tool_name=tool_name,
|
78
|
-
body={
|
79
|
-
"text": "test"
|
80
|
-
},
|
81
|
-
thread_id=self.thread_id,
|
82
|
-
profile=self.profile,
|
83
|
-
)
|
84
|
-
|
85
|
-
# then
|
86
|
-
self.assertTrue(result.startswith("echo message : test"))
|
87
|
-
|
88
|
-
@staticmethod
|
89
|
-
def add(a: int, b: int) -> int:
|
90
|
-
"""
|
91
|
-
Add two numbers
|
92
|
-
|
93
|
-
Args:
|
94
|
-
a(int): first number
|
95
|
-
b(int): second number
|
96
|
-
|
97
|
-
"""
|
98
|
-
|
99
|
-
return a + b
|
100
|
-
|
101
|
-
class FirstNumber(BaseModel):
|
102
|
-
first: int
|
103
|
-
|
104
|
-
class SecondNumber(BaseModel):
|
105
|
-
second: int
|
106
|
-
|
107
|
-
@staticmethod
|
108
|
-
def add_pydantic_args(a: FirstNumber, b: SecondNumber):
|
109
|
-
"""
|
110
|
-
Add two numbers
|
111
|
-
|
112
|
-
Args:
|
113
|
-
a(FirstNumber): first number
|
114
|
-
b(SecondNumber): second number
|
115
|
-
"""
|
116
|
-
return a.first + b.second
|