started gitea api impl #2
@@ -12,18 +12,8 @@
|
|||||||
"containerEnv": {
|
"containerEnv": {
|
||||||
"SHELL": "/bin/bash"
|
"SHELL": "/bin/bash"
|
||||||
},
|
},
|
||||||
"customizations": {
|
|
||||||
"vscode": {
|
|
||||||
"extensions": ["rust-lang.rust-analyzer", "tamasfe.even-better-toml", "fill-labs.dependi"],
|
|
||||||
"settings": {
|
|
||||||
"[rust]": {
|
|
||||||
"editor.defaultFormatter": "rust-lang.rust-analyzer",
|
|
||||||
"editor.formatOnSave": true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"workspaceMount": "source=${localWorkspaceFolder},target=/workspaces/herald,type=bind",
|
"workspaceMount": "source=${localWorkspaceFolder},target=/workspaces/herald,type=bind",
|
||||||
"workspaceFolder": "/workspaces/herald",
|
"workspaceFolder": "/workspaces/herald",
|
||||||
|
"runArgs": ["--userns=keep-id", "--security-opt", "label=disable"],
|
||||||
"appPort": [3000]
|
"appPort": [3000]
|
||||||
}
|
}
|
||||||
|
|||||||
Generated
+314
-18
@@ -229,6 +229,72 @@ dependencies = [
|
|||||||
"cmov",
|
"cmov",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "darling"
|
||||||
|
version = "0.20.11"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "fc7f46116c46ff9ab3eb1597a45688b6715c6e628b5c133e288e709a29bcb4ee"
|
||||||
|
dependencies = [
|
||||||
|
"darling_core",
|
||||||
|
"darling_macro",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "darling_core"
|
||||||
|
version = "0.20.11"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0d00b9596d185e565c2207a0b01f8bd1a135483d02d9b7b0a54b11da8d53412e"
|
||||||
|
dependencies = [
|
||||||
|
"fnv",
|
||||||
|
"ident_case",
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"strsim",
|
||||||
|
"syn 2.0.117",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "darling_macro"
|
||||||
|
version = "0.20.11"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "fc34b93ccb385b40dc71c6fceac4b2ad23662c7eeb248cf10d529b7e055b6ead"
|
||||||
|
dependencies = [
|
||||||
|
"darling_core",
|
||||||
|
"quote",
|
||||||
|
"syn 2.0.117",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "derive_builder"
|
||||||
|
version = "0.20.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "507dfb09ea8b7fa618fcf76e953f4f5e192547945816d5358edffe39f6f94947"
|
||||||
|
dependencies = [
|
||||||
|
"derive_builder_macro",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "derive_builder_core"
|
||||||
|
version = "0.20.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2d5bcf7b024d6835cfb3d473887cd966994907effbe9227e8c8219824d06c4e8"
|
||||||
|
dependencies = [
|
||||||
|
"darling",
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn 2.0.117",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "derive_builder_macro"
|
||||||
|
version = "0.20.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ab63b0e2bf4d5928aff72e83a7dace85d7bba5fe12dcc3c5a572d78caffd3f3c"
|
||||||
|
dependencies = [
|
||||||
|
"derive_builder_core",
|
||||||
|
"syn 2.0.117",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "digest"
|
name = "digest"
|
||||||
version = "0.11.3"
|
version = "0.11.3"
|
||||||
@@ -249,7 +315,7 @@ checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn",
|
"syn 2.0.117",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -258,12 +324,30 @@ version = "0.15.7"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "1aaf95b3e5c8f23aa320147307562d361db0ae0d51242340f558153b4eb2439b"
|
checksum = "1aaf95b3e5c8f23aa320147307562d361db0ae0d51242340f558153b4eb2439b"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "dotenvy_macro"
|
||||||
|
version = "0.15.7"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "cb0235d912a8c749f4e0c9f18ca253b4c28cfefc1d2518096016d6e3230b6424"
|
||||||
|
dependencies = [
|
||||||
|
"dotenvy",
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn 1.0.109",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "dunce"
|
name = "dunce"
|
||||||
version = "1.0.5"
|
version = "1.0.5"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "92773504d58c093f6de2459af4af33faa518c13451eb8f2b5698ed3d36e7c813"
|
checksum = "92773504d58c093f6de2459af4af33faa518c13451eb8f2b5698ed3d36e7c813"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "dyn-clone"
|
||||||
|
version = "1.0.20"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d0881ea181b1df73ff77ffaaf9c7544ecc11e82fba9b5f27b262a3c73a332555"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "encoding_rs"
|
name = "encoding_rs"
|
||||||
version = "0.8.35"
|
version = "0.8.35"
|
||||||
@@ -331,6 +415,23 @@ 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 = "7e3450815272ef58cec6d564423f6e755e25379b217b0bc688e295ba24df6b1d"
|
checksum = "7e3450815272ef58cec6d564423f6e755e25379b217b0bc688e295ba24df6b1d"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "futures-io"
|
||||||
|
version = "0.3.32"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "cecba35d7ad927e23624b22ad55235f2239cfa44fd10428eecbeba6d6a717718"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "futures-macro"
|
||||||
|
version = "0.3.32"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e835b70203e41293343137df5c0664546da5745f82ec9b84d40be8336958447b"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn 2.0.117",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "futures-sink"
|
name = "futures-sink"
|
||||||
version = "0.3.32"
|
version = "0.3.32"
|
||||||
@@ -350,7 +451,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "389ca41296e6190b48053de0321d02a77f32f8a5d2461dd38762c0593805c6d6"
|
checksum = "389ca41296e6190b48053de0321d02a77f32f8a5d2461dd38762c0593805c6d6"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"futures-core",
|
"futures-core",
|
||||||
|
"futures-io",
|
||||||
|
"futures-macro",
|
||||||
|
"futures-sink",
|
||||||
"futures-task",
|
"futures-task",
|
||||||
|
"memchr",
|
||||||
"pin-project-lite",
|
"pin-project-lite",
|
||||||
"slab",
|
"slab",
|
||||||
]
|
]
|
||||||
@@ -417,12 +522,13 @@ dependencies = [
|
|||||||
"dotenvy",
|
"dotenvy",
|
||||||
"hex",
|
"hex",
|
||||||
"hmac",
|
"hmac",
|
||||||
"reqwest",
|
"openrouter-rs",
|
||||||
|
"reqwest 0.13.3",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"sha2",
|
"sha2",
|
||||||
"subtle",
|
"subtle",
|
||||||
"thiserror",
|
"thiserror 2.0.18",
|
||||||
"tokio",
|
"tokio",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -530,6 +636,7 @@ dependencies = [
|
|||||||
"tokio",
|
"tokio",
|
||||||
"tokio-rustls",
|
"tokio-rustls",
|
||||||
"tower-service",
|
"tower-service",
|
||||||
|
"webpki-roots",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -639,6 +746,12 @@ dependencies = [
|
|||||||
"zerovec",
|
"zerovec",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ident_case"
|
||||||
|
version = "1.0.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "idna"
|
name = "idna"
|
||||||
version = "1.1.0"
|
version = "1.1.0"
|
||||||
@@ -694,7 +807,7 @@ dependencies = [
|
|||||||
"jni-sys",
|
"jni-sys",
|
||||||
"log",
|
"log",
|
||||||
"simd_cesu8",
|
"simd_cesu8",
|
||||||
"thiserror",
|
"thiserror 2.0.18",
|
||||||
"walkdir",
|
"walkdir",
|
||||||
"windows-link",
|
"windows-link",
|
||||||
]
|
]
|
||||||
@@ -709,7 +822,7 @@ dependencies = [
|
|||||||
"quote",
|
"quote",
|
||||||
"rustc_version",
|
"rustc_version",
|
||||||
"simd_cesu8",
|
"simd_cesu8",
|
||||||
"syn",
|
"syn 2.0.117",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -728,7 +841,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "38c0b942f458fe50cdac086d2f946512305e5631e720728f2a61aabcd47a6264"
|
checksum = "38c0b942f458fe50cdac086d2f946512305e5631e720728f2a61aabcd47a6264"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"quote",
|
"quote",
|
||||||
"syn",
|
"syn 2.0.117",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -821,6 +934,26 @@ version = "1.21.4"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50"
|
checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "openrouter-rs"
|
||||||
|
version = "0.10.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7f7101578df2f54d9013594e94367adbe656521ef6002f03e4577f1e00e57cb4"
|
||||||
|
dependencies = [
|
||||||
|
"derive_builder",
|
||||||
|
"dotenvy_macro",
|
||||||
|
"futures-util",
|
||||||
|
"http",
|
||||||
|
"reqwest 0.12.28",
|
||||||
|
"schemars",
|
||||||
|
"serde",
|
||||||
|
"serde_json",
|
||||||
|
"thiserror 1.0.69",
|
||||||
|
"tokio",
|
||||||
|
"tokio-util",
|
||||||
|
"urlencoding",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "openssl-probe"
|
name = "openssl-probe"
|
||||||
version = "0.2.1"
|
version = "0.2.1"
|
||||||
@@ -903,7 +1036,7 @@ dependencies = [
|
|||||||
"rustc-hash",
|
"rustc-hash",
|
||||||
"rustls",
|
"rustls",
|
||||||
"socket2",
|
"socket2",
|
||||||
"thiserror",
|
"thiserror 2.0.18",
|
||||||
"tokio",
|
"tokio",
|
||||||
"tracing",
|
"tracing",
|
||||||
"web-time",
|
"web-time",
|
||||||
@@ -925,7 +1058,7 @@ dependencies = [
|
|||||||
"rustls",
|
"rustls",
|
||||||
"rustls-pki-types",
|
"rustls-pki-types",
|
||||||
"slab",
|
"slab",
|
||||||
"thiserror",
|
"thiserror 2.0.18",
|
||||||
"tinyvec",
|
"tinyvec",
|
||||||
"tracing",
|
"tracing",
|
||||||
"web-time",
|
"web-time",
|
||||||
@@ -998,6 +1131,67 @@ dependencies = [
|
|||||||
"bitflags",
|
"bitflags",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ref-cast"
|
||||||
|
version = "1.0.25"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f354300ae66f76f1c85c5f84693f0ce81d747e2c3f21a45fef496d89c960bf7d"
|
||||||
|
dependencies = [
|
||||||
|
"ref-cast-impl",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ref-cast-impl"
|
||||||
|
version = "1.0.25"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b7186006dcb21920990093f30e3dea63b7d6e977bf1256be20c3563a5db070da"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn 2.0.117",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "reqwest"
|
||||||
|
version = "0.12.28"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "eddd3ca559203180a307f12d114c268abf583f59b03cb906fd0b3ff8646c1147"
|
||||||
|
dependencies = [
|
||||||
|
"base64",
|
||||||
|
"bytes",
|
||||||
|
"futures-core",
|
||||||
|
"futures-util",
|
||||||
|
"http",
|
||||||
|
"http-body",
|
||||||
|
"http-body-util",
|
||||||
|
"hyper",
|
||||||
|
"hyper-rustls",
|
||||||
|
"hyper-util",
|
||||||
|
"js-sys",
|
||||||
|
"log",
|
||||||
|
"percent-encoding",
|
||||||
|
"pin-project-lite",
|
||||||
|
"quinn",
|
||||||
|
"rustls",
|
||||||
|
"rustls-pki-types",
|
||||||
|
"serde",
|
||||||
|
"serde_json",
|
||||||
|
"serde_urlencoded",
|
||||||
|
"sync_wrapper",
|
||||||
|
"tokio",
|
||||||
|
"tokio-rustls",
|
||||||
|
"tokio-util",
|
||||||
|
"tower",
|
||||||
|
"tower-http",
|
||||||
|
"tower-service",
|
||||||
|
"url",
|
||||||
|
"wasm-bindgen",
|
||||||
|
"wasm-bindgen-futures",
|
||||||
|
"wasm-streams",
|
||||||
|
"web-sys",
|
||||||
|
"webpki-roots",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "reqwest"
|
name = "reqwest"
|
||||||
version = "0.13.3"
|
version = "0.13.3"
|
||||||
@@ -1075,6 +1269,7 @@ checksum = "ef86cd5876211988985292b91c96a8f2d298df24e75989a43a3c73f2d4d8168b"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"aws-lc-rs",
|
"aws-lc-rs",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
|
"ring",
|
||||||
"rustls-pki-types",
|
"rustls-pki-types",
|
||||||
"rustls-webpki",
|
"rustls-webpki",
|
||||||
"subtle",
|
"subtle",
|
||||||
@@ -1172,6 +1367,31 @@ dependencies = [
|
|||||||
"windows-sys 0.61.2",
|
"windows-sys 0.61.2",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "schemars"
|
||||||
|
version = "1.2.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a2b42f36aa1cd011945615b92222f6bf73c599a102a300334cd7f8dbeec726cc"
|
||||||
|
dependencies = [
|
||||||
|
"dyn-clone",
|
||||||
|
"ref-cast",
|
||||||
|
"schemars_derive",
|
||||||
|
"serde",
|
||||||
|
"serde_json",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "schemars_derive"
|
||||||
|
version = "1.2.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7d115b50f4aaeea07e79c1912f645c7513d81715d0420f8bc77a18c6260b307f"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"serde_derive_internals",
|
||||||
|
"syn 2.0.117",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "scopeguard"
|
name = "scopeguard"
|
||||||
version = "1.2.0"
|
version = "1.2.0"
|
||||||
@@ -1234,7 +1454,18 @@ checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn",
|
"syn 2.0.117",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "serde_derive_internals"
|
||||||
|
version = "0.29.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "18d26a20a969b9e3fdf2fc2d9f21eda6c40e2de84c9408bb5d3b05d499aae711"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn 2.0.117",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -1344,12 +1575,29 @@ version = "1.2.1"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596"
|
checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "strsim"
|
||||||
|
version = "0.11.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "subtle"
|
name = "subtle"
|
||||||
version = "2.6.1"
|
version = "2.6.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292"
|
checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "syn"
|
||||||
|
version = "1.0.109"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"unicode-ident",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "syn"
|
name = "syn"
|
||||||
version = "2.0.117"
|
version = "2.0.117"
|
||||||
@@ -1378,7 +1626,7 @@ checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn",
|
"syn 2.0.117",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -1402,13 +1650,33 @@ dependencies = [
|
|||||||
"libc",
|
"libc",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "thiserror"
|
||||||
|
version = "1.0.69"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52"
|
||||||
|
dependencies = [
|
||||||
|
"thiserror-impl 1.0.69",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "thiserror"
|
name = "thiserror"
|
||||||
version = "2.0.18"
|
version = "2.0.18"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "4288b5bcbc7920c07a1149a35cf9590a2aa808e0bc1eafaade0b80947865fbc4"
|
checksum = "4288b5bcbc7920c07a1149a35cf9590a2aa808e0bc1eafaade0b80947865fbc4"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"thiserror-impl",
|
"thiserror-impl 2.0.18",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "thiserror-impl"
|
||||||
|
version = "1.0.69"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn 2.0.117",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -1419,7 +1687,7 @@ checksum = "ebc4ee7f67670e9b64d05fa4253e753e016c6c95ff35b89b7941d6b856dec1d5"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn",
|
"syn 2.0.117",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -1472,7 +1740,7 @@ checksum = "385a6cb71ab9ab790c5fe8d67f1645e6c450a7ce006a33de03daa956cf70a496"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn",
|
"syn 2.0.117",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -1600,6 +1868,12 @@ dependencies = [
|
|||||||
"serde",
|
"serde",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "urlencoding"
|
||||||
|
version = "2.1.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "daf8dba3b7eb870caf1ddeed7bc9d2a049f3cfdfae7cb521b087cc33ae4c49da"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "utf8_iter"
|
name = "utf8_iter"
|
||||||
version = "1.0.4"
|
version = "1.0.4"
|
||||||
@@ -1682,7 +1956,7 @@ dependencies = [
|
|||||||
"bumpalo",
|
"bumpalo",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn",
|
"syn 2.0.117",
|
||||||
"wasm-bindgen-shared",
|
"wasm-bindgen-shared",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -1695,6 +1969,19 @@ dependencies = [
|
|||||||
"unicode-ident",
|
"unicode-ident",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wasm-streams"
|
||||||
|
version = "0.4.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "15053d8d85c7eccdbefef60f06769760a563c7f0a9d6902a13d35c7800b0ad65"
|
||||||
|
dependencies = [
|
||||||
|
"futures-util",
|
||||||
|
"js-sys",
|
||||||
|
"wasm-bindgen",
|
||||||
|
"wasm-bindgen-futures",
|
||||||
|
"web-sys",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "web-sys"
|
name = "web-sys"
|
||||||
version = "0.3.98"
|
version = "0.3.98"
|
||||||
@@ -1724,6 +2011,15 @@ dependencies = [
|
|||||||
"rustls-pki-types",
|
"rustls-pki-types",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "webpki-roots"
|
||||||
|
version = "1.0.7"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "52f5ee44c96cf55f1b349600768e3ece3a8f26010c05265ab73f945bb1a2eb9d"
|
||||||
|
dependencies = [
|
||||||
|
"rustls-pki-types",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "winapi-util"
|
name = "winapi-util"
|
||||||
version = "0.1.11"
|
version = "0.1.11"
|
||||||
@@ -1955,7 +2251,7 @@ checksum = "de844c262c8848816172cef550288e7dc6c7b7814b4ee56b3e1553f275f1858e"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn",
|
"syn 2.0.117",
|
||||||
"synstructure",
|
"synstructure",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -1976,7 +2272,7 @@ checksum = "70e3cd084b1788766f53af483dd21f93881ff30d7320490ec3ef7526d203bad4"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn",
|
"syn 2.0.117",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -1996,7 +2292,7 @@ checksum = "11532158c46691caf0f2593ea8358fed6bbf68a0315e80aae9bd41fbade684a1"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn",
|
"syn 2.0.117",
|
||||||
"synstructure",
|
"synstructure",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -2036,7 +2332,7 @@ checksum = "625dc425cab0dca6dc3c3319506e6593dcb08a9f387ea3b284dbd52a92c40555"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn",
|
"syn 2.0.117",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ reqwest = { version = "0.13", features = ["json"] }
|
|||||||
tokio = { version = "1.52", features = ["full"] }
|
tokio = { version = "1.52", features = ["full"] }
|
||||||
serde_json = "1.0"
|
serde_json = "1.0"
|
||||||
serde = { version = "1.0", features = ["derive"] }
|
serde = { version = "1.0", features = ["derive"] }
|
||||||
|
openrouter-rs = "0.10"
|
||||||
dotenvy = "0.15"
|
dotenvy = "0.15"
|
||||||
axum = "0.8"
|
axum = "0.8"
|
||||||
anyhow = "1.0"
|
anyhow = "1.0"
|
||||||
|
|||||||
+135
-6
@@ -1,22 +1,81 @@
|
|||||||
use std::time::Duration;
|
use serde::Deserialize;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
consts::{BOT_PROCESS_MSG, REVIEW_PROMPT},
|
||||||
env::EnvConfig,
|
env::EnvConfig,
|
||||||
errors::AppError,
|
errors::AppError,
|
||||||
gitea::{GiteaAPI, ReviewPayload, WebhookType},
|
gitea::{GiteaAPI, ReviewPayload, WebhookType},
|
||||||
|
open_router::OpenRouterClient,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#[derive(Deserialize, Debug)]
|
||||||
|
struct ReviewResult {
|
||||||
|
reviews: Vec<ReviewItem>,
|
||||||
|
comment: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize, Debug)]
|
||||||
|
struct ReviewItem {
|
||||||
|
filename: String,
|
||||||
|
line: Option<u64>,
|
||||||
|
code: String,
|
||||||
|
message: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Map a filename to a markdown language identifier for syntax highlighting.
|
||||||
|
fn lang_from_filename(filename: &str) -> &str {
|
||||||
|
match std::path::Path::new(filename)
|
||||||
|
.extension()
|
||||||
|
.and_then(|e| e.to_str())
|
||||||
|
.unwrap_or("")
|
||||||
|
{
|
||||||
|
"rs" => "rust",
|
||||||
|
"py" => "python",
|
||||||
|
"js" | "mjs" => "javascript",
|
||||||
|
"ts" => "typescript",
|
||||||
|
"jsx" => "jsx",
|
||||||
|
"tsx" => "tsx",
|
||||||
|
"go" => "go",
|
||||||
|
"java" => "java",
|
||||||
|
"kt" | "kts" => "kotlin",
|
||||||
|
"scala" => "scala",
|
||||||
|
"c" | "h" => "c",
|
||||||
|
"cpp" | "cc" | "cxx" | "hpp" | "hxx" => "cpp",
|
||||||
|
"rb" => "ruby",
|
||||||
|
"php" => "php",
|
||||||
|
"swift" => "swift",
|
||||||
|
"sh" | "bash" | "zsh" => "bash",
|
||||||
|
"sql" => "sql",
|
||||||
|
"html" | "htm" => "html",
|
||||||
|
"css" => "css",
|
||||||
|
"scss" | "sass" => "scss",
|
||||||
|
"json" => "json",
|
||||||
|
"yaml" | "yml" => "yaml",
|
||||||
|
"xml" => "xml",
|
||||||
|
"toml" => "toml",
|
||||||
|
"md" | "mdx" => "markdown",
|
||||||
|
"dockerfile" | "Dockerfile" => "dockerfile",
|
||||||
|
"Makefile" => "makefile",
|
||||||
|
_ => "",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub struct Bot {
|
pub struct Bot {
|
||||||
config: EnvConfig,
|
config: EnvConfig,
|
||||||
gitea_api: GiteaAPI,
|
gitea_api: GiteaAPI,
|
||||||
|
open_router_client: OpenRouterClient,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Bot {
|
impl Bot {
|
||||||
pub fn new(config: EnvConfig) -> Self {
|
pub fn new(config: EnvConfig) -> anyhow::Result<Self> {
|
||||||
Self {
|
Ok(Self {
|
||||||
gitea_api: GiteaAPI::new(&config.gitea_url, &config.gitea_token),
|
gitea_api: GiteaAPI::new(&config.gitea_url, &config.gitea_token),
|
||||||
|
open_router_client: OpenRouterClient::new(
|
||||||
|
&config.open_router_api_key,
|
||||||
|
&config.open_router_model,
|
||||||
|
)?,
|
||||||
config,
|
config,
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn start(
|
pub async fn start(
|
||||||
@@ -46,17 +105,87 @@ impl Bot {
|
|||||||
let new_comment = self
|
let new_comment = self
|
||||||
.gitea_api
|
.gitea_api
|
||||||
.comment(
|
.comment(
|
||||||
|
&BOT_PROCESS_MSG.replace("{model}", &self.config.open_router_model),
|
||||||
&review_payload.repository.full_name,
|
&review_payload.repository.full_name,
|
||||||
review_payload.pull_request.number,
|
review_payload.pull_request.number,
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
tokio::time::sleep(Duration::from_secs(10)).await;
|
let bot_result: Result<String, anyhow::Error> = async {
|
||||||
|
let git_diff = self
|
||||||
|
.download_git_diff(&review_payload.pull_request.diff_url)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
let bot_request = &&REVIEW_PROMPT
|
||||||
|
.replace("{subject}", &review_payload.pull_request.title)
|
||||||
|
.replace("{comment}", &review_payload.comment.body)
|
||||||
|
.replace("{diff}", &git_diff);
|
||||||
|
|
||||||
|
self.open_router_client.chat(&bot_request).await
|
||||||
|
}
|
||||||
|
.await;
|
||||||
|
|
||||||
|
let edit_msg = match bot_result {
|
||||||
|
Ok(bot_result) => self.review_result_to_markdown(&bot_result),
|
||||||
|
Err(e) => format!("Error while reviewing: {}", e),
|
||||||
|
};
|
||||||
|
|
||||||
self.gitea_api
|
self.gitea_api
|
||||||
.edit_comment(&review_payload.repository.full_name, new_comment.id)
|
.edit_comment(
|
||||||
|
&edit_msg,
|
||||||
|
&review_payload.repository.full_name,
|
||||||
|
new_comment.id,
|
||||||
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn review_result_to_markdown(&self, result: &str) -> String {
|
||||||
|
let review_result: ReviewResult = match serde_json::from_str(result) {
|
||||||
|
Ok(review_result) => review_result,
|
||||||
|
Err(_) => {
|
||||||
|
return format!(
|
||||||
|
"Failed to parse review result. Raw output:\n\n```json\n{}\n```",
|
||||||
|
result
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if review_result.reviews.is_empty() {
|
||||||
|
return String::from("No issues found. ✅");
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut md = String::from("## Review Feedback\n\n");
|
||||||
|
for (i, item) in review_result.reviews.iter().enumerate() {
|
||||||
|
if i > 0 {
|
||||||
|
md.push_str("\n---\n\n");
|
||||||
|
}
|
||||||
|
md.push_str(&format!("### `{}`\n\n", item.filename));
|
||||||
|
if let Some(line) = item.line {
|
||||||
|
md.push_str(&format!("> **Line {}**\n\n", line));
|
||||||
|
}
|
||||||
|
if !item.code.is_empty() {
|
||||||
|
let lang = lang_from_filename(&item.filename);
|
||||||
|
md.push_str(&format!("```{}\n{}\n```\n\n", lang, item.code));
|
||||||
|
}
|
||||||
|
md.push_str(&item.message);
|
||||||
|
md.push('\n');
|
||||||
|
}
|
||||||
|
|
||||||
|
if !review_result.comment.is_empty() {
|
||||||
|
md.push_str("\n---\n\n");
|
||||||
|
md.push_str("### Summary\n\n");
|
||||||
|
md.push_str(&review_result.comment);
|
||||||
|
md.push('\n');
|
||||||
|
}
|
||||||
|
|
||||||
|
md
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn download_git_diff(&self, url: &str) -> anyhow::Result<String> {
|
||||||
|
let response = reqwest::get(url).await?;
|
||||||
|
let body = response.text().await?;
|
||||||
|
Ok(body)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,36 @@
|
|||||||
pub const GITEA_SIG_HEADER_NAME: &str = "x-gitea-signature";
|
pub const GITEA_SIG_HEADER_NAME: &str = "x-gitea-signature";
|
||||||
pub const GITEA_EVENT_TYPE_HEADER_NAME: &str = "x-gitea-event-type";
|
pub const GITEA_EVENT_TYPE_HEADER_NAME: &str = "x-gitea-event-type";
|
||||||
pub const MAX_WEBHOOK_BODY_SIZE: usize = 1024 * 1024; // 1 MiB
|
pub const MAX_WEBHOOK_BODY_SIZE: usize = 1024 * 1024; // 1 MiB
|
||||||
|
|
||||||
|
pub const BOT_PROCESS_MSG: &str = "
|
||||||
|
Review in progress with the model \"{model}\"...
|
||||||
|
";
|
||||||
|
|
||||||
|
pub const REVIEW_PROMPT: &str = "
|
||||||
|
You are a senior software engineer reviewing code changes.
|
||||||
|
|
||||||
|
Check good practices and code quality.
|
||||||
|
|
||||||
|
This is the pull request subject: \"{subject}\"
|
||||||
|
|
||||||
|
This is the user comment: \"{comment}\"
|
||||||
|
|
||||||
|
This is the git diff of the code changes:
|
||||||
|
|
||||||
|
\"{diff}\"
|
||||||
|
|
||||||
|
Please review the code changes and provide feedback.
|
||||||
|
Return your feedback with only this json format, reviews must contain each review (filename field must contain the full path with extension) and comment msut contain a final summary:
|
||||||
|
|
||||||
|
{
|
||||||
|
\"reviews\": [
|
||||||
|
{
|
||||||
|
\"filename\": \"\",
|
||||||
|
\"line\": ,
|
||||||
|
\"code\": \"\",
|
||||||
|
\"message\": \"\"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
\"comment\": \"\"
|
||||||
|
}
|
||||||
|
";
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ pub struct EnvConfig {
|
|||||||
pub http_port: u16,
|
pub http_port: u16,
|
||||||
pub webhook_secret: String,
|
pub webhook_secret: String,
|
||||||
pub open_router_api_key: String,
|
pub open_router_api_key: String,
|
||||||
|
pub open_router_model: String,
|
||||||
pub bot_name: String,
|
pub bot_name: String,
|
||||||
pub gitea_url: String,
|
pub gitea_url: String,
|
||||||
pub gitea_token: String,
|
pub gitea_token: String,
|
||||||
@@ -18,6 +19,7 @@ pub fn load_config() -> anyhow::Result<EnvConfig> {
|
|||||||
let bot_name = try_get_env("BOT_NAME")?;
|
let bot_name = try_get_env("BOT_NAME")?;
|
||||||
let webhook_secret = try_get_env("WEBHOOK_SIG_HEADER_SECRET")?;
|
let webhook_secret = try_get_env("WEBHOOK_SIG_HEADER_SECRET")?;
|
||||||
let open_router_api_key = try_get_env("OPEN_ROUTER_API_KEY")?;
|
let open_router_api_key = try_get_env("OPEN_ROUTER_API_KEY")?;
|
||||||
|
let open_router_model = try_get_env("OPEN_ROUTER_MODEL")?;
|
||||||
let gitea_url = try_get_env("GITEA_URL")?;
|
let gitea_url = try_get_env("GITEA_URL")?;
|
||||||
let gitea_token = try_get_env("GITEA_TOKEN")?;
|
let gitea_token = try_get_env("GITEA_TOKEN")?;
|
||||||
|
|
||||||
@@ -26,6 +28,7 @@ pub fn load_config() -> anyhow::Result<EnvConfig> {
|
|||||||
webhook_secret,
|
webhook_secret,
|
||||||
bot_name,
|
bot_name,
|
||||||
open_router_api_key,
|
open_router_api_key,
|
||||||
|
open_router_model,
|
||||||
gitea_url,
|
gitea_url,
|
||||||
gitea_token,
|
gitea_token,
|
||||||
})
|
})
|
||||||
|
|||||||
+15
-8
@@ -16,7 +16,12 @@ impl GiteaAPI {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn comment(&self, full_name: &str, index: u64) -> anyhow::Result<Comment> {
|
pub async fn comment(
|
||||||
|
&self,
|
||||||
|
body: &str,
|
||||||
|
full_name: &str,
|
||||||
|
index: u64,
|
||||||
|
) -> anyhow::Result<Comment> {
|
||||||
let url = format!(
|
let url = format!(
|
||||||
"{}/api/v1/repos/{}/issues/{}/comments?access_token={}",
|
"{}/api/v1/repos/{}/issues/{}/comments?access_token={}",
|
||||||
self.base_url, full_name, index, self.token
|
self.base_url, full_name, index, self.token
|
||||||
@@ -26,17 +31,20 @@ impl GiteaAPI {
|
|||||||
let res = client
|
let res = client
|
||||||
.post(url)
|
.post(url)
|
||||||
.json(&json!({
|
.json(&json!({
|
||||||
"body": "Hello world :)"
|
"body": body
|
||||||
}))
|
}))
|
||||||
.send()
|
.send()
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
println!("{}", res.status());
|
|
||||||
|
|
||||||
res.json::<Comment>().await.map_err(anyhow::Error::from)
|
res.json::<Comment>().await.map_err(anyhow::Error::from)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn edit_comment(&self, full_name: &str, comment_id: u64) -> anyhow::Result<()> {
|
pub async fn edit_comment(
|
||||||
|
&self,
|
||||||
|
body: &str,
|
||||||
|
full_name: &str,
|
||||||
|
comment_id: u64,
|
||||||
|
) -> anyhow::Result<()> {
|
||||||
let url = format!(
|
let url = format!(
|
||||||
"{}/api/v1/repos/{}/issues/comments/{}?access_token={}",
|
"{}/api/v1/repos/{}/issues/comments/{}?access_token={}",
|
||||||
self.base_url, full_name, comment_id, self.token
|
self.base_url, full_name, comment_id, self.token
|
||||||
@@ -46,13 +54,11 @@ impl GiteaAPI {
|
|||||||
let res = client
|
let res = client
|
||||||
.patch(url)
|
.patch(url)
|
||||||
.json(&json!({
|
.json(&json!({
|
||||||
"body": "Updated Hello world :)"
|
"body": body
|
||||||
}))
|
}))
|
||||||
.send()
|
.send()
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
println!("{}", res.status());
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -75,6 +81,7 @@ pub struct PullRequest {
|
|||||||
pub id: u64,
|
pub id: u64,
|
||||||
pub diff_url: String,
|
pub diff_url: String,
|
||||||
pub number: u64,
|
pub number: u64,
|
||||||
|
pub title: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize, Debug)]
|
#[derive(Deserialize, Debug)]
|
||||||
|
|||||||
+3
-5
@@ -6,19 +6,17 @@ mod consts;
|
|||||||
mod env;
|
mod env;
|
||||||
mod errors;
|
mod errors;
|
||||||
mod gitea;
|
mod gitea;
|
||||||
|
mod open_router;
|
||||||
mod state;
|
mod state;
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() -> anyhow::Result<()> {
|
async fn main() -> anyhow::Result<()> {
|
||||||
let config = env::load_config()?;
|
let config = env::load_config()?;
|
||||||
let bot = Bot::new(config.clone());
|
let bot = Bot::new(config.clone())?;
|
||||||
|
|
||||||
let (tx, rx) = tokio::sync::mpsc::channel::<WebhookType>(1);
|
let (tx, rx) = tokio::sync::mpsc::channel::<WebhookType>(1);
|
||||||
|
|
||||||
let app_state = AppState {
|
let app_state = AppState { bot_tx: tx, config };
|
||||||
bot_tx: tx,
|
|
||||||
config,
|
|
||||||
};
|
|
||||||
|
|
||||||
tokio::try_join!(bot.start(rx), api::start(app_state))?;
|
tokio::try_join!(bot.start(rx), api::start(app_state))?;
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,34 @@
|
|||||||
|
use openrouter_rs::{Message, api::chat::ChatCompletionRequest};
|
||||||
|
|
||||||
|
pub struct OpenRouterClient {
|
||||||
|
client: openrouter_rs::OpenRouterClient,
|
||||||
|
model: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl OpenRouterClient {
|
||||||
|
pub fn new(token: &str, model: &str) -> anyhow::Result<Self> {
|
||||||
|
Ok(Self {
|
||||||
|
client: openrouter_rs::OpenRouterClient::builder()
|
||||||
|
.api_key(token)
|
||||||
|
.build()?,
|
||||||
|
model: String::from(model),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn chat(&self, msg: &str) -> anyhow::Result<String> {
|
||||||
|
let request = ChatCompletionRequest::builder()
|
||||||
|
.model(&self.model)
|
||||||
|
.messages(vec![Message::new(
|
||||||
|
openrouter_rs::types::Role::Developer,
|
||||||
|
msg,
|
||||||
|
)])
|
||||||
|
.build()?;
|
||||||
|
|
||||||
|
let response = self.client.chat().create(&request).await?;
|
||||||
|
|
||||||
|
response.choices[0]
|
||||||
|
.content()
|
||||||
|
.map(|msg| String::from(msg))
|
||||||
|
.ok_or(anyhow::anyhow!("No content"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user