hyperpocket 0.3.3__py3-none-any.whl → 0.3.4__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.
@@ -0,0 +1,28 @@
1
+ ### API Token Auth
2
+
3
+ This module provides authentication using simple API tokens.
4
+
5
+ 1. To use this authentication in your tool, include the following in your `config.toml`:
6
+
7
+ ```toml
8
+ [auth]
9
+ auth_provider = "apitoken"
10
+ auth_handler = "apitoken"
11
+ scopes = []
12
+ ```
13
+
14
+ 2. To use it with `function_tool`, you can define your function as follows:
15
+
16
+ ```python
17
+ from hyperpocket.tool import function_tool
18
+ from hyperpocket.auth import AuthProvider
19
+
20
+
21
+ @function_tool(
22
+ auth_provider=AuthProvider.API_TOKEN
23
+ )
24
+ def my_function(**kwargs):
25
+ token = kwargs["API_TOKEN"]
26
+
27
+ # ...
28
+ ```
File without changes
@@ -0,0 +1,15 @@
1
+ from hyperpocket.auth.context import AuthContext
2
+
3
+
4
+ class ApiTokenAuthContext(AuthContext):
5
+ _ACCESS_TOKEN_KEY: str = "API_TOKEN"
6
+
7
+ def to_dict(self) -> dict[str, str]:
8
+ return {
9
+ self._ACCESS_TOKEN_KEY: self.access_token,
10
+ }
11
+
12
+ def to_profiled_dict(self, profile: str) -> dict[str, str]:
13
+ return {
14
+ f"{profile.upper()}_{self._ACCESS_TOKEN_KEY}": self.access_token,
15
+ }
@@ -0,0 +1,12 @@
1
+ from hyperpocket.auth.apitoken.context import ApiTokenAuthContext
2
+ from hyperpocket.auth.apitoken.token_schema import ApiTokenResponse
3
+
4
+
5
+ class ApiTokenAuthContext(ApiTokenAuthContext):
6
+ @classmethod
7
+ def from_api_token_response(cls, response: ApiTokenResponse):
8
+ description = "Api Token Context logged in"
9
+
10
+ return cls(
11
+ access_token=response.access_token, description=description, expires_at=None
12
+ )
@@ -0,0 +1,89 @@
1
+ from typing import Optional
2
+ from urllib.parse import urlencode, urljoin
3
+
4
+ from hyperpocket.auth import AuthProvider
5
+ from hyperpocket.auth.context import AuthContext
6
+ from hyperpocket.auth.handler import AuthHandlerInterface
7
+ from hyperpocket.auth.apitoken.token_context import ApiTokenAuthContext
8
+ from hyperpocket.auth.apitoken.token_schema import ApiTokenRequest, ApiTokenResponse
9
+ from hyperpocket.config import config
10
+ from hyperpocket.futures import FutureStore
11
+
12
+
13
+ class ApiTokenAuthHandler(AuthHandlerInterface):
14
+ name: str = "apitoken"
15
+ description: str = "This handler is used to authenticate users using the Api token."
16
+ scoped: bool = False
17
+
18
+ _TOKEN_URL: str = urljoin(
19
+ config().public_base_url + "/",
20
+ f"{config().callback_url_rewrite_prefix}/auth/token",
21
+ )
22
+
23
+ @staticmethod
24
+ def provider() -> AuthProvider:
25
+ return AuthProvider.APITOKEN
26
+
27
+ @staticmethod
28
+ def recommended_scopes() -> set[str]:
29
+ return set()
30
+
31
+ @staticmethod
32
+ def provider_default() -> bool:
33
+ return True
34
+
35
+ def prepare(
36
+ self,
37
+ auth_req: ApiTokenRequest,
38
+ thread_id: str,
39
+ profile: str,
40
+ future_uid: str,
41
+ *args,
42
+ **kwargs,
43
+ ) -> str:
44
+ redirect_uri = urljoin(
45
+ config().public_base_url + "/",
46
+ f"{config().callback_url_rewrite_prefix}/auth/apitoken/token/callback",
47
+ )
48
+ url = self._make_auth_url(
49
+ auth_req=auth_req, redirect_uri=redirect_uri, state=future_uid
50
+ )
51
+ FutureStore.create_future(
52
+ future_uid,
53
+ data={
54
+ "redirect_uri": redirect_uri,
55
+ "thread_id": thread_id,
56
+ "profile": profile,
57
+ },
58
+ )
59
+
60
+ return f"User needs to authenticate using the following URL: {url}"
61
+
62
+ async def authenticate(
63
+ self, auth_req: ApiTokenRequest, future_uid: str, *args, **kwargs
64
+ ) -> AuthContext:
65
+ future_data = FutureStore.get_future(future_uid)
66
+ access_token = await future_data.future
67
+
68
+ response = ApiTokenResponse(access_token=access_token)
69
+ context = ApiTokenAuthContext.from_api_token_response(response)
70
+
71
+ return context
72
+
73
+ async def refresh(
74
+ self, auth_req: ApiTokenRequest, context: AuthContext, *args, **kwargs
75
+ ) -> AuthContext:
76
+ raise Exception("Api token doesn't support refresh")
77
+
78
+ def _make_auth_url(self, auth_req: ApiTokenRequest, redirect_uri: str, state: str):
79
+ params = {
80
+ "redirect_uri": redirect_uri,
81
+ "state": state,
82
+ }
83
+ auth_url = f"{self._TOKEN_URL}?{urlencode(params)}"
84
+ return auth_url
85
+
86
+ def make_request(
87
+ self, auth_scopes: Optional[list[str]] = None, **kwargs
88
+ ) -> ApiTokenRequest:
89
+ return ApiTokenRequest()
@@ -0,0 +1,9 @@
1
+ from hyperpocket.auth.schema import AuthenticateRequest, AuthenticateResponse
2
+
3
+
4
+ class ApiTokenRequest(AuthenticateRequest):
5
+ pass
6
+
7
+
8
+ class ApiTokenResponse(AuthenticateResponse):
9
+ access_token: str
@@ -10,7 +10,9 @@ class AuthProvider(Enum):
10
10
  NOTION = "notion"
11
11
  REDDIT = "reddit"
12
12
  GUMLOOP = "gumloop"
13
+ SERPAPI = "serpapi"
13
14
  X = "x"
15
+ APITOKEN = "apitoken"
14
16
 
15
17
  @classmethod
16
18
  def get_auth_provider(cls, auth_provider_name: str) -> "AuthProvider":
File without changes
@@ -0,0 +1,15 @@
1
+ from hyperpocket.auth.context import AuthContext
2
+
3
+
4
+ class SerpapiAuthContext(AuthContext):
5
+ _ACCESS_TOKEN_KEY: str = "SERPAPI_TOKEN"
6
+
7
+ def to_dict(self) -> dict[str, str]:
8
+ return {
9
+ self._ACCESS_TOKEN_KEY: self.access_token,
10
+ }
11
+
12
+ def to_profiled_dict(self, profile: str) -> dict[str, str]:
13
+ return {
14
+ f"{profile.upper()}_{self._ACCESS_TOKEN_KEY}": self.access_token,
15
+ }
@@ -0,0 +1,13 @@
1
+ from hyperpocket.auth.serpapi.context import SerpapiAuthContext
2
+ from hyperpocket.auth.serpapi.token_schema import SerpapiTokenResponse
3
+
4
+
5
+ class SerpapiTokenAuthContext(SerpapiAuthContext):
6
+ @classmethod
7
+ def from_serpapi_token_response(cls, response: SerpapiTokenResponse):
8
+ description = f'Serpapi Token Context logged in'
9
+ return cls(
10
+ access_token=response.access_token,
11
+ description=description,
12
+ expires_at=None
13
+ )
@@ -0,0 +1,68 @@
1
+ from typing import Optional
2
+ from urllib.parse import urljoin, urlencode
3
+
4
+ from hyperpocket.auth import AuthProvider
5
+ from hyperpocket.auth.context import AuthContext
6
+ from hyperpocket.auth.handler import AuthHandlerInterface, AuthenticateRequest
7
+ from hyperpocket.auth.serpapi.token_context import SerpapiTokenAuthContext
8
+ from hyperpocket.auth.serpapi.token_schema import SerpapiTokenResponse, SerpapiTokenRequest
9
+ from hyperpocket.config import config
10
+ from hyperpocket.futures import FutureStore
11
+
12
+
13
+ class SerpapiTokenAuthHandler(AuthHandlerInterface):
14
+ name: str = "serpapi-token"
15
+ description: str = "This handler is used to authenticate users using the Serpapi token."
16
+ scoped: bool = False
17
+
18
+ _TOKEN_URL: str = urljoin(config().public_base_url + "/", f"{config().callback_url_rewrite_prefix}/auth/token")
19
+
20
+ @staticmethod
21
+ def provider_default() -> bool:
22
+ return True
23
+
24
+ @staticmethod
25
+ def provider() -> AuthProvider:
26
+ return AuthProvider.SERPAPI
27
+
28
+ @staticmethod
29
+ def recommended_scopes() -> set[str]:
30
+ return set()
31
+
32
+ def prepare(self, auth_req: SerpapiTokenRequest, thread_id: str, profile: str,
33
+ future_uid: str, *args, **kwargs) -> str:
34
+ redirect_uri = urljoin(
35
+ config().public_base_url + "/",
36
+ f"{config().callback_url_rewrite_prefix}/auth/serpapi/token/callback",
37
+ )
38
+ url = self._make_auth_url(auth_req=auth_req, redirect_uri=redirect_uri, state=future_uid)
39
+ FutureStore.create_future(future_uid, data={
40
+ "redirect_uri": redirect_uri,
41
+ "thread_id": thread_id,
42
+ "profile": profile,
43
+ })
44
+
45
+ return f'User needs to authenticate using the following URL: {url}'
46
+
47
+ async def authenticate(self, auth_req: SerpapiTokenRequest, future_uid: str, *args, **kwargs) -> AuthContext:
48
+ future_data = FutureStore.get_future(future_uid)
49
+ access_token = await future_data.future
50
+
51
+ response = SerpapiTokenResponse(access_token=access_token)
52
+ context = SerpapiTokenAuthContext.from_serpapi_token_response(response)
53
+
54
+ return context
55
+
56
+ async def refresh(self, auth_req: SerpapiTokenRequest, context: AuthContext, *args, **kwargs) -> AuthContext:
57
+ raise Exception("Serpapi token doesn't support refresh")
58
+
59
+ def _make_auth_url(self, auth_req: SerpapiTokenRequest, redirect_uri: str, state: str):
60
+ params = {
61
+ "redirect_uri": redirect_uri,
62
+ "state": state,
63
+ }
64
+ auth_url = f"{self._TOKEN_URL}?{urlencode(params)}"
65
+ return auth_url
66
+
67
+ def make_request(self, auth_scopes: Optional[list[str]] = None, **kwargs) -> SerpapiTokenRequest:
68
+ return SerpapiTokenRequest()
@@ -0,0 +1,11 @@
1
+ from typing import List, Optional
2
+ from pydantic import BaseModel
3
+ from hyperpocket.auth.schema import AuthenticateRequest, AuthenticateResponse
4
+
5
+
6
+ class SerpapiTokenRequest(AuthenticateRequest):
7
+ pass
8
+
9
+
10
+ class SerpapiTokenResponse(AuthenticateResponse):
11
+ access_token: str
@@ -0,0 +1,16 @@
1
+ from fastapi import APIRouter
2
+ from starlette.responses import HTMLResponse
3
+
4
+ from hyperpocket.futures import FutureStore
5
+
6
+ api_token_auth_router = APIRouter(prefix="/apitoken")
7
+
8
+
9
+ @api_token_auth_router.get("/token/callback")
10
+ async def notion_token_callback(state: str, token: str):
11
+ try:
12
+ FutureStore.resolve_future(state, token)
13
+ except ValueError:
14
+ return HTMLResponse(content="failed")
15
+
16
+ return HTMLResponse(content="success")
@@ -0,0 +1,14 @@
1
+
2
+ from fastapi import APIRouter
3
+ from starlette.responses import HTMLResponse
4
+ from hyperpocket.futures import FutureStore
5
+ serpapi_auth_router = APIRouter(
6
+ prefix="/serpapi"
7
+ )
8
+ @serpapi_auth_router.get("/token/callback")
9
+ async def serpapi_token_callback(state: str, token: str):
10
+ try:
11
+ FutureStore.resolve_future(state, token)
12
+ except ValueError:
13
+ return HTMLResponse(content="failed")
14
+ return HTMLResponse(content="success")
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: hyperpocket
3
- Version: 0.3.3
3
+ Version: 0.3.4
4
4
  Summary: Building AI agent with hyperpocket tool in a flash
5
5
  Project-URL: Homepage, https://vessl-ai.github.io/hyperpocket
6
6
  Project-URL: Repository, https://github.com/vessl-ai/hyperpocket
@@ -10,8 +10,14 @@ hyperpocket/auth/README.md,sha256=zn4QqnFZCA_4X3x8Wb6lE3OP5otYxpByZaCiUkBvaNs,11
10
10
  hyperpocket/auth/__init__.py,sha256=pO8M6SAuq0EPqi848_Iy650wqaLekx98e3RRnEAM_r0,607
11
11
  hyperpocket/auth/context.py,sha256=m-j2gDYUKBMsiakLHsu9thhM4dYyFiXP0Wp0S_iC0bU,1303
12
12
  hyperpocket/auth/handler.py,sha256=5cusl9ANEyG3gORVFjqh709txC0alw6eKtxgV6wjf6k,6683
13
- hyperpocket/auth/provider.py,sha256=Fe5kYX093sd9K0fakPVXYqXL6oIhdPU530W8pkVzZHU,515
13
+ hyperpocket/auth/provider.py,sha256=oy00TuxaQk51nsXnOimLvY3gQzn-jOFgIywSlGuWa1Q,565
14
14
  hyperpocket/auth/schema.py,sha256=pl4oRTNj8PdqQg6UVPWf8ei2uYQ4DtOmmD58cVFMYQw,537
15
+ hyperpocket/auth/apitoken/README.md,sha256=Sq5w_v3_JVp2k3Jaywmx_y_-ytw2Cs_oEeYveoXZVA0,564
16
+ hyperpocket/auth/apitoken/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
17
+ hyperpocket/auth/apitoken/context.py,sha256=uIXQsR7iiJEETOMcAy7s74Fob8N55FqWfUMQPfWGKY4,426
18
+ hyperpocket/auth/apitoken/token_context.py,sha256=3Uet_XfJBi7p8fkgwkT63uFJozq84TzFRpziUEoQVac,439
19
+ hyperpocket/auth/apitoken/token_handler.py,sha256=-BrBgkrPegNaA-03I1I7pBtHHfImbqM6UtlHVR-2zmY,2813
20
+ hyperpocket/auth/apitoken/token_schema.py,sha256=MGaOcRzuobpAPyMBjbwvy32RHhjOOr7D0lXIlkpX7jM,203
15
21
  hyperpocket/auth/calendly/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
16
22
  hyperpocket/auth/calendly/context.py,sha256=oUQzLy_w5NPvbXjFPOhLD-ggONVSy9VVpFabvX4ZpsY,408
17
23
  hyperpocket/auth/calendly/oauth2_context.py,sha256=SiMeZaoWh3aneZVH_MXsT_cZ8qCSVeL-pWHVbfYUS6g,848
@@ -51,6 +57,11 @@ hyperpocket/auth/reddit/context.py,sha256=WlOvIb4u1PvfrbkYbEq5cSRnXxmIEFuHa4LlKj
51
57
  hyperpocket/auth/reddit/oauth2_context.py,sha256=v1u_uy6O52REp2anteTPNgvb_nX-hI6bM7jNngBZXq4,1015
52
58
  hyperpocket/auth/reddit/oauth2_handler.py,sha256=X_lzoyhYnjEFriBuorGdn977uD5GjphPiXi8W9SYdy0,5166
53
59
  hyperpocket/auth/reddit/oauth2_schema.py,sha256=MOcA8VTvjjwewxhyIn_-DRNf6H_5GjsN6C7gV8sDyiI,436
60
+ hyperpocket/auth/serpapi/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
61
+ hyperpocket/auth/serpapi/context.py,sha256=c1CuL53q22kyewrdc4Ae3zNclR87i_WWZ3n46aY3uoA,429
62
+ hyperpocket/auth/serpapi/token_context.py,sha256=0sK9FSAA4takB02EdHEiYvLs46aN_Es8QZ7e4nQo3ec,479
63
+ hyperpocket/auth/serpapi/token_handler.py,sha256=JFXm99eQUmMWfOhJcIqiJ4DIQEMKePou-Pft17PRkFA,2710
64
+ hyperpocket/auth/serpapi/token_schema.py,sha256=gJ2ONKEwVI057U2lyFD7RQJs3HVSoCwN2lMxiU4mEOU,276
54
65
  hyperpocket/auth/slack/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
55
66
  hyperpocket/auth/slack/context.py,sha256=f8dMs7QtSSyissOlPGw8rCZXsVUckFnZWjZ_LAmNXpA,429
56
67
  hyperpocket/auth/slack/oauth2_context.py,sha256=kwahsgxtDo5Wg_nrF8mFv16ijIu6biiGe_qz2JlEKjM,1398
@@ -100,6 +111,7 @@ hyperpocket/server/__init__.py,sha256=8laNl098-IkFkarqwOZs_gm6yG0q3NAObq4cCUxK_T
100
111
  hyperpocket/server/proxy.py,sha256=ItM1qfuUBs6QiPqIpErBWUZWdtsEf0twPJY5r2UUFBU,2042
101
112
  hyperpocket/server/server.py,sha256=KQxspdmw7SQtJpXZYbwaE5z9QwQRAQgXGaixYi6JlI0,8756
102
113
  hyperpocket/server/auth/__init__.py,sha256=IMjz9PCzD7qh4QIf2g-gWIdkDeU36jt-9F55vaHvLoM,286
114
+ hyperpocket/server/auth/apitoken.py,sha256=I-ZDEehzwh7WsoHBnNTW1MZDRcmzNucNVBvGNHFjaao,451
103
115
  hyperpocket/server/auth/calendly.py,sha256=mi9_ysn0SffhnEgaoNa2jcHWCcD_yzqkS0rvzpJG2Qg,478
104
116
  hyperpocket/server/auth/github.py,sha256=5ZdKYoq_1Bh6aLUbSB5RWvr3o5DihZ5Gz5AfRWd4aCg,761
105
117
  hyperpocket/server/auth/google.py,sha256=_C33Bzow7yzjnvf0WUObu8p-dSU5rXqBgSPrENORAmY,470
@@ -107,6 +119,7 @@ hyperpocket/server/auth/gumloop.py,sha256=t_BUQ7RR8_x-ogqXnQ3iNHTVthzJyUTN03iqtR
107
119
  hyperpocket/server/auth/linear.py,sha256=Awd7GC5dIrwKnVthjW_MxutYIUz38DgC9L7BUcVfB04,442
108
120
  hyperpocket/server/auth/notion.py,sha256=NUKwCK61UADhO4FmFpNYjh1vsDzFZoFRDHdcMIBGb6M,443
109
121
  hyperpocket/server/auth/reddit.py,sha256=UloBQNEdhU1_eXaF8qVSQ5ivq5xtWINsHvBDGwgFSLM,443
122
+ hyperpocket/server/auth/serpapi.py,sha256=YCyUAYXNEoXQ3nkPiyrDs-WguUo2lfO-pEZTpHoWwr8,448
110
123
  hyperpocket/server/auth/slack.py,sha256=frMNtBEfe3fbeNzsQ8udapeau45NZmS8guATmS46qyA,710
111
124
  hyperpocket/server/auth/token.py,sha256=Yq5Ym-uEO_3cBpQOsmCBuqtFIdImrNcVUgF5ozs5NHk,1763
112
125
  hyperpocket/server/auth/x.py,sha256=CYCD_ajBY6Jt04E2bSEBZFRRIUZmNjF2gn6F0ZV5XuA,450
@@ -144,7 +157,7 @@ hyperpocket/util/flatten_json_schema.py,sha256=iuNBEmMSKFtPi-uqo6fb3RWN0koHOAihW
144
157
  hyperpocket/util/function_to_model.py,sha256=TXUs-qPbzL8C9-qqpz4Ad4D9MOPP61n_p0iPU6SoBeM,2318
145
158
  hyperpocket/util/get_objects_from_subpackage.py,sha256=4mR_S8eaJSdU68YfCkiXeIcXxb6q7LjFGsY_IHeNIZw,929
146
159
  hyperpocket/util/json_schema_to_model.py,sha256=PqI87pU5dWwcrQWB8eQxRdfgAEvvC1x_DKZnhcsRV-o,3586
147
- hyperpocket-0.3.3.dist-info/METADATA,sha256=SyPQKiQ-LsCfP9vHGwHw-PQOz_wlwjh2o2lSSngYn8w,12958
148
- hyperpocket-0.3.3.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
149
- hyperpocket-0.3.3.dist-info/entry_points.txt,sha256=KpBleaYr0SaENXOa-dFvJ_cvFCHYFEQ4LMl11ShAcBI,61
150
- hyperpocket-0.3.3.dist-info/RECORD,,
160
+ hyperpocket-0.3.4.dist-info/METADATA,sha256=x-XIo1chvunVMxpg7jiSok5x6W1cWj2QAFjMlo_g0zU,12958
161
+ hyperpocket-0.3.4.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
162
+ hyperpocket-0.3.4.dist-info/entry_points.txt,sha256=KpBleaYr0SaENXOa-dFvJ_cvFCHYFEQ4LMl11ShAcBI,61
163
+ hyperpocket-0.3.4.dist-info/RECORD,,