hyperpocket 0.0.1__py3-none-any.whl

Sign up to get free protection for your applications and to get access to all the features.
Files changed (131) hide show
  1. hyperpocket/__init__.py +7 -0
  2. hyperpocket/auth/README.KR.md +309 -0
  3. hyperpocket/auth/README.md +323 -0
  4. hyperpocket/auth/__init__.py +24 -0
  5. hyperpocket/auth/calendly/__init__.py +0 -0
  6. hyperpocket/auth/calendly/context.py +13 -0
  7. hyperpocket/auth/calendly/oauth2_context.py +25 -0
  8. hyperpocket/auth/calendly/oauth2_handler.py +146 -0
  9. hyperpocket/auth/calendly/oauth2_schema.py +16 -0
  10. hyperpocket/auth/context.py +38 -0
  11. hyperpocket/auth/github/__init__.py +0 -0
  12. hyperpocket/auth/github/context.py +13 -0
  13. hyperpocket/auth/github/oauth2_context.py +25 -0
  14. hyperpocket/auth/github/oauth2_handler.py +143 -0
  15. hyperpocket/auth/github/oauth2_schema.py +16 -0
  16. hyperpocket/auth/github/token_context.py +12 -0
  17. hyperpocket/auth/github/token_handler.py +79 -0
  18. hyperpocket/auth/github/token_schema.py +9 -0
  19. hyperpocket/auth/google/__init__.py +0 -0
  20. hyperpocket/auth/google/context.py +15 -0
  21. hyperpocket/auth/google/oauth2_context.py +31 -0
  22. hyperpocket/auth/google/oauth2_handler.py +137 -0
  23. hyperpocket/auth/google/oauth2_schema.py +18 -0
  24. hyperpocket/auth/handler.py +171 -0
  25. hyperpocket/auth/linear/__init__.py +0 -0
  26. hyperpocket/auth/linear/context.py +15 -0
  27. hyperpocket/auth/linear/token_context.py +15 -0
  28. hyperpocket/auth/linear/token_handler.py +68 -0
  29. hyperpocket/auth/linear/token_schema.py +9 -0
  30. hyperpocket/auth/provider.py +16 -0
  31. hyperpocket/auth/schema.py +19 -0
  32. hyperpocket/auth/slack/__init__.py +0 -0
  33. hyperpocket/auth/slack/context.py +15 -0
  34. hyperpocket/auth/slack/oauth2_context.py +40 -0
  35. hyperpocket/auth/slack/oauth2_handler.py +151 -0
  36. hyperpocket/auth/slack/oauth2_schema.py +40 -0
  37. hyperpocket/auth/slack/tests/__init__.py +0 -0
  38. hyperpocket/auth/slack/tests/test_oauth2_handler.py +32 -0
  39. hyperpocket/auth/slack/tests/test_token_handler.py +23 -0
  40. hyperpocket/auth/slack/token_context.py +14 -0
  41. hyperpocket/auth/slack/token_handler.py +64 -0
  42. hyperpocket/auth/slack/token_schema.py +9 -0
  43. hyperpocket/auth/tests/__init__.py +0 -0
  44. hyperpocket/auth/tests/test_google_oauth2_handler.py +147 -0
  45. hyperpocket/auth/tests/test_slack_oauth2_handler.py +147 -0
  46. hyperpocket/auth/tests/test_slack_token_handler.py +66 -0
  47. hyperpocket/cli/__init__.py +0 -0
  48. hyperpocket/cli/__main__.py +12 -0
  49. hyperpocket/cli/pull.py +18 -0
  50. hyperpocket/cli/sync.py +17 -0
  51. hyperpocket/config/__init__.py +9 -0
  52. hyperpocket/config/auth.py +36 -0
  53. hyperpocket/config/git.py +17 -0
  54. hyperpocket/config/logger.py +81 -0
  55. hyperpocket/config/session.py +35 -0
  56. hyperpocket/config/settings.py +62 -0
  57. hyperpocket/constants.py +0 -0
  58. hyperpocket/curated_tools.py +10 -0
  59. hyperpocket/external/__init__.py +7 -0
  60. hyperpocket/external/github_client.py +19 -0
  61. hyperpocket/futures/__init__.py +7 -0
  62. hyperpocket/futures/futurestore.py +48 -0
  63. hyperpocket/pocket_auth.py +344 -0
  64. hyperpocket/pocket_main.py +351 -0
  65. hyperpocket/prompts.py +15 -0
  66. hyperpocket/repository/__init__.py +5 -0
  67. hyperpocket/repository/lock.py +156 -0
  68. hyperpocket/repository/lockfile.py +56 -0
  69. hyperpocket/repository/repository.py +18 -0
  70. hyperpocket/server/__init__.py +3 -0
  71. hyperpocket/server/auth/__init__.py +15 -0
  72. hyperpocket/server/auth/calendly.py +16 -0
  73. hyperpocket/server/auth/github.py +25 -0
  74. hyperpocket/server/auth/google.py +16 -0
  75. hyperpocket/server/auth/linear.py +18 -0
  76. hyperpocket/server/auth/slack.py +28 -0
  77. hyperpocket/server/auth/token.py +51 -0
  78. hyperpocket/server/proxy.py +63 -0
  79. hyperpocket/server/server.py +178 -0
  80. hyperpocket/server/tool/__init__.py +10 -0
  81. hyperpocket/server/tool/dto/__init__.py +0 -0
  82. hyperpocket/server/tool/dto/script.py +15 -0
  83. hyperpocket/server/tool/wasm.py +31 -0
  84. hyperpocket/session/README.KR.md +62 -0
  85. hyperpocket/session/README.md +61 -0
  86. hyperpocket/session/__init__.py +4 -0
  87. hyperpocket/session/in_memory.py +76 -0
  88. hyperpocket/session/interface.py +118 -0
  89. hyperpocket/session/redis.py +126 -0
  90. hyperpocket/session/tests/__init__.py +0 -0
  91. hyperpocket/session/tests/test_in_memory.py +145 -0
  92. hyperpocket/session/tests/test_redis.py +151 -0
  93. hyperpocket/tests/__init__.py +0 -0
  94. hyperpocket/tests/test_pocket.py +118 -0
  95. hyperpocket/tests/test_pocket_auth.py +982 -0
  96. hyperpocket/tool/README.KR.md +68 -0
  97. hyperpocket/tool/README.md +75 -0
  98. hyperpocket/tool/__init__.py +13 -0
  99. hyperpocket/tool/builtins/__init__.py +0 -0
  100. hyperpocket/tool/builtins/example/__init__.py +0 -0
  101. hyperpocket/tool/builtins/example/add_tool.py +18 -0
  102. hyperpocket/tool/function/README.KR.md +159 -0
  103. hyperpocket/tool/function/README.md +169 -0
  104. hyperpocket/tool/function/__init__.py +9 -0
  105. hyperpocket/tool/function/annotation.py +30 -0
  106. hyperpocket/tool/function/tool.py +87 -0
  107. hyperpocket/tool/tests/__init__.py +0 -0
  108. hyperpocket/tool/tests/test_function_tool.py +266 -0
  109. hyperpocket/tool/tool.py +106 -0
  110. hyperpocket/tool/wasm/README.KR.md +144 -0
  111. hyperpocket/tool/wasm/README.md +144 -0
  112. hyperpocket/tool/wasm/__init__.py +3 -0
  113. hyperpocket/tool/wasm/browser.py +63 -0
  114. hyperpocket/tool/wasm/invoker.py +41 -0
  115. hyperpocket/tool/wasm/script.py +82 -0
  116. hyperpocket/tool/wasm/templates/__init__.py +28 -0
  117. hyperpocket/tool/wasm/templates/node.py +87 -0
  118. hyperpocket/tool/wasm/templates/python.py +75 -0
  119. hyperpocket/tool/wasm/tool.py +147 -0
  120. hyperpocket/util/__init__.py +1 -0
  121. hyperpocket/util/extract_func_param_desc_from_docstring.py +97 -0
  122. hyperpocket/util/find_all_leaf_class_in_package.py +17 -0
  123. hyperpocket/util/find_all_subclass_in_package.py +29 -0
  124. hyperpocket/util/flatten_json_schema.py +45 -0
  125. hyperpocket/util/function_to_model.py +46 -0
  126. hyperpocket/util/get_objects_from_subpackage.py +28 -0
  127. hyperpocket/util/json_schema_to_model.py +69 -0
  128. hyperpocket-0.0.1.dist-info/METADATA +304 -0
  129. hyperpocket-0.0.1.dist-info/RECORD +131 -0
  130. hyperpocket-0.0.1.dist-info/WHEEL +4 -0
  131. hyperpocket-0.0.1.dist-info/entry_points.txt +3 -0
@@ -0,0 +1,266 @@
1
+ from unittest import TestCase
2
+
3
+ from pydantic import BaseModel
4
+
5
+ from hyperpocket.auth import AuthProvider
6
+ from hyperpocket.tool.function.annotation import function_tool
7
+ from hyperpocket.tool.function.tool import FunctionTool
8
+ from hyperpocket.util.flatten_json_schema import flatten_json_schema
9
+
10
+
11
+ class TestFunctionTool(TestCase):
12
+
13
+ def test_function_tool_call(self):
14
+ # given
15
+ @function_tool
16
+ def add_numbers(a: int, b: int):
17
+ """
18
+ add two numbers
19
+ a(int): first name
20
+ b(int): second name
21
+ """
22
+ return a + b
23
+
24
+ # when
25
+ result = add_numbers.invoke(body={
26
+ "a": 1,
27
+ "b": 2
28
+ })
29
+
30
+ # then
31
+ self.assertEqual(result, '3')
32
+
33
+ def test_pydantic_input_function_tool_call(self):
34
+ # given
35
+ class FirstNumber(BaseModel):
36
+ first: int
37
+
38
+ class SecondNumber(BaseModel):
39
+ second: int
40
+
41
+ @function_tool
42
+ def add_numbers(a: FirstNumber, b: SecondNumber):
43
+ """
44
+ add two numbers
45
+ a(FirstNumber): first number
46
+ b(SecondNumber): second number
47
+ """
48
+ return a.first + b.second
49
+
50
+ # when
51
+ result = add_numbers.invoke(body={
52
+ "a": {
53
+ "first": 1,
54
+ },
55
+ "b": {
56
+ "second": 2
57
+ }
58
+ })
59
+
60
+ # then
61
+ self.assertEqual(result, '3')
62
+
63
+ def test_register_no_auth_no_init_func_case(self):
64
+ """
65
+ Test register functionTool in case of no-auth and no-init function
66
+ """
67
+
68
+ @function_tool
69
+ def add_numbers(a: int, b: int):
70
+ """
71
+ add two numbers
72
+ a(int): first name
73
+ b(int): second name
74
+ """
75
+ return a + b
76
+
77
+ # when
78
+ result = add_numbers.invoke(body={
79
+ "a": 1,
80
+ "b": 2
81
+ })
82
+
83
+ # then
84
+ self.assertIsInstance(add_numbers, FunctionTool)
85
+ self.assertEqual(result, '3')
86
+
87
+ def test_register_no_auth_init_func_case(self):
88
+ """
89
+ Test register functionTool in case of no-auth and init function
90
+ """
91
+
92
+ @function_tool()
93
+ def add_numbers(a: int, b: int):
94
+ """
95
+ add two numbers
96
+ a(int): first name
97
+ b(int): second name
98
+ """
99
+ return a + b
100
+
101
+ # when
102
+ result = add_numbers.invoke(body={
103
+ "a": 1,
104
+ "b": 2
105
+ })
106
+
107
+ # then
108
+ self.assertIsInstance(add_numbers, FunctionTool)
109
+ self.assertEqual(result, '3')
110
+
111
+ def test_register_auth_init_func_case(self):
112
+ """
113
+ Test register functionTool in case of auth and init function
114
+
115
+ """
116
+
117
+ @function_tool(auth_provider=AuthProvider.SLACK)
118
+ def add_numbers(a: int, b: int):
119
+ """
120
+ add two numbers
121
+ a(int): first name
122
+ b(int): second name
123
+ """
124
+ return a + b
125
+
126
+ # when
127
+ result = add_numbers.invoke(body={
128
+ "a": 1,
129
+ "b": 2
130
+ },
131
+ envs={
132
+ "SLACK_BOT_TOKEN": "test"
133
+ })
134
+
135
+ # then
136
+ self.assertIsInstance(add_numbers, FunctionTool)
137
+ self.assertEqual(result, '3')
138
+
139
+ def test_google_style_docstring_parsing(self):
140
+ """
141
+ Test google style docstring parsing
142
+ """
143
+
144
+ # given
145
+ @function_tool
146
+ def add_numbers(a: int, b: int):
147
+ """
148
+ add two numbers
149
+
150
+ Args:
151
+ a(int): first name
152
+ b(int): second name
153
+ """
154
+ return a + b
155
+
156
+ # when
157
+ schema = add_numbers.schema_model()
158
+ schema_json = schema.model_json_schema()
159
+ flatten_schema_json = flatten_json_schema(schema_json)
160
+ func_schema = flatten_schema_json["properties"]["body"]
161
+
162
+ # then
163
+ self.assertTrue(str(func_schema["description"]).startswith("add two numbers"))
164
+ self.assertEqual(func_schema["title"], "add_numbers")
165
+ self.assertEqual(func_schema["required"], ["a", "b"])
166
+ self.assertEqual(func_schema["type"], "object")
167
+ self.assertEqual(func_schema["properties"]["a"]["type"], "integer")
168
+ self.assertEqual(func_schema["properties"]["a"]["description"], "first name")
169
+ self.assertEqual(func_schema["properties"]["b"]["type"], "integer")
170
+ self.assertEqual(func_schema["properties"]["b"]["description"], "second name")
171
+
172
+ def test_javadoc_style_docstring_parsing(self):
173
+ """
174
+ Test javadoc style docstring parsing
175
+ """
176
+
177
+ # given
178
+ @function_tool
179
+ def add_numbers(a: int, b: int):
180
+ """
181
+ add two numbers
182
+
183
+ @param a first name
184
+ @param b second name
185
+ """
186
+ return a + b
187
+
188
+ # when
189
+ schema = add_numbers.schema_model()
190
+ schema_json = schema.model_json_schema()
191
+ flatten_schema_json = flatten_json_schema(schema_json)
192
+ func_schema = flatten_schema_json["properties"]["body"]
193
+
194
+ # then
195
+ self.assertTrue(str(func_schema["description"]).startswith("add two numbers"))
196
+ self.assertEqual(func_schema["title"], "add_numbers")
197
+ self.assertEqual(func_schema["required"], ["a", "b"])
198
+ self.assertEqual(func_schema["type"], "object")
199
+ self.assertEqual(func_schema["properties"]["a"]["type"], "integer")
200
+ self.assertEqual(func_schema["properties"]["a"]["description"], "first name")
201
+ self.assertEqual(func_schema["properties"]["b"]["type"], "integer")
202
+ self.assertEqual(func_schema["properties"]["b"]["description"], "second name")
203
+
204
+ def test_sphinx_style_docstring_parsing(self):
205
+ """
206
+ Test sphinx style docstring parsing
207
+ """
208
+
209
+ # given
210
+ @function_tool
211
+ def add_numbers(a: int, b: int):
212
+ """
213
+ add two numbers
214
+
215
+ :param a: first name
216
+ :param b: second name
217
+ """
218
+ return a + b
219
+
220
+ # when
221
+ schema = add_numbers.schema_model()
222
+ schema_json = schema.model_json_schema()
223
+ flatten_schema_json = flatten_json_schema(schema_json)
224
+ func_schema = flatten_schema_json["properties"]["body"]
225
+
226
+ # then
227
+ self.assertTrue(str(func_schema["description"]).startswith("add two numbers"))
228
+ self.assertEqual(func_schema["title"], "add_numbers")
229
+ self.assertEqual(func_schema["required"], ["a", "b"])
230
+ self.assertEqual(func_schema["type"], "object")
231
+ self.assertEqual(func_schema["properties"]["a"]["type"], "integer")
232
+ self.assertEqual(func_schema["properties"]["a"]["description"], "first name")
233
+ self.assertEqual(func_schema["properties"]["b"]["type"], "integer")
234
+ self.assertEqual(func_schema["properties"]["b"]["description"], "second name")
235
+
236
+ def test_simple_style_docstring_parsing(self):
237
+ """
238
+ Test simple docstring parsing
239
+ """
240
+
241
+ # given
242
+ @function_tool
243
+ def add_numbers(a: int, b: int):
244
+ """
245
+ add two numbers
246
+
247
+ a: first name
248
+ b(int): second name
249
+ """
250
+ return a + b
251
+
252
+ # when
253
+ schema = add_numbers.schema_model()
254
+ schema_json = schema.model_json_schema()
255
+ flatten_schema_json = flatten_json_schema(schema_json)
256
+ func_schema = flatten_schema_json["properties"]["body"]
257
+
258
+ # then
259
+ self.assertTrue(str(func_schema["description"]).startswith("add two numbers"))
260
+ self.assertEqual(func_schema["title"], "add_numbers")
261
+ self.assertEqual(func_schema["required"], ["a", "b"])
262
+ self.assertEqual(func_schema["type"], "object")
263
+ self.assertEqual(func_schema["properties"]["a"]["type"], "integer")
264
+ self.assertEqual(func_schema["properties"]["a"]["description"], "first name")
265
+ self.assertEqual(func_schema["properties"]["b"]["type"], "integer")
266
+ self.assertEqual(func_schema["properties"]["b"]["description"], "second name")
@@ -0,0 +1,106 @@
1
+ import abc
2
+ from typing import TypeVar, Optional, Type
3
+
4
+ from pydantic import BaseModel, Field
5
+
6
+ from hyperpocket.auth.provider import AuthProvider
7
+ from hyperpocket.config.logger import pocket_logger
8
+ from hyperpocket.util.json_schema_to_model import json_schema_to_model
9
+
10
+
11
+ class ToolAuth(BaseModel):
12
+ """
13
+ ToolAuth is an object that represents the authentication information required to invoke a tool
14
+ """
15
+ scopes: list[str] = Field(
16
+ default=None,
17
+ description="Indicates which authentication provider’s credentials are required to invoke the tool. "
18
+ "If auth_provider is not specified, the tool is considered to require no authentication.")
19
+ auth_provider: Optional[AuthProvider] = Field(
20
+ default=None,
21
+ description="Specifies which authentication handler should be used when invoking the tool. "
22
+ "If auth_handler is not specified, the default handler of the authentication provider will be used.")
23
+ auth_handler: Optional[str] = Field(
24
+ default=None,
25
+ description="Indicates the authentication scopes required to invoke the tool. "
26
+ "If authentication is not performed or the authentication handler is non-scoped, the value should be None.")
27
+
28
+
29
+ class ToolRequest(abc.ABC):
30
+ @abc.abstractmethod
31
+ def __str__(self):
32
+ raise NotImplementedError
33
+
34
+
35
+ class Tool(BaseModel, abc.ABC):
36
+ """
37
+ Pocket Tool Interface
38
+ """
39
+ name: str = Field(description="tool name")
40
+ description: str = Field(description="tool description")
41
+ argument_json_schema: Optional[dict] = Field(default=None, description="tool argument json schema")
42
+ auth: Optional[ToolAuth] = Field(default=None, description="authentication information to invoke tool")
43
+
44
+ @abc.abstractmethod
45
+ def invoke(self, **kwargs) -> str:
46
+ """
47
+ Invoke the tool
48
+ """
49
+ raise NotImplementedError()
50
+
51
+ async def ainvoke(self, **kwargs) -> str:
52
+ """
53
+ Asynchronously invoke the tool
54
+ """
55
+ raise NotImplementedError()
56
+
57
+ def schema_model(self) -> Optional[Type[BaseModel]]:
58
+ """
59
+ Returns a schema_model that wraps the existing argument_json_schema
60
+ to include profile and thread_id as arguments when the tool is invoked
61
+ """
62
+ return self._get_schema_model(self.name, self.argument_json_schema)
63
+
64
+ @classmethod
65
+ def from_tool_request(cls, tool_req: ToolRequest, **kwargs) -> 'Tool':
66
+ from hyperpocket.tool.wasm.tool import WasmTool, WasmToolRequest
67
+ if isinstance(tool_req, WasmToolRequest):
68
+ return WasmTool.from_tool_request(tool_req, **kwargs)
69
+ raise ValueError('Unknown tool request type')
70
+
71
+ @classmethod
72
+ def _get_schema_model(cls, name: str, json_schema: Optional[dict]) -> Optional[Type[BaseModel]]:
73
+ try:
74
+ if not json_schema:
75
+ pocket_logger.info(f"{name} tool's json_schema is none.")
76
+ return None
77
+ if 'description' not in json_schema:
78
+ json_schema['description'] = f'The argument of the tool.'
79
+ extended_schema = {
80
+ 'title': name,
81
+ 'type': 'object',
82
+ 'properties': {
83
+ 'thread_id': {
84
+ 'type': 'string',
85
+ 'default': 'default',
86
+ 'description': 'The ID of the chat thread where the tool is invoked. Omitted when unknown.',
87
+ },
88
+ 'profile': {
89
+ 'type': 'string',
90
+ 'default': 'default',
91
+ 'description': '''The profile of the user invoking the tool. Inferred from user's messages.
92
+ Users can request tools to be invoked in specific personas, which is called a profile.
93
+ If the user's profile name can be inferred from the query, pass it as a string in the 'profile'
94
+ JSON property. Omitted when unknown.''',
95
+ },
96
+ 'body': json_schema
97
+ },
98
+ 'required': [
99
+ 'body',
100
+ ]
101
+ }
102
+ model = json_schema_to_model(extended_schema, name)
103
+ return model
104
+ except Exception as e:
105
+ pocket_logger.warning(f"failed to get tool({name}) schema model. error : {e}")
106
+ pass
@@ -0,0 +1,144 @@
1
+ # Wasm(WebAssembly)
2
+
3
+ ---
4
+
5
+ ## How To Use
6
+
7
+ ### plain url
8
+
9
+ `Pocket` 초기화 시 github url을 넣어서 해당 툴을 불러올 수 있다.
10
+
11
+ ```python
12
+ from hyperpocket import Pocket
13
+
14
+ pocket = Pocket(tools=[
15
+ 'https://github.com/your-organization/your-repository/tree/main',
16
+ ])
17
+ ```
18
+
19
+ - 이 경우 기본적으로 `main` branch를 기준으로 코드를 읽어오게 된다.
20
+
21
+ ### from_git
22
+
23
+ `from_git`을 통해 명시적으로 branch나 경로를 지정해 툴을 불러올 수 있다.
24
+
25
+ ```python
26
+ from hyperpocket import Pocket
27
+ from hyperpocket.tool import from_git
28
+
29
+ pocket = Pocket(tools=[
30
+ from_git("https://github.com/your-organization/your-repository", "branch-name", "your/tool/code/path"),
31
+ ])
32
+ ```
33
+
34
+ ### from_local
35
+
36
+ `from_local`을 통해 로컬 경로를 지정해 툴을 불러올 수 있다.
37
+
38
+ ```python
39
+ from hyperpocket import Pocket
40
+ from hyperpocket.tool import from_local
41
+
42
+ pocket = Pocket(tools=[
43
+ from_local("your/local/tool/code/path")
44
+ ])
45
+ ```
46
+
47
+ ## WasmToolRequest
48
+
49
+ WasmTool을 초기화 하기 위한 객체
50
+
51
+ WasmToolRequest는 다음 build 함수를 제공
52
+
53
+ - `from_local`
54
+ - `from_git`
55
+ - `from_github`
56
+
57
+ WasmToolRequest는 각각 request에 대한 `lock` 객체를 가지고 있다.
58
+
59
+ 해당 `lock` 객체들은 `Pocket`에서 `Lockfile` 객체를 통해 관리된다.
60
+
61
+ ```mermaid
62
+ classDiagram
63
+ class WasmToolRequest {
64
+ +Lock lock
65
+ + from_git()
66
+ + from_local()
67
+ }
68
+
69
+ class Lock{
70
+ +key()
71
+ +sync()
72
+ }
73
+
74
+ class GitLock{
75
+ +key()
76
+ +sync()
77
+ }
78
+
79
+ class LocalLock{
80
+ +key()
81
+ +sync()
82
+ }
83
+
84
+ class Lockfile {
85
+ +dict[tuple,Lock] locks
86
+
87
+ + add_lock()
88
+ + get_lock()
89
+ + sync()
90
+ + write()
91
+ }
92
+
93
+ ToolRequest <|.. WasmToolRequest : Implementation
94
+ Lock o-- WasmToolRequest : 1..1
95
+ Lock <|.. GitLock : Implementation
96
+ Lock <|.. LocalLock : Implementation
97
+ Lock o-- Lockfile : n..1
98
+ Lockfile o-- Pocket : 1..1
99
+ ```
100
+
101
+ ## WasmTool
102
+
103
+ ```python
104
+ class WasmTool(Tool):
105
+ _invoker: WasmInvoker = None
106
+ pkg_lock: Lock = None
107
+ rel_path: str
108
+ runtime: ScriptRuntime = None
109
+ json_schema: Optional[dict] = None
110
+ readme: Optional[str] = None
111
+ ```
112
+
113
+ - `_invoker` : wasm을 실행시키기 위한 클래스
114
+ - `pkg_lock` : 해당 Tool의 lock 클래스
115
+ - pkg_lock을 통해 현재 wasm code가 저장되어 있는 패키지 경로를 확인
116
+ - `rel_path` : package 내에서 wasm code가 존재하는 상대 위치
117
+ - `runtime` : wasm code의 runtime 언어
118
+ - `json_schema` : wasm tool의 json schema
119
+ - `schema.json`로 읽어온 정보
120
+ - `readme` : readme 정보
121
+
122
+ ## WasmInvoker
123
+
124
+ 실제 wasm을 구동하기 위한 클래스
125
+
126
+ 1. runtime 정보, auth 정보, body 정보 등을 종합해 html을 rendering
127
+ 2. rendering된 html을 메모리에 저장
128
+ 3. wasm 실행을 위한 browser를 실행
129
+ 4. browser에서는 서버로 요청을 보내 rendering된 html을 불러옴
130
+ 5. 해당 html에서 각 runtime에 맞는 코드를 실행 후 결괏값을 전달
131
+
132
+ ```mermaid
133
+ sequenceDiagram
134
+ participant WasmTool as WasmTool (Includes Server)
135
+ participant Browser as Browser (Executes WASM Runtime)
136
+
137
+
138
+ WasmTool->>WasmTool: Render HTML and Store in Memory
139
+ WasmTool->>Browser: Launch Browser
140
+ Browser->>WasmTool: Request Rendered HTML
141
+ WasmTool->>Browser: Provide Rendered HTML
142
+ Browser->>Browser: Execute Injected WASM Runtime Script
143
+ Browser->>WasmTool: Return Execution Result
144
+ ```
@@ -0,0 +1,144 @@
1
+ # Wasm(WebAssembly)
2
+
3
+ ---
4
+
5
+ ## How To Use
6
+
7
+ ### plain url
8
+
9
+ load the tool by providing a GitHub URL
10
+
11
+ ```python
12
+ from hyperpocket import Pocket
13
+
14
+ pocket = Pocket(tools=[
15
+ 'https://github.com/your-organization/your-repository/tree/main',
16
+ ])
17
+ ```
18
+
19
+ - in this case, read tool code from `main` branch by default
20
+
21
+ ### from_git
22
+
23
+ - using `from_git`, you can specify branch and tool code path
24
+
25
+ ```python
26
+ from hyperpocket import Pocket
27
+ from hyperpocket.tool import from_git
28
+
29
+ pocket = Pocket(tools=[
30
+ from_git("https://github.com/your-organization/your-repository", "branch-name", "your/tool/code/path"),
31
+ ])
32
+ ```
33
+
34
+ ### from_local
35
+
36
+ - using `from_local`, you can load a tool by specifying a local path
37
+
38
+ ```python
39
+ from hyperpocket import Pocket
40
+ from hyperpocket.tool import from_local
41
+
42
+ pocket = Pocket(tools=[
43
+ from_local("your/local/tool/code/path")
44
+ ])
45
+ ```
46
+
47
+ ## WasmToolRequest
48
+
49
+ The class to initiate WasmTool
50
+
51
+ WasmToolRequest offer those build method:
52
+
53
+ - `from_local`
54
+ - `from_git`
55
+ - `from_github`
56
+
57
+ Each `WasmToolRequest` has it's own `Lock` object
58
+
59
+ Those `Lock` object is managed by `Lockfile` in the `Pocket` class
60
+
61
+ ```mermaid
62
+ classDiagram
63
+ class WasmToolRequest {
64
+ +Lock lock
65
+ + from_git()
66
+ + from_local()
67
+ }
68
+
69
+ class Lock{
70
+ +key()
71
+ +sync()
72
+ }
73
+
74
+ class GitLock{
75
+ +key()
76
+ +sync()
77
+ }
78
+
79
+ class LocalLock{
80
+ +key()
81
+ +sync()
82
+ }
83
+
84
+ class Lockfile {
85
+ +dict[tuple,Lock] locks
86
+
87
+ + add_lock()
88
+ + get_lock()
89
+ + sync()
90
+ + write()
91
+ }
92
+
93
+ ToolRequest <|.. WasmToolRequest : Implementation
94
+ Lock o-- WasmToolRequest : 1..1
95
+ Lock <|.. GitLock : Implementation
96
+ Lock <|.. LocalLock : Implementation
97
+ Lock o-- Lockfile : n..1
98
+ Lockfile o-- Pocket : 1..1
99
+ ```
100
+
101
+ ## WasmTool
102
+
103
+ ```python
104
+ class WasmTool(Tool):
105
+ _invoker: WasmInvoker = None
106
+ pkg_lock: Lock = None
107
+ rel_path: str
108
+ runtime: ScriptRuntime = None
109
+ json_schema: Optional[dict] = None
110
+ readme: Optional[str] = None
111
+ ```
112
+
113
+ - `_invoker`: A class for executing WASM.
114
+ - `pkg_lock`: The lock class for the tool.
115
+ - Used to determine the package path where the current WASM code is stored.
116
+ - `rel_path`: The relative path to the location of the WASM code within the package.
117
+ - `runtime`: The runtime language of the WASM code.
118
+ - `json_schema`: The JSON schema for the WASM tool.
119
+ - Information read from schema.json.
120
+ - `readme`: The README information.
121
+
122
+ ## WasmInvoker
123
+
124
+ A class for running actual WASM
125
+
126
+ 1. Combines runtime information, authentication details, and body content to render HTML.
127
+ 2. Stores the rendered HTML in memory.
128
+ 3. Launches a browser to execute the WASM.
129
+ 4. The browser sends a request to the server to retrieve the rendered HTML.
130
+ 5. Executes code specific to each runtime within the HTML and returns the result.
131
+
132
+ ```mermaid
133
+ sequenceDiagram
134
+ participant WasmTool as WasmTool (Includes Server)
135
+ participant Browser as Browser (Executes WASM Runtime)
136
+
137
+
138
+ WasmTool->>WasmTool: Render HTML and Store in Memory
139
+ WasmTool->>Browser: Launch Browser
140
+ Browser->>WasmTool: Request Rendered HTML
141
+ WasmTool->>Browser: Provide Rendered HTML
142
+ Browser->>Browser: Execute Injected WASM Runtime Script
143
+ Browser->>WasmTool: Return Execution Result
144
+ ```
@@ -0,0 +1,3 @@
1
+ from hyperpocket.tool.wasm.tool import WasmTool
2
+
3
+ __all__ = ["WasmTool"]