diff --git a/.vscode/launch.json b/.vscode/launch.json index 7c5ddf42..b1ad64d6 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -28,7 +28,7 @@ "preLaunchTask": "Create .env.tmp file", "postDebugTask": "Delete .env.tmp file", "module": "uvicorn", - "args": ["src.chat.api.app:app","--reload","--port","8000"], + "args": ["src.askui.chat.api.app:app","--reload","--port","9261"], "envFile": "${workspaceFolder}/.env.tmp", "env": { "ASKUI_WORKSPACES__LOG__FORMAT": "logfmt", diff --git a/README.md b/README.md index d356cd7e..8fcf51f6 100644 --- a/README.md +++ b/README.md @@ -775,25 +775,31 @@ If you would like to disable the recording of usage data, set the `ASKUI__VA__TE ### AskUI Chat AskUI Chat is a web application that allows interacting with an AskUI Vision Agent similar how it can be -done with `VisionAgent.act()` but in a more interactive manner that involves less code. Aside from -telling the AskUI Vision Agent what to do, the user can also demonstrate what to do (currently, only +done with `VisionAgent.act()` or `AndroidVisionAgent.act()` but in a more interactive manner that involves less code. Aside from +telling the agent what to do, the user can also demonstrate what to do (currently, only clicking is supported). **⚠️ Warning:** AskUI Chat is currently in an experimental stage and has several limitations (see below). +#### Architecture + +This repository only includes the AskUI Chat API (`src/askui/chat`). The AskUI Chat UI can be accessed through the [AskUI Hub](https://hub.askui.com/) and connects to the local Chat API after it has been started. + #### Configuration To use the chat, configure the following environment variables: - `ASKUI_TOKEN`: AskUI Vision Agent behind chat uses currently the AskUI API - `ASKUI_WORKSPACE_ID`: AskUI Vision Agent behind chat uses currently the AskUI API -- `ASKUI__CHAT_API__DATA_DIR` (optional, defaults to `$(pwd)/chat`): Currently, the AskUI chat stores its data in a directory locally. You can change the default directory by setting this environment variable. +- `ASKUI__CHAT_API__DATA_DIR` (optional, defaults to `$(pwd)/chat`): Currently, the AskUI chat stores all data in a directory locally. You can change the default directory by setting this environment variable. +- `ASKUI__CHAT_API__HOST` (optional, defaults to `127.0.0.1`): The host to bind the chat API to. +- `ASKUI__CHAT_API__PORT` (optional, defaults to `9261`): The port to bind the chat API to. +- `ASKUI__CHAT_API__LOG_LEVEL` (optional, defaults to `info`): The log level to use for the chat API. #### Installation ```bash -pdm install # is going to install the dependencies of the api -pdm run chat:ui:install # is going to install the dependencies of the ui +pip install askui[chat] ``` You may need to give permissions on the fast run of the Chat UI to demonstrate actions (aka record clicks). @@ -801,8 +807,7 @@ You may need to give permissions on the fast run of the Chat UI to demonstrate a #### Usage ```bash -pdm run chat:api # is going to start the api at port 8000 -pdm run chat:ui # is going to start the ui at port 3000 +python -m askui.chat ``` You can use the chat to record a workflow and redo it later. For that, just tell the agent to redo all previous steps. @@ -815,7 +820,7 @@ You can use the chat to record a workflow and redo it later. For that, just tell #### Limitations - A lot of errors are not handled properly and we allow the user to do a lot of actions that can lead to errors instead of properly guiding the user. -- The chat currently only allows rerunning actions through `VisionAgent.act()` which can be expensive, slow and is not necessary the most reliable way to do it. +- The chat currently only allows rerunning actions through `VisionAgent.act()` (or `AndroidVisionAgent.act()` or `WebVisionAgent.act()`) which can be expensive, slow and is not necessary the most reliable way to do it. - A lot quirks in UI and API. - Currently, api and ui need to be run in dev mode. - When demonstrating actions, the corresponding screenshot may not reflect the correct state of the screen before the action. In this case, cancel demonstrating, delete messages and try again. @@ -824,10 +829,3 @@ You can use the chat to record a workflow and redo it later. For that, just tell - The agent is going to fail if there are no messages in the conversation, there is no tool use result message following the tool use message somewhere in the conversation, a message is too long etc. Just adding or deleting the message in this case should fix the issue. - You should not switch the conversation while waiting for an agent's answers or demonstrating actions. - - - -#### Architecture - -- The chat api/backend is a [FastAPI](https://fastapi.tiangolo.com/) application that provides a REST API similar to [OpenAI's Assistants API](https://platform.openai.com/docs/assistants/overview). -- The chat ui/frontend is a [Next.js](https://nextjs.org/) application that provides a web interface to the chat api. diff --git a/pdm.lock b/pdm.lock index 56b77875..88c11d9a 100644 --- a/pdm.lock +++ b/pdm.lock @@ -2,10 +2,10 @@ # It is not intended for manual editing. [metadata] -groups = ["default", "chat", "pynput", "test"] +groups = ["default", "android", "chat", "pynput", "test", "web"] strategy = ["inherit_metadata"] lock_version = "4.5.0" -content_hash = "sha256:3090c84eb2439f19cf4e2d303fcc89cf6852fa9739e84bd0e7d0cfe9e15a314b" +content_hash = "sha256:cddcbf34746f07954e7be404593f3972cacc6c15aae3dcc3576937f46bf64a0a" [[metadata.targets]] requires_python = ">=3.10" @@ -151,7 +151,7 @@ name = "click" version = "8.1.8" requires_python = ">=3.7" summary = "Composable command line interface toolkit" -groups = ["default", "chat"] +groups = ["chat"] dependencies = [ "colorama; platform_system == \"Windows\"", "importlib-metadata; python_version < \"3.8\"", @@ -318,7 +318,7 @@ name = "evdev" version = "1.9.2" requires_python = ">=3.8" summary = "Bindings to the Linux input handling subsystem" -groups = ["pynput"] +groups = ["chat", "pynput"] marker = "\"linux\" in sys_platform" files = [ {file = "evdev-1.9.2.tar.gz", hash = "sha256:5d3278892ce1f92a74d6bf888cc8525d9f68af85dbe336c95d1c87fb8f423069"}, @@ -330,6 +330,7 @@ version = "1.2.2" requires_python = ">=3.7" summary = "Backport of PEP 654 (exception groups)" groups = ["default", "chat", "test"] +marker = "python_version < \"3.11\"" files = [ {file = "exceptiongroup-1.2.2-py3-none-any.whl", hash = "sha256:3111b9d131c238bec2f8f516e123e14ba243563fb135d3fe885990585aa7795b"}, {file = "exceptiongroup-1.2.2.tar.gz", hash = "sha256:47c2edf7c6738fafb49fd34290706d1a1a2f4d1c6df275526b62cbb4aa5393cc"}, @@ -362,27 +363,6 @@ files = [ {file = "fastapi-0.115.12.tar.gz", hash = "sha256:1e2c2a2646905f9e83d32f04a3f86aff4a286669c6c950ca95b5fd68c2602681"}, ] -[[package]] -name = "fastmcp" -version = "2.3.4" -requires_python = ">=3.10" -summary = "The fast, Pythonic way to build MCP servers." -groups = ["default"] -dependencies = [ - "exceptiongroup>=1.2.2", - "httpx>=0.28.1", - "mcp<2.0.0,>=1.8.1", - "openapi-pydantic>=0.5.1", - "python-dotenv>=1.1.0", - "rich>=13.9.4", - "typer>=0.15.2", - "websockets>=14.0", -] -files = [ - {file = "fastmcp-2.3.4-py3-none-any.whl", hash = "sha256:12a45f72dd95aeaa1a6a56281fff96ca46929def3ccd9f9eb125cb97b722fbab"}, - {file = "fastmcp-2.3.4.tar.gz", hash = "sha256:f3fe004b8735b365a65ec2547eeb47db8352d5613697254854bc7c9c3c360eea"}, -] - [[package]] name = "filelock" version = "3.18.0" @@ -429,7 +409,7 @@ name = "greenlet" version = "3.2.3" requires_python = ">=3.9" summary = "Lightweight in-process concurrent programming" -groups = ["default", "test"] +groups = ["chat", "test", "web"] files = [ {file = "greenlet-3.2.3-cp310-cp310-macosx_11_0_universal2.whl", hash = "sha256:1afd685acd5597349ee6d7a88a8bec83ce13c106ac78c196ee9dde7c04fe87be"}, {file = "greenlet-3.2.3-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:761917cac215c61e9dc7324b2606107b3b292a8349bdebb31503ab4de3f559ac"}, @@ -642,17 +622,6 @@ files = [ {file = "httpx-0.28.1.tar.gz", hash = "sha256:75e98c5f16b0f35b567856f597f06ff2270a374470a5c2392242528e3e3e42fc"}, ] -[[package]] -name = "httpx-sse" -version = "0.4.0" -requires_python = ">=3.8" -summary = "Consume Server-Sent Event (SSE) messages with HTTPX." -groups = ["default"] -files = [ - {file = "httpx-sse-0.4.0.tar.gz", hash = "sha256:1e81a3a3070ce322add1d3529ed42eb5f70817f45ed6ec915ab753f961139721"}, - {file = "httpx_sse-0.4.0-py3-none-any.whl", hash = "sha256:f329af6eae57eaa2bdfd962b42524764af68075ea87370a2de920af5341e318f"}, -] - [[package]] name = "huggingface-hub" version = "0.30.1" @@ -844,28 +813,6 @@ files = [ {file = "markupsafe-3.0.2.tar.gz", hash = "sha256:ee55d3edf80167e48ea11a923c7386f4669df67d7994554387f84e7d8b0a2bf0"}, ] -[[package]] -name = "mcp" -version = "1.9.4" -requires_python = ">=3.10" -summary = "Model Context Protocol SDK" -groups = ["default"] -dependencies = [ - "anyio>=4.5", - "httpx-sse>=0.4", - "httpx>=0.27", - "pydantic-settings>=2.5.2", - "pydantic<3.0.0,>=2.7.2", - "python-multipart>=0.0.9", - "sse-starlette>=1.6.1", - "starlette>=0.27", - "uvicorn>=0.23.1; sys_platform != \"emscripten\"", -] -files = [ - {file = "mcp-1.9.4-py3-none-any.whl", hash = "sha256:7fcf36b62936adb8e63f89346bccca1268eeca9bf6dfb562ee10b1dfbda9dac0"}, - {file = "mcp-1.9.4.tar.gz", hash = "sha256:cfb0bcd1a9535b42edaef89947b9e18a8feb49362e1cc059d6e7fc636f2cb09f"}, -] - [[package]] name = "mdurl" version = "0.1.2" @@ -882,7 +829,7 @@ name = "mss" version = "10.0.0" requires_python = ">=3.9" summary = "An ultra fast cross-platform multiple screenshots module in pure python using ctypes." -groups = ["pynput"] +groups = ["chat", "pynput"] files = [ {file = "mss-10.0.0-py3-none-any.whl", hash = "sha256:82cf6460a53d09e79b7b6d871163c982e6c7e9649c426e7b7591b74956d5cb64"}, {file = "mss-10.0.0.tar.gz", hash = "sha256:d903e0d51262bf0f8782841cf16eaa6d7e3e1f12eae35ab41c2e318837c6637f"}, @@ -960,20 +907,6 @@ files = [ {file = "openai-1.85.0.tar.gz", hash = "sha256:6ba76e4ebc5725f71f2f6126c7cb5169ca8de60dd5aa61f350f9448ad162c913"}, ] -[[package]] -name = "openapi-pydantic" -version = "0.5.1" -requires_python = "<4.0,>=3.8" -summary = "Pydantic OpenAPI schema implementation" -groups = ["default"] -dependencies = [ - "pydantic>=1.8", -] -files = [ - {file = "openapi_pydantic-0.5.1-py3-none-any.whl", hash = "sha256:a3a09ef4586f5bd760a8df7f43028b60cafb6d9f61de2acba9574766255ab146"}, - {file = "openapi_pydantic-0.5.1.tar.gz", hash = "sha256:ff6835af6bde7a459fb93eb93bb92b8749b754fc6e51b2f1590a19dc3005ee0d"}, -] - [[package]] name = "packaging" version = "24.2" @@ -1056,23 +989,23 @@ files = [ [[package]] name = "playwright" -version = "1.52.0" +version = "1.53.0" requires_python = ">=3.9" summary = "A high-level API to automate web browsers" -groups = ["default", "test"] +groups = ["chat", "test", "web"] dependencies = [ "greenlet<4.0.0,>=3.1.1", "pyee<14,>=13", ] files = [ - {file = "playwright-1.52.0-py3-none-macosx_10_13_x86_64.whl", hash = "sha256:19b2cb9d4794062008a635a99bd135b03ebb782d460f96534a91cb583f549512"}, - {file = "playwright-1.52.0-py3-none-macosx_11_0_arm64.whl", hash = "sha256:0797c0479cbdc99607412a3c486a3a2ec9ddc77ac461259fd2878c975bcbb94a"}, - {file = "playwright-1.52.0-py3-none-macosx_11_0_universal2.whl", hash = "sha256:7223960b7dd7ddeec1ba378c302d1d09733b8dac438f492e9854c85d3ca7144f"}, - {file = "playwright-1.52.0-py3-none-manylinux1_x86_64.whl", hash = "sha256:d010124d24a321e0489a8c0d38a3971a7ca7656becea7656c9376bfea7f916d4"}, - {file = "playwright-1.52.0-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4173e453c43180acc60fd77ffe1ebee8d0efbfd9986c03267007b9c3845415af"}, - {file = "playwright-1.52.0-py3-none-win32.whl", hash = "sha256:cd0bdf92df99db6237a99f828e80a6a50db6180ef8d5352fc9495df2c92f9971"}, - {file = "playwright-1.52.0-py3-none-win_amd64.whl", hash = "sha256:dcbf75101eba3066b7521c6519de58721ea44379eb17a0dafa94f9f1b17f59e4"}, - {file = "playwright-1.52.0-py3-none-win_arm64.whl", hash = "sha256:9d0085b8de513de5fb50669f8e6677f0252ef95a9a1d2d23ccee9638e71e65cb"}, + {file = "playwright-1.53.0-py3-none-macosx_10_13_x86_64.whl", hash = "sha256:48a1a15ce810f0ffe512b6050de9871ea193b41dd3cc1bbed87b8431012419ba"}, + {file = "playwright-1.53.0-py3-none-macosx_11_0_arm64.whl", hash = "sha256:a701f9498a5b87e3f929ec01cea3109fbde75821b19c7ba4bba54f6127b94f76"}, + {file = "playwright-1.53.0-py3-none-macosx_11_0_universal2.whl", hash = "sha256:f765498341c4037b4c01e742ae32dd335622f249488ccd77ca32d301d7c82c61"}, + {file = "playwright-1.53.0-py3-none-manylinux1_x86_64.whl", hash = "sha256:db19cb5b58f3b15cad3e2419f4910c053e889202fc202461ee183f1530d1db60"}, + {file = "playwright-1.53.0-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9276c9c935fc062f51f4f5107e56420afd6d9a524348dc437793dc2e34c742e3"}, + {file = "playwright-1.53.0-py3-none-win32.whl", hash = "sha256:36eedec101724ff5a000cddab87dd9a72a39f9b3e65a687169c465484e667c06"}, + {file = "playwright-1.53.0-py3-none-win_amd64.whl", hash = "sha256:d68975807a0fd997433537f1dcf2893cda95884a39dc23c6f591b8d5f691e9e8"}, + {file = "playwright-1.53.0-py3-none-win_arm64.whl", hash = "sha256:fcfd481f76568d7b011571160e801b47034edd9e2383c43d83a5fb3f35c67885"}, ] [[package]] @@ -1106,7 +1039,7 @@ files = [ name = "pure-python-adb" version = "0.3.0.dev0" summary = "Pure python implementation of the adb client" -groups = ["default"] +groups = ["android", "chat"] files = [ {file = "pure-python-adb-0.3.0.dev0.tar.gz", hash = "sha256:0ecc89d780160cfe03260ba26df2c471a05263b2cad0318363573ee8043fb94d"}, ] @@ -1251,7 +1184,7 @@ name = "pyee" version = "13.0.0" requires_python = ">=3.8" summary = "A rough port of Node.js's EventEmitter to Python with a few tricks of its own" -groups = ["default", "test"] +groups = ["chat", "test", "web"] dependencies = [ "typing-extensions", ] @@ -1286,7 +1219,7 @@ files = [ name = "pynput" version = "1.8.1" summary = "Monitor and control user input devices" -groups = ["pynput"] +groups = ["chat", "pynput"] dependencies = [ "enum34; python_version == \"2.7\"", "evdev>=1.3; \"linux\" in sys_platform", @@ -1305,7 +1238,7 @@ name = "pyobjc-core" version = "11.0" requires_python = ">=3.8" summary = "Python<->ObjC Interoperability Module" -groups = ["pynput"] +groups = ["chat", "pynput"] marker = "sys_platform == \"darwin\"" files = [ {file = "pyobjc_core-11.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:10866b3a734d47caf48e456eea0d4815c2c9b21856157db5917b61dee06893a1"}, @@ -1321,7 +1254,7 @@ name = "pyobjc-framework-applicationservices" version = "11.0" requires_python = ">=3.9" summary = "Wrappers for the framework ApplicationServices on macOS" -groups = ["pynput"] +groups = ["chat", "pynput"] marker = "sys_platform == \"darwin\"" dependencies = [ "pyobjc-core>=11.0", @@ -1343,7 +1276,7 @@ name = "pyobjc-framework-cocoa" version = "11.0" requires_python = ">=3.9" summary = "Wrappers for the Cocoa frameworks on macOS" -groups = ["pynput"] +groups = ["chat", "pynput"] marker = "sys_platform == \"darwin\"" dependencies = [ "pyobjc-core>=11.0", @@ -1362,7 +1295,7 @@ name = "pyobjc-framework-coretext" version = "11.0" requires_python = ">=3.9" summary = "Wrappers for the framework CoreText on macOS" -groups = ["pynput"] +groups = ["chat", "pynput"] marker = "sys_platform == \"darwin\"" dependencies = [ "pyobjc-core>=11.0", @@ -1383,7 +1316,7 @@ name = "pyobjc-framework-quartz" version = "11.0" requires_python = ">=3.9" summary = "Wrappers for the Quartz frameworks on macOS" -groups = ["pynput"] +groups = ["chat", "pynput"] marker = "sys_platform == \"darwin\"" dependencies = [ "pyobjc-core>=11.0", @@ -1509,22 +1442,11 @@ files = [ {file = "python_dotenv-1.1.0.tar.gz", hash = "sha256:41f90bc6f5f177fb41f53e87666db362025010eb28f60a01c9143bfa33a2b2d5"}, ] -[[package]] -name = "python-multipart" -version = "0.0.20" -requires_python = ">=3.8" -summary = "A streaming multipart parser for Python" -groups = ["default"] -files = [ - {file = "python_multipart-0.0.20-py3-none-any.whl", hash = "sha256:8a62d3a8335e06589fe01f2a3e178cdcc632f3fbe0d492ad9ee0ec35aab1f104"}, - {file = "python_multipart-0.0.20.tar.gz", hash = "sha256:8dd0cab45b8e23064ae09147625994d090fa46f5b0d1e13af944c331a7fa9d13"}, -] - [[package]] name = "python-xlib" version = "0.33" summary = "Python X Library" -groups = ["pynput"] +groups = ["chat", "pynput"] marker = "\"linux\" in sys_platform" dependencies = [ "six>=1.10.0", @@ -1668,23 +1590,12 @@ files = [ {file = "setuptools-78.1.0.tar.gz", hash = "sha256:18fd474d4a82a5f83dac888df697af65afa82dec7323d09c3e37d1f14288da54"}, ] -[[package]] -name = "shellingham" -version = "1.5.4" -requires_python = ">=3.7" -summary = "Tool to Detect Surrounding Shell" -groups = ["default"] -files = [ - {file = "shellingham-1.5.4-py2.py3-none-any.whl", hash = "sha256:7ecfff8f2fd72616f7481040475a65b2bf8af90a56c89140852d1120324e8686"}, - {file = "shellingham-1.5.4.tar.gz", hash = "sha256:8dbca0739d487e5bd35ab3ca4b36e11c4078f3a234bfce294b0a0291363404de"}, -] - [[package]] name = "six" version = "1.17.0" requires_python = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" summary = "Python 2 and 3 compatibility utilities" -groups = ["default", "pynput"] +groups = ["default", "chat", "pynput"] files = [ {file = "six-1.17.0-py2.py3-none-any.whl", hash = "sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274"}, {file = "six-1.17.0.tar.gz", hash = "sha256:ff70335d468e7eb6ec65b95b99d3a2836546063f63acc5171de367e834932a81"}, @@ -1701,27 +1612,12 @@ files = [ {file = "sniffio-1.3.1.tar.gz", hash = "sha256:f4324edc670a0f49750a81b895f35c3adb843cca46f0530f79fc1babb23789dc"}, ] -[[package]] -name = "sse-starlette" -version = "2.3.5" -requires_python = ">=3.9" -summary = "SSE plugin for Starlette" -groups = ["default"] -dependencies = [ - "anyio>=4.7.0", - "starlette>=0.41.3", -] -files = [ - {file = "sse_starlette-2.3.5-py3-none-any.whl", hash = "sha256:251708539a335570f10eaaa21d1848a10c42ee6dc3a9cf37ef42266cdb1c52a8"}, - {file = "sse_starlette-2.3.5.tar.gz", hash = "sha256:228357b6e42dcc73a427990e2b4a03c023e2495ecee82e14f07ba15077e334b2"}, -] - [[package]] name = "starlette" version = "0.46.2" requires_python = ">=3.9" summary = "The little ASGI library that shines." -groups = ["default", "chat"] +groups = ["chat"] dependencies = [ "anyio<5,>=3.6.2", "typing-extensions>=3.10.0; python_version < \"3.10\"", @@ -1798,23 +1694,6 @@ files = [ {file = "tqdm-4.67.1.tar.gz", hash = "sha256:f8aef9c52c08c13a65f30ea34f4e5aac3fd1a34959879d7e59e63027286627f2"}, ] -[[package]] -name = "typer" -version = "0.15.4" -requires_python = ">=3.7" -summary = "Typer, build great CLIs. Easy to code. Based on Python type hints." -groups = ["default"] -dependencies = [ - "click<8.2,>=8.0.0", - "rich>=10.11.0", - "shellingham>=1.3.0", - "typing-extensions>=3.7.4.3", -] -files = [ - {file = "typer-0.15.4-py3-none-any.whl", hash = "sha256:eb0651654dcdea706780c466cf06d8f174405a659ffff8f163cfbfee98c0e173"}, - {file = "typer-0.15.4.tar.gz", hash = "sha256:89507b104f9b6a0730354f27c39fae5b63ccd0c95b1ce1f1a6ba0cfd329997c3"}, -] - [[package]] name = "types-pillow" version = "10.2.0.20240822" @@ -1889,7 +1768,7 @@ name = "typing-extensions" version = "4.13.1" requires_python = ">=3.8" summary = "Backported and Experimental Type Hints for Python 3.8+" -groups = ["default", "chat", "test"] +groups = ["default", "chat", "test", "web"] files = [ {file = "typing_extensions-4.13.1-py3-none-any.whl", hash = "sha256:4b6cf02909eb5495cfbc3f6e8fd49217e6cc7944e145cdda8caa3734777f9e69"}, {file = "typing_extensions-4.13.1.tar.gz", hash = "sha256:98795af00fb9640edec5b8e31fc647597b4691f099ad75f469a2616be1a76dff"}, @@ -1925,7 +1804,7 @@ name = "uvicorn" version = "0.34.3" requires_python = ">=3.9" summary = "The lightning-fast ASGI server." -groups = ["default", "chat"] +groups = ["chat"] dependencies = [ "click>=7.0", "h11>=0.8", diff --git a/pyproject.toml b/pyproject.toml index bf9a71d6..9b1b5663 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -5,26 +5,23 @@ authors = [ {name = "askui GmbH", email = "info@askui.com"}, ] dependencies = [ - "grpcio>=1.67.0", - "grpcio-tools>=1.67.0", - "pillow>=11.0.0", - "pydantic>=2.11.0", "anthropic>=0.54.0", - "rich>=13.9.4", - "pyperclip>=1.9.0", "gradio-client>=1.4.3", - "requests>=2.32.3", + "grpcio-tools>=1.67.0", + "grpcio>=1.67.0", + "httpx>=0.28.1", "Jinja2>=3.1.4", - "tenacity>=9.1.2", + "openai>=1.61.1", + "pillow>=11.0.0", + "py-machineid>=0.7.0", "pydantic-settings>=2.9.1", + "pydantic>=2.11.0", + "pyperclip>=1.9.0", "python-dateutil>=2.9.0.post0", - "openai>=1.61.1", + "requests>=2.32.3", + "rich>=13.9.4", "segment-analytics-python>=2.3.4", - "py-machineid>=0.7.0", - "httpx>=0.28.1", - "fastmcp>=2.3.4", - "pure-python-adb>=0.3.0.dev0", - "playwright>=1.0.0", + "tenacity>=9.1.2", ] requires-python = ">=3.10" readme = "README.md" @@ -57,20 +54,10 @@ lint = "ruff check src tests" "lint:fix" = "ruff check --fix src tests" typecheck = "mypy" "typecheck:all" = "mypy src tests" -"chat:api" = "uvicorn chat.api.app:app --reload --port 8000" -"chat:ui:install" = {shell = "cd src/chat/ui && npm ci"} -"chat:ui" = {shell = "cd src/chat/ui && npm run dev"} +"chat:api" = "uvicorn askui.chat.api.app:app --reload --port 9261" "mcp:dev" = "mcp dev src/askui/mcp/__init__.py" [dependency-groups] -chat = [ - "fastapi>=0.115.12", - "uvicorn>=0.34.3", -] -pynput = [ - "mss>=10.0.0", - "pynput>=1.8.1", -] test = [ "pytest>=8.3.4", "ruff>=0.9.5", @@ -113,7 +100,6 @@ warn_unreachable = true strict_optional = true plugins = ["pydantic.mypy"] exclude = [ - "src/askui/chat/.*", "src/askui/models/ui_tars_ep/ui_tars_api.py", "src/askui/tools/anthropic/computer.py", "src/askui/tools/askui/askui_ui_controller_grpc/.*", @@ -228,3 +214,24 @@ multiline-quotes = "double" [tool.ruff.lint.isort] known-first-party = ["askui"] known-third-party = ["pytest", "mypy"] + +[project.optional-dependencies] +all = ["askui[android,chat,mcp,pynput,web]"] +android = [ + "pure-python-adb>=0.3.0.dev0" +] +chat = [ + "askui[android,pynput,web]", + "fastapi>=0.115.12", + "uvicorn>=0.34.3", +] +mcp = [ + "fastmcp>=2.3.4", +] +pynput = [ + "mss>=10.0.0", + "pynput>=1.8.1", +] +web = [ + "playwright>=1.41.0", +] diff --git a/src/chat/__init__.py b/src/askui/chat/__init__.py similarity index 100% rename from src/chat/__init__.py rename to src/askui/chat/__init__.py diff --git a/src/askui/chat/__main__.py b/src/askui/chat/__main__.py new file mode 100644 index 00000000..c03101f7 --- /dev/null +++ b/src/askui/chat/__main__.py @@ -0,0 +1,15 @@ +import uvicorn + +from askui.chat.api.app import app +from askui.chat.api.dependencies import get_settings + +if __name__ == "__main__": + settings = get_settings() + uvicorn.run( + app, + host=settings.host, + port=settings.port, + log_level=settings.log_level, + reload=False, + workers=1, + ) diff --git a/src/chat/api/__init__.py b/src/askui/chat/api/__init__.py similarity index 100% rename from src/chat/api/__init__.py rename to src/askui/chat/api/__init__.py diff --git a/src/chat/api/app.py b/src/askui/chat/api/app.py similarity index 69% rename from src/chat/api/app.py rename to src/askui/chat/api/app.py index 2c9aa8e5..22618a3a 100644 --- a/src/chat/api/app.py +++ b/src/askui/chat/api/app.py @@ -4,12 +4,12 @@ from fastapi import APIRouter, FastAPI from fastapi.middleware.cors import CORSMiddleware -from chat.api.assistants.dependencies import get_assistant_service -from chat.api.assistants.router import router as assistants_router -from chat.api.dependencies import get_settings -from chat.api.messages.router import router as messages_router -from chat.api.runs.router import router as runs_router -from chat.api.threads.router import router as threads_router +from askui.chat.api.assistants.dependencies import get_assistant_service +from askui.chat.api.assistants.router import router as assistants_router +from askui.chat.api.dependencies import get_settings +from askui.chat.api.messages.router import router as messages_router +from askui.chat.api.runs.router import router as runs_router +from askui.chat.api.threads.router import router as threads_router @asynccontextmanager diff --git a/src/chat/api/assistants/__init__.py b/src/askui/chat/api/assistants/__init__.py similarity index 100% rename from src/chat/api/assistants/__init__.py rename to src/askui/chat/api/assistants/__init__.py diff --git a/src/chat/api/assistants/dependencies.py b/src/askui/chat/api/assistants/dependencies.py similarity index 61% rename from src/chat/api/assistants/dependencies.py rename to src/askui/chat/api/assistants/dependencies.py index 014f21a5..d0d99dfb 100644 --- a/src/chat/api/assistants/dependencies.py +++ b/src/askui/chat/api/assistants/dependencies.py @@ -1,8 +1,8 @@ from fastapi import Depends -from chat.api.assistants.service import AssistantService -from chat.api.dependencies import SettingsDep -from chat.api.settings import Settings +from askui.chat.api.assistants.service import AssistantService +from askui.chat.api.dependencies import SettingsDep +from askui.chat.api.settings import Settings def get_assistant_service(settings: Settings = SettingsDep) -> AssistantService: diff --git a/src/chat/api/assistants/models.py b/src/askui/chat/api/assistants/models.py similarity index 84% rename from src/chat/api/assistants/models.py rename to src/askui/chat/api/assistants/models.py index fcfb9d6d..af9645c8 100644 --- a/src/chat/api/assistants/models.py +++ b/src/askui/chat/api/assistants/models.py @@ -3,8 +3,8 @@ from pydantic import BaseModel, Field -from chat.api.models import UnixDatetime -from chat.api.utils import generate_time_ordered_id +from askui.chat.api.models import UnixDatetime +from askui.chat.api.utils import generate_time_ordered_id class Assistant(BaseModel): diff --git a/src/chat/api/assistants/router.py b/src/askui/chat/api/assistants/router.py similarity index 85% rename from src/chat/api/assistants/router.py rename to src/askui/chat/api/assistants/router.py index 37140e46..6b136c8d 100644 --- a/src/chat/api/assistants/router.py +++ b/src/askui/chat/api/assistants/router.py @@ -1,12 +1,12 @@ from fastapi import APIRouter, HTTPException # from fastapi import status -from chat.api.assistants.dependencies import AssistantServiceDep -from chat.api.assistants.models import Assistant -from chat.api.assistants.service import ( - AssistantService, # AssistantModifyRequest, CreateAssistantRequest, -) -from chat.api.models import ListQuery, ListQueryDep, ListResponse +from askui.chat.api.assistants.dependencies import AssistantServiceDep +from askui.chat.api.assistants.models import Assistant +from askui.chat.api.assistants.service import ( + AssistantService, +) # AssistantModifyRequest, CreateAssistantRequest, +from askui.chat.api.models import ListQuery, ListQueryDep, ListResponse router = APIRouter(prefix="/assistants", tags=["assistants"]) diff --git a/src/chat/api/assistants/seeds.py b/src/askui/chat/api/assistants/seeds.py similarity index 99% rename from src/chat/api/assistants/seeds.py rename to src/askui/chat/api/assistants/seeds.py index 42c054af..8e5b2db0 100644 --- a/src/chat/api/assistants/seeds.py +++ b/src/askui/chat/api/assistants/seeds.py @@ -1,4 +1,4 @@ -from chat.api.assistants.models import Assistant +from askui.chat.api.assistants.models import Assistant ASKUI_VISION_AGENT = Assistant( id="asst_ge3tiojsga3dgnruge3di2u5ov36shedkcslxnmca", diff --git a/src/chat/api/assistants/service.py b/src/askui/chat/api/assistants/service.py similarity index 96% rename from src/chat/api/assistants/service.py rename to src/askui/chat/api/assistants/service.py index bc743400..0b674312 100644 --- a/src/chat/api/assistants/service.py +++ b/src/askui/chat/api/assistants/service.py @@ -2,9 +2,9 @@ from pydantic import BaseModel, Field -from chat.api.assistants.models import Assistant -from chat.api.assistants.seeds import SEEDS -from chat.api.models import DO_NOT_PATCH, DoNotPatch, ListQuery, ListResponse +from askui.chat.api.assistants.models import Assistant +from askui.chat.api.assistants.seeds import SEEDS +from askui.chat.api.models import DO_NOT_PATCH, DoNotPatch, ListQuery, ListResponse class CreateAssistantRequest(BaseModel): diff --git a/src/chat/api/dependencies.py b/src/askui/chat/api/dependencies.py similarity index 78% rename from src/chat/api/dependencies.py rename to src/askui/chat/api/dependencies.py index ef35a3d7..a9c78c2f 100644 --- a/src/chat/api/dependencies.py +++ b/src/askui/chat/api/dependencies.py @@ -1,6 +1,6 @@ from fastapi import Depends -from chat.api.settings import Settings +from askui.chat.api.settings import Settings def get_settings() -> Settings: diff --git a/src/chat/api/messages/__init__.py b/src/askui/chat/api/messages/__init__.py similarity index 100% rename from src/chat/api/messages/__init__.py rename to src/askui/chat/api/messages/__init__.py diff --git a/src/chat/api/messages/dependencies.py b/src/askui/chat/api/messages/dependencies.py similarity index 62% rename from src/chat/api/messages/dependencies.py rename to src/askui/chat/api/messages/dependencies.py index 59ec54d2..51bff5af 100644 --- a/src/chat/api/messages/dependencies.py +++ b/src/askui/chat/api/messages/dependencies.py @@ -1,8 +1,8 @@ from fastapi import Depends -from chat.api.dependencies import SettingsDep -from chat.api.messages.service import MessageService -from chat.api.settings import Settings +from askui.chat.api.dependencies import SettingsDep +from askui.chat.api.messages.service import MessageService +from askui.chat.api.settings import Settings def get_message_service( diff --git a/src/chat/api/messages/router.py b/src/askui/chat/api/messages/router.py similarity index 88% rename from src/chat/api/messages/router.py rename to src/askui/chat/api/messages/router.py index f35e8e36..d7b7462e 100644 --- a/src/chat/api/messages/router.py +++ b/src/askui/chat/api/messages/router.py @@ -1,8 +1,18 @@ from fastapi import APIRouter, HTTPException, status -from chat.api.messages.dependencies import MessageServiceDep -from chat.api.messages.service import Message, MessageCreateRequest, MessageService -from chat.api.models import ListQuery, ListQueryDep, ListResponse, MessageId, ThreadId +from askui.chat.api.messages.dependencies import MessageServiceDep +from askui.chat.api.messages.service import ( + Message, + MessageCreateRequest, + MessageService, +) +from askui.chat.api.models import ( + ListQuery, + ListQueryDep, + ListResponse, + MessageId, + ThreadId, +) router = APIRouter(prefix="/threads/{thread_id}/messages", tags=["messages"]) diff --git a/src/chat/api/messages/service.py b/src/askui/chat/api/messages/service.py similarity index 97% rename from src/chat/api/messages/service.py rename to src/askui/chat/api/messages/service.py index 4e30c426..517f8456 100644 --- a/src/chat/api/messages/service.py +++ b/src/askui/chat/api/messages/service.py @@ -4,8 +4,7 @@ from pydantic import Field -from askui.models.shared.agent_message_param import MessageParam -from chat.api.models import ( +from askui.chat.api.models import ( MAX_MESSAGES_PER_THREAD, AssistantId, ListQuery, @@ -14,7 +13,8 @@ ThreadId, UnixDatetime, ) -from chat.api.utils import generate_time_ordered_id +from askui.chat.api.utils import generate_time_ordered_id +from askui.models.shared.agent_message_param import MessageParam class MessageBase(MessageParam): diff --git a/src/chat/api/models.py b/src/askui/chat/api/models.py similarity index 100% rename from src/chat/api/models.py rename to src/askui/chat/api/models.py diff --git a/src/chat/api/runs/__init__.py b/src/askui/chat/api/runs/__init__.py similarity index 100% rename from src/chat/api/runs/__init__.py rename to src/askui/chat/api/runs/__init__.py diff --git a/src/chat/api/runs/dependencies.py b/src/askui/chat/api/runs/dependencies.py similarity index 72% rename from src/chat/api/runs/dependencies.py rename to src/askui/chat/api/runs/dependencies.py index 440f07d4..772c2545 100644 --- a/src/chat/api/runs/dependencies.py +++ b/src/askui/chat/api/runs/dependencies.py @@ -1,7 +1,7 @@ from fastapi import Depends -from chat.api.dependencies import SettingsDep -from chat.api.settings import Settings +from askui.chat.api.dependencies import SettingsDep +from askui.chat.api.settings import Settings from .service import RunService diff --git a/src/chat/api/runs/models.py b/src/askui/chat/api/runs/models.py similarity index 92% rename from src/chat/api/runs/models.py rename to src/askui/chat/api/runs/models.py index a2a45190..ef2b3a15 100644 --- a/src/chat/api/runs/models.py +++ b/src/askui/chat/api/runs/models.py @@ -3,8 +3,8 @@ from pydantic import BaseModel, Field, computed_field -from chat.api.models import AssistantId, RunId, ThreadId, UnixDatetime -from chat.api.utils import generate_time_ordered_id +from askui.chat.api.models import AssistantId, RunId, ThreadId, UnixDatetime +from askui.chat.api.utils import generate_time_ordered_id RunStatus = Literal[ "queued", diff --git a/src/chat/api/runs/router.py b/src/askui/chat/api/runs/router.py similarity index 94% rename from src/chat/api/runs/router.py rename to src/askui/chat/api/runs/router.py index c6def410..c56d3025 100644 --- a/src/chat/api/runs/router.py +++ b/src/askui/chat/api/runs/router.py @@ -5,8 +5,8 @@ from fastapi.responses import JSONResponse, StreamingResponse from pydantic import BaseModel -from chat.api.models import ListQuery, ListQueryDep, ListResponse, RunId, ThreadId -from chat.api.runs.service import CreateRunRequest +from askui.chat.api.models import ListQuery, ListQueryDep, ListResponse, RunId, ThreadId +from askui.chat.api.runs.service import CreateRunRequest from .dependencies import RunServiceDep from .models import Run diff --git a/src/chat/api/runs/runner/__init__.py b/src/askui/chat/api/runs/runner/__init__.py similarity index 100% rename from src/chat/api/runs/runner/__init__.py rename to src/askui/chat/api/runs/runner/__init__.py diff --git a/src/askui/chat/api/runs/runner/events/__init__.py b/src/askui/chat/api/runs/runner/events/__init__.py new file mode 100644 index 00000000..11475a34 --- /dev/null +++ b/src/askui/chat/api/runs/runner/events/__init__.py @@ -0,0 +1,15 @@ +from askui.chat.api.runs.runner.events.done_events import DoneEvent +from askui.chat.api.runs.runner.events.error_events import ErrorEvent +from askui.chat.api.runs.runner.events.event_base import EventBase +from askui.chat.api.runs.runner.events.events import Events +from askui.chat.api.runs.runner.events.message_events import MessageEvent +from askui.chat.api.runs.runner.events.run_events import RunEvent + +__all__ = [ + "DoneEvent", + "ErrorEvent", + "EventBase", + "Events", + "MessageEvent", + "RunEvent", +] diff --git a/src/chat/api/runs/runner/events/done_events.py b/src/askui/chat/api/runs/runner/events/done_events.py similarity index 66% rename from src/chat/api/runs/runner/events/done_events.py rename to src/askui/chat/api/runs/runner/events/done_events.py index 88b86a82..64be93fd 100644 --- a/src/chat/api/runs/runner/events/done_events.py +++ b/src/askui/chat/api/runs/runner/events/done_events.py @@ -1,6 +1,6 @@ from typing import Literal -from chat.api.runs.runner.events.event_base import EventBase +from askui.chat.api.runs.runner.events.event_base import EventBase class DoneEvent(EventBase): diff --git a/src/chat/api/runs/runner/events/error_events.py b/src/askui/chat/api/runs/runner/events/error_events.py similarity index 80% rename from src/chat/api/runs/runner/events/error_events.py rename to src/askui/chat/api/runs/runner/events/error_events.py index efb536be..82688d54 100644 --- a/src/chat/api/runs/runner/events/error_events.py +++ b/src/askui/chat/api/runs/runner/events/error_events.py @@ -2,7 +2,7 @@ from pydantic import BaseModel -from chat.api.runs.runner.events.event_base import EventBase +from askui.chat.api.runs.runner.events.event_base import EventBase class ErrorEventDataError(BaseModel): diff --git a/src/chat/api/runs/runner/events/event_base.py b/src/askui/chat/api/runs/runner/events/event_base.py similarity index 100% rename from src/chat/api/runs/runner/events/event_base.py rename to src/askui/chat/api/runs/runner/events/event_base.py diff --git a/src/askui/chat/api/runs/runner/events/events.py b/src/askui/chat/api/runs/runner/events/events.py new file mode 100644 index 00000000..dac1d80f --- /dev/null +++ b/src/askui/chat/api/runs/runner/events/events.py @@ -0,0 +1,6 @@ +from askui.chat.api.runs.runner.events.done_events import DoneEvent +from askui.chat.api.runs.runner.events.error_events import ErrorEvent +from askui.chat.api.runs.runner.events.message_events import MessageEvent +from askui.chat.api.runs.runner.events.run_events import RunEvent + +Events = DoneEvent | ErrorEvent | MessageEvent | RunEvent diff --git a/src/chat/api/runs/runner/events/message_events.py b/src/askui/chat/api/runs/runner/events/message_events.py similarity index 51% rename from src/chat/api/runs/runner/events/message_events.py rename to src/askui/chat/api/runs/runner/events/message_events.py index 3a1b2d88..51807d84 100644 --- a/src/chat/api/runs/runner/events/message_events.py +++ b/src/askui/chat/api/runs/runner/events/message_events.py @@ -1,7 +1,7 @@ from typing import Literal -from chat.api.messages.service import Message -from chat.api.runs.runner.events.event_base import EventBase +from askui.chat.api.messages.service import Message +from askui.chat.api.runs.runner.events.event_base import EventBase class MessageEvent(EventBase): diff --git a/src/chat/api/runs/runner/events/run_events.py b/src/askui/chat/api/runs/runner/events/run_events.py similarity index 75% rename from src/chat/api/runs/runner/events/run_events.py rename to src/askui/chat/api/runs/runner/events/run_events.py index 033ef15f..84952e34 100644 --- a/src/chat/api/runs/runner/events/run_events.py +++ b/src/askui/chat/api/runs/runner/events/run_events.py @@ -1,7 +1,7 @@ from typing import Literal -from chat.api.runs.models import Run -from chat.api.runs.runner.events.event_base import EventBase +from askui.chat.api.runs.models import Run +from askui.chat.api.runs.runner.events.event_base import EventBase class RunEvent(EventBase): diff --git a/src/chat/api/runs/runner/runner.py b/src/askui/chat/api/runs/runner/runner.py similarity index 94% rename from src/chat/api/runs/runner/runner.py rename to src/askui/chat/api/runs/runner/runner.py index 8f12b8d8..9eb5449a 100644 --- a/src/chat/api/runs/runner/runner.py +++ b/src/askui/chat/api/runs/runner/runner.py @@ -7,6 +7,24 @@ from askui.agent import VisionAgent from askui.android_agent import AndroidVisionAgent +from askui.chat.api.assistants.seeds import ( + ANDROID_VISION_AGENT, + ASKUI_VISION_AGENT, + ASKUI_WEB_AGENT, + HUMAN_DEMONSTRATION_AGENT, +) +from askui.chat.api.messages.service import MessageCreateRequest, MessageService +from askui.chat.api.models import MAX_MESSAGES_PER_THREAD, ListQuery +from askui.chat.api.runs.models import Run, RunError +from askui.chat.api.runs.runner.events.done_events import DoneEvent +from askui.chat.api.runs.runner.events.error_events import ( + ErrorEvent, + ErrorEventData, + ErrorEventDataError, +) +from askui.chat.api.runs.runner.events.events import Events +from askui.chat.api.runs.runner.events.message_events import MessageEvent +from askui.chat.api.runs.runner.events.run_events import RunEvent from askui.models.shared.agent_message_param import ( Base64ImageSourceParam, ImageBlockParam, @@ -17,24 +35,6 @@ from askui.tools.pynput_agent_os import PynputAgentOs from askui.utils.image_utils import ImageSource from askui.web_agent import WebVisionAgent -from chat.api.assistants.seeds import ( - ANDROID_VISION_AGENT, - ASKUI_VISION_AGENT, - ASKUI_WEB_AGENT, - HUMAN_DEMONSTRATION_AGENT, -) -from chat.api.messages.service import MessageCreateRequest, MessageService -from chat.api.models import MAX_MESSAGES_PER_THREAD, ListQuery -from chat.api.runs.models import Run, RunError -from chat.api.runs.runner.events.done_events import DoneEvent -from chat.api.runs.runner.events.error_events import ( - ErrorEvent, - ErrorEventData, - ErrorEventDataError, -) -from chat.api.runs.runner.events.events import Events -from chat.api.runs.runner.events.message_events import MessageEvent -from chat.api.runs.runner.events.run_events import RunEvent if TYPE_CHECKING: from askui.tools.agent_os import InputEvent diff --git a/src/chat/api/runs/service.py b/src/askui/chat/api/runs/service.py similarity index 92% rename from src/chat/api/runs/service.py rename to src/askui/chat/api/runs/service.py index a3469896..e68311f0 100644 --- a/src/chat/api/runs/service.py +++ b/src/askui/chat/api/runs/service.py @@ -8,13 +8,13 @@ from pydantic import BaseModel -from chat.api.models import AssistantId, ListQuery, ListResponse, RunId, ThreadId -from chat.api.runs.models import Run -from chat.api.runs.runner.events import Events -from chat.api.runs.runner.events.done_events import DoneEvent -from chat.api.runs.runner.events.error_events import ErrorEvent -from chat.api.runs.runner.events.run_events import RunEvent -from chat.api.runs.runner.runner import Runner +from askui.chat.api.models import AssistantId, ListQuery, ListResponse, RunId, ThreadId +from askui.chat.api.runs.models import Run +from askui.chat.api.runs.runner.events import Events +from askui.chat.api.runs.runner.events.done_events import DoneEvent +from askui.chat.api.runs.runner.events.error_events import ErrorEvent +from askui.chat.api.runs.runner.events.run_events import RunEvent +from askui.chat.api.runs.runner.runner import Runner class CreateRunRequest(BaseModel): diff --git a/src/chat/api/settings.py b/src/askui/chat/api/settings.py similarity index 56% rename from src/chat/api/settings.py rename to src/askui/chat/api/settings.py index c091a6cf..7db215ac 100644 --- a/src/chat/api/settings.py +++ b/src/askui/chat/api/settings.py @@ -15,3 +15,17 @@ class Settings(BaseSettings): default_factory=lambda: Path.cwd() / "chat", description="Base directory for storing chat data", ) + host: str = Field( + default="127.0.0.1", + description="Host for the chat API", + ) + log_level: str | int = Field( + default="info", + description="Log level for the chat API", + ) + port: int = Field( + default=9261, + description="Port for the chat API", + ge=1024, + le=65535, + ) diff --git a/src/chat/api/threads/__init__.py b/src/askui/chat/api/threads/__init__.py similarity index 100% rename from src/chat/api/threads/__init__.py rename to src/askui/chat/api/threads/__init__.py diff --git a/src/chat/api/threads/dependencies.py b/src/askui/chat/api/threads/dependencies.py similarity index 56% rename from src/chat/api/threads/dependencies.py rename to src/askui/chat/api/threads/dependencies.py index 926fdf9e..46f0840d 100644 --- a/src/chat/api/threads/dependencies.py +++ b/src/askui/chat/api/threads/dependencies.py @@ -1,10 +1,10 @@ from fastapi import Depends -from chat.api.dependencies import SettingsDep -from chat.api.messages.dependencies import MessageServiceDep -from chat.api.messages.service import MessageService -from chat.api.settings import Settings -from chat.api.threads.service import ThreadService +from askui.chat.api.dependencies import SettingsDep +from askui.chat.api.messages.dependencies import MessageServiceDep +from askui.chat.api.messages.service import MessageService +from askui.chat.api.settings import Settings +from askui.chat.api.threads.service import ThreadService def get_thread_service( diff --git a/src/chat/api/threads/router.py b/src/askui/chat/api/threads/router.py similarity index 89% rename from src/chat/api/threads/router.py rename to src/askui/chat/api/threads/router.py index e018440c..e29fc336 100644 --- a/src/chat/api/threads/router.py +++ b/src/askui/chat/api/threads/router.py @@ -1,8 +1,8 @@ from fastapi import APIRouter, HTTPException, status -from chat.api.models import ListQuery, ListQueryDep, ListResponse, ThreadId -from chat.api.threads.dependencies import ThreadServiceDep -from chat.api.threads.service import ( +from askui.chat.api.models import ListQuery, ListQueryDep, ListResponse, ThreadId +from askui.chat.api.threads.dependencies import ThreadServiceDep +from askui.chat.api.threads.service import ( Thread, ThreadCreateRequest, ThreadModifyRequest, diff --git a/src/chat/api/threads/service.py b/src/askui/chat/api/threads/service.py similarity index 94% rename from src/chat/api/threads/service.py rename to src/askui/chat/api/threads/service.py index 1ce88aef..1c1fb4f2 100644 --- a/src/chat/api/threads/service.py +++ b/src/askui/chat/api/threads/service.py @@ -4,9 +4,15 @@ from pydantic import BaseModel, Field -from chat.api.messages.service import MessageCreateRequest, MessageService -from chat.api.models import DoNotPatch, ListQuery, ListResponse, ThreadId, UnixDatetime -from chat.api.utils import generate_time_ordered_id +from askui.chat.api.messages.service import MessageCreateRequest, MessageService +from askui.chat.api.models import ( + DoNotPatch, + ListQuery, + ListResponse, + ThreadId, + UnixDatetime, +) +from askui.chat.api.utils import generate_time_ordered_id class Thread(BaseModel): diff --git a/src/chat/api/utils.py b/src/askui/chat/api/utils.py similarity index 100% rename from src/chat/api/utils.py rename to src/askui/chat/api/utils.py diff --git a/src/chat/api/runs/runner/events/__init__.py b/src/chat/api/runs/runner/events/__init__.py deleted file mode 100644 index 89dabf59..00000000 --- a/src/chat/api/runs/runner/events/__init__.py +++ /dev/null @@ -1,15 +0,0 @@ -from chat.api.runs.runner.events.done_events import DoneEvent -from chat.api.runs.runner.events.error_events import ErrorEvent -from chat.api.runs.runner.events.event_base import EventBase -from chat.api.runs.runner.events.events import Events -from chat.api.runs.runner.events.message_events import MessageEvent -from chat.api.runs.runner.events.run_events import RunEvent - -__all__ = [ - "DoneEvent", - "ErrorEvent", - "EventBase", - "Events", - "MessageEvent", - "RunEvent", -] diff --git a/src/chat/api/runs/runner/events/events.py b/src/chat/api/runs/runner/events/events.py deleted file mode 100644 index b11e2b12..00000000 --- a/src/chat/api/runs/runner/events/events.py +++ /dev/null @@ -1,6 +0,0 @@ -from chat.api.runs.runner.events.done_events import DoneEvent -from chat.api.runs.runner.events.error_events import ErrorEvent -from chat.api.runs.runner.events.message_events import MessageEvent -from chat.api.runs.runner.events.run_events import RunEvent - -Events = DoneEvent | ErrorEvent | MessageEvent | RunEvent diff --git a/src/chat/ui/.gitignore b/src/chat/ui/.gitignore deleted file mode 100644 index 5ab2f9bd..00000000 --- a/src/chat/ui/.gitignore +++ /dev/null @@ -1,33 +0,0 @@ -# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. - -# dependencies -/node_modules -/.pnp -.pnp.js -.yarn/install-state.gz - -# testing -/coverage - -# next.js -/.next/ -/out/ - -# production -/build - -# misc -.DS_Store -*.pem - -# debug -npm-debug.log* -yarn-debug.log* -yarn-error.log* - -# vercel -.vercel - -# typescript -*.tsbuildinfo -next-env.d.ts diff --git a/src/chat/ui/app/globals.css b/src/chat/ui/app/globals.css deleted file mode 100644 index 20b1c1db..00000000 --- a/src/chat/ui/app/globals.css +++ /dev/null @@ -1,82 +0,0 @@ -@tailwind base; -@tailwind components; -@tailwind utilities; - -:root { - --foreground-rgb: 0, 0, 0; - --background-start-rgb: 214, 219, 220; - --background-end-rgb: 255, 255, 255; -} - -@media (prefers-color-scheme: dark) { - :root { - --foreground-rgb: 255, 255, 255; - --background-start-rgb: 0, 0, 0; - --background-end-rgb: 0, 0, 0; - } -} - -@layer base { - :root { - --background: 0 0% 100%; - --foreground: 0 0% 3.9%; - --card: 0 0% 100%; - --card-foreground: 0 0% 3.9%; - --popover: 0 0% 100%; - --popover-foreground: 0 0% 3.9%; - --primary: 0 0% 9%; - --primary-foreground: 0 0% 98%; - --secondary: 0 0% 96.1%; - --secondary-foreground: 0 0% 9%; - --muted: 0 0% 96.1%; - --muted-foreground: 0 0% 45.1%; - --accent: 0 0% 96.1%; - --accent-foreground: 0 0% 9%; - --destructive: 0 84.2% 60.2%; - --destructive-foreground: 0 0% 98%; - --border: 0 0% 89.8%; - --input: 0 0% 89.8%; - --ring: 0 0% 3.9%; - --chart-1: 12 76% 61%; - --chart-2: 173 58% 39%; - --chart-3: 197 37% 24%; - --chart-4: 43 74% 66%; - --chart-5: 27 87% 67%; - --radius: 0.5rem; - } - .dark { - --background: 0 0% 3.9%; - --foreground: 0 0% 98%; - --card: 0 0% 3.9%; - --card-foreground: 0 0% 98%; - --popover: 0 0% 3.9%; - --popover-foreground: 0 0% 98%; - --primary: 0 0% 98%; - --primary-foreground: 0 0% 9%; - --secondary: 0 0% 14.9%; - --secondary-foreground: 0 0% 98%; - --muted: 0 0% 14.9%; - --muted-foreground: 0 0% 63.9%; - --accent: 0 0% 14.9%; - --accent-foreground: 0 0% 98%; - --destructive: 0 62.8% 30.6%; - --destructive-foreground: 0 0% 98%; - --border: 0 0% 14.9%; - --input: 0 0% 14.9%; - --ring: 0 0% 83.1%; - --chart-1: 220 70% 50%; - --chart-2: 160 60% 45%; - --chart-3: 30 80% 55%; - --chart-4: 280 65% 60%; - --chart-5: 340 75% 55%; - } -} - -@layer base { - * { - @apply border-border; - } - body { - @apply bg-background text-foreground; - } -} diff --git a/src/chat/ui/app/layout.tsx b/src/chat/ui/app/layout.tsx deleted file mode 100644 index 4ec63bdc..00000000 --- a/src/chat/ui/app/layout.tsx +++ /dev/null @@ -1,31 +0,0 @@ -import "./globals.css"; -import type { Metadata } from "next"; -import { Inter } from "next/font/google"; -import { ThemeProvider } from "next-themes"; - -const inter = Inter({ subsets: ["latin"] }); - -export const metadata: Metadata = { - title: "AskUI Chat", -}; - -export default function RootLayout({ - children, -}: { - children: React.ReactNode; -}) { - return ( - -
-- Start a conversation with AI Computer Agent to automate robotic - processes on your computer. -
-{content.text}
-
- {JSON.stringify(content.input, null, 2)}
-
- - Failed to load messages -
- -- No messages yet. Start the conversation below. -
-- Failed to load threads -
- -- No threads yet. Create your first thread to get started. -
-- {formatDistanceToNow(new Date(thread.created_at * 1000), { - addSuffix: true, - })} -
-