MH0386 commited on
Commit
b380004
·
verified ·
1 Parent(s): 2e5a549

Add HuggingFace sync

Browse files

Add HuggingFace sync workflow and update opencode action version.

.envrc DELETED
@@ -1,6 +0,0 @@
1
- export MODEL__URL=${MODEL__URL:-https://generativelanguage.googleapis.com/v1beta/openai}
2
- export MODEL__NAME=${MODEL__NAME:-gemini-2.5-flash}
3
- export MODEL__API_KEY=${GOOGLE_API_KEY}
4
- export VECTOR_DATABASE__URL=http://localhost:6333
5
- export VECTOR_DATABASE__NAME=main
6
- export CHARACTER__NAME=Napoleon
 
 
 
 
 
 
 
.gitattributes CHANGED
@@ -1,4 +1,2 @@
1
  * text=auto eol=lf
2
- *.jpg filter=lfs diff=lfs merge=lfs -text
3
- *.png filter=lfs diff=lfs merge=lfs -text
4
- *.jpeg filter=lfs diff=lfs merge=lfs -text
 
1
  * text=auto eol=lf
2
+ assets/image/Napoleon.jpg filter=lfs diff=lfs merge=lfs -text
 
 
.github/lint/.ruff.toml CHANGED
@@ -1,5 +1,5 @@
1
  indent-width = 4
2
- line-length = 88
3
  target-version = "py313"
4
 
5
  [lint]
 
1
  indent-width = 4
2
+ line-length = 100
3
  target-version = "py313"
4
 
5
  [lint]
.github/workflows/.docker.yaml CHANGED
@@ -71,7 +71,7 @@ jobs:
71
  uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
72
  - name: Get Python version from pyproject.toml
73
  id: get_python_version
74
- uses: mikefarah/yq@3d918acc2aa75876ca662e50a98391ab1bce34d0 # v4.52.1
75
  with:
76
  cmd: yq -roy '.project.requires-python' pyproject.toml
77
  - name: Log in to ${{ inputs.registry }} Registry
 
71
  uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
72
  - name: Get Python version from pyproject.toml
73
  id: get_python_version
74
+ uses: mikefarah/yq@065b200af9851db0d5132f50bc10b1406ea5c0a8 # v4.50.1
75
  with:
76
  cmd: yq -roy '.project.requires-python' pyproject.toml
77
  - name: Log in to ${{ inputs.registry }} Registry
.github/workflows/.lint.yaml CHANGED
@@ -141,7 +141,7 @@ jobs:
141
  with:
142
  token: ${{ secrets.GH_TOKEN }}
143
  - name: ${{ matrix.command }}
144
- uses: astral-sh/ruff-action@4919ec5cf1f49eff0871dbcea0da843445b837e6 # v3.6.1
145
  with:
146
  args: >-
147
  ${{ matrix.command }} --config .github/lint/.ruff.toml
@@ -305,8 +305,10 @@ jobs:
305
  with:
306
  enable-cache: true
307
  activate-environment: true
 
 
308
  - name: Check
309
- run: uvx ty check --output-format github
310
  markdownlint:
311
  name: MarkdownLint
312
  runs-on: ubuntu-latest
 
141
  with:
142
  token: ${{ secrets.GH_TOKEN }}
143
  - name: ${{ matrix.command }}
144
+ uses: astral-sh/ruff-action@57714a7c8a2e59f32539362ba31877a1957dded1 # v3.5.1
145
  with:
146
  args: >-
147
  ${{ matrix.command }} --config .github/lint/.ruff.toml
 
305
  with:
306
  enable-cache: true
307
  activate-environment: true
308
+ - name: Setup Venv
309
+ run: uv sync
310
  - name: Check
311
+ run: uv run ty check --output-format github
312
  markdownlint:
313
  name: MarkdownLint
314
  runs-on: ubuntu-latest
.github/workflows/build.yaml CHANGED
@@ -28,7 +28,7 @@ jobs:
28
  token: ${{ secrets.GH_TOKEN }}
29
  - name: Get Package version from pyproject.toml
30
  id: get_package_version
31
- uses: mikefarah/yq@3d918acc2aa75876ca662e50a98391ab1bce34d0 # v4.52.1
32
  with:
33
  cmd: yq -roy '.project.version' pyproject.toml
34
  - name: Install uv
 
28
  token: ${{ secrets.GH_TOKEN }}
29
  - name: Get Package version from pyproject.toml
30
  id: get_package_version
31
+ uses: mikefarah/yq@065b200af9851db0d5132f50bc10b1406ea5c0a8 # v4.50.1
32
  with:
33
  cmd: yq -roy '.project.version' pyproject.toml
34
  - name: Install uv
.github/workflows/ci_tools.yaml CHANGED
@@ -31,7 +31,7 @@ jobs:
31
  - name: Checkout repository
32
  uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
33
  - name: Run opencode
34
- uses: sst/opencode/github@597ae57bb16ea8b4314f718bc3250c8b9433d7dc # v1.1.48
35
  env:
36
  OPENCODE_API_KEY: ${{ secrets.OPENCODE_API_KEY }}
37
  with:
@@ -88,18 +88,15 @@ jobs:
88
  url: https://huggingface.co/spaces/${{github.repository}}
89
  steps:
90
  - name: Checkout repository
91
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
92
  with:
93
  fetch-depth: 0
94
  lfs: true
95
  - name: Install uv
96
- uses: astral-sh/setup-uv@803947b9bd8e9f986429fa0c5a41c367cd732b41 # v7.2.1
97
  with:
98
  enable-cache: true
99
  activate-environment: true
100
- - name: Export requirements
101
- run: uv export --no-editable --frozen --no-dev --no-emit-project --output-file
102
- requirements.txt
103
  - name: Push to HF
104
  env:
105
  HF_TOKEN: ${{ secrets.HF_TOKEN }}
 
31
  - name: Checkout repository
32
  uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
33
  - name: Run opencode
34
+ uses: sst/opencode/github@8f537940178772deedf3317c5c669950f1f6c5a6 # v1.1.45
35
  env:
36
  OPENCODE_API_KEY: ${{ secrets.OPENCODE_API_KEY }}
37
  with:
 
88
  url: https://huggingface.co/spaces/${{github.repository}}
89
  steps:
90
  - name: Checkout repository
91
+ uses: actions/checkout@v4.0.0
92
  with:
93
  fetch-depth: 0
94
  lfs: true
95
  - name: Install uv
96
+ uses: astral-sh/setup-uv@61cb8a9741eeb8a550a1b8544337180c0fc8476b # v7.2.0
97
  with:
98
  enable-cache: true
99
  activate-environment: true
 
 
 
100
  - name: Push to HF
101
  env:
102
  HF_TOKEN: ${{ secrets.HF_TOKEN }}
.github/workflows/release.yaml CHANGED
@@ -28,27 +28,6 @@ jobs:
28
  uses: pypa/gh-action-pypi-publish@release/v1
29
  with:
30
  packages-dir: dist/
31
- huggingface:
32
- name: Tag HuggingFace Space
33
- runs-on: ubuntu-latest
34
- permissions:
35
- contents: read
36
- id-token: write
37
- environment:
38
- name: huggingface
39
- url: https://huggingface.co/spaces/${{github.repository}}/tree/${{github.event.release.tag_name}}
40
- steps:
41
- - name: Install uv
42
- uses: astral-sh/setup-uv@803947b9bd8e9f986429fa0c5a41c367cd732b41 # v7.2.1
43
- with:
44
- enable-cache: true
45
- activate-environment: true
46
- - name: Push to HF
47
- env:
48
- HF_TOKEN: ${{ secrets.HF_TOKEN }}
49
- run: >-
50
- uvx hf repo tag create ${{github.repository}} ${{github.event.release.tag_name}}
51
- --repo-type space
52
  image:
53
  name: Release Image
54
  needs: pypi
 
28
  uses: pypa/gh-action-pypi-publish@release/v1
29
  with:
30
  packages-dir: dist/
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
31
  image:
32
  name: Release Image
33
  needs: pypi
.github/workflows/version.yaml CHANGED
@@ -35,7 +35,7 @@ jobs:
35
  run: uv version --bump patch
36
  - name: Get Package version from pyproject.toml
37
  id: get_package_version
38
- uses: mikefarah/yq@3d918acc2aa75876ca662e50a98391ab1bce34d0 # v4.52.1
39
  with:
40
  cmd: yq -roy '.project.version' pyproject.toml
41
  - name: Commit updated count
 
35
  run: uv version --bump patch
36
  - name: Get Package version from pyproject.toml
37
  id: get_package_version
38
+ uses: mikefarah/yq@065b200af9851db0d5132f50bc10b1406ea5c0a8 # v4.50.1
39
  with:
40
  cmd: yq -roy '.project.version' pyproject.toml
41
  - name: Commit updated count
.idea/chattr.iml CHANGED
@@ -3,6 +3,7 @@
3
  <component name="NewModuleRootManager">
4
  <content url="file://$MODULE_DIR$">
5
  <sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
 
6
  <excludeFolder url="file://$MODULE_DIR$/.venv" />
7
  </content>
8
  <orderEntry type="jdk" jdkName="uv (chattr)" jdkType="Python SDK" />
 
3
  <component name="NewModuleRootManager">
4
  <content url="file://$MODULE_DIR$">
5
  <sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
6
+ <sourceFolder url="file://$MODULE_DIR$/tests" isTestSource="true" />
7
  <excludeFolder url="file://$MODULE_DIR$/.venv" />
8
  </content>
9
  <orderEntry type="jdk" jdkName="uv (chattr)" jdkType="Python SDK" />
.idea/codeStyles/codeStyleConfig.xml ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
 
1
+ <component name="ProjectCodeStyleConfiguration">
2
+ <state>
3
+ <option name="PREFERRED_PROJECT_CODE_STYLE" value="Default" />
4
+ </state>
5
+ </component>
.idea/misc.xml CHANGED
@@ -4,6 +4,12 @@
4
  <option name="sdkName" value="uv (chattr)" />
5
  </component>
6
  <component name="ProjectRootManager" version="2" project-jdk-name="uv (chattr)" project-jdk-type="Python SDK" />
 
 
 
 
 
 
7
  <component name="RuffConfiguration">
8
  <option name="enabled" value="true" />
9
  </component>
 
4
  <option name="sdkName" value="uv (chattr)" />
5
  </component>
6
  <component name="ProjectRootManager" version="2" project-jdk-name="uv (chattr)" project-jdk-type="Python SDK" />
7
+ <component name="PyreflyConfiguration">
8
+ <option name="enabled" value="true" />
9
+ </component>
10
+ <component name="PythonCompatibilityInspectionAdvertiser">
11
+ <option name="version" value="3" />
12
+ </component>
13
  <component name="RuffConfiguration">
14
  <option name="enabled" value="true" />
15
  </component>
.idea/runConfigurations/Dev.xml ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ <component name="ProjectRunConfigurationManager">
2
+ <configuration default="false" name="Dev" type="docker-deploy" factoryName="docker-compose.yml" server-name="Docker">
3
+ <deployment type="docker-compose.yml">
4
+ <settings>
5
+ <option name="sourceFilePath" value="docker-compose-dev.yaml" />
6
+ </settings>
7
+ </deployment>
8
+ <method v="2" />
9
+ </configuration>
10
+ </component>
.idea/runConfigurations/Main.xml ADDED
@@ -0,0 +1,27 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <component name="ProjectRunConfigurationManager">
2
+ <configuration default="false" name="Main" type="tests" factoryName="Autodetect">
3
+ <module name="chattr" />
4
+ <option name="ENV_FILES" value="" />
5
+ <option name="INTERPRETER_OPTIONS" value="" />
6
+ <option name="PARENT_ENVS" value="true" />
7
+ <envs>
8
+ <env name="DOPPLER_ENV" value="1" />
9
+ </envs>
10
+ <option name="SDK_HOME" value="" />
11
+ <option name="SDK_NAME" value="uv (chattr)" />
12
+ <option name="WORKING_DIRECTORY" value="" />
13
+ <option name="IS_MODULE_SDK" value="false" />
14
+ <option name="ADD_CONTENT_ROOTS" value="true" />
15
+ <option name="ADD_SOURCE_ROOTS" value="true" />
16
+ <EXTENSION ID="PythonCoverageRunConfigurationExtension" runner="coverage.py" />
17
+ <EXTENSION ID="com.fapiko.jetbrains.plugins.better_direnv.runconfigs.PycharmRunConfigurationExtension">
18
+ <option name="DIRENV_ENABLED" value="true" />
19
+ <option name="DIRENV_TRUSTED" value="true" />
20
+ </EXTENSION>
21
+ <option name="RUN_TOOL" value="true" />
22
+ <option name="_new_additionalArguments" value="&quot;&quot;" />
23
+ <option name="_new_target" value="&quot;$ProjectFileDir$/tests/test_app.py&quot;" />
24
+ <option name="_new_targetType" value="&quot;PATH&quot;" />
25
+ <method v="2" />
26
+ </configuration>
27
+ </component>
.idea/runConfigurations/Qdrant.xml ADDED
@@ -0,0 +1,28 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <component name="ProjectRunConfigurationManager">
2
+ <configuration default="false" name="Qdrant" type="docker-deploy" factoryName="docker-image" server-name="Docker">
3
+ <deployment type="docker-image">
4
+ <settings>
5
+ <option name="imageTag" value="qdrant/qdrant" />
6
+ <option name="containerName" value="vectordb" />
7
+ <option name="portBindings">
8
+ <list>
9
+ <DockerPortBindingImpl>
10
+ <option name="containerPort" value="6333" />
11
+ <option name="hostPort" value="6333" />
12
+ </DockerPortBindingImpl>
13
+ </list>
14
+ </option>
15
+ <option name="showCommandPreview" value="true" />
16
+ <option name="volumeBindings">
17
+ <list>
18
+ <DockerVolumeBindingImpl>
19
+ <option name="containerPath" value="/qdrant/storage" />
20
+ <option name="hostPath" value="qdrant_storage" />
21
+ </DockerVolumeBindingImpl>
22
+ </list>
23
+ </option>
24
+ </settings>
25
+ </deployment>
26
+ <method v="2" />
27
+ </configuration>
28
+ </component>
.idea/runConfigurations/Start_Server.xml ADDED
@@ -0,0 +1,34 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <component name="ProjectRunConfigurationManager">
2
+ <configuration default="false" name="Start Server" type="PythonConfigurationType" factoryName="Python">
3
+ <output_file path="./app.log" is_save="true" />
4
+ <module name="chattr" />
5
+ <option name="ENV_FILES" value="" />
6
+ <option name="INTERPRETER_OPTIONS" value="" />
7
+ <option name="PARENT_ENVS" value="true" />
8
+ <envs>
9
+ <env name="PYTHONUNBUFFERED" value="1" />
10
+ <env name="DEBUG" value="1" />
11
+ <env name="DOPPLER_ENV" value="1" />
12
+ </envs>
13
+ <option name="SDK_HOME" value="" />
14
+ <option name="SDK_NAME" value="uv (chattr)" />
15
+ <option name="WORKING_DIRECTORY" value="" />
16
+ <option name="IS_MODULE_SDK" value="false" />
17
+ <option name="ADD_CONTENT_ROOTS" value="true" />
18
+ <option name="ADD_SOURCE_ROOTS" value="true" />
19
+ <EXTENSION ID="PythonCoverageRunConfigurationExtension" runner="coverage.py" />
20
+ <EXTENSION ID="com.fapiko.jetbrains.plugins.better_direnv.runconfigs.PycharmRunConfigurationExtension">
21
+ <option name="DIRENV_ENABLED" value="true" />
22
+ <option name="DIRENV_TRUSTED" value="true" />
23
+ </EXTENSION>
24
+ <option name="RUN_TOOL" value="true" />
25
+ <option name="SCRIPT_NAME" value="chattr" />
26
+ <option name="PARAMETERS" value="" />
27
+ <option name="SHOW_COMMAND_LINE" value="false" />
28
+ <option name="EMULATE_TERMINAL" value="true" />
29
+ <option name="MODULE_MODE" value="true" />
30
+ <option name="REDIRECT_INPUT" value="false" />
31
+ <option name="INPUT_FILE" value="" />
32
+ <method v="2" />
33
+ </configuration>
34
+ </component>
.idea/runConfigurations/VoiceGenerator.xml ADDED
@@ -0,0 +1,41 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <component name="ProjectRunConfigurationManager">
2
+ <configuration default="false" name="VoiceGenerator" type="docker-deploy" factoryName="docker-image" server-name="Docker">
3
+ <deployment type="docker-image">
4
+ <settings>
5
+ <option name="imageTag" value="alphaspheredotai/vocalizr" />
6
+ <option name="containerName" value="VoiceGenerator" />
7
+ <option name="envVars">
8
+ <list>
9
+ <DockerEnvVarImpl>
10
+ <option name="name" value="GRADIO_DEBUG" />
11
+ <option name="value" value="1" />
12
+ </DockerEnvVarImpl>
13
+ </list>
14
+ </option>
15
+ <option name="portBindings">
16
+ <list>
17
+ <DockerPortBindingImpl>
18
+ <option name="containerPort" value="7860" />
19
+ <option name="hostPort" value="7861" />
20
+ </DockerPortBindingImpl>
21
+ </list>
22
+ </option>
23
+ <option name="commandLineOptions" value="--user root" />
24
+ <option name="showCommandPreview" value="true" />
25
+ <option name="volumeBindings">
26
+ <list>
27
+ <DockerVolumeBindingImpl>
28
+ <option name="containerPath" value="/home/nonroot/hf" />
29
+ <option name="hostPath" value="huggingface" />
30
+ </DockerVolumeBindingImpl>
31
+ <DockerVolumeBindingImpl>
32
+ <option name="containerPath" value="/home/nonroot/results" />
33
+ <option name="hostPath" value="results" />
34
+ </DockerVolumeBindingImpl>
35
+ </list>
36
+ </option>
37
+ </settings>
38
+ </deployment>
39
+ <method v="2" />
40
+ </configuration>
41
+ </component>
.pre-commit-config.yaml CHANGED
@@ -68,13 +68,13 @@ repos:
68
  args:
69
  - --autofix
70
  - repo: https://github.com/renovatebot/pre-commit-hooks
71
- rev: 43.0.6
72
  hooks:
73
  - id: renovate-config-validator
74
  args:
75
  - --strict
76
  - repo: https://github.com/astral-sh/uv-pre-commit
77
- rev: 0.9.28
78
  hooks:
79
  - id: uv-lock
80
  - id: uv-sync
@@ -90,10 +90,6 @@ repos:
90
  args:
91
  - --config
92
  - .github/lint/.ruff.toml
93
- - repo: https://github.com/facebook/pyrefly-pre-commit
94
- rev: 0.50.1
95
- hooks:
96
- - id: pyrefly-check
97
  - repo: https://github.com/lyz-code/yamlfix
98
  rev: 1.19.1
99
  hooks:
@@ -112,7 +108,7 @@ repos:
112
  - repo: https://github.com/hadolint/hadolint
113
  rev: v2.14.0
114
  hooks:
115
- - id: hadolint-docker
116
  args:
117
  - -c
118
  - .github/lint/.hadolint.yaml
 
68
  args:
69
  - --autofix
70
  - repo: https://github.com/renovatebot/pre-commit-hooks
71
+ rev: 43.0.0
72
  hooks:
73
  - id: renovate-config-validator
74
  args:
75
  - --strict
76
  - repo: https://github.com/astral-sh/uv-pre-commit
77
+ rev: 0.9.27
78
  hooks:
79
  - id: uv-lock
80
  - id: uv-sync
 
90
  args:
91
  - --config
92
  - .github/lint/.ruff.toml
 
 
 
 
93
  - repo: https://github.com/lyz-code/yamlfix
94
  rev: 1.19.1
95
  hooks:
 
108
  - repo: https://github.com/hadolint/hadolint
109
  rev: v2.14.0
110
  hooks:
111
+ - id: hadolint
112
  args:
113
  - -c
114
  - .github/lint/.hadolint.yaml
README.md CHANGED
@@ -3,9 +3,8 @@ title: Chattr
3
  emoji: 💬
4
  colorFrom: gray
5
  colorTo: blue
6
- sdk: gradio
7
- python_version: 3.13
8
- app_file: src/chattr/__main__.py
9
  short_description: Chat with Characters
10
  ---
11
 
 
3
  emoji: 💬
4
  colorFrom: gray
5
  colorTo: blue
6
+ sdk: docker
7
+ app_port: 7860
 
8
  short_description: Chat with Characters
9
  ---
10
 
assets/image/Einstein.jpg DELETED

Git LFS Details

  • SHA256: 4c97e39f0682557315535871d13878aef8b89cd16edfd657c9c528a30ba25eb4
  • Pointer size: 131 Bytes
  • Size of remote file: 161 kB
docker-compose-dev.yaml CHANGED
@@ -1,6 +1,7 @@
1
  name: Chattr Dev
2
  services:
3
  vector_database:
 
4
  image: qdrant/qdrant:latest@sha256:0425e3e03e7fd9b3dc95c4214546afe19de2eb2e28ca621441a56663ac6e1f46
5
  ports:
6
  - 6333:6333
@@ -9,6 +10,7 @@ services:
9
  - qdrant_storage:/qdrant/storage
10
  restart: on-failure:3
11
  voice_generator:
 
12
  image: ghcr.io/alphaspheredotai/vocalizr:latest@sha256:df1f4fa0615ae3f34249454ddc3a74e3fd955332da507ff2c7d5373190037863
13
  ports:
14
  - 7861:7860
@@ -48,6 +50,7 @@ services:
48
  capabilities:
49
  - gpu
50
  video_generator:
 
51
  image: ghcr.io/alphaspheredotai/visualizr:latest@sha256:2c5b096a66c6ebee1a5c0242a8b42c393e0cfdcda086ae6ceba11f92618ec7aa
52
  ports:
53
  - 7862:7860
 
1
  name: Chattr Dev
2
  services:
3
  vector_database:
4
+ container_name: VectorDB
5
  image: qdrant/qdrant:latest@sha256:0425e3e03e7fd9b3dc95c4214546afe19de2eb2e28ca621441a56663ac6e1f46
6
  ports:
7
  - 6333:6333
 
10
  - qdrant_storage:/qdrant/storage
11
  restart: on-failure:3
12
  voice_generator:
13
+ container_name: VoiceGenerator
14
  image: ghcr.io/alphaspheredotai/vocalizr:latest@sha256:df1f4fa0615ae3f34249454ddc3a74e3fd955332da507ff2c7d5373190037863
15
  ports:
16
  - 7861:7860
 
50
  capabilities:
51
  - gpu
52
  video_generator:
53
+ container_name: VideoGenerator
54
  image: ghcr.io/alphaspheredotai/visualizr:latest@sha256:2c5b096a66c6ebee1a5c0242a8b42c393e0cfdcda086ae6ceba11f92618ec7aa
55
  ports:
56
  - 7862:7860
pyproject.toml CHANGED
@@ -9,7 +9,6 @@
9
  "gradio[mcp]>=6.5.1",
10
  "m3u8>=6.0.0",
11
  "mem0ai>=1.0.2",
12
- "poml>=0.0.8",
13
  "rich>=14.3.1",
14
  ]
15
  description = "App part of the Chatacter Backend"
@@ -29,6 +28,7 @@
29
  dev = [
30
  "doppler-env>=0.3.1",
31
  "pre-commit>=4.5.1",
 
32
  "pytest-emoji>=0.2.0",
33
  "pytest-md>=0.2.0",
34
  "pytest-mergify>=2026.1.26.1",
 
9
  "gradio[mcp]>=6.5.1",
10
  "m3u8>=6.0.0",
11
  "mem0ai>=1.0.2",
 
12
  "rich>=14.3.1",
13
  ]
14
  description = "App part of the Chatacter Backend"
 
28
  dev = [
29
  "doppler-env>=0.3.1",
30
  "pre-commit>=4.5.1",
31
+ "pyrefly>=0.46.1",
32
  "pytest-emoji>=0.2.0",
33
  "pytest-md>=0.2.0",
34
  "pytest-mergify>=2026.1.26.1",
requirements.txt DELETED
@@ -1,1031 +0,0 @@
1
- # This file was autogenerated by uv via the following command:
2
- # uv export --no-editable --frozen --no-dev --no-emit-project --output-file requirements.txt
3
- agno==2.4.7 \
4
- --hash=sha256:07959ec1928e3d7d487adc763350603fa4bd2243c25315d02416e0007bfecefe \
5
- --hash=sha256:cf39e805e34387925575dfede75a7b5345b559e0bf3f4af04dc76e25e04b2f98
6
- # via chattr
7
- aiofiles==24.1.0 \
8
- --hash=sha256:22a075c9e5a3810f0c2e48f3008c94d68c65d763b9b03857924c99e57355166c \
9
- --hash=sha256:b4ec55f4195e3eb5d7abd1bf7e061763e864dd4954231fb8539a0ef8bb8260e5
10
- # via gradio
11
- annotated-doc==0.0.4 \
12
- --hash=sha256:571ac1dc6991c450b25a9c2d84a3705e2ae7a53467b5d111c24fa8baabbed320 \
13
- --hash=sha256:fbcda96e87e9c92ad167c2e53839e57503ecfda18804ea28102353485033faa4
14
- # via fastapi
15
- annotated-types==0.7.0 \
16
- --hash=sha256:1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53 \
17
- --hash=sha256:aff07c09a53a08bc8cfccb9c85b05f1aa9a2a6f23728d790723543408344ce89
18
- # via pydantic
19
- anyio==4.12.1 \
20
- --hash=sha256:41cfcc3a4c85d3f05c932da7c26d0201ac36f72abd4435ba90d0464a3ffed703 \
21
- --hash=sha256:d405828884fc140aa80a3c667b8beed277f1dfedec42ba031bd6ac3db606ab6c
22
- # via
23
- # google-genai
24
- # gradio
25
- # httpx
26
- # mcp
27
- # openai
28
- # sse-starlette
29
- # starlette
30
- attrs==25.4.0 \
31
- --hash=sha256:16d5969b87f0859ef33a48b35d55ac1be6e42ae49d5e853b597db70c35c57e11 \
32
- --hash=sha256:adcf7e2a1fb3b36ac48d97835bb6d8ade15b8dcce26aba8bf1d14847b57a3373
33
- # via
34
- # jsonschema
35
- # referencing
36
- audioop-lts==0.2.2 \
37
- --hash=sha256:03f061a1915538fd96272bac9551841859dbb2e3bf73ebe4a23ef043766f5449 \
38
- --hash=sha256:106753a83a25ee4d6f473f2be6b0966fc1c9af7e0017192f5531a3e7463dce58 \
39
- --hash=sha256:143fad0311e8209ece30a8dbddab3b65ab419cbe8c0dde6e8828da25999be911 \
40
- --hash=sha256:15ab25dd3e620790f40e9ead897f91e79c0d3ce65fe193c8ed6c26cffdd24be7 \
41
- --hash=sha256:3bcddaaf6cc5935a300a8387c99f7a7fbbe212a11568ec6cf6e4bc458c048636 \
42
- --hash=sha256:3fc38008969796f0f689f1453722a0f463da1b8a6fbee11987830bfbb664f623 \
43
- --hash=sha256:47eba38322370347b1c47024defbd36374a211e8dd5b0dcbce7b34fdb6f8847b \
44
- --hash=sha256:4a53aa7c16a60a6857e6b0b165261436396ef7293f8b5c9c828a3a203147ed4a \
45
- --hash=sha256:4b4cd51a57b698b2d06cb9993b7ac8dfe89a3b2878e96bc7948e9f19ff51dba6 \
46
- --hash=sha256:51c916108c56aa6e426ce611946f901badac950ee2ddaf302b7ed35d9958970d \
47
- --hash=sha256:550c114a8df0aafe9a05442a1162dfc8fec37e9af1d625ae6060fed6e756f303 \
48
- --hash=sha256:5f93a5db13927a37d2d09637ccca4b2b6b48c19cd9eda7b17a2e9f77edee6a6f \
49
- --hash=sha256:64d0c62d88e67b98a1a5e71987b7aa7b5bcffc7dcee65b635823dbdd0a8dbbd0 \
50
- --hash=sha256:73f80bf4cd5d2ca7814da30a120de1f9408ee0619cc75da87d0641273d202a09 \
51
- --hash=sha256:752d76472d9804ac60f0078c79cdae8b956f293177acd2316cd1e15149aee132 \
52
- --hash=sha256:83c381767e2cc10e93e40281a04852facc4cd9334550e0f392f72d1c0a9c5753 \
53
- --hash=sha256:9191d68659eda01e448188f60364c7763a7ca6653ed3f87ebb165822153a8547 \
54
- --hash=sha256:96f19de485a2925314f5020e85911fb447ff5fbef56e8c7c6927851b95533a1c \
55
- --hash=sha256:9a13dc409f2564de15dd68be65b462ba0dde01b19663720c68c1140c782d1d75 \
56
- --hash=sha256:a2c2a947fae7d1062ef08c4e369e0ba2086049a5e598fda41122535557012e9e \
57
- --hash=sha256:a2d4f1513d63c795e82948e1305f31a6d530626e5f9f2605408b300ae6095093 \
58
- --hash=sha256:ba7c3a7e5f23e215cb271516197030c32aef2e754252c4c70a50aaff7031a2c8 \
59
- --hash=sha256:c0022283e9556e0f3643b7c3c03f05063ca72b3063291834cca43234f20c60bb \
60
- --hash=sha256:c174e322bb5783c099aaf87faeb240c8d210686b04bd61dfd05a8e5a83d88969 \
61
- --hash=sha256:c9c8e68d8b4a56fda8c025e538e639f8c5953f5073886b596c93ec9b620055e7 \
62
- --hash=sha256:cfcac6aa6f42397471e4943e0feb2244549db5c5d01efcd02725b96af417f3fe \
63
- --hash=sha256:d5e73fa573e273e4f2e5ff96f9043858a5e9311e94ffefd88a3186a910c70917 \
64
- --hash=sha256:def246fe9e180626731b26e89816e79aae2276f825420a07b4a647abaa84becc \
65
- --hash=sha256:dfbbc74ec68a0fd08cfec1f4b5e8cca3d3cd7de5501b01c4b5d209995033cde9 \
66
- --hash=sha256:e160bf9df356d841bb6c180eeeea1834085464626dc1b68fa4e1d59070affdc3 \
67
- --hash=sha256:e541c3ef484852ef36545f66209444c48b28661e864ccadb29daddb6a4b8e5f5 \
68
- --hash=sha256:fbdd522624141e40948ab3e8cdae6e04c748d78710e9f0f8d4dae2750831de19 \
69
- --hash=sha256:fd3d4602dc64914d462924a08c1a9816435a2155d74f325853c1f1ac3b2d9800
70
- # via gradio
71
- backoff==2.2.1 \
72
- --hash=sha256:03f829f5bb1923180821643f8753b0502c3b682293992485b0eef2807afa5cba \
73
- --hash=sha256:63579f9a0628e06278f7e47b7d7d5b6ce20dc65c5e96a6f3ca99a6adca0396e8
74
- # via posthog
75
- brotli==1.2.0 \
76
- --hash=sha256:0cf8c3b8ba93d496b2fae778039e2f5ecc7cff99df84df337ca31d8f2252896c \
77
- --hash=sha256:1b1d6a4efedd53671c793be6dd760fcf2107da3a52331ad9ea429edf0902f27a \
78
- --hash=sha256:26e8d3ecb0ee458a9804f47f21b74845cc823fd1bb19f02272be70774f56e2a6 \
79
- --hash=sha256:3e1b35d56856f3ed326b140d3c6d9db91740f22e14b06e840fe4bb1923439a18 \
80
- --hash=sha256:4ecdb3b6dc36e6d6e14d3a1bdc6c1057c8cbf80db04031d566eb6080ce283a48 \
81
- --hash=sha256:54a50a9dad16b32136b2241ddea9e4df159b41247b2ce6aac0b3276a66a8f1e5 \
82
- --hash=sha256:67a91c5187e1eec76a61625c77a6c8c785650f5b576ca732bd33ef58b0dff49c \
83
- --hash=sha256:9e5825ba2c9998375530504578fd4d5d1059d09621a02065d1b6bfc41a8e05ab \
84
- --hash=sha256:b63daa43d82f0cdabf98dee215b375b4058cce72871fd07934f179885aad16e8 \
85
- --hash=sha256:c8565e3cdc1808b1a34714b553b262c5de5fbda202285782173ec137fd13709f \
86
- --hash=sha256:e310f77e41941c13340a95976fe66a8a95b01e783d430eeaf7a2f87e0a57dd0a
87
- # via
88
- # gradio
89
- # httpx
90
- brotlicffi==1.2.0.0 ; platform_python_implementation != 'CPython' \
91
- --hash=sha256:23e5c912fdc6fd37143203820230374d24babd078fc054e18070a647118158f6 \
92
- --hash=sha256:33cfb408d0cff64cd50bef268c0fed397c46fbb53944aa37264148614a62e990 \
93
- --hash=sha256:34345d8d1f9d534fcac2249e57a4c3c8801a33c9942ff9f8574f67a175e17adb \
94
- --hash=sha256:84e3d0020cf1bd8b8131f4a07819edee9f283721566fe044a20ec792ca8fd8b7 \
95
- --hash=sha256:9458d08a7ccde8e3c0afedbf2c70a8263227a68dea5ab13590593f4c0a4fd5f4 \
96
- --hash=sha256:f139a7cdfe4ae7859513067b736eb44d19fae1186f9e99370092f6915216451b
97
- # via httpx
98
- certifi==2026.1.4 \
99
- --hash=sha256:9943707519e4add1115f44c2bc244f782c0249876bf51b6599fee1ffbedd685c \
100
- --hash=sha256:ac726dd470482006e014ad384921ed6438c457018f4b3d204aea4281258b2120
101
- # via
102
- # httpcore
103
- # httpx
104
- # requests
105
- cffi==2.0.0 \
106
- --hash=sha256:00bdf7acc5f795150faa6957054fbbca2439db2f775ce831222b66f192f03beb \
107
- --hash=sha256:07b271772c100085dd28b74fa0cd81c8fb1a3ba18b21e03d7c27f3436a10606b \
108
- --hash=sha256:19f705ada2530c1167abacb171925dd886168931e0a7b78f5bffcae5c6b5be75 \
109
- --hash=sha256:256f80b80ca3853f90c21b23ee78cd008713787b1b1e93eae9f3d6a7134abd91 \
110
- --hash=sha256:44d1b5909021139fe36001ae048dbdde8214afa20200eda0f64c068cac5d5529 \
111
- --hash=sha256:45d5e886156860dc35862657e1494b9bae8dfa63bf56796f2fb56e1679fc0bca \
112
- --hash=sha256:6d50360be4546678fc1b79ffe7a66265e28667840010348dd69a314145807a1b \
113
- --hash=sha256:74a03b9698e198d47562765773b4a8309919089150a0bb17d829ad7b44b60d27 \
114
- --hash=sha256:c8d3b5532fc71b7a77c09192b4a5a200ea992702734a2e9279a37f2478236f26 \
115
- --hash=sha256:d48a880098c96020b02d5a1f7d9251308510ce8858940e6fa99ece33f610838b \
116
- --hash=sha256:d9b29c1f0ae438d5ee9acb31cadee00a58c46cc9c0b2f9038c6b0b3470877a8c \
117
- --hash=sha256:dd4f05f54a52fb558f1ba9f528228066954fee3ebe629fc1660d874d040ae5a3 \
118
- --hash=sha256:f93fd8e5c8c0a4aa1f424d6173f14a892044054871c771f8566e4008eaa359d2
119
- # via
120
- # brotlicffi
121
- # cryptography
122
- charset-normalizer==3.4.4 \
123
- --hash=sha256:3162d5d8ce1bb98dd51af660f2121c55d0fa541b46dff7bb9b9f86ea1d87de72 \
124
- --hash=sha256:362d61fd13843997c1c446760ef36f240cf81d3ebf74ac62652aebaf7838561e \
125
- --hash=sha256:542d2cee80be6f80247095cc36c418f7bddd14f4a6de45af91dfad36d817bba2 \
126
- --hash=sha256:554af85e960429cf30784dd47447d5125aaa3b99a6f0683589dbd27e2f45da44 \
127
- --hash=sha256:5bd2293095d766545ec1a8f612559f6b40abc0eb18bb2f5d1171872d34036ede \
128
- --hash=sha256:6b39f987ae8ccdf0d2642338faf2abb1862340facc796048b604ef14919e55ed \
129
- --hash=sha256:74018750915ee7ad843a774364e13a3db91682f26142baddf775342c3f5b1133 \
130
- --hash=sha256:7a32c560861a02ff789ad905a2fe94e3f840803362c84fecf1851cb4cf3dc37f \
131
- --hash=sha256:81d5eb2a312700f4ecaa977a8235b634ce853200e828fbadf3a9c50bab278328 \
132
- --hash=sha256:94537985111c35f28720e43603b8e7b43a6ecfb2ce1d3058bbe955b73404e21a \
133
- --hash=sha256:9a26f18905b8dd5d685d6d07b0cdf98a79f3c7a918906af7cc143ea2e164c8bc \
134
- --hash=sha256:9b35f4c90079ff2e2edc5b26c0c77925e5d2d255c42c74fdb70fb49b172726ac \
135
- --hash=sha256:a8a8b89589086a25749f471e6a900d3f662d1d3b6e2e59dcecf787b1cc3a1894 \
136
- --hash=sha256:b435cba5f4f750aa6c0a0d92c541fb79f69a387c91e61f1795227e4ed9cece14 \
137
- --hash=sha256:bc7637e2f80d8530ee4a78e878bce464f70087ce73cf7c1caf142416923b98f1 \
138
- --hash=sha256:c0463276121fdee9c49b98908b3a89c39be45d86d1dbaa22957e38f6321d4ce3 \
139
- --hash=sha256:e1f185f86a6f3403aa2420e815904c67b2f9ebc443f045edd0de921108345794 \
140
- --hash=sha256:f8bf04158c6b607d747e93949aa60618b61312fe647a6369f88ce2ff16043490
141
- # via requests
142
- click==8.3.1 \
143
- --hash=sha256:12ff4785d337a1bb490bb7e9c2b1ee5da3112e94a8622f26a6c77f5d2fc6842a \
144
- --hash=sha256:981153a64e25f12d547d3426c367a4857371575ee7ad18df2a6183ab0545b2a6
145
- # via
146
- # ddgs
147
- # typer
148
- # typer-slim
149
- # uvicorn
150
- colorama==0.4.6 ; sys_platform == 'win32' \
151
- --hash=sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44 \
152
- --hash=sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6
153
- # via
154
- # click
155
- # loguru
156
- # tqdm
157
- coloredlogs==15.0.1 \
158
- --hash=sha256:612ee75c546f53e92e70049c9dbfcc18c935a2b9a53b66085ce9ef6a6e5c0934 \
159
- --hash=sha256:7c991aa71a4577af2f82600d8f8f3a89f936baeaf9b50a9c197da014e5bf16b0
160
- # via onnxruntime
161
- cryptography==46.0.3 \
162
- --hash=sha256:01ca9ff2885f3acc98c29f1860552e37f6d7c7d013d7334ff2a9de43a449315d \
163
- --hash=sha256:09859af8466b69bc3c27bdf4f5d84a665e0f7ab5088412e9e2ec49758eca5cbc \
164
- --hash=sha256:0abf1ffd6e57c67e92af68330d05760b7b7efb243aab8377e583284dbab72c71 \
165
- --hash=sha256:1000713389b75c449a6e979ffc7dcc8ac90b437048766cef052d4d30b8220971 \
166
- --hash=sha256:109d4ddfadf17e8e7779c39f9b18111a09efb969a301a31e987416a0191ed93a \
167
- --hash=sha256:10b01676fc208c3e6feeb25a8b83d81767e8059e1fe86e1dc62d10a3018fa926 \
168
- --hash=sha256:10ca84c4668d066a9878890047f03546f3ae0a6b8b39b697457b7757aaf18dbc \
169
- --hash=sha256:15ab9b093e8f09daab0f2159bb7e47532596075139dd74365da52ecc9cb46c5d \
170
- --hash=sha256:36e627112085bb3b81b19fed209c05ce2a52ee8b15d161b7c643a7d5a88491f3 \
171
- --hash=sha256:3b51b8ca4f1c6453d8829e1eb7299499ca7f313900dd4d89a24b8b87c0a780d4 \
172
- --hash=sha256:402b58fc32614f00980b66d6e56a5b4118e6cb362ae8f3fda141ba4689bd4506 \
173
- --hash=sha256:416260257577718c05135c55958b674000baef9a1c7d9e8f306ec60d71db850f \
174
- --hash=sha256:46acf53b40ea38f9c6c229599a4a13f0d46a6c3fa9ef19fc1a124d62e338dfa0 \
175
- --hash=sha256:4b7387121ac7d15e550f5cb4a43aef2559ed759c35df7336c402bb8275ac9683 \
176
- --hash=sha256:549e234ff32571b1f4076ac269fcce7a808d3bf98b76c8dd560e42dbc66d7d91 \
177
- --hash=sha256:5d7f93296ee28f68447397bf5198428c9aeeab45705a55d53a6343455dcb2c3c \
178
- --hash=sha256:5ecfccd2329e37e9b7112a888e76d9feca2347f12f37918facbb893d7bb88ee8 \
179
- --hash=sha256:6276eb85ef938dc035d59b87c8a7dc559a232f954962520137529d77b18ff1df \
180
- --hash=sha256:6eae65d4c3d33da080cff9c4ab1f711b15c1d9760809dad6ea763f3812d254cb \
181
- --hash=sha256:71e842ec9bc7abf543b47cf86b9a743baa95f4677d22baa4c7d5c69e49e9bc04 \
182
- --hash=sha256:a04bee9ab6a4da801eb9b51f1b708a1b5b5c9eb48c03f74198464c66f0d344ac \
183
- --hash=sha256:a2c0cd47381a3229c403062f764160d57d4d175e022c1df84e168c6251a22eec \
184
- --hash=sha256:a8b17438104fed022ce745b362294d9ce35b4c2e45c1d958ad4a4b019285f4a1 \
185
- --hash=sha256:a9a3008438615669153eb86b26b61e09993921ebdd75385ddd748702c5adfddb \
186
- --hash=sha256:b02cf04496f6576afffef5ddd04a0cb7d49cf6be16a9059d793a30b035f6b6ac \
187
- --hash=sha256:c0a7bb1a68a5d3471880e264621346c48665b3bf1c3759d682fc0864c540bd9e \
188
- --hash=sha256:cb3d760a6117f621261d662bccc8ef5bc32ca673e037c83fbe565324f5c46936 \
189
- --hash=sha256:d89c3468de4cdc4f08a57e214384d0471911a3830fcdaf7a8cc587e42a866372 \
190
- --hash=sha256:e5bf0ed4490068a2e72ac03d786693adeb909981cc596425d09032d372bcc849 \
191
- --hash=sha256:ef639cb3372f69ec44915fafcd6698b6cc78fbe0c2ea41be867f6ed612811963 \
192
- --hash=sha256:f260d0d41e9b4da1ed1e0f1ce571f97fe370b152ab18778e9e8f67d6af432018
193
- # via pyjwt
194
- ddgs==9.10.0 \
195
- --hash=sha256:81233d79309836eb03e7df2a0d2697adc83c47c342713132c0ba618f1f2c6eee \
196
- --hash=sha256:d9381ff75bdf1ad6691d3d1dc2be12be190d1d32ecd24f1002c492143c52c34f
197
- # via chattr
198
- distro==1.9.0 \
199
- --hash=sha256:2fa77c6fd8940f116ee1d6b94a2f90b13b5ea8d019b98bc8bafdcabcdd9bdbed \
200
- --hash=sha256:7bffd925d65168f85027d8da9af6bddab658135b840670a223589bc0c8ef02b2
201
- # via
202
- # google-genai
203
- # openai
204
- # posthog
205
- docstring-parser==0.17.0 \
206
- --hash=sha256:583de4a309722b3315439bb31d64ba3eebada841f2e2cee23b99df001434c912 \
207
- --hash=sha256:cf2569abd23dce8099b300f9b4fa8191e9582dda731fd533daf54c4551658708
208
- # via agno
209
- fake-useragent==2.2.0 \
210
- --hash=sha256:4e6ab6571e40cc086d788523cf9e018f618d07f9050f822ff409a4dfe17c16b2 \
211
- --hash=sha256:67f35ca4d847b0d298187443aaf020413746e56acd985a611908c73dba2daa24
212
- # via ddgs
213
- fastapi==0.128.0 \
214
- --hash=sha256:1cc179e1cef10a6be60ffe429f79b829dce99d8de32d7acb7e6c8dfdf7f2645a \
215
- --hash=sha256:aebd93f9716ee3b4f4fcfe13ffb7cf308d99c9f3ab5622d8877441072561582d
216
- # via gradio
217
- fastembed==0.7.4 \
218
- --hash=sha256:79250a775f70bd6addb0e054204df042b5029ecae501e40e5bbd08e75844ad83 \
219
- --hash=sha256:8b8a4ea860ca295002f4754e8f5820a636e1065a9444959e18d5988d7f27093b
220
- # via chattr
221
- ffmpy==1.0.0 \
222
- --hash=sha256:5640e5f0fd03fb6236d0e119b16ccf6522db1c826fdf35dcb87087b60fd7504f \
223
- --hash=sha256:b12932e95435c8820f1cd041024402765f821971e4bae753b327fc02a6e12f8b
224
- # via gradio
225
- filelock==3.20.3 \
226
- --hash=sha256:18c57ee915c7ec61cff0ecf7f0f869936c7c30191bb0cf406f1341778d0834e1 \
227
- --hash=sha256:4b0dda527ee31078689fc205ec4f1c1bf7d56cf88b6dc9426c4f230e46c2dce1
228
- # via huggingface-hub
229
- flatbuffers==25.12.19 \
230
- --hash=sha256:7634f50c427838bb021c2d66a3d1168e9d199b0607e6329399f04846d42e20b4
231
- # via onnxruntime
232
- fsspec==2026.1.0 \
233
- --hash=sha256:cb76aa913c2285a3b49bdd5fc55b1d7c708d7208126b60f2eb8194fe1b4cbdcc \
234
- --hash=sha256:e987cb0496a0d81bba3a9d1cee62922fb395e7d4c3b575e57f547953334fe07b
235
- # via
236
- # gradio-client
237
- # huggingface-hub
238
- gitdb==4.0.12 \
239
- --hash=sha256:5ef71f855d191a3326fcfbc0d5da835f26b13fbcba60c32c21091c349ffdb571 \
240
- --hash=sha256:67073e15955400952c6565cc3e707c554a4eea2e428946f7a4c162fab9bd9bcf
241
- # via gitpython
242
- gitpython==3.1.46 \
243
- --hash=sha256:400124c7d0ef4ea03f7310ac2fbf7151e09ff97f2a3288d64a440c584a29c37f \
244
- --hash=sha256:79812ed143d9d25b6d176a10bb511de0f9c67b1fa641d82097b0ab90398a2058
245
- # via agno
246
- google-auth==2.47.0 \
247
- --hash=sha256:833229070a9dfee1a353ae9877dcd2dec069a8281a4e72e72f77d4a70ff945da \
248
- --hash=sha256:c516d68336bfde7cf0da26aab674a36fedcf04b37ac4edd59c597178760c3498
249
- # via google-genai
250
- google-genai==1.60.0 \
251
- --hash=sha256:967338378ffecebec19a8ed90cf8797b26818bacbefd7846a9280beb1099f7f3 \
252
- --hash=sha256:9768061775fddfaecfefb0d6d7a6cabefb3952ebd246cd5f65247151c07d33d1
253
- # via agno
254
- gradio==6.5.1 \
255
- --hash=sha256:31223a1699f15072176dbf48a94f08457228a38263bb4c221a0ccea3a639a595 \
256
- --hash=sha256:5d49ff9691413ca5411189a694de5cbf1b171e2d49bf9f113952ae8a93c7088d
257
- # via chattr
258
- gradio-client==2.0.3 \
259
- --hash=sha256:8f1cec02dccaf64ac0285ed60479a2b0db3778dfe74c85a36d7ec9a95daeccc4 \
260
- --hash=sha256:bcc88da74e3a387bcd41535578abbafe2091bcf4715c9542111804741b9e50b0
261
- # via gradio
262
- greenlet==3.3.1 ; platform_machine == 'AMD64' or platform_machine == 'WIN32' or platform_machine == 'aarch64' or platform_machine == 'amd64' or platform_machine == 'ppc64le' or platform_machine == 'win32' or platform_machine == 'x86_64' \
263
- --hash=sha256:27289986f4e5b0edec7b5a91063c109f0276abb09a7e9bdab08437525977c946 \
264
- --hash=sha256:2f080e028001c5273e0b42690eaf359aeef9cb1389da0f171ea51a5dc3c7608d \
265
- --hash=sha256:33a956fe78bbbda82bfc95e128d61129b32d66bcf0a20a1f0c08aa4839ffa951 \
266
- --hash=sha256:41848f3230b58c08bb43dee542e74a2a2e34d3c59dc3076cec9151aeeedcae98 \
267
- --hash=sha256:4b065d3284be43728dd280f6f9a13990b56470b81be20375a207cdc814a983f2 \
268
- --hash=sha256:6423481193bbbe871313de5fd06a082f2649e7ce6e08015d2a76c1e9186ca5b3 \
269
- --hash=sha256:65be2f026ca6a176f88fb935ee23c18333ccea97048076aef4db1ef5bc0713ac \
270
- --hash=sha256:7a3ae05b3d225b4155bda56b072ceb09d05e974bc74be6c3fc15463cf69f33fd \
271
- --hash=sha256:7ab327905cabb0622adca5971e488064e35115430cec2c35a50fd36e72a315b3
272
- # via sqlalchemy
273
- groovy==0.1.2 \
274
- --hash=sha256:25c1dc09b3f9d7e292458aa762c6beb96ea037071bf5e917fc81fb78d2231083 \
275
- --hash=sha256:7f7975bab18c729a257a8b1ae9dcd70b7cafb1720481beae47719af57c35fa64
276
- # via gradio
277
- grpcio==1.76.0 \
278
- --hash=sha256:25a18e9810fbc7e7f03ec2516addc116a957f8cbb8cbc95ccc80faa072743d03 \
279
- --hash=sha256:26ef06c73eb53267c2b319f43e6634c7556ea37672029241a056629af27c10e2 \
280
- --hash=sha256:3e2a27c89eb9ac3d81ec8835e12414d73536c6e620355d65102503064a4ed6eb \
281
- --hash=sha256:45e0111e73f43f735d70786557dc38141185072d7ff8dc1829d6a77ac1471468 \
282
- --hash=sha256:5e8571632780e08526f118f74170ad8d50fb0a48c23a746bef2a6ebade3abd6f \
283
- --hash=sha256:61f69297cba3950a524f61c7c8ee12e55c486cb5f7db47ff9dcee33da6f0d3ae \
284
- --hash=sha256:6a15c17af8839b6801d554263c546c69c4d7718ad4321e3166175b37eaacca77 \
285
- --hash=sha256:7be78388d6da1a25c0d5ec506523db58b18be22d9c37d8d3a32c08be4987bd73 \
286
- --hash=sha256:83d57312a58dcfe2a3a0f9d1389b299438909a02db60e2f2ea2ae2d8034909d3 \
287
- --hash=sha256:931091142fd8cc14edccc0845a79248bc155425eee9a98b2db2ea4f00a235a42 \
288
- --hash=sha256:f9f7bd5faab55f47231ad8dba7787866b69f5e93bc306e3915606779bbfb4ba8
289
- # via qdrant-client
290
- h11==0.16.0 \
291
- --hash=sha256:4e35b956cf45792e4caa5885e69fba00bdbc6ffafbfa020300e549b208ee5ff1 \
292
- --hash=sha256:63cf8bbe7522de3bf65932fda1d9c2772064ffb3dae62d55932da54b31cb6c86
293
- # via
294
- # agno
295
- # httpcore
296
- # uvicorn
297
- h2==4.3.0 \
298
- --hash=sha256:6c59efe4323fa18b47a632221a1888bd7fde6249819beda254aeca909f221bf1 \
299
- --hash=sha256:c438f029a25f7945c69e0ccf0fb951dc3f73a5f6412981daee861431b70e2bdd
300
- # via httpx
301
- hf-xet==1.2.0 ; platform_machine == 'AMD64' or platform_machine == 'aarch64' or platform_machine == 'amd64' or platform_machine == 'arm64' or platform_machine == 'x86_64' \
302
- --hash=sha256:27df617a076420d8845bea087f59303da8be17ed7ec0cd7ee3b9b9f579dff0e4 \
303
- --hash=sha256:293a7a3787e5c95d7be1857358a9130694a9c6021de3f27fa233f37267174382 \
304
- --hash=sha256:3651fd5bfe0281951b988c0facbe726aa5e347b103a675f49a3fa8144c7968fd \
305
- --hash=sha256:46740d4ac024a7ca9b22bebf77460ff43332868b661186a8e46c227fdae01848 \
306
- --hash=sha256:4c1428c9ae73ec0939410ec73023c4f842927f39db09b063b9482dac5a3bb737 \
307
- --hash=sha256:6de1fc44f58f6dd937956c8d304d8c2dea264c80680bcfa61ca4a15e7b76780f \
308
- --hash=sha256:7d40b18769bb9a8bc82a9ede575ce1a44c75eb80e7375a01d76259089529b5dc \
309
- --hash=sha256:a55558084c16b09b5ed32ab9ed38421e2d87cf3f1f89815764d1177081b99865 \
310
- --hash=sha256:a8c27070ca547293b6890c4bf389f713f80e8c478631432962bb7f4bc0bd7d7f \
311
- --hash=sha256:b70218dd548e9840224df5638fdc94bd033552963cfa97f9170829381179c813 \
312
- --hash=sha256:cd3a6027d59cfb60177c12d6424e31f4b5ff13d8e3a1247b3a584bf8977e6df5 \
313
- --hash=sha256:ceeefcd1b7aed4956ae8499e2199607765fbd1c60510752003b6cc0b8413b649 \
314
- --hash=sha256:d06fa97c8562fb3ee7a378dd9b51e343bc5bc8190254202c9771029152f5e08c \
315
- --hash=sha256:e6584a52253f72c9f52f9e549d5895ca7a471608495c4ecaa6cc73dba2b24d69 \
316
- --hash=sha256:f182f264ed2acd566c514e45da9f2119110e48a87a327ca271027904c70c5832
317
- # via huggingface-hub
318
- hpack==4.1.0 \
319
- --hash=sha256:157ac792668d995c657d93111f46b4535ed114f0c9c8d672271bbec7eae1b496 \
320
- --hash=sha256:ec5eca154f7056aa06f196a557655c5b009b382873ac8d1e66e79e87535f1dca
321
- # via h2
322
- httpcore==1.0.9 \
323
- --hash=sha256:2d400746a40668fc9dec9810239072b40b4484b640a8c38fd654a024c7a1bf55 \
324
- --hash=sha256:6e34463af53fd2ab5d807f399a9b45ea31c3dfa2276f15a2c3f00afff6e176e8
325
- # via httpx
326
- httpx==0.28.1 \
327
- --hash=sha256:75e98c5f16b0f35b567856f597f06ff2270a374470a5c2392242528e3e3e42fc \
328
- --hash=sha256:d909fcccc110f8c7faf814ca82a9a4d816bc5a6dbfea25d6591d6985b8ba59ad
329
- # via
330
- # agno
331
- # ddgs
332
- # google-genai
333
- # gradio
334
- # gradio-client
335
- # huggingface-hub
336
- # mcp
337
- # openai
338
- # qdrant-client
339
- # safehttpx
340
- httpx-sse==0.4.3 \
341
- --hash=sha256:0ac1c9fe3c0afad2e0ebb25a934a59f4c7823b60792691f779fad2c5568830fc \
342
- --hash=sha256:9b1ed0127459a66014aec3c56bebd93da3c1bc8bb6618c8082039a44889a755d
343
- # via mcp
344
- huggingface-hub==1.3.3 \
345
- --hash=sha256:44af7b62380efc87c1c3bde7e1bf0661899b5bdfca1fc60975c61ee68410e10e \
346
- --hash=sha256:f8be6f468da4470db48351e8c77d6d8115dff9b3daeb30276e568767b1ff7574
347
- # via
348
- # fastembed
349
- # gradio
350
- # gradio-client
351
- # tokenizers
352
- humanfriendly==10.0 \
353
- --hash=sha256:1697e1a8a8f550fd43c2865cd84542fc175a61dcb779b6fee18cf6b6ccba1477 \
354
- --hash=sha256:6b0b831ce8f15f7300721aa49829fc4e83921a9a301cc7f606be6686a2288ddc
355
- # via coloredlogs
356
- hyperframe==6.1.0 \
357
- --hash=sha256:b03380493a519fce58ea5af42e4a42317bf9bd425596f7a0835ffce80f1a42e5 \
358
- --hash=sha256:f630908a00854a7adeabd6382b43923a4c4cd4b821fcb527e6ab9e15382a3b08
359
- # via h2
360
- idna==3.11 \
361
- --hash=sha256:771a87f49d9defaf64091e6e6fe9c18d4833f140bd19464795bc32d966ca37ea \
362
- --hash=sha256:795dafcc9c04ed0c1fb032c2aa73654d8e8c5023a7df64a53f39190ada629902
363
- # via
364
- # anyio
365
- # httpx
366
- # requests
367
- jinja2==3.1.6 \
368
- --hash=sha256:0137fb05990d35f1275a587e9aee6d56da821fc83491a0fb838183be43f66d6d \
369
- --hash=sha256:85ece4451f492d0c13c5dd7c13a64681a86afae63a5f347908daf103ce6d2f67
370
- # via gradio
371
- jiter==0.12.0 \
372
- --hash=sha256:048485c654b838140b007390b8182ba9774621103bd4d77c9c3f6f117474ba45 \
373
- --hash=sha256:2a5e90604620f94bf62264e7c2c038704d38217b7465b863896c6d7c902b06c7 \
374
- --hash=sha256:351d54f2b09a41600ffea43d081522d792e81dcfb915f6d2d242744c1cc48beb \
375
- --hash=sha256:37f27a32ce36364d2fa4f7fdc507279db604d27d239ea2e044c8f148410defe1 \
376
- --hash=sha256:4747de73d6b8c78f2e253a2787930f4fffc68da7fa319739f57437f95963c4de \
377
- --hash=sha256:4e017c417b1ebda911bd13b1e40612704b1f5420e30695112efdbed8a4b389ed \
378
- --hash=sha256:53839b35a38f56b8be26a7851a48b89bc47e5d88e900929df10ed93b95fea3d6 \
379
- --hash=sha256:635e737fbb7315bef0037c19b88b799143d2d7d3507e61a76751025226b3ac87 \
380
- --hash=sha256:64dfcd7d5c168b38d3f9f8bba7fc639edb3418abcc74f22fdbe6b8938293f30b \
381
- --hash=sha256:6cc49d5130a14b732e0612bc76ae8db3b49898732223ef8b7599aa8d9810683e \
382
- --hash=sha256:88ef757017e78d2860f96250f9393b7b577b06a956ad102c29c8237554380db3 \
383
- --hash=sha256:89b0bfb8b2bf2351fba36bb211ef8bfceba73ef58e7f0c68fb67b5a2795ca2f9 \
384
- --hash=sha256:94f669548e55c91ab47fef8bddd9c954dab1938644e715ea49d7e117015110a4 \
385
- --hash=sha256:bbc0944aa3d4b4773e348cda635252824a78f4ba44328e042ef1ff3f6080d1cf \
386
- --hash=sha256:c97b92c54fe6110138c872add030a1f99aea2401ddcdaa21edf74705a646dd60 \
387
- --hash=sha256:da25c62d4ee1ffbacb97fac6dfe4dcd6759ebdc9015991e92a6eae5816287f44 \
388
- --hash=sha256:e25012eb0c456fcc13354255d0338cd5397cce26c77b2832b3c4e2e255ea5d9a \
389
- --hash=sha256:ed53b3d6acbcb0fd0b90f20c7cb3b24c357fe82a3518934d4edfa8c6898e498c \
390
- --hash=sha256:f5aa5427a629a824a543672778c9ce0c5e556550d1569bb6ea28a85015287626
391
- # via openai
392
- jsonschema==4.26.0 \
393
- --hash=sha256:0c26707e2efad8aa1bfc5b7ce170f3fccc2e4918ff85989ba9ffa9facb2be326 \
394
- --hash=sha256:d489f15263b8d200f8387e64b4c3a75f06629559fb73deb8fdfb525f2dab50ce
395
- # via mcp
396
- jsonschema-specifications==2025.9.1 \
397
- --hash=sha256:98802fee3a11ee76ecaca44429fda8a41bff98b00a0f2838151b113f210cc6fe \
398
- --hash=sha256:b540987f239e745613c7a9176f3edb72b832a4ac465cf02712288397832b5e8d
399
- # via jsonschema
400
- loguru==0.7.3 \
401
- --hash=sha256:19480589e77d47b8d85b2c827ad95d49bf31b0dcde16593892eb51dd18706eb6 \
402
- --hash=sha256:31a33c10c8e1e10422bfd431aeb5d351c7cf7fa671e3c4df004162264b28220c
403
- # via fastembed
404
- lxml==6.0.2 \
405
- --hash=sha256:13dcecc9946dca97b11b7c40d29fba63b55ab4170d3c0cf8c0c164343b9bfdcf \
406
- --hash=sha256:1941354d92699fb5ffe6ed7b32f9649e43c2feb4b97205f75866f7d21aa91452 \
407
- --hash=sha256:2cbcbf6d6e924c28f04a43f3b6f6e272312a090f269eff68a2982e13e5d57659 \
408
- --hash=sha256:358d9adae670b63e95bc59747c72f4dc97c9ec58881d4627fe0120da0f90d314 \
409
- --hash=sha256:4077b7c79f31755df33b795dc12119cb557a0106bfdab0d2c2d97bd3cf3dffa6 \
410
- --hash=sha256:6c8963287d7a4c5c9a432ff487c52e9c5618667179c18a204bdedb27310f022f \
411
- --hash=sha256:6ec0e3f745021bfed19c456647f0298d60a24c9ff86d9d051f52b509663feeb1 \
412
- --hash=sha256:846ae9a12d54e368933b9759052d6206a9e8b250291109c48e350c1f1f49d916 \
413
- --hash=sha256:8f8d0cbd0674ee89863a523e6994ac25fd5be9c8486acfc3e5ccea679bad2679 \
414
- --hash=sha256:9b33d21594afab46f37ae58dfadd06636f154923c4e8a4d754b0127554eb2e77 \
415
- --hash=sha256:a7c5d5e5f1081955358533be077166ee97ed2571d6a66bdba6ec2f609a715d1a \
416
- --hash=sha256:b30d46379644fbfc3ab81f8f82ae4de55179414651f110a1514f0b1f8f6cb2d7 \
417
- --hash=sha256:bb2f6ca0ae2d983ded09357b84af659c954722bbf04dea98030064996d156048 \
418
- --hash=sha256:cd79f3367bd74b317dda655dc8fcfa304d9eb6e4fb06b7168c5cf27f96e0cd62 \
419
- --hash=sha256:dfb874cfa53340009af6bdd7e54ebc0d21012a60a4e65d927c2e477112e63484 \
420
- --hash=sha256:e8cd2415f372e7e5a789d743d133ae474290a90b9023197fd78f32e2dc6873e2 \
421
- --hash=sha256:eb2a12d704f180a902d7fa778c6d71f36ceb7b0d317f34cdc76a5d05aa1dd1df \
422
- --hash=sha256:ef9266d2aa545d7374938fb5c484531ef5a2ec7f2d573e62f8ce722c735685fd \
423
- --hash=sha256:fb8dae0b6b8b7f9e96c26fdd8121522ce5de9bb5538010870bd538683d30e9a2
424
- # via ddgs
425
- m3u8==6.0.0 \
426
- --hash=sha256:566d0748739c552dad10f8c87150078de6a0ec25071fa48e6968e96fc6dcba5d \
427
- --hash=sha256:7ade990a1667d7a653bcaf9413b16c3eb5cd618982ff46aaff57fe6d9fa9c0fd
428
- # via chattr
429
- markdown-it-py==4.0.0 \
430
- --hash=sha256:87327c59b172c5011896038353a81343b6754500a08cd7a4973bb48c6d578147 \
431
- --hash=sha256:cb0a2b4aa34f932c007117b194e945bd74e0ec24133ceb5bac59009cda1cb9f3
432
- # via rich
433
- markupsafe==3.0.3 \
434
- --hash=sha256:116bb52f642a37c115f517494ea5feb03889e04df47eeff5b130b1808ce7c219 \
435
- --hash=sha256:12c63dfb4a98206f045aa9563db46507995f7ef6d83b2f68eda65c307c6829eb \
436
- --hash=sha256:133a43e73a802c5562be9bbcd03d090aa5a1fe899db609c29e8c8d815c5f6de6 \
437
- --hash=sha256:1b4b79e8ebf6b55351f0d91fe80f893b4743f104bff22e90697db1590e47a218 \
438
- --hash=sha256:218551f6df4868a8d527e3062d0fb968682fe92054e89978594c28e642c43a73 \
439
- --hash=sha256:3524b778fe5cfb3452a09d31e7b5adefeea8c5be1d43c4f810ba09f2ceb29d37 \
440
- --hash=sha256:4e885a3d1efa2eadc93c894a21770e4bc67899e3543680313b09f139e149ab19 \
441
- --hash=sha256:509fa21c6deb7a7a273d629cf5ec029bc209d1a51178615ddf718f5918992ab9 \
442
- --hash=sha256:69c0b73548bc525c8cb9a251cddf1931d1db4d2258e9599c28c07ef3580ef354 \
443
- --hash=sha256:722695808f4b6457b320fdc131280796bdceb04ab50fe1795cd540799ebe1698 \
444
- --hash=sha256:795e7751525cae078558e679d646ae45574b47ed6e7771863fcc079a6171a0fc \
445
- --hash=sha256:7e68f88e5b8799aa49c85cd116c932a1ac15caaa3f5db09087854d218359e485 \
446
- --hash=sha256:8485f406a96febb5140bfeca44a73e3ce5116b2501ac54fe953e488fb1d03b12 \
447
- --hash=sha256:8709b08f4a89aa7586de0aadc8da56180242ee0ada3999749b183aa23df95025 \
448
- --hash=sha256:8f71bc33915be5186016f675cd83a1e08523649b0e33efdb898db577ef5bb009 \
449
- --hash=sha256:9a1abfdc021a164803f4d485104931fb8f8c1efd55bc6b748d2f5774e78b62c5 \
450
- --hash=sha256:9b79b7a16f7fedff2495d684f2b59b0457c3b493778c9eed31111be64d58279f \
451
- --hash=sha256:a4afe79fb3de0b7097d81da19090f4df4f8d3a2b3adaa8764138aac2e44f3af1 \
452
- --hash=sha256:ad2cf8aa28b8c020ab2fc8287b0f823d0a7d8630784c31e9ee5edea20f406287 \
453
- --hash=sha256:b8512a91625c9b3da6f127803b166b629725e68af71f8184ae7e7d54686a56d6 \
454
- --hash=sha256:bdd37121970bfd8be76c5fb069c7751683bdf373db1ed6c010162b2a130248ed \
455
- --hash=sha256:ccfcd093f13f0f0b7fdd0f198b90053bf7b2f02a3927a30e63f3ccc9df56b676 \
456
- --hash=sha256:e1cf1972137e83c5d4c136c43ced9ac51d0e124706ee1c8aa8532c1287fa8795
457
- # via
458
- # gradio
459
- # jinja2
460
- mcp==1.26.0 \
461
- --hash=sha256:904a21c33c25aa98ddbeb47273033c435e595bbacfdb177f4bd87f6dceebe1ca \
462
- --hash=sha256:db6e2ef491eecc1a0d93711a76f28dec2e05999f93afd48795da1c1137142c66
463
- # via gradio
464
- mdurl==0.1.2 \
465
- --hash=sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8 \
466
- --hash=sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba
467
- # via markdown-it-py
468
- mem0ai==1.0.2 \
469
- --hash=sha256:3528523653bc57efa477d55e703dcedf8decc23868d4dbcc6d43a97f2315834a \
470
- --hash=sha256:533c370e8a4e817d47a583cb7fa4df55db59de8dd67be39f2b927e2ad19607d1
471
- # via chattr
472
- mmh3==5.2.0 \
473
- --hash=sha256:03e08c6ebaf666ec1e3d6ea657a2d363bb01effd1a9acfe41f9197decaef0051 \
474
- --hash=sha256:1efc8fec8478e9243a78bb993422cf79f8ff85cb4cf6b79647480a31e0d950a8 \
475
- --hash=sha256:1fdb36b940e9261aff0b5177c5b74a36936b902f473180f6c15bde26143681a9 \
476
- --hash=sha256:45b590e31bc552c6f8e2150ff1ad0c28dd151e9f87589e7eaf508fbdd8e8e908 \
477
- --hash=sha256:58981d6ea9646dbbf9e59a30890cbf9f610df0e4a57dbfe09215116fd90b0093 \
478
- --hash=sha256:7303aab41e97adcf010a09efd8f1403e719e59b7705d5e3cfed3dd7571589290 \
479
- --hash=sha256:7e5634565367b6d98dc4aa2983703526ef556b3688ba3065edb4b9b90ede1c54 \
480
- --hash=sha256:7fddccd4113e7b736706e17a239a696332360cbaddf25ae75b57ba1acce65081 \
481
- --hash=sha256:956127e663d05edbeec54df38885d943dfa27406594c411139690485128525de \
482
- --hash=sha256:9f64bf06f4bf623325fda3a6d02d36cd69199b9ace99b04bb2d7fd9f89688504 \
483
- --hash=sha256:b0271ac12415afd3171ab9a3c7cbfc71dee2c68760a7dc9d05bf8ed6ddfa3a7a \
484
- --hash=sha256:b29044e1ffdb84fe164d0a7ea05c7316afea93c00f8ed9449cf357c36fc4f814 \
485
- --hash=sha256:bb0fdc451fb6d86d81ab8f23d881b8d6e37fc373a2deae1c02d27002d2ad7a05 \
486
- --hash=sha256:bdde97310d59604f2a9119322f61b31546748499a21b44f6715e8ced9308a6c5 \
487
- --hash=sha256:c3dca4cb5b946ee91b3d6bb700d137b1cd85c20827f89fdf9c16258253489044 \
488
- --hash=sha256:c903e71fd8debb35ad2a4184c1316b3cb22f64ce517b4e6747f25b0a34e41266 \
489
- --hash=sha256:ddc63328889bcaee77b743309e5c7d2d52cee0d7d577837c91b6e7cc9e755e0b \
490
- --hash=sha256:e651e17bfde5840e9e4174b01e9e080ce49277b70d424308b36a7969d0d1af73 \
491
- --hash=sha256:e79c00eba78f7258e5b354eccd4d7907d60317ced924ea4a5f2e9d83f5453065 \
492
- --hash=sha256:eed4bba7ff8a0d37106ba931ab03bdd3915fbb025bcf4e1f0aa02bc8114960c5 \
493
- --hash=sha256:fa0c966ee727aad5406d516375593c5f058c766b21236ab8985693934bb5085b \
494
- --hash=sha256:fc9c5f280438cf1c1a8f9abb87dc8ce9630a964120cfb5dd50d1e7ce79690c7a
495
- # via fastembed
496
- mpmath==1.3.0 \
497
- --hash=sha256:7a28eb2a9774d00c7bc92411c19a89209d5da7c4c9a9e227be8330a23a25b91f \
498
- --hash=sha256:a0b2b9fe80bbcd81a6647ff13108738cfb482d481d826cc0e02f5b35e5c88d2c
499
- # via sympy
500
- nodejs-wheel==24.13.0 \
501
- --hash=sha256:8c423cbf434b4c853ebac076d563b0899d3c6594ef0f99f6cd368ca4e3a28ca2 \
502
- --hash=sha256:c0fc56a4677f55f7639f306a6381fb253d11ce24189c87a5489ea848f6e2bf24
503
- # via poml
504
- nodejs-wheel-binaries==24.13.0 \
505
- --hash=sha256:2e3431d869d6b2dbeef1d469ad0090babbdcc8baaa72c01dd3cc2c6121c96af5 \
506
- --hash=sha256:356654baa37bfd894e447e7e00268db403ea1d223863963459a0fbcaaa1d9d48 \
507
- --hash=sha256:3f619ac140e039ecd25f2f71d6e83ad1414017a24608531851b7c31dc140cdfd \
508
- --hash=sha256:605be4763e3ef427a3385a55da5a1bcf0a659aa2716eebbf23f332926d7e5f23 \
509
- --hash=sha256:766aed076e900061b83d3e76ad48bfec32a035ef0d41bd09c55e832eb93ef7a4 \
510
- --hash=sha256:92fdef7376120e575f8b397789bafcb13bbd22a1b4d21b060d200b14910f22a5 \
511
- --hash=sha256:9ad6383613f3485a75b054647a09f1cd56d12380d7459184eebcf4a5d403f35c \
512
- --hash=sha256:dfb31ebc2c129538192ddb5bedd3d63d6de5d271437cd39ea26bf3fe229ba430 \
513
- --hash=sha256:fdd720d7b378d5bb9b2710457bbc880d4c4d1270a94f13fbe257198ac707f358
514
- # via nodejs-wheel
515
- numpy==2.4.1 \
516
- --hash=sha256:178de8f87948163d98a4c9ab5bee4ce6519ca918926ec8df195af582de28544d \
517
- --hash=sha256:20d4649c773f66cc2fc36f663e091f57c3b7655f936a4c681b4250855d1da8f5 \
518
- --hash=sha256:2302dc0224c1cbc49bb94f7064f3f923a971bfae45c33870dcbff63a2a550505 \
519
- --hash=sha256:382ad67d99ef49024f11d1ce5dcb5ad8432446e4246a4b014418ba3a1175a1f4 \
520
- --hash=sha256:3d1a100e48cb266090a031397863ff8a30050ceefd798f686ff92c67a486753d \
521
- --hash=sha256:49e792ec351315e16da54b543db06ca8a86985ab682602d90c60ef4ff4db2a9c \
522
- --hash=sha256:529050522e983e00a6c1c6b67411083630de8b57f65e853d7b03d9281b8694d2 \
523
- --hash=sha256:5b55aa56165b17aaf15520beb9cbd33c9039810e0d9643dd4379e44294c7303e \
524
- --hash=sha256:62fea415f83ad8fdb6c20840578e5fbaf5ddd65e0ec6c3c47eda0f69da172510 \
525
- --hash=sha256:71abbea030f2cfc3092a0ff9f8c8fdefdc5e0bf7d9d9c99663538bb0ecdac0b9 \
526
- --hash=sha256:79e9e06c4c2379db47f3f6fc7a8652e7498251789bf8ff5bd43bf478ef314ca2 \
527
- --hash=sha256:82c55962006156aeef1629b953fd359064aa47e4d82cfc8e67f0918f7da3344f \
528
- --hash=sha256:9171a42fcad32dcf3fa86f0a4faa5e9f8facefdb276f54b8b390d90447cff4e2 \
529
- --hash=sha256:92a0e65272fd60bfa0d9278e0484c2f52fe03b97aedc02b357f33fe752c52ffb \
530
- --hash=sha256:941c2a93313d030f219f3a71fd3d91a728b82979a5e8034eb2e60d394a2b83f9 \
531
- --hash=sha256:98b35775e03ab7f868908b524fc0a84d38932d8daf7b7e1c3c3a1b6c7a2c9f15 \
532
- --hash=sha256:a1ceafc5042451a858231588a104093474c6a5c57dcc724841f5c888d237d690 \
533
- --hash=sha256:a7870e8c5fc11aef57d6fea4b4085e537a3a60ad2cdd14322ed531fdca68d261 \
534
- --hash=sha256:c0faba4a331195bfa96f93dd9dfaa10b2c7aa8cda3a02b7fd635e588fe821bf5 \
535
- --hash=sha256:d3e3087f53e2b4428766b54932644d148613c5a595150533ae7f00dab2f319a8 \
536
- --hash=sha256:d797454e37570cfd61143b73b8debd623c3c0952959adb817dd310a483d58a1b \
537
- --hash=sha256:f93bc6892fe7b0663e5ffa83b61aab510aacffd58c16e012bb9352d489d90cb7
538
- # via
539
- # fastembed
540
- # gradio
541
- # onnxruntime
542
- # pandas
543
- # qdrant-client
544
- onnxruntime==1.23.2 \
545
- --hash=sha256:162f4ca894ec3de1a6fd53589e511e06ecdc3ff646849b62a9da7489dee9ce95 \
546
- --hash=sha256:1f9cc0a55349c584f083c1c076e611a7c35d5b867d5d6e6d6c823bf821978088 \
547
- --hash=sha256:2ff531ad8496281b4297f32b83b01cdd719617e2351ffe0dba5684fb283afa1f \
548
- --hash=sha256:45d127d6e1e9b99d1ebeae9bcd8f98617a812f53f46699eafeb976275744826b \
549
- --hash=sha256:8bace4e0d46480fbeeb7bbe1ffe1f080e6663a42d1086ff95c1551f2d39e7872 \
550
- --hash=sha256:9d2385e774f46ac38f02b3a91a91e30263d41b2f1f4f26ae34805b2a9ddef466 \
551
- --hash=sha256:e2b9233c4947907fd1818d0e581c049c41ccc39b2856cc942ff6d26317cee145
552
- # via fastembed
553
- openai==2.15.0 \
554
- --hash=sha256:42eb8cbb407d84770633f31bf727d4ffb4138711c670565a41663d9439174fba \
555
- --hash=sha256:6ae23b932cd7230f7244e52954daa6602716d6b9bf235401a107af731baea6c3
556
- # via mem0ai
557
- orjson==3.11.5 \
558
- --hash=sha256:2cc79aaad1dfabe1bd2d50ee09814a1253164b3da4c00a78c458d82d04b3bdef \
559
- --hash=sha256:3b01799262081a4c47c035dd77c1301d40f568f77cc7ec1bb7db5d63b0a01629 \
560
- --hash=sha256:4bdd8d164a871c4ec773f9de0f6fe8769c2d6727879c37a9666ba4183b7f8228 \
561
- --hash=sha256:54aae9b654554c3b4edd61896b978568c6daa16af96fa4681c9b5babd469f863 \
562
- --hash=sha256:59ac72ea775c88b163ba8d21b0177628bd015c5dd060647bbab6e22da3aad287 \
563
- --hash=sha256:61de247948108484779f57a9f406e4c84d636fa5a59e411e6352484985e8a7c3 \
564
- --hash=sha256:75bc2e59e6a2ac1dd28901d07115abdebc4563b5b07dd612bf64260a201b1c7f \
565
- --hash=sha256:7cce16ae2f5fb2c53c3eafdd1706cb7b6530a67cc1c17abe8ec747f5cd7c0c51 \
566
- --hash=sha256:82393ab47b4fe44ffd0a7659fa9cfaacc717eb617c93cde83795f14af5c2e9d5 \
567
- --hash=sha256:894aea2e63d4f24a7f04a1908307c738d0dce992e9249e744b8f4e8dd9197f39 \
568
- --hash=sha256:a261fef929bcf98a60713bf5e95ad067cea16ae345d9a35034e73c3990e927d2 \
569
- --hash=sha256:c028a394c766693c5c9909dec76b24f37e6a1b91999e8d0c0d5feecbe93c3e05 \
570
- --hash=sha256:d7345c759276b798ccd6d77a87136029e71e66a8bbf2d2755cbdde1d82e78706 \
571
- --hash=sha256:ddc21521598dbe369d83d4d40338e23d4101dad21dae0e79fa20465dbace019f \
572
- --hash=sha256:e46c762d9f0e1cfb4ccc8515de7f349abbc95b59cb5a2bd68df5973fdef913f8 \
573
- --hash=sha256:ff7877d376add4e16b274e35a3f58b7f37b362abf4aa31863dadacdd20e3a583
574
- # via gradio
575
- packaging==26.0 \
576
- --hash=sha256:00243ae351a257117b6a241061796684b084ed1c516a08c48a3f7e147a9d80b4 \
577
- --hash=sha256:b36f1fef9334a5588b4166f8bcd26a14e521f2b55e6b9de3aaa80d3ff7a37529
578
- # via
579
- # agno
580
- # gradio
581
- # gradio-client
582
- # huggingface-hub
583
- # onnxruntime
584
- pandas==2.3.3 \
585
- --hash=sha256:318d77e0e42a628c04dc56bcef4b40de67918f7041c2b061af1da41dcff670ac \
586
- --hash=sha256:4e0a175408804d566144e170d0476b15d78458795bb18f1304fb94160cabf40c \
587
- --hash=sha256:56851a737e3470de7fa88e6131f41281ed440d29a9268dcbf0002da5ac366713 \
588
- --hash=sha256:6435cb949cb34ec11cc9860246ccb2fdc9ecd742c12d3304989017d53f039a78 \
589
- --hash=sha256:74ecdf1d301e812db96a465a525952f4dde225fdb6d8e5a521d47e1f42041e21 \
590
- --hash=sha256:75ea25f9529fdec2d2e93a42c523962261e567d250b0013b16210e1d40d7c2e5 \
591
- --hash=sha256:900f47d8f20860de523a1ac881c4c36d65efcb2eb850e6948140fa781736e110 \
592
- --hash=sha256:93c2d9ab0fc11822b5eece72ec9587e172f63cff87c00b062f6e37448ced4493 \
593
- --hash=sha256:a45c765238e2ed7d7c608fc5bc4a6f88b642f2f01e70c0c23d2224dd21829d86 \
594
- --hash=sha256:bdcd9d1167f4885211e401b3036c0c8d9e274eee67ea8d0758a256d60704cfe8 \
595
- --hash=sha256:c4fc4c21971a1a9f4bdb4c73978c7f7256caa3e62b323f70d6cb80db583350bc \
596
- --hash=sha256:e05e1af93b977f7eafa636d043f9f94c7ee3ac81af99c13508215942e64c993b \
597
- --hash=sha256:e32e7cc9af0f1cc15548288a51a3b681cc2a219faa838e995f7dc53dbab1062d \
598
- --hash=sha256:f8bfc0e12dc78f777f323f55c58649591b2cd0c43534e8355c51d3fede5f4dee
599
- # via gradio
600
- pillow==11.3.0 \
601
- --hash=sha256:023f6d2d11784a465f09fd09a34b150ea4672e85fb3d05931d89f373ab14abb2 \
602
- --hash=sha256:05f6ecbeff5005399bb48d198f098a9b4b6bdf27b8487c7f38ca16eeb070cd59 \
603
- --hash=sha256:0bce5c4fd0921f99d2e858dc4d4d64193407e1b99478bc5cacecba2311abde51 \
604
- --hash=sha256:1019b04af07fc0163e2810167918cb5add8d74674b6267616021ab558dc98ced \
605
- --hash=sha256:13f87d581e71d9189ab21fe0efb5a23e9f28552d5be6979e84001d3b8505abe8 \
606
- --hash=sha256:1904e1264881f682f02b7f8167935cce37bc97db457f8e7849dc3a6a52b99580 \
607
- --hash=sha256:1c627742b539bba4309df89171356fcb3cc5a9178355b2727d1b74a6cf155fbd \
608
- --hash=sha256:1f85acb69adf2aaee8b7da124efebbdb959a104db34d3a2cb0f3793dbae422a8 \
609
- --hash=sha256:2a3117c06b8fb646639dce83694f2f9eac405472713fcb1ae887469c0d4f6788 \
610
- --hash=sha256:2d6fcc902a24ac74495df63faad1884282239265c6839a0a6416d33faedfae7e \
611
- --hash=sha256:30b7c02f3899d10f13d7a48163c8969e4e653f8b43416d23d13d1bbfdc93b9f8 \
612
- --hash=sha256:3828ee7586cd0b2091b6209e5ad53e20d0649bbe87164a459d0676e035e8f523 \
613
- --hash=sha256:45dfc51ac5975b938e9809451c51734124e73b04d0f0ac621649821a63852e7b \
614
- --hash=sha256:4c834a3921375c48ee6b9624061076bc0a32a60b5532b322cc0ea64e639dd50e \
615
- --hash=sha256:5e05688ccef30ea69b9317a9ead994b93975104a677a36a8ed8106be9260aa6d \
616
- --hash=sha256:7859a4cc7c9295f5838015d8cc0a9c215b77e43d07a25e460f35cf516df8626f \
617
- --hash=sha256:7db51d222548ccfd274e4572fdbf3e810a5e66b00608862f947b163e613b67dd \
618
- --hash=sha256:83e1b0161c9d148125083a35c1c5a89db5b7054834fd4387499e06552035236c \
619
- --hash=sha256:857844335c95bea93fb39e0fa2726b4d9d758850b34075a7e3ff4f4fa3aa3b31 \
620
- --hash=sha256:8797edc41f3e8536ae4b10897ee2f637235c94f27404cac7297f7b607dd0716e \
621
- --hash=sha256:a4d336baed65d50d37b88ca5b60c0fa9d81e3a87d4a7930d3880d1624d5b31f3 \
622
- --hash=sha256:a7bc6e6fd0395bc052f16b1a8670859964dbd7003bd0af2ff08342eb6e442cfe \
623
- --hash=sha256:c37d8ba9411d6003bba9e518db0db0c58a680ab9fe5179f040b0463644bc9805 \
624
- --hash=sha256:ec1ee50470b0d050984394423d96325b744d55c701a439d2bd66089bff963d3c \
625
- --hash=sha256:f0f5d8f4a08090c6d6d578351a2b91acf519a54986c055af27e7a93feae6d3f1 \
626
- --hash=sha256:f944255db153ebb2b19c51fe85dd99ef0ce494123f21b9db4877ffdfc5590c7c
627
- # via
628
- # fastembed
629
- # gradio
630
- poml==0.0.8 \
631
- --hash=sha256:37be5da8572222854464969f76fac2e356297305c84fdcc7d3103d914811932b \
632
- --hash=sha256:48a7880bc8d684231e78f11fb85cd78ce7a9b4121b9376f338f6589b5fccee98 \
633
- --hash=sha256:a0a53edc7615156d6841adbd401831520573dc8393dea9fa6971af09bc864f16 \
634
- --hash=sha256:e826586b9f623c4a4e3fd9457ad23a538adc917f16519d4ecdebab9ced3086aa \
635
- --hash=sha256:f15c2d2e512b3ad699f22df289e7d834b6e85c804905f1431aaa98c223e1560e
636
- # via chattr
637
- portalocker==3.2.0 \
638
- --hash=sha256:1f3002956a54a8c3730586c5c77bf18fae4149e07eaf1c29fc3faf4d5a3f89ac \
639
- --hash=sha256:3cdc5f565312224bc570c49337bd21428bba0ef363bbcf58b9ef4a9f11779968
640
- # via qdrant-client
641
- posthog==7.6.0 \
642
- --hash=sha256:941dfd278ee427c9b14640f09b35b5bb52a71bdf028d7dbb7307e1838fd3002e \
643
- --hash=sha256:c4dd78cf77c4fecceb965f86066e5ac37886ef867d68ffe75a1db5d681d7d9ad
644
- # via mem0ai
645
- primp==0.15.0 \
646
- --hash=sha256:1af8ea4b15f57571ff7fc5e282a82c5eb69bc695e19b8ddeeda324397965b30a \
647
- --hash=sha256:1b281f4ca41a0c6612d4c6e68b96e28acfe786d226a427cd944baa8d7acd644f \
648
- --hash=sha256:489cbab55cd793ceb8f90bb7423c6ea64ebb53208ffcf7a044138e3c66d77299 \
649
- --hash=sha256:592f6079646bdf5abbbfc3b0a28dac8de943f8907a250ce09398cda5eaebd260 \
650
- --hash=sha256:5a728e5a05f37db6189eb413d22c78bd143fa59dd6a8a26dacd43332b3971fe8 \
651
- --hash=sha256:6b84a6ffa083e34668ff0037221d399c24d939b5629cd38223af860de9e17a83 \
652
- --hash=sha256:aeb6bd20b06dfc92cfe4436939c18de88a58c640752cf7f30d9e4ae893cdec32 \
653
- --hash=sha256:c18b45c23f94016215f62d2334552224236217aaeb716871ce0e4dcfa08eb161 \
654
- --hash=sha256:e985a9cba2e3f96a323722e5440aa9eccaac3178e74b884778e926b5249df080
655
- # via ddgs
656
- protobuf==5.29.5 \
657
- --hash=sha256:3f1c6468a2cfd102ff4703976138844f78ebd1fb45f49011afc5139e9e283079 \
658
- --hash=sha256:3f76e3a3675b4a4d867b52e4a5f5b78a2ef9565549d4037e06cf7b0942b1d3fc \
659
- --hash=sha256:63848923da3325e1bf7e9003d680ce6e14b07e55d0473253a690c3a8b8fd6e61 \
660
- --hash=sha256:6cf42630262c59b2d8de33954443d94b746c952b01434fc58a417fdbd2e84bd5 \
661
- --hash=sha256:bc1463bafd4b0929216c35f437a8e28731a2b7fe3d98bb77a600efced5a15c84 \
662
- --hash=sha256:e38c5add5a311f2a6eb0340716ef9b039c1dfa428b28f25a7838ac329204a671 \
663
- --hash=sha256:fa18533a299d7ab6c55a238bf8629311439995f2e7eca5caaff08663606e9015
664
- # via
665
- # mem0ai
666
- # onnxruntime
667
- # qdrant-client
668
- py-rust-stemmers==0.1.5 \
669
- --hash=sha256:191ea8bf922c984631ffa20bf02ef0ad7eec0465baeaed3852779e8f97c7e7a3 \
670
- --hash=sha256:1f9efc4da5e734bdd00612e7506de3d0c9b7abc4b89d192742a0569d0d1fe749 \
671
- --hash=sha256:35d32f6e7bdf6fd90e981765e32293a8be74def807147dea9fdc1f65d6ce382f \
672
- --hash=sha256:398b3a843a9cd4c5d09e726246bc36f66b3d05b0a937996814e91f47708f5db5 \
673
- --hash=sha256:4e308fc7687901f0c73603203869908f3156fa9c17c4ba010a7fcc98a7a1c5f2 \
674
- --hash=sha256:5845709d48afc8b29e248f42f92431155a3d8df9ba30418301c49c6072b181b0 \
675
- --hash=sha256:a231dc6f0b2a5f12a080dfc7abd9e6a4ea0909290b10fd0a4620e5a0f52c3d17 \
676
- --hash=sha256:cc2cc8d2b36bc05b8b06506199ac63d437360ae38caefd98cd19e479d35afd42 \
677
- --hash=sha256:e48bfd5e3ce9d223bfb9e634dc1425cf93ee57eef6f56aa9a7120ada3990d4be \
678
- --hash=sha256:e564c9efdbe7621704e222b53bac265b0e4fbea788f07c814094f0ec6b80adcf \
679
- --hash=sha256:e9c310cfb5c2470d7c7c8a0484725965e7cab8b1237e106a0863d5741da3e1f7
680
- # via fastembed
681
- pyasn1==0.6.2 \
682
- --hash=sha256:1eb26d860996a18e9b6ed05e7aae0e9fc21619fcee6af91cca9bad4fbea224bf \
683
- --hash=sha256:9b59a2b25ba7e4f8197db7686c09fb33e658b98339fadb826e9512629017833b
684
- # via
685
- # pyasn1-modules
686
- # rsa
687
- pyasn1-modules==0.4.2 \
688
- --hash=sha256:29253a9207ce32b64c3ac6600edc75368f98473906e8fd1043bd6b5b1de2c14a \
689
- --hash=sha256:677091de870a80aae844b1ca6134f54652fa2c8c5a52aa396440ac3106e941e6
690
- # via google-auth
691
- pycparser==3.0 ; implementation_name != 'PyPy' \
692
- --hash=sha256:600f49d217304a5902ac3c37e1281c9fe94e4d0489de643a9504c5cdfdfc6b29 \
693
- --hash=sha256:b727414169a36b7d524c1c3e31839a521725078d7b2ff038656844266160a992
694
- # via cffi
695
- pydantic==2.12.5 \
696
- --hash=sha256:4d351024c75c0f085a9febbb665ce8c0c6ec5d30e903bdb6394b7ede26aebb49 \
697
- --hash=sha256:e561593fccf61e8a20fc46dfc2dfe075b8be7d0188df33f221ad1f0139180f9d
698
- # via
699
- # agno
700
- # fastapi
701
- # google-genai
702
- # gradio
703
- # mcp
704
- # mem0ai
705
- # openai
706
- # poml
707
- # pydantic-settings
708
- # qdrant-client
709
- pydantic-core==2.41.5 \
710
- --hash=sha256:01a3d0ab748ee531f4ea6c3e48ad9dac84ddba4b0d82291f87248f2f9de8d740 \
711
- --hash=sha256:03ca43e12fab6023fc79d28ca6b39b05f794ad08ec2feccc59a339b02f2b3d33 \
712
- --hash=sha256:08daa51ea16ad373ffd5e7606252cc32f07bc72b28284b6bc9c6df804816476e \
713
- --hash=sha256:0cbaad15cb0c90aa221d43c00e77bb33c93e8d36e0bf74760cd00e732d10a6a0 \
714
- --hash=sha256:112e305c3314f40c93998e567879e887a3160bb8689ef3d2c04b6cc62c33ac34 \
715
- --hash=sha256:3f84d5c1b4ab906093bdc1ff10484838aca54ef08de4afa9de0f5f14d69639cd \
716
- --hash=sha256:406bf18d345822d6c21366031003612b9c77b3e29ffdb0f612367352aab7d586 \
717
- --hash=sha256:650ae77860b45cfa6e2cdafc42618ceafab3a2d9a3811fcfbd3bbf8ac3c40d36 \
718
- --hash=sha256:6561e94ba9dacc9c61bce40e2d6bdc3bfaa0259d3ff36ace3b1e6901936d2e3e \
719
- --hash=sha256:79ec52ec461e99e13791ec6508c722742ad745571f234ea6255bed38c6480f11 \
720
- --hash=sha256:915c3d10f81bec3a74fbd4faebe8391013ba61e5a1a8d48c4455b923bdda7858 \
721
- --hash=sha256:941103c9be18ac8daf7b7adca8228f8ed6bb7a1849020f643b3a14d15b1924d9 \
722
- --hash=sha256:97aeba56665b4c3235a0e52b2c2f5ae9cd071b8a8310ad27bddb3f7fb30e9aa2 \
723
- --hash=sha256:b93590ae81f7010dbe380cdeab6f515902ebcbefe0b9327cc4804d74e93ae69d \
724
- --hash=sha256:dc799088c08fa04e43144b164feb0c13f9a0bc40503f8df3e9fde58a3c0c101e
725
- # via pydantic
726
- pydantic-settings==2.12.0 \
727
- --hash=sha256:005538ef951e3c2a68e1c08b292b5f2e71490def8589d4221b95dab00dafcfd0 \
728
- --hash=sha256:fddb9fd99a5b18da837b29710391e945b1e30c135477f484084ee513adb93809
729
- # via
730
- # agno
731
- # mcp
732
- pydub==0.25.1 \
733
- --hash=sha256:65617e33033874b59d87db603aa1ed450633288aefead953b30bded59cb599a6 \
734
- --hash=sha256:980a33ce9949cab2a569606b65674d748ecbca4f0796887fd6f46173a7b0d30f
735
- # via gradio
736
- pygments==2.19.2 \
737
- --hash=sha256:636cb2477cec7f8952536970bc533bc43743542f70392ae026374600add5b887 \
738
- --hash=sha256:86540386c03d588bb81d44bc3928634ff26449851e99741617ecb9037ee5ec0b
739
- # via rich
740
- pyjwt==2.10.1 \
741
- --hash=sha256:3cc5772eb20009233caf06e9d8a0577824723b44e6648ee0a2aedb6cf9381953 \
742
- --hash=sha256:dcdd193e30abefd5debf142f9adfcdd2b58004e644f25406ffaebd50bd98dacb
743
- # via mcp
744
- pyreadline3==3.5.4 ; sys_platform == 'win32' \
745
- --hash=sha256:8d57d53039a1c75adba8e50dd3d992b28143480816187ea5efbd5c78e6c885b7 \
746
- --hash=sha256:eaf8e6cc3c49bcccf145fc6067ba8643d1df34d604a1ec0eccbf7a18e6d3fae6
747
- # via humanfriendly
748
- python-dateutil==2.9.0.post0 \
749
- --hash=sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3 \
750
- --hash=sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427
751
- # via
752
- # pandas
753
- # posthog
754
- python-dotenv==1.2.1 \
755
- --hash=sha256:42667e897e16ab0d66954af0e60a9caa94f0fd4ecf3aaf6d2d260eec1aa36ad6 \
756
- --hash=sha256:b81ee9561e9ca4004139c6cbba3a238c32b03e4894671e181b671e8cb8425d61
757
- # via
758
- # agno
759
- # pydantic-settings
760
- python-multipart==0.0.22 \
761
- --hash=sha256:2b2cd894c83d21bf49d702499531c7bafd057d730c201782048f7945d82de155 \
762
- --hash=sha256:7340bef99a7e0032613f56dc36027b959fd3b30a787ed62d310e951f7c3a3a58
763
- # via
764
- # agno
765
- # gradio
766
- # mcp
767
- pytz==2025.2 \
768
- --hash=sha256:360b9e3dbb49a209c21ad61809c7fb453643e048b38924c765813546746e81c3 \
769
- --hash=sha256:5ddf76296dd8c44c26eb8f4b6f35488f3ccbf6fbbd7adee0b7262d43f0ec2f00
770
- # via
771
- # gradio
772
- # mem0ai
773
- # pandas
774
- pywin32==311 ; sys_platform == 'win32' \
775
- --hash=sha256:718a38f7e5b058e76aee1c56ddd06908116d35147e133427e59a3983f703a20d \
776
- --hash=sha256:7b4075d959648406202d92a2310cb990fea19b535c7f4a78d3f5e10b926eeb8a \
777
- --hash=sha256:f95ba5a847cba10dd8c4d8fefa9f2a6cf283b8b88ed6178fa8a6c1ab16054d0d
778
- # via
779
- # mcp
780
- # portalocker
781
- pyyaml==6.0.3 \
782
- --hash=sha256:0f29edc409a6392443abf94b9cf89ce99889a1dd5376d94316ae5145dfedd5d6 \
783
- --hash=sha256:2283a07e2c21a2aa78d9c4442724ec1eb15f5e42a723b99cb3d822d48f5f7ad1 \
784
- --hash=sha256:5498cd1645aa724a7c71c8f378eb29ebe23da2fc0d7a08071d89469bf1d2defb \
785
- --hash=sha256:79005a0d97d5ddabfeeea4cf676af11e647e41d81c9a7722a193022accdb6b7c \
786
- --hash=sha256:8da9669d359f02c0b91ccc01cac4a67f16afec0dac22c2ad09f46bee0697eba8 \
787
- --hash=sha256:a33284e20b78bd4a18c8c2282d549d10bc8408a2a7ff57653c0cf0b9be0afce5 \
788
- --hash=sha256:d0eae10f8159e8fdad514efdc92d74fd8d682c933a6dd088030f3834bc8e6b26 \
789
- --hash=sha256:d76623373421df22fb4cf8817020cbb7ef15c725b9d5e45f17e189bfc384190f \
790
- --hash=sha256:eda16858a3cab07b80edaf74336ece1f986ba330fdb8ee0d6c0d68fe82bc96be \
791
- --hash=sha256:ee2922902c45ae8ccada2c5b501ab86c36525b883eff4255313a253a3160861c \
792
- --hash=sha256:f7057c9a337546edc7973c0d3ba84ddcdf0daa14533c2065749c9075001090e6
793
- # via
794
- # agno
795
- # gradio
796
- # huggingface-hub
797
- qdrant-client==1.16.2 \
798
- --hash=sha256:442c7ef32ae0f005e88b5d3c0783c63d4912b97ae756eb5e052523be682f17d3 \
799
- --hash=sha256:ca4ef5f9be7b5eadeec89a085d96d5c723585a391eb8b2be8192919ab63185f0
800
- # via
801
- # agno
802
- # mem0ai
803
- referencing==0.37.0 \
804
- --hash=sha256:381329a9f99628c9069361716891d34ad94af76e461dcb0335825aecc7692231 \
805
- --hash=sha256:44aefc3142c5b842538163acb373e24cce6632bd54bdb01b21ad5863489f50d8
806
- # via
807
- # jsonschema
808
- # jsonschema-specifications
809
- requests==2.32.5 \
810
- --hash=sha256:2462f94637a34fd532264295e186976db0f5d453d1cdd31473c85a6a161affb6 \
811
- --hash=sha256:dbba0bac56e100853db0ea71b82b4dfd5fe2bf6d3754a8893c3af500cec7d7cf
812
- # via
813
- # fastembed
814
- # google-auth
815
- # google-genai
816
- # posthog
817
- rich==14.3.1 \
818
- --hash=sha256:b8c5f568a3a749f9290ec6bddedf835cec33696bfc1e48bcfecb276c7386e4b8 \
819
- --hash=sha256:da750b1aebbff0b372557426fb3f35ba56de8ef954b3190315eb64076d6fb54e
820
- # via
821
- # agno
822
- # chattr
823
- # typer
824
- rpds-py==0.30.0 \
825
- --hash=sha256:0a59119fc6e3f460315fe9d08149f8102aa322299deaa5cab5b40092345c2136 \
826
- --hash=sha256:1f3587eb9b17f3789ad50824084fa6f81921bbf9a795826570bda82cb3ed91f2 \
827
- --hash=sha256:2771c6c15973347f50fece41fc447c054b7ac2ae0502388ce3b6738cd366e3d4 \
828
- --hash=sha256:39c02563fc592411c2c61d26b6c5fe1e51eaa44a75aa2c8735ca88b0d9599daa \
829
- --hash=sha256:3d4a69de7a3e50ffc214ae16d79d8fbb0922972da0356dcf4d0fdca2878559c6 \
830
- --hash=sha256:47f9a91efc418b54fb8190a6b4aa7813a23fb79c51f4bb84e418f5476c38b8db \
831
- --hash=sha256:4c5f36a861bc4b7da6516dbdf302c55313afa09b81931e8280361a4f6c9a2d27 \
832
- --hash=sha256:51a1234d8febafdfd33a42d97da7a43f5dcb120c1060e352a3fbc0c6d36e2083 \
833
- --hash=sha256:5d4c2aa7c50ad4728a094ebd5eb46c452e9cb7edbfdb18f9e1221f597a73e1e7 \
834
- --hash=sha256:61046904275472a76c8c90c9ccee9013d70a6d0f73eecefd38c1ae7c39045a08 \
835
- --hash=sha256:692bef75a5525db97318e8cd061542b5a79812d711ea03dbc1f6f8dbb0c5f0d2 \
836
- --hash=sha256:6bdfdb946967d816e6adf9a3d8201bfad269c67efe6cefd7093ef959683c8de0 \
837
- --hash=sha256:76fec018282b4ead0364022e3c54b60bf368b9d926877957a8624b58419169b7 \
838
- --hash=sha256:806f36b1b605e2d6a72716f321f20036b9489d29c51c91f4dd29a3e3afb73b15 \
839
- --hash=sha256:9027da1ce107104c50c81383cae773ef5c24d296dd11c99e2629dbd7967a20c6 \
840
- --hash=sha256:922e10f31f303c7c920da8981051ff6d8c1a56207dbdf330d9047f6d30b70e5e \
841
- --hash=sha256:945dccface01af02675628334f7cf49c2af4c1c904748efc5cf7bbdf0b579f95 \
842
- --hash=sha256:9cf69cdda1f5968a30a359aba2f7f9aa648a9ce4b580d6826437f2b291cfc86e \
843
- --hash=sha256:a4796a717bf12b9da9d3ad002519a86063dcac8988b030e405704ef7d74d2d9d \
844
- --hash=sha256:b40fb160a2db369a194cb27943582b38f79fc4887291417685f3ad693c5a1d5d \
845
- --hash=sha256:ba81a9203d07805435eb06f536d95a266c21e5b2dfbf6517748ca40c98d19e31 \
846
- --hash=sha256:c77afbd5f5250bf27bf516c7c4a016813eb2d3e116139aed0096940c5982da94 \
847
- --hash=sha256:cdc62c8286ba9bf7f47befdcea13ea0e26bf294bda99758fd90535cbaf408000 \
848
- --hash=sha256:d96c2086587c7c30d44f31f42eae4eac89b60dabbac18c7669be3700f13c3ce1 \
849
- --hash=sha256:dd8ff7cf90014af0c0f787eea34794ebf6415242ee1d6fa91eaba725cc441e84 \
850
- --hash=sha256:e7536cd91353c5273434b4e003cbda89034d67e7710eab8761fd918ec6c69cf8 \
851
- --hash=sha256:eb0b93f2e5c2189ee831ee43f156ed34e2a89a78a66b98cadad955972548be5a \
852
- --hash=sha256:eb2c4071ab598733724c08221091e8d80e89064cd472819285a9ab0f24bcedb9 \
853
- --hash=sha256:f14fc5df50a716f7ece6a80b6c78bb35ea2ca47c499e422aa4463455dd96d56d \
854
- --hash=sha256:f83424d738204d9770830d35290ff3273fbb02b41f919870479fab14b9d303b2
855
- # via
856
- # jsonschema
857
- # referencing
858
- rsa==4.9.1 \
859
- --hash=sha256:68635866661c6836b8d39430f97a996acbd61bfa49406748ea243539fe239762 \
860
- --hash=sha256:e7bdbfdb5497da4c07dfd35530e1a902659db6ff241e39d9953cad06ebd0ae75
861
- # via google-auth
862
- safehttpx==0.1.7 \
863
- --hash=sha256:c4f4a162db6993464d7ca3d7cc4af0ffc6515a606dfd220b9f82c6945d869cde \
864
- --hash=sha256:db201c0978c41eddb8bb480f3eee59dd67304fdd91646035e9d9a720049a9d23
865
- # via gradio
866
- semantic-version==2.10.0 \
867
- --hash=sha256:bdabb6d336998cbb378d4b9db3a4b56a1e3235701dc05ea2690d9a997ed5041c \
868
- --hash=sha256:de78a3b8e0feda74cabc54aab2da702113e33ac9d9eb9d2389bcf1f58b7d9177
869
- # via gradio
870
- shellingham==1.5.4 \
871
- --hash=sha256:7ecfff8f2fd72616f7481040475a65b2bf8af90a56c89140852d1120324e8686 \
872
- --hash=sha256:8dbca0739d487e5bd35ab3ca4b36e11c4078f3a234bfce294b0a0291363404de
873
- # via
874
- # huggingface-hub
875
- # typer
876
- six==1.17.0 \
877
- --hash=sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274 \
878
- --hash=sha256:ff70335d468e7eb6ec65b95b99d3a2836546063f63acc5171de367e834932a81
879
- # via
880
- # posthog
881
- # python-dateutil
882
- smmap==5.0.2 \
883
- --hash=sha256:26ea65a03958fa0c8a1c7e8c7a58fdc77221b8910f6be2131affade476898ad5 \
884
- --hash=sha256:b30115f0def7d7531d22a0fb6502488d879e75b260a9db4d0819cfb25403af5e
885
- # via gitdb
886
- sniffio==1.3.1 \
887
- --hash=sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2 \
888
- --hash=sha256:f4324edc670a0f49750a81b895f35c3adb843cca46f0530f79fc1babb23789dc
889
- # via
890
- # google-genai
891
- # openai
892
- socksio==1.0.0 \
893
- --hash=sha256:95dc1f15f9b34e8d7b16f06d74b8ccf48f609af32ab33c608d08761c5dcbb1f3 \
894
- --hash=sha256:f88beb3da5b5c38b9890469de67d0cb0f9d494b78b106ca1845f96c10b91c4ac
895
- # via httpx
896
- sqlalchemy==2.0.46 \
897
- --hash=sha256:64901e08c33462acc9ec3bad27fc7a5c2b6491665f2aa57564e57a4f5d7c52ad \
898
- --hash=sha256:77f8071d8fbcbb2dd11b7fd40dedd04e8ebe2eb80497916efedba844298065ef \
899
- --hash=sha256:8d3b44b3d0ab2f1319d71d9863d76eeb46766f8cf9e921ac293511804d39813f \
900
- --hash=sha256:8d679b5f318423eacb61f933a9a0f75535bfca7056daeadbf6bd5bcee6183aee \
901
- --hash=sha256:93a12da97cca70cea10d4b4fc602589c4511f96c1f8f6c11817620c021d21d00 \
902
- --hash=sha256:96c7cca1a4babaaf3bfff3e4e606e38578856917e52f0384635a95b226c87764 \
903
- --hash=sha256:a1e8cc6cc01da346dc92d9509a63033b9b1bda4fed7a7a7807ed385c7dccdc10 \
904
- --hash=sha256:af865c18752d416798dae13f83f38927c52f085c52e2f32b8ab0fef46fdd02c2 \
905
- --hash=sha256:b2a9f9aee38039cf4755891a1e50e1effcc42ea6ba053743f452c372c3152b1b \
906
- --hash=sha256:cf36851ee7219c170bb0793dbc3da3e80c582e04a5437bc601bfe8c85c9216d7 \
907
- --hash=sha256:db23b1bf8cfe1f7fda19018e7207b20cdb5168f83c437ff7e95d19e39289c447 \
908
- --hash=sha256:e8ac45e8f4eaac0f9f8043ea0e224158855c6a4329fd4ee37c45c61e3beb518e \
909
- --hash=sha256:f9c11766e7e7c0a2767dda5acb006a118640c9fc0a4104214b96269bfb78399e
910
- # via mem0ai
911
- sse-starlette==3.2.0 \
912
- --hash=sha256:5876954bd51920fc2cd51baee47a080eb88a37b5b784e615abb0b283f801cdbf \
913
- --hash=sha256:8127594edfb51abe44eac9c49e59b0b01f1039d0c7461c6fd91d4e03b70da422
914
- # via mcp
915
- starlette==0.50.0 \
916
- --hash=sha256:9e5391843ec9b6e472eed1365a78c8098cfceb7a74bfd4d6b1c0c0095efb3bca \
917
- --hash=sha256:a2a17b22203254bcbc2e1f926d2d55f3f9497f769416b3190768befe598fa3ca
918
- # via
919
- # fastapi
920
- # gradio
921
- # mcp
922
- # sse-starlette
923
- sympy==1.14.0 \
924
- --hash=sha256:d3d3fe8df1e5a0b42f0e7bdf50541697dbe7d23746e894990c030e2b05e72517 \
925
- --hash=sha256:e091cc3e99d2141a0ba2847328f5479b05d94a6635cb96148ccb3f34671bd8f5
926
- # via onnxruntime
927
- tenacity==9.1.2 \
928
- --hash=sha256:1169d376c297e7de388d18b4481760d478b0e99a777cad3a9c86e556f4b697cb \
929
- --hash=sha256:f77bf36710d8b73a50b2dd155c97b870017ad21afe6ab300326b0371b3b05138
930
- # via google-genai
931
- tokenizers==0.22.2 \
932
- --hash=sha256:1c774b1276f71e1ef716e5486f21e76333464f47bece56bbd554485982a9e03e \
933
- --hash=sha256:1e418a55456beedca4621dbab65a318981467a2b188e982a23e117f115ce5001 \
934
- --hash=sha256:2249487018adec45d6e3554c71d46eb39fa8ea67156c640f7513eb26f318cec7 \
935
- --hash=sha256:25b85325d0815e86e0bac263506dd114578953b7b53d7de09a6485e4a160a7dd \
936
- --hash=sha256:29c30b83d8dcd061078b05ae0cb94d3c710555fbb44861139f9f83dcca3dc3e4 \
937
- --hash=sha256:369cc9fc8cc10cb24143873a0d95438bb8ee257bb80c71989e3ee290e8d72c67 \
938
- --hash=sha256:37ae80a28c1d3265bb1f22464c856bd23c02a05bb211e56d0c5301a435be6c1a \
939
- --hash=sha256:38337540fbbddff8e999d59970f3c6f35a82de10053206a7562f1ea02d046fa5 \
940
- --hash=sha256:473b83b915e547aa366d1eee11806deaf419e17be16310ac0a14077f1e28f917 \
941
- --hash=sha256:544dd704ae7238755d790de45ba8da072e9af3eea688f698b137915ae959281c \
942
- --hash=sha256:791135ee325f2336f498590eb2f11dc5c295232f288e75c99a36c5dbce63088a \
943
- --hash=sha256:9ce725d22864a1e965217204946f830c37876eee3b2ba6fc6255e8e903d5fcbc \
944
- --hash=sha256:a6bf3f88c554a2b653af81f3204491c818ae2ac6fbc09e76ef4773351292bc92 \
945
- --hash=sha256:bfb88f22a209ff7b40a576d5324bf8286b519d7358663db21d6246fb17eea2d5 \
946
- --hash=sha256:c9ea31edff2968b44a88f97d784c2f16dc0729b8b143ed004699ebca91f05c48 \
947
- --hash=sha256:df6c4265b289083bf710dff49bc51ef252f9d5be33a45ee2bed151114a56207b
948
- # via fastembed
949
- tomlkit==0.13.3 \
950
- --hash=sha256:430cf247ee57df2b94ee3fbe588e71d362a941ebb545dec29b53961d61add2a1 \
951
- --hash=sha256:c89c649d79ee40629a9fda55f8ace8c6a1b42deb912b2a8fd8d942ddadb606b0
952
- # via gradio
953
- tqdm==4.67.1 \
954
- --hash=sha256:26445eca388f82e72884e0d580d5464cd801a3ea01e63e5601bdff9ba6a48de2 \
955
- --hash=sha256:f8aef9c52c08c13a65f30ea34f4e5aac3fd1a34959879d7e59e63027286627f2
956
- # via
957
- # fastembed
958
- # huggingface-hub
959
- # openai
960
- typer==0.21.1 \
961
- --hash=sha256:7985e89081c636b88d172c2ee0cfe33c253160994d47bdfdc302defd7d1f1d01 \
962
- --hash=sha256:ea835607cd752343b6b2b7ce676893e5a0324082268b48f27aa058bdb7d2145d
963
- # via
964
- # agno
965
- # gradio
966
- typer-slim==0.21.1 \
967
- --hash=sha256:6e6c31047f171ac93cc5a973c9e617dbc5ab2bddc4d0a3135dc161b4e2020e0d \
968
- --hash=sha256:73495dd08c2d0940d611c5a8c04e91c2a0a98600cbd4ee19192255a233b6dbfd
969
- # via huggingface-hub
970
- typing-extensions==4.15.0 \
971
- --hash=sha256:0cea48d173cc12fa28ecabc3b837ea3cf6f38c6d1136f85cbaaf598984861466 \
972
- --hash=sha256:f0fa19c6845758ab08074a0cfa8b7aecb71c999ca73d62883bc25cc018c4e548
973
- # via
974
- # agno
975
- # fastapi
976
- # google-genai
977
- # gradio
978
- # gradio-client
979
- # grpcio
980
- # huggingface-hub
981
- # mcp
982
- # openai
983
- # posthog
984
- # pydantic
985
- # pydantic-core
986
- # sqlalchemy
987
- # typer
988
- # typer-slim
989
- # typing-inspection
990
- typing-inspection==0.4.2 \
991
- --hash=sha256:4ed1cacbdc298c220f1bd249ed5287caa16f34d44ef4e9c3d0cbad5b521545e7 \
992
- --hash=sha256:ba561c48a67c5958007083d386c3295464928b01faa735ab8547c5692e87f464
993
- # via
994
- # mcp
995
- # pydantic
996
- # pydantic-settings
997
- tzdata==2025.3 \
998
- --hash=sha256:06a47e5700f3081aab02b2e513160914ff0694bce9947d6b76ebd6bf57cfc5d1 \
999
- --hash=sha256:de39c2ca5dc7b0344f2eba86f49d614019d29f060fc4ebc8a417896a620b56a7
1000
- # via pandas
1001
- urllib3==2.6.3 \
1002
- --hash=sha256:1b62b6884944a57dbe321509ab94fd4d3b307075e0c2eae991ac71ee15ad38ed \
1003
- --hash=sha256:bf272323e553dfb2e87d9bfd225ca7b0f467b919d7bbd355436d3fd37cb0acd4
1004
- # via
1005
- # qdrant-client
1006
- # requests
1007
- uvicorn==0.40.0 \
1008
- --hash=sha256:839676675e87e73694518b5574fd0f24c9d97b46bea16df7b8c05ea1a51071ea \
1009
- --hash=sha256:c6c8f55bc8bf13eb6fa9ff87ad62308bbbc33d0b67f84293151efe87e0d5f2ee
1010
- # via
1011
- # gradio
1012
- # mcp
1013
- websockets==15.0.1 \
1014
- --hash=sha256:0f3c1e2ab208db911594ae5b4f79addeb3501604a165019dd221c0bdcabe4db8 \
1015
- --hash=sha256:229cf1d3ca6c1804400b0a9790dc66528e08a6a1feec0d5040e8b9eb14422375 \
1016
- --hash=sha256:3c714d2fc58b5ca3e285461a4cc0c9a66bd0e24c5da9911e30158286c9b5be7f \
1017
- --hash=sha256:558d023b3df0bffe50a04e710bc87742de35060580a293c2a984299ed83bc4e4 \
1018
- --hash=sha256:595b6c3969023ecf9041b2936ac3827e4623bfa3ccf007575f04c5a6aa318c22 \
1019
- --hash=sha256:5a939de6b7b4e18ca683218320fc67ea886038265fd1ed30173f5ce3f8e85675 \
1020
- --hash=sha256:746ee8dba912cd6fc889a8147168991d50ed70447bf18bcda7039f7d2e3d9151 \
1021
- --hash=sha256:756c56e867a90fb00177d530dca4b097dd753cde348448a1012ed6c5131f8b7d \
1022
- --hash=sha256:82544de02076bafba038ce055ee6412d68da13ab47f0c60cab827346de828dee \
1023
- --hash=sha256:ba9e56e8ceeeedb2e080147ba85ffcd5cd0711b89576b83784d8605a7df455fa \
1024
- --hash=sha256:e09473f095a819042ecb2ab9465aee615bd9c2028e4ef7d933600a8401c79561 \
1025
- --hash=sha256:ee443ef070bb3b6ed74514f5efaa37a252af57c90eb33b956d35c8e9c10a1931 \
1026
- --hash=sha256:f7a866fbc1e97b5c617ee4116daaa09b722101d4a3c170c787450ba409f9736f
1027
- # via google-genai
1028
- win32-setctime==1.2.0 ; sys_platform == 'win32' \
1029
- --hash=sha256:95d644c4e708aba81dc3704a116d8cbc974d70b3bdb8be1d150e36be6e9d1390 \
1030
- --hash=sha256:ae1fdf948f5640aae05c511ade119313fb6a30d7eabe25fef9764dca5873c4c0
1031
- # via loguru
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
src/chattr/__init__.py CHANGED
@@ -1,8 +1,5 @@
1
- from warnings import filterwarnings
2
 
3
- from rich.console import Console
4
 
5
  filterwarnings("ignore", category=DeprecationWarning)
6
-
7
- console = Console()
8
- APP_NAME: str = __package__
 
1
+ """A module for configuring and initializing."""
2
 
3
+ from warnings import filterwarnings
4
 
5
  filterwarnings("ignore", category=DeprecationWarning)
 
 
 
src/chattr/__main__.py CHANGED
@@ -1,21 +1,14 @@
1
- from typing import TYPE_CHECKING
2
-
3
- from chattr.app.runner import app
4
-
5
- if TYPE_CHECKING:
6
- from gradio import Blocks
7
 
8
 
9
  def main() -> None:
10
- """Launch the Gradio Multi-agent system app."""
11
- application: Blocks = app.gui()
12
- application.queue(api_open=True)
13
- application.launch(
14
- debug=True,
15
- enable_monitoring=True,
16
- show_error=True,
17
- pwa=True,
18
- )
19
 
20
 
21
  if __name__ == "__main__":
 
1
+ from chattr.app.app import App
2
+ from chattr.app.settings import Settings
 
 
 
 
3
 
4
 
5
  def main() -> None:
6
+ """Launch the app."""
7
+ settings = Settings()
8
+ application = App(settings)
9
+ gradio_application = application.gradio_app()
10
+ gradio_application.queue(api_open=True)
11
+ gradio_application.launch(debug=True, enable_monitoring=True, show_error=True, pwa=True)
 
 
 
12
 
13
 
14
  if __name__ == "__main__":
src/chattr/agent/__init__.py ADDED
File without changes
src/chattr/agent/agent.py ADDED
@@ -0,0 +1,53 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Main orchestration graph for the Chattr application."""
2
+
3
+ from typing import NamedTuple
4
+
5
+ from agno.agent import Agent
6
+ from agno.db import BaseDb
7
+ from agno.guardrails import PromptInjectionGuardrail
8
+ from agno.knowledge import Knowledge
9
+ from agno.models.openai import OpenAILike
10
+ from agno.tools.mcp import MultiMCPTools
11
+
12
+
13
+ class AgentConfiguration(NamedTuple):
14
+ """Configuration class for the Chattr agent."""
15
+
16
+ model: OpenAILike
17
+ tools: list[MultiMCPTools] | None
18
+ description: str
19
+ instructions: list[str]
20
+ db: BaseDb
21
+ knowledge: Knowledge
22
+ timezone: str
23
+ debug_mode: bool
24
+
25
+
26
+ async def setup_agent(agent_config: AgentConfiguration) -> Agent:
27
+ """
28
+ Initialize the Chattr agent.
29
+
30
+ Args:
31
+ agent_config (AgentConfiguration): Agent configuration.
32
+
33
+ Returns:
34
+ Agent: The Chattr agent.
35
+ """
36
+ return Agent(
37
+ model=agent_config.model,
38
+ tools=agent_config.tools,
39
+ description=agent_config.description,
40
+ instructions=agent_config.instructions,
41
+ db=agent_config.db,
42
+ knowledge=agent_config.knowledge,
43
+ markdown=True,
44
+ add_datetime_to_context=True,
45
+ timezone_identifier=agent_config.timezone,
46
+ pre_hooks=[PromptInjectionGuardrail()],
47
+ debug_mode=agent_config.debug_mode,
48
+ save_response_to_file="agno/response.txt",
49
+ add_history_to_context=True,
50
+ add_memories_to_context=True,
51
+ enable_agentic_state=True,
52
+ cache_session=True,
53
+ )
src/chattr/agent/database.py ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """A module for Initializing the database for Chattr agent."""
2
+
3
+ from agno.db.json import JsonDb
4
+
5
+
6
+ def setup_database() -> JsonDb:
7
+ """
8
+ Initialize the database for Chattr agent.
9
+
10
+ Returns:
11
+ JsonDb: The database for Chattr agent.
12
+ """
13
+ return JsonDb(db_path="agno")
src/chattr/agent/description.py ADDED
@@ -0,0 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from textwrap import dedent
2
+
3
+ from chattr.app.exceptions import CharacterNameMissingError
4
+
5
+
6
+ def setup_description(character: str | None) -> str:
7
+ """Set up the description for the agent."""
8
+ if not character:
9
+ raise CharacterNameMissingError
10
+ return dedent(
11
+ f"""
12
+ You are a helpful assistant
13
+ who can act and mimic {character}'s character
14
+ and answer questions about the era.
15
+ """,
16
+ )
src/chattr/agent/instructions.py ADDED
@@ -0,0 +1,26 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from agno.tools.mcp import MultiMCPTools
2
+
3
+ from chattr.app.exceptions import CharacterNameMissingError
4
+
5
+
6
+ def setup_instructions(character: str | None, tools: list[MultiMCPTools | None]) -> list[str]:
7
+ """Return a list of instructions to mimic a given character."""
8
+ if not character:
9
+ raise CharacterNameMissingError
10
+ instructions: list[str] = [
11
+ "Understand the user's question and context.",
12
+ "Gather relevant information and resources.",
13
+ f"Formulate a clear and concise response in {character}'s voice.",
14
+ ]
15
+ for tool in tools:
16
+ if isinstance(tool, MultiMCPTools):
17
+ for key in tool.functions:
18
+ if tool.functions[key].name == "generate_audio_for_text":
19
+ instructions.append(
20
+ "Generate audio from the formulated response using the appropriate Tool.",
21
+ )
22
+ if tool.functions[key].name == "generate_video_mcp":
23
+ instructions.append(
24
+ "Generate video from the resulted audio using the appropriate Tool.",
25
+ )
26
+ return instructions
src/chattr/agent/knowledge.py ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
 
1
+ from agno.db import BaseDb
2
+ from agno.knowledge.knowledge import Knowledge
3
+ from agno.vectordb.qdrant import Qdrant
4
+
5
+
6
+ def setup_knowledge(vector_db: Qdrant, db: BaseDb) -> Knowledge:
7
+ """Set up the knowledge for the agent."""
8
+ return Knowledge(vector_db=vector_db, contents_db=db)
src/chattr/agent/model.py ADDED
@@ -0,0 +1,37 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from agno.models.openai.like import OpenAILike
2
+ from agno.utils.log import log_info
3
+
4
+ from chattr.app.settings import ModelSettings
5
+ from chattr.app.utils import is_url
6
+
7
+
8
+ def setup_model(model: ModelSettings) -> OpenAILike:
9
+ """
10
+ Initialize the OpenAILike language model using the provided settings.
11
+
12
+ This method creates and returns an OpenAILike instance configured with
13
+ the model's URL, name, API key, and temperature.
14
+
15
+ Returns:
16
+ OpenAILike: The initialized OpenAILike language model instance.
17
+ """
18
+ if not model.url:
19
+ _msg = "Model URL is missing. Set it with `MODEL__URL`"
20
+ raise ValueError(_msg)
21
+ if not is_url(model.url.encoded_string()):
22
+ _msg = "Model URL is invalid. Set it with `MODEL__URL`"
23
+ raise ValueError(_msg)
24
+ if not model.name:
25
+ _msg = "Model name is missing. Set it with `MODEL__NAME`"
26
+ raise ValueError(_msg)
27
+ if not model.api_key:
28
+ _msg = "API key is missing. Set it with `MODEL__API_KEY`"
29
+ raise ValueError(_msg)
30
+ log_info("Initializing OpenAILike language model")
31
+ return OpenAILike(
32
+ base_url=model.url.encoded_string(),
33
+ id=model.name,
34
+ api_key=model.api_key.get_secret_value(),
35
+ temperature=model.temperature,
36
+ cache_response=model.cache_response,
37
+ )
src/chattr/agent/tools.py ADDED
@@ -0,0 +1,37 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from json import loads
2
+
3
+ from agno.tools.mcp import MultiMCPTools
4
+ from agno.utils.log import log_info, log_warning
5
+
6
+ from chattr.app.settings import MCPSettings
7
+
8
+
9
+ async def setup_mcp_tools(mcp: MCPSettings) -> MultiMCPTools | None:
10
+ """Return and setup MCP tools connection."""
11
+ if not mcp.path.exists():
12
+ log_warning("MCP config file not found.")
13
+ return None
14
+ mcp_servers: list[dict] = loads(mcp.path.read_text()).get("mcp_servers", [])
15
+ url_servers: list[dict] = [m for m in mcp_servers if m.get("type") == "url"]
16
+ if not url_servers:
17
+ log_info("No Remote MCP servers found.")
18
+ return None
19
+ mcp_tools = MultiMCPTools(
20
+ urls=[m["url"] for m in url_servers],
21
+ urls_transports=[m["transport"] for m in url_servers],
22
+ allow_partial_failure=True,
23
+ )
24
+ log_info(f"MCP servers: {len(mcp_tools.tools)}")
25
+ if not mcp_tools.tools or len(mcp_tools.tools) == 0:
26
+ log_info("No MCP servers available.")
27
+ return None
28
+ await mcp_tools.connect()
29
+ return mcp_tools
30
+
31
+
32
+ async def close_mcp_tools(mcp_tools: MultiMCPTools | None) -> None:
33
+ """Close the MCP tools connection."""
34
+ log_info("Closing MCP tools...")
35
+ if not mcp_tools:
36
+ return
37
+ await mcp_tools.close()
src/chattr/agent/vector_database.py ADDED
@@ -0,0 +1,20 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from agno.utils.log import log_info
2
+ from agno.vectordb.qdrant import Qdrant
3
+
4
+ from chattr.app.settings import VectorDatabaseSettings
5
+
6
+
7
+ def setup_vector_database(vectordb: VectorDatabaseSettings) -> Qdrant:
8
+ """
9
+ Initialize a vector database connection.
10
+
11
+ Args:
12
+ vectordb (VectorDatabaseSettings): The settings required for
13
+ connecting to the vector database.
14
+
15
+ Returns:
16
+ Qdrant: An instance of Qdrant configured with the specified vector database
17
+ settings.
18
+ """
19
+ log_info("Setting up vector database.")
20
+ return Qdrant(collection=vectordb.name, url=vectordb.url.host, port=vectordb.url.port)
src/chattr/app/app.py ADDED
@@ -0,0 +1,215 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from collections.abc import AsyncGenerator
2
+ from json import dumps
3
+ from typing import TYPE_CHECKING
4
+
5
+ from agno.agent import Agent, RunContentEvent, ToolCallCompletedEvent, ToolCallStartedEvent
6
+ from agno.models.message import Message
7
+ from agno.models.metrics import Metrics
8
+ from agno.models.response import ToolExecution
9
+ from agno.utils.log import configure_agno_logging, log_error, log_warning
10
+ from gradio import Audio, Blocks, ChatInterface, ChatMessage, Error, Video
11
+ from gradio.components.chatbot import MetadataDict
12
+ from qdrant_client.http.exceptions import ResponseHandlingException
13
+
14
+ from chattr.agent.agent import AgentConfiguration, setup_agent
15
+ from chattr.agent.database import setup_database
16
+ from chattr.agent.description import setup_description
17
+ from chattr.agent.instructions import setup_instructions
18
+ from chattr.agent.knowledge import setup_knowledge
19
+ from chattr.agent.model import setup_model
20
+ from chattr.agent.tools import close_mcp_tools, setup_mcp_tools
21
+ from chattr.agent.vector_database import setup_vector_database
22
+ from chattr.app.logger import setup_logger
23
+ from chattr.app.settings import Settings
24
+
25
+ if TYPE_CHECKING:
26
+ from logging import Logger
27
+
28
+ from agno.db.json import JsonDb
29
+ from agno.knowledge import Knowledge
30
+ from agno.models.openai import OpenAILike
31
+ from agno.tools.mcp import MultiMCPTools
32
+ from agno.vectordb.qdrant import Qdrant
33
+
34
+
35
+ class App:
36
+ """Main application class for the Chattr Multi-agent system app."""
37
+
38
+ def __init__(self, settings: Settings) -> None:
39
+ """Initialize the Chattr app."""
40
+ self.settings = settings
41
+ logger: Logger = setup_logger(self.settings.log)
42
+ configure_agno_logging(custom_default_logger=logger)
43
+
44
+ def gradio_app(self) -> Blocks:
45
+ """Create and return the main Gradio Blocks interface for the Chattr app."""
46
+ return ChatInterface(
47
+ fn=self.generate_response,
48
+ save_history=True,
49
+ title="Chattr",
50
+ show_progress="full",
51
+ )
52
+
53
+ def _response_at_run_content_event(
54
+ self,
55
+ history: list[ChatMessage | Audio | Video],
56
+ response: RunContentEvent,
57
+ ) -> list[ChatMessage | Audio | Video]:
58
+ """Handle the response run content event."""
59
+ if not isinstance(response, RunContentEvent):
60
+ _msg = "Expected RunContentEvent"
61
+ raise TypeError(_msg)
62
+ history.append(ChatMessage(role="assistant", content=str(response.content)))
63
+ return history
64
+
65
+ def _response_at_tool_call_started_event(
66
+ self,
67
+ history: list[ChatMessage | Audio | Video],
68
+ response: ToolCallStartedEvent,
69
+ ) -> list[ChatMessage | Audio | Video]:
70
+ """Handle the response tool call started event."""
71
+ if not isinstance(response.tool, ToolExecution):
72
+ _msg = "ToolExecution expected"
73
+ log_error(_msg)
74
+ raise TypeError(_msg)
75
+ history.append(
76
+ ChatMessage(
77
+ role="assistant",
78
+ content=dumps(response.tool.tool_args, indent=4),
79
+ metadata=MetadataDict(
80
+ title=str(response.tool.tool_name),
81
+ id=str(response.tool.tool_call_id),
82
+ duration=response.tool.created_at,
83
+ ),
84
+ ),
85
+ )
86
+ return history
87
+
88
+ def _response_at_tool_call_completed_event(
89
+ self,
90
+ history: list[ChatMessage | Audio | Video],
91
+ response: ToolCallCompletedEvent,
92
+ ) -> list[ChatMessage | Audio | Video]:
93
+ """Handle the response tool call completed event."""
94
+ if not isinstance(response.tool, ToolExecution):
95
+ _msg = "ToolExecution expected"
96
+ log_error(_msg)
97
+ raise TypeError(_msg)
98
+ if response.tool.tool_call_error:
99
+ if not isinstance(response.tool.metrics, Metrics):
100
+ _msg = "Metrics expected"
101
+ log_error(_msg)
102
+ raise TypeError(_msg)
103
+ history.append(
104
+ ChatMessage(
105
+ role="assistant",
106
+ content=dumps(response.tool.tool_args, indent=4),
107
+ metadata=MetadataDict(
108
+ title=str(response.tool.tool_name),
109
+ id=str(response.tool.tool_call_id),
110
+ log="Tool Call Failed",
111
+ duration=float(str(response.tool.metrics.duration)),
112
+ ),
113
+ ),
114
+ )
115
+ else:
116
+ if not isinstance(response.tool.metrics, Metrics):
117
+ _msg = "Metrics expected"
118
+ log_error(_msg)
119
+ raise TypeError(_msg)
120
+ history.append(
121
+ ChatMessage(
122
+ role="assistant",
123
+ content=dumps(response.tool.tool_args, indent=4),
124
+ metadata=MetadataDict(
125
+ title=str(response.tool.tool_name),
126
+ id=str(response.tool.tool_call_id),
127
+ log="Tool Call Succeeded",
128
+ duration=float(str(response.tool.metrics.duration)),
129
+ ),
130
+ ),
131
+ )
132
+ if response.tool.tool_name == "generate_audio_for_text":
133
+ history.append(Audio(response.tool.result, autoplay=True))
134
+ elif response.tool.tool_name == "generate_video_mcp":
135
+ history.append(Video(response.tool.result, autoplay=True))
136
+ else:
137
+ _msg = f"Unknown tool name: {response.tool.tool_name}"
138
+ log_error(_msg)
139
+ raise Error(_msg, print_exception=self.settings.debug)
140
+ return history
141
+
142
+ async def generate_response(
143
+ self,
144
+ message: str,
145
+ history: list[ChatMessage | Audio | Video],
146
+ ) -> AsyncGenerator[list[ChatMessage | Audio | Video]]:
147
+ """
148
+ Generate a response to a user message and update the conversation history.
149
+
150
+ This asynchronous method streams responses from the state graph and
151
+ yields updated history and audio file paths as needed.
152
+
153
+ Args:
154
+ message: The user's input message as a string.
155
+ history: The conversation history as a list of ChatMessage, Audio, or Video objects.
156
+
157
+ Returns:
158
+ AsyncGenerator: Yields a list of the updated history containing
159
+ ChatMessage, Audio, and Video objects if it existed.
160
+ """
161
+ try:
162
+ _tools: list[MultiMCPTools] | None = None
163
+ tools: MultiMCPTools | None = await setup_mcp_tools(self.settings.mcp)
164
+ model: OpenAILike = setup_model(self.settings.model)
165
+ db: JsonDb = setup_database()
166
+ vectordb: Qdrant = setup_vector_database(self.settings.vector_database)
167
+ knowledge: Knowledge = setup_knowledge(vectordb, db)
168
+ description: str = setup_description(self.settings.character.name)
169
+ instructions: list[str] = setup_instructions(self.settings.character.name, [tools])
170
+ if not tools or len(tools.tools) == 0:
171
+ _msg = "No tools found"
172
+ log_warning(_msg)
173
+ else:
174
+ _tools = [tools]
175
+ agent: Agent = await setup_agent(
176
+ AgentConfiguration(
177
+ model=model,
178
+ tools=_tools,
179
+ description=description,
180
+ instructions=instructions,
181
+ db=db,
182
+ knowledge=knowledge,
183
+ timezone=self.settings.timezone,
184
+ debug_mode=self.settings.debug,
185
+ ),
186
+ )
187
+ async for response in agent.arun(
188
+ Message(content=message, role="user"),
189
+ stream=True,
190
+ stream_events=True,
191
+ ):
192
+ # pprint(response)
193
+ if isinstance(response, RunContentEvent):
194
+ history = self._response_at_run_content_event(history, response)
195
+ elif isinstance(response, ToolCallStartedEvent):
196
+ history = self._response_at_tool_call_started_event(history, response)
197
+ elif isinstance(response, ToolCallCompletedEvent):
198
+ history = self._response_at_tool_call_completed_event(history, response)
199
+ print(f"---------- {history}")
200
+ yield history
201
+ await close_mcp_tools(tools)
202
+ except (StopAsyncIteration, StopIteration) as e:
203
+ log_error(f"Iteration stopped. {e}")
204
+ except ResponseHandlingException as e:
205
+ log_error(f"Vector database is not reachable. {e}")
206
+ except RuntimeError as e:
207
+ log_error(f"Runtime error. {e}")
208
+ except ValueError as e:
209
+ log_error(f"Value error. {e}")
210
+ except TypeError as e:
211
+ log_error(f"Type error. {e}")
212
+ except Exception as e:
213
+ log_error(f"Unexpected error. {e}")
214
+ finally:
215
+ yield history
src/chattr/app/builder.py DELETED
@@ -1,323 +0,0 @@
1
- """Main orchestration graph for the Chattr application."""
2
-
3
- from collections.abc import AsyncGenerator
4
- from json import dumps, loads
5
- from pathlib import Path
6
-
7
- from agno.agent import (
8
- Agent,
9
- RunContentEvent,
10
- ToolCallCompletedEvent,
11
- ToolCallStartedEvent,
12
- )
13
- from agno.db import BaseDb
14
- from agno.db.json import JsonDb
15
- from agno.guardrails import PIIDetectionGuardrail, PromptInjectionGuardrail
16
- from agno.knowledge.knowledge import Knowledge
17
- from agno.models.message import Message
18
- from agno.models.openai.like import OpenAILike
19
- from agno.tools import Toolkit
20
- from agno.tools.mcp import MultiMCPTools
21
- from agno.vectordb.qdrant import Qdrant
22
- from gradio import (
23
- Audio,
24
- Blocks,
25
- ChatInterface,
26
- ChatMessage,
27
- Error,
28
- Video,
29
- )
30
- from gradio.components.chatbot import MetadataDict
31
- from m3u8 import M3U8, load
32
- from poml import poml
33
- from pydantic import HttpUrl, ValidationError
34
- from requests import Session
35
- from rich.pretty import pprint
36
-
37
- from chattr.app.settings import Settings, logger
38
-
39
-
40
- class App:
41
- """Main application class for the Chattr Multi-agent system app."""
42
-
43
- def __init__(self, settings: Settings) -> None:
44
- self.settings = settings
45
-
46
- async def _setup_agent(self) -> Agent:
47
- return Agent(
48
- model=self._setup_model(),
49
- tools=await self._setup_tools(),
50
- description="You are a helpful assistant who can act and mimic Napoleon's character and answer questions about the era.",
51
- instructions=[
52
- "Understand the user's question and context.",
53
- "Gather relevant information and resources.",
54
- "Formulate a clear and concise response in Napoleon's voice.",
55
- "ALWAYS generate audio from the formulated response using the appropriate Tool.",
56
- "Generate video from the resulted audio using the appropriate Tool.",
57
- ],
58
- db=self._setup_database(),
59
- knowledge=self._setup_knowledge(
60
- self._setup_vector_database(),
61
- self._setup_database(),
62
- ),
63
- markdown=True,
64
- add_datetime_to_context=True,
65
- timezone_identifier="Africa/Cairo",
66
- pre_hooks=[PIIDetectionGuardrail(), PromptInjectionGuardrail()],
67
- debug_mode=True,
68
- save_response_to_file="agno/response.txt",
69
- add_history_to_context=True,
70
- add_memories_to_context=True,
71
- )
72
-
73
- async def _setup_tools(self) -> list[Toolkit]:
74
- mcp_servers: list[dict] = loads(self.settings.mcp.path.read_text()).get(
75
- "mcp_servers",
76
- [],
77
- )
78
- url_servers = [m for m in mcp_servers if m.get("type") == "url"]
79
- self.mcp_tools = MultiMCPTools(
80
- urls=[m.get("url") for m in url_servers],
81
- urls_transports=[m.get("transport") for m in url_servers],
82
- )
83
- await self.mcp_tools.connect()
84
- return [self.mcp_tools]
85
-
86
- def _setup_prompt(self) -> str:
87
- prompt_template = poml(
88
- self.settings.directory.prompts / "template.poml",
89
- {"character": "Napoleon"},
90
- chat=False,
91
- format="dict",
92
- )
93
- if not isinstance(prompt_template, dict):
94
- _msg = "Prompt template must be a string."
95
- raise TypeError(_msg)
96
- return prompt_template["messages"]
97
-
98
- def _setup_model(self) -> OpenAILike:
99
- """
100
- Initialize the ChatOpenAI language model using the provided settings.
101
-
102
- This method creates and returns a ChatOpenAI instance configured with
103
- the model's URL, name, API key, and temperature.
104
-
105
- Returns:
106
- ChatOpenAI: The initialized ChatOpenAI language model instance.
107
-
108
- Raises:
109
- Exception: If the model initialization fails.
110
- """
111
- try:
112
- return OpenAILike(
113
- base_url=str(self.settings.model.url),
114
- id=self.settings.model.name,
115
- api_key=self.settings.model.api_key.get_secret_value(),
116
- temperature=self.settings.model.temperature,
117
- )
118
- except Exception as e:
119
- _msg: str = f"Failed to initialize ChatOpenAI model: {e}"
120
- logger.error(_msg)
121
- raise Error(_msg) from e
122
-
123
- def _setup_vector_database(self) -> Qdrant:
124
- return Qdrant(
125
- collection=self.settings.vector_database.name,
126
- url=self.settings.vector_database.url.host,
127
- )
128
-
129
- def _setup_knowledge(self, vector_db: Qdrant, db: BaseDb) -> Knowledge:
130
- return Knowledge(
131
- vector_db=vector_db,
132
- contents_db=db,
133
- )
134
-
135
- def _setup_database(self) -> JsonDb:
136
- return JsonDb(
137
- db_path="agno",
138
- )
139
-
140
- def gui(self) -> Blocks:
141
- """
142
- Create and return the main Gradio Blocks interface for the Chattr app.
143
-
144
- Returns:
145
- Blocks: The constructed Gradio Blocks interface for the chat application.
146
- """
147
- return ChatInterface(fn=self.generate_response, save_history=True)
148
-
149
- async def generate_response(
150
- self,
151
- message: str,
152
- history: list[ChatMessage],
153
- ) -> AsyncGenerator[tuple[str, list[ChatMessage], Path | None, Path | None]]:
154
- """
155
- Generate a response to a user message and update the conversation history.
156
-
157
- This asynchronous method streams responses from the state graph and
158
- yields updated history and audio file paths as needed.
159
-
160
- Args:
161
- message: The user's input message as a string.
162
- history: The conversation history as a list of ChatMessage objects.
163
-
164
- Returns:
165
- AsyncGenerator: Yields a tuple containing an
166
- empty string, the updated history, and
167
- a Path to an audio file if generated.
168
- """
169
- try:
170
- agent: Agent = await self._setup_agent()
171
- async for response in agent.arun(
172
- Message(content=message, role="user"),
173
- stream=True,
174
- ):
175
- pprint(response)
176
- if isinstance(response, RunContentEvent):
177
- history.append(
178
- ChatMessage(
179
- role="assistant",
180
- content=response.content,
181
- ),
182
- )
183
- elif isinstance(response, ToolCallStartedEvent):
184
- history.append(
185
- ChatMessage(
186
- role="assistant",
187
- content=dumps(response.tool.tool_args, indent=4),
188
- metadata=MetadataDict(
189
- title=response.tool.tool_name,
190
- id=response.tool.tool_call_id,
191
- duration=response.tool.created_at,
192
- ),
193
- ),
194
- )
195
- elif isinstance(response, ToolCallCompletedEvent):
196
- if response.tool.tool_call_error:
197
- history.append(
198
- ChatMessage(
199
- role="assistant",
200
- content=dumps(response.tool.tool_args, indent=4),
201
- metadata=MetadataDict(
202
- title=response.tool.tool_name,
203
- id=response.tool.tool_call_id,
204
- log="Tool Call Failed",
205
- duration=response.tool.metrics.duration,
206
- ),
207
- ),
208
- )
209
- else:
210
- history.append(
211
- ChatMessage(
212
- role="assistant",
213
- content=dumps(response.tool.tool_args, indent=4),
214
- metadata=MetadataDict(
215
- title=response.tool.tool_name,
216
- id=response.tool.tool_call_id,
217
- log="Tool Call Succeeded",
218
- duration=response.tool.metrics.duration,
219
- ),
220
- ),
221
- )
222
- if response.tool.tool_name == "generate_audio_for_text":
223
- history.append(
224
- Audio(
225
- response.tool.result,
226
- autoplay=True,
227
- show_download_button=True,
228
- show_share_button=True,
229
- ),
230
- )
231
- elif response.tool.tool_name == "generate_video_mcp":
232
- history.append(
233
- Video(
234
- response.tool.result,
235
- autoplay=True,
236
- show_download_button=True,
237
- show_share_button=True,
238
- ),
239
- )
240
- else:
241
- msg = f"Unknown tool name: {response.tool.tool_name}"
242
- raise Error(msg)
243
- yield history
244
- except Exception as e:
245
- _msg: str = f"Error generating response: {e}"
246
- logger.error(_msg)
247
- raise Error(_msg) from e
248
- finally:
249
- await self._close()
250
-
251
- def _is_url(self, value: str | None) -> bool:
252
- """
253
- Check if a string is a valid URL.
254
-
255
- Args:
256
- value: The string to check. Can be None.
257
-
258
- Returns:
259
- bool: True if the string is a valid URL, False otherwise.
260
- """
261
- if value is None:
262
- return False
263
-
264
- try:
265
- _ = HttpUrl(value)
266
- except ValidationError:
267
- return False
268
- return True
269
-
270
- def _download_file(self, url: HttpUrl, path: Path) -> None:
271
- """
272
- Download a file from a URL and save it to a local path.
273
-
274
- Args:
275
- url: The URL to download the file from.
276
- path: The local file path where the downloaded file will be saved.
277
-
278
- Returns:
279
- None
280
-
281
- Raises:
282
- requests.RequestException: If the HTTP request fails.
283
- IOError: If file writing fails.
284
- """
285
- if str(url).endswith(".m3u8"):
286
- _playlist: M3U8 = load(url)
287
- url: str = str(url).replace("playlist.m3u8", _playlist.segments[0].uri)
288
- logger.info(f"Downloading {url} to {path}")
289
- session = Session()
290
- response = session.get(url, stream=True, timeout=30)
291
- response.raise_for_status()
292
- with path.open("wb") as f:
293
- for chunk in response.iter_content(chunk_size=8192):
294
- if chunk:
295
- f.write(chunk)
296
- logger.info(f"File downloaded to {path}")
297
-
298
- async def _close(self) -> None:
299
- try:
300
- logger.info("Closing MCP tools...")
301
- await self.mcp_tools.close()
302
- except Exception as e:
303
- msg: str = (
304
- f"Error closing MCP tools: {e}, Check if the Tool services are running."
305
- )
306
- logger.error(msg)
307
- raise Error(msg) from e
308
-
309
-
310
- async def test() -> None:
311
- settings: Settings = Settings()
312
- app: App = App(settings)
313
- agent: Agent = await app._setup_agent()
314
- try:
315
- await agent.aprint_response("Hello!", debug_mode=True)
316
- finally:
317
- await app._close()
318
-
319
-
320
- if __name__ == "__main__":
321
- import asyncio
322
-
323
- asyncio.run(test())
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
src/chattr/app/exceptions.py ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ class ChattrError(Exception):
2
+ """Base exception for the Chattr application."""
3
+
4
+
5
+ class ConfigurationError(ChattrError):
6
+ """Raised when there is an issue with the application settings."""
7
+
8
+
9
+ class ModelConfigurationError(ConfigurationError):
10
+ """Raised when model-specific settings are missing or invalid."""
11
+
12
+
13
+ class ParameterMissingError(ChattrError):
14
+ """Exception raised for missing parameters."""
15
+
16
+
17
+ class CharacterNameMissingError(ParameterMissingError):
18
+ """Exception raised when the character name is missing."""
19
+
20
+ def __init__(self) -> None:
21
+ super().__init__("Character name is missing. Set it with `CHARACTER__NAME`")
src/chattr/app/logger.py CHANGED
@@ -1,19 +1,23 @@
1
- from logging import INFO, WARNING, Logger, basicConfig, getLogger
2
 
 
 
 
3
  from rich.logging import RichHandler
4
 
5
- from chattr import APP_NAME, console
6
 
7
- basicConfig(
8
- level=INFO,
9
- handlers=[
10
- RichHandler(
11
- level=INFO,
12
- console=console,
13
- rich_tracebacks=True,
14
- ),
15
- ],
16
- format="%(name)s | %(process)d | %(message)s",
17
- )
18
  getLogger("httpx").setLevel(WARNING)
19
- logger: Logger = getLogger(APP_NAME)
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """A module handles the configuration of logging for the application."""
2
 
3
+ from logging import WARNING, Formatter, Logger, getLogger
4
+
5
+ from rich.console import Console
6
  from rich.logging import RichHandler
7
 
8
+ from chattr.app.settings import LoggerSettings
9
 
 
 
 
 
 
 
 
 
 
 
 
10
  getLogger("httpx").setLevel(WARNING)
11
+
12
+
13
+ def setup_logger(log: LoggerSettings) -> Logger:
14
+ """Initialize the logger for the application."""
15
+ logger: Logger = getLogger(log.name)
16
+ console: Console = Console()
17
+ handler: RichHandler = RichHandler(level=log.level.value, console=console, rich_tracebacks=True)
18
+ formatter: Formatter = Formatter(log.format)
19
+ handler.setFormatter(formatter)
20
+ logger.addHandler(handler)
21
+ logger.setLevel(log.level.value)
22
+ logger.propagate = False
23
+ return logger
src/chattr/app/runner.py DELETED
@@ -1,5 +0,0 @@
1
- from chattr.app.builder import App
2
- from chattr.app.settings import Settings
3
-
4
- settings: Settings = Settings()
5
- app: App = App(settings)
 
 
 
 
 
 
src/chattr/app/scheme.py CHANGED
@@ -1,35 +1,32 @@
1
- from typing import Annotated, Literal
2
 
3
- from pydantic import (
4
- BaseModel,
5
- ConfigDict,
6
- Field,
7
- HttpUrl,
8
- ValidationError,
9
- )
10
 
11
- from chattr.app.logger import logger
 
 
 
12
 
13
 
14
- class CommandConnection(BaseModel):
15
  """MCP connection variant using a shell command."""
16
 
17
- model_config = ConfigDict(extra="forbid")
18
  name: str = Field(..., description="Name of the MCP server instance")
19
- type: Literal["command"]
20
- command: str = Field(..., description="Executable command to start MCP server")
21
- args: list[str] | None = Field(default=None)
22
  transport: Literal["stdio"] = Field("stdio")
23
 
24
 
25
- class URLConnection(BaseModel):
 
 
 
 
 
 
 
26
  """MCP connection variant using a URL endpoint."""
27
 
28
- model_config = ConfigDict(extra="forbid")
29
  name: str = Field(..., description="Name of the MCP server instance")
30
- type: Literal["url"]
31
- url: HttpUrl = Field(..., description="URL of the MCP server endpoint")
32
- transport: Literal["sse", "streamable-http"] = Field(...)
33
 
34
 
35
  class MCPScheme(BaseModel):
@@ -37,7 +34,10 @@ class MCPScheme(BaseModel):
37
 
38
  model_config = ConfigDict(extra="forbid")
39
  mcp_servers: list[
40
- Annotated[CommandConnection | URLConnection, Field(discriminator="type")]
 
 
 
41
  ] = Field(default_factory=list)
42
 
43
 
@@ -54,6 +54,7 @@ if __name__ == "__main__":
54
  "type": "command",
55
  "command": "mcp-server",
56
  "args": ["--port", "8080"],
 
57
  },
58
  {
59
  "name": "example_url_server",
@@ -66,12 +67,12 @@ if __name__ == "__main__":
66
  )
67
  pprint(ok1)
68
 
69
- # This will fail: missing required key for the selected type
70
  try:
71
  MCPScheme.model_validate(
72
  {"mcp_servers": [{"type": "url", "command": "ls"}]},
73
  )
74
  except ValidationError as e:
75
- logger.error("Validation error: %s", e)
76
 
77
  # Additional validation examples can be added here if needed.
 
1
+ """Module defining MCP connection scheme configurations."""
2
 
3
+ from typing import Annotated, Literal
 
 
 
 
 
 
4
 
5
+ from agno.tools.mcp import SSEClientParams, StreamableHTTPClientParams
6
+ from agno.utils.log import log_error
7
+ from mcp import StdioServerParameters
8
+ from pydantic import BaseModel, ConfigDict, Field, ValidationError
9
 
10
 
11
+ class CommandConnection(StdioServerParameters):
12
  """MCP connection variant using a shell command."""
13
 
 
14
  name: str = Field(..., description="Name of the MCP server instance")
 
 
 
15
  transport: Literal["stdio"] = Field("stdio")
16
 
17
 
18
+ class SSEConnection(BaseModel, SSEClientParams):
19
+ """SSE connection variant using a URL endpoint."""
20
+
21
+ name: str = Field(..., description="Name of the MCP server instance")
22
+ transport: Literal["sse"] = Field("sse")
23
+
24
+
25
+ class StreamableHTTPConnection(BaseModel, StreamableHTTPClientParams):
26
  """MCP connection variant using a URL endpoint."""
27
 
 
28
  name: str = Field(..., description="Name of the MCP server instance")
29
+ transport: Literal["streamable-http"] = Field("streamable-http")
 
 
30
 
31
 
32
  class MCPScheme(BaseModel):
 
34
 
35
  model_config = ConfigDict(extra="forbid")
36
  mcp_servers: list[
37
+ Annotated[
38
+ CommandConnection | SSEConnection | StreamableHTTPConnection,
39
+ Field(discriminator="transport"),
40
+ ]
41
  ] = Field(default_factory=list)
42
 
43
 
 
54
  "type": "command",
55
  "command": "mcp-server",
56
  "args": ["--port", "8080"],
57
+ "transport": "stdio",
58
  },
59
  {
60
  "name": "example_url_server",
 
67
  )
68
  pprint(ok1)
69
 
70
+ # This will fail: missing the required key for the selected type
71
  try:
72
  MCPScheme.model_validate(
73
  {"mcp_servers": [{"type": "url", "command": "ls"}]},
74
  )
75
  except ValidationError as e:
76
+ log_error(f"Validation error: {e}")
77
 
78
  # Additional validation examples can be added here if needed.
src/chattr/app/settings.py CHANGED
@@ -1,8 +1,11 @@
1
  """Settings for the Chattr app."""
2
 
 
 
3
  from pathlib import Path
4
  from typing import Self
5
 
 
6
  from dotenv import load_dotenv
7
  from pydantic import (
8
  BaseModel,
@@ -16,7 +19,6 @@ from pydantic import (
16
  )
17
  from pydantic_settings import BaseSettings, SettingsConfigDict
18
 
19
- from chattr.app.logger import logger
20
  from chattr.app.scheme import MCPScheme
21
 
22
  load_dotenv()
@@ -41,19 +43,16 @@ class MCPSettings(BaseModel):
41
 
42
  path: FilePath = Field(default_factory=lambda: Path.cwd() / "mcp.json")
43
 
44
- @model_validator(mode="after")
45
- def is_exists(self) -> Self:
46
- """Check if the MCP config file exists."""
47
- if not self.path.exists():
48
- logger.warning("`mcp.json` not found.")
49
- return self
50
-
51
  @model_validator(mode="after")
52
  def is_valid(self) -> Self:
53
- """Validate that the MCP config file is a JSON file."""
54
- if self.path and self.path.suffix != ".json":
55
- msg = "MCP config file must be a JSON file"
56
- raise ValueError(msg)
 
 
 
 
57
  return self
58
 
59
  @model_validator(mode="after")
@@ -107,9 +106,9 @@ class DirectorySettings(BaseModel):
107
  if not directory.exists():
108
  try:
109
  directory.mkdir(parents=True, exist_ok=True)
110
- logger.info("Created directory %s.", directory)
111
  except OSError as e:
112
- logger.error("Error creating directory %s: %s", directory, e)
113
  raise
114
  return self
115
 
@@ -121,33 +120,20 @@ class ModelSettings(BaseModel):
121
  name: str | None = Field(default=None)
122
  api_key: SecretStr | None = Field(default=None)
123
  temperature: float = Field(default=0.0, ge=0.0, le=1.0)
 
124
 
125
  @model_validator(mode="after")
126
- def check_api_key_exist(self) -> Self:
127
- """
128
- Ensure that an API key and model name are provided if a model URL is set.
129
-
130
- This method validates the presence of required
131
- credentials for the model provider.
132
-
133
- Returns:
134
- Self: The validated ModelSettings instance.
135
-
136
- Raises:
137
- ValueError: If the API key or model name is missing
138
- when a model URL is provided.
139
- """
140
  if self.url:
141
  if not self.api_key or not self.api_key.get_secret_value():
142
  _msg: str = (
143
- "You need to provide API Key for the Model provider:"
144
- " Set via `MODEL__API_KEY`"
145
  )
146
  raise ValueError(_msg)
147
  if not self.name:
148
  _msg: str = (
149
- "You need to provide Model name for the Model provider:"
150
- " Set via `MODEL__NAME`"
151
  )
152
  raise ValueError(_msg)
153
  return self
@@ -159,10 +145,30 @@ class CharacterSettings(BaseModel):
159
  name: str | None = Field(default=None)
160
 
161
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
162
  class Settings(BaseSettings):
163
  """Configuration for the Chattr app."""
164
 
165
- model_config: SettingsConfigDict = SettingsConfigDict(
166
  env_nested_delimiter="__",
167
  env_parse_none_str="None",
168
  env_file=".env",
@@ -177,7 +183,9 @@ class Settings(BaseSettings):
177
  )
178
  mcp: MCPSettings = Field(default_factory=MCPSettings)
179
  character: CharacterSettings = Field(default_factory=CharacterSettings)
 
180
  debug: bool = Field(default=False)
 
181
 
182
 
183
  if __name__ == "__main__":
 
1
  """Settings for the Chattr app."""
2
 
3
+ from enum import Enum
4
+ from logging import CRITICAL, DEBUG, ERROR, INFO, NOTSET, WARNING
5
  from pathlib import Path
6
  from typing import Self
7
 
8
+ from agno.utils.log import log_error, log_info
9
  from dotenv import load_dotenv
10
  from pydantic import (
11
  BaseModel,
 
19
  )
20
  from pydantic_settings import BaseSettings, SettingsConfigDict
21
 
 
22
  from chattr.app.scheme import MCPScheme
23
 
24
  load_dotenv()
 
43
 
44
  path: FilePath = Field(default_factory=lambda: Path.cwd() / "mcp.json")
45
 
 
 
 
 
 
 
 
46
  @model_validator(mode="after")
47
  def is_valid(self) -> Self:
48
+ """Validate that the MCP config file is a valid JSON file."""
49
+ if self.path:
50
+ if self.path.suffix != ".json":
51
+ msg = "MCP config file must be a JSON file"
52
+ raise ValueError(msg)
53
+ if self.path.stem != "mcp":
54
+ msg = "MCP config file must be named 'mcp.json'"
55
+ raise ValueError(msg)
56
  return self
57
 
58
  @model_validator(mode="after")
 
106
  if not directory.exists():
107
  try:
108
  directory.mkdir(parents=True, exist_ok=True)
109
+ log_info(f"Created directory {directory}.")
110
  except OSError as e:
111
+ log_error(f"Error creating directory {directory}: {e}")
112
  raise
113
  return self
114
 
 
120
  name: str | None = Field(default=None)
121
  api_key: SecretStr | None = Field(default=None)
122
  temperature: float = Field(default=0.0, ge=0.0, le=1.0)
123
+ cache_response: bool = Field(default=True)
124
 
125
  @model_validator(mode="after")
126
+ def check_param_exist(self) -> Self:
127
+ """Validate the existence of required credentials for the model provider."""
 
 
 
 
 
 
 
 
 
 
 
 
128
  if self.url:
129
  if not self.api_key or not self.api_key.get_secret_value():
130
  _msg: str = (
131
+ "You need to provide API Key for the Model provider: Set via `MODEL__API_KEY`"
 
132
  )
133
  raise ValueError(_msg)
134
  if not self.name:
135
  _msg: str = (
136
+ "You need to provide Model name for the Model provider: Set via `MODEL__NAME`"
 
137
  )
138
  raise ValueError(_msg)
139
  return self
 
145
  name: str | None = Field(default=None)
146
 
147
 
148
+ class LogLevel(Enum):
149
+ """Logging levels."""
150
+
151
+ CRITICAL = CRITICAL
152
+ ERROR = ERROR
153
+ WARNING = WARNING
154
+ INFO = INFO
155
+ DEBUG = DEBUG
156
+ NOTSET = NOTSET
157
+
158
+
159
+ class LoggerSettings(BaseModel):
160
+ """Settings related to logger configuration."""
161
+
162
+ name: str = Field(default="chattr", frozen=True)
163
+ level: LogLevel = Field(default=LogLevel.INFO)
164
+ propagate: bool = Field(default=False)
165
+ format: str = Field(default="%(name)s | %(process)d | %(message)s")
166
+
167
+
168
  class Settings(BaseSettings):
169
  """Configuration for the Chattr app."""
170
 
171
+ model_config = SettingsConfigDict(
172
  env_nested_delimiter="__",
173
  env_parse_none_str="None",
174
  env_file=".env",
 
183
  )
184
  mcp: MCPSettings = Field(default_factory=MCPSettings)
185
  character: CharacterSettings = Field(default_factory=CharacterSettings)
186
+ log: LoggerSettings = Field(default_factory=LoggerSettings)
187
  debug: bool = Field(default=False)
188
+ timezone: str = Field(default="Africa/Cairo")
189
 
190
 
191
  if __name__ == "__main__":
src/chattr/app/utils.py ADDED
@@ -0,0 +1,64 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from pathlib import Path
2
+
3
+ from agno.utils.log import log_info
4
+ from httpx import URL, Client, HTTPStatusError, RequestError
5
+ from pydantic import HttpUrl, ValidationError
6
+
7
+ VALID_STATUS_CODE = 200
8
+
9
+
10
+ def is_url(value: str | None) -> bool:
11
+ """
12
+ Check if a string is a valid URL.
13
+
14
+ Args:
15
+ value: The string to check. Can be None.
16
+
17
+ Returns:
18
+ bool: True if the string is a valid URL, False otherwise.
19
+ """
20
+ if value is None:
21
+ return False
22
+
23
+ try:
24
+ _ = HttpUrl(value)
25
+ except ValidationError:
26
+ return False
27
+ return True
28
+
29
+
30
+ def is_alive(url: HttpUrl) -> bool:
31
+ """
32
+ Check if a given URL is accessible and returns its availability status.
33
+
34
+ Args:
35
+ url (HttpUrl): The URL to check for accessibility.
36
+
37
+ Returns:
38
+ bool: True if the URL is accessible with a valid status code, otherwise False.
39
+ """
40
+ try:
41
+ with Client() as client:
42
+ response = client.get(str(url))
43
+ return response.status_code == VALID_STATUS_CODE
44
+ except (RequestError, HTTPStatusError):
45
+ return False
46
+
47
+
48
+ def download_file(url: URL, path: Path) -> None:
49
+ """
50
+ Download a file from a URL and save it to a local path.
51
+
52
+ Args:
53
+ url (URL): The URL to download the file from.
54
+ path (Path): The local file path where the downloaded file will be saved.
55
+
56
+ Returns:
57
+ None
58
+ """
59
+ log_info(f"Downloading {url} to {path}")
60
+ with Client() as client:
61
+ response = client.get(url)
62
+ response.raise_for_status()
63
+ path.write_bytes(response.content)
64
+ log_info(f"Downloaded {url} to {path}")
tests/test_app.py CHANGED
@@ -1,4 +1,4 @@
1
- """This module contains tests for the application's HTTP endpoints."""
2
 
3
  from os import getenv
4
 
@@ -12,8 +12,5 @@ def test_app() -> None:
12
  Returns:
13
  None
14
  """
15
- response: Response = head(
16
- getenv("CHATTR_URL", "http://localhost:7860/"),
17
- timeout=30,
18
- )
19
  assert response.status_code == 200
 
1
+ """Contain tests for the application's HTTP endpoints."""
2
 
3
  from os import getenv
4
 
 
12
  Returns:
13
  None
14
  """
15
+ response: Response = head(getenv("CHATTR_URL", "http://localhost:7860/"), timeout=30)
 
 
 
16
  assert response.status_code == 200
uv.lock CHANGED
@@ -242,7 +242,6 @@ dependencies = [
242
  { name = "gradio", extra = ["mcp"] },
243
  { name = "m3u8" },
244
  { name = "mem0ai" },
245
- { name = "poml" },
246
  { name = "rich" },
247
  ]
248
 
@@ -250,6 +249,7 @@ dependencies = [
250
  dev = [
251
  { name = "doppler-env" },
252
  { name = "pre-commit" },
 
253
  { name = "pytest-emoji" },
254
  { name = "pytest-md" },
255
  { name = "pytest-mergify" },
@@ -266,7 +266,6 @@ requires-dist = [
266
  { name = "gradio", extras = ["mcp"], specifier = ">=6.5.1" },
267
  { name = "m3u8", specifier = ">=6.0.0" },
268
  { name = "mem0ai", specifier = ">=1.0.2" },
269
- { name = "poml", specifier = ">=0.0.8" },
270
  { name = "rich", specifier = ">=14.3.1" },
271
  ]
272
 
@@ -274,6 +273,7 @@ requires-dist = [
274
  dev = [
275
  { name = "doppler-env", specifier = ">=0.3.1" },
276
  { name = "pre-commit", specifier = ">=4.5.1" },
 
277
  { name = "pytest-emoji", specifier = ">=0.2.0" },
278
  { name = "pytest-md", specifier = ">=0.2.0" },
279
  { name = "pytest-mergify", specifier = ">=2026.1.26.1" },
@@ -1112,34 +1112,6 @@ wheels = [
1112
  { url = "https://files.pythonhosted.org/packages/88/b2/d0896bdcdc8d28a7fc5717c305f1a861c26e18c05047949fb371034d98bd/nodeenv-1.10.0-py2.py3-none-any.whl", hash = "sha256:5bb13e3eed2923615535339b3c620e76779af4cb4c6a90deccc9e36b274d3827", size = 23438, upload-time = "2025-12-20T14:08:52.782Z" },
1113
  ]
1114
 
1115
- [[package]]
1116
- name = "nodejs-wheel"
1117
- version = "24.13.0"
1118
- source = { registry = "https://pypi.org/simple" }
1119
- dependencies = [
1120
- { name = "nodejs-wheel-binaries" },
1121
- ]
1122
- sdist = { url = "https://files.pythonhosted.org/packages/37/f0/3345c6ec958c96eaa9d59355e59c0e93359aec54634f38bc4cd06baf23aa/nodejs_wheel-24.13.0.tar.gz", hash = "sha256:8c423cbf434b4c853ebac076d563b0899d3c6594ef0f99f6cd368ca4e3a28ca2", size = 2965, upload-time = "2026-01-14T11:05:32.811Z" }
1123
- wheels = [
1124
- { url = "https://files.pythonhosted.org/packages/c3/29/f259f6c5d31a0dae8257afd8dd7ab4b60a1b6e03fab793789e5bad480d83/nodejs_wheel-24.13.0-py3-none-any.whl", hash = "sha256:c0fc56a4677f55f7639f306a6381fb253d11ce24189c87a5489ea848f6e2bf24", size = 3986, upload-time = "2026-01-14T11:05:02.807Z" },
1125
- ]
1126
-
1127
- [[package]]
1128
- name = "nodejs-wheel-binaries"
1129
- version = "24.13.0"
1130
- source = { registry = "https://pypi.org/simple" }
1131
- sdist = { url = "https://files.pythonhosted.org/packages/b7/f1/73182280e2c05f49a7c2c8dbd46144efe3f74f03f798fb90da67b4a93bbf/nodejs_wheel_binaries-24.13.0.tar.gz", hash = "sha256:766aed076e900061b83d3e76ad48bfec32a035ef0d41bd09c55e832eb93ef7a4", size = 8056, upload-time = "2026-01-14T11:05:33.653Z" }
1132
- wheels = [
1133
- { url = "https://files.pythonhosted.org/packages/c4/dc/4d7548aa74a5b446d093f03aff4fb236b570959d793f21c9c42ab6ad870a/nodejs_wheel_binaries-24.13.0-py2.py3-none-macosx_13_0_arm64.whl", hash = "sha256:356654baa37bfd894e447e7e00268db403ea1d223863963459a0fbcaaa1d9d48", size = 55133268, upload-time = "2026-01-14T11:05:05.335Z" },
1134
- { url = "https://files.pythonhosted.org/packages/24/8a/8a4454d28339487240dd2232f42f1090e4a58544c581792d427f6239798c/nodejs_wheel_binaries-24.13.0-py2.py3-none-macosx_13_0_x86_64.whl", hash = "sha256:92fdef7376120e575f8b397789bafcb13bbd22a1b4d21b060d200b14910f22a5", size = 55314800, upload-time = "2026-01-14T11:05:09.121Z" },
1135
- { url = "https://files.pythonhosted.org/packages/e7/fb/46c600fcc748bd13bc536a735f11532a003b14f5c4dfd6865f5911672175/nodejs_wheel_binaries-24.13.0-py2.py3-none-manylinux_2_28_aarch64.whl", hash = "sha256:3f619ac140e039ecd25f2f71d6e83ad1414017a24608531851b7c31dc140cdfd", size = 59666320, upload-time = "2026-01-14T11:05:12.369Z" },
1136
- { url = "https://files.pythonhosted.org/packages/85/47/d48f11fc5d1541ace5d806c62a45738a1db9ce33e85a06fe4cd3d9ce83f6/nodejs_wheel_binaries-24.13.0-py2.py3-none-manylinux_2_28_x86_64.whl", hash = "sha256:dfb31ebc2c129538192ddb5bedd3d63d6de5d271437cd39ea26bf3fe229ba430", size = 60162447, upload-time = "2026-01-14T11:05:16.003Z" },
1137
- { url = "https://files.pythonhosted.org/packages/b1/74/d285c579ae8157c925b577dde429543963b845e69cd006549e062d1cf5b6/nodejs_wheel_binaries-24.13.0-py2.py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:fdd720d7b378d5bb9b2710457bbc880d4c4d1270a94f13fbe257198ac707f358", size = 61659994, upload-time = "2026-01-14T11:05:19.68Z" },
1138
- { url = "https://files.pythonhosted.org/packages/ba/97/88b4254a2ff93ed2eaed725f77b7d3d2d8d7973bf134359ce786db894faf/nodejs_wheel_binaries-24.13.0-py2.py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:9ad6383613f3485a75b054647a09f1cd56d12380d7459184eebcf4a5d403f35c", size = 62244373, upload-time = "2026-01-14T11:05:23.987Z" },
1139
- { url = "https://files.pythonhosted.org/packages/4e/c3/0e13a3da78f08cb58650971a6957ac7bfef84164b405176e53ab1e3584e2/nodejs_wheel_binaries-24.13.0-py2.py3-none-win_amd64.whl", hash = "sha256:605be4763e3ef427a3385a55da5a1bcf0a659aa2716eebbf23f332926d7e5f23", size = 41345528, upload-time = "2026-01-14T11:05:27.67Z" },
1140
- { url = "https://files.pythonhosted.org/packages/a3/f1/0578d65b4e3dc572967fd702221ea1f42e1e60accfb6b0dd8d8f15410139/nodejs_wheel_binaries-24.13.0-py2.py3-none-win_arm64.whl", hash = "sha256:2e3431d869d6b2dbeef1d469ad0090babbdcc8baaa72c01dd3cc2c6121c96af5", size = 39054688, upload-time = "2026-01-14T11:05:30.739Z" },
1141
- ]
1142
-
1143
  [[package]]
1144
  name = "numpy"
1145
  version = "2.4.1"
@@ -1411,22 +1383,6 @@ wheels = [
1411
  { url = "https://files.pythonhosted.org/packages/54/20/4d324d65cc6d9205fabedc306948156824eb9f0ee1633355a8f7ec5c66bf/pluggy-1.6.0-py3-none-any.whl", hash = "sha256:e920276dd6813095e9377c0bc5566d94c932c33b27a3e3945d8389c374dd4746", size = 20538, upload-time = "2025-05-15T12:30:06.134Z" },
1412
  ]
1413
 
1414
- [[package]]
1415
- name = "poml"
1416
- version = "0.0.8"
1417
- source = { registry = "https://pypi.org/simple" }
1418
- dependencies = [
1419
- { name = "nodejs-wheel" },
1420
- { name = "pydantic" },
1421
- ]
1422
- wheels = [
1423
- { url = "https://files.pythonhosted.org/packages/b2/94/20b41e3826dcfec0313c8562a430ad158b1a759e064cd5bef61d0f5327d1/poml-0.0.8-py3-none-macosx_10_9_x86_64.whl", hash = "sha256:37be5da8572222854464969f76fac2e356297305c84fdcc7d3103d914811932b", size = 29549351, upload-time = "2025-08-25T04:23:18.411Z" },
1424
- { url = "https://files.pythonhosted.org/packages/28/93/0ab553b3f7da62358309743e64ddf09839fe6b0eaaa189a48d225ab92ab3/poml-0.0.8-py3-none-macosx_11_0_arm64.whl", hash = "sha256:f15c2d2e512b3ad699f22df289e7d834b6e85c804905f1431aaa98c223e1560e", size = 28651082, upload-time = "2025-08-25T04:22:14.277Z" },
1425
- { url = "https://files.pythonhosted.org/packages/98/48/3a265180712709b2a940cce053272b6d14c940e41b0125af85b74bfc0ff8/poml-0.0.8-py3-none-manylinux_2_17_aarch64.whl", hash = "sha256:e826586b9f623c4a4e3fd9457ad23a538adc917f16519d4ecdebab9ced3086aa", size = 35930454, upload-time = "2025-08-25T04:22:43.37Z" },
1426
- { url = "https://files.pythonhosted.org/packages/31/1d/7aead96240c82022cbfec914d6c9121146b95594f5de52a04ceece3ce2ca/poml-0.0.8-py3-none-manylinux_2_17_x86_64.whl", hash = "sha256:a0a53edc7615156d6841adbd401831520573dc8393dea9fa6971af09bc864f16", size = 35979155, upload-time = "2025-08-25T04:22:36.427Z" },
1427
- { url = "https://files.pythonhosted.org/packages/dc/2f/0f3157835901937d1bfe62f4bbfc7533e7642fb862f1fadf6912e224e438/poml-0.0.8-py3-none-win_amd64.whl", hash = "sha256:48a7880bc8d684231e78f11fb85cd78ce7a9b4121b9376f338f6589b5fccee98", size = 29656342, upload-time = "2025-08-25T04:25:43.624Z" },
1428
- ]
1429
-
1430
  [[package]]
1431
  name = "portalocker"
1432
  version = "3.2.0"
@@ -1645,6 +1601,22 @@ wheels = [
1645
  { url = "https://files.pythonhosted.org/packages/5a/dc/491b7661614ab97483abf2056be1deee4dc2490ecbf7bff9ab5cdbac86e1/pyreadline3-3.5.4-py3-none-any.whl", hash = "sha256:eaf8e6cc3c49bcccf145fc6067ba8643d1df34d604a1ec0eccbf7a18e6d3fae6", size = 83178, upload-time = "2024-09-19T02:40:08.598Z" },
1646
  ]
1647
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1648
  [[package]]
1649
  name = "pytest"
1650
  version = "9.0.2"
 
242
  { name = "gradio", extra = ["mcp"] },
243
  { name = "m3u8" },
244
  { name = "mem0ai" },
 
245
  { name = "rich" },
246
  ]
247
 
 
249
  dev = [
250
  { name = "doppler-env" },
251
  { name = "pre-commit" },
252
+ { name = "pyrefly" },
253
  { name = "pytest-emoji" },
254
  { name = "pytest-md" },
255
  { name = "pytest-mergify" },
 
266
  { name = "gradio", extras = ["mcp"], specifier = ">=6.5.1" },
267
  { name = "m3u8", specifier = ">=6.0.0" },
268
  { name = "mem0ai", specifier = ">=1.0.2" },
 
269
  { name = "rich", specifier = ">=14.3.1" },
270
  ]
271
 
 
273
  dev = [
274
  { name = "doppler-env", specifier = ">=0.3.1" },
275
  { name = "pre-commit", specifier = ">=4.5.1" },
276
+ { name = "pyrefly", specifier = ">=0.46.1" },
277
  { name = "pytest-emoji", specifier = ">=0.2.0" },
278
  { name = "pytest-md", specifier = ">=0.2.0" },
279
  { name = "pytest-mergify", specifier = ">=2026.1.26.1" },
 
1112
  { url = "https://files.pythonhosted.org/packages/88/b2/d0896bdcdc8d28a7fc5717c305f1a861c26e18c05047949fb371034d98bd/nodeenv-1.10.0-py2.py3-none-any.whl", hash = "sha256:5bb13e3eed2923615535339b3c620e76779af4cb4c6a90deccc9e36b274d3827", size = 23438, upload-time = "2025-12-20T14:08:52.782Z" },
1113
  ]
1114
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1115
  [[package]]
1116
  name = "numpy"
1117
  version = "2.4.1"
 
1383
  { url = "https://files.pythonhosted.org/packages/54/20/4d324d65cc6d9205fabedc306948156824eb9f0ee1633355a8f7ec5c66bf/pluggy-1.6.0-py3-none-any.whl", hash = "sha256:e920276dd6813095e9377c0bc5566d94c932c33b27a3e3945d8389c374dd4746", size = 20538, upload-time = "2025-05-15T12:30:06.134Z" },
1384
  ]
1385
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1386
  [[package]]
1387
  name = "portalocker"
1388
  version = "3.2.0"
 
1601
  { url = "https://files.pythonhosted.org/packages/5a/dc/491b7661614ab97483abf2056be1deee4dc2490ecbf7bff9ab5cdbac86e1/pyreadline3-3.5.4-py3-none-any.whl", hash = "sha256:eaf8e6cc3c49bcccf145fc6067ba8643d1df34d604a1ec0eccbf7a18e6d3fae6", size = 83178, upload-time = "2024-09-19T02:40:08.598Z" },
1602
  ]
1603
 
1604
+ [[package]]
1605
+ name = "pyrefly"
1606
+ version = "0.46.1"
1607
+ source = { registry = "https://pypi.org/simple" }
1608
+ sdist = { url = "https://files.pythonhosted.org/packages/8d/7e/b4f9f26611f72405af16af916f460025bd6d40d00952a046eab0df98bb82/pyrefly-0.46.1.tar.gz", hash = "sha256:ea6db4788cd11eb7fd7ef7f0bdeef4621861cb44cd7d62db073706022669ef4a", size = 4760174, upload-time = "2025-12-23T23:06:10.501Z" }
1609
+ wheels = [
1610
+ { url = "https://files.pythonhosted.org/packages/16/46/8f9d4400e4d60da6555415351b11cbe5e122cfa299194278ebf7bcf26cd3/pyrefly-0.46.1-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:f4975d4d2a451423727f70461bd1ef3f18c6c8c0e4bb5acf902add73bdaf6642", size = 11659836, upload-time = "2025-12-23T23:05:49.879Z" },
1611
+ { url = "https://files.pythonhosted.org/packages/3b/15/486b8ea769560e65152201df5d887c9f817fa4e536388e86eb6b1ce774f0/pyrefly-0.46.1-py3-none-macosx_11_0_arm64.whl", hash = "sha256:bcecd921990e56759e7ec2c91ab69aaf790dcc6c17b36054d0f42789085e0dde", size = 11269185, upload-time = "2025-12-23T23:05:52.423Z" },
1612
+ { url = "https://files.pythonhosted.org/packages/33/bc/b5982fc9dfe2abe5d5341a3576aca3c8c5e3af24223b56d256f16df1d31b/pyrefly-0.46.1-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:262f6ff2c593ec575eb626dbb3309d9fbb1527cbb0dab2b4d6ae8c8f51bf2715", size = 31504426, upload-time = "2025-12-23T23:05:54.692Z" },
1613
+ { url = "https://files.pythonhosted.org/packages/05/fd/34c9dec50075bbf471c23ec46ccca4b167490a3418aef351cfd0cdd7feeb/pyrefly-0.46.1-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:adccc7e54952a3788f7a108abc3177f9ad83b56b052fc0cb1ed7a93da5c69f71", size = 33721544, upload-time = "2025-12-23T23:05:57.465Z" },
1614
+ { url = "https://files.pythonhosted.org/packages/fe/2f/7c9dcf8b77ad3e3579fe7a8d2eaf3a2df8a31e8be7bc5561b369e0bc73f8/pyrefly-0.46.1-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7251eec7366a3a4df5e87214300645c8f7d27b1339cf30b166227aa8f07979d9", size = 34778153, upload-time = "2025-12-23T23:06:00.313Z" },
1615
+ { url = "https://files.pythonhosted.org/packages/5d/1f/6ffa777f3a8f1a66a96ff5b6a6f1659e2172662fec5fcbce5db0f3ff617d/pyrefly-0.46.1-py3-none-win32.whl", hash = "sha256:a5babc50ebfc2227e4209697e4e5754a10935cedba3ab26d26fd3e20625b6479", size = 10728406, upload-time = "2025-12-23T23:06:02.863Z" },
1616
+ { url = "https://files.pythonhosted.org/packages/f7/34/7faaee043cc6b268010e0124a82bb5793588531e3d4af2e3283588d88eb7/pyrefly-0.46.1-py3-none-win_amd64.whl", hash = "sha256:e2a784530ad8c918ad7f656957c9db8d00e484111298a6601490141cabd9966a", size = 11418624, upload-time = "2025-12-23T23:06:06.16Z" },
1617
+ { url = "https://files.pythonhosted.org/packages/58/4f/13e0e1c2136d35c44a034c9606bce2513ed3e896df86985fedd9c1347432/pyrefly-0.46.1-py3-none-win_arm64.whl", hash = "sha256:1835206055454cc2b88bc0b6acb557c2e5bd9ae8df724bb48fd2dc3dc40ffe13", size = 10964488, upload-time = "2025-12-23T23:06:08.165Z" },
1618
+ ]
1619
+
1620
  [[package]]
1621
  name = "pytest"
1622
  version = "9.0.2"