commit 1cbf5ae4d3cdf9726d115f203d202ffd0ec72179 Author: retoor Date: Sun Nov 24 17:03:43 2024 +0100 Initial commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..d55e67c --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +.venv +__* diff --git a/dist/yura-13.3.7-py3-none-any.whl b/dist/yura-13.3.7-py3-none-any.whl new file mode 100644 index 0000000..4f3daf6 Binary files /dev/null and b/dist/yura-13.3.7-py3-none-any.whl differ diff --git a/dist/yura-13.3.7.tar.gz b/dist/yura-13.3.7.tar.gz new file mode 100644 index 0000000..e562b5e Binary files /dev/null and b/dist/yura-13.3.7.tar.gz differ diff --git a/make b/make new file mode 100755 index 0000000..e352104 --- /dev/null +++ b/make @@ -0,0 +1,16 @@ +#!/usr/bin/env python3 +import pathlib +import os +import sys + +if not pathlib.Path(".venv").exists(): + os.system("python3 -m venv .venv") + +if "build" in sys.argv: + os.system("./.venv/bin/python -m pip install build") + os.system("./.venv/bin/python -m build .") + os.system("./.venv/bin/python -m pip install black") + os.system("./.venv/bin/python -m black .") + + + diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..07de284 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,3 @@ +[build-system] +requires = ["setuptools", "wheel"] +build-backend = "setuptools.build_meta" \ No newline at end of file diff --git a/setup.cfg b/setup.cfg new file mode 100644 index 0000000..763db80 --- /dev/null +++ b/setup.cfg @@ -0,0 +1,27 @@ +[metadata] +name = yura +version = 13.3.7 +description = Yura async AI client +author = retoor +author_email = retoor@retoor.io +license = MIT +long_description = file: README.md +long_description_content_type = text/markdown + +[options] +packages = find: +include_package_data = true +package_dir = + = src +python_requires = >=3.7 +install_requires = + websockets +[options.packages.find] +where = src + +[options.package_data] +;stogram_client = binaries/* + +[options.entry_points] +console_scripts = + yura = yura.client:main diff --git a/src/yura.egg-info/PKG-INFO b/src/yura.egg-info/PKG-INFO new file mode 100644 index 0000000..b5da924 --- /dev/null +++ b/src/yura.egg-info/PKG-INFO @@ -0,0 +1,10 @@ +Metadata-Version: 2.1 +Name: yura +Version: 13.3.7 +Summary: Yura async AI client +Author: retoor +Author-email: retoor@retoor.io +License: MIT +Requires-Python: >=3.7 +Description-Content-Type: text/markdown +Requires-Dist: websockets diff --git a/src/yura.egg-info/SOURCES.txt b/src/yura.egg-info/SOURCES.txt new file mode 100644 index 0000000..0b9922a --- /dev/null +++ b/src/yura.egg-info/SOURCES.txt @@ -0,0 +1,8 @@ +pyproject.toml +setup.cfg +src/yura.egg-info/PKG-INFO +src/yura.egg-info/SOURCES.txt +src/yura.egg-info/dependency_links.txt +src/yura.egg-info/entry_points.txt +src/yura.egg-info/requires.txt +src/yura.egg-info/top_level.txt \ No newline at end of file diff --git a/src/yura.egg-info/dependency_links.txt b/src/yura.egg-info/dependency_links.txt new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/src/yura.egg-info/dependency_links.txt @@ -0,0 +1 @@ + diff --git a/src/yura.egg-info/entry_points.txt b/src/yura.egg-info/entry_points.txt new file mode 100644 index 0000000..7161fa5 --- /dev/null +++ b/src/yura.egg-info/entry_points.txt @@ -0,0 +1,2 @@ +[console_scripts] +yura = yura.client:main diff --git a/src/yura.egg-info/requires.txt b/src/yura.egg-info/requires.txt new file mode 100644 index 0000000..14774b4 --- /dev/null +++ b/src/yura.egg-info/requires.txt @@ -0,0 +1 @@ +websockets diff --git a/src/yura.egg-info/top_level.txt b/src/yura.egg-info/top_level.txt new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/src/yura.egg-info/top_level.txt @@ -0,0 +1 @@ + diff --git a/src/yura/client.py b/src/yura/client.py new file mode 100644 index 0000000..5cea3d5 --- /dev/null +++ b/src/yura/client.py @@ -0,0 +1,106 @@ +import asyncio +import websockets +import json +import sys + + +class AsyncClient: + + def __init__(self, url="ws://127.0.0.1:8470"): + + self.url = url + self.ws = None + self.queue_in = asyncio.Queue() + self.queue_out = asyncio.Queue() + self.communication_task = None + + async def ensure_connection(): + + if not self.ws: + self.ws = await websockets.connect(self.url) + + return self.ws + + async def ensure_communication(self): + + if not self.communication_task: + self.communication_task = asyncio.create_task(self.communicate()) + + return self.communication_task + + async def chat(self, message): + await self.ensure_communication() + await self.queue_out.put(message) + while True: + + while True: + try: + response = await asyncio.wait_for(self.queue_in.get(), 0.1) + + except asyncio.TimeoutError: + continue + break + + yield response + + if response["done"]: + break + + async def communicate(self): + loop = asyncio.get_event_loop() + async with websockets.connect(self.url) as websocket: + while True: + message_content = None + while not message_content: + try: + message_content = await asyncio.wait_for( + self.queue_out.get(), 0.1 + ) + except asyncio.TimeoutError: + continue + + response = await websocket.send(json.dumps(message_content)) + + while True: + response = json.loads(await websocket.recv()) + + if response["done"]: + break + + await self.queue_in.put(response) + + await self.queue_in.put(response) + + +async def cli_client(url="ws://127.0.0.1:8470"): + + loop = asyncio.get_event_loop() + async_client = AsyncClient(url) + + while True: + + sys.stdout.write("> ") + sys.stdout.flush() + message_content = await loop.run_in_executor(None, sys.stdin.readline) + + async for response in async_client.chat(message_content): + + print(response["content"], end="", flush=True) + + if response["done"]: + break + + print("") + + +def main(): + url = "ws://127.0.0.1:8470" + try: + url = sys.argv[1] + except IndexError: + pass + asyncio.run(cli_client(url)) + + +if __name__ == "__main__": + main()