hyperpocket 0.1.10__py3-none-any.whl → 0.2.1__py3-none-any.whl

Sign up to get free protection for your applications and to get access to all the features.
Files changed (92) hide show
  1. hyperpocket/__init__.py +4 -4
  2. hyperpocket/auth/__init__.py +12 -7
  3. hyperpocket/auth/calendly/oauth2_handler.py +24 -17
  4. hyperpocket/auth/calendly/oauth2_schema.py +3 -1
  5. hyperpocket/auth/context.py +2 -1
  6. hyperpocket/auth/github/oauth2_handler.py +13 -8
  7. hyperpocket/auth/github/token_handler.py +27 -21
  8. hyperpocket/auth/google/context.py +1 -3
  9. hyperpocket/auth/google/oauth2_context.py +1 -1
  10. hyperpocket/auth/google/oauth2_handler.py +22 -17
  11. hyperpocket/auth/gumloop/token_context.py +1 -4
  12. hyperpocket/auth/gumloop/token_handler.py +48 -20
  13. hyperpocket/auth/gumloop/token_schema.py +2 -1
  14. hyperpocket/auth/handler.py +21 -6
  15. hyperpocket/auth/linear/token_context.py +2 -5
  16. hyperpocket/auth/linear/token_handler.py +45 -21
  17. hyperpocket/auth/notion/context.py +2 -2
  18. hyperpocket/auth/notion/token_context.py +2 -4
  19. hyperpocket/auth/notion/token_handler.py +45 -21
  20. hyperpocket/auth/notion/token_schema.py +0 -1
  21. hyperpocket/auth/reddit/oauth2_handler.py +9 -10
  22. hyperpocket/auth/reddit/oauth2_schema.py +0 -2
  23. hyperpocket/auth/schema.py +4 -1
  24. hyperpocket/auth/slack/oauth2_context.py +3 -1
  25. hyperpocket/auth/slack/oauth2_handler.py +55 -35
  26. hyperpocket/auth/slack/token_context.py +2 -4
  27. hyperpocket/auth/slack/token_handler.py +42 -19
  28. hyperpocket/builtin.py +4 -2
  29. hyperpocket/cli/__main__.py +4 -2
  30. hyperpocket/cli/auth.py +59 -28
  31. hyperpocket/cli/codegen/auth/auth_context_template.py +3 -2
  32. hyperpocket/cli/codegen/auth/auth_token_context_template.py +3 -2
  33. hyperpocket/cli/codegen/auth/auth_token_handler_template.py +6 -5
  34. hyperpocket/cli/codegen/auth/auth_token_schema_template.py +3 -2
  35. hyperpocket/cli/codegen/auth/server_auth_template.py +3 -2
  36. hyperpocket/cli/pull.py +5 -5
  37. hyperpocket/config/__init__.py +3 -8
  38. hyperpocket/config/auth.py +3 -1
  39. hyperpocket/config/logger.py +20 -15
  40. hyperpocket/config/session.py +4 -2
  41. hyperpocket/config/settings.py +19 -2
  42. hyperpocket/futures/__init__.py +1 -1
  43. hyperpocket/futures/futurestore.py +3 -2
  44. hyperpocket/pocket_auth.py +171 -84
  45. hyperpocket/pocket_core.py +51 -33
  46. hyperpocket/pocket_main.py +122 -93
  47. hyperpocket/prompts.py +2 -2
  48. hyperpocket/repository/__init__.py +1 -1
  49. hyperpocket/repository/lock.py +47 -33
  50. hyperpocket/repository/lockfile.py +2 -2
  51. hyperpocket/repository/repository.py +1 -1
  52. hyperpocket/server/__init__.py +1 -1
  53. hyperpocket/server/auth/github.py +2 -1
  54. hyperpocket/server/auth/linear.py +1 -3
  55. hyperpocket/server/auth/notion.py +2 -5
  56. hyperpocket/server/auth/slack.py +1 -3
  57. hyperpocket/server/auth/token.py +17 -11
  58. hyperpocket/server/proxy.py +29 -13
  59. hyperpocket/server/server.py +75 -31
  60. hyperpocket/server/tool/dto/script.py +15 -10
  61. hyperpocket/server/tool/wasm.py +14 -11
  62. hyperpocket/session/__init__.py +6 -2
  63. hyperpocket/session/in_memory.py +44 -24
  64. hyperpocket/session/interface.py +42 -24
  65. hyperpocket/session/redis.py +48 -31
  66. hyperpocket/tool/__init__.py +10 -10
  67. hyperpocket/tool/function/__init__.py +1 -5
  68. hyperpocket/tool/function/annotation.py +11 -9
  69. hyperpocket/tool/function/tool.py +37 -27
  70. hyperpocket/tool/tool.py +59 -36
  71. hyperpocket/tool/wasm/__init__.py +1 -1
  72. hyperpocket/tool/wasm/browser.py +15 -10
  73. hyperpocket/tool/wasm/invoker.py +16 -16
  74. hyperpocket/tool/wasm/script.py +27 -14
  75. hyperpocket/tool/wasm/templates/__init__.py +22 -15
  76. hyperpocket/tool/wasm/templates/node.py +2 -2
  77. hyperpocket/tool/wasm/templates/python.py +2 -2
  78. hyperpocket/tool/wasm/tool.py +27 -14
  79. hyperpocket/tool_like.py +3 -3
  80. hyperpocket/util/__init__.py +1 -1
  81. hyperpocket/util/extract_func_param_desc_from_docstring.py +23 -7
  82. hyperpocket/util/find_all_leaf_class_in_package.py +4 -3
  83. hyperpocket/util/find_all_subclass_in_package.py +4 -2
  84. hyperpocket/util/flatten_json_schema.py +10 -6
  85. hyperpocket/util/function_to_model.py +33 -12
  86. hyperpocket/util/get_objects_from_subpackage.py +1 -1
  87. hyperpocket/util/json_schema_to_model.py +14 -5
  88. {hyperpocket-0.1.10.dist-info → hyperpocket-0.2.1.dist-info}/METADATA +11 -5
  89. hyperpocket-0.2.1.dist-info/RECORD +137 -0
  90. hyperpocket-0.1.10.dist-info/RECORD +0 -137
  91. {hyperpocket-0.1.10.dist-info → hyperpocket-0.2.1.dist-info}/WHEEL +0 -0
  92. {hyperpocket-0.1.10.dist-info → hyperpocket-0.2.1.dist-info}/entry_points.txt +0 -0
@@ -1,14 +1,18 @@
1
1
  import json
2
- from typing import List, Optional, Any
2
+ from typing import Any, List, Optional
3
3
 
4
4
  import redis
5
5
 
6
- from hyperpocket.auth import AuthProvider, AUTH_CONTEXT_MAP
6
+ from hyperpocket.auth import AUTH_CONTEXT_MAP, AuthProvider
7
7
  from hyperpocket.auth.context import AuthContext
8
- from hyperpocket.config.session import SessionConfigRedis
9
- from hyperpocket.config.session import SessionType
10
- from hyperpocket.session.interface import SessionStorageInterface, SESSION_KEY_DELIMITER, \
11
- BaseSessionValue, V, K
8
+ from hyperpocket.config.session import SessionConfigRedis, SessionType
9
+ from hyperpocket.session.interface import (
10
+ SESSION_KEY_DELIMITER,
11
+ BaseSessionValue,
12
+ K,
13
+ SessionStorageInterface,
14
+ V,
15
+ )
12
16
 
13
17
  RedisSessionKey = str
14
18
  RedisSessionValue = BaseSessionValue
@@ -24,7 +28,9 @@ class RedisSessionStorage(SessionStorageInterface[RedisSessionKey, RedisSessionV
24
28
  def session_storage_type(cls) -> SessionType:
25
29
  return SessionType.REDIS
26
30
 
27
- def get(self, auth_provider: AuthProvider, thread_id: str, profile: str, **kwargs) -> Optional[V]:
31
+ def get(
32
+ self, auth_provider: AuthProvider, thread_id: str, profile: str, **kwargs
33
+ ) -> Optional[V]:
28
34
  key = self._make_session_key(auth_provider.name, thread_id, profile)
29
35
  raw_session: Any = self.client.get(key)
30
36
  if raw_session is None:
@@ -33,7 +39,9 @@ class RedisSessionStorage(SessionStorageInterface[RedisSessionKey, RedisSessionV
33
39
  session = self._deserialize(raw_session)
34
40
  return session
35
41
 
36
- def get_by_thread_id(self, thread_id: str, auth_provider: Optional[AuthProvider] = None, **kwargs) -> List[V]:
42
+ def get_by_thread_id(
43
+ self, thread_id: str, auth_provider: Optional[AuthProvider] = None, **kwargs
44
+ ) -> List[V]:
37
45
  if auth_provider is None:
38
46
  auth_provider_name = "*"
39
47
  else:
@@ -57,19 +65,24 @@ class RedisSessionStorage(SessionStorageInterface[RedisSessionKey, RedisSessionV
57
65
 
58
66
  return session_list
59
67
 
60
- def set(self, auth_provider: AuthProvider,
61
- thread_id: str,
62
- profile: str,
63
- auth_scopes: List[str],
64
- auth_resolve_uid: Optional[str],
65
- auth_context: Optional[AuthContext],
66
- is_auth_scope_universal: bool, **kwargs) -> V:
68
+ def set(
69
+ self,
70
+ auth_provider: AuthProvider,
71
+ thread_id: str,
72
+ profile: str,
73
+ auth_scopes: List[str],
74
+ auth_resolve_uid: Optional[str],
75
+ auth_context: Optional[AuthContext],
76
+ is_auth_scope_universal: bool,
77
+ **kwargs,
78
+ ) -> V:
67
79
  session = self._make_session(
68
80
  auth_provider_name=auth_provider.name,
69
81
  auth_scopes=auth_scopes,
70
82
  auth_context=auth_context,
71
83
  auth_resolve_uid=auth_resolve_uid,
72
- is_auth_scope_universal=is_auth_scope_universal)
84
+ is_auth_scope_universal=is_auth_scope_universal,
85
+ )
73
86
 
74
87
  key = self._make_session_key(auth_provider.name, thread_id, profile)
75
88
 
@@ -77,7 +90,9 @@ class RedisSessionStorage(SessionStorageInterface[RedisSessionKey, RedisSessionV
77
90
  self.client.set(key, raw_session)
78
91
  return session
79
92
 
80
- def delete(self, auth_provider: AuthProvider, thread_id: str, profile: str, **kwargs) -> bool:
93
+ def delete(
94
+ self, auth_provider: AuthProvider, thread_id: str, profile: str, **kwargs
95
+ ) -> bool:
81
96
  key = self._make_session_key(auth_provider.name, thread_id, profile)
82
97
  return self.client.delete(key) == 1
83
98
 
@@ -92,17 +107,18 @@ class RedisSessionStorage(SessionStorageInterface[RedisSessionKey, RedisSessionV
92
107
 
93
108
  @staticmethod
94
109
  def _make_session(
95
- auth_provider_name: str,
96
- auth_scopes: List[str],
97
- auth_context: AuthContext,
98
- auth_resolve_uid: str,
99
- is_auth_scope_universal: bool) -> V:
110
+ auth_provider_name: str,
111
+ auth_scopes: List[str],
112
+ auth_context: AuthContext,
113
+ auth_resolve_uid: str,
114
+ is_auth_scope_universal: bool,
115
+ ) -> V:
100
116
  return RedisSessionValue(
101
117
  auth_provider_name=auth_provider_name,
102
118
  auth_scopes=set(auth_scopes),
103
119
  auth_context=auth_context,
104
120
  auth_resolve_uid=auth_resolve_uid,
105
- scoped=is_auth_scope_universal
121
+ scoped=is_auth_scope_universal,
106
122
  )
107
123
 
108
124
  @staticmethod
@@ -116,13 +132,14 @@ class RedisSessionStorage(SessionStorageInterface[RedisSessionKey, RedisSessionV
116
132
  if auth_scopes:
117
133
  auth_scopes = list(auth_scopes)
118
134
 
119
- serialized = {"auth_context_value": auth_context_value,
120
- "auth_context_type": auth_context_type,
121
- "auth_provider_name": session.auth_provider_name,
122
- "scoped": session.scoped,
123
- "auth_scopes": auth_scopes,
124
- "auth_resolve_uid": session.auth_resolve_uid,
125
- }
135
+ serialized = {
136
+ "auth_context_value": auth_context_value,
137
+ "auth_context_type": auth_context_type,
138
+ "auth_provider_name": session.auth_provider_name,
139
+ "scoped": session.scoped,
140
+ "auth_scopes": auth_scopes,
141
+ "auth_resolve_uid": session.auth_resolve_uid,
142
+ }
126
143
 
127
144
  return json.dumps(serialized)
128
145
 
@@ -146,5 +163,5 @@ class RedisSessionStorage(SessionStorageInterface[RedisSessionKey, RedisSessionV
146
163
  auth_scopes=auth_scopes,
147
164
  auth_resolve_uid=session_dict["auth_resolve_uid"],
148
165
  scoped=session_dict["scoped"],
149
- auth_context=auth_context
166
+ auth_context=auth_context,
150
167
  )
@@ -1,14 +1,14 @@
1
1
  from hyperpocket.tool.function import from_dock, from_func, function_tool
2
- from hyperpocket.tool.tool import Tool, ToolRequest, ToolAuth
3
- from hyperpocket.tool.wasm.tool import from_local, from_git
2
+ from hyperpocket.tool.tool import Tool, ToolAuth, ToolRequest
3
+ from hyperpocket.tool.wasm.tool import from_git, from_local
4
4
 
5
5
  __all__ = [
6
- 'Tool',
7
- 'ToolAuth',
8
- 'ToolRequest',
9
- 'from_local',
10
- 'from_git',
11
- 'from_dock',
12
- 'from_func',
13
- 'function_tool'
6
+ "Tool",
7
+ "ToolAuth",
8
+ "ToolRequest",
9
+ "from_local",
10
+ "from_git",
11
+ "from_dock",
12
+ "from_func",
13
+ "function_tool",
14
14
  ]
@@ -4,8 +4,4 @@ from hyperpocket.tool.function.tool import FunctionTool
4
4
  from_func = FunctionTool.from_func
5
5
  from_dock = FunctionTool.from_dock
6
6
 
7
- __all__ = [
8
- "from_func",
9
- "from_dock",
10
- "function_tool"
11
- ]
7
+ __all__ = ["from_func", "from_dock", "function_tool"]
@@ -1,12 +1,18 @@
1
- from typing import List, Callable, Optional
1
+ from typing import Callable, List, Optional
2
2
 
3
3
  from hyperpocket.auth import AuthProvider
4
4
  from hyperpocket.tool.function.tool import FunctionTool
5
5
  from hyperpocket.tool.tool import ToolAuth
6
6
 
7
7
 
8
- def function_tool(func: Optional[Callable] = None, *, auth_provider: AuthProvider = None, scopes: List[str] = None,
9
- auth_handler: str = None, tool_vars: dict[str, str] = None):
8
+ def function_tool(
9
+ func: Optional[Callable] = None,
10
+ *,
11
+ auth_provider: AuthProvider = None,
12
+ scopes: List[str] = None,
13
+ auth_handler: str = None,
14
+ tool_vars: dict[str, str] = None,
15
+ ):
10
16
  def decorator(inner_func: Callable):
11
17
  if not callable(inner_func):
12
18
  raise ValueError("FunctionTool can only be created from a callable")
@@ -15,14 +21,10 @@ def function_tool(func: Optional[Callable] = None, *, auth_provider: AuthProvide
15
21
  auth = ToolAuth(
16
22
  auth_provider=auth_provider,
17
23
  scopes=scopes if scopes else [],
18
- auth_handler=auth_handler
24
+ auth_handler=auth_handler,
19
25
  )
20
26
 
21
- return FunctionTool.from_func(
22
- func=inner_func,
23
- auth=auth,
24
- tool_vars=tool_vars
25
- )
27
+ return FunctionTool.from_func(func=inner_func, auth=auth, tool_vars=tool_vars)
26
28
 
27
29
  if func is not None:
28
30
  return decorator(func)
@@ -1,8 +1,7 @@
1
1
  import asyncio
2
2
  import copy
3
3
  import inspect
4
- from typing import Any, Coroutine
5
- from typing import Callable, Optional
4
+ from typing import Any, Callable, Coroutine, Optional
6
5
 
7
6
  from pydantic import BaseModel
8
7
 
@@ -15,6 +14,7 @@ class FunctionTool(Tool):
15
14
  """
16
15
  FunctionTool is Tool executing local python method.
17
16
  """
17
+
18
18
  func: Optional[Callable[..., str]]
19
19
  afunc: Optional[Callable[..., Coroutine[Any, Any, str]]]
20
20
 
@@ -90,14 +90,14 @@ class FunctionTool(Tool):
90
90
  @classmethod
91
91
  def from_func(
92
92
  cls,
93
- func: Callable | 'FunctionTool',
94
- afunc: Callable[..., Coroutine[Any, Any, str]] | 'FunctionTool' = None,
93
+ func: Callable | "FunctionTool",
94
+ afunc: Callable[..., Coroutine[Any, Any, str]] | "FunctionTool" = None,
95
95
  auth: Optional[ToolAuth] = None,
96
96
  tool_vars: dict[str, str] = None,
97
97
  ) -> "FunctionTool":
98
98
  if tool_vars is None:
99
99
  tool_vars = dict()
100
-
100
+
101
101
  if isinstance(func, FunctionTool):
102
102
  if tool_vars is not None:
103
103
  func.override_tool_variables(tool_vars)
@@ -108,7 +108,7 @@ class FunctionTool(Tool):
108
108
  return afunc
109
109
  elif not callable(func) and not callable(afunc):
110
110
  raise ValueError("FunctionTool can only be created from a callable")
111
-
111
+
112
112
  model = function_to_model(func)
113
113
  argument_json_schema = flatten_json_schema(model.model_json_schema())
114
114
 
@@ -119,9 +119,9 @@ class FunctionTool(Tool):
119
119
  description=func.__doc__ if func.__doc__ is not None else "",
120
120
  argument_json_schema=argument_json_schema,
121
121
  auth=auth,
122
- default_tool_vars=tool_vars
122
+ default_tool_vars=tool_vars,
123
123
  )
124
-
124
+
125
125
  @classmethod
126
126
  def from_dock(
127
127
  cls,
@@ -138,29 +138,39 @@ class FunctionTool(Tool):
138
138
  model = function_to_model(func)
139
139
  argument_json_schema = flatten_json_schema(model.model_json_schema())
140
140
  if not callable(func):
141
- raise ValueError(f"Dock element should be a list of functions, but found {func}")
141
+ raise ValueError(
142
+ f"Dock element should be a list of functions, but found {func}"
143
+ )
142
144
  is_coroutine = inspect.iscoroutinefunction(func)
143
145
  auth = None
144
146
  if func.__dict__.get("__auth__") is not None:
145
147
  auth = ToolAuth(**func.__dict__["__auth__"])
146
148
  if is_coroutine:
147
- tools.append(cls(
148
- func=None,
149
- afunc=func,
150
- name=func.__name__,
151
- description=func.__doc__,
152
- argument_json_schema=argument_json_schema,
153
- auth=auth,
154
- default_tool_vars=(tool_vars | func.__dict__.get("__vars__", {})),
155
- ))
149
+ tools.append(
150
+ cls(
151
+ func=None,
152
+ afunc=func,
153
+ name=func.__name__,
154
+ description=func.__doc__,
155
+ argument_json_schema=argument_json_schema,
156
+ auth=auth,
157
+ default_tool_vars=(
158
+ tool_vars | func.__dict__.get("__vars__", {})
159
+ ),
160
+ )
161
+ )
156
162
  else:
157
- tools.append(cls(
158
- func=func,
159
- afunc=None,
160
- name=func.__name__,
161
- description=func.__doc__,
162
- argument_json_schema=argument_json_schema,
163
- auth=auth,
164
- default_tool_vars=(tool_vars | func.__dict__.get("__vars__", {})),
165
- ))
163
+ tools.append(
164
+ cls(
165
+ func=func,
166
+ afunc=None,
167
+ name=func.__name__,
168
+ description=func.__doc__,
169
+ argument_json_schema=argument_json_schema,
170
+ auth=auth,
171
+ default_tool_vars=(
172
+ tool_vars | func.__dict__.get("__vars__", {})
173
+ ),
174
+ )
175
+ )
166
176
  return tools
hyperpocket/tool/tool.py CHANGED
@@ -1,5 +1,5 @@
1
1
  import abc
2
- from typing import Optional, Type, Callable
2
+ from typing import Callable, Optional, Type
3
3
 
4
4
  from pydantic import BaseModel, Field
5
5
 
@@ -13,23 +13,29 @@ class ToolAuth(BaseModel):
13
13
  """
14
14
  ToolAuth is an object that represents the authentication information required to invoke a tool
15
15
  """
16
+
16
17
  scopes: list[str] = Field(
17
18
  default=None,
18
19
  description="Indicates which authentication provider’s credentials are required to invoke the tool. "
19
- "If auth_provider is not specified, the tool is considered to require no authentication.")
20
+ "If auth_provider is not specified, the tool is considered to require no authentication.",
21
+ )
20
22
  auth_provider: Optional[AuthProvider] = Field(
21
23
  default=None,
22
24
  description="Specifies which authentication handler should be used when invoking the tool. "
23
- "If auth_handler is not specified, the default handler of the authentication provider will be used.")
25
+ "If auth_handler is not specified, the default handler of the authentication provider will be used.",
26
+ )
24
27
  auth_handler: Optional[str] = Field(
25
28
  default=None,
26
29
  description="Indicates the authentication scopes required to invoke the tool. "
27
- "If authentication is not performed or the authentication handler is non-scoped, the value should be None.")
30
+ "If authentication is not performed or the authentication handler is non-scoped, the value should be None.",
31
+ )
28
32
 
29
33
 
30
34
  class ToolRequest(abc.ABC):
31
35
  postprocessings: Optional[list[Callable]] = None
32
- overridden_tool_vars: dict[str, str] = Field(default_factory=dict, description="overridden tool variables")
36
+ overridden_tool_vars: dict[str, str] = Field(
37
+ default_factory=dict, description="overridden tool variables"
38
+ )
33
39
 
34
40
  @abc.abstractmethod
35
41
  def __str__(self):
@@ -52,7 +58,7 @@ class ToolRequest(abc.ABC):
52
58
  self.postprocessings.extend(postprocessings)
53
59
  return self
54
60
 
55
- def override_tool_variables(self, override_vars: dict[str, str]) -> 'ToolRequest':
61
+ def override_tool_variables(self, override_vars: dict[str, str]) -> "ToolRequest":
56
62
  self.overridden_tool_vars = override_vars
57
63
  return self
58
64
 
@@ -61,14 +67,24 @@ class Tool(BaseModel, abc.ABC):
61
67
  """
62
68
  Pocket Tool Interface
63
69
  """
70
+
64
71
  name: str = Field(description="tool name")
65
72
  description: str = Field(description="tool description")
66
- argument_json_schema: Optional[dict] = Field(default=None, description="tool argument json schema")
67
- auth: Optional[ToolAuth] = Field(default=None, description="authentication information to invoke tool")
68
- postprocessings: Optional[list[Callable]] = Field(default=None,
69
- description="postprocessing functions after tool is invoked")
70
- default_tool_vars: dict[str, str] = Field(default_factory=dict, description="default tool variables")
71
- overridden_tool_vars: dict[str, str] = Field(default_factory=dict, description="overridden tool variables")
73
+ argument_json_schema: Optional[dict] = Field(
74
+ default=None, description="tool argument json schema"
75
+ )
76
+ auth: Optional[ToolAuth] = Field(
77
+ default=None, description="authentication information to invoke tool"
78
+ )
79
+ postprocessings: Optional[list[Callable]] = Field(
80
+ default=None, description="postprocessing functions after tool is invoked"
81
+ )
82
+ default_tool_vars: dict[str, str] = Field(
83
+ default_factory=dict, description="default tool variables"
84
+ )
85
+ overridden_tool_vars: dict[str, str] = Field(
86
+ default_factory=dict, description="overridden tool variables"
87
+ )
72
88
  use_profile: bool = False
73
89
 
74
90
  @abc.abstractmethod
@@ -89,7 +105,9 @@ class Tool(BaseModel, abc.ABC):
89
105
  Returns a schema_model that wraps the existing argument_json_schema
90
106
  to include profile and thread_id as arguments when the tool is invoked
91
107
  """
92
- return self._get_schema_model(self.name, self.argument_json_schema, use_profile=use_profile)
108
+ return self._get_schema_model(
109
+ self.name, self.argument_json_schema, use_profile=use_profile
110
+ )
93
111
 
94
112
  def get_description(self, use_profile: bool = False) -> str:
95
113
  if use_profile:
@@ -97,7 +115,7 @@ class Tool(BaseModel, abc.ABC):
97
115
  else:
98
116
  return self.description
99
117
 
100
- def override_tool_variables(self, override_vars: dict[str, str]) -> 'Tool':
118
+ def override_tool_variables(self, override_vars: dict[str, str]) -> "Tool":
101
119
  self.overridden_tool_vars = override_vars
102
120
  return self
103
121
 
@@ -106,50 +124,55 @@ class Tool(BaseModel, abc.ABC):
106
124
  return self.default_tool_vars | self.overridden_tool_vars
107
125
 
108
126
  @classmethod
109
- def from_tool_request(cls, tool_req: ToolRequest, **kwargs) -> 'Tool':
127
+ def from_tool_request(cls, tool_req: ToolRequest, **kwargs) -> "Tool":
110
128
  from hyperpocket.tool.wasm.tool import WasmTool, WasmToolRequest
129
+
111
130
  if isinstance(tool_req, WasmToolRequest):
112
131
  return WasmTool.from_tool_request(tool_req, **kwargs)
113
- raise ValueError('Unknown tool request type')
132
+ raise ValueError("Unknown tool request type")
114
133
 
115
134
  @classmethod
116
- def _get_schema_model(cls, name: str, json_schema: Optional[dict], use_profile: bool) -> Optional[Type[BaseModel]]:
135
+ def _get_schema_model(
136
+ cls, name: str, json_schema: Optional[dict], use_profile: bool
137
+ ) -> Optional[Type[BaseModel]]:
117
138
  try:
118
139
  if not json_schema:
119
140
  pocket_logger.info(f"{name} tool's json_schema is none.")
120
141
  return None
121
- if 'description' not in json_schema:
122
- json_schema['description'] = 'The argument of the tool.'
142
+ if "description" not in json_schema:
143
+ json_schema["description"] = "The argument of the tool."
123
144
 
124
145
  if use_profile:
125
146
  json_schema = {
126
- 'title': name,
127
- 'type': 'object',
128
- 'properties': {
129
- 'thread_id': {
130
- 'type': 'string',
131
- 'default': 'default',
132
- 'description': 'The ID of the chat thread where the tool is invoked. Omitted when unknown.',
147
+ "title": name,
148
+ "type": "object",
149
+ "properties": {
150
+ "thread_id": {
151
+ "type": "string",
152
+ "default": "default",
153
+ "description": "The ID of the chat thread where the tool is invoked. Omitted when unknown.",
133
154
  },
134
- 'profile': {
135
- 'type': 'string',
136
- 'default': 'default',
137
- 'description': '''The profile of the user invoking the tool. Inferred from user's messages.
155
+ "profile": {
156
+ "type": "string",
157
+ "default": "default",
158
+ "description": """The profile of the user invoking the tool. Inferred from user's messages.
138
159
  Users can request tools to be invoked in specific personas, which is called a profile.
139
160
  If the user's profile name can be inferred from the query, pass it as a string in the 'profile'
140
- JSON property. Omitted when unknown.''',
161
+ JSON property. Omitted when unknown.""",
141
162
  },
142
- 'body': json_schema
163
+ "body": json_schema,
143
164
  },
144
- 'required': [
145
- 'body',
146
- ]
165
+ "required": [
166
+ "body",
167
+ ],
147
168
  }
148
169
 
149
170
  model = json_schema_to_model(json_schema, name)
150
171
  return model
151
172
  except Exception as e:
152
- pocket_logger.warning(f"failed to get tool({name}) schema model. error : {e}")
173
+ pocket_logger.warning(
174
+ f"failed to get tool({name}) schema model. error : {e}"
175
+ )
153
176
  pass
154
177
 
155
178
  def with_postprocessing(self, postprocessing: Callable):
@@ -1,3 +1,3 @@
1
1
  from hyperpocket.tool.wasm.tool import WasmTool
2
2
 
3
- __all__ = ["WasmTool"]
3
+ __all__ = ["WasmTool"]
@@ -1,11 +1,16 @@
1
1
  import asyncio
2
- import os
3
2
 
4
- from playwright.async_api import async_playwright, Page, Playwright, BrowserContext, Route
3
+ from playwright.async_api import (
4
+ BrowserContext,
5
+ Page,
6
+ Playwright,
7
+ Route,
8
+ async_playwright,
9
+ )
5
10
 
6
11
 
7
12
  class InvokerBrowser(object):
8
- _instance: 'InvokerBrowser' = None
13
+ _instance: "InvokerBrowser" = None
9
14
  _lock = asyncio.Lock()
10
15
  playwright: Playwright
11
16
  browser_context: BrowserContext
@@ -18,9 +23,9 @@ class InvokerBrowser(object):
18
23
  self.browser_context = await self.playwright.chromium.launch_persistent_context(
19
24
  headless=True,
20
25
  args=[
21
- '--disable-web-security=True',
26
+ "--disable-web-security=True",
22
27
  ],
23
- user_data_dir='/tmp/chrome_dev_user',
28
+ user_data_dir="/tmp/chrome_dev_user",
24
29
  )
25
30
 
26
31
  @classmethod
@@ -44,13 +49,13 @@ class InvokerBrowser(object):
44
49
  body=body,
45
50
  headers={
46
51
  **response.headers,
47
- 'Cross-Origin-Opener-Policy': 'same-origin',
48
- 'Cross-Origin-Embedder-Policy': 'require-corp',
49
- 'Cross-Origin-Resource-Policy': 'cross-origin',
50
- }
52
+ "Cross-Origin-Opener-Policy": "same-origin",
53
+ "Cross-Origin-Embedder-Policy": "require-corp",
54
+ "Cross-Origin-Resource-Policy": "cross-origin",
55
+ },
51
56
  )
52
57
 
53
- await page.route('**/*', _hijack_route)
58
+ await page.route("**/*", _hijack_route)
54
59
  return page
55
60
 
56
61
  async def teardown(self):
@@ -7,34 +7,34 @@ from urllib.parse import urljoin
7
7
  from hyperpocket.config import config
8
8
  from hyperpocket.futures import FutureStore
9
9
  from hyperpocket.tool.wasm.browser import InvokerBrowser
10
- from hyperpocket.tool.wasm.script import ScriptRuntime, ScriptStore, Script
10
+ from hyperpocket.tool.wasm.script import Script, ScriptRuntime, ScriptStore
11
11
  from hyperpocket.tool.wasm.templates import render
12
12
 
13
13
 
14
14
  class WasmInvoker(object):
15
- def invoke(self,
16
- tool_path: str,
17
- runtime: ScriptRuntime,
18
- body: Any,
19
- envs: dict,
20
- **kwargs) -> str:
15
+ def invoke(
16
+ self, tool_path: str, runtime: ScriptRuntime, body: Any, envs: dict, **kwargs
17
+ ) -> str:
21
18
  loop = asyncio.get_running_loop()
22
- return loop.run_until_complete(self.ainvoke(tool_path, runtime, body, envs, **kwargs))
19
+ return loop.run_until_complete(
20
+ self.ainvoke(tool_path, runtime, body, envs, **kwargs)
21
+ )
23
22
 
24
- async def ainvoke(self,
25
- tool_path: str,
26
- runtime: ScriptRuntime,
27
- body: Any,
28
- envs: dict,
29
- **kwargs) -> str:
23
+ async def ainvoke(
24
+ self, tool_path: str, runtime: ScriptRuntime, body: Any, envs: dict, **kwargs
25
+ ) -> str:
30
26
  uid = str(uuid.uuid4())
31
27
  html = render(runtime.value, uid, envs, json.dumps(body))
32
- script = Script(id=uid, tool_path=tool_path, rendered_html=html, runtime=runtime)
28
+ script = Script(
29
+ id=uid, tool_path=tool_path, rendered_html=html, runtime=runtime
30
+ )
33
31
  ScriptStore.add_script(script=script)
34
32
  future_data = FutureStore.create_future(uid=uid)
35
33
  browser = await InvokerBrowser.get_instance()
36
34
  page = await browser.new_page()
37
- url = urljoin(config.internal_base_url + '/', f'tools/wasm/scripts/{uid}/browse')
35
+ url = urljoin(
36
+ config().internal_base_url + "/", f"tools/wasm/scripts/{uid}/browse"
37
+ )
38
38
  await page.goto(url)
39
39
  stdout = await future_data.future
40
40
  await page.close()