hyperpocket 0.1.9__py3-none-any.whl → 0.2.0__py3-none-any.whl
Sign up to get free protection for your applications and to get access to all the features.
- 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,
|