feat: merge Elf into Bavarder
All checks were successful
ci/woodpecker/push/<no value> Pipeline was successful
26
Cargo.toml
|
@ -1,26 +0,0 @@
|
|||
[package]
|
||||
name = "bavarder"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
env_logger = "0.10.0"
|
||||
|
||||
[dependencies.gtk]
|
||||
package = "gtk4"
|
||||
version = "0.6.2"
|
||||
features = ["v4_10", "xml_validation"]
|
||||
|
||||
[dependencies.gio]
|
||||
package = "gio"
|
||||
version = "0.17.0"
|
||||
features = ["v2_74"]
|
||||
|
||||
[dependencies.adw]
|
||||
package = "libadwaita"
|
||||
version = "0.4.1"
|
||||
features = ["v1_4"]
|
||||
|
||||
[dependencies.gettext-rs]
|
||||
version = "0.7.0"
|
||||
features = ["gettext-system"]
|
127
README.md
|
@ -1,126 +1,3 @@
|
|||
<a href="https://bavarder.codeberg.page">
|
||||
<h1 align="center">
|
||||
<img src="data/icons/hicolor/scalable/apps/io.github.Bavarder.Bavarder.svg" alt="Bavarder" width="192" height="192"/>
|
||||
<br>
|
||||
Bavarder
|
||||
</h1>
|
||||
# bavarder
|
||||
|
||||
<p align="center">
|
||||
<strong>Chit-chat with an AI</strong>
|
||||
</p>
|
||||
</a>
|
||||
|
||||
<p align="center">
|
||||
<a href="https://flathub.org/apps/details/io.github.Bavarder.Bavarder">
|
||||
<img width="200" alt="Download on Flathub" src="https://dl.flathub.org/assets/badges/flathub-badge-i-en.svg"/>
|
||||
</a>
|
||||
<br>
|
||||
</p>
|
||||
|
||||
<br>
|
||||
|
||||
<p align="center">
|
||||
<a href="https://translate.codeberg.org/engage/bavarder/">
|
||||
<img src="https://translate.codeberg.org/widgets/bavarder/-/svg-badge.svg" alt="Translation status" />
|
||||
</a>
|
||||
<a href="https://repology.org/project/bavarder/versions">
|
||||
<img alt="Packaging status" src="https://repology.org/badge/tiny-repos/bavarder.svg">
|
||||
</a>
|
||||
<a href="https://snapcraft.io/bavarder">
|
||||
<img alt="bavarder" src="https://snapcraft.io/bavarder/badge.svg" />
|
||||
</a>
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
<a href="https://stopthemingmy.app">
|
||||
<img alt="Please do not theme this app" src="https://stopthemingmy.app/badge.svg"/>
|
||||
</a>
|
||||
</p>
|
||||
|
||||
<a href="https://bavarder.codeberg.page">
|
||||
<p align="center">
|
||||
<img src="./data/screenshots/preview.png" alt="Preview"/>
|
||||
</p>
|
||||
</a>
|
||||
|
||||
## Usage
|
||||
|
||||
Documentation is available [here](https://bavarder.codeberg.page)
|
||||
|
||||
## Installation
|
||||
|
||||
### Flatpak
|
||||
|
||||
You can either use your GNOME Software and search for "Bavarder" or you can run
|
||||
|
||||
``` shell
|
||||
flatpak install io.github.Bavarder.Bavarder
|
||||
```
|
||||
|
||||
### Latest
|
||||
|
||||
You can download a flatpak from the latest commit [here](https://codeberg.org/Bavarder/-/packages/generic/bavarder/). Run
|
||||
|
||||
``` shell
|
||||
curl -s -o bavarder.flatpak https://codeberg.org/api/packages/Bavarder/generic/Bavarder/164/bavarder.flatpak && flatpak install --user bavarder.flatpak -y
|
||||
```
|
||||
|
||||
#### From Source
|
||||
|
||||
### Flatpak-builder
|
||||
|
||||
Clone the repo and run `flatpak-builder`
|
||||
|
||||
``` shell
|
||||
git clone https://codeberg.org/Bavarder/Bavarder # or https://github.com/Bavarder/Bavarder
|
||||
cd Bavarder
|
||||
flatpak-builder --install --user --force-clean repo/ build-aux/flatpak/io.github.Bavarder.Bavarder.json
|
||||
```
|
||||
### Meson
|
||||
``` shell
|
||||
git clone https://codeberg.org/Bavarder/Bavarder # or https://github.com/Bavarder/Bavarder
|
||||
cd Bavarder
|
||||
meson setup build # Configure the build environment in subdirectory 'build'
|
||||
meson compile -C build
|
||||
meson check -C build
|
||||
meson install -C build
|
||||
chmod 0755 /usr/local/bin/bavarder # Fix binary permissions
|
||||
```
|
||||
|
||||
|
||||
### Others
|
||||
|
||||
You can see more install methods on the [website](https://bavarder.codeberg.page/install/)
|
||||
|
||||
## Contribute
|
||||
|
||||
The [GNOME Code of Conduct](https://wiki.gnome.org/Foundation/CodeOfConduct) is applicable to this project
|
||||
|
||||
See [`SEEN.md`](./SEEN.md) for a list of articles and posts about Bavarder
|
||||
|
||||
### Translate
|
||||
|
||||
<a href="https://translate.codeberg.org/engage/bavarder/">
|
||||
<img src="https://translate.codeberg.org/widgets/bavarder/-/multi-auto.svg" alt="Translation status" />
|
||||
</a>
|
||||
|
||||
You can translate Bavarder using [Codeberg Translate](https://translate.codeberg.org/engage/bavarder/)
|
||||
|
||||
### Mirrors
|
||||
|
||||
- [GitHub](https://github.com/Bavarder/Bavarder)
|
||||
- [GitLab](https://gitlab.com/Bavarder/Bavarder)
|
||||
- [Codeberg](https://codeberg.org/Bavarder/Bavarder)
|
||||
|
||||
## About the name
|
||||
|
||||
Bavarder is a french word, the definiton of Bavarder is "Parler abondamment de choses sans grande portée" (Talking a lot about things that don't matter) (Larousse) which can be translated by Chit-Chat (informal conversation about matters that are not important). For non-french speakers, Bavarder can be hard to speak, it's prounouced as [bavaʀde]. Hear [here](https://youtu.be/9Qoogwxo5YA)
|
||||
|
||||
## See also
|
||||
|
||||
### [Imaginer : Imagine with AI](https://imaginer.codeberg.page)
|
||||
|
||||
A tool for generating pictures with AI (GNOME app)
|
||||
|
||||
- [GitHub](https://github.com/ImaginerApp/Imaginer)
|
||||
- [Codeberg](https://codeberg.org/Imaginer/Imaginer)
|
||||
A description of this project.
|
||||
|
|
47
SEEN.md
|
@ -1,47 +0,0 @@
|
|||
# Where Bavarder has been seen
|
||||
|
||||
## Press
|
||||
|
||||
- https://www.omgubuntu.co.uk/2023/05/bavarder-chatgpt-linux-app
|
||||
- https://gnulinux.ch/bavarder-chatgpt-ohne-account
|
||||
- https://infoidevice.fr/bavarder-application-chatgpt-linux/
|
||||
- https://sempreupdate.com.br/como-instalar-o-chat-bavarder-no-linux/
|
||||
- https://www.linuxjournal.com/content/introducing-bavarder-user-friendly-linux-desktop-app-quick-chatgpt-interaction
|
||||
- https://fostips.com/bavarder-open-source-ai-chat-linux/
|
||||
- https://voyagerlive.org/voyager-chatgpt/
|
||||
- https://plus.diolinux.com.br/t/bavarder-um-aplicativo-de-chatgpt-para-linux/53155
|
||||
- https://mindaizer.com/chatgpt-et-linux-presentation-de-bavarder/
|
||||
- https://wiredgorilla.com/introducing-bavarder-a-user-friendly-linux-desktop-app-for-quick-chatgpt-interaction/
|
||||
- https://www.linuxconsultant.org/bavarder-is-a-chatgpt-app-for-linux-desktops/
|
||||
- https://www.linuxlinks.com/machine-learning-linux-bavarder/
|
||||
- https://www.root.cz/clanky/softwarova-sklizen-24-5-2023-organizace-casu-systemem-kanban/
|
||||
- https://www.makeuseof.com/use-chatgpt-on-linux-with-bavarder/
|
||||
|
||||
## Youtube
|
||||
|
||||
- https://youtu.be/dtAi2ejMwrk
|
||||
- https://youtu.be/bXcSEGb8IPE
|
||||
|
||||
## Fediverse
|
||||
|
||||
- https://bassam.social/notice/AVII4g9FPM0sD1bMWW
|
||||
- https://pleroma.destroyallmachines.net/notice/AVHg9tnvMACshmHJL6
|
||||
- https://floss.social/@omgubuntu/110304976747139717
|
||||
- https://mastodon.social/@geekland/110305211402821977
|
||||
- And more
|
||||
|
||||
## Twitter
|
||||
|
||||
- https://twitter.com/omgubuntu/status/1653752319660417024
|
||||
- https://twitter.com/linuxern00b/status/1653754427373936645
|
||||
- https://twitter.com/infoidevice/status/1653996236461023232
|
||||
- https://twitter.com/search?q=bavarder%20linux&src=typed_query&f=top
|
||||
- And more
|
||||
|
||||
## Misc
|
||||
|
||||
- https://alternativeto.net/software/bavarder/
|
||||
- https://linuxphoneapps.org/apps/io.github.bavarder.bavarder/
|
||||
- https://www.linuxquestions.org/questions/showthread.php?s=7c645a66bd3800801946c6f238e2ee25&p=6429159#post6429159
|
||||
- http://lxer.com/module/newswire/view/329486/index.html
|
||||
- https://www.prime-wow.com/?p=1136455
|
|
@ -1,22 +0,0 @@
|
|||
<Project xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#"
|
||||
xmlns:foaf="http://xmlns.com/foaf/0.1/"
|
||||
xmlns:gnome="http://api.gnome.org/doap-extensions#"
|
||||
xmlns="http://usefulinc.com/ns/doap#">
|
||||
|
||||
<name xml:lang="en">Bavarder</name>
|
||||
<shortdesc xml:lang="en">Chit-chat with an AI</shortdesc>
|
||||
<homepage rdf:resource="https://github.com/Bavarder/Bavarder" />
|
||||
<bug-database rdf:resource="https://github.com/Bavarder/Bavarder/issues"/>
|
||||
<programming-language>Python</programming-language>
|
||||
<platform>GTK 4</platform>
|
||||
<platform>Libadwaita</platform>
|
||||
|
||||
|
||||
<maintainer>
|
||||
<foaf:Person>
|
||||
<foaf:name>0xMRTT</foaf:name>
|
||||
<foaf:mbox rdf:resource="mailto:0xMRTT@proton.me" />
|
||||
</foaf:Person>
|
||||
</maintainer>
|
||||
</Project>
|
|
@ -1,54 +0,0 @@
|
|||
{
|
||||
"app-id" : "io.github.Bavarder.Bavarder.Devel",
|
||||
"runtime" : "org.gnome.Platform",
|
||||
"runtime-version" : "master",
|
||||
"sdk" : "org.gnome.Sdk",
|
||||
"command" : "bavarder",
|
||||
"finish-args" : [
|
||||
"--share=network",
|
||||
"--share=ipc",
|
||||
"--socket=fallback-x11",
|
||||
"--device=dri",
|
||||
"--socket=wayland",
|
||||
"--filesystem=xdg-config/gtk-4.0"
|
||||
],
|
||||
"cleanup" : [
|
||||
"/include",
|
||||
"/lib/pkgconfig",
|
||||
"/man",
|
||||
"/share/doc",
|
||||
"/share/gtk-doc",
|
||||
"/share/man",
|
||||
"/share/pkgconfig",
|
||||
"*.la",
|
||||
"*.a"
|
||||
],
|
||||
"modules" : [
|
||||
"pypi-dependencies.json",
|
||||
{
|
||||
"name" : "blueprint-compiler",
|
||||
"buildsystem" : "meson",
|
||||
"sources" : [
|
||||
{
|
||||
"type" : "git",
|
||||
"url" : "https://gitlab.gnome.org/jwestman/blueprint-compiler.git",
|
||||
"branch" : "main"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name" : "bavarder",
|
||||
"builddir" : true,
|
||||
"buildsystem" : "meson",
|
||||
"config-opts": [
|
||||
"-Dbuildtype=debug"
|
||||
],
|
||||
"sources" : [
|
||||
{
|
||||
"type" : "dir",
|
||||
"path" : "../../."
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"app-id" : "io.github.Bavarder.Bavarder",
|
||||
"runtime" : "org.gnome.Platform",
|
||||
"runtime-version" : "44",
|
||||
"runtime-version" : "master",
|
||||
"sdk" : "org.gnome.Sdk",
|
||||
"command" : "bavarder",
|
||||
"finish-args" : [
|
||||
|
@ -10,7 +10,7 @@
|
|||
"--socket=fallback-x11",
|
||||
"--device=dri",
|
||||
"--socket=wayland",
|
||||
"--filesystem=xdg-config/gtk-4.0"
|
||||
"--talk-name=org.freedesktop.Flatpak"
|
||||
],
|
||||
"cleanup" : [
|
||||
"/include",
|
||||
|
@ -24,9 +24,7 @@
|
|||
"*.a"
|
||||
],
|
||||
"modules" : [
|
||||
|
||||
"pypi-dependencies.json",
|
||||
{
|
||||
{
|
||||
"name" : "blueprint-compiler",
|
||||
"buildsystem" : "meson",
|
||||
"sources" : [
|
||||
|
@ -38,16 +36,47 @@
|
|||
]
|
||||
},
|
||||
{
|
||||
"name" : "bavarder",
|
||||
"builddir" : true,
|
||||
"name" : "libportal",
|
||||
"buildsystem" : "meson",
|
||||
|
||||
"config-opts": [
|
||||
"-Dbuildtype=release"
|
||||
"-Dbackend-gtk4=enabled",
|
||||
"-Dportal-tests=false",
|
||||
"-Ddocs=false"
|
||||
],
|
||||
"sources" : [
|
||||
{
|
||||
"type" : "git",
|
||||
"url" : "https://github.com/flatpak/libportal.git",
|
||||
"branch": "main"
|
||||
|
||||
}
|
||||
]
|
||||
},
|
||||
"pypi-dependencies.json",
|
||||
{
|
||||
"name": "gpt4all",
|
||||
"buildsystem": "simple",
|
||||
"build-commands": [
|
||||
"cd gpt4all-backend/ && mkdir build && cd build && cmake .. && cmake --build . --parallel",
|
||||
"cd gpt4all-bindings/python && pip wheel --no-deps -w dist . && ls && ls dist && pip3 install \"dist/gpt4all-1.0.6-py3-none-any.whl\" --verbose --exists-action=i --no-index --prefix=${FLATPAK_DEST} --no-build-isolation"
|
||||
],
|
||||
"sources": [
|
||||
{
|
||||
"type": "git",
|
||||
"url": "https://github.com/nomic-ai/gpt4all",
|
||||
"branch": "main"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name" : "bavarder",
|
||||
"builddir" : true,
|
||||
"buildsystem" : "meson",
|
||||
"sources" : [
|
||||
{
|
||||
"type" : "dir",
|
||||
"path" : "../../."
|
||||
"path" : "../../."
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
@ -1,155 +0,0 @@
|
|||
{
|
||||
"app-id" : "io.github.Bavarder.Bavarder",
|
||||
"runtime" : "org.gnome.Platform",
|
||||
"runtime-version" : "44",
|
||||
"sdk" : "org.gnome.Sdk",
|
||||
"command" : "bavarder",
|
||||
"finish-args" : [
|
||||
"--share=network",
|
||||
"--share=ipc",
|
||||
"--socket=fallback-x11",
|
||||
"--device=dri",
|
||||
"--socket=wayland",
|
||||
"--filesystem=xdg-config/gtk-4.0"
|
||||
],
|
||||
"cleanup" : [
|
||||
"/include",
|
||||
"/lib/pkgconfig",
|
||||
"/man",
|
||||
"/share/doc",
|
||||
"/share/gtk-doc",
|
||||
"/share/man",
|
||||
"/share/pkgconfig",
|
||||
"*.la",
|
||||
"*.a"
|
||||
],
|
||||
"modules" : [
|
||||
"pypi-dependencies.json",
|
||||
{
|
||||
"name" : "libsass",
|
||||
"buildsystem" : "meson",
|
||||
"sources" : [
|
||||
{
|
||||
"type" : "git",
|
||||
"url" : "https://github.com/lazka/libsass.git",
|
||||
"branch" : "meson"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name" : "sassc",
|
||||
"buildsystem" : "meson",
|
||||
"sources" : [
|
||||
{
|
||||
"type" : "git",
|
||||
"url" : "https://github.com/lazka/sassc.git",
|
||||
"branch" : "meson"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "libyaml",
|
||||
"buildsystem": "autotools",
|
||||
"builddir": true,
|
||||
"config-opts": [
|
||||
"--libdir=/app/lib"
|
||||
],
|
||||
"sources": [
|
||||
{
|
||||
"type": "git",
|
||||
"url": "https://github.com/yaml/libyaml"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "lmdb",
|
||||
"buildsystem": "simple",
|
||||
"subdir": "libraries/liblmdb",
|
||||
"build-commands": [
|
||||
"make install prefix=/ DESTDIR=/app"
|
||||
],
|
||||
"sources": [
|
||||
{
|
||||
"type": "git",
|
||||
"url": "https://git.openldap.org/openldap/openldap.git"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "libxmlb",
|
||||
"buildsystem": "meson",
|
||||
"config-opts": [
|
||||
"-Dgtkdoc=false"
|
||||
],
|
||||
"sources": [
|
||||
{
|
||||
"type": "git",
|
||||
"url": "https://github.com/hughsie/libxmlb.git",
|
||||
"branch": "main"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "appstream",
|
||||
"buildsystem": "meson",
|
||||
"config-opts": [
|
||||
"-Dstemming=false",
|
||||
"-Dapidocs=false"
|
||||
],
|
||||
"sources": [
|
||||
{
|
||||
"type": "git",
|
||||
"url": "https://github.com/ximion/appstream.git/",
|
||||
"branch": "main"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "gtk",
|
||||
"buildsystem": "meson",
|
||||
"sources": [
|
||||
{
|
||||
"type": "git",
|
||||
"url": "https://gitlab.gnome.org/GNOME/gtk.git",
|
||||
"branch": "main"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "libadwaita",
|
||||
"buildsystem": "meson",
|
||||
"sources": [
|
||||
{
|
||||
"type": "git",
|
||||
"url": "https://gitlab.gnome.org/GNOME/libadwaita.git",
|
||||
"branch": "main"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name" : "blueprint-compiler",
|
||||
"buildsystem" : "meson",
|
||||
"sources" : [
|
||||
{
|
||||
"type" : "git",
|
||||
"url" : "https://gitlab.gnome.org/jwestman/blueprint-compiler.git",
|
||||
"tag" : "v0.8.1"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name" : "bavarder",
|
||||
"builddir" : true,
|
||||
"buildsystem" : "meson",
|
||||
"config-opts": [
|
||||
"-Dbuildtype=release"
|
||||
],
|
||||
"sources" : [
|
||||
{
|
||||
"type" : "dir",
|
||||
"path" : "../../."
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
|
@ -3,177 +3,6 @@
|
|||
"buildsystem": "simple",
|
||||
"build-commands": [],
|
||||
"modules": [
|
||||
{
|
||||
"name": "python3-baichat_py",
|
||||
"buildsystem": "simple",
|
||||
"build-commands": [
|
||||
"pip3 install --verbose --exists-action=i --no-index --find-links=\"file://${PWD}\" --prefix=${FLATPAK_DEST} \"baichat_py\" --no-build-isolation"
|
||||
],
|
||||
"sources": [
|
||||
{
|
||||
"type": "file",
|
||||
"url": "https://files.pythonhosted.org/packages/6f/a9/aad1eb9134fe0574b281ad1308fe029cf4ec1ba49ba0a061a18dd3ced789/baichat_py-0.3.0-py3-none-any.whl",
|
||||
"sha256": "aa641939844ea364dcee0c4f40cdca2c42b7d6ed5f0cb360c29f7e35300259d0"
|
||||
},
|
||||
{
|
||||
"type": "file",
|
||||
"url": "https://files.pythonhosted.org/packages/2b/a8/050ab4f0c3d4c1b8aaa805f70e26e84d0e27004907c5b8ecc1d31815f92a/cffi-1.15.1.tar.gz",
|
||||
"sha256": "d400bfb9a37b1351253cb402671cea7e89bdecc294e8016a707f6d1d8ac934f9"
|
||||
},
|
||||
{
|
||||
"type": "file",
|
||||
"url": "https://files.pythonhosted.org/packages/d1/6f/5d591a5628423af4598e2d6ff0861fcbc554cc259590fac9f97d9c984611/curl_cffi-0.5.6-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",
|
||||
"sha256": "7a9df9fabff038f1ac9e7e6f32b5edb5d8df8c2eec64f53f513de1766c17ffdb"
|
||||
},
|
||||
{
|
||||
"type": "file",
|
||||
"url": "https://files.pythonhosted.org/packages/8d/f3/28e7af53e09c9218140901dc23fdd75cdaf3e64d1d06f61801cf2a841bcb/fake_useragent-1.1.3-py3-none-any.whl",
|
||||
"sha256": "695d3b1bf7d11d04ab0f971fb73b0ca8de98b78bbadfbc8bacbc9a48423f7531"
|
||||
},
|
||||
{
|
||||
"type": "file",
|
||||
"url": "https://files.pythonhosted.org/packages/62/d5/5f610ebe421e85889f2e55e33b7f9a6795bd982198517d912eb1c76e1a53/pycparser-2.21-py2.py3-none-any.whl",
|
||||
"sha256": "8ee45429555515e1f6b185e78100aea234072576aa43ab53aefcae078162fca9"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "python3-googlebardpy",
|
||||
"buildsystem": "simple",
|
||||
"build-commands": [
|
||||
"pip3 install --verbose --exists-action=i --no-index --find-links=\"file://${PWD}\" --prefix=${FLATPAK_DEST} \"googlebardpy\" --no-build-isolation"
|
||||
],
|
||||
"sources": [
|
||||
{
|
||||
"type": "file",
|
||||
"url": "https://files.pythonhosted.org/packages/9d/19/59961b522e6757f0c9097e4493fa906031b95b3ebe9360b2c3083561a6b4/certifi-2023.5.7-py3-none-any.whl",
|
||||
"sha256": "c6c2e98f5c7869efca1f8916fed228dd91539f9f1b444c314c06eef02980c716"
|
||||
},
|
||||
{
|
||||
"type": "file",
|
||||
"url": "https://files.pythonhosted.org/packages/ff/d7/8d757f8bd45be079d76309248845a04f09619a7b17d6dfc8c9ff6433cac2/charset-normalizer-3.1.0.tar.gz",
|
||||
"sha256": "34e0a2f9c370eb95597aae63bf85eb5e96826d81e3dcf88b8886012906f509b5"
|
||||
},
|
||||
{
|
||||
"type": "file",
|
||||
"url": "https://files.pythonhosted.org/packages/a8/40/30a6440d5ceec49fc268710705b89e654fc854d9b8754850228deaf64892/googlebardpy-0.1.0-py3-none-any.whl",
|
||||
"sha256": "12e65fdfe99392cbb5e8f93572340b757cd9d7aa83391316eaea3a1527995ef2"
|
||||
},
|
||||
{
|
||||
"type": "file",
|
||||
"url": "https://files.pythonhosted.org/packages/fc/34/3030de6f1370931b9dbb4dad48f6ab1015ab1d32447850b9fc94e60097be/idna-3.4-py3-none-any.whl",
|
||||
"sha256": "90b77e79eaa3eba6de819a0c442c0b4ceefc341a7a2ab77d7562bf49f425c5c2"
|
||||
},
|
||||
{
|
||||
"type": "file",
|
||||
"url": "https://files.pythonhosted.org/packages/70/8e/0e2d847013cb52cd35b38c009bb167a1a26b2ce6cd6965bf26b47bc0bf44/requests-2.31.0-py3-none-any.whl",
|
||||
"sha256": "58cd2187c01e70e6e26505bca751777aa9f2ee0b7f4300988b709f44e013003f"
|
||||
},
|
||||
{
|
||||
"type": "file",
|
||||
"url": "https://files.pythonhosted.org/packages/4b/1d/f8383ef593114755429c307449e7717b87044b3bcd5f7860b89b1f759e34/urllib3-2.0.2-py3-none-any.whl",
|
||||
"sha256": "d055c2f9d38dc53c808f6fdc8eab7360b6fdbbde02340ed25cfbcd817c62469e"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "python3-openai",
|
||||
"buildsystem": "simple",
|
||||
"build-commands": [
|
||||
"pip3 install --verbose --exists-action=i --no-index --find-links=\"file://${PWD}\" --prefix=${FLATPAK_DEST} \"openai\" --no-build-isolation"
|
||||
],
|
||||
"sources": [
|
||||
{
|
||||
"type": "file",
|
||||
"url": "https://files.pythonhosted.org/packages/c2/fd/1ff4da09ca29d8933fda3f3514980357e25419ce5e0f689041edb8f17dab/aiohttp-3.8.4.tar.gz",
|
||||
"sha256": "bf2e1a9162c1e441bf805a1fd166e249d574ca04e03b34f97e2928769e91ab5c"
|
||||
},
|
||||
{
|
||||
"type": "file",
|
||||
"url": "https://files.pythonhosted.org/packages/76/ac/a7305707cb852b7e16ff80eaf5692309bde30e2b1100a1fcacdc8f731d97/aiosignal-1.3.1-py3-none-any.whl",
|
||||
"sha256": "f8376fb07dd1e86a584e4fcdec80b36b7f81aac666ebc724e2c090300dd83b17"
|
||||
},
|
||||
{
|
||||
"type": "file",
|
||||
"url": "https://files.pythonhosted.org/packages/d6/c1/8991e7c5385b897b8c020cdaad718c5b087a6626d1d11a23e1ea87e325a7/async_timeout-4.0.2-py3-none-any.whl",
|
||||
"sha256": "8ca1e4fcf50d07413d66d1a5e416e42cfdf5851c981d679a09851a6853383b3c"
|
||||
},
|
||||
{
|
||||
"type": "file",
|
||||
"url": "https://files.pythonhosted.org/packages/f0/eb/fcb708c7bf5056045e9e98f62b93bd7467eb718b0202e7698eb11d66416c/attrs-23.1.0-py3-none-any.whl",
|
||||
"sha256": "1f28b4522cdc2fb4256ac1a020c78acf9cba2c6b461ccd2c126f3aa8e8335d04"
|
||||
},
|
||||
{
|
||||
"type": "file",
|
||||
"url": "https://files.pythonhosted.org/packages/9d/19/59961b522e6757f0c9097e4493fa906031b95b3ebe9360b2c3083561a6b4/certifi-2023.5.7-py3-none-any.whl",
|
||||
"sha256": "c6c2e98f5c7869efca1f8916fed228dd91539f9f1b444c314c06eef02980c716"
|
||||
},
|
||||
{
|
||||
"type": "file",
|
||||
"url": "https://files.pythonhosted.org/packages/ff/d7/8d757f8bd45be079d76309248845a04f09619a7b17d6dfc8c9ff6433cac2/charset-normalizer-3.1.0.tar.gz",
|
||||
"sha256": "34e0a2f9c370eb95597aae63bf85eb5e96826d81e3dcf88b8886012906f509b5"
|
||||
},
|
||||
{
|
||||
"type": "file",
|
||||
"url": "https://files.pythonhosted.org/packages/e9/10/d629476346112b85c912527b9080944fd2c39a816c2225413dbc0bb6fcc0/frozenlist-1.3.3.tar.gz",
|
||||
"sha256": "58bcc55721e8a90b88332d6cd441261ebb22342e238296bb330968952fbb3a6a"
|
||||
},
|
||||
{
|
||||
"type": "file",
|
||||
"url": "https://files.pythonhosted.org/packages/fc/34/3030de6f1370931b9dbb4dad48f6ab1015ab1d32447850b9fc94e60097be/idna-3.4-py3-none-any.whl",
|
||||
"sha256": "90b77e79eaa3eba6de819a0c442c0b4ceefc341a7a2ab77d7562bf49f425c5c2"
|
||||
},
|
||||
{
|
||||
"type": "file",
|
||||
"url": "https://files.pythonhosted.org/packages/4a/15/bd620f7a6eb9aa5112c4ef93e7031bcd071e0611763d8e17706ef8ba65e0/multidict-6.0.4.tar.gz",
|
||||
"sha256": "3666906492efb76453c0e7b97f2cf459b0682e7402c0489a95484965dbc1da49"
|
||||
},
|
||||
{
|
||||
"type": "file",
|
||||
"url": "https://files.pythonhosted.org/packages/35/c3/de7124146c3edbe8fd8163028d9ac998f2fd5dcda9225655f1d4ed684bbc/openai-0.27.7-py3-none-any.whl",
|
||||
"sha256": "788fb7fa85bf7caac6c1ed7eea5984254a1bdaf09ef485acf0e5718c8b2dc25a"
|
||||
},
|
||||
{
|
||||
"type": "file",
|
||||
"url": "https://files.pythonhosted.org/packages/70/8e/0e2d847013cb52cd35b38c009bb167a1a26b2ce6cd6965bf26b47bc0bf44/requests-2.31.0-py3-none-any.whl",
|
||||
"sha256": "58cd2187c01e70e6e26505bca751777aa9f2ee0b7f4300988b709f44e013003f"
|
||||
},
|
||||
{
|
||||
"type": "file",
|
||||
"url": "https://files.pythonhosted.org/packages/e6/02/a2cff6306177ae6bc73bc0665065de51dfb3b9db7373e122e2735faf0d97/tqdm-4.65.0-py3-none-any.whl",
|
||||
"sha256": "c4f53a17fe37e132815abceec022631be8ffe1b9381c2e6e30aa70edc99e9671"
|
||||
},
|
||||
{
|
||||
"type": "file",
|
||||
"url": "https://files.pythonhosted.org/packages/4b/1d/f8383ef593114755429c307449e7717b87044b3bcd5f7860b89b1f759e34/urllib3-2.0.2-py3-none-any.whl",
|
||||
"sha256": "d055c2f9d38dc53c808f6fdc8eab7360b6fdbbde02340ed25cfbcd817c62469e"
|
||||
},
|
||||
{
|
||||
"type": "file",
|
||||
"url": "https://files.pythonhosted.org/packages/5f/3f/04b3c5e57844fb9c034b09c5cb6d2b43de5d64a093c30529fd233e16cf09/yarl-1.9.2.tar.gz",
|
||||
"sha256": "04ab9d4b9f587c06d801c2abfe9317b77cdf996c65a90d5e84ecc45010823571"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "python3-pymdown-extensions",
|
||||
"buildsystem": "simple",
|
||||
"build-commands": [
|
||||
"pip3 install --verbose --exists-action=i --no-index --find-links=\"file://${PWD}\" --prefix=${FLATPAK_DEST} \"pymdown-extensions\" --no-build-isolation"
|
||||
],
|
||||
"sources": [
|
||||
{
|
||||
"type": "file",
|
||||
"url": "https://files.pythonhosted.org/packages/36/2b/61d51a2c4f25ef062ae3f74576b01638bebad5e045f747ff12643df63844/PyYAML-6.0.tar.gz",
|
||||
"sha256": "68fb519c14306fec9720a2a5b45bc9f0c8d1b9c72adf45c37baedfcd949c35a2"
|
||||
},
|
||||
{
|
||||
"type": "file",
|
||||
"url": "https://files.pythonhosted.org/packages/a2/17/607fc71d709c0df9cca39ed57ed6f8b1cb77863073004c7def8a02a45fe2/pymdown_extensions-10.0.1-py3-none-any.whl",
|
||||
"sha256": "ae66d84013c5d027ce055693e09a4628b67e9dec5bce05727e45b0918e36f274"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "python3-requests",
|
||||
"buildsystem": "simple",
|
||||
|
@ -188,8 +17,8 @@
|
|||
},
|
||||
{
|
||||
"type": "file",
|
||||
"url": "https://files.pythonhosted.org/packages/ff/d7/8d757f8bd45be079d76309248845a04f09619a7b17d6dfc8c9ff6433cac2/charset-normalizer-3.1.0.tar.gz",
|
||||
"sha256": "34e0a2f9c370eb95597aae63bf85eb5e96826d81e3dcf88b8886012906f509b5"
|
||||
"url": "https://files.pythonhosted.org/packages/2a/53/cf0a48de1bdcf6ff6e1c9a023f5f523dfe303e4024f216feac64b6eb7f67/charset-normalizer-3.2.0.tar.gz",
|
||||
"sha256": "3bb3d25a8e6c0aedd251753a79ae98a093c7e7b471faa3aa9a93a81431987ace"
|
||||
},
|
||||
{
|
||||
"type": "file",
|
||||
|
@ -203,231 +32,64 @@
|
|||
},
|
||||
{
|
||||
"type": "file",
|
||||
"url": "https://files.pythonhosted.org/packages/4b/1d/f8383ef593114755429c307449e7717b87044b3bcd5f7860b89b1f759e34/urllib3-2.0.2-py3-none-any.whl",
|
||||
"sha256": "d055c2f9d38dc53c808f6fdc8eab7360b6fdbbde02340ed25cfbcd817c62469e"
|
||||
"url": "https://files.pythonhosted.org/packages/8a/03/ad9306a50d05c166e3456fe810f33cee2b8b2a7a6818ec5d4908c4ec6b36/urllib3-2.0.3-py3-none-any.whl",
|
||||
"sha256": "48e7fafa40319d358848e1bc6809b208340fafe2096f1725d05d67443d0483d1"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "python3-text-generation",
|
||||
"name": "python3-tqdm",
|
||||
"buildsystem": "simple",
|
||||
"build-commands": [
|
||||
"pip3 install --verbose --exists-action=i --no-index --find-links=\"file://${PWD}\" --prefix=${FLATPAK_DEST} \"text-generation\" --no-build-isolation"
|
||||
"pip3 install --verbose --exists-action=i --no-index --find-links=\"file://${PWD}\" --prefix=${FLATPAK_DEST} \"tqdm\" --no-build-isolation"
|
||||
],
|
||||
"sources": [
|
||||
{
|
||||
"type": "file",
|
||||
"url": "https://files.pythonhosted.org/packages/36/2b/61d51a2c4f25ef062ae3f74576b01638bebad5e045f747ff12643df63844/PyYAML-6.0.tar.gz",
|
||||
"sha256": "68fb519c14306fec9720a2a5b45bc9f0c8d1b9c72adf45c37baedfcd949c35a2"
|
||||
},
|
||||
{
|
||||
"type": "file",
|
||||
"url": "https://files.pythonhosted.org/packages/c2/fd/1ff4da09ca29d8933fda3f3514980357e25419ce5e0f689041edb8f17dab/aiohttp-3.8.4.tar.gz",
|
||||
"sha256": "bf2e1a9162c1e441bf805a1fd166e249d574ca04e03b34f97e2928769e91ab5c"
|
||||
},
|
||||
{
|
||||
"type": "file",
|
||||
"url": "https://files.pythonhosted.org/packages/76/ac/a7305707cb852b7e16ff80eaf5692309bde30e2b1100a1fcacdc8f731d97/aiosignal-1.3.1-py3-none-any.whl",
|
||||
"sha256": "f8376fb07dd1e86a584e4fcdec80b36b7f81aac666ebc724e2c090300dd83b17"
|
||||
},
|
||||
{
|
||||
"type": "file",
|
||||
"url": "https://files.pythonhosted.org/packages/d6/c1/8991e7c5385b897b8c020cdaad718c5b087a6626d1d11a23e1ea87e325a7/async_timeout-4.0.2-py3-none-any.whl",
|
||||
"sha256": "8ca1e4fcf50d07413d66d1a5e416e42cfdf5851c981d679a09851a6853383b3c"
|
||||
},
|
||||
{
|
||||
"type": "file",
|
||||
"url": "https://files.pythonhosted.org/packages/f0/eb/fcb708c7bf5056045e9e98f62b93bd7467eb718b0202e7698eb11d66416c/attrs-23.1.0-py3-none-any.whl",
|
||||
"sha256": "1f28b4522cdc2fb4256ac1a020c78acf9cba2c6b461ccd2c126f3aa8e8335d04"
|
||||
},
|
||||
{
|
||||
"type": "file",
|
||||
"url": "https://files.pythonhosted.org/packages/9d/19/59961b522e6757f0c9097e4493fa906031b95b3ebe9360b2c3083561a6b4/certifi-2023.5.7-py3-none-any.whl",
|
||||
"sha256": "c6c2e98f5c7869efca1f8916fed228dd91539f9f1b444c314c06eef02980c716"
|
||||
},
|
||||
{
|
||||
"type": "file",
|
||||
"url": "https://files.pythonhosted.org/packages/ff/d7/8d757f8bd45be079d76309248845a04f09619a7b17d6dfc8c9ff6433cac2/charset-normalizer-3.1.0.tar.gz",
|
||||
"sha256": "34e0a2f9c370eb95597aae63bf85eb5e96826d81e3dcf88b8886012906f509b5"
|
||||
},
|
||||
{
|
||||
"type": "file",
|
||||
"url": "https://files.pythonhosted.org/packages/ad/73/b094a662ae05cdc4ec95bc54e434e307986a5de5960166b8161b7c1373ee/filelock-3.12.0-py3-none-any.whl",
|
||||
"sha256": "ad98852315c2ab702aeb628412cbf7e95b7ce8c3bf9565670b4eaecf1db370a9"
|
||||
},
|
||||
{
|
||||
"type": "file",
|
||||
"url": "https://files.pythonhosted.org/packages/e9/10/d629476346112b85c912527b9080944fd2c39a816c2225413dbc0bb6fcc0/frozenlist-1.3.3.tar.gz",
|
||||
"sha256": "58bcc55721e8a90b88332d6cd441261ebb22342e238296bb330968952fbb3a6a"
|
||||
},
|
||||
{
|
||||
"type": "file",
|
||||
"url": "https://files.pythonhosted.org/packages/ec/4e/397b234a369df06ec782666fcdf9791d125ca6de48729814b381af8c6c03/fsspec-2023.5.0-py3-none-any.whl",
|
||||
"sha256": "51a4ad01a5bb66fcc58036e288c0d53d3975a0df2a5dc59a93b59bade0391f2a"
|
||||
},
|
||||
{
|
||||
"type": "file",
|
||||
"url": "https://files.pythonhosted.org/packages/58/34/c57b951aecd0248845932c1cfc15721237c50e463f26b0536673bcb76f4f/huggingface_hub-0.14.1-py3-none-any.whl",
|
||||
"sha256": "9fc619170d800ff3793ad37c9757c255c8783051e1b5b00501205eb43ccc4f27"
|
||||
},
|
||||
{
|
||||
"type": "file",
|
||||
"url": "https://files.pythonhosted.org/packages/fc/34/3030de6f1370931b9dbb4dad48f6ab1015ab1d32447850b9fc94e60097be/idna-3.4-py3-none-any.whl",
|
||||
"sha256": "90b77e79eaa3eba6de819a0c442c0b4ceefc341a7a2ab77d7562bf49f425c5c2"
|
||||
},
|
||||
{
|
||||
"type": "file",
|
||||
"url": "https://files.pythonhosted.org/packages/4a/15/bd620f7a6eb9aa5112c4ef93e7031bcd071e0611763d8e17706ef8ba65e0/multidict-6.0.4.tar.gz",
|
||||
"sha256": "3666906492efb76453c0e7b97f2cf459b0682e7402c0489a95484965dbc1da49"
|
||||
},
|
||||
{
|
||||
"type": "file",
|
||||
"url": "https://files.pythonhosted.org/packages/ab/c3/57f0601a2d4fe15de7a553c00adbc901425661bf048f2a22dfc500caf121/packaging-23.1-py3-none-any.whl",
|
||||
"sha256": "994793af429502c4ea2ebf6bf664629d07c1a9fe974af92966e4b8d2df7edc61"
|
||||
},
|
||||
{
|
||||
"type": "file",
|
||||
"url": "https://files.pythonhosted.org/packages/23/65/2aa13873e9e0084ecaec00fbe6c6096b65e1ab99ba66bdbf7e4e7c4cc915/pydantic-1.10.8.tar.gz",
|
||||
"sha256": "1410275520dfa70effadf4c21811d755e7ef9bb1f1d077a21958153a92c8d9ca"
|
||||
},
|
||||
{
|
||||
"type": "file",
|
||||
"url": "https://files.pythonhosted.org/packages/70/8e/0e2d847013cb52cd35b38c009bb167a1a26b2ce6cd6965bf26b47bc0bf44/requests-2.31.0-py3-none-any.whl",
|
||||
"sha256": "58cd2187c01e70e6e26505bca751777aa9f2ee0b7f4300988b709f44e013003f"
|
||||
},
|
||||
{
|
||||
"type": "file",
|
||||
"url": "https://files.pythonhosted.org/packages/83/14/643c55e7cf845db3c1ac96cd624511d56c50386f3760448e7dc2ff58f1c1/text_generation-0.5.2-py3-none-any.whl",
|
||||
"sha256": "110dd5b05f8ec9cef00f3977001f1ce0464b133b14d4939b15260b0e863c942d"
|
||||
},
|
||||
{
|
||||
"type": "file",
|
||||
"url": "https://files.pythonhosted.org/packages/e6/02/a2cff6306177ae6bc73bc0665065de51dfb3b9db7373e122e2735faf0d97/tqdm-4.65.0-py3-none-any.whl",
|
||||
"sha256": "c4f53a17fe37e132815abceec022631be8ffe1b9381c2e6e30aa70edc99e9671"
|
||||
},
|
||||
{
|
||||
"type": "file",
|
||||
"url": "https://files.pythonhosted.org/packages/38/60/300ad6f93adca578bf05d5f6cd1d854b7d140bebe2f9829561aa9977d9f3/typing_extensions-4.6.2-py3-none-any.whl",
|
||||
"sha256": "3a8b36f13dd5fdc5d1b16fe317f5668545de77fa0b8e02006381fd49d731ab98"
|
||||
},
|
||||
{
|
||||
"type": "file",
|
||||
"url": "https://files.pythonhosted.org/packages/4b/1d/f8383ef593114755429c307449e7717b87044b3bcd5f7860b89b1f759e34/urllib3-2.0.2-py3-none-any.whl",
|
||||
"sha256": "d055c2f9d38dc53c808f6fdc8eab7360b6fdbbde02340ed25cfbcd817c62469e"
|
||||
},
|
||||
{
|
||||
"type": "file",
|
||||
"url": "https://files.pythonhosted.org/packages/5f/3f/04b3c5e57844fb9c034b09c5cb6d2b43de5d64a093c30529fd233e16cf09/yarl-1.9.2.tar.gz",
|
||||
"sha256": "04ab9d4b9f587c06d801c2abfe9317b77cdf996c65a90d5e84ecc45010823571"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "python3-gradio_client",
|
||||
"name": "python3-charset-normalizer",
|
||||
"buildsystem": "simple",
|
||||
"build-commands": [
|
||||
"pip3 install --verbose --exists-action=i --no-index --find-links=\"file://${PWD}\" --prefix=${FLATPAK_DEST} \"gradio_client\" --no-build-isolation"
|
||||
"pip3 install --verbose --exists-action=i --no-index --find-links=\"file://${PWD}\" --prefix=${FLATPAK_DEST} \"charset-normalizer\" --no-build-isolation"
|
||||
],
|
||||
"sources": [
|
||||
{
|
||||
"type": "file",
|
||||
"url": "https://files.pythonhosted.org/packages/36/2b/61d51a2c4f25ef062ae3f74576b01638bebad5e045f747ff12643df63844/PyYAML-6.0.tar.gz",
|
||||
"sha256": "68fb519c14306fec9720a2a5b45bc9f0c8d1b9c72adf45c37baedfcd949c35a2"
|
||||
},
|
||||
{
|
||||
"type": "file",
|
||||
"url": "https://files.pythonhosted.org/packages/68/fe/7ce1926952c8a403b35029e194555558514b365ad77d75125f521a2bec62/anyio-3.7.0-py3-none-any.whl",
|
||||
"sha256": "eddca883c4175f14df8aedce21054bfca3adb70ffe76a9f607aef9d7fa2ea7f0"
|
||||
},
|
||||
{
|
||||
"type": "file",
|
||||
"url": "https://files.pythonhosted.org/packages/9d/19/59961b522e6757f0c9097e4493fa906031b95b3ebe9360b2c3083561a6b4/certifi-2023.5.7-py3-none-any.whl",
|
||||
"sha256": "c6c2e98f5c7869efca1f8916fed228dd91539f9f1b444c314c06eef02980c716"
|
||||
},
|
||||
{
|
||||
"type": "file",
|
||||
"url": "https://files.pythonhosted.org/packages/ff/d7/8d757f8bd45be079d76309248845a04f09619a7b17d6dfc8c9ff6433cac2/charset-normalizer-3.1.0.tar.gz",
|
||||
"sha256": "34e0a2f9c370eb95597aae63bf85eb5e96826d81e3dcf88b8886012906f509b5"
|
||||
},
|
||||
{
|
||||
"type": "file",
|
||||
"url": "https://files.pythonhosted.org/packages/61/97/17ed81b7a8d24d8f69b62c0db37abbd8c0042d4b3fc429c73dab986e7483/exceptiongroup-1.1.1-py3-none-any.whl",
|
||||
"sha256": "232c37c63e4f682982c8b6459f33a8981039e5fb8756b2074364e5055c498c9e"
|
||||
},
|
||||
{
|
||||
"type": "file",
|
||||
"url": "https://files.pythonhosted.org/packages/ad/73/b094a662ae05cdc4ec95bc54e434e307986a5de5960166b8161b7c1373ee/filelock-3.12.0-py3-none-any.whl",
|
||||
"sha256": "ad98852315c2ab702aeb628412cbf7e95b7ce8c3bf9565670b4eaecf1db370a9"
|
||||
},
|
||||
{
|
||||
"type": "file",
|
||||
"url": "https://files.pythonhosted.org/packages/ec/4e/397b234a369df06ec782666fcdf9791d125ca6de48729814b381af8c6c03/fsspec-2023.5.0-py3-none-any.whl",
|
||||
"sha256": "51a4ad01a5bb66fcc58036e288c0d53d3975a0df2a5dc59a93b59bade0391f2a"
|
||||
},
|
||||
{
|
||||
"type": "file",
|
||||
"url": "https://files.pythonhosted.org/packages/86/ed/3b8b8df6c66f5fd8ab3e458e2086502d7208557e9bbc31592d4c732cf1d3/gradio_client-0.2.5-py3-none-any.whl",
|
||||
"sha256": "922a5188c93797adce023b4caa655318b9c09834095d31763443c1e7a707e301"
|
||||
},
|
||||
{
|
||||
"type": "file",
|
||||
"url": "https://files.pythonhosted.org/packages/95/04/ff642e65ad6b90db43e668d70ffb6736436c7ce41fcc549f4e9472234127/h11-0.14.0-py3-none-any.whl",
|
||||
"sha256": "e3fe4ac4b851c468cc8363d500db52c2ead036020723024a109d37346efaa761"
|
||||
},
|
||||
{
|
||||
"type": "file",
|
||||
"url": "https://files.pythonhosted.org/packages/4d/32/b908f673ccef12b6425b848a541264ee3d95f5f571f18f6ab0d8c311442e/httpcore-0.17.2-py3-none-any.whl",
|
||||
"sha256": "5581b9c12379c4288fe70f43c710d16060c10080617001e6b22a3b6dbcbefd36"
|
||||
},
|
||||
{
|
||||
"type": "file",
|
||||
"url": "https://files.pythonhosted.org/packages/ec/91/e41f64f03d2a13aee7e8c819d82ee3aa7cdc484d18c0ae859742597d5aa0/httpx-0.24.1-py3-none-any.whl",
|
||||
"sha256": "06781eb9ac53cde990577af654bd990a4949de37a28bdb4a230d434f3a30b9bd"
|
||||
},
|
||||
{
|
||||
"type": "file",
|
||||
"url": "https://files.pythonhosted.org/packages/58/34/c57b951aecd0248845932c1cfc15721237c50e463f26b0536673bcb76f4f/huggingface_hub-0.14.1-py3-none-any.whl",
|
||||
"sha256": "9fc619170d800ff3793ad37c9757c255c8783051e1b5b00501205eb43ccc4f27"
|
||||
},
|
||||
"url": "https://files.pythonhosted.org/packages/2a/53/cf0a48de1bdcf6ff6e1c9a023f5f523dfe303e4024f216feac64b6eb7f67/charset-normalizer-3.2.0.tar.gz",
|
||||
"sha256": "3bb3d25a8e6c0aedd251753a79ae98a093c7e7b471faa3aa9a93a81431987ace"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "python3-idna",
|
||||
"buildsystem": "simple",
|
||||
"build-commands": [
|
||||
"pip3 install --verbose --exists-action=i --no-index --find-links=\"file://${PWD}\" --prefix=${FLATPAK_DEST} \"idna\" --no-build-isolation"
|
||||
],
|
||||
"sources": [
|
||||
{
|
||||
"type": "file",
|
||||
"url": "https://files.pythonhosted.org/packages/fc/34/3030de6f1370931b9dbb4dad48f6ab1015ab1d32447850b9fc94e60097be/idna-3.4-py3-none-any.whl",
|
||||
"sha256": "90b77e79eaa3eba6de819a0c442c0b4ceefc341a7a2ab77d7562bf49f425c5c2"
|
||||
},
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "python3-urllib3",
|
||||
"buildsystem": "simple",
|
||||
"build-commands": [
|
||||
"pip3 install --verbose --exists-action=i --no-index --find-links=\"file://${PWD}\" --prefix=${FLATPAK_DEST} \"urllib3\" --no-build-isolation"
|
||||
],
|
||||
"sources": [
|
||||
{
|
||||
"type": "file",
|
||||
"url": "https://files.pythonhosted.org/packages/ab/c3/57f0601a2d4fe15de7a553c00adbc901425661bf048f2a22dfc500caf121/packaging-23.1-py3-none-any.whl",
|
||||
"sha256": "994793af429502c4ea2ebf6bf664629d07c1a9fe974af92966e4b8d2df7edc61"
|
||||
},
|
||||
{
|
||||
"type": "file",
|
||||
"url": "https://files.pythonhosted.org/packages/70/8e/0e2d847013cb52cd35b38c009bb167a1a26b2ce6cd6965bf26b47bc0bf44/requests-2.31.0-py3-none-any.whl",
|
||||
"sha256": "58cd2187c01e70e6e26505bca751777aa9f2ee0b7f4300988b709f44e013003f"
|
||||
},
|
||||
{
|
||||
"type": "file",
|
||||
"url": "https://files.pythonhosted.org/packages/c3/a0/5dba8ed157b0136607c7f2151db695885606968d1fae123dc3391e0cfdbf/sniffio-1.3.0-py3-none-any.whl",
|
||||
"sha256": "eecefdce1e5bbfb7ad2eeaabf7c1eeb404d7757c379bd1f7e5cce9d8bf425384"
|
||||
},
|
||||
{
|
||||
"type": "file",
|
||||
"url": "https://files.pythonhosted.org/packages/e6/02/a2cff6306177ae6bc73bc0665065de51dfb3b9db7373e122e2735faf0d97/tqdm-4.65.0-py3-none-any.whl",
|
||||
"sha256": "c4f53a17fe37e132815abceec022631be8ffe1b9381c2e6e30aa70edc99e9671"
|
||||
},
|
||||
{
|
||||
"type": "file",
|
||||
"url": "https://files.pythonhosted.org/packages/38/60/300ad6f93adca578bf05d5f6cd1d854b7d140bebe2f9829561aa9977d9f3/typing_extensions-4.6.2-py3-none-any.whl",
|
||||
"sha256": "3a8b36f13dd5fdc5d1b16fe317f5668545de77fa0b8e02006381fd49d731ab98"
|
||||
},
|
||||
{
|
||||
"type": "file",
|
||||
"url": "https://files.pythonhosted.org/packages/4b/1d/f8383ef593114755429c307449e7717b87044b3bcd5f7860b89b1f759e34/urllib3-2.0.2-py3-none-any.whl",
|
||||
"sha256": "d055c2f9d38dc53c808f6fdc8eab7360b6fdbbde02340ed25cfbcd817c62469e"
|
||||
},
|
||||
{
|
||||
"type": "file",
|
||||
"url": "https://files.pythonhosted.org/packages/d8/3b/2ed38e52eed4cf277f9df5f0463a99199a04d9e29c9e227cfafa57bd3993/websockets-11.0.3.tar.gz",
|
||||
"sha256": "88fc51d9a26b10fc331be344f1781224a375b78488fc343620184e95a4b27016"
|
||||
"url": "https://files.pythonhosted.org/packages/8a/03/ad9306a50d05c166e3456fe810f33cee2b8b2a7a6818ec5d4908c4ec6b36/urllib3-2.0.3-py3-none-any.whl",
|
||||
"sha256": "48e7fafa40319d358848e1bc6809b208340fafe2096f1725d05d67443d0483d1"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
@ -1,14 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<gresources>
|
||||
<gresource prefix="/io/github/Bavarder/Bavarder">
|
||||
<file preprocess="xml-stripblanks">ui/window.ui</file>
|
||||
<file preprocess="xml-stripblanks">ui/message_bubble.ui</file>
|
||||
<file preprocess="xml-stripblanks" alias="gtk/help-overlay.ui">ui/help-overlay.ui</file>
|
||||
<file preprocess="xml-stripblanks">ui/preferences.ui</file>
|
||||
<file>style.css</file>
|
||||
</gresource>
|
||||
<gresource prefix="/io/github/Bavarder/Bavarder/icons/scalable/actions/">
|
||||
<file preprocess="xml-stripblanks" alias="paper-plane-symbolic.svg">icons/scalable/actions/paper-plane-symbolic.svg</file>
|
||||
<file preprocess="xml-stripblanks" alias="x-circular-symbolic.svg">icons/scalable/actions/x-circular-symbolic.svg</file>
|
||||
</gresource>
|
||||
</gresources>
|
1
data/icons/hicolor/scalable/actions/bot-symbolic.svg
Normal file
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16"><path fill="#222" d="M8.475 0a.497.497 0 0 0-.276.1L6.5 1.375 4.8.1a.5.5 0 0 0-.37-.094A.5.5 0 0 0 4.2.9L6 2.25V4H3C1.338 4 0 5.338 0 7v6c0 1.662 1.338 3 3 3h10c1.662 0 3-1.338 3-3V7c0-1.662-1.338-3-3-3H7V2.25L8.8.9a.5.5 0 0 0-.325-.9zM3 6h10c.554 0 1 .446 1 1v6c0 .554-.446 1-1 1H3c-.554 0-1-.446-1-1V7c0-.554.446-1 1-1zm2 1a2 2 0 0 0-2 2 2 2 0 0 0 2 2 2 2 0 0 0 2-2 2 2 0 0 0-2-2zm6 0a2 2 0 0 0-2 2 2 2 0 0 0 2 2 2 2 0 0 0 2-2 2 2 0 0 0-2-2zM5 8a1 1 0 0 1 1 1 1 1 0 0 1-1 1 1 1 0 0 1-1-1 1 1 0 0 1 1-1zm6 0a1 1 0 0 1 1 1 1 1 0 0 1-1 1 1 1 0 0 1-1-1 1 1 0 0 1 1-1zm-4.5 4a.499.499 0 1 0 0 1h3a.499.499 0 1 0 0-1z"/></svg>
|
After Width: | Height: | Size: 685 B |
|
@ -0,0 +1,2 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" height="16px" viewBox="0 0 16 16" width="16px"><path d="m 5.976562 2 c 0.546876 0 1 0.453125 1 1 v 10 c 0 0.546875 -0.453124 1 -1 1 h -0.976562 c -1.652344 0 -3 -1.347656 -3 -3 v -6 c 0 -1.652344 1.347656 -3 3 -3 z m -5.976562 3 v 6 c 0 2.765625 2.234375 5 5 5 h 0.976562 c 1.660157 0 3 -1.339844 3 -3 v -10 c 0 -1.660156 -1.339843 -3 -3 -3 h -0.976562 c -2.765625 0 -5 2.234375 -5 5 z m 0 0"/><path d="m 1.488281 8.996094 h 1.511719 c 1.101562 0 1.988281 -0.886719 1.988281 -1.984375 v -0.515625 c 0 -0.273438 -0.222656 -0.5 -0.5 -0.5 c -0.273437 0 -0.5 0.226562 -0.5 0.5 v 0.515625 c 0 0.542969 -0.445312 0.984375 -0.988281 0.984375 h -1.511719 c -0.273437 0 -0.5 0.226562 -0.5 0.5 c 0 0.277344 0.226563 0.5 0.5 0.5 z m 0 0"/><path d="m 7.5 9.992188 h -1.511719 c -1.101562 0 -1.988281 0.886718 -1.988281 1.984374 v 0.515626 c 0 0.273437 0.222656 0.5 0.5 0.5 s 0.5 -0.226563 0.5 -0.5 v -0.515626 c 0 -0.539062 0.445312 -0.984374 0.988281 -0.984374 h 1.511719 c 0.277344 0 0.5 -0.226563 0.5 -0.5 c 0 -0.277344 -0.222656 -0.5 -0.5 -0.5 z m 0 0"/><path d="m 4.496094 4.980469 h 3 c 0.277344 0 0.5 -0.226563 0.5 -0.5 c 0 -0.277344 -0.222656 -0.5 -0.5 -0.5 h -3 c -0.277344 0 -0.5 0.222656 -0.5 0.5 c 0 0.273437 0.222656 0.5 0.5 0.5 z m 0 0"/><path d="m 11.015625 14 h -1.035156 c -0.546875 0 -1 -0.453125 -1 -1 v -10 c 0 -0.546875 0.453125 -1 1 -1 h 1.035156 v -2 h -1.035156 c -1.664063 0 -3 1.339844 -3 3 v 10 c 0 1.660156 1.335937 3 3 3 h 1.035156 z m 0 0"/><path d="m 10 8 l 3.5 -0.011719 v -1 l -3.5 0.011719 z m 0 0"/><path d="m 10 5 h 2.242188 l 2.148437 -2.6875 l -0.78125 -0.625 l -2 2.5 l 0.390625 -0.1875 h -2 z m 0 0"/><path d="m 10 11 h 2 l -0.390625 -0.1875 l 2 2.5 l 0.78125 -0.625 l -2.148437 -2.6875 h -2.242188 z m 0 0"/><path d="m 14.488281 1.976562 c -0.265625 0 -0.488281 -0.21875 -0.488281 -0.488281 c 0 -0.265625 0.222656 -0.488281 0.488281 -0.488281 c 0.269531 0 0.488281 0.222656 0.488281 0.488281 c 0 0.269531 -0.21875 0.488281 -0.488281 0.488281 z m 0 -1.976562 c -0.824219 0 -1.488281 0.664062 -1.488281 1.488281 s 0.664062 1.488281 1.488281 1.488281 s 1.488281 -0.664062 1.488281 -1.488281 s -0.664062 -1.488281 -1.488281 -1.488281 z m 0 0"/><path d="m 14.488281 13.976562 c -0.265625 0 -0.488281 -0.21875 -0.488281 -0.488281 c 0 -0.265625 0.222656 -0.488281 0.488281 -0.488281 c 0.269531 0 0.488281 0.222656 0.488281 0.488281 c 0 0.269531 -0.21875 0.488281 -0.488281 0.488281 z m 0 -1.976562 c -0.824219 0 -1.488281 0.664062 -1.488281 1.488281 s 0.664062 1.488281 1.488281 1.488281 s 1.488281 -0.664062 1.488281 -1.488281 s -0.664062 -1.488281 -1.488281 -1.488281 z m 0 0"/><path d="m 14.488281 7.976562 c -0.265625 0 -0.488281 -0.21875 -0.488281 -0.488281 c 0 -0.265625 0.222656 -0.488281 0.488281 -0.488281 c 0.269531 0 0.488281 0.222656 0.488281 0.488281 c 0 0.269531 -0.21875 0.488281 -0.488281 0.488281 z m 0 -1.976562 c -0.824219 0 -1.488281 0.664062 -1.488281 1.488281 s 0.664062 1.488281 1.488281 1.488281 s 1.488281 -0.664062 1.488281 -1.488281 s -0.664062 -1.488281 -1.488281 -1.488281 z m 0 0"/></svg>
|
After Width: | Height: | Size: 3 KiB |
13
data/icons/hicolor/scalable/actions/brain-symbolic.svg
Normal file
|
@ -0,0 +1,13 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg height="16px" viewBox="0 0 16 16" width="16px" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="m 5.976562 2 c 0.546876 0 1 0.453125 1 1 v 10 c 0 0.546875 -0.453124 1 -1 1 h -0.976562 c -1.652344 0 -3 -1.347656 -3 -3 v -6 c 0 -1.652344 1.347656 -3 3 -3 z m -5.976562 3 v 6 c 0 2.765625 2.234375 5 5 5 h 0.976562 c 1.660157 0 3 -1.339844 3 -3 v -10 c 0 -1.660156 -1.339843 -3 -3 -3 h -0.976562 c -2.765625 0 -5 2.234375 -5 5 z m 0 0"/>
|
||||
<path d="m 7.5 9.992188 h -1.511719 c -1.101562 0 -1.988281 0.886718 -1.988281 1.984374 v 0.515626 c 0 0.273437 0.222656 0.5 0.5 0.5 s 0.5 -0.226563 0.5 -0.5 v -0.515626 c 0 -0.539062 0.445312 -0.984374 0.988281 -0.984374 h 1.511719 c 0.277344 0 0.5 -0.226563 0.5 -0.5 c 0 -0.277344 -0.222656 -0.5 -0.5 -0.5 z m 0 0"/>
|
||||
<path d="m 4.496094 4.980469 h 3 c 0.277344 0 0.5 -0.226563 0.5 -0.5 c 0 -0.277344 -0.222656 -0.5 -0.5 -0.5 h -3 c -0.277344 0 -0.5 0.222656 -0.5 0.5 c 0 0.273437 0.222656 0.5 0.5 0.5 z m 0 0"/>
|
||||
<path d="m 9.980469 14 c -0.546875 0 -1 -0.453125 -1 -1 v -10 c 0 -0.546875 0.453125 -1 1 -1 h 1.019531 c 1.652344 0 3 1.347656 3 3 v 6 c 0 1.652344 -1.347656 3 -3 3 z m 6.019531 -3 v -6 c 0 -2.765625 -2.234375 -5 -5 -5 h -1.019531 c -1.664063 0 -3 1.339844 -3 3 v 10 c 0 1.660156 1.335937 3 3 3 h 1.019531 c 2.765625 0 5 -2.234375 5 -5 z m 0 0"/>
|
||||
<path d="m 8.523438 6.015625 h 1.511718 c 1.101563 0 1.988282 -0.886719 1.988282 -1.988281 v -0.511719 c 0 -0.277344 -0.222657 -0.5 -0.5 -0.5 c -0.277344 0 -0.5 0.222656 -0.5 0.5 v 0.511719 c 0 0.542968 -0.445313 0.988281 -0.988282 0.988281 h -1.511718 c -0.277344 0 -0.5 0.222656 -0.5 0.5 c 0 0.273437 0.222656 0.5 0.5 0.5 z m 0 0"/>
|
||||
<path d="m 8.488281 10 h 1.511719 c 0.542969 0 0.988281 0.445312 0.988281 0.988281 v 0.511719 c 0 0.277344 0.222657 0.5 0.5 0.5 c 0.273438 0 0.5 -0.222656 0.5 -0.5 v -0.511719 c 0 -1.101562 -0.886719 -1.988281 -1.988281 -1.988281 h -1.511719 c -0.277343 0 -0.5 0.222656 -0.5 0.5 s 0.222657 0.5 0.5 0.5 z m 0 0"/>
|
||||
<path d="m 15 10 h -1.523438 c -0.277343 0 -0.5 0.222656 -0.5 0.5 s 0.222657 0.5 0.5 0.5 h 1.523438 c 0.277344 0 0.5 -0.222656 0.5 -0.5 s -0.222656 -0.5 -0.5 -0.5 z m 0 0"/>
|
||||
<path d="m 6.488281 8 h 5.042969 c 0.273438 0 0.5 -0.222656 0.5 -0.5 s -0.226562 -0.5 -0.5 -0.5 h -5.042969 c -0.277343 0 -0.5 0.222656 -0.5 0.5 s 0.222657 0.5 0.5 0.5 z m 0 0"/>
|
||||
<path d="m 15.089844 6.015625 h -1.59375 c -0.277344 0 -0.5 0.222656 -0.5 0.5 c 0 0.273437 0.222656 0.5 0.5 0.5 h 1.59375 c 0.273437 0 0.5 -0.226563 0.5 -0.5 c 0 -0.277344 -0.226563 -0.5 -0.5 -0.5 z m 0 0"/>
|
||||
<path d="m 1.488281 9.992188 h 1.511719 c 1.101562 0 1.988281 -0.886719 1.988281 -1.988282 v -0.511718 c 0 -0.277344 -0.222656 -0.5 -0.5 -0.5 c -0.277343 0 -0.5 0.222656 -0.5 0.5 v 0.511718 c 0 0.542969 -0.445312 0.988282 -0.988281 0.988282 h -1.511719 c -0.277343 0 -0.5 0.222656 -0.5 0.5 c 0 0.273437 0.222657 0.5 0.5 0.5 z m 0 0"/>
|
||||
</svg>
|
After Width: | Height: | Size: 2.9 KiB |
|
@ -0,0 +1,3 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" version="1.1">
|
||||
<path style="fill:#dfdfdf" d="M 2.5 1 C 1.115 1 0 2.1162718 0 3.5039062 L 0 10.517578 C 0 11.905212 1.1150052 12.996222 2.5 13 L 10.875 13 L 12.953125 14.998047 L 14 15 L 14 13 C 15.14126 12.767208 16 11.731753 16 10.517578 L 16 3.5039062 C 16 2.1162718 14.885 1 13.5 1 L 2.5 1 z M 2.5 3 L 13.5 3 C 13.777 3 14 3.223 14 3.5 L 14 10.5 C 14 10.777 13.777 11 13.5 11 L 2.5 11 C 2.223 11 2 10.777 2 10.5 L 2 3.5 C 2 3.223 2.223 3 2.5 3 z M 7 4 L 7 6 L 5 6 L 5 8 L 7 8 L 7 10 L 9 10 L 9 8 L 11 8 L 11 6 L 9 6 L 9 4 L 7 4 z"/>
|
||||
</svg>
|
After Width: | Height: | Size: 607 B |
|
@ -0,0 +1,2 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" height="16px" viewBox="0 0 16 16" width="16px"><path d="m 9.492188 0.140625 c -0.851563 -0.1640625 -1.722657 -0.1835938 -2.574219 -0.0664062 c -1.699219 0.2304692 -3.328125 1.0078122 -4.601563 2.2929692 c -2.546875 2.566406 -3.050781 6.539062 -1.230468 9.664062 c 1.824218 3.121094 5.53125 4.636719 9.019531 3.683594 c 3.488281 -0.949219 5.90625 -4.132813 5.890625 -7.75 c 0 -0.550782 -0.453125 -1 -1.003906 -0.996094 c -0.550782 0.003906 -0.996094 0.453125 -0.996094 1.003906 c 0.015625 2.722656 -1.792969 5.097656 -4.417969 5.816406 c -2.625 0.714844 -5.390625 -0.417968 -6.761719 -2.765624 c -1.371094 -2.351563 -0.996094 -5.316407 0.921875 -7.25 c 1.914063 -1.929688 4.875 -2.335938 7.238281 -0.984376 c 0.476563 0.273438 1.089844 0.109376 1.363282 -0.371093 c 0.273437 -0.480469 0.109375 -1.089844 -0.371094 -1.367188 c -0.785156 -0.445312 -1.621094 -0.75 -2.476562 -0.910156 z m 0 0"/><path d="m 15.753906 3.65625 c 0.175782 -0.199219 0.261719 -0.460938 0.246094 -0.722656 c -0.019531 -0.265625 -0.140625 -0.511719 -0.339844 -0.6875 c -0.199218 -0.175782 -0.460937 -0.265625 -0.726562 -0.246094 c -0.265625 0.015625 -0.511719 0.140625 -0.6875 0.339844 l -6.296875 7.195312 l -2.242188 -2.246094 c -0.390625 -0.390624 -1.023437 -0.390624 -1.414062 0 c -0.1875 0.1875 -0.292969 0.445313 -0.292969 0.710938 s 0.105469 0.519531 0.292969 0.707031 l 3 3 c 0.195312 0.195313 0.464843 0.300781 0.742187 0.292969 c 0.277344 -0.011719 0.535156 -0.132812 0.71875 -0.34375 z m 0 0"/></svg>
|
After Width: | Height: | Size: 1.5 KiB |
|
@ -0,0 +1,5 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg height="16px" viewBox="0 0 16 16" width="16px" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="m 10 3 c -1.5625 0.003906 -2.980469 0.914062 -3.628906 2.332031 c -0.425782 -0.214843 -0.894532 -0.332031 -1.371094 -0.332031 c -0.308594 0.007812 -0.613281 0.058594 -0.90625 0.160156 l 8.84375 8.839844 h 0.0625 c 1.65625 0 3 -1.34375 3 -3 c 0 -1.332031 -0.882812 -2.503906 -2.160156 -2.875 c 0.105468 -0.367188 0.160156 -0.746094 0.160156 -1.125 c 0 -2.210938 -1.789062 -4 -4 -4 z m -7.203125 2.984375 c -0.507813 0.550781 -0.792969 1.269531 -0.796875 2.015625 c 0 0.347656 0.0625 0.695312 0.183594 1.023438 c -1.25 0.160156 -2.183594 1.21875 -2.183594 2.476562 c 0 1.378906 1.121094 2.5 2.5 2.5 h 8.3125 z m 0 0"/>
|
||||
<path d="m 1.519531 0.460938 l -1.0625 1.0625 l 14 14 l 1.0625 -1.0625 z m 0 0"/>
|
||||
</svg>
|
After Width: | Height: | Size: 850 B |
|
@ -0,0 +1,4 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg height="16px" viewBox="0 0 16 16" width="16px" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="m 10 3 c -1.5625 0.003906 -2.980469 0.914062 -3.628906 2.332031 c -0.425782 -0.214843 -0.894532 -0.332031 -1.371094 -0.332031 c -1.65625 0 -3 1.34375 -3 3 c 0 0.347656 0.0625 0.695312 0.183594 1.023438 c -1.25 0.160156 -2.183594 1.21875 -2.183594 2.476562 c 0 1.378906 1.121094 2.5 2.5 2.5 h 10.5 c 1.65625 0 3 -1.34375 3 -3 c 0 -1.332031 -0.882812 -2.503906 -2.160156 -2.875 c 0.105468 -0.367188 0.160156 -0.746094 0.160156 -1.125 c 0 -2.210938 -1.789062 -4 -4 -4 z m 0 0"/>
|
||||
</svg>
|
After Width: | Height: | Size: 623 B |
|
@ -0,0 +1,5 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" version="1.1">
|
||||
<path style="fill:#dfdfdf" d="M 11,11 V 12 C 11,12.28 11.1,12.54 11.28,12.72 L 12.06,13.5 11.28,14.28 C 11.1,14.47 11,14.73 11,15 V 16 H 12 C 12.28,16 12.54,15.9 12.72,15.72 L 13.5,14.94 14.28,15.72 C 14.46,15.9 14.73,16 15,16 H 16 V 15 C 16,14.73 15.9,14.47 15.72,14.28 L 14.94,13.5 15.72,12.72 C 15.9,12.54 16,12.28 16,12 V 11 H 15 C 14.73,11 14.46,11.1 14.28,11.28 L 13.5,12.07 12.72,11.28 C 12.54,11.1 12.28,11 12,11 Z"/>
|
||||
<path style="fill:#dfdfdf;opacity:.35" d="M 10,9 15.5,4.5 10,0 C 10,0.01 10,1.34 10,2 9,2 8,2 7,2 7,3.67 7,5.34 7,7 8,7 9,7 10,7 10,7.67 10,9 10,9 Z"/>
|
||||
<path style="fill:#dfdfdf;opacity:.35" d="M 6,6 0.5,10.5 6,15 V 13 H 9 V 8 H 6 Z"/>
|
||||
</svg>
|
After Width: | Height: | Size: 750 B |
|
@ -0,0 +1,5 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" height="16px" viewBox="0 0 16 16" width="16px">
|
||||
<path d="m 15 8 l -14 -7 v 6 l 8 1 l -8 1 v 6 z m 0 0" fill="#222222"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 209 B |
|
@ -0,0 +1,5 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg height="16px" viewBox="0 0 16 16" width="16px" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="m 2.199219 0 c -1.207031 0 -2.199219 1.007812 -2.199219 2.207031 v 10.585938 c 0 1.199219 0.992188 2.207031 2.199219 2.207031 h 11.601562 c 1.207031 0 2.199219 -1.007812 2.199219 -2.207031 v -10.585938 c 0 -1.199219 -0.992188 -2.207031 -2.199219 -2.207031 z m 0 2 h 11.601562 c 0.121094 0 0.199219 0.070312 0.199219 0.207031 v 10.585938 c 0 0.136719 -0.078125 0.207031 -0.199219 0.207031 h -11.601562 c -0.121094 0 -0.199219 -0.070312 -0.199219 -0.207031 v -10.585938 c 0 -0.136719 0.078125 -0.207031 0.199219 -0.207031 z m 0 0"/>
|
||||
<path d="m 4.515625 5.898438 c -0.164063 -0.003907 -0.324219 0.0625 -0.441406 0.175781 c -0.230469 0.234375 -0.230469 0.617187 0 0.851562 l 1.578125 1.574219 l -1.578125 1.574219 c -0.230469 0.234375 -0.230469 0.617187 0 0.851562 c 0.234375 0.230469 0.617187 0.230469 0.851562 0 l 2 -2 c 0.230469 -0.234375 0.230469 -0.617187 0 -0.851562 l -2 -2 c -0.109375 -0.105469 -0.257812 -0.167969 -0.410156 -0.175781 z m 3.484375 4.101562 v 1 h 3 v -1 z m 0 0"/>
|
||||
</svg>
|
After Width: | Height: | Size: 1.1 KiB |
|
@ -1,12 +1,13 @@
|
|||
application_id = 'io.github.Bavarder.Bavarder'
|
||||
|
||||
scalable_dir = join_paths('hicolor', 'scalable', 'apps')
|
||||
install_data(
|
||||
join_paths(scalable_dir, ('@0@.svg').format(APPLICATION_ID)),
|
||||
join_paths(scalable_dir, ('@0@.svg').format(application_id)),
|
||||
install_dir: join_paths(get_option('datadir'), 'icons', scalable_dir)
|
||||
)
|
||||
|
||||
symbolic_dir = join_paths('hicolor', 'symbolic', 'apps')
|
||||
install_data(
|
||||
join_paths(symbolic_dir, ('@0@-symbolic.svg').format(PROJECT_RDNN_NAME)),
|
||||
install_dir: join_paths(get_option('datadir'), 'icons', symbolic_dir),
|
||||
rename: '@0@-symbolic.svg'.format(APPLICATION_ID)
|
||||
join_paths(symbolic_dir, ('@0@-symbolic.svg').format(application_id)),
|
||||
install_dir: join_paths(get_option('datadir'), 'icons', symbolic_dir)
|
||||
)
|
||||
|
|
|
@ -1,2 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" height="16px" viewBox="0 0 16 16" width="16px"><path d="m 15 8 l -14 -7 v 6 l 8 1 l -8 1 v 6 z m 0 0" fill="#222222"/></svg>
|
Before Width: | Height: | Size: 204 B |
|
@ -1,4 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg height="16px" viewBox="0 0 16 16" width="16px" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="m 7.96875 1 c -3.851562 0 -6.96875 3.117188 -6.96875 6.96875 s 3.117188 6.96875 6.96875 6.96875 s 6.96875 -3.117188 6.96875 -6.96875 s -3.117188 -6.96875 -6.96875 -6.96875 z m -3 3.96875 h 1 h 0.03125 c 0.253906 0.011719 0.511719 0.128906 0.6875 0.3125 l 1.28125 1.28125 l 1.3125 -1.28125 c 0.265625 -0.230469 0.445312 -0.304688 0.6875 -0.3125 h 1 v 1 c 0 0.285156 -0.035156 0.550781 -0.25 0.75 l -1.28125 1.28125 l 1.25 1.25 c 0.1875 0.1875 0.28125 0.453125 0.28125 0.71875 v 1 h -1 c -0.265625 0 -0.53125 -0.09375 -0.71875 -0.28125 l -1.28125 -1.28125 l -1.28125 1.28125 c -0.1875 0.1875 -0.453125 0.28125 -0.71875 0.28125 h -1 v -1 c 0 -0.265625 0.09375 -0.53125 0.28125 -0.71875 l 1.28125 -1.25 l -1.28125 -1.28125 c -0.210938 -0.195312 -0.304688 -0.46875 -0.28125 -0.75 z m 0 0" fill="#2e3436"/>
|
||||
</svg>
|
Before Width: | Height: | Size: 948 B |
|
@ -1,179 +1,358 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<component type="desktop">
|
||||
<id>@APP_ID@</id>
|
||||
<name>Bavarder</name>
|
||||
<summary>Chit-chat with an AI</summary>
|
||||
<developer_name>0xMRTT</developer_name>
|
||||
<metadata_license>CC0-1.0</metadata_license>
|
||||
<project_license>GPL-3.0-or-later</project_license>
|
||||
<launchable type="desktop-id">@APP_ID@.desktop</launchable>
|
||||
<content_rating type="oars-1.1"/>
|
||||
|
||||
<id>
|
||||
@APP_ID@
|
||||
</id>
|
||||
<name>
|
||||
Bavarder
|
||||
</name>
|
||||
<summary>
|
||||
Chit-chat with an AI
|
||||
</summary>
|
||||
<developer_name>
|
||||
0xMRTT
|
||||
</developer_name>
|
||||
<metadata_license>
|
||||
CC0-1.0
|
||||
</metadata_license>
|
||||
<project_license>
|
||||
GPL-3.0-or-later
|
||||
</project_license>
|
||||
<launchable type="desktop-id">
|
||||
@APP_ID@.desktop
|
||||
</launchable>
|
||||
<content_rating type="oars-1.1" />
|
||||
<description>
|
||||
<p>Chit-chat with an AI</p>
|
||||
<p>
|
||||
Chit-chat with an AI
|
||||
</p>
|
||||
</description>
|
||||
|
||||
<screenshots>
|
||||
<screenshot width="472" height="622">
|
||||
<caption>Screenshot of Main UI</caption>
|
||||
<image type="source">https://codeberg.org/Bavarder/Bavarder/raw/branch/main/data/screenshots/preview.png</image>
|
||||
<screenshot width="472" height="622">
|
||||
<caption>
|
||||
Screenshot of Main UI
|
||||
</caption>
|
||||
<image type="source">
|
||||
https://codeberg.org/Bavarder/Bavarder/raw/branch/main/data/screenshots/preview.png
|
||||
</image>
|
||||
</screenshot>
|
||||
<screenshot width="724" height="732">
|
||||
<caption>
|
||||
Screenshot of Preferences UI
|
||||
</caption>
|
||||
<image type="source">
|
||||
https://codeberg.org/Bavarder/Bavarder/raw/branch/main/data/screenshots/preferences.png
|
||||
</image>
|
||||
</screenshot>
|
||||
<screenshot width="724" height="732">
|
||||
<caption>Screenshot of Preferences UI</caption>
|
||||
<image type="source">https://codeberg.org/Bavarder/Bavarder/raw/branch/main/data/screenshots/preferences.png</image>
|
||||
</screenshot>
|
||||
</screenshots>
|
||||
|
||||
<url type="homepage">@PROJECT_URL@</url>
|
||||
<url type="bugtracker">@BUGTRACKER_URL@</url>
|
||||
<url type="help">@HELP_URL@</url>
|
||||
<url type="translate">@TRANSLATE_URL@</url>
|
||||
|
||||
<kudos>
|
||||
<kudo>HiDpiIcon</kudo>
|
||||
<kudo>ModernToolkit</kudo>
|
||||
</kudos>
|
||||
|
||||
<custom>
|
||||
<value key="Purism::form_factor">workstation</value>
|
||||
<value key="Purism::form_factor">mobile</value>
|
||||
</custom>
|
||||
|
||||
<requires>
|
||||
<display_length compare="ge">360</display_length>
|
||||
</requires>
|
||||
|
||||
<categories>
|
||||
<category>Utility</category>
|
||||
</categories>
|
||||
|
||||
<recommends>
|
||||
<control>keyboard</control>
|
||||
<control>pointing</control>
|
||||
<control>touch</control>
|
||||
</recommends>
|
||||
|
||||
<url type="homepage">
|
||||
@PROJECT_URL@
|
||||
</url>
|
||||
<url type="bugtracker">
|
||||
@BUGTRACKER_URL@
|
||||
</url>
|
||||
<url type="help">
|
||||
@HELP_URL@
|
||||
</url>
|
||||
<url type="translate">
|
||||
@TRANSLATE_URL@
|
||||
</url>
|
||||
<kudos>
|
||||
<kudo>
|
||||
HiDpiIcon
|
||||
</kudo>
|
||||
<kudo>
|
||||
ModernToolkit
|
||||
</kudo>
|
||||
</kudos>
|
||||
<custom>
|
||||
<value key="Purism::form_factor">
|
||||
workstation
|
||||
</value>
|
||||
<value key="Purism::form_factor">
|
||||
mobile
|
||||
</value>
|
||||
</custom>
|
||||
<requires>
|
||||
<display_length compare="ge">
|
||||
360
|
||||
</display_length>
|
||||
</requires>
|
||||
<categories>
|
||||
<category>
|
||||
Utility
|
||||
</category>
|
||||
</categories>
|
||||
<recommends>
|
||||
<control>
|
||||
keyboard
|
||||
</control>
|
||||
<control>
|
||||
pointing
|
||||
</control>
|
||||
<control>
|
||||
touch
|
||||
</control>
|
||||
</recommends>
|
||||
<keywords>
|
||||
<keyword>Bavarder</keyword>
|
||||
<keyword>Chat</keyword>
|
||||
<keyword>GPT</keyword>
|
||||
<keyword>ChatGPT</keyword>
|
||||
<keyword>AI</keyword>
|
||||
<keyword>OpenAI</keyword>
|
||||
<keyword>Open Assistant</keyword>
|
||||
<keyword>HuggingFace</keyword>
|
||||
<keyword>
|
||||
Bavarder
|
||||
</keyword>
|
||||
<keyword>
|
||||
Chat
|
||||
</keyword>
|
||||
<keyword>
|
||||
GPT
|
||||
</keyword>
|
||||
<keyword>
|
||||
ChatGPT
|
||||
</keyword>
|
||||
<keyword>
|
||||
AI
|
||||
</keyword>
|
||||
<keyword>
|
||||
OpenAI
|
||||
</keyword>
|
||||
<keyword>
|
||||
Open Assistant
|
||||
</keyword>
|
||||
<keyword>
|
||||
HuggingFace
|
||||
</keyword>
|
||||
</keywords>
|
||||
|
||||
<releases>
|
||||
<release version="0.2.4" date="2023-6-16" type="stable">
|
||||
<description>
|
||||
<p>New UI</p>
|
||||
<p>Faster BaiChat</p>
|
||||
<p>Fix some bugs</p>
|
||||
<p>Update translations</p>
|
||||
<p>Add better error handling</p>
|
||||
</description>
|
||||
</release>
|
||||
<release version="0.2.3" date="2023-5-21" type="stable">
|
||||
<description>
|
||||
<p>Add the ability to use local model</p>
|
||||
<p>Add the ability to use custom model in OpenAI</p>
|
||||
<p>Make loading mechanism faster</p>
|
||||
<p>Fix some bugs</p>
|
||||
<p>Update translations</p>
|
||||
<p>Add CI</p>
|
||||
<p>Add support for launching Bavarder offline</p>
|
||||
<p>Update Blueprint to v0.8.0</p>
|
||||
<p>Add better error handling</p>
|
||||
</description>
|
||||
</release>
|
||||
<release version="0.2.2" date="2023-5-16" type="stable">
|
||||
<description>
|
||||
<p>Allow fetching news about providers and check if there is some issues about them</p>
|
||||
<p>Hugging Chat is now disabled because of a change which require to login</p>
|
||||
<p>Providers moved to the menu</p>
|
||||
<p>Update screenshots</p>
|
||||
<p>Fix some bugs</p>
|
||||
<p>Update translations</p>
|
||||
<p>Add CI</p>
|
||||
<p>Add support for launching Bavarder offline</p>
|
||||
<p>Update Blueprint to v0.8.0</p>
|
||||
<p>Add better error handling</p>
|
||||
</description>
|
||||
</release>
|
||||
<release version="0.2.1" date="2023-5-13" type="stable">
|
||||
<description>
|
||||
<p>Fix Theming support of the new render widget</p>
|
||||
<p>Add the ability to have multiple windows open at the same time</p>
|
||||
<p>Update preferences UI</p>
|
||||
<p>Fix some bugs</p>
|
||||
<p>Update translations</p>
|
||||
<p>Add better error handling</p>
|
||||
</description>
|
||||
</release>
|
||||
<release version="0.2.0" date="2023-5-11" type="stable">
|
||||
<description>
|
||||
<p>Add support of formatting in the response view using Markdown</p>
|
||||
<p>Allow disabling the new render method </p>
|
||||
<p>Add description of providers</p>
|
||||
<p>Add help for getting a token for providers</p>
|
||||
<p>New website including some help for providers</p>
|
||||
<p>Fix an issue which caused the app to spin forever</p>
|
||||
<p>Remove Quit entry in the app menu</p>
|
||||
<p>Fix keyboard shortcuts</p>
|
||||
<p>Fix some bugs</p>
|
||||
<p>Update translations</p>
|
||||
<p>Add better error handling</p>
|
||||
</description>
|
||||
</release>
|
||||
<release version="0.1.7" date="2023-5-7" type="stable">
|
||||
<description>
|
||||
<p>Fix an issue which caused the app to crash randomly</p>
|
||||
<p>Add the ability to enable/disable providers from the preferences</p>
|
||||
<p>Add more keyboard shortcuts</p>
|
||||
<p>Update translations</p>
|
||||
<p>Add better error handling</p>
|
||||
</description>
|
||||
</release>
|
||||
<release version="0.1.6" date="2023-5-6" type="stable">
|
||||
<description>
|
||||
<p>Fix an issue which caused the app to crash randomly</p>
|
||||
<p>Add save/load of settings</p>
|
||||
</description>
|
||||
</release>
|
||||
<release version="0.1.5" date="2023-5-4" type="stable">
|
||||
<description>
|
||||
<p>Fix HuggingChat (again)</p>
|
||||
</description>
|
||||
</release>
|
||||
<release version="0.1.4" date="2023-5-4" type="stable">
|
||||
<description>
|
||||
<p>Fix HuggingChat</p>
|
||||
</description>
|
||||
</release>
|
||||
<release version="0.1.3" date="2023-5-4" type="stable">
|
||||
<description>
|
||||
<p>Add multiple providers support</p>
|
||||
<p>Make HuggingChat the default provider</p>
|
||||
<p>Fix some bugs</p>
|
||||
<p>Focus on the response entry</p>
|
||||
<p>Update translations</p>
|
||||
</description>
|
||||
</release>
|
||||
<release version="0.1.2" date="2023-4-27" type="stable">
|
||||
<description>
|
||||
<p>Fix appdata not having release tags</p>
|
||||
</description>
|
||||
</release>
|
||||
<release version="0.1.1" date="2023-4-27" type="stable">
|
||||
<description>
|
||||
<p>Change app ID to io.github.Bavarder.Bavarder</p>
|
||||
</description>
|
||||
</release>
|
||||
<release version="0.1.0" date="2023-4-27" type="stable">
|
||||
<description>
|
||||
<p>First release of Bavarder</p>
|
||||
</description>
|
||||
</release>
|
||||
</releases>
|
||||
<releases>
|
||||
<release version="1.0.0" date="2023-7-19" type="stable">
|
||||
<description>
|
||||
<p>
|
||||
Brand new UI
|
||||
</p>
|
||||
</description>
|
||||
</release>
|
||||
<release version="0.2.4" date="2023-6-16" type="stable">
|
||||
<description>
|
||||
<p>
|
||||
New UI
|
||||
</p>
|
||||
<p>
|
||||
Faster BaiChat
|
||||
</p>
|
||||
<p>
|
||||
Fix some bugs
|
||||
</p>
|
||||
<p>
|
||||
Update translations
|
||||
</p>
|
||||
<p>
|
||||
Add better error handling
|
||||
</p>
|
||||
</description>
|
||||
</release>
|
||||
<release version="0.2.3" date="2023-5-21" type="stable">
|
||||
<description>
|
||||
<p>
|
||||
Add the ability to use local model
|
||||
</p>
|
||||
<p>
|
||||
Add the ability to use custom model in OpenAI
|
||||
</p>
|
||||
<p>
|
||||
Make loading mechanism faster
|
||||
</p>
|
||||
<p>
|
||||
Fix some bugs
|
||||
</p>
|
||||
<p>
|
||||
Update translations
|
||||
</p>
|
||||
<p>
|
||||
Add CI
|
||||
</p>
|
||||
<p>
|
||||
Add support for launching Bavarder offline
|
||||
</p>
|
||||
<p>
|
||||
Update Blueprint to v0.8.0
|
||||
</p>
|
||||
<p>
|
||||
Add better error handling
|
||||
</p>
|
||||
</description>
|
||||
</release>
|
||||
<release version="0.2.2" date="2023-5-16" type="stable">
|
||||
<description>
|
||||
<p>
|
||||
Allow fetching news about providers and check if there is some issues about them
|
||||
</p>
|
||||
<p>
|
||||
Hugging Chat is now disabled because of a change which require to login
|
||||
</p>
|
||||
<p>
|
||||
Providers moved to the menu
|
||||
</p>
|
||||
<p>
|
||||
Update screenshots
|
||||
</p>
|
||||
<p>
|
||||
Fix some bugs
|
||||
</p>
|
||||
<p>
|
||||
Update translations
|
||||
</p>
|
||||
<p>
|
||||
Add CI
|
||||
</p>
|
||||
<p>
|
||||
Add support for launching Bavarder offline
|
||||
</p>
|
||||
<p>
|
||||
Update Blueprint to v0.8.0
|
||||
</p>
|
||||
<p>
|
||||
Add better error handling
|
||||
</p>
|
||||
</description>
|
||||
</release>
|
||||
<release version="0.2.1" date="2023-5-13" type="stable">
|
||||
<description>
|
||||
<p>
|
||||
Fix Theming support of the new render widget
|
||||
</p>
|
||||
<p>
|
||||
Add the ability to have multiple windows open at the same time
|
||||
</p>
|
||||
<p>
|
||||
Update preferences UI
|
||||
</p>
|
||||
<p>
|
||||
Fix some bugs
|
||||
</p>
|
||||
<p>
|
||||
Update translations
|
||||
</p>
|
||||
<p>
|
||||
Add better error handling
|
||||
</p>
|
||||
</description>
|
||||
</release>
|
||||
<release version="0.2.0" date="2023-5-11" type="stable">
|
||||
<description>
|
||||
<p>
|
||||
Add support of formatting in the response view using Markdown
|
||||
</p>
|
||||
<p>
|
||||
Allow disabling the new render method
|
||||
</p>
|
||||
<p>
|
||||
Add description of providers
|
||||
</p>
|
||||
<p>
|
||||
Add help for getting a token for providers
|
||||
</p>
|
||||
<p>
|
||||
New website including some help for providers
|
||||
</p>
|
||||
<p>
|
||||
Fix an issue which caused the app to spin forever
|
||||
</p>
|
||||
<p>
|
||||
Remove Quit entry in the app menu
|
||||
</p>
|
||||
<p>
|
||||
Fix keyboard shortcuts
|
||||
</p>
|
||||
<p>
|
||||
Fix some bugs
|
||||
</p>
|
||||
<p>
|
||||
Update translations
|
||||
</p>
|
||||
<p>
|
||||
Add better error handling
|
||||
</p>
|
||||
</description>
|
||||
</release>
|
||||
<release version="0.1.7" date="2023-5-7" type="stable">
|
||||
<description>
|
||||
<p>
|
||||
Fix an issue which caused the app to crash randomly
|
||||
</p>
|
||||
<p>
|
||||
Add the ability to enable/disable providers from the preferences
|
||||
</p>
|
||||
<p>
|
||||
Add more keyboard shortcuts
|
||||
</p>
|
||||
<p>
|
||||
Update translations
|
||||
</p>
|
||||
<p>
|
||||
Add better error handling
|
||||
</p>
|
||||
</description>
|
||||
</release>
|
||||
<release version="0.1.6" date="2023-5-6" type="stable">
|
||||
<description>
|
||||
<p>
|
||||
Fix an issue which caused the app to crash randomly
|
||||
</p>
|
||||
<p>
|
||||
Add save/load of settings
|
||||
</p>
|
||||
</description>
|
||||
</release>
|
||||
<release version="0.1.5" date="2023-5-4" type="stable">
|
||||
<description>
|
||||
<p>
|
||||
Fix HuggingChat (again)
|
||||
</p>
|
||||
</description>
|
||||
</release>
|
||||
<release version="0.1.4" date="2023-5-4" type="stable">
|
||||
<description>
|
||||
<p>
|
||||
Fix HuggingChat
|
||||
</p>
|
||||
</description>
|
||||
</release>
|
||||
<release version="0.1.3" date="2023-5-4" type="stable">
|
||||
<description>
|
||||
<p>
|
||||
Add multiple providers support
|
||||
</p>
|
||||
<p>
|
||||
Make HuggingChat the default provider
|
||||
</p>
|
||||
<p>
|
||||
Fix some bugs
|
||||
</p>
|
||||
<p>
|
||||
Focus on the response entry
|
||||
</p>
|
||||
<p>
|
||||
Update translations
|
||||
</p>
|
||||
</description>
|
||||
</release>
|
||||
<release version="0.1.2" date="2023-4-27" type="stable">
|
||||
<description>
|
||||
<p>
|
||||
Fix appdata not having release tags
|
||||
</p>
|
||||
</description>
|
||||
</release>
|
||||
<release version="0.1.1" date="2023-4-27" type="stable">
|
||||
<description>
|
||||
<p>
|
||||
Change app ID to io.github.Bavarder.Bavarder
|
||||
</p>
|
||||
</description>
|
||||
</release>
|
||||
<release version="0.1.0" date="2023-4-27" type="stable">
|
||||
<description>
|
||||
<p>
|
||||
First release of Bavarder
|
||||
</p>
|
||||
</description>
|
||||
</release>
|
||||
</releases>
|
||||
</component>
|
||||
|
|
|
@ -1,6 +1,15 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<schemalist gettext-domain="bavarder">
|
||||
<schema id="@APP_ID@" path="/io/github/Bavarder/Bavarder/">
|
||||
<key name="local-mode" type="b">
|
||||
<default>true</default>
|
||||
</key>
|
||||
<key name="current-provider" type="s">
|
||||
<default>'cat-gpt'</default>
|
||||
</key>
|
||||
<key name="model" type="s">
|
||||
<default>'ggml-model-gpt4all-falcon-q4_0.bin'</default>
|
||||
</key>
|
||||
<key name="width" type="i">
|
||||
<default>350</default>
|
||||
</key>
|
||||
|
@ -13,26 +22,6 @@
|
|||
<key name="is-fullscreen" type="b">
|
||||
<default>false</default>
|
||||
</key>
|
||||
<key name="clear-after-send" type="b">
|
||||
<default>false</default>
|
||||
</key>
|
||||
<key name="enabled-providers" type="as">
|
||||
<default>["baichat", "hfopenassistantsft1pythia12b", "catgpt", "openaigpt35turbo"]</default>
|
||||
</key>
|
||||
<key name="latest-provider" type="s">
|
||||
<default>'hfopenassistantsft1pythia12b'</default>
|
||||
</key>
|
||||
<key name="providers-data" type="a{ss}">
|
||||
<default>{}</default>
|
||||
</key>
|
||||
<key name="use-text-view" type="b">
|
||||
<default>false</default>
|
||||
</key>
|
||||
<key name="close-all-without-dialog" type="b">
|
||||
<default>false</default>
|
||||
</key>
|
||||
<key name="allow-remote-fetching" type="b">
|
||||
<default>true</default>
|
||||
</key>
|
||||
|
||||
</schema>
|
||||
</schemalist>
|
||||
|
|
|
@ -1,7 +1,4 @@
|
|||
gnome = import('gnome')
|
||||
pkgdatadir = join_paths(get_option('prefix'), get_option('datadir'), meson.project_name())
|
||||
|
||||
subdir('ui')
|
||||
|
||||
desktop_file = i18n.merge_file(
|
||||
input: configure_file(
|
||||
|
@ -23,15 +20,6 @@ if desktop_utils.found()
|
|||
)
|
||||
endif
|
||||
|
||||
gnome.compile_resources('bavarder',
|
||||
'bavarder.gresource.xml',
|
||||
gresource_bundle: true,
|
||||
source_dir: meson.current_build_dir(),
|
||||
install: true,
|
||||
install_dir: PKGDATA_DIR,
|
||||
dependencies: blueprints
|
||||
)
|
||||
|
||||
appstream_file = i18n.merge_file(
|
||||
input: configure_file(
|
||||
input: '@0@.appdata.xml.in.in'.format(PROJECT_RDNN_NAME),
|
||||
|
|
Before Width: | Height: | Size: 38 KiB |
Before Width: | Height: | Size: 33 KiB |
Before Width: | Height: | Size: 32 KiB |
|
@ -1,44 +0,0 @@
|
|||
.text-box textview,
|
||||
.text-box text {
|
||||
background: none;
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
.scrolled-window undershoot.top {
|
||||
box-shadow: inset 0 1px alpha(@shade_color, .75);
|
||||
background: linear-gradient(to bottom, alpha(@shade_color, .75), transparent 4px);
|
||||
}
|
||||
|
||||
.scrolled-window undershoot.bottom {
|
||||
box-shadow: inset 0 -1px alpha(@shade_color, .75);
|
||||
background: linear-gradient(to top, alpha(@shade_color, .75), transparent 4px);
|
||||
}
|
||||
|
||||
|
||||
/* Global */
|
||||
|
||||
scrolledwindow > viewport > clamp > box {
|
||||
margin: 42px 12px;
|
||||
border-spacing: 24px;
|
||||
}
|
||||
|
||||
entry:disabled {
|
||||
border-color: transparent;
|
||||
color: @view_fg_color;
|
||||
background: none;
|
||||
}
|
||||
|
||||
entry textview {
|
||||
color: @view_fg_color;
|
||||
background: none;
|
||||
}
|
||||
|
||||
entry text {
|
||||
color: @view_fg_color;
|
||||
background: none;
|
||||
}
|
||||
|
||||
|
||||
entry .inline-pill {
|
||||
margin-bottom: -0.5em;
|
||||
}
|
|
@ -1,10 +0,0 @@
|
|||
blueprints = custom_target('blueprints',
|
||||
input: files(
|
||||
'help-overlay.blp',
|
||||
'preferences.blp',
|
||||
'message_bubble.blp',
|
||||
'window.blp',
|
||||
),
|
||||
output: '.',
|
||||
command: [find_program('blueprint-compiler'), 'batch-compile', '@OUTPUT@', '@CURRENT_SOURCE_DIR@', '@INPUT@']
|
||||
)
|
|
@ -1,20 +0,0 @@
|
|||
using Gtk 4.0;
|
||||
using Adw 1;
|
||||
|
||||
template $MessageBubble: Gtk.Box {
|
||||
orientation: vertical;
|
||||
|
||||
Label sender_label {
|
||||
styles ["caption-heading"]
|
||||
|
||||
ellipsize: end;
|
||||
xalign: 0;
|
||||
}
|
||||
|
||||
Adw.Bin message_reply_bin {}
|
||||
|
||||
Adw.Bin prefix_bin {}
|
||||
|
||||
Label message_label {
|
||||
}
|
||||
}
|
|
@ -1,55 +0,0 @@
|
|||
using Gtk 4.0;
|
||||
using Adw 1;
|
||||
|
||||
template $Preferences : Adw.PreferencesWindow {
|
||||
title: _("Preferences");
|
||||
default-height: 400;
|
||||
default-width: 600;
|
||||
modal: true;
|
||||
|
||||
Adw.PreferencesPage general_page {
|
||||
Adw.PreferencesGroup prompt_group {
|
||||
title: _("Prompt");
|
||||
|
||||
Adw.ActionRow {
|
||||
title: _("Clear prompt after send");
|
||||
subtitle: _("The prompt will be cleared after send");
|
||||
activatable-widget: clear_after_send_switch;
|
||||
Gtk.Switch clear_after_send_switch {
|
||||
valign: center;
|
||||
}
|
||||
}
|
||||
|
||||
Adw.ActionRow {
|
||||
title: _("Use plain text for output");
|
||||
subtitle: _("The plain text without formatting will be used");
|
||||
activatable-widget: use_text_view_switch;
|
||||
Gtk.Switch use_text_view_switch {
|
||||
valign: center;
|
||||
}
|
||||
}
|
||||
|
||||
Adw.ActionRow {
|
||||
title: _("Close all windows without warning");
|
||||
subtitle: _("All windows will be closed without warning, this can lead to data loss");
|
||||
activatable-widget: close_all_without_dialog_switch;
|
||||
Gtk.Switch close_all_without_dialog_switch {
|
||||
valign: center;
|
||||
}
|
||||
}
|
||||
|
||||
Adw.ActionRow {
|
||||
title: _("Look for provider news");
|
||||
subtitle: _("News about issues with providers will be fetched from Bavarder website");
|
||||
activatable-widget: allow_remote_fetching_switch;
|
||||
Gtk.Switch allow_remote_fetching_switch {
|
||||
valign: center;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Adw.PreferencesGroup provider_group {
|
||||
title: _("Providers");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,254 +0,0 @@
|
|||
using Gtk 4.0;
|
||||
using Adw 1;
|
||||
using WebKit 6.0;
|
||||
|
||||
template $BavarderWindow : Adw.ApplicationWindow {
|
||||
|
||||
title: _("Bavarder");
|
||||
default-width: 350;
|
||||
default-height: 500;
|
||||
|
||||
ShortcutController {
|
||||
Shortcut {
|
||||
trigger: "<primary>q";
|
||||
action: "action(window.close)";
|
||||
}
|
||||
}
|
||||
|
||||
Adw.ToastOverlay toast_overlay {
|
||||
Box {
|
||||
orientation: vertical;
|
||||
vexpand: true;
|
||||
hexpand: true;
|
||||
Adw.HeaderBar {
|
||||
MenuButton menu {
|
||||
primary: true;
|
||||
menu-model: main-menu;
|
||||
icon-name: "open-menu-symbolic";
|
||||
tooltip-text: _("Main Menu");
|
||||
}
|
||||
styles ["flat"]
|
||||
}
|
||||
|
||||
Adw.Banner banner {
|
||||
title: _("No network connection");
|
||||
revealed: false;
|
||||
}
|
||||
|
||||
Box main {
|
||||
orientation: vertical;
|
||||
vexpand: true;
|
||||
hexpand: true;
|
||||
margin-start: 24;
|
||||
margin-end: 24;
|
||||
spacing: 12;
|
||||
|
||||
Adw.Bin {
|
||||
vexpand: true;
|
||||
hexpand: true;
|
||||
|
||||
Box {
|
||||
orientation: vertical;
|
||||
|
||||
|
||||
Stack stack {
|
||||
transition-type: crossfade;
|
||||
|
||||
styles [ "card"]
|
||||
|
||||
Gtk.StackPage {
|
||||
name: "page_content";
|
||||
child: Overlay overlay {
|
||||
|
||||
Adw.PreferencesGroup bot_group {
|
||||
Box {
|
||||
orientation: vertical;
|
||||
hexpand: true;
|
||||
vexpand: true;
|
||||
|
||||
styles [ "text-box"]
|
||||
|
||||
ScrolledWindow scrolled_response_window {
|
||||
margin-top: 12;
|
||||
margin-bottom: 0;
|
||||
margin-start: 12;
|
||||
margin-end: 12;
|
||||
|
||||
TextView bot_text_view {
|
||||
wrap-mode: word_char;
|
||||
hexpand: true;
|
||||
vexpand: true;
|
||||
editable: false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Box {
|
||||
hexpand: true;
|
||||
halign: end;
|
||||
|
||||
styles ["toolbar"]
|
||||
|
||||
// Button speak {
|
||||
// action-name: "app.speak";
|
||||
// tooltip-text: _("Speak");
|
||||
// icon-name: "audio-speakers-symbolic";
|
||||
// }
|
||||
|
||||
// Button speak_wait {
|
||||
// visible: false;
|
||||
// sensitive: false;
|
||||
// tooltip-text: _("Speaking");
|
||||
// Spinner speak_spinner {
|
||||
// margin-top: 8;
|
||||
// margin-bottom: 8;
|
||||
// margin-start: 8;
|
||||
// margin-end: 8;
|
||||
// }
|
||||
// }
|
||||
|
||||
Button copy_bot {
|
||||
sensitive: false;
|
||||
icon-name: "edit-copy-symbolic";
|
||||
tooltip-text: _("Copy to Clipboard");
|
||||
hexpand: true;
|
||||
halign: end;
|
||||
action-name: "app.copy_bot";
|
||||
}
|
||||
|
||||
Button stop_button {
|
||||
visible: false;
|
||||
sensitive: false;
|
||||
icon-name: "x-circular-symbolic";
|
||||
tooltip-text: _("Stop");
|
||||
hexpand: true;
|
||||
halign: end;
|
||||
action-name: "app.stop";
|
||||
styles ["suggested-action", "circular"]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
Gtk.StackPage {
|
||||
name: "page_loading";
|
||||
child: Spinner {
|
||||
valign: center;
|
||||
halign: center;
|
||||
vexpand: true;
|
||||
};
|
||||
}
|
||||
|
||||
Gtk.StackPage {
|
||||
name: "page_error";
|
||||
child: Adw.StatusPage error {
|
||||
visible: true;
|
||||
vexpand: true;
|
||||
icon-name: "dialog-error-symbolic";
|
||||
title: _("ERROR");
|
||||
description: _("DESCRIPTION");
|
||||
|
||||
Button {
|
||||
label: _("Try Again");
|
||||
halign: center;
|
||||
styles ["pill"]
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// Separator {}
|
||||
|
||||
Adw.Clamp {
|
||||
vexpand: false;
|
||||
hexpand: true;
|
||||
maximum-size: 750;
|
||||
tightening-threshold: 550;
|
||||
|
||||
margin-top: 8;
|
||||
margin-bottom: 8;
|
||||
|
||||
Box {
|
||||
|
||||
// Button {
|
||||
// valign: end;
|
||||
// icon-name: "mail-attachment-symbolic";
|
||||
// }
|
||||
|
||||
|
||||
ScrolledWindow {
|
||||
vexpand: true;
|
||||
hexpand: true;
|
||||
vscrollbar-policy: external;
|
||||
max-content-height: 200;
|
||||
propagate-natural-height: true;
|
||||
|
||||
styles [ "scrolled-window" ]
|
||||
|
||||
|
||||
TextView prompt_text_view {
|
||||
|
||||
styles [ "entry "]
|
||||
|
||||
hexpand: true;
|
||||
accepts-tab: false;
|
||||
top-margin: 7;
|
||||
bottom-margin: 7;
|
||||
left-margin: 5;
|
||||
right-margin: 5;
|
||||
wrap-mode: word;
|
||||
buffer: TextBuffer { };
|
||||
}
|
||||
}
|
||||
|
||||
Button ask_button {
|
||||
valign: end;
|
||||
|
||||
margin-start: 5;
|
||||
|
||||
icon-name: "paper-plane-symbolic";
|
||||
tooltip-text: _("Ask");
|
||||
halign: end;
|
||||
action-name: "app.ask";
|
||||
styles ["suggested-action", "circular"]
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
menu main-menu {
|
||||
section {
|
||||
item {
|
||||
label: _("New window");
|
||||
action: "app.new";
|
||||
}
|
||||
}
|
||||
section {
|
||||
item {
|
||||
label: _("Preferences");
|
||||
action: "app.preferences";
|
||||
}
|
||||
|
||||
item {
|
||||
label: _("Keyboard Shortcuts");
|
||||
action: "win.show-help-overlay";
|
||||
}
|
||||
|
||||
item {
|
||||
label: _("About Bavarder");
|
||||
action: "app.about";
|
||||
}
|
||||
}
|
||||
}
|
15
meson.build
|
@ -1,5 +1,5 @@
|
|||
project('bavarder',
|
||||
version: '0.2.4',
|
||||
version: '0.1.0',
|
||||
meson_version: '>= 0.62.0',
|
||||
default_options: [ 'warning_level=2', 'werror=false', ],
|
||||
)
|
||||
|
@ -10,11 +10,16 @@ python = import('python')
|
|||
|
||||
# Constants
|
||||
PROJECT_RDNN_NAME = 'io.github.Bavarder.Bavarder'
|
||||
BUGTRACKER_URL = 'https://codeberg.org/Bavarder/Bavarder/issues'
|
||||
HELP_URL = 'https://codeberg.orgBavarder/Bavarder/issues'
|
||||
TRANSLATE_URL = 'https://translate.codeberg.org/engage/bavarder/'
|
||||
BUGTRACKER_URL = 'https://gnome.org'
|
||||
HELP_URL = 'https://gnome.org'
|
||||
TRANSLATE_URL = 'https://gnome.org'
|
||||
|
||||
PROJECT_URL = 'https://bavarder.codeberg.page'
|
||||
PROJECT_URL = 'https://gnome.org'
|
||||
|
||||
dependency('gtk4', version: '>= 4.5.0')
|
||||
dependency('libadwaita-1', version: '>= 1.3.99')
|
||||
dependency('libportal', version: '>= 0.6')
|
||||
dependency('gtksourceview-5', version: '>= 5')
|
||||
|
||||
git_bin = find_program('git', required: false)
|
||||
|
||||
|
|
|
@ -1,11 +0,0 @@
|
|||
option(
|
||||
'profile',
|
||||
type: 'combo',
|
||||
description: 'The build profiles for the application. Use development or ci for the .Devel app ID. ci also produces optimized bundles.',
|
||||
choices: [
|
||||
'release',
|
||||
'development',
|
||||
'ci',
|
||||
],
|
||||
value: 'release'
|
||||
)
|
264
po/Bavarder.pot
|
@ -8,7 +8,7 @@ msgid ""
|
|||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2023-06-01 17:40+0000\n"
|
||||
"POT-Creation-Date: 2023-07-19 12:39+0200\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
|
@ -17,175 +17,135 @@ msgstr ""
|
|||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
|
||||
#: data/io.github.Bavarder.Bavarder.desktop.in.in:3 data/ui/window.blp:7
|
||||
#: data/io.github.Bavarder.Bavarder.desktop.in.in:3 src/views/window.blp:6
|
||||
#: src/views/window.blp:26
|
||||
msgid "Bavarder"
|
||||
msgstr ""
|
||||
|
||||
#: data/ui/preferences.blp:5 data/ui/window.blp:230 src/main.py:273
|
||||
msgid "Preferences"
|
||||
#: src/providers/catgpt.py:7
|
||||
msgid "Chit-Chat with a Cat"
|
||||
msgstr ""
|
||||
|
||||
#: data/ui/preferences.blp:12
|
||||
msgid "Prompt"
|
||||
msgstr ""
|
||||
|
||||
#: data/ui/preferences.blp:15
|
||||
msgid "Clear prompt after send"
|
||||
msgstr ""
|
||||
|
||||
#: data/ui/preferences.blp:16
|
||||
msgid "The prompt will be cleared after send"
|
||||
msgstr ""
|
||||
|
||||
#: data/ui/preferences.blp:24
|
||||
msgid "Use plain text for output"
|
||||
msgstr ""
|
||||
|
||||
#: data/ui/preferences.blp:25
|
||||
msgid "The plain text without formatting will be used"
|
||||
msgstr ""
|
||||
|
||||
#: data/ui/preferences.blp:33
|
||||
msgid "Close all windows without warning"
|
||||
msgstr ""
|
||||
|
||||
#: data/ui/preferences.blp:34
|
||||
msgid "All windows will be closed without warning, this can lead to data loss"
|
||||
msgstr ""
|
||||
|
||||
#: data/ui/preferences.blp:42
|
||||
msgid "Look for provider news"
|
||||
msgstr ""
|
||||
|
||||
#: data/ui/preferences.blp:43
|
||||
msgid "News about issues with providers will be fetched from Bavarder website"
|
||||
msgstr ""
|
||||
|
||||
#: data/ui/preferences.blp:52 src/main.py:271
|
||||
msgid "Providers"
|
||||
msgstr ""
|
||||
|
||||
#: data/ui/window.blp:28
|
||||
msgid "Main Menu"
|
||||
msgstr ""
|
||||
|
||||
#: data/ui/window.blp:34 src/providers/base.py:50
|
||||
msgid "No network connection"
|
||||
msgstr ""
|
||||
|
||||
#: data/ui/window.blp:61
|
||||
msgid "Response"
|
||||
msgstr ""
|
||||
|
||||
#: data/ui/window.blp:113
|
||||
msgid "Copy to Clipboard"
|
||||
msgstr ""
|
||||
|
||||
#: data/ui/window.blp:123
|
||||
msgid "Stop"
|
||||
msgstr ""
|
||||
|
||||
#: data/ui/window.blp:152
|
||||
msgid "ERROR"
|
||||
msgstr ""
|
||||
|
||||
#: data/ui/window.blp:153
|
||||
msgid "DESCRIPTION"
|
||||
msgstr ""
|
||||
|
||||
#: data/ui/window.blp:156
|
||||
msgid "Try Again"
|
||||
msgstr ""
|
||||
|
||||
#: data/ui/window.blp:205
|
||||
msgid "Ask"
|
||||
msgstr ""
|
||||
|
||||
#: data/ui/window.blp:224
|
||||
msgid "New window"
|
||||
msgstr ""
|
||||
|
||||
#: data/ui/window.blp:235 src/main.py:274
|
||||
msgid "Keyboard Shortcuts"
|
||||
msgstr ""
|
||||
|
||||
#: data/ui/window.blp:240 src/main.py:275
|
||||
msgid "About Bavarder"
|
||||
msgstr ""
|
||||
|
||||
#: src/providers/base.py:43
|
||||
msgid "No API key provided, you can provide one in settings"
|
||||
msgstr ""
|
||||
|
||||
#: src/providers/base.py:45
|
||||
msgid "Open settings"
|
||||
msgstr ""
|
||||
|
||||
#: src/providers/base.py:81
|
||||
msgid "About provider"
|
||||
msgstr ""
|
||||
|
||||
#: src/providers/base.py:95
|
||||
msgid "How to get a token"
|
||||
msgstr ""
|
||||
|
||||
#: src/providers/base.py:118
|
||||
#: src/providers/provider_item.blp:12
|
||||
msgid "No preferences available"
|
||||
msgstr ""
|
||||
|
||||
#: src/providers/huggingface.py:73 src/providers/transformer.py:68
|
||||
msgid "API Key"
|
||||
msgstr ""
|
||||
|
||||
#: src/providers/openai.py:27
|
||||
msgid "Prompt too long, splitting into chunks."
|
||||
msgstr ""
|
||||
|
||||
#: src/providers/openai.py:49
|
||||
msgid "You don't have access to this model"
|
||||
msgstr ""
|
||||
|
||||
#: src/providers/openai.py:54
|
||||
msgid ""
|
||||
"You exceeded your current quota, please check your plan and billing details."
|
||||
msgstr ""
|
||||
|
||||
#: src/providers/openai.py:59
|
||||
msgid "API Error"
|
||||
msgstr ""
|
||||
|
||||
#: src/providers/openai.py:70
|
||||
msgid "No model selected, you can choose one in preferences"
|
||||
msgstr ""
|
||||
|
||||
#: src/providers/openaicustom.py:33
|
||||
msgid "API Url"
|
||||
msgstr ""
|
||||
|
||||
#: src/providers/openaicustom.py:40
|
||||
msgid "Model"
|
||||
msgstr ""
|
||||
|
||||
#: src/providers/openaicustom.py:80
|
||||
msgid "How to choose a model"
|
||||
msgstr ""
|
||||
|
||||
#: src/views/about_window.py:12
|
||||
msgid "translator-credits"
|
||||
msgstr ""
|
||||
|
||||
#: src/views/about_window.py:26
|
||||
msgid "0xMRTT"
|
||||
msgid "Bavarder Developers"
|
||||
msgstr ""
|
||||
|
||||
#: src/views/about_window.py:44
|
||||
msgid "Copyright © 2023 0xMRTT"
|
||||
msgid "Copyright © 2023 Bavarder Developers"
|
||||
msgstr ""
|
||||
|
||||
#: src/main.py:124
|
||||
msgid "New version available!"
|
||||
#: src/views/preferences_window.py:47 src/views/preferences_window.blp:17
|
||||
msgid "Models"
|
||||
msgstr ""
|
||||
|
||||
#: src/main.py:240
|
||||
msgid "New Window"
|
||||
#: src/views/preferences_window.py:54
|
||||
msgid "Download more models"
|
||||
msgstr ""
|
||||
|
||||
#: src/views/preferences_window.blp:5 src/views/window.py:156
|
||||
#: src/views/window.py:178 src/views/window.blp:218
|
||||
msgid "Preferences"
|
||||
msgstr ""
|
||||
|
||||
#: src/views/preferences_window.blp:13
|
||||
msgid "Providers"
|
||||
msgstr ""
|
||||
|
||||
#: src/views/window.py:227
|
||||
msgid "Generating response"
|
||||
msgstr ""
|
||||
|
||||
#: src/views/window.py:228
|
||||
msgid "Cancel"
|
||||
msgstr ""
|
||||
|
||||
#: src/views/window.blp:33 src/main.py:146
|
||||
msgid "New Chat"
|
||||
msgstr ""
|
||||
|
||||
#: src/views/window.blp:41
|
||||
msgid "Main Menu"
|
||||
msgstr ""
|
||||
|
||||
#: src/views/window.blp:57
|
||||
msgid "Message"
|
||||
msgstr ""
|
||||
|
||||
#: src/views/window.blp:69
|
||||
msgid "Chat"
|
||||
msgstr ""
|
||||
|
||||
#: src/views/window.blp:115
|
||||
msgid "No Chat"
|
||||
msgstr ""
|
||||
|
||||
#: src/views/window.blp:120
|
||||
msgid "No Internet"
|
||||
msgstr ""
|
||||
|
||||
#: src/views/window.blp:179
|
||||
msgid "Ask"
|
||||
msgstr ""
|
||||
|
||||
#: src/views/window.blp:223
|
||||
msgid "Keyboard Shortcuts"
|
||||
msgstr ""
|
||||
|
||||
#: src/views/window.blp:228
|
||||
msgid "About Bavarder"
|
||||
msgstr ""
|
||||
|
||||
#: src/widgets/download_row.py:29
|
||||
#, python-format
|
||||
msgid "Downloading model %s"
|
||||
msgstr ""
|
||||
|
||||
#: src/widgets/download_row.py:45
|
||||
#, python-format
|
||||
msgid "Model %s downloaded!"
|
||||
msgstr ""
|
||||
|
||||
#: src/widgets/item.blp:79
|
||||
msgid "Edit"
|
||||
msgstr ""
|
||||
|
||||
#: src/widgets/item.blp:85
|
||||
msgid "Remove"
|
||||
msgstr ""
|
||||
|
||||
#: src/widgets/item.py:137
|
||||
msgid "User"
|
||||
msgstr ""
|
||||
|
||||
#: src/widgets/item.py:141
|
||||
msgid "Assistant"
|
||||
msgstr ""
|
||||
|
||||
#: src/widgets/model_item.py:30
|
||||
#, python-format
|
||||
msgid "Model %s deleted!"
|
||||
msgstr ""
|
||||
|
||||
#: src/widgets/thread_item.blp:29 src/widgets/thread_item.py:54
|
||||
msgid "Edit Title"
|
||||
msgstr ""
|
||||
|
||||
#: src/widgets/thread_item.py:46
|
||||
msgid "Set Title"
|
||||
msgstr ""
|
||||
|
||||
#: src/main.py:226
|
||||
msgid "Please download a model from Preferences!"
|
||||
msgstr ""
|
||||
|
||||
#: src/main.py:239
|
||||
msgid "Please enable a provider from the Brain Menu"
|
||||
msgstr ""
|
||||
|
|
36
po/LINGUAS
|
@ -1,23 +1,23 @@
|
|||
th
|
||||
sv
|
||||
fa
|
||||
fi
|
||||
ru
|
||||
ta
|
||||
nl
|
||||
gl
|
||||
es
|
||||
fr
|
||||
pt
|
||||
hu
|
||||
de
|
||||
tr
|
||||
pl
|
||||
ar
|
||||
it
|
||||
zh_Hans
|
||||
az
|
||||
cs
|
||||
uk
|
||||
de
|
||||
es
|
||||
et
|
||||
fa
|
||||
fi
|
||||
fr
|
||||
gl
|
||||
hu
|
||||
it
|
||||
nl
|
||||
pl
|
||||
pt
|
||||
ru
|
||||
sv
|
||||
ta
|
||||
th
|
||||
tr
|
||||
uk
|
||||
zh_Hans
|
||||
zh_Hant
|
||||
|
|
45
po/POTFILES
|
@ -1,39 +1,26 @@
|
|||
data/io.github.Bavarder.Bavarder.desktop.in.in
|
||||
data/io.github.Bavarder.Bavarder.gschema.xml.in
|
||||
data/ui/help-overlay.blp
|
||||
data/ui/preferences.blp
|
||||
data/ui/window.blp
|
||||
src/gtk/help-overlay.blp
|
||||
src/providers/__init__.py
|
||||
src/providers/alpacalora.py
|
||||
src/providers/baichat.py
|
||||
src/providers/bard.py
|
||||
src/providers/base.py
|
||||
src/providers/baseoffline.py
|
||||
src/providers/catgpt.py
|
||||
src/providers/gradio.py
|
||||
src/providers/hfdialogpt.py
|
||||
src/providers/hfgoogleflant5xxl.py
|
||||
src/providers/hfgoogleflanu12.py
|
||||
src/providers/hfgpt2.py
|
||||
src/providers/hfgpt2large.py
|
||||
src/providers/hfgpt2xl.py
|
||||
src/providers/hfopenassistantsft1pythia12b.py
|
||||
src/providers/huggingchat.py
|
||||
src/providers/huggingchatbase.py
|
||||
src/providers/huggingface.py
|
||||
src/providers/openai.py
|
||||
src/providers/openaicustom.py
|
||||
src/providers/openaigpt4.py
|
||||
src/providers/openaigpt35turbo.py
|
||||
src/providers/openaitextdavinci003.py
|
||||
src/providers/stablelm.py
|
||||
src/providers/starcoder.py
|
||||
src/providers/transformer.py
|
||||
src/providers/provider_item.blp
|
||||
src/providers/provider_item.py
|
||||
src/views/__init__.py
|
||||
src/views/about_window.py
|
||||
src/views/main_window.py
|
||||
src/views/preferences_window.py
|
||||
src/views/preferences_window.blp
|
||||
src/views/window.py
|
||||
src/views/window.blp
|
||||
src/widgets/__init__.py
|
||||
src/widgets/download_row.blp
|
||||
src/widgets/download_row.py
|
||||
src/widgets/item.blp
|
||||
src/widgets/item.py
|
||||
src/widgets/model_item.blp
|
||||
src/widgets/model_item.py
|
||||
src/widgets/thread_item.blp
|
||||
src/widgets/thread_item.py
|
||||
src/__init__.py
|
||||
src/threading.py
|
||||
src/main.py
|
||||
src/main.py
|
||||
src/threading.py
|
0
po/update-pot.sh
Normal file → Executable file
|
@ -2,25 +2,8 @@
|
|||
# chmod +x flatpak-pip-generator
|
||||
# ./flatpak-pip-generator --requirements-file=requirements.txt --output pypi-dependencies
|
||||
|
||||
# use https://johannesjh.github.io/req2flatpak/main/cli.html
|
||||
# 1. pip-compile -o r.txt requirements.txt
|
||||
# 2. ./req2flatpak.py --requirements-file requirements.txt --target-platforms 310-x86_64 310-aarch64 > build-aux/pypi-dependencies.json
|
||||
|
||||
Pygments
|
||||
baichat_py
|
||||
googlebardpy
|
||||
markdown
|
||||
openai
|
||||
pymdown-extensions
|
||||
requests
|
||||
text-generation
|
||||
gradio_client
|
||||
|
||||
|
||||
# replace the curl-cffi entry with
|
||||
# {
|
||||
# "type": "file",
|
||||
# "url": "https://files.pythonhosted.org/packages/d1/6f/5d591a5628423af4598e2d6ff0861fcbc554cc259590fac9f97d9c984611/curl_cffi-0.5.6-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",
|
||||
# "sha256": "7a9df9fabff038f1ac9e7e6f32b5edb5d8df8c2eec64f53f513de1766c17ffdb"
|
||||
# },
|
||||
#
|
||||
tqdm
|
||||
charset-normalizer
|
||||
idna
|
||||
urllib3
|
|
@ -1,23 +0,0 @@
|
|||
diff -Naur a/data/io.github.Bavarder.Bavarder.appdata.xml.in.in b/data/io.github.Bavarder.Bavarder.appdata.xml.in.in
|
||||
--- a/data/io.github.Bavarder.Bavarder.appdata.xml.in.in 2023-06-24 00:43:11.699372881 +0530
|
||||
+++ b/data/io.github.Bavarder.Bavarder.appdata.xml.in.in 2023-06-24 00:47:32.092750714 +0530
|
||||
@@ -1,6 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<component type="desktop">
|
||||
<id>@APP_ID@</id>
|
||||
+ <icon type="stock">snap.bavarder.@APP_ID@</icon>
|
||||
<name>Bavarder</name>
|
||||
<summary>Chit-chat with an AI</summary>
|
||||
<developer_name>0xMRTT</developer_name>
|
||||
diff -Naur a/data/io.github.Bavarder.Bavarder.desktop.in.in b/data/io.github.Bavarder.Bavarder.desktop.in.in
|
||||
--- a/data/io.github.Bavarder.Bavarder.desktop.in.in 2023-06-24 00:43:11.699372881 +0530
|
||||
+++ b/data/io.github.Bavarder.Bavarder.desktop.in.in 2023-06-24 00:47:54.940385267 +0530
|
||||
@@ -1,7 +1,7 @@
|
||||
[Desktop Entry]
|
||||
Name=Bavarder
|
||||
Exec=bavarder
|
||||
-Icon=@APP_ID@
|
||||
+Icon=snap.bavarder.@APP_ID@
|
||||
Terminal=false
|
||||
Type=Application
|
||||
Categories=GTK;
|
|
@ -1,98 +0,0 @@
|
|||
name: bavarder # you probably want to 'snapcraft register <name>'
|
||||
base: core22 # the base snap is the execution environment for this snap
|
||||
adopt-info: bavarder
|
||||
grade: stable # must be 'stable' to release into candidate/stable channels
|
||||
confinement: strict # use 'strict' once you have the right plugs and slots
|
||||
|
||||
architectures:
|
||||
- build-on: amd64
|
||||
- build-on: arm64
|
||||
|
||||
layout:
|
||||
/usr/lib/x86_64-linux-gnu/webkitgtk-6.0:
|
||||
bind: $SNAP/webkitgtk-platform/usr/lib/x86_64-linux-gnu/webkitgtk-6.0
|
||||
|
||||
parts:
|
||||
blueprint-compiler:
|
||||
source: https://gitlab.gnome.org/jwestman/blueprint-compiler.git
|
||||
source-tag: 'v0.8.1'
|
||||
plugin: meson
|
||||
meson-parameters:
|
||||
- --prefix=/usr
|
||||
override-prime: |
|
||||
echo 'Skip'
|
||||
|
||||
bavarder:
|
||||
after: [blueprint-compiler]
|
||||
# See 'snapcraft plugins'
|
||||
plugin: meson
|
||||
source: https://github.com/Bavarder/Bavarder.git
|
||||
source-tag: '0.2.4'
|
||||
meson-parameters:
|
||||
- --prefix=/snap/bavarder/current/usr
|
||||
- -Dbuildtype=release
|
||||
build-snaps:
|
||||
- webkitgtk-6-gnome-2204-sdk/latest/stable
|
||||
build-environment:
|
||||
- LD_LIBRARY_PATH: /snap/webkitgtk-sdk/current/usr/lib:/snap/webkitgtk-sdk/current/usr/lib/$CRAFT_ARCH_TRIPLET:/snap/webkitgtk-sdk/current/usr/lib/webkitgtk-6.0:/snap/webkitgtk-sdk/current/usr/lib/$CRAFT_ARCH_TRIPLET/girepository-1.0:$LD_LIBRARY_PATH
|
||||
- PYTHONPATH: $CRAFT_STAGE/usr/lib/python3/dist-packages:$CRAFT_PART_INSTALL/usr/local/lib/python3.10/dist-packages:$PYTHONPATH
|
||||
- GI_TYPELIB_PATH: /snap/gnome-42-2204-sdk/current/usr/lib/$CRAFT_ARCH_TRIPLET/girepository-1.0:/snap/gnome-42-2204-sdk/current/usr/lib/girepository-1.0:/snap/webkitgtk-6-gnome-2204-sdk/current/usr/lib/$CRAFT_ARCH_TRIPLET/girepository-1.0
|
||||
override-pull: |
|
||||
craftctl default
|
||||
patch -p1 < $CRAFT_PROJECT_DIR/snap/bavarder.patch
|
||||
pip install --prefix=$CRAFT_PART_INSTALL/usr baichat-py==0.3.0 googlebardpy==0.1.0 openai==0.27.7 pymdown-extensions==10.0.1 requests==2.31.0 text-generation==0.5.2 gradio-client==0.2.5 lxml
|
||||
override-build: |
|
||||
craftctl default
|
||||
mkdir -p $CRAFT_PART_INSTALL/meta/gui
|
||||
cp -r $CRAFT_PART_INSTALL/snap/bavarder/current/usr/share/icons $CRAFT_PART_INSTALL/meta/gui/
|
||||
find $CRAFT_PART_INSTALL/meta/gui/icons -type f -not -name 'io.github.Bavarder.Bavarder*' -exec rm {} + -o -type d -empty -exec rmdir {} +
|
||||
for i in `find $CRAFT_PART_INSTALL/meta/gui/icons -name "*.svg" -o -name "*.png"`; do
|
||||
mv $i "`dirname $i`/snap.$CRAFT_PROJECT_NAME.`basename $i`"
|
||||
done
|
||||
sed -e '1c#!/usr/bin/python3' -i $CRAFT_PART_INSTALL/usr/local/bin/*
|
||||
sed -e '1c#!/usr/bin/env python3' -i $CRAFT_PART_INSTALL/snap/bavarder/current/usr/bin/bavarder
|
||||
chmod +x $CRAFT_PART_INSTALL/snap/bavarder/current/usr/bin/bavarder
|
||||
parse-info: [usr/share/appdata/io.github.Bavarder.Bavarder.appdata.xml]
|
||||
organize:
|
||||
snap/bavarder/current: .
|
||||
usr/local: usr
|
||||
prime:
|
||||
- -snap/bavarder
|
||||
gst:
|
||||
after: [ bavarder ]
|
||||
plugin: nil
|
||||
stage-packages:
|
||||
- gir1.2-gstreamer-1.0
|
||||
prime:
|
||||
- usr/lib/$CRAFT_ARCH_TRIPLET/girepository-1.0/Gst-1.0.typelib
|
||||
- usr/lib/$CRAFT_ARCH_TRIPLET/girepository-1.0/GstBase-1.0.typelib
|
||||
- usr/lib/$CRAFT_ARCH_TRIPLET/girepository-1.0/GstCheck-1.0.typelib
|
||||
- usr/lib/$CRAFT_ARCH_TRIPLET/girepository-1.0/GstController-1.0.typelib
|
||||
- usr/lib/$CRAFT_ARCH_TRIPLET/girepository-1.0/GstNet-1.0.typelib
|
||||
|
||||
plugs:
|
||||
webkitgtk-6-gnome-2204:
|
||||
interface: content
|
||||
target: $SNAP/webkitgtk-platform
|
||||
default-provider: webkitgtk-6-gnome-2204
|
||||
|
||||
slots:
|
||||
bavarder:
|
||||
interface: dbus
|
||||
bus: session
|
||||
name: io.github.Bavarder.Bavarder
|
||||
|
||||
apps:
|
||||
bavarder:
|
||||
command: usr/bin/bavarder
|
||||
extensions: [gnome]
|
||||
common-id: io.github.Bavarder.Bavarder
|
||||
environment:
|
||||
PYTHONPATH: $SNAP/usr/lib/python3.10/dist-packages:$PYTHONPATH
|
||||
GI_TYPELIB_PATH: $SNAP/webkitgtk-platform/usr/lib/$CRAFT_ARCH_TRIPLET/girepository-1.0:$GI_TYPELIB_PATH
|
||||
LD_LIBRARY_PATH: $SNAP/webkitgtk-platform/usr/lib/$SNAPCRAFT_ARCH_TRIPLET:$SNAP/webkitgtk-platform/usr/lib/$SNAPCRAFT_ARCH_TRIPLET/webkitgtk-6.0:$LD_LIBRARY_PATH
|
||||
plugs:
|
||||
- network
|
||||
- network-status
|
||||
- network-bind
|
||||
- unity7
|
27
src/bavarder.gresource.xml
Normal file
|
@ -0,0 +1,27 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<gresources>
|
||||
<gresource prefix="/io/github/Bavarder/Bavarder">
|
||||
<file preprocess="xml-stripblanks" alias="ui/window.ui">views/window.ui</file>
|
||||
<file preprocess="xml-stripblanks" alias="ui/preferences_window.ui">views/preferences_window.ui</file>
|
||||
<file preprocess="xml-stripblanks" alias="ui/thread_item.ui">widgets/thread_item.ui</file>
|
||||
<file preprocess="xml-stripblanks" alias="ui/item.ui">widgets/item.ui</file>
|
||||
<file preprocess="xml-stripblanks" alias="ui/provider_item.ui">providers/provider_item.ui</file>
|
||||
<file preprocess="xml-stripblanks" alias="ui/model_item.ui">widgets/model_item.ui</file>
|
||||
<file preprocess="xml-stripblanks" alias="ui/download_row.ui">widgets/download_row.ui</file>
|
||||
<file preprocess="xml-stripblanks" alias="ui/code_block.ui">widgets/code_block.ui</file>
|
||||
<file preprocess="xml-stripblanks">gtk/help-overlay.ui</file>
|
||||
<file>style.css</file>
|
||||
</gresource>
|
||||
|
||||
<gresource prefix="/io/github/Bavarder/Bavarder/icons/scalable/actions/">
|
||||
<file preprocess="xml-stripblanks" alias="check-round-outline-symbolic.svg">../data/icons/hicolor/scalable/actions/check-round-outline-symbolic.svg</file>
|
||||
<file preprocess="xml-stripblanks" alias="paper-plane-symbolic.svg">../data/icons/hicolor/scalable/actions/paper-plane-symbolic.svg</file>
|
||||
<file preprocess="xml-stripblanks" alias="cloud-disabled-symbolic.svg">../data/icons/hicolor/scalable/actions/cloud-disabled-symbolic.svg</file>
|
||||
<file preprocess="xml-stripblanks" alias="cloud-filled-symbolic.svg">../data/icons/hicolor/scalable/actions/cloud-filled-symbolic.svg</file>
|
||||
<file preprocess="xml-stripblanks" alias="brain-augemnted-symbolic.svg">../data/icons/hicolor/scalable/actions/brain-augemnted-symbolic.svg</file>
|
||||
<file preprocess="xml-stripblanks" alias="chat-message-new-symbolic.svg">../data/icons/hicolor/scalable/actions/chat-message-new-symbolic.svg</file>
|
||||
<file preprocess="xml-stripblanks" alias="network-disconnected-symbolic.svg">../data/icons/hicolor/scalable/actions/network-disconnected-symbolic.svg</file>
|
||||
<file preprocess="xml-stripblanks" alias="bot-symbolic.svg">../data/icons/hicolor/scalable/actions/bot-symbolic.svg</file>
|
||||
<file preprocess="xml-stripblanks" alias="terminal-symbolic.svg">../data/icons/hicolor/scalable/actions/terminal-symbolic.svg</file>
|
||||
</gresource>
|
||||
</gresources>
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
# bavarder.in
|
||||
#
|
||||
# Copyright 2023 Me
|
||||
# Copyright 2023
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
|
|
|
@ -10,11 +10,6 @@ ShortcutsWindow help_overlay {
|
|||
ShortcutsGroup {
|
||||
title: C_("shortcut window", "General");
|
||||
|
||||
ShortcutsShortcut {
|
||||
title: C_("shortcut window", "Ask");
|
||||
action-name: "app.ask";
|
||||
}
|
||||
|
||||
ShortcutsShortcut {
|
||||
title: C_("shortcut window", "Show Shortcuts");
|
||||
action-name: "win.show-help-overlay";
|
||||
|
@ -31,18 +26,13 @@ ShortcutsWindow help_overlay {
|
|||
}
|
||||
|
||||
ShortcutsShortcut {
|
||||
title: C_("shortcut window", "Close all windows");
|
||||
action-name: "app.quit_all";
|
||||
title: C_("shortcut window", "Ask");
|
||||
action-name: "app.ask";
|
||||
}
|
||||
|
||||
ShortcutsShortcut {
|
||||
title: C_("shortcut window", "Copy response");
|
||||
action-name: "app.copy_bot";
|
||||
}
|
||||
|
||||
ShortcutsShortcut {
|
||||
title: C_("shortcut window", "Clear");
|
||||
action-name: "app.clear";
|
||||
title: C_("shortcut window", "Cancel Generation");
|
||||
action-name: "win.cancel";
|
||||
}
|
||||
}
|
||||
}
|
1251
src/main.py
|
@ -1,9 +1,31 @@
|
|||
pkgdatadir = join_paths(get_option('prefix'), get_option('datadir'), meson.project_name())
|
||||
moduledir = join_paths(pkgdatadir, 'bavarder')
|
||||
gnome = import('gnome')
|
||||
|
||||
python = import('python')
|
||||
|
||||
blueprints = custom_target('blueprints',
|
||||
input: files(
|
||||
'gtk/help-overlay.blp',
|
||||
'views/preferences_window.blp',
|
||||
'views/window.blp',
|
||||
'widgets/thread_item.blp',
|
||||
'widgets/item.blp',
|
||||
'widgets/model_item.blp',
|
||||
'widgets/download_row.blp',
|
||||
'widgets/code_block.blp',
|
||||
'providers/provider_item.blp',
|
||||
),
|
||||
output: '.',
|
||||
command: [find_program('blueprint-compiler'), 'batch-compile', '@OUTPUT@', '@CURRENT_SOURCE_DIR@', '@INPUT@']
|
||||
)
|
||||
|
||||
gnome.compile_resources('bavarder',
|
||||
'bavarder.gresource.xml',
|
||||
gresource_bundle: true,
|
||||
install: true,
|
||||
install_dir: PKGDATA_DIR,
|
||||
dependencies: blueprints
|
||||
)
|
||||
|
||||
configure_file(
|
||||
input: 'bavarder.in',
|
||||
output: 'bavarder',
|
||||
|
@ -18,17 +40,17 @@ configure_file(
|
|||
output: 'constants.py',
|
||||
configuration: conf,
|
||||
install: true,
|
||||
install_dir: moduledir
|
||||
install_dir: MODULE_DIR
|
||||
)
|
||||
|
||||
bavarder_sources = [
|
||||
'__init__.py',
|
||||
'main.py',
|
||||
'threading.py',
|
||||
'threading.py'
|
||||
]
|
||||
|
||||
PY_INSTALLDIR.install_sources(bavarder_sources, subdir: moduledir)
|
||||
PY_INSTALLDIR.install_sources(bavarder_sources, subdir: MODULE_DIR)
|
||||
|
||||
subdir('providers')
|
||||
subdir('views')
|
||||
subdir('widgets')
|
||||
subdir('widgets')
|
||||
subdir('providers')
|
|
@ -1,38 +1,5 @@
|
|||
# from .huggingchat import HuggingChatProvider
|
||||
from .baichat import BAIChatProvider
|
||||
from .openaigpt35turbo import OpenAIGPT35TurboProvider
|
||||
from .openaigpt4 import OpenAIGPT4Provider
|
||||
from .openaicustom import OpenAICustomProvider, LocalModel
|
||||
from .catgpt import CatGPTProvider
|
||||
from .openaitextdavinci003 import OpenAITextDavinci003
|
||||
from .alpacalora import AlpacaLoRAProvider
|
||||
from .hfgoogleflant5xxl import HuggingFaceGoogleFlanT5XXLProvider
|
||||
from .hfgoogleflanu12 import HuggingFaceGoogleFlanU12Provider
|
||||
from .hfopenassistantsft1pythia12b import HuggingFaceOpenAssistantSFT1PythiaProvider, HuggingChatMask
|
||||
from .hfgpt2 import HuggingFaceGPT2Provider
|
||||
from .hfdialogpt import HuggingFaceDialoGPTLargeProvider
|
||||
# from .bard import BardProvider
|
||||
from .hfgpt2large import HuggingFaceGPT2LargeProvider
|
||||
from .hfgpt2xl import HuggingFaceGPT2XLProvider
|
||||
from .stablelm import StableLMProvider
|
||||
|
||||
PROVIDERS = {
|
||||
"alpacalora": AlpacaLoRAProvider,
|
||||
"baichat": BAIChatProvider,
|
||||
# "bard": BardProvider, # Disabled because we need more documentation on how to use it
|
||||
"catgpt": CatGPTProvider,
|
||||
"hfdialogpt": HuggingFaceDialoGPTLargeProvider,
|
||||
"hfgoogleflant5xxl": HuggingFaceGoogleFlanT5XXLProvider,
|
||||
"hfgoogleflanu12": HuggingFaceGoogleFlanU12Provider,
|
||||
"hfgpt2": HuggingFaceGPT2Provider,
|
||||
"hfgpt2large": HuggingFaceGPT2LargeProvider,
|
||||
"hfgpt2xl": HuggingFaceGPT2XLProvider,
|
||||
"hfopenassistantsft1pythia12b": HuggingFaceOpenAssistantSFT1PythiaProvider,
|
||||
"huggingchat": HuggingChatMask, # hugging chat is replaced by open assistant
|
||||
"local": LocalModel,
|
||||
"openaicustom": OpenAICustomProvider,
|
||||
"openaigpt35turbo": OpenAIGPT35TurboProvider,
|
||||
"openaigpt4": OpenAIGPT4Provider,
|
||||
"openaitextdavinci003": OpenAITextDavinci003,
|
||||
"stablelm": StableLMProvider,
|
||||
}
|
||||
CatGPTProvider,
|
||||
}
|
|
@ -1,55 +0,0 @@
|
|||
from .base import BavarderProvider
|
||||
|
||||
import socket
|
||||
import requests
|
||||
|
||||
from gi.repository import Gtk, Adw, GLib
|
||||
|
||||
|
||||
class AlpacaLoRAProvider(BavarderProvider):
|
||||
name = "Alpaca-LoRA"
|
||||
slug = "alpacalora"
|
||||
|
||||
def __init__(self, win, app, *args, **kwargs):
|
||||
super().__init__(win, app, *args, **kwargs)
|
||||
|
||||
def ask(self, prompt):
|
||||
try:
|
||||
response = requests.post(
|
||||
"https://tloen-alpaca-lora.hf.space/run/predict",
|
||||
json={
|
||||
"data": [
|
||||
prompt,
|
||||
prompt,
|
||||
0.1,
|
||||
0.75,
|
||||
40,
|
||||
4,
|
||||
128,
|
||||
]
|
||||
},
|
||||
).json()
|
||||
except socket.gaierror:
|
||||
self.no_connection()
|
||||
return ""
|
||||
else:
|
||||
self.win.banner.set_revealed(False)
|
||||
if "error" in response:
|
||||
self.win.banner.props.title = response["error"]
|
||||
self.win.banner.props.button_label = ""
|
||||
self.win.banner.set_revealed(True)
|
||||
return ""
|
||||
else:
|
||||
r = response["data"][0]
|
||||
GLib.idle_add(self.update_response, r)
|
||||
return r
|
||||
|
||||
@property
|
||||
def require_api_key(self):
|
||||
return False
|
||||
|
||||
def save(self):
|
||||
return {}
|
||||
|
||||
def load(self, data):
|
||||
pass
|
|
@ -1,41 +0,0 @@
|
|||
from .base import BavarderProvider
|
||||
|
||||
from baichat_py import Completion
|
||||
import socket
|
||||
|
||||
from gi.repository import Gtk, Adw, GLib
|
||||
|
||||
|
||||
class BAIChatProvider(BavarderProvider):
|
||||
name = "BAI Chat"
|
||||
slug = "baichat"
|
||||
|
||||
def __init__(self, win, app, *args, **kwargs):
|
||||
super().__init__(win, app, *args, **kwargs)
|
||||
|
||||
def ask(self, prompt):
|
||||
try:
|
||||
response = ""
|
||||
for token in Completion.create(prompt):
|
||||
response += token
|
||||
GLib.idle_add(self.update_response, response)
|
||||
except KeyError:
|
||||
self.win.banner.set_revealed(False)
|
||||
return ""
|
||||
except socket.gaierror:
|
||||
self.no_connection()
|
||||
return ""
|
||||
else:
|
||||
self.win.banner.set_revealed(False)
|
||||
GLib.idle_add(self.update_response, response)
|
||||
return response
|
||||
|
||||
@property
|
||||
def require_api_key(self):
|
||||
return False
|
||||
|
||||
def save(self):
|
||||
return {}
|
||||
|
||||
def load(self, data):
|
||||
pass
|
|
@ -1,80 +0,0 @@
|
|||
from .base import BavarderProvider
|
||||
|
||||
import socket
|
||||
|
||||
from googlebardpy import BardChat
|
||||
|
||||
from gi.repository import Gtk, Adw, GLib
|
||||
|
||||
|
||||
class BardProvider(BavarderProvider):
|
||||
name = "Bard"
|
||||
slug = "bard"
|
||||
version = "0.1.0"
|
||||
url = "https://bavarder.codeberg.page/help/bavarder"
|
||||
|
||||
def __init__(self, win, app, *args, **kwargs):
|
||||
super().__init__(win, app, *args, **kwargs)
|
||||
self.pref_win = None
|
||||
|
||||
def ask(self, prompt):
|
||||
try:
|
||||
response = self.chat.ask(prompt)
|
||||
response = response["content"]
|
||||
except AttributeError:
|
||||
self.no_api_key()
|
||||
return ""
|
||||
except socket.gaierror:
|
||||
self.no_connection()
|
||||
return ""
|
||||
else:
|
||||
self.hide_banner()
|
||||
GLib.idle_add(self.update_response, response)
|
||||
return response
|
||||
|
||||
@property
|
||||
def require_api_key(self):
|
||||
return True
|
||||
|
||||
def preferences(self, win):
|
||||
self.pref_win = win
|
||||
|
||||
self.expander = Adw.ExpanderRow()
|
||||
self.expander.props.title = self.name
|
||||
|
||||
self.expander.add_action(self.about())
|
||||
self.expander.add_action(self.enable_switch())
|
||||
|
||||
self.api_row = Adw.PasswordEntryRow()
|
||||
self.api_row.connect("apply", self.on_apply)
|
||||
self.api_row.props.title = "__Secure-1PSID cookie"
|
||||
self.api_row.set_show_apply_button(True)
|
||||
self.api_row.add_suffix(self.how_to_get_a_token())
|
||||
self.expander.add_row(self.api_row)
|
||||
|
||||
return self.expander
|
||||
|
||||
def on_apply(self, widget):
|
||||
self.hide_banner()
|
||||
api_key = self.api_row.get_text()
|
||||
self.api_key = api_key
|
||||
try:
|
||||
self.chat = BardChat(api_key)
|
||||
except AttributeError:
|
||||
self.banner.props.title = "Invalid API key"
|
||||
self.banner.props.button_label = ""
|
||||
self.banner.set_revealed(True)
|
||||
|
||||
def save(self):
|
||||
try:
|
||||
return {"api_key": self.api_key}
|
||||
except AttributeError: # no api key
|
||||
return {}
|
||||
|
||||
def load(self, data):
|
||||
try:
|
||||
self.chat = BardChat(data["api_key"])
|
||||
self.api_key = data["api_key"]
|
||||
except AttributeError:
|
||||
self.chat = None
|
||||
self.api_key = None
|
|
@ -1,140 +1,66 @@
|
|||
from gettext import gettext as _
|
||||
|
||||
import unicodedata
|
||||
import re
|
||||
from typing import List, Dict
|
||||
from gi.repository import Gtk, Adw, GLib
|
||||
|
||||
import json
|
||||
|
||||
|
||||
class BavarderProvider:
|
||||
name = None
|
||||
slug = None
|
||||
description = ""
|
||||
languages = ""
|
||||
version = "0.1.7"
|
||||
developer_name = "0xMRTT"
|
||||
|
||||
class BaseProvider:
|
||||
name: str
|
||||
description: str = ""
|
||||
languages: List[str] = []
|
||||
developer_name: str = "0xMRTT"
|
||||
developers = ["0xMRTT https://github.com/0xMRTT"]
|
||||
license_type = Gtk.License.GPL_3_0
|
||||
copyright = "© 2023 0xMRTT"
|
||||
url = "https://bavarder.codeberg.page/help/bard"
|
||||
data: Dict[str, str] = {}
|
||||
has_auth: bool = False
|
||||
require_authentification: bool = False
|
||||
|
||||
def __init__(self, app, window, providers):
|
||||
self.slug = self.slugify(self.name)
|
||||
self.copyright = f"© 2023 {self.developer_name}"
|
||||
self.url = f"https://bavarder.codeberg.page/providers/{self.slug}"
|
||||
|
||||
|
||||
def __init__(self, win, app, *args, **kwargs):
|
||||
self.win = win
|
||||
self.banner = win.banner
|
||||
self.app = app
|
||||
self.chat = None
|
||||
self.update_response = app.update_response
|
||||
self.window = window
|
||||
|
||||
def ask(self, prompt):
|
||||
raise NotImplementedError()
|
||||
self.providers = providers
|
||||
try:
|
||||
self.providers[self.slug]
|
||||
except KeyError:
|
||||
self.providers[self.slug] = {
|
||||
"enabled": False,
|
||||
"data": {
|
||||
|
||||
}
|
||||
}
|
||||
finally:
|
||||
self.data = self.providers[self.slug]["data"]
|
||||
|
||||
@property
|
||||
def require_api_key(self):
|
||||
def enabled(self):
|
||||
return self.providers[self.slug]["enabled"]
|
||||
|
||||
def set_enabled(self, status):
|
||||
self.providers[self.slug]["enabled"] = status
|
||||
|
||||
def ask(self, prompt, chat):
|
||||
raise NotImplementedError()
|
||||
|
||||
def preferences(self, win):
|
||||
return self.no_preferences(win)
|
||||
|
||||
def no_api_key(self, title=None):
|
||||
if title:
|
||||
self.win.banner.props.title = title
|
||||
else:
|
||||
self.win.banner.props.title = _(
|
||||
"No API key provided, you can provide one in settings"
|
||||
)
|
||||
self.win.banner.props.button_label = _("Open settings")
|
||||
self.win.banner.connect("button-clicked", self.app.on_preferences_action)
|
||||
self.win.banner.set_revealed(True)
|
||||
|
||||
def no_connection(self):
|
||||
self.win.banner.props.title = _("No network connection")
|
||||
self.win.banner.props.button_label = ""
|
||||
self.win.banner.set_revealed(True)
|
||||
|
||||
def hide_banner(self):
|
||||
self.win.banner.set_revealed(False)
|
||||
|
||||
def about(self, *args, **kwargs):
|
||||
popover = Gtk.Popover()
|
||||
vbox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
|
||||
title = Gtk.Label()
|
||||
title.set_markup(f"<b>{self.name}</b>\n<small>Version {self.version}</small>")
|
||||
title.set_halign(Gtk.Align.CENTER)
|
||||
title.set_valign(Gtk.Align.CENTER)
|
||||
vbox.append(title)
|
||||
|
||||
if self.description:
|
||||
description = Gtk.Label()
|
||||
if self.languages:
|
||||
description.set_markup(
|
||||
f"<small>{self.description}</small>\n<small>Languages: {self.languages}</small>"
|
||||
)
|
||||
else:
|
||||
description.set_markup(f"<small>{self.description}</small>")
|
||||
description.set_halign(Gtk.Align.CENTER)
|
||||
description.set_valign(Gtk.Align.CENTER)
|
||||
vbox.append(description)
|
||||
popover.set_child(vbox)
|
||||
|
||||
about_button = Gtk.MenuButton()
|
||||
about_button.set_icon_name("help-about-symbolic")
|
||||
about_button.set_tooltip_text(_("About provider"))
|
||||
about_button.add_css_class("flat")
|
||||
about_button.set_valign(Gtk.Align.CENTER)
|
||||
about_button.set_popover(popover)
|
||||
return about_button
|
||||
|
||||
def open_documentation(self, *args, **kwargs):
|
||||
GLib.spawn_command_line_async(
|
||||
f"xdg-open {self.url}"
|
||||
)
|
||||
|
||||
def how_to_get_a_token(self):
|
||||
about_button = Gtk.Button()
|
||||
about_button.set_icon_name("dialog-information-symbolic")
|
||||
about_button.set_tooltip_text(_("How to get a token"))
|
||||
about_button.add_css_class("flat")
|
||||
about_button.set_valign(Gtk.Align.CENTER)
|
||||
about_button.connect("clicked", self.open_documentation)
|
||||
return about_button
|
||||
|
||||
def enable_switch(self):
|
||||
enabled = Gtk.Switch()
|
||||
enabled.set_active(self.slug in self.app.enabled_providers)
|
||||
enabled.connect("notify::active", self.on_enabled)
|
||||
enabled.set_valign(Gtk.Align.CENTER)
|
||||
return enabled
|
||||
|
||||
def no_preferences(self, win):
|
||||
self.pref_win = win
|
||||
|
||||
self.expander = Adw.ExpanderRow()
|
||||
self.expander.props.title = self.name
|
||||
|
||||
self.expander.add_action(self.about()) # TODO: in Adw 1.4, use add_suffix
|
||||
self.expander.add_action(self.enable_switch())
|
||||
|
||||
self.no_pref_row = Adw.ActionRow()
|
||||
self.no_pref_row.props.title = _("No preferences available")
|
||||
self.expander.add_row(self.no_pref_row)
|
||||
|
||||
return self.expander
|
||||
|
||||
def save(self):
|
||||
return {}
|
||||
|
||||
def load(self, data):
|
||||
def load_authentification(self):
|
||||
"""Must set self.has_auth to True when auth is done"""
|
||||
raise NotImplementedError()
|
||||
|
||||
def get_settings_rows(self) -> list:
|
||||
return []
|
||||
|
||||
# TOOLS
|
||||
def slugify(self, value):
|
||||
value = unicodedata.normalize('NFKD', value).encode('ascii', 'ignore').decode('ascii')
|
||||
value = re.sub('[^\w\s-]', '', value).strip().lower()
|
||||
return re.sub('[-\s]+', '-', value)
|
||||
|
||||
def chunk(self, prompt, n=4000):
|
||||
if len(prompt) > n:
|
||||
print("Chuncking prompt")
|
||||
prompt = [(prompt[i : i + n]) for i in range(0, len(prompt), n)]
|
||||
return prompt
|
||||
|
||||
def on_enabled(self, widget, *args):
|
||||
if widget.get_active():
|
||||
self.app.enabled_providers.append(self.slug)
|
||||
else:
|
||||
self.app.enabled_providers.remove(self.slug)
|
||||
self.app.load_dropdown()
|
||||
|
|
|
@ -1,42 +0,0 @@
|
|||
from .base import BavarderProvider
|
||||
|
||||
import requests
|
||||
import shutil
|
||||
|
||||
class BaseOfflineProvider(BavarderProvider):
|
||||
data = {
|
||||
"setup": False,
|
||||
"weight_path": "",
|
||||
}
|
||||
download_url = ""
|
||||
|
||||
def save(self):
|
||||
return data
|
||||
|
||||
def load(self, data):
|
||||
self.data = data
|
||||
|
||||
def download_file(self, url, filename=None):
|
||||
if not filename:
|
||||
filename = url.split('/')[-1]
|
||||
|
||||
with requests.get(url, stream=True) as r:
|
||||
with open(filename, 'wb') as f:
|
||||
shutil.copyfileobj(r.raw, f)
|
||||
|
||||
return filename
|
||||
|
||||
|
||||
def setup(self):
|
||||
if self.data["setup"]:
|
||||
return
|
||||
else:
|
||||
self.data["setup"] = True
|
||||
self.data["weight_path"] = self.download_file(self.download_url)
|
||||
|
||||
def ask(self, prompt):
|
||||
self.setup()
|
||||
return self._ask(prompt)
|
||||
|
||||
def _ask(self, prompt):
|
||||
raise NotImplementedError()
|
|
@ -1,24 +1,35 @@
|
|||
from .base import BavarderProvider
|
||||
|
||||
from random import choice, randint
|
||||
|
||||
from gi.repository import Gtk, Adw, GLib
|
||||
from .base import BaseProvider
|
||||
|
||||
class CatGPTProvider(BaseProvider):
|
||||
name = "Cat GPT"
|
||||
description = _("Chit-Chat with a Cat")
|
||||
|
||||
def ask(self, prompt, _):
|
||||
return """
|
||||
# H1
|
||||
## H2
|
||||
### H3
|
||||
|
||||
Alternatively, for H1 , an underline-ish style:
|
||||
|
||||
Alt-H1
|
||||
======
|
||||
|
||||
|
||||
class CatGPTProvider(BavarderProvider):
|
||||
name = "CatGPT"
|
||||
slug = "catgpt"
|
||||
description = "🐱️"
|
||||
version = "0.1.0"
|
||||
developer_name = "Astrid Yu"
|
||||
developers = ["Astrid Yu https://github.com/ifd3f"]
|
||||
1. First ordered list item
|
||||
2. Another item
|
||||
|
||||
def __init__(self, win, app, *args, **kwargs):
|
||||
super().__init__(win, app, *args, **kwargs)
|
||||
self.chat = None
|
||||
* Unordered list can use asterisks
|
||||
- Or minuses
|
||||
+ Or pluses
|
||||
|
||||
def ask(self, prompt):
|
||||
return " ".join([self.pick_generator()() for i in range(randint(1, 12))])
|
||||
```
|
||||
$ ls
|
||||
```
|
||||
"""
|
||||
#return " ".join([self.pick_generator()() for i in range(randint(1, 12))])
|
||||
|
||||
def pick_generator(self):
|
||||
if randint(1, 15) == 1:
|
||||
|
@ -46,13 +57,3 @@ class CatGPTProvider(BavarderProvider):
|
|||
lambda: "nya" * randint(1, 3) + "ny" + "a" * randint(1, 10),
|
||||
]
|
||||
)
|
||||
|
||||
@property
|
||||
def require_api_key(self):
|
||||
return False
|
||||
|
||||
def save(self):
|
||||
return {}
|
||||
|
||||
def load(self, data):
|
||||
pass
|
||||
|
|
|
@ -1,64 +0,0 @@
|
|||
import requests
|
||||
import json
|
||||
from .base import BavarderProvider
|
||||
|
||||
import socket
|
||||
|
||||
from gi.repository import Gtk, Adw, GLib
|
||||
|
||||
from gradio_client import Client
|
||||
|
||||
class BaseGradioProvider(BavarderProvider):
|
||||
name = None
|
||||
slug = None
|
||||
url = None
|
||||
|
||||
def __init__(self, win, app, *args, **kwargs):
|
||||
super().__init__(win, app, *args, **kwargs)
|
||||
|
||||
self.client = Client(self.url)
|
||||
|
||||
def ask(self, prompt):
|
||||
print("ASKING " + "="*100)
|
||||
try:
|
||||
response = self.client.predict(
|
||||
prompt, # str representing string value in 'Chat Message Box' Textbox component
|
||||
fn_index=0
|
||||
)
|
||||
print(response)
|
||||
except Exception as e:
|
||||
print(e)
|
||||
self.win.banner.props.title = str(e)
|
||||
self.win.banner.props.button_label = ""
|
||||
self.win.banner.set_revealed(True)
|
||||
else:
|
||||
self.hide_banner()
|
||||
GLib.idle_add(self.update_response, response)
|
||||
return response
|
||||
|
||||
@property
|
||||
def require_api_key(self):
|
||||
return False
|
||||
|
||||
def preferences(self, win):
|
||||
if self.require_api_key:
|
||||
self.expander = Adw.ExpanderRow()
|
||||
self.expander.props.title = self.name
|
||||
|
||||
self.expander.add_action(self.about())
|
||||
self.expander.add_action(self.enable_switch())
|
||||
|
||||
# TODO: ADD DEVICE
|
||||
|
||||
return self.expander
|
||||
else:
|
||||
return self.no_preferences(win)
|
||||
|
||||
def on_apply(self, widget):
|
||||
self.hide_banner()
|
||||
|
||||
def save(self):
|
||||
return {}
|
||||
|
||||
def load(self, data):
|
||||
pass
|
|
@ -1,50 +0,0 @@
|
|||
from .huggingface import BaseHFProvider
|
||||
import json
|
||||
import socket
|
||||
import requests
|
||||
|
||||
from gi.repository import Gtk, Adw, GLib
|
||||
|
||||
|
||||
class HuggingFaceDialoGPTLargeProvider(BaseHFProvider):
|
||||
name = "DialoGPT"
|
||||
slug = "hfdialogpt"
|
||||
model = "microsoft/DialoGPT-large"
|
||||
|
||||
@property
|
||||
def require_api_key(self):
|
||||
return False
|
||||
|
||||
def ask(self, prompt):
|
||||
try:
|
||||
payload = json.dumps(
|
||||
{
|
||||
"inputs": {
|
||||
# "past_user_inputs": ["Which movie is the best ?"],
|
||||
# "generated_responses": ["It's Die Hard for sure."],
|
||||
"text": prompt
|
||||
},
|
||||
}
|
||||
)
|
||||
headers = {"Content-Type": "application/json"}
|
||||
if self.authorization:
|
||||
headers["Authorization"] = f"Bearer {self.api_key}"
|
||||
url = f"https://api-inference.huggingface.co/models/{self.model}"
|
||||
print(url)
|
||||
response = requests.request("POST", url, headers=headers, data=payload)
|
||||
print(response.json())
|
||||
response = response.json()["generated_text"]
|
||||
|
||||
# except NoApikey:
|
||||
# self.no_api_key()
|
||||
# return ""
|
||||
except KeyError:
|
||||
pass
|
||||
except socket.gaierror:
|
||||
self.no_connection()
|
||||
return ""
|
||||
else:
|
||||
self.hide_banner()
|
||||
print(response)
|
||||
GLib.idle_add(self.update_response, response)
|
||||
return response
|
|
@ -1,11 +0,0 @@
|
|||
from .huggingface import BaseHFProvider
|
||||
|
||||
|
||||
class HuggingFaceGoogleFlanT5XXLProvider(BaseHFProvider):
|
||||
name = "Google Flan T5 XXL"
|
||||
slug = "hfgoogleflant5xxl"
|
||||
model = "google/flan-t5-xxl"
|
||||
|
||||
@property
|
||||
def require_api_key(self):
|
||||
return False
|
|
@ -1,11 +0,0 @@
|
|||
from .huggingface import BaseHFProvider
|
||||
|
||||
|
||||
class HuggingFaceGoogleFlanU12Provider(BaseHFProvider):
|
||||
name = "Google Flan U12"
|
||||
slug = "hfgoogleflanu12"
|
||||
model = "google/flan-ul2"
|
||||
|
||||
@property
|
||||
def require_api_key(self):
|
||||
return False
|
|
@ -1,13 +0,0 @@
|
|||
from .huggingface import BaseHFProvider
|
||||
|
||||
|
||||
class HuggingFaceGPT2Provider(BaseHFProvider):
|
||||
name = "GPT 2"
|
||||
slug = "hfgpt2"
|
||||
model = "gpt2"
|
||||
description = "GPT-2 is a transformers model pretrained on a very large corpus of English data \nin a self-supervised fashion. This means it was pretrained on the raw texts only,\n with no humans labelling them in any way (which is why it can use lots of publicly available data)\n with an automatic process to generate inputs and labels from those texts. More precisely,\n it was trained to guess the next word in sentences."
|
||||
languages = "English"
|
||||
|
||||
@property
|
||||
def require_api_key(self):
|
||||
return False
|
|
@ -1,13 +0,0 @@
|
|||
from .huggingface import BaseHFProvider
|
||||
|
||||
|
||||
class HuggingFaceGPT2LargeProvider(BaseHFProvider):
|
||||
name = "GPT 2 Large"
|
||||
slug = "hfgpt2large"
|
||||
model = "gpt2-large"
|
||||
description = "GPT-2 is a transformers model pretrained on a very large corpus of English data \nin a self-supervised fashion. This means it was pretrained on the raw texts only,\n with no humans labelling them in any way (which is why it can use lots of publicly available data)\n with an automatic process to generate inputs and labels from those texts. More precisely,\n it was trained to guess the next word in sentences."
|
||||
languages = "English"
|
||||
|
||||
@property
|
||||
def require_api_key(self):
|
||||
return False
|
|
@ -1,13 +0,0 @@
|
|||
from .huggingface import BaseHFProvider
|
||||
|
||||
|
||||
class HuggingFaceGPT2XLProvider(BaseHFProvider):
|
||||
name = "GPT 2 XL"
|
||||
slug = "hfgpt2"
|
||||
model = "gpt2-xl"
|
||||
description = "GPT-2 is a transformers model pretrained on a very large corpus of English data \nin a self-supervised fashion. This means it was pretrained on the raw texts only,\n with no humans labelling them in any way (which is why it can use lots of publicly available data)\n with an automatic process to generate inputs and labels from those texts. More precisely,\n it was trained to guess the next word in sentences."
|
||||
languages = "English"
|
||||
|
||||
@property
|
||||
def require_api_key(self):
|
||||
return False
|
|
@ -1,54 +0,0 @@
|
|||
from .huggingface import BaseHFProvider
|
||||
|
||||
import requests
|
||||
import json
|
||||
import socket
|
||||
|
||||
from gi.repository import Gtk, Adw, GLib
|
||||
|
||||
class HuggingFaceOpenAssistantSFT1PythiaProvider(BaseHFProvider):
|
||||
name = "Open-Assistant SFT-1 12B Model"
|
||||
slug = "hfopenassistantsft1pythia12b"
|
||||
model = "OpenAssistant/oasst-sft-4-pythia-12b-epoch-3.5"
|
||||
|
||||
@property
|
||||
def require_api_key(self):
|
||||
return False
|
||||
|
||||
def ask(self, prompt):
|
||||
prompt = f"<|prompter|> {prompt}<|endoftext|><|assistant|>"
|
||||
try:
|
||||
payload = json.dumps({"inputs": prompt})
|
||||
headers = {"Content-Type": "application/json"}
|
||||
if self.require_api_key:
|
||||
headers["Authorization"] = f"Bearer {self.api_key}"
|
||||
url = f"https://api-inference.huggingface.co/models/{self.model}"
|
||||
response = requests.request("POST", url, headers=headers, data=payload)
|
||||
if response.status_code == 403:
|
||||
self.no_api_key()
|
||||
return ""
|
||||
elif response.status_code != 200:
|
||||
self.win.banner.props.title = response.json()["error"]
|
||||
self.win.banner.props.button_label = ""
|
||||
self.win.banner.set_revealed(True)
|
||||
return ""
|
||||
response = response.json()[0]["generated_text"].split("<|assistant|>")[1].strip()
|
||||
|
||||
# except NoApikey:
|
||||
# self.no_api_key()
|
||||
# return ""
|
||||
except KeyError:
|
||||
pass
|
||||
except socket.gaierror:
|
||||
self.no_connection()
|
||||
return ""
|
||||
else:
|
||||
self.hide_banner()
|
||||
print(response)
|
||||
GLib.idle_add(self.update_response, response)
|
||||
return response
|
||||
|
||||
class HuggingChatMask(HuggingFaceOpenAssistantSFT1PythiaProvider):
|
||||
url = "https://bavarder.codeberg.page/help/huggingchat"
|
||||
name = "Open-Assistant SFT-1 12B Model (HuggingChat)"
|
||||
slug = "huggingchat"
|
|
@ -1,7 +0,0 @@
|
|||
from .huggingchatbase import BaseHuggingChatProvider
|
||||
|
||||
|
||||
class HuggingChatProvider(BaseHuggingChatProvider):
|
||||
name = "Hugging Chat"
|
||||
slug = "huggingchat"
|
||||
model = "OpenAssistant/oasst-sft-6-llama-30b-xor"
|
|
@ -1,92 +0,0 @@
|
|||
from .base import BavarderProvider
|
||||
|
||||
from hugchat import hugchat
|
||||
import socket
|
||||
import requests
|
||||
import json
|
||||
|
||||
from gi.repository import Gtk, Adw, GLib
|
||||
|
||||
|
||||
class BaseHuggingChatProvider(BavarderProvider):
|
||||
name = "Hugging Chat"
|
||||
slug = "huggingchat"
|
||||
model = None
|
||||
url = "https://bavarder.codeberg.page/help/huggingchat"
|
||||
cookies = {}
|
||||
|
||||
def __init__(self, win, app, *args, **kwargs):
|
||||
super().__init__(win, app, *args, **kwargs)
|
||||
|
||||
def ask(self, prompt):
|
||||
print(self.cookies)
|
||||
try:
|
||||
self.chat = hugchat.ChatBot(cookies=self.cookies) # or cookies=[...]
|
||||
print(self.chat)
|
||||
print(self.cookies)
|
||||
except Exception as e:
|
||||
print(e)
|
||||
self.win.banner.props.title = str(e)
|
||||
self.win.banner.props.button_label = ""
|
||||
self.win.banner.set_revealed(True)
|
||||
return ""
|
||||
else:
|
||||
try:
|
||||
response = self.chat.chat(prompt)
|
||||
except socket.gaierror:
|
||||
self.no_connection()
|
||||
return ""
|
||||
except Exception as e:
|
||||
self.win.banner.props.title = str(e)
|
||||
self.win.banner.props.button_label = ""
|
||||
self.win.banner.set_revealed(True)
|
||||
return ""
|
||||
else:
|
||||
self.win.banner.set_revealed(False)
|
||||
r = ""
|
||||
for i in response:
|
||||
char = i["token"]["text"]
|
||||
if char == "</s>":
|
||||
r += "\n"
|
||||
else:
|
||||
r += char
|
||||
GLib.idle_add(self.update_response, r)
|
||||
return r
|
||||
|
||||
@property
|
||||
def require_api_key(self):
|
||||
return True
|
||||
|
||||
def preferences(self, win):
|
||||
self.pref_win = win
|
||||
|
||||
self.expander = Adw.ExpanderRow()
|
||||
self.expander.props.title = self.name
|
||||
|
||||
self.expander.add_action(self.about()) # TODO: in Adw 1.4, use add_suffix
|
||||
self.expander.add_action(self.enable_switch())
|
||||
|
||||
self.api_row = Adw.EntryRow()
|
||||
self.api_row.connect("apply", self.on_apply)
|
||||
self.api_row.props.text = str(self.cookies) or ""
|
||||
self.api_row.props.title = "Cookies"
|
||||
self.api_row.set_show_apply_button(True)
|
||||
self.api_row.add_suffix(self.how_to_get_a_token())
|
||||
self.expander.add_row(self.api_row)
|
||||
|
||||
return self.expander
|
||||
|
||||
def on_apply(self, widget):
|
||||
self.hide_banner()
|
||||
cookies = self.api_row.get_text()
|
||||
print("cookies", cookies)
|
||||
self.cookies = json.loads(cookies)
|
||||
print("Applied cookies", self.cookies)
|
||||
|
||||
def save(self):
|
||||
print(self.cookies)
|
||||
print("Saved cookies", self.cookies)
|
||||
return self.cookies
|
||||
|
||||
def load(self, data):
|
||||
self.cookies = data
|
|
@ -1,95 +0,0 @@
|
|||
import requests
|
||||
import json
|
||||
from .base import BavarderProvider
|
||||
|
||||
import socket
|
||||
|
||||
from gi.repository import Gtk, Adw, GLib
|
||||
|
||||
# from text_generation import InferenceAPIClient
|
||||
|
||||
class BaseHFProvider(BavarderProvider):
|
||||
name = None
|
||||
slug = None
|
||||
model = None
|
||||
url = "https://bavarder.codeberg.page/help/huggingface"
|
||||
|
||||
def __init__(self, win, app, *args, **kwargs):
|
||||
super().__init__(win, app, *args, **kwargs)
|
||||
self.api_key = None
|
||||
# self.client = InferenceAPIClient(self.model)
|
||||
|
||||
def ask(self, prompt):
|
||||
try:
|
||||
payload = json.dumps({"inputs": prompt})
|
||||
headers = {"Content-Type": "application/json"}
|
||||
if self.require_api_key:
|
||||
headers["Authorization"] = f"Bearer {self.api_key}"
|
||||
url = f"https://api-inference.huggingface.co/models/{self.model}"
|
||||
response = requests.request("POST", url, headers=headers, data=payload)
|
||||
if response.status_code == 403:
|
||||
self.no_api_key()
|
||||
return ""
|
||||
elif response.status_code != 200:
|
||||
self.win.banner.props.title = response.json()["error"]
|
||||
self.win.banner.props.button_label = ""
|
||||
self.win.banner.set_revealed(True)
|
||||
return ""
|
||||
response = response.json()[0]["generated_text"]
|
||||
|
||||
# except NoApikey:
|
||||
# self.no_api_key()
|
||||
# return ""
|
||||
except KeyError:
|
||||
pass
|
||||
except socket.gaierror:
|
||||
self.no_connection()
|
||||
return ""
|
||||
except Exception as e:
|
||||
print(e)
|
||||
self.win.banner.props.title = str(e)
|
||||
self.win.banner.props.button_label = ""
|
||||
self.win.banner.set_revealed(True)
|
||||
else:
|
||||
self.hide_banner()
|
||||
print(response)
|
||||
GLib.idle_add(self.update_response, response)
|
||||
return response
|
||||
|
||||
@property
|
||||
def require_api_key(self):
|
||||
return False
|
||||
|
||||
def preferences(self, win):
|
||||
if self.require_api_key:
|
||||
self.expander = Adw.ExpanderRow()
|
||||
self.expander.props.title = self.name
|
||||
|
||||
self.expander.add_action(self.about())
|
||||
self.expander.add_action(self.enable_switch())
|
||||
|
||||
self.api_row = Adw.PasswordEntryRow()
|
||||
self.api_row.connect("apply", self.on_apply)
|
||||
self.api_row.props.title = _("API Key")
|
||||
self.api_row.props.text = self.api_key or ""
|
||||
self.api_row.add_suffix(self.how_to_get_a_token())
|
||||
self.api_row.set_show_apply_button(True)
|
||||
self.expander.add_row(self.api_row)
|
||||
|
||||
return self.expander
|
||||
else:
|
||||
return self.no_preferences(win)
|
||||
|
||||
def on_apply(self, widget):
|
||||
self.hide_banner()
|
||||
self.api_key = self.api_row.get_text()
|
||||
print(self.api_key)
|
||||
|
||||
def save(self):
|
||||
if self.require_api_key:
|
||||
return {"api_key": self.api_key}
|
||||
return {}
|
||||
|
||||
def load(self, data):
|
||||
if self.require_api_key:
|
||||
self.api_key = data["api_key"]
|
|
@ -1,32 +1,10 @@
|
|||
|
||||
providers_dir = join_paths(moduledir, 'providers')
|
||||
providers_dir = join_paths(MODULE_DIR, 'providers')
|
||||
|
||||
providers_sources = [
|
||||
'__init__.py',
|
||||
'alpacalora.py',
|
||||
'baichat.py',
|
||||
# 'bard.py',
|
||||
'base.py',
|
||||
'catgpt.py',
|
||||
'gradio.py',
|
||||
'hfdialogpt.py',
|
||||
'hfgoogleflant5xxl.py',
|
||||
'hfgoogleflanu12.py',
|
||||
'hfgpt2.py',
|
||||
'hfgpt2large.py',
|
||||
'hfgpt2xl.py',
|
||||
'hfopenassistantsft1pythia12b.py',
|
||||
# 'huggingchat.py',
|
||||
# 'huggingchatbase.py',
|
||||
'huggingface.py',
|
||||
'openai.py',
|
||||
'openaicustom.py',
|
||||
'openaigpt4.py',
|
||||
'openaigpt35turbo.py',
|
||||
'openaitextdavinci003.py',
|
||||
'stablelm.py',
|
||||
'starcoder.py',
|
||||
'transformer.py',
|
||||
'provider_item.py',
|
||||
]
|
||||
|
||||
PY_INSTALLDIR.install_sources(providers_sources, subdir: providers_dir)
|
||||
PY_INSTALLDIR.install_sources(providers_sources, subdir: providers_dir)
|
|
@ -1,130 +0,0 @@
|
|||
from .base import BavarderProvider
|
||||
|
||||
import openai
|
||||
import socket
|
||||
|
||||
from gi.repository import Gtk, Adw, GLib
|
||||
|
||||
|
||||
class BaseOpenAIProvider(BavarderProvider):
|
||||
name = None
|
||||
slug = None
|
||||
model = None
|
||||
version = "0.1.0"
|
||||
api_key_title = "API Key"
|
||||
url = "https://bavarder.codeberg.page/help/openai"
|
||||
|
||||
def __init__(self, win, app, *args, **kwargs):
|
||||
super().__init__(win, app, *args, **kwargs)
|
||||
self.chat = openai.ChatCompletion
|
||||
self.pref_win = None
|
||||
|
||||
def ask(self, prompt):
|
||||
if self.model:
|
||||
prompt = self.chunk(prompt)
|
||||
try:
|
||||
if isinstance(prompt, list):
|
||||
self.win.banner.props.title = _("Prompt too long, splitting into chunks.")
|
||||
self.win.banner.props.button_label = ""
|
||||
self.win.banner.set_revealed(True)
|
||||
response = ""
|
||||
for chunk in prompt:
|
||||
response += (
|
||||
self.chat.create(
|
||||
model=self.model,
|
||||
messages=[{"role": "user", "content": chunk}],
|
||||
)
|
||||
.choices[0]
|
||||
.message.content
|
||||
)
|
||||
else:
|
||||
response = self.chat.create(
|
||||
model=self.model, messages=[{"role": "user", "content": prompt}]
|
||||
)
|
||||
response = response.choices[0].message.content
|
||||
except openai.error.AuthenticationError:
|
||||
self.no_api_key()
|
||||
return ""
|
||||
except openai.error.InvalidRequestError:
|
||||
self.win.banner.props.title = _("You don't have access to this model")
|
||||
self.win.banner.props.button_label = ""
|
||||
self.win.banner.set_revealed(True)
|
||||
return ""
|
||||
except openai.error.RateLimitError:
|
||||
self.win.banner.props.title = _("You exceeded your current quota, please check your plan and billing details.")
|
||||
self.win.banner.props.button_label = ""
|
||||
self.win.banner.set_revealed(True)
|
||||
return ""
|
||||
except openai.error.APIError:
|
||||
self.win.banner.props.title = _("API Error")
|
||||
self.win.banner.props.button_label = ""
|
||||
self.win.banner.set_revealed(True)
|
||||
except socket.gaierror:
|
||||
self.no_connection()
|
||||
return ""
|
||||
else:
|
||||
self.hide_banner()
|
||||
GLib.idle_add(self.update_response, response)
|
||||
return response
|
||||
else:
|
||||
self.no_api_key(title=_("No model selected, you can choose one in preferences"))
|
||||
return ""
|
||||
|
||||
|
||||
@property
|
||||
def require_api_key(self):
|
||||
return True
|
||||
|
||||
def preferences(self, win):
|
||||
self.pref_win = win
|
||||
|
||||
self.expander = Adw.ExpanderRow()
|
||||
self.expander.props.title = self.name
|
||||
|
||||
self.expander.add_action(self.about()) # TODO: in Adw 1.4, use add_suffix
|
||||
self.expander.add_action(self.enable_switch())
|
||||
|
||||
self.api_row = Adw.PasswordEntryRow()
|
||||
self.api_row.connect("apply", self.on_apply)
|
||||
self.api_row.props.text = openai.api_key or ""
|
||||
self.api_row.props.title = self.api_key_title
|
||||
self.api_row.set_show_apply_button(True)
|
||||
self.api_row.add_suffix(self.how_to_get_a_token())
|
||||
self.expander.add_row(self.api_row)
|
||||
|
||||
self.api_url_row = Adw.EntryRow()
|
||||
self.api_url_row.connect("apply", self.on_apply)
|
||||
self.api_url_row.props.text = openai.api_base or ""
|
||||
self.api_url_row.props.title = "API Url"
|
||||
self.api_url_row.set_show_apply_button(True)
|
||||
self.api_url_row.add_suffix(self.how_to_get_base_url())
|
||||
self.expander.add_row(self.api_url_row)
|
||||
|
||||
return self.expander
|
||||
|
||||
def on_apply(self, widget):
|
||||
self.hide_banner()
|
||||
api_key = self.api_row.get_text()
|
||||
openai.api_key = api_key
|
||||
openai.api_base = self.api_url_row.get_text()
|
||||
|
||||
def save(self):
|
||||
return {
|
||||
"api_key": openai.api_key,
|
||||
"api_base": openai.api_base,
|
||||
}
|
||||
|
||||
def load(self, data):
|
||||
if data["api_key"]:
|
||||
openai.api_key = data["api_key"]
|
||||
if data["api_base"]:
|
||||
openai.api_base = data["api_base"]
|
||||
|
||||
def how_to_get_base_url(self):
|
||||
about_button = Gtk.Button()
|
||||
about_button.set_icon_name("dialog-information-symbolic")
|
||||
about_button.set_tooltip_text("How to choose base url")
|
||||
about_button.add_css_class("flat")
|
||||
about_button.set_valign(Gtk.Align.CENTER)
|
||||
about_button.connect("clicked", self.open_documentation)
|
||||
return about_button
|
|
@ -1,89 +0,0 @@
|
|||
from .openai import BaseOpenAIProvider
|
||||
|
||||
from gi.repository import Gtk, Adw, GLib
|
||||
|
||||
import openai
|
||||
|
||||
class OpenAICustomProvider(BaseOpenAIProvider):
|
||||
name = "OpenAI Custom Model"
|
||||
slug = "openaicustom"
|
||||
|
||||
api_base = ""
|
||||
|
||||
def preferences(self, win):
|
||||
self.pref_win = win
|
||||
|
||||
self.expander = Adw.ExpanderRow()
|
||||
self.expander.props.title = self.name
|
||||
|
||||
self.expander.add_action(self.about()) # TODO: in Adw 1.4, use add_suffix
|
||||
self.expander.add_action(self.enable_switch())
|
||||
|
||||
self.api_row = Adw.PasswordEntryRow()
|
||||
self.api_row.connect("apply", self.on_apply)
|
||||
self.api_row.props.text = openai.api_key or ""
|
||||
self.api_row.props.title = self.api_key_title
|
||||
self.api_row.set_show_apply_button(True)
|
||||
self.api_row.add_suffix(self.how_to_get_a_token())
|
||||
self.expander.add_row(self.api_row)
|
||||
|
||||
self.api_url_row = Adw.EntryRow()
|
||||
self.api_url_row.connect("apply", self.on_apply)
|
||||
self.api_url_row.props.text = self.api_base or ""
|
||||
self.api_url_row.props.title = _("API Url")
|
||||
self.api_url_row.set_show_apply_button(True)
|
||||
self.api_url_row.add_suffix(self.how_to_get_a_token())
|
||||
self.expander.add_row(self.api_url_row)
|
||||
|
||||
self.model_row = Adw.EntryRow()
|
||||
self.model_row.connect("apply", self.on_apply)
|
||||
self.model_row.props.title = _("Model")
|
||||
if self.model:
|
||||
self.model_row.props.text = str(self.model)
|
||||
else:
|
||||
print("No model")
|
||||
self.model_row.props.text = ""
|
||||
self.model_row.add_suffix(self.how_to_choose_model())
|
||||
self.model_row.set_show_apply_button(True)
|
||||
self.expander.add_row(self.model_row)
|
||||
return self.expander
|
||||
|
||||
def on_apply(self, widget):
|
||||
self.hide_banner()
|
||||
api_key = self.api_row.get_text()
|
||||
openai.api_key = api_key
|
||||
self.api_base = self.api_url_row.get_text()
|
||||
openai.api_base = self.api_base
|
||||
self.model = str(self.model_row.get_text())
|
||||
|
||||
def save(self):
|
||||
return {
|
||||
"api_key": openai.api_key,
|
||||
"api_base": self.api_base,
|
||||
"model": self.model,
|
||||
}
|
||||
|
||||
def load(self, data):
|
||||
if data["api_key"]:
|
||||
openai.api_key = data["api_key"]
|
||||
else:
|
||||
openai.api_key = ""
|
||||
if data["api_base"]:
|
||||
self.api_base = data["api_base"]
|
||||
openai.api_base = self.api_base
|
||||
if data["model"]:
|
||||
self.model = data["model"]
|
||||
|
||||
def how_to_choose_model(self):
|
||||
about_button = Gtk.Button()
|
||||
about_button.set_icon_name("dialog-information-symbolic")
|
||||
about_button.set_tooltip_text(_("How to choose a model"))
|
||||
about_button.add_css_class("flat")
|
||||
about_button.set_valign(Gtk.Align.CENTER)
|
||||
about_button.connect("clicked", self.open_documentation)
|
||||
return about_button
|
||||
|
||||
class LocalModel(OpenAICustomProvider):
|
||||
name = "Local Model"
|
||||
slug = "local"
|
||||
url = "https://bavarder.codeberg.page/help/local" # just for the url :)
|
|
@ -1,7 +0,0 @@
|
|||
from .openai import BaseOpenAIProvider
|
||||
|
||||
|
||||
class OpenAIGPT35TurboProvider(BaseOpenAIProvider):
|
||||
name = "OpenAI GPT 3.5 Turbo"
|
||||
slug = "openaigpt35turbo"
|
||||
model = "gpt-3.5-turbo"
|
|
@ -1,8 +0,0 @@
|
|||
from .openai import BaseOpenAIProvider
|
||||
|
||||
|
||||
class OpenAIGPT4Provider(BaseOpenAIProvider):
|
||||
name = "OpenAI GPT 4"
|
||||
slug = "openaigpt4"
|
||||
model = "gpt-4"
|
||||
api_key_title = "API Key (Require a plan with access to the GPT-4 model)"
|
|
@ -1,7 +0,0 @@
|
|||
from .openai import BaseOpenAIProvider
|
||||
|
||||
|
||||
class OpenAITextDavinci003(BaseOpenAIProvider):
|
||||
name = "OpenAI Text Davinci 003"
|
||||
slug = "openaitextdavinci003"
|
||||
model = "text-davinci-003"
|
15
src/providers/provider_item.blp
Normal file
|
@ -0,0 +1,15 @@
|
|||
using Gtk 4.0;
|
||||
using Adw 1;
|
||||
|
||||
template $Provider : Adw.ExpanderRow {
|
||||
[suffix]
|
||||
Switch enable_switch {
|
||||
state-set => $on_switch_state_changed();
|
||||
valign: center;
|
||||
}
|
||||
|
||||
Adw.ActionRow no_preferences_available {
|
||||
title: _("No preferences available");
|
||||
}
|
||||
|
||||
}
|
51
src/providers/provider_item.py
Normal file
|
@ -0,0 +1,51 @@
|
|||
import unicodedata
|
||||
import re
|
||||
from typing import List, Dict
|
||||
from gi.repository import Gtk, Adw, GLib
|
||||
|
||||
from bavarder.constants import app_id, rootdir
|
||||
|
||||
|
||||
@Gtk.Template(resource_path=f"{rootdir}/ui/provider_item.ui")
|
||||
class Provider(Adw.ExpanderRow):
|
||||
__gtype_name__ = "Provider"
|
||||
|
||||
enable_switch = Gtk.Template.Child()
|
||||
no_preferences_available = Gtk.Template.Child()
|
||||
|
||||
def __init__(self, app, window, provider, **kwargs):
|
||||
super().__init__(**kwargs)
|
||||
self.app = app
|
||||
self.window = window
|
||||
self.provider = provider
|
||||
|
||||
self.setup()
|
||||
|
||||
def setup(self):
|
||||
self.set_title(self.provider.name)
|
||||
self.set_subtitle(self.provider.description)
|
||||
self.enable_switch.set_active(self.provider.providers[self.provider.slug]["enabled"])
|
||||
|
||||
if self.provider.require_authentification:
|
||||
self.no_preferences_available.set_visible(False)
|
||||
|
||||
for row in self.provider.get_settings_rows():
|
||||
self.add(row)
|
||||
|
||||
# CALLBACKS
|
||||
@Gtk.Template.Callback()
|
||||
def on_switch_state_changed(self, widget, _):
|
||||
self.provider.set_enabled(widget.get_active())
|
||||
self.app.win.load_provider_selector()
|
||||
|
||||
# TOOLS
|
||||
def slugify(self, value):
|
||||
value = unicodedata.normalize('NFKD', value).encode('ascii', 'ignore').decode('ascii')
|
||||
value = re.sub('[^\w\s-]', '', value).strip().lower()
|
||||
return re.sub('[-\s]+', '-', value)
|
||||
|
||||
def chunk(self, prompt, n=4000):
|
||||
if len(prompt) > n:
|
||||
prompt = [(prompt[i : i + n]) for i in range(0, len(prompt), n)]
|
||||
return prompt
|
||||
|
|
@ -1,6 +0,0 @@
|
|||
from .huggingface import BaseHFProvider
|
||||
|
||||
class StableLMProvider(BaseHFProvider):
|
||||
name = "StableLM"
|
||||
slug = "stablelm"
|
||||
model = "stabilityai/stablelm-tuned-alpha-3b"
|
|
@ -1,7 +0,0 @@
|
|||
from .transformer import BaseTransformerProvider
|
||||
|
||||
|
||||
class StarCoderProvider(BaseTransformerProvider):
|
||||
name = "Star Coder"
|
||||
slug = "starcoder"
|
||||
checkpoint = "bigcode/starcoder"
|
|
@ -1,89 +0,0 @@
|
|||
import requests
|
||||
import json
|
||||
from .base import BavarderProvider
|
||||
|
||||
import socket
|
||||
|
||||
from gi.repository import Gtk, Adw, GLib
|
||||
|
||||
from transformers import AutoModelForCausalLM, AutoTokenizer
|
||||
|
||||
class BaseTransformerProvider(BavarderProvider):
|
||||
name = None
|
||||
slug = None
|
||||
checkpoint = None
|
||||
device = "cpu"
|
||||
is_setup = False
|
||||
api_key = None
|
||||
|
||||
def __init__(self, win, app, *args, **kwargs):
|
||||
super().__init__(win, app, *args, **kwargs)
|
||||
|
||||
def setup(self):
|
||||
try:
|
||||
if self.require_api_key:
|
||||
self.tokenizer = AutoTokenizer.from_pretrained(self.checkpoint, use_auth_token=self.api_key)
|
||||
else:
|
||||
self.tokenizer = AutoTokenizer.from_pretrained(self.checkpoint)
|
||||
self.model = AutoModelForCausalLM.from_pretrained(self.checkpoint).to(self.device)
|
||||
except Exception as e:
|
||||
print(e)
|
||||
self.win.banner.props.title = str(e)
|
||||
self.win.banner.props.button_label = ""
|
||||
self.win.banner.set_revealed(True)
|
||||
else:
|
||||
self.is_setup = True
|
||||
|
||||
def ask(self, prompt):
|
||||
self.setup()
|
||||
if self.is_setup:
|
||||
try:
|
||||
inputs = self.tokenizer.encode(prompt, return_tensors="pt").to(self.device)
|
||||
outputs = self.model.generate(inputs)
|
||||
response = self.tokenizer.decode(outputs[0])
|
||||
except Exception as e:
|
||||
print(e)
|
||||
self.win.banner.props.title = str(e)
|
||||
self.win.banner.props.button_label = ""
|
||||
self.win.banner.set_revealed(True)
|
||||
else:
|
||||
self.hide_banner()
|
||||
GLib.idle_add(self.update_response, response)
|
||||
return response
|
||||
|
||||
@property
|
||||
def require_api_key(self):
|
||||
return True
|
||||
|
||||
def preferences(self, win):
|
||||
if self.require_api_key:
|
||||
self.expander = Adw.ExpanderRow()
|
||||
self.expander.props.title = self.name
|
||||
|
||||
self.expander.add_action(self.about())
|
||||
self.expander.add_action(self.enable_switch())
|
||||
|
||||
self.api_row = Adw.PasswordEntryRow()
|
||||
self.api_row.connect("apply", self.on_apply)
|
||||
self.api_row.props.title = _("API Key")
|
||||
self.api_row.props.text = self.api_key or ""
|
||||
self.api_row.add_suffix(self.how_to_get_a_token())
|
||||
self.api_row.set_show_apply_button(True)
|
||||
self.expander.add_row(self.api_row)
|
||||
|
||||
return self.expander
|
||||
else:
|
||||
return self.no_preferences(win)
|
||||
|
||||
def on_apply(self, widget):
|
||||
self.hide_banner()
|
||||
self.api_key = self.api_row.get_text()
|
||||
|
||||
def save(self):
|
||||
if self.require_api_key:
|
||||
return {"api_key": self.api_key}
|
||||
return {}
|
||||
|
||||
def load(self, data):
|
||||
if self.require_api_key:
|
||||
self.api_key = data["api_key"]
|
39
src/style.css
Normal file
|
@ -0,0 +1,39 @@
|
|||
.small-pill {
|
||||
border-radius: 18px;
|
||||
}
|
||||
|
||||
.user{
|
||||
background-color: rgba(61, 152, 255,0.03);
|
||||
}
|
||||
.assistant{
|
||||
background-color: rgba(184, 134, 17,0.02);
|
||||
}
|
||||
|
||||
.chat-entry > text { background: none; }
|
||||
|
||||
.message-bubble {
|
||||
font-size: 16px;
|
||||
color: @window_fg_color;
|
||||
border-radius: 15px;
|
||||
padding: 9px;
|
||||
background-color: mix(@window_bg_color, @window_fg_color, .05);
|
||||
}
|
||||
|
||||
|
||||
.message-bubble-user {
|
||||
background-color: alpha(@accent_bg_color, 0.3);
|
||||
color: @card_fg_color;
|
||||
}
|
||||
|
||||
.avatar-user {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.timestamp {
|
||||
font-size: 12px;
|
||||
padding-left: 6px;
|
||||
}
|
||||
|
||||
.sourceview {
|
||||
font-family: monospace;
|
||||
}
|
|
@ -5,28 +5,28 @@ class KillableThread(threading.Thread):
|
|||
def __init__(self, *args, **keywords):
|
||||
threading.Thread.__init__(self, *args, **keywords)
|
||||
self.killed = False
|
||||
|
||||
|
||||
def start(self):
|
||||
self.__run_backup = self.run
|
||||
self.run = self.__run
|
||||
self.run = self.__run
|
||||
threading.Thread.start(self)
|
||||
|
||||
|
||||
def __run(self):
|
||||
sys.settrace(self.globaltrace)
|
||||
self.__run_backup()
|
||||
self.run = self.__run_backup
|
||||
|
||||
|
||||
def globaltrace(self, frame, event, arg):
|
||||
if event == 'call':
|
||||
return self.localtrace
|
||||
else:
|
||||
return None
|
||||
|
||||
|
||||
def localtrace(self, frame, event, arg):
|
||||
if self.killed:
|
||||
if event == 'line':
|
||||
raise SystemExit()
|
||||
return self.localtrace
|
||||
|
||||
|
||||
def kill(self):
|
||||
self.killed = True
|
||||
self.killed = True
|
||||
|
|
|
@ -11,7 +11,7 @@ import platform
|
|||
# no quotes) and is not meant to be translated literally.
|
||||
translator_credits = _("translator-credits")
|
||||
|
||||
class BavarderAboutWindow:
|
||||
class AboutWindow:
|
||||
def __init__(self, parent):
|
||||
self.parent = parent
|
||||
self.app = self.parent.get_application()
|
||||
|
@ -23,7 +23,7 @@ class BavarderAboutWindow:
|
|||
application_name="Bavarder",
|
||||
transient_for=self.app.get_active_window(),
|
||||
application_icon=constants.app_id,
|
||||
developer_name=_("0xMRTT"),
|
||||
developer_name="0xMRTT",
|
||||
website=constants.project_url,
|
||||
support_url=constants.help_url,
|
||||
issue_url=constants.bugtracker_url,
|
||||
|
@ -34,49 +34,31 @@ class BavarderAboutWindow:
|
|||
"0xMRTT https://github.com/0xMRTT",
|
||||
],
|
||||
designers=[
|
||||
"David Lapshin https://github.com/daudix-UFO"
|
||||
|
||||
],
|
||||
artists=[
|
||||
"David Lapshin https://github.com/daudix-UFO"
|
||||
|
||||
],
|
||||
|
||||
translator_credits=_(translator_credits),
|
||||
translator_credits=translator_credits,
|
||||
copyright=_("Copyright © 2023 0xMRTT"),
|
||||
license_type=Gtk.License.GPL_3_0,
|
||||
version=constants.version,
|
||||
release_notes_version=constants.rel_ver,
|
||||
)
|
||||
|
||||
self.about_window.add_acknowledgement_section(
|
||||
"Special thanks to",
|
||||
[
|
||||
"Telegraph https://apps.gnome.org/app/io.github.fkinoshita.Telegraph",
|
||||
"Apostrophe https://apps.gnome.org/app/org.gnome.gitlab.somas.Apostrophe",
|
||||
],
|
||||
)
|
||||
self.about_window.add_credit_section(
|
||||
_("Packaging"),
|
||||
[
|
||||
_("Soumyadeep Ghosh https://codeberg.org/soumyadghosh")
|
||||
]
|
||||
)
|
||||
self.about_window.set_debug_info(
|
||||
f"""{constants.app_id} {constants.version}
|
||||
Environment: {os.environ.get("XDG_CURRENT_DESKTOP", "Unknown")}
|
||||
Gtk: {Gtk.MAJOR_VERSION}.{Gtk.MINOR_VERSION}.{Gtk.MICRO_VERSION}
|
||||
Python: {platform.python_version()}
|
||||
OS: {platform.system()} {platform.release()} {platform.version()}
|
||||
Providers: {self.app.enabled_providers}
|
||||
Use Theme: {self.app.use_theme}
|
||||
Use Text View: {self.app.use_text_view}
|
||||
Clear After Send: {self.app.clear_after_send}
|
||||
Close All Without Dialog: {self.app.close_all_without_dialog}
|
||||
Current Provider: {self.app.provider}
|
||||
"""
|
||||
)
|
||||
self.about_window.present()
|
||||
|
||||
|
||||
|
||||
def show_about(self):
|
||||
|
||||
def present(self):
|
||||
self.about_window.present()
|
||||
|
||||
|
|
|
@ -1,67 +0,0 @@
|
|||
|
||||
from gi.repository import Adw, Gtk, Gio
|
||||
|
||||
from bavarder.constants import app_id, build_type
|
||||
|
||||
@Gtk.Template(resource_path="/io/github/Bavarder/Bavarder/ui/window.ui")
|
||||
class BavarderWindow(Adw.ApplicationWindow):
|
||||
__gtype_name__ = "BavarderWindow"
|
||||
|
||||
toast_overlay = Gtk.Template.Child()
|
||||
prompt_text_view = Gtk.Template.Child()
|
||||
ask_button = Gtk.Template.Child()
|
||||
scrolled_response_window = Gtk.Template.Child()
|
||||
bot_text_view = Gtk.Template.Child()
|
||||
banner = Gtk.Template.Child()
|
||||
stop_button = Gtk.Template.Child()
|
||||
# listen = Gtk.Template.Child()
|
||||
# listen_wait = Gtk.Template.Child()
|
||||
# listen_spinner = Gtk.Template.Child()
|
||||
# speak = Gtk.Template.Child()
|
||||
# speak_wait = Gtk.Template.Child()
|
||||
# speak_spinner = Gtk.Template.Child()
|
||||
menu = Gtk.Template.Child()
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
super().__init__(**kwargs)
|
||||
|
||||
self.app = Gtk.Application.get_default()
|
||||
self.settings = Gio.Settings(schema_id=app_id)
|
||||
|
||||
self.setup_signals()
|
||||
self.setup_window_props()
|
||||
|
||||
self.setup()
|
||||
|
||||
|
||||
def setup_window_props(self):
|
||||
self.settings.bind(
|
||||
"width", self, "default-width", Gio.SettingsBindFlags.DEFAULT
|
||||
)
|
||||
self.settings.bind(
|
||||
"height", self, "default-height", Gio.SettingsBindFlags.DEFAULT
|
||||
)
|
||||
self.settings.bind(
|
||||
"is-maximized", self, "maximized", Gio.SettingsBindFlags.DEFAULT
|
||||
)
|
||||
self.settings.bind(
|
||||
"is-fullscreen", self, "fullscreened", Gio.SettingsBindFlags.DEFAULT
|
||||
)
|
||||
|
||||
|
||||
def setup_signals(self):
|
||||
self.connect("close-request",
|
||||
self.on_close_request)
|
||||
|
||||
|
||||
|
||||
def setup(self):
|
||||
# Set devel style
|
||||
if build_type == "debug":
|
||||
self.get_style_context().add_class("devel")
|
||||
|
||||
def on_close_request(self, *args):
|
||||
self.settings.set_strv("enabled-providers", list(self.app.enabled_providers))
|
||||
self.settings.set_string("latest-provider", self.app.provider)
|
||||
self.app.save_providers()
|
||||
self.close()
|
|
@ -1,11 +1,10 @@
|
|||
|
||||
views_dir = join_paths(moduledir, 'views')
|
||||
views_dir = join_paths(MODULE_DIR, 'views')
|
||||
|
||||
views_sources = [
|
||||
'__init__.py',
|
||||
'about_window.py',
|
||||
'main_window.py',
|
||||
'preferences_window.py',
|
||||
'window.py',
|
||||
]
|
||||
|
||||
PY_INSTALLDIR.install_sources(views_sources, subdir: views_dir)
|
||||
PY_INSTALLDIR.install_sources(views_sources, subdir: views_dir)
|
21
src/views/preferences_window.blp
Normal file
|
@ -0,0 +1,21 @@
|
|||
using Gtk 4.0;
|
||||
using Adw 1;
|
||||
|
||||
template $Preferences : Adw.PreferencesWindow {
|
||||
title: _("Preferences");
|
||||
default-height: 400;
|
||||
default-width: 600;
|
||||
modal: true;
|
||||
|
||||
Adw.PreferencesPage general_page {
|
||||
|
||||
Adw.PreferencesGroup provider_group {
|
||||
title: _("Providers");
|
||||
}
|
||||
|
||||
Adw.PreferencesGroup model_group {
|
||||
title: _("Models");
|
||||
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,19 +1,19 @@
|
|||
from gi.repository import Gtk, Adw, Gio
|
||||
|
||||
from bavarder.constants import app_id
|
||||
from bavarder.constants import app_id, rootdir
|
||||
from bavarder.providers.provider_item import Provider
|
||||
from bavarder.widgets.model_item import Model
|
||||
from bavarder.widgets.download_row import DownloadRow
|
||||
|
||||
from bavarder.providers import PROVIDERS
|
||||
from gpt4all import GPT4All
|
||||
|
||||
|
||||
@Gtk.Template(resource_path="/io/github/Bavarder/Bavarder/ui/preferences.ui")
|
||||
class Preferences(Adw.PreferencesWindow):
|
||||
@Gtk.Template(resource_path=f"{rootdir}/ui/preferences_window.ui")
|
||||
class PreferencesWindow(Adw.PreferencesWindow):
|
||||
__gtype_name__ = "Preferences"
|
||||
|
||||
clear_after_send_switch = Gtk.Template.Child()
|
||||
provider_group = Gtk.Template.Child()
|
||||
use_text_view_switch = Gtk.Template.Child()
|
||||
close_all_without_dialog_switch = Gtk.Template.Child()
|
||||
allow_remote_fetching_switch = Gtk.Template.Child()
|
||||
general_page = Gtk.Template.Child()
|
||||
model_group = Gtk.Template.Child()
|
||||
|
||||
def __init__(self, parent, **kwargs):
|
||||
super().__init__(**kwargs)
|
||||
|
@ -30,84 +30,32 @@ class Preferences(Adw.PreferencesWindow):
|
|||
|
||||
def setup(self):
|
||||
self.setup_signals()
|
||||
self.load_providers()
|
||||
self.load_models()
|
||||
|
||||
def setup_signals(self):
|
||||
pass
|
||||
|
||||
self.clear_after_send_switch.set_active(self.app.clear_after_send)
|
||||
self.clear_after_send_switch.connect(
|
||||
"notify::active", self.on_clear_after_send_switch_toggled
|
||||
)
|
||||
def load_providers(self):
|
||||
for provider in self.app.providers.values():
|
||||
p = Provider(self.app, self, provider)
|
||||
self.provider_group.add(p)
|
||||
|
||||
self.use_text_view_switch.set_active(self.app.use_text_view)
|
||||
self.use_text_view_switch.connect(
|
||||
"notify::active", self.on_use_text_view_switch_toggled
|
||||
)
|
||||
|
||||
self.close_all_without_dialog_switch.set_active(self.app.close_all_without_dialog)
|
||||
self.close_all_without_dialog_switch.connect(
|
||||
"notify::active", self.on_close_all_without_dialog_switch_toggled
|
||||
)
|
||||
|
||||
self.allow_remote_fetching_switch.set_active(self.app.allow_remote_fetching)
|
||||
self.allow_remote_fetching_switch.connect(
|
||||
"notify::active", self.on_allow_remote_fetching_switch_toggled
|
||||
)
|
||||
|
||||
self.setup_providers()
|
||||
|
||||
def on_clear_after_send_switch_toggled(self, widget, *args):
|
||||
"""Callback for the clear_after_send_switch toggled event."""
|
||||
if widget.get_active():
|
||||
self.settings.set_boolean("clear-after-send", True)
|
||||
self.app.clear_after_send = True
|
||||
def load_models(self):
|
||||
self.general_page.remove(self.model_group)
|
||||
self.model_group = Adw.PreferencesGroup()
|
||||
self.model_group.set_title(_("Models"))
|
||||
|
||||
for model in self.app.models:
|
||||
p = Model(self.app, self, model)
|
||||
self.model_group.add(p)
|
||||
else:
|
||||
self.settings.set_boolean("clear-after-send", False)
|
||||
self.app.clear_after_send = False
|
||||
self.no_models_available = Adw.ExpanderRow()
|
||||
self.no_models_available.set_title(_("Download more models"))
|
||||
|
||||
def on_use_text_view_switch_toggled(self, widget, *args):
|
||||
"""Callback for the use_text_view_switch toggled event."""
|
||||
if widget.get_active():
|
||||
self.settings.set_boolean("use-text-view", True)
|
||||
self.app.use_text_view = True
|
||||
else:
|
||||
self.settings.set_boolean("use-text-view", False)
|
||||
self.app.use_text_view = False
|
||||
for model in GPT4All.list_models():
|
||||
self.no_models_available.add_row(DownloadRow(self.app, self, model))
|
||||
|
||||
def on_close_all_without_dialog_switch_toggled(self, widget, *args):
|
||||
"""Callback for the close_all_without_dialog_switch toggled event."""
|
||||
if widget.get_active():
|
||||
self.settings.set_boolean("close-all-without-dialog", True)
|
||||
self.app.close_all_without_dialog = True
|
||||
else:
|
||||
self.settings.set_boolean("close-all-without-dialog", False)
|
||||
self.app.close_all_without_dialog = False
|
||||
self.model_group.add(self.no_models_available)
|
||||
|
||||
def on_allow_remote_fetching_switch_toggled(self, widget, *args):
|
||||
"""Callback for the allow_remote_fetching_switch toggled event."""
|
||||
if widget.get_active():
|
||||
self.settings.set_boolean("allow-remote-fetching", True)
|
||||
self.app.load_annoucements()
|
||||
self.app.allow_remote_fetching = True
|
||||
else:
|
||||
self.settings.set_boolean("allow-remote-fetching", False)
|
||||
self.app.allow_remote_fetching = False
|
||||
|
||||
def setup_providers(self):
|
||||
# for provider in self.app.providers.values():
|
||||
# try:
|
||||
# self.provider_group.add(provider.preferences(self))
|
||||
# except TypeError: # no prefs
|
||||
# pass
|
||||
# else:
|
||||
# row = Adw.ActionRow()
|
||||
# row.props.title = "No providers available"
|
||||
# self.provider_group.add(row)
|
||||
for provider in PROVIDERS.values():
|
||||
if provider.slug in self.app.providers:
|
||||
self.provider_group.add(
|
||||
self.app.providers[provider.slug].preferences(win=self.app.win)
|
||||
)
|
||||
else:
|
||||
self.provider_group.add(
|
||||
provider(self.app.win, self.app).preferences(win=self.app.win)
|
||||
)
|
||||
self.general_page.add(self.model_group)
|
231
src/views/window.blp
Normal file
|
@ -0,0 +1,231 @@
|
|||
using Gtk 4.0;
|
||||
using Adw 1;
|
||||
|
||||
template $BavarderWindow : Adw.ApplicationWindow {
|
||||
|
||||
title: _("Bavarder");
|
||||
default-width: 350;
|
||||
default-height: 500;
|
||||
width-request: 360;
|
||||
height-request: 200;
|
||||
|
||||
ShortcutController {
|
||||
Shortcut {
|
||||
trigger: "<primary>q";
|
||||
action: "action(window.close)";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
Adw.ToastOverlay toast_overlay {
|
||||
Adw.NavigationSplitView split_view {
|
||||
max-sidebar-width: 260;
|
||||
sidebar-width-fraction: 0.38;
|
||||
sidebar: Adw.NavigationPage {
|
||||
title: _("Bavarder");
|
||||
child: Adw.ToolbarView {
|
||||
[top]
|
||||
Adw.HeaderBar {
|
||||
[start]
|
||||
Button new_chat {
|
||||
icon-name: "chat-message-new-symbolic";
|
||||
tooltip-text: _("New Chat");
|
||||
clicked => $on_new_chat_action();
|
||||
}
|
||||
[end]
|
||||
MenuButton menu_button {
|
||||
primary: true;
|
||||
menu-model: main-menu;
|
||||
icon-name: "open-menu-symbolic";
|
||||
tooltip-text: _("Main Menu");
|
||||
|
||||
}
|
||||
}
|
||||
content: Gtk.ScrolledWindow {
|
||||
hscrollbar-policy: never;
|
||||
child: Gtk.ListBox threads_list {
|
||||
selection-mode: browse;
|
||||
row-activated => $threads_row_activated_cb();
|
||||
styles ["navigation-sidebar"]
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
content: Adw.NavigationPage message_page {
|
||||
tag: "message";
|
||||
title: _("Message");
|
||||
child: Adw.ToolbarView {
|
||||
[top]
|
||||
Adw.HeaderBar {
|
||||
[start]
|
||||
Gtk.ToggleButton local_mode_toggle {
|
||||
icon-name: 'cloud-disabled-symbolic';
|
||||
toggled => $on_local_mode_toggled();
|
||||
}
|
||||
|
||||
[title]
|
||||
Adw.WindowTitle title {
|
||||
title: _("Chat");
|
||||
}
|
||||
|
||||
[end]
|
||||
Button clear_all_button {
|
||||
icon-name: 'edit-clear-all-symbolic';
|
||||
clicked => $on_clear_all();
|
||||
visible: false;
|
||||
}
|
||||
|
||||
[end]
|
||||
MenuButton model_selector_button {
|
||||
icon-name: 'brain-augemnted-symbolic';
|
||||
visible: false;
|
||||
}
|
||||
|
||||
[end]
|
||||
MenuButton provider_selector_button {
|
||||
icon-name: 'brain-augemnted-symbolic';
|
||||
visible: false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
[top]
|
||||
Adw.Banner banner {
|
||||
|
||||
}
|
||||
|
||||
content: Overlay {
|
||||
// [overlay]
|
||||
// Button {
|
||||
// styles [
|
||||
// "circular",
|
||||
// ]
|
||||
// icon-name: "go-bottom-symbolic";
|
||||
// halign: end;
|
||||
// valign: end;
|
||||
// margin-bottom: 7;
|
||||
// margin-end: 7;
|
||||
// clicked => $scroll_down();
|
||||
// }
|
||||
|
||||
Stack stack {
|
||||
|
||||
Adw.StatusPage status_no_chat {
|
||||
title: _("No Chat");
|
||||
icon-name: "chat-message-new-symbolic";
|
||||
}
|
||||
|
||||
Adw.StatusPage status_no_internet {
|
||||
title: _("No Internet");
|
||||
icon-name: "network-disconnect-symbolic";
|
||||
}
|
||||
|
||||
// Message List
|
||||
ScrolledWindow main {
|
||||
//vexpand: true;
|
||||
hscrollbar-policy: never;
|
||||
//edge-overshot => $handle_edge_reached() swapped;
|
||||
|
||||
Adw.Clamp {
|
||||
// vexpand: false;
|
||||
// hexpand: true;
|
||||
maximum-size: 1200;
|
||||
// tightening-threshold: 550;
|
||||
// margin-bottom: 4;
|
||||
// margin-start: 12;
|
||||
// margin-end: 12;
|
||||
|
||||
ListBox main_list {
|
||||
styles [
|
||||
"message-list",
|
||||
"background"
|
||||
]
|
||||
selection-mode: none;
|
||||
show-separators: false;
|
||||
hexpand: true;
|
||||
vexpand: false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
[bottom]
|
||||
Gtk.Box toolbar {
|
||||
orientation: vertical;
|
||||
visible: true;
|
||||
|
||||
Gtk.Box {
|
||||
orientation: horizontal;
|
||||
|
||||
ScrolledWindow scrolled_window {
|
||||
vexpand: true;
|
||||
hexpand: true;
|
||||
vscrollbar-policy: external;
|
||||
max-content-height: 100;
|
||||
propagate-natural-height: true;
|
||||
}
|
||||
|
||||
Button ask_button {
|
||||
valign: end;
|
||||
|
||||
margin-start: 5;
|
||||
|
||||
icon-name: "paper-plane-symbolic";
|
||||
tooltip-text: _("Ask");
|
||||
halign: end;
|
||||
clicked => $on_ask();
|
||||
styles ["suggested-action", "circular"]
|
||||
}
|
||||
}
|
||||
|
||||
styles ["small-pill", "toolbar" ]
|
||||
}
|
||||
|
||||
|
||||
|
||||
};
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
Adw.Breakpoint {
|
||||
condition ("max-width: 400sp")
|
||||
setters {
|
||||
split_view.collapsed: true;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
Adw.Breakpoint {
|
||||
condition ("max-width: 500sp")
|
||||
//unapply => $one_pane_unapply_cb();
|
||||
setters {
|
||||
split_view.sidebar-width-fraction: 0.33;
|
||||
split_view.collapsed: true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
menu main-menu {
|
||||
item {
|
||||
label: _("Preferences");
|
||||
action: "app.preferences";
|
||||
}
|
||||
|
||||
item {
|
||||
label: _("Keyboard Shortcuts");
|
||||
action: "win.show-help-overlay";
|
||||
}
|
||||
|
||||
item {
|
||||
label: _("About Bavarder");
|
||||
action: "app.about";
|
||||
}
|
||||
}
|
304
src/views/window.py
Normal file
|
@ -0,0 +1,304 @@
|
|||
# window.py
|
||||
#
|
||||
# Copyright 2023
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
import time
|
||||
|
||||
from gi.repository import Gtk, Gio, Adw, GLib
|
||||
|
||||
from bavarder.constants import app_id, build_type, rootdir
|
||||
from bavarder.widgets.thread_item import ThreadItem
|
||||
from bavarder.widgets.item import Item
|
||||
from bavarder.threading import KillableThread
|
||||
|
||||
class CustomEntry(Gtk.TextView):
|
||||
def __init__(self, **kwargs):
|
||||
super().__init__(**kwargs)
|
||||
|
||||
@Gtk.Template(resource_path=f'{rootdir}/ui/window.ui')
|
||||
class BavarderWindow(Adw.ApplicationWindow):
|
||||
__gtype_name__ = 'BavarderWindow'
|
||||
|
||||
split_view = Gtk.Template.Child()
|
||||
threads_list = Gtk.Template.Child()
|
||||
title = Gtk.Template.Child()
|
||||
|
||||
main_list = Gtk.Template.Child()
|
||||
status_no_chat = Gtk.Template.Child()
|
||||
status_no_internet = Gtk.Template.Child()
|
||||
scrolled_window = Gtk.Template.Child()
|
||||
local_mode_toggle = Gtk.Template.Child()
|
||||
provider_selector_button = Gtk.Template.Child()
|
||||
model_selector_button = Gtk.Template.Child()
|
||||
clear_all_button = Gtk.Template.Child()
|
||||
banner = Gtk.Template.Child()
|
||||
toast_overlay = Gtk.Template.Child()
|
||||
stack = Gtk.Template.Child()
|
||||
main = Gtk.Template.Child()
|
||||
|
||||
threads = []
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
super().__init__(**kwargs)
|
||||
|
||||
self.app = Gtk.Application.get_default()
|
||||
self.settings = Gio.Settings(schema_id=app_id)
|
||||
|
||||
CustomEntry.set_css_name("entry")
|
||||
self.message_entry = CustomEntry()
|
||||
self.message_entry.set_hexpand(True)
|
||||
self.message_entry.set_accepts_tab(False)
|
||||
self.message_entry.set_margin_start(5)
|
||||
self.message_entry.set_margin_end(5)
|
||||
self.message_entry.set_wrap_mode(Gtk.WrapMode.WORD)
|
||||
self.message_entry.add_css_class("chat-entry")
|
||||
|
||||
self.scrolled_window.set_child(self.message_entry)
|
||||
self.load_threads()
|
||||
|
||||
self.local_mode_toggle.set_active(self.app.local_mode)
|
||||
|
||||
self.on_local_mode_toggled(self.local_mode_toggle)
|
||||
|
||||
self.create_action("cancel", self.cancel, ["<primary>Escape"])
|
||||
|
||||
self.settings.bind(
|
||||
"width", self, "default-width", Gio.SettingsBindFlags.DEFAULT
|
||||
)
|
||||
self.settings.bind(
|
||||
"height", self, "default-height", Gio.SettingsBindFlags.DEFAULT
|
||||
)
|
||||
self.settings.bind(
|
||||
"is-maximized", self, "maximized", Gio.SettingsBindFlags.DEFAULT
|
||||
)
|
||||
self.settings.bind(
|
||||
"is-fullscreen", self, "fullscreened", Gio.SettingsBindFlags.DEFAULT
|
||||
)
|
||||
|
||||
|
||||
@property
|
||||
def chat(self):
|
||||
try:
|
||||
return self.threads_list.get_selected_row().get_child().chat
|
||||
except AttributeError: # create a new chat
|
||||
self.on_new_chat_action()
|
||||
finally:
|
||||
return self.threads_list.get_selected_row().get_child().chat
|
||||
|
||||
@property
|
||||
def content(self):
|
||||
try:
|
||||
return self.chat["content"]
|
||||
except KeyError: # no content
|
||||
self.chat["content"] = []
|
||||
finally:
|
||||
return self.chat["content"]
|
||||
|
||||
def load_threads(self):
|
||||
self.threads_list.remove_all()
|
||||
if self.app.data["chats"]:
|
||||
for chat in self.app.data["chats"]:
|
||||
thread = ThreadItem(self, chat)
|
||||
self.threads_list.append(thread)
|
||||
self.threads.append(thread)
|
||||
self.stack.set_visible_child(self.main)
|
||||
else:
|
||||
self.stack.set_visible_child(self.status_no_chat)
|
||||
|
||||
@Gtk.Template.Callback()
|
||||
def threads_row_activated_cb(self, *args):
|
||||
self.split_view.set_collapsed(True)
|
||||
self.split_view.set_show_content(True)
|
||||
|
||||
self.title.set_title(self.chat["title"])
|
||||
|
||||
if self.content:
|
||||
self.stack.set_visible_child(self.main)
|
||||
self.main_list.remove_all()
|
||||
for item in self.content:
|
||||
i = Item(self, self.chat, item)
|
||||
self.main_list.append(i)
|
||||
else:
|
||||
self.stack.set_visible_child(self.status_no_chat)
|
||||
|
||||
@Gtk.Template.Callback()
|
||||
def on_new_chat_action(self, *args):
|
||||
self.app.on_new_chat_action(_, _)
|
||||
|
||||
# @Gtk.Template.Callback()
|
||||
# def scroll_down(self, *args):
|
||||
# self.scrolled_window.emit("scroll-child", Gtk.ScrollType.END, False)
|
||||
|
||||
@Gtk.Template.Callback()
|
||||
def on_clear_all(self, *args):
|
||||
if self.content:
|
||||
self.stack.set_visible_child(self.main)
|
||||
self.main_list.remove_all()
|
||||
del self.chat["content"]
|
||||
else:
|
||||
self.stack.set_visible_child(self.status_no_chat)
|
||||
|
||||
# PROVIDER - ONLINE
|
||||
def load_provider_selector(self):
|
||||
provider_menu = Gio.Menu()
|
||||
|
||||
for provider in self.app.providers.values():
|
||||
if provider.enabled:
|
||||
item_provider = Gio.MenuItem()
|
||||
item_provider.set_label(provider.name)
|
||||
item_provider.set_action_and_target_value(
|
||||
"app.set_provider",
|
||||
GLib.Variant("s", provider.slug))
|
||||
provider_menu.append_item(item_provider)
|
||||
else:
|
||||
item_provider = Gio.MenuItem()
|
||||
item_provider.set_label(_("Preferences"))
|
||||
item_provider.set_action_and_target_value("app.preferences", None)
|
||||
provider_menu.append_item(item_provider)
|
||||
|
||||
self.provider_selector_button.set_menu_model(provider_menu)
|
||||
|
||||
# MODEL - OFFLINE
|
||||
def load_model_selector(self):
|
||||
provider_menu = Gio.Menu()
|
||||
|
||||
if not self.app.models:
|
||||
self.app.list_models()
|
||||
|
||||
for provider in self.app.models:
|
||||
item_provider = Gio.MenuItem()
|
||||
item_provider.set_label(provider)
|
||||
item_provider.set_action_and_target_value(
|
||||
"app.set_model",
|
||||
GLib.Variant("s", provider))
|
||||
provider_menu.append_item(item_provider)
|
||||
else:
|
||||
item_provider = Gio.MenuItem()
|
||||
item_provider.set_label(_("Preferences"))
|
||||
item_provider.set_action_and_target_value("app.preferences", None)
|
||||
provider_menu.append_item(item_provider)
|
||||
|
||||
self.model_selector_button.set_menu_model(provider_menu)
|
||||
|
||||
@Gtk.Template.Callback()
|
||||
def on_local_mode_toggled(self, widget):
|
||||
self.app.local_mode = widget.get_active()
|
||||
|
||||
if self.app.local_mode:
|
||||
self.local_mode_toggle.set_icon_name("cloud-disabled-symbolic")
|
||||
self.model_selector_button.set_visible(True)
|
||||
self.provider_selector_button.set_visible(False)
|
||||
self.clear_all_button.set_visible(False)
|
||||
else:
|
||||
self.local_mode_toggle.set_icon_name("cloud-filled-symbolic")
|
||||
self.provider_selector_button.set_visible(True)
|
||||
self.model_selector_button.set_visible(False)
|
||||
self.clear_all_button.set_visible(False)
|
||||
|
||||
def check_network(self):
|
||||
if self.app.check_network(): # Internet
|
||||
if not self.content:
|
||||
self.status_no_chat.set_visible(True)
|
||||
self.status_no_internet.set_visible(False)
|
||||
else:
|
||||
self.status_no_chat.set_visible(False)
|
||||
self.status_no_internet.set_visible(False)
|
||||
else:
|
||||
self.status_no_chat.set_visible(False)
|
||||
self.status_no_internet.set_visible(True)
|
||||
|
||||
|
||||
|
||||
@Gtk.Template.Callback()
|
||||
def on_ask(self, *args):
|
||||
if not self.threads: # no chat
|
||||
self.on_new_chat_action()
|
||||
self.threads_list.select_row(self.threads_list.get_row_at_index(0))
|
||||
|
||||
prompt = self.message_entry.get_buffer().props.text.strip()
|
||||
if prompt:
|
||||
self.message_entry.get_buffer().set_text("")
|
||||
|
||||
self.add_user_item(prompt)
|
||||
|
||||
def thread_run():
|
||||
self.toast = Adw.Toast()
|
||||
self.toast.set_title(_("Generating response"))
|
||||
self.toast.set_button_label(_("Cancel"))
|
||||
self.toast.set_action_name("win.cancel")
|
||||
self.toast.set_timeout(0)
|
||||
self.toast_overlay.add_toast(self.toast)
|
||||
response = self.app.ask(prompt, self.chat)
|
||||
GLib.idle_add(cleanup, response, self.toast)
|
||||
|
||||
def cleanup(response, toast):
|
||||
self.t.join()
|
||||
self.toast.dismiss()
|
||||
|
||||
self.add_assistant_item(response)
|
||||
|
||||
self.t = KillableThread(target=thread_run)
|
||||
self.t.start()
|
||||
|
||||
def cancel(self, *args):
|
||||
try:
|
||||
self.t.kill()
|
||||
self.t.join()
|
||||
self.toast.dismiss()
|
||||
except AttributeError: # nothing to stop
|
||||
pass
|
||||
|
||||
def create_action(self, name, callback, shortcuts=None):
|
||||
action = Gio.SimpleAction.new(name, None)
|
||||
action.connect("activate", callback)
|
||||
self.add_action(action)
|
||||
|
||||
if shortcuts:
|
||||
self.app.set_accels_for_action(f"win.{name}", shortcuts)
|
||||
|
||||
|
||||
|
||||
def add_user_item(self, content):
|
||||
self.content.append(
|
||||
{
|
||||
"role": "user",
|
||||
"content": content,
|
||||
"time": time.strftime("%X")
|
||||
}
|
||||
)
|
||||
|
||||
self.threads_row_activated_cb()
|
||||
|
||||
def add_assistant_item(self, content):
|
||||
c = {
|
||||
"role": "assistant",
|
||||
"content": content,
|
||||
"time": time.strftime("%X"),
|
||||
}
|
||||
|
||||
if self.app.local_mode and self.app.model_name:
|
||||
c["model"] = self.app.model_name
|
||||
elif self.app.current_provider:
|
||||
c["model"] = self.app.current_provider
|
||||
|
||||
|
||||
self.content.append(c)
|
||||
|
||||
self.threads_row_activated_cb()
|
||||
|
||||
|
75
src/widgets/code_block.blp
Normal file
|
@ -0,0 +1,75 @@
|
|||
using Gtk 4.0;
|
||||
using Adw 1;
|
||||
using GtkSource 5;
|
||||
|
||||
template $CodeBlock : Gtk.Widget {
|
||||
layout-manager: BinLayout {};
|
||||
vexpand: true;
|
||||
|
||||
height-request: 50;
|
||||
|
||||
Overlay {
|
||||
|
||||
[overlay]
|
||||
Button {
|
||||
styles [
|
||||
"circular",
|
||||
]
|
||||
icon-name: "terminal-symbolic";
|
||||
halign: end;
|
||||
valign: start;
|
||||
margin-top: 7;
|
||||
margin-end: 7;
|
||||
clicked => $run();
|
||||
}
|
||||
|
||||
Box box {
|
||||
orientation: vertical;
|
||||
vexpand: true;
|
||||
hexpand: true;
|
||||
|
||||
Box view {
|
||||
vexpand: true;
|
||||
hexpand: true;
|
||||
GtkSource.View source_view {
|
||||
vexpand: true;
|
||||
hexpand: true;
|
||||
buffer: GtkSource.Buffer buffer {};
|
||||
editable: true;
|
||||
monospace: true;
|
||||
show-line-marks: true;
|
||||
show-line-numbers: true;
|
||||
smart-backspace: true;
|
||||
margin-top: 5;
|
||||
margin-bottom: 5;
|
||||
styles [ "codeview", "card" ]
|
||||
}
|
||||
}
|
||||
|
||||
Box output {
|
||||
visible: false;
|
||||
vexpand: true;
|
||||
hexpand: true;
|
||||
|
||||
GtkSource.View output_source_view {
|
||||
vexpand: true;
|
||||
hexpand: true;
|
||||
buffer: GtkSource.Buffer output_buffer {};
|
||||
editable: false;
|
||||
monospace: true;
|
||||
show-line-marks: true;
|
||||
show-line-numbers: true;
|
||||
margin-top: 5;
|
||||
margin-bottom: 5;
|
||||
styles [ "codeview", "card" ]
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
76
src/widgets/code_block.py
Normal file
|
@ -0,0 +1,76 @@
|
|||
from gi.repository import Gtk, GtkSource, Adw, Xdp
|
||||
|
||||
from bavarder.constants import app_id, rootdir
|
||||
|
||||
import subprocess
|
||||
from subprocess import SubprocessError, CompletedProcess
|
||||
import os
|
||||
|
||||
GtkSource.init()
|
||||
|
||||
@Gtk.Template(resource_path=f"{rootdir}/ui/code_block.ui")
|
||||
class CodeBlock(Gtk.Widget):
|
||||
__gtype_name__ = "CodeBlock"
|
||||
|
||||
buffer = Gtk.Template.Child()
|
||||
source_view = Gtk.Template.Child()
|
||||
output_buffer = Gtk.Template.Child()
|
||||
output_source_view = Gtk.Template.Child()
|
||||
view = Gtk.Template.Child()
|
||||
box = Gtk.Template.Child()
|
||||
output = Gtk.Template.Child()
|
||||
|
||||
def __init__(self, result, **kwargs):
|
||||
super().__init__(**kwargs)
|
||||
|
||||
self.command = result
|
||||
|
||||
self.buffer.set_text(self.command)
|
||||
|
||||
if Adw.StyleManager().get_dark():
|
||||
self.buffer.set_style_scheme(GtkSource.StyleSchemeManager().get_scheme("Adwaita-dark"))
|
||||
else:
|
||||
self.buffer.set_style_scheme(GtkSource.StyleSchemeManager().get_scheme("Adwaita"))
|
||||
|
||||
if Adw.StyleManager().get_dark():
|
||||
self.output_buffer.set_style_scheme(GtkSource.StyleSchemeManager().get_scheme("Adwaita-dark"))
|
||||
else:
|
||||
self.output_buffer.set_style_scheme(GtkSource.StyleSchemeManager().get_scheme("Adwaita"))
|
||||
|
||||
|
||||
@Gtk.Template.Callback()
|
||||
def run(self, widget, *args):
|
||||
command = self.buffer.props.text.split(" ")
|
||||
if self.command.startswith("$"):
|
||||
command.pop(0)
|
||||
|
||||
portal = Xdp.Portal()
|
||||
is_sandboxed = portal.running_under_sandbox()
|
||||
output = self._run(command, allow_escaping=is_sandboxed)
|
||||
|
||||
self.output_buffer.set_text(output)
|
||||
self.output.set_visible(True)
|
||||
|
||||
def _run(self, command: list, timeout: int = None, allow_escaping: bool = False) -> CompletedProcess:
|
||||
if allow_escaping and os.environ.get('FLATPAK_ID'):
|
||||
command = ['flatpak-spawn', '--host'] + command
|
||||
|
||||
try:
|
||||
process = subprocess.Popen(command, stdout=subprocess.PIPE,
|
||||
stderr=subprocess.PIPE, shell=True)
|
||||
except SubprocessError:
|
||||
raise
|
||||
except FileNotFoundError:
|
||||
raise
|
||||
|
||||
stdout, stderr = process.communicate()
|
||||
|
||||
if process.returncode != 0:
|
||||
output = stderr.decode()
|
||||
else:
|
||||
if stdout.decode() == "":
|
||||
output = _("Done")
|
||||
else:
|
||||
output = stdout.decode()
|
||||
|
||||
return output
|
11
src/widgets/download_row.blp
Normal file
|
@ -0,0 +1,11 @@
|
|||
using Gtk 4.0;
|
||||
using Adw 1;
|
||||
|
||||
template $DownloadRow : Adw.ActionRow {
|
||||
[suffix]
|
||||
Button download {
|
||||
valign: center;
|
||||
icon-name: "browser-download-symbolic";
|
||||
clicked => $on_download_button_clicked();
|
||||
}
|
||||
}
|
49
src/widgets/download_row.py
Normal file
|
@ -0,0 +1,49 @@
|
|||
from gi.repository import Gtk, Adw, GLib
|
||||
|
||||
from bavarder.constants import app_id, rootdir
|
||||
from bavarder.threading import KillableThread
|
||||
|
||||
@Gtk.Template(resource_path=f"{rootdir}/ui/download_row.ui")
|
||||
class DownloadRow(Adw.ActionRow):
|
||||
__gtype_name__ = "DownloadRow"
|
||||
|
||||
def __init__(self, app, window, model, **kwargs):
|
||||
super().__init__(**kwargs)
|
||||
self.app = app
|
||||
self.window = window
|
||||
self.model = model
|
||||
|
||||
self.setup()
|
||||
|
||||
def setup(self):
|
||||
self.set_title(self.model["name"])
|
||||
self.set_subtitle(self.model["filename"])
|
||||
|
||||
@Gtk.Template.Callback()
|
||||
def on_download_button_clicked(self, widget, *args):
|
||||
def thread_run():
|
||||
self.app.action_running_in_background = True
|
||||
|
||||
toast = Adw.Toast()
|
||||
toast.set_timeout(0)
|
||||
toast.set_title(_("Downloading model %s" % self.model["name"]) )
|
||||
self.window.add_toast(toast)
|
||||
|
||||
self.app.download_model(self.model["filename"])
|
||||
GLib.idle_add(cleanup, toast)
|
||||
|
||||
def cleanup(toast):
|
||||
t.join()
|
||||
|
||||
toast.dismiss()
|
||||
|
||||
self.app.action_running_in_background = False
|
||||
self.app.list_models()
|
||||
self.window.load_models()
|
||||
|
||||
toast = Adw.Toast()
|
||||
toast.set_title(_("Model %s downloaded!" % self.model["name"]) )
|
||||
self.window.add_toast(toast)
|
||||
|
||||
t = KillableThread(target=thread_run)
|
||||
t.start()
|
110
src/widgets/item.blp
Normal file
|
@ -0,0 +1,110 @@
|
|||
using Gtk 4.0;
|
||||
using Adw 1;
|
||||
|
||||
template $Item : Box {
|
||||
margin-top: 10;
|
||||
margin-bottom: 10;
|
||||
spacing: 10;
|
||||
|
||||
Adw.Avatar avatar {
|
||||
styles [
|
||||
"avatar-other",
|
||||
]
|
||||
valign: start;
|
||||
size: 36;
|
||||
}
|
||||
|
||||
Box {
|
||||
orientation: vertical;
|
||||
|
||||
Box message_bubble {
|
||||
spacing: 2;
|
||||
orientation: vertical;
|
||||
|
||||
styles [
|
||||
"message-bubble",
|
||||
]
|
||||
|
||||
|
||||
Box header {
|
||||
orientation: horizontal;
|
||||
|
||||
Label user {
|
||||
hexpand: true;
|
||||
halign: start;
|
||||
ellipsize: end;
|
||||
selectable: true;
|
||||
margin-end: 15;
|
||||
styles [ "heading" ]
|
||||
}
|
||||
}
|
||||
|
||||
Box message_box {
|
||||
orientation: vertical;
|
||||
|
||||
|
||||
Box content {
|
||||
orientation: vertical;
|
||||
|
||||
}
|
||||
|
||||
Box {
|
||||
vexpand: true;
|
||||
hexpand: true;
|
||||
valign: end;
|
||||
|
||||
Label model {
|
||||
styles [
|
||||
"dim-label",
|
||||
"caption",
|
||||
"timestamp",
|
||||
]
|
||||
|
||||
justify: left;
|
||||
vexpand: true;
|
||||
hexpand: true;
|
||||
halign: start;
|
||||
}
|
||||
|
||||
// Timestamp label
|
||||
Label timestamp {
|
||||
styles [
|
||||
"dim-label",
|
||||
"caption",
|
||||
"timestamp",
|
||||
]
|
||||
|
||||
justify: right;
|
||||
vexpand: true;
|
||||
hexpand: true;
|
||||
halign: end;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
PopoverMenu popover {
|
||||
menu-model: popover-model;
|
||||
}
|
||||
|
||||
menu popover-model {
|
||||
section {
|
||||
item {
|
||||
label: _("Edit");
|
||||
action: "event.edit";
|
||||
}
|
||||
}
|
||||
section {
|
||||
item {
|
||||
label: _("Remove");
|
||||
action: "event.delete";
|
||||
}
|
||||
}
|
||||
}
|
322
src/widgets/item.py
Normal file
|
@ -0,0 +1,322 @@
|
|||
from gi.repository import Gtk, Adw, Gio, GLib, Pango, GtkSource
|
||||
|
||||
import re
|
||||
|
||||
from bavarder.constants import app_id, rootdir
|
||||
from bavarder.widgets.code_block import CodeBlock
|
||||
|
||||
|
||||
H1="H1"
|
||||
H2="H2"
|
||||
H3="H3"
|
||||
UL="BULLET"
|
||||
OL="LIST"
|
||||
CODE="CODE"
|
||||
BOLD="BOLD"
|
||||
EMPH="EMPH"
|
||||
PRE="PRE"
|
||||
LINK="LINK"
|
||||
m2p_sections = [
|
||||
{ "name": H1, "re": re.compile(r"^(#\s+)(.*)(\s*)$"), "sub": r"<big><big><big>\2</big></big></big>" },
|
||||
{ "name": H2, "re": re.compile(r"^(##\s+)(.*)(\s*)$"), "sub": r"<big><big>\2</big></big>" },
|
||||
{ "name": H3, "re": re.compile(r"^(###\s+)(.*)(\s*)$"), "sub": r"<big>\2</big>" },
|
||||
{ "name": UL, "re": re.compile(r"^(\s*[\*\-]\s)(.*)(\s*)$"), "sub": r" • \2" },
|
||||
{ "name": OL, "re": re.compile(r"^(\s*[0-9]+\.\s)(.*)(\s*)$"), "sub": r" \1\2" },
|
||||
{ "name": CODE, "re": re.compile(r"^```[a-z_]*$"), "sub": "<tt>" },
|
||||
]
|
||||
|
||||
m2p_styles = [
|
||||
{ "name": BOLD, "re": re.compile(r"(^|[^\*])(\*\*)(.*)(\*\*)"), "sub": r"\1<b>\3</b>" },
|
||||
{ "name": BOLD, "re": re.compile(r"(\*\*)(.*)(\*\*)([^\*]|$)"), "sub": r"<b>\3</b>\4" },
|
||||
{ "name": EMPH, "re": re.compile(r"(^|[^\*])(\*)(.*)(\*)"), "sub": r"\1<i>\3</i>" },
|
||||
{ "name": EMPH, "re": re.compile(r"(\*)(.*)(\*)([^\*]|$)"), "sub": r"<i>\3</i>\4" },
|
||||
{ "name": PRE, "re": re.compile(r"(`)([^`]*)(`)"), "sub": r"<tt>\2</tt>" },
|
||||
{ "name": LINK, "re": re.compile(r"(!)?(\[)(.*)(\]\()(.+)(\))"), "sub": r"<a href='\5'>\3</a>" },
|
||||
{ "name": LINK, "re": re.compile(r"(!)?(\[)(.*)(\]\(\))"), "sub": r"<a href='\3'>\3</a>" },
|
||||
]
|
||||
|
||||
re_comment = re.compile(r"^\s*<!--.*-->\s*$")
|
||||
re_color = re.compile(r"^(\s*<!--\s*(fg|bg)=(#?[0-9a-z_A-Z-]*)\s*((fg|bg)=(#?[0-9a-z_A-Z-]*))?\s*-->\s*)$")
|
||||
re_reset = re.compile(r"(<!--\/-->)")
|
||||
re_uri = re.compile(r"http[s]?:\/\/[^\s']*")
|
||||
re_href = re.compile(r"href='(http[s]?:\\/\\/[^\\s]*)'")
|
||||
re_atag = re.compile(r"<a\s.*>.*(http[s]?:\\/\\/[^\\s]*).*</a>")
|
||||
re_h1line = re.compile(r"^===+\s*$")
|
||||
re_h2line = re.compile(r"^---+\s*$")
|
||||
|
||||
m2p_escapes = [
|
||||
[re.compile(r"<!--.*-->"), ''],
|
||||
[re.compile(r"&"), '&'],
|
||||
[re.compile(r"<"), '<'],
|
||||
[re.compile(r">"), '>'],
|
||||
]
|
||||
|
||||
|
||||
@Gtk.Template(resource_path=f"{rootdir}/ui/item.ui")
|
||||
class Item(Gtk.Box):
|
||||
__gtype_name__ = "Item"
|
||||
|
||||
user = Gtk.Template.Child()
|
||||
content = Gtk.Template.Child()
|
||||
timestamp = Gtk.Template.Child()
|
||||
popover = Gtk.Template.Child()
|
||||
avatar = Gtk.Template.Child()
|
||||
message_bubble = Gtk.Template.Child()
|
||||
model = Gtk.Template.Child()
|
||||
|
||||
def __init__(self, parent, chat, item, **kwargs):
|
||||
super().__init__(**kwargs)
|
||||
|
||||
self.chat = chat
|
||||
self.item = item
|
||||
|
||||
self.content_text = self.item["content"]
|
||||
|
||||
self.convert_content_to_pango()
|
||||
|
||||
result = ""
|
||||
for line in self.content_markup:
|
||||
if isinstance(line, str):
|
||||
result += f"{line}\n"
|
||||
else: # code
|
||||
label = Gtk.Label()
|
||||
label.set_use_markup(True)
|
||||
label.set_wrap(True)
|
||||
label.set_xalign(0)
|
||||
label.set_wrap_mode(Pango.WrapMode.WORD)
|
||||
label.set_markup(result)
|
||||
label.set_justify(Gtk.Justification.LEFT)
|
||||
label.set_valign(Gtk.Align.START)
|
||||
label.set_hexpand(True)
|
||||
label.set_halign(Gtk.Align.START)
|
||||
self.content.append(label)
|
||||
|
||||
result = "\n".join(line)
|
||||
|
||||
self.content.append(CodeBlock(result))
|
||||
result = ""
|
||||
else:
|
||||
if not result.strip() == "<tt></tt>`":
|
||||
label = Gtk.Label()
|
||||
label.set_use_markup(True)
|
||||
label.set_wrap(True)
|
||||
label.set_xalign(0)
|
||||
label.set_wrap_mode(Pango.WrapMode.WORD)
|
||||
label.set_markup(result)
|
||||
label.set_justify(Gtk.Justification.LEFT)
|
||||
label.set_valign(Gtk.Align.START)
|
||||
label.set_hexpand(True)
|
||||
label.set_halign(Gtk.Align.START)
|
||||
self.content.append(label)
|
||||
|
||||
t = self.item["role"].capitalize()
|
||||
|
||||
if t == "User":
|
||||
self.message_bubble.add_css_class("message-bubble-user")
|
||||
self.avatar.add_css_class("avatar-user")
|
||||
role = _("User")
|
||||
elif t == "Assistant":
|
||||
self.avatar.set_icon_name("bot-symbolic")
|
||||
self.user.add_css_class("warning")
|
||||
role = _("Assistant")
|
||||
else:
|
||||
role = t
|
||||
|
||||
self.timestamp.set_text(self.item.get("time", ""))
|
||||
self.model.set_text(self.item.get("model", ""))
|
||||
|
||||
self.avatar.set_text(role)
|
||||
self.user.set_text(role)
|
||||
|
||||
self.parent = parent
|
||||
self.settings = parent.settings
|
||||
|
||||
self.app = self.parent.get_application()
|
||||
self.win = self.app.get_active_window()
|
||||
|
||||
self.setup()
|
||||
|
||||
def setup(self):
|
||||
self.setup_signals()
|
||||
|
||||
evk = Gtk.GestureClick.new()
|
||||
evk.connect("pressed", self.show_menu)
|
||||
evk.set_button(3)
|
||||
self.add_controller(evk)
|
||||
|
||||
def show_menu(self, gesture, data, x, y):
|
||||
self.popover.set_parent(self)
|
||||
self.popover.popup()
|
||||
|
||||
def setup_signals(self):
|
||||
self.action_group = Gio.SimpleActionGroup()
|
||||
self.create_action("delete", self.on_delete)
|
||||
self.create_action("edit", self.on_edit)
|
||||
self.insert_action_group("event", self.action_group);
|
||||
|
||||
def create_action(self, name, callback, shortcuts=None):
|
||||
action = Gio.SimpleAction.new(name, None)
|
||||
action.connect("activate", callback)
|
||||
self.action_group.add_action(action)
|
||||
|
||||
if shortcuts:
|
||||
self.set_accels_for_action(f"app.{name}", shortcuts)
|
||||
|
||||
def on_delete(self, *args, **kwargs):
|
||||
self.chat["content"].remove(self.item)
|
||||
self.win.threads_row_activated_cb()
|
||||
|
||||
def on_edit(self, *args):
|
||||
self.win.message_entry.get_buffer().set_text(self.item["content"])
|
||||
|
||||
def convert_content_to_pango(self):
|
||||
lines = self.content_text.split("\n")
|
||||
|
||||
is_code = False
|
||||
code_lines = []
|
||||
|
||||
output = []
|
||||
self.color_span_open = False
|
||||
tt_must_close = False
|
||||
|
||||
def try_close_span():
|
||||
if self.color_span_open:
|
||||
output.append('</span>')
|
||||
self.color_span_open = False
|
||||
|
||||
def try_open_span():
|
||||
if not self.color_span_open:
|
||||
output.append('</span>')
|
||||
self.color_span_open = False
|
||||
|
||||
def escape_line(line):
|
||||
for escape in m2p_escapes:
|
||||
line = re.sub(escape[0], escape[1], line)
|
||||
return line
|
||||
|
||||
# def pad(lines, start=1, end=1):
|
||||
# length = 0
|
||||
# for line in lines:
|
||||
# if len(line) > 0:
|
||||
# length += len(line)
|
||||
# else:
|
||||
# length += 0
|
||||
# for line in lines:
|
||||
# line.rjust()
|
||||
# return lines.map((l) => l.padEnd(len + end, ' ').padStart(len + end + start, ' '))
|
||||
|
||||
|
||||
for line in lines:
|
||||
if not is_code:
|
||||
colors = re_color.match(line)
|
||||
if colors or re_reset.match(line):
|
||||
try_close_span()
|
||||
|
||||
|
||||
if colors:
|
||||
try_close_span()
|
||||
if self.color_span_open:
|
||||
try_close_span()
|
||||
|
||||
if colors[2] == 'fg':
|
||||
fg = colors[3]
|
||||
elif colors[5] == 'fg':
|
||||
fg = colors[6]
|
||||
else:
|
||||
fg = ""
|
||||
|
||||
if colors[2] == 'bg':
|
||||
fg = colors[3]
|
||||
elif colors[5] == 'bg':
|
||||
fg = colors[6]
|
||||
else:
|
||||
fg = ""
|
||||
|
||||
attrs = ''
|
||||
|
||||
if fg != '':
|
||||
attrs += f" foreground='{fg}'"
|
||||
|
||||
|
||||
if bg != '':
|
||||
attrs += f" background='{bg}'"
|
||||
|
||||
if attrs != '':
|
||||
output.append("<span {attrs}>")
|
||||
self.color_span_open = True
|
||||
|
||||
if re_comment.match(line):
|
||||
continue
|
||||
|
||||
code_start = False
|
||||
|
||||
if is_code:
|
||||
result = line
|
||||
else:
|
||||
result = escape_line(line)
|
||||
|
||||
for exp in m2p_sections:
|
||||
name = exp["name"]
|
||||
regexp = exp["re"]
|
||||
sub = exp["sub"]
|
||||
if regexp.match(line):
|
||||
if name == CODE:
|
||||
if not is_code:
|
||||
code_start = True
|
||||
is_code = True
|
||||
|
||||
result = ""
|
||||
|
||||
#if self.color_span_open:
|
||||
# result = '<tt>'
|
||||
# tt_must_close = False
|
||||
#else:
|
||||
# result = "<span foreground='#bbb' background='#222'>" + '<tt>'
|
||||
# tt_must_close = True
|
||||
else:
|
||||
is_code = False
|
||||
#output.append(...pad(code_lines).map(escape_line))
|
||||
output.append(code_lines)
|
||||
code_lines = []
|
||||
#result = '</tt>'
|
||||
if tt_must_close:
|
||||
result += '</span>'
|
||||
tt_must_close = False
|
||||
else:
|
||||
if is_code:
|
||||
result = line
|
||||
else:
|
||||
result = re.sub(regexp, sub, line)
|
||||
|
||||
if is_code and not code_start:
|
||||
code_lines.append(result)
|
||||
continue
|
||||
|
||||
|
||||
if re_h1line.match(line):
|
||||
output.append(re.sub(m2p_sections[0]["re"], m2p_sections[0]["sub"], f"# {output.pop()}"))
|
||||
continue
|
||||
|
||||
|
||||
if re_h2line.match(line):
|
||||
output.append(re.sub(m2p_sections[1]["re"], m2p_sections[1]["sub"], f"# {output.pop()}"))
|
||||
continue
|
||||
|
||||
for style in m2p_styles:
|
||||
regexp = style["re"]
|
||||
sub = style["sub"]
|
||||
result = re.sub(regexp, sub, result)
|
||||
|
||||
|
||||
uri = re_uri.match(result) # look for any URI
|
||||
href = re_href.match(result) # and for URIs in href=''
|
||||
atag = re_atag.match(result) # and for URIs in <a></a>
|
||||
|
||||
if uri and (href or atag):
|
||||
result = result.replace(uri, f"<a href='{uri}'>{uri}</a>")
|
||||
|
||||
output.append(result)
|
||||
|
||||
try_close_span()
|
||||
|
||||
self.content_markup = output
|
|
@ -1,9 +1,12 @@
|
|||
|
||||
widgets_dir = join_paths(moduledir, 'widgets')
|
||||
widgets_dir = join_paths(MODULE_DIR, 'widgets')
|
||||
|
||||
widgets_sources = [
|
||||
'__init__.py',
|
||||
'message_bubble.py',
|
||||
'code_block.py',
|
||||
'item.py',
|
||||
'thread_item.py',
|
||||
'download_row.py',
|
||||
'model_item.py',
|
||||
]
|
||||
|
||||
PY_INSTALLDIR.install_sources(widgets_sources, subdir: widgets_dir)
|
||||
PY_INSTALLDIR.install_sources(widgets_sources, subdir: widgets_dir)
|
|
@ -1,59 +0,0 @@
|
|||
from gi.repository import Adw, Gtk, Gio
|
||||
|
||||
from bavarder.constants import app_id, build_type
|
||||
|
||||
MAX_WIDTH = 400
|
||||
|
||||
@Gtk.Template(resource_path="/io/github/Bavarder/Bavarder/ui/message_bubble.ui")
|
||||
class MessageBubble(Gtk.Box):
|
||||
__gtype_name__ = "MessageBubble"
|
||||
|
||||
sender_label = Gtk.Template.Child()
|
||||
message_reply_bin = Gtk.Template.Child()
|
||||
prefix_bin = Gtk.Template.Child()
|
||||
message_label = Gtk.Template.Child()
|
||||
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
super().__init__(**kwargs)
|
||||
|
||||
self.app = Gtk.Application.get_default()
|
||||
|
||||
|
||||
# def measure(self, orientation, , for_size):
|
||||
# # Limit the widget width
|
||||
# if orientation == Gtk.Orientation.HORIZONTAL:
|
||||
# minimum, natural, minimum_baseline, natural_baseline = \
|
||||
# self.overlay.measure(orientation, for_size)
|
||||
|
||||
# return (
|
||||
# minimum.min(MAX_WIDTH),
|
||||
# natural.min(MAX_WIDTH),
|
||||
# minimum_baseline,
|
||||
# natural_baseline,
|
||||
# )
|
||||
# else:
|
||||
# adjusted_for_size = for_size.min(MAX_WIDTH);
|
||||
# self.overlay.measure(orientation, adjusted_for_size)
|
||||
#
|
||||
#
|
||||
|
||||
# def size_allocate(self, width, height, baseline):
|
||||
# self.overlay.allocate(width, height, baseline, None)
|
||||
#
|
||||
|
||||
# def request_mode(self):
|
||||
# return Gtk.SizeRequestMode.HEIGHT_FOR_WIDTH
|
||||
|
||||
def set_label(self, label):
|
||||
if label.is_empty():
|
||||
self.message_label.set_label("")
|
||||
self..message_label.set_visible(false)
|
||||
|
||||
self.remove_css_class("with-label")
|
||||
else:
|
||||
self.message_label.set_label(label)
|
||||
self.message_label.set_visible(true)
|
||||
|
||||
self.add_css_class("with-label")
|
||||
|
11
src/widgets/model_item.blp
Normal file
|
@ -0,0 +1,11 @@
|
|||
using Gtk 4.0;
|
||||
using Adw 1;
|
||||
|
||||
template $Model : Adw.ActionRow {
|
||||
[suffix]
|
||||
Button delete_button {
|
||||
valign: center;
|
||||
icon-name: "user-trash-symbolic";
|
||||
clicked => $on_delete_button_clicked();
|
||||
}
|
||||
}
|
32
src/widgets/model_item.py
Normal file
|
@ -0,0 +1,32 @@
|
|||
import unicodedata
|
||||
import re
|
||||
from typing import List, Dict
|
||||
from gi.repository import Gtk, Adw, GLib
|
||||
|
||||
from bavarder.constants import app_id, rootdir
|
||||
|
||||
|
||||
@Gtk.Template(resource_path=f"{rootdir}/ui/model_item.ui")
|
||||
class Model(Adw.ActionRow):
|
||||
__gtype_name__ = "Model"
|
||||
|
||||
def __init__(self, app, window, model, **kwargs):
|
||||
super().__init__(**kwargs)
|
||||
self.app = app
|
||||
self.window = window
|
||||
self.model = model
|
||||
|
||||
self.setup()
|
||||
|
||||
def setup(self):
|
||||
self.set_title(self.model)
|
||||
self.app.win.load_model_selector()
|
||||
|
||||
@Gtk.Template.Callback()
|
||||
def on_delete_button_clicked(self, widget, *args):
|
||||
self.app.delete_model(self.model)
|
||||
self.window.load_models()
|
||||
|
||||
toast = Adw.Toast()
|
||||
toast.set_title(_("Model %s deleted!" % self.model) )
|
||||
self.window.add_toast(toast)
|
46
src/widgets/thread_item.blp
Normal file
|
@ -0,0 +1,46 @@
|
|||
using Gtk 4.0;
|
||||
using Adw 1;
|
||||
|
||||
template $ThreadItem : Box {
|
||||
orientation: horizontal;
|
||||
styles ["flat"]
|
||||
|
||||
Stack value-stack {
|
||||
styles ["flat"]
|
||||
valign: center;
|
||||
hhomogeneous: false;
|
||||
interpolate-size: true;
|
||||
transition-type: crossfade;
|
||||
|
||||
Gtk.Inscription label {
|
||||
hexpand: true;
|
||||
xalign: 0;
|
||||
text-overflow: ellipsize_end;
|
||||
}
|
||||
|
||||
Entry text-value {
|
||||
styles ["flat"]
|
||||
}
|
||||
}
|
||||
|
||||
ToggleButton text-value-toggle {
|
||||
valign: center;
|
||||
icon-name: "document-edit-symbolic";
|
||||
tooltip-text: _("Edit Title");
|
||||
styles ["flat"]
|
||||
|
||||
toggled => $on_text_value_toggled();
|
||||
}
|
||||
|
||||
Button delete_button {
|
||||
styles ["flat"]
|
||||
icon-name: "user-trash-symbolic";
|
||||
clicked => $on_delete_button_clicked();
|
||||
}
|
||||
|
||||
Button star_button {
|
||||
styles ["flat"]
|
||||
icon-name: "non-starred-symbolic"; // starred-symbolic
|
||||
clicked => $on_star_button_clicked();
|
||||
}
|
||||
}
|
81
src/widgets/thread_item.py
Normal file
|
@ -0,0 +1,81 @@
|
|||
from gi.repository import Gtk, Adw, Gio, GLib
|
||||
|
||||
from bavarder.constants import app_id, rootdir
|
||||
|
||||
@Gtk.Template(resource_path=f"{rootdir}/ui/thread_item.ui")
|
||||
class ThreadItem(Gtk.Box):
|
||||
__gtype_name__ = "ThreadItem"
|
||||
|
||||
label = Gtk.Template.Child()
|
||||
text_value = Gtk.Template.Child("text-value")
|
||||
value_stack = Gtk.Template.Child("value-stack")
|
||||
text_value_toggle = Gtk.Template.Child("text-value-toggle")
|
||||
star_button = Gtk.Template.Child()
|
||||
|
||||
def __init__(self, parent, chat, **kwargs):
|
||||
super().__init__(**kwargs)
|
||||
|
||||
self.chat = chat
|
||||
self.id = chat["id"]
|
||||
self.label_text = chat["title"]
|
||||
self.is_starred = chat.get("starred", False)
|
||||
|
||||
self.label.set_text(self.label_text)
|
||||
|
||||
self.parent = parent
|
||||
self.settings = parent.settings
|
||||
|
||||
self.app = self.parent.get_application()
|
||||
self.win = self.app.get_active_window()
|
||||
|
||||
self.setup()
|
||||
|
||||
def setup(self):
|
||||
self.setup_signals()
|
||||
self.update_star()
|
||||
|
||||
def setup_signals(self):
|
||||
pass
|
||||
|
||||
@Gtk.Template.Callback()
|
||||
def on_text_value_toggled(self, *args):
|
||||
if self.text_value_toggle.get_active():
|
||||
self.text_value_toggle.set_icon_name("check-round-outline-symbolic")
|
||||
self.text_value.set_text(self.label_text)
|
||||
widget = self.text_value
|
||||
tooltip = _("Set Title")
|
||||
else:
|
||||
self.text_value_toggle.set_icon_name("document-edit-symbolic")
|
||||
self.label_text = self.text_value.get_text()
|
||||
self.chat["title"] = self.label_text
|
||||
self.text_value.set_text(self.label_text)
|
||||
self.win.title.set_title(self.label_text)
|
||||
|
||||
tooltip = _("Edit Title")
|
||||
widget = self.label
|
||||
|
||||
self.value_stack.set_visible_child(widget)
|
||||
self.text_value_toggle.set_tooltip_text(tooltip)
|
||||
self.label.set_text(self.label_text)
|
||||
|
||||
@Gtk.Template.Callback()
|
||||
def on_star_button_clicked(self, *args):
|
||||
self.is_starred = not self.is_starred
|
||||
self.update_star()
|
||||
|
||||
def update_star(self):
|
||||
self.chat["starred"] = self.is_starred
|
||||
if self.is_starred:
|
||||
self.star_button.set_icon_name("starred-symbolic")
|
||||
self.label.set_css_classes(["accent"])
|
||||
else:
|
||||
self.star_button.set_icon_name("non-starred-symbolic")
|
||||
self.label.set_css_classes([])
|
||||
|
||||
@Gtk.Template.Callback()
|
||||
def on_delete_button_clicked(self, *args):
|
||||
self.app.data["chats"].remove(self.chat)
|
||||
self.win.load_threads()
|
||||
|
||||
|
||||
|