chore: config chat

This commit is contained in:
nathan 2024-06-28 15:48:13 +08:00
parent e4b1108ff0
commit 4c70ad9b9b
51 changed files with 822 additions and 472 deletions

View File

@ -172,7 +172,7 @@ checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da"
[[package]]
name = "app-error"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=6262816043efeede8823d7a7ea252083adf407e9#6262816043efeede8823d7a7ea252083adf407e9"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=9884d93aa2805013f36a79c1757174a0b5063065#9884d93aa2805013f36a79c1757174a0b5063065"
dependencies = [
"anyhow",
"bincode",
@ -192,7 +192,7 @@ dependencies = [
[[package]]
name = "appflowy-ai-client"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=6262816043efeede8823d7a7ea252083adf407e9#6262816043efeede8823d7a7ea252083adf407e9"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=9884d93aa2805013f36a79c1757174a0b5063065#9884d93aa2805013f36a79c1757174a0b5063065"
dependencies = [
"anyhow",
"bytes",
@ -772,7 +772,7 @@ dependencies = [
[[package]]
name = "client-api"
version = "0.2.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=6262816043efeede8823d7a7ea252083adf407e9#6262816043efeede8823d7a7ea252083adf407e9"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=9884d93aa2805013f36a79c1757174a0b5063065#9884d93aa2805013f36a79c1757174a0b5063065"
dependencies = [
"again",
"anyhow",
@ -787,6 +787,7 @@ dependencies = [
"collab",
"collab-rt-entity",
"collab-rt-protocol",
"futures",
"futures-core",
"futures-util",
"getrandom 0.2.10",
@ -794,6 +795,8 @@ dependencies = [
"infra",
"mime",
"parking_lot 0.12.1",
"percent-encoding",
"pin-project",
"prost",
"reqwest",
"scraper 0.17.1",
@ -818,7 +821,7 @@ dependencies = [
[[package]]
name = "client-api-entity"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=6262816043efeede8823d7a7ea252083adf407e9#6262816043efeede8823d7a7ea252083adf407e9"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=9884d93aa2805013f36a79c1757174a0b5063065#9884d93aa2805013f36a79c1757174a0b5063065"
dependencies = [
"collab-entity",
"collab-rt-entity",
@ -830,7 +833,7 @@ dependencies = [
[[package]]
name = "client-websocket"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=6262816043efeede8823d7a7ea252083adf407e9#6262816043efeede8823d7a7ea252083adf407e9"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=9884d93aa2805013f36a79c1757174a0b5063065#9884d93aa2805013f36a79c1757174a0b5063065"
dependencies = [
"futures-channel",
"futures-util",
@ -1070,7 +1073,7 @@ dependencies = [
[[package]]
name = "collab-rt-entity"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=6262816043efeede8823d7a7ea252083adf407e9#6262816043efeede8823d7a7ea252083adf407e9"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=9884d93aa2805013f36a79c1757174a0b5063065#9884d93aa2805013f36a79c1757174a0b5063065"
dependencies = [
"anyhow",
"bincode",
@ -1095,7 +1098,7 @@ dependencies = [
[[package]]
name = "collab-rt-protocol"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=6262816043efeede8823d7a7ea252083adf407e9#6262816043efeede8823d7a7ea252083adf407e9"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=9884d93aa2805013f36a79c1757174a0b5063065#9884d93aa2805013f36a79c1757174a0b5063065"
dependencies = [
"anyhow",
"async-trait",
@ -1291,12 +1294,9 @@ dependencies = [
[[package]]
name = "crossbeam-utils"
version = "0.8.16"
version = "0.8.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5a22b2d63d4d1dc0b7f1b6b2747dd0088008a9be28b6ddf0b1e7d335e3037294"
dependencies = [
"cfg-if",
]
checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80"
[[package]]
name = "crunchy"
@ -1452,10 +1452,11 @@ checksum = "c2e66c9d817f1720209181c316d28635c050fa304f9c79e47a520882661b7308"
[[package]]
name = "database-entity"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=6262816043efeede8823d7a7ea252083adf407e9#6262816043efeede8823d7a7ea252083adf407e9"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=9884d93aa2805013f36a79c1757174a0b5063065#9884d93aa2805013f36a79c1757174a0b5063065"
dependencies = [
"anyhow",
"app-error",
"appflowy-ai-client",
"bincode",
"chrono",
"collab-entity",
@ -1852,6 +1853,7 @@ dependencies = [
"flowy-derive",
"flowy-error",
"flowy-notification",
"flowy-sidecar",
"flowy-sqlite",
"futures",
"lib-dispatch",
@ -2315,6 +2317,24 @@ dependencies = [
"serde_repr",
]
[[package]]
name = "flowy-sidecar"
version = "0.1.0"
dependencies = [
"anyhow",
"crossbeam-utils",
"lib-infra",
"log",
"once_cell",
"parking_lot 0.12.1",
"serde",
"serde_json",
"thiserror",
"tokio",
"tokio-stream",
"tracing",
]
[[package]]
name = "flowy-sqlite"
version = "0.1.0"
@ -2894,7 +2914,7 @@ dependencies = [
[[package]]
name = "gotrue"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=6262816043efeede8823d7a7ea252083adf407e9#6262816043efeede8823d7a7ea252083adf407e9"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=9884d93aa2805013f36a79c1757174a0b5063065#9884d93aa2805013f36a79c1757174a0b5063065"
dependencies = [
"anyhow",
"futures-util",
@ -2911,7 +2931,7 @@ dependencies = [
[[package]]
name = "gotrue-entity"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=6262816043efeede8823d7a7ea252083adf407e9#6262816043efeede8823d7a7ea252083adf407e9"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=9884d93aa2805013f36a79c1757174a0b5063065#9884d93aa2805013f36a79c1757174a0b5063065"
dependencies = [
"anyhow",
"app-error",
@ -3343,7 +3363,7 @@ dependencies = [
[[package]]
name = "infra"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=6262816043efeede8823d7a7ea252083adf407e9#6262816043efeede8823d7a7ea252083adf407e9"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=9884d93aa2805013f36a79c1757174a0b5063065#9884d93aa2805013f36a79c1757174a0b5063065"
dependencies = [
"anyhow",
"bytes",
@ -3591,6 +3611,7 @@ dependencies = [
"async-trait",
"atomic_refcell",
"bytes",
"cfg-if",
"chrono",
"futures",
"futures-core",
@ -4211,9 +4232,9 @@ dependencies = [
[[package]]
name = "once_cell"
version = "1.18.0"
version = "1.19.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d"
checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92"
[[package]]
name = "oneshot"
@ -5685,9 +5706,9 @@ dependencies = [
[[package]]
name = "serde_json"
version = "1.0.111"
version = "1.0.118"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "176e46fa42316f18edd598015a5166857fc835ec732f5215eac6b7bdbf0a84f4"
checksum = "d947f6b3163d8857ea16c4fa0dd4840d52f3041039a85decd46867eb1abef2e4"
dependencies = [
"itoa 1.0.6",
"ryu",
@ -5835,7 +5856,7 @@ dependencies = [
[[package]]
name = "shared-entity"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=6262816043efeede8823d7a7ea252083adf407e9#6262816043efeede8823d7a7ea252083adf407e9"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=9884d93aa2805013f36a79c1757174a0b5063065#9884d93aa2805013f36a79c1757174a0b5063065"
dependencies = [
"anyhow",
"app-error",
@ -6842,9 +6863,9 @@ dependencies = [
[[package]]
name = "tokio-stream"
version = "0.1.14"
version = "0.1.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "397c988d37662c7dda6d2208364a706264bf3d6138b11d436cbac0ad38832842"
checksum = "267ac89e0bec6e691e5813911606935d77c476ff49024f98abcea3e7b15e37af"
dependencies = [
"futures-core",
"pin-project-lite",

View File

@ -52,7 +52,7 @@ collab-user = { version = "0.2" }
# Run the script:
# scripts/tool/update_client_api_rev.sh new_rev_id
# ⚠️⚠️⚠️️
client-api = { git = "https://github.com/AppFlowy-IO/AppFlowy-Cloud", rev = "6262816043efeede8823d7a7ea252083adf407e9" }
client-api = { git = "https://github.com/AppFlowy-IO/AppFlowy-Cloud", rev = "9884d93aa2805013f36a79c1757174a0b5063065" }
[dependencies]
serde_json.workspace = true

View File

@ -215,7 +215,7 @@ checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da"
[[package]]
name = "app-error"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=6262816043efeede8823d7a7ea252083adf407e9#6262816043efeede8823d7a7ea252083adf407e9"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=9884d93aa2805013f36a79c1757174a0b5063065#9884d93aa2805013f36a79c1757174a0b5063065"
dependencies = [
"anyhow",
"bincode",
@ -235,7 +235,7 @@ dependencies = [
[[package]]
name = "appflowy-ai-client"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=6262816043efeede8823d7a7ea252083adf407e9#6262816043efeede8823d7a7ea252083adf407e9"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=9884d93aa2805013f36a79c1757174a0b5063065#9884d93aa2805013f36a79c1757174a0b5063065"
dependencies = [
"anyhow",
"bytes",
@ -561,7 +561,7 @@ dependencies = [
[[package]]
name = "client-api"
version = "0.2.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=6262816043efeede8823d7a7ea252083adf407e9#6262816043efeede8823d7a7ea252083adf407e9"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=9884d93aa2805013f36a79c1757174a0b5063065#9884d93aa2805013f36a79c1757174a0b5063065"
dependencies = [
"again",
"anyhow",
@ -576,6 +576,7 @@ dependencies = [
"collab",
"collab-rt-entity",
"collab-rt-protocol",
"futures",
"futures-core",
"futures-util",
"getrandom 0.2.12",
@ -583,6 +584,8 @@ dependencies = [
"infra",
"mime",
"parking_lot 0.12.1",
"percent-encoding",
"pin-project",
"prost",
"reqwest",
"scraper 0.17.1",
@ -607,7 +610,7 @@ dependencies = [
[[package]]
name = "client-api-entity"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=6262816043efeede8823d7a7ea252083adf407e9#6262816043efeede8823d7a7ea252083adf407e9"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=9884d93aa2805013f36a79c1757174a0b5063065#9884d93aa2805013f36a79c1757174a0b5063065"
dependencies = [
"collab-entity",
"collab-rt-entity",
@ -619,7 +622,7 @@ dependencies = [
[[package]]
name = "client-websocket"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=6262816043efeede8823d7a7ea252083adf407e9#6262816043efeede8823d7a7ea252083adf407e9"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=9884d93aa2805013f36a79c1757174a0b5063065#9884d93aa2805013f36a79c1757174a0b5063065"
dependencies = [
"futures-channel",
"futures-util",
@ -797,7 +800,7 @@ dependencies = [
[[package]]
name = "collab-rt-entity"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=6262816043efeede8823d7a7ea252083adf407e9#6262816043efeede8823d7a7ea252083adf407e9"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=9884d93aa2805013f36a79c1757174a0b5063065#9884d93aa2805013f36a79c1757174a0b5063065"
dependencies = [
"anyhow",
"bincode",
@ -822,7 +825,7 @@ dependencies = [
[[package]]
name = "collab-rt-protocol"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=6262816043efeede8823d7a7ea252083adf407e9#6262816043efeede8823d7a7ea252083adf407e9"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=9884d93aa2805013f36a79c1757174a0b5063065#9884d93aa2805013f36a79c1757174a0b5063065"
dependencies = [
"anyhow",
"async-trait",
@ -1036,10 +1039,11 @@ checksum = "7e962a19be5cfc3f3bf6dd8f61eb50107f356ad6270fbb3ed41476571db78be5"
[[package]]
name = "database-entity"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=6262816043efeede8823d7a7ea252083adf407e9#6262816043efeede8823d7a7ea252083adf407e9"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=9884d93aa2805013f36a79c1757174a0b5063065#9884d93aa2805013f36a79c1757174a0b5063065"
dependencies = [
"anyhow",
"app-error",
"appflowy-ai-client",
"bincode",
"chrono",
"collab-entity",
@ -1919,7 +1923,7 @@ dependencies = [
[[package]]
name = "gotrue"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=6262816043efeede8823d7a7ea252083adf407e9#6262816043efeede8823d7a7ea252083adf407e9"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=9884d93aa2805013f36a79c1757174a0b5063065#9884d93aa2805013f36a79c1757174a0b5063065"
dependencies = [
"anyhow",
"futures-util",
@ -1936,7 +1940,7 @@ dependencies = [
[[package]]
name = "gotrue-entity"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=6262816043efeede8823d7a7ea252083adf407e9#6262816043efeede8823d7a7ea252083adf407e9"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=9884d93aa2805013f36a79c1757174a0b5063065#9884d93aa2805013f36a79c1757174a0b5063065"
dependencies = [
"anyhow",
"app-error",
@ -2237,7 +2241,7 @@ dependencies = [
[[package]]
name = "infra"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=6262816043efeede8823d7a7ea252083adf407e9#6262816043efeede8823d7a7ea252083adf407e9"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=9884d93aa2805013f36a79c1757174a0b5063065#9884d93aa2805013f36a79c1757174a0b5063065"
dependencies = [
"anyhow",
"bytes",
@ -2378,6 +2382,7 @@ dependencies = [
"async-trait",
"atomic_refcell",
"bytes",
"cfg-if 1.0.0",
"chrono",
"futures",
"futures-core",
@ -3951,7 +3956,7 @@ dependencies = [
[[package]]
name = "shared-entity"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=6262816043efeede8823d7a7ea252083adf407e9#6262816043efeede8823d7a7ea252083adf407e9"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=9884d93aa2805013f36a79c1757174a0b5063065#9884d93aa2805013f36a79c1757174a0b5063065"
dependencies = [
"anyhow",
"app-error",

View File

@ -54,7 +54,7 @@ yrs = "0.18.8"
# Run the script:
# scripts/tool/update_client_api_rev.sh new_rev_id
# ⚠️⚠️⚠️️
client-api = { git = "https://github.com/AppFlowy-IO/AppFlowy-Cloud", rev = "6262816043efeede8823d7a7ea252083adf407e9" }
client-api = { git = "https://github.com/AppFlowy-IO/AppFlowy-Cloud", rev = "9884d93aa2805013f36a79c1757174a0b5063065" }
[profile.dev]
opt-level = 0

View File

@ -163,7 +163,7 @@ checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da"
[[package]]
name = "app-error"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=6262816043efeede8823d7a7ea252083adf407e9#6262816043efeede8823d7a7ea252083adf407e9"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=9884d93aa2805013f36a79c1757174a0b5063065#9884d93aa2805013f36a79c1757174a0b5063065"
dependencies = [
"anyhow",
"bincode",
@ -183,7 +183,7 @@ dependencies = [
[[package]]
name = "appflowy-ai-client"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=6262816043efeede8823d7a7ea252083adf407e9#6262816043efeede8823d7a7ea252083adf407e9"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=9884d93aa2805013f36a79c1757174a0b5063065#9884d93aa2805013f36a79c1757174a0b5063065"
dependencies = [
"anyhow",
"bytes",
@ -746,7 +746,7 @@ dependencies = [
[[package]]
name = "client-api"
version = "0.2.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=6262816043efeede8823d7a7ea252083adf407e9#6262816043efeede8823d7a7ea252083adf407e9"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=9884d93aa2805013f36a79c1757174a0b5063065#9884d93aa2805013f36a79c1757174a0b5063065"
dependencies = [
"again",
"anyhow",
@ -761,6 +761,7 @@ dependencies = [
"collab",
"collab-rt-entity",
"collab-rt-protocol",
"futures",
"futures-core",
"futures-util",
"getrandom 0.2.12",
@ -768,6 +769,8 @@ dependencies = [
"infra",
"mime",
"parking_lot 0.12.1",
"percent-encoding",
"pin-project",
"prost",
"reqwest",
"scraper 0.17.1",
@ -792,7 +795,7 @@ dependencies = [
[[package]]
name = "client-api-entity"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=6262816043efeede8823d7a7ea252083adf407e9#6262816043efeede8823d7a7ea252083adf407e9"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=9884d93aa2805013f36a79c1757174a0b5063065#9884d93aa2805013f36a79c1757174a0b5063065"
dependencies = [
"collab-entity",
"collab-rt-entity",
@ -804,7 +807,7 @@ dependencies = [
[[package]]
name = "client-websocket"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=6262816043efeede8823d7a7ea252083adf407e9#6262816043efeede8823d7a7ea252083adf407e9"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=9884d93aa2805013f36a79c1757174a0b5063065#9884d93aa2805013f36a79c1757174a0b5063065"
dependencies = [
"futures-channel",
"futures-util",
@ -1053,7 +1056,7 @@ dependencies = [
[[package]]
name = "collab-rt-entity"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=6262816043efeede8823d7a7ea252083adf407e9#6262816043efeede8823d7a7ea252083adf407e9"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=9884d93aa2805013f36a79c1757174a0b5063065#9884d93aa2805013f36a79c1757174a0b5063065"
dependencies = [
"anyhow",
"bincode",
@ -1078,7 +1081,7 @@ dependencies = [
[[package]]
name = "collab-rt-protocol"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=6262816043efeede8823d7a7ea252083adf407e9#6262816043efeede8823d7a7ea252083adf407e9"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=9884d93aa2805013f36a79c1757174a0b5063065#9884d93aa2805013f36a79c1757174a0b5063065"
dependencies = [
"anyhow",
"async-trait",
@ -1281,9 +1284,9 @@ dependencies = [
[[package]]
name = "crossbeam-utils"
version = "0.8.19"
version = "0.8.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "248e3bacc7dc6baa3b21e405ee045c3047101a49145e7e9eca583ab4c2ca5345"
checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80"
[[package]]
name = "crunchy"
@ -1439,10 +1442,11 @@ checksum = "7e962a19be5cfc3f3bf6dd8f61eb50107f356ad6270fbb3ed41476571db78be5"
[[package]]
name = "database-entity"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=6262816043efeede8823d7a7ea252083adf407e9#6262816043efeede8823d7a7ea252083adf407e9"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=9884d93aa2805013f36a79c1757174a0b5063065#9884d93aa2805013f36a79c1757174a0b5063065"
dependencies = [
"anyhow",
"app-error",
"appflowy-ai-client",
"bincode",
"chrono",
"collab-entity",
@ -1889,6 +1893,7 @@ dependencies = [
"flowy-derive",
"flowy-error",
"flowy-notification",
"flowy-sidecar",
"flowy-sqlite",
"futures",
"lib-dispatch",
@ -2352,6 +2357,24 @@ dependencies = [
"serde_repr",
]
[[package]]
name = "flowy-sidecar"
version = "0.1.0"
dependencies = [
"anyhow",
"crossbeam-utils",
"lib-infra",
"log",
"once_cell",
"parking_lot 0.12.1",
"serde",
"serde_json",
"thiserror",
"tokio",
"tokio-stream",
"tracing",
]
[[package]]
name = "flowy-sqlite"
version = "0.1.0"
@ -2968,7 +2991,7 @@ dependencies = [
[[package]]
name = "gotrue"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=6262816043efeede8823d7a7ea252083adf407e9#6262816043efeede8823d7a7ea252083adf407e9"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=9884d93aa2805013f36a79c1757174a0b5063065#9884d93aa2805013f36a79c1757174a0b5063065"
dependencies = [
"anyhow",
"futures-util",
@ -2985,7 +3008,7 @@ dependencies = [
[[package]]
name = "gotrue-entity"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=6262816043efeede8823d7a7ea252083adf407e9#6262816043efeede8823d7a7ea252083adf407e9"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=9884d93aa2805013f36a79c1757174a0b5063065#9884d93aa2805013f36a79c1757174a0b5063065"
dependencies = [
"anyhow",
"app-error",
@ -3422,7 +3445,7 @@ dependencies = [
[[package]]
name = "infra"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=6262816043efeede8823d7a7ea252083adf407e9#6262816043efeede8823d7a7ea252083adf407e9"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=9884d93aa2805013f36a79c1757174a0b5063065#9884d93aa2805013f36a79c1757174a0b5063065"
dependencies = [
"anyhow",
"bytes",
@ -3675,6 +3698,7 @@ dependencies = [
"async-trait",
"atomic_refcell",
"bytes",
"cfg-if",
"chrono",
"futures",
"futures-core",
@ -5777,9 +5801,9 @@ dependencies = [
[[package]]
name = "serde_json"
version = "1.0.114"
version = "1.0.118"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c5f09b1bd632ef549eaa9f60a1f8de742bdbc698e6cee2095fc84dde5f549ae0"
checksum = "d947f6b3163d8857ea16c4fa0dd4840d52f3041039a85decd46867eb1abef2e4"
dependencies = [
"indexmap 2.2.6",
"itoa 1.0.10",
@ -5930,7 +5954,7 @@ dependencies = [
[[package]]
name = "shared-entity"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=6262816043efeede8823d7a7ea252083adf407e9#6262816043efeede8823d7a7ea252083adf407e9"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=9884d93aa2805013f36a79c1757174a0b5063065#9884d93aa2805013f36a79c1757174a0b5063065"
dependencies = [
"anyhow",
"app-error",

View File

@ -52,7 +52,7 @@ collab-user = { version = "0.2" }
# Run the script:
# scripts/tool/update_client_api_rev.sh new_rev_id
# ⚠️⚠️⚠️️
client-api = { git = "https://github.com/AppFlowy-IO/AppFlowy-Cloud", rev = "6262816043efeede8823d7a7ea252083adf407e9" }
client-api = { git = "https://github.com/AppFlowy-IO/AppFlowy-Cloud", rev = "9884d93aa2805013f36a79c1757174a0b5063065" }
[dependencies]
serde_json.workspace = true

View File

@ -163,7 +163,7 @@ checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da"
[[package]]
name = "app-error"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=6262816043efeede8823d7a7ea252083adf407e9#6262816043efeede8823d7a7ea252083adf407e9"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=9884d93aa2805013f36a79c1757174a0b5063065#9884d93aa2805013f36a79c1757174a0b5063065"
dependencies = [
"anyhow",
"bincode",
@ -183,7 +183,7 @@ dependencies = [
[[package]]
name = "appflowy-ai-client"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=6262816043efeede8823d7a7ea252083adf407e9#6262816043efeede8823d7a7ea252083adf407e9"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=9884d93aa2805013f36a79c1757174a0b5063065#9884d93aa2805013f36a79c1757174a0b5063065"
dependencies = [
"anyhow",
"bytes",
@ -664,7 +664,7 @@ dependencies = [
[[package]]
name = "client-api"
version = "0.2.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=6262816043efeede8823d7a7ea252083adf407e9#6262816043efeede8823d7a7ea252083adf407e9"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=9884d93aa2805013f36a79c1757174a0b5063065#9884d93aa2805013f36a79c1757174a0b5063065"
dependencies = [
"again",
"anyhow",
@ -679,6 +679,7 @@ dependencies = [
"collab",
"collab-rt-entity",
"collab-rt-protocol",
"futures",
"futures-core",
"futures-util",
"getrandom 0.2.10",
@ -686,6 +687,8 @@ dependencies = [
"infra",
"mime",
"parking_lot 0.12.1",
"percent-encoding",
"pin-project",
"prost",
"reqwest",
"scraper 0.17.1",
@ -710,7 +713,7 @@ dependencies = [
[[package]]
name = "client-api-entity"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=6262816043efeede8823d7a7ea252083adf407e9#6262816043efeede8823d7a7ea252083adf407e9"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=9884d93aa2805013f36a79c1757174a0b5063065#9884d93aa2805013f36a79c1757174a0b5063065"
dependencies = [
"collab-entity",
"collab-rt-entity",
@ -722,7 +725,7 @@ dependencies = [
[[package]]
name = "client-websocket"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=6262816043efeede8823d7a7ea252083adf407e9#6262816043efeede8823d7a7ea252083adf407e9"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=9884d93aa2805013f36a79c1757174a0b5063065#9884d93aa2805013f36a79c1757174a0b5063065"
dependencies = [
"futures-channel",
"futures-util",
@ -931,7 +934,7 @@ dependencies = [
[[package]]
name = "collab-rt-entity"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=6262816043efeede8823d7a7ea252083adf407e9#6262816043efeede8823d7a7ea252083adf407e9"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=9884d93aa2805013f36a79c1757174a0b5063065#9884d93aa2805013f36a79c1757174a0b5063065"
dependencies = [
"anyhow",
"bincode",
@ -956,7 +959,7 @@ dependencies = [
[[package]]
name = "collab-rt-protocol"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=6262816043efeede8823d7a7ea252083adf407e9#6262816043efeede8823d7a7ea252083adf407e9"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=9884d93aa2805013f36a79c1757174a0b5063065#9884d93aa2805013f36a79c1757174a0b5063065"
dependencies = [
"anyhow",
"async-trait",
@ -1273,10 +1276,11 @@ checksum = "c2e66c9d817f1720209181c316d28635c050fa304f9c79e47a520882661b7308"
[[package]]
name = "database-entity"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=6262816043efeede8823d7a7ea252083adf407e9#6262816043efeede8823d7a7ea252083adf407e9"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=9884d93aa2805013f36a79c1757174a0b5063065#9884d93aa2805013f36a79c1757174a0b5063065"
dependencies = [
"anyhow",
"app-error",
"appflowy-ai-client",
"bincode",
"chrono",
"collab-entity",
@ -1662,8 +1666,10 @@ name = "flowy-chat"
version = "0.1.0"
dependencies = [
"allo-isolate",
"anyhow",
"bytes",
"dashmap",
"dotenv",
"flowy-chat-pub",
"flowy-codegen",
"flowy-derive",
@ -1675,10 +1681,15 @@ dependencies = [
"lib-dispatch",
"lib-infra",
"log",
"parking_lot 0.12.1",
"protobuf",
"serde",
"serde_json",
"strum_macros 0.21.1",
"tokio",
"tokio-stream",
"tracing",
"tracing-subscriber",
"uuid",
"validator",
]
@ -2147,7 +2158,6 @@ version = "0.1.0"
dependencies = [
"anyhow",
"crossbeam-utils",
"dotenv",
"lib-infra",
"log",
"once_cell",
@ -2158,8 +2168,6 @@ dependencies = [
"tokio",
"tokio-stream",
"tracing",
"tracing-subscriber",
"uuid",
]
[[package]]
@ -2586,7 +2594,7 @@ dependencies = [
[[package]]
name = "gotrue"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=6262816043efeede8823d7a7ea252083adf407e9#6262816043efeede8823d7a7ea252083adf407e9"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=9884d93aa2805013f36a79c1757174a0b5063065#9884d93aa2805013f36a79c1757174a0b5063065"
dependencies = [
"anyhow",
"futures-util",
@ -2603,7 +2611,7 @@ dependencies = [
[[package]]
name = "gotrue-entity"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=6262816043efeede8823d7a7ea252083adf407e9#6262816043efeede8823d7a7ea252083adf407e9"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=9884d93aa2805013f36a79c1757174a0b5063065#9884d93aa2805013f36a79c1757174a0b5063065"
dependencies = [
"anyhow",
"app-error",
@ -2968,7 +2976,7 @@ dependencies = [
[[package]]
name = "infra"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=6262816043efeede8823d7a7ea252083adf407e9#6262816043efeede8823d7a7ea252083adf407e9"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=9884d93aa2805013f36a79c1757174a0b5063065#9884d93aa2805013f36a79c1757174a0b5063065"
dependencies = [
"anyhow",
"bytes",
@ -5069,7 +5077,7 @@ dependencies = [
[[package]]
name = "shared-entity"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=6262816043efeede8823d7a7ea252083adf407e9#6262816043efeede8823d7a7ea252083adf407e9"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=9884d93aa2805013f36a79c1757174a0b5063065#9884d93aa2805013f36a79c1757174a0b5063065"
dependencies = [
"anyhow",
"app-error",

View File

@ -99,8 +99,8 @@ validator = { version = "0.16.1", features = ["derive"] }
# Run the script.add_workspace_members:
# scripts/tool/update_client_api_rev.sh new_rev_id
# ⚠️⚠️⚠️️
client-api = { git = "https://github.com/AppFlowy-IO/AppFlowy-Cloud", rev = "6262816043efeede8823d7a7ea252083adf407e9" }
client-api-entity = { git = "https://github.com/AppFlowy-IO/AppFlowy-Cloud", rev = "6262816043efeede8823d7a7ea252083adf407e9" }
client-api = { git = "https://github.com/AppFlowy-IO/AppFlowy-Cloud", rev = "9884d93aa2805013f36a79c1757174a0b5063065" }
client-api-entity = { git = "https://github.com/AppFlowy-IO/AppFlowy-Cloud", rev = "9884d93aa2805013f36a79c1757174a0b5063065" }
[profile.dev]
opt-level = 1

View File

@ -5,7 +5,7 @@ use flowy_chat::entities::ChatMessageListPB;
use flowy_chat::notification::ChatNotification;
use flowy_chat_pub::cloud::ChatMessageType;
use futures_util::StreamExt;
use std::time::Duration;
#[tokio::test]
@ -19,8 +19,8 @@ async fn af_cloud_create_chat_message_test() {
let chat_id = view.id.clone();
let chat_service = test.server_provider.get_server().unwrap().chat_service();
for i in 0..10 {
let mut stream = chat_service
.send_chat_message(
let _ = chat_service
.save_question(
&current_workspace.id,
&chat_id,
&format!("hello world {}", i),
@ -28,9 +28,6 @@ async fn af_cloud_create_chat_message_test() {
)
.await
.unwrap();
while let Some(message) = stream.next().await {
message.unwrap();
}
}
let rx = test
.notification_sender
@ -77,8 +74,8 @@ async fn af_cloud_load_remote_system_message_test() {
let chat_service = test.server_provider.get_server().unwrap().chat_service();
for i in 0..10 {
let mut stream = chat_service
.send_chat_message(
let _ = chat_service
.save_question(
&current_workspace.id,
&chat_id,
&format!("hello server {}", i),
@ -86,9 +83,6 @@ async fn af_cloud_load_remote_system_message_test() {
)
.await
.unwrap();
while let Some(message) = stream.next().await {
message.unwrap();
}
}
let rx = test

View File

@ -20,15 +20,7 @@ pub trait ChatCloudService: Send + Sync + 'static {
chat_id: &str,
) -> FutureResult<(), FlowyError>;
async fn send_chat_message(
&self,
workspace_id: &str,
chat_id: &str,
message: &str,
message_type: ChatMessageType,
) -> Result<ChatMessageStream, FlowyError>;
fn send_question(
fn save_question(
&self,
workspace_id: &str,
chat_id: &str,
@ -44,13 +36,20 @@ pub trait ChatCloudService: Send + Sync + 'static {
question_id: i64,
) -> FutureResult<ChatMessage, FlowyError>;
async fn stream_answer(
async fn ask_question(
&self,
workspace_id: &str,
chat_id: &str,
message_id: i64,
) -> Result<StreamAnswer, FlowyError>;
fn generate_answer(
&self,
workspace_id: &str,
chat_id: &str,
question_message_id: i64,
) -> FutureResult<ChatMessage, FlowyError>;
fn get_chat_messages(
&self,
workspace_id: &str,
@ -65,11 +64,4 @@ pub trait ChatCloudService: Send + Sync + 'static {
chat_id: &str,
message_id: i64,
) -> FutureResult<RepeatedRelatedQuestion, FlowyError>;
fn generate_answer(
&self,
workspace_id: &str,
chat_id: &str,
question_message_id: i64,
) -> FutureResult<ChatMessage, FlowyError>;
}

View File

@ -28,6 +28,17 @@ futures.workspace = true
allo-isolate = { version = "^0.1", features = ["catch-unwind"] }
log = "0.4.21"
flowy-sidecar = { workspace = true }
serde = { workspace = true, features = ["derive"] }
serde_json = { workspace = true }
anyhow = "1.0.86"
tokio-stream = "0.1.15"
parking_lot.workspace = true
[dev-dependencies]
dotenv = "0.15.0"
uuid.workspace = true
tracing-subscriber = { version = "0.3.17", features = ["registry", "env-filter", "ansi", "json"] }
[build-dependencies]
flowy-codegen.workspace = true

View File

@ -1,5 +1,5 @@
CHAT_BIN_PATH=
LOCAL_AI_ROOT_PATH=
LOCAL_AI_MODEL_DIR=
LOCAL_AI_CHAT_MODEL_NAME=
LOCAL_AI_EMBEDDING_MODEL_NAME=

View File

@ -93,7 +93,7 @@ impl Chat {
let question = self
.chat_service
.send_question(&workspace_id, &self.chat_id, message, message_type)
.save_question(&workspace_id, &self.chat_id, message, message_type)
.await
.map_err(|err| {
error!("Failed to send question: {}", err);
@ -114,7 +114,7 @@ impl Chat {
tokio::spawn(async move {
let mut text_sink = IsolateSink::new(Isolate::new(text_stream_port));
match cloud_service
.stream_answer(&workspace_id, &chat_id, question_id)
.ask_question(&workspace_id, &chat_id, question_id)
.await
{
Ok(mut stream) => {

View File

@ -1,3 +1,4 @@
use crate::local_ai::manager::LocalAISetting;
use flowy_chat_pub::cloud::{
ChatMessage, RelatedQuestion, RepeatedChatMessage, RepeatedRelatedQuestion,
};
@ -205,3 +206,40 @@ impl From<RepeatedRelatedQuestion> for RepeatedRelatedQuestionPB {
}
}
}
#[derive(Debug, Clone, Default, ProtoBuf)]
pub struct LocalAIChatSettingPB {
#[pb(index = 1)]
pub bin_dir: String,
#[pb(index = 2)]
pub chat_bin: String,
#[pb(index = 3)]
pub chat_model: String,
#[pb(index = 4)]
pub enabled: bool,
}
impl From<LocalAISetting> for LocalAIChatSettingPB {
fn from(value: LocalAISetting) -> Self {
LocalAIChatSettingPB {
bin_dir: value.chat_bin,
chat_bin: value.bin_dir,
chat_model: value.chat_model,
enabled: value.enabled,
}
}
}
impl From<LocalAIChatSettingPB> for LocalAISetting {
fn from(value: LocalAIChatSettingPB) -> Self {
LocalAISetting {
chat_bin: value.bin_dir,
bin_dir: value.chat_bin,
chat_model: value.chat_model,
enabled: value.enabled,
}
}
}

View File

@ -1,4 +1,5 @@
use flowy_chat_pub::cloud::ChatMessageType;
use std::path::Path;
use std::sync::{Arc, Weak};
use validator::Validate;
@ -110,3 +111,53 @@ pub(crate) async fn stop_stream_handler(
chat_manager.stop_stream(&data.chat_id).await?;
Ok(())
}
#[tracing::instrument(level = "debug", skip_all, err)]
pub(crate) async fn get_local_ai_setting_handler(
chat_manager: AFPluginState<Weak<ChatManager>>,
) -> DataResult<LocalAIChatSettingPB, FlowyError> {
let chat_manager = upgrade_chat_manager(chat_manager)?;
let setting = chat_manager.get_local_ai_setting()?;
let pb = setting.into();
data_result_ok(pb)
}
#[tracing::instrument(level = "debug", skip_all, err)]
pub(crate) async fn update_local_ai_setting_handler(
data: AFPluginData<LocalAIChatSettingPB>,
chat_manager: AFPluginState<Weak<ChatManager>>,
) -> Result<(), FlowyError> {
let data = data.into_inner();
let chat_bin_path = Path::new(&data.bin_dir);
if !chat_bin_path.exists() {
return Err(
FlowyError::invalid_data()
.with_context(format!("Chat binary path does not exist: {}", data.bin_dir)),
);
}
if !chat_bin_path.is_file() {
return Err(
FlowyError::invalid_data()
.with_context(format!("Chat binary path is not a file: {}", data.bin_dir)),
);
}
// Check if local_model_dir exists and is a directory
let local_model_dir = Path::new(&data.chat_bin);
if !local_model_dir.exists() {
return Err(FlowyError::invalid_data().with_context(format!(
"Local model directory does not exist: {}",
data.chat_bin
)));
}
if !local_model_dir.is_dir() {
return Err(FlowyError::invalid_data().with_context(format!(
"Local model directory is not a directory: {}",
data.chat_bin
)));
}
let chat_manager = upgrade_chat_manager(chat_manager)?;
chat_manager.update_local_ai_setting(data.into())?;
Ok(())
}

View File

@ -18,6 +18,11 @@ pub fn init(chat_manager: Weak<ChatManager>) -> AFPlugin {
.event(ChatEvent::GetRelatedQuestion, get_related_question_handler)
.event(ChatEvent::GetAnswerForQuestion, get_answer_handler)
.event(ChatEvent::StopStream, stop_stream_handler)
.event(ChatEvent::GetLocalAISetting, get_local_ai_setting_handler)
.event(
ChatEvent::UpdateLocalAISetting,
update_local_ai_setting_handler,
)
}
#[derive(Clone, Copy, PartialEq, Eq, Debug, Display, Hash, ProtoBuf_Enum, Flowy_Event)]
@ -41,4 +46,10 @@ pub enum ChatEvent {
#[event(input = "ChatMessageIdPB", output = "ChatMessagePB")]
GetAnswerForQuestion = 5,
#[event(input = "LocalAIChatSettingPB")]
UpdateLocalAISetting = 6,
#[event(output = "LocalAIChatSettingPB")]
GetLocalAISetting = 7,
}

View File

@ -3,6 +3,7 @@ pub mod event_map;
mod chat;
pub mod entities;
pub mod local_ai;
pub mod manager;
pub mod notification;
mod persistence;

View File

@ -0,0 +1,116 @@
use anyhow::anyhow;
use flowy_error::FlowyError;
use flowy_sidecar::core::parser::ResponseParser;
use flowy_sidecar::core::plugin::{Plugin, PluginId};
use flowy_sidecar::error::{RemoteError, SidecarError};
use serde_json::json;
use serde_json::Value as JsonValue;
use std::sync::Weak;
use tokio_stream::wrappers::ReceiverStream;
pub struct ChatPluginOperation {
plugin: Weak<Plugin>,
}
impl ChatPluginOperation {
pub fn new(plugin: Weak<Plugin>) -> Self {
ChatPluginOperation { plugin }
}
pub async fn send_message(
&self,
chat_id: &str,
_plugin_id: PluginId,
message: &str,
) -> Result<String, SidecarError> {
let plugin = self
.plugin
.upgrade()
.ok_or(SidecarError::Internal(anyhow!("Plugin is dropped")))?;
let params = json!({"chat_id": chat_id, "method": "answer", "params": {"content": message}});
let resp = plugin
.async_request::<ChatResponseParser>("handle", &params)
.await?;
Ok(resp)
}
pub async fn stream_message(
&self,
chat_id: &str,
_plugin_id: PluginId,
message: &str,
) -> Result<ReceiverStream<Result<String, SidecarError>>, FlowyError> {
let plugin = self
.plugin
.upgrade()
.ok_or(FlowyError::internal().with_context("Plugin is dropped"))?;
let params =
json!({"chat_id": chat_id, "method": "stream_answer", "params": {"content": message}});
let stream = plugin
.stream_request::<ChatStreamResponseParser>("handle", &params)
.map_err(|err| FlowyError::internal().with_context(err.to_string()))?;
Ok(stream)
}
pub async fn get_related_questions(
&self,
chat_id: &str,
) -> Result<Vec<serde_json::Value>, SidecarError> {
let plugin = self
.plugin
.upgrade()
.ok_or(SidecarError::Internal(anyhow!("Plugin is dropped")))?;
let params = json!({"chat_id": chat_id, "method": "related_question"});
let resp = plugin
.async_request::<ChatRelatedQuestionsResponseParser>("handle", &params)
.await?;
Ok(resp)
}
}
pub struct ChatResponseParser;
impl ResponseParser for ChatResponseParser {
type ValueType = String;
fn parse_json(json: JsonValue) -> Result<Self::ValueType, RemoteError> {
if json.is_object() {
if let Some(data) = json.get("data") {
if let Some(message) = data.as_str() {
return Ok(message.to_string());
}
}
}
return Err(RemoteError::ParseResponse(json));
}
}
pub struct ChatStreamResponseParser;
impl ResponseParser for ChatStreamResponseParser {
type ValueType = String;
fn parse_json(json: JsonValue) -> Result<Self::ValueType, RemoteError> {
if let Some(message) = json.as_str() {
return Ok(message.to_string());
}
return Err(RemoteError::ParseResponse(json));
}
}
pub struct ChatRelatedQuestionsResponseParser;
impl ResponseParser for ChatRelatedQuestionsResponseParser {
type ValueType = Vec<JsonValue>;
fn parse_json(json: JsonValue) -> Result<Self::ValueType, RemoteError> {
if json.is_object() {
if let Some(data) = json.get("data") {
if let Some(values) = data.as_array() {
return Ok(values.clone());
}
}
}
return Err(RemoteError::ParseResponse(json));
}
}

View File

@ -1,8 +1,9 @@
use crate::core::parser::SimilarityResponseParser;
use crate::core::plugin::Plugin;
use crate::error::SidecarError;
use anyhow::anyhow;
use flowy_sidecar::core::parser::ResponseParser;
use flowy_sidecar::core::plugin::Plugin;
use flowy_sidecar::error::{RemoteError, SidecarError};
use serde_json::json;
use serde_json::Value as JsonValue;
use std::sync::Weak;
pub struct EmbeddingPluginOperation {
@ -30,3 +31,20 @@ impl EmbeddingPluginOperation {
.await
}
}
pub struct SimilarityResponseParser;
impl ResponseParser for SimilarityResponseParser {
type ValueType = f64;
fn parse_json(json: JsonValue) -> Result<Self::ValueType, RemoteError> {
if json.is_object() {
if let Some(data) = json.get("data") {
if let Some(score) = data.get("score").and_then(|v| v.as_f64()) {
return Ok(score);
}
}
}
return Err(RemoteError::ParseResponse(json));
}
}

View File

@ -0,0 +1,176 @@
use crate::local_ai::chat_plugin::ChatPluginOperation;
use dashmap::DashMap;
use flowy_error::{FlowyError, FlowyResult};
use flowy_sidecar::core::plugin::{PluginId, PluginInfo};
use flowy_sidecar::error::SidecarError;
use flowy_sidecar::manager::SidecarManager;
use log::error;
use serde::{Deserialize, Serialize};
use std::path::PathBuf;
use std::sync::Arc;
use tokio::sync::RwLock;
use tokio_stream::wrappers::ReceiverStream;
use tracing::trace;
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
pub struct LocalAISetting {
pub bin_dir: String,
pub chat_bin: String,
pub chat_model: String,
pub enabled: bool,
}
impl LocalAISetting {
pub fn validate(&self) -> FlowyResult<()> {
ChatPluginConfig::new(&self.bin_dir, &self.chat_bin, &self.chat_model)?;
Ok(())
}
pub fn get_chat_plugin_config(&self) -> FlowyResult<ChatPluginConfig> {
let config = ChatPluginConfig::new(&self.bin_dir, &self.chat_bin, &self.chat_model)?;
Ok(config)
}
}
pub struct LocalAIManager {
sidecar_manager: Arc<SidecarManager>,
chat_plugin_config: RwLock<Option<ChatPluginConfig>>,
plugin_map: DashMap<PathBuf, PluginId>,
chat_plugin_id: RwLock<Option<PluginId>>,
}
impl LocalAIManager {
pub fn new(sidecar_manager: Arc<SidecarManager>) -> Self {
Self {
sidecar_manager,
chat_plugin_config: RwLock::new(None),
plugin_map: Default::default(),
chat_plugin_id: Default::default(),
}
}
pub async fn stream_chat_message(
&self,
chat_id: &str,
message: &str,
) -> FlowyResult<ReceiverStream<anyhow::Result<String, SidecarError>>> {
let plugin_id = self
.chat_plugin_id
.read()
.await
.ok_or_else(|| FlowyError::internal().with_context("chat plugin not set"))?;
let plugin = self
.sidecar_manager
.get_plugin(plugin_id)
.await
.map_err(|err| FlowyError::internal().with_context(err.to_string()))?;
let operation = ChatPluginOperation::new(plugin);
let stream = operation
.stream_message(chat_id, plugin_id, message)
.await?;
Ok(stream)
}
pub async fn setup_chat_plugin(&self, config: ChatPluginConfig) -> FlowyResult<()> {
// If the chat_bin_path is different, remove the old plugin
if let Some(chat_plugin_config) = self.chat_plugin_config.read().await.as_ref() {
if chat_plugin_config.chat_bin_path != config.chat_bin_path {
trace!("remove old plugin: {:?}", chat_plugin_config.chat_bin_path);
if let Some(entry) = self.plugin_map.remove(&chat_plugin_config.chat_bin_path) {
if let Err(err) = self.sidecar_manager.remove_plugin(entry.1).await {
error!("remove plugin failed: {:?}", err);
}
}
}
}
// create new plugin
let plugin_info = PluginInfo {
name: "chat_plugin".to_string(),
exec_path: config.chat_bin_path.clone(),
};
let plugin = self
.sidecar_manager
.create_plugin(plugin_info)
.await
.unwrap();
// init plugin
let model_path = config.chat_model_path;
self
.sidecar_manager
.init_plugin(
plugin,
serde_json::json!({
"absolute_chat_model_path": model_path,
}),
)
.map_err(|err| FlowyError::internal().with_context(err.to_string()))?;
self.chat_plugin_id.write().await.replace(plugin);
self.plugin_map.insert(config.chat_bin_path, plugin);
Ok(())
}
}
#[derive(Debug, Clone)]
pub struct ChatPluginConfig {
bin_dir: PathBuf,
chat_bin_path: PathBuf,
chat_model_path: PathBuf,
}
impl ChatPluginConfig {
pub fn new(bin_dir: &str, chat_bin: &str, chat_model_name: &str) -> FlowyResult<Self> {
// check bin_dir exists and is a directory
let bin_dir = PathBuf::from(bin_dir);
if !bin_dir.exists() {
return Err(
FlowyError::invalid_data().with_context(format!("bin path not exists: {:?}", bin_dir)),
);
}
if !bin_dir.is_dir() {
return Err(
FlowyError::invalid_data()
.with_context(format!("bin path is not directory: {:?}", bin_dir)),
);
}
let chat_bin_path = bin_dir.join(chat_bin);
if !chat_bin_path.exists() {
return Err(FlowyError::invalid_data().with_context(format!(
"Chat binary path does not exist: {:?}",
chat_bin_path
)));
}
if !chat_bin_path.is_file() {
return Err(FlowyError::invalid_data().with_context(format!(
"Chat binary path is not a file: {:?}",
chat_bin_path
)));
}
// Check if local_model_dir exists and is a directory
let chat_model_path = bin_dir.join(&chat_model_name);
if !chat_model_path.exists() {
return Err(
FlowyError::invalid_data()
.with_context(format!("Local model does not exist: {:?}", chat_model_path)),
);
}
if !chat_model_path.is_file() {
return Err(
FlowyError::invalid_data()
.with_context(format!("Local model is not a file: {:?}", chat_model_path)),
);
}
Ok(Self {
bin_dir,
chat_bin_path,
chat_model_path,
})
}
}

View File

@ -1,2 +1,4 @@
pub mod chat_plugin;
pub mod manager;
pub mod embedding_plugin;

View File

@ -3,8 +3,8 @@ use crate::entities::{ChatMessageListPB, ChatMessagePB, RepeatedRelatedQuestionP
use crate::persistence::{insert_chat, ChatTable};
use dashmap::DashMap;
use flowy_chat_pub::cloud::{
ChatCloudService, ChatMessage, ChatMessageStream, ChatMessageType, MessageCursor,
RepeatedChatMessage, RepeatedRelatedQuestion, StreamAnswer,
ChatCloudService, ChatMessage, ChatMessageType, MessageCursor, RepeatedChatMessage,
RepeatedRelatedQuestion, StreamAnswer,
};
use flowy_error::{FlowyError, FlowyResult};
use flowy_sidecar::manager::SidecarManager;
@ -12,8 +12,13 @@ use flowy_sqlite::DBConnection;
use lib_infra::future::FutureResult;
use lib_infra::util::timestamp;
use crate::local_ai::manager::{LocalAIManager, LocalAISetting};
use flowy_sqlite::kv::KVStorePreferences;
use lib_infra::async_trait::async_trait;
use parking_lot::RwLock;
use std::sync::Arc;
use tracing::trace;
use tracing::{error, info, trace};
pub trait ChatUserService: Send + Sync + 'static {
fn user_id(&self) -> Result<i64, FlowyError>;
@ -26,24 +31,56 @@ pub struct ChatManager {
chat_service: Arc<ChatService>,
user_service: Arc<dyn ChatUserService>,
chats: Arc<DashMap<String, Arc<Chat>>>,
store_preferences: Arc<KVStorePreferences>,
}
const LOCAL_AI_SETTING_KEY: &str = "local_ai_setting";
impl ChatManager {
pub fn new(
cloud_service: Arc<dyn ChatCloudService>,
user_service: impl ChatUserService,
store_preferences: Arc<KVStorePreferences>,
) -> ChatManager {
let local_ai_setting = store_preferences
.get_object::<LocalAISetting>(LOCAL_AI_SETTING_KEY)
.unwrap_or_default();
let sidecar_manager = Arc::new(SidecarManager::new());
let chat_service = Arc::new(ChatService::new(cloud_service, sidecar_manager));
// Setup local AI chat plugin
let local_ai_manager = Arc::new(LocalAIManager::new(sidecar_manager));
setup_local_ai(&local_ai_setting, local_ai_manager.clone());
//
let chat_service = Arc::new(ChatService::new(
cloud_service,
local_ai_manager,
local_ai_setting,
));
let user_service = Arc::new(user_service);
Self {
chat_service,
user_service,
chats: Arc::new(DashMap::new()),
store_preferences,
}
}
pub fn update_local_ai_setting(&self, setting: LocalAISetting) -> FlowyResult<()> {
setting.validate()?;
self
.store_preferences
.set_object(LOCAL_AI_SETTING_KEY, setting.clone())?;
*self.chat_service.local_ai_setting.write() = setting;
Ok(())
}
pub fn get_local_ai_setting(&self) -> FlowyResult<LocalAISetting> {
let setting = self.chat_service.local_ai_setting.read().clone();
Ok(setting)
}
pub async fn open_chat(&self, chat_id: &str) -> Result<(), FlowyError> {
trace!("open chat: {}", chat_id);
self.chats.entry(chat_id.to_string()).or_insert_with(|| {
@ -186,6 +223,21 @@ impl ChatManager {
}
}
fn setup_local_ai(local_ai_setting: &LocalAISetting, local_ai_manager: Arc<LocalAIManager>) {
if let Ok(config) = local_ai_setting.get_chat_plugin_config() {
tokio::spawn(async move {
match local_ai_manager.setup_chat_plugin(config).await {
Ok(_) => {
info!("Local AI chat plugin setup successfully");
},
Err(err) => {
error!("Failed to setup local AI chat plugin: {:?}", err);
},
}
});
}
}
fn save_chat(conn: DBConnection, chat_id: &str) -> FlowyResult<()> {
let row = ChatTable {
chat_id: chat_id.to_string(),
@ -203,21 +255,25 @@ fn save_chat(conn: DBConnection, chat_id: &str) -> FlowyResult<()> {
pub struct ChatService {
cloud_service: Arc<dyn ChatCloudService>,
sidecar_manager: Arc<SidecarManager>,
local_ai_manager: Arc<LocalAIManager>,
local_ai_setting: Arc<RwLock<LocalAISetting>>,
}
impl ChatService {
pub fn new(
cloud_service: Arc<dyn ChatCloudService>,
sidecar_manager: Arc<SidecarManager>,
local_ai_manager: Arc<LocalAIManager>,
local_ai_setting: LocalAISetting,
) -> Self {
Self {
cloud_service,
sidecar_manager,
local_ai_manager,
local_ai_setting: Arc::new(RwLock::new(local_ai_setting)),
}
}
}
#[async_trait]
impl ChatCloudService for ChatService {
fn create_chat(
&self,
@ -228,27 +284,16 @@ impl ChatCloudService for ChatService {
self.cloud_service.create_chat(uid, workspace_id, chat_id)
}
async fn send_chat_message(
&self,
workspace_id: &str,
chat_id: &str,
message: &str,
message_type: ChatMessageType,
) -> Result<ChatMessageStream, FlowyError> {
self
.cloud_service
.send_chat_message(workspace_id, chat_id, message, message_type)
.await
}
fn send_question(
fn save_question(
&self,
workspace_id: &str,
chat_id: &str,
message: &str,
message_type: ChatMessageType,
) -> FutureResult<ChatMessage, FlowyError> {
todo!()
self
.cloud_service
.save_question(workspace_id, chat_id, message, message_type)
}
fn save_answer(
@ -258,16 +303,41 @@ impl ChatCloudService for ChatService {
message: &str,
question_id: i64,
) -> FutureResult<ChatMessage, FlowyError> {
todo!()
self
.cloud_service
.save_answer(workspace_id, chat_id, message, question_id)
}
async fn stream_answer(
async fn ask_question(
&self,
_workspace_id: &str,
_chat_id: &str,
_message_id: i64,
workspace_id: &str,
chat_id: &str,
message_id: i64,
) -> Result<StreamAnswer, FlowyError> {
if self.local_ai_setting.read().enabled {
// self.local_ai_manager.stream_chat_message(chat_id, "", message_id).await
todo!()
} else {
self
.cloud_service
.ask_question(workspace_id, chat_id, message_id)
.await
}
}
fn generate_answer(
&self,
workspace_id: &str,
chat_id: &str,
question_message_id: i64,
) -> FutureResult<ChatMessage, FlowyError> {
if self.local_ai_setting.read().enabled {
todo!()
} else {
self
.cloud_service
.generate_answer(workspace_id, chat_id, question_message_id)
}
}
fn get_chat_messages(
@ -277,13 +347,9 @@ impl ChatCloudService for ChatService {
offset: MessageCursor,
limit: u64,
) -> FutureResult<RepeatedChatMessage, FlowyError> {
FutureResult::new(async move {
Ok(RepeatedChatMessage {
messages: vec![],
has_more: false,
total: 0,
})
})
self
.cloud_service
.get_chat_messages(workspace_id, chat_id, offset, limit)
}
fn get_related_message(
@ -292,20 +358,17 @@ impl ChatCloudService for ChatService {
chat_id: &str,
message_id: i64,
) -> FutureResult<RepeatedRelatedQuestion, FlowyError> {
if self.local_ai_setting.read().enabled {
FutureResult::new(async move {
Ok(RepeatedRelatedQuestion {
message_id,
items: vec![],
})
})
} else {
self
.cloud_service
.get_related_message(workspace_id, chat_id, message_id)
}
fn generate_answer(
&self,
workspace_id: &str,
chat_id: &str,
question_message_id: i64,
) -> FutureResult<ChatMessage, FlowyError> {
todo!()
}
}

View File

@ -29,18 +29,13 @@ async fn stream_local_model_test() {
let mut resp = test
.stream_chat_message(&chat_id, plugin_id, "hello world")
.await;
let a = resp.next().await.unwrap().unwrap();
eprintln!("chat response: {:?}", a);
let mut list = vec![];
while let Some(s) = resp.next().await {
list.push(s.unwrap());
}
let answer = list.join("");
eprintln!("chat response: {:?}", answer);
tokio::time::sleep(tokio::time::Duration::from_secs(5)).await;
// let mut resp = test
// .stream_chat_message(&chat_id, plugin_id, "How are you")
// .await;
// let a = resp.next().await.unwrap().unwrap();
// eprintln!("chat response: {:?}", a);
// let questions = test.related_question(&chat_id, plugin_id).await;
// assert_eq!(questions.len(), 3);
// eprintln!("related questions: {:?}", questions);
}
}

View File

@ -1,14 +1,14 @@
use anyhow::Result;
use flowy_sidecar::manager::SidecarManager;
use serde_json::json;
use std::path::PathBuf;
use std::sync::Once;
use tokio_stream::wrappers::ReceiverStream;
use tokio_stream::Stream;
use flowy_chat::local_ai::chat_plugin::ChatPluginOperation;
use flowy_chat::local_ai::embedding_plugin::EmbeddingPluginOperation;
use flowy_sidecar::core::plugin::{PluginId, PluginInfo};
use flowy_sidecar::error::SidecarError;
use flowy_sidecar::plugins::chat_plugin::ChatPluginOperation;
use flowy_sidecar::plugins::embedding_plugin::EmbeddingPluginOperation;
use tracing_subscriber::fmt::Subscriber;
use tracing_subscriber::util::SubscriberInitExt;
use tracing_subscriber::EnvFilter;
@ -120,10 +120,10 @@ impl LocalAITest {
}
pub struct LocalAIConfiguration {
root: String,
chat_bin_path: String,
model_dir: String,
chat_bin_path: PathBuf,
chat_model_name: String,
embedding_bin_path: String,
embedding_bin_path: PathBuf,
embedding_model_name: String,
}
@ -133,15 +133,15 @@ impl LocalAIConfiguration {
setup_log();
// load from .env
let root = dotenv::var("LOCAL_AI_ROOT_PATH")?;
let chat_bin_path = dotenv::var("CHAT_BIN_PATH")?;
let model_dir = dotenv::var("LOCAL_AI_MODEL_DIR")?;
let chat_bin_path = PathBuf::from(dotenv::var("CHAT_BIN_PATH")?);
let chat_model_name = dotenv::var("LOCAL_AI_CHAT_MODEL_NAME")?;
let embedding_bin_path = dotenv::var("EMBEDDING_BIN_PATH")?;
let embedding_bin_path = PathBuf::from(dotenv::var("EMBEDDING_BIN_PATH")?);
let embedding_model_name = dotenv::var("LOCAL_AI_EMBEDDING_MODEL_NAME")?;
Ok(Self {
root,
model_dir,
chat_bin_path,
chat_model_name,
embedding_bin_path,
@ -150,11 +150,11 @@ impl LocalAIConfiguration {
}
pub fn chat_model_absolute_path(&self) -> String {
format!("{}/{}", self.root, self.chat_model_name)
format!("{}/{}", self.model_dir, self.chat_model_name)
}
pub fn embedding_model_absolute_path(&self) -> String {
format!("{}/{}", self.root, self.embedding_model_name)
format!("{}/{}", self.model_dir, self.embedding_model_name)
}
}

View File

@ -1,13 +1,13 @@
use std::sync::Weak;
use flowy_error::{FlowyError, FlowyResult};
use flowy_sqlite::kv::StorePreferences;
use flowy_sqlite::kv::KVStorePreferences;
use lib_dispatch::prelude::{data_result_ok, AFPluginData, AFPluginState, DataResult};
use crate::entities::{KeyPB, KeyValuePB};
pub(crate) async fn set_key_value_handler(
store_preferences: AFPluginState<Weak<StorePreferences>>,
store_preferences: AFPluginState<Weak<KVStorePreferences>>,
data: AFPluginData<KeyValuePB>,
) -> FlowyResult<()> {
let data = data.into_inner();
@ -25,7 +25,7 @@ pub(crate) async fn set_key_value_handler(
}
pub(crate) async fn get_key_value_handler(
store_preferences: AFPluginState<Weak<StorePreferences>>,
store_preferences: AFPluginState<Weak<KVStorePreferences>>,
data: AFPluginData<KeyPB>,
) -> DataResult<KeyValuePB, FlowyError> {
match store_preferences.upgrade() {
@ -42,7 +42,7 @@ pub(crate) async fn get_key_value_handler(
}
pub(crate) async fn remove_key_value_handler(
store_preferences: AFPluginState<Weak<StorePreferences>>,
store_preferences: AFPluginState<Weak<KVStorePreferences>>,
data: AFPluginData<KeyPB>,
) -> FlowyResult<()> {
match store_preferences.upgrade() {

View File

@ -3,12 +3,12 @@ use std::sync::Weak;
use strum_macros::Display;
use flowy_derive::{Flowy_Event, ProtoBuf_Enum};
use flowy_sqlite::kv::StorePreferences;
use flowy_sqlite::kv::KVStorePreferences;
use lib_dispatch::prelude::AFPlugin;
use crate::event_handler::*;
pub fn init(store_preferences: Weak<StorePreferences>) -> AFPlugin {
pub fn init(store_preferences: Weak<KVStorePreferences>) -> AFPlugin {
AFPlugin::new()
.name(env!("CARGO_PKG_NAME"))
.state(store_preferences)

View File

@ -1,6 +1,7 @@
use flowy_chat::manager::{ChatManager, ChatUserService};
use flowy_chat_pub::cloud::ChatCloudService;
use flowy_error::FlowyError;
use flowy_sqlite::kv::KVStorePreferences;
use flowy_sqlite::DBConnection;
use flowy_user::services::authenticate_user::AuthenticateUser;
use std::sync::{Arc, Weak};
@ -11,9 +12,14 @@ impl ChatDepsResolver {
pub fn resolve(
authenticate_user: Weak<AuthenticateUser>,
cloud_service: Arc<dyn ChatCloudService>,
store_preferences: Arc<KVStorePreferences>,
) -> Arc<ChatManager> {
let user_service = ChatUserServiceImpl(authenticate_user);
Arc::new(ChatManager::new(cloud_service, user_service))
Arc::new(ChatManager::new(
cloud_service,
user_service,
store_preferences,
))
}
}

View File

@ -18,7 +18,7 @@ use flowy_folder::view_operation::{
use flowy_folder::ViewLayout;
use flowy_folder_pub::folder_builder::NestedViewBuilder;
use flowy_search::folder::indexer::FolderIndexManagerImpl;
use flowy_sqlite::kv::StorePreferences;
use flowy_sqlite::kv::KVStorePreferences;
use flowy_user::services::authenticate_user::AuthenticateUser;
use lib_dispatch::prelude::ToBytes;
use lib_infra::future::FutureResult;
@ -37,7 +37,7 @@ impl FolderDepsResolver {
collab_builder: Arc<AppFlowyCollabBuilder>,
server_provider: Arc<ServerProvider>,
folder_indexer: Arc<FolderIndexManagerImpl>,
store_preferences: Arc<StorePreferences>,
store_preferences: Arc<KVStorePreferences>,
operation_handlers: FolderOperationHandlers,
) -> Arc<FolderManager> {
let user: Arc<dyn FolderUser> = Arc::new(FolderUserImpl {

View File

@ -4,7 +4,7 @@ use flowy_database2::DatabaseManager;
use flowy_error::FlowyResult;
use flowy_folder::manager::FolderManager;
use flowy_folder_pub::folder_builder::ParentChildViews;
use flowy_sqlite::kv::StorePreferences;
use flowy_sqlite::kv::KVStorePreferences;
use flowy_user::services::authenticate_user::AuthenticateUser;
use flowy_user::user_manager::UserManager;
use flowy_user_pub::workspace_service::UserWorkspaceService;
@ -19,7 +19,7 @@ impl UserDepsResolver {
authenticate_user: Arc<AuthenticateUser>,
collab_builder: Arc<AppFlowyCollabBuilder>,
server_provider: Arc<ServerProvider>,
store_preference: Arc<StorePreferences>,
store_preference: Arc<KVStorePreferences>,
database_manager: Arc<DatabaseManager>,
folder_manager: Arc<FolderManager>,
) -> Arc<UserManager> {

View File

@ -14,7 +14,7 @@ use flowy_server::{AppFlowyEncryption, AppFlowyServer, EncryptionImpl};
use flowy_server_pub::af_cloud_config::AFCloudConfiguration;
use flowy_server_pub::supabase_config::SupabaseConfiguration;
use flowy_server_pub::AuthenticatorType;
use flowy_sqlite::kv::StorePreferences;
use flowy_sqlite::kv::KVStorePreferences;
use flowy_user_pub::entities::*;
use crate::AppFlowyCoreConfig;
@ -59,7 +59,7 @@ pub struct ServerProvider {
providers: RwLock<HashMap<Server, Arc<dyn AppFlowyServer>>>,
pub(crate) encryption: RwLock<Arc<dyn AppFlowyEncryption>>,
#[allow(dead_code)]
pub(crate) store_preferences: Weak<StorePreferences>,
pub(crate) store_preferences: Weak<KVStorePreferences>,
pub(crate) user_enable_sync: RwLock<bool>,
/// The authenticator type of the user.
@ -72,7 +72,7 @@ impl ServerProvider {
pub fn new(
config: AppFlowyCoreConfig,
server: Server,
store_preferences: Weak<StorePreferences>,
store_preferences: Weak<KVStorePreferences>,
server_user: impl ServerUser + 'static,
) -> Self {
let user = Arc::new(server_user);

View File

@ -18,8 +18,7 @@ use collab_integrate::collab_builder::{
CollabCloudPluginProvider, CollabPluginProviderContext, CollabPluginProviderType,
};
use flowy_chat_pub::cloud::{
ChatCloudService, ChatMessage, ChatMessageStream, MessageCursor, RepeatedChatMessage,
StreamAnswer,
ChatCloudService, ChatMessage, MessageCursor, RepeatedChatMessage, StreamAnswer,
};
use flowy_database_pub::cloud::{
CollabDocStateByOid, DatabaseCloudService, DatabaseSnapshot, SummaryRowContent,
@ -545,24 +544,7 @@ impl ChatCloudService for ServerProvider {
})
}
async fn send_chat_message(
&self,
workspace_id: &str,
chat_id: &str,
message: &str,
message_type: ChatMessageType,
) -> Result<ChatMessageStream, FlowyError> {
let workspace_id = workspace_id.to_string();
let chat_id = chat_id.to_string();
let message = message.to_string();
let server = self.get_server()?;
server
.chat_service()
.send_chat_message(&workspace_id, &chat_id, &message, message_type)
.await
}
fn send_question(
fn save_question(
&self,
workspace_id: &str,
chat_id: &str,
@ -577,7 +559,7 @@ impl ChatCloudService for ServerProvider {
FutureResult::new(async move {
server?
.chat_service()
.send_question(&workspace_id, &chat_id, &message, message_type)
.save_question(&workspace_id, &chat_id, &message, message_type)
.await
})
}
@ -601,7 +583,7 @@ impl ChatCloudService for ServerProvider {
})
}
async fn stream_answer(
async fn ask_question(
&self,
workspace_id: &str,
chat_id: &str,
@ -612,7 +594,7 @@ impl ChatCloudService for ServerProvider {
let server = self.get_server()?;
server
.chat_service()
.stream_answer(&workspace_id, &chat_id, message_id)
.ask_question(&workspace_id, &chat_id, message_id)
.await
}

View File

@ -16,7 +16,7 @@ use flowy_error::{FlowyError, FlowyResult};
use flowy_folder::manager::FolderManager;
use flowy_server::af_cloud::define::ServerUser;
use flowy_sqlite::kv::StorePreferences;
use flowy_sqlite::kv::KVStorePreferences;
use flowy_storage::manager::StorageManager;
use flowy_user::services::authenticate_user::AuthenticateUser;
use flowy_user::services::entities::UserConfig;
@ -57,7 +57,7 @@ pub struct AppFlowyCore {
pub event_dispatcher: Arc<AFPluginDispatcher>,
pub server_provider: Arc<ServerProvider>,
pub task_dispatcher: Arc<RwLock<TaskDispatcher>>,
pub store_preference: Arc<StorePreferences>,
pub store_preference: Arc<KVStorePreferences>,
pub search_manager: Arc<SearchManager>,
pub chat_manager: Arc<ChatManager>,
pub storage_manager: Arc<StorageManager>,
@ -102,7 +102,7 @@ impl AppFlowyCore {
#[instrument(skip(config, runtime))]
async fn init(config: AppFlowyCoreConfig, runtime: Arc<AFPluginRuntime>) -> Self {
// Init the key value database
let store_preference = Arc::new(StorePreferences::new(&config.storage_path).unwrap());
let store_preference = Arc::new(KVStorePreferences::new(&config.storage_path).unwrap());
info!("🔥{:?}", &config);
let task_scheduler = TaskDispatcher::new(Duration::from_secs(2));
@ -175,8 +175,11 @@ impl AppFlowyCore {
Arc::downgrade(&storage_manager.storage_service),
);
let chat_manager =
ChatDepsResolver::resolve(Arc::downgrade(&authenticate_user), server_provider.clone());
let chat_manager = ChatDepsResolver::resolve(
Arc::downgrade(&authenticate_user),
server_provider.clone(),
store_preference.clone(),
);
let folder_indexer = Arc::new(FolderIndexManagerImpl::new(Some(Arc::downgrade(
&authenticate_user,

View File

@ -30,7 +30,7 @@ use flowy_error::{ErrorCode, FlowyError, FlowyResult};
use flowy_folder_pub::cloud::{gen_view_id, FolderCloudService};
use flowy_folder_pub::folder_builder::ParentChildViews;
use flowy_search_pub::entities::FolderIndexManager;
use flowy_sqlite::kv::StorePreferences;
use flowy_sqlite::kv::KVStorePreferences;
use parking_lot::RwLock;
use std::fmt::{Display, Formatter};
use std::ops::Deref;
@ -51,7 +51,7 @@ pub struct FolderManager {
pub(crate) operation_handlers: FolderOperationHandlers,
pub cloud_service: Arc<dyn FolderCloudService>,
pub(crate) folder_indexer: Arc<dyn FolderIndexManager>,
pub(crate) store_preferences: Arc<StorePreferences>,
pub(crate) store_preferences: Arc<KVStorePreferences>,
}
impl FolderManager {
@ -61,7 +61,7 @@ impl FolderManager {
operation_handlers: FolderOperationHandlers,
cloud_service: Arc<dyn FolderCloudService>,
folder_indexer: Arc<dyn FolderIndexManager>,
store_preferences: Arc<StorePreferences>,
store_preferences: Arc<KVStorePreferences>,
) -> FlowyResult<Self> {
let mutex_folder = Arc::new(MutexFolder::default());
let manager = Self {

View File

@ -4,9 +4,7 @@ use client_api::entity::{
CreateAnswerMessageParams, CreateChatMessageParams, CreateChatParams, MessageCursor,
RepeatedChatMessage,
};
use flowy_chat_pub::cloud::{
ChatCloudService, ChatMessage, ChatMessageStream, ChatMessageType, StreamAnswer,
};
use flowy_chat_pub::cloud::{ChatCloudService, ChatMessage, ChatMessageType, StreamAnswer};
use flowy_error::FlowyError;
use futures_util::StreamExt;
use lib_infra::async_trait::async_trait;
@ -46,27 +44,7 @@ where
})
}
async fn send_chat_message(
&self,
workspace_id: &str,
chat_id: &str,
message: &str,
message_type: ChatMessageType,
) -> Result<ChatMessageStream, FlowyError> {
let try_get_client = self.inner.try_get_client();
let params = CreateChatMessageParams {
content: message.to_string(),
message_type,
};
let stream = try_get_client?
.create_chat_qa_message(workspace_id, chat_id, params)
.await
.map_err(FlowyError::from)?;
Ok(stream.boxed())
}
fn send_question(
fn save_question(
&self,
workspace_id: &str,
chat_id: &str,
@ -83,7 +61,7 @@ where
FutureResult::new(async move {
let message = try_get_client?
.create_question(&workspace_id, &chat_id, params)
.save_question(&workspace_id, &chat_id, params)
.await
.map_err(FlowyError::from)?;
Ok(message)
@ -107,14 +85,14 @@ where
FutureResult::new(async move {
let message = try_get_client?
.create_answer(&workspace_id, &chat_id, params)
.save_answer(&workspace_id, &chat_id, params)
.await
.map_err(FlowyError::from)?;
Ok(message)
})
}
async fn stream_answer(
async fn ask_question(
&self,
workspace_id: &str,
chat_id: &str,
@ -122,12 +100,31 @@ where
) -> Result<StreamAnswer, FlowyError> {
let try_get_client = self.inner.try_get_client();
let stream = try_get_client?
.stream_answer(workspace_id, chat_id, message_id)
.ask_question(workspace_id, chat_id, message_id)
.await
.map_err(FlowyError::from)?;
Ok(stream.boxed())
}
fn generate_answer(
&self,
workspace_id: &str,
chat_id: &str,
question_message_id: i64,
) -> FutureResult<ChatMessage, FlowyError> {
let workspace_id = workspace_id.to_string();
let chat_id = chat_id.to_string();
let try_get_client = self.inner.try_get_client();
FutureResult::new(async move {
let resp = try_get_client?
.generate_answer(&workspace_id, &chat_id, question_message_id)
.await
.map_err(FlowyError::from)?;
Ok(resp)
})
}
fn get_chat_messages(
&self,
workspace_id: &str,
@ -168,23 +165,4 @@ where
Ok(resp)
})
}
fn generate_answer(
&self,
workspace_id: &str,
chat_id: &str,
question_message_id: i64,
) -> FutureResult<ChatMessage, FlowyError> {
let workspace_id = workspace_id.to_string();
let chat_id = chat_id.to_string();
let try_get_client = self.inner.try_get_client();
FutureResult::new(async move {
let resp = try_get_client?
.get_answer(&workspace_id, &chat_id, question_message_id)
.await
.map_err(FlowyError::from)?;
Ok(resp)
})
}
}

View File

@ -20,17 +20,7 @@ impl ChatCloudService for DefaultChatCloudServiceImpl {
})
}
async fn send_chat_message(
&self,
_workspace_id: &str,
_chat_id: &str,
_message: &str,
_message_type: ChatMessageType,
) -> Result<ChatMessageStream, FlowyError> {
Err(FlowyError::not_support().with_context("Chat is not supported in local server."))
}
fn send_question(
fn save_question(
&self,
_workspace_id: &str,
_chat_id: &str,
@ -54,7 +44,7 @@ impl ChatCloudService for DefaultChatCloudServiceImpl {
})
}
async fn stream_answer(
async fn ask_question(
&self,
_workspace_id: &str,
_chat_id: &str,

View File

@ -18,9 +18,3 @@ log = "0.4.21"
parking_lot.workspace = true
tokio-stream = "0.1.15"
lib-infra.workspace = true
[dev-dependencies]
dotenv = "0.15.0"
uuid.workspace = true
tracing-subscriber = { version = "0.3.17", features = ["registry", "env-filter", "ansi", "json"] }

View File

@ -3,7 +3,6 @@ use crate::core::rpc_object::RpcObject;
use crate::error::{ReadError, RemoteError};
use serde_json::{json, Value as JsonValue};
use std::io::BufRead;
use tracing::error;
#[derive(Debug, Default)]
pub struct MessageReader(String);
@ -61,64 +60,3 @@ pub trait ResponseParser {
type ValueType: Send + Sync + 'static;
fn parse_json(payload: JsonValue) -> Result<Self::ValueType, RemoteError>;
}
pub struct ChatResponseParser;
impl ResponseParser for ChatResponseParser {
type ValueType = String;
fn parse_json(json: JsonValue) -> Result<Self::ValueType, RemoteError> {
if json.is_object() {
if let Some(data) = json.get("data") {
if let Some(message) = data.as_str() {
return Ok(message.to_string());
}
}
}
return Err(RemoteError::ParseResponse(json));
}
}
pub struct ChatStreamResponseParser;
impl ResponseParser for ChatStreamResponseParser {
type ValueType = String;
fn parse_json(json: JsonValue) -> Result<Self::ValueType, RemoteError> {
if let Some(message) = json.as_str() {
return Ok(message.to_string());
}
return Err(RemoteError::ParseResponse(json));
}
}
pub struct ChatRelatedQuestionsResponseParser;
impl ResponseParser for ChatRelatedQuestionsResponseParser {
type ValueType = Vec<JsonValue>;
fn parse_json(json: JsonValue) -> Result<Self::ValueType, RemoteError> {
if json.is_object() {
if let Some(data) = json.get("data") {
if let Some(values) = data.as_array() {
return Ok(values.clone());
}
}
}
return Err(RemoteError::ParseResponse(json));
}
}
pub struct SimilarityResponseParser;
impl ResponseParser for SimilarityResponseParser {
type ValueType = f64;
fn parse_json(json: JsonValue) -> Result<Self::ValueType, RemoteError> {
if json.is_object() {
if let Some(data) = json.get("data") {
if let Some(score) = data.get("score").and_then(|v| v.as_f64()) {
return Ok(score);
}
}
}
return Err(RemoteError::ParseResponse(json));
}
}

View File

@ -8,12 +8,12 @@ use anyhow::anyhow;
use serde::{Deserialize, Serialize};
use serde_json::{json, Value as JsonValue};
use std::io::BufReader;
use std::path::PathBuf;
use std::process::{Child, Stdio};
use std::sync::Arc;
use std::thread;
use std::time::Instant;
use tokio_stream::wrappers::ReceiverStream;
use tokio_stream::Stream;
use tracing::{error, info};
@ -126,7 +126,7 @@ impl Plugin {
pub struct PluginInfo {
pub name: String,
pub exec_path: String,
pub exec_path: PathBuf,
}
pub(crate) async fn start_plugin_process(

View File

@ -9,7 +9,7 @@ use std::io::{BufRead, Write};
use std::sync::Arc;
use std::thread;
use std::time::Duration;
use tracing::{error, info, trace};
use tracing::{error, trace};
const MAX_IDLE_WAIT: Duration = Duration::from_millis(5);

View File

@ -1,8 +1,8 @@
use crate::core::parser::{Call, RequestId};
use crate::core::rpc_peer::{Response, ResponsePayload};
use crate::error::RemoteError;
use serde::de::{DeserializeOwned, Error};
use serde_json::{json, Value};
use serde_json::Value;
#[derive(Debug, Clone)]
pub struct RpcObject(pub Value);

View File

@ -200,7 +200,19 @@ impl<W: Write> RawPeer<W> {
}
}
let json = resp.map(|resp| resp.into_json());
response_handler.invoke(json);
match json {
Ok(Some(json)) => {
response_handler.invoke(Ok(json));
},
Ok(None) => {
if !is_stream {
warn!("[RPC] only stream response can be None");
}
},
Err(err) => {
response_handler.invoke(Err(err));
},
}
},
None => error!("[RPC] id {}'s handle not found", request_id),
}
@ -306,19 +318,11 @@ impl ResponsePayload {
matches!(self, ResponsePayload::StreamEnd(_))
}
pub fn json(&self) -> &JsonValue {
pub fn into_json(self) -> Option<JsonValue> {
match self {
ResponsePayload::Json(v) => v,
ResponsePayload::Streaming(v) => v,
ResponsePayload::StreamEnd(v) => v,
}
}
pub fn into_json(self) -> JsonValue {
match self {
ResponsePayload::Json(v) => v,
ResponsePayload::Streaming(v) => v,
ResponsePayload::StreamEnd(v) => v,
ResponsePayload::Json(v) => Some(v),
ResponsePayload::Streaming(v) => Some(v),
ResponsePayload::StreamEnd(_) => None,
}
}
}

View File

@ -1,4 +1,3 @@
pub mod core;
pub mod error;
pub mod manager;
pub mod plugins;

View File

@ -1,70 +0,0 @@
use crate::core::parser::{
ChatRelatedQuestionsResponseParser, ChatResponseParser, ChatStreamResponseParser,
};
use crate::core::plugin::{Plugin, PluginId};
use crate::error::SidecarError;
use anyhow::anyhow;
use serde_json::json;
use std::sync::Weak;
use tokio_stream::wrappers::ReceiverStream;
use tokio_stream::Stream;
pub struct ChatPluginOperation {
plugin: Weak<Plugin>,
}
impl ChatPluginOperation {
pub fn new(plugin: Weak<Plugin>) -> Self {
ChatPluginOperation { plugin }
}
pub async fn send_message(
&self,
chat_id: &str,
_plugin_id: PluginId,
message: &str,
) -> Result<String, SidecarError> {
let plugin = self
.plugin
.upgrade()
.ok_or(SidecarError::Internal(anyhow!("Plugin is dropped")))?;
let params = json!({"chat_id": chat_id, "method": "answer", "params": {"content": message}});
let resp = plugin
.async_request::<ChatResponseParser>("handle", &params)
.await?;
Ok(resp)
}
pub async fn stream_message(
&self,
chat_id: &str,
_plugin_id: PluginId,
message: &str,
) -> Result<ReceiverStream<Result<String, SidecarError>>, SidecarError> {
let plugin = self
.plugin
.upgrade()
.ok_or(SidecarError::Internal(anyhow!("Plugin is dropped")))?;
let params =
json!({"chat_id": chat_id, "method": "stream_answer", "params": {"content": message}});
plugin.stream_request::<ChatStreamResponseParser>("handle", &params)
}
pub async fn get_related_questions(
&self,
chat_id: &str,
) -> Result<Vec<serde_json::Value>, SidecarError> {
let plugin = self
.plugin
.upgrade()
.ok_or(SidecarError::Internal(anyhow!("Plugin is dropped")))?;
let params = json!({"chat_id": chat_id, "method": "related_question"});
let resp = plugin
.async_request::<ChatRelatedQuestionsResponseParser>("handle", &params)
.await?;
Ok(resp)
}
}

View File

@ -11,13 +11,13 @@ use crate::sqlite_impl::{Database, PoolConfig};
const DB_NAME: &str = "cache.db";
/// [StorePreferences] uses a sqlite database to store key value pairs.
/// [KVStorePreferences] uses a sqlite database to store key value pairs.
/// Most of the time, it used to storage AppFlowy configuration.
#[derive(Clone)]
pub struct StorePreferences {
pub struct KVStorePreferences {
database: Option<Database>,
}
impl StorePreferences {
impl KVStorePreferences {
#[tracing::instrument(level = "trace", err)]
pub fn new(root: &str) -> Result<Self, anyhow::Error> {
if !Path::new(root).exists() {
@ -138,7 +138,7 @@ mod tests {
use serde::{Deserialize, Serialize};
use tempfile::TempDir;
use crate::kv::StorePreferences;
use crate::kv::KVStorePreferences;
#[derive(Serialize, Deserialize, Clone, Eq, PartialEq, Debug)]
struct Person {
@ -150,7 +150,7 @@ mod tests {
fn kv_store_test() {
let tempdir = TempDir::new().unwrap();
let path = tempdir.into_path();
let store = StorePreferences::new(path.to_str().unwrap()).unwrap();
let store = KVStorePreferences::new(path.to_str().unwrap()).unwrap();
store.set_str("1", "hello".to_string());
assert_eq!(store.get_str("1").unwrap(), "hello");

View File

@ -1,5 +1,5 @@
use flowy_error::{ErrorCode, FlowyError, FlowyResult};
use flowy_sqlite::kv::StorePreferences;
use flowy_sqlite::kv::KVStorePreferences;
use flowy_user_pub::cloud::UserCloudConfig;
use flowy_user_pub::entities::*;
use lib_dispatch::prelude::*;
@ -25,8 +25,8 @@ fn upgrade_manager(manager: AFPluginState<Weak<UserManager>>) -> FlowyResult<Arc
}
fn upgrade_store_preferences(
store: AFPluginState<Weak<StorePreferences>>,
) -> FlowyResult<Arc<StorePreferences>> {
store: AFPluginState<Weak<KVStorePreferences>>,
) -> FlowyResult<Arc<KVStorePreferences>> {
let store = store
.upgrade()
.ok_or(FlowyError::internal().with_context("The store preferences is already drop"))?;
@ -151,7 +151,7 @@ const APPEARANCE_SETTING_CACHE_KEY: &str = "appearance_settings";
#[tracing::instrument(level = "debug", skip_all, err)]
pub async fn set_appearance_setting(
store_preferences: AFPluginState<Weak<StorePreferences>>,
store_preferences: AFPluginState<Weak<KVStorePreferences>>,
data: AFPluginData<AppearanceSettingsPB>,
) -> Result<(), FlowyError> {
let store_preferences = upgrade_store_preferences(store_preferences)?;
@ -165,7 +165,7 @@ pub async fn set_appearance_setting(
#[tracing::instrument(level = "debug", skip_all, err)]
pub async fn get_appearance_setting(
store_preferences: AFPluginState<Weak<StorePreferences>>,
store_preferences: AFPluginState<Weak<KVStorePreferences>>,
) -> DataResult<AppearanceSettingsPB, FlowyError> {
let store_preferences = upgrade_store_preferences(store_preferences)?;
match store_preferences.get_str(APPEARANCE_SETTING_CACHE_KEY) {
@ -187,7 +187,7 @@ const DATE_TIME_SETTINGS_CACHE_KEY: &str = "date_time_settings";
#[tracing::instrument(level = "debug", skip_all, err)]
pub async fn set_date_time_settings(
store_preferences: AFPluginState<Weak<StorePreferences>>,
store_preferences: AFPluginState<Weak<KVStorePreferences>>,
data: AFPluginData<DateTimeSettingsPB>,
) -> Result<(), FlowyError> {
let store_preferences = upgrade_store_preferences(store_preferences)?;
@ -202,7 +202,7 @@ pub async fn set_date_time_settings(
#[tracing::instrument(level = "debug", skip_all, err)]
pub async fn get_date_time_settings(
store_preferences: AFPluginState<Weak<StorePreferences>>,
store_preferences: AFPluginState<Weak<KVStorePreferences>>,
) -> DataResult<DateTimeSettingsPB, FlowyError> {
let store_preferences = upgrade_store_preferences(store_preferences)?;
match store_preferences.get_str(DATE_TIME_SETTINGS_CACHE_KEY) {
@ -227,7 +227,7 @@ const NOTIFICATION_SETTINGS_CACHE_KEY: &str = "notification_settings";
#[tracing::instrument(level = "debug", skip_all, err)]
pub async fn set_notification_settings(
store_preferences: AFPluginState<Weak<StorePreferences>>,
store_preferences: AFPluginState<Weak<KVStorePreferences>>,
data: AFPluginData<NotificationSettingsPB>,
) -> Result<(), FlowyError> {
let store_preferences = upgrade_store_preferences(store_preferences)?;
@ -238,7 +238,7 @@ pub async fn set_notification_settings(
#[tracing::instrument(level = "debug", skip_all, err)]
pub async fn get_notification_settings(
store_preferences: AFPluginState<Weak<StorePreferences>>,
store_preferences: AFPluginState<Weak<KVStorePreferences>>,
) -> DataResult<NotificationSettingsPB, FlowyError> {
let store_preferences = upgrade_store_preferences(store_preferences)?;
match store_preferences.get_str(NOTIFICATION_SETTINGS_CACHE_KEY) {
@ -348,7 +348,7 @@ pub async fn sign_in_with_provider_handler(
pub async fn set_encrypt_secret_handler(
manager: AFPluginState<Weak<UserManager>>,
data: AFPluginData<UserSecretPB>,
store_preferences: AFPluginState<Weak<StorePreferences>>,
store_preferences: AFPluginState<Weak<KVStorePreferences>>,
) -> Result<(), FlowyError> {
let manager = upgrade_manager(manager)?;
let store_preferences = upgrade_store_preferences(store_preferences)?;
@ -408,7 +408,7 @@ pub async fn check_encrypt_secret_handler(
pub async fn set_cloud_config_handler(
manager: AFPluginState<Weak<UserManager>>,
data: AFPluginData<UpdateCloudConfigPB>,
store_preferences: AFPluginState<Weak<StorePreferences>>,
store_preferences: AFPluginState<Weak<KVStorePreferences>>,
) -> Result<(), FlowyError> {
let manager = upgrade_manager(manager)?;
let session = manager.get_session()?;
@ -468,7 +468,7 @@ pub async fn set_cloud_config_handler(
#[tracing::instrument(level = "info", skip_all, err)]
pub async fn get_cloud_config_handler(
manager: AFPluginState<Weak<UserManager>>,
store_preferences: AFPluginState<Weak<StorePreferences>>,
store_preferences: AFPluginState<Weak<KVStorePreferences>>,
) -> DataResult<CloudSettingPB, FlowyError> {
let manager = upgrade_manager(manager)?;
let session = manager.get_session()?;

View File

@ -1,4 +1,4 @@
use flowy_sqlite::kv::StorePreferences;
use flowy_sqlite::kv::KVStorePreferences;
use flowy_user_pub::session::Session;
use serde_json::{json, Value};
use std::sync::Arc;
@ -8,7 +8,7 @@ const MIGRATION_USER_NO_USER_UUID: &str = "migration_user_no_user_uuid";
pub fn migrate_session_with_user_uuid(
session_cache_key: &str,
store_preferences: &Arc<StorePreferences>,
store_preferences: &Arc<KVStorePreferences>,
) -> Option<Session> {
if !store_preferences.get_bool(MIGRATION_USER_NO_USER_UUID)
&& store_preferences

View File

@ -5,7 +5,7 @@ use crate::services::sqlite_sql::user_sql::vacuum_database;
use collab_integrate::CollabKVDB;
use flowy_error::{internal_error, ErrorCode, FlowyError, FlowyResult};
use flowy_sqlite::kv::StorePreferences;
use flowy_sqlite::kv::KVStorePreferences;
use flowy_sqlite::DBConnection;
use flowy_user_pub::entities::UserWorkspace;
use flowy_user_pub::session::Session;
@ -19,12 +19,12 @@ pub struct AuthenticateUser {
pub user_config: UserConfig,
pub(crate) database: Arc<UserDB>,
pub(crate) user_paths: UserPaths,
store_preferences: Arc<StorePreferences>,
store_preferences: Arc<KVStorePreferences>,
session: Arc<parking_lot::RwLock<Option<Session>>>,
}
impl AuthenticateUser {
pub fn new(user_config: UserConfig, store_preferences: Arc<StorePreferences>) -> Self {
pub fn new(user_config: UserConfig, store_preferences: Arc<KVStorePreferences>) -> Self {
let user_paths = UserPaths::new(user_config.storage_path.clone());
let database = Arc::new(UserDB::new(user_paths.clone()));
let session = Arc::new(parking_lot::RwLock::new(None));

View File

@ -2,12 +2,12 @@ use std::sync::Arc;
use flowy_encrypt::generate_encryption_secret;
use flowy_error::FlowyResult;
use flowy_sqlite::kv::StorePreferences;
use flowy_sqlite::kv::KVStorePreferences;
use flowy_user_pub::cloud::UserCloudConfig;
const CLOUD_CONFIG_KEY: &str = "af_user_cloud_config";
fn generate_cloud_config(uid: i64, store_preference: &Arc<StorePreferences>) -> UserCloudConfig {
fn generate_cloud_config(uid: i64, store_preference: &Arc<KVStorePreferences>) -> UserCloudConfig {
let config = UserCloudConfig::new(generate_encryption_secret());
let key = cache_key_for_cloud_config(uid);
store_preference.set_object(&key, config.clone()).unwrap();
@ -16,7 +16,7 @@ fn generate_cloud_config(uid: i64, store_preference: &Arc<StorePreferences>) ->
pub fn save_cloud_config(
uid: i64,
store_preference: &Arc<StorePreferences>,
store_preference: &Arc<KVStorePreferences>,
config: UserCloudConfig,
) -> FlowyResult<()> {
tracing::info!("save user:{} cloud config: {}", uid, config);
@ -31,7 +31,7 @@ fn cache_key_for_cloud_config(uid: i64) -> String {
pub fn get_cloud_config(
uid: i64,
store_preference: &Arc<StorePreferences>,
store_preference: &Arc<KVStorePreferences>,
) -> Option<UserCloudConfig> {
let key = cache_key_for_cloud_config(uid);
store_preference.get_object::<UserCloudConfig>(&key)
@ -39,7 +39,7 @@ pub fn get_cloud_config(
pub fn get_or_create_cloud_config(
uid: i64,
store_preferences: &Arc<StorePreferences>,
store_preferences: &Arc<KVStorePreferences>,
) -> UserCloudConfig {
let key = cache_key_for_cloud_config(uid);
store_preferences
@ -47,7 +47,7 @@ pub fn get_or_create_cloud_config(
.unwrap_or_else(|| generate_cloud_config(uid, store_preferences))
}
pub fn get_encrypt_secret(uid: i64, store_preference: &Arc<StorePreferences>) -> Option<String> {
pub fn get_encrypt_secret(uid: i64, store_preference: &Arc<KVStorePreferences>) -> Option<String> {
let key = cache_key_for_cloud_config(uid);
store_preference
.get_object::<UserCloudConfig>(&key)

View File

@ -26,7 +26,7 @@ use flowy_error::FlowyError;
use flowy_folder_pub::cloud::gen_view_id;
use flowy_folder_pub::entities::{AppFlowyData, ImportData};
use flowy_folder_pub::folder_builder::{ParentChildViews, ViewBuilder};
use flowy_sqlite::kv::StorePreferences;
use flowy_sqlite::kv::KVStorePreferences;
use flowy_user_pub::cloud::{UserCloudService, UserCollabParams};
use flowy_user_pub::entities::{user_awareness_object_id, Authenticator};
use flowy_user_pub::session::Session;
@ -62,7 +62,7 @@ pub(crate) fn prepare_import(path: &str) -> anyhow::Result<ImportedFolder> {
return Err(anyhow!("The path: {} is not exist", path));
}
let user_paths = UserPaths::new(path.to_string());
let other_store_preferences = Arc::new(StorePreferences::new(path)?);
let other_store_preferences = Arc::new(KVStorePreferences::new(path)?);
migrate_session_with_user_uuid("appflowy_session_cache", &other_store_preferences);
let imported_session = other_store_preferences
.get_object::<Session>("appflowy_session_cache")

View File

@ -4,7 +4,7 @@ use collab_user::core::MutexUserAwareness;
use flowy_error::{internal_error, ErrorCode, FlowyResult};
use flowy_server_pub::AuthenticatorType;
use flowy_sqlite::kv::StorePreferences;
use flowy_sqlite::kv::KVStorePreferences;
use flowy_sqlite::schema::user_table;
use flowy_sqlite::ConnectionPool;
use flowy_sqlite::{query_dsl::*, DBConnection, ExpressionMethods};
@ -48,7 +48,7 @@ use super::manager_user_workspace::save_user_workspace;
pub struct UserManager {
pub(crate) cloud_services: Arc<dyn UserCloudServiceProvider>,
pub(crate) store_preferences: Arc<StorePreferences>,
pub(crate) store_preferences: Arc<KVStorePreferences>,
pub(crate) user_awareness: Arc<Mutex<Option<MutexUserAwareness>>>,
pub(crate) user_status_callback: RwLock<Arc<dyn UserStatusCallback>>,
pub(crate) collab_builder: Weak<AppFlowyCollabBuilder>,
@ -63,7 +63,7 @@ pub struct UserManager {
impl UserManager {
pub fn new(
cloud_services: Arc<dyn UserCloudServiceProvider>,
store_preferences: Arc<StorePreferences>,
store_preferences: Arc<KVStorePreferences>,
collab_builder: Weak<AppFlowyCollabBuilder>,
authenticate_user: Arc<AuthenticateUser>,
user_workspace_service: Arc<dyn UserWorkspaceService>,
@ -110,7 +110,7 @@ impl UserManager {
}
}
pub fn get_store_preferences(&self) -> Weak<StorePreferences> {
pub fn get_store_preferences(&self) -> Weak<KVStorePreferences> {
Arc::downgrade(&self.store_preferences)
}