hyperpocket 0.0.2__tar.gz → 0.1.8__tar.gz
Sign up to get free protection for your applications and to get access to all the features.
- hyperpocket-0.1.8/.gitignore +157 -0
- {hyperpocket-0.0.2 → hyperpocket-0.1.8}/PKG-INFO +101 -72
- {hyperpocket-0.0.2 → hyperpocket-0.1.8}/README.md +83 -49
- {hyperpocket-0.0.2 → hyperpocket-0.1.8}/hyperpocket/auth/README.md +3 -3
- {hyperpocket-0.0.2 → hyperpocket-0.1.8}/hyperpocket/auth/__init__.py +0 -8
- hyperpocket-0.1.8/hyperpocket/auth/gumloop/context.py +13 -0
- hyperpocket-0.1.8/hyperpocket/auth/gumloop/token_context.py +15 -0
- hyperpocket-0.1.8/hyperpocket/auth/gumloop/token_handler.py +66 -0
- hyperpocket-0.1.8/hyperpocket/auth/gumloop/token_schema.py +8 -0
- {hyperpocket-0.0.2 → hyperpocket-0.1.8}/hyperpocket/auth/linear/token_context.py +1 -1
- hyperpocket-0.1.8/hyperpocket/auth/notion/README.md +28 -0
- hyperpocket-0.1.8/hyperpocket/auth/notion/context.py +15 -0
- hyperpocket-0.1.8/hyperpocket/auth/notion/token_context.py +14 -0
- hyperpocket-0.1.8/hyperpocket/auth/notion/token_handler.py +65 -0
- hyperpocket-0.1.8/hyperpocket/auth/notion/token_schema.py +10 -0
- {hyperpocket-0.0.2 → hyperpocket-0.1.8}/hyperpocket/auth/provider.py +8 -5
- hyperpocket-0.1.8/hyperpocket/auth/reddit/context.py +15 -0
- hyperpocket-0.1.8/hyperpocket/auth/reddit/oauth2_context.py +32 -0
- hyperpocket-0.1.8/hyperpocket/auth/reddit/oauth2_handler.py +151 -0
- hyperpocket-0.1.8/hyperpocket/auth/reddit/oauth2_schema.py +18 -0
- {hyperpocket-0.0.2 → hyperpocket-0.1.8}/hyperpocket/auth/slack/token_context.py +1 -1
- hyperpocket-0.1.8/hyperpocket/builtin.py +63 -0
- hyperpocket-0.1.8/hyperpocket/cli/__main__.py +24 -0
- hyperpocket-0.1.8/hyperpocket/cli/auth.py +83 -0
- hyperpocket-0.1.8/hyperpocket/cli/codegen/auth/__init__.py +13 -0
- hyperpocket-0.1.8/hyperpocket/cli/codegen/auth/auth_context_template.py +16 -0
- hyperpocket-0.1.8/hyperpocket/cli/codegen/auth/auth_token_context_template.py +16 -0
- hyperpocket-0.1.8/hyperpocket/cli/codegen/auth/auth_token_handler_template.py +69 -0
- hyperpocket-0.1.8/hyperpocket/cli/codegen/auth/auth_token_schema_template.py +12 -0
- hyperpocket-0.1.8/hyperpocket/cli/codegen/auth/server_auth_template.py +18 -0
- hyperpocket-0.1.8/hyperpocket/cli/eject.py +19 -0
- {hyperpocket-0.0.2 → hyperpocket-0.1.8}/hyperpocket/cli/sync.py +5 -5
- {hyperpocket-0.0.2 → hyperpocket-0.1.8}/hyperpocket/config/settings.py +2 -4
- {hyperpocket-0.0.2 → hyperpocket-0.1.8}/hyperpocket/futures/futurestore.py +0 -1
- {hyperpocket-0.0.2 → hyperpocket-0.1.8}/hyperpocket/pocket_auth.py +25 -5
- hyperpocket-0.0.2/hyperpocket/pocket_main.py → hyperpocket-0.1.8/hyperpocket/pocket_core.py +86 -175
- hyperpocket-0.1.8/hyperpocket/pocket_main.py +305 -0
- hyperpocket-0.1.8/hyperpocket/prompts.py +13 -0
- hyperpocket-0.1.8/hyperpocket/repository/__init__.py +5 -0
- {hyperpocket-0.0.2 → hyperpocket-0.1.8}/hyperpocket/repository/lock.py +19 -0
- {hyperpocket-0.0.2 → hyperpocket-0.1.8}/hyperpocket/repository/lockfile.py +19 -13
- hyperpocket-0.1.8/hyperpocket/repository/repository.py +43 -0
- hyperpocket-0.1.8/hyperpocket/server/auth/__init__.py +9 -0
- hyperpocket-0.1.8/hyperpocket/server/auth/gumloop.py +16 -0
- hyperpocket-0.1.8/hyperpocket/server/auth/notion.py +19 -0
- hyperpocket-0.1.8/hyperpocket/server/auth/reddit.py +16 -0
- {hyperpocket-0.0.2 → hyperpocket-0.1.8}/hyperpocket/server/server.py +52 -16
- hyperpocket-0.1.8/hyperpocket/server/tool/dto/script.py +28 -0
- hyperpocket-0.1.8/hyperpocket/server/tool/wasm.py +43 -0
- {hyperpocket-0.0.2 → hyperpocket-0.1.8}/hyperpocket/session/README.md +2 -2
- {hyperpocket-0.0.2 → hyperpocket-0.1.8}/hyperpocket/session/in_memory.py +18 -5
- {hyperpocket-0.0.2 → hyperpocket-0.1.8}/hyperpocket/session/interface.py +14 -0
- {hyperpocket-0.0.2 → hyperpocket-0.1.8}/hyperpocket/session/redis.py +29 -5
- {hyperpocket-0.0.2 → hyperpocket-0.1.8}/hyperpocket/tool/README.md +16 -12
- {hyperpocket-0.0.2 → hyperpocket-0.1.8}/hyperpocket/tool/__init__.py +4 -3
- {hyperpocket-0.0.2 → hyperpocket-0.1.8}/hyperpocket/tool/function/README.md +39 -10
- {hyperpocket-0.0.2 → hyperpocket-0.1.8}/hyperpocket/tool/function/__init__.py +2 -0
- {hyperpocket-0.0.2 → hyperpocket-0.1.8}/hyperpocket/tool/function/annotation.py +2 -1
- hyperpocket-0.1.8/hyperpocket/tool/function/tool.py +172 -0
- hyperpocket-0.1.8/hyperpocket/tool/tests/test_function_tool.py +321 -0
- hyperpocket-0.1.8/hyperpocket/tool/tests/test_wasm_tool.py +73 -0
- {hyperpocket-0.0.2 → hyperpocket-0.1.8}/hyperpocket/tool/tool.py +65 -2
- {hyperpocket-0.0.2 → hyperpocket-0.1.8}/hyperpocket/tool/wasm/README.md +27 -5
- {hyperpocket-0.0.2 → hyperpocket-0.1.8}/hyperpocket/tool/wasm/script.py +40 -1
- {hyperpocket-0.0.2 → hyperpocket-0.1.8}/hyperpocket/tool/wasm/templates/python.py +32 -14
- {hyperpocket-0.0.2 → hyperpocket-0.1.8}/hyperpocket/tool/wasm/tool.py +21 -18
- hyperpocket-0.1.8/hyperpocket/tool_like.py +5 -0
- hyperpocket-0.1.8/hyperpocket/util/__init__.py +1 -0
- {hyperpocket-0.0.2 → hyperpocket-0.1.8}/hyperpocket/util/extract_func_param_desc_from_docstring.py +4 -4
- {hyperpocket-0.0.2 → hyperpocket-0.1.8}/hyperpocket/util/function_to_model.py +5 -2
- hyperpocket-0.1.8/hyperpocket/util/json_schema_to_model.py +88 -0
- hyperpocket-0.1.8/pyproject.toml +55 -0
- hyperpocket-0.1.8/tests/auth/__init__.py +0 -0
- {hyperpocket-0.0.2/hyperpocket/auth/tests → hyperpocket-0.1.8/tests/auth}/test_google_oauth2_handler.py +1 -2
- hyperpocket-0.1.8/tests/auth/test_gumloop_token_handler.py +67 -0
- hyperpocket-0.1.8/tests/auth/test_notion_token_handler.py +66 -0
- {hyperpocket-0.0.2/hyperpocket/auth/tests → hyperpocket-0.1.8/tests/auth}/test_slack_oauth2_handler.py +4 -5
- {hyperpocket-0.0.2/hyperpocket/auth/tests → hyperpocket-0.1.8/tests/auth}/test_slack_token_handler.py +18 -18
- hyperpocket-0.1.8/tests/session/__init__.py +0 -0
- {hyperpocket-0.0.2/hyperpocket/session/tests → hyperpocket-0.1.8/tests/session}/test_in_memory.py +3 -2
- {hyperpocket-0.0.2/hyperpocket/session/tests → hyperpocket-0.1.8/tests/session}/test_redis.py +3 -2
- hyperpocket-0.1.8/tests/test_pocket.py +174 -0
- {hyperpocket-0.0.2/hyperpocket → hyperpocket-0.1.8}/tests/test_pocket_auth.py +3 -2
- hyperpocket-0.1.8/tests/tool/__init__.py +0 -0
- hyperpocket-0.1.8/uv.lock +996 -0
- hyperpocket-0.0.2/hyperpocket/auth/README.KR.md +0 -309
- hyperpocket-0.0.2/hyperpocket/auth/slack/tests/test_oauth2_handler.py +0 -32
- hyperpocket-0.0.2/hyperpocket/auth/slack/tests/test_token_handler.py +0 -23
- hyperpocket-0.0.2/hyperpocket/cli/__main__.py +0 -12
- hyperpocket-0.0.2/hyperpocket/external/__init__.py +0 -7
- hyperpocket-0.0.2/hyperpocket/external/github_client.py +0 -19
- hyperpocket-0.0.2/hyperpocket/prompts.py +0 -15
- hyperpocket-0.0.2/hyperpocket/repository/__init__.py +0 -5
- hyperpocket-0.0.2/hyperpocket/repository/repository.py +0 -18
- hyperpocket-0.0.2/hyperpocket/server/auth/__init__.py +0 -15
- hyperpocket-0.0.2/hyperpocket/server/tool/dto/script.py +0 -15
- hyperpocket-0.0.2/hyperpocket/server/tool/wasm.py +0 -31
- hyperpocket-0.0.2/hyperpocket/session/README.KR.md +0 -62
- hyperpocket-0.0.2/hyperpocket/tests/test_pocket.py +0 -116
- hyperpocket-0.0.2/hyperpocket/tool/README.KR.md +0 -68
- hyperpocket-0.0.2/hyperpocket/tool/builtins/example/add_tool.py +0 -18
- hyperpocket-0.0.2/hyperpocket/tool/function/README.KR.md +0 -159
- hyperpocket-0.0.2/hyperpocket/tool/function/tool.py +0 -87
- hyperpocket-0.0.2/hyperpocket/tool/wasm/README.KR.md +0 -144
- hyperpocket-0.0.2/hyperpocket/util/__init__.py +0 -1
- hyperpocket-0.0.2/hyperpocket/util/json_schema_to_model.py +0 -69
- hyperpocket-0.0.2/pyproject.toml +0 -40
- {hyperpocket-0.0.2/hyperpocket/auth/calendly → hyperpocket-0.1.8}/__init__.py +0 -0
- {hyperpocket-0.0.2 → hyperpocket-0.1.8}/hyperpocket/__init__.py +0 -0
- {hyperpocket-0.0.2/hyperpocket/auth/github → hyperpocket-0.1.8/hyperpocket/auth/calendly}/__init__.py +0 -0
- {hyperpocket-0.0.2 → hyperpocket-0.1.8}/hyperpocket/auth/calendly/context.py +0 -0
- {hyperpocket-0.0.2 → hyperpocket-0.1.8}/hyperpocket/auth/calendly/oauth2_context.py +0 -0
- {hyperpocket-0.0.2 → hyperpocket-0.1.8}/hyperpocket/auth/calendly/oauth2_handler.py +0 -0
- {hyperpocket-0.0.2 → hyperpocket-0.1.8}/hyperpocket/auth/calendly/oauth2_schema.py +0 -0
- {hyperpocket-0.0.2 → hyperpocket-0.1.8}/hyperpocket/auth/context.py +0 -0
- {hyperpocket-0.0.2/hyperpocket/auth/google → hyperpocket-0.1.8/hyperpocket/auth/github}/__init__.py +0 -0
- {hyperpocket-0.0.2 → hyperpocket-0.1.8}/hyperpocket/auth/github/context.py +0 -0
- {hyperpocket-0.0.2 → hyperpocket-0.1.8}/hyperpocket/auth/github/oauth2_context.py +0 -0
- {hyperpocket-0.0.2 → hyperpocket-0.1.8}/hyperpocket/auth/github/oauth2_handler.py +0 -0
- {hyperpocket-0.0.2 → hyperpocket-0.1.8}/hyperpocket/auth/github/oauth2_schema.py +0 -0
- {hyperpocket-0.0.2 → hyperpocket-0.1.8}/hyperpocket/auth/github/token_context.py +0 -0
- {hyperpocket-0.0.2 → hyperpocket-0.1.8}/hyperpocket/auth/github/token_handler.py +0 -0
- {hyperpocket-0.0.2 → hyperpocket-0.1.8}/hyperpocket/auth/github/token_schema.py +0 -0
- {hyperpocket-0.0.2/hyperpocket/auth/linear → hyperpocket-0.1.8/hyperpocket/auth/google}/__init__.py +0 -0
- {hyperpocket-0.0.2 → hyperpocket-0.1.8}/hyperpocket/auth/google/context.py +0 -0
- {hyperpocket-0.0.2 → hyperpocket-0.1.8}/hyperpocket/auth/google/oauth2_context.py +0 -0
- {hyperpocket-0.0.2 → hyperpocket-0.1.8}/hyperpocket/auth/google/oauth2_handler.py +0 -0
- {hyperpocket-0.0.2 → hyperpocket-0.1.8}/hyperpocket/auth/google/oauth2_schema.py +0 -0
- {hyperpocket-0.0.2/hyperpocket/auth/slack → hyperpocket-0.1.8/hyperpocket/auth/gumloop}/__init__.py +0 -0
- {hyperpocket-0.0.2 → hyperpocket-0.1.8}/hyperpocket/auth/handler.py +0 -0
- {hyperpocket-0.0.2/hyperpocket/auth/slack/tests → hyperpocket-0.1.8/hyperpocket/auth/linear}/__init__.py +0 -0
- {hyperpocket-0.0.2 → hyperpocket-0.1.8}/hyperpocket/auth/linear/context.py +0 -0
- {hyperpocket-0.0.2 → hyperpocket-0.1.8}/hyperpocket/auth/linear/token_handler.py +0 -0
- {hyperpocket-0.0.2 → hyperpocket-0.1.8}/hyperpocket/auth/linear/token_schema.py +0 -0
- {hyperpocket-0.0.2/hyperpocket/auth/tests → hyperpocket-0.1.8/hyperpocket/auth/notion}/__init__.py +0 -0
- {hyperpocket-0.0.2/hyperpocket/cli → hyperpocket-0.1.8/hyperpocket/auth/reddit}/__init__.py +0 -0
- {hyperpocket-0.0.2 → hyperpocket-0.1.8}/hyperpocket/auth/schema.py +0 -0
- {hyperpocket-0.0.2/hyperpocket/server/tool/dto → hyperpocket-0.1.8/hyperpocket/auth/slack}/__init__.py +0 -0
- {hyperpocket-0.0.2 → hyperpocket-0.1.8}/hyperpocket/auth/slack/context.py +0 -0
- {hyperpocket-0.0.2 → hyperpocket-0.1.8}/hyperpocket/auth/slack/oauth2_context.py +0 -0
- {hyperpocket-0.0.2 → hyperpocket-0.1.8}/hyperpocket/auth/slack/oauth2_handler.py +0 -0
- {hyperpocket-0.0.2 → hyperpocket-0.1.8}/hyperpocket/auth/slack/oauth2_schema.py +0 -0
- {hyperpocket-0.0.2 → hyperpocket-0.1.8}/hyperpocket/auth/slack/token_handler.py +0 -0
- {hyperpocket-0.0.2 → hyperpocket-0.1.8}/hyperpocket/auth/slack/token_schema.py +0 -0
- {hyperpocket-0.0.2/hyperpocket/session/tests → hyperpocket-0.1.8/hyperpocket/cli}/__init__.py +0 -0
- {hyperpocket-0.0.2/hyperpocket/tests → hyperpocket-0.1.8/hyperpocket/cli/codegen}/__init__.py +0 -0
- {hyperpocket-0.0.2 → hyperpocket-0.1.8}/hyperpocket/cli/pull.py +0 -0
- {hyperpocket-0.0.2 → hyperpocket-0.1.8}/hyperpocket/config/__init__.py +0 -0
- {hyperpocket-0.0.2 → hyperpocket-0.1.8}/hyperpocket/config/auth.py +0 -0
- {hyperpocket-0.0.2 → hyperpocket-0.1.8}/hyperpocket/config/git.py +0 -0
- {hyperpocket-0.0.2 → hyperpocket-0.1.8}/hyperpocket/config/logger.py +0 -0
- {hyperpocket-0.0.2 → hyperpocket-0.1.8}/hyperpocket/config/session.py +0 -0
- {hyperpocket-0.0.2 → hyperpocket-0.1.8}/hyperpocket/constants.py +0 -0
- {hyperpocket-0.0.2 → hyperpocket-0.1.8}/hyperpocket/futures/__init__.py +0 -0
- {hyperpocket-0.0.2 → hyperpocket-0.1.8}/hyperpocket/server/__init__.py +0 -0
- {hyperpocket-0.0.2 → hyperpocket-0.1.8}/hyperpocket/server/auth/calendly.py +0 -0
- {hyperpocket-0.0.2 → hyperpocket-0.1.8}/hyperpocket/server/auth/github.py +0 -0
- {hyperpocket-0.0.2 → hyperpocket-0.1.8}/hyperpocket/server/auth/google.py +0 -0
- {hyperpocket-0.0.2 → hyperpocket-0.1.8}/hyperpocket/server/auth/linear.py +0 -0
- {hyperpocket-0.0.2 → hyperpocket-0.1.8}/hyperpocket/server/auth/slack.py +0 -0
- {hyperpocket-0.0.2 → hyperpocket-0.1.8}/hyperpocket/server/auth/token.py +0 -0
- {hyperpocket-0.0.2 → hyperpocket-0.1.8}/hyperpocket/server/proxy.py +0 -0
- {hyperpocket-0.0.2 → hyperpocket-0.1.8}/hyperpocket/server/tool/__init__.py +0 -0
- {hyperpocket-0.0.2/hyperpocket/tool/builtins → hyperpocket-0.1.8/hyperpocket/server/tool/dto}/__init__.py +0 -0
- {hyperpocket-0.0.2 → hyperpocket-0.1.8}/hyperpocket/session/__init__.py +0 -0
- {hyperpocket-0.0.2/hyperpocket/tool/builtins/example → hyperpocket-0.1.8/hyperpocket/tool/tests}/__init__.py +0 -0
- {hyperpocket-0.0.2 → hyperpocket-0.1.8}/hyperpocket/tool/wasm/__init__.py +0 -0
- {hyperpocket-0.0.2 → hyperpocket-0.1.8}/hyperpocket/tool/wasm/browser.py +0 -0
- {hyperpocket-0.0.2 → hyperpocket-0.1.8}/hyperpocket/tool/wasm/invoker.py +0 -0
- {hyperpocket-0.0.2 → hyperpocket-0.1.8}/hyperpocket/tool/wasm/templates/__init__.py +0 -0
- {hyperpocket-0.0.2 → hyperpocket-0.1.8}/hyperpocket/tool/wasm/templates/node.py +0 -0
- {hyperpocket-0.0.2 → hyperpocket-0.1.8}/hyperpocket/util/find_all_leaf_class_in_package.py +0 -0
- {hyperpocket-0.0.2 → hyperpocket-0.1.8}/hyperpocket/util/find_all_subclass_in_package.py +0 -0
- {hyperpocket-0.0.2 → hyperpocket-0.1.8}/hyperpocket/util/flatten_json_schema.py +0 -0
- {hyperpocket-0.0.2 → hyperpocket-0.1.8}/hyperpocket/util/get_objects_from_subpackage.py +0 -0
- {hyperpocket-0.0.2/hyperpocket/tool → hyperpocket-0.1.8}/tests/__init__.py +0 -0
- {hyperpocket-0.0.2/hyperpocket/tool/tests → hyperpocket-0.1.8/tests/tool}/test_function_tool.py +0 -0
@@ -0,0 +1,157 @@
|
|
1
|
+
.vs/
|
2
|
+
.vscode/
|
3
|
+
.idea/
|
4
|
+
# Byte-compiled / optimized / DLL files
|
5
|
+
__pycache__/
|
6
|
+
*.py[cod]
|
7
|
+
*$py.class
|
8
|
+
|
9
|
+
# C extensions
|
10
|
+
*.so
|
11
|
+
|
12
|
+
# Distribution / packaging
|
13
|
+
.Python
|
14
|
+
build/
|
15
|
+
develop-eggs/
|
16
|
+
dist/
|
17
|
+
downloads/
|
18
|
+
eggs/
|
19
|
+
.eggs/
|
20
|
+
lib/
|
21
|
+
lib64/
|
22
|
+
parts/
|
23
|
+
sdist/
|
24
|
+
var/
|
25
|
+
wheels/
|
26
|
+
pip-wheel-metadata/
|
27
|
+
share/python-wheels/
|
28
|
+
*.egg-info/
|
29
|
+
.installed.cfg
|
30
|
+
*.egg
|
31
|
+
MANIFEST
|
32
|
+
|
33
|
+
# Google GitHub Actions credentials files created by:
|
34
|
+
# https://github.com/google-github-actions/auth
|
35
|
+
#
|
36
|
+
# That action recommends adding this gitignore to prevent accidentally committing keys.
|
37
|
+
gha-creds-*.json
|
38
|
+
|
39
|
+
# PyInstaller
|
40
|
+
# Usually these files are written by a python script from a template
|
41
|
+
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
42
|
+
*.manifest
|
43
|
+
*.spec
|
44
|
+
|
45
|
+
# Unit test / coverage reports
|
46
|
+
htmlcov/
|
47
|
+
.tox/
|
48
|
+
.nox/
|
49
|
+
.coverage
|
50
|
+
.coverage.*
|
51
|
+
.cache
|
52
|
+
nosetests.xml
|
53
|
+
coverage.xml
|
54
|
+
*.cover
|
55
|
+
*.py,cover
|
56
|
+
.hypothesis/
|
57
|
+
.pytest_cache/
|
58
|
+
|
59
|
+
# Translations
|
60
|
+
*.mo
|
61
|
+
*.pot
|
62
|
+
|
63
|
+
# Django stuff:
|
64
|
+
*.log
|
65
|
+
local_settings.py
|
66
|
+
db.sqlite3
|
67
|
+
db.sqlite3-journal
|
68
|
+
|
69
|
+
# Flask stuff:
|
70
|
+
instance/
|
71
|
+
.webassets-cache
|
72
|
+
|
73
|
+
# Scrapy stuff:
|
74
|
+
.scrapy
|
75
|
+
|
76
|
+
|
77
|
+
# Jupyter Notebook
|
78
|
+
.ipynb_checkpoints
|
79
|
+
notebooks/
|
80
|
+
|
81
|
+
# IPython
|
82
|
+
profile_default/
|
83
|
+
ipython_config.py
|
84
|
+
|
85
|
+
# pyenv
|
86
|
+
.python-version
|
87
|
+
|
88
|
+
# PEP 582; used by e.g. github.com/David-OConnor/pyflow
|
89
|
+
__pypackages__/
|
90
|
+
|
91
|
+
# Celery stuff
|
92
|
+
celerybeat-schedule
|
93
|
+
celerybeat.pid
|
94
|
+
|
95
|
+
# SageMath parsed files
|
96
|
+
*.sage.py
|
97
|
+
|
98
|
+
# Environments
|
99
|
+
.env
|
100
|
+
.envrc
|
101
|
+
.venv*
|
102
|
+
venv*
|
103
|
+
env/
|
104
|
+
ENV/
|
105
|
+
env.bak/
|
106
|
+
|
107
|
+
# Spyder project settings
|
108
|
+
.spyderproject
|
109
|
+
.spyproject
|
110
|
+
|
111
|
+
# Rope project settings
|
112
|
+
.ropeproject
|
113
|
+
|
114
|
+
# mkdocs documentation
|
115
|
+
/site
|
116
|
+
|
117
|
+
# mypy
|
118
|
+
.mypy_cache/
|
119
|
+
.mypy_cache_test/
|
120
|
+
.dmypy.json
|
121
|
+
dmypy.json
|
122
|
+
|
123
|
+
# Pyre type checker
|
124
|
+
.pyre/
|
125
|
+
|
126
|
+
# macOS display setting files
|
127
|
+
.DS_Store
|
128
|
+
|
129
|
+
# Wandb directory
|
130
|
+
wandb/
|
131
|
+
|
132
|
+
# asdf tool versions
|
133
|
+
.tool-versions
|
134
|
+
/.ruff_cache/
|
135
|
+
|
136
|
+
*.pkl
|
137
|
+
*.bin
|
138
|
+
|
139
|
+
# integration test artifacts
|
140
|
+
data_map*
|
141
|
+
\[('_type', 'fake'), ('stop', None)]
|
142
|
+
|
143
|
+
# Replit files
|
144
|
+
*replit*
|
145
|
+
|
146
|
+
|
147
|
+
prof
|
148
|
+
virtualenv/
|
149
|
+
|
150
|
+
# Ignore dynaconf secret files
|
151
|
+
**/.secrets.toml
|
152
|
+
*.xml
|
153
|
+
*.iml
|
154
|
+
pocket.lock
|
155
|
+
.log/
|
156
|
+
.pocket/
|
157
|
+
_build/
|
@@ -1,31 +1,26 @@
|
|
1
|
-
Metadata-Version: 2.
|
1
|
+
Metadata-Version: 2.4
|
2
2
|
Name: hyperpocket
|
3
|
-
Version: 0.
|
3
|
+
Version: 0.1.8
|
4
4
|
Summary: Building AI agent with hyperpocket tool in a flash
|
5
|
-
|
6
|
-
Author: VESSL AI Devs
|
7
|
-
Author-email: dev@vessl.ai
|
8
|
-
Requires-Python: >=3.11,<4.0
|
9
|
-
Classifier: Programming Language :: Python :: 3
|
10
|
-
Classifier: Programming Language :: Python :: 3.11
|
11
|
-
Classifier: Programming Language :: Python :: 3.12
|
12
|
-
Classifier: Programming Language :: Python :: 3.13
|
13
|
-
Requires-Dist: click (>=8.1.7,<9.0.0)
|
14
|
-
Requires-Dist: dynaconf (>=3.2.6,<4.0.0)
|
15
|
-
Requires-Dist: fastapi (>=0.115.5,<0.116.0)
|
16
|
-
Requires-Dist: gitpython (>=3.1.43,<4.0.0)
|
17
|
-
Requires-Dist: httpx (==0.27)
|
18
|
-
Requires-Dist: jinja2 (>=3.1.4,<4.0.0)
|
19
|
-
Requires-Dist: multiprocess (>=0.70.17,<0.71.0)
|
20
|
-
Requires-Dist: playwright (>=1.49.0,<2.0.0)
|
21
|
-
Requires-Dist: pydantic (>=2.10.2,<3.0.0)
|
22
|
-
Requires-Dist: pygithub (>=2.5.0,<3.0.0)
|
23
|
-
Requires-Dist: python-multipart (>=0.0.19,<0.0.20)
|
24
|
-
Requires-Dist: redis (>=5.2.1,<6.0.0)
|
25
|
-
Requires-Dist: requests (>=2.32.3,<3.0.0)
|
26
|
-
Requires-Dist: toml (>=0.10.2,<0.11.0)
|
27
|
-
Requires-Dist: uvicorn (>=0.32.1,<0.33.0)
|
5
|
+
Project-URL: Homepage, https://vessl-ai.github.io/hyperpocket
|
28
6
|
Project-URL: Repository, https://github.com/vessl-ai/hyperpocket
|
7
|
+
Author-email: VESSL AI Devs <dev@vessl.ai>
|
8
|
+
Requires-Python: >=3.10
|
9
|
+
Requires-Dist: click>=8.1.7
|
10
|
+
Requires-Dist: dynaconf>=3.2.6
|
11
|
+
Requires-Dist: fastapi>=0.115.5
|
12
|
+
Requires-Dist: gitpython>=3.1.43
|
13
|
+
Requires-Dist: httpx==0.27
|
14
|
+
Requires-Dist: jinja2>=3.1.4
|
15
|
+
Requires-Dist: multiprocess>=0.70.17
|
16
|
+
Requires-Dist: playwright>=1.49.0
|
17
|
+
Requires-Dist: pydantic>=2.10.2
|
18
|
+
Requires-Dist: pygithub>=2.5.0
|
19
|
+
Requires-Dist: python-multipart>=0.0.19
|
20
|
+
Requires-Dist: redis>=5.2.1
|
21
|
+
Requires-Dist: requests>=2.32.3
|
22
|
+
Requires-Dist: toml>=0.10.2
|
23
|
+
Requires-Dist: uvicorn>=0.32.1
|
29
24
|
Description-Content-Type: text/markdown
|
30
25
|
|
31
26
|
# Pocket 👛
|
@@ -59,10 +54,10 @@ with the dependency spaghetti.
|
|
59
54
|
|
60
55
|
## Installation
|
61
56
|
|
62
|
-
1. install
|
57
|
+
1. install hyperpocket
|
63
58
|
|
64
59
|
```bash
|
65
|
-
pip install
|
60
|
+
pip install hyperpocket
|
66
61
|
```
|
67
62
|
|
68
63
|
2. install playwright
|
@@ -87,17 +82,15 @@ Or just use LLM API Clients out of the box.
|
|
87
82
|
### Using out-of-the-box tools
|
88
83
|
|
89
84
|
```python
|
85
|
+
from hyperpocket.tool import from_git
|
90
86
|
from langchain_openai import ChatOpenAI
|
91
87
|
|
92
|
-
|
93
|
-
import hyperpocket.curated_tools
|
94
|
-
from pocket_langchain import PocketLangchain
|
88
|
+
from hyperpocket_langchain import PocketLangchain
|
95
89
|
|
96
90
|
pklc = PocketLangchain(
|
97
91
|
tools=[
|
98
|
-
|
99
|
-
|
100
|
-
"https://github.com/my-org/some-awesome-tool",
|
92
|
+
from_git("https://github.com/vessl-ai/hyperawesometools", "main", "managed-tools/slack/get-message"),
|
93
|
+
from_git("https://github.com/vessl-ai/hyperawesometools", "main", "managed-tools/slack/post-message"),
|
101
94
|
]
|
102
95
|
)
|
103
96
|
tools = pklc.get_tools()
|
@@ -116,40 +109,38 @@ Pocket provides way to use end user auth easily.
|
|
116
109
|
|
117
110
|
- Supported methods
|
118
111
|
|
119
|
-
|
120
|
-
|
121
|
-
|
112
|
+
- [x] OAuth
|
113
|
+
- [x] Token
|
114
|
+
- [ ] Basic Auth (Username, Password)
|
122
115
|
|
123
116
|
- Supported OAuth Providers
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
117
|
+
- [x] Google
|
118
|
+
- [x] GitHub
|
119
|
+
- [x] Slack
|
120
|
+
- [x] Linear
|
121
|
+
- [ ] Facebook
|
122
|
+
- [ ] X (Previously Twitter)
|
123
|
+
- [ ] LinkedIn
|
124
|
+
- [ ] Discord
|
125
|
+
- [ ] Zoom
|
126
|
+
- [ ] Microsoft
|
127
|
+
- [ ] Spotify
|
128
|
+
- [ ] Twitch
|
136
129
|
|
137
130
|
You can manage your auths in request-wise level. (e.g. you can use different auths for different requests)
|
138
131
|
|
139
132
|
```python
|
133
|
+
from hyperpocket.tool import from_git
|
140
134
|
from langchain_openai import ChatOpenAI
|
141
135
|
from langgraph.graph import StateGraph, START, MessagesState
|
142
136
|
from langgraph.prebuilt import tools_condition
|
143
137
|
|
144
|
-
|
145
|
-
import hyperpocket.curated_tools
|
146
|
-
from pocket_langgraph import PocketLanggraph
|
138
|
+
from hyperpocket_langgraph import PocketLanggraph
|
147
139
|
|
148
140
|
pklg = PocketLanggraph(
|
149
141
|
tools=[
|
150
|
-
|
151
|
-
|
152
|
-
"https://github.com/my-org/some-awesome-tool",
|
142
|
+
from_git("https://github.com/vessl-ai/hyperawesometools", "main", "managed-tools/slack/get-message"),
|
143
|
+
from_git("https://github.com/vessl-ai/hyperawesometools", "main", "managed-tools/slack/post-message"),
|
153
144
|
],
|
154
145
|
)
|
155
146
|
llm = ChatOpenAI()
|
@@ -175,12 +166,12 @@ graph_builder.compile()
|
|
175
166
|
```
|
176
167
|
|
177
168
|
```python
|
169
|
+
from hyperpocket.config import secret
|
170
|
+
from hyperpocket.tool import from_git
|
178
171
|
from llama_index.core.agent import FunctionCallingAgent
|
179
172
|
from llama_index.llms.openai import OpenAI
|
180
|
-
from pocket_llamaindex import PocketLlamaindex
|
181
173
|
|
182
|
-
from
|
183
|
-
from hyperpocket.tool import from_git
|
174
|
+
from hyperpocket_llamaindex import PocketLlamaindex
|
184
175
|
|
185
176
|
llm = OpenAI(api_key=secret["OPENAI_API_KEY"])
|
186
177
|
pocket = PocketLlamaindex(
|
@@ -273,11 +264,11 @@ client_secret = "" # your github client secret
|
|
273
264
|
|
274
265
|
- While creating your github OAuth app, configuring your app's `Authorization callback URL` is different for your
|
275
266
|
development environment and production environment.
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
267
|
+
- For development environment, you can use `http://localhost:8000/auth/github/callback`
|
268
|
+
- **Note**: Default port for pocket dev server is `8000`. If you are using a different port, make sure to
|
269
|
+
replace `8000` with your actual port number.
|
270
|
+
- For production environment, you can use `https://yourdomain.com/auth/github/callback`
|
271
|
+
- **Note**: Make sure to replace `yourdomain.com` with your actual domain name that this app will be hosted on.
|
281
272
|
|
282
273
|
#### How to integrate SLACK OAuth app
|
283
274
|
|
@@ -288,15 +279,53 @@ client_secret = "" # your github client secret
|
|
288
279
|
- Redirect URLs :
|
289
280
|
`{public_server_protocol}://{public_hostname}:[{public_server_port}]/{callback_url_rewrite_prefix}/auth/slack/oauth2/callback`
|
290
281
|
- Scopes : What you want to request to user.
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
|
282
|
+
- Recommended scopes :
|
283
|
+
- channels:history,
|
284
|
+
- channels:read,
|
285
|
+
- chat:write,
|
286
|
+
- groups:history,
|
287
|
+
- groups:read,
|
288
|
+
- im:history,
|
289
|
+
- mpim:history,
|
290
|
+
- reactions:read,
|
291
|
+
- reactions:write,
|
301
292
|
|
302
293
|
3. Set your Slack APP Client ID / Client Secret in `$HOME/.pocket/settings.toml`
|
294
|
+
|
295
|
+
#### How to start adding a new token auth
|
296
|
+
|
297
|
+
1. Generate boilerplate codes for token-based auth services ?
|
298
|
+
|
299
|
+
```
|
300
|
+
# service_name should be lowercase including underscore
|
301
|
+
poetry run hyperpocket devtool create-token-auth-template {service_name}
|
302
|
+
```
|
303
|
+
|
304
|
+
It will generate boilerplate code lines for a new token-based auth service
|
305
|
+
|
306
|
+
2. Extend AuthProvider enum to add your new auth provider.
|
307
|
+
|
308
|
+
```python
|
309
|
+
class AuthProvider(Enum):
|
310
|
+
SERVICE = 'service'
|
311
|
+
```
|
312
|
+
|
313
|
+
3. Specify auth provider for tools
|
314
|
+
|
315
|
+
1) github repo or local
|
316
|
+
|
317
|
+
```toml
|
318
|
+
[auth]
|
319
|
+
auth_provider = "{service_name}"
|
320
|
+
auth_handler = "{service_name}-token"
|
321
|
+
scopes = []
|
322
|
+
```
|
323
|
+
|
324
|
+
2. function_tool
|
325
|
+
|
326
|
+
```python
|
327
|
+
@function_tool(
|
328
|
+
auth_provider=AuthProvider.SERVICE
|
329
|
+
)
|
330
|
+
def my_function(**kwargs):
|
331
|
+
```
|
@@ -29,10 +29,10 @@ with the dependency spaghetti.
|
|
29
29
|
|
30
30
|
## Installation
|
31
31
|
|
32
|
-
1. install
|
32
|
+
1. install hyperpocket
|
33
33
|
|
34
34
|
```bash
|
35
|
-
pip install
|
35
|
+
pip install hyperpocket
|
36
36
|
```
|
37
37
|
|
38
38
|
2. install playwright
|
@@ -57,17 +57,15 @@ Or just use LLM API Clients out of the box.
|
|
57
57
|
### Using out-of-the-box tools
|
58
58
|
|
59
59
|
```python
|
60
|
+
from hyperpocket.tool import from_git
|
60
61
|
from langchain_openai import ChatOpenAI
|
61
62
|
|
62
|
-
|
63
|
-
import hyperpocket.curated_tools
|
64
|
-
from pocket_langchain import PocketLangchain
|
63
|
+
from hyperpocket_langchain import PocketLangchain
|
65
64
|
|
66
65
|
pklc = PocketLangchain(
|
67
66
|
tools=[
|
68
|
-
|
69
|
-
|
70
|
-
"https://github.com/my-org/some-awesome-tool",
|
67
|
+
from_git("https://github.com/vessl-ai/hyperawesometools", "main", "managed-tools/slack/get-message"),
|
68
|
+
from_git("https://github.com/vessl-ai/hyperawesometools", "main", "managed-tools/slack/post-message"),
|
71
69
|
]
|
72
70
|
)
|
73
71
|
tools = pklc.get_tools()
|
@@ -86,40 +84,38 @@ Pocket provides way to use end user auth easily.
|
|
86
84
|
|
87
85
|
- Supported methods
|
88
86
|
|
89
|
-
|
90
|
-
|
91
|
-
|
87
|
+
- [x] OAuth
|
88
|
+
- [x] Token
|
89
|
+
- [ ] Basic Auth (Username, Password)
|
92
90
|
|
93
91
|
- Supported OAuth Providers
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
92
|
+
- [x] Google
|
93
|
+
- [x] GitHub
|
94
|
+
- [x] Slack
|
95
|
+
- [x] Linear
|
96
|
+
- [ ] Facebook
|
97
|
+
- [ ] X (Previously Twitter)
|
98
|
+
- [ ] LinkedIn
|
99
|
+
- [ ] Discord
|
100
|
+
- [ ] Zoom
|
101
|
+
- [ ] Microsoft
|
102
|
+
- [ ] Spotify
|
103
|
+
- [ ] Twitch
|
106
104
|
|
107
105
|
You can manage your auths in request-wise level. (e.g. you can use different auths for different requests)
|
108
106
|
|
109
107
|
```python
|
108
|
+
from hyperpocket.tool import from_git
|
110
109
|
from langchain_openai import ChatOpenAI
|
111
110
|
from langgraph.graph import StateGraph, START, MessagesState
|
112
111
|
from langgraph.prebuilt import tools_condition
|
113
112
|
|
114
|
-
|
115
|
-
import hyperpocket.curated_tools
|
116
|
-
from pocket_langgraph import PocketLanggraph
|
113
|
+
from hyperpocket_langgraph import PocketLanggraph
|
117
114
|
|
118
115
|
pklg = PocketLanggraph(
|
119
116
|
tools=[
|
120
|
-
|
121
|
-
|
122
|
-
"https://github.com/my-org/some-awesome-tool",
|
117
|
+
from_git("https://github.com/vessl-ai/hyperawesometools", "main", "managed-tools/slack/get-message"),
|
118
|
+
from_git("https://github.com/vessl-ai/hyperawesometools", "main", "managed-tools/slack/post-message"),
|
123
119
|
],
|
124
120
|
)
|
125
121
|
llm = ChatOpenAI()
|
@@ -145,12 +141,12 @@ graph_builder.compile()
|
|
145
141
|
```
|
146
142
|
|
147
143
|
```python
|
144
|
+
from hyperpocket.config import secret
|
145
|
+
from hyperpocket.tool import from_git
|
148
146
|
from llama_index.core.agent import FunctionCallingAgent
|
149
147
|
from llama_index.llms.openai import OpenAI
|
150
|
-
from pocket_llamaindex import PocketLlamaindex
|
151
148
|
|
152
|
-
from
|
153
|
-
from hyperpocket.tool import from_git
|
149
|
+
from hyperpocket_llamaindex import PocketLlamaindex
|
154
150
|
|
155
151
|
llm = OpenAI(api_key=secret["OPENAI_API_KEY"])
|
156
152
|
pocket = PocketLlamaindex(
|
@@ -243,11 +239,11 @@ client_secret = "" # your github client secret
|
|
243
239
|
|
244
240
|
- While creating your github OAuth app, configuring your app's `Authorization callback URL` is different for your
|
245
241
|
development environment and production environment.
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
242
|
+
- For development environment, you can use `http://localhost:8000/auth/github/callback`
|
243
|
+
- **Note**: Default port for pocket dev server is `8000`. If you are using a different port, make sure to
|
244
|
+
replace `8000` with your actual port number.
|
245
|
+
- For production environment, you can use `https://yourdomain.com/auth/github/callback`
|
246
|
+
- **Note**: Make sure to replace `yourdomain.com` with your actual domain name that this app will be hosted on.
|
251
247
|
|
252
248
|
#### How to integrate SLACK OAuth app
|
253
249
|
|
@@ -258,15 +254,53 @@ client_secret = "" # your github client secret
|
|
258
254
|
- Redirect URLs :
|
259
255
|
`{public_server_protocol}://{public_hostname}:[{public_server_port}]/{callback_url_rewrite_prefix}/auth/slack/oauth2/callback`
|
260
256
|
- Scopes : What you want to request to user.
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
3. Set your Slack APP Client ID / Client Secret in `$HOME/.pocket/settings.toml`
|
257
|
+
- Recommended scopes :
|
258
|
+
- channels:history,
|
259
|
+
- channels:read,
|
260
|
+
- chat:write,
|
261
|
+
- groups:history,
|
262
|
+
- groups:read,
|
263
|
+
- im:history,
|
264
|
+
- mpim:history,
|
265
|
+
- reactions:read,
|
266
|
+
- reactions:write,
|
267
|
+
|
268
|
+
3. Set your Slack APP Client ID / Client Secret in `$HOME/.pocket/settings.toml`
|
269
|
+
|
270
|
+
#### How to start adding a new token auth
|
271
|
+
|
272
|
+
1. Generate boilerplate codes for token-based auth services ?
|
273
|
+
|
274
|
+
```
|
275
|
+
# service_name should be lowercase including underscore
|
276
|
+
poetry run hyperpocket devtool create-token-auth-template {service_name}
|
277
|
+
```
|
278
|
+
|
279
|
+
It will generate boilerplate code lines for a new token-based auth service
|
280
|
+
|
281
|
+
2. Extend AuthProvider enum to add your new auth provider.
|
282
|
+
|
283
|
+
```python
|
284
|
+
class AuthProvider(Enum):
|
285
|
+
SERVICE = 'service'
|
286
|
+
```
|
287
|
+
|
288
|
+
3. Specify auth provider for tools
|
289
|
+
|
290
|
+
1) github repo or local
|
291
|
+
|
292
|
+
```toml
|
293
|
+
[auth]
|
294
|
+
auth_provider = "{service_name}"
|
295
|
+
auth_handler = "{service_name}-token"
|
296
|
+
scopes = []
|
297
|
+
```
|
298
|
+
|
299
|
+
2. function_tool
|
300
|
+
|
301
|
+
```python
|
302
|
+
@function_tool(
|
303
|
+
auth_provider=AuthProvider.SERVICE
|
304
|
+
)
|
305
|
+
def my_function(**kwargs):
|
306
|
+
```
|
@@ -236,15 +236,15 @@ class AuthHandlerInterface(ABC):
|
|
236
236
|
- This class perform the actual prepare, authenticate, and refresh steps.
|
237
237
|
|
238
238
|
5. Add a new enum value to the `AuthProvider` Enum(only implement new auth provider)
|
239
|
-
- If a new `AuthProvider` is added, update the `AuthProvider` enum in `
|
239
|
+
- If a new `AuthProvider` is added, update the `AuthProvider` enum in `hyperpocket/auth/provider.py`
|
240
240
|
|
241
241
|
6. Add new auth callback server endpoint
|
242
|
-
- Add the endpoint under `
|
242
|
+
- Add the endpoint under `hyperpocket/server/auth/` packages.
|
243
243
|
- Declare an appropriate `APIRouter` in the package. Pocket will automatically register the endpoint during
|
244
244
|
initialization.
|
245
245
|
|
246
246
|
7. Add test code(optional)
|
247
|
-
- Add the test code under `
|
247
|
+
- Add the test code under `hyperpocket/auth/tests/` packages.
|
248
248
|
|
249
249
|
---
|
250
250
|
|
@@ -1,14 +1,6 @@
|
|
1
1
|
from hyperpocket.auth.context import AuthContext
|
2
|
-
from hyperpocket.auth.github.context import GitHubAuthContext
|
3
|
-
from hyperpocket.auth.github.oauth2_context import GitHubOAuth2AuthContext
|
4
|
-
from hyperpocket.auth.github.token_context import GitHubTokenAuthContext
|
5
|
-
from hyperpocket.auth.google.context import GoogleAuthContext
|
6
|
-
from hyperpocket.auth.google.oauth2_context import GoogleOAuth2AuthContext
|
7
2
|
from hyperpocket.auth.handler import AuthHandlerInterface
|
8
|
-
from hyperpocket.auth.linear.token_context import LinearTokenAuthContext
|
9
3
|
from hyperpocket.auth.provider import AuthProvider
|
10
|
-
from hyperpocket.auth.slack.oauth2_context import SlackOAuth2AuthContext
|
11
|
-
from hyperpocket.auth.slack.token_context import SlackTokenAuthContext
|
12
4
|
from hyperpocket.util.find_all_leaf_class_in_package import find_all_leaf_class_in_package
|
13
5
|
|
14
6
|
PREBUILT_AUTH_HANDLERS = find_all_leaf_class_in_package("hyperpocket.auth", AuthHandlerInterface)
|
@@ -0,0 +1,13 @@
|
|
1
|
+
from hyperpocket.auth.context import AuthContext
|
2
|
+
|
3
|
+
|
4
|
+
class GumLoopContext(AuthContext):
|
5
|
+
_ACCESS_TOKEN_KEY: str = "GUMLOOP_TOKEN"
|
6
|
+
|
7
|
+
def to_dict(self) -> dict[str, str]:
|
8
|
+
return {self._ACCESS_TOKEN_KEY: self.access_token}
|
9
|
+
|
10
|
+
def to_profiled_dict(self, profile: str) -> dict[str, str]:
|
11
|
+
return {
|
12
|
+
f"{profile.upper()}_{self._ACCESS_TOKEN_KEY}": self.access_token,
|
13
|
+
}
|
@@ -0,0 +1,15 @@
|
|
1
|
+
from hyperpocket.auth.gumloop.context import GumLoopContext
|
2
|
+
from hyperpocket.auth.gumloop.token_schema import GumloopTokenResponse
|
3
|
+
|
4
|
+
|
5
|
+
class GumLoopTokenContext(GumLoopContext):
|
6
|
+
|
7
|
+
@classmethod
|
8
|
+
def from_gumloop_token_response(cls, response: GumloopTokenResponse):
|
9
|
+
description = "Gumloop Token Context logged in"
|
10
|
+
|
11
|
+
return cls(
|
12
|
+
access_token=response.access_token,
|
13
|
+
description=description,
|
14
|
+
expires_at=None
|
15
|
+
)
|