Compare commits

...

10 Commits

Author SHA1 Message Date
Slavi Pantaleev
bbc122fbb1 Release 1.14.3
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-18 06:37:11 +02:00
renovate[bot]
2413c8b88b Update actions/checkout action to v6 2026-02-18 06:31:39 +02:00
renovate[bot]
10c3c64469 Update Rust crate async-openai to 0.33.0 2026-02-18 06:25:58 +02:00
renovate[bot]
b3307b404b Update docker.io/rust Docker tag to v1.93.1 2026-02-18 06:25:48 +02:00
Slavi Pantaleev
7a0d1e830d Add Renovate configuration for automated dependency updates
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-18 06:06:02 +02:00
Slavi Pantaleev
b3bd241823 Release 1.14.2
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-18 05:53:46 +02:00
Slavi Pantaleev
de3d8b054f Update dependencies 2026-02-18 05:44:41 +02:00
Slavi Pantaleev
0a55e276a2 Update dependencies 2026-02-18 05:40:25 +02:00
Slavi Pantaleev
1f2c65d2e6 Refactor dev services to support homeserver choice (Continuwuity or Synapse)
The dev environment previously hardcoded Synapse (bundled with Postgres
and Element Web) in a monolithic etc/services/core/ directory.

With Continuwuity now available as a lighter alternative (no external DB),
this refactors the service layout so developers choose their homeserver
once and everything derives from that choice. Continuwuity is the new
default for its smaller footprint.

Key changes:
- Break etc/services/core/ into etc/services/synapse/ and
  etc/services/element-web/, each with their own compose.yml
- Add `homeserver` variable in justfile (reads var/homeserver,
  defaults to continuwuity)
- Add `homeserver-init` recipe to persist the choice
- Use placeholders (__HOMESERVER_SERVER_NAME__, __HOMESERVER_URL__,
  __HOMESERVER_CLIENT_URL__) in config templates, resolved at
  prepare time based on the chosen homeserver
- Make services-start/stop/prepare/tail-logs delegate to the chosen
  homeserver's recipes + element-web
- Make users-prepare delegate to {homeserver}-users-prepare
- Update docs/development.md for the new homeserver choice flow

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-18 05:28:32 +02:00
Slavi Pantaleev
3b5e4745f2 Add optional Continuwuity homeserver service for development/testing
Adds Continuwuity as an alternative to Synapse for local development,
useful for testing baibot compatibility with different homeserver
implementations. Follows the same optional service pattern as localai/ollama.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-18 04:47:22 +02:00
21 changed files with 452 additions and 182 deletions

View File

@@ -16,7 +16,7 @@ jobs:
name: Unit testing and linting name: Unit testing and linting
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v6
- uses: dtolnay/rust-toolchain@stable - uses: dtolnay/rust-toolchain@stable
- name: Install SQLite3 - name: Install SQLite3
run: sudo apt-get update && sudo apt-get install -y libsqlite3-dev run: sudo apt-get update && sudo apt-get install -y libsqlite3-dev
@@ -56,7 +56,7 @@ jobs:
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v4 uses: actions/checkout@v6
- name: Log in to the GitHub Container registry - name: Log in to the GitHub Container registry
uses: docker/login-action@v3 uses: docker/login-action@v3
with: with:

View File

@@ -1,3 +1,17 @@
# (2026-02-18) Version 1.14.3
- (**Internal Improvement**) Add [Renovate](https://docs.renovatebot.com/) configuration for automated dependency updates
- (**Internal Improvement**) Dependency updates
# (2026-02-18) Version 1.14.2
- (**Internal Improvement**) Dependency updates
- (**Internal Improvement**) Reorganize the development environment to support [Continuwuity](https://continuwuity.org/) as a homeserver choice (in addition to [Synapse](https://github.com/element-hq/synapse)). Continuwuity is now the default for its lighter footprint (no external database required). See [development docs](./docs/development.md) for details.
# (2026-02-10) Version 1.14.1 # (2026-02-10) Version 1.14.1
- (**Security**) Dependency updates to fix security vulnerabilities ([time](https://crates.io/crates/time) stack exhaustion DoS, [bytes](https://crates.io/crates/bytes) integer overflow), via [mxlink](https://crates.io/crates/mxlink) 1.12.0 - (**Security**) Dependency updates to fix security vulnerabilities ([time](https://crates.io/crates/time) stack exhaustion DoS, [bytes](https://crates.io/crates/bytes) integer overflow), via [mxlink](https://crates.io/crates/mxlink) 1.12.0

213
Cargo.lock generated
View File

@@ -11,7 +11,7 @@ dependencies = [
"macroific", "macroific",
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.114", "syn 2.0.116",
] ]
[[package]] [[package]]
@@ -116,7 +116,7 @@ dependencies = [
"proc-macro-error2", "proc-macro-error2",
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.114", "syn 2.0.116",
] ]
[[package]] [[package]]
@@ -178,9 +178,9 @@ dependencies = [
[[package]] [[package]]
name = "async-openai" name = "async-openai"
version = "0.32.4" version = "0.33.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f4d91c2005832450ad9ac92411b9d4cec39e30be21adc76553efc47f812d59c7" checksum = "b3ef6d66e53b3ec8ed4bae8e6dcdda75c0f5b4f67faba78fac1b09434cb4f2fc"
dependencies = [ dependencies = [
"async-openai-macros", "async-openai-macros",
"backoff", "backoff",
@@ -213,7 +213,7 @@ checksum = "81872a8e595e8ceceab71c6ba1f9078e313b452a1e31934e6763ef5d308705e4"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.114", "syn 2.0.116",
] ]
[[package]] [[package]]
@@ -235,7 +235,7 @@ checksum = "c7c24de15d275a1ecfd47a380fb4d5ec9bfe0933f309ed5e705b775596a3574d"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.114", "syn 2.0.116",
] ]
[[package]] [[package]]
@@ -246,7 +246,7 @@ checksum = "9035ad2d096bed7955a320ee7e2230574d28fd3c3a0f186cbea1ff3c7eed5dbb"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.114", "syn 2.0.116",
] ]
[[package]] [[package]]
@@ -288,7 +288,7 @@ dependencies = [
[[package]] [[package]]
name = "baibot" name = "baibot"
version = "1.14.1" version = "1.14.3"
dependencies = [ dependencies = [
"anthropic", "anthropic",
"anyhow", "anyhow",
@@ -360,9 +360,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]] [[package]]
name = "bitflags" name = "bitflags"
version = "2.10.0" version = "2.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "812e12b5285cc515a9c72a5c1d3b6d46a19dac5acfef5265968c166106e31dd3" checksum = "843867be96c8daad0d758b57df9392b6d8d271134fce549de6ce169ff98a92af"
dependencies = [ dependencies = [
"serde_core", "serde_core",
] ]
@@ -460,9 +460,9 @@ dependencies = [
[[package]] [[package]]
name = "cc" name = "cc"
version = "1.2.55" version = "1.2.56"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "47b26a0954ae34af09b50f0de26458fa95369a0d478d8236d3f93082b219bd29" checksum = "aebf35691d1bfb0ac386a69bac2fde4dd276fb618cf8bf4f5318fe285e821bb2"
dependencies = [ dependencies = [
"find-msvc-tools", "find-msvc-tools",
"shlex", "shlex",
@@ -705,7 +705,7 @@ checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.114", "syn 2.0.116",
] ]
[[package]] [[package]]
@@ -753,7 +753,7 @@ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"strsim 0.11.1", "strsim 0.11.1",
"syn 2.0.114", "syn 2.0.116",
] ]
[[package]] [[package]]
@@ -775,7 +775,7 @@ checksum = "fc34b93ccb385b40dc71c6fceac4b2ad23662c7eeb248cf10d529b7e055b6ead"
dependencies = [ dependencies = [
"darling_core 0.20.11", "darling_core 0.20.11",
"quote", "quote",
"syn 2.0.114", "syn 2.0.116",
] ]
[[package]] [[package]]
@@ -835,7 +835,7 @@ dependencies = [
"macroific", "macroific",
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.114", "syn 2.0.116",
] ]
[[package]] [[package]]
@@ -850,9 +850,9 @@ dependencies = [
[[package]] [[package]]
name = "deranged" name = "deranged"
version = "0.5.5" version = "0.5.6"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ececcb659e7ba858fb4f10388c250a7252eb0a27373f1a72b8748afdd248e587" checksum = "cc3dc5ad92c2e2d1c193bbbbdf2ea477cb81331de4f3103f267ca18368b988c4"
dependencies = [ dependencies = [
"powerfmt", "powerfmt",
] ]
@@ -907,7 +907,7 @@ dependencies = [
"darling 0.20.11", "darling 0.20.11",
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.114", "syn 2.0.116",
] ]
[[package]] [[package]]
@@ -927,7 +927,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ab63b0e2bf4d5928aff72e83a7dace85d7bba5fe12dcc3c5a572d78caffd3f3c" checksum = "ab63b0e2bf4d5928aff72e83a7dace85d7bba5fe12dcc3c5a572d78caffd3f3c"
dependencies = [ dependencies = [
"derive_builder_core 0.20.2", "derive_builder_core 0.20.2",
"syn 2.0.114", "syn 2.0.116",
] ]
[[package]] [[package]]
@@ -956,7 +956,7 @@ checksum = "cb7330aeadfbe296029522e6c40f315320aba36fc43a5b3632f3795348f3bd22"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.114", "syn 2.0.116",
] ]
[[package]] [[package]]
@@ -968,7 +968,7 @@ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"rustc_version", "rustc_version",
"syn 2.0.114", "syn 2.0.116",
"unicode-xid", "unicode-xid",
] ]
@@ -991,7 +991,7 @@ checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.114", "syn 2.0.116",
] ]
[[package]] [[package]]
@@ -1155,7 +1155,7 @@ dependencies = [
"macroific", "macroific",
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.114", "syn 2.0.116",
] ]
[[package]] [[package]]
@@ -1234,9 +1234,9 @@ dependencies = [
[[package]] [[package]]
name = "futures" name = "futures"
version = "0.3.31" version = "0.3.32"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876" checksum = "8b147ee9d1f6d097cef9ce628cd2ee62288d963e16fb287bd9286455b241382d"
dependencies = [ dependencies = [
"futures-channel", "futures-channel",
"futures-core", "futures-core",
@@ -1249,9 +1249,9 @@ dependencies = [
[[package]] [[package]]
name = "futures-channel" name = "futures-channel"
version = "0.3.31" version = "0.3.32"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" checksum = "07bbe89c50d7a535e539b8c17bc0b49bdb77747034daa8087407d655f3f7cc1d"
dependencies = [ dependencies = [
"futures-core", "futures-core",
"futures-sink", "futures-sink",
@@ -1259,15 +1259,15 @@ dependencies = [
[[package]] [[package]]
name = "futures-core" name = "futures-core"
version = "0.3.31" version = "0.3.32"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" checksum = "7e3450815272ef58cec6d564423f6e755e25379b217b0bc688e295ba24df6b1d"
[[package]] [[package]]
name = "futures-executor" name = "futures-executor"
version = "0.3.31" version = "0.3.32"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e28d1d997f585e54aebc3f97d39e72338912123a67330d723fdbb564d646c9f" checksum = "baf29c38818342a3b26b5b923639e7b1f4a61fc5e76102d4b1981c6dc7a7579d"
dependencies = [ dependencies = [
"futures-core", "futures-core",
"futures-task", "futures-task",
@@ -1276,32 +1276,32 @@ dependencies = [
[[package]] [[package]]
name = "futures-io" name = "futures-io"
version = "0.3.31" version = "0.3.32"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" checksum = "cecba35d7ad927e23624b22ad55235f2239cfa44fd10428eecbeba6d6a717718"
[[package]] [[package]]
name = "futures-macro" name = "futures-macro"
version = "0.3.31" version = "0.3.32"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" checksum = "e835b70203e41293343137df5c0664546da5745f82ec9b84d40be8336958447b"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.114", "syn 2.0.116",
] ]
[[package]] [[package]]
name = "futures-sink" name = "futures-sink"
version = "0.3.31" version = "0.3.32"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" checksum = "c39754e157331b013978ec91992bde1ac089843443c49cbc7f46150b0fad0893"
[[package]] [[package]]
name = "futures-task" name = "futures-task"
version = "0.3.31" version = "0.3.32"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" checksum = "037711b3d59c33004d3856fbdc83b99d4ff37a24768fa1be9ce3538a1cde4393"
[[package]] [[package]]
name = "futures-timer" name = "futures-timer"
@@ -1311,9 +1311,9 @@ checksum = "f288b0a4f20f9a56b5d1da57e2227c661b7b16168e2f72365f57b63326e29b24"
[[package]] [[package]]
name = "futures-util" name = "futures-util"
version = "0.3.31" version = "0.3.32"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" checksum = "389ca41296e6190b48053de0321d02a77f32f8a5d2461dd38762c0593805c6d6"
dependencies = [ dependencies = [
"futures-channel", "futures-channel",
"futures-core", "futures-core",
@@ -1323,7 +1323,6 @@ dependencies = [
"futures-task", "futures-task",
"memchr", "memchr",
"pin-project-lite", "pin-project-lite",
"pin-utils",
"slab", "slab",
] ]
@@ -1910,7 +1909,7 @@ checksum = "0ab604ee7085efba6efc65e4ebca0e9533e3aff6cb501d7d77b211e3a781c6d5"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.114", "syn 2.0.116",
] ]
[[package]] [[package]]
@@ -2071,9 +2070,9 @@ checksum = "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2"
[[package]] [[package]]
name = "libc" name = "libc"
version = "0.2.181" version = "0.2.182"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "459427e2af2b9c839b132acb702a1c654d95e10f8c326bfc2ad11310e458b1c5" checksum = "6800badb6cb2082ffd7b6a67e6125bb39f18782f793520caee8cb8846be06112"
[[package]] [[package]]
name = "libsqlite3-sys" name = "libsqlite3-sys"
@@ -2144,7 +2143,7 @@ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"sealed", "sealed",
"syn 2.0.114", "syn 2.0.116",
] ]
[[package]] [[package]]
@@ -2156,7 +2155,7 @@ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"sealed", "sealed",
"syn 2.0.114", "syn 2.0.116",
] ]
[[package]] [[package]]
@@ -2169,7 +2168,7 @@ dependencies = [
"macroific_core", "macroific_core",
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.114", "syn 2.0.116",
] ]
[[package]] [[package]]
@@ -2197,7 +2196,7 @@ checksum = "ac84fd3f360fcc43dc5f5d186f02a94192761a080e8bc58621ad4d12296a58cf"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.114", "syn 2.0.116",
] ]
[[package]] [[package]]
@@ -2229,7 +2228,7 @@ dependencies = [
"proc-macro-error2", "proc-macro-error2",
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.114", "syn 2.0.116",
] ]
[[package]] [[package]]
@@ -2296,7 +2295,7 @@ checksum = "70f404a390ff98a73c426b1496b169be60ce6a93723a9a664e579d978a84c5e4"
dependencies = [ dependencies = [
"as_variant", "as_variant",
"async-trait", "async-trait",
"bitflags 2.10.0", "bitflags 2.11.0",
"decancer", "decancer",
"eyeball", "eyeball",
"eyeball-im", "eyeball-im",
@@ -2498,7 +2497,7 @@ dependencies = [
"macroific", "macroific",
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.114", "syn 2.0.116",
] ]
[[package]] [[package]]
@@ -2587,17 +2586,17 @@ dependencies = [
[[package]] [[package]]
name = "native-tls" name = "native-tls"
version = "0.2.14" version = "0.2.16"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "87de3442987e9dbec73158d5c715e7ad9072fda936bb03d19d7fa10e00520f0e" checksum = "9d5d26952a508f321b4d3d2e80e78fc2603eaefcdf0c30783867f19586518bdc"
dependencies = [ dependencies = [
"libc", "libc",
"log", "log",
"openssl", "openssl",
"openssl-probe 0.1.6", "openssl-probe 0.2.1",
"openssl-sys", "openssl-sys",
"schannel", "schannel",
"security-framework 2.11.1", "security-framework 3.6.0",
"security-framework-sys", "security-framework-sys",
"tempfile", "tempfile",
] ]
@@ -2690,7 +2689,7 @@ version = "0.10.75"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "08838db121398ad17ab8531ce9de97b244589089e290a384c900cb9ff7434328" checksum = "08838db121398ad17ab8531ce9de97b244589089e290a384c900cb9ff7434328"
dependencies = [ dependencies = [
"bitflags 2.10.0", "bitflags 2.11.0",
"cfg-if", "cfg-if",
"foreign-types", "foreign-types",
"libc", "libc",
@@ -2707,7 +2706,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.114", "syn 2.0.116",
] ]
[[package]] [[package]]
@@ -2899,7 +2898,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b" checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"syn 2.0.114", "syn 2.0.116",
] ]
[[package]] [[package]]
@@ -2961,7 +2960,7 @@ dependencies = [
"itertools 0.14.0", "itertools 0.14.0",
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.114", "syn 2.0.116",
] ]
[[package]] [[package]]
@@ -2970,7 +2969,7 @@ version = "0.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e8bbe1a966bd2f362681a44f6edce3c2310ac21e4d5067a6e7ec396297a6ea0" checksum = "1e8bbe1a966bd2f362681a44f6edce3c2310ac21e4d5067a6e7ec396297a6ea0"
dependencies = [ dependencies = [
"bitflags 2.10.0", "bitflags 2.11.0",
"memchr", "memchr",
"pulldown-cmark-escape", "pulldown-cmark-escape",
"unicase", "unicase",
@@ -3170,7 +3169,7 @@ version = "0.5.18"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d" checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d"
dependencies = [ dependencies = [
"bitflags 2.10.0", "bitflags 2.11.0",
] ]
[[package]] [[package]]
@@ -3523,7 +3522,7 @@ dependencies = [
"quote", "quote",
"ruma-identifiers-validation", "ruma-identifiers-validation",
"serde", "serde",
"syn 2.0.114", "syn 2.0.116",
"toml", "toml",
] ]
@@ -3549,7 +3548,7 @@ version = "0.37.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "165ca6e57b20e1351573e3729b958bc62f0e48025386970b6e4d29e7a7e71f3f" checksum = "165ca6e57b20e1351573e3729b958bc62f0e48025386970b6e4d29e7a7e71f3f"
dependencies = [ dependencies = [
"bitflags 2.10.0", "bitflags 2.11.0",
"fallible-iterator", "fallible-iterator",
"fallible-streaming-iterator", "fallible-streaming-iterator",
"hashlink", "hashlink",
@@ -3584,7 +3583,7 @@ version = "1.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "146c9e247ccc180c1f61615433868c99f3de3ae256a30a43b49f67c2d9171f34" checksum = "146c9e247ccc180c1f61615433868c99f3de3ae256a30a43b49f67c2d9171f34"
dependencies = [ dependencies = [
"bitflags 2.10.0", "bitflags 2.11.0",
"errno", "errno",
"libc", "libc",
"linux-raw-sys", "linux-raw-sys",
@@ -3639,7 +3638,7 @@ dependencies = [
"openssl-probe 0.2.1", "openssl-probe 0.2.1",
"rustls-pki-types", "rustls-pki-types",
"schannel", "schannel",
"security-framework 3.5.1", "security-framework 3.6.0",
] ]
[[package]] [[package]]
@@ -3727,7 +3726,7 @@ checksum = "22f968c5ea23d555e670b449c1c5e7b2fc399fdaec1d304a17cd48e288abc107"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.114", "syn 2.0.116",
] ]
[[package]] [[package]]
@@ -3746,7 +3745,7 @@ version = "2.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02"
dependencies = [ dependencies = [
"bitflags 2.10.0", "bitflags 2.11.0",
"core-foundation 0.9.4", "core-foundation 0.9.4",
"core-foundation-sys", "core-foundation-sys",
"libc", "libc",
@@ -3755,11 +3754,11 @@ dependencies = [
[[package]] [[package]]
name = "security-framework" name = "security-framework"
version = "3.5.1" version = "3.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b3297343eaf830f66ede390ea39da1d462b6b0c1b000f420d0a83f898bbbe6ef" checksum = "d17b898a6d6948c3a8ee4372c17cb384f90d2e6e912ef00895b14fd7ab54ec38"
dependencies = [ dependencies = [
"bitflags 2.10.0", "bitflags 2.11.0",
"core-foundation 0.10.1", "core-foundation 0.10.1",
"core-foundation-sys", "core-foundation-sys",
"libc", "libc",
@@ -3768,9 +3767,9 @@ dependencies = [
[[package]] [[package]]
name = "security-framework-sys" name = "security-framework-sys"
version = "2.15.0" version = "2.16.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cc1f0cbffaac4852523ce30d8bd3c5cdc873501d96ff467ca09b6767bb8cd5c0" checksum = "321c8673b092a9a42605034a9879d73cb79101ed5fd117bc9a597b89b4e9e61a"
dependencies = [ dependencies = [
"core-foundation-sys", "core-foundation-sys",
"libc", "libc",
@@ -3830,7 +3829,7 @@ checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.114", "syn 2.0.116",
] ]
[[package]] [[package]]
@@ -4069,9 +4068,9 @@ dependencies = [
[[package]] [[package]]
name = "syn" name = "syn"
version = "2.0.114" version = "2.0.116"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d4d107df263a3013ef9b1879b0df87d706ff80f65a86ea879bd9c31f9b307c2a" checksum = "3df424c70518695237746f84cede799c9c58fcb37450d7b23716568cc8bc69cb"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
@@ -4101,7 +4100,7 @@ checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.114", "syn 2.0.116",
] ]
[[package]] [[package]]
@@ -4175,7 +4174,7 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.114", "syn 2.0.116",
] ]
[[package]] [[package]]
@@ -4186,7 +4185,7 @@ checksum = "ebc4ee7f67670e9b64d05fa4253e753e016c6c95ff35b89b7941d6b856dec1d5"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.114", "syn 2.0.116",
] ]
[[package]] [[package]]
@@ -4292,7 +4291,7 @@ checksum = "af407857209536a95c8e56f8231ef2c2e2aff839b22e07a1ffcbc617e9db9fa5"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.114", "syn 2.0.116",
] ]
[[package]] [[package]]
@@ -4352,9 +4351,9 @@ dependencies = [
[[package]] [[package]]
name = "toml" name = "toml"
version = "0.9.11+spec-1.1.0" version = "0.9.12+spec-1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f3afc9a848309fe1aaffaed6e1546a7a14de1f935dc9d89d32afd9a44bab7c46" checksum = "cf92845e79fc2e2def6a5d828f0801e29a2f8acc037becc5ab08595c7d5e9863"
dependencies = [ dependencies = [
"serde_core", "serde_core",
"serde_spanned", "serde_spanned",
@@ -4386,9 +4385,9 @@ dependencies = [
[[package]] [[package]]
name = "toml_parser" name = "toml_parser"
version = "1.0.6+spec-1.1.0" version = "1.0.9+spec-1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a3198b4b0a8e11f09dd03e133c0280504d0801269e9afa46362ffde1cbeebf44" checksum = "702d4415e08923e7e1ef96cd5727c0dfed80b4d2fa25db9647fe5eb6f7c5a4c4"
dependencies = [ dependencies = [
"winnow", "winnow",
] ]
@@ -4415,7 +4414,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d4e6559d53cc268e5031cd8429d05415bc4cb4aefc4aa5d6cc35fbf5b924a1f8" checksum = "d4e6559d53cc268e5031cd8429d05415bc4cb4aefc4aa5d6cc35fbf5b924a1f8"
dependencies = [ dependencies = [
"async-compression", "async-compression",
"bitflags 2.10.0", "bitflags 2.11.0",
"bytes", "bytes",
"futures-core", "futures-core",
"futures-util", "futures-util",
@@ -4462,7 +4461,7 @@ checksum = "7490cfa5ec963746568740651ac6781f701c9c5ea257c58e057f3ba8cf69e8da"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.114", "syn 2.0.116",
] ]
[[package]] [[package]]
@@ -4549,9 +4548,9 @@ checksum = "dbc4bc3a9f746d862c45cb89d705aa10f187bb96c76001afab07a0d35ce60142"
[[package]] [[package]]
name = "unicode-ident" name = "unicode-ident"
version = "1.0.23" version = "1.0.24"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "537dd038a89878be9b64dd4bd1b260315c1bb94f4d784956b81e27a088d9a09e" checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75"
[[package]] [[package]]
name = "unicode-normalization" name = "unicode-normalization"
@@ -4641,11 +4640,11 @@ checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be"
[[package]] [[package]]
name = "uuid" name = "uuid"
version = "1.20.0" version = "1.21.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ee48d38b119b0cd71fe4141b30f5ba9c7c5d9f4e7a3a8b4a674e4b6ef789976f" checksum = "b672338555252d43fd2240c714dc444b8c6fb0a5c5335e65a07bba7742735ddb"
dependencies = [ dependencies = [
"getrandom 0.3.4", "getrandom 0.4.1",
"js-sys", "js-sys",
"serde_core", "serde_core",
"wasm-bindgen", "wasm-bindgen",
@@ -4778,7 +4777,7 @@ dependencies = [
"bumpalo", "bumpalo",
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.114", "syn 2.0.116",
"wasm-bindgen-shared", "wasm-bindgen-shared",
] ]
@@ -4850,7 +4849,7 @@ version = "0.244.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "47b807c72e1bac69382b3a6fb3dbe8ea4c0ed87ff5629b8685ae6b9a611028fe" checksum = "47b807c72e1bac69382b3a6fb3dbe8ea4c0ed87ff5629b8685ae6b9a611028fe"
dependencies = [ dependencies = [
"bitflags 2.10.0", "bitflags 2.11.0",
"hashbrown 0.15.5", "hashbrown 0.15.5",
"indexmap", "indexmap",
"semver", "semver",
@@ -4934,7 +4933,7 @@ checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.114", "syn 2.0.116",
] ]
[[package]] [[package]]
@@ -4945,7 +4944,7 @@ checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.114", "syn 2.0.116",
] ]
[[package]] [[package]]
@@ -5243,7 +5242,7 @@ dependencies = [
"heck", "heck",
"indexmap", "indexmap",
"prettyplease", "prettyplease",
"syn 2.0.114", "syn 2.0.116",
"wasm-metadata", "wasm-metadata",
"wit-bindgen-core", "wit-bindgen-core",
"wit-component", "wit-component",
@@ -5259,7 +5258,7 @@ dependencies = [
"prettyplease", "prettyplease",
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.114", "syn 2.0.116",
"wit-bindgen-core", "wit-bindgen-core",
"wit-bindgen-rust", "wit-bindgen-rust",
] ]
@@ -5271,7 +5270,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9d66ea20e9553b30172b5e831994e35fbde2d165325bec84fc43dbf6f4eb9cb2" checksum = "9d66ea20e9553b30172b5e831994e35fbde2d165325bec84fc43dbf6f4eb9cb2"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"bitflags 2.10.0", "bitflags 2.11.0",
"indexmap", "indexmap",
"log", "log",
"serde", "serde",
@@ -5344,7 +5343,7 @@ checksum = "b659052874eb698efe5b9e8cf382204678a0086ebf46982b79d6ca3182927e5d"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.114", "syn 2.0.116",
"synstructure", "synstructure",
] ]
@@ -5365,7 +5364,7 @@ checksum = "4122cd3169e94605190e77839c9a40d40ed048d305bfdc146e7df40ab0f3e517"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.114", "syn 2.0.116",
] ]
[[package]] [[package]]
@@ -5385,7 +5384,7 @@ checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.114", "syn 2.0.116",
"synstructure", "synstructure",
] ]
@@ -5406,7 +5405,7 @@ checksum = "85a5b4158499876c763cb03bc4e49185d3cccbabb15b33c627f7884f43db852e"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.114", "syn 2.0.116",
] ]
[[package]] [[package]]
@@ -5439,11 +5438,11 @@ checksum = "eadce39539ca5cb3985590102671f2567e659fca9666581ad3411d59207951f3"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.114", "syn 2.0.116",
] ]
[[package]] [[package]]
name = "zmij" name = "zmij"
version = "1.0.20" version = "1.0.21"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4de98dfa5d5b7fef4ee834d0073d560c9ca7b6c46a71d058c48db7960f8cfaf7" checksum = "b8848ee67ecc8aedbaf3e4122217aff892639231befc6a1b58d29fff4c2cabaa"

View File

@@ -7,7 +7,7 @@ license = "AGPL-3.0-or-later"
readme = "README.md" readme = "README.md"
keywords = ["matrix", "chat", "bot", "AI", "LLM"] keywords = ["matrix", "chat", "bot", "AI", "LLM"]
include = ["/etc/assets/baibot-torso-768.png", "/src", "/README.md", "/CHANGELOG.md", "/LICENSE"] include = ["/etc/assets/baibot-torso-768.png", "/src", "/README.md", "/CHANGELOG.md", "/LICENSE"]
version = "1.14.1" version = "1.14.3"
edition = "2024" edition = "2024"
[lib] [lib]
@@ -17,7 +17,7 @@ path = "src/lib.rs"
[dependencies] [dependencies]
anthropic = { git = "https://github.com/etkecc/anthropic-rs.git", branch = "fix-content-block-image" } anthropic = { git = "https://github.com/etkecc/anthropic-rs.git", branch = "fix-content-block-image" }
anyhow = "1.0.*" anyhow = "1.0.*"
async-openai = { version = "0.32.4", features = ["audio", "chat-completion", "image", "responses"] } async-openai = { version = "0.33.0", features = ["audio", "chat-completion", "image", "responses"] }
base64 = "0.22.*" base64 = "0.22.*"
chrono = { version = "0.4.*", default-features = false, features = ["std", "now"] } chrono = { version = "0.4.*", default-features = false, features = ["std", "now"] }
# We'd rather not depend on this, but we cannot use the ruma-events EventContent macro without it. # We'd rather not depend on this, but we cannot use the ruma-events EventContent macro without it.

View File

@@ -4,7 +4,7 @@
# # # #
####################################### #######################################
FROM docker.io/rust:1.93.0-slim-trixie AS build FROM docker.io/rust:1.93.1-slim-trixie AS build
RUN apt-get update && apt-get install -y build-essential pkg-config libssl-dev libsqlite3-dev RUN apt-get update && apt-get install -y build-essential pkg-config libssl-dev libsqlite3-dev

View File

@@ -4,7 +4,7 @@
# # # #
####################################### #######################################
FROM docker.io/rust:1.93.0-slim-trixie AS build FROM docker.io/rust:1.93.1-slim-trixie AS build
RUN apt-get update && apt-get install -y build-essential pkg-config libssl-dev libsqlite3-dev RUN apt-get update && apt-get install -y build-essential pkg-config libssl-dev libsqlite3-dev

View File

@@ -18,6 +18,27 @@ For local development, we run all dependency services in [🐋 Docker](https://w
- (Optional) an API key for some Large Language Model [☁️ provider](./providers.md) (e.g. [OpenAI](./providers.md#openai)), though we recommend using [LocalAI](#localai) or [Ollama](#ollama) for local development - (Optional) an API key for some Large Language Model [☁️ provider](./providers.md) (e.g. [OpenAI](./providers.md#openai)), though we recommend using [LocalAI](#localai) or [Ollama](#ollama) for local development
### Choosing a homeserver
The development environment supports two homeserver implementations:
- **[Continuwuity](https://continuwuity.org/)** (default) — lightweight, no external database required. Good for most development needs.
- **[Synapse](https://github.com/element-hq/synapse)** — the reference implementation, bundled with Postgres. Use this if you need Synapse-specific behavior.
To choose a homeserver (optional — defaults to Continuwuity if skipped):
```sh
just homeserver-init continuwuity # or: just homeserver-init synapse
```
The choice is stored in `var/homeserver` and affects all subsequent commands.
> **Note:** If you switch homeservers after initial setup, you will need to:
> - Delete `var/app/local/` and/or `var/app/container/` (app config and data)
> - Delete `var/services/element-web/` (to regenerate its config)
> - Re-run the prepare and user registration steps
### Getting started guide ### Getting started guide
Developing [locally](#running-locally) is possible, but requires a [Rust](https://www.rust-lang.org/) toolchain. Developing [locally](#running-locally) is possible, but requires a [Rust](https://www.rust-lang.org/) toolchain.
@@ -28,11 +49,12 @@ In any case, you will need [🐋 Docker](https://www.docker.com/) as [dependency
#### Running locally #### Running locally
1. Start the core dependency services (Postgres, Synapse, Element Web): `just services-start` 1. (Optional) Choose a homeserver: `just homeserver-init continuwuity` (or `synapse`). Default is `continuwuity`.
2. (Only the first time around) Prepare initial app configuration in `var/app/local/config.yml`: `just app-local-prepare` 2. Start the homeserver and Element Web: `just services-start`
3. (Only the first time around) [Prepare your configuration file](#prepare-your-configuration-file) 3. (Only the first time around) Prepare initial app configuration in `var/app/local/config.yml`: `just app-local-prepare`
4. (Only the first time around) Prepare initial default Matrix user accounts (`admin` and `baibot`): `just users-prepare` 4. (Only the first time around) [Prepare your configuration file](#prepare-your-configuration-file)
5. (Optional) Start additional services depending on which [agent provider you've chosen](#choosing-an-agent-provider): 5. (Only the first time around) Prepare initial default Matrix user accounts (`admin` and `baibot`): `just users-prepare`
6. (Optional) Start additional services depending on which [agent provider you've chosen](#choosing-an-agent-provider):
- for [LocalAI](#localai): - for [LocalAI](#localai):
- Start services: `just localai-start` - Start services: `just localai-start`
- Wait a while for LocalAI to start up. It has a lot of models to download. Monitor progress using `just localai-tail-logs` - Wait a while for LocalAI to start up. It has a lot of models to download. Monitor progress using `just localai-tail-logs`
@@ -40,12 +62,12 @@ In any case, you will need [🐋 Docker](https://www.docker.com/) as [dependency
- for [Ollama](#ollama): - for [Ollama](#ollama):
- Start services: `just ollama-start` - Start services: `just ollama-start`
- (Only the first time around) Pull the model configured in `agents.static_definitions` in the configuration file: `just ollama-pull-model gemma2:2b` - (Only the first time around) Pull the model configured in `agents.static_definitions` in the configuration file: `just ollama-pull-model gemma2:2b`
6. Start the bot: `just run-locally` 7. Start the bot: `just run-locally`
7. Go to http://element.127.0.0.1.nip.io:42025/ and login with `admin` / `admin` 8. Go to http://element.127.0.0.1.nip.io:42025/ and login with `admin` / `admin`
8. Create a new room and invite `@baibot:synapse.127.0.0.1.nip.io` 9. Create a new room and invite `@baibot:continuwuity.127.0.0.1.nip.io` (or `@baibot:synapse.127.0.0.1.nip.io` if using Synapse)
9. When done, stop the bot (`Ctrl` + `C`) 10. When done, stop the bot (`Ctrl` + `C`)
10. Stop the core dependency services: `just services-stop` 11. Stop the services: `just services-stop`
11. (Optional) Stop additional services: 12. (Optional) Stop additional services:
- for [LocalAI](#localai): `just localai-stop` - for [LocalAI](#localai): `just localai-stop`
- for [Ollama](#ollama): `just ollama-stop` - for [Ollama](#ollama): `just ollama-stop`
@@ -54,11 +76,12 @@ In any case, you will need [🐋 Docker](https://www.docker.com/) as [dependency
You can avoid having a [Rust](https://www.rust-lang.org/) toolchain installed locally and build/run this in a container. You can avoid having a [Rust](https://www.rust-lang.org/) toolchain installed locally and build/run this in a container.
1. Start the core dependency services (Postgres, Synapse, Element Web): `just services-start` 1. (Optional) Choose a homeserver: `just homeserver-init continuwuity` (or `synapse`). Default is `continuwuity`.
2. (Only the first time around) Prepare initial app configuration in `var/app/container/config.yml`: `just app-container-prepare` 2. Start the homeserver and Element Web: `just services-start`
3. (Only the first time around) [Prepare your configuration file](#prepare-your-configuration-file) 3. (Only the first time around) Prepare initial app configuration in `var/app/container/config.yml`: `just app-container-prepare`
4. (Only the first time around) Prepare initial default Matrix user accounts (`admin` and `baibot`): `just users-prepare` 4. (Only the first time around) [Prepare your configuration file](#prepare-your-configuration-file)
5. (Optional) Start additional services depending on which [agent provider you've chosen](#choosing-an-agent-provider): 5. (Only the first time around) Prepare initial default Matrix user accounts (`admin` and `baibot`): `just users-prepare`
6. (Optional) Start additional services depending on which [agent provider you've chosen](#choosing-an-agent-provider):
- for [LocalAI](#localai): - for [LocalAI](#localai):
- Start services: `just localai-start` - Start services: `just localai-start`
- Wait a while for LocalAI to start up. It has a lot of models to download. Monitor progress using `just localai-tail-logs` - Wait a while for LocalAI to start up. It has a lot of models to download. Monitor progress using `just localai-tail-logs`
@@ -66,12 +89,12 @@ You can avoid having a [Rust](https://www.rust-lang.org/) toolchain installed lo
- for [Ollama](#ollama): - for [Ollama](#ollama):
- Start services: `just ollama-start` - Start services: `just ollama-start`
- (Only the first time around) Pull the model configured in `agents.static_definitions` in the configuration file: `just ollama-pull-model gemma2:2b` - (Only the first time around) Pull the model configured in `agents.static_definitions` in the configuration file: `just ollama-pull-model gemma2:2b`
6. Start the bot: `just run-in-container` 7. Start the bot: `just run-in-container`
7. Go to http://element.127.0.0.1.nip.io:42025/ and login with `admin` / `admin` 8. Go to http://element.127.0.0.1.nip.io:42025/ and login with `admin` / `admin`
8. Create a new room and invite `@baibot:synapse.127.0.0.1.nip.io` 9. Create a new room and invite `@baibot:continuwuity.127.0.0.1.nip.io` (or `@baibot:synapse.127.0.0.1.nip.io` if using Synapse)
9. When done, stop the bot (`Ctrl` + `C`) 10. When done, stop the bot (`Ctrl` + `C`)
10. Stop the dependency services: `just services-stop` 11. Stop the services: `just services-stop`
11. (Optional) Stop additional services: 12. (Optional) Stop additional services:
- for [LocalAI](#localai): `just localai-stop` - for [LocalAI](#localai): `just localai-stop`
- for [Ollama](#ollama): `just ollama-stop` - for [Ollama](#ollama): `just ollama-stop`

View File

@@ -1,7 +1,7 @@
homeserver: homeserver:
# The canonical homeserver domain name # The canonical homeserver domain name
server_name: synapse.127.0.0.1.nip.io server_name: __HOMESERVER_SERVER_NAME__
url: http://synapse.127.0.0.1.nip.io:42020 url: __HOMESERVER_URL__
user: user:
mxid_localpart: baibot mxid_localpart: baibot
@@ -45,7 +45,7 @@ room:
access: access:
# Space-separated list of MXID patterns which specify who is an admin. # Space-separated list of MXID patterns which specify who is an admin.
admin_patterns: admin_patterns:
- "@admin:synapse.127.0.0.1.nip.io" - "@admin:__HOMESERVER_SERVER_NAME__"
persistence: persistence:
# This is unset here, because we expect the configuration to come from an environment variable (BAIBOT_PERSISTENCE_DATA_DIR_PATH). # This is unset here, because we expect the configuration to come from an environment variable (BAIBOT_PERSISTENCE_DATA_DIR_PATH).
@@ -157,7 +157,7 @@ initial_global_config:
# Space-separated list of MXID patterns which specify who can use the bot. # Space-separated list of MXID patterns which specify who can use the bot.
# By default, we let anyone on the homeserver use the bot. # By default, we let anyone on the homeserver use the bot.
user_patterns: user_patterns:
- "@*:synapse.127.0.0.1.nip.io" - "@*:__HOMESERVER_SERVER_NAME__"
# Controls logging. # Controls logging.
# #

View File

@@ -0,0 +1,23 @@
services:
continuwuity:
image: forgejo.ellis.link/continuwuation/continuwuity:v0.5.5
user: "${UID}:${GID}"
restart: unless-stopped
cap_drop:
- ALL
read_only: true
environment:
CONDUWUIT_CONFIG: /etc/continuwuity/continuwuity.toml
CONDUWUIT_DATABASE_PATH: /var/lib/continuwuity
ports:
- "${SERVICE_CONTINUWUITY_BIND_PORT_CLIENT_API}:6167"
volumes:
- ../../etc/services/continuwuity/config:/etc/continuwuity:ro
- ./continuwuity/data:/var/lib/continuwuity
tmpfs:
- /tmp:rw,noexec,nosuid,size=500m
networks:
default:
name: ${NETWORK_NAME}
external: true

View File

@@ -0,0 +1,19 @@
[global]
server_name = "continuwuity.127.0.0.1.nip.io"
address = "0.0.0.0"
port = 6167
database_path = "/var/lib/continuwuity"
allow_registration = true
yes_i_am_very_very_sure_i_want_an_open_registration_server_prone_to_abuse = true
new_user_displayname_suffix = ""
max_request_size = 20_000_000
allow_federation = false
trusted_servers = ["matrix.org"]
log = "info,state_res=warn,rocket=off,_=off,sled=off"

View File

@@ -0,0 +1,48 @@
#!/bin/sh
set -eu
if [ $# -ne 3 ]; then
echo "Usage: $0 <env-file> <username> <password>"
exit 1
fi
ENV_FILE="$1"
USERNAME="$2"
PASSWORD="$3"
SERVER="http://$(grep '^SERVICE_CONTINUWUITY_BIND_PORT_CLIENT_API=' "${ENV_FILE}" | cut -d= -f2)"
REGISTER_URL="${SERVER}/_matrix/client/v3/register"
echo "Registering user '${USERNAME}' on ${SERVER}..."
SESSION_RESPONSE=$(curl -s -X POST "${REGISTER_URL}" \
-H 'Content-Type: application/json' \
-d "{\"username\": \"${USERNAME}\", \"password\": \"${PASSWORD}\"}")
SESSION_ID=$(echo "${SESSION_RESPONSE}" | grep -o '"session":"[^"]*"' | head -1 | cut -d'"' -f4)
if [ -z "${SESSION_ID}" ]; then
echo "Error: Could not get session ID. Response: ${SESSION_RESPONSE}"
exit 1
fi
# Determine the required auth flow from the server response.
# The first user requires m.login.registration_token (bootstrap token from logs).
# Subsequent users use m.login.dummy (open registration).
if echo "${SESSION_RESPONSE}" | grep -q 'm.login.registration_token'; then
CONTAINER_ID=$(docker ps -q --filter name=baibot-continuwuity-continuwuity)
REG_TOKEN=$(docker logs "${CONTAINER_ID}" 2>&1 | sed 's/\x1b\[[0-9;]*m//g' | grep 'using the registration token' | grep -oP 'registration token \K[A-Za-z0-9]+' | head -1)
AUTH_BODY="{\"type\": \"m.login.registration_token\", \"token\": \"${REG_TOKEN}\", \"session\": \"${SESSION_ID}\"}"
else
AUTH_BODY="{\"type\": \"m.login.dummy\", \"session\": \"${SESSION_ID}\"}"
fi
RESULT=$(curl -s -X POST "${REGISTER_URL}" \
-H 'Content-Type: application/json' \
-d "{\"username\": \"${USERNAME}\", \"password\": \"${PASSWORD}\", \"auth\": ${AUTH_BODY}}")
if echo "${RESULT}" | grep -q '"user_id"'; then
echo "Successfully registered user: $(echo "${RESULT}" | grep -o '"user_id":"[^"]*"' | cut -d'"' -f4)"
else
echo "Registration failed. Response: ${RESULT}"
exit 1
fi

View File

@@ -0,0 +1,21 @@
services:
element-web:
image: ghcr.io/element-hq/element-web:v1.12.10
user: "${UID}:${GID}"
restart: unless-stopped
environment:
ELEMENT_WEB_PORT: 8080
ports:
- "${SERVICE_ELEMENT_WEB_BIND_PORT_HTTP}:8080"
volumes:
- ./element-web/config.json:/app/config.json:ro
tmpfs:
- /var/cache/nginx:rw,mode=777
- /var/run:rw,mode=777
- /tmp/element-web-config:rw,mode=777
- /etc/nginx/conf.d:rw,mode=777
networks:
default:
name: ${NETWORK_NAME}
external: true

View File

@@ -1,5 +1,5 @@
{ {
"default_hs_url": "http://synapse.127.0.0.1.nip.io:42020", "default_hs_url": "__HOMESERVER_CLIENT_URL__",
"default_is_url": "https://vector.im", "default_is_url": "https://vector.im",
"integrations_ui_url": "https://scalar.vector.im/", "integrations_ui_url": "https://scalar.vector.im/",
"integrations_rest_url": "https://scalar.vector.im/api", "integrations_rest_url": "https://scalar.vector.im/api",

View File

@@ -3,6 +3,8 @@ SERVICE_SYNAPSE_BIND_PORT_FEDERATION_API=127.0.0.1:42028
SERVICE_ELEMENT_WEB_BIND_PORT_HTTP=127.0.0.1:42025 SERVICE_ELEMENT_WEB_BIND_PORT_HTTP=127.0.0.1:42025
SERVICE_CONTINUWUITY_BIND_PORT_CLIENT_API=127.0.0.1:42030
SERVICE_OLLAMA_BIND_PORT_HTTP=127.0.0.1:42026 SERVICE_OLLAMA_BIND_PORT_HTTP=127.0.0.1:42026
# See https://localai.io/basics/container/#all-in-one-images for the list of available images # See https://localai.io/basics/container/#all-in-one-images for the list of available images

View File

@@ -1,6 +1,6 @@
services: services:
ollama: ollama:
image: docker.io/ollama/ollama:0.15.4 image: docker.io/ollama/ollama:0.16.2
restart: unless-stopped restart: unless-stopped
ports: ports:
- "${SERVICE_OLLAMA_BIND_PORT_HTTP}:11434" - "${SERVICE_OLLAMA_BIND_PORT_HTTP}:11434"

View File

@@ -1,6 +1,6 @@
services: services:
postgres: postgres:
image: docker.io/postgres:18.1-alpine image: docker.io/postgres:18.2-alpine
user: ${UID}:${GID} user: ${UID}:${GID}
restart: unless-stopped restart: unless-stopped
environment: environment:
@@ -14,7 +14,7 @@ services:
- /etc/passwd:/etc/passwd:ro - /etc/passwd:/etc/passwd:ro
synapse: synapse:
image: ghcr.io/element-hq/synapse:v1.146.0 image: ghcr.io/element-hq/synapse:v1.147.1
user: "${UID}:${GID}" user: "${UID}:${GID}"
restart: unless-stopped restart: unless-stopped
entrypoint: python entrypoint: python
@@ -23,25 +23,9 @@ services:
- "${SERVICE_SYNAPSE_BIND_PORT_CLIENT_API}:8008" - "${SERVICE_SYNAPSE_BIND_PORT_CLIENT_API}:8008"
- "${SERVICE_SYNAPSE_BIND_PORT_FEDERATION_API}:8008" - "${SERVICE_SYNAPSE_BIND_PORT_FEDERATION_API}:8008"
volumes: volumes:
- ../../etc/services/core/synapse/config:/config:ro - ../../etc/services/synapse/config:/config:ro
- ./synapse/media-store:/media-store - ./synapse/media-store:/media-store
element-web:
image: ghcr.io/element-hq/element-web:v1.12.9
user: "${UID}:${GID}"
restart: unless-stopped
environment:
ELEMENT_WEB_PORT: 8080
ports:
- "${SERVICE_ELEMENT_WEB_BIND_PORT_HTTP}:8080"
volumes:
- ../../etc/services/core/element-web/config.json:/app/config.json:ro
tmpfs:
- /var/cache/nginx:rw,mode=777
- /var/run:rw,mode=777
- /tmp/element-web-config:rw,mode=777
- /etc/nginx/conf.d:rw,mode=777
networks: networks:
default: default:
name: ${NETWORK_NAME} name: ${NETWORK_NAME}

172
justfile
View File

@@ -2,6 +2,13 @@ project_name := "baibot"
container_image_name := "localhost/baibot" container_image_name := "localhost/baibot"
project_container_network := "baibot" project_container_network := "baibot"
admin_username := "admin"
admin_password := "admin"
bot_username := "baibot"
bot_password := "baibot"
homeserver := `cat var/homeserver 2>/dev/null || echo continuwuity`
mise_data_dir := env("MISE_DATA_DIR", justfile_directory() / "var/mise") mise_data_dir := env("MISE_DATA_DIR", justfile_directory() / "var/mise")
mise_trusted_config_paths := justfile_directory() / "mise.toml" mise_trusted_config_paths := justfile_directory() / "mise.toml"
@@ -9,6 +16,19 @@ mise_trusted_config_paths := justfile_directory() / "mise.toml"
default: default:
@just --list --justfile {{ justfile() }} @just --list --justfile {{ justfile() }}
# Selects which homeserver implementation to use (continuwuity or synapse)
homeserver-init value:
#!/bin/sh
mkdir -p {{ justfile_directory() }}/var
echo {{ value }} > {{ justfile_directory() }}/var/homeserver
echo ""
echo "⚠️ If you had already prepared your app configuration (var/app/local/config.yml or var/app/container/config.yml),"
echo " you will need to update it manually or delete it and re-run the prepare step."
echo " You should also delete var/app/local/data and/or var/app/container/data,"
echo " as old application state is not compatible across homeserver implementations."
echo ""
echo "⚠️ If Element Web was already prepared, delete var/services/element-web/ to regenerate its config."
# Builds and runs a development binary # Builds and runs a development binary
run-locally *extra_args: app-local-prepare run-locally *extra_args: app-local-prepare
RUST_BACKTRACE=1 \ RUST_BACKTRACE=1 \
@@ -68,9 +88,13 @@ docker-compose services_type *extra_args:
-p {{ project_name }}-{{ services_type }} \ -p {{ project_name }}-{{ services_type }} \
{{ extra_args }} {{ extra_args }}
# Runs a docker-compose command against the core services # Runs a docker-compose command against the synapse services
docker-compose-core *extra_args: docker-compose-synapse *extra_args:
just docker-compose core {{ extra_args }} just docker-compose synapse {{ extra_args }}
# Runs a docker-compose command against the element-web services
docker-compose-element-web *extra_args:
just docker-compose element-web {{ extra_args }}
# Runs a docker-compose command against the localai services # Runs a docker-compose command against the localai services
docker-compose-localai *extra_args: docker-compose-localai *extra_args:
@@ -80,17 +104,52 @@ docker-compose-localai *extra_args:
docker-compose-ollama *extra_args: docker-compose-ollama *extra_args:
just docker-compose ollama {{ extra_args }} just docker-compose ollama {{ extra_args }}
# Runs all core dependency components (in the background) # Runs a docker-compose command against the continuwuity services
services-start: services-prepare (docker-compose-core "up" "-d") docker-compose-continuwuity *extra_args:
just docker-compose continuwuity {{ extra_args }}
# Stops all core dependency components # Runs the homeserver and Element Web (in the background)
services-stop: (docker-compose-core "down") services-start: services-prepare
just -f {{ justfile_directory() }}/justfile {{ homeserver }}-start
just -f {{ justfile_directory() }}/justfile element-web-start
# Tails the logs for all running core services # Stops Element Web and the homeserver
services-tail-logs: (docker-compose-core "logs" "-f") services-stop:
just -f {{ justfile_directory() }}/justfile element-web-stop
just -f {{ justfile_directory() }}/justfile {{ homeserver }}-stop
# Prepares the core services for running # Tails the logs for the homeserver and Element Web
services-prepare: _prepare-var-services-env _prepare-var-services-postgres _prepare-var-services-synapse _prepare-container-network services-tail-logs:
just -f {{ justfile_directory() }}/justfile {{ homeserver }}-tail-logs
# Prepares the homeserver and Element Web for running
services-prepare:
just -f {{ justfile_directory() }}/justfile {{ homeserver }}-prepare
just -f {{ justfile_directory() }}/justfile element-web-prepare
# Runs Synapse (in the background)
synapse-start: synapse-prepare (docker-compose-synapse "up" "-d")
# Stops Synapse
synapse-stop: (docker-compose-synapse "down")
# Tails the logs for Synapse
synapse-tail-logs: (docker-compose-synapse "logs" "-f")
# Prepares Synapse for running
synapse-prepare: _prepare-var-services-env _prepare-var-services-postgres _prepare-var-services-synapse _prepare-container-network
# Runs Element Web (in the background)
element-web-start: element-web-prepare (docker-compose-element-web "up" "-d")
# Stops Element Web
element-web-stop: (docker-compose-element-web "down")
# Tails the logs for Element Web
element-web-tail-logs: (docker-compose-element-web "logs" "-f")
# Prepares Element Web for running
element-web-prepare: _prepare-var-services-env _prepare-var-services-element-web _prepare-container-network
# Runs LocalAI (in the background) # Runs LocalAI (in the background)
localai-start: localai-prepare (docker-compose-localai "up" "-d") localai-start: localai-prepare (docker-compose-localai "up" "-d")
@@ -116,6 +175,27 @@ ollama-tail-logs: (docker-compose-ollama "logs" "-f")
# Prepares Ollama for running # Prepares Ollama for running
ollama-prepare: _prepare-var-services-env _prepare-var-services-ollama _prepare-container-network ollama-prepare: _prepare-var-services-env _prepare-var-services-ollama _prepare-container-network
# Runs Continuwuity (in the background)
continuwuity-start: continuwuity-prepare (docker-compose-continuwuity "up" "-d")
# Stops Continuwuity
continuwuity-stop: (docker-compose-continuwuity "down")
# Tails the logs for Continuwuity
continuwuity-tail-logs: (docker-compose-continuwuity "logs" "-f")
# Prepares Continuwuity for running
continuwuity-prepare: _prepare-var-services-env _prepare-var-services-continuwuity _prepare-container-network
# Registers a user on Continuwuity via the Matrix Client-Server API
continuwuity-register-user username password:
{{ justfile_directory() }}/etc/services/continuwuity/register-user.sh {{ justfile_directory() }}/var/services/env {{ username }} {{ password }}
# Prepares the Continuwuity user accounts
continuwuity-users-prepare: continuwuity-prepare
just -f {{ justfile_directory() }}/justfile continuwuity-register-user "{{ admin_username }}" "{{ admin_password }}"
just -f {{ justfile_directory() }}/justfile continuwuity-register-user "{{ bot_username }}" "{{ bot_password }}"
# Pulls an Ollama model # Pulls an Ollama model
ollama-pull-model model_id: ollama-pull-model model_id:
just -f {{ justfile_directory() }}/justfile docker-compose-ollama \ just -f {{ justfile_directory() }}/justfile docker-compose-ollama \
@@ -129,16 +209,20 @@ app-local-prepare: _prepare-var-app-local-config_yml _prepare-var-app-local-data
app-container-prepare: _prepare-var-app-container-config_yml _prepare-var-app-container-data app-container-prepare: _prepare-var-app-container-config_yml _prepare-var-app-container-data
# Prepares the user accounts # Prepares the user accounts
users-prepare: services-prepare users-prepare:
just -f {{ justfile_directory() }}/justfile synapse-register-admin-user "admin" "admin" just -f {{ justfile_directory() }}/justfile {{ homeserver }}-users-prepare
just -f {{ justfile_directory() }}/justfile synapse-register-regular-user "baibot" "baibot"
# Prepares the Synapse user accounts
synapse-users-prepare: synapse-prepare
just -f {{ justfile_directory() }}/justfile synapse-register-admin-user "{{ admin_username }}" "{{ admin_password }}"
just -f {{ justfile_directory() }}/justfile synapse-register-regular-user "{{ bot_username }}" "{{ bot_password }}"
# Starts a Postgres CLI (psql) # Starts a Postgres CLI (psql)
postgres-cli: services-prepare (docker-compose-core "exec" "postgres" "/bin/sh" "-c" "'PGUSER=synapse PGPASSWORD=synapse-password PGDATABASE=homeserver psql -h postgres'") postgres-cli: synapse-prepare (docker-compose-synapse "exec" "postgres" "/bin/sh" "-c" "'PGUSER=synapse PGPASSWORD=synapse-password PGDATABASE=homeserver psql -h postgres'")
# Creates an administrator user # Creates an administrator user on Synapse
synapse-register-admin-user username password: services-prepare synapse-register-admin-user username password: synapse-prepare
just -f {{ justfile_directory() }}/justfile docker-compose-core \ just -f {{ justfile_directory() }}/justfile docker-compose-synapse \
exec synapse \ exec synapse \
register_new_matrix_user \ register_new_matrix_user \
--admin \ --admin \
@@ -147,9 +231,9 @@ synapse-register-admin-user username password: services-prepare
-c /config/homeserver.yaml \ -c /config/homeserver.yaml \
http://localhost:8008 http://localhost:8008
# Create a regular user # Creates a regular user on Synapse
synapse-register-regular-user username password: services-prepare synapse-register-regular-user username password: synapse-prepare
just -f {{ justfile_directory() }}/justfile docker-compose-core \ just -f {{ justfile_directory() }}/justfile docker-compose-synapse \
exec synapse \ exec synapse \
register_new_matrix_user \ register_new_matrix_user \
--no-admin \ --no-admin \
@@ -229,6 +313,22 @@ _prepare-var-services-synapse:
mkdir -p var/services/synapse/media-store mkdir -p var/services/synapse/media-store
fi fi
_prepare-var-services-element-web:
#!/bin/sh
cd {{ justfile_directory() }};
if [ ! -f var/services/element-web/config.json ]; then
mkdir -p var/services/element-web
cp {{ justfile_directory() }}/etc/services/element-web/config.json.dist var/services/element-web/config.json
homeserver="{{ homeserver }}"
if [ "$homeserver" = "continuwuity" ]; then
sed --in-place 's|__HOMESERVER_CLIENT_URL__|http://continuwuity.127.0.0.1.nip.io:42030|g' var/services/element-web/config.json
elif [ "$homeserver" = "synapse" ]; then
sed --in-place 's|__HOMESERVER_CLIENT_URL__|http://synapse.127.0.0.1.nip.io:42020|g' var/services/element-web/config.json
fi
fi
_prepare-var-services-ollama: _prepare-var-services-ollama:
#!/bin/sh #!/bin/sh
cd {{ justfile_directory() }}; cd {{ justfile_directory() }};
@@ -237,6 +337,14 @@ _prepare-var-services-ollama:
mkdir -p var/services/ollama mkdir -p var/services/ollama
fi fi
_prepare-var-services-continuwuity:
#!/bin/sh
cd {{ justfile_directory() }};
if [ ! -f var/services/continuwuity ]; then
mkdir -p var/services/continuwuity/data
fi
_prepare-var-services-localai: _prepare-var-services-localai:
#!/bin/sh #!/bin/sh
cd {{ justfile_directory() }}; cd {{ justfile_directory() }};
@@ -260,6 +368,15 @@ _prepare-var-app-local-config_yml:
if [ ! -f var/app/local/config.yml ]; then if [ ! -f var/app/local/config.yml ]; then
mkdir -p var/app/local mkdir -p var/app/local
cp {{ justfile_directory() }}/etc/app/config.yml.dist var/app/local/config.yml cp {{ justfile_directory() }}/etc/app/config.yml.dist var/app/local/config.yml
homeserver="{{ homeserver }}"
if [ "$homeserver" = "continuwuity" ]; then
sed --in-place 's/__HOMESERVER_SERVER_NAME__/continuwuity.127.0.0.1.nip.io/g' var/app/local/config.yml
sed --in-place 's|__HOMESERVER_URL__|http://continuwuity.127.0.0.1.nip.io:42030|g' var/app/local/config.yml
elif [ "$homeserver" = "synapse" ]; then
sed --in-place 's/__HOMESERVER_SERVER_NAME__/synapse.127.0.0.1.nip.io/g' var/app/local/config.yml
sed --in-place 's|__HOMESERVER_URL__|http://synapse.127.0.0.1.nip.io:42020|g' var/app/local/config.yml
fi
fi fi
_prepare-var-app-local-data: _prepare-var-app-local-data:
@@ -277,7 +394,18 @@ _prepare-var-app-container-config_yml:
if [ ! -f var/app/container/config.yml ]; then if [ ! -f var/app/container/config.yml ]; then
mkdir -p var/app/container mkdir -p var/app/container
cp {{ justfile_directory() }}/etc/app/config.yml.dist var/app/container/config.yml cp {{ justfile_directory() }}/etc/app/config.yml.dist var/app/container/config.yml
sed --in-place 's/synapse.127.0.0.1.nip.io:42020/synapse:8008/g' var/app/container/config.yml
homeserver="{{ homeserver }}"
if [ "$homeserver" = "continuwuity" ]; then
sed --in-place 's/__HOMESERVER_SERVER_NAME__/continuwuity.127.0.0.1.nip.io/g' var/app/container/config.yml
sed --in-place 's|__HOMESERVER_URL__|http://continuwuity.127.0.0.1.nip.io:42030|g' var/app/container/config.yml
sed --in-place 's/continuwuity.127.0.0.1.nip.io:42030/continuwuity:6167/g' var/app/container/config.yml
elif [ "$homeserver" = "synapse" ]; then
sed --in-place 's/__HOMESERVER_SERVER_NAME__/synapse.127.0.0.1.nip.io/g' var/app/container/config.yml
sed --in-place 's|__HOMESERVER_URL__|http://synapse.127.0.0.1.nip.io:42020|g' var/app/container/config.yml
sed --in-place 's/synapse.127.0.0.1.nip.io:42020/synapse:8008/g' var/app/container/config.yml
fi
sed --in-place 's/127.0.0.1:42026/ollama:11434/g' var/app/container/config.yml sed --in-place 's/127.0.0.1:42026/ollama:11434/g' var/app/container/config.yml
sed --in-place 's/127.0.0.1:42027/localai:8080/g' var/app/container/config.yml sed --in-place 's/127.0.0.1:42027/localai:8080/g' var/app/container/config.yml
fi fi

9
renovate.json Normal file
View File

@@ -0,0 +1,9 @@
{
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
"extends": [
"config:recommended"
],
"labels": [
"dependencies"
]
}