hyperpocket 0.1.9__py3-none-any.whl → 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.
- hyperpocket/__init__.py +4 -4
- hyperpocket/auth/__init__.py +12 -7
- hyperpocket/auth/calendly/oauth2_handler.py +24 -17
- hyperpocket/auth/calendly/oauth2_schema.py +3 -1
- hyperpocket/auth/context.py +2 -1
- hyperpocket/auth/github/oauth2_handler.py +13 -8
- hyperpocket/auth/github/token_handler.py +27 -21
- hyperpocket/auth/google/context.py +1 -3
- hyperpocket/auth/google/oauth2_context.py +1 -1
- hyperpocket/auth/google/oauth2_handler.py +22 -17
- hyperpocket/auth/gumloop/token_context.py +1 -4
- hyperpocket/auth/gumloop/token_handler.py +48 -20
- hyperpocket/auth/gumloop/token_schema.py +2 -1
- hyperpocket/auth/handler.py +21 -6
- hyperpocket/auth/linear/token_context.py +2 -5
- hyperpocket/auth/linear/token_handler.py +45 -21
- hyperpocket/auth/notion/context.py +2 -2
- hyperpocket/auth/notion/token_context.py +2 -4
- hyperpocket/auth/notion/token_handler.py +45 -21
- hyperpocket/auth/notion/token_schema.py +0 -1
- hyperpocket/auth/reddit/oauth2_handler.py +9 -10
- hyperpocket/auth/reddit/oauth2_schema.py +0 -2
- hyperpocket/auth/schema.py +4 -1
- hyperpocket/auth/slack/oauth2_context.py +3 -1
- hyperpocket/auth/slack/oauth2_handler.py +55 -35
- hyperpocket/auth/slack/token_context.py +2 -4
- hyperpocket/auth/slack/token_handler.py +42 -19
- hyperpocket/builtin.py +4 -2
- hyperpocket/cli/__main__.py +4 -2
- hyperpocket/cli/auth.py +59 -28
- hyperpocket/cli/codegen/auth/auth_context_template.py +3 -2
- hyperpocket/cli/codegen/auth/auth_token_context_template.py +3 -2
- hyperpocket/cli/codegen/auth/auth_token_handler_template.py +6 -5
- hyperpocket/cli/codegen/auth/auth_token_schema_template.py +3 -2
- hyperpocket/cli/codegen/auth/server_auth_template.py +3 -2
- hyperpocket/cli/pull.py +5 -5
- hyperpocket/config/__init__.py +3 -8
- hyperpocket/config/auth.py +3 -1
- hyperpocket/config/logger.py +20 -15
- hyperpocket/config/session.py +4 -2
- hyperpocket/config/settings.py +19 -2
- hyperpocket/futures/__init__.py +1 -1
- hyperpocket/futures/futurestore.py +3 -2
- hyperpocket/pocket_auth.py +171 -84
- hyperpocket/pocket_core.py +51 -33
- hyperpocket/pocket_main.py +122 -93
- hyperpocket/prompts.py +2 -2
- hyperpocket/repository/__init__.py +1 -1
- hyperpocket/repository/lock.py +47 -33
- hyperpocket/repository/lockfile.py +2 -2
- hyperpocket/repository/repository.py +1 -1
- hyperpocket/server/__init__.py +1 -1
- hyperpocket/server/auth/github.py +2 -1
- hyperpocket/server/auth/linear.py +1 -3
- hyperpocket/server/auth/notion.py +2 -5
- hyperpocket/server/auth/slack.py +1 -3
- hyperpocket/server/auth/token.py +17 -11
- hyperpocket/server/proxy.py +29 -13
- hyperpocket/server/server.py +75 -31
- hyperpocket/server/tool/dto/script.py +15 -10
- hyperpocket/server/tool/wasm.py +14 -11
- hyperpocket/session/__init__.py +6 -2
- hyperpocket/session/in_memory.py +44 -24
- hyperpocket/session/interface.py +42 -24
- hyperpocket/session/redis.py +48 -31
- hyperpocket/tool/__init__.py +10 -10
- hyperpocket/tool/function/__init__.py +1 -5
- hyperpocket/tool/function/annotation.py +11 -9
- hyperpocket/tool/function/tool.py +37 -27
- hyperpocket/tool/tool.py +59 -36
- hyperpocket/tool/wasm/__init__.py +1 -1
- hyperpocket/tool/wasm/browser.py +15 -10
- hyperpocket/tool/wasm/invoker.py +16 -16
- hyperpocket/tool/wasm/script.py +27 -14
- hyperpocket/tool/wasm/templates/__init__.py +22 -15
- hyperpocket/tool/wasm/templates/node.py +2 -2
- hyperpocket/tool/wasm/templates/python.py +2 -2
- hyperpocket/tool/wasm/tool.py +27 -14
- hyperpocket/tool_like.py +3 -3
- hyperpocket/util/__init__.py +1 -1
- hyperpocket/util/extract_func_param_desc_from_docstring.py +33 -14
- hyperpocket/util/find_all_leaf_class_in_package.py +4 -3
- hyperpocket/util/find_all_subclass_in_package.py +4 -2
- hyperpocket/util/flatten_json_schema.py +10 -6
- hyperpocket/util/function_to_model.py +33 -12
- hyperpocket/util/get_objects_from_subpackage.py +1 -1
- hyperpocket/util/json_schema_to_model.py +14 -5
- {hyperpocket-0.1.9.dist-info → hyperpocket-0.2.0.dist-info}/METADATA +29 -24
- hyperpocket-0.2.0.dist-info/RECORD +137 -0
- hyperpocket-0.1.9.dist-info/RECORD +0 -137
- {hyperpocket-0.1.9.dist-info → hyperpocket-0.2.0.dist-info}/WHEEL +0 -0
- {hyperpocket-0.1.9.dist-info → hyperpocket-0.2.0.dist-info}/entry_points.txt +0 -0
hyperpocket/pocket_auth.py
CHANGED
@@ -3,13 +3,13 @@ import enum
|
|
3
3
|
import uuid
|
4
4
|
from typing import Optional, Type
|
5
5
|
|
6
|
-
from hyperpocket.auth import
|
6
|
+
from hyperpocket.auth import PREBUILT_AUTH_HANDLERS, AuthProvider
|
7
7
|
from hyperpocket.auth.context import AuthContext
|
8
|
-
from hyperpocket.auth.handler import
|
8
|
+
from hyperpocket.auth.handler import AuthenticateRequest, AuthHandlerInterface
|
9
9
|
from hyperpocket.config import config, pocket_logger
|
10
10
|
from hyperpocket.futures import FutureStore
|
11
11
|
from hyperpocket.session import SESSION_STORAGE_LIST
|
12
|
-
from hyperpocket.session.interface import
|
12
|
+
from hyperpocket.session.interface import BaseSessionValue, SessionStorageInterface
|
13
13
|
|
14
14
|
|
15
15
|
class AuthState(enum.Enum):
|
@@ -26,11 +26,12 @@ class PocketAuth(object):
|
|
26
26
|
session_storage: SessionStorageInterface
|
27
27
|
|
28
28
|
def __init__(
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
29
|
+
self,
|
30
|
+
handlers: Optional[list[Type[AuthHandlerInterface]]] = None,
|
31
|
+
session_storage: Optional[SessionStorageInterface] = None,
|
32
|
+
use_prebuilt_handlers: bool = None,
|
33
|
+
):
|
34
|
+
if config().auth.use_prebuilt_auth or use_prebuilt_handlers:
|
34
35
|
handlers = PREBUILT_AUTH_HANDLERS + (handlers or [])
|
35
36
|
handler_impls = [C() for C in handlers] if handlers else []
|
36
37
|
self.handlers = {handler.name: handler for handler in handler_impls}
|
@@ -38,21 +39,31 @@ class PocketAuth(object):
|
|
38
39
|
self.session_storage = session_storage
|
39
40
|
else:
|
40
41
|
for session_type in SESSION_STORAGE_LIST:
|
41
|
-
if session_type.session_storage_type() == config.session.session_type:
|
42
|
-
session_config = getattr(
|
43
|
-
|
44
|
-
|
42
|
+
if session_type.session_storage_type() == config().session.session_type:
|
43
|
+
session_config = getattr(
|
44
|
+
config().session, config().session.session_type.value
|
45
|
+
)
|
46
|
+
|
47
|
+
pocket_logger.info(
|
48
|
+
f"init {session_type.session_storage_type()} session storage.."
|
49
|
+
)
|
45
50
|
self.session_storage = session_type(session_config)
|
46
51
|
|
47
52
|
if self.session_storage is None:
|
48
|
-
pocket_logger.error(
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
53
|
+
pocket_logger.error(
|
54
|
+
f"not supported session type({config().session.session_type})"
|
55
|
+
)
|
56
|
+
raise RuntimeError(
|
57
|
+
f"Not Supported Session Type({config().session.session_type})"
|
58
|
+
)
|
59
|
+
|
60
|
+
def make_request(
|
61
|
+
self,
|
62
|
+
auth_scopes: list[str] = None,
|
63
|
+
auth_handler_name: Optional[str] = None,
|
64
|
+
auth_provider: Optional[AuthProvider] = None,
|
65
|
+
**kwargs,
|
66
|
+
) -> AuthenticateRequest:
|
56
67
|
"""
|
57
68
|
Make AuthenticationRequest based on authentication handler.
|
58
69
|
|
@@ -67,14 +78,16 @@ class PocketAuth(object):
|
|
67
78
|
handler = self.find_handler_instance(auth_handler_name, auth_provider)
|
68
79
|
return handler.make_request(auth_scopes, **kwargs)
|
69
80
|
|
70
|
-
def check(
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
81
|
+
def check(
|
82
|
+
self,
|
83
|
+
auth_req: AuthenticateRequest,
|
84
|
+
auth_handler_name: Optional[str] = None,
|
85
|
+
auth_provider: Optional[AuthProvider] = None,
|
86
|
+
thread_id: str = "default",
|
87
|
+
profile: str = "default",
|
88
|
+
*args,
|
89
|
+
**kwargs,
|
90
|
+
) -> AuthState:
|
78
91
|
"""
|
79
92
|
Check current authentication state.
|
80
93
|
|
@@ -104,7 +117,9 @@ class PocketAuth(object):
|
|
104
117
|
return auth_state
|
105
118
|
|
106
119
|
@staticmethod
|
107
|
-
def get_session_state(
|
120
|
+
def get_session_state(
|
121
|
+
session: Optional[BaseSessionValue], auth_req: Optional[AuthenticateRequest]
|
122
|
+
) -> AuthState:
|
108
123
|
if not session:
|
109
124
|
return AuthState.NO_SESSION
|
110
125
|
|
@@ -115,8 +130,9 @@ class PocketAuth(object):
|
|
115
130
|
|
116
131
|
return AuthState.PENDING_RESOLVE
|
117
132
|
|
118
|
-
if auth_req is not None and not session.is_auth_applicable(
|
119
|
-
|
133
|
+
if auth_req is not None and not session.is_auth_applicable(
|
134
|
+
auth_provider_name=session.auth_provider_name, auth_req=auth_req
|
135
|
+
):
|
120
136
|
return AuthState.DO_AUTH
|
121
137
|
|
122
138
|
if session.is_near_expires():
|
@@ -124,13 +140,15 @@ class PocketAuth(object):
|
|
124
140
|
|
125
141
|
return AuthState.SKIP_AUTH
|
126
142
|
|
127
|
-
def prepare(
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
143
|
+
def prepare(
|
144
|
+
self,
|
145
|
+
auth_req: AuthenticateRequest,
|
146
|
+
auth_handler_name: Optional[str] = None,
|
147
|
+
auth_provider: Optional[AuthProvider] = None,
|
148
|
+
thread_id: str = "default",
|
149
|
+
profile: str = "default",
|
150
|
+
**kwargs,
|
151
|
+
) -> Optional[str]:
|
134
152
|
"""
|
135
153
|
Prepare authentication.
|
136
154
|
|
@@ -158,8 +176,13 @@ class PocketAuth(object):
|
|
158
176
|
)
|
159
177
|
|
160
178
|
pocket_logger.debug(
|
161
|
-
f"[thread_id({thread_id}):profile({profile})] {auth_provider.name} provider current auth state in prepare : {auth_state}"
|
162
|
-
|
179
|
+
f"[thread_id({thread_id}):profile({profile})] {auth_provider.name} provider current auth state in prepare : {auth_state}"
|
180
|
+
)
|
181
|
+
if auth_state in [
|
182
|
+
AuthState.SKIP_AUTH,
|
183
|
+
AuthState.DO_REFRESH,
|
184
|
+
AuthState.RESOLVED,
|
185
|
+
]:
|
163
186
|
return None
|
164
187
|
|
165
188
|
handler = self.find_handler_instance(auth_handler_name, auth_provider)
|
@@ -168,12 +191,13 @@ class PocketAuth(object):
|
|
168
191
|
if session:
|
169
192
|
scope = scope.union(session.auth_scopes)
|
170
193
|
|
171
|
-
modified_req = auth_req.model_copy(update={
|
194
|
+
modified_req = auth_req.model_copy(update={"auth_scopes": scope})
|
172
195
|
|
173
196
|
# session in pending
|
174
197
|
if session and session.auth_resolve_uid:
|
175
198
|
pocket_logger.debug(
|
176
|
-
f"[thread_id({thread_id}):profile({profile})] already exists pending session(auth_resolve_uid:{session.auth_resolve_uid})."
|
199
|
+
f"[thread_id({thread_id}):profile({profile})] already exists pending session(auth_resolve_uid:{session.auth_resolve_uid})."
|
200
|
+
)
|
177
201
|
future_uid = session.auth_resolve_uid
|
178
202
|
|
179
203
|
# update session, in case of requesting new scopes before session pending resolved.
|
@@ -182,7 +206,7 @@ class PocketAuth(object):
|
|
182
206
|
future_uid=session.auth_resolve_uid,
|
183
207
|
profile=profile,
|
184
208
|
thread_id=thread_id,
|
185
|
-
scope=scope
|
209
|
+
scope=scope,
|
186
210
|
)
|
187
211
|
else: # create new pending session
|
188
212
|
future_uid = str(uuid.uuid4())
|
@@ -191,25 +215,34 @@ class PocketAuth(object):
|
|
191
215
|
future_uid=future_uid,
|
192
216
|
profile=profile,
|
193
217
|
thread_id=thread_id,
|
194
|
-
scope=scope
|
218
|
+
scope=scope,
|
219
|
+
)
|
195
220
|
|
196
221
|
pocket_logger.debug(
|
197
|
-
f"[thread_id({thread_id}):profile({profile})] create new pending session(auth_resolve_uid:{future_uid})."
|
198
|
-
|
222
|
+
f"[thread_id({thread_id}):profile({profile})] create new pending session(auth_resolve_uid:{future_uid})."
|
223
|
+
)
|
224
|
+
asyncio.create_task(
|
225
|
+
self._check_session_pending_resolved(handler, thread_id, profile)
|
226
|
+
)
|
199
227
|
|
200
|
-
prepare_url = handler.prepare(
|
228
|
+
prepare_url = handler.prepare(
|
229
|
+
modified_req, thread_id, profile, future_uid, **kwargs
|
230
|
+
)
|
201
231
|
pocket_logger.debug(
|
202
|
-
f"[thread_id({thread_id}):profile({profile})] auth_handler({auth_handler_name})'s prepare_url : {prepare_url}."
|
232
|
+
f"[thread_id({thread_id}):profile({profile})] auth_handler({auth_handler_name})'s prepare_url : {prepare_url}."
|
233
|
+
)
|
203
234
|
|
204
235
|
return prepare_url
|
205
236
|
|
206
|
-
async def authenticate_async(
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
237
|
+
async def authenticate_async(
|
238
|
+
self,
|
239
|
+
auth_req: AuthenticateRequest,
|
240
|
+
auth_handler_name: Optional[str] = None,
|
241
|
+
auth_provider: Optional[AuthProvider] = None,
|
242
|
+
thread_id: str = "default",
|
243
|
+
profile: str = "default",
|
244
|
+
**kwargs,
|
245
|
+
) -> AuthContext:
|
213
246
|
"""
|
214
247
|
Performing authentication.
|
215
248
|
It is performing authentication. and save the session in session storage.
|
@@ -243,42 +276,61 @@ class PocketAuth(object):
|
|
243
276
|
session = self.session_storage.get(handler.provider(), thread_id, profile)
|
244
277
|
if session is None:
|
245
278
|
pocket_logger.warning(
|
246
|
-
f"[thread_id({thread_id}):profile({profile})] Session can't find. session should exist in 'authenticate'."
|
279
|
+
f"[thread_id({thread_id}):profile({profile})] Session can't find. session should exist in 'authenticate'."
|
280
|
+
)
|
247
281
|
raise RuntimeError(
|
248
|
-
f"[thread_id({thread_id}):profile({profile})] Session can't find. session should exist in 'authenticate'."
|
282
|
+
f"[thread_id({thread_id}):profile({profile})] Session can't find. session should exist in 'authenticate'."
|
283
|
+
)
|
249
284
|
|
250
285
|
pocket_logger.debug(
|
251
|
-
f"[thread_id({thread_id}):profile({profile})] auth_handler({auth_handler_name})'s auth state : {auth_state}"
|
286
|
+
f"[thread_id({thread_id}):profile({profile})] auth_handler({auth_handler_name})'s auth state : {auth_state}"
|
287
|
+
)
|
252
288
|
try:
|
253
289
|
if auth_state == AuthState.SKIP_AUTH:
|
254
290
|
context = session.auth_context
|
255
291
|
elif auth_state == AuthState.DO_REFRESH:
|
256
292
|
try:
|
257
293
|
context = await asyncio.wait_for(
|
258
|
-
handler.refresh(
|
294
|
+
handler.refresh(
|
295
|
+
auth_req=auth_req, context=session.auth_context, **kwargs
|
296
|
+
),
|
297
|
+
timeout=300,
|
298
|
+
)
|
259
299
|
except Exception as e:
|
260
300
|
self.session_storage.delete(handler.provider(), thread_id, profile)
|
261
301
|
FutureStore.delete_future(session.auth_resolve_uid)
|
262
302
|
|
263
303
|
pocket_logger.warning(
|
264
|
-
f"[thread_id({thread_id}):profile({profile})] auth_handler({auth_handler_name}) failed to refresh the token."
|
265
|
-
|
266
|
-
|
304
|
+
f"[thread_id({thread_id}):profile({profile})] auth_handler({auth_handler_name}) failed to refresh the token."
|
305
|
+
)
|
306
|
+
raise RuntimeError(
|
307
|
+
"Failed to refresh the token. Please re-authenticate."
|
308
|
+
) from e
|
309
|
+
elif (
|
310
|
+
auth_state == AuthState.PENDING_RESOLVE
|
311
|
+
or auth_state == AuthState.RESOLVED
|
312
|
+
):
|
267
313
|
future_uid = session.auth_resolve_uid
|
268
314
|
context = await asyncio.wait_for(
|
269
|
-
handler.authenticate(
|
315
|
+
handler.authenticate(
|
316
|
+
auth_req=auth_req, future_uid=future_uid, **kwargs
|
317
|
+
),
|
318
|
+
timeout=300,
|
319
|
+
)
|
270
320
|
else:
|
271
321
|
# maybe auth_state is either AuthState.NO_SESSION or AuthState.DO_AUTH
|
272
322
|
pocket_logger.warning(
|
273
|
-
f"[thread_id({thread_id}):profile({profile})] Invalid State. 'authenticate' cannot be reached while in state {auth_state}"
|
323
|
+
f"[thread_id({thread_id}):profile({profile})] Invalid State. 'authenticate' cannot be reached while in state {auth_state}"
|
324
|
+
)
|
274
325
|
raise RuntimeError(
|
275
|
-
f"[thread_id({thread_id}):profile({profile})] Invalid State. 'authenticate' cannot be reached while in state {auth_state}"
|
326
|
+
f"[thread_id({thread_id}):profile({profile})] Invalid State. 'authenticate' cannot be reached while in state {auth_state}"
|
327
|
+
)
|
276
328
|
|
277
329
|
session = await self._set_session_active(
|
278
330
|
context=context,
|
279
331
|
provider=handler.provider(),
|
280
332
|
profile=profile,
|
281
|
-
thread_id=thread_id
|
333
|
+
thread_id=thread_id,
|
282
334
|
)
|
283
335
|
|
284
336
|
return session.auth_context
|
@@ -288,33 +340,50 @@ class PocketAuth(object):
|
|
288
340
|
FutureStore.delete_future(session.auth_resolve_uid)
|
289
341
|
raise e
|
290
342
|
|
291
|
-
def get_auth_context(
|
292
|
-
|
343
|
+
def get_auth_context(
|
344
|
+
self,
|
345
|
+
auth_provider: AuthProvider,
|
346
|
+
thread_id: str = "default",
|
347
|
+
profile: str = "default",
|
348
|
+
**kwargs,
|
349
|
+
) -> Optional[AuthContext]:
|
293
350
|
session = self.session_storage.get(auth_provider, thread_id, profile, **kwargs)
|
294
351
|
if session is None:
|
295
352
|
return None
|
296
353
|
|
297
354
|
return session.auth_context
|
298
355
|
|
299
|
-
def list_session_state(
|
300
|
-
|
356
|
+
def list_session_state(
|
357
|
+
self, thread_id: str, auth_provider: Optional[AuthProvider] = None
|
358
|
+
):
|
359
|
+
session_list = self.session_storage.get_by_thread_id(
|
360
|
+
thread_id=thread_id, auth_provider=auth_provider
|
361
|
+
)
|
301
362
|
session_state_list = []
|
302
363
|
for session in session_list:
|
303
364
|
state = self.get_session_state(session=session, auth_req=None)
|
304
365
|
|
305
|
-
session_state_list.append(
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
|
366
|
+
session_state_list.append(
|
367
|
+
{
|
368
|
+
"provider": session.auth_provider_name,
|
369
|
+
"scope": session.auth_scopes,
|
370
|
+
"state": state,
|
371
|
+
}
|
372
|
+
)
|
310
373
|
|
311
374
|
return session_state_list
|
312
375
|
|
313
|
-
def delete_session(
|
376
|
+
def delete_session(
|
377
|
+
self,
|
378
|
+
auth_provider: AuthProvider,
|
379
|
+
thread_id: str = "default",
|
380
|
+
profile: str = "default",
|
381
|
+
) -> bool:
|
314
382
|
return self.session_storage.delete(auth_provider, thread_id, profile)
|
315
383
|
|
316
|
-
def find_handler_instance(
|
317
|
-
|
384
|
+
def find_handler_instance(
|
385
|
+
self, name: Optional[str] = None, auth_provider: Optional[AuthProvider] = None
|
386
|
+
) -> AuthHandlerInterface:
|
318
387
|
if name:
|
319
388
|
return self.handlers[name]
|
320
389
|
if auth_provider:
|
@@ -323,19 +392,35 @@ class PocketAuth(object):
|
|
323
392
|
return handler
|
324
393
|
raise ValueError("No handler found")
|
325
394
|
|
326
|
-
async def _check_session_pending_resolved(
|
327
|
-
|
395
|
+
async def _check_session_pending_resolved(
|
396
|
+
self,
|
397
|
+
auth_handler: AuthHandlerInterface,
|
398
|
+
thread_id: str = "default",
|
399
|
+
profile: str = "default",
|
400
|
+
timeout_seconds=300,
|
401
|
+
**kwargs,
|
402
|
+
):
|
328
403
|
await asyncio.sleep(timeout_seconds)
|
329
|
-
session = self.session_storage.get(
|
404
|
+
session = self.session_storage.get(
|
405
|
+
auth_handler.provider(), thread_id, profile, **kwargs
|
406
|
+
)
|
330
407
|
if session.auth_resolve_uid is not None:
|
331
|
-
pocket_logger.info(
|
408
|
+
pocket_logger.info(
|
409
|
+
f"session({session.auth_resolve_uid}) is not resolved yet and timeout. remove session"
|
410
|
+
)
|
332
411
|
self.delete_session(auth_handler.provider(), thread_id, profile)
|
333
412
|
FutureStore.delete_future(session.auth_resolve_uid)
|
334
413
|
|
335
414
|
return
|
336
415
|
|
337
416
|
def _upsert_pending_session(
|
338
|
-
|
417
|
+
self,
|
418
|
+
auth_handler: AuthHandlerInterface,
|
419
|
+
future_uid: str,
|
420
|
+
profile: str,
|
421
|
+
thread_id: str,
|
422
|
+
scope: set[str],
|
423
|
+
):
|
339
424
|
return self.session_storage.set(
|
340
425
|
auth_provider=auth_handler.provider(),
|
341
426
|
thread_id=thread_id,
|
@@ -346,7 +431,9 @@ class PocketAuth(object):
|
|
346
431
|
auth_resolve_uid=future_uid,
|
347
432
|
)
|
348
433
|
|
349
|
-
async def _set_session_active(
|
434
|
+
async def _set_session_active(
|
435
|
+
self, context: AuthContext, provider: AuthProvider, profile: str, thread_id: str
|
436
|
+
):
|
350
437
|
session = self.session_storage.get(provider, thread_id, profile)
|
351
438
|
if session is None:
|
352
439
|
pocket_logger.error("the session to be active doesn't exist.")
|
hyperpocket/pocket_core.py
CHANGED
@@ -1,12 +1,12 @@
|
|
1
1
|
import asyncio
|
2
2
|
import pathlib
|
3
|
-
from typing import Any,
|
3
|
+
from typing import Any, Callable, List, Optional, Union
|
4
4
|
|
5
5
|
from hyperpocket.builtin import get_builtin_tools
|
6
6
|
from hyperpocket.config import pocket_logger
|
7
7
|
from hyperpocket.pocket_auth import PocketAuth
|
8
8
|
from hyperpocket.repository import Lockfile
|
9
|
-
from hyperpocket.repository.lock import
|
9
|
+
from hyperpocket.repository.lock import GitLock, LocalLock
|
10
10
|
from hyperpocket.tool import Tool, ToolRequest
|
11
11
|
from hyperpocket.tool.function import from_func
|
12
12
|
from hyperpocket.tool.wasm import WasmTool
|
@@ -18,11 +18,13 @@ class PocketCore:
|
|
18
18
|
auth: PocketAuth
|
19
19
|
tools: dict[str, Tool]
|
20
20
|
|
21
|
-
def __init__(
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
21
|
+
def __init__(
|
22
|
+
self,
|
23
|
+
tools: list[ToolLike],
|
24
|
+
auth: PocketAuth = None,
|
25
|
+
lockfile_path: Optional[str] = None,
|
26
|
+
force_update: bool = False,
|
27
|
+
):
|
26
28
|
if auth is None:
|
27
29
|
auth = PocketAuth()
|
28
30
|
self.auth = auth
|
@@ -37,8 +39,10 @@ class PocketCore:
|
|
37
39
|
if pathlib.Path(tool_like).exists():
|
38
40
|
lock = LocalLock(tool_like)
|
39
41
|
req = WasmToolRequest(lock, "")
|
40
|
-
|
41
|
-
base_repo_url, git_ref, rel_path = GitLock.
|
42
|
+
elif tool_like.startswith("https://github.com"):
|
43
|
+
base_repo_url, git_ref, rel_path = GitLock.parse_repo_url(
|
44
|
+
repo_url=tool_like
|
45
|
+
)
|
42
46
|
lock = GitLock(repository_url=base_repo_url, git_ref=git_ref)
|
43
47
|
req = WasmToolRequest(lock=lock, rel_path=rel_path, tool_vars={})
|
44
48
|
|
@@ -63,19 +67,26 @@ class PocketCore:
|
|
63
67
|
raise ValueError(f"Duplicate tool name: {tool.name}")
|
64
68
|
self.tools[tool.name] = tool
|
65
69
|
|
66
|
-
pocket_logger.info(
|
70
|
+
pocket_logger.info(
|
71
|
+
f"All Registered Tools Loaded successfully. total registered tools : {len(self.tools)}"
|
72
|
+
)
|
67
73
|
|
68
74
|
builtin_tools = get_builtin_tools(self.auth)
|
69
75
|
for tool in builtin_tools:
|
70
76
|
self.tools[tool.name] = tool
|
71
|
-
pocket_logger.info(
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
77
|
+
pocket_logger.info(
|
78
|
+
f"All BuiltIn Tools Loaded successfully. total tools : {len(self.tools)}"
|
79
|
+
)
|
80
|
+
|
81
|
+
async def acall(
|
82
|
+
self,
|
83
|
+
tool_name: str,
|
84
|
+
body: Any,
|
85
|
+
thread_id: str = "default",
|
86
|
+
profile: str = "default",
|
87
|
+
*args,
|
88
|
+
**kwargs,
|
89
|
+
) -> tuple[str, bool]:
|
79
90
|
"""
|
80
91
|
Invoke tool asynchronously, not that different from `Pocket.invoke`
|
81
92
|
But this method is called only in subprocess.
|
@@ -105,11 +116,13 @@ class PocketCore:
|
|
105
116
|
result = await self.tool_call(tool_name, body=body, envs=credentials, **kwargs)
|
106
117
|
return result, False
|
107
118
|
|
108
|
-
def prepare_auth(
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
119
|
+
def prepare_auth(
|
120
|
+
self,
|
121
|
+
tool_name: Union[str, List[str]],
|
122
|
+
thread_id: str = "default",
|
123
|
+
profile: str = "default",
|
124
|
+
**kwargs,
|
125
|
+
) -> Optional[str]:
|
113
126
|
"""
|
114
127
|
Prepares the authentication process for the tool if necessary.
|
115
128
|
Returns callback URL and whether the tool requires authentication.
|
@@ -142,12 +155,14 @@ class PocketCore:
|
|
142
155
|
for tool in tools:
|
143
156
|
if tool.auth.auth_handler != auth_handler_name:
|
144
157
|
pocket_logger.error(
|
145
|
-
f"All Tools should have same auth handler. but it's different {tool.auth.auth_handler}, {auth_handler_name}"
|
158
|
+
f"All Tools should have same auth handler. but it's different {tool.auth.auth_handler}, {auth_handler_name}"
|
159
|
+
)
|
146
160
|
|
147
161
|
return f"All Tools should have same auth handler. but it's different {tool.auth.auth_handler}, {auth_handler_name}"
|
148
162
|
if tool.auth.auth_provider != auth_provider:
|
149
163
|
pocket_logger.error(
|
150
|
-
f"All Tools should have same auth provider. but it's different {tool.auth.auth_provider}, {auth_provider}"
|
164
|
+
f"All Tools should have same auth provider. but it's different {tool.auth.auth_provider}, {auth_provider}"
|
165
|
+
)
|
151
166
|
return f"All Tools should have same auth provider. but it's different {tool.auth.auth_provider}, {auth_provider}"
|
152
167
|
|
153
168
|
if tool.auth.scopes is not None:
|
@@ -156,7 +171,8 @@ class PocketCore:
|
|
156
171
|
auth_req = self.auth.make_request(
|
157
172
|
auth_handler_name=auth_handler_name,
|
158
173
|
auth_provider=auth_provider,
|
159
|
-
auth_scopes=list(auth_scopes)
|
174
|
+
auth_scopes=list(auth_scopes),
|
175
|
+
)
|
160
176
|
|
161
177
|
return self.auth.prepare(
|
162
178
|
auth_req=auth_req,
|
@@ -164,15 +180,16 @@ class PocketCore:
|
|
164
180
|
auth_provider=auth_provider,
|
165
181
|
thread_id=thread_id,
|
166
182
|
profile=profile,
|
167
|
-
**kwargs
|
183
|
+
**kwargs,
|
168
184
|
)
|
169
185
|
|
170
186
|
async def authenticate(
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
187
|
+
self,
|
188
|
+
tool_name: str,
|
189
|
+
thread_id: str = "default",
|
190
|
+
profile: str = "default",
|
191
|
+
**kwargs,
|
192
|
+
) -> dict[str, str]:
|
176
193
|
"""
|
177
194
|
Authenticates the handler included in the tool and returns credentials.
|
178
195
|
|
@@ -190,7 +207,8 @@ class PocketCore:
|
|
190
207
|
auth_req = self.auth.make_request(
|
191
208
|
auth_handler_name=tool.auth.auth_handler,
|
192
209
|
auth_provider=tool.auth.auth_provider,
|
193
|
-
auth_scopes=tool.auth.scopes
|
210
|
+
auth_scopes=tool.auth.scopes,
|
211
|
+
)
|
194
212
|
auth_ctx = await self.auth.authenticate_async(
|
195
213
|
auth_req=auth_req,
|
196
214
|
auth_handler_name=tool.auth.auth_handler,
|